Dashboards: It always detect changes when saving an existing dashboard (#76116)

Deep clone originalDashboard to avoid mutations by object reference
This commit is contained in:
Ivan Ortega Alba 2023-10-06 14:32:04 +02:00 committed by GitHub
parent 4d1f8f21bf
commit 1a96f3742f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 5 deletions

View File

@ -1,7 +1,7 @@
import { keys as _keys } from 'lodash';
import { dateTime, TimeRange, VariableHide } from '@grafana/data';
import { defaultVariableModel } from '@grafana/schema';
import { Dashboard, defaultVariableModel } from '@grafana/schema';
import { contextSrv } from 'app/core/services/context_srv';
import { getDashboardModel } from '../../../../test/helpers/getDashboardModel';
@ -52,6 +52,29 @@ describe('DashboardModel', () => {
});
});
describe('when storing original dashboard data', () => {
let originalDashboard: Dashboard = {
editable: true,
graphTooltip: 0,
schemaVersion: 1,
timezone: '',
title: 'original.title',
};
let model: DashboardModel;
beforeEach(() => {
model = new DashboardModel(originalDashboard);
});
it('should be returned from getOriginalDashboard without modifications', () => {
expect(model.getOriginalDashboard()).toEqual(originalDashboard);
});
it('should return a copy of the provided object', () => {
expect(model.getOriginalDashboard()).not.toBe(originalDashboard);
});
});
describe('when getting next panel id', () => {
let model: DashboardModel;

View File

@ -24,6 +24,7 @@ import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERT
import { contextSrv } from 'app/core/services/context_srv';
import { sortedDeepCloneWithoutNulls } from 'app/core/utils/object';
import { isAngularDatasourcePlugin } from 'app/features/plugins/angularDeprecation/utils';
import { deepFreeze } from 'app/features/plugins/extensions/utils';
import { variableAdapters } from 'app/features/variables/adapters';
import { onTimeRangeUpdated } from 'app/features/variables/state/actions';
import { GetVariables, getVariablesByKey } from 'app/features/variables/state/selectors';
@ -172,7 +173,8 @@ export class DashboardModel implements TimeModel {
this.links = data.links ?? [];
this.gnetId = data.gnetId || null;
this.panels = map(data.panels ?? [], (panelData: any) => new PanelModel(panelData));
this.originalDashboard = data;
// Deep clone original dashboard to avoid mutations by object reference
this.originalDashboard = cloneDeep(data);
this.ensurePanelsHaveUniqueIds();
this.formatDate = this.formatDate.bind(this);
@ -1081,7 +1083,7 @@ export class DashboardModel implements TimeModel {
}
resetOriginalTime() {
this.originalTime = cloneDeep(this.time);
this.originalTime = deepFreeze(this.time);
}
hasTimeChanged() {
@ -1267,8 +1269,8 @@ export class DashboardModel implements TimeModel {
return variables.map((variable) => ({
name: variable.name,
type: variable.type,
current: cloneDeep(variable.current),
filters: cloneDeep(variable.filters),
current: deepFreeze(variable.current),
filters: deepFreeze(variable.filters),
}));
}