Commit 0cb57f52 by woodsaj

refactor how template vars are updated. fixes #4283

Use promises to order the updates of variable options so that
parents are always updated before children.
This ensures that we only need to query the datasource once per
variable as variables that depend on other variables will only be
processed once their parent has been.
This commit also ensures that variable options are refreshed if
"refresh_on_load" is true even when query params are used to
set the variable seltion.
parent d2aaa221
......@@ -27,29 +27,72 @@ function (angular, _, kbn) {
var queryParams = $location.search();
var promises = [];
//use promises to delay processing variables that
//depend on other variables.
this.variableLock = {};
var self = this;
_.forEach(this.variables, function(variable) {
self.variableLock[variable.name] = $q.defer();
});
for (var i = 0; i < this.variables.length; i++) {
var variable = this.variables[i];
promises.push(this.processVariable(variable, queryParams));
}
return $q.all(promises);
};
this.processVariable = function(variable, queryParams) {
var dependencies = [];
var self = this;
// determine our dependencies.
if (variable.type === "query") {
_.forEach(this.variables, function(v) {
if (templateSrv.containsVariable(variable.query, v.name)) {
dependencies.push(self.variableLock[v.name].promise);
}
});
}
return $q.all(dependencies).then(function() {
var variableName = variable.name;
var urlValue = queryParams['var-' + variable.name];
if (urlValue !== void 0) {
promises.push(this.setVariableFromUrl(variable, urlValue));
return self.setVariableFromUrl(variable, urlValue).then(function() {
self.variableLock[variableName].resolve();
});
}
else if (variable.refresh) {
promises.push(this.updateOptions(variable));
return self.updateOptions(variable).then(function() {
self.variableLock[variableName].resolve();
});
}
else if (variable.type === 'interval') {
this.updateAutoInterval(variable);
self.updateAutoInterval(variable);
self.variableLock[variableName].resolve();
} else {
self.variableLock[variableName].resolve();
}
}
return $q.all(promises);
});
};
this.setVariableFromUrl = function(variable, urlValue) {
if (variable.refresh) {
var self = this;
//refresh the list of options before setting the value
return this.updateOptions(variable).then(function() {
var option = _.findWhere(variable.options, { text: urlValue });
option = option || { text: urlValue, value: urlValue };
self.updateAutoInterval(variable);
return self.setVariableValue(variable, option, true);
});
}
var option = _.findWhere(variable.options, { text: urlValue });
option = option || { text: urlValue, value: urlValue };
this.updateAutoInterval(variable);
return this.setVariableValue(variable, option);
return this.setVariableValue(variable, option, true);
};
this.updateAutoInterval = function(variable) {
......@@ -64,7 +107,7 @@ function (angular, _, kbn) {
templateSrv.setGrafanaVariable('$__auto_interval', interval);
};
this.setVariableValue = function(variable, option) {
this.setVariableValue = function(variable, option, firstLoad) {
variable.current = angular.copy(option);
if (_.isArray(variable.current.value)) {
......@@ -74,6 +117,11 @@ function (angular, _, kbn) {
self.selectOptionsForCurrentValue(variable);
templateSrv.updateTemplateData();
// on first load, variable loading is ordered to ensure
// that parents are updated before children.
if (firstLoad) {
return $q.when();
}
return self.updateOptionsInChildVariables(variable);
};
......@@ -119,8 +167,7 @@ function (angular, _, kbn) {
return datasourceSrv.get(variable.datasource)
.then(_.partial(this.updateOptionsFromMetricFindQuery, variable))
.then(_.partial(this.updateTags, variable))
.then(_.partial(this.validateVariableSelectionState, variable));
.then(_.partial(this.updateTags, variable));
};
this.selectOptionsForCurrentValue = function(variable) {
......
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