fix(dashboard): Chart stuck in loading state when when datasets request and chart request fail (#19327)

This commit is contained in:
Kamil Gabryjelski 2022-03-23 15:43:32 +01:00 committed by GitHub
parent 468c5ca29a
commit a08f83bc60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 37 additions and 4 deletions

View File

@ -29,6 +29,7 @@ import ErrorBoundary from 'src/components/ErrorBoundary';
import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils'; import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils';
import { URL_PARAMS } from 'src/constants'; import { URL_PARAMS } from 'src/constants';
import { getUrlParam } from 'src/utils/urlUtils'; import { getUrlParam } from 'src/utils/urlUtils';
import { ResourceStatus } from 'src/hooks/apiResources/apiResources';
import ChartRenderer from './ChartRenderer'; import ChartRenderer from './ChartRenderer';
import { ChartErrorMessage } from './ChartErrorMessage'; import { ChartErrorMessage } from './ChartErrorMessage';
@ -72,6 +73,7 @@ const propTypes = {
onFilterMenuClose: PropTypes.func, onFilterMenuClose: PropTypes.func,
ownState: PropTypes.object, ownState: PropTypes.object,
postTransformProps: PropTypes.func, postTransformProps: PropTypes.func,
datasetsStatus: PropTypes.oneOf(['loading', 'error', 'complete']),
}; };
const BLANK = {}; const BLANK = {};
@ -207,6 +209,7 @@ class Chart extends React.PureComponent {
datasource, datasource,
dashboardId, dashboardId,
height, height,
datasetsStatus,
} = this.props; } = this.props;
const error = queryResponse?.errors?.[0]; const error = queryResponse?.errors?.[0];
@ -216,7 +219,8 @@ class Chart extends React.PureComponent {
if ( if (
chartAlert !== undefined && chartAlert !== undefined &&
chartAlert !== NONEXISTENT_DATASET && chartAlert !== NONEXISTENT_DATASET &&
datasource === PLACEHOLDER_DATASOURCE datasource === PLACEHOLDER_DATASOURCE &&
datasetsStatus !== ResourceStatus.ERROR
) { ) {
return ( return (
<Styles <Styles

View File

@ -612,3 +612,11 @@ export function maxUndoHistoryToast() {
); );
}; };
} }
export const SET_DATASETS_STATUS = 'SET_DATASETS_STATUS';
export function setDatasetsStatus(status) {
return {
type: SET_DATASETS_STATUS,
status,
};
}

View File

@ -51,6 +51,7 @@ import { TIME_RANGE } from 'src/visualizations/FilterBox/FilterBox';
import { URL_PARAMS } from 'src/constants'; import { URL_PARAMS } from 'src/constants';
import { getUrlParam } from 'src/utils/urlUtils'; import { getUrlParam } from 'src/utils/urlUtils';
import { FILTER_BOX_MIGRATION_STATES } from 'src/explore/constants'; import { FILTER_BOX_MIGRATION_STATES } from 'src/explore/constants';
import { ResourceStatus } from 'src/hooks/apiResources/apiResources';
import { FeatureFlag, isFeatureEnabled } from '../../featureFlags'; import { FeatureFlag, isFeatureEnabled } from '../../featureFlags';
import extractUrlParams from '../util/extractUrlParams'; import extractUrlParams from '../util/extractUrlParams';
import getNativeFilterConfig from '../util/filterboxMigrationHelper'; import getNativeFilterConfig from '../util/filterboxMigrationHelper';
@ -400,6 +401,7 @@ export const hydrateDashboard =
isFiltersRefreshing: false, isFiltersRefreshing: false,
activeTabs: dashboardState?.activeTabs || [], activeTabs: dashboardState?.activeTabs || [],
filterboxMigrationState, filterboxMigrationState,
datasetsStatus: ResourceStatus.LOADING,
}, },
dashboardLayout, dashboardLayout,
}, },

View File

