Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions app/components/PublicRoute/__snapshots__/PublicRoute.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ exports[`<PublicRoute /> renders Login if user is not authenticated 1`] = `
>
Login
</h2>
<a
class="Link__StyledLink-sc-1vpl4pu-0 gEErvb"
href="/register"
theme="[object Object]"
<button
class="StyledButton-sc-323bzc-0 liUmex Button__StyledGrommetButton-sc-5cxguj-0 liIZVq"
style="background: transparent;"
type="button"
>
or Create An Account
</a>
<span
class="StyledText-sc-1sadyjn-0 iNHOlp Text__StyledGrommetText-sc-1qclgcc-0 lkunaY"
>
or Create An Account
</span>
</button>
</div>
<form
id="login-form"
Expand Down Expand Up @@ -160,13 +164,17 @@ exports[`<PublicRoute /> renders Login if user is not authenticated 1`] = `
Login
</button>
</div>
<a
class="Link__StyledLink-sc-1vpl4pu-0 gEErvb"
href="/password-reset-request"
theme="[object Object]"
<button
class="StyledButton-sc-323bzc-0 liUmex Button__StyledGrommetButton-sc-5cxguj-0 liIZVq"
style="background: transparent;"
type="button"
>
Forgot Password?
</a>
<span
class="StyledText-sc-1sadyjn-0 iNHOlp Text__StyledGrommetText-sc-1qclgcc-0 lkunaY"
>
Forgot Password?
</span>
</button>
<div
class="StyledBox-sc-13pk1d4-0 bFwQzJ"
/>
Expand Down
2 changes: 1 addition & 1 deletion app/components/TextInput/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- ! This is a generated file. To make changes, edit <Component>.doc.js ! -->
## TextInput
## undefined
A control to input a single line of text, with optional suggestions.

## Usage
Expand Down
8 changes: 4 additions & 4 deletions app/components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable react/prop-types */
import React from 'react'
import React, { forwardRef } from 'react'

// Components
import { TextInput as GrommetTextInput } from 'grommet'
Expand All @@ -13,9 +13,9 @@ import { createWithDoc } from '../../utils/helpers'
* TextInput
*
*/
const TextInput = ({ name, type, ...rest }) => (
<GrommetTextInput name={name} type={type} style={{ border: 'none' }} {...rest} />
)
const TextInput = forwardRef(({ name, type, ...rest }, ref) => (
<GrommetTextInput name={name} ref={ref} type={type} style={{ border: 'none' }} {...rest} />
))

