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';
15 selector: 'eg-catalog-results',
16 templateUrl: 'results.component.html'
18 export class ResultsComponent implements OnInit, OnDestroy {
20 searchContext: CatalogSearchContext;
22 // Cache record creator/editor since this will likely be a
23 // reasonably small set of data w/ lots of repitition.
24 userCache: {[id: number]: IdlObject} = {};
26 allRecsSelected: boolean;
28 searchSub: Subscription;
29 routeSub: Subscription;
30 basketSub: Subscription;
33 private route: ActivatedRoute,
34 private pcrud: PcrudService,
35 private cat: CatalogService,
36 private bib: BibRecordService,
37 private catUrl: CatalogUrlService,
38 private staffCat: StaffCatalogService,
39 private basket: BasketService
43 this.searchContext = this.staffCat.searchContext;
45 // Our search context is initialized on page load. Once
46 // ResultsComponent is active, it will not be reinitialized,
47 // even if the route parameters changes (unless we change the
48 // route reuse policy). Watch for changes here to pick up new
51 // This will also fire on page load.
53 this.route.queryParamMap.subscribe((params: ParamMap) => {
55 // TODO: Angular docs suggest using switchMap(), but
56 // it's not firing for some reason. Also, could avoid
57 // firing unnecessary searches when a param unrelated to
58 // searching is changed by .map()'ing out only the desired
59 // params and running through .distinctUntilChanged(), but
60 // .map() is not firing either. I'm missing something.
61 this.searchByUrl(params);
64 // After each completed search, update the record selector.
65 this.searchSub = this.cat.onSearchComplete.subscribe(
66 ctx => this.applyRecordSelection());
68 // Watch for basket changes applied by other components.
69 this.basketSub = this.basket.onChange.subscribe(
70 () => this.applyRecordSelection());
74 this.routeSub.unsubscribe();
75 this.searchSub.unsubscribe();
76 this.basketSub.unsubscribe();
79 // Apply the select-all checkbox when all visible records
81 applyRecordSelection() {
82 const ids = this.searchContext.currentResultIds();
83 let allChecked = true;
85 if (!this.basket.hasRecordId(id)) {
89 this.allRecsSelected = allChecked;
92 // Pull values from the URL and run the requested search.
93 searchByUrl(params: ParamMap): void {
94 this.catUrl.applyUrlParams(this.searchContext, params);
96 if (this.searchContext.isSearchable()) {
98 this.cat.search(this.searchContext)
100 this.cat.fetchFacets(this.searchContext);
101 this.cat.fetchBibSummaries(this.searchContext)
102 .then(ok2 => this.fleshSearchResults());
107 // Records file into place randomly as the server returns data.
108 // To reduce page display shuffling, avoid showing the list of
109 // records until the first few are ready to render.
110 shouldStartRendering(): boolean {
112 if (this.searchHasResults()) {
113 const pageCount = this.searchContext.currentResultIds().length;
116 return this.searchContext.result.records[0];
118 return this.searchContext.result.records[0]
119 && this.searchContext.result.records[1];
126 fleshSearchResults(): void {
127 const records = this.searchContext.result.records;
128 if (!records || records.length === 0) { return; }
130 // Flesh the creator / editor fields with the user object.
131 this.bib.fleshBibUsers(records.map(r => r.record));
134 searchIsDone(): boolean {
135 return this.searchContext.searchState === CatalogSearchState.COMPLETE;
138 searchIsActive(): boolean {
139 return this.searchContext.searchState === CatalogSearchState.SEARCHING;
142 searchHasResults(): boolean {
143 return this.searchIsDone() && this.searchContext.result.count > 0;
146 toggleAllRecsSelected() {
147 const ids = this.searchContext.currentResultIds();
149 if (this.allRecsSelected) {
150 this.basket.addRecordIds(ids);
152 this.basket.removeRecordIds(ids);