frontend/app/common/TimeIntervalComponent.jsx (88 lines of code) (raw):

import React from 'react'; import PropTypes from 'prop-types'; import moment from 'moment'; import 'moment-duration-format'; import {withStyles, createStyles, TextField, Typography} from "@material-ui/core"; const styles = (theme) => createStyles({ timeInterval: { marginLeft: "1em", width: "3em" } }); class TimeIntervalComponent extends React.Component { static propTypes = { editable: PropTypes.bool.isRequired, value: PropTypes.number.isRequired, didUpdate: PropTypes.func, classes: PropTypes.object }; constructor(props){ super(props); this.state = { daysSet: 0, hoursSet: 0, minutesSet: 0, secondsSet:0, moment: null }; this.notifyParent = this.notifyParent.bind(this); } componentDidMount(){ const d = moment.duration(this.props.value,"seconds"); this.setState({moment: d, daysSet: d.days(), hoursSet: d.hours(), minutesSet: d.minutes(), secondsSet: d.seconds()}) } componentDidUpdate(oldProps,oldState){ if(oldProps.value!==this.props.value){ console.log("time interval seconds updated from ", oldProps.value, " to ", this.props.value); const d = moment.duration(this.props.value,"seconds"); this.setState({moment: d, hoursSet: d.hours(), minutesSet: d.minutes(), secondsSet: d.seconds()}); console.log(d); } } notifyParent(){ console.log("notifyParent", this.state); if(this.props.didUpdate) this.props.didUpdate(this.state.daysSet*(3600*24)+this.state.hoursSet*3600+this.state.minutesSet*60+this.state.secondsSet); } safeUpdateValue(key, newValue){ let update = {}; update[key] = parseInt(newValue); console.log("new value for " + key, newValue); if(!isNaN(update[key])) //only set the update if the number is valid this.setState(update,this.notifyParent) } render(){ if(this.props.editable){ return <span className="duration"> <TextField className="time-interval" type="number" value={this.state.daysSet} onChange={evt=>this.safeUpdateValue("daysSet", evt.target.value)}/> days <TextField className="time-interval" type="number" value={this.state.hoursSet} onChange={evt=>this.safeUpdateValue("hoursSet", evt.target.value)}/> hours <TextField className="time-interval" type="number" value={this.state.minutesSet} onChange={evt=>this.safeUpdateValue("minutesSet", evt.target.value)}/> minutes <TextField className="time-interval" type="number" value={this.state.secondsSet} onChange={evt=>this.safeUpdateValue("secondsSet", evt.target.value)}/> seconds </span> } else { let fmtStringParts = []; if (this.state.daysSet > 0) fmtStringParts = fmtStringParts.concat(["d [days]"]); if (this.state.hoursSet > 0) fmtStringParts = fmtStringParts.concat(["h [hours]"]); if (this.state.minutesSet > 0) fmtStringParts = fmtStringParts.concat(["m [minutes]"]); if (this.state.secondsSet > 0) fmtStringParts = fmtStringParts.concat(["s [seconds]"]); if(fmtStringParts.length===0){ return <Typography className="duration">invalid duration</Typography> } else { const formatString = fmtStringParts.join(", "); return <Typography className="duration">{this.state.moment.format(formatString)}</Typography> } } } } export default withStyles(styles)(TimeIntervalComponent);