From 0992b6a616fd575e3593ff174e493b1009a753b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 29 May 2015 14:53:16 +0200 Subject: [PATCH] Progress on template variable dropdown, lots of unit tests for selection behavior, --- public/app/directives/variableValueSelect.js | 78 +++++++++---------- public/app/features/dashboard/submenuCtrl.js | 4 + public/app/partials/submenu.html | 2 +- public/test/specs/selectDropdownCtrl-specs.js | 74 +++++++++++++++++- 4 files changed, 114 insertions(+), 44 deletions(-) diff --git a/public/app/directives/variableValueSelect.js b/public/app/directives/variableValueSelect.js index 173429a8a1f..f77510afc0d 100644 --- a/public/app/directives/variableValueSelect.js +++ b/public/app/directives/variableValueSelect.js @@ -9,7 +9,7 @@ function (angular, app, _) { angular .module('grafana.controllers') - .controller('SelectDropdownCtrl', function() { + .controller('SelectDropdownCtrl', function($q) { var vm = this; vm.show = function() { @@ -56,23 +56,29 @@ function (angular, app, _) { vm.selectTag = function(tag) { tag.selected = !tag.selected; + var tagValuesPromise; 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) { @@ -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) { for (var i = 0; i < vm.selectedTags.length; i++) { @@ -156,8 +168,9 @@ function (angular, app, _) { return true; }); + vm.variable.current = {}; + vm.variable.current.value = _.pluck(selected, 'value'); vm.variable.current.text = _.pluck(valuesNotInTag, 'text').join(', '); - vm.selectedValuesCount = vm.variable.current.value.length; // only single value @@ -195,12 +208,12 @@ function (angular, app, _) { }); - angular + angular .module('grafana.directives') .directive('variableValueSelect', function($compile, $window, $timeout) { return { - scope: { variable: "=", onUpdated: "&" }, + scope: { variable: "=", onUpdated: "&", getValuesForTag: "&" }, templateUrl: 'app/features/dashboard/partials/variableValueSelect.html', controller: 'SelectDropdownCtrl', controllerAs: 'vm', @@ -209,7 +222,6 @@ function (angular, app, _) { var bodyEl = angular.element($window.document.body); var linkEl = elem.find('.variable-value-link'); var inputEl = elem.find('input'); - var cancelBlur = null; function openDropdown() { inputEl.css('width', Math.max(linkEl.width(), 30) + 'px'); @@ -217,27 +229,13 @@ function (angular, app, _) { inputEl.show(); linkEl.hide(); - linkEl.hide(); - inputEl.show(); inputEl.focus(); - $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); } @@ -252,7 +250,7 @@ function (angular, app, _) { scope.$watch('vm.dropdownVisible', function(newValue) { if (newValue) { openDropdown(); - } { + } else { switchToLink(); } }); diff --git a/public/app/features/dashboard/submenuCtrl.js b/public/app/features/dashboard/submenuCtrl.js index 84764ef7f31..6f423ebbe59 100644 --- a/public/app/features/dashboard/submenuCtrl.js +++ b/public/app/features/dashboard/submenuCtrl.js @@ -28,6 +28,10 @@ function (angular, _) { $rootScope.$broadcast('refresh'); }; + $scope.getValuesForTag = function() { + return $q.when(['backend_01', 'backend_02']); + }; + $scope.variableUpdated = function(variable) { templateValuesSrv.variableUpdated(variable).then(function() { dynamicDashboardSrv.update($scope.dashboard); diff --git a/public/app/partials/submenu.html b/public/app/partials/submenu.html index 3e99f21dd86..43a5581e0b5 100644 --- a/public/app/partials/submenu.html +++ b/public/app/partials/submenu.html @@ -6,7 +6,7 @@ {{variable.label || variable.name}}: - + diff --git a/public/test/specs/selectDropdownCtrl-specs.js b/public/test/specs/selectDropdownCtrl-specs.js index bd9f0919d20..c919b3b8bee 100644 --- a/public/test/specs/selectDropdownCtrl-specs.js +++ b/public/test/specs/selectDropdownCtrl-specs.js @@ -8,11 +8,17 @@ function () { describe("SelectDropdownCtrl", function() { var scope; var ctrl; + var tagValuesMap = {}; + var rootScope; beforeEach(module('grafana.controllers')); - beforeEach(inject(function($controller, $rootScope) { + beforeEach(inject(function($controller, $rootScope, $q) { + rootScope = $rootScope; scope = $rootScope.$new(); ctrl = $controller('SelectDropdownCtrl', {$scope: scope}); + ctrl.getValuesForTag = function(obj) { + return $q.when(tagValuesMap[obj.tagKey]); + }; })); describe("Given simple variable", function() { @@ -24,9 +30,71 @@ function () { it("Should init labelText and linkText", function() { 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); + }); + }); + }); + }); + }); });