Declarative categories list

This commit is contained in:
Tom Russell 2019-08-14 11:37:09 +01:00
parent 43f239c853
commit 1c265b828d
7 changed files with 182 additions and 156 deletions

View File

@ -11,7 +11,7 @@ import BuildingView from './building/building-view';
import ColouringMap from './map/map'; import ColouringMap from './map/map';
import Header from './header'; import Header from './header';
import MultiEdit from './building/multi-edit'; import MultiEdit from './building/multi-edit';
import Overview from './building/overview'; import Categories from './building/categories';
import AboutPage from './pages/about'; import AboutPage from './pages/about';
import ContributorAgreementPage from './pages/contributor-agreement'; import ContributorAgreementPage from './pages/contributor-agreement';
@ -195,6 +195,9 @@ class App extends React.Component<any, any> { // TODO: add proper types
} }
render() { render() {
const building_id = (this.state.building)?
this.state.building.building_id
: 2503371 // Default to UCL main building. TODO use last selected if any
return ( return (
<Fragment> <Fragment>
<Header user={this.state.user} /> <Header user={this.state.user} />
@ -203,18 +206,18 @@ class App extends React.Component<any, any> { // TODO: add proper types
<Route exact path="/"> <Route exact path="/">
<Welcome /> <Welcome />
</Route> </Route>
<Route exact path="/view/:cat.html" render={(props) => ( <Route exact path="/view/categories.html">
<Overview <Categories
{...props} mode="view"
mode='view' user={this.state.user} building_id={building_id}
/> />
) } /> </Route>
<Route exact path="/edit/:cat.html" render={(props) => ( <Route exact path="/edit/categories.html">
<Overview <Categories
{...props} mode="edit"
mode='edit' user={this.state.user} building_id={building_id}
/> />
) } /> </Route>
<Route exact path="/multi-edit/:cat.html" render={(props) => ( <Route exact path="/multi-edit/:cat.html" render={(props) => (
<MultiEdit <MultiEdit
{...props} {...props}

View File

@ -0,0 +1,147 @@
import React from 'react';
import { NavLink } from 'react-router-dom';
import PropTypes from 'prop-types';
import Sidebar from './sidebar';
const Categories = (props) => (
<Sidebar>
<Category
title="Location"
slug="location"
help="https://pages.colouring.london/location"
inactive={false}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Land Use"
slug="use"
help="https://pages.colouring.london/use"
inactive={true}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Type"
slug="type"
help="https://pages.colouring.london/buildingtypology"
inactive={true}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Age"
slug="age"
help="https://pages.colouring.london/age"
inactive={false}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Size &amp; Shape"
slug="size"
help="https://pages.colouring.london/shapeandsize"
inactive={false}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Construction"
slug="construction"
help="https://pages.colouring.london/construction"
inactive={true}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Team"
slug="team"
help="https://pages.colouring.london/team"
inactive={true}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Sustainability"
slug="sustainability"
help="https://pages.colouring.london/sustainability"
inactive={true}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Greenery"
slug="greenery"
help="https://pages.colouring.london/greenery"
inactive={true}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Community"
slug="community"
help="https://pages.colouring.london/community"
inactive={false}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Planning"
slug="planning"
help="https://pages.colouring.london/planning"
inactive={true}
mode={props.mode}
building_id={props.building_id}
/>
<Category
title="Like Me!"
slug="like"
help="https://pages.colouring.london/likeme"
inactive={false}
mode={props.mode}
building_id={props.building_id}
/>
</Sidebar>
)
Categories.propTypes = {
mode: PropTypes.string,
building_id: PropTypes.number
}
const Category = (props) => (
<section className={(props.inactive? 'inactive ': '') + 'data-section legend'}>
<header className={`section-header ${props.mode} ${props.slug}`}>
<NavLink
to={`/${props.mode}/${props.slug}/building/${props.building_id}.html`}
title={
(props.inactive)?
'Coming soon… Click the ? for more info.'
: 'Show on map'
}>
<h3 className="h3">{props.title}</h3>
</NavLink>
<nav className="icon-buttons">
{
props.help?
<a className="icon-button help" href={props.help}>
Info
</a>
: null
}
</nav>
</header>
</section>
)
Category.propTypes = {
title: PropTypes.string,
slug: PropTypes.string,
help: PropTypes.string,
inactive: PropTypes.bool,
mode: PropTypes.string,
building_id: PropTypes.number
}
export default Categories;

View File

@ -1,107 +0,0 @@
import React, { Fragment } from 'react';
import { NavLink, Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';
import Sidebar from './sidebar';
import { EditIcon } from '../components/icons';
import CONFIG from './fields-config.json';
const Overview = (props) => {
var dataLayer = 'age'; // always default
if (props.match && props.match.params && props.match.params.cat) {
dataLayer = props.match.params.cat;
}
if (props.mode === 'edit' && !props.user){
return <Redirect to="/sign-up.html" />
}
const title = (props.mode === 'view')? 'View maps' : 'Add or edit data';
const back = (props.mode === 'edit')? `/view/${dataLayer}.html` : undefined;
return (
<Sidebar title={title} back={back}>
{
CONFIG.map((dataGroup) => (
<OverviewSection {...dataGroup}
dataLayer={dataLayer} key={dataGroup.slug} mode={props.mode} />
))
}
</Sidebar>
);
}
Overview.propTypes = {
match: PropTypes.object,
mode: PropTypes.string,
user: PropTypes.object
}
const OverviewSection = (props) => {
const match = props.dataLayer === props.slug;
const inactive = props.inactive;
return (
<section className={(inactive? 'inactive ': '') + 'data-section legend'}>
<header className={`section-header ${props.mode} ${props.slug} ${(match? 'active' : '')}`}>
<NavLink
to={`/${props.mode}/${props.slug}.html`}
isActive={() => match}
title={(inactive)? 'Coming soon… Click the ? for more info.' :
(match)? '' : 'Show on map'}>
<h3 className="h3">{props.title}</h3>
</NavLink>
<nav className="icon-buttons">
{
props.help?
<a className="icon-button help" href={props.help}>
Info
</a>
: null
}
{
props.mode === 'view'?
<NavLink className="icon-button edit" title="Edit data"
to={`/edit/${props.slug}.html`}>
Edit
<EditIcon />
</NavLink>
: null
}
</nav>
</header>
{
(match && props.intro)?
(
<Fragment>
<p className="data-intro">{props.intro}</p>
<ul>
{
props.fields.map((field) => {
return (<li key={field.slug}>{field.title}</li>)
})
}
</ul>
</Fragment>
)
: null
}
</section>
)
};
OverviewSection.propTypes = {
title: PropTypes.string,
slug: PropTypes.string,
intro: PropTypes.string,
help: PropTypes.string,
dataLayer: PropTypes.string,
mode: PropTypes.string,
inactive: PropTypes.bool,
fields: PropTypes.arrayOf(PropTypes.shape({
title: PropTypes.string,
slug: PropTypes.string
}))
}
export default Overview;

View File

@ -53,24 +53,6 @@
/** /**
* Sidebar main header * Sidebar main header
*/ */
.sidebar-header {
border-bottom: 6px solid;
border-image: linear-gradient(
to right,
#edc40b 0%, #edc40b 8.3%,
#f0ee0c 8.3%, #f0ee0c 16.6%,
#ff9100 16.6%, #ff9100 25%,
#ee5f63 25%, #ee5f63 33.3%,
#ee91bf 33.3%, #ee91bf 41.6%,
#aa7fa7 41.6%, #aa7fa7 50%,
#6f879c 50%, #6f879c 58.3%,
#5ec232 58.3%, #5ec232 66.6%,
#6dbb8b 66.6%, #6dbb8b 75%,
#65b7ff 75%, #65b7ff 83.3%,
#a1a3a9 83.3%, #a1a3a9 91.6%,
#9c896d 91.6%, #9c896d 100%
) 1;
}
.sidebar-header h2 { .sidebar-header h2 {
margin: 0.45rem 0 0.6rem; margin: 0.45rem 0 0.6rem;
display: inline-block; display: inline-block;

View File

@ -6,18 +6,24 @@ import './sidebar.css';
import { BackIcon } from '../components/icons'; import { BackIcon } from '../components/icons';
const Sidebar = (props) => ( const Sidebar = (props) => (
<div id="legend" className="info-container"> <div id="sidebar" className="info-container">
<header className="sidebar-header"> {
{ props.title?
props.back? <header className="sidebar-header">
<Link className="icon-button back" to={props.back}> {
<BackIcon /> props.back?
</Link> <Link className="icon-button back" to={props.back}>
: null <BackIcon />
} </Link>
<h2 className="h2">{props.title}</h2> : null
</header> }
{props.children} <h2 className="h2">{props.title}</h2>
</header>
: null
}
{
props.children
}
</div> </div>
); );

View File

@ -51,13 +51,8 @@ class Header extends React.Component<any, any> { // TODO: add proper types
</a> </a>
</li> </li>
<li className="nav-item"> <li className="nav-item">
<NavLink to="/view/age.html" className="nav-link"> <NavLink to="/view/categories.html" className="nav-link">
View Maps View/Edit Maps
</NavLink>
</li>
<li className="nav-item">
<NavLink to="/edit/age.html" className="nav-link">
Add/Edit Data
</NavLink> </NavLink>
</li> </li>
<li className="nav-item"> <li className="nav-item">

View File

@ -17,7 +17,7 @@ const Welcome = () => (
volunteers of all ages and abilities to test and provide feedback on the site as we volunteers of all ages and abilities to test and provide feedback on the site as we
build it. build it.
</p> </p>
<Link to="/view/age.html" <Link to="/view/categories.html"
className="btn btn-outline-dark btn-lg btn-block"> className="btn btn-outline-dark btn-lg btn-block">
Start Colouring Here! Start Colouring Here!
</Link> </Link>