handle __all__ error message from server in FormSubmitError

This commit is contained in:
Keith Grant
2020-02-05 16:29:17 -08:00
parent 44e4263bee
commit ac376f9c87
4 changed files with 29 additions and 55 deletions

View File

@@ -18,8 +18,13 @@ function FormSubmitError({ error }) {
} }
// check for field-specific errors from API // check for field-specific errors from API
if (error.response?.data && typeof error.response.data === 'object') { if (error.response?.data && typeof error.response.data === 'object') {
setErrors(error.response.data); const errorMessages = error.response.data;
setFormError(null); setErrors(errorMessages);
if (errorMessages.__all__) {
setFormError({ message: errorMessages.__all__ });
} else {
setFormError(null);
}
} else { } else {
/* eslint-disable-next-line no-console */ /* eslint-disable-next-line no-console */
console.error(error); console.error(error);

View File

@@ -1,14 +1,10 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useHistory, useRouteMatch } from 'react-router-dom'; import { useHistory, useRouteMatch } from 'react-router-dom';
import { t } from '@lingui/macro';
import { withI18n } from '@lingui/react';
import { CardBody } from '@components/Card'; import { CardBody } from '@components/Card';
import ErrorDetail from '@components/ErrorDetail';
import AlertModal from '@components/AlertModal';
import { HostsAPI } from '@api'; import { HostsAPI } from '@api';
import HostForm from '../shared'; import HostForm from '../shared';
function HostAdd({ i18n }) { function HostAdd() {
const [formError, setFormError] = useState(null); const [formError, setFormError] = useState(null);
const history = useHistory(); const history = useHistory();
const hostsMatch = useRouteMatch('/hosts'); const hostsMatch = useRouteMatch('/hosts');
@@ -27,10 +23,6 @@ function HostAdd({ i18n }) {
const { data: response } = await HostsAPI.create(values); const { data: response } = await HostsAPI.create(values);
history.push(`${url}/${response.id}/details`); history.push(`${url}/${response.id}/details`);
} catch (error) { } catch (error) {
// check for field-specific errors from API
if (error.response?.data && typeof error.response.data === 'object') {
throw error.response.data;
}
setFormError(error); setFormError(error);
} }
}; };
@@ -41,20 +33,13 @@ function HostAdd({ i18n }) {
return ( return (
<CardBody> <CardBody>
<HostForm handleSubmit={handleSubmit} handleCancel={handleCancel} /> <HostForm
{formError && ( handleSubmit={handleSubmit}
<AlertModal handleCancel={handleCancel}
variant="danger" submitError={formError}
title={i18n._(t`Error!`)} />
isOpen={formError}
onClose={() => setFormError(null)}
>
{i18n._(t`An error occurred when saving Host`)}
<ErrorDetail error={formError} />
</AlertModal>
)}
</CardBody> </CardBody>
); );
} }
export default withI18n()(HostAdd); export default HostAdd;

View File

