You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ms...@apache.org on 2025/12/05 15:33:33 UTC

(superset) branch master updated: feat(state): remove chart state when navigation away from the dashboard (#36421)

This is an automated email from the ASF dual-hosted git repository.

msyavuz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 8c603a6f8b feat(state): remove chart state when navigation away from the dashboard (#36421)
8c603a6f8b is described below

commit 8c603a6f8bd2c66e9c681da44633b2cb844fca79
Author: Alexandru Soare <37...@users.noreply.github.com>
AuthorDate: Fri Dec 5 17:33:26 2025 +0200

    feat(state): remove chart state when navigation away from the dashboard (#36421)
---
 .../src/dashboard/actions/dashboardState.js        |  5 ++
 .../src/dashboard/components/Dashboard.jsx         |  1 +
 .../src/dashboard/components/Dashboard.test.jsx    |  2 +
 .../src/dashboard/containers/Dashboard.ts          |  2 +
 .../src/dashboard/reducers/dashboardState.js       |  7 ++
 .../src/dashboard/reducers/dashboardState.test.js  | 78 ++++++++++++++++++++++
 6 files changed, 95 insertions(+)

diff --git a/superset-frontend/src/dashboard/actions/dashboardState.js b/superset-frontend/src/dashboard/actions/dashboardState.js
index 45f9c2af46..18b567e20f 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 7d909b5154..4b47b34081 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 008b9fdd47..dd00834ba2 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 a59767c004..f649a471a1 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 e24f875022..70b5b6ab19 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 56e647c3be..83fe01c8b6 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');
+  });
 });