From 1d4af12f57e30b55bca037a737b07e4dc286ffce Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Mon, 15 Jul 2013 10:52:57 -0700 Subject: [PATCH] Added the ability to toggle filters --- dashboards/default.json | 85 ++++++++++++++---------------- js/services.js | 97 +++++++++++++++++++---------------- panels/filtering/module.html | 25 ++++++--- panels/filtering/module.js | 10 ++-- panels/timepicker/module.html | 16 ++++-- panels/timepicker/module.js | 29 +++++++---- partials/dasheditor.html | 8 +-- 7 files changed, 151 insertions(+), 119 deletions(-) diff --git a/dashboards/default.json b/dashboards/default.json index 0302eecbb64..0b59b1375db 100644 --- a/dashboards/default.json +++ b/dashboards/default.json @@ -2,7 +2,12 @@ "title": "Logstash Search", "services": { "query": { - "idQueue": [], + "idQueue": [ + 1, + 2, + 3, + 4 + ], "list": { "0": { "query": "*", @@ -16,14 +21,18 @@ ] }, "filter": { - "idQueue": [], + "idQueue": [ + 1, + 2 + ], "list": { "0": { - "from": "2013-07-15T03:54:27.219Z", - "to": "2013-07-15T04:09:27.219Z", + "from": "2013-07-15T16:50:45.363Z", + "to": "2013-07-15T17:50:45.363Z", "field": "@timestamp", "type": "time", "mandate": "must", + "active": true, "alias": "", "id": 0 } @@ -63,7 +72,7 @@ "7d", "30d" ], - "timespan": "15m", + "timespan": "1h", "timefield": "@timestamp", "timeformat": "", "refresh": { @@ -125,6 +134,26 @@ } ] }, + { + "title": "Filters", + "height": "50px", + "editable": true, + "collapse": true, + "collapsable": true, + "panels": [ + { + "loading": false, + "error": false, + "span": 12, + "editable": true, + "group": [ + "default" + ], + "type": "filtering", + "status": "Experimental" + } + ] + }, { "title": "Graph", "height": "350px", @@ -134,7 +163,7 @@ "panels": [ { "loading": false, - "span": 9, + "span": 12, "editable": true, "group": [ "default" @@ -152,14 +181,14 @@ "value_field": null, "auto_int": true, "resolution": 100, - "interval": "10s", + "interval": "30s", "fill": 3, "linewidth": 3, "timezone": "browser", "spyable": true, "zoomlinks": true, "bars": true, - "stack": true, + "stack": false, "points": false, "lines": false, "legend": true, @@ -167,44 +196,6 @@ "y-axis": true, "percentage": false, "interactive": true - }, - { - "loading": false, - "error": false, - "span": 3, - "editable": true, - "group": [ - "default" - ], - "type": "filtering", - "status": "Stable", - "query": [ - { - "query": "*", - "label": "Query" - } - ], - "mode": "count", - "time_field": "@timestamp", - "value_field": null, - "auto_int": true, - "resolution": 100, - "interval": "5m", - "fill": 3, - "linewidth": 3, - "timezone": "browser", - "spyable": true, - "zoomlinks": true, - "bars": true, - "stack": true, - "points": false, - "lines": false, - "legend": true, - "x-axis": true, - "y-axis": true, - "percentage": false, - "interactive": true, - "title": "Filters" } ] }, @@ -273,6 +264,6 @@ "index": { "interval": "day", "pattern": "[logstash-]YYYY.MM.DD", - "default": "MISSING_INDEX" + "default": "logstash-*" } } \ No newline at end of file diff --git a/js/services.js b/js/services.js index f7e797fef40..87eefcb0bb0 100644 --- a/js/services.js +++ b/js/services.js @@ -300,6 +300,7 @@ angular.module('kibana.services', []) // If an id is passed, the filter at that id is updated this.set = function(filter,id) { _.defaults(filter,{mandate:'must'}) + filter.active = true; if(!_.isUndefined(id)) { if(!_.isUndefined(self.list[id])) { _.extend(self.list[id],filter); @@ -328,16 +329,18 @@ angular.module('kibana.services', []) // A default match all filter, just in case there are no other filters var bool = ejs.BoolFilter().must(ejs.MatchAllFilter()); _.each(ids,function(id) { - switch(self.list[id].mandate) - { - case 'mustNot': - bool = bool.mustNot(self.getEjsObj(id)); - break; - case 'should': - bool = bool.should(self.getEjsObj(id)); - break; - default: - bool = bool.must(self.getEjsObj(id)); + if(self.list[id].active) { + switch(self.list[id].mandate) + { + case 'mustNot': + bool = bool.mustNot(self.getEjsObj(id)); + break; + case 'should': + bool = bool.should(self.getEjsObj(id)); + break; + default: + bool = bool.must(self.getEjsObj(id)); + } } }) return bool; @@ -348,6 +351,9 @@ angular.module('kibana.services', []) } this.toEjsObj = function (filter) { + if(!filter.active) { + return false + } switch(filter.type) { case 'time': @@ -377,8 +383,8 @@ angular.module('kibana.services', []) } } - this.getByType = function(type) { - return _.pick(self.list,self.idsByType(type)) + this.getByType = function(type,inactive) { + return _.pick(self.list,self.idsByType(type,inactive)) } this.removeByType = function(type) { @@ -389,13 +395,13 @@ angular.module('kibana.services', []) return ids; } - this.idsByType = function(type) { - return _.pluck(_.where(self.list,{type:type}),'id') + this.idsByType = function(type,inactive) { + return _.pluck(_.where(self.list,{type:type,active:(inactive ? false:true)}),'id') } // This special function looks for all time filters, and returns a time range according to the mode this.timeRange = function(mode) { - var _t = _.where(self.list,{type:'time'}) + var _t = _.where(self.list,{type:'time',active:true}) if(_t.length == 0) { return false; } @@ -526,11 +532,43 @@ angular.module('kibana.services', []) $rootScope.$broadcast('refresh') } } else { - self.indices = [self.current.index.pattern] + self.indices = [self.current.index.default] $rootScope.$broadcast('refresh') } } + this.dash_load = function(dashboard) { + timer.cancel_all(); + + if(dashboard.index.interval === 'none') { + self.indices = [dashboard.index.default] + } + + self.current = dashboard; + + // Ok, now that we've setup the current dashboard, we can inject our services + query = $injector.get('query'); + filterSrv = $injector.get('filterSrv') + + if(dashboard.index.interval !== 'none' && filterSrv.idsByType('time').length == 0) { + self.refresh(); + } + + return true; + } + + this.gist_id = function(string) { + if(self.is_gist(string)) + return string.match(gist_pattern)[0].replace(/.*\//, ''); + } + + this.is_gist = function(string) { + if(!_.isUndefined(string) && string != '' && !_.isNull(string.match(gist_pattern))) + return string.match(gist_pattern).length > 0 ? true : false; + else + return false + } + this.to_file = function() { var blob = new Blob([angular.toJson(self.current,true)], {type: "application/json;charset=utf-8"}); // from filesaver.js @@ -699,33 +737,6 @@ angular.module('kibana.services', []) }); } - this.dash_load = function(dashboard) { - timer.cancel_all(); - - if(dashboard.index.interval === 'none') { - self.indices = [dashboard.index.pattern] - } - - self.current = dashboard; - - // Ok, now that we've setup the current dashboard, we can inject our services - query = $injector.get('query'); - filterSrv = $injector.get('filterSrv') - return true; - } - - this.gist_id = function(string) { - if(self.is_gist(string)) - return string.match(gist_pattern)[0].replace(/.*\//, ''); - } - - this.is_gist = function(string) { - if(!_.isUndefined(string) && string != '' && !_.isNull(string.match(gist_pattern))) - return string.match(gist_pattern).length > 0 ? true : false; - else - return false - } - }) .service('keylistener', function($rootScope) { var keys = []; diff --git a/panels/filtering/module.html b/panels/filtering/module.html index 7413d5d7291..21ce51ffd47 100644 --- a/panels/filtering/module.html +++ b/panels/filtering/module.html @@ -1,7 +1,11 @@ -
-
- {{filterSrv.list[id].type}} ({{filterSrv.list[id].mandate}}) - +
+
+
+ {{filterSrv.list[id].type}} {{filterSrv.list[id].mandate}} + + + +
+
    +
  • {{key}} : {{value}}
  • +
-
    -
  • {{key}} : {{value}}
  • -
\ No newline at end of file diff --git a/panels/filtering/module.js b/panels/filtering/module.js index 7b30aeb304a..4c70615a617 100644 --- a/panels/filtering/module.js +++ b/panels/filtering/module.js @@ -26,6 +26,11 @@ angular.module('kibana.filtering', []) dashboard.refresh(); } + $scope.toggle = function(id) { + filterSrv.list[id].active = !filterSrv.list[id].active; + dashboard.refresh(); + } + $scope.refresh = function(query) { $rootScope.$broadcast('refresh') } @@ -34,9 +39,8 @@ angular.module('kibana.filtering', []) $rootScope.$broadcast('render') } - $scope.stripped = function(filter) { - var filter = _.omit(filter,'type','id','alias','mandate') - return filter + $scope.show_key = function(key) { + return !_.contains(['type','id','alias','mandate','active'],key) } }); \ No newline at end of file diff --git a/panels/timepicker/module.html b/panels/timepicker/module.html index 2d31d62b3b2..2c89289a0f4 100644 --- a/panels/timepicker/module.html +++ b/panels/timepicker/module.html @@ -1,5 +1,5 @@ -
+
@@ -47,17 +47,27 @@
+
+
+
+

