|
import React from 'react' |
|
import { |
|
Alert, |
|
Button, |
|
Col, ControlLabel, |
|
Form, FormControl, FormGroup, |
|
HelpBlock, |
|
} from 'react-bootstrap' |
|
|
|
import {APPS, APPS_BY_RELEASE} from './metadata' |
|
import SelectApps from './SelectApps' |
|
|
|
const EMR_RELEASES = Object.keys(APPS_BY_RELEASE) |
|
|
|
function validate(values) { |
|
let errors = {} |
|
if (values.applications.length === 0) { |
|
errors.applications = 'Please select some applications to install.' |
|
} |
|
return errors |
|
} |
|
|
|
let FormExample = React.createClass({ |
|
getInitialState() { |
|
return { |
|
errors: {}, |
|
touched: { |
|
applications: false, |
|
}, |
|
values: { |
|
applications: ['hue', 'hive', 'pig', 'spark', 'hadoop'], |
|
releaseLabel: '', |
|
}, |
|
} |
|
}, |
|
|
|
/** |
|
* Update selected application state. |
|
*/ |
|
handleApplicationChange(applications) { |
|
let values = {...this.state.values, applications} |
|
let stateChange = {errors: validate(values), values} |
|
if (!this.state.touched.applications) { |
|
stateChange.touched = {...this.state.touched, applications: true} |
|
} |
|
this.setState(stateChange) |
|
}, |
|
|
|
/** |
|
* Correct selected applications when the release label is changed. |
|
*/ |
|
handleReleaseLabelChange(e) { |
|
let {value: releaseLabel} = e.target |
|
// If the release label has been cleared, don't do anything else |
|
if (releaseLabel === '') { |
|
return this.setState({values: {...this.state.values, releaseLabel}}) |
|
} |
|
let {applications} = this.state.values |
|
let nextAppIds = Object.keys(APPS_BY_RELEASE[releaseLabel]) |
|
let values = { |
|
...this.state.values, |
|
// Deselect any selected apps which no longer apply |
|
applications: applications.filter(appId => nextAppIds.indexOf(appId) !== -1), |
|
releaseLabel, |
|
} |
|
this.setState({errors: validate(values), values}) |
|
}, |
|
|
|
/** |
|
* Generic onChange handler. |
|
*/ |
|
handleChange(e) { |
|
let input = e.target |
|
this.setState({ |
|
values: { |
|
...this.state.values, |
|
[input.name]: input.type === 'checkbox' ? input.checked : input.value, |
|
} |
|
}) |
|
}, |
|
|
|
handleSubmit(e) { |
|
e.preventDefault() |
|
|
|
let errors = validate(this.state.values) |
|
if (Object.keys(errors).length > 0) { |
|
return this.setState({errors}) |
|
} |
|
|
|
// Create a cluster model object for submission |
|
let {applications, ...cluster} = this.state.values |
|
let isV4 = /^emr-4/.test(cluster.releaseLabel) |
|
// Convert application ids to names for submission |
|
cluster.applications = applications.map(appId => { |
|
let {name, v4Sandbox} = APPS[appId] |
|
// Certain apps need a '-Sandbox' suffix in EMR v4 |
|
return `${name}${isV4 && v4Sandbox ? '-Sandbox' : ''}` |
|
}) |
|
|
|
console.log(JSON.stringify(cluster, null, 2)) |
|
}, |
|
|
|
render() { |
|
let {errors, touched, values} = this.state |
|
let releaseSelected = values.releaseLabel !== '' |
|
return <Form onSubmit={this.handleSubmit} horizontal> |
|
<legend>React Form Example</legend> |
|
<FormGroup controlId="releaseLabel"> |
|
<Col componentClass={ControlLabel} sm={3} md={2}>Release Label:</Col> |
|
<Col sm={9} md={6}> |
|
<FormControl required componentClass="select" name="releaseLabel" |
|
value={values.releaseLabel} onChange={this.handleReleaseLabelChange} |
|
> |
|
<option value=""></option> |
|
{EMR_RELEASES.map(version => |
|
<option key={version} value={version}>{version}</option> |
|
)} |
|
</FormControl> |
|
<HelpBlock> |
|
The identifier for the EMR release, which includes a set of software, |
|
to use with Amazon EC2 instances that are part of an Amazon EMR cluster. |
|
See <a href="http://docs.aws.amazon.com/ElasticMapReduce/latest/ReleaseGuide/emr-release-components.html" target="_blank">About Amazon EMR Releases</a>. |
|
</HelpBlock> |
|
</Col> |
|
</FormGroup> |
|
<FormGroup> |
|
<Col componentClass={ControlLabel} sm={3} md={2}>Applications:</Col> |
|
<Col sm={9} md={6}> |
|
{!releaseSelected && <HelpBlock>Select a Release Label to show available applications.</HelpBlock>} |
|
{releaseSelected && <div> |
|
<SelectApps |
|
onChange={this.handleApplicationChange} |
|
release={values.releaseLabel} |
|
value={values.applications} |
|
/> |
|
{errors.applications && touched.applications |
|
? <Alert bsStyle="danger">{errors.applications}</Alert> |
|
: <HelpBlock>Select applications to install on your cluster.</HelpBlock> |
|
} |
|
</div>} |
|
</Col> |
|
</FormGroup> |
|
|
|
<FormGroup> |
|
<Col smOffset={3} sm={9} mdOffset={2} md={6}> |
|
<hr/> |
|
<Button bsStyle="primary" type="submit">Create Cluster</Button> |
|
</Col> |
|
</FormGroup> |
|
</Form> |
|
} |
|
}) |
|
|
|
export default FormExample |