diff --git a/CHANGELOG.md b/CHANGELOG.md index adf4db4a525..9102807b6e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - [Issue #219](https://github.com/grafana/grafana/issues/219). Templating: Template variable value selection is now a typeahead autocomplete dropdown **New features and improvements** +- [Issue #281](https://github.com/grafana/grafana/issues/281). Graphite: Metric node/segment selection is now a textbox with autocomplete dropdown, allow for custom glob expression for single node segment without entering text editor mode. - [Issue #578](https://github.com/grafana/grafana/issues/578). Dashboard: Row option to display row title even when the row is visible - [Issue #672](https://github.com/grafana/grafana/issues/672). Dashboard: panel fullscreen & edit state is present in url, can now link to graph in edit & fullscreen mode. - [Issue #709](https://github.com/grafana/grafana/issues/709). Dashboard: Small UI look polish to search results, made dashboard title link are larger diff --git a/src/app/controllers/dashboardNavCtrl.js b/src/app/controllers/dashboardNavCtrl.js index 6f08ffb255e..204b874db70 100644 --- a/src/app/controllers/dashboardNavCtrl.js +++ b/src/app/controllers/dashboardNavCtrl.js @@ -81,8 +81,10 @@ function (angular, _, moment, config, store) { .then(function(result) { alertSrv.set('Dashboard Saved', 'Dashboard has been saved as "' + result.title + '"','success', 5000); - $location.search({}); - $location.path(result.url); + if (result.url !== $location.path()) { + $location.search({}); + $location.path(result.url); + } $rootScope.$emit('dashboard-saved', $scope.dashboard); diff --git a/src/app/controllers/graphiteTarget.js b/src/app/controllers/graphiteTarget.js index aebc297b278..493f01eb562 100644 --- a/src/app/controllers/graphiteTarget.js +++ b/src/app/controllers/graphiteTarget.js @@ -168,17 +168,14 @@ function (angular, _, config, gfunc, Parser) { }); }; - $scope.setSegment = function (altIndex, segmentIndex) { + $scope.segmentValueChanged = function (segment, segmentIndex) { delete $scope.parserError; - $scope.segments[segmentIndex].value = $scope.altSegments[altIndex].value; - $scope.segments[segmentIndex].html = $scope.altSegments[altIndex].html; - if ($scope.functions.length > 0 && $scope.functions[0].def.fake) { $scope.functions = []; } - if ($scope.altSegments[altIndex].expandable) { + if (segment.expandable) { return checkOtherSegments(segmentIndex + 1) .then(function () { setSegmentFocus(segmentIndex + 1); diff --git a/src/app/directives/all.js b/src/app/directives/all.js index f6051da8caa..35d718fc942 100644 --- a/src/app/directives/all.js +++ b/src/app/directives/all.js @@ -16,6 +16,7 @@ define([ './addGraphiteFunc', './graphiteFuncEditor', './templateParamSelector', + './graphiteSegment', './grafanaVersionCheck', './influxdbFuncEditor' ], function () {}); diff --git a/src/app/directives/graphiteSegment.js b/src/app/directives/graphiteSegment.js new file mode 100644 index 00000000000..0f1e4397d25 --- /dev/null +++ b/src/app/directives/graphiteSegment.js @@ -0,0 +1,137 @@ +define([ + 'angular', + 'app', + 'lodash', + 'jquery', +], +function (angular, app, _, $) { + 'use strict'; + + angular + .module('grafana.directives') + .directive('graphiteSegment', function($compile, $sce) { + var inputTemplate = ''; + + var buttonTemplate = ''; + + return { + link: function($scope, elem) { + var $input = $(inputTemplate); + var $button = $(buttonTemplate); + var segment = $scope.segment; + var options = null; + var cancelBlur = null; + + $input.appendTo(elem); + $button.appendTo(elem); + + $scope.updateVariableValue = function(value) { + if (value === '' || segment.value === value) { + return; + } + + $scope.$apply(function() { + var selected = _.findWhere($scope.altSegments, { value: value }); + if (selected) { + segment.value = selected.value; + segment.html = selected.html; + segment.expandable = selected.expandable; + } + else { + segment.value = value; + segment.html = $sce.trustAsHtml(value); + segment.expandable = true; + } + $scope.segmentValueChanged(segment, $scope.$index); + }); + }; + + $scope.switchToLink = function(now) { + if (now === true || cancelBlur) { + clearTimeout(cancelBlur); + cancelBlur = null; + $input.hide(); + $button.show(); + $scope.updateVariableValue($input.val()); + } + else { + // need to have long delay because the blur + // happens long before the click event on the typeahead options + cancelBlur = setTimeout($scope.switchToLink, 350); + } + }; + + $scope.source = function(query, callback) { + console.log("source!", callback); + if (options) { + return options; + } + + $scope.$apply(function() { + $scope.getAltSegments($scope.$index).then(function() { + options = _.map($scope.altSegments, function(alt) { return alt.value; }); + + // add custom values + if (segment.value !== 'select metric' && _.indexOf(options, segment.value) === -1) { + options.unshift(segment.value); + } + + callback(options); + }); + }); + }; + + $scope.updater = function(value) { + if (value === segment.value) { + clearTimeout(cancelBlur); + $input.focus(); + return value; + } + + $input.val(value); + $scope.switchToLink(true); + + return value; + }; + + $input.attr('data-provide', 'typeahead'); + $input.typeahead({ source: $scope.source, minLength: 0, items: 100, updater: $scope.updater }); + + var typeahead = $input.data('typeahead'); + typeahead.lookup = function () { + this.query = this.$element.val() || ''; + var items = this.source(this.query, $.proxy(this.process, this)); + return items ? this.process(items) : items; + }; + + $button.keydown(function(evt) { + // trigger typeahead on down arrow or enter key + if (evt.keyCode === 40 || evt.keyCode === 13) { + $button.click(); + } + }); + + $button.click(function() { + options = null; + $input.css('width', ($button.width() + 16) + 'px'); + + $button.hide(); + $input.show(); + $input.focus(); + + var typeahead = $input.data('typeahead'); + if (typeahead) { + $input.val(''); + typeahead.lookup(); + } + }); + + $input.blur($scope.switchToLink); + + $compile(elem.contents())($scope); + } + }; + }); +}); diff --git a/src/app/partials/graphite/editor.html b/src/app/partials/graphite/editor.html index b25478dba37..2a314615963 100755 --- a/src/app/partials/graphite/editor.html +++ b/src/app/partials/graphite/editor.html @@ -1,4 +1,3 @@ -