mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 01:47:35 -02:30
move FormSubmitError to inline beside form buttons; add tests
This commit is contained in:
@@ -1,9 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import styled from 'styled-components';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { ActionGroup as PFActionGroup, Button } from '@patternfly/react-core';
|
import { ActionGroup as PFActionGroup, Button } from '@patternfly/react-core';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
const ErrorMessage = styled('div')`
|
||||||
|
color: var(--pf-global--danger-color--200);
|
||||||
|
font-weight: var(--pf-global--FontWeight--bold);
|
||||||
|
`;
|
||||||
|
|
||||||
const ActionGroup = styled(PFActionGroup)`
|
const ActionGroup = styled(PFActionGroup)`
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -11,19 +16,25 @@ const ActionGroup = styled(PFActionGroup)`
|
|||||||
--pf-c-form__group--m-action--MarginTop: 0;
|
--pf-c-form__group--m-action--MarginTop: 0;
|
||||||
|
|
||||||
.pf-c-form__actions {
|
.pf-c-form__actions {
|
||||||
display: grid;
|
|
||||||
gap: 24px;
|
|
||||||
grid-template-columns: auto auto;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
& > button {
|
& > button {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& > :not(:first-child) {
|
||||||
|
margin-left: 24px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const FormActionGroup = ({ onSubmit, submitDisabled, onCancel, i18n }) => (
|
const FormActionGroup = ({
|
||||||
|
onSubmit,
|
||||||
|
submitDisabled,
|
||||||
|
onCancel,
|
||||||
|
errorMessage,
|
||||||
|
i18n,
|
||||||
|
}) => (
|
||||||
<ActionGroup>
|
<ActionGroup>
|
||||||
|
{errorMessage ? <ErrorMessage>{errorMessage}</ErrorMessage> : null}
|
||||||
<Button
|
<Button
|
||||||
aria-label={i18n._(t`Save`)}
|
aria-label={i18n._(t`Save`)}
|
||||||
variant="primary"
|
variant="primary"
|
||||||
@@ -48,10 +59,12 @@ FormActionGroup.propTypes = {
|
|||||||
onCancel: PropTypes.func.isRequired,
|
onCancel: PropTypes.func.isRequired,
|
||||||
onSubmit: PropTypes.func.isRequired,
|
onSubmit: PropTypes.func.isRequired,
|
||||||
submitDisabled: PropTypes.bool,
|
submitDisabled: PropTypes.bool,
|
||||||
|
errorMessage: PropTypes.node,
|
||||||
};
|
};
|
||||||
|
|
||||||
FormActionGroup.defaultProps = {
|
FormActionGroup.defaultProps = {
|
||||||
submitDisabled: false,
|
submitDisabled: false,
|
||||||
|
errorMessage: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withI18n()(FormActionGroup);
|
export default withI18n()(FormActionGroup);
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
import { t } from '@lingui/macro';
|
|
||||||
import { withI18n } from '@lingui/react';
|
|
||||||
import ErrorDetail from '@components/ErrorDetail';
|
|
||||||
import AlertModal from '@components/AlertModal';
|
|
||||||
|
|
||||||
function FormSubmitError({ error, i18n }) {
|
function FormSubmitError({ error }) {
|
||||||
const [formError, setFormError] = useState(null);
|
const [formError, setFormError] = useState(null);
|
||||||
const { setErrors } = useFormikContext();
|
const { setErrors } = useFormikContext();
|
||||||
|
|
||||||
@@ -18,6 +14,8 @@ function FormSubmitError({ error, i18n }) {
|
|||||||
setErrors(error.response.data);
|
setErrors(error.response.data);
|
||||||
setFormError(null);
|
setFormError(null);
|
||||||
} else {
|
} else {
|
||||||
|
/* eslint-disable-next-line no-console */
|
||||||
|
console.error(error);
|
||||||
setFormError(error);
|
setFormError(error);
|
||||||
}
|
}
|
||||||
}, [error, setErrors]);
|
}, [error, setErrors]);
|
||||||
@@ -26,17 +24,7 @@ function FormSubmitError({ error, i18n }) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <span>{formError.message}</span>;
|
||||||
<AlertModal
|
|
||||||
variant="danger"
|
|
||||||
title={i18n._(t`Error!`)}
|
|
||||||
isOpen={formError}
|
|
||||||
onClose={() => setFormError(null)}
|
|
||||||
>
|
|
||||||
{i18n._(t`An error occurred when saving`)}
|
|
||||||
<ErrorDetail error={formError} />
|
|
||||||
</AlertModal>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withI18n()(FormSubmitError);
|
export default FormSubmitError;
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||||
|
import { Formik } from 'formik';
|
||||||
|
import FormSubmitError from './FormSubmitError';
|
||||||
|
|
||||||
|
describe('<FormSubmitError>', () => {
|
||||||
|
test('should render null when no error present', () => {
|
||||||
|
const wrapper = mountWithContexts(
|
||||||
|
<Formik>{() => <FormSubmitError error={null} />}</Formik>
|
||||||
|
);
|
||||||
|
expect(wrapper.find('FormSubmitError').text()).toEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should pass field errors to Formik', () => {
|
||||||
|
const error = {
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
name: 'invalid',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const wrapper = mountWithContexts(
|
||||||
|
<Formik>
|
||||||
|
{({ errors }) => (
|
||||||
|
<div>
|
||||||
|
<p>{errors.name}</p>
|
||||||
|
<FormSubmitError error={error} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
);
|
||||||
|
expect(wrapper.find('p').text()).toEqual('invalid');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should display error message if field errors not provided', async () => {
|
||||||
|
const realConsole = global.console;
|
||||||
|
global.console = {
|
||||||
|
error: jest.fn(),
|
||||||
|
};
|
||||||
|
const error = {
|
||||||
|
message: 'There was an error',
|
||||||
|
};
|
||||||
|
let wrapper;
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<Formik>{() => <FormSubmitError error={error} />}</Formik>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(wrapper.text()).toEqual('There was an error');
|
||||||
|
expect(global.console.error).toHaveBeenCalledWith(error);
|
||||||
|
global.console = realConsole;
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -593,8 +593,11 @@ class JobTemplateForm extends Component {
|
|||||||
</FormRow>
|
</FormRow>
|
||||||
</div>
|
</div>
|
||||||
</AdvancedFieldsWrapper>
|
</AdvancedFieldsWrapper>
|
||||||
<FormActionGroup onCancel={handleCancel} onSubmit={handleSubmit} />
|
<FormActionGroup
|
||||||
<FormSubmitError error={submitError} />
|
onCancel={handleCancel}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
errorMessage={<FormSubmitError error={submitError} />}
|
||||||
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user