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

added panel configuration framework

Rashid Khan 13 лет назад
Родитель
Сommit
19798b0891

+ 19 - 3
common/css/main.css

@@ -17,7 +17,24 @@
 .panel-error {
   opacity: 0.9;
   position:absolute;
-  z-index: 99999;
+  z-index: 2000;
+}
+
+span.editlink {
+  position: absolute;
+  right: 5px;
+  z-index: 800;
+  display: none;
+}
+
+.panel:hover span.editlink {
+  display: block;
+  opacity: 0.3;
+}
+
+.panel span.editlink:hover {
+  display: block;
+  opacity: 1;
 }
 
 .pointer {
@@ -54,8 +71,7 @@
 }
 
 .remove:hover {
-  color: #A60000;
-  text-decoration: line-through;
+  background-color: #A60000;
 }
 
 .typeahead { z-index: 1051; }

+ 18 - 55
js/directives.js

@@ -3,22 +3,26 @@
 'use strict';
 
 angular.module('kibana.directives', [])
-.directive('panel', function($compile) {
+.directive('kibanaPanel', function($compile) {
   return {
-    restrict: 'A',
-    compile: function(element, attrs) {
-      return function(scope, element, attrs) {
-        scope.$watch(function () {
-          return (attrs.panel && scope.index) ? true : false;
-        }, function (ready) {
-          if (ready) {
-            element.html($compile("<div "+attrs.panel+" params={{panel}} "+
-              "style='height:{{row.height}}'></div>")(scope))
-          }
-        });
-      }
+    restrict: 'E',
+    link: function(scope, elem, attrs) {
+      var template = '<span class="pointer editlink" bs-modal="\'partials/paneleditor.html\'" ng-show="panel.editable != false">'+
+        '<i class="icon-edit"></i></span><h4>{{panel.title}}</h4>';
+      elem.prepend($compile(angular.element(template))(scope));
+    }
+  };
+})
+.directive('panelEdit', function(){
+    return {
+        restrict: 'E',
+        replace: true,
+        scope: {
+          'panel': '=panel'
+        },
+        templateUrl: 'panels/table/editor.html',
+        //controller: 'ChildElement'
     }
-  }
 })
 .directive('arrayJoin', function() {
   return {
@@ -72,46 +76,5 @@ angular.module('kibana.directives', [])
       }
     }
   }
-})
-.directive('datepicker', function(){
-  return {
-    restrict: 'A',
-    require: 'ngModel', 
-    link: function(scope, elem, attrs) {
-      elem.datepicker({
-        noDefault: false, // set this to true if you don't want the current date inserted if the value-attribute is empty
-        format: 'mm/dd/yyyy hh:ii:ss'
-      });
-    }
-  };
-})
-.directive('date', function(dateFilter) {
-  return {
-    require: 'ngModel',
-    link: function(scope, elm, attrs, ctrl) {
-
-      var dateFormat = attrs['date'] || 'yyyy-MM-dd HH:mm:ss';
-      var minDate = Date.parse(attrs['min']) || 0;
-      var maxDate = Date.parse(attrs['max']) || 9007199254740992;
-
-      ctrl.$parsers.unshift(function(viewValue) {
-        var parsedDateMilissec = Date.parse(viewValue);
-        if (parsedDateMilissec > 0) {
-          if (parsedDateMilissec >= minDate && parsedDateMilissec <= maxDate) {
-              ctrl.$setValidity('date', true);
-              return new Date(parsedDateMilissec);
-          }
-        }
-
-        // in all other cases it is invalid, return undefined (no model update)
-        ctrl.$setValidity('date', false);
-        return undefined;
-      });
-
-      ctrl.$formatters.unshift(function(modelValue) {
-        return dateFilter(modelValue, dateFormat);
-      });
-    }
-  };
 });
 

+ 0 - 0
panels/fields/editor.html


+ 2 - 3
panels/fields/module.html

@@ -1,6 +1,5 @@
-<div ng-controller='fields'>
-  <h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4>
+<kibana-panel ng-controller='fields'>
   <ul class="nav nav-list" style="height:{{row.height}};overflow-y:auto;overflow-x:hidden;">
     <li ng-style="panel.style" ng-repeat="field in fields" ng-class="is_active(field)" ng-click="toggle_field(field)"><a>{{field}}</a></li>
   </ul>
