UNPKG

cspace-ui

Version:
205 lines (173 loc) 6.03 kB
/* global window, FormData */ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { Helmet } from 'react-helmet'; import { defineMessages, FormattedMessage, injectIntl, intlShape, } from 'react-intl'; import { isValidEmail } from '../../../helpers/validationHelpers'; const messages = defineMessages({ title: { id: 'passwordResetRequestPage.title', description: 'Title of the password reset request page.', defaultMessage: 'Reset Password', }, prompt: { id: 'passwordResetRequestPage.prompt', description: 'The prompt displayed on the password reset request page.', defaultMessage: 'Please enter your email address to request a password reset.', }, email: { id: 'passwordResetRequestPage.email', description: 'Label for the email field on the password reset request page.', defaultMessage: 'Email', }, submit: { id: 'passwordResetRequestPage.submit', description: 'Label for the submit button on the password reset request page.', defaultMessage: 'Submit', }, success: { id: 'passwordResetRequestPage.success', description: 'Message displayed when a password reset has been successfully requested.', defaultMessage: 'An email has been sent to {email}. Follow the instructions in the email to finish resetting your password.', }, error: { id: 'passwordResetRequestPage.error', description: 'Generic message to display when a password reset request fails, and no more specific message is available.', defaultMessage: 'An error occurred while attempting to request the password reset: {detail}', }, errorNotFound: { id: 'passwordResetRequestPage.errorNotFound', description: 'Message to display when the email is not found for a password reset request.', defaultMessage: 'Could not find an account with the email {email}.', }, errorMissingEmail: { id: 'passwordResetRequestPage.errorMissingEmail', description: 'Message to display when no email is entered on the password reset request page.', defaultMessage: 'Please enter an email address.', }, errorInvalidEmail: { id: 'passwordResetRequestPage.errorInvalidEmail', description: 'Message to display when the email entered on the password reset request page is not a valid email address.', defaultMessage: '{email} is not a valid email address.', }, errorSSORequired: { id: 'passwordResetRequestPage.errorSSORequired', description: 'Message to display on the password reset page when the account requires single sign-on.', defaultMessage: '{email} is required to sign in using a single sign-on provider. The CollectionSpace account password cannot be reset.', }, }); const propTypes = { csrf: PropTypes.object, tenantId: PropTypes.string, intl: intlShape.isRequired, }; const defaultProps = { csrf: null, tenantId: null, }; function PasswordResetRequestPage(props) { const { csrf, intl, tenantId, } = props; const [error, setError] = useState(); const [isPending, setPending] = useState(); const [success, setSuccess] = useState(); if (success) { return ( <p className="status success">{success}</p> ); } const handleSubmit = (event) => { event.preventDefault(); const form = event.target; const formData = new FormData(form); const email = formData.get('email'); if (!email) { setError(<FormattedMessage {...messages.errorMissingEmail} />); return; } if (!isValidEmail(email)) { setError(<FormattedMessage {...messages.errorInvalidEmail} values={{ email }} />); return; } const url = new URL(form.action); const params = url.searchParams; if (tenantId) { params.set('tid', tenantId); } params.set('email', email); if (csrf) { params.set(csrf.parameterName, csrf.token); } setError(null); setPending(true); window.fetch(url, { method: 'POST', }) .then((response) => Promise.all([response, response.text()])) .then(([response, text]) => { if (response.ok) { setSuccess(<FormattedMessage {...messages.success} values={{ email: text }} />); setError(null); } else { setSuccess(null); if (response.status === 404) { setError(<FormattedMessage {...messages.errorNotFound} values={{ email }} />); } else if (/requires single sign-on/.test(text)) { setError(<FormattedMessage {...messages.errorSSORequired} values={{ email }} />); } else { setError(<FormattedMessage {...messages.error} values={{ detail: text }} />); } } }) .catch((err) => { setError(<FormattedMessage {...messages.error} values={{ detail: err.message }} />); }) .finally(() => { setPending(false); }); }; const errorMessage = error ? <p className="status error">{error}</p> : undefined; return ( <> <Helmet> <title>{intl.formatMessage(messages.title)}</title> </Helmet> {errorMessage} <main> <p><FormattedMessage {...messages.prompt} /></p> <form method="POST" onSubmit={handleSubmit}> <div> {/* Ignore an eslint misfire. */} {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */} <label> <FormattedMessage {...messages.email} /> <input autoComplete="email" name="email" type="text" /> </label> </div> <div> <button className="send" disabled={isPending} type="submit"> <FormattedMessage {...messages.submit} /> </button> </div> </form> </main> </> ); } PasswordResetRequestPage.propTypes = propTypes; PasswordResetRequestPage.defaultProps = defaultProps; export default injectIntl(PasswordResetRequestPage);