Skip to content

Commit b170b6e

Browse files
committed
feat(query part): moved query part editor from influxdb to core
1 parent cca37ca commit b170b6e

File tree

9 files changed

+277
-225
lines changed

9 files changed

+277
-225
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
///<reference path="../../../headers/common.d.ts" />
2+
3+
import _ from 'lodash';
4+
import $ from 'jquery';
5+
import coreModule from 'app/core/core_module';
6+
7+
var template = `
8+
<div class="tight-form-func-controls">
9+
<span class="pointer fa fa-remove" ng-click="removeActionInternal()"></span>
10+
</div>
11+
12+
<a ng-click="toggleControls()" class="query-part-name">{{part.def.type}}</a>
13+
<span>(</span><span class="query-part-parameters"></span><span>)</span>
14+
`;
15+
16+
/** @ngInject */
17+
export function queryPartEditorDirective($compile, templateSrv) {
18+
19+
var paramTemplate = '<input type="text" style="display:none"' +
20+
' class="input-mini tight-form-func-param"></input>';
21+
return {
22+
restrict: 'E',
23+
template: template,
24+
scope: {
25+
part: "=",
26+
removeAction: "&",
27+
partUpdated: "&",
28+
getOptions: "&",
29+
},
30+
link: function postLink($scope, elem) {
31+
var part = $scope.part;
32+
var partDef = part.def;
33+
var $paramsContainer = elem.find('.query-part-parameters');
34+
var $controlsContainer = elem.find('.tight-form-func-controls');
35+
36+
function clickFuncParam(paramIndex) {
37+
/*jshint validthis:true */
38+
var $link = $(this);
39+
var $input = $link.next();
40+
41+
$input.val(part.params[paramIndex]);
42+
$input.css('width', ($link.width() + 16) + 'px');
43+
44+
$link.hide();
45+
$input.show();
46+
$input.focus();
47+
$input.select();
48+
49+
var typeahead = $input.data('typeahead');
50+
if (typeahead) {
51+
$input.val('');
52+
typeahead.lookup();
53+
}
54+
}
55+
56+
function inputBlur(paramIndex) {
57+
/*jshint validthis:true */
58+
var $input = $(this);
59+
var $link = $input.prev();
60+
var newValue = $input.val();
61+
62+
if (newValue !== '' || part.def.params[paramIndex].optional) {
63+
$link.html(templateSrv.highlightVariablesAsHtml(newValue));
64+
65+
part.updateParam($input.val(), paramIndex);
66+
$scope.$apply($scope.partUpdated);
67+
}
68+
69+
$input.hide();
70+
$link.show();
71+
}
72+
73+
function inputKeyPress(paramIndex, e) {
74+
/*jshint validthis:true */
75+
if (e.which === 13) {
76+
inputBlur.call(this, paramIndex);
77+
}
78+
}
79+
80+
function inputKeyDown() {
81+
/*jshint validthis:true */
82+
this.style.width = (3 + this.value.length) * 8 + 'px';
83+
}
84+
85+
function addTypeahead($input, param, paramIndex) {
86+
if (!param.options && !param.dynamicLookup) {
87+
return;
88+
}
89+
90+
var typeaheadSource = function (query, callback) {
91+
if (param.options) { return param.options; }
92+
93+
$scope.$apply(function() {
94+
$scope.getOptions().then(function(result) {
95+
var dynamicOptions = _.map(result, function(op) { return op.value; });
96+
callback(dynamicOptions);
97+
});
98+
});
99+
};
100+
101+
$input.attr('data-provide', 'typeahead');
102+
var options = param.options;
103+
if (param.type === 'int') {
104+
options = _.map(options, function(val) { return val.toString(); });
105+
}
106+
107+
$input.typeahead({
108+
source: typeaheadSource,
109+
minLength: 0,
110+
items: 1000,
111+
updater: function (value) {
112+
setTimeout(function() {
113+
inputBlur.call($input[0], paramIndex);
114+
}, 0);
115+
return value;
116+
}
117+
});
118+
119+
var typeahead = $input.data('typeahead');
120+
typeahead.lookup = function () {
121+
this.query = this.$element.val() || '';
122+
var items = this.source(this.query, $.proxy(this.process, this));
123+
return items ? this.process(items) : items;
124+
};
125+
}
126+
127+
$scope.toggleControls = function() {
128+
var targetDiv = elem.closest('.tight-form');
129+
130+
if (elem.hasClass('show-function-controls')) {
131+
elem.removeClass('show-function-controls');
132+
targetDiv.removeClass('has-open-function');
133+
$controlsContainer.hide();
134+
return;
135+
}
136+
137+
elem.addClass('show-function-controls');
138+
targetDiv.addClass('has-open-function');
139+
$controlsContainer.show();
140+
};
141+
142+
$scope.removeActionInternal = function() {
143+
$scope.toggleControls();
144+
$scope.removeAction();
145+
};
146+
147+
function addElementsAndCompile() {
148+
_.each(partDef.params, function(param, index) {
149+
if (param.optional && part.params.length <= index) {
150+
return;
151+
}
152+
153+
if (index > 0) {
154+
$('<span>, </span>').appendTo($paramsContainer);
155+
}
156+
157+
var paramValue = templateSrv.highlightVariablesAsHtml(part.params[index]);
158+
var $paramLink = $('<a class="graphite-func-param-link pointer">' + paramValue + '</a>');
159+
var $input = $(paramTemplate);
160+
161+
$paramLink.appendTo($paramsContainer);
162+
$input.appendTo($paramsContainer);
163+
164+
$input.blur(_.partial(inputBlur, index));
165+
$input.keyup(inputKeyDown);
166+
$input.keypress(_.partial(inputKeyPress, index));
167+
$paramLink.click(_.partial(clickFuncParam, index));
168+
169+
addTypeahead($input, param, index);
170+
});
171+
}
172+
173+
function relink() {
174+
$paramsContainer.empty();
175+
addElementsAndCompile();
176+
}
177+
178+
relink();
179+
}
180+
};
181+
}
182+
183+
coreModule.directive('queryPartEditor', queryPartEditorDirective);

