From af8fec941c372f637ed2a5ed435698b95566254d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 23 Sep 2014 08:18:59 +0200 Subject: [PATCH 1/6] Graph: Fix for series draw order not being the same after hiding/unhiding series, Fixes #847 --- CHANGELOG.md | 5 +++++ src/app/directives/grafanaGraph.js | 26 ++++++-------------------- src/test/specs/grafanaGraph-specs.js | 13 +++++++++++++ 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d28e9223f0..79bc9c23752 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 1.9.0 (unreleased) + +**Fixes** +- [Issue #847](https://github.com/grafana/grafana/issues/847). Graph: Fix for series draw order not being the same after hiding/unhiding series + # 1.8.0 (2014-09-22) Read this [blog post](http://grafana.org/blog/2014/09/11/grafana-1-8-0-rc1-released.html) for an overview of all improvements. diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index 15f1556aa62..a2987213cb4 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -16,7 +16,6 @@ function (angular, $, kbn, moment, _) { template: '
', link: function(scope, elem) { var data, annotations; - var hiddenData = {}; var dashboard = scope.dashboard; var legendSideLastValue = null; @@ -24,14 +23,7 @@ function (angular, $, kbn, moment, _) { scope.get_data(); }); - scope.$on('toggleLegend', function(e, series) { - _.each(series, function(serie) { - if (hiddenData[serie.alias]) { - data.push(hiddenData[serie.alias]); - delete hiddenData[serie.alias]; - } - }); - + scope.$on('toggleLegend', function() { render_panel(); }); @@ -95,17 +87,6 @@ function (angular, $, kbn, moment, _) { } var panel = scope.panel; - - _.each(_.keys(scope.hiddenSeries), function(seriesAlias) { - var dataSeries = _.find(data, function(series) { - return series.info.alias === seriesAlias; - }); - if (dataSeries) { - hiddenData[dataSeries.info.alias] = dataSeries; - data = _.without(data, dataSeries); - } - }); - var stack = panel.stack ? true : null; // Populate element @@ -156,6 +137,11 @@ function (angular, $, kbn, moment, _) { var series = data[i]; series.applySeriesOverrides(panel.seriesOverrides); series.data = series.getFlotPairs(panel.nullPointMode, panel.y_formats); + // if hidden remove points and disable stack + if (scope.hiddenSeries[series.info.alias]) { + series.data = []; + series.stack = false; + } } if (data.length && data[0].info.timeStep) { diff --git a/src/test/specs/grafanaGraph-specs.js b/src/test/specs/grafanaGraph-specs.js index 1b86ee9073d..faf19119d27 100644 --- a/src/test/specs/grafanaGraph-specs.js +++ b/src/test/specs/grafanaGraph-specs.js @@ -29,6 +29,7 @@ define([ y_formats: [], seriesOverrides: [] }; + scope.hiddenSeries = {}; scope.dashboard = { timezone: 'browser' }; scope.range = { from: new Date('2014-08-09 10:00:00'), @@ -145,6 +146,18 @@ define([ }); }); + graphScenario('when series is hidden', function(ctx) { + ctx.setup(function(scope) { + scope.hiddenSeries = {'series2': true}; + }); + + it('should remove datapoints and disable stack', function() { + expect(ctx.plotData[0].info.alias).to.be('series1'); + expect(ctx.plotData[1].data.length).to.be(0); + expect(ctx.plotData[1].stack).to.be(false); + }); + }); + }); }); From 0fbace72856e5854ce7483c945a007e5f3591e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 23 Sep 2014 08:32:04 +0200 Subject: [PATCH 2/6] Row: fix for row editor and scroll pos, Fixes #846 --- src/app/directives/dashEditLink.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/directives/dashEditLink.js b/src/app/directives/dashEditLink.js index 599cf341fe5..d0babd967e4 100644 --- a/src/app/directives/dashEditLink.js +++ b/src/app/directives/dashEditLink.js @@ -34,6 +34,7 @@ function (angular, $) { function hideScrollbars(value) { if (value) { + window.scrollTo(0,0); document.documentElement.style.overflow = 'hidden'; // firefox, chrome document.body.scroll = "no"; // ie only } else { From 81747e162326d3381a7f0b0a88e372e76f11ed07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 24 Sep 2014 09:03:04 +0200 Subject: [PATCH 3/6] Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations, Fixes #851 --- CHANGELOG.md | 3 +++ src/app/services/annotationsSrv.js | 3 ++- src/app/services/elasticsearch/es-datasource.js | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79bc9c23752..c70461859dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # 1.9.0 (unreleased) +# 1.8.1 (unreleased) + **Fixes** - [Issue #847](https://github.com/grafana/grafana/issues/847). Graph: Fix for series draw order not being the same after hiding/unhiding series +- [Issue #851](https://github.com/grafana/grafana/issues/851). Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations # 1.8.0 (2014-09-22) diff --git a/src/app/services/annotationsSrv.js b/src/app/services/annotationsSrv.js index 04fb4224cc6..25c76caeb77 100644 --- a/src/app/services/annotationsSrv.js +++ b/src/app/services/annotationsSrv.js @@ -13,7 +13,8 @@ define([ var timezone; this.init = function() { - $rootScope.$on('refresh', this.clearCache); + $rootScope.onAppEvent('refresh', this.clearCache); + $rootScope.onAppEvent('setup-dashboard', this.clearCache); }; this.clearCache = function() { diff --git a/src/app/services/elasticsearch/es-datasource.js b/src/app/services/elasticsearch/es-datasource.js index 04d1e62ce04..f9ec01dbd4c 100644 --- a/src/app/services/elasticsearch/es-datasource.js +++ b/src/app/services/elasticsearch/es-datasource.js @@ -94,6 +94,10 @@ function (angular, _, config, kbn, moment) { for (var i = 0; i < fieldNames.length; i++) { fieldValue = fieldValue[fieldNames[i]]; + if (!fieldValue) { + console.log('could not find field in annotatation: ', fieldName); + return ''; + } } if (_.isArray(fieldValue)) { From f4e24038feebf6c52d144c1634fa6c4c0a354210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 24 Sep 2014 10:51:20 +0200 Subject: [PATCH 4/6] Import: Fixes to import from json file and import from graphite. Issues was lingering state from previous dashboard. Closes #840, Closes #853 --- CHANGELOG.md | 2 ++ src/app/controllers/dashboardCtrl.js | 10 ++++----- src/app/controllers/grafanaCtrl.js | 6 ++++- src/app/controllers/graphiteImport.js | 13 ++++++----- src/app/controllers/row.js | 1 + src/app/directives/dashUpload.js | 12 +++++----- src/app/partials/dashboard.html | 2 +- src/app/partials/import.html | 12 ++++++---- src/app/routes/dashboard-from-db.js | 29 ++++++++++++++++++++----- src/app/routes/dashboard-from-file.js | 2 +- src/app/routes/dashboard-from-script.js | 2 +- 11 files changed, 61 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c70461859dd..dce1108a1c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ **Fixes** - [Issue #847](https://github.com/grafana/grafana/issues/847). Graph: Fix for series draw order not being the same after hiding/unhiding series - [Issue #851](https://github.com/grafana/grafana/issues/851). Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations +- [Issue #846](https://github.com/grafana/grafana/issues/846). Edit panes: Issue when open row or json editor when scrolled down the page, unable to scroll and you did not see editor +- [Issue #840](https://github.com/grafana/grafana/issues/840). Import: Fixes to import from json file and import from graphite. Issues was lingering state from previous dashboard. # 1.8.0 (2014-09-22) diff --git a/src/app/controllers/dashboardCtrl.js b/src/app/controllers/dashboardCtrl.js index 424f0e225e8..709e33ae7d3 100644 --- a/src/app/controllers/dashboardCtrl.js +++ b/src/app/controllers/dashboardCtrl.js @@ -19,19 +19,18 @@ function (angular, $, config, _) { dashboardSrv, dashboardViewStateSrv, panelMoveSrv, - timer, $timeout) { $scope.editor = { index: 0 }; $scope.panelNames = config.panels; var resizeEventTimeout; - $scope.init = function() { + this.init = function(dashboardData) { $scope.availablePanels = config.panels; - $scope.onAppEvent('setup-dashboard', $scope.setupDashboard); - $scope.onAppEvent('show-json-editor', $scope.showJsonEditor); $scope.reset_row(); $scope.registerWindowResizeEvent(); + $scope.onAppEvent('show-json-editor', $scope.showJsonEditor); + $scope.setupDashboard(dashboardData); }; $scope.registerWindowResizeEvent = function() { @@ -41,7 +40,7 @@ function (angular, $, config, _) { }); }; - $scope.setupDashboard = function(event, dashboardData) { + $scope.setupDashboard = function(dashboardData) { $rootScope.performance.dashboardLoadStart = new Date().getTime(); $rootScope.performance.panelsInitialized = 0; $rootScope.performance.panelsRendered = 0; @@ -129,6 +128,5 @@ function (angular, $, config, _) { return $scope.editorTabs; }; - $scope.init(); }); }); diff --git a/src/app/controllers/grafanaCtrl.js b/src/app/controllers/grafanaCtrl.js index 060c0bc0803..5d406dee1b6 100644 --- a/src/app/controllers/grafanaCtrl.js +++ b/src/app/controllers/grafanaCtrl.js @@ -10,7 +10,7 @@ function (angular, config, _, $, store) { var module = angular.module('grafana.controllers'); - module.controller('GrafanaCtrl', function($scope, alertSrv, grafanaVersion, $rootScope) { + module.controller('GrafanaCtrl', function($scope, alertSrv, grafanaVersion, $rootScope, $controller) { $scope.grafanaVersion = grafanaVersion[0] === '@' ? 'master' : grafanaVersion; $scope.consoleEnabled = store.getBool('grafanaConsole'); @@ -32,6 +32,10 @@ function (angular, config, _, $, store) { store.set('grafanaConsole', $scope.consoleEnabled); }; + $scope.initDashboard = function(dashboardData, viewScope) { + $controller('DashboardCtrl', { $scope: viewScope }).init(dashboardData); + }; + $rootScope.onAppEvent = function(name, callback) { var unbind = $rootScope.$on(name, callback); this.$on('$destroy', unbind); diff --git a/src/app/controllers/graphiteImport.js b/src/app/controllers/graphiteImport.js index d60c8ada3be..a552cd73560 100644 --- a/src/app/controllers/graphiteImport.js +++ b/src/app/controllers/graphiteImport.js @@ -1,14 +1,15 @@ define([ 'angular', 'app', - 'lodash' + 'lodash', + 'kbn' ], -function (angular, app, _) { +function (angular, app, _, kbn) { 'use strict'; var module = angular.module('grafana.controllers'); - module.controller('GraphiteImportCtrl', function($scope, $rootScope, $timeout, datasourceSrv) { + module.controller('GraphiteImportCtrl', function($scope, $rootScope, $timeout, datasourceSrv, $location) { $scope.init = function() { $scope.datasources = datasourceSrv.getMetricSources(); @@ -79,7 +80,7 @@ function (angular, app, _) { } panel = { - type: 'graphite', + type: 'graph', span: 12 / graphsPerRow, title: graph[1].title, targets: [], @@ -95,7 +96,9 @@ function (angular, app, _) { currentRow.panels.push(panel); }); - $scope.emitAppEvent('setup-dashboard', newDashboard); + window.grafanaImportDashboard = newDashboard; + $location.path('/dashboard/import/' + kbn.slugifyForUrl(newDashboard.title)); + $scope.dismiss(); } diff --git a/src/app/controllers/row.js b/src/app/controllers/row.js index 621c3eddda5..b877f7d10fb 100644 --- a/src/app/controllers/row.js +++ b/src/app/controllers/row.js @@ -13,6 +13,7 @@ function (angular, app, _) { title: "Row", height: "150px", collapse: false, + editable: true, panels: [], }; diff --git a/src/app/directives/dashUpload.js b/src/app/directives/dashUpload.js index 1d7c4ec405e..ba214cf19a4 100644 --- a/src/app/directives/dashUpload.js +++ b/src/app/directives/dashUpload.js @@ -1,12 +1,13 @@ define([ - 'angular' + 'angular', + 'kbn' ], -function (angular) { +function (angular, kbn) { 'use strict'; var module = angular.module('grafana.directives'); - module.directive('dashUpload', function(timer, alertSrv) { + module.directive('dashUpload', function(timer, alertSrv, $location) { return { restrict: 'A', link: function(scope) { @@ -14,9 +15,10 @@ function (angular) { var files = evt.target.files; // FileList object var readerOnload = function() { return function(e) { - var dashboard = JSON.parse(e.target.result); scope.$apply(function() { - scope.emitAppEvent('setup-dashboard', dashboard); + window.grafanaImportDashboard = JSON.parse(e.target.result); + var title = kbn.slugifyForUrl(window.grafanaImportDashboard.title); + $location.path('/dashboard/import/' + title); }); }; }; diff --git a/src/app/partials/dashboard.html b/src/app/partials/dashboard.html index 8afe5d40824..2fa9bbcf2eb 100644 --- a/src/app/partials/dashboard.html +++ b/src/app/partials/dashboard.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/app/partials/import.html b/src/app/partials/import.html index f81468465d4..e89aff41342 100644 --- a/src/app/partials/import.html +++ b/src/app/partials/import.html @@ -16,11 +16,15 @@
-
- +
+
- + +
- {{dash.name}}{{dash.name}} + + import + +
diff --git a/src/app/routes/dashboard-from-db.js b/src/app/routes/dashboard-from-db.js index a5a37ece12d..67c25ab4946 100644 --- a/src/app/routes/dashboard-from-db.js +++ b/src/app/routes/dashboard-from-db.js @@ -22,7 +22,13 @@ function (angular) { templateUrl: 'app/partials/dashboard.html', controller : 'DashFromDBProvider', reloadOnSearch: false, + }) + .when('/dashboard/import/:id', { + templateUrl: 'app/partials/dashboard.html', + controller : 'DashFromImportCtrl', + reloadOnSearch: false, }); + }); module.controller('DashFromDBProvider', function($scope, $rootScope, datasourceSrv, $routeParams, alertSrv) { @@ -31,12 +37,23 @@ function (angular) { var isTemp = window.location.href.indexOf('dashboard/temp') !== -1; db.getDashboard($routeParams.id, isTemp) - .then(function(dashboard) { - $scope.emitAppEvent('setup-dashboard', dashboard); - }).then(null, function(error) { - $scope.emitAppEvent('setup-dashboard', { title: 'Grafana'}); - alertSrv.set('Error', error, 'error'); - }); + .then(function(dashboard) { + $scope.initDashboard(dashboard, $scope); + }).then(null, function(error) { + $scope.initDashboard({ title: 'Grafana'}, $scope); + alertSrv.set('Error', error, 'error'); + }); + }); + + module.controller('DashFromImportCtrl', function($scope, $location, alertSrv) { + + if (!window.grafanaImportDashboard) { + alertSrv.set('Not found', 'Cannot reload page with unsaved imported dashboard', 'warning', 7000); + $location.path(''); + return; + } + + $scope.initDashboard(window.grafanaImportDashboard, $scope); }); }); diff --git a/src/app/routes/dashboard-from-file.js b/src/app/routes/dashboard-from-file.js index dc54eaddaf6..82db05480b4 100644 --- a/src/app/routes/dashboard-from-file.js +++ b/src/app/routes/dashboard-from-file.js @@ -52,7 +52,7 @@ function (angular, $, config, _) { }; file_load($routeParams.jsonFile).then(function(result) { - $scope.emitAppEvent('setup-dashboard', result); + $scope.initDashboard(result, $scope); }); }); diff --git a/src/app/routes/dashboard-from-script.js b/src/app/routes/dashboard-from-script.js index cacdf9939b6..fa3abd36e81 100644 --- a/src/app/routes/dashboard-from-script.js +++ b/src/app/routes/dashboard-from-script.js @@ -53,7 +53,7 @@ function (angular, $, config, _, kbn, moment) { }; script_load($routeParams.jsFile).then(function(result) { - $scope.emitAppEvent('setup-dashboard', result.data); + $scope.initDashboard(result.data, $scope); }); }); From 34f36fff5c296e9f22a697f213bf7ca926288f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 24 Sep 2014 11:17:34 +0200 Subject: [PATCH 5/6] small fix for graphite-web import --- src/app/controllers/graphiteImport.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/controllers/graphiteImport.js b/src/app/controllers/graphiteImport.js index a552cd73560..091f4b8fe5f 100644 --- a/src/app/controllers/graphiteImport.js +++ b/src/app/controllers/graphiteImport.js @@ -73,7 +73,7 @@ function (angular, app, _, kbn) { newDashboard.title = state.name; newDashboard.rows.push(currentRow); - _.each(state.graphs, function(graph) { + _.each(state.graphs, function(graph, index) { if (currentRow.panels.length === graphsPerRow) { currentRow = angular.copy(rowTemplate); newDashboard.rows.push(currentRow); @@ -84,7 +84,8 @@ function (angular, app, _, kbn) { span: 12 / graphsPerRow, title: graph[1].title, targets: [], - datasource: datasource + datasource: datasource, + id: index + 1 }; _.each(graph[1].target, function(target) { From bce6e75cfaf336767b778a3d7a46912c5f35734b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 24 Sep 2014 11:35:08 +0200 Subject: [PATCH 6/6] InfluxDB: Fix for bug when saving dashboard where title is the same as slugified url id, Fixes #859 --- CHANGELOG.md | 1 + src/app/services/influxdb/influxdbDatasource.js | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dce1108a1c7..92bdd66eca0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - [Issue #851](https://github.com/grafana/grafana/issues/851). Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations - [Issue #846](https://github.com/grafana/grafana/issues/846). Edit panes: Issue when open row or json editor when scrolled down the page, unable to scroll and you did not see editor - [Issue #840](https://github.com/grafana/grafana/issues/840). Import: Fixes to import from json file and import from graphite. Issues was lingering state from previous dashboard. +- [Issue #859](https://github.com/grafana/grafana/issues/859). InfluxDB: Fix for bug when saving dashboard where title is the same as slugified url id # 1.8.0 (2014-09-22) diff --git a/src/app/services/influxdb/influxdbDatasource.js b/src/app/services/influxdb/influxdbDatasource.js index c076fb2c5e1..8ad003cc632 100644 --- a/src/app/services/influxdb/influxdbDatasource.js +++ b/src/app/services/influxdb/influxdbDatasource.js @@ -203,7 +203,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) { else { var self = this; return this._influxRequest('POST', '/series', data).then(function() { - self._removeUnslugifiedDashboard(title, false); + self._removeUnslugifiedDashboard(id, title, false); return { title: title, url: '/dashboard/db/' + id }; }, function(err) { throw 'Failed to save dashboard to InfluxDB: ' + err.data; @@ -211,7 +211,9 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) { } }; - InfluxDatasource.prototype._removeUnslugifiedDashboard = function(id, isTemp) { + InfluxDatasource.prototype._removeUnslugifiedDashboard = function(id, title, isTemp) { + if (id === title) { return; } + var self = this; self._getDashboardInternal(id, isTemp).then(function(dashboard) { if (dashboard !== null) {