]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/catalog/cnbrowse/results.component.ts
LP1889685 Staff catalog record CN browse retains search
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / catalog / cnbrowse / results.component.ts
1 import {Component, Input, OnInit, OnDestroy} from '@angular/core';
2 import {ActivatedRoute, Router, ParamMap} from '@angular/router';
3 import {Subscription} from 'rxjs';
4 import {IdlObject} from '@eg/core/idl.service';
5 import {PcrudService} from '@eg/core/pcrud.service';
6 import {CatalogService} from '@eg/share/catalog/catalog.service';
7 import {BibRecordService} from '@eg/share/catalog/bib-record.service';
8 import {CatalogUrlService} from '@eg/share/catalog/catalog-url.service';
9 import {CatalogSearchContext, CatalogSearchState} from '@eg/share/catalog/search-context';
10 import {StaffCatalogService} from '../catalog.service';
11 import {BibRecordSummary} from '@eg/share/catalog/bib-record.service';
12 import {OrgService} from '@eg/core/org.service';
13
14 @Component({
15   selector: 'eg-catalog-cn-browse-results',
16   templateUrl: 'results.component.html'
17 })
18 export class CnBrowseResultsComponent implements OnInit, OnDestroy {
19
20     // If set, this is a bib-focused browse
21     @Input() bibSummary: BibRecordSummary;
22
23     @Input() rowCount = 5;
24     rowIndexList: number[] = [];
25
26     // hard-coded because it requires template changes.
27     colCount = 3;
28
29     searchContext: CatalogSearchContext;
30     results: any[] = [];
31     routeSub: Subscription;
32
33     // When browsing by a specific record, keep tabs on the initial
34     // browse call number.
35     browseCn: string;
36
37     constructor(
38         private router: Router,
39         private route: ActivatedRoute,
40         private org: OrgService,
41         private pcrud: PcrudService,
42         private cat: CatalogService,
43         private bib: BibRecordService,
44         private catUrl: CatalogUrlService,
45         private staffCat: StaffCatalogService
46     ) {}
47
48     ngOnInit() {
49         this.searchContext = this.staffCat.searchContext;
50
51         if (this.bibSummary) {
52             // Avoid clobbering the active search when browsing in
53             // the context of a specific record.
54             this.searchContext =
55                 this.staffCat.cloneContext(this.searchContext);
56         }
57
58         for (let idx = 0; idx < this.rowCount; idx++) {
59             this.rowIndexList.push(idx);
60         }
61
62         let promise = Promise.resolve();
63         if (this.bibSummary) {
64             promise = this.getBrowseCallnumber();
65         }
66
67         promise.then(_ => {
68             this.routeSub = this.route.queryParamMap.subscribe(
69                 (params: ParamMap) => this.browseByUrl(params)
70             );
71         });
72     }
73
74     ngOnDestroy() {
75         this.routeSub.unsubscribe();
76     }
77
78     getBrowseCallnumber(): Promise<any> {
79         let org = this.searchContext.searchOrg.id();
80
81         if (this.searchContext.searchOrg.ou_type().can_have_vols() === 'f') {
82             // If the current search org unit cannot hold volumes, search
83             // across child org units.
84             org = this.org.descendants(this.searchContext.searchOrg, true);
85         }
86
87         return this.pcrud.search('acn',
88             {record: this.bibSummary.id, owning_lib: org},
89             {limit: 1}
90         ).toPromise().then(cn =>
91             this.browseCn = cn ? cn.label() : this.bibSummary.bibCallNumber
92         );
93     }
94
95     browseByUrl(params: ParamMap): void {
96         this.catUrl.applyUrlParams(this.searchContext, params);
97         this.getBrowseResults();
98     }
99
100     getBrowseResults() {
101         const cbs = this.searchContext.cnBrowseSearch;
102         cbs.limit = this.rowCount * this.colCount;
103
104         if (this.browseCn) {
105             // Override any call number browse URL parameters
106             cbs.value = this.browseCn;
107         }
108
109         if (cbs.isSearchable()) {
110             this.results = [];
111             this.cat.cnBrowse(this.searchContext)
112                 .subscribe(results => this.processResults(results));
113         }
114     }
115
116     processResults(results: any[]) {
117         this.results = results;
118
119         const depth = this.searchContext.global ?
120             this.searchContext.org.root().ou_type().depth() :
121             this.searchContext.searchOrg.ou_type().depth();
122
123         const bibIds = this.results.map(r => r.record().id());
124         const distinct = (value: any, index: number, self: Array<number>) => {
125             return self.indexOf(value) === index;
126         };
127
128         const bres: IdlObject[] = [];
129         this.bib.getBibSummaries(
130             bibIds.filter(distinct),
131             this.searchContext.searchOrg.id(), this.searchContext.isStaff
132         ).subscribe(
133             summary => {
134                 // Response order not guaranteed.  Match the summary
135                 // object up with its response object.  A bib may be
136                 // linked to multiple call numbers
137                 const bibResults = this.results.filter(
138                     r => Number(r.record().id()) === summary.id);
139
140                 bres.push(summary.record);
141
142                 // Use _ since result is an 'acn' object.
143                 bibResults.forEach(r => r._bibSummary = summary);
144             }
145         );
146     }
147
148     browseIsDone(): boolean {
149         return this.searchContext.searchState === CatalogSearchState.COMPLETE;
150     }
151
152     browseIsActive(): boolean {
153         return this.searchContext.searchState === CatalogSearchState.SEARCHING;
154     }
155
156     browseHasResults(): boolean {
157         return this.browseIsDone() && this.results.length > 0;
158     }
159
160     prevPage() {
161         this.searchContext.cnBrowseSearch.offset--;
162         if (this.bibSummary) {
163             // Browse without navigation
164             this.getBrowseResults();
165         } else {
166             this.staffCat.cnBrowse();
167         }
168
169     }
170
171     nextPage() {
172         this.searchContext.cnBrowseSearch.offset++;
173         if (this.bibSummary) {
174             // Browse without navigation
175             this.getBrowseResults();
176         } else {
177             this.staffCat.cnBrowse();
178         }
179     }
180
181     /**
182      * Propagate the search params along when navigating to each record.
183      */
184     navigateToRecord(summary: BibRecordSummary) {
185         const params = this.catUrl.toUrlParams(this.searchContext);
186
187         this.router.navigate(
188             ['/staff/catalog/record/' + summary.id], {queryParams: params});
189     }
190
191     resultSlice(rowIdx: number): number[] {
192         const offset = rowIdx * this.colCount;
193         return this.results.slice(offset, offset + this.colCount);
194     }
195
196     isCenter(rowIdx: number, colIdx: number): boolean {
197         const total = this.rowCount * this.colCount;
198         return Math.floor(total / 2) === ((rowIdx * this.colCount) + colIdx);
199     }
200
201     orgName(orgId: number): string {
202         return this.org.get(orgId).shortname();
203     }
204
205     getAuthorSearchParams(summary: BibRecordSummary): any {
206         return this.staffCat.getAuthorSearchParams(summary);
207     }
208 }
209
210