export default createWithDoc({
envName: process.env.NODE_ENV,
Expand Down
55 changes: 45 additions & 10 deletions app/pages/Login/Login.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* @flow */
import React, { useContext, useEffect, useState } from 'react'
import React, { useContext, useEffect, useRef, useState } from 'react'
import { isEmail } from 'validator'
import PropTypes from 'prop-types'
import { useHistory } from 'react-router-dom'

// Components
import { Box } from 'components/Box'
Expand All @@ -10,28 +11,42 @@ import { Form, FormField } from 'components/Form'
import { FormContainer } from 'components/FormContainer'
import { Heading } from 'components/Heading'
import { Message } from 'components/Message'
import { Link } from 'components/Link'
import { LogoHeader } from 'components/LogoHeader'
import { PasswordInput } from 'components/PasswordInput'
import { Text } from 'components/Text'
import { TextInput } from 'components/TextInput'

// Utils and messages
import useFlashMessage from '../../hooks/FlashMessage'
// Service
import { login } from '../../services/user.service'

// Store
import { UserStoreContext } from '../../stores/UserStore'

// Style
import { baseColors } from '../../utils/colors'

// Utils
import useFlashMessage from '../../hooks/FlashMessage'

/**
*
* Login
*
*/
const Login = ({ location }) => {
// Messages
const { message: error, showMessage: showError } = useFlashMessage(null)
const { message: redirectedMessage, showMessage: showRedirectedMessage } = useFlashMessage(null)

// Context
const history = useHistory()
const { setCurrentUser, setCurrentTokens } = useContext(UserStoreContext)

// State
const [loading, setLoading] = useState(false)

const { setCurrentUser, setCurrentTokens } = useContext(UserStoreContext)
// Ref
const emailRef = useRef()

/**
* Check if the user has been redirected to this page with a URL parameter
Expand All @@ -56,7 +71,16 @@ const Login = ({ location }) => {
<FormContainer>
<Box align="center" data-testid="login-header">
<Heading level="2">Login</Heading>
<Link to="/register">or Create An Account</Link>
<Button
label={
<Text color={baseColors.blue} size="15px">
or Create An Account
</Text>
}
onClick={() => history.push('/register', { email: emailRef.current?.value })}
plain
style={{ background: 'transparent' }}
/>
</Box>

<Form
Expand All @@ -80,13 +104,13 @@ const Login = ({ location }) => {
name="email"
required
validate={[
email => {
if (email && !isEmail(email)) return 'Please enter a valid email address'
e => {
if (e && !isEmail(e)) return 'Please enter a valid email address'
return undefined
},
]}
>
<TextInput type="email" />
<TextInput ref={emailRef} type="email" />
</FormField>

<FormField
Expand Down Expand Up @@ -115,7 +139,18 @@ const Login = ({ location }) => {
/>
</Box>

<Link to="/password-reset-request">Forgot Password?</Link>
<Button
label={
<Text color={baseColors.blue} size="15px">
Forgot Password?
</Text>
}
onClick={() =>
history.push('/password-reset-request', { email: emailRef.current?.value })
}
plain
style={{ background: 'transparent' }}
/>

{/* Status Messages */}
<Box>{error && <Message message={error} isError />}</Box>
Expand Down
6 changes: 5 additions & 1 deletion app/pages/PasswordReset/PasswordReset.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@ import { RootStoreContext } from '../../stores/RootStore'
*
*/
const PasswordReset = observer(({ location }) => {
// Message
const { message: error, showMessage: showError } = useFlashMessage(null)

// State
const [loading, setLoading] = useState(false)
const [redirect, setRedirect] = useState(false)
const [tokenError, setTokenError] = useState(false)
const { message: error, showMessage: showError } = useFlashMessage(null)

// Context
const {
clearStore,
user: { isAuthenticated },
Expand Down
31 changes: 26 additions & 5 deletions app/pages/PasswordResetRequest/PasswordResetRequest.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* @flow */
import React, { useEffect, useState } from 'react'
import { isEmail } from 'validator'
import { useLocation } from 'react-router-dom'

// Components
import { Box } from 'components/Box'
Expand All @@ -12,23 +13,41 @@ import { Link } from 'components/Link'
import { LogoHeader } from 'components/LogoHeader'
import { Message } from 'components/Message'

// Component
import { TextInput } from 'components/TextInput'

// Utils and messages
import useFlashMessage from '../../hooks/FlashMessage'
// Service
import { forgotPassword } from '../../services/user.service'

// Utils
import useFlashMessage from '../../hooks/FlashMessage'

/**
*
* PasswordResetRequest
*
*/
const PasswordResetRequest = () => {
// Message
const { message: error, showMessage: showError } = useFlashMessage(null)

const [loading, setLoading] = useState(false)
// Context
const location = useLocation()

// State
const [loading, setLoading] = useState(false)
const [success, setSuccess] = useState(false)
const [email, setEmail] = useState(null)

/**
* If there is an email provided through the route, use that as the default value
*/
useEffect(() => {
if (location.state && location.state.email) {
setEmail(location.state.email)
}
}, [])

useEffect(() => {
document.getElementById('reset-password-request-form').reset()
}, [success])
Expand All @@ -49,14 +68,16 @@ const PasswordResetRequest = () => {
onSubmit={({ value }) => {
forgotPassword(value, showError, setLoading, setSuccess)
}}
value={{ email }}
>
<FormField
label="Email"
name="email"
onChange={e => setEmail(e.target.value)}
required
validate={[
email => {
if (email && !isEmail(email)) return 'Please enter a valid email address'
e => {
if (e && !isEmail(e)) return 'Please enter a valid email address'
return undefined
},
]}
Expand Down
46 changes: 35 additions & 11 deletions app/pages/Register/Register.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/* @flow */
import React, { useState, useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import {
CheckBox,
Markdown,
RadioButtonGroup,
} from 'grommet' /** @todo replace with wrapper component */
import { isEmail } from 'validator'
import { useLocation } from 'react-router-dom'

// Components
import { Box } from 'components/Box'
Expand Down Expand Up @@ -34,13 +35,34 @@ import { createAccount } from '../../services/user.service'
*
*/
const Register = () => {
const [showModal, setShowModal] = useState(false)

// Message
const { message: error, showMessage: showError } = useFlashMessage(null)

const [loading, setLoading] = useState(false)
// Context
const location = useLocation()

// State
const [showModal, setShowModal] = useState(false)
const [loading, setLoading] = useState(false)
const [success, setSuccess] = useState(false)
const [registration, setRegistration] = useState({
confirmPassword: null,
email: null,
firstName: null,
lastName: null,
password: null,
role: null,
})

/**
* If there is an email provided through the route, use that as the default value
*/
useEffect(() => {
if (location.state && location.state.email) {
setRegistration({ ...registration, email: location.state.email })
}
}, [])

useEffect(() => {
document.getElementById('register-form').reset()
}, [success])
Expand All @@ -58,14 +80,16 @@ const Register = () => {
<Form
id="register-form"
validate="blur"
onChange={e => setRegistration(e.value)}
onSubmit={({ value }) => {
createAccount(value, showError, setLoading, setSuccess)
}}
value={registration}
>
<Box flex="grow" gap="small" direction="row" alignItems="stretch">
<FormField
label="First Name"
name="first_name"
name="firstName"
required
style={{ flex: 1 }}
validate={[
Expand All @@ -78,7 +102,7 @@ const Register = () => {

<FormField
label="Last Name"
name="last_name"
name="lastName"
required
style={{ flex: 1 }}
validate={[
Expand All @@ -95,8 +119,8 @@ const Register = () => {
name="email"
required
validate={[
email => {
if (email && !isEmail(email)) return 'Please enter a valid email address'
e => {
if (e && !isEmail(e)) return 'Please enter a valid email address'
return undefined
},
]}
Expand All @@ -114,7 +138,7 @@ const Register = () => {
return undefined
},
password => {
const confirmPasswordInput = document.getElementsByName('confirm_password')[0]
const confirmPasswordInput = document.getElementsByName('confirmPassword')[0]
if (
password &&
confirmPasswordInput instanceof HTMLInputElement &&
Expand All @@ -131,7 +155,7 @@ const Register = () => {

<FormField
label="Re-enter Password"
name="confirm_password"
name="confirmPassword"
required
validate={[
confirmPassword => {
Expand All @@ -156,7 +180,7 @@ const Register = () => {
<PasswordInput />
</FormField>

<FormField label="Account Type." name="role" required>
<FormField label="Account Type" name="role" required>
<RadioButtonGroup
direction="row"
gap="xsmall"
Expand Down