ice-frontend-react-mobx
Version:
ICE Frontend REACT+MobX
249 lines (214 loc) • 9.13 kB
JavaScript
var debug = require('debug')('ice:Devices:Form'); // eslint-disable-line no-unused-vars
import React from 'react';
import { inject, observer } from 'mobx-react';
import { Input, Dropdown, Dialog } from 'react-toolbox';
import Validators from '../../../common/helpers/Validators';
import Notify from '../../../common/helpers/Notify';
import FormWrapper from '../../common/FormWrapper/FormWrapper';
let styles = require('./DeviceForm.css');
const defaultState = {
name: '',
nameError: '',
ip: '',
ipError: '',
port: '',
portError: '',
deviceInfo: '',
deviceInfoError: '',
feed: '',
desc: '',
phase: '',
upstreamFailureSensor: '',
breakerLimit: ''
};
export default class DeviceForm extends React.Component {
constructor (props) {
super(props);
this.deviceStore = this.props.store.deviceStore;
this.messageStore = this.props.store.messageStore;
this.allFeeds = this.props.store.feedStore.all;
this.wordStore = this.props.store.wordStore;
this.state = defaultState;
}
componentWillReceiveProps (nextProps) {
let newState = Object.assign({}, defaultState);
if (nextProps.deviceId) {
let device = this.deviceStore.getById(nextProps.deviceId);
newState.device = device;
newState.name = device.name;
newState.ip = device.ip;
newState.port = device.port;
newState.deviceInfo = device.deviceInfo;
newState.feed = device.feedId;
newState.desc = device.description;
newState.phase = (device.phase) ? device.phase : 'None';
newState.upstreamFailureSensor = device.upstreamFailureSensor;
newState.breakerLimit = device.breakerLimit;
} else if (nextProps.active) {
newState.device = this.deviceStore.createDevice();
}
this.setState(newState);
}
validate = (field) => {
let error = '';
let value = this.state[field];
let combos;
let ip = this.state.ip !== '' ? this.state.ip : false;
let port = this.state.port !== '' ? this.state.port : false;
let isDumb = false;
try {
isDumb = JSON.parse(this.state.deviceInfo).isDumb;
} catch (error) {
debug('No device info, using default of false', error);
}
if (ip && port) {
combos = this.deviceStore.all.map((device) => (device.ip + ':' + device.port));
}
switch (field) {
case 'name':
let names = this.deviceStore.all.map((device) => (device.name));
let originalName = (this.state.device) ? this.state.device.name : null;
error = Validators.device.name(value, names, originalName);
break;
case 'ip':
let originalIp = (this.state.device) ? this.state.device.ip : null;
error = Validators.device.ip(value, port, combos, originalIp, isDumb);
break;
case 'port':
let originalPort = (this.state.device) ? this.state.device.port : null;
error = Validators.device.port(value, ip, combos, originalPort, isDumb);
break;
case 'deviceInfo':
error = Validators.device.model(value);
break;
case 'breakerLimit':
error = Validators.device.breakerLimit(value);
break;
}
return error;
}
isValid = () => {
var p = new Promise((resolve, reject) => {
let newState = {};
['name', 'ip', 'port', 'deviceInfo', 'breakerLimit'].forEach((field) => {
newState[ field + 'Error' ] = this.validate(field);
});
this.setState(newState, () => {
if (this.state.nameError === '' && this.state.ipError === '' && this.state.portError === '' && this.state.deviceInfoError === '' &&
this.state.name !== '' && this.state.deviceInfo !== '') {
resolve();
} else {
reject(new Error('form not valid'));
}
});
});
return p;
}
handleChange = (field, value) => {
this.setState({ [field]: value }, () => {
if (field === 'deviceInfo') {
this.setState({ [field + 'Error']: this.validate(field) });
}
});
}
handleBlur = (name) => {
let error = this.validate(name);
this.setState({ [name + 'Error']: error });
}
save = () => {
this.isValid().then(() => {
let device = this.state.device || this.deviceStore.createDevice();
device.name = this.state.name;
device.ip = this.state.ip;
device.port = this.state.port;
device.deviceInfo = this.state.deviceInfo;
device.sensorStreamEnabled = device.model !== 'dumbRpdu';
device.feed = this.state.feed;
device.description = this.state.desc;
device.upstreamFailureSensor = this.state.upstreamFailureSensor;
if (this.state.breakerLimit) {
device.breakerLimit = parseInt(this.state.breakerLimit);
}
device.phase = (this.state.phase !== 'None') ? this.state.phase : null;
device.save().then(() => {
Notify.success('Device Saved');
}).catch((error) => {
if (error.response && error.response.data && error.response.data.errorMessage) {
Notify.error(error.response.data.errorMessage);
} else {
Notify.error('Error saving device');
}
});
this.props.onSave();
}, () => {
debug('Form is notvalid');
});
}
cancel = () => {
this.setState(defaultState);
this.props.onCancel();
}
render () {
let availableDevices = this.props.store.catalogStore.all.map((device) => {
return { label: device.name, value: JSON.stringify({ type: device.type, model: device.model, isDumb: device.isDumb }) };
});
let availableFeeds = this.props.store.feedStore.all.map((feed) => {
return { label: feed.name, value: feed.id };
});
let availablePhases = [{value: 'NONE', name: 'None'}, {value: 'ONE', name: '1-2'}, {value: 'TWO', name: '2-3'}, {value: 'THREE', name: '3-1'}, {value: 'ALL PHASES', name: 'All'}].map((phase) => {
return { label: phase.value, value: phase.name };
});
let iceBlocks = this.deviceStore.iceblocks.map((device) => {
return { label: device.name, value: device.id };
});
let title = (this.props.deviceId) ? this.wordStore.translate('Edit Device') : this.wordStore.translate('Add Device');
let actions = [
{ label: this.wordStore.translate('Cancel'), onClick: this.cancel },
{ label: this.wordStore.translate('Save'), onClick: this.save }
];
return (
<Dialog title={title} actions={actions} active={this.props.active} onEscKeyDown={this.cancel}>
<FormWrapper onSubmit={this.save}>
<div className={styles.twoColumn}>
<div className={styles.wideColumn}>
<Input type='text' label='Name' value={this.state.name} error={this.state.nameError} onChange={this.handleChange.bind(this, 'name')} onBlur={this.handleBlur.bind(this, 'name')} />
</div>
<div className={styles.narrowColumn}>
<Input type='text' label='Breaker Limit' value={this.state.breakerLimit} error={this.state.breakerLimitError} onChange={this.handleChange.bind(this, 'breakerLimit')} onBlur={this.handleBlur.bind(this, 'breakerLimit')} />
</div>
</div>
<div className={styles.threeColumn}>
<div className={styles.wideColumn}>
<Dropdown label='Model' source={availableDevices} value={this.state.deviceInfo} error={this.state.deviceInfoError} onChange={this.handleChange.bind(this, 'deviceInfo')} />
</div>
<div className={styles.narrowColumn}>
<Dropdown label='Feed' source={availableFeeds} value={this.state.feed} onChange={this.handleChange.bind(this, 'feed')} />
</div>
<div className={styles.narrowColumn}>
<Dropdown label='Phase' source={availablePhases} value={this.state.phase} onChange={this.handleChange.bind(this, 'phase')} />
</div>
</div>
<div className={styles.twoColumn}>
<div className={styles.wideColumn}>
<Input type='text' label='IP' value={this.state.ip} error={this.state.ipError} onChange={this.handleChange.bind(this, 'ip')} onBlur={this.handleBlur.bind(this, 'ip')} />
</div>
<div className={styles.narrowColumn}>
<Input type='Number' label='Port' value={this.state.port} error={this.state.portError} onChange={this.handleChange.bind(this, 'port')} onBlur={this.handleBlur.bind(this, 'port')} />
</div>
</div>
<div className={styles.wideColumn}>
<Dropdown auto={false} label='Upstream Sensor Failure' source={iceBlocks} value={this.state.upstreamFailureSensor} onChange={this.handleChange.bind(this, 'upstreamFailureSensor')} />
</div>
<Input label='Description' value={this.state.desc} onChange={this.handleChange.bind(this, 'desc')} />
</FormWrapper>
</Dialog>
);
}
}
DeviceForm.wrappedComponent.propTypes = {
deviceId: React.PropTypes.string,
active: React.PropTypes.bool.isRequired,
onCancel: React.PropTypes.func.isRequired,
onSave: React.PropTypes.func.isRequired
};