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

added field selector to table panel, deprecated field panel

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

+ 0 - 1
js/controllers.js

@@ -131,7 +131,6 @@ angular.module('kibana.controllers', [])
   $scope.reset_panel = function() {
 
     $scope.panel = {
-      loading : false,
       error   : false,
       span    : 3,
       editable: true,

+ 1 - 1
js/directives.js

@@ -7,7 +7,7 @@ angular.module('kibana.directives', [])
   return {
     restrict: 'E',
     link: function(scope, elem, attrs) {
-      var template = '<img src="common/img/load.gif" class="panel-loading" ng-show="panel.loading == true">'+
+      var template = '<img src="common/img/load.gif" class="panel-loading" ng-show="panelMeta.loading == true">'+
         ' <span class="editlink panelextra pointer" style="right:15px;top:0px" ' + 
         'bs-modal="\'partials/paneleditor.html\'" ng-show="panel.editable != false">'+
         '<span class="small">{{panel.type}}</span> <i class="icon-cog pointer"></i> '+

+ 2 - 2
panels/bettermap/module.js

@@ -96,7 +96,7 @@ angular.module('kibana.bettermap', [])
 
     // Populate scope when we have results
     results.then(function(results) {
-      $scope.panel.loading = false;
+      $scope.panelMeta.loading = false;
 
       if(_segment === 0) {
         $scope.hits = 0;
@@ -174,7 +174,7 @@ angular.module('kibana.bettermap', [])
       var map, markers, layerGroup, mcg;
 
       function render_panel() { 
-        scope.panel.loading = false;
+        scope.panelMeta.loading = false;
 
         var scripts = $LAB.script("panels/bettermap/lib/leaflet.js").wait()
           .script("panels/bettermap/lib/plugins.js");

+ 2 - 2
panels/derivequeries/module.js

@@ -57,7 +57,7 @@ angular.module('kibana.derivequeries', [])
       return;
     }
 
-    $scope.panel.loading = true;
+    $scope.panelMeta.loading = true;
     var request = $scope.ejs.Request().indices(dashboard.indices);
 
     // Terms mode
@@ -78,7 +78,7 @@ angular.module('kibana.derivequeries', [])
 
     // Populate scope when we have results
     results.then(function(results) {
-      $scope.panel.loading = false;
+      $scope.panelMeta.loading = false;
       var suffix,
           data = [];
       if ($scope.panel.query === '' || $scope.panel.mode === 'terms only') {

+ 1 - 6
panels/fields/module.html

@@ -1,8 +1,3 @@
 <kibana-panel ng-controller='fields' ng-init="init()">
-  <ul class="unstyled" style="height:{{row.height}};overflow-y:auto;overflow-x:hidden;" ng-class="{'inline': panel.arrange == 'horizontal'}">
-    <li ng-style="panel.style" ng-repeat="field in fields" >
-      <i class="pointer" ng-class="{'icon-check': _.indexOf(active,field)>-1,'icon-check-empty': _.indexOf(active,field)<0}" ng-click="toggle_field(field)"></i>
-      <a data-unique="1" bs-popover="'panels/fields/micropanel.html'" data-placement="{{panel.micropanel_position}}" ng-click="toggle_micropanel(field)" ng-class="{label: _.indexOf(active,field)>-1}">{{field}}</a>
-    </li>
-  </ul>
+ <h4>The 'fields' panel is deprecated.</h4> The table panel now integrates a field selector.
 </kibana-panel>

+ 4 - 5
panels/fields/module.js

@@ -3,7 +3,7 @@
 
 /*
 
-  ## Fields
+  ## Fields (DEPRECATED)
 
 
   ### Parameters
@@ -25,10 +25,9 @@ angular.module('kibana.fields', [])
 .controller('fields', function($scope, eventBus, $timeout, dashboard, filterSrv) {
 
   $scope.panelMeta = {
-    status  : "Deprecating Soon",
-    description : "Allows for enabling and disabling of fields in the table panel as well as a "+
-      "micro anaylsis panel for analyzing the events in the table panel. This panel will soon be"+
-      "combined with the table panel"
+    status  : "Deprecated",
+    description : "You should not use this table, it does not work anymore. The table panel now"+
+      "integrates a field selector. This module will soon be removed."
   };
 
 

+ 2 - 2
panels/histogram/module.js

@@ -98,7 +98,7 @@ angular.module('kibana.histogram', [])
         kbn.calculate_interval(_range.from,_range.to,$scope.panel.resolution,0)/1000);
     }
 
-    $scope.panel.loading = true;
+    $scope.panelMeta.loading = true;
     var _segment = _.isUndefined(segment) ? 0 : segment;
     var request = $scope.ejs.Request().indices(dashboard.indices[_segment]);
 
@@ -133,7 +133,7 @@ angular.module('kibana.histogram', [])
 
     // Populate scope when we have results
     results.then(function(results) {
-      $scope.panel.loading = false;
+      $scope.panelMeta.loading = false;
       if(_segment === 0) {
         $scope.hits = 0;
         $scope.data = [];

+ 2 - 2
panels/hits/module.js

@@ -54,7 +54,7 @@ angular.module('kibana.hits', [])
 
   $scope.get_data = function(segment,query_id) {
     delete $scope.panel.error;
-    $scope.panel.loading = true;
+    $scope.panelMeta.loading = true;
 
     // Make sure we have everything for the request to complete
     if(dashboard.indices.length === 0) {
@@ -85,7 +85,7 @@ angular.module('kibana.hits', [])
 
     // Populate scope when we have results
     results.then(function(results) {
-      $scope.panel.loading = false;
+      $scope.panelMeta.loading = false;
       if(_segment === 0) {
         $scope.hits = 0;
         $scope.data = [];

+ 2 - 2
panels/map/module.js

@@ -55,7 +55,7 @@ angular.module('kibana.map', [])
     if(dashboard.indices.length === 0) {
       return;
     }
-    $scope.panel.loading = true;
+    $scope.panelMeta.loading = true;
 
 
     var request;
@@ -86,7 +86,7 @@ angular.module('kibana.map', [])
 
     // Populate scope when we have results
     results.then(function(results) {
-      $scope.panel.loading = false;
+      $scope.panelMeta.loading = false;
       $scope.hits = results.hits.total;
       $scope.data = {};
       _.each(results.facets.map.terms, function(v) {

+ 3 - 3
panels/pie/module.js

@@ -87,7 +87,7 @@ angular.module('kibana.pie', [])
     } 
 
 
-    $scope.panel.loading = true;
+    $scope.panelMeta.loading = true;
     var request = $scope.ejs.Request().indices(dashboard.indices);
 
     $scope.panel.queries.ids = querySrv.idsByMode($scope.panel.queries);
@@ -119,7 +119,7 @@ angular.module('kibana.pie', [])
 
       // Populate scope when we have results
       results.then(function(results) {
-        $scope.panel.loading = false;
+        $scope.panelMeta.loading = false;
         $scope.hits = results.hits.total;
         $scope.data = [];
         var k = 0;
@@ -143,7 +143,7 @@ angular.module('kibana.pie', [])
       results = request.doSearch();
 
       results.then(function(results) {
-        $scope.panel.loading = false;
+        $scope.panelMeta.loading = false;
         var complete  = results.hits.total;
         var remaining = $scope.panel.query.goal - complete;
         $scope.data = [

+ 25 - 0
panels/table/micropanel.html

@@ -0,0 +1,25 @@
+<a class="close" ng-click="dismiss()" href="">×</a>
+<h4>
+  Micro Analysis of {{micropanel.field}} 
+  <i class="pointer icon-search" ng-click="fieldExists(micropanel.field,'must');dismiss();"></i>
+  <i class="pointer icon-ban-circle" ng-click="fieldExists(micropanel.field,'mustNot');dismiss();"></i>
+  <br><small>{{micropanel.count}} events in the table set</small>
+</h4>
+<table style="width:480px" class='table table-bordered table-striped table-condensed'>
+  <thead>
+    <th>{{micropanel.field}}</th>
+    <th>Action</th>
+    <th>In set</th>
+  </thead>
+  <tbody>
+    <tr ng-repeat='field in micropanel.values'>
+      <td>{{{true: "__blank__",false:field[0]}[field[0] == ""]}}</td>
+      <td>
+        <i class="pointer icon-search" ng-click="build_search(micropanel.field,field[0]);dismiss();"></i>
+        <i class="pointer icon-ban-circle" ng-click="build_search(micropanel.field,field[0],true);dismiss();"></i>
+      </td>
+      <td>{{field[1]}}</td>
+    </tr>
+  </tbody>
+</table>
+<span ng-repeat='(field,count) in micropanel.related'><a ng-click="toggle_field(field)">{{field}}</a> ({{Math.round((count / micropanel.count) * 100)}}%), </span>

+ 85 - 63
panels/table/module.html

@@ -1,75 +1,97 @@
 <kibana-panel ng-controller='table' ng-init='init()'>
+  <style>
+    .table-doc-table {
+      margin-left: 0px !important;
+      overflow-y: auto;
+      overflow-x: auto;
+    }
+  </style>
 
   <span ng-show="panel.spyable" style="position:absolute;right:0px;top:0px" class='panelextra pointer'>
       <i bs-modal="'partials/modal.html'" class="icon-eye-open"></i>
   </span>
 
-  <div style="{{panel.overflow}}:{{panel.height || row.height}};overflow-y:auto;overflow-x:auto">
-    <div class="row-fluid" ng-show="panel.paging">
-      <div class="span1 offset1" style="text-align:right">
-        <i ng-click="panel.offset = 0" ng-show="panel.offset > 0" class='icon-circle-arrow-left pointer'></i>
-        <i ng-click="panel.offset = (panel.offset - panel.size)" ng-show="panel.offset > 0" class='icon-arrow-left pointer'></i>
-      </div>
-      <div class="span8" style="text-align:center">
-        <strong>{{panel.offset}}</strong> to <strong>{{panel.offset + data.slice(panel.offset,panel.offset+panel.size).length}}</strong>
-        <small> of {{data.length}} available for paging</small>
-      </div>
-      <div class="span1" style="text-align:left">
-        <i ng-click="panel.offset = (panel.offset + panel.size)" ng-show="data.length > panel.offset+panel.size" class='icon-arrow-right pointer'></i>
-      </div>
-    </div>
-    <div class="small" ng-show="panel.fields.length == 0">No columns configured. You may want to add a <strong>fields panel</strong>, or click the edit button in the top right of this panel to add some columns</div>
-    <table class="table-hover table table-condensed" ng-style="panel.style">
-      <thead ng-show="panel.header">
-        
-        <th style="white-space:nowrap" ng-repeat="field in panel.fields">
-          <i ng-show="!$first" class="pointer link icon-caret-left" ng-click="_.move(panel.fields,$index,$index-1)"></i>
+  <div class="row-fluid">
+    <div ng-class="{'span3':panel.field_list}" ng-show="panel.field_list">
+      <div class="sidebar-nav">
+        <h5>Fields <i class=" icon-chevron-sign-left pointer " ng-click="panel.field_list = !panel.field_list" bs-tooltip="'Hide field list'" ng-show="panel.field_list"></i></h5>
+        <ul class="unstyled" style="height:{{row.height}};overflow-y:auto;overflow-x:hidden;">
+          <li ng-style="panel.style" ng-repeat="field in all_fields" >
+            <i class="pointer" ng-class="{'icon-check': _.contains(panel.fields,field),'icon-check-empty': !_.contains(panel.fields,field)}" ng-click="toggle_field(field)"></i>
+            <a data-unique="1" bs-popover="'panels/table/micropanel.html'" data-placement="right" ng-click="toggle_micropanel(field)" ng-class="{label: _.contains(panel.fields,field)}">{{field}}</a>
+          </li>
+        </ul>
 
-          <span  class="pointer" ng-click="set_sort(field)" ng-show='panel.sortable'>
-            {{field}} 
-            <i ng-show='field == panel.sort[0]' class="pointer link" ng-class="{'icon-chevron-up': panel.sort[1] == 'asc','icon-chevron-down': panel.sort[1] == 'desc'}"></i>
-          </span> 
-          <span ng-show='!panel.sortable'>{{field}}</span> 
-          <i ng-show="!$last" class="pointer link icon-caret-right" ng-click="_.move(panel.fields,$index,$index+1)"></i>
-        </th>
-      
-      </thead>
-      <tbody ng-repeat="row in data | slice:panel.offset:panel.offset+panel.size" ng-class-odd="'odd'">
-        <tr ng-click="toggle_details(row)" class="pointer">
-          <td ng-repeat="field in panel.fields" ng-bind-html-unsafe="(row.highlight[field]||row._source[field]) | highlight"></td>
-        </tr>
-        <tr ng-show="row.kibana.details">
-          <td colspan=1000>
-            <table class='table table-bordered table-condensed'>
-              <thead>
-                <th>Field</th>
-                <th>Action</th>
-                <th>Value</th>
-              </thead>
-              <tr ng-repeat="(key,value) in row.kibana.details._source" ng-class-odd="'odd'">
-                <td>{{key}}</td>
-                <td>
-                  <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>{{value}}</td>
-              </tr> 
-            </table>
-          </td>
-        </tr>
-      </tbody>
-    </table>
-    <div class="row-fluid" ng-show="panel.paging">
-      <div class="span1 offset3" style="text-align:right">
-        <i ng-click="panel.offset = 0" ng-show="panel.offset > 0" class='icon-circle-arrow-left pointer'></i>
-        <i ng-click="panel.offset = (panel.offset - panel.size)" ng-show="panel.offset > 0" class='icon-arrow-left pointer'></i>
       </div>
-      <div class="span4" style="text-align:center">
-        <strong>{{panel.offset}}</strong> to <strong>{{panel.offset + data.slice(panel.offset,panel.offset+panel.size).length}}</strong>
-        <small> of {{data.length}} available for paging</small>
+    </div>
+    <div style="{{panel.overflow}}:{{panel.height || row.height}};" ng-class="{'span9':panel.field_list,'span12':!panel.field_list}" class="table-doc-table">
+      <i class="pull-left icon-chevron-sign-right pointer" ng-click="panel.field_list = !panel.field_list" bs-tooltip="'Show field list'" ng-show="!panel.field_list"></i>
+      <div class="row-fluid" ng-show="panel.paging">
+        <div class="span1 offset1" style="text-align:right">
+          <i ng-click="panel.offset = 0" ng-show="panel.offset > 0" class='icon-circle-arrow-left pointer'></i>
+          <i ng-click="panel.offset = (panel.offset - panel.size)" ng-show="panel.offset > 0" class='icon-arrow-left pointer'></i>
+        </div>
+        <div class="span8" style="text-align:center">
+          <strong>{{panel.offset}}</strong> to <strong>{{panel.offset + data.slice(panel.offset,panel.offset+panel.size).length}}</strong>
+          <small> of {{data.length}} available for paging</small>
+        </div>
+        <div class="span1" style="text-align:left">
+          <i ng-click="panel.offset = (panel.offset + panel.size)" ng-show="data.length > panel.offset+panel.size" class='icon-arrow-right pointer'></i>
+        </div>
       </div>
-      <div class="span1" style="text-align:left">
-        <i ng-click="panel.offset = (panel.offset + panel.size)" ng-show="data.length > panel.offset+panel.size" class='icon-arrow-right pointer'></i>
+      <div class="small" ng-show="panel.fields.length == 0">No columns configured. You may want to add a <strong>fields panel</strong>, or click the edit button in the top right of this panel to add some columns</div>
+      <table class="table-hover table table-condensed" ng-style="panel.style">
+        <thead ng-show="panel.header">
+          
+          <th style="white-space:nowrap" ng-repeat="field in panel.fields">
+            <i ng-show="!$first" class="pointer link icon-caret-left" ng-click="_.move(panel.fields,$index,$index-1)"></i>
+
+            <span  class="pointer" ng-click="set_sort(field)" ng-show='panel.sortable'>
+              {{field}} 
+              <i ng-show='field == panel.sort[0]' class="pointer link" ng-class="{'icon-chevron-up': panel.sort[1] == 'asc','icon-chevron-down': panel.sort[1] == 'desc'}"></i>
+            </span> 
+            <span ng-show='!panel.sortable'>{{field}}</span> 
+            <i ng-show="!$last" class="pointer link icon-caret-right" ng-click="_.move(panel.fields,$index,$index+1)"></i>
+          </th>
+        
+        </thead>
+        <tbody ng-repeat="row in data | slice:panel.offset:panel.offset+panel.size" ng-class-odd="'odd'">
+          <tr ng-click="toggle_details(row)" class="pointer">
+            <td ng-repeat="field in panel.fields" ng-bind-html-unsafe="(row.highlight[field]||row._source[field]) | highlight"></td>
+          </tr>
+          <tr ng-show="row.kibana.details">
+            <td colspan=1000>
+              <table class='table table-bordered table-condensed'>
+                <thead>
+                  <th>Field</th>
+                  <th>Action</th>
+                  <th>Value</th>
+                </thead>
+                <tr ng-repeat="(key,value) in row.kibana.details._source" ng-class-odd="'odd'">
+                  <td>{{key}}</td>
+                  <td>
+                    <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>{{value}}</td>
+                </tr> 
+              </table>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+      <div class="row-fluid" ng-show="panel.paging">
+        <div class="span1 offset3" style="text-align:right">
+          <i ng-click="panel.offset = 0" ng-show="panel.offset > 0" class='icon-circle-arrow-left pointer'></i>
+          <i ng-click="panel.offset = (panel.offset - panel.size)" ng-show="panel.offset > 0" class='icon-arrow-left pointer'></i>
+        </div>
+        <div class="span4" style="text-align:center">
+          <strong>{{panel.offset}}</strong> to <strong>{{panel.offset + data.slice(panel.offset,panel.offset+panel.size).length}}</strong>
+          <small> of {{data.length}} available for paging</small>
+        </div>
+        <div class="span1" style="text-align:left">
+          <i ng-click="panel.offset = (panel.offset + panel.size)" ng-show="data.length > panel.offset+panel.size" class='icon-arrow-right pointer'></i>
+        </div>
       </div>
     </div>
   </div>

+ 21 - 33
panels/table/module.js

@@ -53,26 +53,28 @@ angular.module('kibana.table', [])
     highlight : [],
     sortable: true,
     header  : true,
-    paging  : true, 
-    spyable: true
+    paging  : true,
+    field_list: true, 
+    spyable : true
   };
   _.defaults($scope.panel,_d);
 
   $scope.init = function () {
-    $scope.set_listeners($scope.panel.group);
+    $scope.Math = Math;
+
+    $scope.$on('refresh',function(){$scope.get_data();});
 
     $scope.get_data();
   };
 
-  $scope.set_listeners = function(group) {
-    $scope.$on('refresh',function(){$scope.get_data();});
-    eventBus.register($scope,'sort', function(event,sort){
-      $scope.panel.sort = _.clone(sort);
-      $scope.get_data();
-    });
-    eventBus.register($scope,'selected_fields', function(event, fields) {
-      $scope.panel.fields = _.clone(fields);
-    });
+  $scope.toggle_micropanel = function(field) {
+    var docs = _.pluck($scope.data,'_source');
+    $scope.micropanel = {
+      field: field,
+      values : kbn.top_field_values(docs,field,10),
+      related : kbn.get_related_fields(docs,field),
+      count: _.countBy(docs,function(doc){return _.contains(_.keys(doc),field);})['true']
+    };
   };
 
   $scope.set_sort = function(field) {
@@ -90,7 +92,6 @@ angular.module('kibana.table', [])
     } else {
       $scope.panel.fields.push(field);
     }
-    broadcast_results();
   };
 
   $scope.toggle_highlight = function(field) {
@@ -124,6 +125,11 @@ angular.module('kibana.table', [])
     dashboard.refresh();
   };
 
+  $scope.fieldExists = function(field,mandate) {
+    filterSrv.set({type:'exists',field:field,mandate:mandate});
+    dashboard.refresh();
+  };
+
   $scope.get_data = function(segment,query_id) {
     $scope.panel.error =  false;
 
@@ -132,7 +138,7 @@ angular.module('kibana.table', [])
       return;
     }
     
-    $scope.panel.loading = true;
+    $scope.panelMeta.loading = true;
 
     $scope.panel.queries.ids = querySrv.idsByMode($scope.panel.queries);
 
@@ -166,7 +172,7 @@ angular.module('kibana.table', [])
 
     // Populate scope when we have results
     results.then(function(results) {
-      $scope.panel.loading = false;
+      $scope.panelMeta.loading = false;
 
       if(_segment === 0) {
         $scope.hits = 0;
@@ -210,7 +216,6 @@ angular.module('kibana.table', [])
       
       // This breaks, use $scope.data for this
       $scope.all_fields = kbn.get_all_fields(_.pluck($scope.data,'_source'));
-      broadcast_results();
 
       // If we're not sorting in reverse chrono order, query every index for
       // size*pages results
@@ -242,23 +247,6 @@ angular.module('kibana.table', [])
     };
   }; 
 
-  // Broadcast a list of all fields. Note that receivers of field array 
-  // events should be able to receive from multiple sources, merge, dedupe 
-  // and sort on the fly if needed.
-  function broadcast_results() {
-    eventBus.broadcast($scope.$id,$scope.panel.group,"fields", {
-      all   : $scope.all_fields,
-      sort  : $scope.panel.sort,
-      active: $scope.panel.fields      
-    });
-    eventBus.broadcast($scope.$id,$scope.panel.group,"table_documents", 
-      {
-        query: querySrv.list[querySrv.ids[0]].query,
-        docs : _.pluck($scope.data,'_source'),
-        index: $scope.index
-      });
-  }
-
   $scope.set_refresh = function (state) { 
     $scope.refresh = state; 
   };

+ 2 - 2
panels/terms/module.js

@@ -64,7 +64,7 @@ angular.module('kibana.terms', [])
       return;
     } 
 
-    $scope.panel.loading = true;
+    $scope.panelMeta.loading = true;
     var request,
       results,
       boolQuery;
@@ -97,7 +97,7 @@ angular.module('kibana.terms', [])
     // Populate scope when we have results
     results.then(function(results) {
       var k = 0;
-      $scope.panel.loading = false;
+      $scope.panelMeta.loading = false;
       $scope.hits = results.hits.total;
       $scope.data = [];
       _.each(results.facets.terms.terms, function(v) {

+ 2 - 2
panels/trends/module.js

@@ -47,7 +47,7 @@ angular.module('kibana.trends', [])
 
   $scope.get_data = function(segment,query_id) {
     delete $scope.panel.error;
-    $scope.panel.loading = true;
+    $scope.panelMeta.loading = true;
 
     // Make sure we have everything for the request to complete
     if(dashboard.indices.length === 0) {
@@ -138,7 +138,7 @@ angular.module('kibana.trends', [])
   // Populate scope when we have results
   var process_results = function(results,_segment,query_id) { 
     results.then(function(results) {
-      $scope.panel.loading = false;
+      $scope.panelMeta.loading = false;
       if(_segment === 0) {
         $scope.hits = {};
         $scope.data = [];