Skip to content

Commit 5ce3e40

Browse files
committed
feat(templating): more work on new variable handling code, grafana#6048
1 parent 4188c46 commit 5ce3e40

File tree

8 files changed

+176
-50
lines changed

8 files changed

+176
-50
lines changed

public/app/core/utils/kbn.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function($, _, moment) {
1010
kbn.valueFormats = {};
1111

1212
kbn.regexEscape = function(value) {
13-
return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&')
13+
return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&');
1414
};
1515

1616
///// HELPER FUNCTIONS /////

public/app/features/templating/all.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import {IntervalVariable} from './interval_variable';
77
import {QueryVariable} from './query_variable';
88
import {DatasourceVariable} from './datasource_variable';
99
import {CustomVariable} from './custom_variable';
10+
import {ConstantVariable} from './constant_variable';
1011

1112
export {
1213
VariableSrv,
1314
IntervalVariable,
1415
QueryVariable,
1516
DatasourceVariable,
1617
CustomVariable,
18+
ConstantVariable,
1719
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
///<reference path="../../headers/common.d.ts" />
2+
3+
import _ from 'lodash';
4+
import {Variable} from './variable';
5+
import {VariableSrv, variableConstructorMap} from './variable_srv';
6+
7+
export class ConstantVariable implements Variable {
8+
query: string;
9+
options: any[];
10+
11+
/** @ngInject */
12+
constructor(private model, private variableSrv) {
13+
_.extend(this, model);
14+
}
15+
16+
setValue(option) {
17+
this.variableSrv.setOptionAsCurrent(this, option);
18+
}
19+
20+
updateOptions() {
21+
this.options = [{text: this.query.trim(), value: this.query.trim()}];
22+
this.setValue(this.options[0]);
23+
}
24+
25+
dependsOn(variable) {
26+
return false;
27+
}
28+
29+
setValueFromUrl(urlValue) {
30+
return this.variableSrv.setOptionFromUrl(this, urlValue);
31+
}
32+
}
33+
34+
variableConstructorMap['constant'] = ConstantVariable;
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
2+
3+
import moment from 'moment';
4+
import helpers from 'test/specs/helpers';
5+
import '../all';
6+
7+
describe('VariableSrv Init', function() {
8+
var ctx = new helpers.ControllerTestContext();
9+
10+
beforeEach(angularMocks.module('grafana.core'));
11+
beforeEach(angularMocks.module('grafana.controllers'));
12+
beforeEach(angularMocks.module('grafana.services'));
13+
14+
beforeEach(ctx.providePhase(['datasourceSrv', 'timeSrv', 'templateSrv', '$location']));
15+
beforeEach(angularMocks.inject(($rootScope, $q, $location, $injector) => {
16+
ctx.$q = $q;
17+
ctx.$rootScope = $rootScope;
18+
ctx.$location = $location;
19+
ctx.variableSrv = $injector.get('variableSrv');
20+
ctx.variableSrv.init({templating: {list: []}});
21+
ctx.$rootScope.$digest();
22+
}));
23+
24+
function describeInitSceneario(desc, fn) {
25+
describe(desc, function() {
26+
var scenario: any = {
27+
urlParams: {},
28+
setup: setupFn => {
29+
scenario.setupFn = setupFn;
30+
}
31+
};
32+
33+
beforeEach(function() {
34+
scenario.setupFn();
35+
var ds: any = {};
36+
ds.metricFindQuery = sinon.stub().returns(ctx.$q.when(scenario.queryResult));
37+
ctx.datasourceSrv.get = sinon.stub().returns(ctx.$q.when(ds));
38+
ctx.datasourceSrv.getMetricSources = sinon.stub().returns(scenario.metricSources);
39+
40+
ctx.$location.search = sinon.stub().returns(scenario.urlParams);
41+
42+
ctx.dashboard = {templating: {list: scenario.variables}};
43+
ctx.variableSrv.init(ctx.dashboard);
44+
ctx.$rootScope.$digest();
45+
46+
scenario.variables = ctx.variableSrv.variables;
47+
});
48+
49+
fn(scenario);
50+
});
51+
}
52+
53+
describeInitSceneario('when setting query variable via url', scenario => {
54+
scenario.setup(() => {
55+
scenario.variables = [{
56+
name: 'apps',
57+
type: 'query',
58+
current: {text: "test", value: "test"},
59+
options: [{text: "test", value: "test"}]
60+
}];
61+
scenario.urlParams["var-apps"] = "new";
62+
});
63+
64+
it('should update current value', () => {
65+
expect(scenario.variables[0].current.value).to.be("new");
66+
expect(scenario.variables[0].current.text).to.be("new");
67+
});
68+
});
69+
70+
describeInitSceneario('when setting custom variable via url', scenario => {
71+
scenario.setup(() => {
72+
scenario.variables = [{
73+
name: 'apps',
74+
type: 'custom',
75+
current: {text: "test", value: "test"},
76+
options: [{text: "test", value: "test"}]
77+
}];
78+
scenario.urlParams["var-apps"] = "new";
79+
});
80+
81+
it('should update current value', () => {
82+
expect(scenario.variables[0].current.value).to.be("new");
83+
expect(scenario.variables[0].current.text).to.be("new");
84+
});
85+
});
86+
87+
});
88+

public/app/features/templating/specs/variable_srv_init_specs.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,5 +109,34 @@ describe('VariableSrv init', function() {
109109
});
110110
});
111111

