Commit 4188c46f by Torkel Ödegaard

feat(templating): more work on new variable handling code, #6048

parent 46ebae73
......@@ -11,11 +11,12 @@ export class CustomVariable implements Variable {
includeAll: boolean;
/** @ngInject */
constructor(private model, private timeSrv, private templateSrv) {
constructor(private model, private timeSrv, private templateSrv, private variableSrv) {
_.extend(this, model);
}
setValue(option) {
this.variableSrv.setOptionAsCurrent(this, option);
}
updateOptions() {
......@@ -33,9 +34,13 @@ export class CustomVariable implements Variable {
this.options.unshift({text: 'All', value: "$__all"});
}
dependsOn(variableName) {
dependsOn(variable) {
return false;
}
setValueFromUrl(urlValue) {
return this.variableSrv.setOptionFromUrl(this, urlValue);
}
}
variableConstructorMap['custom'] = CustomVariable;
......@@ -11,11 +11,12 @@ export class DatasourceVariable implements Variable {
options: any;
/** @ngInject */
constructor(private model, private datasourceSrv) {
constructor(private model, private datasourceSrv, private variableSrv) {
_.extend(this, model);
}
setValue(option) {
this.variableSrv.setOptionAsCurrent(this, option);
}
updateOptions() {
......@@ -48,9 +49,13 @@ export class DatasourceVariable implements Variable {
this.options = options;
}
dependsOn(variableName) {
dependsOn(variable) {
return false;
}
setValueFromUrl(urlValue) {
return this.variableSrv.setOptionFromUrl(this, urlValue);
}
}
variableConstructorMap['datasource'] = DatasourceVariable;
......@@ -13,17 +13,20 @@ export class IntervalVariable implements Variable {
query: string;
/** @ngInject */
constructor(private model, private timeSrv, private templateSrv) {
constructor(private model, private timeSrv, private templateSrv, private variableSrv) {
_.extend(this, model);
}
setValue(option) {
if (this.auto) {
this.updateAutoValue();
}
this.updateAutoValue();
this.variableSrv.setOptionAsCurrent(this, option);
}
updateAutoValue() {
if (!this.auto) {
return;
}
// add auto option if missing
if (this.options.length && this.options[0].text !== 'auto') {
this.options.unshift({ text: 'auto', value: '$__auto_interval' });
......@@ -44,9 +47,14 @@ export class IntervalVariable implements Variable {
}
}
dependsOn(variableName) {
dependsOn(variable) {
return false;
}
setValueFromUrl(urlValue) {
this.updateAutoValue();
return this.variableSrv.setOptionFromUrl(this, urlValue);
}
}
variableConstructorMap['interval'] = IntervalVariable;
......@@ -24,31 +24,11 @@ export class QueryVariable implements Variable {
}
setValue(option){
this.current = _.cloneDeep(option);
if (_.isArray(this.current.text)) {
this.current.text = this.current.text.join(' + ');
}
this.variableSrv.selectOptionsForCurrentValue(this);
return this.variableSrv.variableUpdated(this);
this.variableSrv.setOptionAsCurrent(this, option);
}
setValueFromUrl(urlValue) {
var promise = this.$q.when();
if (this.refresh) {
promise = this.updateOptions();
}
return promise.then(() => {
var option = _.find(this.options, op => {
return op.text === urlValue || op.value === urlValue;
});
option = option || { text: urlValue, value: urlValue };
return this.setValue(option);
});
return this.variableSrv.setOptionFromUrl(this, urlValue);
}
updateOptions() {
......@@ -126,11 +106,11 @@ export class QueryVariable implements Variable {
} else if (sortType === 2) {
options = _.sortBy(options, function(opt) {
var matches = opt.text.match(/.*?(\d+).*/);
if (!matches) {
return 0;
} else {
return parseInt(matches[1], 10);
}
if (!matches) {
return 0;
} else {
return parseInt(matches[1], 10);
}
});
}
......@@ -141,8 +121,8 @@ if (!matches) {
return options;
}
dependsOn(variableName) {
return containsVariable(this.query, variableName) || containsVariable(this.datasource, variableName);
dependsOn(variable) {
return containsVariable(this.query, this.datasource, variable.name);
}
}
......
......@@ -30,6 +30,12 @@ describe('containsVariable', function() {
var contains = containsVariable('$env', 'env');
expect(contains).to.be(true);
});
it('should be able to pass in multiple test strings', function() {
var contains = containsVariable('asd','asd2.$env', 'env');
expect(contains).to.be(true);
});
});
});
......
import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
import _ from 'lodash';
import helpers from 'test/specs/helpers';
import '../all';
describe('VariableSrv init', function() {
var ctx = new helpers.ControllerTestContext();
beforeEach(angularMocks.module('grafana.core'));
beforeEach(angularMocks.module('grafana.controllers'));
beforeEach(angularMocks.module('grafana.services'));
beforeEach(ctx.providePhase(['datasourceSrv', 'timeSrv', 'templateSrv', '$location']));
beforeEach(angularMocks.inject(($rootScope, $q, $location, $injector) => {
ctx.$q = $q;
ctx.$rootScope = $rootScope;
ctx.$location = $location;
ctx.variableSrv = $injector.get('variableSrv');
ctx.variableSrv.init({templating: {list: []}});
ctx.$rootScope.$digest();
}));
function describeInitScenario(desc, fn) {
describe(desc, function() {
var scenario: any = {
urlParams: {},
setup: setupFn => {
scenario.setupFn = setupFn;
}
};
beforeEach(function() {
scenario.setupFn();
ctx.datasource = {};
ctx.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when(scenario.queryResult));
ctx.datasourceSrv.get = sinon.stub().returns(ctx.$q.when(ctx.datasource));
ctx.datasourceSrv.getMetricSources = sinon.stub().returns(scenario.metricSources);
ctx.$location.search = sinon.stub().returns(scenario.urlParams);
ctx.dashboard = {templating: {list: scenario.variables}};
ctx.variableSrv.init(ctx.dashboard);
ctx.$rootScope.$digest();
scenario.variables = ctx.variableSrv.variables;
});
fn(scenario);
});
}
['query', 'interval', 'custom', 'datasource'].forEach(type => {
describeInitScenario('when setting ' + type + ' variable via url', scenario => {
scenario.setup(() => {
scenario.variables = [{
name: 'apps',
type: type,
current: {text: "test", value: "test"},
options: [{text: "test", value: "test"}]
}];
scenario.urlParams["var-apps"] = "new";
});
it('should update current value', () => {
expect(scenario.variables[0].current.value).to.be("new");
expect(scenario.variables[0].current.text).to.be("new");
});
});
});
describe('given dependent variables', () => {
var variableList = [
{
name: 'app',
type: 'query',
query: '',
current: {text: "app1", value: "app1"},
options: [{text: "app1", value: "app1"}]
},
{
name: 'server',
type: 'query',
refresh: 1,
query: '$app.*',
current: {text: "server1", value: "server1"},
options: [{text: "server1", value: "server1"}]
},
];
describeInitScenario('when setting parent var from url', scenario => {
scenario.setup(() => {
scenario.variables = _.cloneDeep(variableList);
scenario.urlParams["var-app"] = "google";
scenario.queryResult = [{text: 'google-server1'}, {text: 'google-server2'}];
});
it('should update child variable', () => {
expect(scenario.variables[1].options.length).to.be(2);
expect(scenario.variables[1].current.text).to.be("google-server1");
});
it('should only update it once', () => {
expect(ctx.datasource.metricFindQuery.callCount).to.be(1);
});
});
});
});
......@@ -21,52 +21,6 @@ describe('VariableSrv', function() {
ctx.$rootScope.$digest();
}));
function describeInitSceneario(desc, fn) {
describe(desc, function() {
var scenario: any = {
urlParams: {},
setup: setupFn => {
scenario.setupFn = setupFn;
}
};
beforeEach(function() {
scenario.setupFn();
var ds: any = {};
ds.metricFindQuery = sinon.stub().returns(ctx.$q.when(scenario.queryResult));
ctx.datasourceSrv.get = sinon.stub().returns(ctx.$q.when(ds));
ctx.datasourceSrv.getMetricSources = sinon.stub().returns(scenario.metricSources);
ctx.$location.search = sinon.stub().returns(scenario.urlParams);
ctx.dashboard = {templating: {list: scenario.variables}};
ctx.variableSrv.init(ctx.dashboard);
ctx.$rootScope.$digest();
scenario.variables = ctx.variableSrv.variables;
});
fn(scenario);
});
}
describeInitSceneario('when setting simple variable via url', scenario => {
scenario.setup(() => {
scenario.variables = [{
name: 'apps',
type: 'query',
current: {text: "test", value: "test"},
options: [{text: "test", value: "test"}]
}];
scenario.urlParams["var-apps"] = "new";
});
it('should update current value', () => {
expect(scenario.variables[0].current.value).to.be("new");
expect(scenario.variables[0].current.text).to.be("new");
});
});
function describeUpdateVariable(desc, fn) {
describe(desc, function() {
var scenario: any = {};
......
///<reference path="../../headers/common.d.ts" />
import _ from 'lodash';
import kbn from 'app/core/utils/kbn';
export function containsVariable(str, variableName) {
if (!str) {
return false;
export function containsVariable(...args: any[]) {
var variableName = args[args.length-1];
var str = args[0] || '';
for (var i = 1; i < args.length-1; i++) {
str += args[i] || '';
}
variableName = kbn.regexEscape(variableName);
......@@ -15,7 +20,8 @@ export function containsVariable(str, variableName) {
export interface Variable {
setValue(option);
updateOptions();
dependsOn(variableName);
dependsOn(variable);
setValueFromUrl(urlValue);
}
......
......@@ -40,12 +40,6 @@ export class VariableSrv {
this.variableLock[variable.name] = this.$q.defer();
}
var promises = [];
for (let variable of this.variables) {
promises.push(this.processVariable(variable, queryParams));
}
return this.$q.all(this.variables.map(variable => {
return this.processVariable(variable, queryParams);
}));
......@@ -66,7 +60,6 @@ export class VariableSrv {
if (urlValue !== void 0) {
return variable.setValueFromUrl(urlValue).then(lock.resolve);
}
if (variable.refresh === 1 || variable.refresh === 2) {
return variable.updateOptions().then(() => {
// if (_.isEmpty(variable.current) && variable.options.length) {
......@@ -174,6 +167,33 @@ export class VariableSrv {
}
}
setOptionFromUrl(variable, urlValue) {
var promise = this.$q.when();
if (variable.refresh) {
promise = variable.updateOptions();
}
return promise.then(() => {
var option = _.find(variable.options, op => {
return op.text === urlValue || op.value === urlValue;
});
option = option || {text: urlValue, value: urlValue};
return variable.setValue(option);
});
}
setOptionAsCurrent(variable, option) {
variable.current = _.cloneDeep(option);
if (_.isArray(variable.current.text)) {
variable.current.text = variable.current.text.join(' + ');
}
this.selectOptionsForCurrentValue(variable);
return this.variableUpdated(variable);
}
}
coreModule.service('variableSrv', VariableSrv);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment