|  | 
|  | 1 | +import React, { Component, PropTypes } from "react"; | 
|  | 2 | + | 
|  | 3 | +import { shouldRender, parseDateString, toDateString, pad } from "../../utils"; | 
|  | 4 | +import SelectWidget from "../widgets/SelectWidget"; | 
|  | 5 | + | 
|  | 6 | + | 
|  | 7 | +function rangeOptions(start, stop) { | 
|  | 8 | + let options = []; | 
|  | 9 | + for (let i=start; i<= stop; i++) { | 
|  | 10 | + options.push({value: i, label: pad(i, 2)}); | 
|  | 11 | + } | 
|  | 12 | + return options; | 
|  | 13 | +} | 
|  | 14 | + | 
|  | 15 | +function DateElement({type, range, value, select, rootId}) { | 
|  | 16 | + const id = rootId + "_" + type; | 
|  | 17 | + return ( | 
|  | 18 | + <span> | 
|  | 19 | + <SelectWidget | 
|  | 20 | + schema={{type: "integer"}} | 
|  | 21 | + id={id} | 
|  | 22 | + className="form-control" | 
|  | 23 | + options={rangeOptions(range[0], range[1])} | 
|  | 24 | + value={value} | 
|  | 25 | + onChange={(value) => select(type, value)} /> | 
|  | 26 | + <p className="text-center help-block"> | 
|  | 27 | + <label htmlFor={id}><small>{type}</small></label> | 
|  | 28 | + </p> | 
|  | 29 | + </span> | 
|  | 30 | + ); | 
|  | 31 | +} | 
|  | 32 | + | 
|  | 33 | +class DateWidget extends Component { | 
|  | 34 | + defaultProps = { | 
|  | 35 | + time: false | 
|  | 36 | + }; | 
|  | 37 | + | 
|  | 38 | + constructor(props) { | 
|  | 39 | + super(props); | 
|  | 40 | + this.state = parseDateString(props.value, !!props.time); | 
|  | 41 | + } | 
|  | 42 | + | 
|  | 43 | + componentWillReceiveProps(nextProps) { | 
|  | 44 | + this.setState(parseDateString(nextProps.value, !!nextProps.time)); | 
|  | 45 | + } | 
|  | 46 | + | 
|  | 47 | + shouldComponentUpdate(nextProps, nextState) { | 
|  | 48 | + return shouldRender(this, nextProps, nextState); | 
|  | 49 | + } | 
|  | 50 | + | 
|  | 51 | + onChange = (property, value) => { | 
|  | 52 | + this.setState({[property]: value}, () => { | 
|  | 53 | + this.props.onChange(toDateString(this.state)); | 
|  | 54 | + }); | 
|  | 55 | + }; | 
|  | 56 | + | 
|  | 57 | + get dateElements() { | 
|  | 58 | + const {id, time} = this.props; | 
|  | 59 | + const {year, month, day, hour, minute, second} = this.state; | 
|  | 60 | + const data = [ | 
|  | 61 | + {type: "year", range: [1900, 2020], value: year}, | 
|  | 62 | + {type: "month", range: [1, 12], value: month}, | 
|  | 63 | + {type: "day", range: [1, 31], value: day}, | 
|  | 64 | + ]; | 
|  | 65 | + if (time) { | 
|  | 66 | + data.push( | 
|  | 67 | + {type: "hour", range: [0, 23], value: hour}, | 
|  | 68 | + {type: "minute", range: [0, 59], value: minute}, | 
|  | 69 | + {type: "second", range: [0, 59], value: second} | 
|  | 70 | + ); | 
|  | 71 | + } | 
|  | 72 | + return data.map(props => { | 
|  | 73 | + return <DateElement rootId={id} select={this.onChange} {...props} />; | 
|  | 74 | + }); | 
|  | 75 | + } | 
|  | 76 | + | 
|  | 77 | + render() { | 
|  | 78 | + return ( | 
|  | 79 | + <ul className="list-inline">{ | 
|  | 80 | + this.dateElements.map((elem, i) => <li key={i}>{elem}</li>) | 
|  | 81 | + }</ul> | 
|  | 82 | + ); | 
|  | 83 | + } | 
|  | 84 | +} | 
|  | 85 | + | 
|  | 86 | +if (process.env.NODE_ENV !== "production") { | 
|  | 87 | + DateWidget.propTypes = { | 
|  | 88 | + schema: PropTypes.object.isRequired, | 
|  | 89 | + id: PropTypes.string.isRequired, | 
|  | 90 | + placeholder: PropTypes.string, | 
|  | 91 | + value: React.PropTypes.string, | 
|  | 92 | + required: PropTypes.bool, | 
|  | 93 | + onChange: PropTypes.func, | 
|  | 94 | + time: PropTypes.bool, | 
|  | 95 | + }; | 
|  | 96 | +} | 
|  | 97 | + | 
|  | 98 | +export default DateWidget; | 
0 commit comments