1 import {Injectable} from '@angular/core';
2 import {ParamMap} from '@angular/router';
3 import {OrgService} from '@eg/core/org.service';
4 import {CatalogSearchContext, CatalogBrowseContext, CatalogMarcContext,
5 CatalogTermContext, FacetFilter} from './search-context';
6 import {CATALOG_CCVM_FILTERS} from './search-context';
7 import {HashParams} from '@eg/share/util/hash-params';
10 export class CatalogUrlService {
12 // consider supporting a param name prefix/namespace
14 constructor(private org: OrgService) { }
17 * Returns a URL query structure suitable for using with
18 * router.navigate(..., {queryParams:...}).
19 * No navigation is performed within.
21 toUrlParams(context: CatalogSearchContext):
22 {[key: string]: string | string[]} {
24 const params: any = {};
26 if (context.searchOrg) {
27 params.org = context.searchOrg.id();
30 if (context.pager.limit) {
31 params.limit = context.pager.limit;
34 if (context.pager.offset) {
35 params.offset = context.pager.offset;
38 // These fields can be copied directly into place
39 ['limit', 'offset', 'sort', 'global', 'showBasket', 'sort']
42 // Only propagate applied values to the URL.
43 params[field] = context[field];
47 if (context.marcSearch.isSearchable()) {
48 const ms = context.marcSearch;
50 params.marcSubfield = [];
51 params.marcValue = [];
53 ms.values.forEach((val, idx) => {
55 params.marcTag.push(ms.tags[idx]);
56 params.marcSubfield.push(ms.subfields[idx]);
57 params.marcValue.push(ms.values[idx]);
62 if (context.identSearch.isSearchable()) {
63 params.identQuery = context.identSearch.value;
64 params.identQueryType = context.identSearch.queryType;
67 if (context.browseSearch.isSearchable()) {
68 params.browseTerm = context.browseSearch.value;
69 params.browseClass = context.browseSearch.fieldClass;
70 if (context.browseSearch.pivot) {
71 params.browsePivot = context.browseSearch.pivot;
75 if (context.termSearch.isSearchable()) {
77 const ts = context.termSearch;
80 params.fieldClass = [];
84 ['format', 'available', 'hasBrowseEntry', 'date1',
85 'date2', 'dateOp', 'groupByMetarecord', 'fromMetarecord']
88 params[field] = ts[field];
92 ts.query.forEach((val, idx) => {
94 params.query.push(ts.query[idx]);
95 params.fieldClass.push(ts.fieldClass[idx]);
96 params.joinOp.push(ts.joinOp[idx]);
97 params.matchOp.push(ts.matchOp[idx]);
101 // CCVM filters are encoded as comma-separated lists
102 Object.keys(ts.ccvmFilters).forEach(code => {
103 if (ts.ccvmFilters[code] &&
104 ts.ccvmFilters[code][0] !== '') {
105 params[code] = ts.ccvmFilters[code].join(',');
109 // Each facet is a JSON encoded blob of class, name, and value
110 if (ts.facetFilters.length) {
112 ts.facetFilters.forEach(facet => {
113 params.facets.push(JSON.stringify({
114 c : facet.facetClass,
121 if (ts.copyLocations.length && ts.copyLocations[0] !== '') {
122 params.copyLocations = ts.copyLocations.join(',');
126 if (context.cnBrowseSearch.isSearchable()) {
127 params.cnBrowseTerm = context.cnBrowseSearch.value;
128 params.cnBrowsePage = context.cnBrowseSearch.offset;
129 params.cnBrowsePageSize = context.cnBrowseSearch.limit;
135 fromUrlHash(params: any): CatalogSearchContext {
136 return this.fromUrlParams(new HashParams(params));
140 * Creates a new search context from the active route params.
142 fromUrlParams(params: ParamMap): CatalogSearchContext {
143 const context = new CatalogSearchContext();
145 this.applyUrlParams(context, params);
150 applyUrlParams(context: CatalogSearchContext, params: ParamMap): void {
152 // Reset query/filter args. The will be reconstructed below.
156 if (params.get('org')) {
157 context.searchOrg = this.org.get(+params.get('org'));
160 if (val = params.get('limit')) {
161 context.pager.limit = +val;
164 if (val = params.get('offset')) {
165 context.pager.offset = +val;
168 if (val = params.get('sort')) {
172 if (val = params.get('global')) {
173 context.global = val;
176 if (val = params.get('showBasket')) {
177 context.showBasket = val;
180 if (params.has('marcValue')) {
181 context.marcSearch.tags = params.getAll('marcTag');
182 context.marcSearch.subfields = params.getAll('marcSubfield');
183 context.marcSearch.values = params.getAll('marcValue');
186 if (params.has('identQuery')) {
187 context.identSearch.value = params.get('identQuery');
188 context.identSearch.queryType = params.get('identQueryType');
191 if (params.has('browseTerm')) {
192 context.browseSearch.value = params.get('browseTerm');
193 context.browseSearch.fieldClass = params.get('browseClass');
194 if (params.has('browsePivot')) {
195 context.browseSearch.pivot = +params.get('browsePivot');
199 if (params.has('cnBrowseTerm')) {
200 context.cnBrowseSearch.value = params.get('cnBrowseTerm');
201 context.cnBrowseSearch.offset = Number(params.get('cnBrowsePage'));
202 context.cnBrowseSearch.limit = Number(params.get('cnBrowsePageSize'));
205 const ts = context.termSearch;
207 // browseEntry and query searches may be facet-limited
208 params.getAll('facets').forEach(blob => {
209 const facet = JSON.parse(blob);
210 ts.addFacet(new FacetFilter(facet.c, facet.n, facet.v));
213 if (params.has('hasBrowseEntry')) {
215 ts.hasBrowseEntry = params.get('hasBrowseEntry');
217 } else if (params.has('query')) {
220 ['format', 'available', 'date1', 'date2',
221 'dateOp', 'groupByMetarecord', 'fromMetarecord']
223 if (params.has(field)) {
224 ts[field] = params.get(field);
229 ['query', 'fieldClass', 'joinOp', 'matchOp'].forEach(field => {
230 const arr = params.getAll(field);
231 if (params.has(field)) {
232 ts[field] = params.getAll(field);
236 CATALOG_CCVM_FILTERS.forEach(code => {
237 const ccvmVal = params.get(code);
239 ts.ccvmFilters[code] = ccvmVal.split(/,/);
241 ts.ccvmFilters[code] = [''];
245 if (params.get('copyLocations')) {
246 ts.copyLocations = params.get('copyLocations').split(/,/);