mirror of
https://github.com/grafana/grafana.git
synced 2024-12-01 21:19:28 -06:00
fix: graphite func editor fixes, this component is messy and ugly as hell
This commit is contained in:
parent
1a6bf692c6
commit
e9d33750cb
@ -1,137 +1,130 @@
|
||||
define([
|
||||
'angular',
|
||||
'lodash',
|
||||
'jquery',
|
||||
'rst2html',
|
||||
'tether-drop',
|
||||
],
|
||||
function (angular, _, $, rst2html, Drop) {
|
||||
define(['angular', 'lodash', 'jquery', 'rst2html', 'tether-drop'], function(angular, _, $, rst2html, Drop) {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('grafana.directives')
|
||||
.directive('graphiteAddFunc', function($compile) {
|
||||
var inputTemplate = '<input type="text"'+
|
||||
' class="gf-form-input"' +
|
||||
' spellcheck="false" style="display:none"></input>';
|
||||
angular.module('grafana.directives').directive('graphiteAddFunc', function($compile) {
|
||||
var inputTemplate =
|
||||
'<input type="text"' + ' class="gf-form-input"' + ' spellcheck="false" style="display:none"></input>';
|
||||
|
||||
var buttonTemplate = '<a class="gf-form-label query-part dropdown-toggle"' +
|
||||
' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' +
|
||||
'<i class="fa fa-plus"></i></a>';
|
||||
var buttonTemplate =
|
||||
'<a class="gf-form-label query-part dropdown-toggle"' +
|
||||
' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' +
|
||||
'<i class="fa fa-plus"></i></a>';
|
||||
|
||||
return {
|
||||
link: function($scope, elem) {
|
||||
var ctrl = $scope.ctrl;
|
||||
return {
|
||||
link: function($scope, elem) {
|
||||
var ctrl = $scope.ctrl;
|
||||
|
||||
var $input = $(inputTemplate);
|
||||
var $button = $(buttonTemplate);
|
||||
var $input = $(inputTemplate);
|
||||
var $button = $(buttonTemplate);
|
||||
|
||||
$input.appendTo(elem);
|
||||
$button.appendTo(elem);
|
||||
$input.appendTo(elem);
|
||||
$button.appendTo(elem);
|
||||
|
||||
ctrl.datasource.getFuncDefs().then(function(funcDefs) {
|
||||
var allFunctions = _.map(funcDefs, 'name').sort();
|
||||
ctrl.datasource.getFuncDefs().then(function(funcDefs) {
|
||||
var allFunctions = _.map(funcDefs, 'name').sort();
|
||||
|
||||
$scope.functionMenu = createFunctionDropDownMenu(funcDefs);
|
||||
$scope.functionMenu = createFunctionDropDownMenu(funcDefs);
|
||||
|
||||
$input.attr('data-provide', 'typeahead');
|
||||
$input.typeahead({
|
||||
source: allFunctions,
|
||||
minLength: 1,
|
||||
items: 10,
|
||||
updater: function (value) {
|
||||
var funcDef = ctrl.datasource.getFuncDef(value);
|
||||
if (!funcDef) {
|
||||
// try find close match
|
||||
value = value.toLowerCase();
|
||||
funcDef = _.find(allFunctions, function(funcName) {
|
||||
return funcName.toLowerCase().indexOf(value) === 0;
|
||||
});
|
||||
|
||||
if (!funcDef) { return; }
|
||||
}
|
||||
|
||||
$scope.$apply(function() {
|
||||
ctrl.addFunction(funcDef);
|
||||
$input.attr('data-provide', 'typeahead');
|
||||
$input.typeahead({
|
||||
source: allFunctions,
|
||||
minLength: 1,
|
||||
items: 10,
|
||||
updater: function(value) {
|
||||
var funcDef = ctrl.datasource.getFuncDef(value);
|
||||
if (!funcDef) {
|
||||
// try find close match
|
||||
value = value.toLowerCase();
|
||||
funcDef = _.find(allFunctions, function(funcName) {
|
||||
return funcName.toLowerCase().indexOf(value) === 0;
|
||||
});
|
||||
|
||||
$input.trigger('blur');
|
||||
return '';
|
||||
if (!funcDef) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$button.click(function() {
|
||||
$button.hide();
|
||||
$input.show();
|
||||
$input.focus();
|
||||
});
|
||||
$scope.$apply(function() {
|
||||
ctrl.addFunction(funcDef);
|
||||
});
|
||||
|
||||
$input.keyup(function() {
|
||||
elem.toggleClass('open', $input.val() === '');
|
||||
});
|
||||
|
||||
$input.blur(function() {
|
||||
// clicking the function dropdown menu wont
|
||||
// work if you remove class at once
|
||||
setTimeout(function() {
|
||||
$input.val('');
|
||||
$input.hide();
|
||||
$button.show();
|
||||
elem.removeClass('open');
|
||||
}, 200);
|
||||
});
|
||||
|
||||
$compile(elem.contents())($scope);
|
||||
$input.trigger('blur');
|
||||
return '';
|
||||
},
|
||||
});
|
||||
|
||||
var drops = [];
|
||||
$button.click(function() {
|
||||
$button.hide();
|
||||
$input.show();
|
||||
$input.focus();
|
||||
});
|
||||
|
||||
$(elem)
|
||||
.on('mouseenter', 'ul.dropdown-menu li', function () {
|
||||
while (drops.length > 0) {
|
||||
drops.pop().remove();
|
||||
$input.keyup(function() {
|
||||
elem.toggleClass('open', $input.val() === '');
|
||||
});
|
||||
|
||||
$input.blur(function() {
|
||||
// clicking the function dropdown menu wont
|
||||
// work if you remove class at once
|
||||
setTimeout(function() {
|
||||
$input.val('');
|
||||
$input.hide();
|
||||
$button.show();
|
||||
elem.removeClass('open');
|
||||
}, 200);
|
||||
});
|
||||
|
||||
$compile(elem.contents())($scope);
|
||||
});
|
||||
|
||||
var drop;
|
||||
var cleanUpDrop = function() {
|
||||
if (drop) {
|
||||
drop.destroy();
|
||||
drop = null;
|
||||
}
|
||||
};
|
||||
|
||||
$(elem)
|
||||
.on('mouseenter', 'ul.dropdown-menu li', function() {
|
||||
cleanUpDrop();
|
||||
|
||||
var funcDef;
|
||||
try {
|
||||
funcDef = ctrl.datasource.getFuncDef($('a', this).text());
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
if (funcDef && funcDef.description) {
|
||||
var shortDesc = funcDef.description;
|
||||
if (shortDesc.length > 500) {
|
||||
shortDesc = shortDesc.substring(0, 497) + '...';
|
||||
}
|
||||
|
||||
var funcDef;
|
||||
try {
|
||||
funcDef = ctrl.datasource.getFuncDef($('a', this).text());
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
var contentElement = document.createElement('div');
|
||||
contentElement.innerHTML = '<h4>' + funcDef.name + '</h4>' + rst2html(shortDesc);
|
||||
|
||||
if (funcDef && funcDef.description) {
|
||||
var shortDesc = funcDef.description;
|
||||
if (shortDesc.length > 500) {
|
||||
shortDesc = shortDesc.substring(0, 497) + '...';
|
||||
}
|
||||
drop = new Drop({
|
||||
target: this,
|
||||
content: contentElement,
|
||||
classes: 'drop-popover',
|
||||
openOn: 'always',
|
||||
tetherOptions: {
|
||||
attachment: 'bottom left',
|
||||
targetAttachment: 'bottom right',
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
.on('mouseout', 'ul.dropdown-menu li', function() {
|
||||
cleanUpDrop();
|
||||
});
|
||||
|
||||
var contentElement = document.createElement('div');
|
||||
contentElement.innerHTML = '<h4>' + funcDef.name + '</h4>' + rst2html(shortDesc);
|
||||
|
||||
var drop = new Drop({
|
||||
target: this,
|
||||
content: contentElement,
|
||||
classes: 'drop-popover',
|
||||
openOn: 'always',
|
||||
tetherOptions: {
|
||||
attachment: 'bottom left',
|
||||
targetAttachment: 'bottom right',
|
||||
},
|
||||
});
|
||||
|
||||
drops.push(drop);
|
||||
|
||||
drop.open();
|
||||
}
|
||||
})
|
||||
.on('mouseout', 'ul.dropdown-menu li', function() {
|
||||
while (drops.length > 0) {
|
||||
drops.pop().remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
$scope.$on('$destroy', cleanUpDrop);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
function createFunctionDropDownMenu(funcDefs) {
|
||||
var categories = {};
|
||||
@ -149,11 +142,14 @@ function (angular, _, $, rst2html, Drop) {
|
||||
});
|
||||
});
|
||||
|
||||
return _.sortBy(_.map(categories, function(submenu, category) {
|
||||
return {
|
||||
text: category,
|
||||
submenu: _.sortBy(submenu, 'text')
|
||||
};
|
||||
}), 'text');
|
||||
return _.sortBy(
|
||||
_.map(categories, function(submenu, category) {
|
||||
return {
|
||||
text: category,
|
||||
submenu: _.sortBy(submenu, 'text'),
|
||||
};
|
||||
}),
|
||||
'text'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -32,6 +32,7 @@ function (angular, _, $, rst2html) {
|
||||
var func = $scope.func;
|
||||
var scheduledRelink = false;
|
||||
var paramCountAtLink = 0;
|
||||
var cancelBlur = null;
|
||||
|
||||
function clickFuncParam(paramIndex) {
|
||||
/*jshint validthis:true */
|
||||
@ -79,41 +80,54 @@ function (angular, _, $, rst2html) {
|
||||
return {};
|
||||
}
|
||||
|
||||
function inputBlur(paramIndex) {
|
||||
function switchToLink(inputElem, paramIndex) {
|
||||
/*jshint validthis:true */
|
||||
var $input = $(this);
|
||||
if ($input.data('typeahead') && $input.data('typeahead').shown) {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
$link.html(templateSrv.highlightVariablesAsHtml(newValue));
|
||||
|
||||
func.updateParam(newValue, paramIndex);
|
||||
scheduledRelinkIfNeeded();
|
||||
|
||||
$scope.$apply(function() {
|
||||
ctrl.targetChanged();
|
||||
});
|
||||
|
||||
if ($link.hasClass('last') && newValue === '') {
|
||||
$comma.addClass('last');
|
||||
} else {
|
||||
$link.removeClass('last');
|
||||
}
|
||||
$input.hide();
|
||||
$link.show();
|
||||
}
|
||||
|
||||
$link.html(templateSrv.highlightVariablesAsHtml(newValue));
|
||||
scheduledRelinkIfNeeded();
|
||||
|
||||
$scope.$apply(function() {
|
||||
ctrl.targetChanged();
|
||||
});
|
||||
|
||||
if ($link.hasClass('last') && newValue === '') {
|
||||
$comma.addClass('last');
|
||||
} else {
|
||||
$link.removeClass('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) {
|
||||
inputBlur.call(this, paramIndex);
|
||||
$(this).blur();
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,9 +149,8 @@ function (angular, _, $, rst2html) {
|
||||
minLength: 0,
|
||||
items: 20,
|
||||
updater: function (value) {
|
||||
setTimeout(function() {
|
||||
inputBlur.call($input[0], paramIndex);
|
||||
}, 0);
|
||||
$input.val(value);
|
||||
switchToLink($input[0], paramIndex);
|
||||
return value;
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user