New assets, fixed list box scrolling, header text, etc..
This commit is contained in:
@@ -12,7 +12,7 @@ export class UserForm extends React.Component {
|
||||
user: PropTypes.object,
|
||||
onSave: PropTypes.func,
|
||||
onRemove: PropTypes.func,
|
||||
onAnyModified: PropTypes.func,
|
||||
onModifiedChanged: PropTypes.func,
|
||||
onChangeEmail: PropTypes.func,
|
||||
onResendEmail: PropTypes.func
|
||||
}
|
||||
@@ -20,18 +20,18 @@ export class UserForm extends React.Component {
|
||||
static bindings = {
|
||||
email: {
|
||||
isValid: (r, v) => (regExpPattern.email.test(v)),
|
||||
isDisabled: (r) => (!!r._id)
|
||||
isDisabled: (r) => (r._id)
|
||||
},
|
||||
emailValidated: {
|
||||
isDisabled: (r) => (!!r._id === false)
|
||||
isDisabled: (r) => (!r._id)
|
||||
},
|
||||
changeEmail: {
|
||||
nonValue: true,
|
||||
isDisabled: (r) => (!!r._id === false)
|
||||
isDisabled: (r) => (!r._id)
|
||||
},
|
||||
resendEmail: {
|
||||
nonValue: true,
|
||||
isDisabled: (r) => (!!r._id === false)
|
||||
isDisabled: (r) => (!r._id || !!r.getFieldValue('emailValidated'))
|
||||
},
|
||||
firstName: {
|
||||
isValid: (r, v) => (v !== '')
|
||||
@@ -40,15 +40,13 @@ export class UserForm extends React.Component {
|
||||
isValid: (r, v) => (v !== '')
|
||||
},
|
||||
administrator: {
|
||||
isValid: (r, v) => (v !== ''),
|
||||
isDisabled: (r) => (api.loggedInUser._id === r._id) // Adding a new user
|
||||
},
|
||||
project: {
|
||||
isValid: (r, v) => (v !== '' || v === '')
|
||||
isValid: (r, v) => true,
|
||||
isDisabled: (r) => (api.loggedInUser._id === r._id), // Adding a new user
|
||||
alwaysGet: true,
|
||||
},
|
||||
remove: {
|
||||
nonValue: true,
|
||||
isVisible: (r) => (!!r._id),
|
||||
isVisible: (r) => (r._id),
|
||||
isDisabled: (r) => (api.loggedInUser._id === r._id)
|
||||
},
|
||||
reset: {
|
||||
@@ -57,7 +55,7 @@ export class UserForm extends React.Component {
|
||||
},
|
||||
submit: {
|
||||
nonValue: true,
|
||||
isDisabled: (r) => (!r.anyModified && !r.allValid)
|
||||
isDisabled: (r) => (!r.anyModified || !r.allValid),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -65,33 +63,35 @@ export class UserForm extends React.Component {
|
||||
super(props)
|
||||
reactAutoBind(this)
|
||||
this.state = {
|
||||
binder: new FormBinder(this.props.user, UserForm.bindings, this.props.onAnyModified)
|
||||
binder: new FormBinder(this.props.user, UserForm.bindings, this.props.onModifiedChanged)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.user !== this.props.user) {
|
||||
this.setState({
|
||||
binder: new FormBinder(nextProps.user, UserForm.bindings, nextProps.onAnyModified)
|
||||
binder: new FormBinder(nextProps.user, UserForm.bindings, nextProps.onModifiedChanged)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault()
|
||||
let obj = this.state.binder.getValues()
|
||||
|
||||
let obj = this.state.binder.getModifiedFieldValues()
|
||||
|
||||
if (obj) {
|
||||
this.props.onSave(obj)
|
||||
}
|
||||
}
|
||||
|
||||
handleReset() {
|
||||
const { user, onAnyModified } = this.props
|
||||
const { user, onModifiedChanged } = this.props
|
||||
|
||||
this.setState({ binder: new FormBinder(user, UserForm.bindings, onAnyModified) })
|
||||
this.setState({ binder: new FormBinder(user, UserForm.bindings, onModifiedChanged) })
|
||||
|
||||
if (onAnyModified) {
|
||||
onAnyModified(false)
|
||||
if (onModifiedChanged) {
|
||||
onModifiedChanged(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ export class UserForm extends React.Component {
|
||||
const { binder } = this.state
|
||||
|
||||
return (
|
||||
<form id='userForm' onSubmit={this.handleSubmit}>
|
||||
<form style={{ width: '100%', height: '100%', overflow: 'scroll' }} id='userForm' onSubmit={this.handleSubmit}>
|
||||
<Column>
|
||||
<Column.Item height={20} />
|
||||
<Row>
|
||||
@@ -118,18 +118,17 @@ export class UserForm extends React.Component {
|
||||
<Column.Item>
|
||||
<Row>
|
||||
<Row.Item grow>
|
||||
<BoundInput label='First Name' name='firstName' binder={binder} />
|
||||
<BoundInput label='First Name' name='firstName' message='Must not be empty' binder={binder} />
|
||||
</Row.Item>
|
||||
<Row.Item width={20} />
|
||||
<Row.Item grow>
|
||||
<BoundInput label='Last Name' name='lastName' binder={binder} />
|
||||
</Row.Item>
|
||||
<Row.Item width={20} />
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<Row>
|
||||
<Row.Item>
|
||||
<Row.Item grow>
|
||||
<BoundInput label='Email' name='email' message='Must be a valid email address. Required.' binder={binder} />
|
||||
</Row.Item>
|
||||
<Row.Item width={10} />
|
||||
@@ -138,17 +137,21 @@ export class UserForm extends React.Component {
|
||||
</Row.Item>
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item height={20} />
|
||||
<Column.Item minHeight={sizeInfo.buttonHeight}>
|
||||
<Row>
|
||||
<Row.Item>
|
||||
<BoundButton text='Change Email' name='changeEmail' binder={binder} onClick={this.handleChangeEmail} />
|
||||
<BoundButton text='Change Email' name='changeEmail' binder={binder}
|
||||
width={220} onClick={this.handleChangeEmail} />
|
||||
</Row.Item>
|
||||
<Row.Item grow />
|
||||
<Row.Item>
|
||||
<BoundButton text='Resend Confirmation Email' name='resendEmail' binder={binder} onClick={this.handleResendEmail} />
|
||||
<BoundButton text='Resend Confirmation Email' name='resendEmail' binder={binder}
|
||||
width={220} onClick={this.handleResendEmail} />
|
||||
</Row.Item>
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item height={20} />
|
||||
<Column.Item>
|
||||
<Row>
|
||||
<Row.Item>
|
||||
@@ -157,6 +160,7 @@ export class UserForm extends React.Component {
|
||||
<Row.Item grow />
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item height={20} />
|
||||
<Column.Item minHeight={sizeInfo.buttonHeight}>
|
||||
<Row>
|
||||
<Row.Item>
|
||||
@@ -166,6 +170,7 @@ export class UserForm extends React.Component {
|
||||
<Row.Item>
|
||||
<BoundButton text='Remove' name='remove' binder={binder} onClick={this.props.onRemove} />
|
||||
</Row.Item>
|
||||
<Row.Item width={20} />
|
||||
<Row.Item>
|
||||
<BoundButton submit='userForm' text={binder._id ? 'Save' : 'Add'} name='submit' binder={binder} />
|
||||
</Row.Item>
|
||||
|
||||
@@ -17,7 +17,6 @@ export class UserList extends React.Component {
|
||||
this.state = {
|
||||
users: null
|
||||
}
|
||||
this.filterUsers = this.filterUsers.bind(this)
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
@@ -26,16 +25,9 @@ export class UserList extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
filterUsers(e, data) {
|
||||
e.preventDefault()
|
||||
let users = this.props.users
|
||||
if (data.value !== 'all') {
|
||||
users = users.filter(user => data.value === user.role)
|
||||
}
|
||||
this.setState({ users })
|
||||
}
|
||||
|
||||
render() {
|
||||
const { selectedUser, selectionModified } = this.props
|
||||
|
||||
return (
|
||||
<Column fillParent>
|
||||
<Column.Item grow>
|
||||
@@ -43,13 +35,13 @@ export class UserList extends React.Component {
|
||||
{
|
||||
this.state.users
|
||||
? this.state.users.map((user, index) =>
|
||||
(<List.Item className='user-list-item' key={user._id || '0'} onClick={this.props.onUserListClick}
|
||||
active={user === this.props.selectedUser} data-index={index}>
|
||||
<List.Icon name='profile' size={30} />
|
||||
(<List.Item className='user-list-item' key={user._id || '0'} onClick={(e) => (this.props.onUserListClick(e, index))}
|
||||
active={user === this.props.selectedUser}>
|
||||
<List.Icon name={user.administrator ? 'admin' : 'profile'} size={25} />
|
||||
<List.Text>
|
||||
{ user._id ? user.firstName + ' ' + user.lastName : '[New User]' }
|
||||
</List.Text>
|
||||
{ user === this.props.selectedUser && this.props.selectionModified ? <List.Icon className='user-update' name='edit' /> : null }
|
||||
{ user === selectedUser && selectionModified ? <List.Icon name='edit' size={25} /> : null }
|
||||
</List.Item>)
|
||||
)
|
||||
: null
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { Component, Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { reactAutoBind } from 'auto-bind2'
|
||||
import { UserList } from './UserList'
|
||||
import { UserForm } from './UserForm'
|
||||
@@ -9,10 +10,15 @@ import { YesNoMessageModal, MessageModal, ChangeEmailModal, WaitModal } from '..
|
||||
import { sizeInfo, colorInfo } from 'ui/style'
|
||||
|
||||
export class Users extends Component {
|
||||
constructor() {
|
||||
super()
|
||||
static propTypes = {
|
||||
onChangeTitle: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
reactAutoBind(this)
|
||||
this.state = {
|
||||
modified: false,
|
||||
selectedUser: null,
|
||||
users: [],
|
||||
yesNoModal: null,
|
||||
@@ -23,15 +29,17 @@ export class Users extends Component {
|
||||
}
|
||||
|
||||
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: {
|
||||
error: true,
|
||||
title: 'User List Error',
|
||||
message: `Unable to get the list of users. ${error.message}`
|
||||
icon: 'hand',
|
||||
message: 'Unable to get the list of users.',
|
||||
detail: error.message,
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -45,15 +53,14 @@ export class Users extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleUserListClick(e) {
|
||||
let user = this.state.users[Number(e.currentTarget.getAttribute('data-index'))]
|
||||
handleUserListClick(e, index) {
|
||||
let user = this.state.users[index]
|
||||
|
||||
if (this.state.modified) {
|
||||
this.nextSelectedUser = user
|
||||
this.setState({
|
||||
yesNoModal: {
|
||||
title: 'User Modified',
|
||||
message: 'This user has been modified. Are you sure you would like to navigate away?',
|
||||
question: 'This user has been modified. Are you sure you would like to navigate away?',
|
||||
onDismiss: this.handleModifiedModalDismiss
|
||||
}
|
||||
})
|
||||
@@ -77,9 +84,9 @@ export class Users extends Component {
|
||||
this.setState({
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Update Error',
|
||||
message: `Unable to save the user changes. ${error.message}`
|
||||
icon: 'hand',
|
||||
message: 'Unable to save the user changes',
|
||||
detail: error.message,
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -88,7 +95,9 @@ export class Users extends Component {
|
||||
api.createUser(user).then((createdUser) => {
|
||||
this.setState({
|
||||
waitModal: false,
|
||||
users: this.state.users.map((user) => (!user._id ? createdUser : user)),
|
||||
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
|
||||
})
|
||||
@@ -96,9 +105,9 @@ export class Users extends Component {
|
||||
this.setState({
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Create Error',
|
||||
message: `Unable to create the user. ${error.message}`
|
||||
icon: 'hand',
|
||||
message: 'Unable to create the user.',
|
||||
detail: error.message,
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -117,9 +126,8 @@ export class Users extends Component {
|
||||
this.setState({
|
||||
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.`
|
||||
icon: 'thumb',
|
||||
message: `An email has been sent to '${this.state.selectedUser.email}' with further instructions.`
|
||||
}
|
||||
})
|
||||
}).catch((error) => {
|
||||
@@ -127,9 +135,9 @@ export class Users extends Component {
|
||||
error: true,
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Email Change Error...',
|
||||
message: `Unable to request email change. ${error ? error.message : ''}`
|
||||
error: 'hand',
|
||||
message: 'Unable to request email change.',
|
||||
detail: error.message,
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -147,9 +155,8 @@ export class Users extends Component {
|
||||
this.setState({
|
||||
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.`
|
||||
icon: 'hand',
|
||||
message: `An email has been sent to '${newEmail}' to confirm this email.`
|
||||
}
|
||||
})
|
||||
}).catch((error) => {
|
||||
@@ -157,9 +164,9 @@ export class Users extends Component {
|
||||
error: true,
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Email Change Error...',
|
||||
message: `Unable to request email change. ${error ? error.message : ''}`
|
||||
icon: 'hand',
|
||||
message: 'Unable to request email change.',
|
||||
detail: error.message,
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -168,8 +175,7 @@ export class Users extends Component {
|
||||
handleRemove() {
|
||||
this.setState({
|
||||
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?',
|
||||
question: 'Are you sure you want to remove this user? This will also remove them from any teams they belong to.',
|
||||
onDismiss: this.handleRemoveModalDismiss
|
||||
}
|
||||
})
|
||||
@@ -193,9 +199,9 @@ export class Users extends Component {
|
||||
this.setState({
|
||||
waitModal: null,
|
||||
messageModal: {
|
||||
error: true,
|
||||
title: 'Remove Error',
|
||||
message: `Unable to remove the user. ${error.message}`
|
||||
icon: 'hand',
|
||||
message: 'Unable to remove the user.',
|
||||
detail: error.message,
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -237,7 +243,7 @@ export class Users extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { messageModal } = this.state
|
||||
const { messageModal, yesNoModal } = this.state
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
@@ -268,17 +274,15 @@ export class Users extends Component {
|
||||
<Column.Item height={20}>
|
||||
<ChangeEmailModal open={!!this.state.changeEmailModal} onDismiss={this.handleChangeEmailDismiss} />
|
||||
|
||||
<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} />
|
||||
<YesNoMessageModal open={!!yesNoModal}
|
||||
question={yesNoModal ? yesNoModal.question : ''}
|
||||
onDismiss={yesNoModal ? yesNoModal.onDismiss : null} />
|
||||
|
||||
<MessageModal
|
||||
open={!!messageModal}
|
||||
icon={messageModal ? messageModal.icon : ''}
|
||||
error={messageModal ? messageModal.error : false}
|
||||
title={messageModal ? messageModal.title : ''}
|
||||
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 : ''} />
|
||||
|
||||
Reference in New Issue
Block a user