diff --git a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx index 7aecba1eb2..a4511f4e10 100644 --- a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx +++ b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx @@ -1,11 +1,15 @@ import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; +import { t } from '@lingui/macro'; +import { withI18n } from '@lingui/react'; import { Card } from '@patternfly/react-core'; import { CardBody } from '@components/Card'; +import ErrorDetail from '@components/ErrorDetail'; +import AlertModal from '@components/AlertModal'; import JobTemplateForm from '../shared/JobTemplateForm'; import { JobTemplatesAPI } from '@api'; -function JobTemplateAdd() { +function JobTemplateAdd({ i18n }) { const [formSubmitError, setFormSubmitError] = useState(null); const history = useHistory(); @@ -31,6 +35,10 @@ function JobTemplateAdd() { ]); history.push(`/templates/${type}/${id}/details`); } catch (error) { + // check for field-specific errors from API + if (error.response?.data && typeof error.response.data === 'object') { + throw error.response.data; + } setFormSubmitError(error); } } @@ -68,9 +76,19 @@ function JobTemplateAdd() { handleSubmit={handleSubmit} /> - {formSubmitError ?
formSubmitError
: ''} + {formSubmitError && ( + setFormSubmitError(null)} + > + {i18n._(t`An error occurred when saving`)} + + + )} ); } -export default JobTemplateAdd; +export default withI18n()(JobTemplateAdd); diff --git a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx index 73d90a8a26..07e1085936 100644 --- a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx +++ b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx @@ -1,9 +1,13 @@ /* eslint react/no-unused-state: 0 */ import React, { Component } from 'react'; import { withRouter, Redirect } from 'react-router-dom'; +import { t } from '@lingui/macro'; +import { withI18n } from '@lingui/react'; import { CardBody } from '@components/Card'; import ContentError from '@components/ContentError'; import ContentLoading from '@components/ContentLoading'; +import ErrorDetail from '@components/ErrorDetail'; +import AlertModal from '@components/AlertModal'; import { JobTemplatesAPI, ProjectsAPI } from '@api'; import { JobTemplate } from '@types'; import { getAddedAndRemoved } from '@util/lists'; @@ -113,8 +117,12 @@ class JobTemplateEdit extends Component { this.submitCredentials(credentials), ]); history.push(this.detailsUrl); - } catch (formSubmitError) { - this.setState({ formSubmitError }); + } catch (error) { + // check for field-specific errors from API + if (error.response?.data && typeof error.response.data === 'object') { + throw error.response.data; + } + this.setState({ formSubmitError: error }); } } @@ -173,7 +181,7 @@ class JobTemplateEdit extends Component { } render() { - const { template } = this.props; + const { template, i18n } = this.props; const { contentError, formSubmitError, @@ -210,10 +218,20 @@ class JobTemplateEdit extends Component { handleSubmit={this.handleSubmit} relatedProjectPlaybooks={relatedProjectPlaybooks} /> - {formSubmitError ?
error
: null} + {formSubmitError && ( + this.setState({ formSubmitError: null })} + > + {i18n._(t`An error occurred when saving`)} + + + )} ); } } -export default withRouter(JobTemplateEdit); +export default withI18n()(withRouter(JobTemplateEdit)); diff --git a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx index c2f1ca9c4c..19973cfdd5 100644 --- a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx +++ b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx @@ -163,6 +163,7 @@ class JobTemplateForm extends Component { setFieldValue, i18n, template, + formik, } = this.props; const jobTypeOptions = [ @@ -631,7 +632,13 @@ const FormikApp = withFormik({ credentials: summary_fields.credentials || [], }; }, - handleSubmit: (values, { props }) => props.handleSubmit(values), + handleSubmit: async (values, { props, setErrors }) => { + try { + await props.handleSubmit(values); + } catch (errors) { + setErrors(errors); + } + }, })(JobTemplateForm); export { JobTemplateForm as _JobTemplateForm };