2014-04-25 15:23:17 +02:00
|
|
|
define([
|
|
|
|
|
'angular',
|
2014-08-07 14:35:19 +02:00
|
|
|
'lodash',
|
2014-04-25 15:23:17 +02:00
|
|
|
],
|
2015-04-28 13:45:59 +02:00
|
|
|
function(angular, _) {
|
2014-04-25 15:23:17 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
2014-07-28 18:11:52 +02:00
|
|
|
var module = angular.module('grafana.services');
|
2014-04-25 15:23:17 +02:00
|
|
|
|
2015-07-16 10:44:55 +02:00
|
|
|
module.service('unsavedChangesSrv', function($rootScope, $q, $location, $timeout, contextSrv, $window) {
|
2014-06-08 14:40:44 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
function Tracker(dashboard, scope) {
|
|
|
|
|
var self = this;
|
2014-04-25 15:23:17 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
this.original = dashboard.getSaveModelClone();
|
|
|
|
|
this.current = dashboard;
|
|
|
|
|
this.originalPath = $location.path();
|
|
|
|
|
this.scope = scope;
|
2015-04-06 11:22:35 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
// register events
|
|
|
|
|
scope.onAppEvent('dashboard-saved', function() {
|
|
|
|
|
self.original = self.current.getSaveModelClone();
|
|
|
|
|
self.originalPath = $location.path();
|
|
|
|
|
});
|
2015-04-06 11:22:35 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
$window.onbeforeunload = function() {
|
|
|
|
|
if (self.ignoreChanges()) { return; }
|
|
|
|
|
if (self.hasChanges()) {
|
|
|
|
|
return "There are unsaved changes to this dashboard";
|
|
|
|
|
}
|
|
|
|
|
};
|
2014-04-27 12:27:06 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
scope.$on("$locationChangeStart", function(event, next) {
|
2015-04-02 08:08:22 +02:00
|
|
|
// check if we should look for changes
|
|
|
|
|
if (self.originalPath === $location.path()) { return true; }
|
2015-04-06 11:22:35 +02:00
|
|
|
if (self.ignoreChanges()) { return true; }
|
2014-08-13 17:20:54 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
if (self.hasChanges()) {
|
2014-04-27 12:22:38 +02:00
|
|
|
event.preventDefault();
|
|
|
|
|
self.next = next;
|
2014-06-12 16:35:44 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
$timeout(function() {
|
|
|
|
|
self.open_modal();
|
|
|
|
|
});
|
2014-04-27 12:22:38 +02:00
|
|
|
}
|
|
|
|
|
});
|
2015-04-28 13:45:59 +02:00
|
|
|
}
|
2014-04-25 15:23:17 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
var p = Tracker.prototype;
|
2014-04-25 15:23:17 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
// for some dashboards and users
|
|
|
|
|
// changes should be ignored
|
|
|
|
|
p.ignoreChanges = function() {
|
2015-05-06 07:59:47 +02:00
|
|
|
if (!this.original) { return true; }
|
2015-04-28 13:45:59 +02:00
|
|
|
if (!contextSrv.isEditor) { return true; }
|
|
|
|
|
if (!this.current || !this.current.meta) { return true; }
|
|
|
|
|
|
|
|
|
|
var meta = this.current.meta;
|
|
|
|
|
return !meta.canSave || meta.fromScript || meta.fromFile;
|
2014-04-25 15:23:17 +02:00
|
|
|
};
|
|
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
// remove stuff that should not count in diff
|
|
|
|
|
p.cleanDashboardFromIgnoredChanges = function(dash) {
|
2015-04-28 16:42:40 +02:00
|
|
|
// ignore time and refresh
|
|
|
|
|
dash.time = 0;
|
|
|
|
|
dash.refresh = 0;
|
2015-04-28 17:28:34 +02:00
|
|
|
dash.schemaVersion = 0;
|
2015-04-28 16:42:40 +02:00
|
|
|
|
|
|
|
|
// filter row and panels properties that should be ignored
|
2015-04-28 12:02:39 +02:00
|
|
|
dash.rows = _.filter(dash.rows, function(row) {
|
|
|
|
|
if (row.repeatRowId) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
row.panels = _.filter(row.panels, function(panel) {
|
|
|
|
|
if (panel.repeatPanelId) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-04-28 16:42:40 +02:00
|
|
|
|
2015-04-28 12:02:39 +02:00
|
|
|
// remove scopedVars
|
|
|
|
|
panel.scopedVars = null;
|
2015-04-28 16:42:40 +02:00
|
|
|
|
2015-07-18 10:14:21 +02:00
|
|
|
// ignore span changes
|
|
|
|
|
panel.span = null;
|
|
|
|
|
|
2015-04-28 16:42:40 +02:00
|
|
|
// ignore panel legend sort
|
|
|
|
|
if (panel.legend) {
|
|
|
|
|
delete panel.legend.sort;
|
|
|
|
|
delete panel.legend.sortDesc;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-28 12:02:39 +02:00
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
2015-04-28 16:42:40 +02:00
|
|
|
// ignore collapse state
|
|
|
|
|
row.collapse = false;
|
2015-04-28 12:02:39 +02:00
|
|
|
return true;
|
|
|
|
|
});
|
2014-04-27 12:22:38 +02:00
|
|
|
|
2014-09-09 11:40:37 +02:00
|
|
|
// ignore template variable values
|
2015-04-28 16:42:40 +02:00
|
|
|
_.each(dash.templating.list, function(value) {
|
2014-09-09 11:40:37 +02:00
|
|
|
value.current = null;
|
|
|
|
|
value.options = null;
|
|
|
|
|
});
|
2015-04-28 16:42:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
p.hasChanges = function() {
|
|
|
|
|
var current = this.current.getSaveModelClone();
|
|
|
|
|
var original = this.original;
|
|
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
this.cleanDashboardFromIgnoredChanges(current);
|
|
|
|
|
this.cleanDashboardFromIgnoredChanges(original);
|
2015-04-28 12:02:39 +02:00
|
|
|
|
2016-09-13 22:10:44 +02:00
|
|
|
var currentTimepicker = _.find(current.nav, { type: 'timepicker' });
|
|
|
|
|
var originalTimepicker = _.find(original.nav, { type: 'timepicker' });
|
2014-04-27 12:22:38 +02:00
|
|
|
|
|
|
|
|
if (currentTimepicker && originalTimepicker) {
|
|
|
|
|
currentTimepicker.now = originalTimepicker.now;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-25 15:23:17 +02:00
|
|
|
var currentJson = angular.toJson(current);
|
2014-04-27 12:22:38 +02:00
|
|
|
var originalJson = angular.toJson(original);
|
2014-04-25 15:23:17 +02:00
|
|
|
|
2015-11-24 07:29:52 +01:00
|
|
|
return currentJson !== originalJson;
|
2014-04-25 15:23:17 +02:00
|
|
|
};
|
|
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
p.open_modal = function() {
|
|
|
|
|
var tracker = this;
|
2014-04-25 16:50:35 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
var modalScope = this.scope.$new();
|
|
|
|
|
modalScope.ignore = function() {
|
|
|
|
|
tracker.original = null;
|
|
|
|
|
tracker.goto_next();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
modalScope.save = function() {
|
|
|
|
|
tracker.scope.$emit('save-dashboard');
|
|
|
|
|
};
|
2014-04-27 12:22:38 +02:00
|
|
|
|
2015-07-16 10:44:55 +02:00
|
|
|
$rootScope.appEvent('show-modal', {
|
2016-02-01 18:19:02 +01:00
|
|
|
src: 'public/app/partials/unsaved-changes.html',
|
2016-03-04 20:56:53 +01:00
|
|
|
modalClass: 'confirm-modal',
|
2015-04-28 13:45:59 +02:00
|
|
|
scope: modalScope,
|
|
|
|
|
});
|
|
|
|
|
};
|
2014-04-25 16:50:35 +02:00
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
p.goto_next = function() {
|
|
|
|
|
var baseLen = $location.absUrl().length - $location.url().length;
|
|
|
|
|
var nextUrl = this.next.substring(baseLen);
|
|
|
|
|
$location.url(nextUrl);
|
2014-04-25 15:23:17 +02:00
|
|
|
};
|
|
|
|
|
|
2015-04-28 13:45:59 +02:00
|
|
|
this.Tracker = Tracker;
|
|
|
|
|
this.init = function(dashboard, scope) {
|
|
|
|
|
// wait for different services to patch the dashboard (missing properties)
|
|
|
|
|
$timeout(function() { new Tracker(dashboard, scope); }, 1200);
|
|
|
|
|
};
|
2014-04-25 15:23:17 +02:00
|
|
|
});
|
2014-05-19 15:31:30 +02:00
|
|
|
});
|