mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 16:15:42 -06:00
176 lines
4.7 KiB
JavaScript
176 lines
4.7 KiB
JavaScript
define([
|
|
'angular',
|
|
'lodash',
|
|
],
|
|
function(angular, _) {
|
|
'use strict';
|
|
|
|
var module = angular.module('grafana.services');
|
|
|
|
module.service('unsavedChangesSrv', function($rootScope, $q, $location, $timeout, contextSrv, $window) {
|
|
|
|
function Tracker(dashboard, scope, originalCopyDelay) {
|
|
var self = this;
|
|
|
|
this.current = dashboard;
|
|
this.originalPath = $location.path();
|
|
this.scope = scope;
|
|
|
|
// register events
|
|
scope.onAppEvent('dashboard-saved', function() {
|
|
this.original = this.current.getSaveModelClone();
|
|
this.originalPath = $location.path();
|
|
}.bind(this));
|
|
|
|
$window.onbeforeunload = function() {
|
|
if (self.ignoreChanges()) { return; }
|
|
if (self.hasChanges()) {
|
|
return "There are unsaved changes to this dashboard";
|
|
}
|
|
};
|
|
|
|
scope.$on("$locationChangeStart", function(event, next) {
|
|
// check if we should look for changes
|
|
if (self.originalPath === $location.path()) { return true; }
|
|
if (self.ignoreChanges()) { return true; }
|
|
|
|
if (self.hasChanges()) {
|
|
event.preventDefault();
|
|
self.next = next;
|
|
|
|
$timeout(function() {
|
|
self.open_modal();
|
|
});
|
|
}
|
|
});
|
|
|
|
if (originalCopyDelay) {
|
|
$timeout(function() {
|
|
// wait for different services to patch the dashboard (missing properties)
|
|
self.original = dashboard.getSaveModelClone();
|
|
}, originalCopyDelay);
|
|
} else {
|
|
self.original = dashboard.getSaveModelClone();
|
|
}
|
|
}
|
|
|
|
var p = Tracker.prototype;
|
|
|
|
// for some dashboards and users
|
|
// changes should be ignored
|
|
p.ignoreChanges = function() {
|
|
if (!this.original) { return true; }
|
|
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;
|
|
};
|
|
|
|
// remove stuff that should not count in diff
|
|
p.cleanDashboardFromIgnoredChanges = function(dash) {
|
|
// ignore time and refresh
|
|
dash.time = 0;
|
|
dash.refresh = 0;
|
|
dash.schemaVersion = 0;
|
|
dash.editMode = false;
|
|
|
|
// filter row and panels properties that should be ignored
|
|
dash.rows = _.filter(dash.rows, function(row) {
|
|
if (row.repeatRowId) {
|
|
return false;
|
|
}
|
|
|
|
row.panels = _.filter(row.panels, function(panel) {
|
|
if (panel.repeatPanelId) {
|
|
return false;
|
|
}
|
|
|
|
// remove scopedVars
|
|
panel.scopedVars = null;
|
|
|
|
// ignore span changes
|
|
panel.span = null;
|
|
|
|
// ignore panel legend sort
|
|
if (panel.legend) {
|
|
delete panel.legend.sort;
|
|
delete panel.legend.sortDesc;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
// ignore collapse state
|
|
row.collapse = false;
|
|
return true;
|
|
});
|
|
|
|
// ignore template variable values
|
|
_.each(dash.templating.list, function(value) {
|
|
value.current = null;
|
|
value.options = null;
|
|
value.filters = null;
|
|
});
|
|
};
|
|
|
|
p.hasChanges = function() {
|
|
var current = this.current.getSaveModelClone();
|
|
var original = this.original;
|
|
|
|
this.cleanDashboardFromIgnoredChanges(current);
|
|
this.cleanDashboardFromIgnoredChanges(original);
|
|
|
|
var currentTimepicker = _.find(current.nav, { type: 'timepicker' });
|
|
var originalTimepicker = _.find(original.nav, { type: 'timepicker' });
|
|
|
|
if (currentTimepicker && originalTimepicker) {
|
|
currentTimepicker.now = originalTimepicker.now;
|
|
}
|
|
|
|
var currentJson = angular.toJson(current);
|
|
var originalJson = angular.toJson(original);
|
|
|
|
return currentJson !== originalJson;
|
|
};
|
|
|
|
p.open_modal = function() {
|
|
var tracker = this;
|
|
|
|
var modalScope = this.scope.$new();
|
|
modalScope.ignore = function() {
|
|
tracker.original = null;
|
|
tracker.goto_next();
|
|
};
|
|
|
|
modalScope.save = function() {
|
|
var cancel = $rootScope.$on('dashboard-saved', function() {
|
|
cancel();
|
|
$timeout(function() {
|
|
tracker.goto_next();
|
|
});
|
|
});
|
|
|
|
$rootScope.$emit('save-dashboard');
|
|
};
|
|
|
|
$rootScope.appEvent('show-modal', {
|
|
src: 'public/app/partials/unsaved-changes.html',
|
|
modalClass: 'confirm-modal',
|
|
scope: modalScope,
|
|
});
|
|
};
|
|
|
|
p.goto_next = function() {
|
|
var baseLen = $location.absUrl().length - $location.url().length;
|
|
var nextUrl = this.next.substring(baseLen);
|
|
$location.url(nextUrl);
|
|
};
|
|
|
|
this.Tracker = Tracker;
|
|
this.init = function(dashboard, scope) {
|
|
return new Tracker(dashboard, scope, 1000);
|
|
};
|
|
});
|
|
});
|