Upgrade to new form binder

This commit is contained in:
John Lyon-Smith
2018-05-15 13:09:13 -07:00
parent 8fcfa26063
commit aa2da7d55d
26 changed files with 307 additions and 194 deletions

View File

@@ -5109,9 +5109,9 @@
} }
}, },
"react-form-binder": { "react-form-binder": {
"version": "2.0.1", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/react-form-binder/-/react-form-binder-2.0.1.tgz", "resolved": "https://registry.npmjs.org/react-form-binder/-/react-form-binder-3.0.0.tgz",
"integrity": "sha512-QOIO7dd6s+zvw6V3JdaWbuCKm6OwunOemuvR7ds98nnPoUXXZ3Fv4SLRGkt3GcI97a5PDlWvNAN/9qz571SHjA==", "integrity": "sha512-XPXw+OVxfko1rcN1WjLxaCt8FVZaWrjCI7XNaNx1Su8/QFDqeAh1dgWpySE31i73un2v3ig+0r0WL+lHaV9Y3Q==",
"requires": { "requires": {
"eventemitter3": "^2.0.3", "eventemitter3": "^2.0.3",
"prop-types": "^15.5.10", "prop-types": "^15.5.10",

View File

@@ -23,7 +23,7 @@
"eventemitter3": "^3.1.0", "eventemitter3": "^3.1.0",
"moment": "^2.22.1", "moment": "^2.22.1",
"react": "^16.3.2", "react": "^16.3.2",
"react-form-binder": "^2.0.1", "react-form-binder": "^3.0.0",
"react-native": "^0.55.4", "react-native": "^0.55.4",
"react-native-fs": "^2.9.12", "react-native-fs": "^2.9.12",
"react-native-image-picker": "^0.26.7", "react-native-image-picker": "^0.26.7",

View File

@@ -191,7 +191,7 @@ export class Activity extends React.Component {
@autobind @autobind
handleDonePress() { handleDonePress() {
const { binder } = this.state const { binder } = this.state
let obj = binder.getModifiedFieldValues() let obj = binder.getmodifiedBindingValues()
if (!obj._id) { if (!obj._id) {
api api

View File

@@ -94,7 +94,7 @@ export class Login extends React.Component {
@autobind @autobind
handleLogin() { handleLogin() {
let obj = this.state.binder.getModifiedFieldValues() let obj = this.state.binder.getmodifiedBindingValues()
let { history } = this.props let { history } = this.props
if (obj) { if (obj) {

View File

@@ -64,6 +64,10 @@ export class WorkItem extends React.Component {
isValid: (r, v) => v !== "", isValid: (r, v) => v !== "",
isReadOnly: true, isReadOnly: true,
alwaysGet: true, alwaysGet: true,
initValue: null,
pre: (v) =>
v !== null && formatLatLng(v.coordinates[1], v.coordinates[0]),
post: (v) => parseLatLng(v),
}, },
address: { address: {
isValid: true, isValid: true,
@@ -105,10 +109,10 @@ export class WorkItem extends React.Component {
.getWorkItem(id) .getWorkItem(id)
.then((workItem) => { .then((workItem) => {
if (workItem) { if (workItem) {
const [lng, lat] = workItem.location.coordinates const [longitude, latitude] = workItem.location.coordinates
const region = { const region = {
latitude: lat, latitude,
longitude: lng, longitude,
latitudeDelta: 0.01, latitudeDelta: 0.01,
longitudeDelta: 0.01, longitudeDelta: 0.01,
} }
@@ -119,7 +123,6 @@ export class WorkItem extends React.Component {
this.goToRegion = region this.goToRegion = region
} }
workItem.location = formatLatLng(lat, lng)
this.setState({ this.setState({
binder: new FormBinder(workItem, WorkItem.bindings), binder: new FormBinder(workItem, WorkItem.bindings),
}) })
@@ -158,9 +161,7 @@ export class WorkItem extends React.Component {
@autobind @autobind
handleDonePress() { handleDonePress() {
const { binder } = this.state const { binder } = this.state
let obj = binder.getModifiedFieldValues() let obj = binder.getmodifiedBindingValues()
obj.location = parseLatLng(obj.location)
if (!obj._id) { if (!obj._id) {
api api

View File

@@ -1,7 +1,7 @@
import React from 'react' import React from "react"
import PropTypes from 'prop-types' import PropTypes from "prop-types"
import { View, Text, TouchableHighlight } from 'react-native' import { View, Text, TouchableHighlight } from "react-native"
import autobind from 'autobind-decorator' import autobind from "autobind-decorator"
export class BoundButton extends React.Component { export class BoundButton extends React.Component {
static propTypes = { static propTypes = {
@@ -9,7 +9,7 @@ export class BoundButton extends React.Component {
title: PropTypes.string, title: PropTypes.string,
binder: PropTypes.object.isRequired, binder: PropTypes.object.isRequired,
onPress: PropTypes.func, onPress: PropTypes.func,
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]), width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
} }
constructor(props) { constructor(props) {
@@ -18,7 +18,7 @@ export class BoundButton extends React.Component {
const { name, binder } = this.props const { name, binder } = this.props
binder.addListener(name, this.updateValue) binder.addListener(name, this.updateValue)
this.state = binder.getFieldState(name) this.state = binder.getBindingState(name)
} }
@autobind @autobind
@@ -34,7 +34,7 @@ export class BoundButton extends React.Component {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.props.binder.removeListener(this.props.name, this.updateValue) this.props.binder.removeListener(this.props.name, this.updateValue)
nextProps.binder.addListener(nextProps.name, this.updateValue) nextProps.binder.addListener(nextProps.name, this.updateValue)
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }
@@ -48,17 +48,31 @@ export class BoundButton extends React.Component {
if (disabled) { if (disabled) {
return ( return (
<View style={{ flexDirection: 'column', justifyContent: 'center', paddingHorizontal: 10, height: 40, width , backgroundColor: '#E0E0E0' }}> <View
<Text style={{ alignSelf: 'center', color: '#AAAAAA' }}>{title}</Text> style={{
flexDirection: "column",
justifyContent: "center",
paddingHorizontal: 10,
height: 40,
width,
backgroundColor: "#E0E0E0",
}}>
<Text style={{ alignSelf: "center", color: "#AAAAAA" }}>{title}</Text>
</View> </View>
) )
} else { } else {
return ( return (
<TouchableHighlight <TouchableHighlight
onPress={onPress} onPress={onPress}
style={{ justifyContent: 'center', paddingHorizontal: 10, height: 40, width, backgroundColor: '#3BB0FD' }} style={{
underlayColor='#1A72AC'> justifyContent: "center",
<Text style={{ alignSelf: 'center', color: 'black' }}>{title}</Text> paddingHorizontal: 10,
height: 40,
width,
backgroundColor: "#3BB0FD",
}}
underlayColor="#1A72AC">
<Text style={{ alignSelf: "center", color: "black" }}>{title}</Text>
</TouchableHighlight> </TouchableHighlight>
) )
} }

View File

@@ -1,9 +1,12 @@
import React from 'react' import React from "react"
import PropTypes from 'prop-types' import PropTypes from "prop-types"
import { Header } from '.' import { Header } from "."
import autobind from 'autobind-decorator' import autobind from "autobind-decorator"
const headerButtonShape = { icon: PropTypes.string.isRequired, onPress: PropTypes.func } const headerButtonShape = {
icon: PropTypes.string.isRequired,
onPress: PropTypes.func,
}
export class BoundHeader extends React.Component { export class BoundHeader extends React.Component {
static propTypes = { static propTypes = {
@@ -20,7 +23,7 @@ export class BoundHeader extends React.Component {
const { name, binder } = this.props const { name, binder } = this.props
binder.addListener(name, this.updateValue) binder.addListener(name, this.updateValue)
this.state = binder.getFieldState(name) this.state = binder.getBindingState(name)
} }
@autobind @autobind
@@ -36,7 +39,7 @@ export class BoundHeader extends React.Component {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.props.binder.removeListener(this.props.name, this.updateValue) this.props.binder.removeListener(this.props.name, this.updateValue)
nextProps.binder.addListener(nextProps.name, this.updateValue) nextProps.binder.addListener(nextProps.name, this.updateValue)
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }
@@ -54,7 +57,8 @@ export class BoundHeader extends React.Component {
title={title} title={title}
disabled={disabled} disabled={disabled}
leftButton={leftButton} leftButton={leftButton}
rightButton={rightButton} /> rightButton={rightButton}
/>
) )
} }
} }

View File

@@ -23,13 +23,13 @@ export class BoundInput extends React.Component {
const { name, binder } = this.props const { name, binder } = this.props
this.state = binder.getFieldState(name) this.state = binder.getBindingState(name)
this.handleChangeText = this.handleChangeText.bind(this) this.handleChangeText = this.handleChangeText.bind(this)
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }
@@ -38,7 +38,7 @@ export class BoundInput extends React.Component {
const { binder, name } = this.props const { binder, name } = this.props
if (binder) { if (binder) {
this.setState(binder.updateFieldValue(name, newText)) this.setState(binder.updateBindingValue(name, newText))
} }
} }

View File

@@ -17,17 +17,19 @@ export class BoundOptionStrip extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = props.binder.getFieldState(props.name) this.state = props.binder.getBindingState(props.name)
} }
@autobind @autobind
handleValueChanged(newValue) { handleValueChanged(newValue) {
this.setState(this.props.binder.updateFieldValue(this.props.name, newValue)) this.setState(
this.props.binder.updateBindingValue(this.props.name, newValue)
)
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }

View File

@@ -38,12 +38,12 @@ export class BoundPhotoPanel extends Component {
const { name, binder } = this.props const { name, binder } = this.props
this.state = binder.getFieldState(name) this.state = binder.getBindingState(name)
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }
@@ -80,12 +80,12 @@ export class BoundPhotoPanel extends Component {
const { binder, name } = this.props const { binder, name } = this.props
if (binder) { if (binder) {
const value = binder.getFieldValue(name) const value = binder.getBindingValue(name)
let newValue = value instanceof Array ? value.slice(0) : [] let newValue = value instanceof Array ? value.slice(0) : []
newValue[index] = uploadData.assetId newValue[index] = uploadData.assetId
this.setState(binder.updateFieldValue(name, newValue)) this.setState(binder.updateBindingValue(name, newValue))
} }
}) })
.catch((err) => { .catch((err) => {

View File

@@ -1,7 +1,7 @@
import React from 'react' import React from "react"
import PropTypes from 'prop-types' import PropTypes from "prop-types"
import { View, Switch, Text } from 'react-native' import { View, Switch, Text } from "react-native"
import autobind from 'autobind-decorator' import autobind from "autobind-decorator"
export class BoundSwitch extends React.Component { export class BoundSwitch extends React.Component {
static propTypes = { static propTypes = {
@@ -12,22 +12,22 @@ export class BoundSwitch extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = props.binder.getFieldState(props.name) this.state = props.binder.getBindingState(props.name)
} }
@autobind @autobind
handleValueChange(newValue) { handleValueChange(newValue) {
const { binder, name } = this.props const { binder, name } = this.props
const state = binder.getFieldState(name) const state = binder.getBindingState(name)
if (!state.readOnly && !state.disabled) { if (!state.readOnly && !state.disabled) {
this.setState(binder.updateFieldValue(name, newValue)) this.setState(binder.updateBindingValue(name, newValue))
} }
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }
@@ -36,16 +36,22 @@ export class BoundSwitch extends React.Component {
const { visible, disabled, value } = this.state const { visible, disabled, value } = this.state
return ( return (
<View style={{ <View
display: visible ? 'flex' : 'none', style={{
flexDirection: 'row', display: visible ? "flex" : "none",
flexDirection: "row",
}}> }}>
<Switch disabled={disabled} value={value} onValueChange={this.handleValueChange} /> <Switch
<Text style={{ disabled={disabled}
color: disabled ? 'gray' : 'black', value={value}
onValueChange={this.handleValueChange}
/>
<Text
style={{
color: disabled ? "gray" : "black",
fontSize: 16, fontSize: 16,
paddingLeft: 8, paddingLeft: 8,
alignSelf: 'center' alignSelf: "center",
}}> }}>
{label} {label}
</Text> </Text>

View File

@@ -14167,9 +14167,9 @@
} }
}, },
"react-form-binder": { "react-form-binder": {
"version": "2.0.1", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/react-form-binder/-/react-form-binder-2.0.1.tgz", "resolved": "https://registry.npmjs.org/react-form-binder/-/react-form-binder-3.0.0.tgz",
"integrity": "sha512-QOIO7dd6s+zvw6V3JdaWbuCKm6OwunOemuvR7ds98nnPoUXXZ3Fv4SLRGkt3GcI97a5PDlWvNAN/9qz571SHjA==", "integrity": "sha512-XPXw+OVxfko1rcN1WjLxaCt8FVZaWrjCI7XNaNx1Su8/QFDqeAh1dgWpySE31i73un2v3ig+0r0WL+lHaV9Y3Q==",
"requires": { "requires": {
"eventemitter3": "^2.0.3", "eventemitter3": "^2.0.3",
"prop-types": "^15.5.10", "prop-types": "^15.5.10",

View File

@@ -12,7 +12,7 @@
"radium": "^0.22.0", "radium": "^0.22.0",
"react": "^16.2.0", "react": "^16.2.0",
"react-dom": "^16.2.0", "react-dom": "^16.2.0",
"react-form-binder": "^2.0.1", "react-form-binder": "^3.0.0",
"react-router-dom": "^4.1.1", "react-router-dom": "^4.1.1",
"regexp-pattern": "^1.0.4", "regexp-pattern": "^1.0.4",
"socket.io-client": "^2.0.3" "socket.io-client": "^2.0.3"

View File

@@ -43,7 +43,7 @@ export class ForgotPassword extends Component {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
const obj = this.state.binder.getModifiedFieldValues() const obj = this.state.binder.getmodifiedBindingValues()
this.setState({ waitModal: { message: "Requesting Reset Email" } }) this.setState({ waitModal: { message: "Requesting Reset Email" } })

View File

@@ -65,7 +65,7 @@ export class Login extends Component {
return return
} }
let obj = this.state.binder.getModifiedFieldValues() let obj = this.state.binder.getmodifiedBindingValues()
if (obj) { if (obj) {
this.setState({ waitModal: true }) this.setState({ waitModal: true })
@@ -102,7 +102,7 @@ export class Login extends Component {
this.setState({ this.setState({
messageModal: null, messageModal: null,
binder: new FormBinder( binder: new FormBinder(
{ email: this.state.binder.getFieldValue("email") }, { email: this.state.binder.getBindingValue("email") },
Login.bindings Login.bindings
), ),
}) })

View File

@@ -19,7 +19,7 @@ export class ResetPassword extends Component {
isValid: (r, v) => v.length >= 6, isValid: (r, v) => v.length >= 6,
}, },
reenteredNewPassword: { reenteredNewPassword: {
isValid: (r, v) => v !== "" && v === r.getFieldValue("newPassword"), isValid: (r, v) => v !== "" && v === r.getBindingValue("newPassword"),
}, },
submit: { submit: {
noValue: true, noValue: true,
@@ -73,7 +73,7 @@ export class ResetPassword extends Component {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
const obj = this.state.binder.getModifiedFieldValues() const obj = this.state.binder.getmodifiedBindingValues()
const passwordToken = new URLSearchParams( const passwordToken = new URLSearchParams(
decodeURIComponent(window.location.search) decodeURIComponent(window.location.search)
).get("password-token") ).get("password-token")

View File

@@ -1,16 +1,16 @@
import React from 'react' import React from "react"
import PropTypes from 'prop-types' import PropTypes from "prop-types"
import autobind from 'autobind-decorator' import autobind from "autobind-decorator"
import { Modal, Button, Row, Column, BoundInput, BoundButton, Text } from 'ui' import { Modal, Button, Row, Column, BoundInput, BoundButton, Text } from "ui"
import { regExpPattern } from 'regexp-pattern' import { regExpPattern } from "regexp-pattern"
import { FormBinder } from 'react-form-binder' import { FormBinder } from "react-form-binder"
import { sizeInfo } from 'ui/style' import { sizeInfo } from "ui/style"
export class ChangeEmailModal extends React.Component { export class ChangeEmailModal extends React.Component {
static propTypes = { static propTypes = {
open: PropTypes.bool, open: PropTypes.bool,
oldEmail: PropTypes.string, oldEmail: PropTypes.string,
onDismiss: PropTypes.func onDismiss: PropTypes.func,
} }
static bindings = { static bindings = {
@@ -18,20 +18,26 @@ export class ChangeEmailModal extends React.Component {
noValue: true, noValue: true,
}, },
newEmail: { newEmail: {
isValid: (r, v) => (v !== '' && regExpPattern.email.test(v) && v !== r.getFieldValue('oldEmail')) isValid: (r, v) =>
v !== "" &&
regExpPattern.email.test(v) &&
v !== r.getBindingValue("oldEmail"),
}, },
submit: { submit: {
isDisabled: (r) => (!r.allValid), isDisabled: (r) => !r.allValid,
noValue: true noValue: true,
} },
} }
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
binder: new FormBinder({ binder: new FormBinder(
oldEmail: props.oldEmail, {
}, ChangeEmailModal.bindings) oldEmail: props.oldEmail,
},
ChangeEmailModal.bindings
),
} }
} }
@@ -48,7 +54,7 @@ export class ChangeEmailModal extends React.Component {
@autobind @autobind
handleSubmit(e) { handleSubmit(e) {
e.preventDefault() e.preventDefault()
let newEmail = this.state.binder.getFieldValue('newEmail') let newEmail = this.state.binder.getBindingValue("newEmail")
this.close(newEmail) this.close(newEmail)
} }
@@ -62,7 +68,7 @@ export class ChangeEmailModal extends React.Component {
return ( return (
<Modal open={this.props.open} width={sizeInfo.modalWidth}> <Modal open={this.props.open} width={sizeInfo.modalWidth}>
<form id='changeEmailForm' onSubmit={this.handleSubmit}> <form id="changeEmailForm" onSubmit={this.handleSubmit}>
<Column> <Column>
<Column.Item height={sizeInfo.formColumnSpacing} /> <Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item> <Column.Item>
@@ -71,8 +77,8 @@ export class ChangeEmailModal extends React.Component {
<Row.Item grow> <Row.Item grow>
<Column> <Column>
<Column.Item height={sizeInfo.formColumnSpacing} /> <Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item color='black' icon='edit'> <Column.Item color="black" icon="edit">
<Text size='large'>Change Password</Text> <Text size="large">Change Password</Text>
</Column.Item> </Column.Item>
<Column.Item height={sizeInfo.formColumnSpacing} /> <Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item> <Column.Item>
@@ -80,20 +86,28 @@ export class ChangeEmailModal extends React.Component {
</Column.Item> </Column.Item>
<Column.Item height={sizeInfo.formColumnSpacing} /> <Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item> <Column.Item>
<BoundInput label='New Email' name='newEmail' <BoundInput
message='Your new email address, e.g. xyz@abc.com, cannot be blank' label="New Email"
binder={binder} /> name="newEmail"
message="Your new email address, e.g. xyz@abc.com, cannot be blank"
binder={binder}
/>
</Column.Item> </Column.Item>
<Column.Item height={sizeInfo.formColumnSpacing} /> <Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item> <Column.Item>
<Row> <Row>
<Row.Item grow /> <Row.Item grow />
<Row.Item> <Row.Item>
<Button onClick={this.handleClick} text='Cancel' /> <Button onClick={this.handleClick} text="Cancel" />
</Row.Item> </Row.Item>
<Row.Item width={sizeInfo.formRowSpacing} /> <Row.Item width={sizeInfo.formRowSpacing} />
<Row.Item> <Row.Item>
<BoundButton submit='changeEmailForm' name='submit' binder={binder} text='OK' /> <BoundButton
submit="changeEmailForm"
name="submit"
binder={binder}
text="OK"
/>
</Row.Item> </Row.Item>
</Row> </Row>
</Column.Item> </Column.Item>

View File

@@ -1,38 +1,38 @@
import React from 'react' import React from "react"
import PropTypes from 'prop-types' import PropTypes from "prop-types"
import autobind from 'autobind-decorator' import autobind from "autobind-decorator"
import { Modal, Button, Column, Row, Text, BoundInput, BoundButton } from 'ui' import { Modal, Button, Column, Row, Text, BoundInput, BoundButton } from "ui"
import { FormBinder } from 'react-form-binder' import { FormBinder } from "react-form-binder"
import { sizeInfo } from 'ui/style' import { sizeInfo } from "ui/style"
export class ChangePasswordModal extends React.Component { export class ChangePasswordModal extends React.Component {
static propTypes = { static propTypes = {
open: PropTypes.bool, open: PropTypes.bool,
onDismiss: PropTypes.func onDismiss: PropTypes.func,
} }
static bindings = { static bindings = {
oldPassword: { oldPassword: {
alwaysGet: true, alwaysGet: true,
isValid: (r, v) => (v !== '') isValid: (r, v) => v !== "",
}, },
newPassword: { newPassword: {
alwaysGet: true, alwaysGet: true,
isValid: (r, v) => (v !== '' && v !== r.fields.oldPassword.value) isValid: (r, v) => v !== "" && v !== r.getBindingValue("oldPassword"),
}, },
reenteredNewPassword: { reenteredNewPassword: {
isValid: (r, v) => (v !== '' && v === r.getFieldValue('newPassword')), isValid: (r, v) => v !== "" && v === r.getBindingValue("newPassword"),
}, },
submit: { submit: {
isDisabled: (r) => (!r.allValid), isDisabled: (r) => !r.allValid,
noValue: true noValue: true,
} },
} }
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
binder: new FormBinder({}, ChangePasswordModal.bindings) binder: new FormBinder({}, ChangePasswordModal.bindings),
} }
} }
@@ -53,8 +53,8 @@ export class ChangePasswordModal extends React.Component {
const { binder } = this.state const { binder } = this.state
if (binder.allValid) { if (binder.allValid) {
const oldPassword = binder.getFieldValue('oldPassword') const oldPassword = binder.getBindingValue("oldPassword")
const newPassword = binder.getFieldValue('newPassword') const newPassword = binder.getBindingValue("newPassword")
passwords = { oldPassword, newPassword } passwords = { oldPassword, newPassword }
} }
this.close(passwords) this.close(passwords)
@@ -70,32 +70,44 @@ export class ChangePasswordModal extends React.Component {
return ( return (
<Modal open={this.props.open} width={sizeInfo.modalWidth}> <Modal open={this.props.open} width={sizeInfo.modalWidth}>
<form id='changePasswordForm' onSubmit={this.handleSubmit}> <form id="changePasswordForm" onSubmit={this.handleSubmit}>
<Row> <Row>
<Row.Item width={sizeInfo.formRowSpacing} /> <Row.Item width={sizeInfo.formRowSpacing} />
<Row.Item grow> <Row.Item grow>
<Column> <Column>
<Column.Item height={sizeInfo.formColumnSpacing} /> <Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item color='black' icon='edit'> <Column.Item color="black" icon="edit">
<Text size='large'>Change Password</Text> <Text size="large">Change Password</Text>
</Column.Item> </Column.Item>
<Column.Item height={sizeInfo.formColumnSpacing} /> <Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item> <Column.Item>
<Column> <Column>
<Column.Item> <Column.Item>
<BoundInput label='Current Password' password name='oldPassword' <BoundInput
message='Your existing password, cannot be blank' label="Current Password"
binder={binder} /> password
name="oldPassword"
message="Your existing password, cannot be blank"
binder={binder}
/>
</Column.Item> </Column.Item>
<Column.Item> <Column.Item>
<BoundInput label='New Password' password name='newPassword' <BoundInput
message='A new password, cannot be blank or the same as your old password' label="New Password"
binder={binder} /> password
name="newPassword"
message="A new password, cannot be blank or the same as your old password"
binder={binder}
/>
</Column.Item> </Column.Item>
<Column.Item> <Column.Item>
<BoundInput label='Re-entered New Password' password name='reenteredNewPassword' <BoundInput
message='The new password again, must match and cannot be blank' label="Re-entered New Password"
binder={binder} /> password
name="reenteredNewPassword"
message="The new password again, must match and cannot be blank"
binder={binder}
/>
</Column.Item> </Column.Item>
</Column> </Column>
</Column.Item> </Column.Item>
@@ -104,11 +116,16 @@ export class ChangePasswordModal extends React.Component {
<Row> <Row>
<Row.Item grow /> <Row.Item grow />
<Row.Item> <Row.Item>
<Button onClick={this.handleClick} text='Cancel' /> <Button onClick={this.handleClick} text="Cancel" />
</Row.Item> </Row.Item>
<Row.Item width={sizeInfo.formRowSpacing} /> <Row.Item width={sizeInfo.formRowSpacing} />
<Row.Item> <Row.Item>
<BoundButton text='Submit' submit='changePasswordForm' name='submit' binder={binder} /> <BoundButton
text="Submit"
submit="changePasswordForm"
name="submit"
binder={binder}
/>
</Row.Item> </Row.Item>
</Row> </Row>
</Column.Item> </Column.Item>

View File

@@ -1,9 +1,9 @@
import React from 'react' import React from "react"
import PropTypes from 'prop-types' import PropTypes from "prop-types"
import { Column, Row, Box, Button, BoundInput, BoundButton } from 'ui' import { Column, Row, Box, Button, BoundInput, BoundButton } from "ui"
import { sizeInfo, colorInfo } from 'ui/style' import { sizeInfo, colorInfo } from "ui/style"
import { FormBinder } from 'react-form-binder' import { FormBinder } from "react-form-binder"
import autobind from 'autobind-decorator' import autobind from "autobind-decorator"
export class ProfileForm extends React.Component { export class ProfileForm extends React.Component {
static propTypes = { static propTypes = {
@@ -11,31 +11,34 @@ export class ProfileForm extends React.Component {
onSaved: PropTypes.func.isRequired, onSaved: PropTypes.func.isRequired,
onModifiedChanged: PropTypes.func, onModifiedChanged: PropTypes.func,
onChangePassword: PropTypes.func, onChangePassword: PropTypes.func,
onChangeEmail: PropTypes.func onChangeEmail: PropTypes.func,
} }
static bindings = { static bindings = {
email: { email: {
isValid: (r, v) => (v !== ''), isValid: (r, v) => v !== "",
isDisabled: (r) => (!!r._id) isDisabled: (r) => !!r._id,
}, },
firstName: { firstName: {
isValid: (r, v) => (v !== '') isValid: (r, v) => v !== "",
}, },
lastName: { lastName: {
isValid: (r, v) => (v !== '') isValid: (r, v) => v !== "",
}, },
save: { save: {
noValue: true, noValue: true,
isDisabled: (r) => (!r.anyModified || !r.allValid) isDisabled: (r) => !r.anyModified || !r.allValid,
} },
} }
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
binder: new FormBinder( binder: new FormBinder(
this.props.user, ProfileForm.bindings, this.props.onModifiedChanged) this.props.user,
ProfileForm.bindings,
this.props.onModifiedChanged
),
} }
} }
@@ -43,7 +46,10 @@ export class ProfileForm extends React.Component {
if (nextProps.user !== this.props.user) { if (nextProps.user !== this.props.user) {
this.setState({ this.setState({
binder: new FormBinder( binder: new FormBinder(
nextProps.user, ProfileForm.bindings, nextProps.onModifiedChanged) nextProps.user,
ProfileForm.bindings,
nextProps.onModifiedChanged
),
}) })
} }
} }
@@ -61,15 +67,19 @@ export class ProfileForm extends React.Component {
@autobind @autobind
handleChangeEmail() { handleChangeEmail() {
this.props.onChangeEmail(this.state.binder.getFieldValue('email')) this.props.onChangeEmail(this.state.binder.getBindingValue("email"))
} }
render() { render() {
const { binder } = this.state const { binder } = this.state
return ( return (
<form onSubmit={this.handleSubmit} id='profileForm'> <form onSubmit={this.handleSubmit} id="profileForm">
<Box border={{ width: sizeInfo.headerBorderWidth, color: colorInfo.headerBorder }} <Box
border={{
width: sizeInfo.headerBorderWidth,
color: colorInfo.headerBorder,
}}
radius={sizeInfo.formBoxRadius}> radius={sizeInfo.formBoxRadius}>
<Row> <Row>
<Row.Item width={sizeInfo.formRowSpacing} /> <Row.Item width={sizeInfo.formRowSpacing} />
@@ -77,34 +87,58 @@ export class ProfileForm extends React.Component {
<Column> <Column>
<Column.Item height={sizeInfo.formColumnSpacing} /> <Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item> <Column.Item>
<BoundInput label='First Name' name='firstName' <BoundInput
message='First name is required' binder={binder} /> label="First Name"
name="firstName"
message="First name is required"
binder={binder}
/>
</Column.Item> </Column.Item>
<Column.Item> <Column.Item>
<BoundInput label='Last Name' name='lastName' <BoundInput
binder={binder} /> label="Last Name"
name="lastName"
binder={binder}
/>
</Column.Item> </Column.Item>
<Column.Item> <Column.Item>
<BoundInput label='Email' name='email' <BoundInput
message='Required. Must be a valid email address.' label="Email"
binder={binder} /> name="email"
message="Required. Must be a valid email address."
binder={binder}
/>
</Column.Item> </Column.Item>
<Column.Item height={sizeInfo.formColumnSpacing} /> <Column.Item height={sizeInfo.formColumnSpacing} />
<Column.Item height={sizeInfo.buttonHeight}> <Column.Item height={sizeInfo.buttonHeight}>
<Row> <Row>
<Row.Item> <Row.Item>
<Button text={'Change Email'} label='&nbsp;' <Button
width={sizeInfo.buttonWideWidth} onClick={this.handleChangeEmail} /> text={"Change Email"}
label="&nbsp;"
width={sizeInfo.buttonWideWidth}
onClick={this.handleChangeEmail}
/>
</Row.Item> </Row.Item>
<Row.Item width={sizeInfo.formRowSpacing} /> <Row.Item width={sizeInfo.formRowSpacing} />
<Row.Item> <Row.Item>
<Button text={'Change Password'} label='&nbsp;' <Button
width={sizeInfo.buttonWideWidth} onClick={this.props.onChangePassword} /> text={"Change Password"}
label="&nbsp;"
width={sizeInfo.buttonWideWidth}
onClick={this.props.onChangePassword}
/>
</Row.Item> </Row.Item>
<Row.Item grow /> <Row.Item grow />
<Row.Item> <Row.Item>
<BoundButton submit='profileForm' size='medium' text='Save' label='&nbsp;' name='save' <BoundButton
binder={binder} /> submit="profileForm"
size="medium"
text="Save"
label="&nbsp;"
name="save"
binder={binder}
/>
</Row.Item> </Row.Item>
</Row> </Row>
</Column.Item> </Column.Item>

View File

@@ -93,7 +93,7 @@ export class TeamForm extends React.Component {
handleSubmit(e) { handleSubmit(e) {
e.preventDefault() e.preventDefault()
let obj = this.state.binder.getModifiedFieldValues() let obj = this.state.binder.getmodifiedBindingValues()
if (obj) { if (obj) {
this.props.onSave(obj) this.props.onSave(obj)

View File

@@ -45,7 +45,7 @@ export class UserForm extends React.Component {
}, },
resendEmail: { resendEmail: {
noValue: true, noValue: true,
isDisabled: (r) => !r._id || !!r.getFieldValue("emailValidated"), isDisabled: (r) => !r._id || !!r.getBindingValue("emailValidated"),
}, },
firstName: { firstName: {
isValid: (r, v) => v !== "", isValid: (r, v) => v !== "",
@@ -128,7 +128,7 @@ export class UserForm extends React.Component {
handleSubmit(e) { handleSubmit(e) {
e.preventDefault() e.preventDefault()
let obj = this.state.binder.getModifiedFieldValues() let obj = this.state.binder.getmodifiedBindingValues()
if (obj) { if (obj) {
this.props.onSave(obj) this.props.onSave(obj)

View File

@@ -1,7 +1,7 @@
import React from 'react' import React from "react"
import PropTypes from 'prop-types' import PropTypes from "prop-types"
import { Button } from 'ui' import { Button } from "ui"
import autobind from 'autobind-decorator' import autobind from "autobind-decorator"
export class BoundButton extends React.Component { export class BoundButton extends React.Component {
static propTypes = { static propTypes = {
@@ -10,14 +10,14 @@ export class BoundButton extends React.Component {
binder: PropTypes.object.isRequired, binder: PropTypes.object.isRequired,
submit: PropTypes.string, submit: PropTypes.string,
onClick: PropTypes.func, onClick: PropTypes.func,
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]), width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
} }
constructor(props) { constructor(props) {
super(props) super(props)
let { name, binder } = this.props let { name, binder } = this.props
binder.addListener(name, this.updateValue) binder.addListener(name, this.updateValue)
this.state = binder.getFieldState(name) this.state = binder.getBindingState(name)
} }
@autobind @autobind
@@ -33,7 +33,7 @@ export class BoundButton extends React.Component {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.props.binder.removeListener(this.props.name, this.updateValue) this.props.binder.removeListener(this.props.name, this.updateValue)
nextProps.binder.addListener(nextProps.name, this.updateValue) nextProps.binder.addListener(nextProps.name, this.updateValue)
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }
@@ -46,8 +46,14 @@ export class BoundButton extends React.Component {
} }
return ( return (
<Button disabled={disabled} submit={submit} onClick={onClick} <Button
name={name} text={text} width={width} /> disabled={disabled}
submit={submit}
onClick={onClick}
name={name}
text={text}
width={width}
/>
) )
} }
} }

View File

@@ -1,8 +1,8 @@
import React from 'react' import React from "react"
import PropTypes from 'prop-types' import PropTypes from "prop-types"
import { Checkbox } from 'ui' import { Checkbox } from "ui"
import autobind from 'autobind-decorator' import autobind from "autobind-decorator"
import { fontInfo } from 'ui/style' import { fontInfo } from "ui/style"
export class BoundCheckbox extends React.Component { export class BoundCheckbox extends React.Component {
static propTypes = { static propTypes = {
@@ -13,22 +13,22 @@ export class BoundCheckbox extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = props.binder.getFieldState(props.name) this.state = props.binder.getBindingState(props.name)
} }
@autobind @autobind
handleChange(e, data) { handleChange(e, data) {
const { binder, name } = this.props const { binder, name } = this.props
const state = binder.getFieldState(name) const state = binder.getBindingState(name)
if (!state.readOnly && !state.disabled) { if (!state.readOnly && !state.disabled) {
this.setState(binder.updateFieldValue(name, data.checked)) this.setState(binder.updateBindingValue(name, data.checked))
} }
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }
@@ -42,12 +42,17 @@ export class BoundCheckbox extends React.Component {
return ( return (
<div> <div>
<Checkbox id={name} disabled={disabled} value={value} onChange={this.handleChange} /> <Checkbox
id={name}
disabled={disabled}
value={value}
onChange={this.handleChange}
/>
<label <label
htmlFor={name} htmlFor={name}
style={{ style={{
marginLeft: 10, marginLeft: 10,
verticalAlign: 'top', verticalAlign: "top",
fontSize: fontInfo.size.medium, fontSize: fontInfo.size.medium,
fontFamily: fontInfo.family, fontFamily: fontInfo.family,
color: disabled ? fontInfo.color.dimmed : fontInfo.color.normal, color: disabled ? fontInfo.color.dimmed : fontInfo.color.normal,

View File

@@ -1,36 +1,42 @@
import React from 'react' import React from "react"
import PropTypes from 'prop-types' import PropTypes from "prop-types"
import { Dropdown } from 'ui' import { Dropdown } from "ui"
import autobind from 'autobind-decorator' import autobind from "autobind-decorator"
import { sizeInfo, fontInfo } from 'ui/style' import { sizeInfo, fontInfo } from "ui/style"
export class BoundDropdown extends React.Component { export class BoundDropdown extends React.Component {
static propTypes = { static propTypes = {
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
label: PropTypes.string, label: PropTypes.string,
binder: PropTypes.object.isRequired, binder: PropTypes.object.isRequired,
items: PropTypes.arrayOf(PropTypes.shape({ value: PropTypes.string, text: PropTypes.string, icon: PropTypes.string })), items: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.string,
text: PropTypes.string,
icon: PropTypes.string,
})
),
icon: PropTypes.string, icon: PropTypes.string,
} }
constructor(props) { constructor(props) {
super(props) super(props)
this.state = props.binder.getFieldState(props.name) this.state = props.binder.getBindingState(props.name)
} }
@autobind @autobind
handleChange(item) { handleChange(item) {
const { binder, name } = this.props const { binder, name } = this.props
const state = binder.getFieldState(name) const state = binder.getBindingState(name)
if (!state.readOnly && !state.disabled) { if (!state.readOnly && !state.disabled) {
this.setState(binder.updateFieldValue(name, item.value)) this.setState(binder.updateBindingValue(name, item.value))
} }
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
if (nextProps.items !== this.props.items) { if (nextProps.items !== this.props.items) {
@@ -59,15 +65,19 @@ export class BoundDropdown extends React.Component {
<Dropdown <Dropdown
items={items} items={items}
value={value} value={value}
emptyItem={{ value: null, text: '', icon: 'team' }} emptyItem={{ value: null, text: "", icon: "team" }}
icon={icon} icon={icon}
onChange={this.handleChange} onChange={this.handleChange}
render={(item) => ( render={(item) => (
<Dropdown.Item key={item.value}> <Dropdown.Item key={item.value}>
<Dropdown.Icon name={item.icon} size={sizeInfo.dropdownIconSize} /> <Dropdown.Icon
name={item.icon}
size={sizeInfo.dropdownIconSize}
/>
<Dropdown.Text>{item.text}</Dropdown.Text> <Dropdown.Text>{item.text}</Dropdown.Text>
</Dropdown.Item> </Dropdown.Item>
)} /> )}
/>
</label> </label>
</div> </div>
) )

View File

@@ -11,12 +11,12 @@ export class BoundEmailIcon extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = props.binder.getFieldState(props.name) this.state = props.binder.getBindingState(props.name)
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }

View File

@@ -15,22 +15,22 @@ export class BoundInput extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = props.binder.getFieldState(props.name) this.state = props.binder.getBindingState(props.name)
} }
@autobind @autobind
handleChange(newValue) { handleChange(newValue) {
const { binder, name } = this.props const { binder, name } = this.props
const state = binder.getFieldState(name) const state = binder.getBindingState(name)
if (!state.readOnly && !state.disabled) { if (!state.readOnly && !state.disabled) {
this.setState(binder.updateFieldValue(name, newValue)) this.setState(binder.updateBindingValue(name, newValue))
} }
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.binder !== this.props.binder) { if (nextProps.binder !== this.props.binder) {
this.setState(nextProps.binder.getFieldState(nextProps.name)) this.setState(nextProps.binder.getBindingState(nextProps.name))
} }
} }