]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/eg2/src/app/share/catalog/catalog-url.service.ts
253e3aacdd69c2a86aa01a216b864d9095a666bc
[working/Evergreen.git] / Open-ILS / src / eg2 / src / app / share / catalog / catalog-url.service.ts
1 import {Injectable} from '@angular/core';
2 import {ParamMap} from '@angular/router';
3 import {OrgService} from '@eg/core/org.service';
4 import {CatalogSearchContext, FacetFilter} from './search-context';
5 import {CATALOG_CCVM_FILTERS} from './catalog.service';
6
7 @Injectable()
8 export class CatalogUrlService {
9
10     // consider supporting a param name prefix/namespace
11
12     constructor(private org: OrgService) { }
13
14     /**
15      * Returns a URL query structure suitable for using with
16      * router.navigate(..., {queryParams:...}).
17      * No navigation is performed within.
18      */
19     toUrlParams(context: CatalogSearchContext):
20             {[key: string]: string | string[]} {
21
22         const params = {
23             query: [],
24             fieldClass: [],
25             joinOp: [],
26             matchOp: [],
27             facets: [],
28             identQuery: null,
29             identQueryType: null,
30             org: null,
31             limit: null,
32             offset: null
33         };
34
35         params.org = context.searchOrg.id();
36
37         params.limit = context.pager.limit;
38         if (context.pager.offset) {
39             params.offset = context.pager.offset;
40         }
41
42         // These fields can be copied directly into place
43         ['format', 'sort', 'available', 'global', 'identQuery', 'identQueryType']
44         .forEach(field => {
45             if (context[field]) {
46                 // Only propagate applied values to the URL.
47                 params[field] = context[field];
48             }
49         });
50
51         if (params.identQuery) {
52             // Ident queries (e.g. tcn search) discards all remaining filters
53             return params;
54         }
55
56         context.query.forEach((q, idx) => {
57             ['query', 'fieldClass', 'joinOp', 'matchOp'].forEach(field => {
58                 // Propagate all array-based fields regardless of
59                 // whether a value is applied to ensure correct
60                 // correlation between values.
61                 params[field][idx] = context[field][idx];
62             });
63         });
64
65         // CCVM filters are encoded as comma-separated lists
66         Object.keys(context.ccvmFilters).forEach(code => {
67             if (context.ccvmFilters[code] &&
68                 context.ccvmFilters[code][0] !== '') {
69                 params[code] = context.ccvmFilters[code].join(',');
70             }
71         });
72
73         // Each facet is a JSON encoded blob of class, name, and value
74         context.facetFilters.forEach(facet => {
75             params.facets.push(JSON.stringify({
76                 c : facet.facetClass,
77                 n : facet.facetName,
78                 v : facet.facetValue
79             }));
80         });
81
82         return params;
83     }
84
85     /**
86      * Creates a new search context from the active route params.
87      */
88     fromUrlParams(params: ParamMap): CatalogSearchContext {
89         const context = new CatalogSearchContext();
90
91         this.applyUrlParams(context, params);
92
93         return context;
94     }
95
96     applyUrlParams(context: CatalogSearchContext, params: ParamMap): void {
97
98         // Reset query/filter args.  The will be reconstructed below.
99         context.reset();
100
101         // These fields can be copied directly into place
102         ['format', 'sort', 'available', 'global', 'identQuery', 'identQueryType']
103         .forEach(field => {
104             const val = params.get(field);
105             if (val !== null) {
106                 context[field] = val;
107             }
108         });
109
110         if (params.get('limit')) {
111             context.pager.limit = +params.get('limit');
112         }
113
114         if (params.get('offset')) {
115             context.pager.offset = +params.get('offset');
116         }
117
118         ['query', 'fieldClass', 'joinOp', 'matchOp'].forEach(field => {
119             const arr = params.getAll(field);
120             if (arr && arr.length) {
121                 context[field] = arr;
122             }
123         });
124
125         CATALOG_CCVM_FILTERS.forEach(code => {
126             const val = params.get(code);
127             if (val) {
128                 context.ccvmFilters[code] = val.split(/,/);
129             } else {
130                 context.ccvmFilters[code] = [''];
131             }
132         });
133
134         params.getAll('facets').forEach(blob => {
135             const facet = JSON.parse(blob);
136             context.addFacet(new FacetFilter(facet.c, facet.n, facet.v));
137         });
138
139         if (params.get('org')) {
140             context.searchOrg = this.org.get(+params.get('org'));
141         }
142     }
143 }