Debug routing, id corner cases

This commit is contained in:
Tom Russell 2018-09-13 23:55:53 +01:00
parent 3baccffd36
commit 853def333e
10 changed files with 103 additions and 61 deletions

View File

@ -61,13 +61,16 @@ class App extends React.Component {
</Route> </Route>
<Route exact path="/map/:map.html" component={Legend} /> <Route exact path="/map/:map.html" component={Legend} />
<Route exact path="/building/:building.html"> <Route exact path="/building/:building.html">
<BuildingView {...this.state.building} <BuildingView
{...this.state.building}
user={this.state.user} user={this.state.user}
selectBuilding={this.selectBuilding} selectBuilding={this.selectBuilding}
/> />
</Route> </Route>
<Route exact path="/building/:building/edit.html"> <Route exact path="/building/:building/edit.html">
<BuildingEdit {...this.state.building} <BuildingEdit
{...this.state.building}
{...props} // includes route history/match
user={this.state.user} user={this.state.user}
selectBuilding={this.selectBuilding} selectBuilding={this.selectBuilding}
/> />
@ -75,7 +78,8 @@ class App extends React.Component {
</Switch> </Switch>
</CSSTransition> </CSSTransition>
</TransitionGroup> </TransitionGroup>
<ColouringMap {...props} <ColouringMap
{...props}
building={this.state.building} building={this.state.building}
selectBuilding={this.selectBuilding} selectBuilding={this.selectBuilding}
/> />

View File

@ -11,6 +11,8 @@ class BuildingEdit extends Component {
const user = props.user || {}; const user = props.user || {};
this.state = { this.state = {
error: undefined, error: undefined,
id: props.id,
geometry_id: props.geometry_id,
location_name: props.location_name, location_name: props.location_name,
location_number: props.location_number, location_number: props.location_number,
location_line_two: props.location_line_two, location_line_two: props.location_line_two,
@ -80,6 +82,7 @@ class BuildingEdit extends Component {
this.setState({error: res.error}) this.setState({error: res.error})
} else { } else {
this.props.selectBuilding(this.state); this.props.selectBuilding(this.state);
this.props.history.push(`/building/${this.props.id}.html`)
} }
}.bind(this)).catch( }.bind(this)).catch(
(err) => this.setState({error: err}) (err) => this.setState({error: err})

View File

@ -1,6 +1,8 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
const ErrorBox = (props) => ( function ErrorBox(props){
console.error(props.msg);
return (
<Fragment> <Fragment>
{ {
(props.msg)? (props.msg)?
@ -16,5 +18,6 @@ const ErrorBox = (props) => (
} }
</Fragment> </Fragment>
); );
}
export default ErrorBox; export default ErrorBox;

View File

@ -1,7 +1,8 @@
/** /**
* Logo * Logo
*/ */
.logo { .logo,
.logo.navbar-brand {
display: block; display: block;
width: 6em; width: 6em;
padding: 0; padding: 0;

View File

@ -50,24 +50,33 @@ class ColouringMap extends Component {
} }
render() { render() {
const data_layer = (
this.props.match && this.props.match.params && this.props.match.params[1]
)? this.props.match.params[1].replace("/", "")
: 'date_year';
const position = [this.state.lat, this.state.lng]; const position = [this.state.lat, this.state.lng];
// baselayer
const key = OS_API_KEY const key = OS_API_KEY
const tilematrixSet = 'EPSG:3857' const tilematrixSet = 'EPSG:3857'
const layer = (this.state.theme === 'light')? 'Light 3857' : 'Night 3857'; const layer = (this.state.theme === 'light')? 'Light 3857' : 'Night 3857';
const url = `https://api2.ordnancesurvey.co.uk/mapping_api/v1/service/zxy/${tilematrixSet}/${layer}/{z}/{x}/{y}.png?key=${key}` const url = `https://api2.ordnancesurvey.co.uk/mapping_api/v1/service/zxy/${tilematrixSet}/${layer}/{z}/{x}/{y}.png?key=${key}`
const attribution = 'Building attribute data is © Colouring London contributors. Maps contain OS data © Crown copyright: OS Maps baselayers and building outlines.' const attribution = 'Building attribute data is © Colouring London contributors. Maps contain OS data © Crown copyright: OS Maps baselayers and building outlines.'
const colour = `/tiles/${data_layer}/{z}/{x}/{y}.png`; // colour-data tiles
var data_tileset, is_building;
if (this.props.match && this.props.match.params && this.props.match.params[1]) {
data_tileset = this.props.match.params[1].replace("/", "")
is_building = this.props.match.params[0] === 'building'
} else {
is_building = false;
data_tileset = 'date_year';
}
const dataLayer = !is_building ? (
<TileLayer key={data_tileset} url={`/tiles/${data_tileset}/{z}/{x}/{y}.png`} />
) : null;
// highlight
const geometry_id = (this.props.building) ? this.props.building.geometry_id : undefined; const geometry_id = (this.props.building) ? this.props.building.geometry_id : undefined;
const highlight = `/tiles/highlight/{z}/{x}/{y}.png?highlight=${geometry_id}` const highlight = `/tiles/highlight/{z}/{x}/{y}.png?highlight=${geometry_id}`
const highlightLayer = this.props.building ? ( const highlightLayer = is_building ? (
<TileLayer key={data_layer} url={highlight} /> <TileLayer key={this.props.building.id} url={highlight} />
) : null; ) : null;
return ( return (
@ -83,7 +92,7 @@ class ColouringMap extends Component {
onClick={this.handleClick} onClick={this.handleClick}
> >
<TileLayer url={url} attribution={attribution} /> <TileLayer url={url} attribution={attribution} />
<TileLayer url={colour} /> { dataLayer }
{ highlightLayer } { highlightLayer }
<ZoomControl position="topright" /> <ZoomControl position="topright" />
<AttributionControl prefix="" /> <AttributionControl prefix="" />

View File

@ -10,6 +10,11 @@
z-index: 1000; z-index: 1000;
overflow-y: auto; overflow-y: auto;
} }
.info-container .h2:first-child {
margin-bottom: 0.5rem;
margin-top: 0.5rem;
margin-left: -0.1em;
}
.leaflet-container .leaflet-control-attribution { .leaflet-container .leaflet-control-attribution {
width: 100%; width: 100%;
height: 3rem; height: 3rem;

View File

@ -9,7 +9,7 @@
@media (min-width: 768px){ @media (min-width: 768px){
main.beta { main.beta {
position: absolute; position: absolute;
top: 117px; /* 32px banner + 82px header + 3px border */ top: 114px; /* 32px banner + 82px header */
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;

View File

@ -15,10 +15,10 @@ function strictParseInt(value) {
function parseBuildingURL(url){ function parseBuildingURL(url){
const re = /^\/building\/(.*)\/edit?.html$/; const re = /^\/building\/([^\/]+)(\/edit)?.html$/;
const matches = re.exec(url); const matches = re.exec(url);
if (matches && matches.length === 2) {
if (matches && matches.length >= 2) {
return strictParseInt(matches[1]) return strictParseInt(matches[1])
} }
return undefined; return undefined;

View File

@ -56,7 +56,9 @@ function render_tile(bbox, table_def, style_def, cb){
const layer = new mapnik.Layer('tile', PROJ4_STRING); const layer = new mapnik.Layer('tile', PROJ4_STRING);
const conf = Object.assign({table: table_def}, DATASOURCE_CONFIG) const conf = Object.assign({table: table_def}, DATASOURCE_CONFIG)
const postgis = new mapnik.Datasource(conf); var postgis;
try {
postgis = new mapnik.Datasource(conf);
layer.datasource = postgis; layer.datasource = postgis;
layer.styles = style_def layer.styles = style_def
@ -64,7 +66,10 @@ function render_tile(bbox, table_def, style_def, cb){
path.join(__dirname, '..', 'map_styles', 'polygon.xml'), path.join(__dirname, '..', 'map_styles', 'polygon.xml'),
{ strict: true }, { strict: true },
function(err, map){ function(err, map){
if (err) throw err if (err) {
console.error(err);
return
}
map.add_layer(layer) map.add_layer(layer)
const im = new mapnik.Image(map.width, map.height) const im = new mapnik.Image(map.width, map.height)
@ -72,6 +77,9 @@ function render_tile(bbox, table_def, style_def, cb){
map.render(im, cb); map.render(im, cb);
} }
) )
} catch(err) {
console.error(err);
}
} }
export { get_bbox, render_tile }; export { get_bbox, render_tile };

View File

@ -1,6 +1,7 @@
import express from 'express'; import express from 'express';
import { get_bbox, render_tile } from './tile'; import { get_bbox, render_tile } from './tile';
import { strictParseInt } from './parse';
// tiles router // tiles router
const router = express.Router() const router = express.Router()
@ -21,8 +22,11 @@ router.get('/outline/:z/:x/:y.png', function(req, res) {
// highlight single geometry // highlight single geometry
router.get('/highlight/:z/:x/:y.png', function(req, res) { router.get('/highlight/:z/:x/:y.png', function(req, res) {
const { highlight } = req.query const { highlight } = req.query
const geometry_id = parseInt(highlight); const geometry_id = strictParseInt(highlight);
if(!geometry_id) res.status(400).send({error:'Bad parameter'}) if(isNaN(geometry_id)){
res.status(400).send({error:'Bad parameter'})
return
}
const bbox = get_bbox(req.params) const bbox = get_bbox(req.params)
const table_def = `( const table_def = `(
SELECT SELECT
@ -54,7 +58,7 @@ router.get('/date_year/:z/:x/:y.png', function(req, res) {
const table_def = `( const table_def = `(
SELECT SELECT
cast( cast(
b.building_doc->>'date_year' NULLIF(b.building_doc->>'date_year', '')
as integer as integer
) as date_year, ) as date_year,
g.geometry_geom g.geometry_geom
@ -80,9 +84,14 @@ router.get('/size_storeys/:z/:x/:y.png', function(req, res) {
const table_def = `( const table_def = `(
SELECT SELECT
cast( cast(
b.building_doc->>'size_storeys' NULLIF(b.building_doc->>'size_attic', '')
as integer as integer
) as size_storeys, ) +
cast(
NULLIF(b.building_doc->>'size_core', '')
as integer
)
as size_storeys,
g.geometry_geom g.geometry_geom
FROM FROM
geometries as g, geometries as g,