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