Skip to content

Commit 0906312

Browse files
committed
Merge branch 'adhoc-filters'
2 parents 159a8bf + 15423e6 commit 0906312

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3310
-1998
lines changed

public/app/core/services/context_srv.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export class User {
99
isGrafanaAdmin: any;
1010
isSignedIn: any;
1111
orgRole: any;
12+
timezone: string;
1213

1314
constructor() {
1415
if (config.bootData.user) {

public/app/core/utils/kbn.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ function($, _, moment) {
99
var kbn = {};
1010
kbn.valueFormats = {};
1111

12+
kbn.regexEscape = function(value) {
13+
return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&');
14+
};
15+
1216
///// HELPER FUNCTIONS /////
1317

1418
kbn.round_interval = function(interval) {

public/app/features/all.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ define([
22
'./panellinks/module',
33
'./dashlinks/module',
44
'./annotations/annotations_srv',
5-
'./templating/templateSrv',
5+
'./templating/all',
66
'./dashboard/all',
77
'./playlist/all',
88
'./snapshot/all',
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
///<reference path="../../headers/common.d.ts" />
2+
3+
import _ from 'lodash';
4+
import angular from 'angular';
5+
import coreModule from 'app/core/core_module';
6+
7+
export class AdHocFiltersCtrl {
8+
segments: any;
9+
variable: any;
10+
removeTagFilterSegment: any;
11+
12+
/** @ngInject */
13+
constructor(private uiSegmentSrv, private datasourceSrv, private $q, private templateSrv, private $rootScope) {
14+
this.removeTagFilterSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove filter --'});
15+
this.buildSegmentModel();
16+
}
17+
18+
buildSegmentModel() {
19+
this.segments = [];
20+
21+
if (this.variable.value && !_.isArray(this.variable.value)) {
22+
}
23+
24+
for (let tag of this.variable.filters) {
25+
if (this.segments.length > 0) {
26+
this.segments.push(this.uiSegmentSrv.newCondition('AND'));
27+
}
28+
29+
if (tag.key !== undefined && tag.value !== undefined) {
30+
this.segments.push(this.uiSegmentSrv.newKey(tag.key));
31+
this.segments.push(this.uiSegmentSrv.newOperator(tag.operator));
32+
this.segments.push(this.uiSegmentSrv.newKeyValue(tag.value));
33+
}
34+
}
35+
36+
this.segments.push(this.uiSegmentSrv.newPlusButton());
37+
}
38+
39+
getOptions(segment, index) {
40+
if (segment.type === 'operator') {
41+
return this.$q.when(this.uiSegmentSrv.newOperators(['=', '!=', '<', '>', '=~', '!~']));
42+
}
43+
44+
if (segment.type === 'condition') {
45+
return this.$q.when([this.uiSegmentSrv.newSegment('AND')]);
46+
}
47+
48+
return this.datasourceSrv.get(this.variable.datasource).then(ds => {
49+
var options: any = {};
50+
var promise = null;
51+
52+
if (segment.type !== 'value') {
53+
promise = ds.getTagKeys();
54+
} else {
55+
options.key = this.segments[index-2].value;
56+
promise = ds.getTagValues(options);
57+
}
58+
59+
return promise.then(results => {
60+
results = _.map(results, segment => {
61+
return this.uiSegmentSrv.newSegment({value: segment.text});
62+
});
63+
64+
// add remove option for keys
65+
if (segment.type === 'key') {
66+
results.splice(0, 0, angular.copy(this.removeTagFilterSegment));
67+
}
68+
return results;
69+
});
70+
});
71+
}
72+
73+
segmentChanged(segment, index) {
74+
this.segments[index] = segment;
75+
76+
// handle remove tag condition
77+
if (segment.value === this.removeTagFilterSegment.value) {
78+
this.segments.splice(index, 3);
79+
if (this.segments.length === 0) {
80+
this.segments.push(this.uiSegmentSrv.newPlusButton());
81+
} else if (this.segments.length > 2) {
82+
this.segments.splice(Math.max(index-1, 0), 1);
83+
if (this.segments[this.segments.length-1].type !== 'plus-button') {
84+
this.segments.push(this.uiSegmentSrv.newPlusButton());
85+
}
86+
}
87+
} else {
88+
if (segment.type === 'plus-button') {
89+
if (index > 2) {
90+
this.segments.splice(index, 0, this.uiSegmentSrv.newCondition('AND'));
91+
}
92+
this.segments.push(this.uiSegmentSrv.newOperator('='));
93+
this.segments.push(this.uiSegmentSrv.newFake('select tag value', 'value', 'query-segment-value'));
94+
segment.type = 'key';
95+
segment.cssClass = 'query-segment-key';
96+
}
97+
98+
if ((index+1) === this.segments.length) {
99+
this.segments.push(this.uiSegmentSrv.newPlusButton());
100+
}
101+
}
102+
103+
this.updateVariableModel();
104+
}
105+
106+
updateVariableModel() {
107+
var filters = [];
108+
var filterIndex = -1;
109+
var operator = "";
110+
var hasFakes = false;
111+
112+
this.segments.forEach(segment => {
113+
if (segment.type === 'value' && segment.fake) {
114+
hasFakes = true;
115+
return;
116+
}
117+
118+
switch (segment.type) {
119+
case 'key': {
120+
filters.push({key: segment.value});
121+
filterIndex += 1;
122+
break;
123+
}
124+
case 'value': {
125+
filters[filterIndex].value = segment.value;
126+
break;
127+
}
128+
case 'operator': {
129+
filters[filterIndex].operator = segment.value;
130+
break;
131+
}
132+
case 'condition': {
133+
filters[filterIndex].condition = segment.value;
134+
break;
135+
}
136+
}
137+
});
138+
139+
if (hasFakes) {
140+
return;
141+
}
142+
143+
this.variable.setFilters(filters);
144+
this.$rootScope.$emit('template-variable-value-updated');
145+
this.$rootScope.$broadcast('refresh');
146+
}
147+
}
148+
149+
var template = `
150+
<div class="gf-form-inline">
151+
<div class="gf-form" ng-repeat="segment in ctrl.segments">
152+
<metric-segment segment="segment" get-options="ctrl.getOptions(segment, $index)"
153+
on-change="ctrl.segmentChanged(segment, $index)"></metric-segment>
154+
</div>
155+
</div>
156+
`;
157+
158+
export function adHocFiltersComponent() {
159+
return {
160+
restrict: 'E',
161+
template: template,
162+
controller: AdHocFiltersCtrl,
163+
bindToController: true,
164+
controllerAs: 'ctrl',
165+
scope: {
166+
variable: "="
167+
}
168+
};
169+
}
170+
171+
coreModule.directive('adHocFilters', adHocFiltersComponent);

public/app/features/dashboard/all.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ define([
77
'./rowCtrl',
88
'./shareModalCtrl',
99
'./shareSnapshotCtrl',
10-
'./dashboardSrv',
10+
'./dashboard_srv',
1111
'./keybindings',
1212
'./viewStateSrv',
1313
'./timeSrv',
@@ -20,4 +20,5 @@ define([
2020
'./import/dash_import',
2121
'./export/export_modal',
2222
'./dash_list_ctrl',
23+
'./ad_hoc_filters',
2324
], function () {});

0 commit comments

Comments
 (0)