Просмотр исходного кода

Refactoring query communication into service

Rashid Khan 12 лет назад
Родитель
Сommit
0d560c24e6

Разница между файлами не показана из-за своего большого размера
+ 8 - 0
common/css/bootstrap.light.min.css


+ 4 - 0
common/css/main.css

@@ -107,6 +107,10 @@
   cursor: pointer;
 }
 
+.pointer:hover {
+  color: #fff;
+}
+
 .pointer {
   cursor: pointer;
 }

+ 1 - 1
common/lib/shared.js

@@ -91,7 +91,7 @@ function top_field_values(docs,field,count) {
 }
 
 function add_to_query(original,field,value,negate) {
-  var not = negate ? "NOT " : "";
+  var not = negate ? "-" : "";
   if(value !== '')
     var query = field + ":" + "\"" + addslashes(value.toString()) + "\"";
   else

+ 1 - 1
config.js

@@ -22,6 +22,6 @@ var config = new Settings(
   kibana_index:     "kibana-int", 
   modules:          ['histogram','map','pie','table','stringquery','sort',
                     'timepicker','text','fields','hits','dashcontrol',
-                    'column','derivequeries','trends','bettermap'],
+                    'column','derivequeries','trends','bettermap','query'],
   }
 );

+ 83 - 1
js/services.js

@@ -186,7 +186,89 @@ angular.module('kibana.services', [])
   }
 
 })
