Lint 4-space indent
This commit is contained in:
parent
907afa29f0
commit
af9c23d883
@ -21,7 +21,8 @@
|
||||
"no-console": "off",
|
||||
"strict": ["error", "global"],
|
||||
"curly": "warn",
|
||||
"quotes": ["warn", "single"]
|
||||
"quotes": ["warn", "single"],
|
||||
"indent": ["warn", 4]
|
||||
},
|
||||
"plugins": [
|
||||
"react"
|
||||
|
@ -11,12 +11,12 @@ import App from './frontend/app';
|
||||
const data = window.__PRELOADED_STATE__;
|
||||
|
||||
hydrate(
|
||||
<BrowserRouter>
|
||||
<App user={data.user} building={data.building} building_like={data.building_like} />
|
||||
</BrowserRouter>,
|
||||
document.getElementById('root')
|
||||
<BrowserRouter>
|
||||
<App user={data.user} building={data.building} building_like={data.building_like} />
|
||||
</BrowserRouter>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.accept();
|
||||
module.hot.accept();
|
||||
}
|
||||
|
@ -5,51 +5,51 @@ import './about.css';
|
||||
|
||||
const AboutPage = () => (
|
||||
<article>
|
||||
<section className="main-col">
|
||||
<h1 className="h2">
|
||||
<section className="main-col">
|
||||
<h1 className="h2">
|
||||
Can you help us capture information on every building in London?
|
||||
</h1>
|
||||
<p>
|
||||
</h1>
|
||||
<p>
|
||||
|
||||
How many buildings are there in London? What are their characteristics? Where
|
||||
are they located and how do they contribute to the city? How adaptable are
|
||||
they? How long will they last, and what are the environmental and
|
||||
socio-economic implications of demolition?
|
||||
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
Colouring London is being designed to address these questions by crowdsourcing
|
||||
and visualising information on London’s buildings. We’re releasing the
|
||||
prototype for testing in the late summer. See the slideshow below for what it
|
||||
will look like.
|
||||
|
||||
</p>
|
||||
<div className="buttons-container btn-center">
|
||||
<a className="btn btn-outline-dark btn-lg" href="#sign-up">Sign up for updates</a>
|
||||
</div>
|
||||
<div className="carousel">
|
||||
<button className="carousel-control offscreen-text back">Back</button>
|
||||
<ul className="carousel-content">
|
||||
<li><img src="images/slide-1-welcome.png" alt="Welcome" /></li>
|
||||
<li><img src="images/slide-2-categories.png" alt="Categories" /></li>
|
||||
<li><img src="images/slide-3-edit.png" alt="Add/edit data" /></li>
|
||||
<li><img src="images/slide-4-view.png" alt="View maps" /></li>
|
||||
<li><img src="images/slide-5-download.png" alt="Download data" /></li>
|
||||
<li><img src="images/slide-6-showcase.png" alt="Showcase" /></li>
|
||||
<li><img src="images/slide-7-partners.png" alt="Partners" /></li>
|
||||
</ul>
|
||||
<button className="carousel-control offscreen-text next">Next</button>
|
||||
</div>
|
||||
<div className="buttons-container btn-center">
|
||||
<a className="btn btn-outline-dark btn-lg"
|
||||
href="files/colouring-london-online-exhibition.pdf">
|
||||
</p>
|
||||
<div className="buttons-container btn-center">
|
||||
<a className="btn btn-outline-dark btn-lg" href="#sign-up">Sign up for updates</a>
|
||||
</div>
|
||||
<div className="carousel">
|
||||
<button className="carousel-control offscreen-text back">Back</button>
|
||||
<ul className="carousel-content">
|
||||
<li><img src="images/slide-1-welcome.png" alt="Welcome" /></li>
|
||||
<li><img src="images/slide-2-categories.png" alt="Categories" /></li>
|
||||
<li><img src="images/slide-3-edit.png" alt="Add/edit data" /></li>
|
||||
<li><img src="images/slide-4-view.png" alt="View maps" /></li>
|
||||
<li><img src="images/slide-5-download.png" alt="Download data" /></li>
|
||||
<li><img src="images/slide-6-showcase.png" alt="Showcase" /></li>
|
||||
<li><img src="images/slide-7-partners.png" alt="Partners" /></li>
|
||||
</ul>
|
||||
<button className="carousel-control offscreen-text next">Next</button>
|
||||
</div>
|
||||
<div className="buttons-container btn-center">
|
||||
<a className="btn btn-outline-dark btn-lg"
|
||||
href="files/colouring-london-online-exhibition.pdf">
|
||||
View online exhibition</a>
|
||||
</div>
|
||||
</section>
|
||||
<hr/>
|
||||
<section className="main-col">
|
||||
<p>
|
||||
</div>
|
||||
</section>
|
||||
<hr/>
|
||||
<section className="main-col">
|
||||
<p>
|
||||
|
||||
Colouring London is being designed and built by the Centre for Advanced Spatial
|
||||
Analysis (CASA), University College London and funded by Historic England.
|
||||
@ -57,159 +57,159 @@ const AboutPage = () => (
|
||||
facilitated by the GLA, and giving access to its API and technical support. It
|
||||
will launch in 2019.
|
||||
|
||||
</p>
|
||||
<SupporterLogos />
|
||||
</section>
|
||||
<hr/>
|
||||
<div className="main-col">
|
||||
<h2 className="h1">Data Categories</h2>
|
||||
<p>
|
||||
</p>
|
||||
<SupporterLogos />
|
||||
</section>
|
||||
<hr/>
|
||||
<div className="main-col">
|
||||
<h2 className="h1">Data Categories</h2>
|
||||
<p>
|
||||
|
||||
12 categories have been chosen in consultation with specialists working in a
|
||||
range of areas, from energy analysis and sustainable urban planning and design
|
||||
to building conservation, community planning, architecture and historical
|
||||
research.
|
||||
|
||||
</p>
|
||||
<ol className="data-category-list">
|
||||
<li className="bold-yellow">
|
||||
<h3 className="category">Location</h3>
|
||||
<p className="description">Where is it?</p>
|
||||
</li>
|
||||
<li className="bright-yellow">
|
||||
<h3 className="category">Use</h3>
|
||||
<p className="description">How is it used?</p>
|
||||
</li>
|
||||
<li className="bold-orange">
|
||||
<h3 className="category">Type</h3>
|
||||
<p className="description">How was it first used?</p>
|
||||
</li>
|
||||
<li className="red">
|
||||
<h3 className="category">Age</h3>
|
||||
<p className="description">When was it built?</p>
|
||||
</li>
|
||||
<li className="pastel-pink">
|
||||
<h3 className="category">Size</h3>
|
||||
<p className="description">How big is it?</p>
|
||||
</li>
|
||||
<li className="pastel-purple">
|
||||
<h3 className="category">Construction</h3>
|
||||
<p className="description">How is it built?</p>
|
||||
</li>
|
||||
<li className="blue-grey">
|
||||
<h3 className="category">Design/Build</h3>
|
||||
<p className="description">Who built it?</p>
|
||||
</li>
|
||||
<li className="bright-green">
|
||||
<h3 className="category">Street Front</h3>
|
||||
<p className="description">How does it relate to the street?</p>
|
||||
</li>
|
||||
<li className="pastel-green">
|
||||
<h3 className="category">Greenery</h3>
|
||||
<p className="description">Is it near a tree or park?</p>
|
||||
</li>
|
||||
<li className="bright-blue">
|
||||
<h3 className="category">Protection</h3>
|
||||
<p className="description">Is it designated?</p>
|
||||
</li>
|
||||
<li className="pale-grey">
|
||||
<h3 className="category">Demolitions</h3>
|
||||
<p className="description">How many rebuilds on the site?</p>
|
||||
</li>
|
||||
<li className="pale-brown">
|
||||
<h3 className="category">Like Me?</h3>
|
||||
<p className="description">Do you like it?</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<hr/>
|
||||
<div className="main-col">
|
||||
<h2 className="h1">Once built, our platform will allow you to:</h2>
|
||||
</div>
|
||||
<section className="pale-pink color-block">
|
||||
</p>
|
||||
<ol className="data-category-list">
|
||||
<li className="bold-yellow">
|
||||
<h3 className="category">Location</h3>
|
||||
<p className="description">Where is it?</p>
|
||||
</li>
|
||||
<li className="bright-yellow">
|
||||
<h3 className="category">Use</h3>
|
||||
<p className="description">How is it used?</p>
|
||||
</li>
|
||||
<li className="bold-orange">
|
||||
<h3 className="category">Type</h3>
|
||||
<p className="description">How was it first used?</p>
|
||||
</li>
|
||||
<li className="red">
|
||||
<h3 className="category">Age</h3>
|
||||
<p className="description">When was it built?</p>
|
||||
</li>
|
||||
<li className="pastel-pink">
|
||||
<h3 className="category">Size</h3>
|
||||
<p className="description">How big is it?</p>
|
||||
</li>
|
||||
<li className="pastel-purple">
|
||||
<h3 className="category">Construction</h3>
|
||||
<p className="description">How is it built?</p>
|
||||
</li>
|
||||
<li className="blue-grey">
|
||||
<h3 className="category">Design/Build</h3>
|
||||
<p className="description">Who built it?</p>
|
||||
</li>
|
||||
<li className="bright-green">
|
||||
<h3 className="category">Street Front</h3>
|
||||
<p className="description">How does it relate to the street?</p>
|
||||
</li>
|
||||
<li className="pastel-green">
|
||||
<h3 className="category">Greenery</h3>
|
||||
<p className="description">Is it near a tree or park?</p>
|
||||
</li>
|
||||
<li className="bright-blue">
|
||||
<h3 className="category">Protection</h3>
|
||||
<p className="description">Is it designated?</p>
|
||||
</li>
|
||||
<li className="pale-grey">
|
||||
<h3 className="category">Demolitions</h3>
|
||||
<p className="description">How many rebuilds on the site?</p>
|
||||
</li>
|
||||
<li className="pale-brown">
|
||||
<h3 className="category">Like Me?</h3>
|
||||
<p className="description">Do you like it?</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<hr/>
|
||||
<div className="main-col">
|
||||
<h3 className="h2">View maps</h3>
|
||||
<p>
|
||||
<h2 className="h1">Once built, our platform will allow you to:</h2>
|
||||
</div>
|
||||
<section className="pale-pink color-block">
|
||||
<div className="main-col">
|
||||
<h3 className="h2">View maps</h3>
|
||||
<p>
|
||||
|
||||
To view the data, navigate to the ‘View Maps’ page and find the category that
|
||||
interests you.
|
||||
|
||||
</p>
|
||||
<img className="border-image" src="images/slide-4-view.png"
|
||||
alt="Preview of view maps page" />
|
||||
</div>
|
||||
</section>
|
||||
<section className="pale-yellow color-block">
|
||||
<div className="main-col">
|
||||
<h3 className="h2">Add and edit data</h3>
|
||||
<p>
|
||||
</p>
|
||||
<img className="border-image" src="images/slide-4-view.png"
|
||||
alt="Preview of view maps page" />
|
||||
</div>
|
||||
</section>
|
||||
<section className="pale-yellow color-block">
|
||||
<div className="main-col">
|
||||
<h3 className="h2">Add and edit data</h3>
|
||||
<p>
|
||||
|
||||
Find a building and add or edit data for any of the 12 core categories.
|
||||
|
||||
</p>
|
||||
<img className="border-image" src="images/slide-3-edit.png"
|
||||
alt="Preview of add/edit data page" />
|
||||
</div>
|
||||
</section>
|
||||
<section className="pale-orange color-block">
|
||||
<div className="main-col">
|
||||
<h3 className="h2">See how people are using our data</h3>
|
||||
<p>
|
||||
</p>
|
||||
<img className="border-image" src="images/slide-3-edit.png"
|
||||
alt="Preview of add/edit data page" />
|
||||
</div>
|
||||
</section>
|
||||
<section className="pale-orange color-block">
|
||||
<div className="main-col">
|
||||
<h3 className="h2">See how people are using our data</h3>
|
||||
<p>
|
||||
|
||||
Find links to visualisations and analysis, art projects and applications
|
||||
relating to the evolution of London, housing, energy, planning, heritage and
|
||||
history—or something we haven’t imagined yet.
|
||||
|
||||
</p>
|
||||
<img className="border-image" src="images/slide-6-showcase.png"
|
||||
alt="Preview of data showcase page" />
|
||||
</div>
|
||||
</section>
|
||||
</p>
|
||||
<img className="border-image" src="images/slide-6-showcase.png"
|
||||
alt="Preview of data showcase page" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="pale-green color-block">
|
||||
<div className="main-col">
|
||||
<h3 className="h2">Download, remix and reuse</h3>
|
||||
<p>
|
||||
<section className="pale-green color-block">
|
||||
<div className="main-col">
|
||||
<h3 className="h2">Download, remix and reuse</h3>
|
||||
<p>
|
||||
|
||||
Access bulk downloads of data created through the project to use and reuse
|
||||
under a liberal open data license. Let us know and we’ll feature showcase
|
||||
projects on the Colouring London site.
|
||||
|
||||
</p>
|
||||
<img className="border-image" src="images/slide-5-download.png"
|
||||
alt="Preview of download page" />
|
||||
</div>
|
||||
</section>
|
||||
</p>
|
||||
<img className="border-image" src="images/slide-5-download.png"
|
||||
alt="Preview of download page" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="main-col">
|
||||
<div className="main-col">
|
||||
|
||||
<form id="sign-up" action="https://tinyletter.com/colouringlondon" method="post"
|
||||
target="popupwindow"
|
||||
onSubmit={function() {window.open(
|
||||
<form id="sign-up" action="https://tinyletter.com/colouringlondon" method="post"
|
||||
target="popupwindow"
|
||||
onSubmit={function() {window.open(
|
||||
'https://tinyletter.com/colouringlondon',
|
||||
'popupwindow',
|
||||
'scrollbars=yes,width=800,height=600'); return true}}>
|
||||
<h3 className="h1">Keep in touch</h3>
|
||||
<p>
|
||||
<h3 className="h1">Keep in touch</h3>
|
||||
<p>
|
||||
|
||||
Receive occasional newsletters about the project as it develops. You can
|
||||
read previous newsletters in our <a
|
||||
href="https://tinyletter.com/colouringlondon/archive">newsletter archive</a>.
|
||||
href="https://tinyletter.com/colouringlondon/archive">newsletter archive</a>.
|
||||
|
||||
</p>
|
||||
<label htmlFor="tlemail">Enter your email address:</label>
|
||||
<input className="form-control" type="email" name="email" id="tlemail" placeholder="name@example.com" />
|
||||
<input type="hidden" value="1" name="embed"/>
|
||||
<small className="form-text text-muted">
|
||||
<a href="https://tinyletter.com">
|
||||
</p>
|
||||
<label htmlFor="tlemail">Enter your email address:</label>
|
||||
<input className="form-control" type="email" name="email" id="tlemail" placeholder="name@example.com" />
|
||||
<input type="hidden" value="1" name="embed"/>
|
||||
<small className="form-text text-muted">
|
||||
<a href="https://tinyletter.com">
|
||||
powered by TinyLetter</a>.
|
||||
We’ll never share your email address.
|
||||
</small>
|
||||
<div className="buttons-container">
|
||||
<input className="btn btn-outline-dark btn-block" type="submit" value="Sign up for updates" />
|
||||
</small>
|
||||
<div className="buttons-container">
|
||||
<input className="btn btn-outline-dark btn-block" type="submit" value="Sign up for updates" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
|
||||
|
@ -59,11 +59,11 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
selectBuilding(building) {
|
||||
// get UPRNs and update
|
||||
// get UPRNs and update
|
||||
fetch(`/building/${building.building_id}/uprns.json`, {
|
||||
method: 'GET',
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'same-origin'
|
||||
}).then(
|
||||
@ -84,7 +84,7 @@ class App extends React.Component {
|
||||
fetch(`/building/${building.building_id}/like.json`, {
|
||||
method: 'GET',
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'same-origin'
|
||||
}).then(
|
||||
@ -114,13 +114,13 @@ class App extends React.Component {
|
||||
<Overview
|
||||
{...props}
|
||||
mode='view' user={this.state.user}
|
||||
/>
|
||||
/>
|
||||
) } />
|
||||
<Route exact path="/edit/:cat.html" render={(props) => (
|
||||
<Overview
|
||||
{...props}
|
||||
mode='edit' user={this.state.user}
|
||||
/>
|
||||
/>
|
||||
) } />
|
||||
<Route exact path="/view/:cat/building/:building.html" render={(props) => (
|
||||
<BuildingView
|
||||
@ -128,7 +128,7 @@ class App extends React.Component {
|
||||
{...this.state.building}
|
||||
user={this.state.user}
|
||||
building_like={this.state.building_like}
|
||||
/>
|
||||
/>
|
||||
) } />
|
||||
<Route exact path="/edit/:cat/building/:building.html" render={(props) => (
|
||||
<BuildingEdit
|
||||
@ -137,7 +137,7 @@ class App extends React.Component {
|
||||
user={this.state.user}
|
||||
building_like={this.state.building_like}
|
||||
selectBuilding={this.selectBuilding}
|
||||
/>
|
||||
/>
|
||||
) } />
|
||||
</Switch>
|
||||
<Switch>
|
||||
@ -146,7 +146,7 @@ class App extends React.Component {
|
||||
{...props}
|
||||
building={this.state.building}
|
||||
selectBuilding={this.selectBuilding}
|
||||
/>
|
||||
/>
|
||||
) } />
|
||||
<Route exact path="/about.html" component={AboutPage} />
|
||||
<Route exact path="/login.html">
|
||||
@ -160,7 +160,7 @@ class App extends React.Component {
|
||||
user={this.state.user}
|
||||
updateUser={this.updateUser}
|
||||
logout={this.logout}
|
||||
/>
|
||||
/>
|
||||
</Route>
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
|
@ -5,13 +5,13 @@ import { MemoryRouter } from 'react-router-dom';
|
||||
import App from './app';
|
||||
|
||||
describe('<App />', () => {
|
||||
test('renders without exploding', () => {
|
||||
const div = document.createElement('div');
|
||||
ReactDOM.render(
|
||||
<MemoryRouter>
|
||||
<App />
|
||||
</MemoryRouter>,
|
||||
div
|
||||
);
|
||||
});
|
||||
test('renders without exploding', () => {
|
||||
const div = document.createElement('div');
|
||||
ReactDOM.render(
|
||||
<MemoryRouter>
|
||||
<App />
|
||||
</MemoryRouter>,
|
||||
div
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -121,7 +121,7 @@ class EditForm extends Component {
|
||||
fetch(`/building/${this.props.building_id}/like.json`, {
|
||||
method: 'POST',
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({like: like})
|
||||
@ -149,7 +149,7 @@ class EditForm extends Component {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(this.state),
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'same-origin'
|
||||
}).then(
|
||||
@ -179,82 +179,82 @@ class EditForm extends Component {
|
||||
<h3 className="h3">{this.props.title}</h3>
|
||||
</NavLink>
|
||||
<nav className="icon-buttons">
|
||||
{
|
||||
this.props.help?
|
||||
<a className="icon-button help" title="Find out more" href={this.props.help}>
|
||||
{
|
||||
this.props.help?
|
||||
<a className="icon-button help" title="Find out more" href={this.props.help}>
|
||||
Info
|
||||
</a>
|
||||
: null
|
||||
}
|
||||
{
|
||||
(match && !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`}>
|
||||
</a>
|
||||
: null
|
||||
}
|
||||
{
|
||||
(match && !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
|
||||
}
|
||||
<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}
|
||||
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}
|
||||
value={this.state[props.slug]} key={props.slug} />
|
||||
case 'text_list':
|
||||
return <TextListInput {...props} handleChange={this.handleChange}
|
||||
case 'text_list':
|
||||
return <TextListInput {...props} handleChange={this.handleChange}
|
||||
value={this.state[props.slug]} key={props.slug} />
|
||||
case 'text_long':
|
||||
return <LongTextInput {...props} handleChange={this.handleChange}
|
||||
case 'text_long':
|
||||
return <LongTextInput {...props} handleChange={this.handleChange}
|
||||
value={this.state[props.slug]} key={props.slug} />
|
||||
case 'number':
|
||||
return <NumberInput {...props} handleChange={this.handleChange}
|
||||
case 'number':
|
||||
return <NumberInput {...props} handleChange={this.handleChange}
|
||||
value={this.state[props.slug]} key={props.slug} />
|
||||
case 'year_estimator':
|
||||
return <YearEstimator {...props} handleChange={this.handleChange}
|
||||
case 'year_estimator':
|
||||
return <YearEstimator {...props} handleChange={this.handleChange}
|
||||
value={this.state[props.slug]} key={props.slug} />
|
||||
case 'text_multi':
|
||||
return <MultiTextInput {...props} handleChange={this.handleUpdate}
|
||||
case 'text_multi':
|
||||
return <MultiTextInput {...props} handleChange={this.handleUpdate}
|
||||
value={this.state[props.slug]} key={props.slug} />
|
||||
case 'checkbox':
|
||||
return <CheckboxInput {...props} handleChange={this.handleCheck}
|
||||
case 'checkbox':
|
||||
return <CheckboxInput {...props} handleChange={this.handleCheck}
|
||||
value={this.state[props.slug]} key={props.slug} />
|
||||
case 'like':
|
||||
return <LikeButton {...props} handleLike={this.handleLike}
|
||||
case 'like':
|
||||
return <LikeButton {...props} handleLike={this.handleLike}
|
||||
building_like={building_like}
|
||||
value={this.state[props.slug]} key={props.slug} />
|
||||
default:
|
||||
return null
|
||||
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)." />
|
||||
<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 collection data on ${this.props.title.toLowerCase()} yet - check back soon.`} /></form>
|
||||
) : null
|
||||
}
|
||||
{
|
||||
(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 collection data on ${this.props.title.toLowerCase()} yet - check back soon.`} /></form>
|
||||
) : null
|
||||
}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@ -270,7 +270,7 @@ const TextInput = (props) => (
|
||||
disabled={props.disabled}
|
||||
placeholder={props.placeholder}
|
||||
onChange={props.handleChange}
|
||||
/>
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
@ -327,30 +327,30 @@ class MultiTextInput extends Component {
|
||||
render() {
|
||||
const values = this.getValues();
|
||||
return (
|
||||
<Fragment>
|
||||
<Label slug={this.props.slug} title={this.props.title} tooltip={this.props.tooltip} />
|
||||
{
|
||||
values.map((item, i) => (
|
||||
<div className="input-group" key={i}>
|
||||
<input className="form-control" type="text"
|
||||
key={`${this.props.slug}-${i}`} name={`${this.props.slug}-${i}`}
|
||||
data-index={i}
|
||||
value={item || ''}
|
||||
placeholder={this.props.placeholder}
|
||||
disabled={this.props.disabled}
|
||||
onChange={this.edit}
|
||||
/>
|
||||
<div className="input-group-append">
|
||||
<button type="button" onClick={this.remove}
|
||||
title="Remove"
|
||||
data-index={i} className="btn btn-outline-dark">✕</button>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
<button type="button" title="Add" onClick={this.add}
|
||||
<Fragment>
|
||||
<Label slug={this.props.slug} title={this.props.title} tooltip={this.props.tooltip} />
|
||||
{
|
||||
values.map((item, i) => (
|
||||
<div className="input-group" key={i}>
|
||||
<input className="form-control" type="text"
|
||||
key={`${this.props.slug}-${i}`} name={`${this.props.slug}-${i}`}
|
||||
data-index={i}
|
||||
value={item || ''}
|
||||
placeholder={this.props.placeholder}
|
||||
disabled={this.props.disabled}
|
||||
onChange={this.edit}
|
||||
/>
|
||||
<div className="input-group-append">
|
||||
<button type="button" onClick={this.remove}
|
||||
title="Remove"
|
||||
data-index={i} className="btn btn-outline-dark">✕</button>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
<button type="button" title="Add" onClick={this.add}
|
||||
className="btn btn-outline-dark">+</button>
|
||||
</Fragment>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -382,7 +382,7 @@ const NumberInput = (props) => (
|
||||
value={props.value || ''}
|
||||
disabled={props.disabled}
|
||||
onChange={props.handleChange}
|
||||
/>
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
@ -403,7 +403,7 @@ class YearEstimator extends Component {
|
||||
render() {
|
||||
return (
|
||||
<NumberInput {...this.props} handleChange={this.props.handleChange}
|
||||
value={this.props.value} key={this.props.slug} />
|
||||
value={this.props.value} key={this.props.slug} />
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -415,7 +415,7 @@ const CheckboxInput = (props) => (
|
||||
checked={!!props.value}
|
||||
disabled={props.disabled}
|
||||
onChange={props.handleChange}
|
||||
/>
|
||||
/>
|
||||
<label htmlFor={props.slug} className="form-check-label">
|
||||
{props.title}
|
||||
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
||||
@ -432,7 +432,7 @@ const LikeButton = (props) => (
|
||||
checked={!!props.building_like}
|
||||
disabled={props.disabled}
|
||||
onChange={props.handleLike}
|
||||
/>
|
||||
/>
|
||||
<label htmlFor={props.slug} className="form-check-label">
|
||||
I like this building and think it contributes to the city!
|
||||
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
||||
|
@ -35,31 +35,31 @@ const BuildingView = (props) => {
|
||||
section_props.fields.map(field_props => {
|
||||
|
||||
switch (field_props.type) {
|
||||
case 'uprn_list':
|
||||
return <UPRNsDataEntry
|
||||
key={field_props.slug}
|
||||
title={field_props.title}
|
||||
value={props.uprns}
|
||||
tooltip={field_props.tooltip} />
|
||||
case 'text_multi':
|
||||
return <MultiDataEntry
|
||||
key={field_props.slug}
|
||||
title={field_props.title}
|
||||
value={props[field_props.slug]}
|
||||
tooltip={field_props.tooltip} />
|
||||
case 'like':
|
||||
return <LikeDataEntry
|
||||
key={field_props.slug}
|
||||
title={field_props.title}
|
||||
value={props[field_props.slug]}
|
||||
user_building_like={props.building_like}
|
||||
tooltip={field_props.tooltip} />
|
||||
default:
|
||||
return <DataEntry
|
||||
key={field_props.slug}
|
||||
title={field_props.title}
|
||||
value={props[field_props.slug]}
|
||||
tooltip={field_props.tooltip} />
|
||||
case 'uprn_list':
|
||||
return <UPRNsDataEntry
|
||||
key={field_props.slug}
|
||||
title={field_props.title}
|
||||
value={props.uprns}
|
||||
tooltip={field_props.tooltip} />
|
||||
case 'text_multi':
|
||||
return <MultiDataEntry
|
||||
key={field_props.slug}
|
||||
title={field_props.title}
|
||||
value={props[field_props.slug]}
|
||||
tooltip={field_props.tooltip} />
|
||||
case 'like':
|
||||
return <LikeDataEntry
|
||||
key={field_props.slug}
|
||||
title={field_props.title}
|
||||
value={props[field_props.slug]}
|
||||
user_building_like={props.building_like}
|
||||
tooltip={field_props.tooltip} />
|
||||
default:
|
||||
return <DataEntry
|
||||
key={field_props.slug}
|
||||
title={field_props.title}
|
||||
value={props[field_props.slug]}
|
||||
tooltip={field_props.tooltip} />
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -84,30 +84,30 @@ const DataSection = (props) => {
|
||||
<h3 className="h3">{props.title}</h3>
|
||||
</NavLink>
|
||||
<nav className="icon-buttons">
|
||||
{
|
||||
props.help?
|
||||
<a className="icon-button help" title="Find out more" href={props.help}>
|
||||
{
|
||||
props.help?
|
||||
<a className="icon-button help" title="Find out more" href={props.help}>
|
||||
Info
|
||||
</a>
|
||||
: null
|
||||
}
|
||||
{
|
||||
!props.inactive?
|
||||
<NavLink className="icon-button edit" title="Edit data"
|
||||
to={`/edit/${props.slug}/building/${props.building_id}.html`}>
|
||||
</a>
|
||||
: null
|
||||
}
|
||||
{
|
||||
!props.inactive?
|
||||
<NavLink className="icon-button edit" title="Edit data"
|
||||
to={`/edit/${props.slug}/building/${props.building_id}.html`}>
|
||||
Edit
|
||||
<EditIcon />
|
||||
</NavLink>
|
||||
: null
|
||||
}
|
||||
<EditIcon />
|
||||
</NavLink>
|
||||
: null
|
||||
}
|
||||
</nav>
|
||||
</header>
|
||||
{
|
||||
match?
|
||||
!props.inactive?
|
||||
<dl className="data-list">{props.children}</dl>
|
||||
: <p className="data-intro">{props.intro}</p>
|
||||
: null
|
||||
<dl className="data-list">{props.children}</dl>
|
||||
: <p className="data-intro">{props.intro}</p>
|
||||
: null
|
||||
}
|
||||
</section>
|
||||
);
|
||||
@ -135,13 +135,13 @@ const LikeDataEntry = (props) => (
|
||||
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
||||
</dt>
|
||||
<dd>
|
||||
{
|
||||
(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'
|
||||
}
|
||||
</dd>
|
||||
{
|
||||
(props.user_building_like)? <dd>…including you!</dd> : null
|
||||
@ -215,33 +215,33 @@ const UPRNsDataEntry = (props) => {
|
||||
const with_parent = uprns.filter(uprn => uprn.parent_uprn != null);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<dt>
|
||||
{ props.title }
|
||||
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
||||
</dt>
|
||||
<dd><ul className="uprn-list">
|
||||
<Fragment>{
|
||||
no_parent.length?
|
||||
no_parent.map(uprn => (
|
||||
<li key={uprn.uprn}>{uprn.uprn}</li>
|
||||
))
|
||||
: '\u00A0'
|
||||
}</Fragment>
|
||||
{
|
||||
with_parent.length?
|
||||
<details>
|
||||
<summary>Children</summary>
|
||||
{
|
||||
with_parent.map(uprn => (
|
||||
<li key={uprn.uprn}>{uprn.uprn} (child of {uprn.parent_uprn})</li>
|
||||
<Fragment>
|
||||
<dt>
|
||||
{ props.title }
|
||||
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
||||
</dt>
|
||||
<dd><ul className="uprn-list">
|
||||
<Fragment>{
|
||||
no_parent.length?
|
||||
no_parent.map(uprn => (
|
||||
<li key={uprn.uprn}>{uprn.uprn}</li>
|
||||
))
|
||||
}
|
||||
</details>
|
||||
: null
|
||||
}
|
||||
</ul></dd>
|
||||
</Fragment>
|
||||
: '\u00A0'
|
||||
}</Fragment>
|
||||
{
|
||||
with_parent.length?
|
||||
<details>
|
||||
<summary>Children</summary>
|
||||
{
|
||||
with_parent.map(uprn => (
|
||||
<li key={uprn.uprn}>{uprn.uprn} (child of {uprn.parent_uprn})</li>
|
||||
))
|
||||
}
|
||||
</details>
|
||||
: null
|
||||
}
|
||||
</ul></dd>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -8,15 +8,15 @@ function ErrorBox(props){
|
||||
<Fragment>
|
||||
{
|
||||
(props.msg)?
|
||||
(
|
||||
<div className="alert alert-danger" role="alert">
|
||||
{
|
||||
(typeof props.msg === 'string' || props.msg instanceof String)?
|
||||
props.msg
|
||||
: 'Unexpected error'
|
||||
}
|
||||
</div>
|
||||
) : null
|
||||
(
|
||||
<div className="alert alert-danger" role="alert">
|
||||
{
|
||||
(typeof props.msg === 'string' || props.msg instanceof String)?
|
||||
props.msg
|
||||
: 'Unexpected error'
|
||||
}
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
|
@ -8,78 +8,96 @@ import './header.css';
|
||||
* Render the main header using a responsive design
|
||||
*/
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {collapseMenu: true};
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {collapseMenu: true};
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
this.setState(state => ({
|
||||
collapseMenu: !state.collapseMenu
|
||||
}));
|
||||
}
|
||||
handleClick() {
|
||||
this.setState(state => ({
|
||||
collapseMenu: !state.collapseMenu
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<header className="main-header">
|
||||
<nav className="navbar navbar-light navbar-expand-md">
|
||||
<span className="navbar-brand">
|
||||
<Logo/>
|
||||
</span>
|
||||
<button className="navbar-toggler navbar-toggler-right" type="button"
|
||||
onClick={this.handleClick} aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div className={this.state.collapseMenu ? 'collapse navbar-collapse' : 'navbar-collapse'}>
|
||||
<ul className="navbar-nav ml-auto">
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://pages.colouring.london">Hello</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://pages.colouring.london/buildingcategories">Data Categories</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<NavLink to="/view/age.html" className="nav-link">View Maps</NavLink>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<NavLink to="/edit/age.html" className="nav-link">Add/Edit Data</NavLink>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://pages.colouring.london/about">More about</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://pages.colouring.london/whoisinvolved">Who’s Involved?</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://discuss.colouring.london">Discuss</a>
|
||||
</li>
|
||||
{
|
||||
this.props.user?
|
||||
(
|
||||
<li className="nav-item">
|
||||
<NavLink to="/my-account.html" className="nav-link">
|
||||
My account (Logged in as {this.props.user.username})
|
||||
</NavLink>
|
||||
</li>
|
||||
):
|
||||
(
|
||||
<Fragment>
|
||||
<li className="nav-item">
|
||||
<NavLink to="/login.html" className="nav-link">Log in</NavLink>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<NavLink to="/sign-up.html" className="nav-link">Sign up</NavLink>
|
||||
</li>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<header className="main-header">
|
||||
<nav className="navbar navbar-light navbar-expand-md">
|
||||
<span className="navbar-brand">
|
||||
<Logo/>
|
||||
</span>
|
||||
<button className="navbar-toggler navbar-toggler-right" type="button"
|
||||
onClick={this.handleClick} aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div className={this.state.collapseMenu ? 'collapse navbar-collapse' : 'navbar-collapse'}>
|
||||
<ul className="navbar-nav ml-auto">
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://pages.colouring.london">
|
||||
Hello
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://pages.colouring.london/buildingcategories">
|
||||
Data Categories
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<NavLink to="/view/age.html" className="nav-link">
|
||||
View Maps
|
||||
</NavLink>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<NavLink to="/edit/age.html" className="nav-link">
|
||||
Add/Edit Data
|
||||
</NavLink>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://pages.colouring.london/about">
|
||||
More about
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://pages.colouring.london/whoisinvolved">
|
||||
Who’s Involved?
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="https://discuss.colouring.london">
|
||||
Discuss
|
||||
</a>
|
||||
</li>
|
||||
{
|
||||
this.props.user?
|
||||
(
|
||||
<li className="nav-item">
|
||||
<NavLink to="/my-account.html" className="nav-link">
|
||||
My account (Logged in as {this.props.user.username})
|
||||
</NavLink>
|
||||
</li>
|
||||
):
|
||||
(
|
||||
<Fragment>
|
||||
<li className="nav-item">
|
||||
<NavLink to="/login.html" className="nav-link">
|
||||
Log in
|
||||
</NavLink>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<NavLink to="/sign-up.html" className="nav-link">
|
||||
Sign up
|
||||
</NavLink>
|
||||
</li>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Header;
|
||||
|
@ -5,7 +5,7 @@ import React from 'react'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faQuestionCircle, faPaintBrush, faInfoCircle, faTimes, faCheck, faCheckDouble,
|
||||
faAngleLeft, faCaretDown } from '@fortawesome/free-solid-svg-icons'
|
||||
faAngleLeft, faCaretDown } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
library.add(
|
||||
faQuestionCircle,
|
||||
|
@ -4,18 +4,18 @@ const InfoBox = (props) => (
|
||||
<Fragment>
|
||||
{
|
||||
(props.msg || props.children)?
|
||||
(
|
||||
<div className="alert alert-info" role="alert">
|
||||
{
|
||||
(typeof props.msg === 'string' || props.msg instanceof String)?
|
||||
props.msg
|
||||
: 'Enjoy the colouring! Usual service should resume shortly.'
|
||||
}
|
||||
{
|
||||
props.children
|
||||
}
|
||||
</div>
|
||||
) : null
|
||||
(
|
||||
<div className="alert alert-info" role="alert">
|
||||
{
|
||||
(typeof props.msg === 'string' || props.msg instanceof String)?
|
||||
props.msg
|
||||
: 'Enjoy the colouring! Usual service should resume shortly.'
|
||||
}
|
||||
{
|
||||
props.children
|
||||
}
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
|
@ -18,46 +18,46 @@ const LEGEND_CONFIG = {
|
||||
age: {
|
||||
title: 'Age',
|
||||
elements: [
|
||||
{ color: '#f0eaba', text: '≥2000' },
|
||||
{ color: '#fae269', text: '1980–2000' },
|
||||
{ color: '#fbaf27', text: '1960–1980' },
|
||||
{ color: '#e6711d', text: '1940–1960' },
|
||||
{ color: '#d73d3a', text: '1920–1940' },
|
||||
{ color: '#ba221c', text: '1900–1920' },
|
||||
{ color: '#bb859b', text: '1880–1900' },
|
||||
{ color: '#8b3654', text: '1860–1880' },
|
||||
{ color: '#8f5385', text: '1840–1860' },
|
||||
{ color: '#56619b', text: '1820–1840' },
|
||||
{ color: '#6793b2', text: '1800–1820' },
|
||||
{ color: '#83c3b3', text: '1780–1800' },
|
||||
{ color: '#adc88f', text: '1760–1780' },
|
||||
{ color: '#83a663', text: '1740–1760' },
|
||||
{ color: '#77852d', text: '1720–1740' },
|
||||
{ color: '#69814e', text: '1700–1720' },
|
||||
{ color: '#d0c291', text: '1680–1700' },
|
||||
{ color: '#918158', text: '1660–1680' },
|
||||
{ color: '#7a5732', text: '<1660' },
|
||||
{ color: '#f0eaba', text: '≥2000' },
|
||||
{ color: '#fae269', text: '1980–2000' },
|
||||
{ color: '#fbaf27', text: '1960–1980' },
|
||||
{ color: '#e6711d', text: '1940–1960' },
|
||||
{ color: '#d73d3a', text: '1920–1940' },
|
||||
{ color: '#ba221c', text: '1900–1920' },
|
||||
{ color: '#bb859b', text: '1880–1900' },
|
||||
{ color: '#8b3654', text: '1860–1880' },
|
||||
{ color: '#8f5385', text: '1840–1860' },
|
||||
{ color: '#56619b', text: '1820–1840' },
|
||||
{ color: '#6793b2', text: '1800–1820' },
|
||||
{ color: '#83c3b3', text: '1780–1800' },
|
||||
{ color: '#adc88f', text: '1760–1780' },
|
||||
{ color: '#83a663', text: '1740–1760' },
|
||||
{ color: '#77852d', text: '1720–1740' },
|
||||
{ color: '#69814e', text: '1700–1720' },
|
||||
{ color: '#d0c291', text: '1680–1700' },
|
||||
{ color: '#918158', text: '1660–1680' },
|
||||
{ color: '#7a5732', text: '<1660' },
|
||||
]
|
||||
},
|
||||
size: {
|
||||
title: 'Number of storeys',
|
||||
elements: [
|
||||
{ color: '#ffffcc', text: '≥40' },
|
||||
{ color: '#fed976', text: '20–39' },
|
||||
{ color: '#fd8d3c', text: '10–19' },
|
||||
{ color: '#e31a1c', text: '6–9' },
|
||||
{ color: '#800026', text: '1–5' },
|
||||
{ color: '#ffffcc', text: '≥40' },
|
||||
{ color: '#fed976', text: '20–39' },
|
||||
{ color: '#fd8d3c', text: '10–19' },
|
||||
{ color: '#e31a1c', text: '6–9' },
|
||||
{ color: '#800026', text: '1–5' },
|
||||
]
|
||||
},
|
||||
like: {
|
||||
title: 'Like Me',
|
||||
elements: [
|
||||
{ color: '#bd0026', text: '👍👍👍 ≥10' },
|
||||
{ color: '#e31a1c', text: '👍👍 5–10' },
|
||||
{ color: '#fc4e2a', text: '👍 4' },
|
||||
{ color: '#fd8d3c', text: '👍 3' },
|
||||
{ color: '#feb24c', text: '👍 2' },
|
||||
{ color: '#fed976', text: '👍 1' },
|
||||
{ color: '#bd0026', text: '👍👍👍 ≥10' },
|
||||
{ color: '#e31a1c', text: '👍👍 5–10' },
|
||||
{ color: '#fc4e2a', text: '👍 4' },
|
||||
{ color: '#fd8d3c', text: '👍 3' },
|
||||
{ color: '#feb24c', text: '👍 2' },
|
||||
{ color: '#fed976', text: '👍 1' },
|
||||
]
|
||||
},
|
||||
use: {
|
||||
@ -87,7 +87,7 @@ const LEGEND_CONFIG = {
|
||||
planning: {
|
||||
title: 'Planning',
|
||||
elements: [
|
||||
{ color: '#73ebaf', text: 'within conservation area' },
|
||||
{ color: '#73ebaf', text: 'within conservation area' },
|
||||
]
|
||||
},
|
||||
demolition: {
|
||||
@ -136,14 +136,14 @@ const Legend = (props) => {
|
||||
}
|
||||
{
|
||||
elements.length?
|
||||
(<ul className="data-legend">
|
||||
{
|
||||
elements.map((data_item) => (
|
||||
<LegendItem {...data_item} key={data_item.color} />
|
||||
))
|
||||
}
|
||||
</ul>)
|
||||
: (<p className="data-intro">Coming soon…</p>)
|
||||
(<ul className="data-legend">
|
||||
{
|
||||
elements.map((data_item) => (
|
||||
<LegendItem {...data_item} key={data_item.color} />
|
||||
))
|
||||
}
|
||||
</ul>)
|
||||
: (<p className="data-intro">Coming soon…</p>)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
@ -37,7 +37,7 @@ class Login extends Component {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(this.state),
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'same-origin'
|
||||
}).then(
|
||||
@ -76,32 +76,32 @@ class Login extends Component {
|
||||
<InfoBox msg="Welcome to Colouring London. You're one of the first people to use the site! ">
|
||||
<br/>Please <a href="https://discuss.colouring.london/">discuss
|
||||
suggestions for improvements</a> and <a
|
||||
href="https://github.com/tomalrussell/colouring-london/issues">
|
||||
href="https://github.com/tomalrussell/colouring-london/issues">
|
||||
report issues or problems</a>.
|
||||
</InfoBox>
|
||||
<ErrorBox msg={this.state.error} />
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<label htmlFor="username">Username*</label>
|
||||
<input name="username" id="username"
|
||||
className="form-control" type="text"
|
||||
value={this.state.username} onChange={this.handleChange}
|
||||
placeholder="not-your-real-name" required
|
||||
/>
|
||||
className="form-control" type="text"
|
||||
value={this.state.username} onChange={this.handleChange}
|
||||
placeholder="not-your-real-name" required
|
||||
/>
|
||||
|
||||
<label htmlFor="password">Password</label>
|
||||
<input name="password" id="password"
|
||||
className="form-control"
|
||||
type={(this.state.show_password)? 'text': 'password'}
|
||||
value={this.state.password} onChange={this.handleChange}
|
||||
required
|
||||
/>
|
||||
className="form-control"
|
||||
type={(this.state.show_password)? 'text': 'password'}
|
||||
value={this.state.password} onChange={this.handleChange}
|
||||
required
|
||||
/>
|
||||
|
||||
<div className="form-check">
|
||||
<input id="show_password" name="show_password"
|
||||
className="form-check-input" type="checkbox"
|
||||
checked={this.state.show_password}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
className="form-check-input" type="checkbox"
|
||||
checked={this.state.show_password}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<label htmlFor="show_password" className="form-check-label">Show password?</label>
|
||||
</div>
|
||||
|
||||
|
@ -126,7 +126,7 @@ class ColouringMap extends Component {
|
||||
zoomControl={false}
|
||||
attributionControl={false}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
>
|
||||
<TileLayer url={url} attribution={attribution} />
|
||||
<TileLayer url={base_layer_url} minZoom={14} />
|
||||
{ dataLayer }
|
||||
@ -143,11 +143,11 @@ class ColouringMap extends Component {
|
||||
}
|
||||
{
|
||||
this.props.match.url !== '/'? (
|
||||
<Fragment>
|
||||
<Legend slug={cat} />
|
||||
<ThemeSwitcher onSubmit={this.themeSwitch} currentTheme={this.state.theme} />
|
||||
<SearchBox onLocate={this.handleLocate} is_building={is_building} />
|
||||
</Fragment>
|
||||
<Fragment>
|
||||
<Legend slug={cat} />
|
||||
<ThemeSwitcher onSubmit={this.themeSwitch} currentTheme={this.state.theme} />
|
||||
<SearchBox onLocate={this.handleLocate} is_building={is_building} />
|
||||
</Fragment>
|
||||
) : null
|
||||
}
|
||||
</Fragment>
|
||||
|
@ -63,7 +63,7 @@ class MyAccountPage extends Component {
|
||||
|
||||
Colouring London is under active development, Please <a href="https://discuss.colouring.london/">discuss
|
||||
suggestions for improvements</a> and <a
|
||||
href="https://github.com/tomalrussell/colouring-london/issues">
|
||||
href="https://github.com/tomalrussell/colouring-london/issues">
|
||||
report issues or problems</a>.
|
||||
|
||||
</p>
|
||||
|
@ -47,37 +47,37 @@ const OverviewSection = (props) => {
|
||||
<nav className="icon-buttons">
|
||||
{
|
||||
props.help?
|
||||
<a className="icon-button help" href={props.help}>
|
||||
<a className="icon-button help" href={props.help}>
|
||||
Info
|
||||
</a>
|
||||
: null
|
||||
</a>
|
||||
: null
|
||||
}
|
||||
{
|
||||
props.mode === 'view'?
|
||||
<NavLink className="icon-button edit" title="Edit data"
|
||||
to={`/edit/${props.slug}.html`}>
|
||||
<NavLink className="icon-button edit" title="Edit data"
|
||||
to={`/edit/${props.slug}.html`}>
|
||||
Edit
|
||||
<EditIcon />
|
||||
</NavLink>
|
||||
: null
|
||||
<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
|
||||
(
|
||||
<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>
|
||||
)
|
||||
|
@ -28,7 +28,7 @@ class SearchBox extends Component {
|
||||
});
|
||||
// If the ‘clear’ icon has been clicked, clear results list as well
|
||||
if(e.target.value === '') {
|
||||
this.clearResults();
|
||||
this.clearResults();
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,41 +79,41 @@ class SearchBox extends Component {
|
||||
})
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error(err)
|
||||
console.error(err)
|
||||
|
||||
this.setState({
|
||||
results: [],
|
||||
fetching: false
|
||||
})
|
||||
this.setState({
|
||||
results: [],
|
||||
fetching: false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const resultsList = this.state.results.length?
|
||||
<ul className="search-box-results">
|
||||
{
|
||||
this.state.results.map((result) => {
|
||||
const label = result.attributes.label;
|
||||
const lng = result.geometry.coordinates[0];
|
||||
const lat = result.geometry.coordinates[1];
|
||||
const zoom = result.attributes.zoom;
|
||||
const href = `?lng=${lng}&lat=${lat}&zoom=${zoom}`
|
||||
return (
|
||||
<li key={result.attributes.label}>
|
||||
<a
|
||||
className="search-box-result"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
this.props.onLocate(lat, lng, zoom);
|
||||
}}
|
||||
href={href}
|
||||
{
|
||||
this.state.results.map((result) => {
|
||||
const label = result.attributes.label;
|
||||
const lng = result.geometry.coordinates[0];
|
||||
const lat = result.geometry.coordinates[1];
|
||||
const zoom = result.attributes.zoom;
|
||||
const href = `?lng=${lng}&lat=${lat}&zoom=${zoom}`
|
||||
return (
|
||||
<li key={result.attributes.label}>
|
||||
<a
|
||||
className="search-box-result"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
this.props.onLocate(lat, lng, zoom);
|
||||
}}
|
||||
href={href}
|
||||
>{`${label.substring(0,4)} ${label.substring(4, 7)}`}</a>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
}
|
||||
</li>
|
||||
)
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
: null;
|
||||
: null;
|
||||
return (
|
||||
<div className={`search-box ${this.props.is_building? 'building' : ''}`} onKeyDown={this.handleKeyPress}>
|
||||
<form action="/search" method="GET" onSubmit={this.search}
|
||||
@ -127,7 +127,7 @@ class SearchBox extends Component {
|
||||
placeholder="Search for a postcode"
|
||||
aria-label="Search for a postcode"
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
/>
|
||||
<button className="btn btn-outline-dark" type="submit">Search</button>
|
||||
</form>
|
||||
{ resultsList }
|
||||
|
@ -12,7 +12,7 @@ const Sidebar = (props) => (
|
||||
<Link className="icon-button back" to={props.back}>
|
||||
<BackIcon />
|
||||
</Link>
|
||||
: null
|
||||
: null
|
||||
}
|
||||
<h2 className="h2">{props.title}</h2>
|
||||
</header>
|
||||
|
@ -40,7 +40,7 @@ class SignUp extends Component {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(this.state),
|
||||
headers:{
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'same-origin'
|
||||
}).then(
|
||||
@ -75,7 +75,7 @@ class SignUp extends Component {
|
||||
<InfoBox msg="Welcome to Colouring London. You're one of the first people to sign up! ">
|
||||
<br/>Please <a href="https://discuss.colouring.london/">discuss
|
||||
suggestions for improvements</a> and <a
|
||||
href="https://github.com/tomalrussell/colouring-london/issues">
|
||||
href="https://github.com/tomalrussell/colouring-london/issues">
|
||||
report issues or problems</a>.
|
||||
</InfoBox>
|
||||
<p>
|
||||
@ -85,38 +85,38 @@ class SignUp extends Component {
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<label htmlFor="username">Username*</label>
|
||||
<input name="username" id="username"
|
||||
className="form-control" type="text"
|
||||
value={this.state.username} onChange={this.handleChange}
|
||||
placeholder="not-your-real-name" required
|
||||
/>
|
||||
className="form-control" type="text"
|
||||
value={this.state.username} onChange={this.handleChange}
|
||||
placeholder="not-your-real-name" required
|
||||
/>
|
||||
|
||||
<label htmlFor="email">Email (optional)</label>
|
||||
<input name="email" id="email"
|
||||
className="form-control" type="email"
|
||||
value={this.state.email} onChange={this.handleChange}
|
||||
placeholder="someone@example.com"
|
||||
/>
|
||||
className="form-control" type="email"
|
||||
value={this.state.email} onChange={this.handleChange}
|
||||
placeholder="someone@example.com"
|
||||
/>
|
||||
|
||||
<label htmlFor="confirm_email">Confirm email (optional)</label>
|
||||
<input name="confirm_email" id="confirm_email"
|
||||
className="form-control" type="email"
|
||||
value={this.state.confirm_email} onChange={this.handleChange}
|
||||
/>
|
||||
className="form-control" type="email"
|
||||
value={this.state.confirm_email} onChange={this.handleChange}
|
||||
/>
|
||||
|
||||
<label htmlFor="password">Password (at least 8 characters)</label>
|
||||
<input name="password" id="password"
|
||||
className="form-control"
|
||||
type={(this.state.show_password)? 'text': 'password'}
|
||||
value={this.state.password} onChange={this.handleChange}
|
||||
required
|
||||
/>
|
||||
className="form-control"
|
||||
type={(this.state.show_password)? 'text': 'password'}
|
||||
value={this.state.password} onChange={this.handleChange}
|
||||
required
|
||||
/>
|
||||
|
||||
<div className="form-check">
|
||||
<input id="show_password" name="show_password"
|
||||
className="form-check-input" type="checkbox"
|
||||
checked={this.state.show_password}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
className="form-check-input" type="checkbox"
|
||||
checked={this.state.show_password}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<label className="form-check-label" htmlFor="show_password">
|
||||
Show password?
|
||||
</label>
|
||||
@ -124,14 +124,14 @@ class SignUp extends Component {
|
||||
|
||||
<div className="form-check">
|
||||
<input id="confirm_conditions" name="confirm_conditions"
|
||||
className="form-check-input" type="checkbox"
|
||||
checked={this.state.confirm_conditions}
|
||||
onChange={this.handleChange}
|
||||
required />
|
||||
className="form-check-input" type="checkbox"
|
||||
checked={this.state.confirm_conditions}
|
||||
onChange={this.handleChange}
|
||||
required />
|
||||
<label className="form-check-label" htmlFor="confirm_conditions">
|
||||
I confirm that I have read and agree to the <a
|
||||
href="/privacy-policy">privacy policy</a> and <a
|
||||
href="/user-agreement">contributor agreement</a>.
|
||||
href="/privacy-policy">privacy policy</a> and <a
|
||||
href="/user-agreement">contributor agreement</a>.
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
@ -5,7 +5,7 @@ import './theme-switcher.css';
|
||||
const ThemeSwitcher = (props) => (
|
||||
<form className={`theme-switcher ${props.currentTheme}`} onSubmit={props.onSubmit}>
|
||||
<button className="btn btn-outline btn-outline-dark"
|
||||
type="submit">
|
||||
type="submit">
|
||||
Switch theme ({(props.currentTheme === 'light')? 'Light' : 'Night'})
|
||||
</button>
|
||||
</form>
|
||||
|
@ -23,20 +23,20 @@ class Tooltip extends Component {
|
||||
return (
|
||||
<div className="tooltip-wrap">
|
||||
<button className={(this.state.active? 'active ': '') + 'tooltip-hint icon-button'}
|
||||
title={this.props.text}
|
||||
onClick={this.handleClick}>
|
||||
title={this.props.text}
|
||||
onClick={this.handleClick}>
|
||||
Hint
|
||||
<InfoIcon />
|
||||
</button>
|
||||
{
|
||||
this.state.active?
|
||||
(
|
||||
<div className="tooltip bs-tooltip-bottom">
|
||||
<div className="arrow"></div>
|
||||
<div className="tooltip-inner">{this.props.text}</div>
|
||||
</div>
|
||||
)
|
||||
: null
|
||||
(
|
||||
<div className="tooltip bs-tooltip-bottom">
|
||||
<div className="arrow"></div>
|
||||
<div className="tooltip-inner">{this.props.text}</div>
|
||||
</div>
|
||||
)
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
@ -12,22 +12,22 @@ const server = http.createServer(app);
|
||||
let currentApp = app;
|
||||
|
||||
server.listen(process.env.PORT || 3000, error => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
console.log('🚀 started');
|
||||
console.log('🚀 started');
|
||||
});
|
||||
|
||||
// In development mode, enable hot module reloading (HMR)
|
||||
if (module.hot) {
|
||||
console.log('✅ Server-side HMR Enabled!');
|
||||
console.log('✅ Server-side HMR Enabled!');
|
||||
|
||||
module.hot.accept('./server', () => {
|
||||
console.log('🔁 HMR Reloading x`./server`...');
|
||||
server.removeListener('request', currentApp);
|
||||
const newApp = require('./server').default;
|
||||
server.on('request', newApp);
|
||||
currentApp = newApp;
|
||||
});
|
||||
module.hot.accept('./server', () => {
|
||||
console.log('🔁 HMR Reloading x`./server`...');
|
||||
server.removeListener('request', currentApp);
|
||||
const newApp = require('./server').default;
|
||||
server.on('request', newApp);
|
||||
currentApp = newApp;
|
||||
});
|
||||
}
|
||||
|
@ -141,15 +141,15 @@ function renderHTML(context, data, req, res) {
|
||||
}
|
||||
</style>
|
||||
${
|
||||
assets.client.css
|
||||
? `<link rel="stylesheet" href="${assets.client.css}">`
|
||||
: ''
|
||||
}
|
||||
assets.client.css
|
||||
? `<link rel="stylesheet" href="${assets.client.css}">`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
process.env.NODE_ENV === 'production'
|
||||
? `<script src="${assets.client.js}" defer></script>`
|
||||
: `<script src="${assets.client.js}" defer crossorigin></script>`
|
||||
}
|
||||
process.env.NODE_ENV === 'production'
|
||||
? `<script src="${assets.client.js}" defer></script>`
|
||||
: `<script src="${assets.client.js}" defer crossorigin></script>`
|
||||
}
|
||||
</head>
|
||||
<body>
|
||||
<div id="root">${markup}</div>
|
||||
|
@ -157,11 +157,11 @@ function cache_location(tileset, z, x, y) {
|
||||
*/
|
||||
function should_try_cache(tileset, z) {
|
||||
if (tileset === 'date_year') {
|
||||
// cache high zoom because of front page hits
|
||||
// cache high zoom because of front page hits
|
||||
return z <= 16
|
||||
}
|
||||
if (tileset === 'base_light' || tileset === 'base_night') {
|
||||
// cache for higher zoom levels (unlikely to change)
|
||||
// cache for higher zoom levels (unlikely to change)
|
||||
return z <= 17
|
||||
}
|
||||
// else cache for lower zoom levels (change slowly)
|
||||
|
@ -138,7 +138,7 @@ function stitch_tile(tileset, z, x, y) {
|
||||
const next_xy = get_xyz(bbox, next_z)
|
||||
|
||||
return Promise.all([
|
||||
// recurse down through zoom levels, using cache if available...
|
||||
// recurse down through zoom levels, using cache if available...
|
||||
load_tile(tileset, next_z, next_xy.minX, next_xy.minY),
|
||||
load_tile(tileset, next_z, next_xy.maxX, next_xy.minY),
|
||||
load_tile(tileset, next_z, next_xy.minX, next_xy.maxY),
|
||||
@ -149,9 +149,9 @@ function stitch_tile(tileset, z, x, y) {
|
||||
bottom_left,
|
||||
bottom_right
|
||||
]) => {
|
||||
// not possible to chain overlays in a single pipeline, but there may still be a better
|
||||
// way to create image buffer here (four tiles resize to one at the next zoom level)
|
||||
// instead of repeatedly creating `sharp` objects, to png, to buffer...
|
||||
// not possible to chain overlays in a single pipeline, but there may still be a better
|
||||
// way to create image buffer here (four tiles resize to one at the next zoom level)
|
||||
// instead of repeatedly creating `sharp` objects, to png, to buffer...
|
||||
return sharp({
|
||||
create: {
|
||||
width: TILE_SIZE * 2,
|
||||
|
Loading…
Reference in New Issue
Block a user