define([
'angular', 'lodash', 'config', 'kbn'
], function (angular, _, config, kbn) {
'use strict'; var module = angular.module('kibana.services'); module.service('filterSrv', function(dashboard, ejsResource, $rootScope, $timeout) { // Create an object to hold our service state on the dashboard dashboard.current.services.filter = dashboard.current.services.filter || {}; // Defaults for it var _d = { list : {}, ids : [] }; // For convenience var ejs = ejsResource(config.elasticsearch); // Save a reference to this var self = this; // Call this whenever we need to reload the important stuff this.init = function() { // Populate defaults _.defaults(dashboard.current.services.filter,_d); _.each(dashboard.current.services.filter.list,function(f) { self.set(f,f.id,true); }); }; this.ids = function() { return dashboard.current.services.filter.ids; }; this.list = function() { return dashboard.current.services.filter.list; }; // This is used both for adding filters and modifying them. // If an id is passed, the filter at that id is updated this.set = function(filter,id,noRefresh) { var _r; _.defaults(filter,{ mandate:'must', active: true }); if(!_.isUndefined(id)) { if(!_.isUndefined(dashboard.current.services.filter.list[id])) { _.extend(dashboard.current.services.filter.list[id],filter); _r = id; } else { _r = false; } } else { if(_.isUndefined(filter.type)) { _r = false; } else { var _id = nextId(); var _filter = { alias: '', id: _id, mandate: 'must' }; _.defaults(filter,_filter); dashboard.current.services.filter.list[_id] = filter; dashboard.current.services.filter.ids.push(_id); _r = _id; } } if(!$rootScope.$$phase) { $rootScope.$apply(); } if(noRefresh !== true) { $timeout(function(){ dashboard.refresh(); },0); } dashboard.current.services.filter.ids = dashboard.current.services.filter.ids = _.intersection(_.map(dashboard.current.services.filter.list, function(v,k){return parseInt(k,10);}),dashboard.current.services.filter.ids); $rootScope.$broadcast('filter'); return _r; }; this.remove = function(id,noRefresh) { var _r; if(!_.isUndefined(dashboard.current.services.filter.list[id])) { delete dashboard.current.services.filter.list[id]; // This must happen on the full path also since _.without returns a copy dashboard.current.services.filter.ids = dashboard.current.services.filter.ids = _.without(dashboard.current.services.filter.ids,id); _r = true; } else { _r = false; } if(!$rootScope.$$phase) { $rootScope.$apply(); } if(noRefresh !== true) { $timeout(function(){ dashboard.refresh(); },0); } $rootScope.$broadcast('filter'); return _r; }; this.removeByType = function(type,noRefresh) { var ids = self.idsByType(type); _.each(ids,function(id) { self.remove(id,true); }); if(noRefresh !== true) { $timeout(function(){ dashboard.refresh(); },0); } return ids; }; this.getBoolFilter = function(ids) { var bool = ejs.BoolFilter(); // there is no way to introspect the BoolFilter and find out if it has a filter. We must keep note. var added_a_filter = false; _.each(ids,function(id) { if(dashboard.current.services.filter.list[id].active) { added_a_filter = true; switch(dashboard.current.services.filter.list[id].mandate) { case 'mustNot': bool.mustNot(self.getEjsObj(id)); break; case 'either': bool.should(self.getEjsObj(id)); break; default: bool.must(self.getEjsObj(id)); } } }); // add a match filter so we'd get some data if (!added_a_filter) { bool.must(ejs.MatchAllFilter()); } return bool; }; this.getEjsObj = function(id) { return self.toEjsObj(dashboard.current.services.filter.list[id]); }; this.toEjsObj = function (filter) { if(!filter.active) { return false; } switch(filter.type) { case 'time': var _f = ejs.RangeFilter(filter.field).from(kbn.parseDate(filter.from).valueOf()); if(!_.isUndefined(filter.to)) { _f = _f.to(kbn.parseDate(filter.to).valueOf()); } return _f; case 'range': return ejs.RangeFilter(filter.field) .from(filter.from) .to(filter.to); case 'querystring': return ejs.QueryFilter(ejs.QueryStringQuery(filter.query)).cache(true); case 'field': return ejs.QueryFilter(ejs.QueryStringQuery(filter.field+":("+filter.query+")")).cache(true); case 'terms': return ejs.TermsFilter(filter.field,filter.value); case 'exists': return ejs.ExistsFilter(filter.field); case 'missing': return ejs.MissingFilter(filter.field); default: return false; } }; this.getByType = function(type,inactive) { return _.pick(dashboard.current.services.filter.list,self.idsByType(type,inactive)); }; this.idsByType = function(type,inactive) { var _require = inactive ? {type:type} : {type:type,active:true}; return _.pluck(_.where(dashboard.current.services.filter.list,_require),'id'); }; // TOFIX: Error handling when there is more than one field this.timeField = function() { return _.pluck(self.getByType('time'),'field'); }; // Parse is used when you need to know about the raw filter this.timeRange = function(parse) { var _t = _.last(_.where(dashboard.current.services.filter.list,{type:'time',active:true})); if(_.isUndefined(_t)) { return false; } if(parse === false) { return { from: _t.from, to: _t.to }; } else { var _from = _t.from, _to = _t.to || new Date(); return { from : kbn.parseDate(_from), to : kbn.parseDate(_to) }; } }; var nextId = function() { var idCount = dashboard.current.services.filter.ids.length; if(idCount > 0) { // Make a sorted copy of the ids array var ids = _.sortBy(_.clone(dashboard.current.services.filter.ids),function(num){ return num; }); return kbn.smallestMissing(ids); } else { // No ids currently in list return 0; } }; // Now init self.init(); });
});