From d96f5598ca09c4d8e0011ba032466b06675b0b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 29 May 2015 10:52:38 +0200 Subject: [PATCH] Breaking out logic for variable dropdown into a controller, this needs some unit tests --- public/app/directives/variableValueSelect.js | 367 +++++++++--------- .../partials/variableValueSelect.html | 22 +- public/css/less/submenu.less | 18 +- 3 files changed, 210 insertions(+), 197 deletions(-) diff --git a/public/app/directives/variableValueSelect.js b/public/app/directives/variableValueSelect.js index 1b25544bb50..c2dd2f3fa51 100644 --- a/public/app/directives/variableValueSelect.js +++ b/public/app/directives/variableValueSelect.js @@ -8,24 +8,206 @@ function (angular, app, _) { 'use strict'; angular + .module('grafana.controllers') + .controller('VariableSelectCtrl', function($scope) { + var vm = this; + + vm.beforeDropdownShow = function() { + vm.oldCurrentText = vm.variable.current.text; + vm.highlightIndex = -1; + + var currentValues = vm.variable.current.value; + + if (_.isString(currentValues)) { + currentValues = [currentValues]; + } + + vm.options = _.map(vm.variable.options, function(option) { + if (_.indexOf(currentValues, option.value) >= 0) { + option.selected = true; + } + return option; + }); + + vm.search = {query: '', options: vm.options}; + vm.selectedValuesCount = currentValues.length; + vm.selectedTags = vm.selectedTag || []; + + if (!vm.tags) { + vm.tags = _.map(vm.variable.tags, function(value) { + return { text: value, selected: false }; + }); + } + }; + + vm.updateLinkText = function() { + vm.labelText = vm.variable.label || '$' + vm.variable.name; + vm.linkText = vm.variable.current.text; + }; + + vm.clearSelections = function() { + _.each(vm.options, function(option) { + option.selected = false; + }); + + vm.selectionsChanged(vm.options[0], false); + }; + + vm.selectTag = function(tag) { + tag.selected = !tag.selected; + 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'); + } + + _.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(vm.options[0], false); + }; + + vm.keyDown = function (evt) { + if (evt.keyCode === 27) { + vm.hide(); + } + if (evt.keyCode === 40) { + vm.moveHighlight(1); + } + if (evt.keyCode === 38) { + vm.moveHighlight(-1); + } + if (evt.keyCode === 13) { + vm.optionSelected(vm.search.options[vm.highlightIndex], {}, true, false); + } + if (evt.keyCode === 32) { + vm.optionSelected(vm.search.options[vm.highlightIndex], {}, false, false); + } + }; + + vm.moveHighlight = function(direction) { + vm.highlightIndex = (vm.highlightIndex + direction) % vm.search.options.length; + }; + + vm.optionSelected = function(option, event, commitChange, excludeOthers) { + if (!option) { return; } + + option.selected = !option.selected; + + commitChange = commitChange || false; + excludeOthers = excludeOthers || false; + + var setAllExceptCurrentTo = function(newValue) { + _.each(vm.options, function(other) { + if (option !== other) { other.selected = newValue; } + }); + }; + + // commit action (enter key), should not deselect it + if (commitChange) { + option.selected = true; + } + + if (option.text === 'All' || excludeOthers) { + setAllExceptCurrentTo(false); + commitChange = true; + } + else if (!vm.variable.multi) { + setAllExceptCurrentTo(false); + commitChange = true; + } else if (event.ctrlKey || event.metaKey || event.shiftKey) { + commitChange = true; + setAllExceptCurrentTo(false); + } + + vm.selectionsChanged(option, commitChange); + }; + + vm.selectionsChanged = function(defaultItem, commitChange) { + var selected = _.filter(vm.options, {selected: true}); + + if (selected.length === 0) { + defaultItem.selected = true; + selected = [defaultItem]; + } + + if (selected.length > 1 && selected.length !== vm.options.length) { + if (selected[0].text === 'All') { + selected[0].selected = false; + selected = selected.slice(1, selected.length); + } + } + + vm.variable.current = { + text: _.pluck(selected, 'text').join(', '), + value: _.pluck(selected, 'value'), + }; + + var valuesNotInTag = _.filter(selected, function(test) { + for (var i = 0; i < vm.selectedTags.length; i++) { + var tag = vm.selectedTags[i]; + if (_.indexOf(tag.values, test.value) !== -1) { + return false; + } + } + return true; + }); + + vm.variable.current.text = _.pluck(valuesNotInTag, 'text').join(', '); + + vm.selectedValuesCount = vm.variable.current.value.length; + + // only single value + if (vm.selectedValuesCount === 1) { + vm.variable.current.value = selected[0].value; + } + + if (commitChange) { + vm.switchToLink(); + } + }; + + vm.queryChanged = function() { + vm.highlightIndex = -1; + vm.search.options = _.filter(vm.options, function(option) { + return option.text.toLowerCase().indexOf(vm.search.query.toLowerCase()) !== -1; + }); + }; + + $scope.$watchGroup(['vm.variable.hideLabel', 'vm.variable.name', 'vm.variable.label', 'vm.variable.current.text'], function() { + vm.updateLinkText(); + }); + + }); + + angular .module('grafana.directives') .directive('variableValueSelect', function($compile, $window, $timeout) { return { scope: { variable: "=", onUpdated: "&" }, templateUrl: 'app/features/dashboard/partials/variableValueSelect.html', - + controller: 'VariableSelectCtrl', + controllerAs: 'vm', + bindToController: true, link: function(scope, elem) { + var vm = scope.vm; var bodyEl = angular.element($window.document.body); var linkEl = elem.find('.variable-value-link'); var inputEl = elem.find('input'); - var variable = scope.variable; var cancelBlur = null; scope.openDropdown = function() { inputEl.show(); linkEl.hide(); - scope.dropdownVisible = true; + vm.dropdownVisible = true; inputEl.css('width', (linkEl.width() + 16) + 'px'); @@ -42,11 +224,12 @@ function (angular, app, _) { cancelBlur = null; inputEl.hide(); linkEl.show(); - scope.dropdownVisible = false; + + vm.dropdownVisible = false; scope.$digest(); - scope.updateLinkText(); - scope.onUpdated(); + scope.vm.updateLinkText(); + scope.vm.onUpdated(); } else { // need to have long delay because the blur @@ -64,180 +247,10 @@ function (angular, app, _) { }; scope.show = function() { - scope.oldCurrentText = variable.current.text; - scope.highlightIndex = -1; - - var currentValues = variable.current.value; - - if (_.isString(currentValues)) { - currentValues = [currentValues]; - } - - scope.options = _.map(variable.options, function(option) { - if (_.indexOf(currentValues, option.value) >= 0) { - option.selected = true; - } - return option; - }); - - scope.search = {query: '', options: scope.options}; - scope.selectedValuesCount = currentValues.length; - scope.selectedTags = scope.selectedTag || []; - - if (!scope.tags) { - scope.tags = _.map(variable.tags, function(value) { - return { text: value, selected: false }; - }); - } - + vm.beforeDropdownShow(); scope.openDropdown(); }; - scope.queryChanged = function() { - scope.highlightIndex = -1; - scope.search.options = _.filter(scope.options, function(option) { - return option.text.toLowerCase().indexOf(scope.search.query.toLowerCase()) !== -1; - }); - }; - - scope.keyDown = function (evt) { - if (evt.keyCode === 27) { - scope.hide(); - } - if (evt.keyCode === 40) { - scope.moveHighlight(1); - } - if (evt.keyCode === 38) { - scope.moveHighlight(-1); - } - if (evt.keyCode === 13) { - scope.optionSelected(scope.search.options[scope.highlightIndex], {}, true, false); - } - if (evt.keyCode === 32) { - scope.optionSelected(scope.search.options[scope.highlightIndex], {}, false, false); - } - }; - - scope.moveHighlight = function(direction) { - scope.highlightIndex = (scope.highlightIndex + direction) % scope.search.options.length; - }; - - scope.optionSelected = function(option, event, commitChange, excludeOthers) { - if (!option) { return; } - - option.selected = !option.selected; - - commitChange = commitChange || false; - excludeOthers = excludeOthers || false; - - var setAllExceptCurrentTo = function(newValue) { - _.each(scope.options, function(other) { - if (option !== other) { other.selected = newValue; } - }); - }; - - // commit action (enter key), should not deselect it - if (commitChange) { - option.selected = true; - } - - if (option.text === 'All' || excludeOthers) { - setAllExceptCurrentTo(false); - commitChange = true; - } - else if (!variable.multi) { - setAllExceptCurrentTo(false); - commitChange = true; - } else if (event.ctrlKey || event.metaKey || event.shiftKey) { - commitChange = true; - setAllExceptCurrentTo(false); - } - - scope.selectionsChanged(option, commitChange); - }; - - scope.selectionsChanged = function(defaultItem, commitChange) { - var selected = _.filter(scope.options, {selected: true}); - - if (selected.length === 0) { - defaultItem.selected = true; - selected = [defaultItem]; - } - - if (selected.length > 1 && selected.length !== scope.options.length) { - if (selected[0].text === 'All') { - selected[0].selected = false; - selected = selected.slice(1, selected.length); - } - } - - variable.current = { - text: _.pluck(selected, 'text').join(', '), - value: _.pluck(selected, 'value'), - }; - - var valuesNotInTag = _.filter(selected, function(test) { - for (var i = 0; i < scope.selectedTags.length; i++) { - var tag = scope.selectedTags[i]; - if (_.indexOf(tag.values, test.value) !== -1) { - return false; - } - } - return true; - }); - - variable.current.text = _.pluck(valuesNotInTag, 'text').join(', '); - - scope.selectedValuesCount = variable.current.value.length; - - // only single value - if (scope.selectedValuesCount === 1) { - variable.current.value = selected[0].value; - } - - if (commitChange) { - scope.switchToLink(); - } - }; - - scope.clearSelections = function() { - _.each(scope.options, function(option) { - option.selected = false; - }); - - scope.selectionsChanged(scope.options[0], false); - }; - - scope.selectTag = function(tag) { - tag.selected = !tag.selected; - 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'); - } - - _.each(scope.options, function(option) { - if (_.indexOf(tag.values, option.value) !== -1) { - option.selected = tag.selected; - } - }); - - scope.selectedTags = _.filter(scope.tags, {selected: true}); - scope.selectionsChanged(scope.options[0], false); - }; - - scope.updateLinkText = function() { - scope.labelText = variable.label || '$' + variable.name; - scope.linkText = variable.current.text; - }; - - scope.$watchGroup(['variable.hideLabel', 'variable.name', 'variable.label', 'variable.current.text'], function() { - scope.updateLinkText(); - }); - linkEl.click(scope.openDropdown); }, }; diff --git a/public/app/features/dashboard/partials/variableValueSelect.html b/public/app/features/dashboard/partials/variableValueSelect.html index e0a4cf2f3c2..411416fb767 100644 --- a/public/app/features/dashboard/partials/variableValueSelect.html +++ b/public/app/features/dashboard/partials/variableValueSelect.html @@ -1,36 +1,36 @@ - - {{labelText}}: + + {{vm.labelText}}: