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

Closes #164, typeahead / autocomplete for adding graphite functions to a target expression

Torkel Ödegaard 11 лет назад
Родитель
Сommit
2be71c577c

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

@@ -13,7 +13,6 @@ function (angular, _, config, gfunc, Parser) {
   module.controller('GraphiteTargetCtrl', function($scope, $http, filterSrv) {
 
     $scope.init = function() {
-      $scope.funcCategories = gfunc.getCategories();
       parseTarget();
     };
 

+ 101 - 0
src/app/directives/addGraphiteFunc.js

@@ -0,0 +1,101 @@
+define([
+  'angular',
+  'app',
+  'underscore',
+  'jquery',
+  '../services/graphite/gfunc',
+],
+function (angular, app, _, $, gfunc) {
+  'use strict';
+
+
+  angular
+    .module('kibana.directives')
+    .directive('graphiteAddFunc', function($compile) {
+      var inputTemplate = '<input type="text"'+
+                            ' class="grafana-target-segment-input input-medium grafana-target-segment-input"' +
+                            ' spellcheck="false" style="display:none"></input>';
+
+      var buttonTemplate = '<a  class="grafana-target-segment grafana-target-function dropdown-toggle"' +
+                              ' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown"' +
+                              ' data-placement="bottom"><i class="icon-plus"></i></a>';
+
+      return {
+        link: function($scope, elem) {
+          var categories = gfunc.getCategories();
+          var allFunctions = getAllFunctionNames(categories);
+
+          $scope.functionMenu = createFunctionDropDownMenu(categories);
+
+          var $input = $(inputTemplate);
+          var $button = $(buttonTemplate);
+          $input.appendTo(elem);
+          $button.appendTo(elem);
+
+          $input.attr('data-provide', 'typeahead');
+          $input.typeahead({
+            source: allFunctions,
+            minLength: 1,
+            items: 10,
+            updater: function (value) {
+              var funcDef = gfunc.getFuncDef(value);
+
+              $scope.$apply(function() {
+                $scope.addFunction(funcDef);
+              });
+
+              $input.trigger('blur');
+              return '';
+            }
+          });
+
+          $button.click(function() {
+            $button.hide();
+            $input.show();
+            $input.focus();
+          });
+
+          $input.keyup(function() {
+            elem.toggleClass('open', $input.val() === '');
+          });
+
+          $input.blur(function() {
+            $input.hide();
+            $input.val('');
+            $button.show();
+            $button.focus();
+            // clicking the function dropdown menu wont
+            // work if you remove class at once
+            setTimeout(function() {
+              elem.removeClass('open');
+            }, 200);
+          });
+
+          $compile(elem.contents())($scope);
+        }
+      };
+    });
+
+  function getAllFunctionNames(categories) {
+    return _.reduce(categories, function(list, category) {
+      _.each(category, function(func) {
+        list.push(func.name);
+      });
+      return list;
+    }, []);
+  }
+
+  function createFunctionDropDownMenu(categories) {
+    return _.map(categories, function(list, category) {
+      return {
+        text: category,
+        submenu: _.map(list, function(value) {
+          return {
+            text: value.name,
+            click: "addFunction('" + value.name + "')",
+          };
+        })
+      };
+    });
+  }
+});

+ 2 - 1
src/app/directives/all.js

@@ -12,5 +12,6 @@ define([
   './spectrumPicker',
   './grafanaGraph',
   './bootstrap-tagsinput',
-  './bodyClass'
+  './bodyClass',
+  './addGraphiteFunc'
 ], function () {});

+ 1 - 1
src/app/directives/arrayJoin.js

@@ -31,4 +31,4 @@ function (angular, app, _) {
         }
       };
     });
-});
+});

+ 2 - 2
src/app/directives/bootstrap-tagsinput.js

