import { StoragePathListComponent } from './components/manage/storage-path-list/storage-path-list.component'
import { TasksComponent } from './components/manage/tasks/tasks.component'
import { DirtyDocGuard } from './guards/dirty-doc.guard'
+import { DirtySavedViewGuard } from './guards/dirty-saved-view.guard'
const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
canDeactivate: [DirtyDocGuard],
children: [
{ path: 'dashboard', component: DashboardComponent },
- { path: 'documents', component: DocumentListComponent },
- { path: 'view/:id', component: DocumentListComponent },
+ {
+ path: 'documents',
+ component: DocumentListComponent,
+ canDeactivate: [DirtySavedViewGuard],
+ },
+ {
+ path: 'view/:id',
+ component: DocumentListComponent,
+ canDeactivate: [DirtySavedViewGuard],
+ },
{ path: 'documents/:id', component: DocumentDetailComponent },
{ path: 'asn/:id', component: DocumentAsnComponent },
{ path: 'tags', component: TagListComponent },
import { DocumentAsnComponent } from './components/document-asn/document-asn.component'
import { DocumentCommentsComponent } from './components/document-comments/document-comments.component'
import { DirtyDocGuard } from './guards/dirty-doc.guard'
+import { DirtySavedViewGuard } from './guards/dirty-saved-view.guard'
import { StoragePathListComponent } from './components/manage/storage-path-list/storage-path-list.component'
import { StoragePathEditDialogComponent } from './components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component'
import { SettingsService } from './services/settings.service'
{ provide: NgbDateAdapter, useClass: ISODateAdapter },
{ provide: NgbDateParserFormatter, useClass: LocalizedDateParserFormatter },
DirtyDocGuard,
+ DirtySavedViewGuard,
],
bootstrap: [AppComponent],
})
<ngb-progressbar *ngIf="!confirmButtonEnabled" style="height: 1px;" type="dark" [max]="secondsTotal" [value]="seconds"></ngb-progressbar>
<span class="visually-hidden">{{ seconds | number: '1.0-0' }} seconds</span>
</button>
+ <button *ngIf="alternativeBtnCaption" type="button" class="btn" [class]="alternativeBtnClass" (click)="alternative()" [disabled]="!alternativeButtonEnabled || !buttonsEnabled">
+ {{alternativeBtnCaption}}
+ </button>
</div>
@Output()
public confirmClicked = new EventEmitter()
+ @Output()
+ public alternativeClicked = new EventEmitter()
+
@Input()
title = $localize`Confirmation`
@Input()
btnCaption = $localize`Confirm`
+ @Input()
+ alternativeBtnClass = 'btn-secondary'
+
+ @Input()
+ alternativeBtnCaption
+
@Input()
buttonsEnabled = true
confirmButtonEnabled = true
+ alternativeButtonEnabled = true
seconds = 0
secondsTotal = 0
confirmSubject: Subject<boolean>
+ alternativeSubject: Subject<boolean>
delayConfirm(seconds: number) {
const refreshInterval = 0.15 // s
this.confirmSubject?.next(true)
this.confirmSubject?.complete()
}
+
+ alternative() {
+ this.alternativeClicked.emit()
+ this.alternativeSubject?.next(true)
+ this.alternativeSubject?.complete()
+ }
}
</div>
<div class="btn-group ms-2 flex-fill" ngbDropdown role="group">
- <button class="btn btn-sm btn-outline-primary dropdown-toggle flex-fill" tourAnchor="tour.documents-views" ngbDropdownToggle i18n>Views</button>
+ <button class="btn btn-sm btn-outline-primary dropdown-toggle flex-fill" tourAnchor="tour.documents-views" ngbDropdownToggle>
+ <ng-container i18n>Views</ng-container>
+ <div *ngIf="savedViewIsModified" class="position-absolute top-0 start-100 p-2 translate-middle badge bg-secondary border border-light rounded-circle">
+ <span class="visually-hidden">selected</span>
+ </div>
+ </button>
<div class="dropdown-menu shadow dropdown-menu-right" ngbDropdownMenu>
<ng-container *ngIf="!list.activeSavedViewId">
<button ngbDropdownItem *ngFor="let view of savedViewService.allViews" (click)="loadViewConfig(view.id)">{{view.name}}</button>
--- /dev/null
+import { CanDeactivate } from '@angular/router'
+import { Injectable } from '@angular/core'
+import { first, Observable, Subject } from 'rxjs'
+import { DocumentListComponent } from '../components/document-list/document-list.component'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
+import { ConfirmDialogComponent } from '../components/common/confirm-dialog/confirm-dialog.component'
+
+@Injectable()
+export class DirtySavedViewGuard
+ implements CanDeactivate<DocumentListComponent>
+{
+ constructor(private modalService: NgbModal) {}
+
+ canDeactivate(
+ component: DocumentListComponent
+ ): boolean | Observable<boolean> {
+ return component.savedViewIsModified ? this.warn(component) : true
+ }
+
+ warn(component: DocumentListComponent) {
+ let modal = this.modalService.open(ConfirmDialogComponent, {
+ backdrop: 'static',
+ })
+ modal.componentInstance.title = $localize`Unsaved Changes`
+ modal.componentInstance.messageBold =
+ $localize`You have unsaved changes to the saved view` +
+ ' "' +
+ component.getTitle()
+ ;('".')
+ modal.componentInstance.message = $localize`Are you sure you want to close this saved view?`
+ modal.componentInstance.btnClass = 'btn-secondary'
+ modal.componentInstance.btnCaption = $localize`Close`
+ modal.componentInstance.alternativeBtnClass = 'btn-primary'
+ modal.componentInstance.alternativeBtnCaption = $localize`Save and close`
+ modal.componentInstance.alternativeClicked.pipe(first()).subscribe(() => {
+ modal.componentInstance.buttonsEnabled = false
+ component.saveViewConfig()
+ modal.close()
+ })
+ modal.componentInstance.confirmClicked.pipe(first()).subscribe(() => {
+ modal.componentInstance.buttonsEnabled = false
+ modal.close()
+ })
+
+ const subject = new Subject<boolean>()
+ modal.componentInstance.confirmSubject = subject
+ modal.componentInstance.alternativeSubject = subject
+
+ return subject
+ }
+}