Explorar el Código

Added details view, nested fields, clickable query building to table panel

Rashid Khan hace 13 años
padre
commit
38c92ac482
Se han modificado 7 ficheros con 78 adiciones y 13 borrados
  1. 8 0
      common/css/main.css
  2. 3 2
      js/services.js
  3. 4 0
      panels/stringquery/module.js
  4. 25 4
      panels/table/module.html
  5. 26 1
      panels/table/module.js
  6. 6 2
      scripts/load.sh
  7. 6 4
      scripts/reader.js

+ 8 - 0
common/css/main.css

@@ -10,10 +10,18 @@
   display: inline-block;
 }
 
+.odd {
+  background-color: #f9f9f9;
+}
+
 [ng\:cloak], [ng-cloak], .ng-cloak {
   display: none !important;
 }
 
+.table tbody + tbody{
+  border-top: 0px;
+}
+
 .panel-error {
   opacity: 0.9;
   position:absolute;

+ 3 - 2
js/services.js

@@ -33,9 +33,10 @@ angular.module('kibana.services', [])
       if(!(_.isArray(_group)))
         _group = [_group];
       
-      if(_.intersection(_to,_group).length > 0 || 
+      if((_.intersection(_to,_group).length > 0 || 
         _.indexOf(_to,_id) > -1 ||
-        _.indexOf(_to,'ALL') > -1
+        _.indexOf(_to,'ALL') > -1) &&
+        _from !== _id
         ) {
         //console.log('Got: '+type + ' from ' + _from + ' to ' + _to + ': ' + angular.toJson(packet.data))
         fn(event,packet.data);

+ 4 - 0
panels/stringquery/module.js

@@ -17,6 +17,10 @@ angular.module('kibana.stringquery', [])
     $scope.panel.group : [$scope.panel.group];
 
   $scope.init = function() {
+    eventBus.register($scope,'query',function(event,query) {
+      $scope.panel.query = query;
+    });
+
     $scope.send_query = function(query) {
       eventBus.broadcast($scope.$id,$scope.panel.group,'query',query)
     }    

+ 25 - 4
panels/table/module.html

@@ -14,7 +14,7 @@
       </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 table-condensed table-striped" ng-style="panel.style">
+    <table class="table-hover table table-condensed" ng-style="panel.style">
       <thead>
         <th style="white-space:nowrap" ng-repeat="field in panel.fields">
           <span  class="pointer" ng-click="set_sort(field)">
@@ -23,9 +23,30 @@
           </span>
         </th>
       </thead>
-      <tr ng-repeat="row in data">
-        <td ng-repeat="field in panel.fields">{{row['_source'][field]}}</td>
-      </tr>
+      <tbody ng-repeat="row in data" ng-class-odd="'odd'">
+        <tr ng-click="toggle_details(row)">
+          <td ng-repeat="field in panel.fields">{{row[field]}}</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">
+                <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('NOT '+key,value)"></i>
+                </td>
+                <td>{{value}}</td>
+              </tr> 
+            </table>
+          </td>
+        </tr>
+      </tbody>
     </table>
     <div class="row-fluid">
       <div class="span1 offset3" style="text-align:right">

+ 26 - 1
panels/table/module.js

@@ -24,9 +24,11 @@ angular.module('kibana.table', [])
 
   $scope.set_listeners = function(group) {
     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 = query;
       $scope.get_data();
     });
@@ -55,11 +57,25 @@ angular.module('kibana.table', [])
     broadcast_fields();
   }
 
+  $scope.toggle_details = function(row) {
+    row.kibana = row.kibana || {};
+    row.kibana.details = !row.kibana.details ? $scope.without_kibana(row) : false;
+  }
+
   $scope.page = function(page) {
     $scope.panel.offset = page*$scope.panel.size
     $scope.get_data();
   }
 
+  $scope.build_search = function(field, value) {
+    var query = field + ":" + "\"" + addslashes(value.toString()) + "\"";
+    var glue = $scope.panel.query != "" ? " AND " : "";
+    $scope.panel.query = $scope.panel.query + glue + query;
+    $scope.panel.offset = 0;
+    $scope.get_data();
+    eventBus.broadcast($scope.$id,$scope.panel.group,'query',$scope.panel.query);
+  }
+
   $scope.get_data = function() {
     // Make sure we have everything for the request to complete
     if(_.isUndefined($scope.panel.index) || _.isUndefined($scope.time))
@@ -88,13 +104,22 @@ angular.module('kibana.table', [])
       }
       $scope.panel.error =  false;
       $scope.hits = results.hits.total;
-      $scope.data = results.hits.hits;
+      $scope.data = []
+      _.each(results.hits.hits, function(v,k) {
+        $scope.data.push(flatten_json(v['_source']))
+      })
       $scope.all_fields = get_all_fields(results);
 
       broadcast_fields();
     });
   }
 
+  $scope.without_kibana = function (row) {
+    row = _.clone(row)
+    delete row.kibana
+    return row
+  } 
+
   // 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.

+ 6 - 2
scripts/load.sh

@@ -13,8 +13,12 @@ curl -XPUT http://localhost:9200/_template/shakespeare -d '
     "play_name" : {"type": "string", "index" : "not_analyzed" },
     "line_id" : { "type" : "integer", "index": "not_analyzed" },
     "speech_number" : { "type" : "integer", "index": "not_analyzed" },
-    "state" : {"type": "string", "index" : "not_analyzed" },
-    "country" : {"type": "string", "index" : "not_analyzed" }
+    "geo" : {
+      "properties": {
+        "state" : {"type": "string", "index" : "not_analyzed" },
+        "country" : {"type": "string", "index" : "not_analyzed" }
+      }
+    }
    }
   }
  }

+ 6 - 4
scripts/reader.js

@@ -24,10 +24,12 @@ fs.readFile('shakespeare.json', 'utf8', function (err,data) {
     var randomnumber=Math.floor(Math.random()*57600000)
     var command = {index:{_index: "shakespeare", _type: "line", _id: i}};
     o['@timestamp'] = new Date((new Date()).getTime() -9000000 + randomnumber);
-    o.geo = [getRandomInRange(-90, 90, 3),getRandomInRange(-180, 180, 3)]
-    o.country = get_country();
-    if(o.country == 'US')
-      o.state = get_state()
+    o.geo = {
+      geojson : [getRandomInRange(-90, 90, 3),getRandomInRange(-180, 180, 3)],
+      country : get_country()
+    }
+    if(o.geo.country == 'US')
+      o.geo.state = get_state();
     console.log(JSON.stringify(command))
     console.log(JSON.stringify(o));
     var percent = Math.floor((i/lines)*100)