public/app/core/core.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {Emitter} from './utils/emitter';
3333
import {layoutSelector} from './components/layout_selector/layout_selector';
3434
import {switchDirective} from './components/switch';
3535
import {dashboardSelector} from './components/dashboard_selector';
36+
import {queryPartEditorDirective} from './components/query_part/query_part_editor';
3637
import 'app/core/controllers/all';
3738
import 'app/core/services/all';
3839
import 'app/core/routes/routes';
@@ -56,4 +57,5 @@ export {
5657
Emitter,
5758
appEvents,
5859
dashboardSelector,
60+
queryPartEditorDirective,
5961
};

public/app/plugins/datasource/influxdb/partials/query.editor.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@
3535
</div>
3636

3737
<div class="gf-form" ng-repeat="part in selectParts">
38-
<influx-query-part-editor
38+
<query-part-editor
3939
class="gf-form-label query-part"
4040
part="part"
4141
remove-action="ctrl.removeSelectPart(selectParts, part)"
4242
part-updated="ctrl.selectPartUpdated(selectParts, part)"
4343
get-options="ctrl.getPartOptions(part)">
44-
</influx-query-part-editor>
44+
</query-part-editor>
4545
</div>
4646

4747
<div class="gf-form">
@@ -62,12 +62,12 @@
6262
<span>GROUP BY</span>
6363
</label>
6464

65-
<influx-query-part-editor
65+
<query-part-editor
6666
ng-repeat="part in ctrl.queryModel.groupByParts"
6767
part="part"
6868
class="gf-form-label query-part"
6969
remove-action="ctrl.removeGroupByPart(part, $index)" part-updated="ctrl.refresh();" get-options="ctrl.getPartOptions(part)">
70-
</influx-query-part-editor>
70+
</query-part-editor>
7171
</div>
7272

7373
<div class="gf-form">

public/app/plugins/datasource/influxdb/partials/query_part.html

Lines changed: 0 additions & 5 deletions
This file was deleted.

public/app/plugins/datasource/influxdb/query_ctrl.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
///<reference path="../../../headers/common.d.ts" />
22

3-
import './query_part_editor';
4-
import './query_part_editor';
5-
63
import angular from 'angular';
74
import _ from 'lodash';
85
import InfluxQueryBuilder from './query_builder';

0 commit comments

Comments
 (0)