feat(state): remove chart state when navigation away from the dashboard (#36421)

This commit is contained in:
Alexandru Soare
2025-12-05 17:33:26 +02:00
committed by GitHub
parent 45a42396ab
commit 8c603a6f8b
6 changed files with 95 additions and 0 deletions

View File

@@ -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) {

View File

@@ -188,6 +188,7 @@ class Dashboard extends PureComponent {
componentWillUnmount() {
window.removeEventListener('visibilitychange', this.onVisibilityChange);
this.props.actions.clearDataMaskState();
this.props.actions.clearAllChartStates();
}
onVisibilityChange() {

View File

@@ -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,

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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');
});
});