diff --git a/src/app/components/settings.js b/src/app/components/settings.js index b7785d5ce4b..734dd34e947 100644 --- a/src/app/components/settings.js +++ b/src/app/components/settings.js @@ -25,6 +25,7 @@ function (_, crypto) { grafana_index : 'grafana-dash', elasticsearch_all_disabled : false, timezoneOffset : null, + unsaved_changes_warning : true }; // This initializes a new hash on purpose, to avoid adding parameters to diff --git a/src/app/controllers/dash.js b/src/app/controllers/dash.js index cda62826aa5..98f5df2983e 100644 --- a/src/app/controllers/dash.js +++ b/src/app/controllers/dash.js @@ -31,7 +31,7 @@ function (angular, $, config, _) { module.controller('DashCtrl', function( $scope, $rootScope, ejsResource, dashboard, - alertSrv, panelMove, keyboardManager, grafanaVersion, unsavedChangesSrv) { + alertSrv, panelMove, keyboardManager, grafanaVersion) { $scope.requiredElasticSearchVersion = ">=0.90.3"; diff --git a/src/app/controllers/dashLoader.js b/src/app/controllers/dashLoader.js index 4cbf5c3aa1b..7f9dc9232dd 100644 --- a/src/app/controllers/dashLoader.js +++ b/src/app/controllers/dashLoader.js @@ -65,23 +65,20 @@ function (angular, _, moment) { }; $scope.elasticsearch_save = function(type,ttl) { - dashboard.elasticsearch_save( - type, - ($scope.elasticsearch.title || dashboard.current.title), - ($scope.loader.save_temp_ttl_enable ? ttl : false) - ).then(function(result) { - if(_.isUndefined(result._id)) { - alertSrv.set('Save failed','Dashboard could not be saved to Elasticsearch','error',5000); - return; - } + dashboard.elasticsearch_save(type, dashboard.current.title, ttl) + .then(function(result) { + if(_.isUndefined(result._id)) { + alertSrv.set('Save failed','Dashboard could not be saved to Elasticsearch','error',5000); + return; + } - alertSrv.set('Dashboard Saved', 'This dashboard has been saved to Elasticsearch as "' + result._id + '"','success', 5000); - if(type === 'temp') { - $scope.share = dashboard.share_link(dashboard.current.title,'temp',result._id); - } + alertSrv.set('Dashboard Saved', 'Dashboard has been saved to Elasticsearch as "' + result._id + '"','success', 5000); + if(type === 'temp') { + $scope.share = dashboard.share_link(dashboard.current.title,'temp',result._id); + } - $rootScope.$emit('dashboard-saved'); - }); + $rootScope.$emit('dashboard-saved'); + }); }; $scope.elasticsearch_delete = function(id) { diff --git a/src/app/partials/unsaved-changes.html b/src/app/partials/unsaved-changes.html index 5ea9082d13f..87220e41e8d 100644 --- a/src/app/partials/unsaved-changes.html +++ b/src/app/partials/unsaved-changes.html @@ -5,9 +5,9 @@

Unsaved changes

