mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboards: Move slow dashboard logic to css (#45686)
This commit is contained in:
parent
01df00fd0f
commit
49ac8b9f0a
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { css } from '@emotion/css';
|
import { css, keyframes } from '@emotion/css';
|
||||||
import { Button, HorizontalGroup, Spinner, useStyles, VerticalGroup } from '@grafana/ui';
|
import { Button, HorizontalGroup, Spinner, useStyles, VerticalGroup } from '@grafana/ui';
|
||||||
import { locationService } from '@grafana/runtime';
|
import { locationService } from '@grafana/runtime';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
@ -34,12 +34,22 @@ export const DashboardLoading = ({ initPhase }: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getStyles = (theme: GrafanaTheme) => {
|
export const getStyles = (theme: GrafanaTheme) => {
|
||||||
|
// Amount of time we want to pass before we start showing loading spinner
|
||||||
|
const slowStartThreshold = '0.5s';
|
||||||
|
|
||||||
|
const invisibleToVisible = keyframes`
|
||||||
|
0% { opacity: 0%; }
|
||||||
|
100% { opacity: 100%; }
|
||||||
|
`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dashboardLoading: css`
|
dashboardLoading: css`
|
||||||
height: 60vh;
|
height: 60vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
opacity: 0%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
animation: ${invisibleToVisible} 0s step-end ${slowStartThreshold} 1 normal forwards;
|
||||||
`,
|
`,
|
||||||
dashboardLoadingText: css`
|
dashboardLoadingText: css`
|
||||||
font-size: ${theme.typography.size.lg};
|
font-size: ${theme.typography.size.lg};
|
||||||
|
@ -103,7 +103,6 @@ function dashboardPageScenario(description: string, scenarioFn: (ctx: ScenarioCo
|
|||||||
route: { routeName: DashboardRoutes.Normal } as any,
|
route: { routeName: DashboardRoutes.Normal } as any,
|
||||||
}),
|
}),
|
||||||
initPhase: DashboardInitPhase.NotStarted,
|
initPhase: DashboardInitPhase.NotStarted,
|
||||||
isInitSlow: false,
|
|
||||||
initError: null,
|
initError: null,
|
||||||
initDashboard: jest.fn(),
|
initDashboard: jest.fn(),
|
||||||
notifyApp: mockToolkitActionCreator(notifyApp),
|
notifyApp: mockToolkitActionCreator(notifyApp),
|
||||||
@ -169,18 +168,6 @@ describe('DashboardPage', () => {
|
|||||||
urlSlug: 'my-dash',
|
urlSlug: 'my-dash',
|
||||||
urlUid: '11',
|
urlUid: '11',
|
||||||
});
|
});
|
||||||
expect(ctx.container).toBeEmptyDOMElement();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
dashboardPageScenario('Given dashboard slow loading state', (ctx) => {
|
|
||||||
ctx.setup(() => {
|
|
||||||
ctx.mount();
|
|
||||||
ctx.rerender({ isInitSlow: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should show spinner', () => {
|
|
||||||
expect(screen.getByText('Cancel loading dashboard')).toBeInTheDocument();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ type DashboardPageRouteSearchParams = {
|
|||||||
|
|
||||||
export const mapStateToProps = (state: StoreState) => ({
|
export const mapStateToProps = (state: StoreState) => ({
|
||||||
initPhase: state.dashboard.initPhase,
|
initPhase: state.dashboard.initPhase,
|
||||||
isInitSlow: state.dashboard.isInitSlow,
|
|
||||||
initError: state.dashboard.initError,
|
initError: state.dashboard.initError,
|
||||||
dashboard: state.dashboard.getModel(),
|
dashboard: state.dashboard.getModel(),
|
||||||
});
|
});
|
||||||
@ -311,17 +310,13 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { dashboard, isInitSlow, initError, queryParams, theme } = this.props;
|
const { dashboard, initError, queryParams, theme } = this.props;
|
||||||
const { editPanel, viewPanel, updateScrollTop } = this.state;
|
const { editPanel, viewPanel, updateScrollTop } = this.state;
|
||||||
const kioskMode = getKioskMode();
|
const kioskMode = getKioskMode();
|
||||||
const styles = getStyles(theme, kioskMode);
|
const styles = getStyles(theme, kioskMode);
|
||||||
|
|
||||||
if (!dashboard) {
|
if (!dashboard) {
|
||||||
if (isInitSlow) {
|
return <DashboardLoading initPhase={this.props.initPhase} />;
|
||||||
return <DashboardLoading initPhase={this.props.initPhase} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const inspectPanel = this.getInspectPanel();
|
const inspectPanel = this.getInspectPanel();
|
||||||
|
@ -7,13 +7,7 @@ import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
|||||||
import { keybindingSrv } from 'app/core/services/keybindingSrv';
|
import { keybindingSrv } from 'app/core/services/keybindingSrv';
|
||||||
// Actions
|
// Actions
|
||||||
import { notifyApp } from 'app/core/actions';
|
import { notifyApp } from 'app/core/actions';
|
||||||
import {
|
import { dashboardInitCompleted, dashboardInitFailed, dashboardInitFetching, dashboardInitServices } from './reducers';
|
||||||
dashboardInitCompleted,
|
|
||||||
dashboardInitFailed,
|
|
||||||
dashboardInitFetching,
|
|
||||||
dashboardInitServices,
|
|
||||||
dashboardInitSlow,
|
|
||||||
} from './reducers';
|
|
||||||
// Types
|
// Types
|
||||||
import { DashboardDTO, DashboardInitPhase, DashboardRoutes, StoreState, ThunkDispatch, ThunkResult } from 'app/types';
|
import { DashboardDTO, DashboardInitPhase, DashboardRoutes, StoreState, ThunkDispatch, ThunkResult } from 'app/types';
|
||||||
import { DashboardModel } from './DashboardModel';
|
import { DashboardModel } from './DashboardModel';
|
||||||
@ -110,14 +104,6 @@ export function initDashboard(args: InitDashboardArgs): ThunkResult<void> {
|
|||||||
// set fetching state
|
// set fetching state
|
||||||
dispatch(dashboardInitFetching());
|
dispatch(dashboardInitFetching());
|
||||||
|
|
||||||
// Detect slow loading / initializing and set state flag
|
|
||||||
// This is in order to not show loading indication for fast loading dashboards as it creates blinking/flashing
|
|
||||||
setTimeout(() => {
|
|
||||||
if (getState().dashboard.getModel() === null) {
|
|
||||||
dispatch(dashboardInitSlow());
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
// fetch dashboard data
|
// fetch dashboard data
|
||||||
const dashDTO = await fetchDashboard(args, dispatch, getState);
|
const dashDTO = await fetchDashboard(args, dispatch, getState);
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ import {
|
|||||||
dashboardInitCompleted,
|
dashboardInitCompleted,
|
||||||
dashboardInitFailed,
|
dashboardInitFailed,
|
||||||
dashboardInitFetching,
|
dashboardInitFetching,
|
||||||
dashboardInitSlow,
|
|
||||||
loadDashboardPermissions,
|
loadDashboardPermissions,
|
||||||
dashboardReducer,
|
dashboardReducer,
|
||||||
initialState,
|
initialState,
|
||||||
@ -32,7 +31,6 @@ describe('dashboard reducer', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
state = dashboardReducer(initialState, dashboardInitFetching());
|
state = dashboardReducer(initialState, dashboardInitFetching());
|
||||||
state = dashboardReducer(state, dashboardInitSlow());
|
|
||||||
state = dashboardReducer(
|
state = dashboardReducer(
|
||||||
state,
|
state,
|
||||||
dashboardInitCompleted(
|
dashboardInitCompleted(
|
||||||
@ -47,10 +45,6 @@ describe('dashboard reducer', () => {
|
|||||||
it('should set model', async () => {
|
it('should set model', async () => {
|
||||||
expect(state.getModel()!.title).toBe('My dashboard');
|
expect(state.getModel()!.title).toBe('My dashboard');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set reset isInitSlow', async () => {
|
|
||||||
expect(state.isInitSlow).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('dashboardInitFailed', () => {
|
describe('dashboardInitFailed', () => {
|
||||||
@ -65,10 +59,6 @@ describe('dashboard reducer', () => {
|
|||||||
expect(state.getModel()?.title).toBe('Dashboard init failed');
|
expect(state.getModel()?.title).toBe('Dashboard init failed');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set reset isInitSlow', async () => {
|
|
||||||
expect(state.isInitSlow).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set initError', async () => {
|
it('should set initError', async () => {
|
||||||
expect(state.initError?.message).toBe('Oh no');
|
expect(state.initError?.message).toBe('Oh no');
|
||||||
});
|
});
|
||||||
|
@ -8,7 +8,6 @@ import { PanelPlugin } from '@grafana/data';
|
|||||||
|
|
||||||
export const initialState: DashboardState = {
|
export const initialState: DashboardState = {
|
||||||
initPhase: DashboardInitPhase.NotStarted,
|
initPhase: DashboardInitPhase.NotStarted,
|
||||||
isInitSlow: false,
|
|
||||||
getModel: () => null,
|
getModel: () => null,
|
||||||
permissions: [],
|
permissions: [],
|
||||||
initError: null,
|
initError: null,
|
||||||
@ -27,13 +26,9 @@ const dashboardSlice = createSlice({
|
|||||||
dashboardInitServices: (state) => {
|
dashboardInitServices: (state) => {
|
||||||
state.initPhase = DashboardInitPhase.Services;
|
state.initPhase = DashboardInitPhase.Services;
|
||||||
},
|
},
|
||||||
dashboardInitSlow: (state) => {
|
|
||||||
state.isInitSlow = true;
|
|
||||||
},
|
|
||||||
dashboardInitCompleted: (state, action: PayloadAction<DashboardModel>) => {
|
dashboardInitCompleted: (state, action: PayloadAction<DashboardModel>) => {
|
||||||
state.getModel = () => action.payload;
|
state.getModel = () => action.payload;
|
||||||
state.initPhase = DashboardInitPhase.Completed;
|
state.initPhase = DashboardInitPhase.Completed;
|
||||||
state.isInitSlow = false;
|
|
||||||
},
|
},
|
||||||
dashboardInitFailed: (state, action: PayloadAction<DashboardInitError>) => {
|
dashboardInitFailed: (state, action: PayloadAction<DashboardInitError>) => {
|
||||||
state.initPhase = DashboardInitPhase.Failed;
|
state.initPhase = DashboardInitPhase.Failed;
|
||||||
@ -44,7 +39,6 @@ const dashboardSlice = createSlice({
|
|||||||
},
|
},
|
||||||
cleanUpDashboard: (state) => {
|
cleanUpDashboard: (state) => {
|
||||||
state.initPhase = DashboardInitPhase.NotStarted;
|
state.initPhase = DashboardInitPhase.NotStarted;
|
||||||
state.isInitSlow = false;
|
|
||||||
state.initError = null;
|
state.initError = null;
|
||||||
state.getModel = () => null;
|
state.getModel = () => null;
|
||||||
},
|
},
|
||||||
@ -73,7 +67,6 @@ export const {
|
|||||||
loadDashboardPermissions,
|
loadDashboardPermissions,
|
||||||
dashboardInitFetching,
|
dashboardInitFetching,
|
||||||
dashboardInitFailed,
|
dashboardInitFailed,
|
||||||
dashboardInitSlow,
|
|
||||||
dashboardInitCompleted,
|
dashboardInitCompleted,
|
||||||
dashboardInitServices,
|
dashboardInitServices,
|
||||||
cleanUpDashboard,
|
cleanUpDashboard,
|
||||||
|
@ -77,7 +77,6 @@ export interface QueriesToUpdateOnDashboardLoad {
|
|||||||
export interface DashboardState {
|
export interface DashboardState {
|
||||||
getModel: GetMutableDashboardModelFn;
|
getModel: GetMutableDashboardModelFn;
|
||||||
initPhase: DashboardInitPhase;
|
initPhase: DashboardInitPhase;
|
||||||
isInitSlow: boolean;
|
|
||||||
initError: DashboardInitError | null;
|
initError: DashboardInitError | null;
|
||||||
permissions: DashboardAcl[];
|
permissions: DashboardAcl[];
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user