From f7add546ada882d60993f790fdc019bedb99c1f3 Mon Sep 17 00:00:00 2001 From: Lyndsi Kay Williams <55605634+lyndsiWilliams@users.noreply.github.com> Date: Mon, 10 Jan 2022 17:01:08 -0600 Subject: [PATCH] Fixed error handling in Report modal (#17988) --- .../src/components/ReportModal/index.tsx | 75 +++++++++++-------- .../src/reports/actions/reports.js | 21 +----- 2 files changed, 47 insertions(+), 49 deletions(-) diff --git a/superset-frontend/src/components/ReportModal/index.tsx b/superset-frontend/src/components/ReportModal/index.tsx index fc5469d17c174..240d3176ccec9 100644 --- a/superset-frontend/src/components/ReportModal/index.tsx +++ b/superset-frontend/src/components/ReportModal/index.tsx @@ -25,6 +25,7 @@ import React, { FunctionComponent, } from 'react'; import { t, SupersetTheme } from '@superset-ui/core'; +import { getClientErrorObject } from 'src/utils/getClientErrorObject'; import { bindActionCreators } from 'redux'; import { connect, useDispatch, useSelector } from 'react-redux'; import { addReport, editReport } from 'src/reports/actions/reports'; @@ -72,6 +73,7 @@ export interface ReportObject { working_timeout: number; creation_method: string; force_screenshot: boolean; + error?: string; } interface ChartObject { @@ -88,8 +90,6 @@ interface ChartObject { } interface ReportProps { - addDangerToast: (msg: string) => void; - addSuccessToast: (msg: string) => void; addReport: (report?: ReportObject) => {}; onHide: () => {}; onReportAdd: (report?: ReportObject) => {}; @@ -111,6 +111,7 @@ enum ActionType { inputChange, fetched, reset, + error, } type ReportActionType = @@ -124,6 +125,12 @@ type ReportActionType = } | { type: ActionType.reset; + } + | { + type: ActionType.error; + payload: { + name: string[]; + }; }; const TEXT_BASED_VISUALIZATION_TYPES = [ @@ -161,6 +168,11 @@ const reportReducer = ( }; case ActionType.reset: return { ...initialState }; + case ActionType.error: + return { + ...state, + error: action.payload.name[0], + }; default: return state; } @@ -181,11 +193,10 @@ const ReportModal: FunctionComponent = ({ const [currentReport, setCurrentReport] = useReducer< Reducer | null, ReportActionType> >(reportReducer, null); - const onChange = useCallback((type: any, payload: any) => { + const onReducerChange = useCallback((type: any, payload: any) => { setCurrentReport({ type, payload }); }, []); - const [error, setError] = useState(); - // const [isLoading, setLoading] = useState(false); + const [cronError, setCronError] = useState(); const dispatch = useDispatch(); // Report fetch logic const reports = useSelector(state => state.reports); @@ -205,9 +216,7 @@ const ReportModal: FunctionComponent = ({ }); } }, [reports]); - const onClose = () => { - onHide(); - }; + const onSave = async () => { // Create new Report const newReportValues: Partial = { @@ -235,15 +244,19 @@ const ReportModal: FunctionComponent = ({ await dispatch( editReport(currentReport?.id, newReportValues as ReportObject), ); + onHide(); } else { - await dispatch(addReport(newReportValues as ReportObject)); + try { + await dispatch(addReport(newReportValues as ReportObject)); + onHide(); + } catch (e) { + const parsedError = await getClientErrorObject(e); + const errorMessage = parsedError.message; + onReducerChange(ActionType.error, errorMessage); + } } - if (onReportAdd) { - onReportAdd(); - } - - onClose(); + if (onReportAdd) onReportAdd(); }; const wrappedTitle = ( @@ -257,7 +270,7 @@ const ReportModal: FunctionComponent = ({ const renderModalFooter = ( <> - + {t('Cancel')} = ({
{ - onChange(ActionType.inputChange, { + onReducerChange(ActionType.inputChange, { name: 'report_format', value: event.target.value, }); @@ -305,7 +318,7 @@ const ReportModal: FunctionComponent = ({ return ( = ({ id="name" name="name" value={currentReport?.name || ''} - placeholder="Weekly Report" + placeholder={t('Weekly Report')} required validationMethods={{ onChange: ({ target }: { target: HTMLInputElement }) => - onChange(ActionType.inputChange, { + onReducerChange(ActionType.inputChange, { name: target.name, value: target.value, }), }} - errorMessage={ - currentReport?.name === 'error' ? t('REPORT NAME ERROR') : '' - } + errorMessage={currentReport?.error || ''} label="Report Name" data-test="report-name-test" /> @@ -338,16 +349,16 @@ const ReportModal: FunctionComponent = ({ value={currentReport?.description || ''} validationMethods={{ onChange: ({ target }: { target: HTMLInputElement }) => - onChange(ActionType.inputChange, { + onReducerChange(ActionType.inputChange, { name: target.name, value: target.value, }), }} - errorMessage={ - currentReport?.description === 'error' ? t('DESCRIPTION ERROR') : '' - } - label="Description" - placeholder="Include a description that will be sent with your report" + errorMessage="" + label={t('Description')} + placeholder={t( + 'Include a description that will be sent with your report', + )} css={noBottomMargin} data-test="report-description-test" /> @@ -363,16 +374,16 @@ const ReportModal: FunctionComponent = ({ { - onChange(ActionType.inputChange, { + onReducerChange(ActionType.inputChange, { name: 'crontab', value: newValue, }); }} - onError={setError} + onError={setCronError} /> - {error} + {cronError}
TimezoneHeaderStyle(theme)} diff --git a/superset-frontend/src/reports/actions/reports.js b/superset-frontend/src/reports/actions/reports.js index 345cfa1e40644..8f23e283522df 100644 --- a/superset-frontend/src/reports/actions/reports.js +++ b/superset-frontend/src/reports/actions/reports.js @@ -19,7 +19,6 @@ /* eslint camelcase: 0 */ import { t, SupersetClient } from '@superset-ui/core'; import rison from 'rison'; -import { getClientErrorObject } from 'src/utils/getClientErrorObject'; import { addDangerToast, addSuccessToast, @@ -105,22 +104,10 @@ export const addReport = report => dispatch => SupersetClient.post({ endpoint: `/api/v1/report/`, jsonPayload: report, - }) - .then(({ json }) => { - dispatch({ type: ADD_REPORT, json }); - dispatch(addSuccessToast(t('The report has been created'))); - }) - .catch(async e => { - const parsedError = await getClientErrorObject(e); - const errorMessage = parsedError.message; - const errorArr = Object.keys(errorMessage); - const error = errorMessage[errorArr[0]]; - dispatch( - addDangerToast( - t('An error occurred while editing this report: %s', error), - ), - ); - }); + }).then(({ json }) => { + dispatch({ type: ADD_REPORT, json }); + dispatch(addSuccessToast(t('The report has been created'))); + }); export const EDIT_REPORT = 'EDIT_REPORT';