Browse Source

added func controls

Torkel Ödegaard 11 years ago
parent
commit
feb20243e5

+ 1 - 1
src/app/controllers/graphiteTarget.js

@@ -10,7 +10,7 @@ function (angular, _, config, gfunc, Parser) {
 
   var module = angular.module('kibana.controllers');
 
-  module.controller('GraphiteTargetCtrl', function($scope, $http, filterSrv, $timeout) {
+  module.controller('GraphiteTargetCtrl', function($scope, $http, filterSrv) {
 
     $scope.init = function() {
       parseTarget();

+ 168 - 87
src/app/directives/graphiteFuncEditor.js

@@ -14,120 +14,201 @@ function (angular, _, $) {
       var paramTemplate = '<input type="text" style="display:none"' +
                           ' class="input-mini grafana-function-param-input"></input>';
 
-      var clickFuncParam = function(func, paramIndex) {
-        var $link = $(this);
-        var $input = $link.next();
-
-        $input.val(func.params[paramIndex]);
-        $input.css('width', ($link.width() + 16) + 'px');
-
-        $link.hide();
-        $input.show();
-        $input.focus();
-        $input.select();
-
-        var typeahead = $input.data('typeahead');
-        if (typeahead) {
-          $input.val('');
-          typeahead.lookup();
-        }
-      };
+      var funcControlsTemplate =
+         '<span class="graphite-func-controls">' +
+           '<span class="pointer icon-arrow-left"></span>' +
+           '<span class="pointer icon-info-sign"></span>' +
+           '<span class="pointer icon-remove" ></span>' +
+           '<span class="pointer icon-arrow-right"></span>' +
+         '</span>';
 
-      var inputBlur = function(scope, func, paramIndex) {
-        var $input = $(this);
-        var $link = $input.prev();
+      return {
+        restrict: 'A',
+        link: function postLink($scope, elem) {
+          var $funcLink = $(funcSpanTemplate);
+          var $funcControls = $(funcControlsTemplate);
+          var func = $scope.func;
+          var funcDef = func.def;
 
-        if ($input.val() !== '') {
-          $link.text($input.val());
+          function clickFuncParam(paramIndex) {
+            /*jshint validthis:true */
 
-          if (func.updateParam($input.val(), paramIndex)) {
-            scope.$apply(function() {
-              scope.targetChanged();
-            });
-          }
-        }
+            var $link = $(this);
+            var $input = $link.next();
 
-        $input.hide();
-        $link.show();
-      };
+            $input.val(func.params[paramIndex]);
+            $input.css('width', ($link.width() + 16) + 'px');
 
-      var inputKeyPress = function(scope, func, paramIndex, e) {
-        if(e.which === 13) {
-          inputBlur.call(this, scope, func, paramIndex);
-        }
-      };
+            $link.hide();
+            $input.show();
+            $input.focus();
+            $input.select();
 
-      var inputKeyDown = function() {
-        this.style.width = (3 + this.value.length) * 8 + 'px';
-      };
+            var typeahead = $input.data('typeahead');
+            if (typeahead) {
+              $input.val('');
+              typeahead.lookup();
+            }
+          }
 
-      var addTypeahead = function($input, scope, func, paramIndex) {
-        $input.attr('data-provide', 'typeahead');
+          function inputBlur(paramIndex) {
+            /*jshint validthis:true */
 
-        var options = func.def.params[paramIndex].options;
-        if (func.def.params[paramIndex].type === 'int') {
-          options = _.map(options, function(val) { return val.toString(); } );
-        }
+            var $input = $(this);
+            var $link = $input.prev();
 
-        $input.typeahead({
-          source: options,
-          minLength: 0,
-          items: 20,
-          updater: function (value) {
-            setTimeout(function() {
-              inputBlur.call($input[0], scope, func, paramIndex);
-            }, 0);
-            return value;
+            if ($input.val() !== '') {
+              $link.text($input.val());
+
+              if (func.updateParam($input.val(), paramIndex)) {
+                $scope.$apply(function() {
+                  $scope.targetChanged();
+                });
+              }
+            }
+
+            $input.hide();
+            $link.show();
           }
-        });
 
-        var typeahead = $input.data('typeahead');
-        typeahead.lookup = function () {
-          this.query = this.$element.val() || '';
-          return this.process(this.source);
-        };
+          function inputKeyPress(paramIndex, e) {
+            /*jshint validthis:true */
 
-      };
+            if(e.which === 13) {
+              inputBlur.call(this, paramIndex);
+            }
+          }
 
-      return {
-        restrict: 'A',
-        link: function postLink($scope, elem) {
-          var $funcLink = $(funcSpanTemplate);
+          function inputKeyDown() {
+            /*jshint validthis:true */
+            this.style.width = (3 + this.value.length) * 8 + 'px';
+          }
 
-          $funcLink.appendTo(elem);
+          function addTypeahead($input, paramIndex) {
+            $input.attr('data-provide', 'typeahead');
 
-          _.each($scope.func.def.params, function(param, index) {
-            var $paramLink = $('<a ng-click="">' + $scope.func.params[index] + '</a>');
-            var $input = $(paramTemplate);
+            var options = funcDef.params[paramIndex].options;
+            if (funcDef.params[paramIndex].type === 'int') {
+              options = _.map(options, function(val) { return val.toString(); } );
+            }
 
-            $paramLink.appendTo(elem);
-            $input.appendTo(elem);
+            $input.typeahead({
+              source: options,
+              minLength: 0,
+              items: 20,
+              updater: function (value) {
+                setTimeout(function() {
+                  inputBlur.call($input[0], paramIndex);
+                }, 0);
+                return value;
+              }
+            });
 
-            $input.blur(_.partial(inputBlur, $scope, $scope.func, index));
-            $input.keyup(inputKeyDown);
-            $input.keypress(_.partial(inputKeyPress, $scope, $scope.func, index));
-            $paramLink.click(_.partial(clickFuncParam, $scope.func, index));
+            var typeahead = $input.data('typeahead');
+            typeahead.lookup = function () {
+              this.query = this.$element.val() || '';
+              return this.process(this.source);
+            };
+          }
 
-            if (index !== $scope.func.def.params.length - 1) {
-              $('<span>, </span>').appendTo(elem);
+          function getPosition() {
+            var el = elem[0];
+            var pos = {};
+            if (typeof el.getBoundingClientRect === 'function') {
+              pos = el.getBoundingClientRect();
             }
-
-            if ($scope.func.def.params[index].options) {
-              addTypeahead($input, $scope, $scope.func, index);
+            else {
+              pos = { width: el.offsetWidth, height: el.offsetHeight };
             }
 
-          });
+            return $.extend(pos, elem.offset());
+          }
+
+          function toggleFuncControls() {
+            var targetDiv = elem.closest('.grafana-target-inner');
 
-          $('<span>)</span>').appendTo(elem);
+            if (elem.hasClass('show-function-controls')) {
+              elem.removeClass('show-function-controls');
+              targetDiv.removeClass('has-open-function');
+              $funcControls.hide();
+              return;
+            }
 
-          $compile(elem.contents())($scope);
+            elem.addClass('show-function-controls');
+            targetDiv.addClass('has-open-function');
 
-          if ($scope.func.added) {
-            $scope.func.added = false;
             setTimeout(function() {
-              elem.find('a').click();
+              var pos = getPosition();
+              $funcControls.css('position', 'absolute');
+              $funcControls.css('top', (pos.top - 78) + 'px');
+              $funcControls.css('left', pos.left + 'px');
+              $funcControls.css('width', pos.width + 'px');
+              console.log(pos);
+              $funcControls.show();
             }, 10);
           }
+
+          function addElementsAndCompile() {
+            $funcLink.appendTo(elem);
+
+            _.each(funcDef.params, function(param, index) {
+              var $paramLink = $('<a ng-click="" class="graphite-func-param-link">' + func.params[index] + '</a>');
+              var $input = $(paramTemplate);
+
+              $paramLink.appendTo(elem);
+              $input.appendTo(elem);
+
+              $input.blur(_.partial(inputBlur, index));
+              $input.keyup(inputKeyDown);
+              $input.keypress(_.partial(inputKeyPress, index));
+              $paramLink.click(_.partial(clickFuncParam, index));
+
+              if (index !== funcDef.params.length - 1) {
+                $('<span>, </span>').appendTo(elem);
+              }
+
+              if (funcDef.params[index].options) {
+                addTypeahead($input, index);
+              }
+
+            });
+
+            $('<span>)</span>').appendTo(elem);
+
+            elem.append($funcControls);
+
+            $compile(elem.contents())($scope);
+          }
+
+          function ifJustAddedFocusFistParam() {
+            if ($scope.func.added) {
+              $scope.func.added = false;
+              setTimeout(function() {
+                elem.find('.graphite-func-param-link').first().click();
+              }, 10);
+            }
+          }
+
+          function registerFuncControlsToggle() {
+            $funcLink.click(toggleFuncControls);
+          }
+
+          function registerFuncControlsActions() {
+            $funcControls.click(function(e) {
+              var $target = $(e.target);
+              if ($target.hasClass('icon-remove')) {
+                toggleFuncControls();
+                $scope.$apply(function() {
+                  $scope.removeFunction($scope.func);
+                });
+              }
+            });
+          }
+
+          addElementsAndCompile();
+          ifJustAddedFocusFistParam();
+          registerFuncControlsToggle();
+          registerFuncControlsActions();
         }
       };
 

+ 85 - 87
src/app/partials/graphite/editor.html

@@ -7,99 +7,97 @@
         ng-controller="GraphiteTargetCtrl"
         ng-init="init()">
 
-    <div class="grafana-target-inner-wrapper">
-      <div class="grafana-target-inner">
-        <ul class="grafana-target-controls">
-          <li ng-show="parserError">
-            <a bs-tooltip="parserError" style="color: rgb(229, 189, 28)" role="menuitem">
-              <i class="icon-warning-sign"></i>
-            </a>
-          </li>
-          <li>
-            <a class="pointer" tabindex="1" ng-click="showTextEditor = !showTextEditor">
-              <i class="icon-pencil"></i>
-            </a>
-          </li>
-          <li class="dropdown">
-            <a  class="pointer dropdown-toggle"
-                data-toggle="dropdown"
-                tabindex="1">
-              <i class="icon-cog"></i>
-            </a>
-            <ul class="dropdown-menu pull-right" role="menu">
-              <li role="menuitem">
-                <a  tabindex="1"
-                    ng-click="duplicate()">
-                  Duplicate
-                </a>
-              </li>
-            </ul>
-          </li>
-          <li>
-            <a class="pointer" tabindex="1" ng-click="removeTarget(target)">
-              <i class="icon-remove"></i>
-            </a>
-          </li>
-        </ul>
+    <div class="grafana-target-inner">
+      <ul class="grafana-target-controls">
+        <li ng-show="parserError">
+          <a bs-tooltip="parserError" style="color: rgb(229, 189, 28)" role="menuitem">
+            <i class="icon-warning-sign"></i>
+          </a>
+        </li>
+        <li>
+          <a class="pointer" tabindex="1" ng-click="showTextEditor = !showTextEditor">
+            <i class="icon-pencil"></i>
+          </a>
+        </li>
+        <li class="dropdown">
+          <a  class="pointer dropdown-toggle"
+              data-toggle="dropdown"
+              tabindex="1">
+            <i class="icon-cog"></i>
+          </a>
+          <ul class="dropdown-menu pull-right" role="menu">
+            <li role="menuitem">
+              <a  tabindex="1"
+                  ng-click="duplicate()">
+                Duplicate
+              </a>
+            </li>
+          </ul>
+        </li>
+        <li>
+          <a class="pointer" tabindex="1" ng-click="removeTarget(target)">
+            <i class="icon-remove"></i>
+          </a>
+        </li>
+      </ul>
 
-        <ul class="grafana-target-controls-left">
-          <li>
-            <a  class="grafana-target-segment"
-                ng-click="target.hide = !target.hide; get_data();"
-                role="menuitem">
-              <i class="icon-eye-open"></i>
-            </a>
-          </li>
-        </ul>
+      <ul class="grafana-target-controls-left">
+        <li>
+          <a  class="grafana-target-segment"
+              ng-click="target.hide = !target.hide; get_data();"
+              role="menuitem">
+            <i class="icon-eye-open"></i>
+          </a>
+        </li>
+      </ul>
 
-        <input  type="text"
-                class="grafana-target-text-input span10"
-                ng-model="target.target"
-                focus-me="showTextEditor"
-                spellcheck='false'
-                ng-model-onblur ng-change="targetTextChanged()"
-                ng-show="showTextEditor" />
+      <input  type="text"
+              class="grafana-target-text-input span10"
+              ng-model="target.target"
+              focus-me="showTextEditor"
+              spellcheck='false'
+              ng-model-onblur ng-change="targetTextChanged()"
+              ng-show="showTextEditor" />
 
-        <ul class="grafana-segment-list" role="menu" ng-hide="showTextEditor">
-          <li class="dropdown" ng-repeat="segment in segments" role="menuitem">
-            <a  tabindex="1"
-                class="grafana-target-segment dropdown-toggle"
-                data-toggle="dropdown"
-                ng-click="getAltSegments($index)"
-                focus-me="segment.focus"
-                ng-bind-html-unsafe="segment.html">
-            </a>
-            <ul class="dropdown-menu scrollable grafana-segment-dropdown-menu" role="menu">
-              <li ng-repeat="altSegment in altSegments" role="menuitem">
-                <a href="javascript:void(0)" tabindex="1" ng-click="setSegment($index, $parent.$index)" ng-bind-html-unsafe="altSegment.html"></a>
-              </li>
-            </ul>
-          </li>
-          <li ng-repeat="func in functions">
-            <span graphite-func-editor class="grafana-target-segment grafana-target-function">
-            </span>
-            <!-- <a  class="grafana-target-segment grafana-target-function dropdown-toggle"
-                bs-popover="'app/partials/graphite/funcEditor.html'"
-                data-placement="bottom">
-              {{func.def.name}}
-            </a> -->
-            <!-- <span class="grafana-target-segment grafana-target-function">
-              <span>{{func.def.name}}(</span><span ng-repeat="param in func.def.params">
-                <input  type="text"
-                        class="input-mini grafana-function-param-input"
-                        dynamic-width
-                        ng-model="func.params[$index]"></input>
-              </span><span>)</span>
-            </span> -->
-          </li>
-          <li class="dropdown" graphite-add-func>
+      <ul class="grafana-segment-list" role="menu" ng-hide="showTextEditor">
+        <li class="dropdown" ng-repeat="segment in segments" role="menuitem">
+          <a  tabindex="1"
+              class="grafana-target-segment dropdown-toggle"
+              data-toggle="dropdown"
+              ng-click="getAltSegments($index)"
+              focus-me="segment.focus"
+              ng-bind-html-unsafe="segment.html">
+          </a>
+          <ul class="dropdown-menu scrollable grafana-segment-dropdown-menu" role="menu">
+            <li ng-repeat="altSegment in altSegments" role="menuitem">
+              <a href="javascript:void(0)" tabindex="1" ng-click="setSegment($index, $parent.$index)" ng-bind-html-unsafe="altSegment.html"></a>
+            </li>
+          </ul>
+        </li>
+        <li ng-repeat="func in functions">
+          <span graphite-func-editor class="grafana-target-segment grafana-target-function">
+          </span>
+          <!-- <a  class="grafana-target-segment grafana-target-function dropdown-toggle"
+              bs-popover="'app/partials/graphite/funcEditor.html'"
+              data-placement="bottom">
+            {{func.def.name}}
+          </a> -->
+          <!-- <span class="grafana-target-segment grafana-target-function">
+            <span>{{func.def.name}}(</span><span ng-repeat="param in func.def.params">
+              <input  type="text"
+                      class="input-mini grafana-function-param-input"
+                      dynamic-width
+                      ng-model="func.params[$index]"></input>
+            </span><span>)</span>
+          </span> -->
+        </li>
+        <li class="dropdown" graphite-add-func>
 
-          </li>
-        </ul>
+        </li>
+      </ul>
 
 
-        <div class="clearfix"></div>
-      </div>
+      <div class="clearfix"></div>
     </div>
   </div>
 </div>

File diff suppressed because it is too large
+ 0 - 0
src/css/bootstrap.dark.min.css


File diff suppressed because it is too large
+ 0 - 0
src/css/bootstrap.light.min.css


+ 28 - 4
src/css/less/grafana.less

@@ -221,16 +221,16 @@
   border-bottom: 1px solid @grafanaTargetBorder;
 }
 
-.grafana-target-inner-wrapper {
-  width: 100%;
-}
-
 .grafana-target-inner {
   border-top: 1px solid @grafanaTargetBorder;
   border-left: 1px solid @grafanaTargetBorder;
   border-right: 1px solid @grafanaTargetBorder;
   background: @grafanaTargetBackground;
   width: 100%;
+
+  &.has-open-function {
+    margin-top: 35px;
+  }
 }
 
 .grafana-target-onoff {
@@ -282,6 +282,11 @@
   > a:hover {
     color: @linkColor;
   }
+
+  &.show-function-controls {
+    min-width: 100px;
+    text-align: center;
+  }
 }
 
 input[type=text].grafana-function-param-input {
@@ -358,6 +363,25 @@ select.grafana-target-segment-input {
   padding: 0; margin: 0;
 }
 
+.graphite-func-controls {
+  display: none;
+  text-align: center;
+
+  .icon-arrow-left {
+    float: left;
+    position: relative;
+    top: 2px;
+  }
+  .icon-arrow-right {
+    float: right;
+    position: relative;
+    top: 2px;
+  }
+  .icon-remove {
+    margin-left: 10px;
+  }
+}
+
 input[type=text].func-param {
   border: none;
   background: inherit;

Some files were not shown because too many files changed in this diff