Integrated master/detail, refactor Icon, add base router

This commit is contained in:
John Lyon-Smith
2018-05-12 12:36:39 -07:00
parent 84babf0e4b
commit 6fae5ef5d6
61 changed files with 1203 additions and 1620 deletions

View File

@@ -1,47 +1,14 @@
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'
import React, { Component } from "react"
import { Route, Redirect } from "react-router-dom"
import PropTypes from "prop-types"
export class DefaultRoute extends Component {
@autobind
updateComponent() {
this.forceUpdate()
}
componentDidMount() {
api.addListener('login', this.updateComponent)
}
componentWillUnmount() {
api.removeListener('login', this.updateComponent)
static propTypes = {
redirect: PropTypes.string,
}
render() {
const user = api.loggedInUser
let path = null
if (user) {
if (!user.pending) {
path = user.administrator ? '/home' : '/profile'
}
} else {
path = '/login'
}
return (
<Route
path='/'
render={() => {
return (
<Fragment>
<Column.Item grow />
{path ? <Redirect to={path} /> : null}
</Fragment>
)
}}
/>
)
// NOTE: When working on the site, Redirect to the page you are working on
return <Route render={() => <Redirect to={this.props.redirect} />} />
}
}

View File

@@ -1,28 +1,28 @@
import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'
import { regExpPattern } from 'regexp-pattern'
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 headerLogo from 'images/deighton.png'
import { sizeInfo, colorInfo } from 'ui/style'
import autobind from 'autobind-decorator'
import React, { Component, Fragment } from "react"
import PropTypes from "prop-types"
import { regExpPattern } from "regexp-pattern"
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 headerLogo from "images/badge.png"
import { sizeInfo, colorInfo } from "ui/style"
import autobind from "autobind-decorator"
export class ForgotPassword extends Component {
static propTypes = {
history: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
history: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
}
static bindings = {
email: {
alwaysGet: true,
isValid: (r, v) => (regExpPattern.email.test(v))
isValid: (r, v) => regExpPattern.email.test(v),
},
submit: {
noValue: true,
isDisabled: (r) => (!r.anyModified || !r.allValid)
}
isDisabled: (r) => !r.anyModified || !r.allValid,
},
}
constructor(props) {
@@ -30,7 +30,7 @@ export class ForgotPassword extends Component {
this.state = {
binder: new FormBinder({}, ForgotPassword.bindings),
messageModal: null,
waitModal: null
waitModal: null,
}
}
@@ -45,16 +45,18 @@ export class ForgotPassword extends Component {
const obj = this.state.binder.getModifiedFieldValues()
this.setState({ waitModal: { message: 'Requesting Reset Email' } })
this.setState({ waitModal: { message: "Requesting Reset Email" } })
const cb = (res) => {
this.setState({
waitModal: null,
messageModal: {
icon: 'thumb',
title: 'Password Reset Requested',
message: `If everything checks out, an email will be sent to '${obj.email}' with a reset link. Please click on it to finish resetting the password.`
}
icon: "thumb",
title: "Password Reset Requested",
message: `If everything checks out, an email will be sent to '${
obj.email
}' with a reset link. Please click on it to finish resetting the password.`,
},
})
}
@@ -63,7 +65,7 @@ export class ForgotPassword extends Component {
@autobind
handleMessageModalDismiss() {
this.props.history.replace('/')
this.props.history.replace("/")
}
render() {
@@ -77,8 +79,13 @@ export class ForgotPassword extends Component {
<Row.Item grow />
<Row.Item width={sizeInfo.formRowSpacing} />
<Row.Item width={sizeInfo.modalWidth}>
<form id='forgotPasswordForm' onSubmit={this.handleSubmit}>
<Box border={{ width: sizeInfo.headerBorderWidth, color: colorInfo.headerBorder }} radius={sizeInfo.formBoxRadius}>
<form id="forgotPasswordForm" onSubmit={this.handleSubmit}>
<Box
border={{
width: sizeInfo.headerBorderWidth,
color: colorInfo.headerBorder,
}}
radius={sizeInfo.formBoxRadius}>
<Row>
<Row.Item width={sizeInfo.formRowSpacing} />
<Row.Item>
@@ -88,31 +95,46 @@ export class ForgotPassword extends Component {
<Row>
<Row.Item grow />
<Row.Item>
<Image source={headerLogo} width={sizeInfo.loginLogoWidth} />
<Image
source={headerLogo}
width={sizeInfo.loginLogoWidth}
/>
</Row.Item>
<Row.Item grow />
</Row>
</Column.Item>
<Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item>
<Text size='large'>Forgotten Password</Text>
<Text size="large">Forgotten Password</Text>
</Column.Item>
<Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item>
<BoundInput label='Email' name='email'
placeholder='example@xyz.com' binder={this.state.binder}
message='A valid email address' />
<BoundInput
label="Email"
name="email"
placeholder="example@xyz.com"
binder={this.state.binder}
message="A valid email address"
/>
</Column.Item>
<Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item>
<Text>The email address of an existing user to send the password reset link to.</Text>
<Text>
The email address of an existing user to send the
password reset link to.
</Text>
</Column.Item>
<Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item minHeight={sizeInfo.buttonHeight}>
<Row>
<Row.Item grow />
<Row.Item>
<BoundButton text='Submit' name='submit' submit='forgotPasswordForm' binder={binder} />
<BoundButton
text="Submit"
name="submit"
submit="forgotPasswordForm"
binder={binder}
/>
</Row.Item>
</Row>
</Column.Item>
@@ -128,15 +150,18 @@ export class ForgotPassword extends Component {
</Row>
</Column.Item>
<Column.Item grow>
<WaitModal active={!!waitModal}
message={waitModal ? waitModal.message : ''} />
<WaitModal
active={!!waitModal}
message={waitModal ? waitModal.message : ""}
/>
<MessageModal
open={!!messageModal}
icon={messageModal ? messageModal.icon : ''}
message={messageModal ? messageModal.message : ''}
detail={messageModal ? messageModal.detail : ''}
onDismiss={this.handleMessageModalDismiss} />
icon={messageModal ? messageModal.icon : ""}
message={messageModal ? messageModal.message : ""}
detail={messageModal ? messageModal.detail : ""}
onDismiss={this.handleMessageModalDismiss}
/>
</Column.Item>
</Fragment>
)

View File

@@ -14,7 +14,7 @@ import {
BoundCheckbox,
BoundButton,
} from "ui"
import headerLogo from "images/deighton.png"
import headerLogo from "images/logo.png"
import { versionInfo } from "../version"
import { FormBinder } from "react-form-binder"
import autobind from "autobind-decorator"

View File

@@ -6,7 +6,10 @@ import autobind from 'autobind-decorator'
export class ProtectedRoute extends React.Component {
static propTypes = {
location: PropTypes.shape({ pathname: PropTypes.string, search: PropTypes.string }),
location: PropTypes.shape({
pathname: PropTypes.string,
search: PropTypes.string,
}),
admin: PropTypes.bool,
}
@@ -16,26 +19,32 @@ export class ProtectedRoute extends React.Component {
}
componentDidMount() {
api.addListener('login', this.updateComponent)
api.addListener("login", this.updateComponent)
api.addListener("logout", this.updateComponent)
}
componentWillUnmount() {
api.removeListener('login', this.updateComponent)
api.removeListener("login", this.updateComponent)
api.removeListener("logout", this.updateComponent)
}
render(props) {
const user = api.loggedInUser
if (user) {
if (user.pending) {
// The API might be in the middle of fetching the user information
// Return something and wait for login evint to fire to re-render
return <div />
} else if (!this.props.admin || (this.props.admin && user.administrator)) {
if (user.pending) {
return null
} else {
if (!user._id || (this.props.admin && !user.administrator)) {
return (
<Redirect
to={`/login?redirect=${this.props.location.pathname}${
this.props.location.search
}`}
/>
)
} else {
return <Route {...this.props} />
}
}
return <Redirect to={`/login?redirect=${this.props.location.pathname}${this.props.location.search}`} />
}
}

View File

@@ -6,7 +6,7 @@ import { api } from "src/API"
import { FormBinder } from "react-form-binder"
import { sizeInfo, colorInfo } from "ui/style"
import autobind from "autobind-decorator"
import headerLogo from "images/deighton.png"
import headerLogo from "images/logo.png"
export class ResetPassword extends Component {
static propTypes = {