]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/catalog/catalog.service.ts
LP1615805 No inputs after submit in patron search (AngularJS)
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / catalog / catalog.service.ts
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';
10
11 /**
12  * Shared bits needed by the staff version of the catalog.
13  */
14
15 @Injectable()
16 export class StaffCatalogService {
17
18     searchContext: CatalogSearchContext;
19     routeIndex = 0;
20     defaultSearchOrg: IdlObject;
21     defaultSearchLimit: number;
22     // Track the current template through route changes.
23     selectedTemplate: string;
24
25     // Display the Exclude Electronic checkbox
26     showExcludeElectronic = false;
27
28     // Advanced search filters to display
29     searchFilters: string[];
30
31     // TODO: does unapi support pref-lib for result-page copy counts?
32     prefOrg: IdlObject;
33
34     // Default search tab
35     defaultTab: string;
36
37     // Patron barcode we hope to place a hold for.
38     holdForBarcode: string;
39     // User object for above barcode.
40     holdForUser: IdlObject;
41
42     // Emit that the value has changed so components can detect
43     // the change even when the component is not itself digesting
44     // new values.
45     holdForChange: EventEmitter<void> = new EventEmitter<void>();
46
47     // Cache the currently selected detail record (i.g. catalog/record/123)
48     // summary so the record detail component can avoid duplicate fetches
49     // during record tab navigation.
50     currentDetailRecordSummary: any;
51
52     // Add digital bookplate to search options.
53     enableBookplates = false;
54
55     // Cache of browse results so the browse pager is not forced to
56     // re-run the browse search on each navigation.
57     browsePagerData: any[];
58
59     // whether to redirect to record page upon a single search
60     // result
61     jumpOnSingleHit = false;
62
63     constructor(
64         private router: Router,
65         private route: ActivatedRoute,
66         private org: OrgService,
67         private cat: CatalogService,
68         private patron: PatronService,
69         private catUrl: CatalogUrlService
70     ) { }
71
72     createContext(): void {
73         // Initialize the search context from the load-time URL params.
74         // Do this here so the search form and other context data are
75         // applied on every page, not just the search results page.  The
76         // search results pages will handle running the actual search.
77         this.searchContext =
78             this.catUrl.fromUrlParams(this.route.snapshot.queryParamMap);
79
80         this.holdForBarcode = this.route.snapshot.queryParams['holdForBarcode'];
81
82         if (this.holdForBarcode) {
83             this.patron.getByBarcode(this.holdForBarcode)
84             .then(user => {
85                 this.holdForUser = user;
86                 this.holdForChange.emit();
87             });
88         }
89
90         this.searchContext.org = this.org; // service, not searchOrg
91         this.searchContext.isStaff = true;
92         this.applySearchDefaults();
93     }
94
95     clearHoldPatron() {
96         this.holdForUser = null;
97         this.holdForBarcode = null;
98         this.holdForChange.emit();
99     }
100
101     cloneContext(context: CatalogSearchContext): CatalogSearchContext {
102         const params: any = this.catUrl.toUrlParams(context);
103         const ctx = this.catUrl.fromUrlHash(params);
104         ctx.isStaff = true; // not carried in the URL
105         return ctx;
106     }
107
108     applySearchDefaults(): void {
109         if (!this.searchContext.searchOrg) {
110             this.searchContext.searchOrg =
111                 this.defaultSearchOrg || this.org.root();
112         }
113
114         if (!this.searchContext.pager.limit) {
115             this.searchContext.pager.limit = this.defaultSearchLimit || 10;
116         }
117     }
118
119     /**
120      * Redirect to the search results page while propagating the current
121      * search paramters into the URL.  Let the search results component
122      * execute the actual search.
123      */
124     search(): void {
125         if (!this.searchContext.isSearchable()) { return; }
126
127         // Clear cached detail summary for new searches.
128         this.currentDetailRecordSummary = null;
129
130         const params = this.catUrl.toUrlParams(this.searchContext);
131
132         // Force a new search every time this method is called, even if
133         // it's the same as the active search.  Since router navigation
134         // exits early when the route + params is identical, add a
135         // random token to the route params to force a full navigation.
136         // This also resolves a problem where only removing secondary+
137         // versions of a query param fail to cause a route navigation.
138         // (E.g. going from two query= params to one).  Investigation
139         // pending.
140         params.ridx = '' + this.routeIndex++;
141
142         this.router.navigate(
143           ['/staff/catalog/search'], {queryParams: params});
144     }
145
146     /**
147      * Redirect to the browse results page while propagating the current
148      * browse paramters into the URL.  Let the browse results component
149      * execute the actual browse.
150      */
151     browse(): void {
152         if (!this.searchContext.browseSearch.isSearchable()) { return; }
153         const params = this.catUrl.toUrlParams(this.searchContext);
154
155         // Force a new browse every time this method is called, even if
156         // it's the same as the active browse.  Since router navigation
157         // exits early when the route + params is identical, add a
158         // random token to the route params to force a full navigation.
159         // This also resolves a problem where only removing secondary+
160         // versions of a query param fail to cause a route navigation.
161         // (E.g. going from two query= params to one).
162         params.ridx = '' + this.routeIndex++;
163
164         this.router.navigate(
165             ['/staff/catalog/browse'], {queryParams: params});
166     }
167
168     // Call number browse.
169     // Redirect to cn browse page and let its component perform the search
170     cnBrowse(): void {
171         if (!this.searchContext.cnBrowseSearch.isSearchable()) { return; }
172         const params = this.catUrl.toUrlParams(this.searchContext);
173         params.ridx = '' + this.routeIndex++; // see comments above
174         this.router.navigate(['/staff/catalog/cnbrowse'], {queryParams: params});
175     }
176
177     // Params to genreate a new author search based on a reset
178     // clone of the current page params.
179     getAuthorSearchParams(summary: BibRecordSummary): any {
180         const tmpContext = this.cloneContext(this.searchContext);
181         tmpContext.reset();
182         tmpContext.termSearch.fieldClass = ['author'];
183         tmpContext.termSearch.query = [summary.display.author];
184         return this.catUrl.toUrlParams(tmpContext);
185     }
186 }
187
188