X-Git-Url: https://git.evergreen-ils.org/?p=working%2FEvergreen.git;a=blobdiff_plain;f=Open-ILS%2Fsrc%2Feg2%2Fsrc%2Fapp%2Fstaff%2Fcatalog%2Frecord%2Frecord.component.ts;h=b900ea87340d623d85a2d973ac7bf45f5bec49f5;hp=b217e5c9b63c77ea72d09caf47c0765cc1e9c275;hb=0df5d1f8f7e0d907489feaa0156b966440310fb3;hpb=6c706f454b2b9cdf2d46df3c60e53a0d3cb531d7 diff --git a/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.ts b/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.ts index b217e5c9b6..b900ea8734 100644 --- a/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/catalog/record/record.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit, Input, ViewChild} from '@angular/core'; +import {Component, OnInit, Input, ViewChild, HostListener} from '@angular/core'; import {NgbTabset, NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap'; import {Router, ActivatedRoute, ParamMap} from '@angular/router'; import {PcrudService} from '@eg/core/pcrud.service'; @@ -8,6 +8,9 @@ import {CatalogService} from '@eg/share/catalog/catalog.service'; import {BibRecordService, BibRecordSummary} from '@eg/share/catalog/bib-record.service'; import {StaffCatalogService} from '../catalog.service'; import {BibSummaryComponent} from '@eg/staff/share/bib-summary/bib-summary.component'; +import {StoreService} from '@eg/core/store.service'; +import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component'; +import {MarcEditorComponent} from '@eg/staff/share/marc-edit/editor.component'; @Component({ selector: 'eg-catalog-record', @@ -19,7 +22,12 @@ export class RecordComponent implements OnInit { recordTab: string; summary: BibRecordSummary; searchContext: CatalogSearchContext; - @ViewChild('recordTabs') recordTabs: NgbTabset; + @ViewChild('recordTabs', { static: true }) recordTabs: NgbTabset; + @ViewChild('marcEditor', {static: false}) marcEditor: MarcEditorComponent; + defaultTab: string; // eg.cat.default_record_tab + + @ViewChild('pendingChangesDialog', {static: false}) + pendingChangesDialog: ConfirmDialogComponent; constructor( private router: Router, @@ -27,33 +35,96 @@ export class RecordComponent implements OnInit { private pcrud: PcrudService, private bib: BibRecordService, private cat: CatalogService, - private staffCat: StaffCatalogService + private staffCat: StaffCatalogService, + private store: StoreService ) {} ngOnInit() { this.searchContext = this.staffCat.searchContext; + this.defaultTab = + this.store.getLocalItem('eg.cat.default_record_tab') + || 'item_table'; + // Watch for URL record ID changes + // This includes the initial route. + // When applying the default configured tab, no navigation occurs + // to apply the tab name to the URL, it displays as the default. + // This is done so no intermediate redirect is required, which + // messes with browser back/forward navigation. this.route.paramMap.subscribe((params: ParamMap) => { - this.recordTab = params.get('tab') || 'copy_table'; + this.recordTab = params.get('tab'); this.recordId = +params.get('id'); this.searchContext = this.staffCat.searchContext; + + if (!this.recordTab) { + this.recordTab = this.defaultTab || 'item_table'; + } + this.loadRecord(); }); } + setDefaultTab() { + this.defaultTab = this.recordTab; + this.store.setLocalItem('eg.cat.default_record_tab', this.recordTab); + } + // Changing a tab in the UI means changing the route. // Changing the route ultimately results in changing the tab. - onTabChange(evt: NgbTabChangeEvent) { - this.recordTab = evt.nextId; + beforeTabChange(evt: NgbTabChangeEvent) { // prevent tab changing until after route navigation evt.preventDefault(); - let url = '/staff/catalog/record/' + this.recordId; - if (this.recordTab !== 'copy_table') { - url += '/' + this.recordTab; + // Protect against tab changes with dirty data. + this.canDeactivate().then(ok => { + if (ok) { + this.recordTab = evt.nextId; + this.routeToTab(); + } + }); + } + + /* + * Handle 3 types of navigation which can cause loss of data. + * 1. Record detail tab navigation (see also beforeTabChange()) + * 2. Intra-Angular route navigation away from the record detail page + * 3. Browser page unload/reload + * + * For the #1, and #2, display a eg confirmation dialog. + * For #3 use the stock browser onbeforeunload dialog. + * + * Note in this case a tab change is a route change, but it's one + * which does not cause RecordComponent to unload, so it has to be + * manually tracked in beforeTabChange(). + */ + @HostListener('window:beforeunload', ['$event']) + canDeactivate($event?: Event): Promise { + + if (this.marcEditor && this.marcEditor.changesPending()) { + + // Each warning dialog clears the current "changes are pending" + // flag so the user is not presented with the dialog again + // unless new changes are made. + this.marcEditor.clearPendingChanges(); + + if ($event) { // window.onbeforeunload + $event.preventDefault(); + $event.returnValue = true; + + } else { // tab OR route change. + return this.pendingChangesDialog.open().toPromise(); + } + + } else { + return Promise.resolve(true); } + } + + routeToTab() { + const url = + `/staff/catalog/record/${this.recordId}/${this.recordTab}`; // Retain search parameters this.router.navigate([url], {queryParamsHandling: 'merge'}); @@ -79,6 +150,35 @@ export class RecordComponent implements OnInit { this.bib.fleshBibUsers([summary.record]); }); } + + // Lets us intercept the summary object and augment it with + // search highlight data if/when it becomes available from + // an externally executed search. + summaryForDisplay(): BibRecordSummary { + if (!this.summary) { return null; } + const sum = this.summary; + const ctx = this.searchContext; + + if (Object.keys(sum.displayHighlights).length === 0) { + if (ctx.highlightData[sum.id]) { + sum.displayHighlights = ctx.highlightData[sum.id]; + } + } + + return this.summary; + } + + currentSearchOrg(): IdlObject { + if (this.staffCat && this.staffCat.searchContext) { + return this.staffCat.searchContext.searchOrg; + } + return null; + } + + handleMarcRecordSaved() { + this.staffCat.currentDetailRecordSummary = null; + this.loadRecord(); + } }