@@ -1,15 +1,11 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useHistory, useRouteMatch } from 'react-router-dom'; import { useHistory, useRouteMatch } from 'react-router-dom';
import { t } from '@lingui/macro';
import { withI18n } from '@lingui/react';
import { CardBody } from '@components/Card'; import { CardBody } from '@components/Card';
import ErrorDetail from '@components/ErrorDetail';
import AlertModal from '@components/AlertModal';
import { HostsAPI } from '@api'; import { HostsAPI } from '@api';
import HostForm from '../shared'; import HostForm from '../shared';
function HostEdit({ host, i18n }) { function HostEdit({ host }) {
const [formError, setFormError] = useState(null); const [formError, setFormError] = useState(null);
const hostsMatch = useRouteMatch('/hosts/:id/edit'); const hostsMatch = useRouteMatch('/hosts/:id/edit');
const inventoriesMatch = useRouteMatch( const inventoriesMatch = useRouteMatch(
@@ -35,13 +31,15 @@ function HostEdit({ host, i18n }) {
await HostsAPI.update(host.id, values); await HostsAPI.update(host.id, values);
history.push(detailsUrl); history.push(detailsUrl);
} catch (error) { } catch (error) {
// check for field-specific errors from API console.log('caught:', error);
if (error.response?.data && typeof error.response.data === 'object') { // // check for field-specific errors from API
throw error.response.data; // if (error.response?.data && typeof error.response.data === 'object') {
} // throw error.response.data;
// }
setFormError(error); setFormError(error);
} }
}; };
console.log('render:', formError);
const handleCancel = () => { const handleCancel = () => {
history.push(detailsUrl); history.push(detailsUrl);
@@ -53,18 +51,8 @@ function HostEdit({ host, i18n }) {
host={host} host={host}
handleSubmit={handleSubmit} handleSubmit={handleSubmit}
handleCancel={handleCancel} handleCancel={handleCancel}
submitError={formError}
/> />
{formError && (
<AlertModal
variant="danger"
title={i18n._(t`Error!`)}
isOpen={formError}
onClose={() => setFormError(null)}
>
{i18n._(t`An error occurred when saving Host`)}
<ErrorDetail error={formError} />
</AlertModal>
)}
</CardBody> </CardBody>
); );
} }
@@ -73,5 +61,4 @@ HostEdit.propTypes = {
host: PropTypes.shape().isRequired, host: PropTypes.shape().isRequired,
}; };
export { HostEdit as _HostEdit }; export default HostEdit;
export default withI18n()(HostEdit);

View File

@@ -9,13 +9,13 @@ import { t } from '@lingui/macro';
import { Form } from '@patternfly/react-core'; import { Form } from '@patternfly/react-core';
import FormRow from '@components/FormRow'; import FormRow from '@components/FormRow';
import FormField from '@components/FormField'; import FormField, { FormSubmitError } from '@components/FormField';
import FormActionGroup from '@components/FormActionGroup/FormActionGroup'; import FormActionGroup from '@components/FormActionGroup/FormActionGroup';
import { VariablesField } from '@components/CodeMirrorInput'; import { VariablesField } from '@components/CodeMirrorInput';
import { required } from '@util/validators'; import { required } from '@util/validators';
import { InventoryLookup } from '@components/Lookup'; import { InventoryLookup } from '@components/Lookup';
function HostForm({ handleSubmit, handleCancel, host, i18n }) { function HostForm({ handleSubmit, handleCancel, host, submitError, i18n }) {
const [inventory, setInventory] = useState( const [inventory, setInventory] = useState(
host ? host.summary_fields.inventory : '' host ? host.summary_fields.inventory : ''
); );
@@ -30,13 +30,7 @@ function HostForm({ handleSubmit, handleCancel, host, i18n }) {
inventory: host.inventory || '', inventory: host.inventory || '',
variables: host.variables, variables: host.variables,
}} }}
onSubmit={async (values, formik) => { onSubmit={handleSubmit}
try {
await handleSubmit(values);
} catch (errors) {
formik.setErrors(errors);
}
}}
> >
{formik => ( {formik => (
<Form autoComplete="off" onSubmit={formik.handleSubmit}> <Form autoComplete="off" onSubmit={formik.handleSubmit}>
@@ -94,6 +88,7 @@ function HostForm({ handleSubmit, handleCancel, host, i18n }) {
<FormActionGroup <FormActionGroup
onCancel={handleCancel} onCancel={handleCancel}
onSubmit={formik.handleSubmit} onSubmit={formik.handleSubmit}
errorMessage={<FormSubmitError error={submitError} />}
/> />
</Form> </Form>
)} )}
@@ -105,6 +100,7 @@ HostForm.propTypes = {
handleSubmit: func.isRequired, handleSubmit: func.isRequired,
handleCancel: func.isRequired, handleCancel: func.isRequired,
host: shape({}), host: shape({}),
submitError: shape({}),
}; };
HostForm.defaultProps = { HostForm.defaultProps = {
@@ -117,6 +113,7 @@ HostForm.defaultProps = {
inventory: null, inventory: null,
}, },
}, },
submitError: null,
}; };
export { HostForm as _HostForm }; export { HostForm as _HostForm };