LP1869898 Angular staff cat place hold from patron
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / catalog / catalog.service.ts
1 import {Injectable} 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     // TODO: does unapi support pref-lib for result-page copy counts?
26     prefOrg: IdlObject;
27
28     // Default search tab
29     defaultTab: string;
30
31     // Patron barcode we hope to place a hold for.
32     holdForBarcode: string;
33     // User object for above barcode.
34     holdForUser: IdlObject;
35
36     // Cache the currently selected detail record (i.g. catalog/record/123)
37     // summary so the record detail component can avoid duplicate fetches
38     // during record tab navigation.
39     currentDetailRecordSummary: any;
40
41     constructor(
42         private router: Router,
43         private route: ActivatedRoute,
44         private org: OrgService,
45         private cat: CatalogService,
46         private patron: PatronService,
47         private catUrl: CatalogUrlService
48     ) { }
49
50     createContext(): void {
51         // Initialize the search context from the load-time URL params.
52         // Do this here so the search form and other context data are
53         // applied on every page, not just the search results page.  The
54         // search results pages will handle running the actual search.
55         this.searchContext =
56             this.catUrl.fromUrlParams(this.route.snapshot.queryParamMap);
57
58         this.holdForBarcode = this.route.snapshot.queryParams['holdForBarcode'];
59
60         if (this.holdForBarcode) {
61             this.patron.getByBarcode(this.holdForBarcode)
62             .then(user => this.holdForUser = user);
63         }
64
65         this.searchContext.org = this.org; // service, not searchOrg
66         this.searchContext.isStaff = true;
67         this.applySearchDefaults();
68     }
69
70     cloneContext(context: CatalogSearchContext): CatalogSearchContext {
71         const params: any = this.catUrl.toUrlParams(context);
72         return this.catUrl.fromUrlHash(params);
73     }
74
75     applySearchDefaults(): void {
76         if (!this.searchContext.searchOrg) {
77             this.searchContext.searchOrg =
78                 this.defaultSearchOrg || this.org.root();
79         }
80
81         if (!this.searchContext.pager.limit) {
82             this.searchContext.pager.limit = this.defaultSearchLimit || 10;
83         }
84     }
85
86     /**
87      * Redirect to the search results page while propagating the current
88      * search paramters into the URL.  Let the search results component
89      * execute the actual search.
90      */
91     search(): void {
92         if (!this.searchContext.isSearchable()) { return; }
93
94         const params = this.catUrl.toUrlParams(this.searchContext);
95
96         // Force a new search every time this method is called, even if
97         // it's the same as the active search.  Since router navigation
98         // exits early when the route + params is identical, add a
99         // random token to the route params to force a full navigation.
100         // This also resolves a problem where only removing secondary+
101         // versions of a query param fail to cause a route navigation.
102         // (E.g. going from two query= params to one).  Investigation
103         // pending.
104         params.ridx = '' + this.routeIndex++;
105
106         this.router.navigate(
107           ['/staff/catalog/search'], {queryParams: params});
108     }
109
110     /**
111      * Redirect to the browse results page while propagating the current
112      * browse paramters into the URL.  Let the browse results component
113      * execute the actual browse.
114      */
115     browse(): void {
116         if (!this.searchContext.browseSearch.isSearchable()) { return; }
117         const params = this.catUrl.toUrlParams(this.searchContext);
118
119         // Force a new browse every time this method is called, even if
120         // it's the same as the active browse.  Since router navigation
121         // exits early when the route + params is identical, add a
122         // random token to the route params to force a full navigation.
123         // This also resolves a problem where only removing secondary+
124         // versions of a query param fail to cause a route navigation.
125         // (E.g. going from two query= params to one).
126         params.ridx = '' + this.routeIndex++;
127
128         this.router.navigate(
129             ['/staff/catalog/browse'], {queryParams: params});
130     }
131
132     // Call number browse.
133     // Redirect to cn browse page and let its component perform the search
134     cnBrowse(): void {
135         if (!this.searchContext.cnBrowseSearch.isSearchable()) { return; }
136         const params = this.catUrl.toUrlParams(this.searchContext);
137         params.ridx = '' + this.routeIndex++; // see comments above
138         this.router.navigate(['/staff/catalog/cnbrowse'], {queryParams: params});
139     }
140
141     // Params to genreate a new author search based on a reset
142     // clone of the current page params.
143     getAuthorSearchParams(summary: BibRecordSummary): any {
144         const tmpContext = this.cloneContext(this.searchContext);
145         tmpContext.reset();
146         tmpContext.termSearch.fieldClass = ['author'];
147         tmpContext.termSearch.query = [summary.display.author];
148         return this.catUrl.toUrlParams(tmpContext);
149     }
150 }
151
152