From eb70d23e44adfad966bdf55e5fc61d347db3a3a4 Mon Sep 17 00:00:00 2001 From: Ivan Ortega Alba Date: Fri, 11 Apr 2025 16:03:24 +0200 Subject: [PATCH] Dashboards: Create dashboard with the correct apiVersion (#103839) --- .../DashboardScenePageStateManager.test.ts | 70 ++++++++++++++++++- .../pages/DashboardScenePageStateManager.ts | 13 +++- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts index 40f058b6d0e..ad4e6acb3c6 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts +++ b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts @@ -1,6 +1,6 @@ import { advanceBy } from 'jest-date-mock'; -import { BackendSrv, locationService, setBackendSrv } from '@grafana/runtime'; +import { BackendSrv, config, locationService, setBackendSrv } from '@grafana/runtime'; import { Spec as DashboardV2Spec, defaultSpec as defaultDashboardV2Spec, @@ -26,6 +26,21 @@ import { DASHBOARD_CACHE_TTL, } from './DashboardScenePageStateManager'; +// Mock the config module +jest.mock('@grafana/runtime', () => { + const original = jest.requireActual('@grafana/runtime'); + return { + ...original, + config: { + ...original.config, + featureToggles: { + ...original.config.featureToggles, + dashboardNewLayouts: false, // Default value + }, + }, + }; +}); + jest.mock('app/features/dashboard/api/dashboard_api', () => ({ getDashboardAPI: jest.fn(), })); @@ -776,6 +791,7 @@ describe('DashboardScenePageStateManager v2', () => { describe('UnifiedDashboardScenePageStateManager', () => { afterEach(() => { store.delete(DASHBOARD_FROM_LS_KEY); + config.featureToggles.dashboardNewLayouts = false; }); describe('when fetching/loading a dashboard', () => { @@ -987,6 +1003,58 @@ describe('UnifiedDashboardScenePageStateManager', () => { expect(loader.state.dashboard!.serializer.initialSaveModel).toEqual(customHomeDashboardV1Spec); }); }); + + describe('New dashboards', () => { + it('should use v1 manager for new dashboards when dashboardNewLayouts feature toggle is disabled', async () => { + config.featureToggles.dashboardNewLayouts = false; + + const manager = new UnifiedDashboardScenePageStateManager({}); + manager.setActiveManager('v2'); + expect(manager['activeManager']).toBeInstanceOf(DashboardScenePageStateManagerV2); + + await manager.loadDashboard({ uid: '', route: DashboardRoutes.New }); + + expect(manager['activeManager']).toBeInstanceOf(DashboardScenePageStateManager); + expect(manager.state.dashboard).toBeDefined(); + expect(manager.state.dashboard?.state.title).toBe('New dashboard'); + }); + + it('should use v2 manager for new dashboards when dashboardNewLayouts feature toggle is enabled', async () => { + config.featureToggles.dashboardNewLayouts = true; + + const manager = new UnifiedDashboardScenePageStateManager({}); + manager.setActiveManager('v1'); + expect(manager['activeManager']).toBeInstanceOf(DashboardScenePageStateManager); + + await manager.loadDashboard({ uid: '', route: DashboardRoutes.New }); + + expect(manager['activeManager']).toBeInstanceOf(DashboardScenePageStateManagerV2); + expect(manager.state.dashboard).toBeDefined(); + expect(manager.state.dashboard?.state.title).toBe('New dashboard'); + }); + + it('should maintain manager version for subsequent loads based on feature toggle', async () => { + config.featureToggles.dashboardNewLayouts = false; + const manager1 = new UnifiedDashboardScenePageStateManager({}); + manager1.setActiveManager('v2'); + await manager1.loadDashboard({ uid: '', route: DashboardRoutes.New }); + expect(manager1['activeManager']).toBeInstanceOf(DashboardScenePageStateManager); + + manager1.setActiveManager('v2'); + await manager1.loadDashboard({ uid: '', route: DashboardRoutes.New }); + expect(manager1['activeManager']).toBeInstanceOf(DashboardScenePageStateManager); + + config.featureToggles.dashboardNewLayouts = true; + const manager2 = new UnifiedDashboardScenePageStateManager({}); + manager2.setActiveManager('v1'); + await manager2.loadDashboard({ uid: '', route: DashboardRoutes.New }); + expect(manager2['activeManager']).toBeInstanceOf(DashboardScenePageStateManagerV2); + + manager2.setActiveManager('v1'); + await manager2.loadDashboard({ uid: '', route: DashboardRoutes.New }); + expect(manager2['activeManager']).toBeInstanceOf(DashboardScenePageStateManagerV2); + }); + }); }); const customHomeDashboardV1Spec = { diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts index 33b8661681d..f8c3cc3a1a8 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts +++ b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts @@ -659,7 +659,6 @@ export class UnifiedDashboardScenePageStateManager extends DashboardScenePageSta this.v1Manager = new DashboardScenePageStateManager(initialState); this.v2Manager = new DashboardScenePageStateManagerV2(initialState); - // Start with v2 if newDashboardLayout is enabled, otherwise v1 this.activeManager = this.v1Manager; } @@ -752,8 +751,20 @@ export class UnifiedDashboardScenePageStateManager extends DashboardScenePageSta } public async loadDashboard(options: LoadDashboardOptions): Promise { + if (options.route === DashboardRoutes.New) { + const newDashboardVersion = config.featureToggles.dashboardNewLayouts ? 'v2' : 'v1'; + this.setActiveManager(newDashboardVersion); + } return this.withVersionHandling((manager) => manager.loadDashboard.call(this, options)); } + + public setActiveManager(manager: 'v1' | 'v2') { + if (manager === 'v1') { + this.activeManager = this.v1Manager; + } else { + this.activeManager = this.v2Manager; + } + } } const managers: {