Handle building not found

This commit is contained in:
Tom Russell 2018-09-13 20:41:42 +01:00
parent 6c0c1b51c0
commit 9fb4fa052a
9 changed files with 143 additions and 83 deletions

View File

@ -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;
});
}

View File

@ -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')
);

View File

@ -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&hellip;</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>
);

View File

@ -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}>

View File

@ -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&shy;imately this much space.
Section introduction of up to roughly 100 characters will take
approx&shy;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;

View 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;

View File

@ -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>

View File

@ -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;
}

View File

@ -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>