فهرست منبع

prettied up histogram hover, added line width options, fixed excessive refresh on string query

Rashid Khan 12 سال پیش
والد
کامیت
d685fddcbe
6فایلهای تغییر یافته به همراه206 افزوده شده و 108 حذف شده
  1. 62 56
      panels/histogram/editor.html
  2. 17 10
      panels/histogram/module.js
  3. 38 15
      panels/hits/editor.html
  4. 9 1
      panels/hits/module.html
  5. 79 25
      panels/hits/module.js
  6. 1 1
      panels/stringquery/module.html

+ 62 - 56
panels/histogram/editor.html

@@ -1,61 +1,67 @@
-<div class="row-fluid" ng-controller='histogram'>
-  <div class="span3">
-    <form style="margin-bottom: 0px">
-      <h6>Label</h6>
-      <input type="text" placeholder="New Label" style="width:70%" ng-model="newlabel">
-    </form>
+<div ng-controller='histogram'>
+  <div class="row-fluid">
+    <div class="span3">
+      <form style="margin-bottom: 0px">
+        <h6>Label</h6>
+        <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">
+        <h6>Query</h6>
+        <input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
+        <button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery=''"><i class="icon-plus"></i></button>
+      </form>
+    </div>
+    <div class="span1">
+    </div>
   </div>
-  <div class="span8">
-    <form class="input-append" style="margin-bottom: 0px">
-      <h6>Query</h6>
-      <input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
-      <button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery=''"><i class="icon-plus"></i></button>
-    </form>
+  <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">
+      </form>
+    </div>
+    <div class="span8">
+      <form class="input-append" style="margin-bottom: 0px">
+        <input type="text" style="width:80%" ng-model="q.query">
+        <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 class="span1">
+  <div class="row-fluid">    
+    <div class="span3">
+      <label class="small">Chart Options</label> 
+      <select ng-change="$emit('render')" multiple style="width:95%" ng-model="panel.show" ng-options="f for f in ['bars','points','stack','lines','legend','x-axis','y-axis']"></select>
+    </div>
+    <div class="span2">
+      <label class="small">Line Fill</label> 
+      <select ng-change="$emit('render')" class="input-mini" ng-model="panel.fill" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
+    </div>
+    <div class="span2">
+      <label class="small">Line Width</label> 
+      <select ng-change="$emit('render')" class="input-mini" ng-model="panel.linewidth" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
+    </div>
+    <div class="span3">
+      <label class="small">Time correction</label> 
+      <select ng-change="$emit('render')" ng-model="panel.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
+    </div>
+    <div class="span2"> 
+      <label class="small">Zoom Links</label><input type="checkbox" ng-model="panel.zoomlinks" ng-checked="panel.zoomlinks">
+    </div>
   </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">
-    </form>
-  </div>
-  <div class="span8">
-    <form class="input-append" style="margin-bottom: 0px">
-      <input type="text" style="width:80%" ng-model="q.query">
-      <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 class="row-fluid">    
-  <div class="span3">
-    <label class="small">Chart Options</label> 
-    <select ng-change="$emit('render')" multiple style="width:95%" ng-model="panel.show" ng-options="f for f in ['bars','points','stack','lines','legend','x-axis','y-axis']"></select>
-  </div>
-  <div class="span3">
-    <label class="small">Line Fill (1 - 10)</label> 
-    <input ng-change="$emit('render')" type="number" class="input-mini" ng-model="panel.fill">
-  </div>
-  <div class="span3">
-    <label class="small">Time correction</label> 
-    <select ng-change="$emit('render')" ng-model="panel.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
-  </div>
-  <div class="span2"> 
-    <label class="small">Zoom Links</label><input type="checkbox" ng-model="panel.zoomlinks" ng-checked="panel.zoomlinks">
-  </div>
-</div>
-<h5>Panel Spy</h5>
-<div class="row-fluid">
-  <div class="span2"> 
-    <label class="small">Spyable</label><input type="checkbox" ng-model="panel.spyable" ng-checked="panel.spyable">
-  </div>
-  <div class="span9 small">
-    The panel spy shows 'behind the scenes' information about a panel. It can
-    be accessed by clicking the <i class='icon-eye-open'></i> in the top right
-    of the panel.
+  <h5>Panel Spy</h5>
+  <div class="row-fluid">
+    <div class="span2"> 
+      <label class="small">Spyable</label><input type="checkbox" ng-model="panel.spyable" ng-checked="panel.spyable">
+    </div>
+    <div class="span9 small">
+      The panel spy shows 'behind the scenes' information about a panel. It can
+      be accessed by clicking the <i class='icon-eye-open'></i> in the top right
+      of the panel.
+    </div>
   </div>
 </div>

