mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Library Panels: Improve unsaved changes handling (#32026)
* Library Panels: Improve unsaved changes handling
This commit is contained in:
parent
093e5947f4
commit
298ff3ea01
@ -1,5 +1,6 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { connect, ConnectedProps } from 'react-redux';
|
import { connect, ConnectedProps } from 'react-redux';
|
||||||
|
import { Prompt } from 'react-router-dom';
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
import { css, cx } from 'emotion';
|
import { css, cx } from 'emotion';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
@ -29,6 +30,7 @@ import { DashboardPanel } from '../../dashgrid/DashboardPanel';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
exitPanelEditor,
|
exitPanelEditor,
|
||||||
|
discardPanelChanges,
|
||||||
initPanelEditor,
|
initPanelEditor,
|
||||||
panelEditorCleanUp,
|
panelEditorCleanUp,
|
||||||
updatePanelEditorUIState,
|
updatePanelEditorUIState,
|
||||||
@ -36,7 +38,6 @@ import {
|
|||||||
} from './state/actions';
|
} from './state/actions';
|
||||||
|
|
||||||
import { updateTimeZoneForSession } from 'app/features/profile/state/reducers';
|
import { updateTimeZoneForSession } from 'app/features/profile/state/reducers';
|
||||||
import { setDiscardChanges } from './state/reducers';
|
|
||||||
|
|
||||||
import { getPanelEditorTabs } from './state/selectors';
|
import { getPanelEditorTabs } from './state/selectors';
|
||||||
import { getPanelStateById } from '../../state/selectors';
|
import { getPanelStateById } from '../../state/selectors';
|
||||||
@ -83,7 +84,7 @@ const mapDispatchToProps = {
|
|||||||
exitPanelEditor,
|
exitPanelEditor,
|
||||||
updateSourcePanel,
|
updateSourcePanel,
|
||||||
panelEditorCleanUp,
|
panelEditorCleanUp,
|
||||||
setDiscardChanges,
|
discardPanelChanges,
|
||||||
updatePanelEditorUIState,
|
updatePanelEditorUIState,
|
||||||
updateTimeZoneForSession,
|
updateTimeZoneForSession,
|
||||||
notifyApp,
|
notifyApp,
|
||||||
@ -118,15 +119,18 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
|||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
onDiscard = () => {
|
onBack = () => {
|
||||||
this.props.setDiscardChanges(true);
|
|
||||||
|
|
||||||
locationService.partial({
|
locationService.partial({
|
||||||
editPanel: null,
|
editPanel: null,
|
||||||
tab: null,
|
tab: null,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onDiscard = () => {
|
||||||
|
this.props.discardPanelChanges();
|
||||||
|
this.onBack();
|
||||||
|
};
|
||||||
|
|
||||||
onOpenDashboardSettings = () => {
|
onOpenDashboardSettings = () => {
|
||||||
locationService.partial({
|
locationService.partial({
|
||||||
editview: 'settings',
|
editview: 'settings',
|
||||||
@ -148,12 +152,11 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.panel.libraryPanel.meta.connectedDashboards === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const connectedDashboards = await getLibraryPanelConnectedDashboards(this.props.panel.libraryPanel.uid);
|
const connectedDashboards = await getLibraryPanelConnectedDashboards(this.props.panel.libraryPanel.uid);
|
||||||
if (connectedDashboards.length === 1 && connectedDashboards.indexOf(this.props.dashboard.id) !== -1) {
|
if (
|
||||||
|
connectedDashboards.length === 0 ||
|
||||||
|
(connectedDashboards.length === 1 && connectedDashboards.includes(this.props.dashboard.id))
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
await saveAndRefreshLibraryPanel(this.props.panel, this.props.dashboard.meta.folderId!);
|
await saveAndRefreshLibraryPanel(this.props.panel, this.props.dashboard.meta.folderId!);
|
||||||
this.props.updateSourcePanel(this.props.panel);
|
this.props.updateSourcePanel(this.props.panel);
|
||||||
@ -327,12 +330,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
|||||||
Save
|
Save
|
||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
),
|
),
|
||||||
<ToolbarButton
|
<ToolbarButton onClick={this.onBack} variant="primary" title="Apply changes and go back to dashboard" key="apply">
|
||||||
onClick={this.props.exitPanelEditor}
|
|
||||||
variant="primary"
|
|
||||||
title="Apply changes and go back to dashboard"
|
|
||||||
key="apply"
|
|
||||||
>
|
|
||||||
Apply
|
Apply
|
||||||
</ToolbarButton>,
|
</ToolbarButton>,
|
||||||
];
|
];
|
||||||
@ -408,6 +406,18 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrapper} aria-label={selectors.components.PanelEditor.General.content}>
|
<div className={styles.wrapper} aria-label={selectors.components.PanelEditor.General.content}>
|
||||||
|
<Prompt
|
||||||
|
when={true}
|
||||||
|
message={(location) => {
|
||||||
|
const searchParams = new URLSearchParams(location.search);
|
||||||
|
if (!this.props.panel.libraryPanel || !this.props.panel.hasChanged || searchParams.has('editPanel')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
exitPanelEditor();
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<PageToolbar title={`${dashboard.title} / Edit Panel`} onGoBack={exitPanelEditor}>
|
<PageToolbar title={`${dashboard.title} / Edit Panel`} onGoBack={exitPanelEditor}>
|
||||||
{this.renderEditorActions()}
|
{this.renderEditorActions()}
|
||||||
</PageToolbar>
|
</PageToolbar>
|
||||||
|
@ -42,19 +42,25 @@ export function updateSourcePanel(sourcePanel: PanelModel): ThunkResult<void> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function discardPanelChanges(): ThunkResult<void> {
|
||||||
|
return async (dispatch, getStore) => {
|
||||||
|
const { getPanel } = getStore().panelEditor;
|
||||||
|
getPanel().hasChanged = false;
|
||||||
|
dispatch(setDiscardChanges(true));
|
||||||
|
};
|
||||||
|
}
|
||||||
export function exitPanelEditor(): ThunkResult<void> {
|
export function exitPanelEditor(): ThunkResult<void> {
|
||||||
return async (dispatch, getStore) => {
|
return async (dispatch, getStore) => {
|
||||||
const dashboard = getStore().dashboard.getModel();
|
const dashboard = getStore().dashboard.getModel();
|
||||||
const { getPanel, shouldDiscardChanges } = getStore().panelEditor;
|
const { getPanel, shouldDiscardChanges } = getStore().panelEditor;
|
||||||
const onConfirm = () => locationService.partial({ editPanel: null, tab: null });
|
const onConfirm = () => locationService.partial({ editPanel: null, tab: null });
|
||||||
|
|
||||||
|
const panel = getPanel();
|
||||||
const onDiscard = () => {
|
const onDiscard = () => {
|
||||||
dispatch(setDiscardChanges(true));
|
dispatch(discardPanelChanges());
|
||||||
onConfirm();
|
onConfirm();
|
||||||
};
|
};
|
||||||
|
|
||||||
const panel = getPanel();
|
|
||||||
|
|
||||||
if (shouldDiscardChanges || !panel.libraryPanel) {
|
if (shouldDiscardChanges || !panel.libraryPanel) {
|
||||||
onConfirm();
|
onConfirm();
|
||||||
return;
|
return;
|
||||||
|
@ -109,12 +109,12 @@ export const SaveLibraryPanelModal: React.FC<Props> = ({
|
|||||||
>
|
>
|
||||||
Update all
|
Update all
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="secondary" onClick={onDismiss}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button variant="destructive" onClick={discardAndClose}>
|
<Button variant="destructive" onClick={discardAndClose}>
|
||||||
Discard
|
Discard
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button variant="secondary" onClick={onDismiss}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
Loading…
Reference in New Issue
Block a user