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

Added a checkbox to the tooltip's settings that will cause the query to be displayed in the case an alias is not set.

Spencer Alger 12 лет назад
Родитель
Сommit
2431e40145
6 измененных файлов с 95 добавлено и 30 удалено
  1. 36 0
      js/filters.js
  2. 15 5
      js/services.js
  3. 25 14
      panels/histogram/editor.html
  4. 15 8
      panels/histogram/module.js
  5. 2 2
      panels/query/module.html
  6. 2 1
      panels/table/module.html

+ 36 - 0
js/filters.js

@@ -32,4 +32,40 @@ angular.module('kibana.filters', [])
       return arr.toString();
     }
   };
+
+}).filter('noXml', function() {
+  return function(text) {
+    if(!_.isString(text)) {
+      return text;
+    }
+    return text.
+      replace(/&/g, '&').
+      replace(/</g, '&lt;').
+      replace(/>/g, '&gt;').
+      replace(/'/g, '&#39;').
+      replace(/"/g, '&quot;');
+  };
+}).filter('urlLink', function() {
+  var  //URLs starting with http://, https://, or ftp://
+    r1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim,
+    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
+    r2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim,
+    //Change email addresses to mailto:: links.
+    r3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
+
+  return function(text, target, otherProp) {
+    if(!_.isString(text)) {
+      return text;
+    }
+    _.each(text.match(r1), function(url) {
+      text = text.replace(r1, "<a href=\"$1\" target=\"_blank\">$1</a>");
+    });
+    _.each(text.match(r2), function(url) {
+      text = text.replace(r2, "$1<a href=\"http://$2\" target=\"_blank\">$2</a>");
+    });
+    _.each(text.match(r3), function(url) {
+      text = text.replace(r3, "<a href=\"mailto:$1\">$1</a>");
+    });
+    return text;
+  };
 });

+ 15 - 5
js/services.js

@@ -11,11 +11,21 @@ angular.module('kibana.services', [])
   this.list = [];
 
   this.set = function(title,text,severity,timeout) {
-    var _a = {
-      title: title || '',
-      text: text || '',
-      severity: severity || 'info',
-    };
+    var
+      _a = {
+        title: title || '',
+        text: text || '',
+        severity: severity || 'info',
+      },
+      _ca = angular.toJson(_a),
+      _clist = _.map(self.list,function(alert){return angular.toJson(alert);});
+
+    // If we already have this alert, remove it and add a new one
+    // Why do this instead of skipping the add because it resets the timer
+    if(_.contains(_clist,_ca)) {
+      _.remove(self.list,_.indexOf(_clist,_ca));
+    }
+
     self.list.push(_a);
     if (timeout > 0) {
       $timeout(function() {

+ 25 - 14
panels/histogram/editor.html

@@ -1,6 +1,6 @@
   <div class="row-fluid">
     <div class="span2">
-      <label class="small">Mode</label> 
+      <label class="small">Mode</label>
       <select ng-change="set_refresh(true)" class="input-small" ng-model="panel.mode" ng-options="f for f in ['count','min','mean','max','total']"></select>
     </div>
     <div class="span2">
@@ -15,47 +15,58 @@
       <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>
+  <h5>Chart Settings</h5>
   <div class="row-fluid" style="margin-bottom:10px;">
-    <h5>Chart Settings</h5>
     <div class="span1"> <label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars"></div>
     <div class="span1"> <label class="small">Lines</label><input type="checkbox" ng-model="panel.lines" ng-checked="panel.lines"></div>
     <div class="span1"> <label class="small">Points</label><input type="checkbox" ng-model="panel.points" ng-checked="panel.points"></div>
     <div class="span1"> <label class="small">Stack</label><input type="checkbox" ng-model="panel.stack" ng-checked="panel.stack"></div>
-    <!--<div class="span1" ng-show="panel.stack"> <label class="small" bs-tooltip="'Stack as a percentage of total'">Percent</label><input type="checkbox"  ng-model="panel.percentage" ng-checked="panel.percentage"></div>-->
+    <!--<div class="span1" ng-show="panel.stack">Percent <tip>Stack as a percentage of total</tip></label><input type="checkbox"  ng-model="panel.percentage" ng-checked="panel.percentage"></div>-->
     <div class="span1"> <label class="small">Legend</label><input type="checkbox" ng-model="panel.legend" ng-checked="panel.legend"></div>
     <div class="span1"> <label class="small">xAxis</label><input type="checkbox" ng-model="panel['x-axis']" ng-checked="panel['x-axis']"></div>
     <div class="span1"> <label class="small">yAxis</label><input type="checkbox" ng-model="panel['y-axis']" ng-checked="panel['y-axis']"></div>
     <div class="span2" ng-show="panel.lines">
-      <label class="small">Line Fill</label> 
+      <label class="small">Line Fill</label>
       <select 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" ng-show="panel.lines">
-      <label class="small">Line Width</label> 
+      <label class="small">Line Width</label>
       <select 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> 
-  <div class="row-fluid">  
+  </div>
+  <div class="row-fluid">
     <div class="span2">
-      <label class="small">Time correction</label> 
+      <label class="small">Time correction</label>
       <select ng-model="panel.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
     </div>
     <div class="span1"> <label class="small">Selectable</label><input type="checkbox" ng-model="panel.interactive" ng-checked="panel.interactive"></div>
-    <div class="span2"> 
+    <div class="span2">
       <label class="small">Zoom Links</label><input type="checkbox" ng-model="panel.zoomlinks" ng-checked="panel.zoomlinks" />
     </div>
-    <div class="span2"> 
+    <div class="span2">
       <label class="small">Auto-interval</label><input type="checkbox" ng-model="panel.auto_int" ng-checked="panel.auto_int" />
     </div>
-    <div class="span2" ng-show='panel.auto_int'> 
+    <div class="span2" ng-show='panel.auto_int'>
       <label class="small">Resolution</label><input type="number" class='input-mini' ng-model="panel.resolution" ng-change='set_refresh(true)'/>
     </div>
-    <div class="span3" ng-show='panel.auto_int'> 
+    <div class="span3" ng-show='panel.auto_int'>
       <label class="small">Shoot for this many data points, rounding to sane intervals</label>
     </div>
-    <div class="span2" ng-hide='panel.auto_int'> 
+    <div class="span2" ng-hide='panel.auto_int'>
       <label class="small">Interval</label><input type="text" class='input-mini' ng-model="panel.interval" ng-change='set_refresh(true)'/>
     </div>
-    <div class="span3" ng-hide='panel.auto_int'> 
+    <div class="span3" ng-hide='panel.auto_int'>
       <label class="small">Use Elasticsearch date math format (eg 1m, 5m, 1d, 2w, 1y)</label>
     </div>
   </div>
+  <h5>Tooltip Settings</h5>
+  <div class="row-fluid" style="margin-bottom:10px;">
+    <div class="span3">
+      <label class="small">Stacked Values <tip>How should the values in stacked charts to be calculated?></tip></label>
+      <select class="input-medium" ng-model="panel.tooltip.value_type" ng-options="f for f in ['cumulative','individual']"></select>
+    </div>
+    <div class="span3">
+      <label class="small">Display Query <tip>If an alias is set, it will be shown in the tooltip. If not, should it show the query?</tip></label>
+      <input type="checkbox" ng-model="panel.tooltip.query_as_alias" />
+    </div>
+  </div>

+ 15 - 8
panels/histogram/module.js

@@ -72,6 +72,10 @@ angular.module('kibana.histogram', [])
     'y-axis'    : true,
     percentage  : false,
     interactive : true,
+    tooltip     : {
+      value_type: 'cumulative',
+      query_as_alias: false
+    }
   };
 
   _.defaults($scope.panel,_d);
@@ -426,21 +430,24 @@ angular.module('kibana.histogram', [])
 
       var $tooltip = $('<div>');
       elem.bind("plothover", function (event, pos, item) {
-        var grouping;
+        var group, value;
         if (item) {
-          if (item.series.info.alias) {
-            grouping = '<small style="font-size:0.9em;">' +
+          if (item.series.info.alias || scope.panel.tooltip.query_as_alias) {
+            group = '<small style="font-size:0.9em;">' +
               '<i class="icon-circle" style="color:'+item.series.color+';"></i>' + ' ' +
-              item.series.info.alias +
+              (item.series.info.alias || item.series.info.query)+
             '</small><br>';
           } else {
-            grouping = kbn.query_color_dot(item.series.color, 15) + ' ';
+            group = kbn.query_color_dot(item.series.color, 15) + ' ';
+          }
+          if (scope.panel.stack && scope.panel.tooltip.value_type === 'individual')  {
+            value = item.datapoint[1] - item.datapoint[2];
+          } else {
+            value = item.datapoint[1];
           }
           $tooltip
             .html(
-              grouping +
-              item.datapoint[1].toFixed(0) + " @ " +
-              moment(item.datapoint[0]).format('MM/DD HH:mm:ss')
+              group + value + " @ " + moment(item.datapoint[0]).format('MM/DD HH:mm:ss')
             )
             .place_tt(pos.pageX, pos.pageY);
         } else {

+ 2 - 2
panels/query/module.html

@@ -45,9 +45,9 @@
     <form class="form-search" style="position:relative;margin-bottom:5px;" ng-submit="refresh()">
       <span class="begin-query">
         <i class="icon-circle pointer" data-unique="1" bs-popover="'panels/query/meta.html'" data-placement="right" ng-style="{color: querySrv.list[id].color}"></i>
-        <i class="icon-remove-sign pointer remove-query" ng-show="unPinnedQueries.length>1" ng-click="querySrv.remove(id);refresh()"></i>
+        <i class="icon-remove-sign pointer remove-query" ng-show="querySrv.ids.length > 1" ng-click="querySrv.remove(id);refresh()"></i>
       </span>
-      <input class="search-query panel-query" ng-class="{'input-block-level': unPinnedQueries.length==1,'last-query': $last,'has-remove': unPinnedQueries.length>1}" bs-typeahead="panel.history" data-min-length=0 data-items=100 type="text" ng-model="querySrv.list[id].query"/>
+      <input class="search-query panel-query" ng-class="{ 'input-block-level': unPinnedQueries.length==1, 'last-query': $last, 'has-remove': querySrv.ids.length > 1 }" bs-typeahead="panel.history" data-min-length=0 data-items=100 type="text" ng-model="querySrv.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="querySrv.set({})" ng-show="$last"></i>

+ 2 - 1
panels/table/module.html

@@ -74,7 +74,8 @@
                     <i class='icon-search pointer' ng-click="build_search(key,value)"></i>
                     <i class='icon-ban-circle pointer' ng-click="build_search(key,value,true)"></i>
                   </td>
-                  <td style="white-space:pre-wrap">{{value}}</td>
+                  <!-- At some point we need to create a more efficient way of applying the filter pipeline -->
+                  <td style="white-space:pre-wrap" ng-bind-html-unsafe="value|noXml|urlLink"></td>
                 </tr>
               </table>
             </td>