瀏覽代碼

More work on unsaved changes warning (Issue #324)

Torkel Ödegaard 11 年之前
父節點
當前提交
bdd2c9d033

+ 1 - 0
src/app/components/settings.js

@@ -25,6 +25,7 @@ function (_, crypto) {
       grafana_index                 : 'grafana-dash',
       grafana_index                 : 'grafana-dash',
       elasticsearch_all_disabled    : false,
       elasticsearch_all_disabled    : false,
       timezoneOffset                : null,
       timezoneOffset                : null,
+      unsaved_changes_warning       : true
     };
     };
 
 
     // This initializes a new hash on purpose, to avoid adding parameters to
     // This initializes a new hash on purpose, to avoid adding parameters to

+ 1 - 1
src/app/controllers/dash.js

@@ -31,7 +31,7 @@ function (angular, $, config, _) {
 
 
   module.controller('DashCtrl', function(
   module.controller('DashCtrl', function(
     $scope, $rootScope, ejsResource, dashboard,
     $scope, $rootScope, ejsResource, dashboard,
-    alertSrv, panelMove, keyboardManager, grafanaVersion, unsavedChangesSrv) {
+    alertSrv, panelMove, keyboardManager, grafanaVersion) {
 
 
     $scope.requiredElasticSearchVersion = ">=0.90.3";
     $scope.requiredElasticSearchVersion = ">=0.90.3";
 
 

+ 12 - 15
src/app/controllers/dashLoader.js

@@ -65,23 +65,20 @@ function (angular, _, moment) {
     };
     };
 
 
     $scope.elasticsearch_save = function(type,ttl) {
     $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) {
     $scope.elasticsearch_delete = function(id) {

+ 3 - 3
src/app/partials/unsaved-changes.html

@@ -5,9 +5,9 @@
   <h3 class="text-center"><i class="icon-warning-sign"></i> Unsaved changes</h3>
   <h3 class="text-center"><i class="icon-warning-sign"></i> Unsaved changes</h3>
   <div class="row-fluid">
   <div class="row-fluid">
 	<span class="span3"></span>
 	<span class="span3"></span>
-	<button type="button" class="btn btn-info span2" ng-click="dismiss()">Cancel</button>
-	<button type="button" class="btn btn-success span2" ng-click="save()">Save Changes</button>
-	<button type="button" class="btn btn-warning span2" ng-click="ignore();dismiss();">Ignore changes</button>
+	<button type="button" class="btn btn-success span2" ng-click="dismiss()">Cancel</button>
+	<button type="button" class="btn btn-success span2" ng-click="save();dismiss();">Save</button>
+	<button type="button" class="btn btn-warning span2" ng-click="ignore();dismiss();">Ignore</button>
 	<span class="span3"></span>
 	<span class="span3"></span>
   </div>
   </div>
 
 

+ 7 - 11
src/app/services/dashboard.js

@@ -63,6 +63,7 @@ function (angular, $, kbn, _, config, moment, Modernizr) {
     $rootScope.$on('$routeChangeSuccess',function(){
     $rootScope.$on('$routeChangeSuccess',function(){
       // Clear the current dashboard to prevent reloading
       // Clear the current dashboard to prevent reloading
       self.current = {};
       self.current = {};
+      self.original = null;
       self.indices = [];
       self.indices = [];
       route();
       route();
     });
     });
@@ -156,18 +157,9 @@ function (angular, $, kbn, _, config, moment, Modernizr) {
 
 
       // Set the current dashboard
       // Set the current dashboard
       self.current = angular.copy(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) {
       if(dashboard.refresh) {
         self.set_interval(dashboard.refresh);
         self.set_interval(dashboard.refresh);
@@ -182,6 +174,10 @@ function (angular, $, kbn, _, config, moment, Modernizr) {
 
 
       $rootScope.$emit('dashboard-loaded');
       $rootScope.$emit('dashboard-loaded');
 
 
+      $timeout(function() {
+        self.original = angular.copy(self.current);
+      }, 500);
+
       return true;
       return true;
     };
     };
 
 

+ 48 - 17
src/app/services/unsavedChangesSrv.js

@@ -1,26 +1,32 @@
 define([
 define([
   'angular',
   'angular',
-  'underscore'
+  'underscore',
+  'config',
 ],
 ],
-function (angular, _) {
+function (angular, _, config) {
   'use strict';
   'use strict';
 
 
+  if (!config.unsaved_changes_warning) {
+    return;
+  }
+
   var module = angular.module('kibana.services');
   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 self = this;
-
     var modalScope = $rootScope.$new();
     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({
       var confirmModal = $modal({
           template: './app/partials/unsaved-changes.html',
           template: './app/partials/unsaved-changes.html',
           persist: true,
           persist: true,
@@ -34,32 +40,57 @@ function (angular, _) {
       });
       });
     };
     };
 
 
-    this.has_unsaved_changes = function() {
+    this.has_unsaved_changes = function () {
       if (!dashboard.original) {
       if (!dashboard.original) {
         return false;
         return false;
       }
       }
 
 
       var current = angular.copy(dashboard.current);
       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 currentJson = angular.toJson(current);
-      var originalJson = angular.toJson(dashboard.original);
+      var originalJson = angular.toJson(original);
 
 
       if (currentJson !== originalJson) {
       if (currentJson !== originalJson) {
-        return true; //confirm('There are unsaved changes, are you sure you want to change dashboard?');
+        return true;
       }
       }
 
 
       return false;
       return false;
     };
     };
 
 
-    modalScope.ignore = function() {
-      dashboard.original = null;
+    this.goto_next = function () {
       var baseLen = $location.absUrl().length - $location.url().length;
       var baseLen = $location.absUrl().length - $location.url().length;
       var nextUrl = self.next.substring(baseLen);
       var nextUrl = self.next.substring(baseLen);
       $location.url(nextUrl);
       $location.url(nextUrl);
     };
     };
 
 
+    modalScope.ignore = function() {
+      dashboard.original = null;
+      self.goto_next();
+    };
+
     modalScope.save = function() {
     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();
   });
   });
 });
 });

+ 9 - 0
src/config.sample.js

@@ -48,8 +48,17 @@ function (Settings) {
 
 
     timezoneOffset: null,
     timezoneOffset: null,
 
 
+    /**
+     * Elasticsearch index for storing dashboards
+     *
+     */
     grafana_index: "grafana-dash",
     grafana_index: "grafana-dash",
 
 
+    /**
+     * set to false to disable unsaved changes warning
+     */
+    unsaved_changes_warning: true,
+
     panel_names: [
     panel_names: [
       'text',
       'text',
       'graphite'
       'graphite'