112+
describeInitScenario('when template variable is present in url multiple times', scenario => {
113+
scenario.setup(() => {
114+
scenario.variables = [{
115+
name: 'apps',
116+
type: 'query',
117+
multi: true,
118+
current: {text: "val1", value: "val1"},
119+
options: [{text: "val1", value: "val1"}, {text: 'val2', value: 'val2'}, {text: 'val3', value: 'val3', selected: true}]
120+
}];
121+
scenario.urlParams["var-apps"] = ["val2", "val1"];
122+
});
123+
124+
it('should update current value', function() {
125+
var variable = ctx.variableSrv.variables[0];
126+
expect(variable.current.value.length).to.be(2);
127+
expect(variable.current.value[0]).to.be("val2");
128+
expect(variable.current.value[1]).to.be("val1");
129+
expect(variable.current.text).to.be("val2 + val1");
130+
expect(variable.options[0].selected).to.be(true);
131+
expect(variable.options[1].selected).to.be(true);
132+
});
133+
134+
it('should set options that are not in value to selected false', function() {
135+
var variable = ctx.variableSrv.variables[0];
136+
expect(variable.options[2].selected).to.be(false);
137+
});
138+
});
139+
140+
112141
});
113142

public/app/features/templating/variable.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
import _ from 'lodash';
44
import kbn from 'app/core/utils/kbn';
55

6+
export interface Variable {
7+
setValue(option);
8+
updateOptions();
9+
dependsOn(variable);
10+
setValueFromUrl(urlValue);
11+
}
12+
613
export function containsVariable(...args: any[]) {
714
var variableName = args[args.length-1];
815
var str = args[0] || '';
@@ -17,12 +24,6 @@ export function containsVariable(...args: any[]) {
1724
return match !== null;
1825
}
1926

20-
export interface Variable {
21-
setValue(option);
22-
updateOptions();
23-
dependsOn(variable);
24-
setValueFromUrl(urlValue);
25-
}
2627

2728

2829

public/app/features/templating/variable_srv.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ export class VariableSrv {
2929
init(dashboard) {
3030
this.variableLock = {};
3131
this.dashboard = dashboard;
32-
this.variables = [];
33-
34-
dashboard.templating.list.map(this.addVariable.bind(this));
32+
this.variables = dashboard.templating.list.map(this.createVariableFromModel.bind(this));
3533
this.templateSrv.init(this.variables);
3634

3735
var queryParams = this.$location.search();
@@ -60,13 +58,9 @@ export class VariableSrv {
6058
if (urlValue !== void 0) {
6159
return variable.setValueFromUrl(urlValue).then(lock.resolve);
6260
}
61+
6362
if (variable.refresh === 1 || variable.refresh === 2) {
64-
return variable.updateOptions().then(() => {
65-
// if (_.isEmpty(variable.current) && variable.options.length) {
66-
// self.setVariableValue(variable, variable.options[0]);
67-
// }
68-
lock.resolve();
69-
});
63+
return variable.updateOptions().then(lock.resolve);
7064
}
7165

7266
lock.resolve();
@@ -75,19 +69,28 @@ export class VariableSrv {
7569
});
7670
}
7771

78-
addVariable(model) {
72+
createVariableFromModel(model) {
7973
var ctor = variableConstructorMap[model.type];
8074
if (!ctor) {
8175
throw "Unable to find variable constructor for " + model.type;
8276
}
8377

8478
var variable = this.$injector.instantiate(ctor, {model: model});
85-
this.variables.push(variable);
86-
this.dashboard.templating.list.push(model);
79+
return variable;
80+
}
8781

82+
addVariable(model) {
83+
var variable = this.createVariableFromModel(model);
84+
this.variables.push(this.createVariableFromModel(variable));
8885
return variable;
8986
}
9087

88+
syncToDashboardModel() {
89+
this.dashboard.templating.list = this.variables.map(variable => {
90+
return variable.model;
91+
});
92+
}
93+
9194
updateOptions(variable) {
9295
return variable.updateOptions();
9396
}

public/test/specs/templateValuesSrv-specs.js

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -53,37 +53,6 @@ define([
5353
// });
5454
});
5555

56-
describe('when template variable is present in url multiple times', function() {
57-
var variable = {
58-
name: 'apps',
59-
multi: true,
60-
current: {text: "val1", value: "val1"},
61-
options: [{text: "val1", value: "val1"}, {text: 'val2', value: 'val2'}, {text: 'val3', value: 'val3', selected: true}]
62-
};
63-
64-
beforeEach(function(done) {
65-
var dashboard = { templating: { list: [variable] } };
66-
var urlParams = {};
67-
urlParams["var-apps"] = ["val2", "val1"];
68-
ctx.$location.search = sinon.stub().returns(urlParams);
69-
ctx.service.init(dashboard).then(function() { done(); });
70-
ctx.$rootScope.$digest();
71-
});
72-
73-
it('should update current value', function() {
74-
expect(variable.current.value.length).to.be(2);
75-
expect(variable.current.value[0]).to.be("val2");
76-
expect(variable.current.value[1]).to.be("val1");
77-
expect(variable.current.text).to.be("val2 + val1");
78-
expect(variable.options[0].selected).to.be(true);
79-
expect(variable.options[1].selected).to.be(true);
80-
});
81-
82-
it('should set options that are not in value to selected false', function() {
83-
expect(variable.options[2].selected).to.be(false);
84-
});
85-
});
86-
8756

8857
});
8958
});

0 commit comments

Comments
 (0)