Handle building not found
This commit is contained in:
parent
6c0c1b51c0
commit
9fb4fa052a
@ -31,10 +31,10 @@ function queryBuildingAtPoint(lng, lat) {
|
||||
doc.geometry_id = geometry_id
|
||||
return doc
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
}).catch(function(error){
|
||||
console.error(error);
|
||||
return null;
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
@ -61,10 +61,10 @@ function getBuildingById(id) {
|
||||
doc.geometry_id = geometry_id
|
||||
return doc
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
}).catch(function(error){
|
||||
console.error(error);
|
||||
return null;
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ function saveBuilding(id, building_doc) {
|
||||
[ id, building_doc ]
|
||||
).catch(function(error){
|
||||
console.error(error);
|
||||
return null;
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ const data = window.__PRELOADED_STATE__;
|
||||
|
||||
hydrate(
|
||||
<BrowserRouter>
|
||||
<App user={data.user} />
|
||||
<App user={data.user} building={data.building} />
|
||||
</BrowserRouter>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import { Route, Switch, Link } from 'react-router-dom';
|
||||
|
||||
import AboutPage from './about';
|
||||
import BetaBanner from './beta-banner';
|
||||
@ -96,7 +96,13 @@ class App extends React.Component {
|
||||
const NotFound = () => (
|
||||
<article>
|
||||
<section className="main-col">
|
||||
<h1>Not found…</h1>
|
||||
<h1 class="h1">Page not found</h1>
|
||||
<p className="lead">
|
||||
|
||||
We can't find that one anywhere.
|
||||
|
||||
</p>
|
||||
<Link className="btn btn-outline-dark" to="/">Back home</Link>
|
||||
</section>
|
||||
</article>
|
||||
);
|
||||
|
@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import ErrorBox from './error-box';
|
||||
import InfoBox from './info-box';
|
||||
import Sidebar from './sidebar';
|
||||
|
||||
class BuildingEdit extends Component {
|
||||
@ -86,6 +87,16 @@ class BuildingEdit extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.props.id){
|
||||
return (
|
||||
<Sidebar title="Building Not Found">
|
||||
<InfoBox msg="We can't find that one anywhere - try the map again?" />
|
||||
<div className="buttons-container">
|
||||
<Link to="/map/date_year.html" className="btn btn-secondary">Back to maps</Link>
|
||||
</div>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Sidebar title={`Building ${this.props.id}`}>
|
||||
<form action="building-view.html" method="GET" onSubmit={this.handleSubmit}>
|
||||
|
@ -3,74 +3,87 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
import Sidebar from './sidebar';
|
||||
import Tooltip from './tooltip';
|
||||
import InfoBox from './info-box';
|
||||
|
||||
const BuildingView = (props) => (
|
||||
<Sidebar title={`Building ${props.id}`}>
|
||||
<section className="data-section">
|
||||
<h3 className="h3 bullet-prefix location">Location</h3>
|
||||
<p className="data-intro">
|
||||
const BuildingView = function(props){
|
||||
if (!props.id){
|
||||
return (
|
||||
<Sidebar title="Building Not Found">
|
||||
<InfoBox msg="We can't find that one anywhere - try the map again?" />
|
||||
<div className="buttons-container">
|
||||
<Link to="/map/date_year.html" className="btn btn-secondary">Back to maps</Link>
|
||||
</div>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Sidebar title={`Building ${props.id}`}>
|
||||
<section className="data-section">
|
||||
<h3 className="h3 bullet-prefix location">Location</h3>
|
||||
<p className="data-intro">
|
||||
|
||||
Section introduction of up to roughly 100 characters will take
|
||||
approx­imately this much space.
|
||||
Section introduction of up to roughly 100 characters will take
|
||||
approx­imately this much space.
|
||||
|
||||
<a href="/">Read more</a>.
|
||||
</p>
|
||||
<dl id="data-list-location" className="data-list collapse show">
|
||||
<dt>
|
||||
Building Name
|
||||
<Tooltip text="Hint tooltip content should be ~40 chars." />
|
||||
</dt>
|
||||
<dd>{props.location_name ? props.location_name : '-'}</dd>
|
||||
<dt>Building Number</dt>
|
||||
<dd>{props.location_number ? props.location_number : '-'}</dd>
|
||||
<dt>Street</dt>
|
||||
<dd>{props.location_street ? props.location_street : '-'}</dd>
|
||||
<dt>Address line 2</dt>
|
||||
<dd>{props.location_line_two ? props.location_line_two : '-'}</dd>
|
||||
<dt>Town</dt>
|
||||
<dd>{props.location_town ? props.location_town : '-'}</dd>
|
||||
<dt>Postcode</dt>
|
||||
<dd>{props.location_postcode ? props.location_postcode : '-'}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section className="data-section">
|
||||
<h3 className="h3 bullet-prefix age">Age</h3>
|
||||
<dl className="data-list">
|
||||
<dt>Year built (best estimate)</dt>
|
||||
<dd>{props.date_year? props.date_year : '-'}</dd>
|
||||
<dt>Year built (lower estimate)</dt>
|
||||
<dd>{props.date_lower? props.date_lower : '-'}</dd>
|
||||
<dt>Year built (upper estimate)</dt>
|
||||
<dd>{props.date_upper? props.date_upper : '-'}</dd>
|
||||
<dt>Date Source</dt>
|
||||
<dd>{props.date_source? props.date_source : '-'}</dd>
|
||||
<dt>Facade date</dt>
|
||||
<dd>{props.date_facade? props.date_facade : '-'}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section className="data-section">
|
||||
<h3 className="h3 bullet-prefix size">Size</h3>
|
||||
<dl className="data-list">
|
||||
<dt>Attic storeys</dt>
|
||||
<dd>{props.size_attic? props.size_attic : '-'}</dd>
|
||||
<dt>Core storeys</dt>
|
||||
<dd>{props.size_core? props.size_core : '-'}</dd>
|
||||
<dt>Basement storeys</dt>
|
||||
<dd>{props.size_basement? props.size_basement : '-'}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section className="data-section">
|
||||
<h3 className="h3 bullet-prefix like">Like Me!</h3>
|
||||
<dl className="data-list">
|
||||
<dt>Likes</dt>
|
||||
<dd>{props.likes ? props.likes.length : 0}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<div className="buttons-container">
|
||||
<Link to="/map/date_year.html" className="btn btn-secondary">Back to maps</Link>
|
||||
<Link to={`/building/${props.id}/edit.html`} className="btn btn-primary">Edit data</Link>
|
||||
</div>
|
||||
</Sidebar>
|
||||
);
|
||||
<a href="/">Read more</a>.
|
||||
</p>
|
||||
<dl id="data-list-location" className="data-list collapse show">
|
||||
<dt>
|
||||
Building Name
|
||||
<Tooltip text="Hint tooltip content should be ~40 chars." />
|
||||
</dt>
|
||||
<dd>{props.location_name ? props.location_name : '-'}</dd>
|
||||
<dt>Building Number</dt>
|
||||
<dd>{props.location_number ? props.location_number : '-'}</dd>
|
||||
<dt>Street</dt>
|
||||
<dd>{props.location_street ? props.location_street : '-'}</dd>
|
||||
<dt>Address line 2</dt>
|
||||
<dd>{props.location_line_two ? props.location_line_two : '-'}</dd>
|
||||
<dt>Town</dt>
|
||||
<dd>{props.location_town ? props.location_town : '-'}</dd>
|
||||
<dt>Postcode</dt>
|
||||
<dd>{props.location_postcode ? props.location_postcode : '-'}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section className="data-section">
|
||||
<h3 className="h3 bullet-prefix age">Age</h3>
|
||||
<dl className="data-list">
|
||||
<dt>Year built (best estimate)</dt>
|
||||
<dd>{props.date_year? props.date_year : '-'}</dd>
|
||||
<dt>Year built (lower estimate)</dt>
|
||||
<dd>{props.date_lower? props.date_lower : '-'}</dd>
|
||||
<dt>Year built (upper estimate)</dt>
|
||||
<dd>{props.date_upper? props.date_upper : '-'}</dd>
|
||||
<dt>Date Source</dt>
|
||||
<dd>{props.date_source? props.date_source : '-'}</dd>
|
||||
<dt>Facade date</dt>
|
||||
<dd>{props.date_facade? props.date_facade : '-'}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section className="data-section">
|
||||
<h3 className="h3 bullet-prefix size">Size</h3>
|
||||
<dl className="data-list">
|
||||
<dt>Attic storeys</dt>
|
||||
<dd>{props.size_attic? props.size_attic : '-'}</dd>
|
||||
<dt>Core storeys</dt>
|
||||
<dd>{props.size_core? props.size_core : '-'}</dd>
|
||||
<dt>Basement storeys</dt>
|
||||
<dd>{props.size_basement? props.size_basement : '-'}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section className="data-section">
|
||||
<h3 className="h3 bullet-prefix like">Like Me!</h3>
|
||||
<dl className="data-list">
|
||||
<dt>Likes</dt>
|
||||
<dd>{props.likes ? props.likes.length : 0}</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<div className="buttons-container">
|
||||
<Link to="/map/date_year.html" className="btn btn-secondary">Back to maps</Link>
|
||||
<Link to={`/building/${props.id}/edit.html`} className="btn btn-primary">Edit data</Link>
|
||||
</div>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
|
||||
export default BuildingView;
|
||||
|
20
app/src/frontend/info-box.js
Normal file
20
app/src/frontend/info-box.js
Normal file
@ -0,0 +1,20 @@
|
||||
import React, { Fragment } from 'react';
|
||||
|
||||
const InfoBox = (props) => (
|
||||
<Fragment>
|
||||
{
|
||||
(props.msg)?
|
||||
(
|
||||
<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.'
|
||||
}
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
export default InfoBox;
|
@ -3,8 +3,8 @@ import React from 'react';
|
||||
import './theme-switcher.css';
|
||||
|
||||
const ThemeSwitcher = (props) => (
|
||||
<form class={`theme-switcher ${props.currentTheme}`} onSubmit={props.onSubmit}>
|
||||
<button class="btn btn-outline btn-outline-dark"
|
||||
<form className={`theme-switcher ${props.currentTheme}`} onSubmit={props.onSubmit}>
|
||||
<button className="btn btn-outline btn-outline-dark"
|
||||
type="submit">
|
||||
Switch theme ({(props.currentTheme === 'light')? 'Light' : 'Night'})
|
||||
</button>
|
||||
|
@ -15,10 +15,11 @@ function strictParseInt(value) {
|
||||
|
||||
|
||||
function parseBuildingURL(url){
|
||||
const re = /^\/building\/([1-9][0-9]+).html$/;
|
||||
const re = /^\/building\/(.*)\/edit?.html$/;
|
||||
|
||||
const matches = re.exec(url);
|
||||
if (matches && matches.length === 2) {
|
||||
return parseInt(matches[1])
|
||||
return strictParseInt(matches[1])
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
@ -56,24 +56,33 @@ server.get('/*.html', frontendRoute);
|
||||
server.get('/', frontendRoute);
|
||||
|
||||
function frontendRoute(req, res) {
|
||||
const context = {};
|
||||
const data = {};
|
||||
context.status = 200;
|
||||
|
||||
const building_id = parseBuildingURL(req.url);
|
||||
if (isNaN(building_id)){
|
||||
context.status = 404;
|
||||
}
|
||||
const is_building = (typeof(building_id) !== "undefined")
|
||||
|
||||
|
||||
Promise.all([
|
||||
req.session.user_id? getUserById(req.session.user_id) : undefined,
|
||||
building_id? getBuildingById(building_id) : undefined
|
||||
is_building? getBuildingById(building_id) : undefined
|
||||
]).then(function(values){
|
||||
const user = values[0];
|
||||
const building = values[1];
|
||||
if (is_building && typeof(building) === "undefined"){
|
||||
context.status = 404
|
||||
}
|
||||
data.user = user;
|
||||
data.building = building;
|
||||
renderHTML(data, req, res)
|
||||
renderHTML(context, data, req, res)
|
||||
})
|
||||
}
|
||||
|
||||
function renderHTML(data, req, res){
|
||||
const context = {};
|
||||
function renderHTML(context, data, req, res){
|
||||
const markup = renderToString(
|
||||
<StaticRouter context={context} location={req.url}>
|
||||
<App user={data.user} building={data.building} />
|
||||
@ -83,7 +92,7 @@ function renderHTML(data, req, res){
|
||||
if (context.url) {
|
||||
res.redirect(context.url);
|
||||
} else {
|
||||
res.status(200).send(
|
||||
res.status(context.status).send(
|
||||
`<!doctype html>
|
||||
<html lang="">
|
||||
<head>
|
||||
|
Loading…
Reference in New Issue
Block a user