@@ -101,8 +101,8 @@ function (angular, $) {
           }
 
           var li = '<li' + (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') + '>' +
-            '<a tabindex="-1" ng-href="' + (item.href || '') + '"' + (item.click ? '" ng-click="' + item.click + '"' : '') +
-              (item.target ? '" target="' + item.target + '"' : '') + (item.method ? '" data-method="' + item.method + '"' : '') +
+            '<a tabindex="-1" ng-href="' + (item.href || '') + '"' + (item.click ? ' ng-click="' + item.click + '"' : '') +
+              (item.target ? ' target="' + item.target + '"' : '') + (item.method ? ' data-method="' + item.method + '"' : '') +
               (item.configModal ? ' config-modal="' + item.configModal + '"' : "") +
               '>' + (item.text || '') + '</a>';
 

+ 3 - 23
src/app/partials/graphite/editor.html

@@ -53,7 +53,7 @@
         </ul>
 
         <input  type="text"
-                class="grafana-target-text-input span12"
+                class="grafana-target-text-input span10"
                 ng-model="target.target"
                 focus-me="showTextEditor"
                 spellcheck='false'
@@ -80,28 +80,8 @@
               {{func.text}}
             </a>
           </li>
-          <li class="dropdown dropup">
-            <a  class="grafana-target-segment grafana-target-function dropdown-toggle"
-                data-toggle="dropdown"
-                tabindex="1"
-                ng-click="addFunction">
-                <i class="icon-plus"></i>
-            </a>
-            <ul class="dropdown-menu" role="menu">
-              <li ng-repeat="(category, funcList) in funcCategories" class="dropdown-submenu" role="menuitem">
-                <a href="javascript:void(0)"
-                   tabindex="1">
-                   {{category}}
-                </a>
-                <ul class="dropdown-menu" role="menu">
-                  <li ng-repeat="func in funcList" role="menuitem">
-                    <a ng-click="addFunction(func)" tabindex="1">
-                      {{func.name}}
-                    </a>
-                  </li>
-                </ul>
-              </li>
-            </ul>
+          <li class="dropdown" graphite-add-func>
+
           </li>
         </ul>
 

+ 7 - 3
src/app/services/graphite/gfunc.js

@@ -245,8 +245,8 @@ function (_) {
     name: 'lowestCurrent',
     category: categories.Filter,
     params: [ { name: "count", type: "int" } ],
-    defaultParams: [5] 
-  }); 
+    defaultParams: [5]
+  });
 
   addFuncDef({
     name: 'movingAverage',
@@ -260,7 +260,7 @@ function (_) {
     category: categories.Filter,
     params: [ { name: "count", type: "int" } ],
     defaultParams: [5]
-  }); 
+  });
 
   addFuncDef({
     name: 'lowestAverage',
@@ -318,6 +318,10 @@ function (_) {
       return new FuncInstance(funcDef);
     },
 
+    getFuncDef: function(name) {
+      return index[name];
+    },
+
     getCategories: function() {
       return categories;
     }

+ 1 - 1
src/vendor/angular/angular-strap.js

@@ -393,7 +393,7 @@ angular.module('$strap.directives').directive('bsDropdown', [
       angular.forEach(items, function (item, index) {
         if (item.divider)
           return ul.splice(index + 1, 0, '<li class="divider"></li>');
-        var li = '<li' + (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') + '>' + '<a tabindex="-1" ng-href="' + (item.href || '') + '"' + (item.click ? '" ng-click="' + item.click + '"' : '') + (item.target ? '" target="' + item.target + '"' : '') + (item.method ? '" data-method="' + item.method + '"' : '') + '>' + (item.text || '') + '</a>';
+        var li = '<li' + (item.submenu && item.submenu.length ? ' class="dropdown-submenu"' : '') + '>' + '<a tabindex="1" ng-href="' + (item.href || '') + '"' + (item.click ? '" ng-click="' + item.click + '"' : '') + (item.target ? '" target="' + item.target + '"' : '') + (item.method ? ' data-method="' + item.method + '"' : '') + '>' + (item.text || '') + '</a>';
         if (item.submenu && item.submenu.length)
           li += buildTemplate(item.submenu).join('\n');
         li += '</li>';