-</div>
+</kibana-panel>

+ 0 - 0
panels/histogram/editor.html


+ 2 - 3
panels/histogram/module.html

@@ -1,4 +1,3 @@
-<div ng-controller='histogram' style="height:{{row.height}}">
-  <h4>{{panel.title}}</h4>
+<kibana-panel ng-controller='histogram' style="height:{{row.height}}">
   <div histogram params="{{panel}}" style="height:{{row.height}}"></div>
-</div>         
+</kibana-panel>         

+ 0 - 0
panels/hits/editor.html


+ 2 - 3
panels/hits/module.html

@@ -1,4 +1,3 @@
-<div ng-controller='hits'>
-  <h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4>
+<kibana-panel ng-controller='hits'>
   <p ng-style="panel.style">{{hits}}</p>
-</div>         
+</kibana-panel>         

+ 2 - 3
panels/map/module.html

@@ -1,4 +1,3 @@
-<div ng-controller='map'>
-  <h4>{{panel.title}}</h4>
+<kibana-panel ng-controller='map'>
   <div map params="{{panel}}" style="height:{{row.height}}"></div>
-</div>
+</kibana-panel>

+ 42 - 0
panels/pie/editor.html

@@ -0,0 +1,42 @@
+<h4 style="text-transform: capitalize;">{{panel.type}} <small> panel settings</small></h4>
+<div class="row-fluid">    
+  <div class="span4">
+    <form class="input-append">
+      <h5>Field</h5>
+      <input type="text" style="width:70%" ng-model="panel.query.field">
+      <button class="btn" ng-click="get_data()"><i class="icon-search"></i></button>
+    </form>
+  </div>
+  <div class="span8">
+    <form class="input-append">
+      <h5>Query</h5>
+      <input type="text" style="width:80%" ng-model="panel.query.query">
+      <button class="btn" ng-click="get_data()"><i class="icon-search"></i></button>
+    </form>
+  </div>
+</div>
+<div class="row-fluid">    
+  <div class="span1">
+    <label class="small"> Donut </label><input type="checkbox" ng-model="panel.donut" ng-checked="panel.donut">
+  </div>
+  <div class="span1">
+    <label class="small"> Tilt </label><input type="checkbox" ng-model="panel.tilt" ng-checked="panel.tilt">
+  </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"> Labels </label><input type="checkbox" ng-model="panel.labels" ng-checked="panel.labels">
+  </div>
+</div>
+<div class="row-fluid">    
+  <div class="span4">
+    <h5>Sort</h5>
+    <select style="width:85%" ng-model="panel.sort[0]" ng-options="f for f in all_fields"></select>
+    <i ng-click="set_sort(panel.sort[0])" ng-class="{'icon-chevron-up': panel.sort[1] == 'asc','icon-chevron-down': panel.sort[1] == 'desc'}"></i>
+  </div>
+  <div class="span1">
+    <h5>Length</h5>
+    <input type="number" class="input-mini" ng-model="panel.size" ng-change="get_data()">
+  </div>
+</div>

+ 2 - 3
panels/pie/module.html

@@ -1,4 +1,3 @@
-<div ng-controller='pie'>
-  <h4>{{panel.title}}</h4>
+<kibana-panel ng-controller='pie'>
   <div pie params="{{panel}}" style="height:{{row.height}}"></div>
-</div>         
+</kibana-panel>         

+ 0 - 0
panels/sort/editor.html


+ 2 - 3
panels/sort/module.html

@@ -1,6 +1,5 @@
-<div ng-controller='sort' style="white-space: nowrap;">
-  <h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4>
+<kibana-panel ng-controller='sort' style="white-space: nowrap;">
   <label><small>{{panel.label}}</small></label>
   <select style="width:85%" ng-model="panel.sort[0]" ng-change="set_sort()" ng-options="f for f in fields"></select>
   <i ng-click="toggle_sort()" ng-class="{'icon-chevron-up': panel.sort[1] == 'asc','icon-chevron-down': panel.sort[1] == 'desc'}"></i>
-</div>
+</kibana-panel>

+ 0 - 0
panels/stringquery/editor.html


+ 2 - 3
panels/stringquery/module.html

