Basic UI elements in place
This commit is contained in:
@@ -1,23 +1,22 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { autoBind } from 'auto-bind2'
|
||||
import { reactAutoBind } from 'auto-bind2'
|
||||
import { regExpPattern } from 'regexp-pattern'
|
||||
import { ValidatedEmailIcon } from './ValidatedEmailIcon'
|
||||
import { Constants, api } from '../helpers'
|
||||
import { Validator, ValidatedInput, ValidatedButton, ValidatedCheckbox } from '../Validated'
|
||||
import { Column } from 'ui'
|
||||
import { Column, BoundInput, BoundButton, BoundCheckbox, BoundEmailIcon } from 'ui'
|
||||
import { FormBinder } from 'react-form-binder'
|
||||
|
||||
export class UserForm extends React.Component {
|
||||
static propTypes = {
|
||||
user: PropTypes.object,
|
||||
onSave: PropTypes.func,
|
||||
onRemove: PropTypes.func,
|
||||
onModifiedChanged: PropTypes.func,
|
||||
onAnyModified: PropTypes.func,
|
||||
onChangeEmail: PropTypes.func,
|
||||
onResendEmail: PropTypes.func
|
||||
}
|
||||
|
||||
static validations = {
|
||||
static bindings = {
|
||||
email: {
|
||||
isValid: (r, v) => (regExpPattern.email.test(v)),
|
||||
isDisabled: (r) => (!!r._id)
|
||||
@@ -35,45 +34,6 @@ export class UserForm extends React.Component {
|
||||
lastName: {
|
||||
isValid: (r, v) => (v !== '')
|
||||
},
|
||||
zip: {
|
||||
isValid: (r, v) => (v === '' || regExpPattern.zip.test(v))
|
||||
},
|
||||
state: {
|
||||
isValid: (r, v) => (v === '' || regExpPattern.state.test(v))
|
||||
},
|
||||
city: {
|
||||
isValid: true
|
||||
},
|
||||
address1: {
|
||||
isValid: true
|
||||
},
|
||||
address2: {
|
||||
isValid: true
|
||||
},
|
||||
homePhone: {
|
||||
isValid: (r, v) => (v === '' || regExpPattern.phone.test(v))
|
||||
},
|
||||
cellPhone: {
|
||||
isValid: (r, v) => (v === '' || regExpPattern.phone.test(v))
|
||||
},
|
||||
dateOfBirth: {
|
||||
isValid: true
|
||||
},
|
||||
dateOfHire: {
|
||||
isValid: true
|
||||
},
|
||||
ssn: {
|
||||
isValid: (r, v) => (v === '' || regExpPattern.ssn.test(v))
|
||||
},
|
||||
numHouseholds: {
|
||||
isValid: true
|
||||
},
|
||||
t12: {
|
||||
isValid: true
|
||||
},
|
||||
aum: {
|
||||
isValid: true
|
||||
},
|
||||
role: {
|
||||
isValid: (r, v) => (v !== ''),
|
||||
isDisabled: (r) => (api.loggedInUser._id === r._id)
|
||||
@@ -94,43 +54,40 @@ export class UserForm extends React.Component {
|
||||
nonValue: true,
|
||||
isDisabled: (r) => (!r.anyModified && !r.allValid)
|
||||
},
|
||||
'broker-fields': {
|
||||
nonValue: true,
|
||||
isVisible: (r, v) => (r.getField('role').value === 'broker')
|
||||
},
|
||||
'standard-fields': {
|
||||
nonValue: true,
|
||||
isVisible: (r, v) => (r.getField('role').value !== 'broker')
|
||||
}
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
autoBind(this, (name) => (name.startsWith('handle')))
|
||||
reactAutoBind(this)
|
||||
this.state = {
|
||||
validator: new Validator(this.props.user, UserForm.validations, this.props.onModifiedChanged)
|
||||
binder: new FormBinder(this.props.user, UserForm.bindings, this.props.onAnyModified)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.user !== this.props.user) {
|
||||
this.setState({
|
||||
validator: new Validator(nextProps.user, UserForm.validations, nextProps.onModifiedChanged)
|
||||
binder: new FormBinder(nextProps.user, UserForm.bindings, nextProps.onAnyModified)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault()
|
||||
let obj = this.state.validator.getValues()
|
||||
let obj = this.state.binder.getValues()
|
||||
if (obj) {
|
||||
this.props.onSave(obj)
|
||||
}
|
||||
}
|
||||
|
||||
handleReset() {
|
||||
this.setState({ validator: new Validator(this.props.user, UserForm.validations, this.props.onModifiedChanged) })
|
||||
this.props.onModifiedChanged(false)
|
||||
const { user, onAnyModified } = this.props
|
||||
|
||||
this.setState({ binder: new FormBinder(user, UserForm.bindings, onAnyModified) })
|
||||
|
||||
if (onAnyModified) {
|
||||
onAnyModified(false)
|
||||
}
|
||||
}
|
||||
|
||||
handleChangeEmail() {
|
||||
@@ -146,37 +103,37 @@ export class UserForm extends React.Component {
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<Column>
|
||||
<Column.Item>
|
||||
<ValidatedCheckbox label={'Deighton Access & Security Level'} width={6} selection
|
||||
<BoundCheckbox label={'Deighton Access & Security Level'} width={6} selection
|
||||
options={Constants.accessLevels} name='role' message='The user role and security level'
|
||||
placeholder='' validator={this.state.validator} />
|
||||
placeholder='' binder={this.state.binder} />
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<ValidatedInput label='First Name' name='firstName'
|
||||
width={8} validator={this.state.validator} />
|
||||
<BoundInput label='First Name' name='firstName'
|
||||
width={8} binder={this.state.binder} />
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<ValidatedInput label='Last Name' name='lastName'
|
||||
width={8} validator={this.state.validator} />
|
||||
<BoundInput label='Last Name' name='lastName'
|
||||
width={8} binder={this.state.binder} />
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<ValidatedInput label='Email' name='email' width={8} message='Must be a valid email address. Required.'
|
||||
validator={this.state.validator} />
|
||||
<ValidatedEmailIcon name='emailValidated' validator={this.state.validator} width={4}
|
||||
<BoundInput label='Email' name='email' width={8} message='Must be a valid email address. Required.'
|
||||
binder={this.state.binder} />
|
||||
<BoundEmailIcon name='emailValidated' binder={this.state.binder} width={4}
|
||||
onClick={this.handleResendEmail} />
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<ValidatedButton width={4} size='medium' content='Change Email' label=' ' name='changeEmail'
|
||||
validator={this.state.validator} onClick={this.handleChangeEmail} />
|
||||
<BoundButton width={4} size='medium' content='Change Email' label=' ' name='changeEmail'
|
||||
binder={this.state.binder} onClick={this.handleChangeEmail} />
|
||||
</Column.Item>
|
||||
|
||||
<Column.Item>
|
||||
<ValidatedButton color='red' width={4} size='medium' content='Remove' label=' ' name='remove'
|
||||
validator={this.state.validator} onClick={this.props.onRemove} />
|
||||
<ValidatedButton width={4} size='medium' content='Reset' label=' ' name='reset'
|
||||
validator={this.state.validator} onClick={this.handleReset} />
|
||||
<ValidatedButton primary submit width={4} size='medium'
|
||||
content={this.state.validator._id ? 'Save' : 'Add'} label=' ' name='submit'
|
||||
validator={this.state.validator} />
|
||||
<BoundButton color='red' width={4} size='medium' content='Remove' label=' ' name='remove'
|
||||
binder={this.state.binder} onClick={this.props.onRemove} />
|
||||
<BoundButton width={4} size='medium' content='Reset' label=' ' name='reset'
|
||||
binder={this.state.binder} onClick={this.handleReset} />
|
||||
<BoundButton primary submit width={4} size='medium'
|
||||
content={this.state.binder._id ? 'Save' : 'Add'} label=' ' name='submit'
|
||||
binder={this.state.binder} />
|
||||
</Column.Item>
|
||||
</Column>
|
||||
</form>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
.user-form {
|
||||
text-align: left;
|
||||
margin: 3em auto 4em auto;
|
||||
}
|
||||
|
||||
.user-form > .fields {
|
||||
margin-bottom: 1.5em !important;
|
||||
}
|
||||
@@ -2,7 +2,6 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Dropdown, List, Icon, Button, Image } from 'ui'
|
||||
import { Constants, api } from '../helpers'
|
||||
import './UserList.scss'
|
||||
|
||||
const selectionOptions = Constants.accessLevels.concat([{ value: 'all', text: 'All Levels' }])
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
.user-list {
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0.25em !important;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 0.25em 2px Silver;
|
||||
-webkit-box-shadow: 0 0 0.25em 2px Silver;
|
||||
max-height: 60vh;
|
||||
min-height: 60vh;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.user-list > .item {
|
||||
margin: 5em 0;
|
||||
}
|
||||
|
||||
i.user-update {
|
||||
position: absolute;
|
||||
right: 7.5%;
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { UserForm } from './UserForm'
|
||||
import { UserFormPlaceholder } from './UserFormPlaceholder'
|
||||
import { api } from '../helpers'
|
||||
import { Row } from 'ui'
|
||||
import { YesNoMessageDialog, MessageDialog, ChangeEmailDialog, WaitDialog } from '../Dialog'
|
||||
import { YesNoMessageModal, MessageModal, ChangeEmailModal, WaitModal } from '../Modal'
|
||||
|
||||
export class Users extends React.Component {
|
||||
constructor() {
|
||||
@@ -14,10 +14,10 @@ export class Users extends React.Component {
|
||||
this.state = {
|
||||
selectedUser: null,
|
||||
users: [],
|
||||
yesNoDialog: null,
|
||||
messageDialog: null,
|
||||
waitDialog: null,
|
||||
changeEmailDialog: null
|
||||
yesNoModal: null,
|
||||
messageModal: null,
|
||||
waitModal: null,
|
||||
changeEmailModal: null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export class Users extends React.Component {
|
||||
this.setState({ users: list.items })
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
messageDialog: {
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'User List Error',
|
||||
message: `Unable to get the list of users. ${error.message}`
|
||||
@@ -50,10 +50,10 @@ export class Users extends React.Component {
|
||||
if (this.state.modified) {
|
||||
this.nextSelectedUser = user
|
||||
this.setState({
|
||||
yesNoDialog: {
|
||||
yesNoModal: {
|
||||
title: 'User Modified',
|
||||
message: 'This user has been modified. Are you sure you would like to navigate away?',
|
||||
onDismiss: this.handleModifiedDialogDismiss
|
||||
onDismiss: this.handleModifiedModalDismiss
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -64,18 +64,18 @@ export class Users extends React.Component {
|
||||
|
||||
handleSave(user) {
|
||||
if (user._id) {
|
||||
this.setState({ waitDialog: { message: 'Updating User' } })
|
||||
this.setState({ waitModal: { message: 'Updating User' } })
|
||||
api.updateUser(user).then((updatedUser) => {
|
||||
this.setState({
|
||||
waitDialog: null,
|
||||
waitModal: null,
|
||||
users: this.state.users.map((user) => (user._id === updatedUser._id ? updatedUser : user)),
|
||||
modified: false,
|
||||
selectedUser: updatedUser
|
||||
})
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
waitDialog: null,
|
||||
messageDialog: {
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Update Error',
|
||||
message: `Unable to save the user changes. ${error.message}`
|
||||
@@ -83,18 +83,18 @@ export class Users extends React.Component {
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.setState({ waitDialog: { message: 'Creating User' } })
|
||||
this.setState({ waitModal: { message: 'Creating User' } })
|
||||
api.createUser(user).then((createdUser) => {
|
||||
this.setState({
|
||||
waitDialog: false,
|
||||
waitModal: false,
|
||||
users: this.state.users.map((user) => (!user._id ? createdUser : user)),
|
||||
modified: false,
|
||||
selectedUser: createdUser
|
||||
})
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
waitDialog: null,
|
||||
messageDialog: {
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Create Error',
|
||||
message: `Unable to create the user. ${error.message}`
|
||||
@@ -105,17 +105,17 @@ export class Users extends React.Component {
|
||||
}
|
||||
|
||||
handleChangeEmail() {
|
||||
this.setState({ changeEmailDialog: {} })
|
||||
this.setState({ changeEmailModal: {} })
|
||||
}
|
||||
|
||||
handleResendEmail() {
|
||||
this.setState({
|
||||
waitDialog: { message: 'Resending Email...' }
|
||||
waitModal: { message: 'Resending Email...' }
|
||||
})
|
||||
api.sendConfirmEmail({ existingEmail: this.state.selectedUser.email }).then(() => {
|
||||
this.setState({
|
||||
waitDialog: null,
|
||||
messageDialog: {
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: false,
|
||||
title: "We've Re-Sent the Email...",
|
||||
message: `An email has been sent to '${this.state.selectedUser.email}'. This user will need to follow that email's included link to verify their account.`
|
||||
@@ -124,8 +124,8 @@ export class Users extends React.Component {
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
error: true,
|
||||
waitDialog: null,
|
||||
messageDialog: {
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Email Change Error...',
|
||||
message: `Unable to request email change. ${error ? error.message : ''}`
|
||||
@@ -135,17 +135,17 @@ export class Users extends React.Component {
|
||||
}
|
||||
|
||||
handleChangeEmailDismiss(newEmail) {
|
||||
this.setState({ changeEmailDialog: null })
|
||||
this.setState({ changeEmailModal: null })
|
||||
if (!newEmail) {
|
||||
return
|
||||
}
|
||||
this.setState({
|
||||
waitDialog: { message: 'Requesting Email Change...' }
|
||||
waitModal: { message: 'Requesting Email Change...' }
|
||||
})
|
||||
api.sendConfirmEmail({ existingEmail: this.state.selectedUser.email, newEmail }).then(() => {
|
||||
this.setState({
|
||||
waitDialog: null,
|
||||
messageDialog: {
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: false,
|
||||
title: 'Email Change Requested...',
|
||||
message: `An email has been sent to '${newEmail}'. This user will need to follow that email's included link to finish changing their email.`
|
||||
@@ -154,8 +154,8 @@ export class Users extends React.Component {
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
error: true,
|
||||
waitDialog: null,
|
||||
messageDialog: {
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Email Change Error...',
|
||||
message: `Unable to request email change. ${error ? error.message : ''}`
|
||||
@@ -166,32 +166,32 @@ export class Users extends React.Component {
|
||||
|
||||
handleRemove() {
|
||||
this.setState({
|
||||
yesNoDialog: {
|
||||
yesNoModal: {
|
||||
title: 'Permanently Delete User?',
|
||||
message: 'You are about to delete this user from the system. This includes references to this user in Projects, Packages, and so on. Are you sure you want to remove this user?',
|
||||
onDismiss: this.handleRemoveDialogDismiss
|
||||
onDismiss: this.handleRemoveModalDismiss
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleRemoveDialogDismiss(yes) {
|
||||
handleRemoveModalDismiss(yes) {
|
||||
if (yes) {
|
||||
// TODO: Pass the _id back from the dialog input data
|
||||
const selectedUserId = this.state.selectedUser._id
|
||||
const selectedIndex = this.state.users.findIndex((user) => (user._id === selectedUserId))
|
||||
|
||||
if (selectedIndex >= 0) {
|
||||
this.setState({ waitDialog: { message: 'Removing User' } })
|
||||
this.setState({ waitModal: { message: 'Removing User' } })
|
||||
api.deleteUser(selectedUserId).then(() => {
|
||||
this.setState({
|
||||
waitDialog: null,
|
||||
waitModal: null,
|
||||
users: [...this.state.users.slice(0, selectedIndex), ...this.state.users.slice(selectedIndex + 1)],
|
||||
selectedUser: null
|
||||
})
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
waitDialog: null,
|
||||
messageDialog: {
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Remove Error',
|
||||
message: `Unable to remove the user. ${error.message}`
|
||||
@@ -202,11 +202,11 @@ export class Users extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
yesNoDialog: null
|
||||
yesNoModal: null
|
||||
})
|
||||
}
|
||||
|
||||
handleModifiedDialogDismiss(yes) {
|
||||
handleModifiedModalDismiss(yes) {
|
||||
if (yes) {
|
||||
this.setState({
|
||||
selectedUser: this.nextSelectedUser,
|
||||
@@ -217,12 +217,12 @@ export class Users extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
yesNoDialog: null
|
||||
yesNoModal: null
|
||||
})
|
||||
}
|
||||
|
||||
handleMessageDialogDismiss() {
|
||||
this.setState({ messageDialog: null })
|
||||
handleMessageModalDismiss() {
|
||||
this.setState({ messageModal: null })
|
||||
}
|
||||
|
||||
handleModifiedChanged(modified) {
|
||||
@@ -260,21 +260,21 @@ export class Users extends React.Component {
|
||||
</Row.Item>
|
||||
</Row>
|
||||
|
||||
<ChangeEmailDialog open={!!this.state.changeEmailDialog} onDismiss={this.handleChangeEmailDismiss} />
|
||||
<ChangeEmailModal open={!!this.state.changeEmailModal} onDismiss={this.handleChangeEmailDismiss} />
|
||||
|
||||
<YesNoMessageDialog open={!!this.state.yesNoDialog}
|
||||
title={this.state.yesNoDialog ? this.state.yesNoDialog.title : ''}
|
||||
message={this.state.yesNoDialog ? this.state.yesNoDialog.message : ''}
|
||||
onDismiss={this.state.yesNoDialog ? this.state.yesNoDialog.onDismiss : null} />
|
||||
<YesNoMessageModal open={!!this.state.yesNoModal}
|
||||
title={this.state.yesNoModal ? this.state.yesNoModal.title : ''}
|
||||
message={this.state.yesNoModal ? this.state.yesNoModal.message : ''}
|
||||
onDismiss={this.state.yesNoModal ? this.state.yesNoModal.onDismiss : null} />
|
||||
|
||||
<MessageDialog
|
||||
open={!!this.state.messageDialog}
|
||||
error={this.state.messageDialog ? this.state.messageDialog.error : false}
|
||||
title={this.state.messageDialog ? this.state.messageDialog.title : ''}
|
||||
message={this.state.messageDialog ? this.state.messageDialog.message : ''}
|
||||
onDismiss={this.handleMessageDialogDismiss} />
|
||||
<MessageModal
|
||||
open={!!this.state.messageModal}
|
||||
error={this.state.messageModal ? this.state.messageModal.error : false}
|
||||
title={this.state.messageModal ? this.state.messageModal.title : ''}
|
||||
message={this.state.messageModal ? this.state.messageModal.message : ''}
|
||||
onDismiss={this.handleMessageModalDismiss} />
|
||||
|
||||
<WaitDialog active={!!this.state.waitDialog} message={this.state.waitDialog ? this.state.waitDialog.message : ''} />
|
||||
<WaitModal active={!!this.state.waitModal} message={this.state.waitModal ? this.state.waitModal.message : ''} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Text, Button, Icon } from 'ui'
|
||||
|
||||
// This is a validated component with a value that cannot change itself and is specialized
|
||||
|
||||
export class ValidatedEmailIcon extends React.Component {
|
||||
static propTypes = {
|
||||
name: PropTypes.string,
|
||||
validator: PropTypes.object,
|
||||
width: PropTypes.number,
|
||||
onClick: PropTypes.func
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = props.validator.getField('emailValidated')
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.validator !== this.props.validator) {
|
||||
this.setState(nextProps.validator.getField(nextProps.name))
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.value) {
|
||||
return (
|
||||
<div width={this.props.width}>
|
||||
<Text> </Text>
|
||||
<Icon name='mail' color='green' size='big' className='mail-validated-icon' />
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div width={this.props.width}>
|
||||
<Text> </Text>
|
||||
<Button fluid icon='mail outline' color='red' labelPosition='left'
|
||||
content='Resend Email' onClick={this.props.onClick} disabled={this.state.disabled} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user