Explorar el Código

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 hace 12 años
padre
commit
2431e40145
Se han modificado 6 ficheros con 95 adiciones y 30 borrados
  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>