@@ -1,8 +1,7 @@
-<div ng-controller='stringquery'>
-  <h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4>
+<kibana-panel ng-controller='stringquery'>
   <form class="input-append" style="margin-bottom:0px; white-space:nowrap;">
     <label><small>{{panel.label}}</small></label>
     <input type="text" ng-model="panel.query" style="width:90%">
     <button type="submit" class="btn" ng-click="send_query(panel.query)"><i class="icon-search"></i></button>
   </form>
-</div>
+</kibana-panel>

+ 24 - 21
panels/table/editor.html

@@ -1,30 +1,33 @@
-<div class="modal-header">
-  <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
-  <h3>{{panel.title}}</h3>
-</div>
-<div class="modal-body">
-  <h4>Panel Settings</h4>
-  <form class="form-inline">
-    <label>Span</label> <input type="number" class="input-mini" ng-model="panel.span"><br>
-    <label class="checkbox"> Editable <input type="checkbox" ng-model="panel.editable" ng-checked="panel.editable"></label>
-  </form>
-  <label>Group(s)</label><input array-join type="text" class="input-large" ng-model='panel.group'></input> <small>Comma seperated</small>
-  <div class="row-fluid">
-    
+  <div class="row-fluid">    
+    <div class="span12">
+      <form class="input-append">
+        <h5>Query</h5>
+        <input type="text" style="width:90%" ng-model="panel.query">
+        <button class="btn" ng-click="get_data();"><i class="icon-search"></i></button>
+      </form>
+    </div>
+  </div>
+  <div class="row-fluid">    
     <div class="span4">
       <form class="input-append">
-        <h4>Add field</h4>
+        <h5>Add field</h5>
         <input bs-typeahead="all_fields" type="text" class="input-small" ng-model='newfield'>
         <button class="btn" ng-click="toggle_field(newfield);newfield=''"><i class="icon-plus"></i></button>
       </form>
     </div>
     <div class="span8">
-      <h4>Selected fields <small>Click to a field to remove it</small></h4>
-      <span ng-click="toggle_field(field)" ng-repeat="field in panel.fields" class="remove pointer">{{field}} </span>
+      <h5>Selected fields <small>Click to remove</small></h5>
+      <span style="margin-left:3px" ng-click="toggle_field(field)" ng-repeat="field in $parent.panel.fields" class="label remove pointer">{{field}} </span>
     </div>
   </div>
-</div>
-<div class="modal-footer">
-  <button type="button" class="btn" ng-click="dismiss()">Close</button>
-  <button class="btn btn-primary" ng-click="dismiss()">Save changes</button>
-</div>
+  <div class="row-fluid">    
+    <div class="span4">
+      <h5>Sort</h5>
+      <select style="width:85%" ng-model="panel.sort[0]" ng-options="f for f in all_fields"></select>
+      <i ng-click="set_sort(panel.sort[0])" ng-class="{'icon-chevron-up': panel.sort[1] == 'asc','icon-chevron-down': panel.sort[1] == 'desc'}"></i>
+    </div>
+    <div class="span1">
+      <h5>Length</h5>
+      <input type="number" class="input-mini" ng-model="panel.size" ng-change="get_data()">
+    </div>
+  </div>

+ 2 - 3
panels/table/module.html

@@ -1,5 +1,4 @@
-<div ng-controller='table'>
-  <h4>{{panel.title}}  <small class="pointer" bs-modal="'panels/table/editor.html'" ng-hide="!panel.editable"><i class="icon-edit"></i></small></h4>
+<kibana-panel ng-controller='table'>
   <div style="height:{{row.height}};overflow-y:auto;overflow-x:auto"> 
     <table class="table table-condensed table-striped" ng-style="panel.style">
       <thead>
@@ -15,4 +14,4 @@
       </tr>
     </table>
   </div>
-</div>         
+</kibana-panel>         

+ 3 - 0
panels/text/editor.html

@@ -0,0 +1,3 @@
+<label class="small">Font Size</label> <select class="input-mini" 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>
+<label class=small>Content</label>
+<textarea ng-model="panel.content" rows="6" style="width:95%"></textarea>

+ 2 - 3
panels/text/module.html

@@ -1,4 +1,3 @@
-<div ng-controller='text'>
-  <h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4>
+<kibana-panel ng-controller='text'>
   <p ng-style="panel.style">{{panel.content}}</p>