- - - + + +
diff --git a/src/app/services/dashboard.js b/src/app/services/dashboard.js index 5b7e4eb88e7..2addf29d0b9 100644 --- a/src/app/services/dashboard.js +++ b/src/app/services/dashboard.js @@ -63,6 +63,7 @@ function (angular, $, kbn, _, config, moment, Modernizr) { $rootScope.$on('$routeChangeSuccess',function(){ // Clear the current dashboard to prevent reloading self.current = {}; + self.original = null; self.indices = []; route(); }); @@ -156,18 +157,9 @@ function (angular, $, kbn, _, config, moment, Modernizr) { // Set the current dashboard self.current = angular.copy(dashboard); - self.original = angular.copy(dashboard); - // Delay this until we're sure that querySrv and filterSrv are ready - $timeout(function() { - // Ok, now that we've setup the current dashboard, we can inject our services - filterSrv = $injector.get('filterSrv'); - filterSrv.init(); - - },0).then(function() { - // Call refresh to calculate the indices and notify the panels that we're ready to roll - self.refresh(); - }); + filterSrv = $injector.get('filterSrv'); + filterSrv.init(); if(dashboard.refresh) { self.set_interval(dashboard.refresh); @@ -182,6 +174,10 @@ function (angular, $, kbn, _, config, moment, Modernizr) { $rootScope.$emit('dashboard-loaded'); + $timeout(function() { + self.original = angular.copy(self.current); + }, 500); + return true; }; diff --git a/src/app/services/unsavedChangesSrv.js b/src/app/services/unsavedChangesSrv.js index 3789b9fa2eb..682d3a4fc4b 100644 --- a/src/app/services/unsavedChangesSrv.js +++ b/src/app/services/unsavedChangesSrv.js @@ -1,26 +1,32 @@ define([ 'angular', - 'underscore' + 'underscore', + 'config', ], -function (angular, _) { +function (angular, _, config) { 'use strict'; + if (!config.unsaved_changes_warning) { + return; + } + var module = angular.module('kibana.services'); - module.service('unsavedChangesSrv', function($rootScope, $modal, dashboard, $q, $location) { + module.service('unsavedChangesSrv', function($rootScope, $modal, dashboard, $q, $location, $timeout) { var self = this; - var modalScope = $rootScope.$new(); - $rootScope.$on("$locationChangeStart", function(event, next, current) { - if (self.has_unsaved_changes()) { - event.preventDefault(); - self.next = next; - self.open_modal(); - } - }); + this.init = function() { + $rootScope.$on("$locationChangeStart", function(event, next) { + if (self.has_unsaved_changes()) { + event.preventDefault(); + self.next = next; + self.open_modal(); + } + }); + }; - this.open_modal = function() { + this.open_modal = function () { var confirmModal = $modal({ template: './app/partials/unsaved-changes.html', persist: true, @@ -34,32 +40,57 @@ function (angular, _) { }); }; - this.has_unsaved_changes = function() { + this.has_unsaved_changes = function () { if (!dashboard.original) { return false; } var current = angular.copy(dashboard.current); + var original = dashboard.original; + + // ignore timespan changes + current.services.filter.time = original.services.filter.time = {}; + current.refresh = original.refresh; + + var currentTimepicker = _.findWhere(current.nav, { type: 'timepicker' }); + var originalTimepicker = _.findWhere(original.nav, { type: 'timepicker' }); + + if (currentTimepicker && originalTimepicker) { + currentTimepicker.now = originalTimepicker.now; + } + var currentJson = angular.toJson(current); - var originalJson = angular.toJson(dashboard.original); + var originalJson = angular.toJson(original); if (currentJson !== originalJson) { - return true; //confirm('There are unsaved changes, are you sure you want to change dashboard?'); + return true; } return false; }; - modalScope.ignore = function() { - dashboard.original = null; + this.goto_next = function () { var baseLen = $location.absUrl().length - $location.url().length; var nextUrl = self.next.substring(baseLen); $location.url(nextUrl); }; - modalScope.save = function() { - + modalScope.ignore = function() { + dashboard.original = null; + self.goto_next(); }; + modalScope.save = function() { + var unregister = $rootScope.$on('dashboard-saved', function() { + self.goto_next(); + }); + + $timeout(unregister, 2000); + + $rootScope.$emit('save-dashboard'); + }; + + }).run(function(unsavedChangesSrv) { + unsavedChangesSrv.init(); }); }); \ No newline at end of file diff --git a/src/config.sample.js b/src/config.sample.js index 3673e97c417..968af7bf4e4 100644 --- a/src/config.sample.js +++ b/src/config.sample.js @@ -48,8 +48,17 @@ function (Settings) { timezoneOffset: null, + /** + * Elasticsearch index for storing dashboards + * + */ grafana_index: "grafana-dash", + /** + * set to false to disable unsaved changes warning + */ + unsaved_changes_warning: true, + panel_names: [ 'text', 'graphite'