mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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
This commit is contained in:
parent
50dd95c09b
commit
ae04580e5f
@ -19,7 +19,9 @@ export interface Props extends GrafanaRouteComponentProps<DashboardPageRoutePara
|
|||||||
|
|
||||||
export function DashboardScenePage({ match, route, queryParams, history }: Props) {
|
export function DashboardScenePage({ match, route, queryParams, history }: Props) {
|
||||||
const stateManager = getDashboardScenePageStateManager();
|
const stateManager = getDashboardScenePageStateManager();
|
||||||
|
|
||||||
const { dashboard, isLoading, loadError } = stateManager.useState();
|
const { dashboard, isLoading, loadError } = stateManager.useState();
|
||||||
|
|
||||||
// After scene migration is complete and we get rid of old dashboard we should refactor dashboardWatcher so this route reload is not need
|
// After scene migration is complete and we get rid of old dashboard we should refactor dashboardWatcher so this route reload is not need
|
||||||
const routeReloadCounter = (history.location.state as any)?.routeReloadCounter;
|
const routeReloadCounter = (history.location.state as any)?.routeReloadCounter;
|
||||||
|
|
||||||
|
@ -35,21 +35,9 @@ describe('DashboardScenePageStateManager', () => {
|
|||||||
const loader = new DashboardScenePageStateManager({});
|
const loader = new DashboardScenePageStateManager({});
|
||||||
await loader.loadDashboard({ uid: 'fake-dash', route: DashboardRoutes.Normal });
|
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.isLoading).toBe(false);
|
||||||
expect(loader.state.loadError).toBe('Error: Dashboard not found');
|
expect(loader.state.loadError).toBe('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();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shoud fetch dashboard from local storage and remove it after if it exists', async () => {
|
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);
|
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', () => {
|
describe('New dashboards', () => {
|
||||||
it('Should have new empty model with meta.isNew and should not be cached', async () => {
|
it('Should have new empty model with meta.isNew and should not be cached', async () => {
|
||||||
const loader = new DashboardScenePageStateManager({});
|
const loader = new DashboardScenePageStateManager({});
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import { locationUtil } from '@grafana/data';
|
import { locationUtil } from '@grafana/data';
|
||||||
import { config, getBackendSrv, isFetchError, locationService } from '@grafana/runtime';
|
import { config, getBackendSrv, isFetchError, locationService } from '@grafana/runtime';
|
||||||
|
import { defaultDashboard } from '@grafana/schema';
|
||||||
import { StateManagerBase } from 'app/core/services/StateManagerBase';
|
import { StateManagerBase } from 'app/core/services/StateManagerBase';
|
||||||
import { default as localStorageStore } from 'app/core/store';
|
import { default as localStorageStore } from 'app/core/store';
|
||||||
|
import { getMessageFromError } from 'app/core/utils/errors';
|
||||||
import { startMeasure, stopMeasure } from 'app/core/utils/metrics';
|
import { startMeasure, stopMeasure } from 'app/core/utils/metrics';
|
||||||
import { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
|
import { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
|
||||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||||
|
import { DashboardModel } from 'app/features/dashboard/state';
|
||||||
import { emitDashboardViewEvent } from 'app/features/dashboard/state/analyticsProcessor';
|
import { emitDashboardViewEvent } from 'app/features/dashboard/state/analyticsProcessor';
|
||||||
import {
|
import {
|
||||||
DASHBOARD_FROM_LS_KEY,
|
DASHBOARD_FROM_LS_KEY,
|
||||||
@ -16,7 +19,10 @@ import { DashboardDTO, DashboardRoutes } from 'app/types';
|
|||||||
import { PanelEditor } from '../panel-edit/PanelEditor';
|
import { PanelEditor } from '../panel-edit/PanelEditor';
|
||||||
import { DashboardScene } from '../scene/DashboardScene';
|
import { DashboardScene } from '../scene/DashboardScene';
|
||||||
import { buildNewDashboardSaveModel } from '../serialization/buildNewDashboardSaveModel';
|
import { buildNewDashboardSaveModel } from '../serialization/buildNewDashboardSaveModel';
|
||||||
import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene';
|
import {
|
||||||
|
createDashboardSceneFromDashboardModel,
|
||||||
|
transformSaveModelToScene,
|
||||||
|
} from '../serialization/transformSaveModelToScene';
|
||||||
import { restoreDashboardStateFromLocalStorage } from '../utils/dashboardSessionState';
|
import { restoreDashboardStateFromLocalStorage } from '../utils/dashboardSessionState';
|
||||||
|
|
||||||
import { updateNavModel } from './utils';
|
import { updateNavModel } from './utils';
|
||||||
@ -143,7 +149,6 @@ export class DashboardScenePageStateManager extends StateManagerBase<DashboardSc
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(e);
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +201,12 @@ export class DashboardScenePageStateManager extends StateManagerBase<DashboardSc
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.setState({ isLoading: false, loadError: String(err) });
|
const msg = getMessageFromError(err);
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
loadError: msg,
|
||||||
|
dashboard: getErrorScene(msg),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,3 +292,42 @@ export function getDashboardScenePageStateManager(): DashboardScenePageStateMana
|
|||||||
|
|
||||||
return stateManager;
|
return stateManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getErrorScene(msg: string) {
|
||||||
|
return createDashboardSceneFromDashboardModel(
|
||||||
|
new DashboardModel(
|
||||||
|
{
|
||||||
|
...defaultDashboard,
|
||||||
|
title: msg,
|
||||||
|
panels: [
|
||||||
|
{
|
||||||
|
fieldConfig: {
|
||||||
|
defaults: {},
|
||||||
|
overrides: [],
|
||||||
|
},
|
||||||
|
gridPos: {
|
||||||
|
h: 6,
|
||||||
|
w: 12,
|
||||||
|
x: 7,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
id: 1,
|
||||||
|
options: {
|
||||||
|
code: {
|
||||||
|
language: 'plaintext',
|
||||||
|
showLineNumbers: false,
|
||||||
|
showMiniMap: false,
|
||||||
|
},
|
||||||
|
content: `<br/><br/><center><h1>${msg}</h1></center>`,
|
||||||
|
mode: 'html',
|
||||||
|
},
|
||||||
|
title: '',
|
||||||
|
transparent: true,
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ canSave: false, canEdit: false }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user