diff --git a/superset-frontend/src/dashboard/actions/dashboardState.js b/superset-frontend/src/dashboard/actions/dashboardState.js index 45f9c2af465..18b567e20f5 100644 --- a/superset-frontend/src/dashboard/actions/dashboardState.js +++ b/superset-frontend/src/dashboard/actions/dashboardState.js @@ -769,6 +769,11 @@ export function restoreChartStates(chartStates) { return { type: RESTORE_CHART_STATES, chartStates }; } +export const CLEAR_ALL_CHART_STATES = 'CLEAR_ALL_CHART_STATES'; +export function clearAllChartStates() { + return { type: CLEAR_ALL_CHART_STATES }; +} + // Undo history --------------------------------------------------------------- export const SET_MAX_UNDO_HISTORY_EXCEEDED = 'SET_MAX_UNDO_HISTORY_EXCEEDED'; export function setMaxUndoHistoryExceeded(maxUndoHistoryExceeded = true) { diff --git a/superset-frontend/src/dashboard/components/Dashboard.jsx b/superset-frontend/src/dashboard/components/Dashboard.jsx index 7d909b5154c..4b47b340814 100644 --- a/superset-frontend/src/dashboard/components/Dashboard.jsx +++ b/superset-frontend/src/dashboard/components/Dashboard.jsx @@ -188,6 +188,7 @@ class Dashboard extends PureComponent { componentWillUnmount() { window.removeEventListener('visibilitychange', this.onVisibilityChange); this.props.actions.clearDataMaskState(); + this.props.actions.clearAllChartStates(); } onVisibilityChange() { diff --git a/superset-frontend/src/dashboard/components/Dashboard.test.jsx b/superset-frontend/src/dashboard/components/Dashboard.test.jsx index 008b9fdd476..dd00834ba2e 100644 --- a/superset-frontend/src/dashboard/components/Dashboard.test.jsx +++ b/superset-frontend/src/dashboard/components/Dashboard.test.jsx @@ -46,6 +46,7 @@ describe('Dashboard', () => { const mockTriggerQuery = jest.fn(); const mockLogEvent = jest.fn(); const mockClearDataMask = jest.fn(); + const mockClearAllChartStates = jest.fn(); const props = { actions: { @@ -54,6 +55,7 @@ describe('Dashboard', () => { triggerQuery: mockTriggerQuery, logEvent: mockLogEvent, clearDataMaskState: mockClearDataMask, + clearAllChartStates: mockClearAllChartStates, }, dashboardState, dashboardInfo, diff --git a/superset-frontend/src/dashboard/containers/Dashboard.ts b/superset-frontend/src/dashboard/containers/Dashboard.ts index a59767c004a..f649a471a18 100644 --- a/superset-frontend/src/dashboard/containers/Dashboard.ts +++ b/superset-frontend/src/dashboard/containers/Dashboard.ts @@ -23,6 +23,7 @@ import Dashboard from 'src/dashboard/components/Dashboard'; import { addSliceToDashboard, removeSliceFromDashboard, + clearAllChartStates, } from 'src/dashboard/actions/dashboardState'; import { setDatasources } from 'src/dashboard/actions/datasources'; @@ -61,6 +62,7 @@ function mapDispatchToProps(dispatch: Dispatch) { { setDatasources, clearDataMaskState, + clearAllChartStates, addSliceToDashboard, removeSliceFromDashboard, triggerQuery, diff --git a/superset-frontend/src/dashboard/reducers/dashboardState.js b/superset-frontend/src/dashboard/reducers/dashboardState.js index e24f875022f..70b5b6ab19d 100644 --- a/superset-frontend/src/dashboard/reducers/dashboardState.js +++ b/superset-frontend/src/dashboard/reducers/dashboardState.js @@ -53,6 +53,7 @@ import { UPDATE_CHART_STATE, REMOVE_CHART_STATE, RESTORE_CHART_STATES, + CLEAR_ALL_CHART_STATES, } from '../actions/dashboardState'; import { HYDRATE_DASHBOARD } from '../actions/hydrate'; @@ -326,6 +327,12 @@ export default function dashboardStateReducer(state = {}, action) { chartStates: chartStates || {}, }; }, + [CLEAR_ALL_CHART_STATES]() { + return { + ...state, + chartStates: {}, + }; + }, }; if (action.type in actionHandlers) { diff --git a/superset-frontend/src/dashboard/reducers/dashboardState.test.js b/superset-frontend/src/dashboard/reducers/dashboardState.test.js index 56e647c3be2..83fe01c8b6b 100644 --- a/superset-frontend/src/dashboard/reducers/dashboardState.test.js +++ b/superset-frontend/src/dashboard/reducers/dashboardState.test.js @@ -29,6 +29,10 @@ import { TOGGLE_FAVE_STAR, TOGGLE_NATIVE_FILTERS_BAR, UNSET_FOCUSED_FILTER_FIELD, + UPDATE_CHART_STATE, + REMOVE_CHART_STATE, + RESTORE_CHART_STATES, + CLEAR_ALL_CHART_STATES, } from 'src/dashboard/actions/dashboardState'; import dashboardStateReducer from 'src/dashboard/reducers/dashboardState'; @@ -215,4 +219,78 @@ describe('dashboardState reducer', () => { ), ).toEqual({ nativeFiltersBarOpen: false }); }); + + test('should update chart state', () => { + const chartState = { columnState: [], filterModel: {} }; + const result = dashboardStateReducer( + { chartStates: {} }, + { + type: UPDATE_CHART_STATE, + chartId: 123, + vizType: 'ag-grid-table', + chartState, + lastModified: 1234567890, + }, + ); + expect(result.chartStates[123]).toEqual({ + chartId: 123, + vizType: 'ag-grid-table', + state: chartState, + lastModified: 1234567890, + }); + }); + + test('should remove chart state', () => { + const initState = { + chartStates: { + 123: { chartId: 123, vizType: 'ag-grid-table', state: {} }, + 456: { chartId: 456, vizType: 'ag-grid-table', state: {} }, + }, + }; + const result = dashboardStateReducer(initState, { + type: REMOVE_CHART_STATE, + chartId: 123, + }); + expect(result.chartStates[123]).toBeUndefined(); + expect(result.chartStates[456]).toBeDefined(); + }); + + test('should restore chart states', () => { + const chartStates = { + 123: { chartId: 123, vizType: 'ag-grid-table', state: {} }, + }; + const result = dashboardStateReducer( + { chartStates: {} }, + { type: RESTORE_CHART_STATES, chartStates }, + ); + expect(result.chartStates).toEqual(chartStates); + }); + + test('should restore chart states to empty when given null', () => { + const initState = { + chartStates: { + 123: { chartId: 123, vizType: 'ag-grid-table', state: {} }, + }, + }; + const result = dashboardStateReducer(initState, { + type: RESTORE_CHART_STATES, + chartStates: null, + }); + expect(result.chartStates).toEqual({}); + }); + + test('should clear all chart states', () => { + const initState = { + chartStates: { + 123: { chartId: 123, vizType: 'ag-grid-table', state: {} }, + 456: { chartId: 456, vizType: 'ag-grid-table', state: {} }, + }, + otherState: 'preserved', + }; + const result = dashboardStateReducer(initState, { + type: CLEAR_ALL_CHART_STATES, + }); + expect(result.chartStates).toEqual({}); + expect(result.otherState).toEqual('preserved'); + }); });