mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Variables: enables cancel for slow query variables queries (#24430)
* Refactor: initial commit * Tests: updates tests * Tests: updates snapshots * Chore: updates after PR comments * Chore: renamed initVariablesBatch * Tests: adds transactionReducer tests * Chore: updates after PR comments * Refactor: renames cancelAllDataSourceRequests * Refactor: reduces cancellation complexity * Tests: adds tests for cancelAllInFlightRequests * Tests: adds initVariablesTransaction tests * Tests: adds tests for cleanUpVariables and cancelVariables * Always cleanup dashboard on unmount, even if init is in progress. Check if init phase has changed after services init is completed * fixed failing tests and added some more to test new scenario. Co-authored-by: Torkel Ödegaard <torkel@grafana.com> Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
This commit is contained in:
@@ -2,19 +2,15 @@ import React from 'react';
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { DashboardPage, mapStateToProps, Props, State } from './DashboardPage';
|
||||
import { DashboardModel } from '../state';
|
||||
import { cleanUpDashboard } from '../state/reducers';
|
||||
import {
|
||||
mockToolkitActionCreator,
|
||||
mockToolkitActionCreatorWithoutPayload,
|
||||
ToolkitActionCreatorWithoutPayloadMockType,
|
||||
} from 'test/core/redux/mocks';
|
||||
import { mockToolkitActionCreator } from 'test/core/redux/mocks';
|
||||
import { DashboardInitPhase, DashboardRouteInfo } from 'app/types';
|
||||
import { notifyApp, updateLocation } from 'app/core/actions';
|
||||
import { cleanUpDashboardAndVariables } from '../state/actions';
|
||||
|
||||
jest.mock('app/features/dashboard/components/DashboardSettings/SettingsCtrl', () => ({}));
|
||||
|
||||
interface ScenarioContext {
|
||||
cleanUpDashboardMock: ToolkitActionCreatorWithoutPayloadMockType;
|
||||
cleanUpDashboardAndVariablesMock: typeof cleanUpDashboardAndVariables;
|
||||
dashboard?: DashboardModel | null;
|
||||
setDashboardProp: (overrides?: any, metaOverrides?: any) => void;
|
||||
wrapper?: ShallowWrapper<Props, State, DashboardPage>;
|
||||
@@ -47,7 +43,7 @@ function dashboardPageScenario(description: string, scenarioFn: (ctx: ScenarioCo
|
||||
let setupFn: () => void;
|
||||
|
||||
const ctx: ScenarioContext = {
|
||||
cleanUpDashboardMock: mockToolkitActionCreatorWithoutPayload(cleanUpDashboard),
|
||||
cleanUpDashboardAndVariablesMock: jest.fn(),
|
||||
setup: fn => {
|
||||
setupFn = fn;
|
||||
},
|
||||
@@ -67,7 +63,8 @@ function dashboardPageScenario(description: string, scenarioFn: (ctx: ScenarioCo
|
||||
initDashboard: jest.fn(),
|
||||
updateLocation: mockToolkitActionCreator(updateLocation),
|
||||
notifyApp: mockToolkitActionCreator(notifyApp),
|
||||
cleanUpDashboard: ctx.cleanUpDashboardMock,
|
||||
cleanUpDashboardAndVariables: ctx.cleanUpDashboardAndVariablesMock,
|
||||
cancelVariables: jest.fn(),
|
||||
dashboard: null,
|
||||
};
|
||||
|
||||
@@ -233,7 +230,7 @@ describe('DashboardPage', () => {
|
||||
});
|
||||
|
||||
it('Should call clean up action', () => {
|
||||
expect(ctx.cleanUpDashboardMock).toHaveBeenCalledTimes(1);
|
||||
expect(ctx.cleanUpDashboardAndVariablesMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -8,16 +8,14 @@ import classNames from 'classnames';
|
||||
import { createErrorNotification } from 'app/core/copy/appNotification';
|
||||
import { getMessageFromError } from 'app/core/utils/errors';
|
||||
import { Branding } from 'app/core/components/Branding/Branding';
|
||||
|
||||
// Components
|
||||
import { DashboardGrid } from '../dashgrid/DashboardGrid';
|
||||
import { DashNav } from '../components/DashNav';
|
||||
import { DashboardSettings } from '../components/DashboardSettings';
|
||||
import { PanelEditor } from '../components/PanelEditor/PanelEditor';
|
||||
import { Alert, CustomScrollbar, Icon } from '@grafana/ui';
|
||||
import { Alert, Button, CustomScrollbar, HorizontalGroup, Icon, VerticalGroup } from '@grafana/ui';
|
||||
// Redux
|
||||
import { initDashboard } from '../state/initDashboard';
|
||||
import { cleanUpDashboard } from '../state/reducers';
|
||||
import { notifyApp, updateLocation } from 'app/core/actions';
|
||||
// Types
|
||||
import {
|
||||
@@ -32,6 +30,8 @@ import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { InspectTab, PanelInspector } from '../components/Inspector/PanelInspector';
|
||||
import { getConfig } from '../../../core/config';
|
||||
import { SubMenu } from '../components/SubMenu/SubMenu';
|
||||
import { cleanUpDashboardAndVariables } from '../state/actions';
|
||||
import { cancelVariables } from '../../variables/state/actions';
|
||||
|
||||
export interface Props {
|
||||
urlUid?: string;
|
||||
@@ -51,11 +51,12 @@ export interface Props {
|
||||
dashboard: DashboardModel | null;
|
||||
initError?: DashboardInitError;
|
||||
initDashboard: typeof initDashboard;
|
||||
cleanUpDashboard: typeof cleanUpDashboard;
|
||||
cleanUpDashboardAndVariables: typeof cleanUpDashboardAndVariables;
|
||||
notifyApp: typeof notifyApp;
|
||||
updateLocation: typeof updateLocation;
|
||||
inspectTab?: InspectTab;
|
||||
isPanelEditorOpen?: boolean;
|
||||
cancelVariables: typeof cancelVariables;
|
||||
}
|
||||
|
||||
export interface State {
|
||||
@@ -90,10 +91,8 @@ export class DashboardPage extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.props.dashboard) {
|
||||
this.props.cleanUpDashboard();
|
||||
this.setPanelFullscreenClass(false);
|
||||
}
|
||||
this.props.cleanUpDashboardAndVariables();
|
||||
this.setPanelFullscreenClass(false);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
@@ -210,11 +209,24 @@ export class DashboardPage extends PureComponent<Props, State> {
|
||||
this.setState({ updateScrollTop: 0 });
|
||||
};
|
||||
|
||||
cancelVariables = () => {
|
||||
this.props.updateLocation({ path: '/' });
|
||||
};
|
||||
|
||||
renderSlowInitState() {
|
||||
return (
|
||||
<div className="dashboard-loading">
|
||||
<div className="dashboard-loading__text">
|
||||
<Icon name="fa fa-spinner" className="fa-spin" /> {this.props.initPhase}
|
||||
<VerticalGroup spacing="md">
|
||||
<HorizontalGroup align="center" justify="center" spacing="xs">
|
||||
<Icon name="fa fa-spinner" className="fa-spin" /> {this.props.initPhase}
|
||||
</HorizontalGroup>{' '}
|
||||
<HorizontalGroup align="center" justify="center">
|
||||
<Button variant="secondary" size="md" icon="repeat" onClick={this.cancelVariables}>
|
||||
Cancel loading dashboard
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -336,9 +348,10 @@ export const mapStateToProps = (state: StoreState) => ({
|
||||
|
||||
const mapDispatchToProps = {
|
||||
initDashboard,
|
||||
cleanUpDashboard,
|
||||
cleanUpDashboardAndVariables,
|
||||
notifyApp,
|
||||
updateLocation,
|
||||
cancelVariables,
|
||||
};
|
||||
|
||||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(DashboardPage));
|
||||
|
||||
@@ -320,12 +320,36 @@ exports[`DashboardPage Dashboard is fetching slowly Should render slow init stat
|
||||
<div
|
||||
className="dashboard-loading__text"
|
||||
>
|
||||
<Icon
|
||||
className="fa-spin"
|
||||
name="fa fa-spinner"
|
||||
/>
|
||||
|
||||
Fetching
|
||||
<Component
|
||||
spacing="md"
|
||||
>
|
||||
<Component
|
||||
align="center"
|
||||
justify="center"
|
||||
spacing="xs"
|
||||
>
|
||||
<Icon
|
||||
className="fa-spin"
|
||||
name="fa fa-spinner"
|
||||
/>
|
||||
|
||||
Fetching
|
||||
</Component>
|
||||
|
||||
<Component
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
<Button
|
||||
icon="repeat"
|
||||
onClick={[Function]}
|
||||
size="md"
|
||||
variant="secondary"
|
||||
>
|
||||
Cancel loading dashboard
|
||||
</Button>
|
||||
</Component>
|
||||
</Component>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user