1 import {Injectable, EventEmitter} from '@angular/core';
2 import {Router, ActivatedRoute} from '@angular/router';
3 import {IdlObject} from '@eg/core/idl.service';
4 import {OrgService} from '@eg/core/org.service';
5 import {CatalogService} from '@eg/share/catalog/catalog.service';
6 import {CatalogUrlService} from '@eg/share/catalog/catalog-url.service';
7 import {CatalogSearchContext} from '@eg/share/catalog/search-context';
8 import {BibRecordSummary} from '@eg/share/catalog/bib-record.service';
9 import {PatronService} from '@eg/staff/share/patron/patron.service';
12 * Shared bits needed by the staff version of the catalog.
16 export class StaffCatalogService {
18 searchContext: CatalogSearchContext;
20 defaultSearchOrg: IdlObject;
21 defaultSearchLimit: number;
22 // Track the current template through route changes.
23 selectedTemplate: string;
25 // Display the Exclude Electronic checkbox
26 showExcludeElectronic = false;
28 // TODO: does unapi support pref-lib for result-page copy counts?
34 // Patron barcode we hope to place a hold for.
35 holdForBarcode: string;
36 // User object for above barcode.
37 holdForUser: IdlObject;
39 // Emit that the value has changed so components can detect
40 // the change even when the component is not itself digesting
42 holdForChange: EventEmitter<void> = new EventEmitter<void>();
44 // Cache the currently selected detail record (i.g. catalog/record/123)
45 // summary so the record detail component can avoid duplicate fetches
46 // during record tab navigation.
47 currentDetailRecordSummary: any;
49 // Add digital bookplate to search options.
50 enableBookplates = false;
53 private router: Router,
54 private route: ActivatedRoute,
55 private org: OrgService,
56 private cat: CatalogService,
57 private patron: PatronService,
58 private catUrl: CatalogUrlService
61 createContext(): void {
62 // Initialize the search context from the load-time URL params.
63 // Do this here so the search form and other context data are
64 // applied on every page, not just the search results page. The
65 // search results pages will handle running the actual search.
67 this.catUrl.fromUrlParams(this.route.snapshot.queryParamMap);
69 this.holdForBarcode = this.route.snapshot.queryParams['holdForBarcode'];
71 if (this.holdForBarcode) {
72 this.patron.getByBarcode(this.holdForBarcode)
74 this.holdForUser = user;
75 this.holdForChange.emit();
79 this.searchContext.org = this.org; // service, not searchOrg
80 this.searchContext.isStaff = true;
81 this.applySearchDefaults();
85 this.holdForUser = null;
86 this.holdForBarcode = null;
87 this.holdForChange.emit();
90 cloneContext(context: CatalogSearchContext): CatalogSearchContext {
91 const params: any = this.catUrl.toUrlParams(context);
92 const ctx = this.catUrl.fromUrlHash(params);
93 ctx.isStaff = true; // not carried in the URL
97 applySearchDefaults(): void {
98 if (!this.searchContext.searchOrg) {
99 this.searchContext.searchOrg =
100 this.defaultSearchOrg || this.org.root();
103 if (!this.searchContext.pager.limit) {
104 this.searchContext.pager.limit = this.defaultSearchLimit || 10;
109 * Redirect to the search results page while propagating the current
110 * search paramters into the URL. Let the search results component
111 * execute the actual search.
114 if (!this.searchContext.isSearchable()) { return; }
116 // Clear cached detail summary for new searches.
117 this.currentDetailRecordSummary = null;
119 const params = this.catUrl.toUrlParams(this.searchContext);
121 // Force a new search every time this method is called, even if
122 // it's the same as the active search. Since router navigation
123 // exits early when the route + params is identical, add a
124 // random token to the route params to force a full navigation.
125 // This also resolves a problem where only removing secondary+
126 // versions of a query param fail to cause a route navigation.
127 // (E.g. going from two query= params to one). Investigation
129 params.ridx = '' + this.routeIndex++;
131 this.router.navigate(
132 ['/staff/catalog/search'], {queryParams: params});
136 * Redirect to the browse results page while propagating the current
137 * browse paramters into the URL. Let the browse results component
138 * execute the actual browse.
141 if (!this.searchContext.browseSearch.isSearchable()) { return; }
142 const params = this.catUrl.toUrlParams(this.searchContext);
144 // Force a new browse every time this method is called, even if
145 // it's the same as the active browse. Since router navigation
146 // exits early when the route + params is identical, add a
147 // random token to the route params to force a full navigation.
148 // This also resolves a problem where only removing secondary+
149 // versions of a query param fail to cause a route navigation.
150 // (E.g. going from two query= params to one).
151 params.ridx = '' + this.routeIndex++;
153 this.router.navigate(
154 ['/staff/catalog/browse'], {queryParams: params});
157 // Call number browse.
158 // Redirect to cn browse page and let its component perform the search
160 if (!this.searchContext.cnBrowseSearch.isSearchable()) { return; }
161 const params = this.catUrl.toUrlParams(this.searchContext);
162 params.ridx = '' + this.routeIndex++; // see comments above
163 this.router.navigate(['/staff/catalog/cnbrowse'], {queryParams: params});
166 // Params to genreate a new author search based on a reset
167 // clone of the current page params.
168 getAuthorSearchParams(summary: BibRecordSummary): any {
169 const tmpContext = this.cloneContext(this.searchContext);
171 tmpContext.termSearch.fieldClass = ['author'];
172 tmpContext.termSearch.query = [summary.display.author];
173 return this.catUrl.toUrlParams(tmpContext);