-.service('query', function() {
+.service('query', function(dashboard) {
+  // Create an object to hold our service state on the dashboard
+  dashboard.current.services.query = dashboard.current.services.query || {};
+  _.defaults(dashboard.current.services.query,{
+    idQueue : [],
+    list : {},
+    ids : [],
+  });
+
+  // For convenience 
+  var _q = dashboard.current.services.query;
+  this.colors = [ 
+    "#7EB26D","#EAB839","#6ED0E0","#EF843C","#E24D42","#1F78C1","#BA43A9","#705DA0", //1
+    "#508642","#CCA300","#447EBC","#C15C17","#890F02","#0A437C","#6D1F62","#584477", //2
+    "#B7DBAB","#F4D598","#70DBED","#F9BA8F","#F29191","#82B5D8","#E5A8E2","#AEA2E0", //3
+    "#629E51","#E5AC0E","#64B0C8","#E0752D","#BF1B00","#0A50A1","#962D82","#614D93", //4
+    "#9AC48A","#F2C96D","#65C5DB","#F9934E","#EA6460","#5195CE","#D683CE","#806EB7", //5
+    "#3F6833","#967302","#2F575E","#99440A","#58140C","#052B51","#511749","#3F2B5B", //6
+    "#E0F9D7","#FCEACA","#CFFAFF","#F9E2D2","#FCE2DE","#BADFF4","#F9D9F9","#DEDAF7"  //7
+  ];
+
+  // Save a reference to this
+  this.list = dashboard.current.services.query.list;
+  this.ids = dashboard.current.services.query.ids;
+
+  var self = this;
+
+  var init = function() {
+    if (self.ids.length == 0) {
+      self.set({});
+    }
+  }
+
+  // This is used both for adding queries and modifying them. If an id is passed, the query at that id is updated
+  this.set = function(query,id) {
+    if(!_.isUndefined(id)) {
+      if(!_.isUndefined(self.list[id])) {
+        _.extend(self.list[id],query);
+        return id;
+      } else {
+        return false;
+      }
+    } else {
+      var _id = nextId();
+      var _query = {
+        query: '*',
+        alias: '',
+        color: colorAt(_id)
+      }
+      _.defaults(query,_query)
+      self.list[_id] = query;
+      self.ids.push(_id)
+      return id;
+    }
+
+  }
+
+  this.remove = function(id) {
+    if(!_.isUndefined(self.list[id])) {
+      delete self.list[id];
+      // This must happen on the full path also since _.without returns a copy
+      self.ids = dashboard.current.services.query.ids = _.without(self.ids,id)
+      _q.idQueue.unshift(id)
+      _q.idQueue.sort(function(a,b){return a-b});
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  var nextId = function() {
+    if(_q.idQueue.length > 0) {
+      return _q.idQueue.shift()
+    } else {
+      return self.ids.length;
+    }
+  }
+
+  var colorAt = function(id) {
+    return self.colors[id % self.colors.length]
+  }
+
+  init();
 
 })
 .service('dashboard', function($routeParams, $http, $rootScope, ejsResource, timer) {

+ 0 - 7
panels/bettermap/editor.html

@@ -5,13 +5,6 @@
     Also note that geoJSON is <strong>long,lat NOT lat,long</strong>.
     </div>
   </div>
-
-  <div class="row-fluid">
-    <div class="span11">
-      <h6>Query</h6>
-      <input type="text" style="width:100%" ng-model="panel.query">
-    </div>
-  </div>
   <div class="row-fluid">    
     <div class="span4">
       <form>

+ 12 - 12
panels/bettermap/module.js

@@ -22,7 +22,7 @@
 */
 
 angular.module('kibana.bettermap', [])
-.controller('bettermap', function($scope, eventBus) {
+.controller('bettermap', function($scope, eventBus, query) {
 
   // Set and populate defaults
   var _d = {
@@ -37,11 +37,12 @@ angular.module('kibana.bettermap', [])
   _.defaults($scope.panel,_d)
 
   $scope.init = function() {
-    eventBus.register($scope,'time', function(event,time){set_time(time)});
-    eventBus.register($scope,'query', function(event, query) {
-      $scope.panel.query = _.isArray(query) ? query[0] : query;
+
+    $scope.$on('refresh',function(){
       $scope.get_data();
-    });
+    })
+
+    eventBus.register($scope,'time', function(event,time){set_time(time)});
 
     // Now that we're all setup, request the time from our group
     eventBus.broadcast($scope.$id,$scope.panel.group,'get_time')
@@ -64,9 +65,14 @@ $scope.get_data = function(segment,query_id) {
     var _segment = _.isUndefined(segment) ? 0 : segment
     $scope.segment = _segment;
 
+    var boolQuery = ejs.BoolQuery();
+    _.each(query.list,function(q) {
+      boolQuery = boolQuery.should(ejs.QueryStringQuery((q.query || '*') + " AND _exists_:"+$scope.panel.field))
+    })
+
     var request = $scope.ejs.Request().indices($scope.index[_segment])
       .query(ejs.FilteredQuery(
-        ejs.QueryStringQuery(($scope.panel.query || '*') + " AND _exists_:"+$scope.panel.field),
+        boolQuery,
         ejs.RangeFilter($scope.time.field)
           .from($scope.time.from)
           .to($scope.time.to)
@@ -142,12 +148,6 @@ $scope.get_data = function(segment,query_id) {
     $scope.get_data();
   }
 
-  $scope.build_search = function(field,value) {
-    $scope.panel.query = add_to_query($scope.panel.query,field,value,false)
-    $scope.get_data();
-    eventBus.broadcast($scope.$id,$scope.panel.group,'query',[$scope.panel.query]);
-  }
-
 })
 .directive('bettermap', function() {
   return {

+ 0 - 32
panels/histogram/editor.html

@@ -14,38 +14,6 @@
       <label class="small">Note</label><small> In <strong>{{panel.mode}}</strong> mode the configured field <strong>must</strong> be a numeric type</small>
     </div>
   </div>
-  <div class="row-fluid">
-    <div class="span3">
-      <form style="margin-bottom: 0px">
-        <label class="small">Label</label>
-        <input type="text" placeholder="New Label" style="width:70%" ng-model="newlabel">
-      </form>
-    </div>
-    <div class="span8">
-      <label class="small">Query</label>
-      <form class="input-append" style="margin-bottom: 0px">
-        <input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
-        <button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery='';set_refresh(true)"><i class="icon-plus"></i></button>
-      </form>
-    </div>
-    <div class="span1">
-    </div>
-  </div>
-  <div class="row-fluid" ng-repeat="q in panel.query">        
-    <div class="span3">
-      <form style="margin-bottom: 0px">
-        <input type="text" style="width:70%" ng-model="q.label" ng-change="set_refresh(true)">
-      </form>
-    </div>
-    <div class="span8">
-      <form style="margin-bottom: 0px">
-        <input type="text" style="width:80%" ng-model="q.query" ng-change="set_refresh(true)">
-      </form>
-    </div>
-    <div class="span1">
-      <i class="icon-remove pointer" ng-click="remove_query(q)"></i>
-    </div>
-  </div>
   <h5>Chart Options</h5>
   <div class="row-fluid" style="margin-bottom:10px;">
     <div class="span1"> <label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars"></div>

+ 24 - 46
panels/histogram/module.js

@@ -42,7 +42,7 @@
 */
 
 angular.module('kibana.histogram', [])
-.controller('histogram', function($scope, eventBus) {
+.controller('histogram', function($scope, eventBus,query) {
 
   // Set and populate defaults
   var _d = {
@@ -72,19 +72,14 @@ angular.module('kibana.histogram', [])
   _.defaults($scope.panel,_d)
 
   $scope.init = function() {
+
+    $scope.queries = query;
+
     eventBus.register($scope,'time', function(event,time){$scope.set_time(time)});
-    
-    // Consider eliminating the check for array, this should always be an array
-    eventBus.register($scope,'query', function(event, query) {
-      if(_.isArray(query)) {
-        $scope.panel.query = _.map(query,function(q) {
-          return {query: q, label: q};
-        })
-      } else {
-        $scope.panel.query[0] = {query: query, label: query}
-      }
+
+    $scope.$on('refresh',function(){
       $scope.get_data();
-    });
+    })
 
     // Now that we're all setup, request the time from our group if we don't 
     // have it yet
@@ -92,21 +87,6 @@ angular.module('kibana.histogram', [])
       eventBus.broadcast($scope.$id,$scope.panel.group,'get_time')
   }
 
-  $scope.remove_query = function(q) {
-    $scope.panel.query = _.without($scope.panel.query,q);
-    $scope.get_data();
-  }
-
-  $scope.add_query = function(label,query) {
-    if(!(_.isArray($scope.panel.query)))
-      $scope.panel.query = new Array();
-    $scope.panel.query.unshift({
-      query: query,
-      label: label, 
-    });
-    $scope.get_data();
-  }
-
   $scope.get_data = function(segment,query_id) {
     delete $scope.panel.error
     // Make sure we have everything for the request to complete
@@ -120,22 +100,17 @@ angular.module('kibana.histogram', [])
     var _segment = _.isUndefined(segment) ? 0 : segment
     var request = $scope.ejs.Request().indices($scope.index[_segment]);
 
-    // Build the question part of the query
-    var queries = [];
-    _.each($scope.panel.query, function(v) {
-      queries.push($scope.ejs.FilteredQuery(
-        ejs.QueryStringQuery(v.query || '*'),
+    // Build the query
+    _.each($scope.queries.ids, function(id) {
+      var query = $scope.ejs.FilteredQuery(
+        ejs.QueryStringQuery($scope.queries.list[id].query || '*'),
         ejs.RangeFilter($scope.time.field)
           .from($scope.time.from)
-          .to($scope.time.to))
+          .to($scope.time.to)
       )
-    });
-
-    // Build the facet part, injecting the query in as a facet filter
-    _.each(queries, function(v) {
-
-      var facet = $scope.ejs.DateHistogramFacet("chart"+_.indexOf(queries,v))
 
+      var facet = $scope.ejs.DateHistogramFacet(id)
+      
       if($scope.panel.mode === 'count') {
         facet = facet.field($scope.time.field)
       } else {
@@ -145,9 +120,9 @@ angular.module('kibana.histogram', [])
         }
         facet = facet.keyField($scope.time.field).valueField($scope.panel.value_field)
       }
-      facet = facet.interval($scope.panel.interval).facetFilter($scope.ejs.QueryFilter(v))
+      facet = facet.interval($scope.panel.interval).facetFilter($scope.ejs.QueryFilter(query))
       request = request.facet(facet).size(0)
-    })
+    });
 
     // Populate the inspector panel
     $scope.populate_modal(request);
@@ -174,7 +149,7 @@ angular.module('kibana.histogram', [])
       if($scope.query_id === query_id) {
 
         var i = 0;
-        _.each(results.facets, function(v, k) {
+        _.each(results.facets, function(v, id) {
 
           // Null values at each end of the time range ensure we see entire range
           if(_.isUndefined($scope.data[i]) || _segment == 0) {
@@ -197,15 +172,12 @@ angular.module('kibana.histogram', [])
           // Create the flot series object
           var series = { 
             data: {
-              label: $scope.panel.query[i].label || "query"+(parseInt(i)+1), 
+              id: id,
               data: data,
               hits: hits
             },
           };
 
-          if (!(_.isUndefined($scope.panel.query[i].color)))
-            series.data.color = $scope.panel.query[i].color;
-          
           $scope.data[i] = series.data
 
           i++;
@@ -276,6 +248,12 @@ angular.module('kibana.histogram', [])
       // Function for rendering panel
       function render_panel() {
  
+        // Populate from the query service
+        _.each(scope.data,function(series) {
+          series.label = scope.queries.list[series.id].alias,
+          series.color = scope.queries.list[series.id].color
+        })
+
         // Set barwidth based on specified interval
         var barwidth = interval_to_seconds(scope.panel.interval)*1000
 

+ 0 - 34
panels/hits/editor.html

@@ -26,38 +26,4 @@
       <label class="small">Labels</label><input type="checkbox" ng-model="panel.labels" ng-checked="panel.labels">
     </div>
   </div>
-  <h5>Queries</h5>    
-  <div class="row-fluid">
-    <div class="span3">
-      <form style="margin-bottom: 0px">
-       <label class="small">Label</label>
-        <input type="text" placeholder="New Label" style="width:70%" ng-model="newlabel">
-      </form>
-    </div>
-    <div class="span8">
-      <form class="input-append" style="margin-bottom: 0px">
-        <label class="small">Query</label>
-        <input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
-        <button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery='';set_refresh(true)"><i class="icon-plus"></i></button>
-      </form>
-    </div>
-    <div class="span1">
-    </div>
-  </div>
-  <div class="row-fluid" ng-repeat="q in panel.query">        
-    <div class="span3">
-      <form style="margin-bottom: 0px">
-        <input type="text" style="width:70%" ng-model="q.label" ng-change="set_refresh(true)">
-      </form>
-    </div>
-    <div class="span8">
-      <form class="input-append" style="margin-bottom: 0px">
-        <input type="text" style="width:80%" ng-model="q.query" ng-change="set_refresh(true)">
-        <button class="btn" ng-click="get_data()"><i class="icon-search"></i></button>
-      </form>
-    </div>
-    <div class="span1">
-      <i class="icon-remove pointer" ng-click="remove_query(q)"></i>
-    </div>
-  </div>
 </div>

+ 25 - 20
panels/hits/module.js

@@ -22,7 +22,7 @@
 
 */
 angular.module('kibana.hits', [])
-.controller('hits', function($scope, eventBus) {
+.controller('hits', function($scope, eventBus, query) {
 
   // Set and populate defaults
   var _d = {
@@ -40,16 +40,20 @@ angular.module('kibana.hits', [])
   _.defaults($scope.panel,_d)
 
   $scope.init = function () {
+    $scope.queries = query;
+
     $scope.hits = 0;
     eventBus.register($scope,'time', function(event,time){
       set_time(time)
     });
-    eventBus.register($scope,'query', function(event, query) {
-      $scope.panel.query = _.map(query,function(q) {
-        return {query: q, label: q};
-      })
+
+
+    $scope.$on('refresh',function(){
+      console.log($scope.queries)
+      console.log(query)
       $scope.get_data();
-    });
+    })
+
     // Now that we're all setup, request the time from our group
     eventBus.broadcast($scope.$id,$scope.panel.group,'get_time')
   }
@@ -66,23 +70,18 @@ angular.module('kibana.hits', [])
     var request = $scope.ejs.Request().indices($scope.index[_segment]);
     
     // Build the question part of the query
-    var queries = [];
-    _.each($scope.panel.query, function(v) {
-      queries.push($scope.ejs.FilteredQuery(
-        ejs.QueryStringQuery(v.query || '*'),
+    _.each($scope.queries.ids, function(id) {
+      var query = $scope.ejs.FilteredQuery(
+        ejs.QueryStringQuery($scope.queries.list[id].query || '*'),
         ejs.RangeFilter($scope.time.field)
           .from($scope.time.from)
           .to($scope.time.to))
-      )
-    });
-
-    // Build the facet part
-    _.each(queries, function(v) {
+    
       request = request
-        .facet($scope.ejs.QueryFacet("query"+_.indexOf(queries,v))
-          .query(v)
+        .facet($scope.ejs.QueryFacet(id)
+          .query(query)
         ).size(0)
-    })
+    });
 
     // TODO: Spy for hits panel
     //$scope.populate_modal(request);
@@ -107,14 +106,15 @@ angular.module('kibana.hits', [])
       }
       if($scope.query_id === query_id) {
         var i = 0;
-        _.each(results.facets, function(v, k) {
+        _.each(results.facets, function(v, id) {
           var hits = _.isUndefined($scope.data[i]) || _segment == 0 ? 
             v.count : $scope.data[i].hits+v.count
           $scope.hits += v.count
 
           // Create series
           $scope.data[i] = { 
-            label: $scope.panel.query[i].label || "query"+(parseInt(i)+1), 
+            //label: $scope.panel.query[i].label || "query"+(parseInt(i)+1), 
+            id: id,
             hits: hits,
             data: [[i,hits]]
           };
@@ -177,6 +177,11 @@ angular.module('kibana.hits', [])
       // Function for rendering panel
       function render_panel() {
 
+        _.each(scope.data,function(series) {
+          series.label = scope.queries.list[series.id].alias,
+          series.color = scope.queries.list[series.id].color
+        })
+
         var scripts = $LAB.script("common/lib/panels/jquery.flot.js").wait()
                           .script("common/lib/panels/jquery.flot.pie.js")
 

+ 7 - 0
panels/query/editor.html

@@ -0,0 +1,7 @@
+<div>
+  <div class="row-fluid">    
+    <div class="span12">
+      No options here
+    </div>
+  </div>
+</div>

+ 5 - 0
panels/query/meta.html

@@ -0,0 +1,5 @@
+<style>
+</style>
+<a class="close" ng-click="render();dismiss();" href="">×</a>
+<input class="input-medium" type="text" ng-model="queries.list[id].alias" placeholder='Alias...' />
+<i ng-repeat="color in queries.colors" class="pointer" ng-class="{'icon-circle-blank':queries.list[id].color == color,'icon-circle':queries.list[id].color != color}" style="color:{{color}}" ng-click="queries.list[id].color = color;render();"> </i>

+ 51 - 0
panels/query/module.html

@@ -0,0 +1,51 @@
+<kibana-panel ng-controller='query' ng-init="init()">
+<style>
+  .short-query {
+    display:inline-block;
+    margin-left: 10px;
+  }
+  .begin-query {
+    position:absolute;
+    left:15px;
+    top:5px;
+  }
+  .end-query {
+    position:absolute;
+    right:15px;
+    top:5px;
+  }
+  .panel-query {
+    padding-left: 35px !important;
+    height: 31px !important;
+    -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+    -moz-box-sizing: border-box;    /* Firefox, other Gecko */
+    box-sizing: border-box;         /* Opera/IE 8+ */
+  }
+  .form-search:hover .has-remove {
+    padding-left: 50px !important;
+  }
+  .remove-query {
+    opacity: 0;
+  }
+  .last-query {
+    padding-right: 45px !important;
+  }
+  .form-search:hover .remove-query {
+    opacity: 1;
+  }
+</style>
+  <label class="small">{{panel.label}}</label>
+  <div ng-repeat="id in queries.ids" ng-class="{'short-query': queries.ids.length>1}">
+    <form class="form-search" style="position:relative" ng-submit="refresh()">
+      <span class="begin-query">
+        <i class="icon-circle pointer" data-unique="1" bs-popover="'panels/query/meta.html'" data-placement="right" style="color:{{queries.list[id].color}}"></i>
+        <i class="icon-remove-sign pointer remove-query" ng-show="queries.ids.length>1" ng-click="queries.remove(id);refresh()"></i>
+      </span>
+      <input class="search-query panel-query" ng-class="{'input-block-level': queries.ids.length==1,'last-query': $last,'has-remove': queries.ids.length>1}" bs-typeahead="panel.history" data-min-length=0 data-items=100 type="text" ng-model="queries.list[id].query"/>
+      <span class="end-query">
+        <i class="icon-search pointer" ng-click="refresh()" ng-show="$last"></i>
+        <i class="icon-plus pointer" ng-click="queries.set({})" ng-show="$last"></i>
+      </span
+    </form>
+  </div>
+</kibana-panel>

+ 70 - 0
panels/query/module.js

@@ -0,0 +1,70 @@
+/*
+
+  ## query
+
+  An experimental panel for the query service
+
+  ### Parameters
+  * label ::  The label to stick over the field 
+  * query ::  A string or an array of querys. String if multi is off, array if it is on
+              This should be fixed, it should always be an array even if its only 
+              one element
+  * multi :: Allow input of multiple queries? true/false
+  * multi_arrange :: How to arrange multu query string panels, 'vertical' or 'horizontal'
+  ### Group Events
+  #### Sends
+  * query :: Always broadcast as an array, even in multi: false
+  #### Receives
+  * query :: An array of queries. This is probably needs to be fixed.
+
+*/
+
+angular.module('kibana.query', [])
+.controller('query', function($scope, eventBus, query, $rootScope) {
+
+  // Set and populate defaults
+  var _d = {
+    status  : "Experimental",
+    label   : "Search",
+    query   : "*",
+    group   : "default",
+    history : [],
+    remember: 10 // max: 100, angular strap can't take a variable for items param
+  }
+  _.defaults($scope.panel,_d);
+
+  $scope.queries = query;
+
+  $scope.init = function() {
+  }
+
+  $scope.refresh = function(query) {
+    console.log('refresh')
+    $rootScope.$broadcast('refresh')
+  }
+
+  $scope.render = function(query) {
+    console.log('render')
+    $rootScope.$broadcast('render')
+  }
+
+  $scope.add_query = function() {
+    if (_.isArray($scope.panel.query))
+      $scope.panel.query.push("")
+    else {
+      $scope.panel.query = new Array($scope.panel.query)
+      $scope.panel.query.push("")
+    }
+  }
+
+  var update_history = function(query) {
+    if($scope.panel.remember > 0) {
+      $scope.panel.history = _.union(query.reverse(),$scope.panel.history)
+      var _length = $scope.panel.history.length
+      if(_length > $scope.panel.remember) {
+        $scope.panel.history = $scope.panel.history.slice(0,$scope.panel.remember)
+      }
+    }
+  }
+
+});

+ 0 - 9
panels/table/editor.html

@@ -1,12 +1,3 @@
-  <div class="row-fluid">    
-    <div style="width:90%">
-      <form class="input-append">
-        <h6>Query</h6>
-        <input type="text" style="width:90%" ng-model="panel.query">
-        <button class="btn" ng-click="get_data();"><i class="icon-search"></i></button>
-      </form>
-    </div>
-  </div>
   <div class="row-fluid">    
     <div class="span4">
       <form class="input-append">

+ 17 - 13
panels/table/module.js

@@ -29,7 +29,7 @@
 */
 
 angular.module('kibana.table', [])
-.controller('table', function($scope, eventBus, fields) {
+.controller('table', function($rootScope, $scope, eventBus, fields, query) {
 
   // Set and populate defaults
   var _d = {
@@ -60,15 +60,11 @@ angular.module('kibana.table', [])
   }
 
   $scope.set_listeners = function(group) {
+    $scope.$on('refresh',function(){$scope.get_data()})
     eventBus.register($scope,'time',function(event,time) {
       $scope.panel.offset = 0;
       set_time(time)
     });
-    eventBus.register($scope,'query',function(event,query) {
-      $scope.panel.offset = 0;
-      $scope.panel.query = _.isArray(query) ? query[0] : query;
-      $scope.get_data();
-    });
     eventBus.register($scope,'sort', function(event,sort){
       $scope.panel.sort = _.clone(sort);
       $scope.get_data();
@@ -77,7 +73,7 @@ angular.module('kibana.table', [])
       $scope.panel.fields = _.clone(fields)
     });
     eventBus.register($scope,'table_documents', function(event, docs) {
-        $scope.panel.query = docs.query;
+        query.list[query.ids[0]].query = docs.query;
         $scope.data = docs.docs;
     });
   }
@@ -116,10 +112,11 @@ angular.module('kibana.table', [])
   }
 
   $scope.build_search = function(field,value,negate) {
-    $scope.panel.query = add_to_query($scope.panel.query,field,value,negate)
+    _.each(query.list,function(q) {
+      q.query = add_to_query(q.query,field,value,negate);
+    })
     $scope.panel.offset = 0;
-    $scope.get_data();
-    eventBus.broadcast($scope.$id,$scope.panel.group,'query',[$scope.panel.query]);
+    $rootScope.$broadcast('refresh')
   }
 
   $scope.get_data = function(segment,query_id) {
@@ -135,8 +132,15 @@ angular.module('kibana.table', [])
     $scope.segment = _segment;
 
     var request = $scope.ejs.Request().indices($scope.index[_segment])
-      .query(ejs.FilteredQuery(
-        ejs.QueryStringQuery($scope.panel.query || '*'),
+
+    var boolQuery = ejs.BoolQuery();
+    _.each(query.list,function(q) {
+      boolQuery = boolQuery.should(ejs.QueryStringQuery(q.query || '*'))
+    })
+
+    request = request.query(
+      ejs.FilteredQuery(
+        boolQuery,
         ejs.RangeFilter($scope.time.field)
           .from($scope.time.from)
           .to($scope.time.to)
@@ -244,7 +248,7 @@ angular.module('kibana.table', [])
     });
     eventBus.broadcast($scope.$id,$scope.panel.group,"table_documents", 
       {
-        query: $scope.panel.query,
+        query: query.list[query.ids[0]].query,
         docs : _.pluck($scope.data,'_source'),
         index: $scope.index
       });

+ 0 - 32
panels/trends/editor.html

@@ -26,36 +26,4 @@
       <select class="input-small" ng-model="panel.arrangement" ng-options="f for f in ['horizontal','vertical']"></select></span>
     </div>
   </div>
-
-  <h5>Queries</h5>    
-  <div class="row-fluid">
-    <div class="span3">
-      <form style="margin-bottom: 0px">
-       <label class="small">Label</label>
-        <input type="text" placeholder="New Label" style="width:70%" ng-model="newlabel">
-      </form>
-    </div>
-    <div class="span8">
-      <form class="input-append" style="margin-bottom: 0px">
-        <label class="small">Query</label>
-        <input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
-        <button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery='';set_refresh(true)"><i class="icon-plus"></i></button>
-      </form>
-    </div>
-    <div class="span1">
-    </div>
-  </div>
-  <div class="row-fluid" ng-repeat="q in panel.query">        
-    <div class="span3">
-      <form style="margin-bottom: 0px">
-        <input type="text" style="width:70%" ng-model="q.label" ng-change="set_refresh(true)">
-      </form>
-    </div>
-    <div class="span8">
-        <input type="text" style="width:80%" ng-model="q.query" ng-change="set_refresh(true)">
-    </div>
-    <div class="span1">
-      <i class="icon-remove pointer" ng-click="remove_query(q)"></i>
-    </div>
-  </div>
 </div>

+ 2 - 1
panels/trends/module.html

@@ -1,10 +1,11 @@
 <kibana-panel ng-controller='trends' ng-init="init()">
 
   <div ng-style="panel.style" style="line-height:{{panel.style['font-size']}};display:inline-block;padding-right: 5px;" ng-repeat="query in trends">
+    <i class="icon-circle" style="color:{{query.info.color}}"></i>
     <span ng-class="{'text-success': query.hits.new >= query.hits.old, 'text-error': query.hits.old > query.hits.new}" class='strong'>
       <i class='large' ng-class="{'icon-caret-up': query.hits.new >= query.hits.old, 'icon-caret-down': query.hits.old > query.hits.new}"></i> {{query.percent}}% 
     </span>
-    <span class="tiny pointer light" bs-tooltip="'Then: '+query.hits.old+', Now: '+query.hits.new">({{query.label}})</span>
+    <span class="tiny pointer light" bs-tooltip="'Then: '+query.hits.old+', Now: '+query.hits.new" ng-show="query.label != ''">({{query.info.alias}})</span>
     <br ng-show="panel.arrangement == 'vertical'">
   </div>
 </kibana-panel>         

+ 20 - 30
panels/trends/module.js

@@ -19,7 +19,7 @@
 
 */
 angular.module('kibana.trends', [])
-.controller('trends', function($scope, eventBus, kbnIndex) {
+.controller('trends', function($scope, eventBus, kbnIndex, query) {
 
   // Set and populate defaults
   var _d = {
@@ -64,43 +64,32 @@ angular.module('kibana.trends', [])
     var request = $scope.ejs.Request();
 
     // Build the question part of the query
-    var queries = [];
-    _.each($scope.panel.query, function(v) {
-      queries.push($scope.ejs.FilteredQuery(
-        ejs.QueryStringQuery(v.query || '*'),
+    _.each(query.ids, function(id) {
+      var q = $scope.ejs.FilteredQuery(
+        ejs.QueryStringQuery(query.list[id].query || '*'),
         ejs.RangeFilter($scope.time.field)
           .from($scope.time.from)
           .to($scope.time.to))
-      )
-    });
-
-    // Build the facet part
-    _.each(queries, function(v) {
       request = request
-        .facet($scope.ejs.QueryFacet("new"+_.indexOf(queries,v))
-          .query(v)
+        .facet($scope.ejs.QueryFacet(id)
+          .query(q)
         ).size(0)
-    })
+    });
 
-    var queries = [];
-    _.each($scope.panel.query, function(v) {
-      queries.push($scope.ejs.FilteredQuery(
-        ejs.QueryStringQuery(v.query || '*'),
+    // And again for the old time period
+    _.each(query.ids, function(id) {
+      var q = $scope.ejs.FilteredQuery(
+        ejs.QueryStringQuery(query.list[id].query || '*'),
         ejs.RangeFilter($scope.time.field)
           .from($scope.old_time.from)
           .to($scope.old_time.to))
-      )
-    });
-
-    // Build the facet part
-    _.each(queries, function(v) {
       request = request
-        .facet($scope.ejs.QueryFacet("old"+_.indexOf(queries,v))
-          .query(v)
+        .facet($scope.ejs.QueryFacet("old_"+id)
+          .query(q)
         ).size(0)
-    })
+    });
 
-    // TODO: Spy for hits panel
+    // TODO: Spy for trend panel
     //$scope.populate_modal(request);
 
     // If we're on the first segment we need to get our indices
@@ -121,6 +110,7 @@ angular.module('kibana.trends', [])
     // Populate scope when we have results
     function process_results(results) { 
       results.then(function(results) {
+        console.log(results)
 
         $scope.panel.loading = false;
         if(_segment == 0) {
@@ -136,9 +126,9 @@ angular.module('kibana.trends', [])
         }
         if($scope.query_id === query_id) {
           var i = 0;
-          _.each($scope.panel.query, function(k) {
-            var n = results.facets['new'+i].count
-            var o = results.facets['old'+i].count
+          _.each(query.ids, function(id) {
+            var n = results.facets[id].count
+            var o = results.facets['old_'+id].count
 
             var hits = {
               new : _.isUndefined($scope.data[i]) || _segment == 0 ? n : $scope.data[i].hits.new+n,        
@@ -152,7 +142,7 @@ angular.module('kibana.trends', [])
               '?' : Math.round(percentage(hits.old,hits.new)*100)/100
             // Create series
             $scope.data[i] = { 
-              label: $scope.panel.query[i].label || "query"+(parseInt(i)+1), 
+              info: query.list[id],
               hits: {
                 new : hits.new,
                 old : hits.old

Некоторые файлы не были показаны из-за большого количества измененных файлов