public/lib/filters-service.js (258 lines of code) (raw):

import angular from 'angular'; import _ from 'lodash'; import './date-service'; import './trusted-html'; angular.module('wfFiltersService', ['wfDateService', 'wfTrustedHtml']) .factory('wfFiltersService', ['$rootScope', '$location', '$state', 'wfDateParser', 'wfFormatDateTimeFilter', 'wfPreferencesService', 'wfTrustedHtmlFilter', function($rootScope, $location, $state, wfDateParser, wfFormatDateTimeFilter, wfPreferencesService, wfTrustedHtmlFilter) { class FiltersService { attachListeners() { var self = this; $rootScope.$on('filtersChanged.prodOffice', function(event, data) { self.update('prodOffice', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.content-type', function(event, data) { self.update('content-type', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.article-format', function(event, data) { self.update('article-format', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.atom-type', function(event, data) { self.update('atom-type', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.section', function(event, data) { self.update('section', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.state', function(event, data) { self.update('state', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.status', function(event, data) { self.update('status', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.flags', function(event, data) { self.update('flags', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.deadline', function (event, data) { self.update('deadline', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.created', function(event, data) { self.update('created', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.desk', function(event, data) { if (data !== -1) { self.update('desk', data); } else { self.update('desk', null); } // Desk ignored so no need to request content }); $rootScope.$on('filtersChanged.touched', function(event, data) { self.update('touched', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.assigneeEmail', function(event, data) { self.update('assigneeEmail', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.trashed', function(event, data) { self.update('trashed', data); $rootScope.$broadcast('getContent'); }); var keywords = { "type" : "content-type", "status" : "status", "state" : "state", "who" : "assignee", "assignee" : "assignee", "assignedto" : "assignee" }; var savedFilters = null; function enterSearchMode(data) { savedFilters = _.clone(self.filters); self.clearAll(true, true); $rootScope.$broadcast("search-mode.enter"); } function exitSearchMode(data) { self.clearAll(true, true); if(savedFilters != null) { _.forOwn(savedFilters, (value, key) => self.update(key, value)); } $rootScope.$broadcast("search-mode.exit"); } $rootScope.$on('filtersChanged.freeText', function(event, data) { var newValue = data.newValue; var oldValue = data.oldValue; if(oldValue == null && newValue != null) { enterSearchMode(data); } else if(newValue == null && oldValue != null) { exitSearchMode(data); } if(newValue != null) { var rest = newValue.replace(/\s*([A-Za-z-]+):(\S+)\s*/g, (match, field, value) => { if(_.has(keywords, field)) { self.update(keywords[field], value, true, true); } return ""; }); self.update('text', rest, true, true); } else { self.update('text', null, true, true); } $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.incopy', function(event, data) { self.update('incopy', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.view', function(event, data) { self.update('view', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.hasPrintInfo', function(event, data) { self.update('hasPrintInfo', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.hasMainMedia', function(event, data) { self.update('hasMainMedia', data); $rootScope.$broadcast('getContent'); }); $rootScope.$on('filtersChanged.rights', function(event, data) { self.update('rights', data); $rootScope.$broadcast('getContent'); }); } init() { this.attachListeners() } constructor() { // TODO: Refactor filters service to promise based architecture to allow for deferred loading of filters based on preferences var self = this; var params = $location.search(); var setUpFilters = function (params) { var deadline = params['deadline']; self.filters = { 'status' : params['status'], 'state' : params['state'], 'section' : params['section'], 'content-type' : params['content-type'], 'atom-type' : params['atom-type'], 'deadline' : wfDateParser.parseQueryString(deadline), 'flags' : params['flags'], 'prodOffice' : params['prodOffice'], 'created' : params['created'], 'assignee' : params['assignee'], 'assigneeEmail' : params['assigneeEmail'], 'incopy' : params['incopy'], 'touched' : params['touched'], 'composerId' : params['composerId'], 'view' : params['view'], 'news-list' : params['news-list'], 'trashed' : params['trashed'], 'plan-start-date': params['plan-start-date'], 'plan-end-date' : params['plan-end-date'], 'editorId' : params['editorId'], 'hasPrintInfo' : params['hasPrintInfo'], 'hasMainMedia' : params['hasMainMedia'], 'hasAnyRights' : params['rights'], 'display-hint' : params['display-hint'], 'article-format' : params['article-format'], }; $rootScope.currentlySelectedStatusFilters = self.transformStatusList(self.filters['status']); }; setUpFilters(params); // base setting if (Object.keys(params).length === 0) { // if no params in URL attempt to load filters from user prefs wfPreferencesService.getPreference('location').then((data) => { params = data || {}; setUpFilters(params); for (var key in params) { if (params.hasOwnProperty(key)) { self.update(key, params[key], true); } } $rootScope.$broadcast('filtersChanged.fromPreferences'); $rootScope.$broadcast('getContent'); }, () => { setUpFilters(params); }); } else { setUpFilters(params); } } update(key, value, doNotUpdateprefs, doNotUpdateUrl) { if ($state.is('dashboard')) { if (key === 'news-list' || key === 'plan-start-date' || key === 'plan-end-date') { value = null; } } if (value !== null && (value === undefined || value.length === 0)) { // empty String or Array value = null; // Remove query param } if (Array.isArray(value)) { value = value.join(','); } if (key === 'deadline') { var dateStr = wfDateParser.setQueryString(value); this.filters[key] = dateStr; doNotUpdateUrl || $location.search(key, dateStr); } else { this.filters[key] = value; doNotUpdateUrl || $location.search(key, value); if (key == "status") { $rootScope.currentlySelectedStatusFilters = this.transformStatusList(value); } } if (!doNotUpdateprefs) { wfPreferencesService.setPreference('location', this.sanitizeFilters(this.filters)); } this.postUpdate(); } postUpdate() { if (this.filters['composerId'] || this.filters['text'] || this.filters['editorId']) { $rootScope.$broadcast("search-mode.enter"); } else { $rootScope.$broadcast("search-mode.exit"); } } get(key) { return this.filters[key]; } getAll() { return this.filters; } clearAll(noPrefs, noUI) { _.forOwn(this.filters, (value, key) => { this.update(key, null, noPrefs); }); if(!noUI) { $rootScope.$broadcast("filters.clearAll"); } } /** * Remove null or undefined keys from filters object for storage in user prefs * @param filters * @returns $scope.filter.namespace */ sanitizeFilters (filters) { Object.keys(filters).map((key) => { if (filters[key] === null || filters[key] === undefined) { delete filters[key]; } }); return filters; } /** * Transform a comma separated list of statues for use by the angular interface * @param list * @returns {U[]} */ transformStatusList (list) { return list ? list.split(',') : list; } } return new FiltersService(); }]) .run(['wfFiltersService', function (wfFiltersService) { wfFiltersService.init(); }]);