Просмотр исходного кода

Merge pull request #4287 from grafana/raintank-issue4283

refactor how template vars are updated. fixes #4283
Torkel Ödegaard 9 лет назад
Родитель
Сommit
3af4b1ff98

+ 62 - 14
public/app/features/templating/templateValuesSrv.js

@@ -27,29 +27,71 @@ function (angular, _, kbn) {
       var queryParams = $location.search();
       var promises = [];
 
+      // use promises to delay processing variables that
+      // depend on other variables.
+      this.variableLock = {};
+      _.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 lock = self.variableLock[variable.name];
+
+      // 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 urlValue = queryParams['var-' + variable.name];
         if (urlValue !== void 0) {
-          promises.push(this.setVariableFromUrl(variable, urlValue));
+          return self.setVariableFromUrl(variable, urlValue).then(lock.resolve);
         }
         else if (variable.refresh) {
-          promises.push(this.updateOptions(variable));
+          return self.updateOptions(variable).then(function() {
+            if (_.isEmpty(variable.current) && variable.options.length) {
+              console.log("setting current for %s", variable.name);
+              self.setVariableValue(variable, variable.options[0]);
+            }
+            lock.resolve();
+          });
         }
         else if (variable.type === 'interval') {
-          this.updateAutoInterval(variable);
+          self.updateAutoInterval(variable);
+          lock.resolve();
+        } else {
+          lock.resolve();
         }
-      }
-
-      return $q.all(promises);
+      });
     };
 
     this.setVariableFromUrl = function(variable, urlValue) {
-      var option = _.findWhere(variable.options, { text: urlValue });
-      option = option || { text: urlValue, value: urlValue };
+      var promise = $q.when(true);
+
+      if (variable.refresh) {
+        promise = this.updateOptions(variable);
+      }
 
-      this.updateAutoInterval(variable);
-      return this.setVariableValue(variable, option);
+      return promise.then(function() {
+        var option = _.findWhere(variable.options, { text: urlValue });
+        option = option || { text: urlValue, value: urlValue };
+
+        self.updateAutoInterval(variable);
+        return self.setVariableValue(variable, option, true);
+      });
     };
 
     this.updateAutoInterval = function(variable) {
@@ -64,7 +106,7 @@ function (angular, _, kbn) {
       templateSrv.setGrafanaVariable('$__auto_interval', interval);
     };
 
-    this.setVariableValue = function(variable, option) {
+    this.setVariableValue = function(variable, option, initPhase) {
       variable.current = angular.copy(option);
 
       if (_.isArray(variable.current.value)) {
@@ -72,8 +114,14 @@ function (angular, _, kbn) {
       }
 
       self.selectOptionsForCurrentValue(variable);
-
       templateSrv.updateTemplateData();
+
+      // on first load, variable loading is ordered to ensure
+      // that parents are updated before children.
+      if (initPhase) {
+        return $q.when();
+      }
+
       return self.updateOptionsInChildVariables(variable);
     };
 
@@ -145,7 +193,7 @@ function (angular, _, kbn) {
     this.validateVariableSelectionState = function(variable) {
       if (!variable.current) {
         if (!variable.options.length) { return; }
-        return self.setVariableValue(variable, variable.options[0]);
+        return self.setVariableValue(variable, variable.options[0], true);
       }
 
       if (_.isArray(variable.current.value)) {
@@ -153,7 +201,7 @@ function (angular, _, kbn) {
       } else {
         var currentOption = _.findWhere(variable.options, { text: variable.current.text });
         if (currentOption) {
-          return self.setVariableValue(variable, currentOption);
+          return self.setVariableValue(variable, currentOption, true);
         } else {
           if (!variable.options.length) { return; }
           return self.setVariableValue(variable, variable.options[0]);

+ 6 - 4
public/test/specs/templateValuesSrv-specs.js

@@ -34,12 +34,13 @@ define([
         options: [{text: "test", value: "test"}]
       };
 
-      beforeEach(function() {
+      beforeEach(function(done) {
         var dashboard = { templating: { list: [variable] } };
         var urlParams = {};
         urlParams["var-apps"] = "new";
         ctx.$location.search = sinon.stub().returns(urlParams);
-        ctx.service.init(dashboard);
+        ctx.service.init(dashboard).then(function() { done(); });
+        ctx.$rootScope.$digest();
       });
 
       it('should update current value', function() {
@@ -56,12 +57,13 @@ define([
         options: [{text: "val1", value: "val1"}, {text: 'val2', value: 'val2'}, {text: 'val3', value: 'val3', selected: true}]
       };
 
-      beforeEach(function() {
+      beforeEach(function(done) {
         var dashboard = { templating: { list: [variable] } };
         var urlParams = {};
         urlParams["var-apps"] = ["val2", "val1"];
         ctx.$location.search = sinon.stub().returns(urlParams);
-        ctx.service.init(dashboard);
+        ctx.service.init(dashboard).then(function() { done(); });
+        ctx.$rootScope.$digest();
       });
 
       it('should update current value', function() {