2021-04-21 02:38:00 -05:00
|
|
|
import { debounce, each, map, partial, escape, unescape } from 'lodash';
|
2017-12-20 05:33:33 -06:00
|
|
|
import $ from 'jquery';
|
|
|
|
import coreModule from 'app/core/core_module';
|
2021-11-08 11:41:04 -06:00
|
|
|
import { promiseToDigest } from '../../core/utils/promiseToDigest';
|
2016-05-11 07:52:44 -05:00
|
|
|
|
2018-08-29 07:26:50 -05:00
|
|
|
const template = `
|
2016-08-15 06:51:55 -05:00
|
|
|
<div class="dropdown cascade-open">
|
|
|
|
<a ng-click="showActionsMenu()" class="query-part-name pointer dropdown-toggle" data-toggle="dropdown">{{part.def.type}}</a>
|
2016-05-11 07:52:44 -05:00
|
|
|
<span>(</span><span class="query-part-parameters"></span><span>)</span>
|
2016-08-15 06:51:55 -05:00
|
|
|
<ul class="dropdown-menu">
|
|
|
|
<li ng-repeat="action in partActions">
|
|
|
|
<a ng-click="triggerPartAction(action)">{{action.text}}</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
2016-05-11 07:52:44 -05:00
|
|
|
`;
|
|
|
|
|
2017-12-19 09:06:54 -06:00
|
|
|
/** @ngInject */
|
2019-05-12 07:15:23 -05:00
|
|
|
export function queryPartEditorDirective(templateSrv: any) {
|
2018-08-29 07:26:50 -05:00
|
|
|
const paramTemplate = '<input type="text" class="hide input-mini tight-form-func-param"></input>';
|
2016-08-15 06:51:55 -05:00
|
|
|
|
2016-05-11 07:52:44 -05:00
|
|
|
return {
|
2017-12-20 05:33:33 -06:00
|
|
|
restrict: 'E',
|
2016-05-11 07:52:44 -05:00
|
|
|
template: template,
|
|
|
|
scope: {
|
2017-12-20 05:33:33 -06:00
|
|
|
part: '=',
|
|
|
|
handleEvent: '&',
|
2018-02-09 09:20:30 -06:00
|
|
|
debounce: '@',
|
2016-05-11 07:52:44 -05:00
|
|
|
},
|
2019-05-12 07:15:23 -05:00
|
|
|
link: function postLink($scope: any, elem: any) {
|
2018-08-29 07:26:50 -05:00
|
|
|
const part = $scope.part;
|
|
|
|
const partDef = part.def;
|
|
|
|
const $paramsContainer = elem.find('.query-part-parameters');
|
|
|
|
const debounceLookup = $scope.debounce;
|
2016-08-15 06:51:55 -05:00
|
|
|
|
|
|
|
$scope.partActions = [];
|
2016-05-11 07:52:44 -05:00
|
|
|
|
2019-05-12 07:15:23 -05:00
|
|
|
function clickFuncParam(this: any, paramIndex: number) {
|
2018-08-29 07:26:50 -05:00
|
|
|
const $link = $(this);
|
|
|
|
const $input = $link.next();
|
2016-05-11 07:52:44 -05:00
|
|
|
|
|
|
|
$input.val(part.params[paramIndex]);
|
Chore: Fix all Typescript strict null errors (#26204)
* Chore: Fix typescript strict null errors
* Added new limit
* Fixed ts issue
* fixed tests
* trying to fix type inference
* Fixing more ts errors
* Revert tsconfig option
* Fix
* Fixed code
* More fixes
* fix tests
* Updated snapshot
* Chore: More ts strict null fixes
* More fixes in some really messed up azure config components
* More fixes, current count: 441
* 419
* More fixes
* Fixed invalid initial state in explore
* Fixing tests
* Fixed tests
* Explore fix
* More fixes
* Progress
* Sub 300
* Now at 218
* Progress
* Update
* Progress
* Updated tests
* at 159
* fixed tests
* Progress
* YAy blow 100! at 94
* 10,9,8,7,6,5,4,3,2,1... lift off
* Fixed tests
* Fixed more type errors
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
2020-07-10 05:46:59 -05:00
|
|
|
$input.css('width', $link.width()! + 16 + 'px');
|
2016-05-11 07:52:44 -05:00
|
|
|
|
|
|
|
$link.hide();
|
|
|
|
$input.show();
|
|
|
|
$input.focus();
|
|
|
|
$input.select();
|
|
|
|
|
2018-08-29 07:26:50 -05:00
|
|
|
const typeahead = $input.data('typeahead');
|
2016-05-11 07:52:44 -05:00
|
|
|
if (typeahead) {
|
2017-12-20 05:33:33 -06:00
|
|
|
$input.val('');
|
2016-05-11 07:52:44 -05:00
|
|
|
typeahead.lookup();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-12 07:15:23 -05:00
|
|
|
function inputBlur(this: any, paramIndex: number) {
|
2018-08-29 07:26:50 -05:00
|
|
|
const $input = $(this);
|
|
|
|
const $link = $input.prev();
|
|
|
|
const newValue = $input.val();
|
2016-05-11 07:52:44 -05:00
|
|
|
|
2017-12-20 05:33:33 -06:00
|
|
|
if (newValue !== '' || part.def.params[paramIndex].optional) {
|
2016-05-11 07:52:44 -05:00
|
|
|
$link.html(templateSrv.highlightVariablesAsHtml(newValue));
|
|
|
|
|
|
|
|
part.updateParam($input.val(), paramIndex);
|
2016-08-15 10:20:45 -05:00
|
|
|
$scope.$apply(() => {
|
2017-12-20 05:33:33 -06:00
|
|
|
$scope.handleEvent({ $event: { name: 'part-param-changed' } });
|
2016-08-15 10:20:45 -05:00
|
|
|
});
|
2016-05-11 07:52:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
$input.hide();
|
|
|
|
$link.show();
|
|
|
|
}
|
|
|
|
|
2019-05-12 07:15:23 -05:00
|
|
|
function inputKeyPress(this: any, paramIndex: number, e: any) {
|
2016-05-11 07:52:44 -05:00
|
|
|
if (e.which === 13) {
|
|
|
|
inputBlur.call(this, paramIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-30 03:49:18 -05:00
|
|
|
function inputKeyDown(this: any) {
|
2017-12-20 05:33:33 -06:00
|
|
|
this.style.width = (3 + this.value.length) * 8 + 'px';
|
2016-05-11 07:52:44 -05:00
|
|
|
}
|
|
|
|
|
2019-05-12 07:15:23 -05:00
|
|
|
function addTypeahead($input: JQuery, param: any, paramIndex: number) {
|
2016-05-11 07:52:44 -05:00
|
|
|
if (!param.options && !param.dynamicLookup) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-12 07:15:23 -05:00
|
|
|
const typeaheadSource = (query: string, callback: any) => {
|
2017-04-11 07:40:08 -05:00
|
|
|
if (param.options) {
|
2018-08-30 01:58:43 -05:00
|
|
|
let options = param.options;
|
2017-12-20 05:33:33 -06:00
|
|
|
if (param.type === 'int') {
|
2021-04-21 02:38:00 -05:00
|
|
|
options = map(options, (val) => {
|
2017-12-19 09:06:54 -06:00
|
|
|
return val.toString();
|
|
|
|
});
|
2017-04-11 07:40:08 -05:00
|
|
|
}
|
|
|
|
return options;
|
|
|
|
}
|
2016-05-11 07:52:44 -05:00
|
|
|
|
2018-09-04 07:27:03 -05:00
|
|
|
$scope.$apply(() => {
|
2019-05-12 07:15:23 -05:00
|
|
|
$scope.handleEvent({ $event: { name: 'get-param-options' } }).then((result: any) => {
|
2021-04-21 02:38:00 -05:00
|
|
|
const dynamicOptions = map(result, (op) => {
|
|
|
|
return escape(op.value);
|
2017-12-19 09:06:54 -06:00
|
|
|
});
|
2017-12-21 01:39:31 -06:00
|
|
|
callback(dynamicOptions);
|
|
|
|
});
|
2016-05-11 07:52:44 -05:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2017-12-20 05:33:33 -06:00
|
|
|
$input.attr('data-provide', 'typeahead');
|
2016-05-11 07:52:44 -05:00
|
|
|
|
|
|
|
$input.typeahead({
|
|
|
|
source: typeaheadSource,
|
|
|
|
minLength: 0,
|
|
|
|
items: 1000,
|
2019-05-12 07:15:23 -05:00
|
|
|
updater: (value: string) => {
|
2021-04-21 02:38:00 -05:00
|
|
|
value = unescape(value);
|
2018-09-04 07:27:03 -05:00
|
|
|
setTimeout(() => {
|
2016-05-11 07:52:44 -05:00
|
|
|
inputBlur.call($input[0], paramIndex);
|
|
|
|
}, 0);
|
|
|
|
return value;
|
2017-12-20 05:33:33 -06:00
|
|
|
},
|
2016-05-11 07:52:44 -05:00
|
|
|
});
|
|
|
|
|
2018-08-29 07:26:50 -05:00
|
|
|
const typeahead = $input.data('typeahead');
|
2021-01-20 00:59:48 -06:00
|
|
|
typeahead.lookup = function () {
|
2017-12-20 05:33:33 -06:00
|
|
|
this.query = this.$element.val() || '';
|
2018-08-29 07:26:50 -05:00
|
|
|
const items = this.source(this.query, $.proxy(this.process, this));
|
2016-05-11 07:52:44 -05:00
|
|
|
return items ? this.process(items) : items;
|
2018-01-29 01:38:23 -06:00
|
|
|
};
|
2018-02-09 09:20:30 -06:00
|
|
|
|
|
|
|
if (debounceLookup) {
|
2021-04-21 02:38:00 -05:00
|
|
|
typeahead.lookup = debounce(typeahead.lookup, 500, { leading: true });
|
2018-02-09 09:20:30 -06:00
|
|
|
}
|
2016-05-11 07:52:44 -05:00
|
|
|
}
|
|
|
|
|
2018-09-04 07:27:03 -05:00
|
|
|
$scope.showActionsMenu = () => {
|
2020-01-30 02:13:22 -06:00
|
|
|
promiseToDigest($scope)(
|
|
|
|
$scope.handleEvent({ $event: { name: 'get-part-actions' } }).then((res: any) => {
|
|
|
|
$scope.partActions = res;
|
|
|
|
})
|
|
|
|
);
|
2016-05-11 07:52:44 -05:00
|
|
|
};
|
|
|
|
|
2019-05-12 07:15:23 -05:00
|
|
|
$scope.triggerPartAction = (action: string) => {
|
2017-12-20 05:33:33 -06:00
|
|
|
$scope.handleEvent({ $event: { name: 'action', action: action } });
|
2016-05-11 07:52:44 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
function addElementsAndCompile() {
|
2021-04-21 02:38:00 -05:00
|
|
|
each(partDef.params, (param: any, index: number) => {
|
2016-05-11 07:52:44 -05:00
|
|
|
if (param.optional && part.params.length <= index) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index > 0) {
|
2017-12-20 05:33:33 -06:00
|
|
|
$('<span>, </span>').appendTo($paramsContainer);
|
2016-05-11 07:52:44 -05:00
|
|
|
}
|
|
|
|
|
2018-08-29 07:26:50 -05:00
|
|
|
const paramValue = templateSrv.highlightVariablesAsHtml(part.params[index]);
|
|
|
|
const $paramLink = $('<a class="graphite-func-param-link pointer">' + paramValue + '</a>');
|
|
|
|
const $input = $(paramTemplate);
|
2016-05-11 07:52:44 -05:00
|
|
|
|
|
|
|
$paramLink.appendTo($paramsContainer);
|
|
|
|
$input.appendTo($paramsContainer);
|
|
|
|
|
2021-04-21 02:38:00 -05:00
|
|
|
$input.blur(partial(inputBlur, index));
|
2016-05-11 07:52:44 -05:00
|
|
|
$input.keyup(inputKeyDown);
|
2021-04-21 02:38:00 -05:00
|
|
|
$input.keypress(partial(inputKeyPress, index));
|
|
|
|
$paramLink.click(partial(clickFuncParam, index));
|
2016-05-11 07:52:44 -05:00
|
|
|
|
|
|
|
addTypeahead($input, param, index);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function relink() {
|
|
|
|
$paramsContainer.empty();
|
|
|
|
addElementsAndCompile();
|
|
|
|
}
|
|
|
|
|
|
|
|
relink();
|
2017-12-20 05:33:33 -06:00
|
|
|
},
|
2016-05-11 07:52:44 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-12-20 05:33:33 -06:00
|
|
|
coreModule.directive('queryPartEditor', queryPartEditorDirective);
|