mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 14:57:18 +10:00
Refactor LoginForm: use Form connector from Final Form
This commit is contained in:
parent
15fabc7ec8
commit
9cd15f1908
5 changed files with 110 additions and 102 deletions
|
|
@ -79,7 +79,7 @@ exports[`AuthenticationPageComponent matches snapshot 1`] = `
|
|||
]
|
||||
}
|
||||
/>
|
||||
<ReduxForm
|
||||
<LoginForm
|
||||
inProgress={false}
|
||||
onSubmit={[Function]}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import LoginForm from './LoginForm';
|
|||
export const Empty = {
|
||||
component: LoginForm,
|
||||
props: {
|
||||
formId: 'LoginFormExample',
|
||||
onSubmit(values) {
|
||||
console.log('log in with form values:', values);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,123 +2,131 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { compose } from 'redux';
|
||||
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
||||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import { Form as FinalForm } from 'react-final-form';
|
||||
import classNames from 'classnames';
|
||||
import { Form, PrimaryButton, TextInputField, NamedLink } from '../../components';
|
||||
import { Form, PrimaryButton, FieldTextInput, NamedLink } from '../../components';
|
||||
import * as validators from '../../util/validators';
|
||||
|
||||
import css from './LoginForm.css';
|
||||
|
||||
const LoginFormComponent = props => {
|
||||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
form,
|
||||
handleSubmit,
|
||||
submitting,
|
||||
inProgress,
|
||||
intl,
|
||||
invalid,
|
||||
} = props;
|
||||
const LoginFormComponent = props => (
|
||||
<FinalForm
|
||||
{...props}
|
||||
render={fieldRenderProps => {
|
||||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
formId,
|
||||
handleSubmit,
|
||||
submitting,
|
||||
inProgress,
|
||||
intl,
|
||||
invalid,
|
||||
} = fieldRenderProps;
|
||||
|
||||
// email
|
||||
const emailLabel = intl.formatMessage({
|
||||
id: 'LoginForm.emailLabel',
|
||||
});
|
||||
const emailPlaceholder = intl.formatMessage({
|
||||
id: 'LoginForm.emailPlaceholder',
|
||||
});
|
||||
const emailRequiredMessage = intl.formatMessage({
|
||||
id: 'LoginForm.emailRequired',
|
||||
});
|
||||
const emailRequired = validators.required(emailRequiredMessage);
|
||||
const emailInvalidMessage = intl.formatMessage({
|
||||
id: 'LoginForm.emailInvalid',
|
||||
});
|
||||
const emailValid = validators.emailFormatValid(emailInvalidMessage);
|
||||
// email
|
||||
const emailLabel = intl.formatMessage({
|
||||
id: 'LoginForm.emailLabel',
|
||||
});
|
||||
const emailPlaceholder = intl.formatMessage({
|
||||
id: 'LoginForm.emailPlaceholder',
|
||||
});
|
||||
const emailRequiredMessage = intl.formatMessage({
|
||||
id: 'LoginForm.emailRequired',
|
||||
});
|
||||
const emailRequired = validators.required(emailRequiredMessage);
|
||||
const emailInvalidMessage = intl.formatMessage({
|
||||
id: 'LoginForm.emailInvalid',
|
||||
});
|
||||
const emailValid = validators.emailFormatValid(emailInvalidMessage);
|
||||
|
||||
// password
|
||||
const passwordLabel = intl.formatMessage({
|
||||
id: 'LoginForm.passwordLabel',
|
||||
});
|
||||
const passwordPlaceholder = intl.formatMessage({
|
||||
id: 'LoginForm.passwordPlaceholder',
|
||||
});
|
||||
const passwordRequiredMessage = intl.formatMessage({
|
||||
id: 'LoginForm.passwordRequired',
|
||||
});
|
||||
const passwordRequired = validators.requiredStringNoTrim(passwordRequiredMessage);
|
||||
// password
|
||||
const passwordLabel = intl.formatMessage({
|
||||
id: 'LoginForm.passwordLabel',
|
||||
});
|
||||
const passwordPlaceholder = intl.formatMessage({
|
||||
id: 'LoginForm.passwordPlaceholder',
|
||||
});
|
||||
const passwordRequiredMessage = intl.formatMessage({
|
||||
id: 'LoginForm.passwordRequired',
|
||||
});
|
||||
const passwordRequired = validators.requiredStringNoTrim(passwordRequiredMessage);
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const submitInProgress = submitting || inProgress;
|
||||
const submitDisabled = invalid || submitInProgress;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const submitInProgress = submitting || inProgress;
|
||||
const submitDisabled = invalid || submitInProgress;
|
||||
|
||||
const passwordRecoveryLink = (
|
||||
<NamedLink name="PasswordRecoveryPage" className={css.recoveryLink}>
|
||||
<FormattedMessage id="LoginForm.forgotPassword" />
|
||||
</NamedLink>
|
||||
);
|
||||
const passwordRecoveryLink = (
|
||||
<NamedLink name="PasswordRecoveryPage" className={css.recoveryLink}>
|
||||
<FormattedMessage id="LoginForm.forgotPassword" />
|
||||
</NamedLink>
|
||||
);
|
||||
|
||||
return (
|
||||
<Form className={classes} onSubmit={handleSubmit}>
|
||||
<div>
|
||||
<TextInputField
|
||||
type="email"
|
||||
name="email"
|
||||
autoComplete="email"
|
||||
id={`${form}.email`}
|
||||
label={emailLabel}
|
||||
placeholder={emailPlaceholder}
|
||||
validate={[emailRequired, emailValid]}
|
||||
/>
|
||||
<TextInputField
|
||||
className={css.password}
|
||||
type="password"
|
||||
name="password"
|
||||
autoComplete="current-password"
|
||||
id={`${form}.password`}
|
||||
label={passwordLabel}
|
||||
placeholder={passwordPlaceholder}
|
||||
validate={passwordRequired}
|
||||
/>
|
||||
</div>
|
||||
<div className={css.bottomWrapper}>
|
||||
<p className={css.bottomWrapperText}>
|
||||
<span className={css.recoveryLinkInfo}>
|
||||
<FormattedMessage id="LoginForm.forgotPasswordInfo" values={{ passwordRecoveryLink }} />
|
||||
</span>
|
||||
</p>
|
||||
<PrimaryButton
|
||||
className={css.submitButton}
|
||||
type="submit"
|
||||
inProgress={submitInProgress}
|
||||
disabled={submitDisabled}
|
||||
>
|
||||
<FormattedMessage id="LoginForm.logIn" />
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Form className={classes} onSubmit={handleSubmit}>
|
||||
<div>
|
||||
<FieldTextInput
|
||||
type="email"
|
||||
id={formId ? `${formId}.email` : 'email'}
|
||||
name="email"
|
||||
autoComplete="email"
|
||||
label={emailLabel}
|
||||
placeholder={emailPlaceholder}
|
||||
validate={validators.composeValidators(emailRequired, emailValid)}
|
||||
/>
|
||||
<FieldTextInput
|
||||
className={css.password}
|
||||
type="password"
|
||||
id={formId ? `${formId}.password` : 'password'}
|
||||
name="password"
|
||||
autoComplete="current-password"
|
||||
label={passwordLabel}
|
||||
placeholder={passwordPlaceholder}
|
||||
validate={passwordRequired}
|
||||
/>
|
||||
</div>
|
||||
<div className={css.bottomWrapper}>
|
||||
<p className={css.bottomWrapperText}>
|
||||
<span className={css.recoveryLinkInfo}>
|
||||
<FormattedMessage
|
||||
id="LoginForm.forgotPasswordInfo"
|
||||
values={{ passwordRecoveryLink }}
|
||||
/>
|
||||
</span>
|
||||
</p>
|
||||
<PrimaryButton
|
||||
className={css.submitButton}
|
||||
type="submit"
|
||||
inProgress={submitInProgress}
|
||||
disabled={submitDisabled}
|
||||
>
|
||||
<FormattedMessage id="LoginForm.logIn" />
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
LoginFormComponent.defaultProps = {
|
||||
rootClassName: null,
|
||||
className: null,
|
||||
form: null,
|
||||
inProgress: false,
|
||||
};
|
||||
|
||||
const { string, bool } = PropTypes;
|
||||
|
||||
LoginFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
form: string,
|
||||
inProgress: bool,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
const defaultFormName = 'LoginForm';
|
||||
|
||||
const LoginForm = compose(reduxForm({ form: defaultFormName }), injectIntl)(LoginFormComponent);
|
||||
const LoginForm = compose(injectIntl)(LoginFormComponent);
|
||||
LoginForm.displayName = 'LoginForm';
|
||||
|
||||
export default LoginForm;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import React from 'react';
|
||||
import { renderDeep } from '../../util/test-helpers';
|
||||
import { fakeIntl } from '../../util/test-data';
|
||||
import LoginForm from './LoginForm';
|
||||
|
||||
const noop = () => null;
|
||||
|
||||
describe('LoginForm', () => {
|
||||
it('matches snapshot', () => {
|
||||
const tree = renderDeep(<LoginForm />);
|
||||
const tree = renderDeep(<LoginForm intl={fakeIntl} onSubmit={noop} />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,19 +12,17 @@ exports[`LoginForm matches snapshot 1`] = `
|
|||
className=""
|
||||
>
|
||||
<label
|
||||
htmlFor="LoginForm.email"
|
||||
htmlFor="email"
|
||||
>
|
||||
LoginForm.emailLabel
|
||||
</label>
|
||||
<input
|
||||
autoComplete="email"
|
||||
className=""
|
||||
id="LoginForm.email"
|
||||
id="email"
|
||||
name="email"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onDragStart={[Function]}
|
||||
onDrop={[Function]}
|
||||
onFocus={[Function]}
|
||||
placeholder="LoginForm.emailPlaceholder"
|
||||
type="email"
|
||||
|
|
@ -35,19 +33,17 @@ exports[`LoginForm matches snapshot 1`] = `
|
|||
className=""
|
||||
>
|
||||
<label
|
||||
htmlFor="LoginForm.password"
|
||||
htmlFor="password"
|
||||
>
|
||||
LoginForm.passwordLabel
|
||||
</label>
|
||||
<input
|
||||
autoComplete="current-password"
|
||||
className=""
|
||||
id="LoginForm.password"
|
||||
id="password"
|
||||
name="password"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onDragStart={[Function]}
|
||||
onDrop={[Function]}
|
||||
onFocus={[Function]}
|
||||
placeholder="LoginForm.passwordPlaceholder"
|
||||
type="password"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue