Files
deighton-ar/website/src/Users/Users.js
2018-03-06 07:43:21 -08:00

294 lines
8.4 KiB
JavaScript

import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'
import { reactAutoBind } from 'auto-bind2'
import { UserList } from './UserList'
import { UserForm } from './UserForm'
import { UserFormPlaceholder } from './UserFormPlaceholder'
import { api } from 'src/API'
import { Row, Column, Box } from 'ui'
import { YesNoMessageModal, MessageModal, ChangeEmailModal, WaitModal } from '../Modal'
import { sizeInfo, colorInfo } from 'ui/style'
export class Users extends Component {
static propTypes = {
onChangeTitle: PropTypes.func.isRequired,
}
constructor(props) {
super(props)
reactAutoBind(this)
this.state = {
modified: false,
selectedUser: null,
users: [],
yesNoModal: null,
messageModal: null,
waitModal: null,
changeEmailModal: null
}
}
componentDidMount() {
this.props.onChangeTitle('Users')
api.listUsers().then((list) => {
list.items.sort((userA, userB) => (userA.lastName.localeCompare(userB.lastName)))
this.setState({ users: list.items })
}).catch((error) => {
this.setState({
messageModal: {
icon: 'hand',
message: 'Unable to get the list of users.',
detail: error.message,
}
})
})
}
removeUnfinishedNewUser() {
let users = this.state.users
if (users.length > 0 && !users[0]._id) {
this.setState({ users: this.state.users.slice(1) })
}
}
handleUserListClick(e, index) {
let user = this.state.users[index]
if (this.state.modified) {
this.nextSelectedUser = user
this.setState({
yesNoModal: {
question: 'This user has been modified. Are you sure you would like to navigate away?',
onDismiss: this.handleModifiedModalDismiss
}
})
} else {
this.setState({ selectedUser: user })
this.removeUnfinishedNewUser()
}
}
handleSave(user) {
if (user._id) {
this.setState({ waitModal: { message: 'Updating User' } })
api.updateUser(user).then((updatedUser) => {
this.setState({
waitModal: null,
users: this.state.users.map((user) => (user._id === updatedUser._id ? updatedUser : user)),
modified: false,
selectedUser: updatedUser
})
}).catch((error) => {
this.setState({
waitModal: null,
messageModal: {
icon: 'hand',
message: 'Unable to save the user changes',
detail: error.message,
}
})
})
} else {
this.setState({ waitModal: { message: 'Creating User' } })
api.createUser(user).then((createdUser) => {
this.setState({
waitModal: false,
users: this.state.users.map((user) => (!user._id ? createdUser : user)).sort((a, b) => (
a.lastName < b.lastName ? -1 : a.lastName > b.lastName : 0
)),
modified: false,
selectedUser: createdUser
})
}).catch((error) => {
this.setState({
waitModal: null,
messageModal: {
icon: 'hand',
message: 'Unable to create the user.',
detail: error.message,
}
})
})
}
}
handleChangeEmail() {
this.setState({ changeEmailModal: {} })
}
handleResendEmail() {
this.setState({
waitModal: { message: 'Resending Email...' }
})
api.sendConfirmEmail({ existingEmail: this.state.selectedUser.email }).then(() => {
this.setState({
waitModal: null,
messageModal: {
icon: 'thumb',
message: `An email has been sent to '${this.state.selectedUser.email}' with further instructions.`
}
})
}).catch((error) => {
this.setState({
error: true,
waitModal: null,
messageModal: {
error: 'hand',
message: 'Unable to request email change.',
detail: error.message,
}
})
})
}
handleChangeEmailDismiss(newEmail) {
this.setState({ changeEmailModal: null })
if (!newEmail) {
return
}
this.setState({
waitModal: { message: 'Requesting Email Change...' }
})
api.sendConfirmEmail({ existingEmail: this.state.selectedUser.email, newEmail }).then(() => {
this.setState({
waitModal: null,
messageModal: {
icon: 'hand',
message: `An email has been sent to '${newEmail}' to confirm this email.`
}
})
}).catch((error) => {
this.setState({
error: true,
waitModal: null,
messageModal: {
icon: 'hand',
message: 'Unable to request email change.',
detail: error.message,
}
})
})
}
handleRemove() {
this.setState({
yesNoModal: {
question: 'Are you sure you want to remove this user? This will also remove them from any teams they belong to.',
onDismiss: this.handleRemoveModalDismiss
}
})
}
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({ waitModal: { message: 'Removing User' } })
api.deleteUser(selectedUserId).then(() => {
this.setState({
waitModal: null,
users: [...this.state.users.slice(0, selectedIndex), ...this.state.users.slice(selectedIndex + 1)],
selectedUser: null
})
}).catch((error) => {
this.setState({
waitModal: null,
messageModal: {
icon: 'hand',
message: 'Unable to remove the user.',
detail: error.message,
}
})
})
}
}
this.setState({
yesNoModal: null
})
}
handleModifiedModalDismiss(yes) {
if (yes) {
this.setState({
selectedUser: this.nextSelectedUser,
modified: false
})
this.removeUnfinishedNewUser()
delete this.nextSelectedUser
}
this.setState({
yesNoModal: null
})
}
handleMessageModalDismiss() {
this.setState({ messageModal: null })
}
handleModifiedChanged(modified) {
this.setState({ modified: modified })
}
handleAddNewUser() {
let newUser = {}
let newUsers = [newUser].concat(this.state.users)
this.setState({ users: newUsers, selectedUser: newUser })
}
render() {
const { messageModal, yesNoModal } = this.state
return (
<Fragment>
<Column.Item height={20} />
<Column.Item grow>
<Row fillParent>
<Row.Item width={20} />
<Row.Item width='25vw'>
<UserList users={this.state.users} selectedUser={this.state.selectedUser}
selectionModified={this.state.modified} onUserListClick={this.handleUserListClick}
onAddNewUser={this.handleAddNewUser} />
</Row.Item>
<Row.Item width={20} />
<Row.Item grow>
<Box border={{ width: sizeInfo.headerBorderWidth, color: colorInfo.headerBorder }} radius={sizeInfo.formBoxRadius}>
{
this.state.selectedUser
? <UserForm user={this.state.selectedUser} onSave={this.handleSave}
onRemove={this.handleRemove} onModifiedChanged={this.handleModifiedChanged}
onChangeEmail={this.handleChangeEmail} onResendEmail={this.handleResendEmail} />
: <UserFormPlaceholder />
}
</Box>
</Row.Item>
<Row.Item width={20} />
</Row>
</Column.Item>
<Column.Item height={20}>
<ChangeEmailModal open={!!this.state.changeEmailModal} onDismiss={this.handleChangeEmailDismiss} />
<YesNoMessageModal open={!!yesNoModal}
question={yesNoModal ? yesNoModal.question : ''}
onDismiss={yesNoModal ? yesNoModal.onDismiss : null} />
<MessageModal
open={!!messageModal}
icon={messageModal ? messageModal.icon : ''}
message={messageModal ? messageModal.message : ''}
detail={messageModal ? messageModal.detail : null}
onDismiss={this.handleMessageModalDismiss} />
<WaitModal active={!!this.state.waitModal} message={this.state.waitModal ? this.state.waitModal.message : ''} />
</Column.Item>
</Fragment>
)
}
}