Fold edit-handling functionality into data-container
The intention is to wrap components using withCopyEdit and to use a 'mode' prop to control view/edit/copy/paste mode. Next steps to unpack form field data components and update in eaech category container.
This commit is contained in:
parent
5060628937
commit
51d8ac3ed7
@ -1,367 +1,8 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
import React, { Component, Fragment } from 'react';
|
||||||
import { Link, NavLink, Redirect } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import Sidebar from './sidebar';
|
|
||||||
import BuildingNotFound from './building-not-found';
|
|
||||||
import ErrorBox from '../components/error-box';
|
|
||||||
import InfoBox from '../components/info-box';
|
|
||||||
import Tooltip from '../components/tooltip';
|
import Tooltip from '../components/tooltip';
|
||||||
import { BackIcon, SaveIcon } from '../components/icons';
|
|
||||||
|
|
||||||
import CONFIG from './fields-config.json';
|
|
||||||
|
|
||||||
const BuildingEdit = (props) => {
|
|
||||||
if (!props.user){
|
|
||||||
return <Redirect to="/sign-up.html" />
|
|
||||||
}
|
|
||||||
const cat = props.match.params.cat;
|
|
||||||
const sections = CONFIG.filter((d) => d.slug === cat)
|
|
||||||
|
|
||||||
if (!props.building_id || sections.length !== 1){
|
|
||||||
return (<BuildingNotFound mode="edit" />);
|
|
||||||
}
|
|
||||||
|
|
||||||
const section = sections[0];
|
|
||||||
return (
|
|
||||||
<Sidebar>
|
|
||||||
<EditForm
|
|
||||||
key={props.building_id} // provide key so that React re-creates if props change
|
|
||||||
{...section}
|
|
||||||
{...props}
|
|
||||||
cat={cat}
|
|
||||||
/>
|
|
||||||
</Sidebar>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildingEdit.propTypes = {
|
|
||||||
user: PropTypes.object,
|
|
||||||
match: PropTypes.object,
|
|
||||||
building_id: PropTypes.number
|
|
||||||
}
|
|
||||||
|
|
||||||
class EditForm extends Component<any, any> { // TODO: add proper types
|
|
||||||
static propTypes = { // TODO: generate propTypes from TS
|
|
||||||
title: PropTypes.string,
|
|
||||||
slug: PropTypes.string,
|
|
||||||
cat: PropTypes.string,
|
|
||||||
help: PropTypes.string,
|
|
||||||
error: PropTypes.object,
|
|
||||||
like: PropTypes.bool,
|
|
||||||
building_like: PropTypes.bool,
|
|
||||||
selectBuilding: PropTypes.func,
|
|
||||||
building_id: PropTypes.number,
|
|
||||||
inactive: PropTypes.bool,
|
|
||||||
fields: PropTypes.array
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
// create object and spread into state to avoid TS complaining about modifying readonly state
|
|
||||||
let fieldsObj = {};
|
|
||||||
for (const field of props.fields) {
|
|
||||||
fieldsObj[field.slug] = props[field.slug];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
error: this.props.error || undefined,
|
|
||||||
like: this.props.like || undefined,
|
|
||||||
copying: false,
|
|
||||||
keys_to_copy: {},
|
|
||||||
...fieldsObj
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
this.toggleCopying = this.toggleCopying.bind(this);
|
|
||||||
this.toggleCopyAttribute = this.toggleCopyAttribute.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enter or exit "copying" state - allow user to select attributes to copy
|
|
||||||
*/
|
|
||||||
toggleCopying() {
|
|
||||||
this.setState({
|
|
||||||
copying: !this.state.copying
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keep track of data to copy (accumulate while in "copying" state)
|
|
||||||
*
|
|
||||||
* Note that we track keys only - values are already held in state
|
|
||||||
*
|
|
||||||
* @param {string} key
|
|
||||||
*/
|
|
||||||
toggleCopyAttribute(key) {
|
|
||||||
const keys = this.state.keys_to_copy;
|
|
||||||
if(this.state.keys_to_copy[key]){
|
|
||||||
delete keys[key];
|
|
||||||
} else {
|
|
||||||
keys[key] = true;
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
keys_to_copy: keys
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(`/api/buildings/${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(`/api/buildings/${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 cat = this.props.cat;
|
|
||||||
const buildingLike = this.props.building_like;
|
|
||||||
|
|
||||||
const values_to_copy = {}
|
|
||||||
for (const key of Object.keys(this.state.keys_to_copy)) {
|
|
||||||
values_to_copy[key] = this.state[key]
|
|
||||||
}
|
|
||||||
const data_string = JSON.stringify(values_to_copy);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section className={(this.props.inactive)? 'data-section inactive': 'data-section'}>
|
|
||||||
<header className={`section-header edit ${this.props.slug} background-${this.props.slug}`}>
|
|
||||||
<Link className="icon-button back" to="/edit/categories.html">
|
|
||||||
<BackIcon />
|
|
||||||
</Link>
|
|
||||||
<h2 className="h2">{this.props.title}</h2>
|
|
||||||
<nav className="icon-buttons">
|
|
||||||
{
|
|
||||||
(match && !this.props.inactive && this.props.slug !== 'like')?
|
|
||||||
this.state.copying?
|
|
||||||
<Fragment>
|
|
||||||
<NavLink
|
|
||||||
to={`/multi-edit/${this.props.cat}.html?data=${data_string}`}
|
|
||||||
className="icon-button copy">
|
|
||||||
Copy selected
|
|
||||||
</NavLink>
|
|
||||||
<a className="icon-button copy" onClick={this.toggleCopying}>Cancel</a>
|
|
||||||
</Fragment>
|
|
||||||
:
|
|
||||||
<a className="icon-button copy" onClick={this.toggleCopying}>Copy</a>
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
{
|
|
||||||
(match && this.props.slug === 'like')?
|
|
||||||
<NavLink
|
|
||||||
to={`/multi-edit/${this.props.cat}.html`}
|
|
||||||
className="icon-button copy">
|
|
||||||
Copy
|
|
||||||
</NavLink>
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.props.help && !this.state.copying?
|
|
||||||
<a className="icon-button help" title="Find out more" href={this.props.help}>
|
|
||||||
Info
|
|
||||||
</a>
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
{
|
|
||||||
(match && !this.state.copying && !this.props.inactive && this.props.slug !== 'like')? // special-case for likes
|
|
||||||
<NavLink className="icon-button save" title="Save Changes"
|
|
||||||
onClick={this.handleSubmit}
|
|
||||||
to={`/edit/${this.props.slug}/building/${this.props.building_id}.html`}>
|
|
||||||
Save
|
|
||||||
<SaveIcon />
|
|
||||||
</NavLink>
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
{
|
|
||||||
match? (
|
|
||||||
!this.props.inactive?
|
|
||||||
<form action={`/edit/${this.props.slug}/building/${this.props.building_id}.html`}
|
|
||||||
method="GET" onSubmit={this.handleSubmit}>
|
|
||||||
{
|
|
||||||
this.props.slug === 'location'?
|
|
||||||
<InfoBox msg="Text-based address fields are disabled at the moment. We're looking into how best to collect this data." />
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
<ErrorBox msg={this.state.error} />
|
|
||||||
{
|
|
||||||
this.props.fields.map((props) => {
|
|
||||||
switch (props.type) {
|
|
||||||
case 'text':
|
|
||||||
return <TextInput {...props} handleChange={this.handleChange}
|
|
||||||
copying={this.state.copying}
|
|
||||||
toggleCopyAttribute={this.toggleCopyAttribute}
|
|
||||||
copy={this.state.keys_to_copy[props.slug]}
|
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
|
||||||
case 'text_list':
|
|
||||||
return <TextListInput {...props} handleChange={this.handleChange}
|
|
||||||
copying={this.state.copying}
|
|
||||||
toggleCopyAttribute={this.toggleCopyAttribute}
|
|
||||||
copy={this.state.keys_to_copy[props.slug]}
|
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
|
||||||
case 'text_long':
|
|
||||||
return <LongTextInput {...props} handleChange={this.handleChange}
|
|
||||||
copying={this.state.copying}
|
|
||||||
toggleCopyAttribute={this.toggleCopyAttribute}
|
|
||||||
copy={this.state.keys_to_copy[props.slug]}
|
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
|
||||||
case 'number':
|
|
||||||
return <NumberInput {...props} handleChange={this.handleChange}
|
|
||||||
copying={this.state.copying}
|
|
||||||
toggleCopyAttribute={this.toggleCopyAttribute}
|
|
||||||
copy={this.state.keys_to_copy[props.slug]}
|
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
|
||||||
case 'year_estimator':
|
|
||||||
return <YearEstimator {...props} handleChange={this.handleChange}
|
|
||||||
copying={this.state.copying}
|
|
||||||
toggleCopyAttribute={this.toggleCopyAttribute}
|
|
||||||
copy={this.state.keys_to_copy[props.slug]}
|
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
|
||||||
case 'text_multi':
|
|
||||||
return <MultiTextInput {...props} handleChange={this.handleUpdate}
|
|
||||||
copying={this.state.copying}
|
|
||||||
toggleCopyAttribute={this.toggleCopyAttribute}
|
|
||||||
copy={this.state.keys_to_copy[props.slug]}
|
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
|
||||||
case 'checkbox':
|
|
||||||
return <CheckboxInput {...props} handleChange={this.handleCheck}
|
|
||||||
copying={this.state.copying}
|
|
||||||
toggleCopyAttribute={this.toggleCopyAttribute}
|
|
||||||
copy={this.state.keys_to_copy[props.slug]}
|
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
|
||||||
case 'like':
|
|
||||||
return <LikeButton {...props} handleLike={this.handleLike}
|
|
||||||
building_like={buildingLike}
|
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
|
||||||
default:
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
<InfoBox msg="Colouring may take a few seconds - try zooming the map or hitting refresh after saving (we're working on making this smoother)." />
|
|
||||||
{
|
|
||||||
(this.props.slug === 'like')? // special-case for likes
|
|
||||||
null :
|
|
||||||
<div className="buttons-container">
|
|
||||||
<button type="submit" className="btn btn-primary">Save</button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</form>
|
|
||||||
: <form>
|
|
||||||
<InfoBox msg={`We're not collecting data on ${this.props.title.toLowerCase()} yet - check back soon.`} />
|
|
||||||
</form>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const TextInput = (props) => (
|
const TextInput = (props) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
@ -598,9 +239,12 @@ class YearEstimator extends Component<any, any> { // TODO: add proper types
|
|||||||
// TODO handle changes internally, reporting out date_year, date_upper, date_lower
|
// TODO handle changes internally, reporting out date_year, date_upper, date_lower
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<NumberInput {...this.props} handleChange={this.props.handleChange}
|
<NumberInput {...this.props}
|
||||||
|
handleChange={this.props.handleChange}
|
||||||
|
|
||||||
value={this.props.value} key={this.props.slug} />
|
value={this.props.value}
|
||||||
|
key={this.props.slug}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import React from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { Redirect } from 'react-router-dom';
|
||||||
|
|
||||||
import BuildingNotFound from './building-not-found';
|
import BuildingNotFound from './building-not-found';
|
||||||
import ContainerHeader from './container-header';
|
import ContainerHeader from './container-header';
|
||||||
import Sidebar from './sidebar';
|
import Sidebar from './sidebar';
|
||||||
|
import ErrorBox from '../components/error-box';
|
||||||
|
import InfoBox from '../components/info-box';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shared functionality for view/edit forms
|
* Shared functionality for view/edit forms
|
||||||
@ -27,10 +30,27 @@ const withCopyEdit = (WrappedComponent) => {
|
|||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
// create object and spread into state to avoid TS complaining about modifying readonly state
|
||||||
|
let fieldsObj = {};
|
||||||
|
for (const field of props.fields) {
|
||||||
|
fieldsObj[field.slug] = props[field.slug];
|
||||||
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
error: this.props.error || undefined,
|
||||||
|
like: this.props.like || undefined,
|
||||||
copying: false,
|
copying: false,
|
||||||
values_to_copy: {}
|
keys_to_copy: {},
|
||||||
|
...fieldsObj
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
this.toggleCopying = this.toggleCopying.bind(this);
|
this.toggleCopying = this.toggleCopying.bind(this);
|
||||||
this.toggleCopyAttribute = this.toggleCopyAttribute.bind(this);
|
this.toggleCopyAttribute = this.toggleCopyAttribute.bind(this);
|
||||||
}
|
}
|
||||||
@ -49,21 +69,134 @@ const withCopyEdit = (WrappedComponent) => {
|
|||||||
*
|
*
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
*/
|
*/
|
||||||
toggleCopyAttribute(key) {
|
toggleCopyAttribute(key: string) {
|
||||||
const value = this.props.building[key];
|
const keys = this.state.keys_to_copy;
|
||||||
const values = this.state.values_to_copy;
|
if(this.state.keys_to_copy[key]){
|
||||||
if(Object.keys(this.state.values_to_copy).includes(key)){
|
delete keys[key];
|
||||||
delete values[key];
|
|
||||||
} else {
|
} else {
|
||||||
values[key] = value;
|
keys[key] = true;
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
values_to_copy: values
|
keys_to_copy: keys
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
render() {
|
||||||
const data_string = JSON.stringify(this.state.values_to_copy);
|
if (this.state.mode === 'edit' && !this.props.user){
|
||||||
|
return <Redirect to="/sign-up.html" />
|
||||||
|
}
|
||||||
|
|
||||||
|
const values_to_copy = {}
|
||||||
|
for (const key of Object.keys(this.state.keys_to_copy)) {
|
||||||
|
values_to_copy[key] = this.state[key]
|
||||||
|
}
|
||||||
|
const data_string = JSON.stringify(values_to_copy);
|
||||||
const copy = {
|
const copy = {
|
||||||
copying: this.state.copying,
|
copying: this.state.copying,
|
||||||
toggleCopying: this.toggleCopying,
|
toggleCopying: this.toggleCopying,
|
||||||
@ -72,13 +205,54 @@ const withCopyEdit = (WrappedComponent) => {
|
|||||||
}
|
}
|
||||||
return this.props.building?
|
return this.props.building?
|
||||||
<Sidebar>
|
<Sidebar>
|
||||||
<section id={this.props.slug} className="data-section">
|
<section
|
||||||
|
id={this.props.slug}
|
||||||
|
className="data-section">
|
||||||
|
<form
|
||||||
|
action={`/edit/${this.props.slug}/building/${this.props.building_id}.html`}
|
||||||
|
method="POST"
|
||||||
|
onSubmit={this.handleSubmit}>
|
||||||
<ContainerHeader
|
<ContainerHeader
|
||||||
{...this.props}
|
{...this.props}
|
||||||
data_string={data_string}
|
data_string={data_string}
|
||||||
copy={copy}
|
copy={copy}
|
||||||
/>
|
/>
|
||||||
<WrappedComponent {...this.props} copy={copy} />
|
<ErrorBox msg={this.state.error} />
|
||||||
|
{
|
||||||
|
(this.props.mode === 'edit' && this.props.inactive)?
|
||||||
|
<InfoBox
|
||||||
|
msg={`We're not collecting data on ${this.props.title.toLowerCase()} yet - check back soon.`}
|
||||||
|
/>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
<WrappedComponent
|
||||||
|
{...this.props}
|
||||||
|
copy={copy}
|
||||||
|
handleChange={this.handleChange}
|
||||||
|
handleCheck={this.handleCheck}
|
||||||
|
handleLike={this.handleLike}
|
||||||
|
handleUpdate={this.handleUpdate}
|
||||||
|
/>
|
||||||
|
{
|
||||||
|
(this.props.mode === 'edit' && !this.props.inactive)?
|
||||||
|
<Fragment>
|
||||||
|
<InfoBox
|
||||||
|
msg="Colouring may take a few seconds - try zooming the map or hitting refresh after saving (we're working on making this smoother)." />
|
||||||
|
{
|
||||||
|
this.props.slug === 'like'? // special-case for likes
|
||||||
|
null :
|
||||||
|
<div className="buttons-container">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-primary">
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</Fragment>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
: <BuildingNotFound mode="view" />
|
: <BuildingNotFound mode="view" />
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import React from 'react';
|
import React, { Fragment } from 'react';
|
||||||
|
|
||||||
import withCopyEdit from '../data-container';
|
import withCopyEdit from '../data-container';
|
||||||
import DataEntry from '../data-components/data-entry';
|
import DataEntry from '../data-components/data-entry';
|
||||||
import UPRNsDataEntry from '../data-components/uprns-data-entry';
|
import UPRNsDataEntry from '../data-components/uprns-data-entry';
|
||||||
|
import InfoBox from '../../components/info-box';
|
||||||
|
|
||||||
const LocationView = (props) => (
|
const LocationView = (props) => (
|
||||||
|
<Fragment>
|
||||||
|
<InfoBox msg="Text-based address fields are disabled at the moment. We're looking into how best to collect this data." />
|
||||||
<dl className="data-list">
|
<dl className="data-list">
|
||||||
<DataEntry
|
<DataEntry
|
||||||
title="Building Name"
|
title="Building Name"
|
||||||
@ -120,6 +123,7 @@ const LocationView = (props) => (
|
|||||||
// "placeholder": 0
|
// "placeholder": 0
|
||||||
}
|
}
|
||||||
</dl>
|
</dl>
|
||||||
|
</Fragment>
|
||||||
)
|
)
|
||||||
const LocationContainer = withCopyEdit(LocationView);
|
const LocationContainer = withCopyEdit(LocationView);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user