-</div>
+</kibana-panel>

+ 0 - 0
panels/timepicker/editor.html


+ 56 - 57
panels/timepicker/module.html

@@ -1,64 +1,63 @@
-<div ng-controller='timepicker' style="white-space: nowrap;">
-  <h4 ng-class="{'ng-cloak': !panel.title}">{{panel.title}}</h4>
-    <div class="row-fluid" ng-switch="panel.mode">
-      <div ng-switch-when="absolute">
-        <div class="span5">
-          <form class="nomargin">
-            <label><small>From</small></label>
-            <input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.from.date" data-date-format="mm/dd/yyyy" bs-datepicker>  
-            <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.from.time" bs-timepicker>
-          </form>
-        </div>
-        <div class="span5" style="margin-left:10px">
-          <form class="nomargin">
-            <label style="margin-left:5px"><small>To (<a ng-click="to_now()">now</a>)</small></label>
-            <input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.to.date" data-date-format="mm/dd/yyyy" bs-datepicker>  
-            <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.to.time" bs-timepicker>
+<kibana-panel ng-controller='timepicker' style="white-space: nowrap;">
+  <div class="row-fluid" ng-switch="panel.mode">
+    <div ng-switch-when="absolute">
+      <div class="span5">
+        <form class="nomargin">
+          <label><small>From</small></label>
+          <input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.from.date" data-date-format="mm/dd/yyyy" bs-datepicker>  
+          <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.from.time" bs-timepicker>
         </form>
-        </div>
-        <div class="span1">
-          <form class="nomargin">
-            <label><small><br></small></label>
-            <button class="btn" ng-click="time_apply()" ><i class="icon-check"></i></button>
-          </form>
-        </div>
       </div>
-      <div ng-switch-when="since">
-        <div class="span5">
-          <form class="nomargin">
-            <label><small>Since</small></label>
-            <input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.from.date" data-date-format="mm/dd/yyyy" bs-datepicker>  
-            <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.from.time" bs-timepicker>
-          </form>
-        </div>
-        <div class="span1" style="margin-left:10px">
-          <form class="nomargin">
-            <label><small><br></small></label>
-            <button class="btn" ng-click="time_apply()" ><i class="icon-check"></i></button>
-          </form>
-        </div>
+      <div class="span5" style="margin-left:10px">
+        <form class="nomargin">
+          <label style="margin-left:5px"><small>To (<a ng-click="to_now()">now</a>)</small></label>
+          <input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.to.date" data-date-format="mm/dd/yyyy" bs-datepicker>  
+          <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.to.time" bs-timepicker>
+      </form>
       </div>
-      <div ng-switch-when="relative">
-        <div class="span11">
-          <form class="nomargin input-append">
-            <label><small>The last</small></label>
-            <button class="btn btn" ng-repeat='timespan in panel.time_options' ng-class="{'btn-success': (panel.timespan == timespan)}" ng-click="set_timespan(timespan)">{{timespan}}</button>
-            <!--<select ng-model="panel.sort[0]" ng-options="f for f in fields"></select>-->
-          </form>
-        </div>
+      <div class="span1">
+        <form class="nomargin">
+          <label><small><br></small></label>
+          <button class="btn" ng-click="time_apply()" ><i class="icon-check"></i></button>
+        </form>
       </div>
     </div>
-    <div class="row-fluid nomargin">
-      <div class="span12 small">
-        <a ng-click="set_mode('relative')" ng-class="{'strong': (panel.mode == 'relative')}">Relative</a> | 
-        <a ng-click="set_mode('absolute')" ng-class="{'strong': (panel.mode == 'absolute')}">Absolute</a> | 
-        <a ng-click="set_mode('since')"    ng-class="{'strong': (panel.mode == 'since')}">Since</a>
-        <span ng-hide="panel.mode == 'absolute'"> | 
-          <input type="checkbox" ng-model="panel.refresh.enable"> Auto-refresh 
-          <span ng-class="{'ng-cloak': !panel.refresh.enable}">
-            every <a data-title="<small>Auto-refresh Settings</small>" data-placement="bottom" bs-popover="'panels/timepicker/refreshctrl.html'">{{panel.refresh.interval}}s</a>.
-          </span>
-        </span>
+    <div ng-switch-when="since">
+      <div class="span5">
+        <form class="nomargin">
+          <label><small>Since</small></label>
+          <input type="text" class="input-smaller" ng-change="time_check()" ng-model="timepicker.from.date" data-date-format="mm/dd/yyyy" bs-datepicker>  
+          <input type="text" class="input-mini" ng-change="time_check()" data-show-meridian="false" data-show-seconds="true" ng-model="timepicker.from.time" bs-timepicker>
+        </form>
+      </div>
+      <div class="span1" style="margin-left:10px">
+        <form class="nomargin">
+          <label><small><br></small></label>
+          <button class="btn" ng-click="time_apply()" ><i class="icon-check"></i></button>
+        </form>
       </div>
     </div>
