PanelEdit: Fixed timing and state related issues (#22131)

* PanelEdit: Fixed timing and state related issues

* Added unit test and changed some logic

* Fixed id logic

* Updated snapshots

* Update public/app/features/dashboard/state/PanelModel.ts

Co-Authored-By: Dominik Prokop <dominik.prokop@grafana.com>

Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
This commit is contained in:
Torkel Ödegaard
2020-02-13 16:06:45 +01:00
committed by GitHub
parent 9c55500cc0
commit 70b0ec65b3
13 changed files with 139 additions and 37 deletions

View File

@@ -25,6 +25,7 @@ import { setDisplayMode, toggleOptionsView, setDiscardChanges } from './state/re
import { FieldConfigEditor } from './FieldConfigEditor';
import { OptionsGroup } from './OptionsGroup';
import { getPanelEditorTabs } from './state/selectors';
import { getPanelStateById } from '../../state/selectors';
interface OwnProps {
dashboard: DashboardModel;
@@ -281,7 +282,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state, props) => {
const panel = state.panelEditorNew.getPanel();
const plugin = state.plugins.panels[panel.type];
const { plugin } = getPanelStateById(state.dashboard, panel.id);
return {
location: state.location,

View File

@@ -0,0 +1,60 @@
import { thunkTester } from '../../../../../../test/core/thunk/thunkTester';
import { initialState } from './reducers';
import { initPanelEditor, panelEditorCleanUp } from './actions';
import { PanelEditorStateNew, closeCompleted } from './reducers';
import { PanelModel, DashboardModel } from '../../../state';
describe('panelEditor actions', () => {
describe('initPanelEditor', () => {
it('initPanelEditor should create edit panel model as clone', async () => {
const dashboard = new DashboardModel({
panels: [{ id: 12, type: 'graph' }],
});
const sourcePanel = new PanelModel({ id: 12, type: 'graph' });
const dispatchedActions = await thunkTester({
panelEditorNew: { ...initialState },
})
.givenThunk(initPanelEditor)
.whenThunkIsDispatched(sourcePanel, dashboard);
expect(dispatchedActions.length).toBe(1);
expect(dispatchedActions[0].payload.sourcePanel).toBe(sourcePanel);
expect(dispatchedActions[0].payload.panel).not.toBe(sourcePanel);
expect(dispatchedActions[0].payload.panel.id).not.toBe(sourcePanel.id);
});
});
describe('panelEditorCleanUp', () => {
it('create update source panel', async () => {
const sourcePanel = new PanelModel({ id: 12, type: 'graph' });
const dashboard = new DashboardModel({
panels: [{ id: 12, type: 'graph' }],
});
const panel = sourcePanel.getEditClone();
panel.updateOptions({ prop: true });
const state: PanelEditorStateNew = {
...initialState,
getPanel: () => panel,
getSourcePanel: () => sourcePanel,
querySubscription: { unsubscribe: jest.fn() },
};
const dispatchedActions = await thunkTester({
panelEditorNew: state,
dashboard: {
getModel: () => dashboard,
},
})
.givenThunk(panelEditorCleanUp)
.whenThunkIsDispatched();
expect(dispatchedActions.length).toBe(1);
expect(dispatchedActions[0].type).toBe(closeCompleted.type);
expect(sourcePanel.getOptions()).toEqual({ prop: true });
expect(sourcePanel.id).toEqual(12);
});
});
});

View File

@@ -25,10 +25,18 @@ export function initPanelEditor(sourcePanel: PanelModel, dashboard: DashboardMod
export function panelEditorCleanUp(): ThunkResult<void> {
return (dispatch, getStore) => {
const dashboard = getStore().dashboard.getModel();
const { getPanel, querySubscription, shouldDiscardChanges } = getStore().panelEditorNew;
const { getPanel, getSourcePanel, querySubscription, shouldDiscardChanges } = getStore().panelEditorNew;
if (!shouldDiscardChanges) {
dashboard.updatePanel(getPanel());
const panel = getPanel();
const modifiedSaveModel = panel.getSaveModel();
const sourcePanel = getSourcePanel();
// restore the source panel id before we update source panel
modifiedSaveModel.id = sourcePanel.id;
sourcePanel.restoreModel(modifiedSaveModel);
sourcePanel.getQueryRunner().pipeDataToSubject(panel.getQueryRunner().getLastResult());
}
dashboard.exitPanelEditor();