diff --git a/public/app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer.test.tsx b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer.test.tsx index a978f97da2a..ee9bb67e9df 100644 --- a/public/app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer.test.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer.test.tsx @@ -22,12 +22,6 @@ jest.mock('@grafana/runtime', () => ({ }), })); -jest.mock('app/core/services/backend_srv', () => ({ - backendSrv: { - getDashboardByUid: jest.fn().mockResolvedValue({ dashboard: {} }), - }, -})); - const store = configureStore(); const mockPost = jest.fn(); const buildMocks = () => ({ @@ -76,7 +70,7 @@ describe('SaveDashboardDrawer', () => { expect(screen.getByRole('button', { name: /overwrite/i })).toBeInTheDocument(); }); - it('should render corresponding save modal once the errror is handled', async () => { + it('should render corresponding save modal once the error is handled', async () => { const { onDismiss, dashboard, error } = buildMocks(); mockPost.mockRejectedValueOnce(error); diff --git a/public/app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer.tsx b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer.tsx index 56abc04a20d..bc5f917d101 100644 --- a/public/app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer.tsx +++ b/public/app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer.tsx @@ -1,9 +1,7 @@ import React, { useMemo, useState } from 'react'; -import { useAsync } from 'react-use'; import { config, isFetchError } from '@grafana/runtime'; import { Drawer, Tab, TabsBar } from '@grafana/ui'; -import { backendSrv } from 'app/core/services/backend_srv'; import { jsonDiff } from '../VersionHistory/utils'; @@ -18,33 +16,24 @@ import { useDashboardSave } from './useDashboardSave'; export const SaveDashboardDrawer = ({ dashboard, onDismiss, onSaveSuccess, isCopy }: SaveDashboardModalProps) => { const [options, setOptions] = useState({}); - + const previous = dashboard.getOriginalDashboard(); const isProvisioned = dashboard.meta.provisioned; const isNew = dashboard.version === 0; - const previous = useAsync(async () => { - if (isNew) { - return undefined; - } - - const result = await backendSrv.getDashboardByUid(dashboard.uid); - return result.dashboard; - }, [dashboard, isNew]); - const data = useMemo(() => { const clone = dashboard.getSaveModelClone({ saveTimerange: Boolean(options.saveTimerange), saveVariables: Boolean(options.saveVariables), }); - if (!previous.value) { + if (!previous) { return { clone, diff: {}, diffCount: 0, hasChanges: false }; } const cloneJSON = JSON.stringify(clone, null, 2); const cloneSafe = JSON.parse(cloneJSON); // avoids undefined issues - const diff = jsonDiff(previous.value, cloneSafe); + const diff = jsonDiff(previous, cloneSafe); let diffCount = 0; for (const d of Object.values(diff)) { diffCount += d.length; @@ -56,7 +45,7 @@ export const SaveDashboardDrawer = ({ dashboard, onDismiss, onSaveSuccess, isCop diffCount, hasChanges: diffCount > 0 && !isNew, }; - }, [dashboard, previous.value, options, isNew]); + }, [dashboard, previous, options, isNew]); const [showDiff, setShowDiff] = useState(false); const { state, onDashboardSave } = useDashboardSave(dashboard, isCopy); @@ -69,7 +58,7 @@ export const SaveDashboardDrawer = ({ dashboard, onDismiss, onSaveSuccess, isCop const renderSaveBody = () => { if (showDiff) { - return ; + return ; } if (isNew || isCopy) { diff --git a/public/app/features/dashboard/containers/PublicDashboardPage.test.tsx b/public/app/features/dashboard/containers/PublicDashboardPage.test.tsx index 7fe40b8230d..e9076a91655 100644 --- a/public/app/features/dashboard/containers/PublicDashboardPage.test.tsx +++ b/public/app/features/dashboard/containers/PublicDashboardPage.test.tsx @@ -124,6 +124,13 @@ const getTestDashboard = (overrides?: Partial, metaOverrides?: Partia return new DashboardModel(data, metaOverrides); }; +const dashboardBase = { + getModel: getTestDashboard, + initError: null, + initPhase: DashboardInitPhase.Completed, + permissions: [], +}; + describe('PublicDashboardPage', () => { beforeEach(() => { config.featureToggles.publicDashboards = true; @@ -144,12 +151,7 @@ describe('PublicDashboardPage', () => { describe('Given a simple public dashboard', () => { const newState = { - dashboard: { - getModel: getTestDashboard, - initError: null, - initPhase: DashboardInitPhase.Completed, - permissions: [], - }, + dashboard: dashboardBase, }; it('Should render panels', async () => { @@ -220,10 +222,8 @@ describe('PublicDashboardPage', () => { const newState = { dashboard: { + ...dashboardBase, getModel: () => getTestDashboard({ panels }), - initError: null, - initPhase: DashboardInitPhase.Completed, - permissions: [], }, }; setup(undefined, newState); @@ -247,13 +247,11 @@ describe('PublicDashboardPage', () => { it('Should render time range and refresh picker buttons', async () => { setup(undefined, { dashboard: { + ...dashboardBase, getModel: () => getTestDashboard({ timepicker: { hidden: false, collapse: false, refresh_intervals: [], time_options: [] }, }), - initError: null, - initPhase: DashboardInitPhase.Completed, - permissions: [], }, }); expect(await screen.findByTestId(selectors.TimePicker.openButton)).toBeInTheDocument(); @@ -266,10 +264,8 @@ describe('PublicDashboardPage', () => { it('Should render public dashboard paused screen', async () => { setup(undefined, { dashboard: { + ...dashboardBase, getModel: () => getTestDashboard(undefined, { publicDashboardEnabled: false, dashboardNotFound: false }), - initError: null, - initPhase: DashboardInitPhase.Completed, - permissions: [], }, }); @@ -285,10 +281,8 @@ describe('PublicDashboardPage', () => { it('Should render public dashboard deleted screen', async () => { setup(undefined, { dashboard: { + ...dashboardBase, getModel: () => getTestDashboard(undefined, { dashboardNotFound: true }), - initError: null, - initPhase: DashboardInitPhase.Completed, - permissions: [], }, }); diff --git a/public/app/features/dashboard/state/DashboardModel.ts b/public/app/features/dashboard/state/DashboardModel.ts index 404197eabd9..c0456568f05 100644 --- a/public/app/features/dashboard/state/DashboardModel.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -104,6 +104,7 @@ export class DashboardModel implements TimeModel { private appEventsSubscription: Subscription; private lastRefresh: number; private timeRangeUpdatedDuringEdit = false; + private originalDashboard: Dashboard | null = null; // ------------------ // not persisted @@ -130,6 +131,7 @@ export class DashboardModel implements TimeModel { panelsAffectedByVariableChange: true, lastRefresh: true, timeRangeUpdatedDuringEdit: true, + originalDashboard: true, }; constructor( @@ -169,6 +171,7 @@ 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; this.ensurePanelsHaveUniqueIds(); this.formatDate = this.formatDate.bind(this); @@ -1296,6 +1299,10 @@ export class DashboardModel implements TimeModel { this.templateVariableValueUpdated(); this.startRefresh(event.payload); } + + getOriginalDashboard() { + return this.originalDashboard; + } } function isPanelWithLegend(panel: PanelModel): panel is PanelModel & Pick, 'legend'> {