-</div>
+    <div ng-switch-when="relative">
+      <div class="span11">
+        <form class="nomargin input-append">
+          <label><small>The last</small></label>
+          <button class="btn btn" ng-repeat='timespan in panel.time_options' ng-class="{'btn-success': (panel.timespan == timespan)}" ng-click="set_timespan(timespan)">{{timespan}}</button>
+          <!--<select ng-model="panel.sort[0]" ng-options="f for f in fields"></select>-->
+        </form>
+      </div>
+    </div>
+  </div>
+  <div class="row-fluid nomargin">
+    <div class="span12 small">
+      <a ng-click="set_mode('relative')" ng-class="{'strong': (panel.mode == 'relative')}">Relative</a> | 
+      <a ng-click="set_mode('absolute')" ng-class="{'strong': (panel.mode == 'absolute')}">Absolute</a> | 
+      <a ng-click="set_mode('since')"    ng-class="{'strong': (panel.mode == 'since')}">Since</a>
+      <span ng-hide="panel.mode == 'absolute'"> | 
+        <input type="checkbox" ng-model="panel.refresh.enable"> Auto-refresh 
+        <span ng-class="{'ng-cloak': !panel.refresh.enable}">
+          every <a data-title="<small>Auto-refresh Settings</small>" data-placement="bottom" bs-popover="'panels/timepicker/refreshctrl.html'">{{panel.refresh.interval}}s</a>.
+        </span>
+      </span>
+    </div>
+  </div>
+</kibana-panel>

+ 1 - 1
partials/dashboard.html

@@ -11,7 +11,7 @@
       </div>
       <div class="row-fluid" style="padding-top:10px" ng-hide="row.collapse">
         <!-- Panels -->
-        <div ng-repeat="(name, panel) in row.panels" ng-hide="panel.span == 0" class="span{{panel.span}}" style="min-height:{{row.height}}; position:relative">
+        <div ng-repeat="(name, panel) in row.panels" ng-hide="panel.span == 0" class="span{{panel.span}} panel" style="min-height:{{row.height}}; position:relative">
           <!-- Error Panel -->
           <div class="row-fluid">
             <div class="span12 alert alert-error panel-error" ng-hide="!panel.error">

+ 30 - 0
partials/paneleditor.html

@@ -0,0 +1,30 @@
+<div class="modal-header">
+  <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+  <h3>{{panel.title}} <small>editor</small></h3>
+</div>
+<div class="modal-body">
+
+
+  <h4>General</h4>
+  <div class="row-fluid">
+    <div class="span4">
+      <label class="small">Title</label><input type="text" class="input-medium" ng-model='panel.title'></input>
+    </div>
+    <div class="span4">
+      <label class="small">Group(s) (comma seperated)</label><input array-join type="text" class="input-medium" ng-model='panel.group'></input>
+    </div>
+    <div class="span2">
+      <label class="small">Span</label> <select class="input-mini" ng-model="panel.span" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10,11,12]"></select>
+    </div>
+    <div class="span1"> 
+      <label class="small"> Editable </label><input type="checkbox" ng-model="panel.editable" ng-checked="panel.editable">
+    </div>
+  </div>
+  
+  <h4 style="text-transform: capitalize;">{{panel.type}} <small> panel settings</small></h4>
+  <div ng-include src="'panels/'+panel.type+'/editor.html'">No additional settings are available for this type of panel.</div>
+  
+</div>
+<div class="modal-footer">
+  <button type="button" class="btn btn-success" ng-click="dismiss()">Close</button>
+</div>