fix(dashboard): Refresh Native Filters when Dashboard refreshes (#15890)
* Implement onRefresh action
* Update tests
* Clean up
* Fix type
* Add effect dependency
diff --git a/superset-frontend/src/dashboard/actions/dashboardState.js b/superset-frontend/src/dashboard/actions/dashboardState.js
index d0953e8..36868b8 100644
--- a/superset-frontend/src/dashboard/actions/dashboardState.js
+++ b/superset-frontend/src/dashboard/actions/dashboardState.js
@@ -275,6 +275,32 @@
};
}
+const refreshCharts = (chartList, force, interval, dashboardId, dispatch) =>
+ new Promise(resolve => {
+ dispatch(fetchCharts(chartList, force, interval, dashboardId));
+ resolve();
+ });
+
+export const ON_REFRESH_SUCCESS = 'ON_REFRESH_SUCCESS';
+export function onRefreshSuccess() {
+ return { type: ON_REFRESH_SUCCESS };
+}
+
+export const ON_REFRESH = 'ON_REFRESH';
+export function onRefresh(
+ chartList = [],
+ force = false,
+ interval = 0,
+ dashboardId,
+) {
+ return dispatch => {
+ dispatch({ type: ON_REFRESH });
+ refreshCharts(chartList, force, interval, dashboardId, dispatch).then(() =>
+ dispatch({ type: ON_REFRESH_SUCCESS }),
+ );
+ };
+}
+
export const SHOW_BUILDER_PANE = 'SHOW_BUILDER_PANE';
export function showBuilderPane() {
return { type: SHOW_BUILDER_PANE };
diff --git a/superset-frontend/src/dashboard/actions/hydrate.js b/superset-frontend/src/dashboard/actions/hydrate.js
index 8eebbba..67ce361 100644
--- a/superset-frontend/src/dashboard/actions/hydrate.js
+++ b/superset-frontend/src/dashboard/actions/hydrate.js
@@ -378,6 +378,7 @@
hasUnsavedChanges: false,
maxUndoHistoryExceeded: false,
lastModifiedTime: dashboardData.changed_on,
+ isRefreshing: false,
activeTabs: [],
},
dashboardLayout,
diff --git a/superset-frontend/src/dashboard/components/Header/Header.test.tsx b/superset-frontend/src/dashboard/components/Header/Header.test.tsx
index 88d22b8..da52757 100644
--- a/superset-frontend/src/dashboard/components/Header/Header.test.tsx
+++ b/superset-frontend/src/dashboard/components/Header/Header.test.tsx
@@ -54,6 +54,7 @@
onChange: jest.fn(),
fetchFaveStar: jest.fn(),
fetchCharts: jest.fn(),
+ onRefresh: jest.fn(),
saveFaveStar: jest.fn(),
savePublished: jest.fn(),
isPublished: false,
@@ -301,5 +302,5 @@
render(setup(mockedProps));
await openActionsDropdown();
userEvent.click(screen.getByText('Refresh dashboard'));
- expect(mockedProps.fetchCharts).toHaveBeenCalledTimes(1);
+ expect(mockedProps.onRefresh).toHaveBeenCalledTimes(1);
});
diff --git a/superset-frontend/src/dashboard/components/Header/index.jsx b/superset-frontend/src/dashboard/components/Header/index.jsx
index 79411fa..39e4751 100644
--- a/superset-frontend/src/dashboard/components/Header/index.jsx
+++ b/superset-frontend/src/dashboard/components/Header/index.jsx
@@ -82,6 +82,7 @@
lastModifiedTime: PropTypes.number.isRequired,
// redux
+ onRefresh: PropTypes.func.isRequired,
onUndo: PropTypes.func.isRequired,
onRedo: PropTypes.func.isRequired,
undoLength: PropTypes.number.isRequired,
@@ -216,8 +217,7 @@
interval: 0,
chartCount: chartList.length,
});
-
- return this.props.fetchCharts(
+ return this.props.onRefresh(
chartList,
true,
0,
diff --git a/superset-frontend/src/dashboard/components/Header/types.ts b/superset-frontend/src/dashboard/components/Header/types.ts
index 3c8e8cf..2262411 100644
--- a/superset-frontend/src/dashboard/components/Header/types.ts
+++ b/superset-frontend/src/dashboard/components/Header/types.ts
@@ -87,6 +87,7 @@
lastModifiedTime: number;
onUndo: () => void;
onRedo: () => void;
+ onRefresh: () => void;
undoLength: number;
redoLength: number;
setMaxUndoHistoryExceeded: () => void;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
index eb9ace7..0ce0ad0 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx
@@ -28,7 +28,7 @@
JsonObject,
getChartMetadataRegistry,
} from '@superset-ui/core';
-import { useDispatch } from 'react-redux';
+import { useDispatch, useSelector } from 'react-redux';
import { areObjectsEqual } from 'src/reduxUtils';
import { getChartDataRequest } from 'src/chart/chartAction';
import Loading from 'src/components/Loading';
@@ -36,6 +36,7 @@
import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
import { waitForAsyncData } from 'src/middleware/asyncEvent';
import { ClientErrorObject } from 'src/utils/getClientErrorObject';
+import { RootState } from 'src/dashboard/types';
import { dispatchFocusAction } from './utils';
import { FilterProps } from './types';
import { getFormData } from '../../utils';
@@ -62,6 +63,9 @@
const { id, targets, filterType, adhoc_filters, time_range } = filter;
const metadata = getChartMetadataRegistry().get(filterType);
const cascadingFilters = useCascadingFilters(id, dataMaskSelected);
+ const isDashboardRefreshing = useSelector<RootState, boolean>(
+ state => state.dashboardState.isRefreshing,
+ );
const [state, setState] = useState<ChartDataResponseResult[]>([]);
const [error, setError] = useState<string>('');
const [formData, setFormData] = useState<Partial<QueryFormData>>({
@@ -78,7 +82,7 @@
const { name: groupby } = column;
const hasDataSource = !!datasetId;
const [isLoading, setIsLoading] = useState<boolean>(hasDataSource);
- const [isRefreshing, setIsRefreshing] = useState(true);
+ const [isRefreshing, setIsRefreshing] = useState(false);
const dispatch = useDispatch();
useEffect(() => {
@@ -102,8 +106,10 @@
});
const filterOwnState = filter.dataMask?.ownState || {};
if (
- !areObjectsEqual(formData, newFormData) ||
- !areObjectsEqual(ownState, filterOwnState)
+ !isRefreshing &&
+ (!areObjectsEqual(formData, newFormData) ||
+ !areObjectsEqual(ownState, filterOwnState) ||
+ isDashboardRefreshing)
) {
setFormData(newFormData);
setOwnState(filterOwnState);
@@ -165,6 +171,8 @@
groupby,
JSON.stringify(filter),
hasDataSource,
+ isRefreshing,
+ isDashboardRefreshing,
]);
useEffect(() => {
diff --git a/superset-frontend/src/dashboard/containers/DashboardHeader.jsx b/superset-frontend/src/dashboard/containers/DashboardHeader.jsx
index f54f0f0..f8862b9 100644
--- a/superset-frontend/src/dashboard/containers/DashboardHeader.jsx
+++ b/superset-frontend/src/dashboard/containers/DashboardHeader.jsx
@@ -39,6 +39,7 @@
setMaxUndoHistoryExceeded,
maxUndoHistoryToast,
setRefreshFrequency,
+ onRefresh,
} from '../actions/dashboardState';
import {
@@ -120,6 +121,7 @@
maxUndoHistoryToast,
logEvent,
setRefreshFrequency,
+ onRefresh,
dashboardInfoChanged,
dashboardTitleChanged,
updateDataMask,
diff --git a/superset-frontend/src/dashboard/reducers/dashboardState.js b/superset-frontend/src/dashboard/reducers/dashboardState.js
index 55455dd..3c3963a 100644
--- a/superset-frontend/src/dashboard/reducers/dashboardState.js
+++ b/superset-frontend/src/dashboard/reducers/dashboardState.js
@@ -32,6 +32,8 @@
TOGGLE_PUBLISHED,
UPDATE_CSS,
SET_REFRESH_FREQUENCY,
+ ON_REFRESH,
+ ON_REFRESH_SUCCESS,
SET_DIRECT_PATH,
SET_FOCUSED_FILTER_FIELD,
UNSET_FOCUSED_FILTER_FIELD,
@@ -128,6 +130,18 @@
hasUnsavedChanges: action.isPersistent,
};
},
+ [ON_REFRESH]() {
+ return {
+ ...state,
+ isRefreshing: true,
+ };
+ },
+ [ON_REFRESH_SUCCESS]() {
+ return {
+ ...state,
+ isRefreshing: false,
+ };
+ },
[SET_DIRECT_PATH]() {
return {
...state,
diff --git a/superset-frontend/src/dashboard/types.ts b/superset-frontend/src/dashboard/types.ts
index c2b316b..ae602aa 100644
--- a/superset-frontend/src/dashboard/types.ts
+++ b/superset-frontend/src/dashboard/types.ts
@@ -60,6 +60,7 @@
directPathToChild: string[];
activeTabs: ActiveTabs;
fullSizeChartId: number | null;
+ isRefreshing: boolean;
};
export type DashboardInfo = {
common: {