From c6dda2dfc386007818a7034495dd334d351442d0 Mon Sep 17 00:00:00 2001 From: Kristina Demeshchik Date: Tue, 16 Dec 2025 09:33:54 -0500 Subject: [PATCH] Dashboards: exit edit mode after saving changes modal (#115380) Exit edit mode with unsaved changes --- .../scene/DashboardScene.test.tsx | 35 +++++++++++++++++++ .../dashboard-scene/scene/DashboardScene.tsx | 6 +++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx index ebe63e8e43e..b6bd3c2c4ca 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx @@ -30,8 +30,10 @@ import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher'; import { DashboardEventAction } from 'app/features/live/dashboard/types'; import { VariablesChanged } from 'app/features/variables/types'; +import { ShowConfirmModalEvent } from 'app/types/events'; import { buildPanelEditScene } from '../panel-edit/PanelEditor'; +import { SaveDashboardDrawer } from '../saving/SaveDashboardDrawer'; import { createWorker } from '../saving/createDetectChangesWorker'; import { buildGridItemForPanel, transformSaveModelToScene } from '../serialization/transformSaveModelToScene'; import { DecoratedRevisionModel } from '../settings/VersionsEditView'; @@ -39,6 +41,7 @@ import { historySrv } from '../settings/version-history/HistorySrv'; import { getCloneKey } from '../utils/clone'; import { dashboardSceneGraph } from '../utils/dashboardSceneGraph'; import { findVizPanelByKey, getLibraryPanelBehavior, isLibraryPanel } from '../utils/utils'; +import * as utils from '../utils/utils'; import { DashboardControls } from './DashboardControls'; import { DashboardScene, DashboardSceneState } from './DashboardScene'; @@ -162,6 +165,38 @@ describe('DashboardScene', () => { expect(scene.state.meta.version).toEqual(2); }); + it('Should exit edit mode after saving from unsaved changes modal when dashboardNewLayouts is enabled', () => { + const originalFeatureToggle = config.featureToggles.dashboardNewLayouts; + config.featureToggles.dashboardNewLayouts = true; + + const publishSpy = jest.spyOn(appEvents, 'publish'); + const hasActualSaveChangesSpy = jest.spyOn(utils, 'hasActualSaveChanges').mockReturnValue(true); + + scene.setState({ title: 'Updated title' }); + expect(scene.state.isDirty).toBe(true); + scene.exitEditMode({ skipConfirm: false }); + + const modalCall = publishSpy.mock.calls.find((call) => call[0] instanceof ShowConfirmModalEvent); + expect(modalCall).toBeDefined(); + + const modalEvent = modalCall![0] as ShowConfirmModalEvent; + expect(modalEvent.payload.altActionText).toBeDefined(); + + modalEvent.payload.onAltAction?.(); + + expect(scene.state.overlay).toBeDefined(); + + const overlay = scene.state.overlay as SaveDashboardDrawer; + expect(overlay.state.onSaveSuccess).toBeDefined(); + + overlay.state.onSaveSuccess!(); + expect(scene.state.isEditing).toBe(false); + + publishSpy.mockRestore(); + hasActualSaveChangesSpy.mockRestore(); + config.featureToggles.dashboardNewLayouts = originalFeatureToggle; + }); + it('Should start the detect changes worker', () => { expect(worker.onmessage).toBeDefined(); }); diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index 00655036d04..82a20dbcd52 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -335,7 +335,11 @@ export class DashboardScene extends SceneObjectBase impleme yesText: t('dashboard-scene.dashboard-scene.modal.discard', 'Discard'), yesButtonVariant: 'destructive', onAltAction: () => { - this.openSaveDrawer({}); + this.openSaveDrawer({ + onSaveSuccess: () => { + this.exitEditModeConfirmed(false); + }, + }); }, onConfirm: () => { this.exitEditModeConfirmed();