filterSrv.js 6.3 KB

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