filterSrv.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. define([
  2. 'angular',
  3. 'underscore',
  4. 'config',
  5. 'kbn'
  6. ], function (angular, _, config, kbn) {
  7. 'use strict';
  8. var module = angular.module('kibana.services');
  9. module.service('filterSrv', function(dashboard, ejsResource, $rootScope, $timeout) {
  10. // Create an object to hold our service state on the dashboard
  11. dashboard.current.services.filter = dashboard.current.services.filter || {};
  12. // Defaults for it
  13. var _d = {
  14. idQueue : [],
  15. list : {},
  16. ids : []
  17. };
  18. // For convenience
  19. var ejs = ejsResource(config.elasticsearch);
  20. var _f = dashboard.current.services.filter;
  21. // Save a reference to this
  22. var self = this;
  23. // Call this whenever we need to reload the important stuff
  24. this.init = function() {
  25. // Populate defaults
  26. _.defaults(dashboard.current.services.filter,_d);
  27. // Accessors
  28. self.list = dashboard.current.services.filter.list;
  29. self.ids = dashboard.current.services.filter.ids;
  30. _f = dashboard.current.services.filter;
  31. _.each(self.list,function(f) {
  32. self.set(f,f.id,true);
  33. });
  34. // Date filters hold strings now, not dates
  35. /*
  36. _.each(self.getByType('time',true),function(time) {
  37. self.list[time.id].from = new Date(time.from);
  38. self.list[time.id].to = new Date(time.to);
  39. });
  40. */
  41. };
  42. // This is used both for adding filters and modifying them.
  43. // If an id is passed, the filter at that id is updated
  44. this.set = function(filter,id,noRefresh) {
  45. var _r;
  46. _.defaults(filter,{
  47. mandate:'must',
  48. active: true
  49. });
  50. if(!_.isUndefined(id)) {
  51. if(!_.isUndefined(self.list[id])) {
  52. _.extend(self.list[id],filter);
  53. _r = id;
  54. } else {
  55. _r = false;
  56. }
  57. } else {
  58. if(_.isUndefined(filter.type)) {
  59. _r = false;
  60. } else {
  61. var _id = nextId();
  62. var _filter = {
  63. alias: '',
  64. id: _id,
  65. mandate: 'must'
  66. };
  67. _.defaults(filter,_filter);
  68. self.list[_id] = filter;
  69. self.ids.push(_id);
  70. _r = _id;
  71. }
  72. }
  73. if(!$rootScope.$$phase) {
  74. $rootScope.$apply();
  75. }
  76. if(noRefresh !== true) {
  77. $timeout(function(){
  78. dashboard.refresh();
  79. },0);
  80. }
  81. $rootScope.$broadcast('filter');
  82. return _r;
  83. };
  84. this.remove = function(id,noRefresh) {
  85. var _r;
  86. if(!_.isUndefined(self.list[id])) {
  87. delete self.list[id];
  88. // This must happen on the full path also since _.without returns a copy
  89. self.ids = dashboard.current.services.filter.ids = _.without(self.ids,id);
  90. _f.idQueue.unshift(id);
  91. _f.idQueue.sort(function(v,k){return v-k;});
  92. _r = true;
  93. } else {
  94. _r = false;
  95. }
  96. if(!$rootScope.$$phase) {
  97. $rootScope.$apply();
  98. }
  99. if(noRefresh !== true) {
  100. $timeout(function(){
  101. dashboard.refresh();
  102. },0);
  103. }
  104. $rootScope.$broadcast('filter');
  105. return _r;
  106. };
  107. this.removeByType = function(type,noRefresh) {
  108. var ids = self.idsByType(type);
  109. _.each(ids,function(id) {
  110. self.remove(id,true);
  111. });
  112. if(noRefresh !== true) {
  113. $timeout(function(){
  114. dashboard.refresh();
  115. },0);
  116. }
  117. return ids;
  118. };
  119. this.getBoolFilter = function(ids) {
  120. // A default match all filter, just in case there are no other filters
  121. var bool = ejs.BoolFilter().must(ejs.MatchAllFilter());
  122. var either_bool = ejs.BoolFilter().must(ejs.MatchAllFilter());
  123. _.each(ids,function(id) {
  124. if(self.list[id].active) {
  125. switch(self.list[id].mandate)
  126. {
  127. case 'mustNot':
  128. bool = bool.mustNot(self.getEjsObj(id));
  129. break;
  130. case 'either':
  131. either_bool = either_bool.should(self.getEjsObj(id));
  132. break;
  133. default:
  134. bool = bool.must(self.getEjsObj(id));
  135. }
  136. }
  137. });
  138. return bool.must(either_bool);
  139. };
  140. this.getEjsObj = function(id) {
  141. return self.toEjsObj(self.list[id]);
  142. };
  143. this.toEjsObj = function (filter) {
  144. if(!filter.active) {
  145. return false;
  146. }
  147. switch(filter.type)
  148. {
  149. case 'time':
  150. var _f = ejs.RangeFilter(filter.field).from(kbn.parseDate(filter.from).valueOf());
  151. if(!_.isUndefined(filter.to)) {
  152. _f = _f.to(filter.to.valueOf());
  153. }
  154. return _f;
  155. case 'range':
  156. return ejs.RangeFilter(filter.field)
  157. .from(filter.from)
  158. .to(filter.to);
  159. case 'querystring':
  160. return ejs.QueryFilter(ejs.QueryStringQuery(filter.query)).cache(true);
  161. case 'field':
  162. return ejs.QueryFilter(ejs.FieldQuery(filter.field,filter.query)).cache(true);
  163. case 'terms':
  164. return ejs.TermsFilter(filter.field,filter.value);
  165. case 'exists':
  166. return ejs.ExistsFilter(filter.field);
  167. case 'missing':
  168. return ejs.MissingFilter(filter.field);
  169. default:
  170. return false;
  171. }
  172. };
  173. this.getByType = function(type,inactive) {
  174. return _.pick(self.list,self.idsByType(type,inactive));
  175. };
  176. this.idsByType = function(type,inactive) {
  177. var _require = inactive ? {type:type} : {type:type,active:true};
  178. return _.pluck(_.where(self.list,_require),'id');
  179. };
  180. // TOFIX: Error handling when there is more than one field
  181. this.timeField = function() {
  182. return _.pluck(self.getByType('time'),'field');
  183. };
  184. // Parse is used when you need to know about the raw filter
  185. this.timeRange = function(parse) {
  186. var _t = _.last(_.where(self.list,{type:'time',active:true}));
  187. if(_.isUndefined(_t)) {
  188. return false;
  189. }
  190. if(parse === false) {
  191. return {
  192. from: _t.from,
  193. to: _t.to
  194. };
  195. } else {
  196. var
  197. _from = _t.from,
  198. _to = _t.to || new Date();
  199. return {
  200. from : kbn.parseDate(_from),
  201. to : kbn.parseDate(_to)
  202. };
  203. }
  204. };
  205. var nextId = function() {
  206. if(_f.idQueue.length > 0) {
  207. return _f.idQueue.shift();
  208. } else {
  209. return self.ids.length;
  210. }
  211. };
  212. // Now init
  213. self.init();
  214. });
  215. });