fix(dashboard): Refresh Native Filters when Dashboard refreshes (#15890)

* Implement onRefresh action

* Update tests

* Clean up

* Fix type

* Add effect dependency
This commit is contained in:
Geido 2021-07-27 01:27:08 +02:00 committed by GitHub
parent 62550db385
commit 1297fd9169
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 61 additions and 7 deletions

View File

@ -275,6 +275,32 @@ export function fetchCharts(
};
}
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 };

View File

@ -378,6 +378,7 @@ export const hydrateDashboard = (dashboardData, chartData) => (
hasUnsavedChanges: false,
maxUndoHistoryExceeded: false,
lastModifiedTime: dashboardData.changed_on,
isRefreshing: false,
activeTabs: [],
},
dashboardLayout,

View File

@ -54,6 +54,7 @@ const createProps = () => ({
onChange: jest.fn(),
fetchFaveStar: jest.fn(),
fetchCharts: jest.fn(),
onRefresh: jest.fn(),
saveFaveStar: jest.fn(),
savePublished: jest.fn(),
isPublished: false,
@ -301,5 +302,5 @@ test('should refresh the charts', async () => {
render(setup(mockedProps));
await openActionsDropdown();
userEvent.click(screen.getByText('Refresh dashboard'));
expect(mockedProps.fetchCharts).toHaveBeenCalledTimes(1);
expect(mockedProps.onRefresh).toHaveBeenCalledTimes(1);
});

View File

@ -82,6 +82,7 @@ const propTypes = {
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 @@ class Header extends React.PureComponent {
interval: 0,
chartCount: chartList.length,
});
return this.props.fetchCharts(
return this.props.onRefresh(
chartList,
true,
0,

View File

@ -87,6 +87,7 @@ export interface HeaderProps {
lastModifiedTime: number;
onUndo: () => void;
onRedo: () => void;
onRefresh: () => void;
undoLength: number;
redoLength: number;
setMaxUndoHistoryExceeded: () => void;

View File

@ -28,7 +28,7 @@ import {
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 BasicErrorAlert from 'src/components/ErrorMessage/BasicErrorAlert';
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 FilterValue: React.FC<FilterProps> = ({
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 FilterValue: React.FC<FilterProps> = ({
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 FilterValue: React.FC<FilterProps> = ({
});
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 @@ const FilterValue: React.FC<FilterProps> = ({
groupby,
JSON.stringify(filter),
hasDataSource,
isRefreshing,
isDashboardRefreshing,
]);
useEffect(() => {

View File

@ -39,6 +39,7 @@ import {
setMaxUndoHistoryExceeded,
maxUndoHistoryToast,
setRefreshFrequency,
onRefresh,
} from '../actions/dashboardState';
import {
@ -120,6 +121,7 @@ function mapDispatchToProps(dispatch) {
maxUndoHistoryToast,
logEvent,
setRefreshFrequency,
onRefresh,
dashboardInfoChanged,
dashboardTitleChanged,
updateDataMask,

View File

@ -32,6 +32,8 @@ import {
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 @@ export default function dashboardStateReducer(state = {}, action) {
hasUnsavedChanges: action.isPersistent,
};
},
[ON_REFRESH]() {
return {
...state,
isRefreshing: true,
};
},
[ON_REFRESH_SUCCESS]() {
return {
...state,
isRefreshing: false,
};
},
[SET_DIRECT_PATH]() {
return {
...state,

View File

@ -60,6 +60,7 @@ export type DashboardState = {
directPathToChild: string[];
activeTabs: ActiveTabs;
fullSizeChartId: number | null;
isRefreshing: boolean;
};
export type DashboardInfo = {
common: {