diff --git a/app/src/frontend/app.js b/app/src/frontend/app.js
index 857ef73f..f23ffc3f 100644
--- a/app/src/frontend/app.js
+++ b/app/src/frontend/app.js
@@ -118,16 +118,22 @@ class App extends React.Component {
});
}
+ /**
+ * Colour building
+ *
+ * Used in multi-edit mode to colour buildings on map click
+ *
+ * Pulls data from URL to form update
+ *
+ * @param {object} building
+ */
colourBuilding(building) {
const cat = parseCategoryURL(window.location.pathname);
const q = parse(window.location.search);
- let data;
+ const data = (cat === 'like')? {like: true}: JSON.parse(q.data);
if (cat === 'like'){
- data = {like: true}
this.likeBuilding(building.building_id)
} else {
- data = {}
- data[q.k] = q.v;
this.updateBuilding(building.building_id, data)
}
}
diff --git a/app/src/frontend/building-edit.js b/app/src/frontend/building-edit.js
index a7925cba..8f61a79e 100644
--- a/app/src/frontend/building-edit.js
+++ b/app/src/frontend/building-edit.js
@@ -50,18 +50,52 @@ BuildingEdit.propTypes = {
class EditForm extends Component {
constructor(props) {
super(props);
- this.state = {}
+ this.state = {
+ error: this.props.error || undefined,
+ like: this.props.like || undefined,
+ copying: false,
+ keys_to_copy: {}
+ }
for (const 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);
+
+ 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
+ })
}
/**
@@ -175,6 +209,12 @@ class EditForm extends Component {
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 (
+ );
+ }
}
DataSection.propTypes = {
@@ -135,30 +205,32 @@ DataSection.propTypes = {
children: PropTypes.node
}
-const DataEntry = (props) => (
-
-
- { props.title }
- { props.tooltip? : null }
- { (props.cat && props.slug && !props.disabled)?
-
-
- Copy
-
-
- : null
- }
-
- {
- (props.value != null && props.value !== '')?
- (typeof(props.value) === 'boolean')?
- (props.value)? 'Yes' : 'No'
- : props.value
- : '\u00A0'}
-
-);
+const DataEntry = (props) => {
+ return (
+
+
+ { props.title }
+ { props.tooltip? : null }
+ { (props.copying && props.cat && props.slug && !props.disabled)?
+
+
+
+ : null
+ }
+
+ {
+ (props.value != null && props.value !== '')?
+ (typeof(props.value) === 'boolean')?
+ (props.value)? 'Yes' : 'No'
+ : props.value
+ : '\u00A0'}
+
+ );
+}
DataEntry.propTypes = {
title: PropTypes.string,
@@ -169,33 +241,36 @@ DataEntry.propTypes = {
value: PropTypes.any
}
-const LikeDataEntry = (props) => (
-
-
- { props.title }
- { props.tooltip? : null }
-
-
- Copy
-
-
-
-
+const LikeDataEntry = (props) => {
+ const data_string = JSON.stringify({like: true});
+ (
+
+
+ { props.title }
+ { props.tooltip? : null }
+
+
+ Copy
+
+
+
+
+ {
+ (props.value != null)?
+ (props.value === 1)?
+ `${props.value} person likes this building`
+ : `${props.value} people like this building`
+ : '\u00A0'
+ }
+
{
- (props.value != null)?
- (props.value === 1)?
- `${props.value} person likes this building`
- : `${props.value} people like this building`
- : '\u00A0'
+ (props.user_building_like)? …including you! : null
}
-
- {
- (props.user_building_like)? …including you! : null
- }
-
-);
+
+ );
+}
LikeDataEntry.propTypes = {
title: PropTypes.string,
@@ -223,6 +298,16 @@ const MultiDataEntry = (props) => {
{ props.title }
{ props.tooltip? : null }
+ { (props.copying && props.cat && props.slug && !props.disabled)?
+
+
+
+ : null
+ }
{ content }
@@ -235,42 +320,6 @@ MultiDataEntry.propTypes = {
value: PropTypes.arrayOf(PropTypes.string)
}
-function sanitiseURL(string){
- let url_
-
- // http or https
- if (!(string.substring(0, 7) === 'http://' || string.substring(0, 8) === 'https://')){
- return null
- }
-
- try {
- url_ = document.createElement('a')
- url_.href = string
- } catch (error) {
- try {
- url_ = urlapi.parse(string)
- } catch (error) {
- return null
- }
- }
-
- // required (www.example.com)
- if (!url_.hostname || url_.hostname === '' || url_.hostname === 'localhost'){
- return null
- }
-
- // optional (/some/path)
- // url_.pathname;
-
- // optional (?name=value)
- // url_.search;
-
- // optional (#anchor)
- // url_.hash;
-
- return `${url_.protocol}//${url_.hostname}${url_.pathname || ''}${url_.search || ''}${url_.hash || ''}`
-}
-
const UPRNsDataEntry = (props) => {
const uprns = props.value || [];
const noParent = uprns.filter(uprn => uprn.parent_uprn == null);
diff --git a/app/src/frontend/helpers.js b/app/src/frontend/helpers.js
new file mode 100644
index 00000000..b4a5d45c
--- /dev/null
+++ b/app/src/frontend/helpers.js
@@ -0,0 +1,39 @@
+import urlapi from 'url';
+
+function sanitiseURL(string){
+ let url_
+
+ // http or https
+ if (!(string.substring(0, 7) === 'http://' || string.substring(0, 8) === 'https://')){
+ return null
+ }
+
+ try {
+ url_ = document.createElement('a')
+ url_.href = string
+ } catch (error) {
+ try {
+ url_ = urlapi.parse(string)
+ } catch (error) {
+ return null
+ }
+ }
+
+ // required (www.example.com)
+ if (!url_.hostname || url_.hostname === '' || url_.hostname === 'localhost'){
+ return null
+ }
+
+ // optional (/some/path)
+ // url_.pathname;
+
+ // optional (?name=value)
+ // url_.search;
+
+ // optional (#anchor)
+ // url_.hash;
+
+ return `${url_.protocol}//${url_.hostname}${url_.pathname || ''}${url_.search || ''}${url_.hash || ''}`
+}
+
+export { sanitiseURL }
diff --git a/app/src/frontend/multi-edit.js b/app/src/frontend/multi-edit.js
index ab592533..c4f2e0e5 100644
--- a/app/src/frontend/multi-edit.js
+++ b/app/src/frontend/multi-edit.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Fragment } from 'react';
import { Link, Redirect } from 'react-router-dom';
import { parse } from 'query-string';
import PropTypes from 'prop-types';
@@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
import Sidebar from './sidebar';
import CONFIG from './fields-config.json';
import InfoBox from './info-box';
+import { sanitiseURL } from './helpers';
const MultiEdit = (props) => {
if (!props.user){
@@ -34,7 +35,7 @@ const MultiEdit = (props) => {
}
const q = parse(props.location.search);
- const label = fieldTitleFromSlug(q.k);
+ const data = JSON.parse(q.data)
const title = sectionTitleFromCat(cat);
return (
{
- Set {label} to {q.v}
+
+ {
+ Object.keys(data).map((key => {
+ const label = fieldTitleFromSlug(key);
+ return
+ }))
+ }
+