first commit
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { postJSON } from '../../../../../frontend/js/infrastructure/fetch-json'
|
||||
|
||||
function RegisterForm({
|
||||
setRegistrationSuccess,
|
||||
setEmails,
|
||||
setRegisterError,
|
||||
setFailedEmails,
|
||||
}) {
|
||||
function handleRegister(event) {
|
||||
event.preventDefault()
|
||||
const formData = new FormData(event.target)
|
||||
const formDataAsEntries = formData.entries()
|
||||
const formDataAsObject = Object.fromEntries(formDataAsEntries)
|
||||
const emailString = formDataAsObject.email
|
||||
setRegistrationSuccess(false)
|
||||
setRegisterError(false)
|
||||
setEmails([])
|
||||
registerGivenUsers(parseEmails(emailString))
|
||||
}
|
||||
|
||||
async function registerGivenUsers(emails) {
|
||||
const registeredEmails = []
|
||||
const failingEmails = []
|
||||
for (const email of emails) {
|
||||
try {
|
||||
const result = await registerUser(email)
|
||||
registeredEmails.push(result)
|
||||
} catch {
|
||||
failingEmails.push(email)
|
||||
}
|
||||
}
|
||||
if (registeredEmails.length > 0) setRegistrationSuccess(true)
|
||||
if (failingEmails.length > 0) {
|
||||
setRegisterError(true)
|
||||
setFailedEmails(failingEmails)
|
||||
}
|
||||
setEmails(registeredEmails)
|
||||
}
|
||||
|
||||
function registerUser(email) {
|
||||
const options = { email }
|
||||
const url = `/admin/register`
|
||||
return postJSON(url, { body: options })
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleRegister}>
|
||||
<div className="row">
|
||||
<div className="col-md-4 col-xs-8">
|
||||
<input
|
||||
className="form-control"
|
||||
name="email"
|
||||
type="text"
|
||||
placeholder="jane@example.com, joe@example.com"
|
||||
aria-label="emails to register"
|
||||
aria-describedby="input-details"
|
||||
/>
|
||||
<p id="input-details" className="sr-only">
|
||||
Enter the emails you would like to register and separate them using
|
||||
commas
|
||||
</p>
|
||||
</div>
|
||||
<div className="col-md-8 col-xs-4">
|
||||
<button className="btn btn-primary">Register</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
function parseEmails(emailsText) {
|
||||
const regexBySpaceOrComma = /[\s,]+/
|
||||
let emails = emailsText.split(regexBySpaceOrComma)
|
||||
emails.map(email => email.trim())
|
||||
emails = emails.filter(email => email.indexOf('@') !== -1)
|
||||
return emails
|
||||
}
|
||||
|
||||
RegisterForm.propTypes = {
|
||||
setRegistrationSuccess: PropTypes.func,
|
||||
setEmails: PropTypes.func,
|
||||
setRegisterError: PropTypes.func,
|
||||
setFailedEmails: PropTypes.func,
|
||||
}
|
||||
|
||||
export default RegisterForm
|
@@ -0,0 +1,92 @@
|
||||
import { useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import RegisterForm from './register-form'
|
||||
function UserActivateRegister() {
|
||||
const [emails, setEmails] = useState([])
|
||||
const [failedEmails, setFailedEmails] = useState([])
|
||||
const [registerError, setRegisterError] = useState(false)
|
||||
const [registrationSuccess, setRegistrationSuccess] = useState(false)
|
||||
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="card">
|
||||
<div className="page-header">
|
||||
<h1> Register New Users</h1>
|
||||
</div>
|
||||
<RegisterForm
|
||||
setRegistrationSuccess={setRegistrationSuccess}
|
||||
setEmails={setEmails}
|
||||
setRegisterError={setRegisterError}
|
||||
setFailedEmails={setFailedEmails}
|
||||
/>
|
||||
{registerError ? (
|
||||
<UserActivateError failedEmails={failedEmails} />
|
||||
) : null}
|
||||
{registrationSuccess ? (
|
||||
<>
|
||||
<SuccessfulRegistrationMessage />
|
||||
<hr />
|
||||
<DisplayEmailsList emails={emails} />
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function UserActivateError({ failedEmails }) {
|
||||
return (
|
||||
<div className="row-spaced text-danger">
|
||||
<p>Sorry, an error occured, failed to register these emails.</p>
|
||||
{failedEmails.map(email => (
|
||||
<p key={email}>{email}</p>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function SuccessfulRegistrationMessage() {
|
||||
return (
|
||||
<div className="row-spaced text-success">
|
||||
<p>We've sent out welcome emails to the registered users.</p>
|
||||
<p>
|
||||
You can also manually send them URLs below to allow them to reset their
|
||||
password and log in for the first time.
|
||||
</p>
|
||||
<p>
|
||||
(Password reset tokens will expire after one week and the user will need
|
||||
registering again).
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DisplayEmailsList({ emails }) {
|
||||
return (
|
||||
<table className="table table-striped ">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Email</th>
|
||||
<th>Set Password Url</th>
|
||||
</tr>
|
||||
{emails.map(user => (
|
||||
<tr key={user.email}>
|
||||
<td>{user.email}</td>
|
||||
<td style={{ wordBreak: 'break-all' }}>{user.setNewPasswordUrl}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
}
|
||||
|
||||
DisplayEmailsList.propTypes = {
|
||||
emails: PropTypes.array,
|
||||
}
|
||||
UserActivateError.propTypes = {
|
||||
failedEmails: PropTypes.array,
|
||||
}
|
||||
|
||||
export default UserActivateRegister
|
@@ -0,0 +1,9 @@
|
||||
import '@/marketing'
|
||||
|
||||
import ReactDOM from 'react-dom'
|
||||
import UserActivateRegister from '../components/user-activate-register'
|
||||
|
||||
ReactDOM.render(
|
||||
<UserActivateRegister />,
|
||||
document.getElementById('user-activate-register-container')
|
||||
)
|
Reference in New Issue
Block a user