diff --git a/app/src/frontend/app.tsx b/app/src/frontend/app.tsx index 94c2fe3a..f0e8da27 100644 --- a/app/src/frontend/app.tsx +++ b/app/src/frontend/app.tsx @@ -6,7 +6,6 @@ import { parse } from 'query-string'; import '../../node_modules/bootstrap/dist/css/bootstrap.min.css'; import './app.css'; -import BuildingEdit from './building/building-edit'; import BuildingView from './building/building-view'; import ColouringMap from './map/map'; import Header from './header'; diff --git a/app/src/frontend/building/building-view.tsx b/app/src/frontend/building/building-view.tsx index 157469d1..ab953c75 100644 --- a/app/src/frontend/building/building-view.tsx +++ b/app/src/frontend/building/building-view.tsx @@ -1,13 +1,6 @@ -import React, { Fragment } from 'react'; -import { NavLink } from 'react-router-dom'; -import PropTypes from 'prop-types'; - -import Tooltip from '../components/tooltip'; -import { sanitiseURL } from '../helpers'; +import React from 'react'; import BuildingNotFound from './building-not-found'; -import ContainerHeader from './container-header'; -import Sidebar from './sidebar'; import LocationContainer from './data-containers/location'; import UseContainer from './data-containers/use'; @@ -125,244 +118,4 @@ const BuildingView = (props) => { } } -/** - * Shared functionality for view/edit forms - * - * See React Higher-order-component docs for the pattern - * - https://reactjs.org/docs/higher-order-components.html - * - * @param WrappedComponent - */ -function withCopyEdit(WrappedComponent) { - return class extends React.Component { // TODO: add proper types - static propTypes = { // TODO: generate propTypes from TS - title: PropTypes.string, - slug: PropTypes.string, - intro: PropTypes.string, - help: PropTypes.string, - inactive: PropTypes.bool, - building_id: PropTypes.number, - children: PropTypes.node - }; - - constructor(props) { - super(props); - this.state = { - copying: false, - values_to_copy: {} - }; - 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) - * - * @param {string} key - */ - toggleCopyAttribute(key) { - const value = this.props[key]; - const values = this.state.values_to_copy; - if(Object.keys(this.state.values_to_copy).includes(key)){ - delete values[key]; - } else { - values[key] = value; - } - this.setState({ - values_to_copy: values - }) - } - - render() { - const data_string = JSON.stringify(this.state.values_to_copy); - const copy = { - copying: this.state.copying, - toggleCopyAttribute: this.toggleCopyAttribute, - copyingKey: (key) => Object.keys(this.state.values_to_copy).includes(key) - } - return this.props.building? - -
- - -
-
- : - } - } -} - - -const DataEntry: React.FunctionComponent = (props) => { // TODO: remove any - return ( - -
- { props.title } - { props.tooltip? : null } - { (props.copy.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, - cat: PropTypes.string, - slug: PropTypes.string, - tooltip: PropTypes.string, - disabled: PropTypes.bool, - value: PropTypes.any -} - -const LikeDataEntry: React.FunctionComponent = (props) => { // TODO: remove any - const data_string = JSON.stringify({like: true}); - return ( - -
- { 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.user_building_like)?
…including you!
: '' - } -
- ); -} - -LikeDataEntry.propTypes = { - title: PropTypes.string, - cat: PropTypes.string, - tooltip: PropTypes.string, - value: PropTypes.any, - user_building_like: PropTypes.bool -} - -const MultiDataEntry: React.FunctionComponent = (props) => { // TODO: remove any - let content; - - if (props.value && props.value.length) { - content =
    { - props.value.map((item, index) => { - return
  • {item}
  • - }) - }
- } else { - content = '\u00A0' - } - - return ( - -
- { props.title } - { props.tooltip? : null } - { (props.copying && props.cat && props.slug && !props.disabled)? -
- -
- : null - } -
-
{ content }
-
- ); -} - -MultiDataEntry.propTypes = { - title: PropTypes.string, - tooltip: PropTypes.string, - value: PropTypes.arrayOf(PropTypes.string) -} - -const UPRNsDataEntry = (props) => { - const uprns = props.value || []; - const noParent = uprns.filter(uprn => uprn.parent_uprn == null); - const withParent = uprns.filter(uprn => uprn.parent_uprn != null); - - return ( - -
- { props.title } - { props.tooltip? : null } -
-
    - { - noParent.length? - noParent.map(uprn => ( -
  • {uprn.uprn}
  • - )) - : '\u00A0' - }
    - { - withParent.length? -
    - Children - { - withParent.map(uprn => ( -
  • {uprn.uprn} (child of {uprn.parent_uprn})
  • - )) - } -
    - : null - } -
-
- ) -} - -UPRNsDataEntry.propTypes = { - title: PropTypes.string, - tooltip: PropTypes.string, - value: PropTypes.arrayOf(PropTypes.shape({ - uprn: PropTypes.string.isRequired, - parent_uprn: PropTypes.string - })) -} - export default BuildingView; -export { withCopyEdit }; diff --git a/app/src/frontend/building/container-header.tsx b/app/src/frontend/building/container-header.tsx index 6d53fc4e..94b60fd6 100644 --- a/app/src/frontend/building/container-header.tsx +++ b/app/src/frontend/building/container-header.tsx @@ -49,7 +49,7 @@ const ContainerHeader: React.FunctionComponent = (props) => ( + to={`/edit/${props.cat}/building/${props.building.building_id}.html`}> Edit diff --git a/app/src/frontend/building/data-container.tsx b/app/src/frontend/building/data-container.tsx new file mode 100644 index 00000000..ec0c5026 --- /dev/null +++ b/app/src/frontend/building/data-container.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import BuildingNotFound from './building-not-found'; +import ContainerHeader from './container-header'; +import Sidebar from './sidebar'; + +/** + * Shared functionality for view/edit forms + * + * See React Higher-order-component docs for the pattern + * - https://reactjs.org/docs/higher-order-components.html + * + * @param WrappedComponent + */ +const withCopyEdit = (WrappedComponent) => { + return class extends React.Component { // TODO: add proper types + static propTypes = { // TODO: generate propTypes from TS + title: PropTypes.string, + slug: PropTypes.string, + intro: PropTypes.string, + help: PropTypes.string, + inactive: PropTypes.bool, + building_id: PropTypes.number, + children: PropTypes.node + }; + + constructor(props) { + super(props); + this.state = { + copying: false, + values_to_copy: {} + }; + 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) + * + * @param {string} key + */ + toggleCopyAttribute(key) { + const value = this.props.building[key]; + const values = this.state.values_to_copy; + if(Object.keys(this.state.values_to_copy).includes(key)){ + delete values[key]; + } else { + values[key] = value; + } + this.setState({ + values_to_copy: values + }) + } + + render() { + const data_string = JSON.stringify(this.state.values_to_copy); + const copy = { + copying: this.state.copying, + toggleCopying: this.toggleCopying, + toggleCopyAttribute: this.toggleCopyAttribute, + copyingKey: (key) => Object.keys(this.state.values_to_copy).includes(key) + } + return this.props.building? + +
+ + +
+
+ : + } + } +} + +export default withCopyEdit; diff --git a/app/src/frontend/building/data-containers/age.tsx b/app/src/frontend/building/data-containers/age.tsx index 18757f00..4203c2cd 100644 --- a/app/src/frontend/building/data-containers/age.tsx +++ b/app/src/frontend/building/data-containers/age.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Age view/edit section diff --git a/app/src/frontend/building/data-containers/community.tsx b/app/src/frontend/building/data-containers/community.tsx index 4e8b63df..10223ed0 100644 --- a/app/src/frontend/building/data-containers/community.tsx +++ b/app/src/frontend/building/data-containers/community.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Community view/edit section diff --git a/app/src/frontend/building/data-containers/construction.tsx b/app/src/frontend/building/data-containers/construction.tsx index 3ca2d63a..aa2cae0b 100644 --- a/app/src/frontend/building/data-containers/construction.tsx +++ b/app/src/frontend/building/data-containers/construction.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Construction view/edit section diff --git a/app/src/frontend/building/data-containers/greenery.tsx b/app/src/frontend/building/data-containers/greenery.tsx index 8635bb07..a49c7ab2 100644 --- a/app/src/frontend/building/data-containers/greenery.tsx +++ b/app/src/frontend/building/data-containers/greenery.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Greenery view/edit section diff --git a/app/src/frontend/building/data-containers/like.tsx b/app/src/frontend/building/data-containers/like.tsx index 0d292c95..3f6e8439 100644 --- a/app/src/frontend/building/data-containers/like.tsx +++ b/app/src/frontend/building/data-containers/like.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Like view/edit section diff --git a/app/src/frontend/building/data-containers/location.tsx b/app/src/frontend/building/data-containers/location.tsx index c7a68efe..6cc63ded 100644 --- a/app/src/frontend/building/data-containers/location.tsx +++ b/app/src/frontend/building/data-containers/location.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; const LocationView = (props) => (
diff --git a/app/src/frontend/building/data-containers/planning.tsx b/app/src/frontend/building/data-containers/planning.tsx index 4f1f69ae..04c3d481 100644 --- a/app/src/frontend/building/data-containers/planning.tsx +++ b/app/src/frontend/building/data-containers/planning.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Planning view/edit section diff --git a/app/src/frontend/building/data-containers/size.tsx b/app/src/frontend/building/data-containers/size.tsx index bd2edbee..ca0a1032 100644 --- a/app/src/frontend/building/data-containers/size.tsx +++ b/app/src/frontend/building/data-containers/size.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Size view/edit section diff --git a/app/src/frontend/building/data-containers/sustainability.tsx b/app/src/frontend/building/data-containers/sustainability.tsx index 65650c52..ccbad05b 100644 --- a/app/src/frontend/building/data-containers/sustainability.tsx +++ b/app/src/frontend/building/data-containers/sustainability.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Sustainability view/edit section diff --git a/app/src/frontend/building/data-containers/team.tsx b/app/src/frontend/building/data-containers/team.tsx index 1264f953..c86ca8aa 100644 --- a/app/src/frontend/building/data-containers/team.tsx +++ b/app/src/frontend/building/data-containers/team.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Team view/edit section diff --git a/app/src/frontend/building/data-containers/type.tsx b/app/src/frontend/building/data-containers/type.tsx index e122a27c..d4eec296 100644 --- a/app/src/frontend/building/data-containers/type.tsx +++ b/app/src/frontend/building/data-containers/type.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Type view/edit section diff --git a/app/src/frontend/building/data-containers/use.tsx b/app/src/frontend/building/data-containers/use.tsx index a913f580..f5efeaea 100644 --- a/app/src/frontend/building/data-containers/use.tsx +++ b/app/src/frontend/building/data-containers/use.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { withCopyEdit } from '../building-view'; +import withCopyEdit from '../data-container'; +import DataEntry from '../data-components/data-entry'; /** * Use view/edit section