fix(report-add): make to add error toast message when already attached report is added again into dashboard or chart (#19122)

* fix(report-add): make to add error toast message when already attached report is added again into dashboard or chart

* fix(export-add): make to setup the default error message

* fix(report-add): make to allow the errorMessage undefined in LabeledErrorBoundInput component
This commit is contained in:
smileydev 2022-03-24 19:18:34 -04:00 committed by GitHub
parent 8947eb9680
commit cb0357005e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 12 deletions

View File

@ -29,7 +29,7 @@ export interface LabeledErrorBoundInputProps {
validationMethods: validationMethods:
| { onBlur: (value: any) => void } | { onBlur: (value: any) => void }
| { onChange: (value: any) => void }; | { onChange: (value: any) => void };
errorMessage: string | null; errorMessage?: string | null;
helpText?: string; helpText?: string;
required?: boolean; required?: boolean;
hasTooltip?: boolean; hasTooltip?: boolean;

View File

@ -31,6 +31,7 @@ import { connect, useDispatch, useSelector } from 'react-redux';
import { addReport, editReport } from 'src/reports/actions/reports'; import { addReport, editReport } from 'src/reports/actions/reports';
import { AlertObject } from 'src/views/CRUD/alert/types'; import { AlertObject } from 'src/views/CRUD/alert/types';
import Alert from 'src/components/Alert';
import TimezoneSelector from 'src/components/TimezoneSelector'; import TimezoneSelector from 'src/components/TimezoneSelector';
import LabeledErrorBoundInput from 'src/components/Form/LabeledErrorBoundInput'; import LabeledErrorBoundInput from 'src/components/Form/LabeledErrorBoundInput';
import Icons from 'src/components/Icons'; import Icons from 'src/components/Icons';
@ -38,6 +39,7 @@ import withToasts from 'src/components/MessageToasts/withToasts';
import { CronError } from 'src/components/CronPicker'; import { CronError } from 'src/components/CronPicker';
import { RadioChangeEvent } from 'src/components'; import { RadioChangeEvent } from 'src/components';
import { import {
antDErrorAlertStyles,
StyledModal, StyledModal,
StyledTopSection, StyledTopSection,
StyledBottomSection, StyledBottomSection,
@ -73,7 +75,7 @@ export interface ReportObject {
working_timeout: number; working_timeout: number;
creation_method: string; creation_method: string;
force_screenshot: boolean; force_screenshot: boolean;
error?: string; error: string;
} }
interface ChartObject { interface ChartObject {
@ -93,6 +95,7 @@ interface ReportProps {
addReport: (report?: ReportObject) => {}; addReport: (report?: ReportObject) => {};
onHide: () => {}; onHide: () => {};
onReportAdd: (report?: ReportObject) => {}; onReportAdd: (report?: ReportObject) => {};
addDangerToast: (msg: string) => void;
show: boolean; show: boolean;
userId: number; userId: number;
userEmail: string; userEmail: string;
@ -128,9 +131,7 @@ type ReportActionType =
} }
| { | {
type: ActionType.error; type: ActionType.error;
payload: { payload: { name: string[] };
name: string[];
};
}; };
const TEXT_BASED_VISUALIZATION_TYPES = [ const TEXT_BASED_VISUALIZATION_TYPES = [
@ -146,6 +147,10 @@ const NOTIFICATION_FORMATS = {
CSV: 'CSV', CSV: 'CSV',
}; };
const defaultErrorMsg = t(
'We were unable to create your report. Please try again.',
);
const reportReducer = ( const reportReducer = (
state: Partial<ReportObject> | null, state: Partial<ReportObject> | null,
action: ReportActionType, action: ReportActionType,
@ -171,7 +176,7 @@ const reportReducer = (
case ActionType.error: case ActionType.error:
return { return {
...state, ...state,
error: action.payload.name[0], error: action.payload?.name[0] || defaultErrorMsg,
}; };
default: default:
return state; return state;
@ -250,9 +255,8 @@ const ReportModal: FunctionComponent<ReportProps> = ({
await dispatch(addReport(newReportValues as ReportObject)); await dispatch(addReport(newReportValues as ReportObject));
onHide(); onHide();
} catch (e) { } catch (e) {
const parsedError = await getClientErrorObject(e); const { message } = await getClientErrorObject(e);
const errorMessage = parsedError.message; onReducerChange(ActionType.error, message);
onReducerChange(ActionType.error, errorMessage);
} }
} }
@ -315,6 +319,15 @@ const ReportModal: FunctionComponent<ReportProps> = ({
</> </>
); );
const errorAlert = () => (
<Alert
type="error"
css={(theme: SupersetTheme) => antDErrorAlertStyles(theme)}
message={t('Report Creation Error')}
description={currentReport?.error}
/>
);
return ( return (
<StyledModal <StyledModal
show={show} show={show}
@ -338,11 +351,9 @@ const ReportModal: FunctionComponent<ReportProps> = ({
value: target.value, value: target.value,
}), }),
}} }}
errorMessage={currentReport?.error || ''}
label="Report Name" label="Report Name"
data-test="report-name-test" data-test="report-name-test"
/> />
<LabeledErrorBoundInput <LabeledErrorBoundInput
id="description" id="description"
name="description" name="description"
@ -354,7 +365,6 @@ const ReportModal: FunctionComponent<ReportProps> = ({
value: target.value, value: target.value,
}), }),
}} }}
errorMessage=""
label={t('Description')} label={t('Description')}
placeholder={t( placeholder={t(
'Include a description that will be sent with your report', 'Include a description that will be sent with your report',
@ -401,6 +411,7 @@ const ReportModal: FunctionComponent<ReportProps> = ({
/> />
{isChart && renderMessageContentSection} {isChart && renderMessageContentSection}
</StyledBottomSection> </StyledBottomSection>
{currentReport?.error && errorAlert()}
</StyledModal> </StyledModal>
); );
}; };

View File

@ -106,3 +106,24 @@ export const StyledRadio = styled(Radio)`
export const StyledRadioGroup = styled(Radio.Group)` export const StyledRadioGroup = styled(Radio.Group)`
margin-left: ${({ theme }) => theme.gridUnit * 0.5}px; margin-left: ${({ theme }) => theme.gridUnit * 0.5}px;
`; `;
export const antDErrorAlertStyles = (theme: SupersetTheme) => css`
border: ${theme.colors.error.base} 1px solid;
padding: ${theme.gridUnit * 4}px;
margin: ${theme.gridUnit * 8}px ${theme.gridUnit * 4}px;
color: ${theme.colors.error.dark2};
.ant-alert-message {
font-size: ${theme.typography.sizes.s + 1}px;
font-weight: bold;
}
.ant-alert-description {
font-size: ${theme.typography.sizes.s + 1}px;
line-height: ${theme.gridUnit * 4}px;
.ant-alert-icon {
margin-right: ${theme.gridUnit * 2.5}px;
font-size: ${theme.typography.sizes.l + 1}px;
position: relative;
top: ${theme.gridUnit / 4}px;
}
}
`;