From e4a82fedbd30b2cf701f2f0e8edf8d2aab565e60 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Wed, 19 Jun 2024 10:38:12 +0200 Subject: [PATCH] [v11.1.x] DashboardScene: Make Grafana usable when custom home dashboard is invalid (#89366) 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 (cherry picked from commit ae04580e5f16335b5867252a18bc33c3ccbb95f4) --- .../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 84ca43a33e3..d4ba5135a91 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx +++ b/public/app/features/dashboard-scene/pages/DashboardScenePage.tsx @@ -18,7 +18,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 () => { @@ -129,6 +117,37 @@ describe('DashboardScenePageStateManager', () => { expect(dash!.state.$timeRange?.state.from).toEqual('now-6h'); }); + 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 08f414d058b..6ebce05e09f 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 } + ) + ); +}