mirror of https://github.com/fspc/workstand.git
Drew Larson
8 years ago
5 changed files with 311 additions and 5 deletions
@ -0,0 +1,110 @@ |
|||
import React from 'react'; |
|||
import Dialog from 'material-ui/Dialog'; |
|||
import FlatButton from 'material-ui/FlatButton'; |
|||
import TextField from 'material-ui/TextField'; |
|||
import DatePicker from 'material-ui/DatePicker'; |
|||
import RaisedButton from 'material-ui/RaisedButton'; |
|||
import moment from 'moment-timezone'; |
|||
import Size from '../Size'; |
|||
import Source from '../Source'; |
|||
import Checkbox from 'material-ui/Checkbox'; |
|||
|
|||
/** |
|||
* A modal dialog can only be closed by selecting one of the actions. |
|||
*/ |
|||
export default class BikeModal extends React.Component { |
|||
constructor(props) { |
|||
super(props); |
|||
|
|||
this.state = { |
|||
open: props.open, |
|||
bike: undefined, |
|||
}; |
|||
} |
|||
componentWillReceiveProps(newProps) { |
|||
this.setState({ open: newProps.open || false, bike: newProps.bike || false }); |
|||
} |
|||
handleClose = () => { |
|||
this.setState({ open: false }); |
|||
}; |
|||
|
|||
render() { |
|||
const styles = { |
|||
block: { |
|||
maxWidth: 250, |
|||
}, |
|||
checkbox: { |
|||
marginBottom: 16, |
|||
}, |
|||
}; |
|||
|
|||
const actions = [ |
|||
<FlatButton |
|||
label="Cancel" |
|||
primary |
|||
onTouchTap={this.handleClose} |
|||
/>, |
|||
<FlatButton |
|||
label="Submit" |
|||
primary |
|||
disabled |
|||
onTouchTap={this.handleClose} |
|||
/>, |
|||
]; |
|||
|
|||
let form; |
|||
|
|||
|
|||
if (this.state.bike !== undefined) { |
|||
const timezone = moment.tz.guess(); |
|||
const { |
|||
make, |
|||
price, |
|||
claimed_at, |
|||
claimed_by, |
|||
colour, |
|||
cpic_searched_at, |
|||
created_at, |
|||
size, |
|||
serial_number, |
|||
source, |
|||
stripped } = this.state.bike; |
|||
const createdAtFormatted = moment(created_at).tz(timezone).fromNow(); |
|||
|
|||
form = ( |
|||
<div> |
|||
<TextField label={'Blah'} value={make} /><TextField label="Price" value={price} /><br /> |
|||
<TextField label="Claimed on" value={claimed_at} /><TextField label="Claimed by" value={claimed_by} /><br /> |
|||
<TextField label="Colour" value={colour} /><br /> |
|||
<TextField label="CPIC Searched on" value={cpic_searched_at} /><br /> |
|||
<TextField label="Created at" value={createdAtFormatted} readOnly disabled /><br /> |
|||
<Size size={size} /> |
|||
<TextField label="Serial number" value={serial_number} /> |
|||
<Source source={source} /> |
|||
<div style={styles.block}> |
|||
<Checkbox |
|||
label="Stripped" |
|||
labelPosition="left" |
|||
style={styles.checkbox} |
|||
value={stripped} |
|||
/> |
|||
</div> |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
return ( |
|||
<div> |
|||
<Dialog |
|||
title="Edit Bike" |
|||
actions={actions} |
|||
modal={true} |
|||
open={this.state.open} |
|||
> |
|||
{(form) ? form : <div>Unable to edit bike.</div>} |
|||
|
|||
</Dialog> |
|||
</div> |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,104 @@ |
|||
import React from 'react'; |
|||
import { polyFill } from 'es6-promise'; |
|||
import moment from 'moment-timezone'; |
|||
import fetch from 'isomorphic-fetch'; |
|||
import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table'; |
|||
import FlatButton from 'material-ui/FlatButton'; |
|||
import { friendlySize } from '../Size'; |
|||
import BikeModal from '../BikeModal'; |
|||
|
|||
function checkStatus(response) { |
|||
if (response.status >= 200 && response.status < 300) { |
|||
return response; |
|||
} |
|||
const error = new Error(response.statusText); |
|||
error.response = response; |
|||
throw error; |
|||
} |
|||
|
|||
function parseJSON(response) { |
|||
return response.json(); |
|||
} |
|||
|
|||
export default class BikeTable extends React.Component { |
|||
constructor(props) { |
|||
super(props); |
|||
|
|||
this.state = { |
|||
bikes: [], |
|||
bikeModal: { |
|||
open: false, |
|||
bike: undefined, |
|||
}, |
|||
}; |
|||
|
|||
this.handleEditBike = this.handleEditBike.bind(this); |
|||
} |
|||
|
|||
componentDidMount() { |
|||
fetch('/api/v1/bikes/') |
|||
.then(checkStatus) |
|||
.then(parseJSON) |
|||
.then((data) => { |
|||
this.setState({ bikes: data }); |
|||
console.log('request succeeded with JSON response', data); |
|||
}) |
|||
.catch((error) => { |
|||
console.log('request failed', error); |
|||
}); |
|||
} |
|||
|
|||
handleEditBike(bike) { |
|||
console.log('Bike edit!'); |
|||
this.setState({ |
|||
bikeModal: { |
|||
open: true, |
|||
bike, |
|||
}, |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
const bikeRows = this.state.bikes.map(bike => ( |
|||
<TableRow selectable={false} key={bike.id}> |
|||
<TableRowColumn>{friendlySize(bike.size)}</TableRowColumn> |
|||
<TableRowColumn>{bike.colour}</TableRowColumn> |
|||
<TableRowColumn>{bike.make}</TableRowColumn> |
|||
<TableRowColumn>{bike.serial_number}</TableRowColumn> |
|||
<TableRowColumn>{bike.state}</TableRowColumn> |
|||
<TableRowColumn>{bike.claimed_by}</TableRowColumn> |
|||
<TableRowColumn><FlatButton label="Edit" primary onTouchTap={this.handleEditBike.bind(null, bike)} /></TableRowColumn> |
|||
</TableRow> |
|||
)); |
|||
|
|||
return ( |
|||
<div className="mdl-grid"> |
|||
<div className="mdl-cell mdl-cell--12-col"> |
|||
<h3>Bikes</h3> |
|||
<Table selectable={false}> |
|||
<TableHeader adjustForCheckbox={false} displaySelectAll={false}> |
|||
<TableRow> |
|||
<TableHeaderColumn>Size</TableHeaderColumn> |
|||
<TableHeaderColumn>Colour</TableHeaderColumn> |
|||
<TableHeaderColumn>Make</TableHeaderColumn> |
|||
<TableHeaderColumn>Serial number</TableHeaderColumn> |
|||
<TableHeaderColumn>State</TableHeaderColumn> |
|||
<TableHeaderColumn>Claimed by</TableHeaderColumn> |
|||
<TableRowColumn /> |
|||
</TableRow> |
|||
</TableHeader> |
|||
<TableBody displayRowCheckbox={false}> |
|||
{bikeRows.length ? |
|||
bikeRows : |
|||
<TableRow> |
|||
<TableRowColumn>{'No members currently signed in.'}</TableRowColumn> |
|||
</TableRow> |
|||
} |
|||
</TableBody> |
|||
</Table> |
|||
<BikeModal bike={this.state.bikeModal.bike} open={this.state.bikeModal.open} /> |
|||
</div> |
|||
</div> |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
import React, { PropTypes } from 'react'; |
|||
import SelectField from 'material-ui/SelectField'; |
|||
import MenuItem from 'material-ui/MenuItem'; |
|||
|
|||
const sizes = ['C', 'S', 'M', 'L', 'XL']; |
|||
|
|||
export const friendlySize = (size) => { |
|||
switch (size) { |
|||
case 'C': |
|||
return 'child'; |
|||
case 'S': |
|||
return 'small'; |
|||
case 'M': |
|||
return 'medium'; |
|||
case 'L': |
|||
return 'large'; |
|||
case 'XL': |
|||
return 'extra large'; |
|||
default: |
|||
return 'unknown'; |
|||
} |
|||
}; |
|||
|
|||
const Size = ({ size }) => { |
|||
const items = sizes.map(s => |
|||
<MenuItem value={s} primaryText={friendlySize(s)} />, |
|||
); |
|||
|
|||
return ( |
|||
<div> |
|||
<SelectField |
|||
floatingLabelText="Size" |
|||
value={size} |
|||
onChange={undefined} |
|||
> |
|||
<MenuItem value={null} primaryText="" /> |
|||
{items} |
|||
</SelectField> |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
Size.propTypes = { |
|||
size: PropTypes.string, |
|||
}; |
|||
|
|||
export default Size; |
@ -0,0 +1,44 @@ |
|||
import React, { PropTypes } from 'react'; |
|||
import SelectField from 'material-ui/SelectField'; |
|||
import MenuItem from 'material-ui/MenuItem'; |
|||
|
|||
const sources = ['COS_BIKE_DIVERSION_PILOT', 'UOFS', 'DROP_OFF']; |
|||
|
|||
export const friendly = (s) => { |
|||
switch (s) { |
|||
case 'COS_BIKE_DIVERSION_PILOT': |
|||
return 'City of Saskatoon Bike Diversion Pilot'; |
|||
case 'UOFS': |
|||
return 'University of Saskatchewan'; |
|||
case 'DROP_OFF': |
|||
return 'Drop Off'; |
|||
default: |
|||
return undefined; |
|||
}; |
|||
}; |
|||
|
|||
const Source = ({ source }) => { |
|||
const items = sources.map(s => |
|||
<MenuItem value={s} primaryText={friendly(s)} />, |
|||
); |
|||
|
|||
return ( |
|||
<div> |
|||
<SelectField |
|||
floatingLabelText="Source" |
|||
value={source} |
|||
onChange={undefined} |
|||
autoWidth={true} |
|||
> |
|||
<MenuItem value={null} primaryText="" /> |
|||
{items} |
|||
</SelectField> |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
Source.propTypes = { |
|||
source: PropTypes.string, |
|||
}; |
|||
|
|||
export default Source; |
Loading…
Reference in new issue