2018-10-01 07:45:33 -04:00
|
|
|
import React, { Component, Fragment } from 'react';
|
|
|
|
import { Link, NavLink, Redirect } from 'react-router-dom';
|
2018-10-04 17:50:33 -04:00
|
|
|
import queryString from 'query-string';
|
2018-09-13 12:13:03 -04:00
|
|
|
|
|
|
|
import ErrorBox from './error-box';
|
2018-09-13 15:41:42 -04:00
|
|
|
import InfoBox from './info-box';
|
2018-09-11 15:59:59 -04:00
|
|
|
import Sidebar from './sidebar';
|
2018-10-05 13:41:12 -04:00
|
|
|
import Tooltip from './tooltip';
|
2018-10-04 17:50:33 -04:00
|
|
|
import { HelpIcon, CloseIcon, SaveIcon } from './icons';
|
2018-09-09 17:22:44 -04:00
|
|
|
|
2018-10-03 16:47:49 -04:00
|
|
|
import CONFIG from './fields-config.json';
|
|
|
|
|
2018-10-01 07:45:33 -04:00
|
|
|
|
2018-10-04 17:50:33 -04:00
|
|
|
const BuildingEdit = (props) => {
|
|
|
|
if (!props.user){
|
|
|
|
return <Redirect to="/sign-up.html" />
|
|
|
|
}
|
|
|
|
if (!props.building_id){
|
2018-10-01 07:45:33 -04:00
|
|
|
return (
|
2018-10-05 17:19:26 -04:00
|
|
|
<Sidebar title="Building Not Found" back="/map/age.html">
|
2018-10-04 17:50:33 -04:00
|
|
|
<InfoBox msg="We can't find that one anywhere - try the map again?" />
|
|
|
|
<div className="buttons-container">
|
2018-10-05 17:19:26 -04:00
|
|
|
<Link to="/map/age.html" className="btn btn-secondary">Back to maps</Link>
|
2018-10-04 17:50:33 -04:00
|
|
|
</div>
|
2018-10-01 07:45:33 -04:00
|
|
|
</Sidebar>
|
|
|
|
);
|
|
|
|
}
|
2018-10-04 17:50:33 -04:00
|
|
|
|
|
|
|
const search = (props.location && props.location.search)?
|
|
|
|
queryString.parse(props.location.search):
|
|
|
|
{};
|
|
|
|
return (
|
2018-10-05 13:41:12 -04:00
|
|
|
<Sidebar title={`Edit Building`}
|
|
|
|
back={search.cat? `/building/${props.building_id}.html?cat=${search.cat}`: `/building//${props.building_id}.html`}>
|
2018-10-04 17:50:33 -04:00
|
|
|
{
|
|
|
|
CONFIG.map((conf_props) => {
|
|
|
|
return <EditForm
|
|
|
|
{...conf_props} {...props}
|
|
|
|
search={search} key={conf_props.slug} />
|
|
|
|
})
|
|
|
|
}
|
|
|
|
</Sidebar>
|
|
|
|
);
|
2018-10-01 07:45:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
class EditForm extends Component {
|
2018-09-11 15:59:59 -04:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2018-10-01 07:45:33 -04:00
|
|
|
this.state = {...props}
|
|
|
|
this.state.error = this.state.error || undefined;
|
2018-09-11 15:59:59 -04:00
|
|
|
|
|
|
|
this.handleChange = this.handleChange.bind(this);
|
|
|
|
this.handleLike = this.handleLike.bind(this);
|
|
|
|
this.handleSubmit = this.handleSubmit.bind(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
handleChange(event) {
|
|
|
|
const target = event.target;
|
2018-09-30 18:06:30 -04:00
|
|
|
const value = (target.value === '')? null : target.value;
|
2018-09-11 15:59:59 -04:00
|
|
|
const name = target.name;
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
[name]: value
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
handleLike(event) {
|
|
|
|
const liked = event.target.checked;
|
2018-10-01 07:45:33 -04:00
|
|
|
this.setState({
|
|
|
|
like: liked
|
|
|
|
});
|
2018-09-11 15:59:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
handleSubmit(event) {
|
|
|
|
event.preventDefault();
|
2018-09-13 12:13:03 -04:00
|
|
|
this.setState({error: undefined})
|
|
|
|
|
2018-09-30 16:54:47 -04:00
|
|
|
fetch(`/building/${this.props.building_id}.json`, {
|
2018-09-11 15:59:59 -04:00
|
|
|
method: 'POST',
|
|
|
|
body: JSON.stringify(this.state),
|
|
|
|
headers:{
|
|
|
|
'Content-Type': 'application/json'
|
2018-09-30 15:29:46 -04:00
|
|
|
},
|
|
|
|
credentials: 'same-origin'
|
2018-09-11 15:59:59 -04:00
|
|
|
}).then(
|
|
|
|
res => res.json()
|
|
|
|
).then(function(res){
|
|
|
|
if (res.error) {
|
2018-09-13 12:13:03 -04:00
|
|
|
this.setState({error: res.error})
|
2018-09-11 15:59:59 -04:00
|
|
|
} else {
|
2018-10-01 07:45:33 -04:00
|
|
|
this.props.selectBuilding(res);
|
2018-10-05 17:19:26 -04:00
|
|
|
const new_cat = this.props.search.cat;
|
|
|
|
this.props.history.push(`/building/${res.building_id}.html?cat=${new_cat}`);
|
2018-09-11 15:59:59 -04:00
|
|
|
}
|
2018-09-13 12:13:03 -04:00
|
|
|
}.bind(this)).catch(
|
|
|
|
(err) => this.setState({error: err})
|
2018-09-11 15:59:59 -04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2018-10-04 17:50:33 -04:00
|
|
|
const match = this.props.search.cat === this.props.slug;
|
2018-10-05 17:19:26 -04:00
|
|
|
if (!match) {
|
|
|
|
return null
|
|
|
|
}
|
2018-09-11 15:59:59 -04:00
|
|
|
return (
|
2018-10-01 07:45:33 -04:00
|
|
|
<section className={(this.props.inactive)? "data-section inactive": "data-section"}>
|
2018-10-04 17:50:33 -04:00
|
|
|
<header className={(match? "active " : "") + "bullet-prefix section-header"}>
|
2018-10-05 17:37:46 -04:00
|
|
|
<a><h3 className="h3">{this.props.title}</h3></a>
|
2018-10-05 04:10:20 -04:00
|
|
|
<nav className="icon-buttons">
|
2018-10-04 17:50:33 -04:00
|
|
|
{
|
|
|
|
this.props.help?
|
|
|
|
<a className="icon-button help" title="Find out more" href={this.props.help}
|
|
|
|
target="_blank" rel="noopener noreferrer">
|
|
|
|
<HelpIcon />
|
|
|
|
</a>
|
|
|
|
: null
|
|
|
|
}
|
2018-10-05 17:19:26 -04:00
|
|
|
<NavLink className="icon-button save" title="Save Changes"
|
|
|
|
onClick={this.handleSubmit}
|
|
|
|
to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}>
|
|
|
|
<SaveIcon />
|
|
|
|
</NavLink>
|
|
|
|
<NavLink className="icon-button close" title="Cancel"
|
|
|
|
to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}>
|
|
|
|
<CloseIcon />
|
|
|
|
</NavLink>
|
2018-10-05 04:10:20 -04:00
|
|
|
</nav>
|
2018-10-04 17:50:33 -04:00
|
|
|
</header>
|
2018-10-05 17:19:26 -04:00
|
|
|
{ this.props.intro? <p className="data-intro">{ this.props.intro }</p> : null }
|
|
|
|
<form action={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}
|
|
|
|
method="GET" onSubmit={this.handleSubmit}>
|
|
|
|
<ErrorBox msg={this.state.error} />
|
|
|
|
{
|
|
|
|
this.props.fields.map((props) => {
|
|
|
|
var el;
|
|
|
|
switch (props.type) {
|
|
|
|
case "text":
|
|
|
|
el = <TextInput {...props} handleChange={this.handleChange}
|
|
|
|
value={this.state[props.slug]} key={props.slug} />
|
|
|
|
break;
|
|
|
|
case "text_list":
|
|
|
|
el = <TextListInput {...props} handleChange={this.handleChange}
|
|
|
|
value={this.state[props.slug]} key={props.slug} />
|
|
|
|
break;
|
|
|
|
case "number":
|
|
|
|
el = <NumberInput {...props} handleChange={this.handleChange}
|
|
|
|
value={this.state[props.slug]} key={props.slug} />
|
|
|
|
break;
|
|
|
|
case "like":
|
|
|
|
el = <LikeButton {...props} handleLike={this.handleLike}
|
|
|
|
value={this.state[props.slug]} key={props.slug} />
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
el = null
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return el
|
|
|
|
})
|
|
|
|
}
|
|
|
|
{
|
|
|
|
(this.props.inactive)?
|
|
|
|
null : (
|
|
|
|
<div className="buttons-container">
|
|
|
|
<Link to={`/building/${this.props.building_id}.html?cat=${this.props.slug}`}
|
|
|
|
className="btn btn-secondary">Cancel</Link>
|
|
|
|
<button type="submit" className="btn btn-primary">Save</button>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
</form>
|
2018-10-05 17:37:46 -04:00
|
|
|
<p className="data-intro">
|
|
|
|
Colouring may take a few seconds - try zooming the map or
|
|
|
|
hitting refresh after saving (we're working on making this
|
|
|
|
smoother).</p>
|
2018-10-01 07:45:33 -04:00
|
|
|
</section>
|
|
|
|
)
|
2018-09-11 15:59:59 -04:00
|
|
|
}
|
|
|
|
}
|
2018-09-09 17:22:44 -04:00
|
|
|
|
2018-10-01 07:45:33 -04:00
|
|
|
const TextInput = (props) => (
|
|
|
|
<Fragment>
|
2018-10-05 13:41:12 -04:00
|
|
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip} />
|
2018-10-01 07:45:33 -04:00
|
|
|
<input className="form-control" type="text"
|
|
|
|
id={props.slug} name={props.slug}
|
|
|
|
value={props.value || ""}
|
2018-10-05 17:19:26 -04:00
|
|
|
disabled={props.disabled}
|
2018-10-01 07:45:33 -04:00
|
|
|
onChange={props.handleChange}
|
|
|
|
/>
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
|
2018-10-05 13:41:12 -04:00
|
|
|
const TextListInput = (props) => (
|
|
|
|
<Fragment>
|
|
|
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip} />
|
|
|
|
<select className="form-control"
|
|
|
|
id={props.slug} name={props.slug}
|
|
|
|
value={props.value || ""}
|
2018-10-05 17:19:26 -04:00
|
|
|
disabled={props.disabled}
|
2018-10-05 13:41:12 -04:00
|
|
|
list={`${props.slug}_suggestions`}
|
|
|
|
onChange={props.handleChange}>
|
|
|
|
<option value="">Select a source</option>
|
|
|
|
{
|
|
|
|
props.options.map(option => (
|
2018-10-05 17:19:26 -04:00
|
|
|
<option key={option} value={option}>{option}</option>
|
2018-10-05 13:41:12 -04:00
|
|
|
))
|
|
|
|
}
|
|
|
|
</select>
|
|
|
|
</Fragment>
|
|
|
|
)
|
|
|
|
|
2018-10-01 07:45:33 -04:00
|
|
|
const NumberInput = (props) => (
|
|
|
|
<Fragment>
|
2018-10-05 13:41:12 -04:00
|
|
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip} />
|
2018-10-01 07:45:33 -04:00
|
|
|
<input className="form-control" type="number" step={props.step}
|
|
|
|
id={props.slug} name={props.slug}
|
|
|
|
value={props.value || ""}
|
2018-10-05 17:19:26 -04:00
|
|
|
disabled={props.disabled}
|
2018-10-01 07:45:33 -04:00
|
|
|
onChange={props.handleChange}
|
|
|
|
/>
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
|
|
|
|
const LikeButton = (props) => (
|
|
|
|
<Fragment>
|
|
|
|
<label htmlFor="likes">Like this building?</label>
|
|
|
|
<div className="form-check">
|
|
|
|
<input className="form-check-input position-static"
|
|
|
|
type="checkbox"
|
|
|
|
checked={props.value}
|
|
|
|
onChange={props.handleLike}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
|
2018-10-05 13:41:12 -04:00
|
|
|
const Label = (props) => (
|
|
|
|
<label htmlFor={props.slug}>
|
|
|
|
{props.title}
|
|
|
|
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
|
|
|
</label>
|
|
|
|
)
|
|
|
|
|
2018-09-09 17:22:44 -04:00
|
|
|
export default BuildingEdit;
|