@ -83,6 +83,7 @@ const propTypes = {
ownState: PropTypes.object, ownState: PropTypes.object,
filterState: PropTypes.object, filterState: PropTypes.object,
postTransformProps: PropTypes.func, postTransformProps: PropTypes.func,
datasetsStatus: PropTypes.oneOf(['loading', 'error', 'complete']),
}; };
const defaultProps = { const defaultProps = {
@ -338,6 +339,7 @@ export default class Chart extends React.Component {
isFullSize, isFullSize,
filterboxMigrationState, filterboxMigrationState,
postTransformProps, postTransformProps,
datasetsStatus,
} = this.props; } = this.props;
const { width } = this.state; const { width } = this.state;
@ -463,6 +465,7 @@ export default class Chart extends React.Component {
isDeactivatedViz={isDeactivatedViz} isDeactivatedViz={isDeactivatedViz}
filterboxMigrationState={filterboxMigrationState} filterboxMigrationState={filterboxMigrationState}
postTransformProps={postTransformProps} postTransformProps={postTransformProps}
datasetsStatus={datasetsStatus}
/> />
</div> </div>
</div> </div>

View File

@ -60,7 +60,7 @@ function mapStateToProps(
const datasource = const datasource =
(chart && chart.form_data && datasources[chart.form_data.datasource]) || (chart && chart.form_data && datasources[chart.form_data.datasource]) ||
PLACEHOLDER_DATASOURCE; PLACEHOLDER_DATASOURCE;
const { colorScheme, colorNamespace } = dashboardState; const { colorScheme, colorNamespace, datasetsStatus } = dashboardState;
const labelColors = dashboardInfo?.metadata?.label_colors || {}; const labelColors = dashboardInfo?.metadata?.label_colors || {};
const sharedLabelColors = dashboardInfo?.metadata?.shared_label_colors || {}; const sharedLabelColors = dashboardInfo?.metadata?.shared_label_colors || {};
// note: this method caches filters if possible to prevent render cascades // note: this method caches filters if possible to prevent render cascades
@ -101,6 +101,7 @@ function mapStateToProps(
filterState: dataMask[id]?.filterState, filterState: dataMask[id]?.filterState,
maxRows: common.conf.SQL_MAX_ROW, maxRows: common.conf.SQL_MAX_ROW,
filterboxMigrationState: dashboardState.filterboxMigrationState, filterboxMigrationState: dashboardState.filterboxMigrationState,
datasetsStatus,
}; };
} }

View File

@ -56,6 +56,7 @@ import { URL_PARAMS } from 'src/constants';
import { getUrlParam } from 'src/utils/urlUtils'; import { getUrlParam } from 'src/utils/urlUtils';
import { canUserEditDashboard } from 'src/dashboard/util/findPermission'; import { canUserEditDashboard } from 'src/dashboard/util/findPermission';
import { getFilterSets } from '../actions/nativeFilters'; import { getFilterSets } from '../actions/nativeFilters';
import { setDatasetsStatus } from '../actions/dashboardState';
import { import {
getFilterValue, getFilterValue,
getPermalinkValue, getPermalinkValue,
@ -90,8 +91,11 @@ const DashboardPage: FC = () => {
useDashboard(idOrSlug); useDashboard(idOrSlug);
const { result: charts, error: chartsApiError } = const { result: charts, error: chartsApiError } =
useDashboardCharts(idOrSlug); useDashboardCharts(idOrSlug);
const { result: datasets, error: datasetsApiError } = const {
useDashboardDatasets(idOrSlug); result: datasets,
error: datasetsApiError,
status,
} = useDashboardDatasets(idOrSlug);
const isDashboardHydrated = useRef(false); const isDashboardHydrated = useRef(false);
const error = dashboardApiError || chartsApiError; const error = dashboardApiError || chartsApiError;
@ -107,6 +111,10 @@ const DashboardPage: FC = () => {
migrationStateParam || FILTER_BOX_MIGRATION_STATES.NOOP, migrationStateParam || FILTER_BOX_MIGRATION_STATES.NOOP,
); );
useEffect(() => {
dispatch(setDatasetsStatus(status));
}, [dispatch, status]);
useEffect(() => { useEffect(() => {
// should convert filter_box to filter component? // should convert filter_box to filter component?
const hasFilterBox = const hasFilterBox =

View File

@ -42,6 +42,7 @@ import {
RESET_SLICE, RESET_SLICE,
ON_FILTERS_REFRESH, ON_FILTERS_REFRESH,
ON_FILTERS_REFRESH_SUCCESS, ON_FILTERS_REFRESH_SUCCESS,
SET_DATASETS_STATUS,
} from '../actions/dashboardState'; } from '../actions/dashboardState';
import { HYDRATE_DASHBOARD } from '../actions/hydrate'; import { HYDRATE_DASHBOARD } from '../actions/hydrate';
@ -212,6 +213,12 @@ export default function dashboardStateReducer(state = {}, action) {
fullSizeChartId: action.chartId, fullSizeChartId: action.chartId,
}; };
}, },
[SET_DATASETS_STATUS]() {
return {
...state,
datasetsStatus: action.status,
};
},
}; };
if (action.type in actionHandlers) { if (action.type in actionHandlers) {