+ 17 - 10
panels/histogram/module.js

@@ -7,6 +7,7 @@ angular.module('kibana.histogram', [])
     interval  : secondsToHms(calculate_interval($scope.from,$scope.to,40,0)/1000),
     show      : ['bars','y-axis','x-axis','legend'],
     fill      : 3,
+    linewidth : 3,
     timezone  : 'browser', // browser, utc or a standard timezone
     spyable   : true,
     zoomlinks : true,
@@ -148,7 +149,6 @@ angular.module('kibana.histogram', [])
           i++;
         });
 
-        eventBus.broadcast($scope.$id,$scope.panel.group,'hits',$scope.hits)
         $scope.$emit('render')
         if(_segment < $scope.panel.index.length-1) {
           $scope.get_data(_segment+1,query_id)
@@ -236,7 +236,12 @@ angular.module('kibana.histogram', [])
               },
               series: {
                 stack:  show.stack,
-                lines:  { show: show.lines, fill: scope.panel.fill/10 },
+                lines:  { 
+                  show: show.lines, 
+                  fill: scope.panel.fill/10, 
+                  lineWidth: scope.panel.linewidth,
+                  steps: true
+                },
                 bars:   { show: show.bars,  fill: 1, barWidth: barwidth/1.8 },
                 points: { show: show.points, fill: 1, fillColor: false},
                 shadowSize: 1
@@ -294,23 +299,25 @@ angular.module('kibana.histogram', [])
         var tooltip = $('#pie-tooltip').length ? 
           $('#pie-tooltip') : $('<div id="pie-tooltip"></div>');
         //var tooltip = $('#pie-tooltip')
-        tooltip.text(contents).css({
+        tooltip.html(contents).css({
           position: 'absolute',
           top     : y + 5,
           left    : x + 5,
-          color   : "#FFF",
-          border  : '1px solid #FFF',
-          padding : '2px',
-          'font-size': '8pt',
-          'background-color': '#000',
+          color   : "#000",
+          border  : '3px solid #000',
+          padding : '10px',
+          'font-size': '11pt',
+          'font-weight' : 'bold',
+          'background-color': '#FFF',
+          'border-radius': '10px',
         }).appendTo("body");
       }
 
       elem.bind("plothover", function (event, pos, item) {
         if (item) {
-          var percent = parseFloat(item.series.percent).toFixed(1) + "%";
           tt(pos.pageX, pos.pageY,
-            item.datapoint[1].toFixed(1) + " @ " + 
+            "<div style='vertical-align:middle;display:inline-block;background:"+item.series.color+";height:20px;width:20px'></div> "+
+            item.datapoint[1].toFixed(0) + " @ " + 
             new Date(item.datapoint[0]).format('mm/dd HH:MM:ss'));
         } else {
           $("#pie-tooltip").remove();

+ 38 - 15
panels/hits/editor.html

@@ -1,23 +1,46 @@
-  <div class="row-fluid" ng-controller="hits">
-    <div class="span2"> 
-      <label class="small">Run Query</label><input type="checkbox" ng-model="panel.run_query" ng-checked="panel.run_query">
+<div ng-controller="hits">
+  <div class="row-fluid">
+    <div class="span3"><h6>Font Size</h6> 
+      <select class="input-small" ng-model="panel.style['font-size']" ng-options="f for f in ['7pt','8pt','9pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select></span>
     </div>
-    <div class="span9" ng-show='!panel.run_query'>
-      With query running disabled, this panel receives its hit count from a histogram panel. If multiple queries are running this <strong>will show the total of all queries</strong>.
+    <div class="span2"> 
+      <label class="small">Aggregate Queries</label><input type="checkbox" ng-model="panel.aggregate" ng-checked="panel.aggregate">
     </div>
-    <div class="span9" ng-show='panel.run_query'>
-      This shows a simple count of how many records match your filtered query. If multiple queries are sent from a single panel the <strong>first query will be displayed</strong>
+    <div class="span3" ng-show="!panel.aggregate"><h6>Arrangement</h6> 
+      <select class="input-medium" ng-model="panel.arrangement" ng-options="f for f in ['horizontal','vertical']"></select></span>
     </div>
   </div>
-
-  <div class="row-fluid">    
-    <div class="span9" ng-show='panel.run_query'>
-      <form class="input-append">
+  <div class="row-fluid">
+    <div class="span3">
+      <form style="margin-bottom: 0px">
+        <h6>Label</h6>
+        <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">
         <h6>Query</h6>
-        <input type="text" style="width:85%" ng-model="panel.query">
-        <button class="btn" ng-click="get_data();"><i class="icon-search"></i></button>
+        <input type="text" placeholder="New Query" style="width:80%" ng-model="newquery">
+        <button class="btn" ng-click="add_query(newlabel,newquery);newlabel='';newquery=''"><i class="icon-plus"></i></button>
       </form>
     </div>
-    <div class="span3"><h6>Font Size</h6> 
-      <select class="input-small" ng-model="panel.style['font-size']" ng-options="f for f in ['6pt','7pt','8pt','10pt','12pt','14pt','16pt','18pt','20pt','24pt','28pt','32pt','36pt','42pt','48pt','52pt','60pt','72pt']"></select></span>
+    <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">
+      </form>
+    </div>
+    <div class="span8">
+      <form class="input-append" style="margin-bottom: 0px">
+        <input type="text" style="width:80%" ng-model="q.query">
+        <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>

+ 9 - 1
panels/hits/module.html

@@ -1,3 +1,11 @@
 <kibana-panel ng-controller='hits' ng-init="init()">
-  <p ng-style="panel.style">&#8805 {{hits}}</p>
+  <p ng-style="panel.style" ng-show="panel.aggregate">{{hits}}</p>
+  <table ng-style="panel.style" ng-show="!panel.aggregate && panel.arrangement == 'vertical'">  
+    <tr style="line-height:{{panel.style['font-size']}}" ng-repeat="query in data">
+      <td style="padding-right:10px">{{query.label}}</td><td>{{query.hits}}</td>
+    </tr>
+  </table>
+  <div ng-style="panel.style" ng-show="!panel.aggregate && panel.arrangement == 'horizontal'" ng-repeat="query in data" style="float:left; padding-left: 10px">
+    {{query.label}} {{query.hits}} <span ng-show="!$last">|</span>
+  </div>
 </kibana-panel>         

+ 79 - 25
panels/hits/module.js

@@ -5,60 +5,114 @@ angular.module('kibana.hits', [])
   var _d = {
     query   : "*",
     group   : "default",
-    style   : { "font-size": '36pt', "font-weight": "bold" },
-    run_query : false
+    style   : { "font-size": '36pt'},
+    aggregate   : true,
+    arrangement : 'vertical'
   }
   _.defaults($scope.panel,_d)
 
   $scope.init = function () {
     $scope.hits = 0;
     eventBus.register($scope,'time', function(event,time){
-      if($scope.panel.run_query)
-        set_time(time)
+      set_time(time)
     });
     eventBus.register($scope,'query', function(event, query) {
-      $scope.panel.query = _.isArray(query) ? query[0] : query;
-      if($scope.panel.run_query)
-        $scope.get_data();
+      $scope.panel.query = _.map(query,function(q) {
+        return {query: q, label: q};
+      })
+      $scope.get_data();
     });
-    eventBus.register($scope,'hits', function(event, hits) {
-      $scope.hits = hits;
-    })
     // Now that we're all setup, request the time from our group
     eventBus.broadcast($scope.$id,$scope.panel.group,'get_time')
   }
 
-  $scope.get_data = function() {
+  $scope.get_data = function(segment,query_id) {
+    delete $scope.panel.error
+    $scope.panel.loading = true;
+
     // Make sure we have everything for the request to complete
     if(_.isUndefined($scope.panel.index) || _.isUndefined($scope.time))
       return
 
-    $scope.panel.loading = true;
-    var request = $scope.ejs.Request().indices($scope.panel.index);
-
-    var results = request
-      .query(ejs.FilteredQuery(
-        ejs.QueryStringQuery($scope.panel.query || '*'),
+    var _segment = _.isUndefined(segment) ? 0 : segment
+    var request = $scope.ejs.Request().indices($scope.panel.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 || '*'),
         ejs.RangeFilter($scope.time.field)
           .from($scope.time.from)
-          .to($scope.time.to)
-        )
+          .to($scope.time.to))
       )
-      .size(0)
-      .doSearch();
+    });
+
+    // Build the facet part
+    _.each(queries, function(v) {
+      request = request
+        .facet($scope.ejs.QueryFacet("query"+_.indexOf(queries,v))
+          .query(v)
+        ).size(0)
+    })
+
+    // TODO: Spy for hits panel
+    //$scope.populate_modal(request);
+
+    // Then run it
+    var results = request.doSearch();
 
     // Populate scope when we have results
     results.then(function(results) {
+
       $scope.panel.loading = false;
-      if(_.isUndefined(results)) {
-        $scope.panel.error = 'Your query was unsuccessful';
+      if(_segment == 0) {
+        $scope.hits = 0;
+        $scope.data = [];
+        query_id = $scope.query_id = new Date().getTime();
+      }
+      
+      // Check for error and abort if found
+      if(!(_.isUndefined(results.error))) {
+        $scope.panel.error = $scope.parse_error(results.error);
         return;
       }
-      $scope.panel.error =  false;
-      $scope.hits = results.hits.total;
+      if($scope.query_id === query_id) {
+        var i = 0;
+        _.each(results.facets, function(v, k) {
+          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), 
+            hits: hits
+          };
+
+          i++;
+        });
+
+        if(_segment < $scope.panel.index.length-1) 
+          $scope.get_data(_segment+1,query_id)
+      
+      }
     });
   }
 
+  $scope.remove_query = function(q) {
+    $scope.panel.query = _.without($scope.panel.query,q);
+    $scope.get_data();
+  }
+
+  $scope.add_query = function(label,query) {
+    $scope.panel.query.unshift({
+      query: query,
+      label: label, 
+    });
+    $scope.get_data();
+  }
+
   function set_time(time) {
     $scope.time = time;
     $scope.panel.index = _.isUndefined(time.index) ? $scope.panel.index : time.index

+ 1 - 1
panels/stringquery/module.html

@@ -31,7 +31,7 @@
         </span>
       </form>
       <button type="submit" class="btn btn-info" ng-click="send_query(panel.query)"><i class="icon-search"></i> Search</button>
-      <button type="submit" class="btn" ng-click="send_query(panel.query);add_query();"><i class="icon-plus"></i> Add Query</button>
+      <button type="submit" class="btn" ng-click="add_query();"><i class="icon-plus"></i> Add Query</button>
   </div>
   <div ng-show="panel.multi && panel.multi_arrange == 'vertical'">
     <form>