feat(templating): good progress on new variable update code, #6048
This commit is contained in:
@@ -2,7 +2,7 @@ define([
|
||||
'./panellinks/module',
|
||||
'./dashlinks/module',
|
||||
'./annotations/annotations_srv',
|
||||
'./templating/templateSrv',
|
||||
'./templating/all',
|
||||
'./dashboard/all',
|
||||
'./playlist/all',
|
||||
'./snapshot/all',
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import './templateSrv';
|
||||
import './templateValuesSrv';
|
||||
import './editorCtrl';
|
||||
|
||||
import {VariableSrv} from './variable_srv';
|
||||
import {IntervalVariable} from './interval_variable';
|
||||
import {QueryVariable} from './query_variable';
|
||||
|
||||
export {
|
||||
VariableSrv,
|
||||
IntervalVariable,
|
||||
QueryVariable,
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import {Variable} from './variable';
|
||||
import {VariableSrv, variableConstructorMap} from './variable_srv';
|
||||
|
||||
export class IntervalVariable implements Variable {
|
||||
auto_count: number;
|
||||
auto_min: number;
|
||||
options: any;
|
||||
auto: boolean;
|
||||
query: string;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private model, private timeSrv, private templateSrv) {
|
||||
_.extend(this, model);
|
||||
}
|
||||
|
||||
setValue(option) {
|
||||
if (this.auto) {
|
||||
this.updateAutoValue();
|
||||
}
|
||||
}
|
||||
|
||||
updateAutoValue() {
|
||||
// add auto option if missing
|
||||
if (this.options.length && this.options[0].text !== 'auto') {
|
||||
this.options.unshift({ text: 'auto', value: '$__auto_interval' });
|
||||
}
|
||||
|
||||
var interval = kbn.calculateInterval(this.timeSrv.timeRange(), this.auto_count, (this.auto_min ? ">"+this.auto_min : null));
|
||||
this.templateSrv.setGrafanaVariable('$__auto_interval', interval);
|
||||
}
|
||||
|
||||
updateOptions() {
|
||||
// extract options in comma separated string
|
||||
this.options = _.map(this.query.split(/[,]+/), function(text) {
|
||||
return {text: text.trim(), value: text.trim()};
|
||||
});
|
||||
|
||||
if (this.auto) {
|
||||
this.updateAutoValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variableConstructorMap['interval'] = IntervalVariable;
|
||||
@@ -0,0 +1,125 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import _ from 'lodash';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import {Variable} from './variable';
|
||||
import {VariableSrv, variableConstructorMap} from './variable_srv';
|
||||
|
||||
function getNoneOption() {
|
||||
return { text: 'None', value: '', isNone: true };
|
||||
}
|
||||
|
||||
export class QueryVariable implements Variable {
|
||||
datasource: any;
|
||||
query: any;
|
||||
regex: any;
|
||||
sort: any;
|
||||
options: any;
|
||||
current: any;
|
||||
includeAll: boolean;
|
||||
|
||||
constructor(private model, private datasourceSrv, private templateSrv, private variableSrv) {
|
||||
_.extend(this, model);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
updateOptions() {
|
||||
return this.datasourceSrv.get(this.datasource)
|
||||
.then(this.updateOptionsFromMetricFindQuery.bind(this))
|
||||
.then(() => {
|
||||
this.variableSrv.validateVariableSelectionState(this);
|
||||
});
|
||||
}
|
||||
|
||||
updateOptionsFromMetricFindQuery(datasource) {
|
||||
return datasource.metricFindQuery(this.query).then(results => {
|
||||
this.options = this.metricNamesToVariableValues(results);
|
||||
if (this.includeAll) {
|
||||
this.addAllOption();
|
||||
}
|
||||
if (!this.options.length) {
|
||||
this.options.push(getNoneOption());
|
||||
}
|
||||
return datasource;
|
||||
});
|
||||
}
|
||||
|
||||
addAllOption() {
|
||||
this.options.unshift({text: 'All', value: "$__all"});
|
||||
}
|
||||
|
||||
metricNamesToVariableValues(metricNames) {
|
||||
var regex, options, i, matches;
|
||||
options = [];
|
||||
|
||||
if (this.model.regex) {
|
||||
regex = kbn.stringToJsRegex(this.templateSrv.replace(this.regex));
|
||||
}
|
||||
|
||||
for (i = 0; i < metricNames.length; i++) {
|
||||
var item = metricNames[i];
|
||||
var value = item.value || item.text;
|
||||
var text = item.text || item.value;
|
||||
|
||||
if (_.isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (_.isNumber(text)) {
|
||||
text = text.toString();
|
||||
}
|
||||
|
||||
if (regex) {
|
||||
matches = regex.exec(value);
|
||||
if (!matches) { continue; }
|
||||
if (matches.length > 1) {
|
||||
value = matches[1];
|
||||
text = value;
|
||||
}
|
||||
}
|
||||
|
||||
options.push({text: text, value: value});
|
||||
}
|
||||
|
||||
options = _.uniq(options, 'value');
|
||||
return this.sortVariableValues(options, this.sort);
|
||||
}
|
||||
|
||||
sortVariableValues(options, sortOrder) {
|
||||
if (sortOrder === 0) {
|
||||
return options;
|
||||
}
|
||||
|
||||
var sortType = Math.ceil(sortOrder / 2);
|
||||
var reverseSort = (sortOrder % 2 === 0);
|
||||
if (sortType === 1) {
|
||||
options = _.sortBy(options, 'text');
|
||||
} else if (sortType === 2) {
|
||||
options = _.sortBy(options, function(opt) {
|
||||
var matches = opt.text.match(new RegExp(".*?(\d+).*"));
|
||||
if (!matches) {
|
||||
return 0;
|
||||
} else {
|
||||
return parseInt(matches[1], 10);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (reverseSort) {
|
||||
options = options.reverse();
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
variableConstructorMap['query'] = QueryVariable;
|
||||
@@ -1,4 +1,279 @@
|
||||
import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
|
||||
|
||||
describe('VariableSrv', function() {
|
||||
import moment from 'moment';
|
||||
import helpers from 'test/specs/helpers';
|
||||
import '../all';
|
||||
|
||||
describe.only('VariableSrv', 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.variableSrv = $injector.get('variableSrv');
|
||||
ctx.variableSrv.init({templating: {list: []}});
|
||||
ctx.$rootScope.$digest();
|
||||
}));
|
||||
|
||||
function describeUpdateVariable(desc, fn) {
|
||||
describe(desc, function() {
|
||||
var scenario: any = {};
|
||||
scenario.setup = function(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));
|
||||
|
||||
scenario.variable = ctx.variableSrv.addVariable(scenario.variableModel);
|
||||
ctx.variableSrv.updateOptions(scenario.variable);
|
||||
ctx.$rootScope.$digest();
|
||||
});
|
||||
|
||||
fn(scenario);
|
||||
});
|
||||
}
|
||||
|
||||
describeUpdateVariable('interval variable without auto', scenario => {
|
||||
scenario.setup(() => {
|
||||
scenario.variableModel = {type: 'interval', query: '1s,2h,5h,1d', name: 'test'};
|
||||
});
|
||||
|
||||
it('should update options array', () => {
|
||||
expect(scenario.variable.options.length).to.be(4);
|
||||
expect(scenario.variable.options[0].text).to.be('1s');
|
||||
expect(scenario.variable.options[0].value).to.be('1s');
|
||||
});
|
||||
});
|
||||
|
||||
//
|
||||
// Interval variable update
|
||||
//
|
||||
describeUpdateVariable('interval variable with auto', scenario => {
|
||||
scenario.setup(() => {
|
||||
scenario.variableModel = {type: 'interval', query: '1s,2h,5h,1d', name: 'test', auto: true, auto_count: 10 };
|
||||
|
||||
var range = {
|
||||
from: moment(new Date()).subtract(7, 'days').toDate(),
|
||||
to: new Date()
|
||||
};
|
||||
|
||||
ctx.timeSrv.timeRange = sinon.stub().returns(range);
|
||||
ctx.templateSrv.setGrafanaVariable = sinon.spy();
|
||||
});
|
||||
|
||||
it('should update options array', function() {
|
||||
expect(scenario.variable.options.length).to.be(5);
|
||||
expect(scenario.variable.options[0].text).to.be('auto');
|
||||
expect(scenario.variable.options[0].value).to.be('$__auto_interval');
|
||||
});
|
||||
|
||||
it('should set $__auto_interval', function() {
|
||||
var call = ctx.templateSrv.setGrafanaVariable.getCall(0);
|
||||
expect(call.args[0]).to.be('$__auto_interval');
|
||||
expect(call.args[1]).to.be('12h');
|
||||
});
|
||||
});
|
||||
|
||||
//
|
||||
// Query variable update
|
||||
//
|
||||
describeUpdateVariable('query variable with empty current object and refresh', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {type: 'query', query: '', name: 'test', current: {}};
|
||||
scenario.queryResult = [{text: 'backend1'}, {text: 'backend2'}];
|
||||
});
|
||||
|
||||
it('should set current value to first option', function() {
|
||||
expect(scenario.variable.options.length).to.be(2);
|
||||
expect(scenario.variable.current.value).to.be('backend1');
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('query variable with multi select and new options does not contain some selected values', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {
|
||||
type: 'query',
|
||||
query: '',
|
||||
name: 'test',
|
||||
current: {
|
||||
value: ['val1', 'val2', 'val3'],
|
||||
text: 'val1 + val2 + val3'
|
||||
}
|
||||
};
|
||||
scenario.queryResult = [{text: 'val2'}, {text: 'val3'}];
|
||||
});
|
||||
|
||||
it('should update current value', function() {
|
||||
expect(scenario.variable.current.value).to.eql(['val2', 'val3']);
|
||||
expect(scenario.variable.current.text).to.eql('val2 + val3');
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('query variable with multi select and new options does not contain any selected values', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {
|
||||
type: 'query',
|
||||
query: '',
|
||||
name: 'test',
|
||||
current: {
|
||||
value: ['val1', 'val2', 'val3'],
|
||||
text: 'val1 + val2 + val3'
|
||||
}
|
||||
};
|
||||
scenario.queryResult = [{text: 'val5'}, {text: 'val6'}];
|
||||
});
|
||||
|
||||
it('should update current value with first one', function() {
|
||||
expect(scenario.variable.current.value).to.eql('val5');
|
||||
expect(scenario.variable.current.text).to.eql('val5');
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('query variable with multi select and $__all selected', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {
|
||||
type: 'query',
|
||||
query: '',
|
||||
name: 'test',
|
||||
includeAll: true,
|
||||
current: {
|
||||
value: ['$__all'],
|
||||
text: 'All'
|
||||
}
|
||||
};
|
||||
scenario.queryResult = [{text: 'val5'}, {text: 'val6'}];
|
||||
});
|
||||
|
||||
it('should keep current All value', function() {
|
||||
expect(scenario.variable.current.value).to.eql(['$__all']);
|
||||
expect(scenario.variable.current.text).to.eql('All');
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('query variable with numeric results', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = { type: 'query', query: '', name: 'test', current: {} };
|
||||
scenario.queryResult = [{text: 12, value: 12}];
|
||||
});
|
||||
|
||||
it('should set current value to first option', function() {
|
||||
expect(scenario.variable.current.value).to.be('12');
|
||||
expect(scenario.variable.options[0].value).to.be('12');
|
||||
expect(scenario.variable.options[0].text).to.be('12');
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('basic query variable', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = { type: 'query', query: 'apps.*', name: 'test' };
|
||||
scenario.queryResult = [{text: 'backend1'}, {text: 'backend2'}];
|
||||
});
|
||||
|
||||
it('should update options array', function() {
|
||||
expect(scenario.variable.options.length).to.be(2);
|
||||
expect(scenario.variable.options[0].text).to.be('backend1');
|
||||
expect(scenario.variable.options[0].value).to.be('backend1');
|
||||
expect(scenario.variable.options[1].value).to.be('backend2');
|
||||
});
|
||||
|
||||
it('should select first option as value', function() {
|
||||
expect(scenario.variable.current.value).to.be('backend1');
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('and existing value still exists in options', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {type: 'query', query: 'apps.*', name: 'test'};
|
||||
scenario.variableModel.current = { value: 'backend2', text: 'backend2'};
|
||||
scenario.queryResult = [{text: 'backend1'}, {text: 'backend2'}];
|
||||
});
|
||||
|
||||
it('should keep variable value', function() {
|
||||
expect(scenario.variable.current.text).to.be('backend2');
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('and regex pattern exists', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {type: 'query', query: 'apps.*', name: 'test'};
|
||||
scenario.variableModel.regex = '/apps.*(backend_[0-9]+)/';
|
||||
scenario.queryResult = [{text: 'apps.backend.backend_01.counters.req'}, {text: 'apps.backend.backend_02.counters.req'}];
|
||||
});
|
||||
|
||||
it('should extract and use match group', function() {
|
||||
expect(scenario.variable.options[0].value).to.be('backend_01');
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('and regex pattern exists and no match', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {type: 'query', query: 'apps.*', name: 'test'};
|
||||
scenario.variableModel.regex = '/apps.*(backendasd[0-9]+)/';
|
||||
scenario.queryResult = [{text: 'apps.backend.backend_01.counters.req'}, {text: 'apps.backend.backend_02.counters.req'}];
|
||||
});
|
||||
|
||||
it('should not add non matching items, None option should be added instead', function() {
|
||||
expect(scenario.variable.options.length).to.be(1);
|
||||
expect(scenario.variable.options[0].isNone).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('regex pattern without slashes', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {type: 'query', query: 'apps.*', name: 'test'};
|
||||
scenario.variableModel.regex = 'backend_01';
|
||||
scenario.queryResult = [{text: 'apps.backend.backend_01.counters.req'}, {text: 'apps.backend.backend_02.counters.req'}];
|
||||
});
|
||||
|
||||
it('should return matches options', function() {
|
||||
expect(scenario.variable.options.length).to.be(1);
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('regex pattern remove duplicates', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {type: 'query', query: 'apps.*', name: 'test'};
|
||||
scenario.variableModel.regex = 'backend_01';
|
||||
scenario.queryResult = [{text: 'apps.backend.backend_01.counters.req'}, {text: 'apps.backend.backend_01.counters.req'}];
|
||||
});
|
||||
|
||||
it('should return matches options', function() {
|
||||
expect(scenario.variable.options.length).to.be(1);
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('with include All', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {type: 'query', query: 'apps.*', name: 'test', includeAll: true};
|
||||
scenario.queryResult = [{text: 'backend1'}, {text: 'backend2'}, { text: 'backend3'}];
|
||||
});
|
||||
|
||||
it('should add All option', function() {
|
||||
expect(scenario.variable.options[0].text).to.be('All');
|
||||
expect(scenario.variable.options[0].value).to.be('$__all');
|
||||
});
|
||||
});
|
||||
|
||||
describeUpdateVariable('with include all and custom value', function(scenario) {
|
||||
scenario.setup(function() {
|
||||
scenario.variableModel = {type: 'query', query: 'apps.*', name: 'test', includeAll: true, allValue: '*'};
|
||||
scenario.queryResult = [{text: 'backend1'}, {text: 'backend2'}, { text: 'backend3'}];
|
||||
});
|
||||
|
||||
it('should add All option with custom value', function() {
|
||||
expect(scenario.variable.options[0].value).to.be('$__all');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
define([
|
||||
'angular',
|
||||
'lodash',
|
||||
'./editorCtrl',
|
||||
'./variable_srv',
|
||||
'./templateValuesSrv',
|
||||
],
|
||||
function (angular, _) {
|
||||
'use strict';
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
export interface Variable {
|
||||
setValue(option);
|
||||
}
|
||||
|
||||
@@ -3,49 +3,13 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import $ from 'jquery';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import coreModule from 'app/core/core_module';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import {IntervalVariable} from './interval_variable';
|
||||
import {Variable} from './variable';
|
||||
|
||||
interface Variable {
|
||||
}
|
||||
|
||||
class ConstantVariable implements Variable {
|
||||
constructor(private model) {
|
||||
}
|
||||
}
|
||||
|
||||
class CustomVariable implements Variable {
|
||||
constructor(private model) {
|
||||
}
|
||||
}
|
||||
|
||||
class IntervalVariable implements Variable {
|
||||
constructor(private model) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class QueryVariable implements Variable {
|
||||
|
||||
constructor(private model,
|
||||
private variableSrv: VariableSrv,
|
||||
private datasourceSrv) {
|
||||
_.extend(this, model);
|
||||
}
|
||||
|
||||
updateOptions() {
|
||||
return this.datasourceSrv.get(this.datasource)
|
||||
.then(_.partial(this.updateOptionsFromMetricFindQuery, variable))
|
||||
.then(_.partial(this.updateTags, variable))
|
||||
.then(_.partial(this.validateVariableSelectionState, variable));
|
||||
}
|
||||
}
|
||||
|
||||
class DatasourceVariable implements Variable {
|
||||
constructor(private model) {
|
||||
}
|
||||
}
|
||||
|
||||
export var variableConstructorMap: any = {};
|
||||
|
||||
export class VariableSrv {
|
||||
dashboard: any;
|
||||
@@ -55,53 +19,116 @@ export class VariableSrv {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(
|
||||
private $q,
|
||||
private $rootScope,
|
||||
private datasourceSrv,
|
||||
private $q,
|
||||
private $location,
|
||||
private templateSrv,
|
||||
private timeSrv) {
|
||||
private $injector,
|
||||
private templateSrv) {
|
||||
}
|
||||
|
||||
}
|
||||
init(dashboard) {
|
||||
this.variableLock = {};
|
||||
this.dashboard = dashboard;
|
||||
this.variables = [];
|
||||
|
||||
init(dashboard) {
|
||||
this.variableLock = {};
|
||||
this.dashboard = dashboard;
|
||||
dashboard.templating.list.map(this.addVariable.bind(this));
|
||||
this.templateSrv.init(this.variables);
|
||||
|
||||
this.variables = dashboard.templating.list.map(item => {
|
||||
return new QueryVariable(item, this);
|
||||
});
|
||||
|
||||
this.templateSrv.init(this.variables);
|
||||
return this.$q.when();
|
||||
}
|
||||
|
||||
updateOptions(variable) {
|
||||
return variable.updateOptions();
|
||||
}
|
||||
|
||||
variableUpdated(variable) {
|
||||
// if there is a variable lock ignore cascading update because we are in a boot up scenario
|
||||
if (this.variableLock[variable.name]) {
|
||||
return this.$q.when();
|
||||
}
|
||||
|
||||
var promises = _.map(this.variables, otherVariable => {
|
||||
if (otherVariable === variable) {
|
||||
return;
|
||||
addVariable(model) {
|
||||
var ctor = variableConstructorMap[model.type];
|
||||
if (!ctor) {
|
||||
throw "Unable to find variable constructor for " + model.type;
|
||||
}
|
||||
|
||||
if (this.templateSrv.containsVariable(otherVariable.regex, variable.name) ||
|
||||
this.templateSrv.containsVariable(otherVariable.query, variable.name) ||
|
||||
this.templateSrv.containsVariable(otherVariable.datasource, variable.name)) {
|
||||
var variable = this.$injector.instantiate(ctor, {model: model});
|
||||
this.variables.push(variable);
|
||||
this.dashboard.templating.list.push(model);
|
||||
|
||||
return variable;
|
||||
}
|
||||
|
||||
updateOptions(variable) {
|
||||
return variable.updateOptions();
|
||||
}
|
||||
|
||||
variableUpdated(variable) {
|
||||
// if there is a variable lock ignore cascading update because we are in a boot up scenario
|
||||
if (this.variableLock[variable.name]) {
|
||||
return this.$q.when();
|
||||
}
|
||||
|
||||
var promises = _.map(this.variables, otherVariable => {
|
||||
if (otherVariable === variable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.templateSrv.containsVariable(otherVariable.regex, variable.name) ||
|
||||
this.templateSrv.containsVariable(otherVariable.query, variable.name) ||
|
||||
this.templateSrv.containsVariable(otherVariable.datasource, variable.name)) {
|
||||
return this.updateOptions(otherVariable);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return this.$q.all(promises);
|
||||
}
|
||||
return this.$q.all(promises);
|
||||
}
|
||||
|
||||
selectOptionsForCurrentValue(variable) {
|
||||
var i, y, value, option;
|
||||
var selected: any = [];
|
||||
|
||||
for (i = 0; i < variable.options.length; i++) {
|
||||
option = variable.options[i];
|
||||
option.selected = false;
|
||||
if (_.isArray(variable.current.value)) {
|
||||
for (y = 0; y < variable.current.value.length; y++) {
|
||||
value = variable.current.value[y];
|
||||
if (option.value === value) {
|
||||
option.selected = true;
|
||||
selected.push(option);
|
||||
}
|
||||
}
|
||||
} else if (option.value === variable.current.value) {
|
||||
option.selected = true;
|
||||
selected.push(option);
|
||||
}
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
validateVariableSelectionState(variable) {
|
||||
if (!variable.current) {
|
||||
if (!variable.options.length) { return Promise.resolve(); }
|
||||
return variable.setValue(variable.options[0]);
|
||||
}
|
||||
|
||||
if (_.isArray(variable.current.value)) {
|
||||
var selected = this.selectOptionsForCurrentValue(variable);
|
||||
|
||||
// if none pick first
|
||||
if (selected.length === 0) {
|
||||
selected = variable.options[0];
|
||||
} else {
|
||||
selected = {
|
||||
value: _.map(selected, function(val) {return val.value;}),
|
||||
text: _.map(selected, function(val) {return val.text;}).join(' + '),
|
||||
};
|
||||
}
|
||||
|
||||
return variable.setValue(selected);
|
||||
} else {
|
||||
var currentOption = _.find(variable.options, {text: variable.current.text});
|
||||
if (currentOption) {
|
||||
return variable.setValue(currentOption);
|
||||
} else {
|
||||
if (!variable.options.length) { return Promise.resolve(); }
|
||||
return variable.setValue(variable.options[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
coreModule.service('variableSrv', VariableSrv);
|
||||
|
||||
Reference in New Issue
Block a user