Added initial metric functions directives based on graphite query
editor.
This commit is contained in:
107
plugins/datasource-zabbix/addMetricFunction.js
Normal file
107
plugins/datasource-zabbix/addMetricFunction.js
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
define([
|
||||||
|
'angular',
|
||||||
|
'lodash',
|
||||||
|
'jquery',
|
||||||
|
'./metricFunctions'
|
||||||
|
],
|
||||||
|
function (angular, _, $, metricFunctions) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('grafana.directives')
|
||||||
|
.directive('addMetricFunction', function($compile) {
|
||||||
|
var inputTemplate = '<input type="text"'+
|
||||||
|
' class="tight-form-input input-medium tight-form-input"' +
|
||||||
|
' spellcheck="false" style="display:none"></input>';
|
||||||
|
|
||||||
|
var buttonTemplate = '<a class="tight-form-item tight-form-func dropdown-toggle"' +
|
||||||
|
' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' +
|
||||||
|
'<i class="fa fa-plus"></i></a>';
|
||||||
|
|
||||||
|
return {
|
||||||
|
link: function($scope, elem) {
|
||||||
|
var categories = metricFunctions.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 = metricFunctions.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() {
|
||||||
|
$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() {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
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 + "')",
|
||||||
|
};
|
||||||
|
})
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -9,7 +9,9 @@ define([
|
|||||||
'./helperFunctions',
|
'./helperFunctions',
|
||||||
'./dataProcessingService',
|
'./dataProcessingService',
|
||||||
'./zabbixCache',
|
'./zabbixCache',
|
||||||
'./queryCtrl'
|
'./queryCtrl',
|
||||||
|
'./addMetricFunction',
|
||||||
|
'./metricFunctionEditor'
|
||||||
],
|
],
|
||||||
function (angular, _, dateMath, utils) {
|
function (angular, _, dateMath, utils) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|||||||
244
plugins/datasource-zabbix/metricFunctionEditor.js
Normal file
244
plugins/datasource-zabbix/metricFunctionEditor.js
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
define([
|
||||||
|
'angular',
|
||||||
|
'lodash',
|
||||||
|
'jquery',
|
||||||
|
],
|
||||||
|
function (angular, _, $) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('grafana.directives')
|
||||||
|
.directive('metricFunctionEditor', function($compile, templateSrv) {
|
||||||
|
|
||||||
|
var funcSpanTemplate = '<a ng-click="">{{func.def.name}}</a><span>(</span>';
|
||||||
|
var paramTemplate = '<input type="text" style="display:none"' +
|
||||||
|
' class="input-mini tight-form-func-param"></input>';
|
||||||
|
|
||||||
|
var funcControlsTemplate =
|
||||||
|
'<div class="tight-form-func-controls">' +
|
||||||
|
'<span class="pointer fa fa-arrow-left"></span>' +
|
||||||
|
'<span class="pointer fa fa-question-circle"></span>' +
|
||||||
|
'<span class="pointer fa fa-remove" ></span>' +
|
||||||
|
'<span class="pointer fa fa-arrow-right"></span>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: function postLink($scope, elem) {
|
||||||
|
var $funcLink = $(funcSpanTemplate);
|
||||||
|
var $funcControls = $(funcControlsTemplate);
|
||||||
|
var func = $scope.func;
|
||||||
|
var funcDef = func.def;
|
||||||
|
var scheduledRelink = false;
|
||||||
|
var paramCountAtLink = 0;
|
||||||
|
|
||||||
|
function clickFuncParam(paramIndex) {
|
||||||
|
/*jshint validthis:true */
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduledRelinkIfNeeded() {
|
||||||
|
if (paramCountAtLink === func.params.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scheduledRelink) {
|
||||||
|
scheduledRelink = true;
|
||||||
|
setTimeout(function() {
|
||||||
|
relink();
|
||||||
|
scheduledRelink = false;
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inputBlur(paramIndex) {
|
||||||
|
/*jshint validthis:true */
|
||||||
|
var $input = $(this);
|
||||||
|
var $link = $input.prev();
|
||||||
|
var newValue = $input.val();
|
||||||
|
|
||||||
|
if (newValue !== '' || func.def.params[paramIndex].optional) {
|
||||||
|
$link.html(templateSrv.highlightVariablesAsHtml(newValue));
|
||||||
|
|
||||||
|
func.updateParam($input.val(), paramIndex);
|
||||||
|
scheduledRelinkIfNeeded();
|
||||||
|
|
||||||
|
$scope.$apply($scope.targetChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
$input.hide();
|
||||||
|
$link.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function inputKeyPress(paramIndex, e) {
|
||||||
|
/*jshint validthis:true */
|
||||||
|
if(e.which === 13) {
|
||||||
|
inputBlur.call(this, paramIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = funcDef.params[paramIndex].options;
|
||||||
|
if (funcDef.params[paramIndex].type === 'int') {
|
||||||
|
options = _.map(options, function(val) { return val.toString(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
$input.typeahead({
|
||||||
|
source: options,
|
||||||
|
minLength: 0,
|
||||||
|
items: 20,
|
||||||
|
updater: function (value) {
|
||||||
|
setTimeout(function() {
|
||||||
|
inputBlur.call($input[0], paramIndex);
|
||||||
|
}, 0);
|
||||||
|
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);
|
||||||
|
|
||||||
|
_.each(funcDef.params, function(param, index) {
|
||||||
|
if (param.optional && func.params.length <= index) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index > 0) {
|
||||||
|
$('<span>, </span>').appendTo(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
var paramValue = templateSrv.highlightVariablesAsHtml(func.params[index]);
|
||||||
|
var $paramLink = $('<a ng-click="" class="graphite-func-param-link">' + paramValue + '</a>');
|
||||||
|
var $input = $(paramTemplate);
|
||||||
|
|
||||||
|
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 (funcDef.params[index].options) {
|
||||||
|
addTypeahead($input, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$('<span>)</span>').appendTo(elem);
|
||||||
|
|
||||||
|
$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('fa-remove')) {
|
||||||
|
toggleFuncControls();
|
||||||
|
$scope.$apply(function() {
|
||||||
|
$scope.removeFunction($scope.func);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($target.hasClass('fa-arrow-left')) {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
_.move($scope.target.functions, $scope.$index, $scope.$index - 1);
|
||||||
|
$scope.targetChanged();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($target.hasClass('fa-arrow-right')) {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
_.move($scope.target.functions, $scope.$index, $scope.$index + 1);
|
||||||
|
$scope.targetChanged();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($target.hasClass('fa-question-circle')) {
|
||||||
|
window.open("http://graphite.readthedocs.org/en/latest/functions.html#graphite.render.functions." + funcDef.name,'_blank');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function relink() {
|
||||||
|
elem.children().remove();
|
||||||
|
|
||||||
|
addElementsAndCompile();
|
||||||
|
ifJustAddedFocusFistParam();
|
||||||
|
registerFuncControlsToggle();
|
||||||
|
registerFuncControlsActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
relink();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
189
plugins/datasource-zabbix/metricFunctions.js
Normal file
189
plugins/datasource-zabbix/metricFunctions.js
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
define([
|
||||||
|
'lodash',
|
||||||
|
'jquery'
|
||||||
|
],
|
||||||
|
function (_, $) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var index = [];
|
||||||
|
var categories = {
|
||||||
|
Transform: [],
|
||||||
|
Aggregate: [],
|
||||||
|
Alias: []
|
||||||
|
};
|
||||||
|
|
||||||
|
function addFuncDef(funcDef) {
|
||||||
|
funcDef.params = funcDef.params || [];
|
||||||
|
funcDef.defaultParams = funcDef.defaultParams || [];
|
||||||
|
|
||||||
|
if (funcDef.category) {
|
||||||
|
funcDef.category.push(funcDef);
|
||||||
|
}
|
||||||
|
index[funcDef.name] = funcDef;
|
||||||
|
index[funcDef.shortName || funcDef.name] = funcDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
var optionalSeriesRefArgs = [
|
||||||
|
{ name: 'other', type: 'value_or_series', optional: true },
|
||||||
|
{ name: 'other', type: 'value_or_series', optional: true },
|
||||||
|
{ name: 'other', type: 'value_or_series', optional: true },
|
||||||
|
{ name: 'other', type: 'value_or_series', optional: true },
|
||||||
|
{ name: 'other', type: 'value_or_series', optional: true }
|
||||||
|
];
|
||||||
|
|
||||||
|
addFuncDef({
|
||||||
|
name: 'scaleToSeconds',
|
||||||
|
category: categories.Transform,
|
||||||
|
params: [{ name: 'seconds', type: 'int' }],
|
||||||
|
defaultParams: [1],
|
||||||
|
});
|
||||||
|
|
||||||
|
addFuncDef({
|
||||||
|
name: 'groupBy',
|
||||||
|
category: categories.Transform,
|
||||||
|
params: [
|
||||||
|
{ name: 'interval', type: 'string'},
|
||||||
|
{ name: 'function', type: 'string', options: ['avg', 'min', 'max'] }
|
||||||
|
],
|
||||||
|
defaultParams: ['1m', 'avg'],
|
||||||
|
});
|
||||||
|
|
||||||
|
addFuncDef({
|
||||||
|
name: 'perSecond',
|
||||||
|
category: categories.Transform,
|
||||||
|
params: [{ name: "max value", type: "int", optional: true }],
|
||||||
|
defaultParams: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
addFuncDef({
|
||||||
|
name: 'aggregate',
|
||||||
|
category: categories.Aggregate,
|
||||||
|
params: [
|
||||||
|
{ name: 'function', type: 'string', options: ['sum', 'avg', 'min', 'max'] }
|
||||||
|
],
|
||||||
|
defaultParams: ['sum'],
|
||||||
|
});
|
||||||
|
|
||||||
|
addFuncDef({
|
||||||
|
name: "holtWintersConfidenceBands",
|
||||||
|
category: categories.Aggregate,
|
||||||
|
params: [{ name: "delta", type: 'int' }],
|
||||||
|
defaultParams: [3]
|
||||||
|
});
|
||||||
|
|
||||||
|
addFuncDef({
|
||||||
|
name: 'alias',
|
||||||
|
category: categories.Alias,
|
||||||
|
params: [
|
||||||
|
{ name: 'alias', type: 'string'}
|
||||||
|
],
|
||||||
|
defaultParams: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
addFuncDef({
|
||||||
|
name: 'averageSeries',
|
||||||
|
shortName: 'avg',
|
||||||
|
category: categories.Alias,
|
||||||
|
params: optionalSeriesRefArgs,
|
||||||
|
defaultParams: [''],
|
||||||
|
});
|
||||||
|
|
||||||
|
_.each(categories, function(funcList, catName) {
|
||||||
|
categories[catName] = _.sortBy(funcList, 'name');
|
||||||
|
});
|
||||||
|
|
||||||
|
function FuncInstance(funcDef, options) {
|
||||||
|
this.def = funcDef;
|
||||||
|
this.params = [];
|
||||||
|
|
||||||
|
if (options && options.withDefaultParams) {
|
||||||
|
this.params = funcDef.defaultParams.slice(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateText();
|
||||||
|
}
|
||||||
|
|
||||||
|
FuncInstance.prototype.render = function(metricExp) {
|
||||||
|
var str = this.def.name + '(';
|
||||||
|
var parameters = _.map(this.params, function(value, index) {
|
||||||
|
|
||||||
|
var paramType = this.def.params[index].type;
|
||||||
|
if (paramType === 'int' || paramType === 'value_or_series' || paramType === 'boolean') {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
else if (paramType === 'int_or_interval' && $.isNumeric(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "'" + value + "'";
|
||||||
|
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
if (metricExp) {
|
||||||
|
parameters.unshift(metricExp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str + parameters.join(', ') + ')';
|
||||||
|
};
|
||||||
|
|
||||||
|
FuncInstance.prototype._hasMultipleParamsInString = function(strValue, index) {
|
||||||
|
if (strValue.indexOf(',') === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.def.params[index + 1] && this.def.params[index + 1].optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
FuncInstance.prototype.updateParam = function(strValue, index) {
|
||||||
|
// handle optional parameters
|
||||||
|
// if string contains ',' and next param is optional, split and update both
|
||||||
|
if (this._hasMultipleParamsInString(strValue, index)) {
|
||||||
|
_.each(strValue.split(','), function(partVal, idx) {
|
||||||
|
this.updateParam(partVal.trim(), idx);
|
||||||
|
}, this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strValue === '' && this.def.params[index].optional) {
|
||||||
|
this.params.splice(index, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.params[index] = strValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateText();
|
||||||
|
};
|
||||||
|
|
||||||
|
FuncInstance.prototype.updateText = function () {
|
||||||
|
if (this.params.length === 0) {
|
||||||
|
this.text = this.def.name + '()';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var text = this.def.name + '(';
|
||||||
|
text += this.params.join(', ');
|
||||||
|
text += ')';
|
||||||
|
this.text = text;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
createFuncInstance: function(funcDef, options) {
|
||||||
|
if (_.isString(funcDef)) {
|
||||||
|
if (!index[funcDef]) {
|
||||||
|
throw { message: 'Method not found ' + name };
|
||||||
|
}
|
||||||
|
funcDef = index[funcDef];
|
||||||
|
}
|
||||||
|
return new FuncInstance(funcDef, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
getFuncDef: function(name) {
|
||||||
|
return index[name];
|
||||||
|
},
|
||||||
|
|
||||||
|
getCategories: function() {
|
||||||
|
return categories;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
@@ -174,7 +174,11 @@
|
|||||||
ng-style="target.item.style">
|
ng-style="target.item.style">
|
||||||
</li>
|
</li>
|
||||||
<li class="tight-form-item query-keyword">Options</li>
|
<li class="tight-form-item query-keyword">Options</li>
|
||||||
<li class="dropdown" dropdown-typeahead="optionsMenu" dropdown-typeahead-on-select="addSelectPart(selectParts, $item, $subItem)">
|
<li ng-repeat="func in target.functions">
|
||||||
|
<span metric-function-editor class="tight-form-item tight-form-func">
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="dropdown" add-metric-function>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- Scale -->
|
<!-- Scale -->
|
||||||
@@ -195,6 +199,16 @@
|
|||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tight-form" ng-hide="target.mode == 1" ng-if="target.options">
|
||||||
|
<ul class="tight-form-list" role="menu">
|
||||||
|
<li class="tight-form-item" style="width: 44px"> </li>
|
||||||
|
|
||||||
|
<!-- Select Application -->
|
||||||
|
<li class="tight-form-item query-keyword" style="width: 5em">Options</li>
|
||||||
|
</ul>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="tight-form" ng-show="target.mode == 2">
|
<div class="tight-form" ng-show="target.mode == 2">
|
||||||
<ul class="tight-form-list" role="menu">
|
<ul class="tight-form-list" role="menu">
|
||||||
<li class="tight-form-item" style="width: 44px"> </li>
|
<li class="tight-form-item" style="width: 44px"> </li>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
define([
|
define([
|
||||||
'angular',
|
'angular',
|
||||||
'lodash',
|
'lodash',
|
||||||
|
'./metricFunctions',
|
||||||
'./utils'
|
'./utils'
|
||||||
],
|
],
|
||||||
function (angular, _, Utils) {
|
function (angular, _, metricFunctions, Utils) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var module = angular.module('grafana.controllers');
|
var module = angular.module('grafana.controllers');
|
||||||
@@ -16,22 +17,7 @@ define([
|
|||||||
$scope.init = function () {
|
$scope.init = function () {
|
||||||
$scope.targetLetters = targetLetters;
|
$scope.targetLetters = targetLetters;
|
||||||
$scope.metric = {};
|
$scope.metric = {};
|
||||||
|
$scope.target.functions = [];
|
||||||
$scope.optionsMenu = [
|
|
||||||
{text: "Transformations", submenu: [
|
|
||||||
{text: "groupBy", value: null},
|
|
||||||
{text: "scale", value: null}
|
|
||||||
]},
|
|
||||||
{text: "Aggregations", submenu: [
|
|
||||||
{text: "sum", value: null},
|
|
||||||
{text: "average", value: null},
|
|
||||||
{text: "min", value: null},
|
|
||||||
{text: "max", value: null}
|
|
||||||
]},
|
|
||||||
{text: "Alias", submenu: [
|
|
||||||
{text: "set alias", value: null},
|
|
||||||
]},
|
|
||||||
];
|
|
||||||
|
|
||||||
// Load default values
|
// Load default values
|
||||||
var targetDefaults = {
|
var targetDefaults = {
|
||||||
@@ -274,9 +260,45 @@ define([
|
|||||||
// Parse target
|
// Parse target
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.targetChanged = function() {
|
||||||
|
console.log($scope.target.functions);
|
||||||
|
};
|
||||||
|
|
||||||
// Validate target and set validation info
|
// Validate target and set validation info
|
||||||
$scope.validateTarget = function () {};
|
$scope.validateTarget = function () {};
|
||||||
|
|
||||||
|
$scope.addFunction = function(funcDef) {
|
||||||
|
var newFunc = metricFunctions.createFuncInstance(funcDef, { withDefaultParams: true });
|
||||||
|
newFunc.added = true;
|
||||||
|
$scope.target.functions.push(newFunc);
|
||||||
|
|
||||||
|
$scope.moveAliasFuncLast();
|
||||||
|
|
||||||
|
if (!newFunc.params.length && newFunc.added) {
|
||||||
|
$scope.targetChanged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.removeFunction = function(func) {
|
||||||
|
$scope.target.functions = _.without($scope.target.functions, func);
|
||||||
|
$scope.targetChanged();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.moveAliasFuncLast = function() {
|
||||||
|
var aliasFunc = _.find($scope.target.functions, function(func) {
|
||||||
|
return func.def.name === 'alias' ||
|
||||||
|
func.def.name === 'aliasByNode' ||
|
||||||
|
func.def.name === 'aliasByMetric';
|
||||||
|
});
|
||||||
|
|
||||||
|
if (aliasFunc) {
|
||||||
|
$scope.target.functions = _.without($scope.target.functions, aliasFunc);
|
||||||
|
$scope.target.functions.push(aliasFunc);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.functionChanged = function() {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch query editor to specified mode.
|
* Switch query editor to specified mode.
|
||||||
* Modes:
|
* Modes:
|
||||||
|
|||||||
Reference in New Issue
Block a user