diff --git a/public/app/plugins/datasource/graphite/func_editor.js b/public/app/plugins/datasource/graphite/func_editor.js deleted file mode 100644 index 5648aa4935b..00000000000 --- a/public/app/plugins/datasource/graphite/func_editor.js +++ /dev/null @@ -1,309 +0,0 @@ -define([ - 'angular', - 'lodash', - 'jquery', - 'rst2html', -], -function (angular, _, $, rst2html) { - 'use strict'; - - angular - .module('grafana.directives') - .directive('graphiteFuncEditor', function($compile, templateSrv, popoverSrv) { - - var funcSpanTemplate = '{{func.def.name}}('; - var paramTemplate = ''; - - var funcControlsTemplate = - '
' + - '' + - '' + - '' + - '' + - '
'; - - return { - restrict: 'A', - link: function postLink($scope, elem) { - var $funcLink = $(funcSpanTemplate); - var $funcControls = $(funcControlsTemplate); - var ctrl = $scope.ctrl; - var func = $scope.func; - var scheduledRelink = false; - var paramCountAtLink = 0; - var cancelBlur = null; - - function clickFuncParam(paramIndex) { - /*jshint validthis:true */ - - var $link = $(this); - var $comma = $link.prev('.comma'); - var $input = $link.next(); - - $input.val(func.params[paramIndex]); - - $comma.removeClass('query-part__last'); - $link.hide(); - $input.show(); - $input.focus(); - $input.select(); - - var typeahead = $input.data('typeahead'); - if (typeahead) { - $input.val(''); - typeahead.lookup(); - } - } - - function scheduledRelinkIfNeeded() { - if (paramCountAtLink === func.params.length) { - return; - } - - if (!scheduledRelink) { - scheduledRelink = true; - setTimeout(function() { - relink(); - scheduledRelink = false; - }, 200); - } - } - - function paramDef(index) { - if (index < func.def.params.length) { - return func.def.params[index]; - } - if (_.last(func.def.params).multiple) { - return _.assign({}, _.last(func.def.params), {optional: true}); - } - return {}; - } - - function switchToLink(inputElem, paramIndex) { - /*jshint validthis:true */ - var $input = $(inputElem); - - clearTimeout(cancelBlur); - cancelBlur = null; - - var $link = $input.prev(); - var $comma = $link.prev('.comma'); - var newValue = $input.val(); - - // remove optional empty params - if (newValue !== '' || paramDef(paramIndex).optional) { - func.updateParam(newValue, paramIndex); - $link.html(newValue ? templateSrv.highlightVariablesAsHtml(newValue) : ' '); - } - - scheduledRelinkIfNeeded(); - - $scope.$apply(function() { - ctrl.targetChanged(); - }); - - if ($link.hasClass('query-part__last') && newValue === '') { - $comma.addClass('query-part__last'); - } else { - $link.removeClass('query-part__last'); - } - - $input.hide(); - $link.show(); - } - - // this = input element - function inputBlur(paramIndex) { - /*jshint validthis:true */ - var inputElem = this; - // happens long before the click event on the typeahead options - // need to have long delay because the blur - cancelBlur = setTimeout(function() { - switchToLink(inputElem, paramIndex); - }, 200); - } - - function inputKeyPress(paramIndex, e) { - /*jshint validthis:true */ - if(e.which === 13) { - $(this).blur(); - } - } - - function inputKeyDown() { - /*jshint validthis:true */ - this.style.width = (3 + this.value.length) * 8 + 'px'; - } - - function addTypeahead($input, paramIndex) { - $input.attr('data-provide', 'typeahead'); - - var options = paramDef(paramIndex).options; - if (paramDef(paramIndex).type === 'int') { - options = _.map(options, function(val) { return val.toString(); }); - } - - $input.typeahead({ - source: options, - minLength: 0, - items: 20, - updater: function (value) { - $input.val(value); - switchToLink($input[0], paramIndex); - return value; - } - }); - - var typeahead = $input.data('typeahead'); - typeahead.lookup = function () { - this.query = this.$element.val() || ''; - return this.process(this.source); - }; - } - - function toggleFuncControls() { - var targetDiv = elem.closest('.tight-form'); - - if (elem.hasClass('show-function-controls')) { - elem.removeClass('show-function-controls'); - targetDiv.removeClass('has-open-function'); - $funcControls.hide(); - return; - } - - elem.addClass('show-function-controls'); - targetDiv.addClass('has-open-function'); - - $funcControls.show(); - } - - function addElementsAndCompile() { - $funcControls.appendTo(elem); - $funcLink.appendTo(elem); - - var defParams = _.clone(func.def.params); - var lastParam = _.last(func.def.params); - - while (func.params.length >= defParams.length && lastParam && lastParam.multiple) { - defParams.push(_.assign({}, lastParam, {optional: true})); - } - - _.each(defParams, function(param, index) { - if (param.optional && func.params.length < index) { - return false; - } - - var paramValue = templateSrv.highlightVariablesAsHtml(func.params[index]); - - var last = (index >= func.params.length - 1) && param.optional && !paramValue; - if (last && param.multiple) { - paramValue = '+'; - } - - if (index > 0) { - $(', ').appendTo(elem); - } - - var $paramLink = $( - '' - + (paramValue || ' ') + ''); - var $input = $(paramTemplate); - $input.attr('placeholder', param.name); - - paramCountAtLink++; - - $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 (param.options) { - addTypeahead($input, index); - } - }); - - $(')').appendTo(elem); - - $compile(elem.contents())($scope); - } - - function ifJustAddedFocusFirstParam() { - 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('fa-remove')) { - toggleFuncControls(); - $scope.$apply(function() { - ctrl.removeFunction($scope.func); - }); - return; - } - - if ($target.hasClass('fa-arrow-left')) { - $scope.$apply(function() { - _.move(ctrl.queryModel.functions, $scope.$index, $scope.$index - 1); - ctrl.targetChanged(); - }); - return; - } - - if ($target.hasClass('fa-arrow-right')) { - $scope.$apply(function() { - _.move(ctrl.queryModel.functions, $scope.$index, $scope.$index + 1); - ctrl.targetChanged(); - }); - return; - } - - if ($target.hasClass('fa-question-circle')) { - var funcDef = ctrl.datasource.getFuncDef(func.def.name); - if (funcDef && funcDef.description) { - popoverSrv.show({ - element: e.target, - position: 'bottom left', - classNames: 'drop-popover drop-function-def', - template: '
' - + '

' + funcDef.name + '

' + rst2html(funcDef.description) + '
', - openOn: 'click', - }); - } else { - window.open( - "http://graphite.readthedocs.org/en/latest/functions.html#graphite.render.functions." + func.def.name,'_blank'); - } - return; - } - }); - } - - function relink() { - elem.children().remove(); - - addElementsAndCompile(); - ifJustAddedFocusFirstParam(); - registerFuncControlsToggle(); - registerFuncControlsActions(); - } - - relink(); - } - }; - - }); - -}); diff --git a/public/app/plugins/datasource/graphite/func_editor.ts b/public/app/plugins/datasource/graphite/func_editor.ts new file mode 100644 index 00000000000..86135aef343 --- /dev/null +++ b/public/app/plugins/datasource/graphite/func_editor.ts @@ -0,0 +1,317 @@ +import angular from 'angular'; +import _ from 'lodash'; +import $ from 'jquery'; +import rst2html from 'rst2html'; + +export function graphiteFuncEditor($compile, templateSrv, popoverSrv) { + const funcSpanTemplate = '{{func.def.name}}('; + const paramTemplate = + ''; + + const funcControlsTemplate = ` +
+ + + + +
`; + + return { + restrict: 'A', + link: function postLink($scope, elem) { + var $funcLink = $(funcSpanTemplate); + var $funcControls = $(funcControlsTemplate); + var ctrl = $scope.ctrl; + var func = $scope.func; + var scheduledRelink = false; + var paramCountAtLink = 0; + var cancelBlur = null; + + function clickFuncParam(paramIndex) { + /*jshint validthis:true */ + + var $link = $(this); + var $comma = $link.prev('.comma'); + var $input = $link.next(); + + $input.val(func.params[paramIndex]); + + $comma.removeClass('query-part__last'); + $link.hide(); + $input.show(); + $input.focus(); + $input.select(); + + var typeahead = $input.data('typeahead'); + if (typeahead) { + $input.val(''); + typeahead.lookup(); + } + } + + function scheduledRelinkIfNeeded() { + if (paramCountAtLink === func.params.length) { + return; + } + + if (!scheduledRelink) { + scheduledRelink = true; + setTimeout(function() { + relink(); + scheduledRelink = false; + }, 200); + } + } + + function paramDef(index) { + if (index < func.def.params.length) { + return func.def.params[index]; + } + if (_.last(func.def.params).multiple) { + return _.assign({}, _.last(func.def.params), { optional: true }); + } + return {}; + } + + function switchToLink(inputElem, paramIndex) { + /*jshint validthis:true */ + var $input = $(inputElem); + + clearTimeout(cancelBlur); + cancelBlur = null; + + var $link = $input.prev(); + var $comma = $link.prev('.comma'); + var newValue = $input.val(); + + // remove optional empty params + if (newValue !== '' || paramDef(paramIndex).optional) { + func.updateParam(newValue, paramIndex); + $link.html(newValue ? templateSrv.highlightVariablesAsHtml(newValue) : ' '); + } + + scheduledRelinkIfNeeded(); + + $scope.$apply(function() { + ctrl.targetChanged(); + }); + + if ($link.hasClass('query-part__last') && newValue === '') { + $comma.addClass('query-part__last'); + } else { + $link.removeClass('query-part__last'); + } + + $input.hide(); + $link.show(); + } + + // this = input element + function inputBlur(paramIndex) { + /*jshint validthis:true */ + var inputElem = this; + // happens long before the click event on the typeahead options + // need to have long delay because the blur + cancelBlur = setTimeout(function() { + switchToLink(inputElem, paramIndex); + }, 200); + } + + function inputKeyPress(paramIndex, e) { + /*jshint validthis:true */ + if (e.which === 13) { + $(this).blur(); + } + } + + function inputKeyDown() { + /*jshint validthis:true */ + this.style.width = (3 + this.value.length) * 8 + 'px'; + } + + function addTypeahead($input, paramIndex) { + $input.attr('data-provide', 'typeahead'); + + var options = paramDef(paramIndex).options; + if (paramDef(paramIndex).type === 'int') { + options = _.map(options, function(val) { + return val.toString(); + }); + } + + $input.typeahead({ + source: options, + minLength: 0, + items: 20, + updater: function(value) { + $input.val(value); + switchToLink($input[0], paramIndex); + return value; + }, + }); + + var typeahead = $input.data('typeahead'); + typeahead.lookup = function() { + this.query = this.$element.val() || ''; + return this.process(this.source); + }; + } + + function toggleFuncControls() { + var targetDiv = elem.closest('.tight-form'); + + if (elem.hasClass('show-function-controls')) { + elem.removeClass('show-function-controls'); + targetDiv.removeClass('has-open-function'); + $funcControls.hide(); + return; + } + + elem.addClass('show-function-controls'); + targetDiv.addClass('has-open-function'); + + $funcControls.show(); + } + + function addElementsAndCompile() { + $funcControls.appendTo(elem); + $funcLink.appendTo(elem); + + var defParams = _.clone(func.def.params); + var lastParam = _.last(func.def.params); + + while (func.params.length >= defParams.length && lastParam && lastParam.multiple) { + defParams.push(_.assign({}, lastParam, { optional: true })); + } + + _.each(defParams, function(param, index) { + if (param.optional && func.params.length < index) { + return false; + } + + var paramValue = templateSrv.highlightVariablesAsHtml(func.params[index]); + + var last = index >= func.params.length - 1 && param.optional && !paramValue; + if (last && param.multiple) { + paramValue = '+'; + } + + if (index > 0) { + $(', ').appendTo(elem); + } + + var $paramLink = $( + '' + + (paramValue || ' ') + + '' + ); + var $input = $(paramTemplate); + $input.attr('placeholder', param.name); + + paramCountAtLink++; + + $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 (param.options) { + addTypeahead($input, index); + } + + return true; + }); + + $(')').appendTo(elem); + + $compile(elem.contents())($scope); + } + + function ifJustAddedFocusFirstParam() { + 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('fa-remove')) { + toggleFuncControls(); + $scope.$apply(function() { + ctrl.removeFunction($scope.func); + }); + return; + } + + if ($target.hasClass('fa-arrow-left')) { + $scope.$apply(function() { + _.move(ctrl.queryModel.functions, $scope.$index, $scope.$index - 1); + ctrl.targetChanged(); + }); + return; + } + + if ($target.hasClass('fa-arrow-right')) { + $scope.$apply(function() { + _.move(ctrl.queryModel.functions, $scope.$index, $scope.$index + 1); + ctrl.targetChanged(); + }); + return; + } + + if ($target.hasClass('fa-question-circle')) { + var funcDef = ctrl.datasource.getFuncDef(func.def.name); + if (funcDef && funcDef.description) { + popoverSrv.show({ + element: e.target, + position: 'bottom left', + classNames: 'drop-popover drop-function-def', + template: ` +
+

${funcDef.name}

+ ${rst2html(funcDef.description)} +
`, + openOn: 'click', + }); + } else { + window.open( + 'http://graphite.readthedocs.org/en/latest/functions.html#graphite.render.functions.' + func.def.name, + '_blank' + ); + } + return; + } + }); + } + + function relink() { + elem.children().remove(); + + addElementsAndCompile(); + ifJustAddedFocusFirstParam(); + registerFuncControlsToggle(); + registerFuncControlsActions(); + } + + relink(); + }, + }; +} + +angular.module('grafana.directives').directive('graphiteFuncEditor', graphiteFuncEditor);