Categories everywhere
This commit is contained in:
parent
ca6ba7f217
commit
1a8e035fea
@ -44,7 +44,7 @@ const BuildingView: React.FunctionComponent<BuildingViewProps> = (props) => {
|
|||||||
return <UseContainer
|
return <UseContainer
|
||||||
{...props}
|
{...props}
|
||||||
inactive={false}
|
inactive={false}
|
||||||
title="Land Use"
|
title="Current Use"
|
||||||
intro="How are buildings used, and how does use change over time? Coming soon…"
|
intro="How are buildings used, and how does use change over time? Coming soon…"
|
||||||
help="https://pages.colouring.london/use"
|
help="https://pages.colouring.london/use"
|
||||||
/>;
|
/>;
|
||||||
@ -52,7 +52,7 @@ const BuildingView: React.FunctionComponent<BuildingViewProps> = (props) => {
|
|||||||
return <TypeContainer
|
return <TypeContainer
|
||||||
{...props}
|
{...props}
|
||||||
inactive={false}
|
inactive={false}
|
||||||
title="Type"
|
title="Original Use"
|
||||||
intro="How were buildings previously used?"
|
intro="How were buildings previously used?"
|
||||||
help="https://www.pages.colouring.london/buildingtypology"
|
help="https://www.pages.colouring.london/buildingtypology"
|
||||||
/>;
|
/>;
|
||||||
|
@ -1,25 +1,36 @@
|
|||||||
/**
|
/**
|
||||||
* Data categories
|
* Data categories
|
||||||
*/
|
*/
|
||||||
.data-category-list {
|
.data-category-list {
|
||||||
padding: 0 0 0.75rem;
|
padding: 0px 0 10px 9px;
|
||||||
text-align: center;
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0 0 0 0.2rem;
|
margin: 0;
|
||||||
text-align: center;
|
text-align: left;
|
||||||
|
max-width: 480px;
|
||||||
|
}
|
||||||
|
.navbar .data-category-list {
|
||||||
|
padding: 0px 0 0px 15px;
|
||||||
}
|
}
|
||||||
.data-category-list li {
|
.data-category-list li {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
width: 10rem;
|
width: 110px;
|
||||||
height: 10rem;
|
height: 110px;
|
||||||
margin: 0.375rem;
|
margin: 2px;
|
||||||
box-shadow: 0 0 2px 5px #ffffff;
|
box-shadow: 0 0 2px 3px #ffffff;
|
||||||
transition: box-shadow 0.2s;
|
transition: box-shadow 0.2s;
|
||||||
}
|
}
|
||||||
|
.navbar .data-category-list li {
|
||||||
|
width: 105px;
|
||||||
|
height: 105px;
|
||||||
|
}
|
||||||
|
.data-category-list li:nth-child(4n) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
.data-category-list li:hover {
|
.data-category-list li:hover {
|
||||||
box-shadow: 0 0 2px 5px #00ffff;
|
box-shadow: 0 0 2px 3px #00ffff;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.data-category-list a {
|
.data-category-list a {
|
||||||
color: #222;
|
color: #222;
|
||||||
@ -41,6 +52,6 @@
|
|||||||
|
|
||||||
.data-category-list .category {
|
.data-category-list .category {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.4em;
|
font-size: 1em;
|
||||||
margin: 0 0 0.5em;
|
margin: 0 0 0.5em;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { BackIcon }from '../components/icons';
|
|
||||||
|
|
||||||
interface ContainerHeaderProps {
|
interface ContainerHeaderProps {
|
||||||
cat?: string;
|
cat?: string;
|
||||||
@ -11,9 +8,6 @@ interface ContainerHeaderProps {
|
|||||||
|
|
||||||
const ContainerHeader: React.FunctionComponent<ContainerHeaderProps> = (props) => (
|
const ContainerHeader: React.FunctionComponent<ContainerHeaderProps> = (props) => (
|
||||||
<header className={`section-header view ${props.cat ? props.cat : ''} ${props.cat ? `background-${props.cat}` : ''}`}>
|
<header className={`section-header view ${props.cat ? props.cat : ''} ${props.cat ? `background-${props.cat}` : ''}`}>
|
||||||
<Link className="icon-button back" to={props.backLink}>
|
|
||||||
<BackIcon />
|
|
||||||
</Link>
|
|
||||||
<h2 className="h2">{props.title}</h2>
|
<h2 className="h2">{props.title}</h2>
|
||||||
<nav className="icon-buttons">
|
<nav className="icon-buttons">
|
||||||
{props.children}
|
{props.children}
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
import { parse } from 'query-string';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link, Redirect, RouteComponentProps } from 'react-router-dom';
|
import { Link, Redirect } from 'react-router-dom';
|
||||||
|
|
||||||
import { parseJsonOrDefault } from '../../helpers';
|
import { parseJsonOrDefault } from '../../helpers';
|
||||||
import ErrorBox from '../components/error-box';
|
import ErrorBox from '../components/error-box';
|
||||||
import { BackIcon } from '../components/icons';
|
|
||||||
import InfoBox from '../components/info-box';
|
import InfoBox from '../components/info-box';
|
||||||
import { dataFields } from '../data_fields';
|
import { dataFields } from '../data_fields';
|
||||||
import { User } from '../models/user';
|
import { User } from '../models/user';
|
||||||
|
|
||||||
import DataEntry from './data-components/data-entry';
|
import DataEntry from './data-components/data-entry';
|
||||||
import Sidebar from './sidebar';
|
import Sidebar from './sidebar';
|
||||||
|
import Categories from './categories';
|
||||||
|
|
||||||
interface MultiEditProps {
|
interface MultiEditProps {
|
||||||
user?: User;
|
user?: User;
|
||||||
@ -26,6 +25,7 @@ const MultiEdit: React.FC<MultiEditProps> = (props) => {
|
|||||||
// special case for likes
|
// special case for likes
|
||||||
return (
|
return (
|
||||||
<Sidebar>
|
<Sidebar>
|
||||||
|
<Categories mode={'view'} />
|
||||||
<section className='data-section'>
|
<section className='data-section'>
|
||||||
<header className={`section-header view ${props.category} background-${props.category}`}>
|
<header className={`section-header view ${props.category} background-${props.category}`}>
|
||||||
<h2 className="h2">Like me!</h2>
|
<h2 className="h2">Like me!</h2>
|
||||||
@ -54,39 +54,37 @@ const MultiEdit: React.FC<MultiEditProps> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar>
|
<Sidebar>
|
||||||
|
<Categories mode={'view'} />
|
||||||
<section className='data-section'>
|
<section className='data-section'>
|
||||||
<header className={`section-header view ${props.category} background-${props.category}`}>
|
<header className={`section-header view ${props.category} background-${props.category}`}>
|
||||||
<Link
|
|
||||||
className="icon-button back"
|
|
||||||
to={`/edit/${props.category}`}>
|
|
||||||
<BackIcon />
|
|
||||||
</Link>
|
|
||||||
<h2 className="h2">Copy {props.category} data</h2>
|
<h2 className="h2">Copy {props.category} data</h2>
|
||||||
</header>
|
</header>
|
||||||
<form>
|
<div className="section-body">
|
||||||
|
<form>
|
||||||
{
|
{
|
||||||
error ?
|
error ?
|
||||||
<ErrorBox msg={error} /> :
|
<ErrorBox msg={error} /> :
|
||||||
<InfoBox msg='Click buildings one at a time to colour using the data below' />
|
<InfoBox msg='Click buildings one at a time to colour using the data below' />
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Object.keys(data).map((key => {
|
Object.keys(data).map((key => {
|
||||||
const info = dataFields[key] || {};
|
const info = dataFields[key] || {};
|
||||||
return (
|
return (
|
||||||
<DataEntry
|
<DataEntry
|
||||||
title={info.title || `Unknown field (${key})`}
|
title={info.title || `Unknown field (${key})`}
|
||||||
slug={key}
|
slug={key}
|
||||||
disabled={true}
|
disabled={true}
|
||||||
value={data[key]}
|
value={data[key]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
</form>
|
</form>
|
||||||
<form className='buttons-container'>
|
<form className='buttons-container'>
|
||||||
<Link to={`/view/${props.category}`} className='btn btn-secondary'>Back to view</Link>
|
<Link to={`/view/${props.category}`} className='btn btn-secondary'>Back to view</Link>
|
||||||
<Link to={`/edit/${props.category}`} className='btn btn-secondary'>Back to edit</Link>
|
<Link to={`/edit/${props.category}`} className='btn btn-secondary'>Back to edit</Link>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
);
|
);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 95%;
|
width: 95%;
|
||||||
width: calc(100% - 40px);
|
width: calc(100% - 40px);
|
||||||
|
border-right: 1px solid #000;
|
||||||
z-index: 1001;
|
z-index: 1001;
|
||||||
transition: transform 0.3s;
|
transition: transform 0.3s;
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
@ -49,15 +50,10 @@
|
|||||||
clear: both;
|
clear: both;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #222;
|
color: #222;
|
||||||
padding: 0.75rem 0.25rem 0.5rem 0;
|
padding: 0.75rem 0.25rem 0.5rem 0.75rem;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
}
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
@media (min-width: 990px) {
|
|
||||||
.section-header {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.section-header h2,
|
.section-header h2,
|
||||||
.section-header .icon-buttons {
|
.section-header .icon-buttons {
|
||||||
@ -168,11 +164,11 @@
|
|||||||
/**
|
/**
|
||||||
* Data list sections
|
* Data list sections
|
||||||
*/
|
*/
|
||||||
|
.section-body {
|
||||||
.section-body {
|
margin-top: 0.75em;
|
||||||
margin-top: 0.75em;
|
padding: 0 0.75em 5em 0.75em;
|
||||||
padding: 0 0.75em;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
.data-section .h3 {
|
.data-section .h3 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@ -218,6 +214,10 @@
|
|||||||
.data-section select {
|
.data-section select {
|
||||||
margin: 0 0 0.5em 0;
|
margin: 0 0 0.5em 0;
|
||||||
}
|
}
|
||||||
|
.data-section input[type="checkbox"] {
|
||||||
|
position: static;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
.data-list dd {
|
.data-list dd {
|
||||||
margin: 0 0 0.5rem;
|
margin: 0 0 0.5rem;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
@ -53,6 +53,9 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
border-right: 1px solid #000;
|
border-right: 1px solid #000;
|
||||||
}
|
}
|
||||||
|
.main-header .navbar-collapse > ul:last-child {
|
||||||
|
padding-bottom: 5rem;
|
||||||
|
}
|
||||||
.navbar-collapse.collapse {
|
.navbar-collapse.collapse {
|
||||||
transform: translateY(-100vh);
|
transform: translateY(-100vh);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import './header.css';
|
|||||||
|
|
||||||
import { Logo } from './components/logo';
|
import { Logo } from './components/logo';
|
||||||
import { User } from './models/user';
|
import { User } from './models/user';
|
||||||
|
import Categories from './building/categories';
|
||||||
|
|
||||||
|
|
||||||
interface HeaderProps {
|
interface HeaderProps {
|
||||||
@ -132,6 +133,8 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr />
|
<hr />
|
||||||
|
<Categories mode='view' />
|
||||||
|
<hr />
|
||||||
<ul className="navbar-nav flex-column">
|
<ul className="navbar-nav flex-column">
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<NavLink to="/contact.html" className="nav-link" onClick={this.handleNavigate}>
|
<NavLink to="/contact.html" className="nav-link" onClick={this.handleNavigate}>
|
||||||
|
@ -66,7 +66,7 @@ class MapApp extends React.Component<MapAppProps, MapAppState> {
|
|||||||
async fetchLatestRevision() {
|
async fetchLatestRevision() {
|
||||||
try {
|
try {
|
||||||
const {latestRevisionId} = await apiGet(`/api/buildings/revision`);
|
const {latestRevisionId} = await apiGet(`/api/buildings/revision`);
|
||||||
|
|
||||||
this.increaseRevision(latestRevisionId);
|
this.increaseRevision(latestRevisionId);
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -74,7 +74,7 @@ class MapApp extends React.Component<MapAppProps, MapAppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches building data if a building is selected but no data provided through
|
* Fetches building data if a building is selected but no data provided through
|
||||||
* props (from server-side rendering)
|
* props (from server-side rendering)
|
||||||
*/
|
*/
|
||||||
async fetchBuildingData() {
|
async fetchBuildingData() {
|
||||||
@ -173,13 +173,13 @@ class MapApp extends React.Component<MapAppProps, MapAppState> {
|
|||||||
*/
|
*/
|
||||||
colourBuilding(building: Building) {
|
colourBuilding(building: Building) {
|
||||||
const cat = this.props.match.params.category;
|
const cat = this.props.match.params.category;
|
||||||
|
|
||||||
if (cat === 'like') {
|
if (cat === 'like') {
|
||||||
this.likeBuilding(building.building_id);
|
this.likeBuilding(building.building_id);
|
||||||
} else {
|
} else {
|
||||||
const data = parseJsonOrDefault(this.getMultiEditDataString());
|
const data = parseJsonOrDefault(this.getMultiEditDataString());
|
||||||
|
|
||||||
|
|
||||||
if (data != undefined && !Object.values(data).some(x => x == undefined)) {
|
if (data != undefined && !Object.values(data).some(x => x == undefined)) {
|
||||||
this.updateBuilding(building.building_id, data);
|
this.updateBuilding(building.building_id, data);
|
||||||
}
|
}
|
||||||
@ -240,6 +240,7 @@ class MapApp extends React.Component<MapAppProps, MapAppState> {
|
|||||||
)} />
|
)} />
|
||||||
<Route exact path="/:mode/:cat/:building?">
|
<Route exact path="/:mode/:cat/:building?">
|
||||||
<Sidebar>
|
<Sidebar>
|
||||||
|
<Categories mode={mode || 'view'} building_id={building_id} />
|
||||||
<BuildingView
|
<BuildingView
|
||||||
mode={viewEditMode}
|
mode={viewEditMode}
|
||||||
cat={category}
|
cat={category}
|
||||||
@ -252,11 +253,12 @@ class MapApp extends React.Component<MapAppProps, MapAppState> {
|
|||||||
</Route>
|
</Route>
|
||||||
<Route exact path="/:mode/:cat/:building/history">
|
<Route exact path="/:mode/:cat/:building/history">
|
||||||
<Sidebar>
|
<Sidebar>
|
||||||
|
<Categories mode={mode || 'view'} building_id={building_id} />
|
||||||
<EditHistory building={this.state.building} />
|
<EditHistory building={this.state.building} />
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
</Route>
|
</Route>
|
||||||
<Route exact path="/:mode(view|edit|multi-edit)"
|
<Route exact path="/:mode(view|edit|multi-edit)"
|
||||||
render={props => (<Redirect to={`/${props.match.params.mode}/categories`} />)}
|
render={props => (<Redirect to={`/${props.match.params.mode}/categories`} />)}
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
<ColouringMap
|
<ColouringMap
|
||||||
|
Loading…
Reference in New Issue
Block a user