No time filter present

+
+
+
-
+
Relative | Absolute | Since - | + | Auto-refresh every {{panel.refresh.interval}}s.
+
\ No newline at end of file diff --git a/panels/timepicker/module.js b/panels/timepicker/module.js index 0bce82e4270..1975f416b1f 100644 --- a/panels/timepicker/module.js +++ b/panels/timepicker/module.js @@ -44,7 +44,7 @@ angular.module('kibana.timepicker', []) // Private refresh interval that we can use for view display without causing // unnecessary refreshes during changes $scope.refresh_interval = $scope.panel.refresh.interval - + $scope.filterSrv = filterSrv; // Init a private time object with Date() objects depending on mode switch($scope.panel.mode) { @@ -68,7 +68,12 @@ angular.module('kibana.timepicker', []) break; } $scope.time.field = $scope.panel.timefield; - $scope.time_apply(); + // These 3 statements basicly do everything time_apply() does + set_timepicker($scope.time.from,$scope.time.to) + update_panel() + set_time_filter($scope.time) + dashboard.refresh(); + // Start refresh timer if enabled if ($scope.panel.refresh.enable) @@ -76,17 +81,19 @@ angular.module('kibana.timepicker', []) // In case some other panel broadcasts a time, set us to an absolute range $scope.$on('refresh', function() { - var time = filterSrv.timeRange('min') + if(filterSrv.idsByType('time').length > 0) { + var time = filterSrv.timeRange('min') - if($scope.time.from.diff(moment.utc(time.from)) != 0 - || $scope.time.to.diff(moment.utc(time.to)) != 0) - { - $scope.panel.mode = 'absolute'; + if($scope.time.from.diff(moment.utc(time.from)) != 0 + || $scope.time.to.diff(moment.utc(time.to)) != 0) + { + $scope.set_mode('absolute'); - // These 3 statements basicly do everything time_apply() does - set_timepicker(moment(time.from),moment(time.to)) - $scope.time = $scope.time_calc(); - update_panel() + // These 3 statements basicly do everything time_apply() does + set_timepicker(moment(time.from),moment(time.to)) + $scope.time = $scope.time_calc(); + update_panel() + } } }); } diff --git a/partials/dasheditor.html b/partials/dasheditor.html index d6773959e5b..83c61ed8188 100644 --- a/partials/dasheditor.html +++ b/partials/dasheditor.html @@ -36,12 +36,12 @@
Timestamping
-
-
Index pattern Absolutes in []
+
+
Index pattern Absolutes in []
-
Failover Index If index not found
+
Default Index If index not found
@@ -87,5 +87,5 @@
\ No newline at end of file