import React, { Component, Fragment } from 'react'; import { Link, NavLink, Redirect } from 'react-router-dom'; import ErrorBox from './error-box'; import InfoBox from './info-box'; import Sidebar from './sidebar'; import Tooltip from './tooltip'; import { SaveIcon } from './icons'; import { parseCategoryURL } from '../parse'; import CONFIG from './fields-config.json'; const BuildingEdit = (props) => { if (!props.user){ return } const cat = parseCategoryURL(props.match.url); if (!props.building_id){ return (
Back to maps
); } return ( { CONFIG.map((conf_props) => { return }) } ); } class EditForm extends Component { constructor(props) { super(props); this.state = {} for (let field of props.fields) { this.state[field.slug] = props[field.slug] } this.state.error = this.props.error || undefined; this.state.like = this.props.like || undefined; this.handleChange = this.handleChange.bind(this); this.handleCheck = this.handleCheck.bind(this); this.handleLike = this.handleLike.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.handleUpdate = this.handleUpdate.bind(this); } /** * Handle changes on typical inputs * - e.g. input[type=text], radio, select, textare * * @param {DocumentEvent} event */ handleChange(event) { const target = event.target; let value = (target.value === '')? null : target.value; const name = target.name; // special transform - consider something data driven before adding 'else if's if (name === 'location_postcode' && value !== null) { value = value.toUpperCase(); } this.setState({ [name]: value }); } /** * Handle changes on checkboxes * - e.g. input[type=checkbox] * * @param {DocumentEvent} event */ handleCheck(event) { const target = event.target; const value = target.checked; const name = target.name; this.setState({ [name]: value }); } /** * Handle update directly * - e.g. as callback from MultiTextInput where we set a list of strings * * @param {String} key * @param {*} value */ handleUpdate(key, value) { this.setState({ [key]: value }); } /** * Handle likes separately * - like/love reaction is limited to set/unset per user * * @param {DocumentEvent} event */ handleLike(event) { event.preventDefault(); const like = event.target.checked; fetch(`/building/${this.props.building_id}/like.json`, { method: 'POST', headers:{ 'Content-Type': 'application/json' }, credentials: 'same-origin', body: JSON.stringify({like: like}) }).then( res => res.json() ).then(function(res){ if (res.error) { this.setState({error: res.error}) } else { this.props.selectBuilding(res); this.setState({ likes_total: res.likes_total }) } }.bind(this)).catch( (err) => this.setState({error: err}) ); } handleSubmit(event) { event.preventDefault(); this.setState({error: undefined}) fetch(`/building/${this.props.building_id}.json`, { method: 'POST', body: JSON.stringify(this.state), headers:{ 'Content-Type': 'application/json' }, credentials: 'same-origin' }).then( res => res.json() ).then(function(res){ if (res.error) { this.setState({error: res.error}) } else { this.props.selectBuilding(res); } }.bind(this)).catch( (err) => this.setState({error: err}) ); } render() { const match = this.props.cat === this.props.slug; const building_like = this.props.building_like; return (
match}>

{this.props.title}

{ match? ( !this.props.inactive?
{ this.props.slug === 'location'? : null } { this.props.fields.map((props) => { switch (props.type) { case "text": return case "text_list": return case "text_long": return case "number": return case "year_estimator": return case "text_multi": return case "checkbox": return case "like": return default: return null } }) } { (this.props.slug === 'like')? // special-case for likes null :
} :
) : null }
) } } const TextInput = (props) => ( ); const LongTextInput = (props) => ( ) class MultiTextInput extends Component { constructor(props) { super(props); this.edit = this.edit.bind(this); this.add = this.add.bind(this); this.remove = this.remove.bind(this); this.getValues = this.getValues.bind(this); } getValues() { return (this.props.value && this.props.value.length)? this.props.value : [null]; } edit(event) { const edit_i = +event.target.dataset.index; const edit_item = event.target.value; const old_values = this.getValues(); const values = old_values.map((item, i) => { return i === edit_i ? edit_item : item; }); this.props.handleChange(this.props.slug, values); } add(event) { event.preventDefault(); const values = this.getValues().concat(""); this.props.handleChange(this.props.slug, values); } remove(event){ const remove_i = +event.target.dataset.index; const values = this.getValues().filter((_, i) => { return i !== remove_i; }); this.props.handleChange(this.props.slug, values); } render() { const values = this.getValues(); return ( ) } } const TextListInput = (props) => ( ) const NumberInput = (props) => ( ); class YearEstimator extends Component { constructor(props) { super(props); this.state = { year: props.date_year, upper: props.date_upper, lower: props.date_lower, decade: Math.floor(props.date_year / 10) * 10, century: Math.floor(props.date_year / 100) * 100 } } // TODO add dropdown for decade, century // TODO roll in first/last year estimate // TODO handle changes internally, reporting out date_year, date_upper, date_lower render() { return ( ) } } const CheckboxInput = (props) => (
) const LikeButton = (props) => (

{(props.value)? props.value : 0} likes

); const Label = (props) => ( ) export default BuildingEdit;