325 lines
9.3 KiB
JavaScript
325 lines
9.3 KiB
JavaScript
import React from "react"
|
|
import PropTypes from "prop-types"
|
|
import autobind from "autobind-decorator"
|
|
import { regExpPattern } from "regexp-pattern"
|
|
import { api } from "src/API"
|
|
import {
|
|
Row,
|
|
Column,
|
|
BoundInput,
|
|
BoundButton,
|
|
BoundCheckbox,
|
|
BoundEmailIcon,
|
|
BoundDropdown,
|
|
} from "ui"
|
|
import { FormBinder } from "react-form-binder"
|
|
import { sizeInfo } from "ui/style"
|
|
|
|
export class UserForm extends React.Component {
|
|
static propTypes = {
|
|
user: PropTypes.object,
|
|
onSave: PropTypes.func,
|
|
onRemove: PropTypes.func,
|
|
onModifiedChanged: PropTypes.func,
|
|
onChangeEmail: PropTypes.func,
|
|
onResendEmail: PropTypes.func,
|
|
onResetPassword: PropTypes.func,
|
|
}
|
|
|
|
static bindings = {
|
|
email: {
|
|
isValid: (r, v) => regExpPattern.email.test(v),
|
|
isDisabled: (r) => r._id,
|
|
},
|
|
emailValidated: {
|
|
initValue: false,
|
|
isDisabled: (r) => !r._id,
|
|
},
|
|
resetPassword: {
|
|
noValue: true,
|
|
isDisabled: (r) => !r._id || api.loggedInUser._id === r._id,
|
|
},
|
|
changeEmail: {
|
|
noValue: true,
|
|
isDisabled: (r) => !r._id,
|
|
},
|
|
resendEmail: {
|
|
noValue: true,
|
|
isDisabled: (r) => !r._id || !!r.getFieldValue("emailValidated"),
|
|
},
|
|
firstName: {
|
|
isValid: (r, v) => v !== "",
|
|
},
|
|
lastName: {
|
|
isValid: (r, v) => v !== "",
|
|
},
|
|
team: {
|
|
isValid: true,
|
|
},
|
|
administrator: {
|
|
isValid: (r, v) => true,
|
|
initValue: false,
|
|
isDisabled: (r) => api.loggedInUser._id === r._id, // Adding a new user
|
|
alwaysGet: true,
|
|
},
|
|
remove: {
|
|
noValue: true,
|
|
isVisible: (r) => r._id,
|
|
isDisabled: (r) => api.loggedInUser._id === r._id,
|
|
},
|
|
reset: {
|
|
noValue: true,
|
|
isDisabled: (r) => {
|
|
return !r.anyModified
|
|
},
|
|
},
|
|
submit: {
|
|
noValue: true,
|
|
isDisabled: (r) => !r.anyModified || !r.allValid,
|
|
},
|
|
}
|
|
|
|
constructor(props) {
|
|
super(props)
|
|
this.state = {
|
|
binder: new FormBinder(
|
|
props.user,
|
|
UserForm.bindings,
|
|
props.onModifiedChanged
|
|
),
|
|
teams: [],
|
|
}
|
|
|
|
this.getTeams()
|
|
}
|
|
|
|
// TODO: This is not very efficient. Better to get the teams in User.js and pass them in
|
|
// This however will always be up-to-date. Need to use the WebSocket to refresh.
|
|
getTeams() {
|
|
api
|
|
.listTeams()
|
|
.then((list) => {
|
|
this.setState({
|
|
teams: list.items
|
|
.map((item) => ({ value: item._id, text: item.name, icon: "team" }))
|
|
.sort((a, b) => a.text.localeCompare(b.text)),
|
|
})
|
|
})
|
|
.catch(() => {
|
|
this.setState({ teams: [] })
|
|
})
|
|
}
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
if (nextProps.user !== this.props.user) {
|
|
this.setState({
|
|
binder: new FormBinder(
|
|
nextProps.user,
|
|
UserForm.bindings,
|
|
nextProps.onModifiedChanged
|
|
),
|
|
})
|
|
|
|
this.getTeams()
|
|
}
|
|
}
|
|
|
|
@autobind
|
|
handleSubmit(e) {
|
|
e.preventDefault()
|
|
|
|
let obj = this.state.binder.getModifiedFieldValues()
|
|
|
|
if (obj) {
|
|
this.props.onSave(obj)
|
|
}
|
|
}
|
|
|
|
@autobind
|
|
handleReset() {
|
|
const { user, onModifiedChanged } = this.props
|
|
|
|
this.setState({
|
|
binder: new FormBinder(user, UserForm.bindings, onModifiedChanged),
|
|
})
|
|
|
|
if (onModifiedChanged) {
|
|
onModifiedChanged(false)
|
|
}
|
|
}
|
|
|
|
@autobind
|
|
handleChangeEmail() {
|
|
const { onChangeEmail } = this.props
|
|
|
|
if (onChangeEmail) {
|
|
onChangeEmail()
|
|
}
|
|
}
|
|
|
|
@autobind
|
|
handleResendEmail() {
|
|
const { onResendEmail } = this.props
|
|
if (onResendEmail) {
|
|
onResendEmail()
|
|
}
|
|
}
|
|
|
|
@autobind
|
|
handleResetPassword() {
|
|
const { onResetPassword } = this.props
|
|
if (onResetPassword) {
|
|
onResetPassword()
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const { binder, teams } = this.state
|
|
|
|
return (
|
|
<form
|
|
style={{ width: "100%", height: "100%", overflow: "scroll" }}
|
|
id="userForm"
|
|
onSubmit={this.handleSubmit}>
|
|
<Column>
|
|
<Column.Item height={sizeInfo.formColumnSpacing} />
|
|
<Row>
|
|
<Row.Item width={sizeInfo.formRowSpacing} />
|
|
<Row.Item grow>
|
|
<Column.Item>
|
|
<Column>
|
|
<Column.Item>
|
|
<Row>
|
|
<Row.Item grow>
|
|
<BoundInput
|
|
label="First Name"
|
|
name="firstName"
|
|
message="Must not be empty"
|
|
binder={binder}
|
|
/>
|
|
</Row.Item>
|
|
<Row.Item width={sizeInfo.formRowSpacing} />
|
|
<Row.Item grow>
|
|
<BoundInput
|
|
label="Last Name"
|
|
name="lastName"
|
|
binder={binder}
|
|
/>
|
|
</Row.Item>
|
|
</Row>
|
|
</Column.Item>
|
|
<Column.Item>
|
|
<Row>
|
|
<Row.Item grow>
|
|
<BoundInput
|
|
label="Email"
|
|
name="email"
|
|
message="Must be a valid email address. Required."
|
|
binder={binder}
|
|
/>
|
|
</Row.Item>
|
|
<Row.Item width={sizeInfo.formRowSpacing} />
|
|
<Row.Item>
|
|
<BoundEmailIcon name="emailValidated" binder={binder} />
|
|
</Row.Item>
|
|
</Row>
|
|
</Column.Item>
|
|
<Column.Item>
|
|
<BoundDropdown
|
|
name="team"
|
|
label="Team"
|
|
icon="team"
|
|
items={teams}
|
|
binder={binder}
|
|
/>
|
|
</Column.Item>
|
|
<Column.Item height={sizeInfo.formColumnSpacing} />
|
|
<Column.Item minHeight={sizeInfo.buttonHeight}>
|
|
<Row>
|
|
<Row.Item>
|
|
<BoundButton
|
|
text="Reset Password"
|
|
name="resetPassword"
|
|
binder={binder}
|
|
width={sizeInfo.buttonWideWidth}
|
|
onClick={this.handleResetPassword}
|
|
/>
|
|
</Row.Item>
|
|
<Row.Item grow />
|
|
<Row.Item>
|
|
<BoundButton
|
|
text="Change Email"
|
|
name="changeEmail"
|
|
binder={binder}
|
|
width={sizeInfo.buttonWideWidth}
|
|
onClick={this.handleChangeEmail}
|
|
/>
|
|
</Row.Item>
|
|
<Row.Item width={sizeInfo.formRowSpacing} />
|
|
<Row.Item>
|
|
<BoundButton
|
|
text="Resend Confirmation Email"
|
|
name="resendEmail"
|
|
binder={binder}
|
|
width={sizeInfo.buttonWideWidth}
|
|
onClick={this.handleResendEmail}
|
|
/>
|
|
</Row.Item>
|
|
</Row>
|
|
</Column.Item>
|
|
<Column.Item height={sizeInfo.formColumnSpacing} />
|
|
<Column.Item>
|
|
<Row>
|
|
<Row.Item>
|
|
<BoundCheckbox
|
|
label={"Administrator"}
|
|
name="administrator"
|
|
binder={this.state.binder}
|
|
/>
|
|
</Row.Item>
|
|
<Row.Item grow />
|
|
</Row>
|
|
</Column.Item>
|
|
<Column.Item height={sizeInfo.formColumnSpacing} />
|
|
<Column.Item minHeight={sizeInfo.buttonHeight}>
|
|
<Row>
|
|
<Row.Item>
|
|
<BoundButton
|
|
text="Reset"
|
|
name="reset"
|
|
binder={binder}
|
|
onClick={this.handleReset}
|
|
/>
|
|
</Row.Item>
|
|
<Row.Item grow />
|
|
<Row.Item>
|
|
<BoundButton
|
|
text="Remove"
|
|
name="remove"
|
|
binder={binder}
|
|
onClick={this.props.onRemove}
|
|
/>
|
|
</Row.Item>
|
|
<Row.Item width={sizeInfo.formRowSpacing} />
|
|
<Row.Item>
|
|
<BoundButton
|
|
submit="userForm"
|
|
text={binder._id ? "Save" : "Add"}
|
|
name="submit"
|
|
binder={binder}
|
|
/>
|
|
</Row.Item>
|
|
</Row>
|
|
</Column.Item>
|
|
</Column>
|
|
</Column.Item>
|
|
</Row.Item>
|
|
<Row.Item width={sizeInfo.formRowSpacing} />
|
|
</Row>
|
|
<Column.Item height={sizeInfo.formColumnSpacing} />
|
|
</Column>
|
|
</form>
|
|
)
|
|
}
|
|
}
|