From ae04580e5f16335b5867252a18bc33c3ccbb95f4 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Tue, 18 Jun 2024 16:08:16 +0200 Subject: [PATCH] DashboardScene: Make Grafana usable when custom home dashboard is invalid (#89305) * DashboardScene: Make Grafana usable when custom home dashboard is invalid * Tests * Remove console.error --- .../pages/DashboardScenePage.tsx | 2 + .../DashboardScenePageStateManager.test.ts | 47 +++++++++++----- .../pages/DashboardScenePageStateManager.ts | 55 ++++++++++++++++++- 3 files changed, 87 insertions(+), 17 deletions(-) diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx b/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx index a1b4f0f46f3..0df1d89260b 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx +++ b/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx @@ -19,7 +19,9 @@ export interface Props extends GrafanaRouteComponentProps { const loader = new DashboardScenePageStateManager({}); await loader.loadDashboard({ uid: 'fake-dash', route: DashboardRoutes.Normal }); - expect(loader.state.dashboard).toBeUndefined(); + expect(loader.state.dashboard).toBeDefined(); expect(loader.state.isLoading).toBe(false); - expect(loader.state.loadError).toBe('Error: Dashboard not found'); - }); - - it('should handle home dashboard redirect', async () => { - setBackendSrv({ - get: () => Promise.resolve({ redirectUri: '/d/asd' }), - } as unknown as BackendSrv); - - const loader = new DashboardScenePageStateManager({}); - await loader.loadDashboard({ uid: '', route: DashboardRoutes.Home }); - - expect(loader.state.dashboard).toBeUndefined(); - expect(loader.state.loadError).toBeUndefined(); + expect(loader.state.loadError).toBe('Dashboard not found'); }); it('shoud fetch dashboard from local storage and remove it after if it exists', async () => { @@ -94,6 +82,37 @@ describe('DashboardScenePageStateManager', () => { expect(loader.state.isLoading).toBe(false); }); + describe('Home dashboard', () => { + it('should handle home dashboard redirect', async () => { + setBackendSrv({ + get: () => Promise.resolve({ redirectUri: '/d/asd' }), + } as unknown as BackendSrv); + + const loader = new DashboardScenePageStateManager({}); + await loader.loadDashboard({ uid: '', route: DashboardRoutes.Home }); + + expect(loader.state.dashboard).toBeUndefined(); + expect(loader.state.loadError).toBeUndefined(); + }); + + it('should handle invalid home dashboard request', async () => { + setBackendSrv({ + get: () => + Promise.reject({ + status: 500, + data: { message: 'Failed to load home dashboard' }, + }), + } as unknown as BackendSrv); + + const loader = new DashboardScenePageStateManager({}); + await loader.loadDashboard({ uid: '', route: DashboardRoutes.Home }); + + expect(loader.state.dashboard).toBeDefined(); + expect(loader.state.dashboard?.state.title).toEqual('Failed to load home dashboard'); + expect(loader.state.loadError).toEqual('Failed to load home dashboard'); + }); + }); + describe('New dashboards', () => { it('Should have new empty model with meta.isNew and should not be cached', async () => { const loader = new DashboardScenePageStateManager({}); diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts index 30e7064eb2a..551d4208308 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts +++ b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts @@ -1,10 +1,13 @@ import { locationUtil } from '@grafana/data'; import { config, getBackendSrv, isFetchError, locationService } from '@grafana/runtime'; +import { defaultDashboard } from '@grafana/schema'; import { StateManagerBase } from 'app/core/services/StateManagerBase'; import { default as localStorageStore } from 'app/core/store'; +import { getMessageFromError } from 'app/core/utils/errors'; import { startMeasure, stopMeasure } from 'app/core/utils/metrics'; import { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; +import { DashboardModel } from 'app/features/dashboard/state'; import { emitDashboardViewEvent } from 'app/features/dashboard/state/analyticsProcessor'; import { DASHBOARD_FROM_LS_KEY, @@ -16,7 +19,10 @@ import { DashboardDTO, DashboardRoutes } from 'app/types'; import { PanelEditor } from '../panel-edit/PanelEditor'; import { DashboardScene } from '../scene/DashboardScene'; import { buildNewDashboardSaveModel } from '../serialization/buildNewDashboardSaveModel'; -import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene'; +import { + createDashboardSceneFromDashboardModel, + transformSaveModelToScene, +} from '../serialization/transformSaveModelToScene'; import { restoreDashboardStateFromLocalStorage } from '../utils/dashboardSessionState'; import { updateNavModel } from './utils'; @@ -143,7 +149,6 @@ export class DashboardScenePageStateManager extends StateManagerBase

${msg}

`, + mode: 'html', + }, + title: '', + transparent: true, + type: 'text', + }, + ], + }, + { canSave: false, canEdit: false } + ) + ); +}