Fix routing issues. Fix panel layout.

This commit is contained in:
John Lyon-Smith
2018-03-23 13:49:41 -07:00
parent 54365d3566
commit ce25d56dfe
17 changed files with 240 additions and 98 deletions

View File

@@ -2,6 +2,7 @@ import React from 'react'
import { api } from 'src/API'
import PropTypes from 'prop-types'
import { MessageModal, WaitModal } from '../Modal'
import { Logout } from '.'
import autobind from 'autobind-decorator'
export class ConfirmEmail extends React.Component {
@@ -17,7 +18,8 @@ export class ConfirmEmail extends React.Component {
}
componentDidMount(props) {
let emailToken = new URLSearchParams(decodeURIComponent(window.location.search)).get('email-token')
const emailToken = new URLSearchParams(decodeURIComponent(window.location.search)).get('email-token')
this.setState({ waitModal: { message: 'Validating Email...' } })
if (emailToken) {
api.confirmEmail(emailToken).then((response) => {
@@ -29,21 +31,17 @@ export class ConfirmEmail extends React.Component {
this.props.history.replace('/login')
}
}).catch((err) => {
console.error(err)
const supportEmail = 'support@kingstonsoftware.solutions' // TODO: From configuration
const message = err.message.includes('The token was not found')
? 'This email address may have already been confirmed.'
: `Please contact ${supportEmail} to request a new user invitation`
this.setState({
waitModal: null,
messageModal: {
title: 'Error Verifying Email...',
message: `We couldn't complete that request. ${message}`
icon: 'hand',
message: `Please contact ${process.env.REACT_APP_SUPPORT_EMAIL} to request another confirmation email.`,
detail: err.message
}
})
})
} else {
this.props.history.replace('/login')
this.props.history.replace('/')
}
}
@@ -54,14 +52,23 @@ export class ConfirmEmail extends React.Component {
}
render() {
const { messageModal, waitModal } = this.state
if (api.loggedInUser) {
return <Logout redirect={`${window.location.pathname}${window.location.search}`} />
}
return (
<div>
<WaitModal active={!!this.state.waitModal}
message={this.state.waitModal ? this.state.waitModal.message : ''} />
<WaitModal
active={!!waitModal}
message={waitModal ? waitModal.message : ''} />
<MessageModal error open={!!this.state.messageModal}
title={this.state.messageModal ? this.state.messageModal.title : ''}
message={this.state.messageModal ? this.state.messageModal.message : ''}
<MessageModal
open={!!messageModal}
icon={messageModal ? messageModal.icon : ''}
message={messageModal ? messageModal.message : ''}
detail={messageModal ? messageModal.title : ''}
onDismiss={this.handleMessageModalDismiss} />
</div>
)

View File

@@ -0,0 +1,47 @@
import React, { Fragment, Component } from 'react'
import { api } from 'src/API'
import { Route, Redirect } from 'react-router-dom'
import { Column } from 'ui'
import autobind from 'autobind-decorator'
export class DefaultRoute extends Component {
@autobind
updateComponent() {
this.forceUpdate()
}
componentDidMount() {
api.addListener('login', this.updateComponent)
}
componentWillUnmount() {
api.removeListener('login', this.updateComponent)
}
render() {
const user = api.loggedInUser
let redirect = null
if (user) {
if (!user.pending) {
redirect = <Redirect to={user.administrator ? '/home' : '/profile'} />
}
} else {
redirect = <Redirect to='/login' />
}
return (
<Route
path='/'
render={() => {
return (
<Fragment>
<Column.Item grow />
{redirect}
</Fragment>
)
}}
/>
)
}
}

View File

@@ -5,6 +5,7 @@ import { Image, Text, Column, Row, BoundInput, BoundButton, Box } from 'ui'
import { MessageModal, WaitModal } from '../Modal'
import { api } from 'src/API'
import { FormBinder } from 'react-form-binder'
import { Logout } from '.'
import headerLogo from 'images/deighton.png'
import { sizeInfo, colorInfo } from 'ui/style'
import autobind from 'autobind-decorator'
@@ -65,6 +66,10 @@ export class ForgotPassword extends Component {
render() {
const { binder, waitModal, messageModal } = this.state
if (api.loggedInUser) {
return <Logout redirect={`${window.location.pathname}${window.location.search}`} />
}
return (
<Fragment>
<Column.Item grow />

View File

@@ -1,21 +1,36 @@
import React from 'react'
import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'
import { api } from 'src/API'
import { Column } from 'ui'
export class Logout extends React.Component {
export class Logout extends Component {
static propTypes = {
history: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
redirect: PropTypes.string,
}
componentDidMount(event) {
api.logout().then(() => {
if (this.props.history) {
this.props.history.replace('/login')
const { history, redirect } = this.props
const cb = () => {
if (history && redirect) {
try {
history.replace(redirect)
} catch (error) {
history.replace('/login')
}
} else {
window.location.replace('/login')
}
})
}
api.logout().then(cb, cb)
}
render() {
return null
return (
<Fragment>
<Column.Item grow />
</Fragment>
)
}
}

View File

@@ -6,14 +6,7 @@ import autobind from 'autobind-decorator'
export class ProtectedRoute extends React.Component {
static propTypes = {
location: PropTypes.shape({
pathname: PropTypes.string,
search: PropTypes.string,
}),
}
static defaultProps = {
roles: ['administrator']
location: PropTypes.shape({ pathname: PropTypes.string, search: PropTypes.string }),
}
@autobind
@@ -30,7 +23,7 @@ export class ProtectedRoute extends React.Component {
}
render(props) {
let user = api.loggedInUser
const user = api.loggedInUser
if (user) {
if (user.pending) {
@@ -40,8 +33,8 @@ export class ProtectedRoute extends React.Component {
} else if (user.administrator) {
return <Route {...this.props} />
}
} else {
return <Redirect to={`/login?redirect=${this.props.location.pathname}${this.props.location.search}`} />
}
return <Redirect to={`/login?redirect=${this.props.location.pathname}${this.props.location.search}`} />
}
}

View File

@@ -1,6 +1,7 @@
import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'
import { Box, Text, Image, Column, Row, BoundInput, BoundButton } from 'ui'
import { Logout } from '.'
import { MessageModal, WaitModal } from '../Modal'
import { api } from 'src/API'
import { FormBinder } from 'react-form-binder'
@@ -32,7 +33,39 @@ export class ResetPassword extends Component {
this.state = {
binder: new FormBinder({}, ResetPassword.bindings),
messageModal: null,
waitModal: null
waitModal: null,
tokenConfirmed: false,
}
}
componentDidMount(props) {
if (this.state.tokenConfirmed) {
return
}
const passwordToken = new URLSearchParams(decodeURIComponent(window.location.search)).get('password-token')
this.setState({ waitModal: { message: 'Confirming password reset...' } })
if (passwordToken) {
api.confirmResetPassword(passwordToken).then((response) => {
this.setState({ waitModal: null })
if (response && response.valid) {
this.setState({ tokenConfirmed: true })
} else {
this.props.history.replace('/')
}
}).catch((err) => {
this.setState({
waitModal: null,
messageModal: {
icon: 'hand',
message: `We were unable to confirm you requested a password reset. Please request another reset email.`,
detail: err.message
}
})
})
} else {
this.props.history.replace('/')
}
}
@@ -54,8 +87,9 @@ export class ResetPassword extends Component {
waitModal: null,
messageModal: {
icon: 'hand',
title: 'There was a problem changing your password',
message: 'There was a problem changing your password. Please request another reset email.',
detail: err.message,
noRetry: true,
}
})
})
@@ -63,12 +97,20 @@ export class ResetPassword extends Component {
@autobind
handleMessageModalDismiss() {
this.setState({ messageModal: null })
if (this.state.messageModal.noRetry) {
this.props.history.replace('/login')
} else {
this.setState({ messageModal: null })
}
}
render() {
const { messageModal, waitModal, binder } = this.state
if (api.loggedInUser) {
return <Logout redirect={`${window.location.pathname}${window.location.search}`} />
}
return (
<Fragment>
<Column.Item grow />
@@ -132,8 +174,8 @@ export class ResetPassword extends Component {
<MessageModal
open={!!messageModal}
icon={messageModal ? messageModal.icon : ''}
title={messageModal ? messageModal.title : ''}
message={messageModal ? messageModal.message : ''}
detail={messageModal ? messageModal.title : ''}
onDismiss={this.handleMessageModalDismiss} />
<WaitModal active={!!waitModal}

View File

@@ -3,4 +3,5 @@ export { Logout } from './Logout'
export { ResetPassword } from './ResetPassword'
export { ForgotPassword } from './ForgotPassword'
export { ConfirmEmail } from './ConfirmEmail'
export { DefaultRoute } from './DefaultRoute'
export { ProtectedRoute } from './ProtectedRoute'