UNPKG

my-test123

Version:
625 lines 26.3 kB
import { Observable } from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; import { Injectable, Inject } from '@angular/core'; import { Headers } from '@angular/http'; import { ActivatedRoute } from '@angular/router'; import { WIT_API_URL, Spaces } from 'ngx-fabric8-wit'; import { HttpService } from './http-service'; var FilterService = /** @class */ (function () { function FilterService(http, spaces, route, baseApiUrl) { this.http = http; this.spaces = spaces; this.route = route; this.baseApiUrl = baseApiUrl; this.filters = []; this.activeFilters = []; this.filterChange = new Subject(); this.filterObservable = new Subject(); this.headers = new Headers({ 'Content-Type': 'application/json' }); this.and_notation = '$AND'; this.or_notation = '$OR'; this.equal_notation = '$EQ'; this.not_equal_notation = '$NEQ'; this.in_notation = '$IN'; this.not_in_notation = '$NIN'; this.sub_str_notation = '$SUBSTR'; this.special_keys = { 'null': null, 'true': true, 'false': false, '': null }; this.compare_notations = [ this.equal_notation, this.not_equal_notation, this.in_notation, this.not_in_notation, this.sub_str_notation ]; this.join_notations = [ this.and_notation, this.or_notation, ]; this.filtertoWorkItemMap = { 'assignee': ['relationships', 'assignees', 'data', ['id']], 'creator': ['relationships', 'creator', 'data', 'id'], 'area': ['relationships', 'area', 'data', 'id'], 'workitemtype': ['relationships', 'baseType', 'data', 'id'], 'iteration': ['relationships', 'iteration', 'data', 'id'], 'state': ['attributes', 'system.state'], }; } FilterService.prototype.setFilterValues = function (id, value) { var index = this.activeFilters.findIndex(function (f) { return f.id === id; }); if (index > -1 && value !== undefined) { this.activeFilters[index].paramKey = 'filter[' + id + ']'; this.activeFilters[index].value = value; } else { this.activeFilters.push({ id: id, paramKey: 'filter[' + id + ']', value: value }); } //Emit filter update event this.filterObservable.next(); }; FilterService.prototype.getFilterValue = function (id) { var filter = this.activeFilters.find(function (f) { return f.id === id; }); return filter ? filter.value : null; }; FilterService.prototype.applyFilter = function () { console.log('[FilterService::applyFilter] - Applying filters', this.activeFilters); this.filterChange.next(this.activeFilters); }; FilterService.prototype.getAppliedFilters = function (includeSidePanel) { if (includeSidePanel === void 0) { includeSidePanel = false; } if (includeSidePanel) { var arr = this.getFiltersFromUrl(); arr = arr.concat(this.activeFilters); //remove duplicates arr = arr .filter(function (thing, index, self) { return self.findIndex(function (t) { return t.id === thing.id; }) === index; }); return arr; } else { return this.activeFilters; } }; FilterService.prototype.getFiltersFromUrl = function () { // TODO // This code needs to be looked at // to support in query from the expression as well var refCurrentFilter = []; if (this.route.snapshot.queryParams['q']) { var urlString = this.route.snapshot.queryParams['q'] .replace(' $AND ', ' ') .replace(' $OR ', ' ') .replace('(', '') .replace(')', ''); var temp_arr = urlString.split(' '); for (var i = 0; i < temp_arr.length; i++) { var arr = temp_arr[i].split(':'); if (arr[1] !== undefined) { refCurrentFilter.push({ id: arr[0], paramKey: 'filter[' + arr[0] + ']', value: arr[1] }); } } ; } //active filter will have the transient filters //witgroup and space are permanent filters return refCurrentFilter.filter(function (f) { return f.id === 'typegroup.name' || f.id === 'space' || f.id === 'iteration'; }); }; FilterService.prototype.clearFilters = function (keys) { if (keys === void 0) { keys = []; } if (keys.length) { this.activeFilters = this.activeFilters.filter(function (f) { return keys.indexOf(f.id) > -1; }); } else { this.activeFilters = []; } }; /** * getFilters - Fetches all the available filters * @param apiUrl - The url to get list of all filters * @return Observable of FilterModel[] - Array of filters */ FilterService.prototype.getFilters = function () { var _this = this; return this.spaces.current.switchMap(function (space) { if (space) { var apiUrl = space.links.filters; return _this.http .get(apiUrl) .map(function (response) { return response.json().data; }) .catch(function (error) { console.log('API returned error: ', error.message); return Observable.throw('Error - [FilterService - getFilters]' + error.message); }); } else { return Observable.of([]); } }); }; /** * getFilters - Fetches all the available filters * @param apiUrl - The url to get list of all filters * @return Observable of FilterModel[] - Array of filters */ FilterService.prototype.getFilters2 = function (apiUrl) { return this.http .get(apiUrl) .map(function (response) { return response.json().data; }) .catch(function (error) { console.log('API returned error: ', error.message); return Observable.throw('Error - [FilterService - getFilters]' + error.message); }); }; FilterService.prototype.returnFilters = function () { return this.filters; }; /** * Usage: to check if the workitem matches with current applied filter or not. * TODO: Make this function better and smarter * NOTE: To add a new filter you have to do nothing here, just update the filtertoWorkItemMap * @param WorkItem - workItem * @returns boolean */ FilterService.prototype.doesMatchCurrentFilter = function (workItem) { var _this = this; var refCurrentFilter = this.getFiltersFromUrl(); //concat both arrays refCurrentFilter = refCurrentFilter.concat(this.activeFilters); console.log('***refCurrentFilter = ', refCurrentFilter); //remove duplicates refCurrentFilter = refCurrentFilter .filter(function (thing, index, self) { return self.findIndex(function (t) { return t.id === thing.id; }) === index; }); return refCurrentFilter.every(function (filter) { if (filter.id && Object.keys(_this.filtertoWorkItemMap).indexOf(filter.id) > -1) { var currentAttr_1 = workItem; return _this.filtertoWorkItemMap[filter.id].every(function (attr, map_index) { console.log('****** attr = ', attr); console.log('****** map_index = ', map_index); console.log('****** filter value = ', filter.value); if (Array.isArray(attr)) { if (Array.isArray(currentAttr_1)) { var innerAttr = currentAttr_1; return currentAttr_1.some(function (item) { return item[attr[0]] == filter.value; }); } else { return false; } } else if (currentAttr_1[attr]) { currentAttr_1 = currentAttr_1[attr]; if (map_index === _this.filtertoWorkItemMap[filter.id].length - 1 && currentAttr_1 != filter.value) { return false; } else { return true; } } else { return false; } }); } return true; }); }; /** * Take the existing query and simply AND it with provided options * @param existingQuery * @param options */ FilterService.prototype.constructQueryURL = function (existingQuery, options) { var _this = this; var processedObject = ''; // If onptions has any length enclose processedObject with () if (Object.keys(options).length > 1) { processedObject = '(' + Object.keys(options).map(function (key) { return typeof (options[key]) !== 'string' ? key + ':' + options[key] : options[key].split(',').map(function (val) { return key + ':' + val; }).join(' ' + _this.and_notation + ' '); }).join(' ' + this.and_notation + ' ') + ')'; } else if (Object.keys(options).length === 1) { processedObject = Object.keys(options).map(function (key) { return typeof (options[key]) !== 'string' ? key + ':' + options[key] : options[key].split(',').map(function (val) { return key + ':' + val; }).join(' ' + _this.and_notation + ' '); }).join(' ' + this.and_notation + ' '); } else { return decodeURIComponent(existingQuery); } // Check if the existing query is empty // Then return processedObject if (existingQuery === '') { return processedObject; } else { // Decode existing URL var decodedURL = decodeURIComponent(existingQuery); // Check if there is any composite query in existing one if (decodedURL.indexOf(this.and_notation) > -1 || decodedURL.indexOf(this.or_notation) > -1) { // Check if existing query is a group i.e. enclosed if (decodedURL[0] != '(' || decodedURL[decodedURL.length - 1] != ')') { // enclose it with () decodedURL = '(' + decodedURL + ')'; } } // Add the query from option with AND operation return '(' + decodedURL + ' ' + this.and_notation + ' ' + processedObject + ')'; } }; /** * * @param key The value is the object key like 'workitem_type', 'iteration' etc * @param compare The values are * FilterService::equal_notation', * FilterService::not_equal_notation', * FilterService::not_equal_notation', * FilterService::in_notation', * FilterService::not_in_notation' * @param value string or array of string of values (in case of IN or NOT IN) */ FilterService.prototype.queryBuilder = function (key, compare, value) { if (this.compare_notations.indexOf(compare.trim()) == -1) { throw new Error('Not a valid compare notation'); } var op = {}; op[key.trim()] = {}; if (Array.isArray(value)) { op[key.trim()][compare.trim()] = value.map(function (v) { return v.trim(); }); } else { op[key.trim()][compare.trim()] = value.trim(); } return op; }; /** * * @param existingQueryObject * @param join The values are * FilterService::and_notation, * FilterService::or_notation * @param newQueryObject */ FilterService.prototype.queryJoiner = function (existingQueryObject, join, newQueryObject) { if (this.join_notations.indexOf(join.trim()) == -1) { throw new Error('Not a valid compare notation'); } // existingQueryObject is empty if (!Object.keys(existingQueryObject).length) { if (Object.keys(newQueryObject).length) { if (this.join_notations.indexOf(Object.keys(newQueryObject)[0]) > -1) { return newQueryObject; } else { var op = {}; op[this.or_notation] = [newQueryObject]; return op; } } else { return {}; } } else { // If existingObject is not empty var existingJoiner = Object.keys(existingQueryObject)[0]; // If existing joiner is not valid if (this.join_notations.indexOf(existingJoiner) == -1) { throw new Error('Existing query object is invalid without a joiner in root'); } // If new object is empty then return existingQueryObject if (!Object.keys(newQueryObject).length) { return existingQueryObject; } var newJoiner = Object.keys(newQueryObject)[0]; // If new object has join_notation as root if (this.join_notations.indexOf(newJoiner) > -1) { // If new joiner existing joiner and given joiner is same // put all of them under one joiner if (join === newJoiner && join === existingJoiner) { var op = {}; op[join] = existingQueryObject[join].concat(newQueryObject[join]); return op; } else if (existingQueryObject[existingJoiner].length === 1 && newQueryObject[newJoiner].length === 1) { var op = {}; op[join] = existingQueryObject[existingJoiner].concat(newQueryObject[newJoiner]); return op; } else if (existingQueryObject[existingJoiner].length === 1) { var op = {}; if (newJoiner === join) { op[join] = existingQueryObject[existingJoiner].concat(newQueryObject[newJoiner]); } else { op[join] = existingQueryObject[existingJoiner].concat([ newQueryObject ]); } return op; } else if (newQueryObject[newJoiner].length === 1) { var op = {}; if (existingJoiner === join) { op[join] = existingQueryObject[existingJoiner].concat(newQueryObject[newJoiner]); } else { op[join] = [ existingQueryObject ].concat(newQueryObject[newJoiner]); } return op; } else { var op = {}; op[join] = [ existingQueryObject, newQueryObject ]; return op; } } else { if (join === existingJoiner) { existingQueryObject[join].push(newQueryObject); return existingQueryObject; } else { var op = {}; // If existingQueryObject has only one item in the array if (existingQueryObject[existingJoiner].length === 1) { op[join] = existingQueryObject[existingJoiner].concat([ newQueryObject ]); } else { op[join] = [ existingQueryObject, newQueryObject ]; } return op; } } } }; /** * Query string to JSON conversion */ FilterService.prototype.queryToJson = function (query, first_level) { var _this = this; if (first_level === void 0) { first_level = true; } var temp = [], p_count = 0, p_start = -1, new_str = '', output = {}; for (var i = 0; i < query.length; i++) { if (query[i] === '(') { if (p_start < 0) p_start = i; p_count += 1; } if (p_start === -1) { new_str += query[i]; } if (query[i] === ')') { p_count -= 1; } if (p_start >= 0 && p_count === 0) { temp.push(query.substring(p_start + 1, i)); new_str += '__temp__'; p_start = -1; } } temp.reverse(); var arr = new_str.split(this.or_notation); if (arr.length > 1) { output[this.or_notation] = arr.map(function (item) { item = item.trim(); if (item == '__temp__') { item = temp.pop(); } while (item.indexOf('__temp__') > -1) { item = item.replace('__temp__', temp.pop()); } return _this.queryToJson(item, false); }); } else { arr = new_str.split(this.and_notation); if (arr.length > 1) { output[this.and_notation] = arr.map(function (item) { if (item.trim() == '__temp__') { item = temp.pop(); } return _this.queryToJson(item, false); }); } else { var dObj = {}; while (new_str.indexOf('__temp__') > -1) { new_str = new_str.replace('__temp__', temp.pop()); } if (new_str.indexOf(this.and_notation) > -1 || new_str.indexOf(this.or_notation) > -1) { return this.queryToJson(new_str, false); } var keyIndex = -1; var splitter = ''; for (var i = 0; i < new_str.length; i++) { if (new_str[i] === ':' || new_str[i] === '!') { splitter = new_str[i]; keyIndex = i; break; } } var key = new_str.substring(0, keyIndex).trim(); var value = new_str.substring(keyIndex + 1).trim(); var val_arr_1 = value.split(',').map(function (i) { return i.trim(); }); dObj[key] = {}; if (splitter === '!') { if (val_arr_1.length > 1) { dObj[key][this.not_in_notation] = val_arr_1; } else { if (Object.keys(this.special_keys).findIndex(function (k) { return k === val_arr_1[0]; }) > -1) { dObj[key][this.not_equal_notation] = this.special_keys[val_arr_1[0]]; } else if (key === 'title') { dObj[key][this.sub_str_notation] = val_arr_1[0]; } else { dObj[key][this.not_equal_notation] = val_arr_1[0]; } } } else if (splitter === ':') { if (val_arr_1.length > 1) { dObj[key][this.in_notation] = val_arr_1; } else { if (Object.keys(this.special_keys).findIndex(function (k) { return k === val_arr_1[0]; }) > -1) { dObj[key][this.equal_notation] = this.special_keys[val_arr_1[0]]; } else if (key === 'title') { dObj[key][this.sub_str_notation] = val_arr_1[0]; } else { dObj[key][this.equal_notation] = val_arr_1[0]; } } } if (first_level) { output[this.or_notation] = [dObj]; } else { return dObj; } } } return output; }; FilterService.prototype.jsonToQuery = function (obj) { var _this = this; var key = Object.keys(obj)[0]; // key will be AND or OR var value = obj[key]; return '(' + value.map(function (item) { if (Object.keys(item)[0] == _this.and_notation || Object.keys(item)[0] == _this.or_notation) { return _this.jsonToQuery(item); } else { var data_key = Object.keys(item)[0]; var data = item[data_key]; var conditional_operator = Object.keys(data)[0]; var splitter = ''; switch (conditional_operator) { case _this.equal_notation: splitter = ':'; return data_key + splitter + data[conditional_operator]; case _this.not_equal_notation: splitter = '!'; return data_key + splitter + data[conditional_operator]; case _this.in_notation: splitter = ':'; return data_key + splitter + data[conditional_operator].join(); case _this.not_in_notation: splitter = '!'; return data_key + splitter + data[conditional_operator].join(); case _this.sub_str_notation: splitter = ':'; return data_key + splitter + data[conditional_operator]; } } }) .join(' ' + key + ' ') + ')'; }; /** * This decodes a key query term value from a given query string. It is used to * shortcut the parsing of the query string to get context info from it. Currently, * it is used when getting the context info from an existing query to give context * to a following UX flow. This only supports a very narrow usecase currently, but * may be extended later. * * @param queryString search/filter query string. * @param key key of the term for which we look for the value. */ FilterService.prototype.getConditionFromQuery = function (queryString, key) { if (queryString) { var decodedQuery = this.queryToJson(queryString); // we ignore non-AND queries for now, might want to extend that later. if (!decodedQuery['$AND']) { console.log('The current query is not supported by getConditionFromQuery() (non-AND query): ' + queryString); return undefined; } else { var terms = decodedQuery['$AND']; if (terms || !Array.isArray(terms)) { for (var i = 0; i < terms.length; i++) { var thisTerm = terms[i]; if (thisTerm && thisTerm[key]) { // format of value: {$EQ: "value"}, if not found, value remains undefined return thisTerm[key]['$EQ']; } } console.log('Condition key not found in query: ' + key + ', query= ' + queryString); return undefined; } else { console.log('The current query is not supported by getConditionFromQuery() (bad format): ' + queryString); // use standard non-context create dialog return undefined; } } } }; // Temporary function to deal with single level $AND operator FilterService.prototype.queryToFlat = function (query) { return query.replace(/^\((.+)\)$/, "$1") .split(this.and_notation).map(function (item, index) { return { field: item.split(':')[0].trim(), index: index, value: item.split(':')[1].trim() }; }); }; FilterService.prototype.flatToQuery = function (arr) { var _this = this; var query = {}; arr.forEach(function (item) { var newQuery = _this.queryBuilder(item.field, _this.equal_notation, item.value); query = _this.queryJoiner(query, _this.and_notation, newQuery); }); return query; }; FilterService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ FilterService.ctorParameters = function () { return [ { type: HttpService, }, { type: Spaces, }, { type: ActivatedRoute, }, { type: undefined, decorators: [{ type: Inject, args: [WIT_API_URL,] },] }, ]; }; return FilterService; }()); export { FilterService }; //# sourceMappingURL=filter.service.js.map