1 import {OrgService} from '@eg/core/org.service';
2 import {IdlObject} from '@eg/core/idl.service';
3 import {Pager} from '@eg/share/util/pager';
4 import {Params} from '@angular/router';
6 export enum CatalogSearchState {
12 export class FacetFilter {
17 constructor(cls: string, name: string, value: string) {
18 this.facetClass = cls;
19 this.facetName = name;
20 this.facetValue = value;
23 equals(filter: FacetFilter): boolean {
25 this.facetClass === filter.facetClass &&
26 this.facetName === filter.facetName &&
27 this.facetValue === filter.facetValue
32 // Not an angular service.
33 // It's conceviable there could be multiple contexts.
34 export class CatalogSearchContext {
36 // Search options and filters
43 identQueryType: string; // isbn, issn, etc.
48 ccvmFilters: {[ccvmCode: string]: string[]};
49 facetFilters: FacetFilter[];
52 // Result from most recent search.
54 searchState: CatalogSearchState = CatalogSearchState.PENDING;
56 // List of IDs in page/offset context.
57 resultIds: number[] = [];
64 this.pager = new Pager();
68 // List of result IDs for the current page of data.
69 currentResultIds(): number[] {
72 this.pager.offset + this.pager.limit,
73 this.pager.resultCount
75 for (let idx = this.pager.offset; idx < max; idx++) {
76 ids.push(this.resultIds[idx]);
81 addResultId(id: number, resultIdx: number ): void {
82 this.resultIds[resultIdx + this.pager.offset] = id;
85 // Return the record at the requested index.
86 resultIdAt(index: number): number {
87 return this.resultIds[index] || null;
90 // Return the index of the requested record
91 indexForResult(id: number): number {
92 for (let i = 0; i < this.resultIds.length; i++) {
93 if (this.resultIds[i] === id) {
101 * Return search context to its default state, resetting search
102 * parameters and clearing any cached result data.
103 * This does not reset global filters like limit-to-available
104 * search-global, or search-org.
107 this.pager.offset = 0;
111 this.identQuery = null;
112 this.identQueryType = 'identifier|isbn';
113 this.fieldClass = ['keyword'];
114 this.matchOp = ['contains'];
116 this.ccvmFilters = {};
117 this.facetFilters = [];
120 this.searchState = CatalogSearchState.PENDING;
123 isSearchable(): boolean {
125 if (this.identQuery && this.identQueryType) {
129 return this.query.length
130 && this.query[0] !== ''
131 && this.searchOrg !== null;
134 compileSearch(): string {
137 if (this.available) {
142 // e.g. title, title.descending
143 const parts = this.sort.split(/\./);
144 if (parts[1]) { str += ' #descending'; }
145 str += ' sort(' + parts[0] + ')';
148 if (this.identQuery && this.identQueryType) {
149 if (str) { str += ' '; }
150 str += this.identQueryType + ':' + this.identQuery;
155 // Compile boolean sub-query components
156 if (str.length) { str += ' '; }
157 const qcount = this.query.length;
159 // if we multiple boolean query components, wrap them in parens.
160 if (qcount > 1) { str += '('; }
161 this.query.forEach((q, idx) => {
162 str += this.compileBoolQuerySet(idx);
164 if (qcount > 1) { str += ')'; }
169 str += ' format(' + this.format + ')';
174 this.org.root().ou_type().depth() + ')';
177 str += ' site(' + this.searchOrg.shortname() + ')';
179 Object.keys(this.ccvmFilters).forEach(field => {
180 if (this.ccvmFilters[field][0] !== '') {
181 str += ' ' + field + '(' + this.ccvmFilters[field] + ')';
185 this.facetFilters.forEach(f => {
186 str += ' ' + f.facetClass + '|'
187 + f.facetName + '[' + f.facetValue + ']';
193 stripQuotes(query: string): string {
194 return query.replace(/"/g, '');
197 stripAnchors(query: string): string {
198 return query.replace(/[\^\$]/g, '');
201 addQuotes(query: string): string {
202 if (query.match(/ /)) {
203 return '"' + query + '"';
208 compileBoolQuerySet(idx: number): string {
209 let query = this.query[idx];
210 const joinOp = this.joinOp[idx];
211 const matchOp = this.matchOp[idx];
212 const fieldClass = this.fieldClass[idx];
215 if (!query) { return str; }
217 if (idx > 0) { str += ' ' + joinOp + ' '; }
220 if (fieldClass) { str += fieldClass + ':'; }
224 query = this.addQuotes(this.stripQuotes(query));
227 query = '-' + this.addQuotes(this.stripQuotes(query));
230 query = '^' + this.stripAnchors(query) + '$';
233 query = this.addQuotes('^' +
234 this.stripAnchors(this.stripQuotes(query)));
238 return str + query + ')';
241 hasFacet(facet: FacetFilter): boolean {
243 this.facetFilters.filter(f => f.equals(facet))[0]
247 removeFacet(facet: FacetFilter): void {
248 this.facetFilters = this.facetFilters.filter(f => !f.equals(facet));
251 addFacet(facet: FacetFilter): void {
252 if (!this.hasFacet(facet)) {
253 this.facetFilters.push(facet);
257 toggleFacet(facet: FacetFilter): void {
258 if (this.hasFacet(facet)) {
259 this.removeFacet(facet);
261 this.facetFilters.push(facet);