From 2be71c577c2e53289426ecc189ef797ce0e430ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 4 Mar 2014 18:50:38 +0100 Subject: [PATCH] Closes #164, typeahead / autocomplete for adding graphite functions to a target expression --- src/app/controllers/graphiteTarget.js | 1 - src/app/directives/addGraphiteFunc.js | 101 ++++++++++++++++++++++ src/app/directives/all.js | 3 +- src/app/directives/arrayJoin.js | 2 +- src/app/directives/bootstrap-tagsinput.js | 4 +- src/app/partials/graphite/editor.html | 26 +----- src/app/services/graphite/gfunc.js | 10 ++- src/vendor/angular/angular-strap.js | 2 +- 8 files changed, 117 insertions(+), 32 deletions(-) create mode 100644 src/app/directives/addGraphiteFunc.js diff --git a/src/app/controllers/graphiteTarget.js b/src/app/controllers/graphiteTarget.js index 6c0f4aca09d..07ae8bec5dd 100644 --- a/src/app/controllers/graphiteTarget.js +++ b/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(); }; diff --git a/src/app/directives/addGraphiteFunc.js b/src/app/directives/addGraphiteFunc.js new file mode 100644 index 00000000000..6ea24a18cfe --- /dev/null +++ b/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 = ''; + + var buttonTemplate = ''; + + 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 + "')", + }; + }) + }; + }); + } +}); \ No newline at end of file diff --git a/src/app/directives/all.js b/src/app/directives/all.js index 14b918c570d..f9befcf40d1 100644 --- a/src/app/directives/all.js +++ b/src/app/directives/all.js @@ -12,5 +12,6 @@ define([ './spectrumPicker', './grafanaGraph', './bootstrap-tagsinput', - './bodyClass' + './bodyClass', + './addGraphiteFunc' ], function () {}); \ No newline at end of file diff --git a/src/app/directives/arrayJoin.js b/src/app/directives/arrayJoin.js index 2b614c40335..db85fe3719e 100644 --- a/src/app/directives/arrayJoin.js +++ b/src/app/directives/arrayJoin.js @@ -31,4 +31,4 @@ function (angular, app, _) { } }; }); -}); \ No newline at end of file +}); diff --git a/src/app/directives/bootstrap-tagsinput.js b/src/app/directives/bootstrap-tagsinput.js index 356ed60b195..5012fa03212 100644 --- a/src/app/directives/bootstrap-tagsinput.js +++ b/src/app/directives/bootstrap-tagsinput.js @@ -101,8 +101,8 @@ function (angular, $) { } var li = '' + - '' + (item.text || '') + ''; diff --git a/src/app/partials/graphite/editor.html b/src/app/partials/graphite/editor.html index c1304bce136..65cfe883181 100644 --- a/src/app/partials/graphite/editor.html +++ b/src/app/partials/graphite/editor.html @@ -53,7 +53,7 @@ - diff --git a/src/app/services/graphite/gfunc.js b/src/app/services/graphite/gfunc.js index e7aab235630..8631db50bcd 100644 --- a/src/app/services/graphite/gfunc.js +++ b/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; } diff --git a/src/vendor/angular/angular-strap.js b/src/vendor/angular/angular-strap.js index 281ce1145f4..faed7c5d0df 100644 --- a/src/vendor/angular/angular-strap.js +++ b/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, '
  • '); - var li = '' + '' + (item.text || '') + ''; + var li = '' + '' + (item.text || '') + ''; if (item.submenu && item.submenu.length) li += buildTemplate(item.submenu).join('\n'); li += '';