34706f117be9af311322a3e9ef491ffadeb3ffb9
[evergreen-equinox.git] / Open-ILS / src / eg2 / src / app / staff / catalog / result / results.component.ts
1 import {Component, OnInit, OnDestroy, Input} from '@angular/core';
2 import {Observable, Subscription} from 'rxjs';
3 import {map, switchMap, distinctUntilChanged} from 'rxjs/operators';
4 import {ActivatedRoute, ParamMap} from '@angular/router';
5 import {CatalogService} from '@eg/share/catalog/catalog.service';
6 import {BibRecordService} from '@eg/share/catalog/bib-record.service';
7 import {CatalogUrlService} from '@eg/share/catalog/catalog-url.service';
8 import {CatalogSearchContext, CatalogSearchState} from '@eg/share/catalog/search-context';
9 import {PcrudService} from '@eg/core/pcrud.service';
10 import {StaffCatalogService} from '../catalog.service';
11 import {IdlObject} from '@eg/core/idl.service';
12 import {BasketService} from '@eg/share/catalog/basket.service';
13 import {ServerStoreService} from '@eg/core/server-store.service';
14
15 @Component({
16   selector: 'eg-catalog-results',
17   templateUrl: 'results.component.html'
18 })
19 export class ResultsComponent implements OnInit, OnDestroy {
20
21     searchContext: CatalogSearchContext;
22
23     // Cache record creator/editor since this will likely be a
24     // reasonably small set of data w/ lots of repitition.
25     userCache: {[id: number]: IdlObject} = {};
26
27     allRecsSelected: boolean;
28
29     searchSub: Subscription;
30     routeSub: Subscription;
31     basketSub: Subscription;
32     showMoreDetails = false;
33
34     constructor(
35         private route: ActivatedRoute,
36         private pcrud: PcrudService,
37         private cat: CatalogService,
38         private bib: BibRecordService,
39         private catUrl: CatalogUrlService,
40         private staffCat: StaffCatalogService,
41         private serverStore: ServerStoreService,
42         private basket: BasketService
43     ) {}
44
45     ngOnInit() {
46         this.searchContext = this.staffCat.searchContext;
47
48         // Our search context is initialized on page load.  Once
49         // ResultsComponent is active, it will not be reinitialized,
50         // even if the route parameters changes (unless we change the
51         // route reuse policy).  Watch for changes here to pick up new
52         // searches.
53         //
54         // This will also fire on page load.
55         this.routeSub =
56             this.route.queryParamMap.subscribe((params: ParamMap) => {
57
58               // TODO: Angular docs suggest using switchMap(), but
59               // it's not firing for some reason.  Also, could avoid
60               // firing unnecessary searches when a param unrelated to
61               // searching is changed by .map()'ing out only the desired
62               // params and running through .distinctUntilChanged(), but
63               // .map() is not firing either.  I'm missing something.
64               this.searchByUrl(params);
65         });
66
67         // After each completed search, update the record selector.
68         this.searchSub = this.cat.onSearchComplete.subscribe(
69             ctx => this.applyRecordSelection());
70
71         // Watch for basket changes applied by other components.
72         this.basketSub = this.basket.onChange.subscribe(
73             () => this.applyRecordSelection());
74     }
75
76     ngOnDestroy() {
77         if (this.routeSub) {
78             this.routeSub.unsubscribe();
79             this.searchSub.unsubscribe();
80             this.basketSub.unsubscribe();
81         }
82     }
83
84     // Apply the select-all checkbox when all visible records
85     // are selected.
86     applyRecordSelection() {
87         const ids = this.searchContext.currentResultIds();
88         let allChecked = true;
89         ids.forEach(id => {
90             if (!this.basket.hasRecordId(id)) {
91                 allChecked = false;
92             }
93         });
94         this.allRecsSelected = allChecked;
95     }
96
97     // Pull values from the URL and run the requested search.
98     searchByUrl(params: ParamMap): void {
99         this.catUrl.applyUrlParams(this.searchContext, params);
100
101
102         if (this.searchContext.isSearchable()) {
103
104             this.serverStore.getItem('eg.staff.catalog.results.show_more')
105             .then(showMore => {
106
107                 this.showMoreDetails =
108                     this.searchContext.showResultExtras = showMore;
109
110                 if (this.staffCat.prefOrg) {
111                     this.searchContext.prefOu = this.staffCat.prefOrg.id();
112                 }
113
114                 this.cat.search(this.searchContext)
115                 .then(ok => {
116                     this.cat.fetchFacets(this.searchContext);
117                     this.cat.fetchBibSummaries(this.searchContext);
118                 });
119             });
120         }
121     }
122
123     toggleShowMore() {
124         this.showMoreDetails = !this.showMoreDetails;
125
126         this.serverStore.setItem(
127             'eg.staff.catalog.results.show_more', this.showMoreDetails)
128         .then(_ => {
129
130             if (this.showMoreDetails) {
131                 this.staffCat.search();
132             } else {
133                 // Clear the collected copies.  No need for another search.
134                 this.searchContext.result.records.forEach(rec => rec.copies = undefined);
135             }
136         });
137     }
138
139     searchIsDone(): boolean {
140         return this.searchContext.searchState === CatalogSearchState.COMPLETE;
141     }
142
143     searchIsActive(): boolean {
144         return this.searchContext.searchState === CatalogSearchState.SEARCHING;
145     }
146
147     searchHasResults(): boolean {
148         return this.searchIsDone() && this.searchContext.result.count > 0;
149     }
150
151     toggleAllRecsSelected() {
152         const ids = this.searchContext.currentResultIds();
153
154         if (this.allRecsSelected) {
155             this.basket.addRecordIds(ids);
156         } else {
157             this.basket.removeRecordIds(ids);
158         }
159     }
160 }
161
162