Преглед изворни кода

Progress on template variable dropdown, lots of unit tests for selection behavior,

Torkel Ödegaard пре 10 година
родитељ
комит
0992b6a616

+ 38 - 40
public/app/directives/variableValueSelect.js

@@ -9,7 +9,7 @@ function (angular, app, _) {
 
 
   angular
   angular
     .module('grafana.controllers')
     .module('grafana.controllers')
-    .controller('SelectDropdownCtrl', function() {
+    .controller('SelectDropdownCtrl', function($q) {
       var vm = this;
       var vm = this;
 
 
       vm.show = function() {
       vm.show = function() {
@@ -56,23 +56,29 @@ function (angular, app, _) {
 
 
       vm.selectTag = function(tag) {
       vm.selectTag = function(tag) {
         tag.selected = !tag.selected;
         tag.selected = !tag.selected;
+        var tagValuesPromise;
         if (!tag.values) {
         if (!tag.values) {
-          if (tag.text === 'backend') {
-            tag.values = ['backend_01', 'backend_02', 'backend_03', 'backend_04'];
-          } else {
-            tag.values = ['web_server_01', 'web_server_02', 'web_server_03', 'web_server_04'];
-          }
-          console.log('querying for tag values');
+          tagValuesPromise = vm.getValuesForTag({tagKey: tag.text});
+          // if (tag.text === 'backend') {
+          //   tag.values = ['backend_01', 'backend_02', 'backend_03', 'backend_04'];
+          // } else {
+          //   tag.values = ['web_server_01', 'web_server_02', 'web_server_03', 'web_server_04'];
+          // }
+        } else {
+          tagValuesPromise = $q.when(tag.values);
         }
         }
 
 
-        _.each(vm.options, function(option) {
-          if (_.indexOf(tag.values, option.value) !== -1) {
-            option.selected = tag.selected;
-          }
-        });
+        tagValuesPromise.then(function(values) {
+          tag.values = values;
+          _.each(vm.options, function(option) {
+            if (_.indexOf(tag.values, option.value) !== -1) {
+              option.selected = tag.selected;
+            }
+          });
 
 
-        vm.selectedTags = _.filter(vm.tags, {selected: true});
-        vm.selectionsChanged(false);
+          vm.selectedTags = _.filter(vm.tags, {selected: true});
+          vm.selectionsChanged(false);
+        });
       };
       };
 
 
       vm.keyDown = function (evt) {
       vm.keyDown = function (evt) {
@@ -141,10 +147,16 @@ function (angular, app, _) {
           }
           }
         }
         }
 
 
-        vm.variable.current = {
-          text: _.pluck(selected, 'text').join(', '),
-          value: _.pluck(selected, 'value'),
-        };
+        // validate selected tags
+        _.each(vm.selectedTags, function(tag) {
+          _.each(tag.values, function(value) {
+            if (!_.findWhere(selected, {value: value})) {
+              tag.selected = false;
+            }
+          });
+        });
+
+        vm.selectedTags = _.filter(vm.tags, {selected: true});
 
 
         var valuesNotInTag = _.filter(selected, function(test) {
         var valuesNotInTag = _.filter(selected, function(test) {
           for (var i = 0; i < vm.selectedTags.length; i++) {
           for (var i = 0; i < vm.selectedTags.length; i++) {
@@ -156,8 +168,9 @@ function (angular, app, _) {
           return true;
           return true;
         });
         });
 
 
+        vm.variable.current = {};
+        vm.variable.current.value = _.pluck(selected, 'value');
         vm.variable.current.text = _.pluck(valuesNotInTag, 'text').join(', ');
         vm.variable.current.text = _.pluck(valuesNotInTag, 'text').join(', ');
-
         vm.selectedValuesCount = vm.variable.current.value.length;
         vm.selectedValuesCount = vm.variable.current.value.length;
 
 
         // only single value
         // only single value
@@ -195,12 +208,12 @@ function (angular, app, _) {
 
 
     });
     });
 
 
-    angular
+  angular
     .module('grafana.directives')
     .module('grafana.directives')
     .directive('variableValueSelect', function($compile, $window, $timeout) {
     .directive('variableValueSelect', function($compile, $window, $timeout) {
 
 
       return {
       return {
-        scope: { variable: "=", onUpdated: "&" },
+        scope: { variable: "=", onUpdated: "&", getValuesForTag: "&" },
         templateUrl: 'app/features/dashboard/partials/variableValueSelect.html',
         templateUrl: 'app/features/dashboard/partials/variableValueSelect.html',
         controller: 'SelectDropdownCtrl',
         controller: 'SelectDropdownCtrl',
         controllerAs: 'vm',
         controllerAs: 'vm',
@@ -209,7 +222,6 @@ function (angular, app, _) {
           var bodyEl = angular.element($window.document.body);
           var bodyEl = angular.element($window.document.body);
           var linkEl = elem.find('.variable-value-link');
           var linkEl = elem.find('.variable-value-link');
           var inputEl = elem.find('input');
           var inputEl = elem.find('input');
-          var cancelBlur = null;
 
 
           function openDropdown() {
           function openDropdown() {
             inputEl.css('width', Math.max(linkEl.width(), 30) + 'px');
             inputEl.css('width', Math.max(linkEl.width(), 30) + 'px');
@@ -217,27 +229,13 @@ function (angular, app, _) {
             inputEl.show();
             inputEl.show();
             linkEl.hide();
             linkEl.hide();
 
 
-            linkEl.hide();
-            inputEl.show();
             inputEl.focus();
             inputEl.focus();
-
             $timeout(function() { bodyEl.on('click', bodyOnClick); }, 0, false);
             $timeout(function() { bodyEl.on('click', bodyOnClick); }, 0, false);
           }
           }
 
 
-          function switchToLink(now) {
-            if (now === true || cancelBlur) {
-              clearTimeout(cancelBlur);
-              cancelBlur = null;
-              inputEl.hide();
-              linkEl.show();
-
-           }
-            else {
-              // need to have long delay because the blur
-              // happens long before the click event on the typeahead options
-              cancelBlur = setTimeout(scope.switchToLink, 50);
-            }
-
+          function switchToLink() {
+            inputEl.hide();
+            linkEl.show();
             bodyEl.off('click', bodyOnClick);
             bodyEl.off('click', bodyOnClick);
           }
           }
 
 
@@ -252,7 +250,7 @@ function (angular, app, _) {
           scope.$watch('vm.dropdownVisible', function(newValue) {
           scope.$watch('vm.dropdownVisible', function(newValue) {
             if (newValue) {
             if (newValue) {
               openDropdown();
               openDropdown();
-            } {
+            } else {
               switchToLink();
               switchToLink();
             }
             }
           });
           });

+ 4 - 0
public/app/features/dashboard/submenuCtrl.js

@@ -28,6 +28,10 @@ function (angular, _) {
       $rootScope.$broadcast('refresh');
       $rootScope.$broadcast('refresh');
     };
     };
 
 
+    $scope.getValuesForTag = function() {
+      return $q.when(['backend_01', 'backend_02']);
+    };
+
     $scope.variableUpdated = function(variable) {
     $scope.variableUpdated = function(variable) {
       templateValuesSrv.variableUpdated(variable).then(function() {
       templateValuesSrv.variableUpdated(variable).then(function() {
         dynamicDashboardSrv.update($scope.dashboard);
         dynamicDashboardSrv.update($scope.dashboard);

+ 1 - 1
public/app/partials/submenu.html

@@ -6,7 +6,7 @@
 				<span class="template-variable tight-form-item" ng-show="!variable.hideLabel" style="padding-right: 5px">
 				<span class="template-variable tight-form-item" ng-show="!variable.hideLabel" style="padding-right: 5px">
 					{{variable.label || variable.name}}:
 					{{variable.label || variable.name}}:
 				</span>
 				</span>
-				<variable-value-select variable="variable" on-updated="variableUpdated(variable)"></variable-value-select>
+				<variable-value-select variable="variable" on-updated="variableUpdated(variable)" get-values-for-tag="getValuesForTag(tagKey)"></variable-value-select>
 			</li>
 			</li>
 		</ul>
 		</ul>
 
 

+ 71 - 3
public/test/specs/selectDropdownCtrl-specs.js

@@ -8,11 +8,17 @@ function () {
   describe("SelectDropdownCtrl", function() {
   describe("SelectDropdownCtrl", function() {
     var scope;
     var scope;
     var ctrl;
     var ctrl;
+    var tagValuesMap = {};
+    var rootScope;
 
 
     beforeEach(module('grafana.controllers'));
     beforeEach(module('grafana.controllers'));
-    beforeEach(inject(function($controller, $rootScope) {
+    beforeEach(inject(function($controller, $rootScope, $q) {
+      rootScope = $rootScope;
       scope = $rootScope.$new();
       scope = $rootScope.$new();
       ctrl = $controller('SelectDropdownCtrl', {$scope: scope});
       ctrl = $controller('SelectDropdownCtrl', {$scope: scope});
+      ctrl.getValuesForTag = function(obj) {
+        return $q.when(tagValuesMap[obj.tagKey]);
+      };
     }));
     }));
 
 
     describe("Given simple variable", function() {
     describe("Given simple variable", function() {
@@ -24,9 +30,71 @@ function () {
       it("Should init labelText and linkText", function() {
       it("Should init labelText and linkText", function() {
         expect(ctrl.linkText).to.be("hej");
         expect(ctrl.linkText).to.be("hej");
       });
       });
-
     });
     });
 
 
-  });
+    describe("Given variable with tags and dropdown is opened", function() {
+      beforeEach(function() {
+        ctrl.variable = {
+          current: {text: 'hej', value: 'hej'},
+          options: [
+            {text: 'server-1', value: 'server-1'},
+            {text: 'server-2', value: 'server-2'},
+            {text: 'server-3', value: 'server-3'},
+          ],
+          tags: ["key1", "key2", "key3"]
+        };
+        tagValuesMap.key1 = ['server-1', 'server-3'];
+        tagValuesMap.key2 = ['server-2', 'server-3'];
+        tagValuesMap.key3 = ['server-1', 'server-2', 'server-3'];
+        ctrl.init();
+        ctrl.show();
+      });
+
+      it("should init tags model", function() {
+        expect(ctrl.tags.length).to.be(3);
+        expect(ctrl.tags[0].text).to.be("key1");
+      });
+
+      it("should init options model", function() {
+        expect(ctrl.options.length).to.be(3);
+      });
 
 
+      describe('When tag is selected', function() {
+        beforeEach(function() {
+          ctrl.selectTag(ctrl.tags[0]);
+          rootScope.$digest();
+        });
+
+        it("should select tag", function() {
+          expect(ctrl.selectedTags.length).to.be(1);
+        });
+
+        it("should select values", function() {
+          expect(ctrl.options[0].selected).to.be(true);
+          expect(ctrl.options[2].selected).to.be(true);
+        });
+
+        describe('and then unselected', function() {
+          beforeEach(function() {
+            ctrl.selectTag(ctrl.tags[0]);
+            rootScope.$digest();
+          });
+
+          it("should deselect tag", function() {
+            expect(ctrl.selectedTags.length).to.be(0);
+          });
+        });
+
+        describe('and then value is unselected', function() {
+          beforeEach(function() {
+            ctrl.optionSelected(ctrl.options[0]);
+          });
+
+          it("should deselect tag", function() {
+            expect(ctrl.selectedTags.length).to.be(0);
+          });
+        });
+      });
+    });
+  });
 });
 });