diff --git a/app/src/frontend/app.js b/app/src/frontend/app.js index 449b7cbd..d03ae0a0 100644 --- a/app/src/frontend/app.js +++ b/app/src/frontend/app.js @@ -61,24 +61,28 @@ class App extends React.Component { - + - + - + ) } /> diff --git a/app/src/frontend/building-edit.js b/app/src/frontend/building-edit.js index 35dbd364..0d954fa9 100644 --- a/app/src/frontend/building-edit.js +++ b/app/src/frontend/building-edit.js @@ -11,6 +11,8 @@ class BuildingEdit extends Component { const user = props.user || {}; this.state = { error: undefined, + id: props.id, + geometry_id: props.geometry_id, location_name: props.location_name, location_number: props.location_number, location_line_two: props.location_line_two, @@ -80,6 +82,7 @@ class BuildingEdit extends Component { this.setState({error: res.error}) } else { this.props.selectBuilding(this.state); + this.props.history.push(`/building/${this.props.id}.html`) } }.bind(this)).catch( (err) => this.setState({error: err}) diff --git a/app/src/frontend/error-box.js b/app/src/frontend/error-box.js index c533016c..87e2382b 100644 --- a/app/src/frontend/error-box.js +++ b/app/src/frontend/error-box.js @@ -1,20 +1,23 @@ import React, { Fragment } from 'react'; -const ErrorBox = (props) => ( - - { - (props.msg)? - ( - - { - (typeof props.msg === 'string' || props.msg instanceof String)? - props.msg - : 'Unexpected error' - } - - ) : null - } - -); +function ErrorBox(props){ + console.error(props.msg); + return ( + + { + (props.msg)? + ( + + { + (typeof props.msg === 'string' || props.msg instanceof String)? + props.msg + : 'Unexpected error' + } + + ) : null + } + + ); +} export default ErrorBox; diff --git a/app/src/frontend/logo.css b/app/src/frontend/logo.css index c6b9e78a..92d29c01 100644 --- a/app/src/frontend/logo.css +++ b/app/src/frontend/logo.css @@ -1,7 +1,8 @@ /** * Logo */ - .logo { +.logo, +.logo.navbar-brand { display: block; width: 6em; padding: 0; diff --git a/app/src/frontend/map.js b/app/src/frontend/map.js index d21cab89..405bee62 100644 --- a/app/src/frontend/map.js +++ b/app/src/frontend/map.js @@ -50,24 +50,33 @@ class ColouringMap extends Component { } 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]; + + // baselayer const key = OS_API_KEY const tilematrixSet = 'EPSG: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 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 ? ( + + ) : null; + // highlight const geometry_id = (this.props.building) ? this.props.building.geometry_id : undefined; const highlight = `/tiles/highlight/{z}/{x}/{y}.png?highlight=${geometry_id}` - const highlightLayer = this.props.building ? ( - + const highlightLayer = is_building ? ( + ) : null; return ( @@ -83,7 +92,7 @@ class ColouringMap extends Component { onClick={this.handleClick} > - + { dataLayer } { highlightLayer } diff --git a/app/src/frontend/sidebar.css b/app/src/frontend/sidebar.css index 8de693e5..f7fe64a0 100644 --- a/app/src/frontend/sidebar.css +++ b/app/src/frontend/sidebar.css @@ -10,6 +10,11 @@ z-index: 1000; 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 { width: 100%; height: 3rem; diff --git a/app/src/frontend/styles/layout.css b/app/src/frontend/styles/layout.css index f6009546..c472dd45 100644 --- a/app/src/frontend/styles/layout.css +++ b/app/src/frontend/styles/layout.css @@ -9,7 +9,7 @@ @media (min-width: 768px){ main.beta { position: absolute; - top: 117px; /* 32px banner + 82px header + 3px border */ + top: 114px; /* 32px banner + 82px header */ bottom: 0; left: 0; right: 0; diff --git a/app/src/parse.js b/app/src/parse.js index 8a47fea1..f8394d31 100644 --- a/app/src/parse.js +++ b/app/src/parse.js @@ -15,10 +15,10 @@ function strictParseInt(value) { function parseBuildingURL(url){ - const re = /^\/building\/(.*)\/edit?.html$/; - + const re = /^\/building\/([^\/]+)(\/edit)?.html$/; const matches = re.exec(url); - if (matches && matches.length === 2) { + + if (matches && matches.length >= 2) { return strictParseInt(matches[1]) } return undefined; diff --git a/app/src/tile.js b/app/src/tile.js index 7653ce0c..e23ffcbe 100644 --- a/app/src/tile.js +++ b/app/src/tile.js @@ -56,22 +56,30 @@ function render_tile(bbox, table_def, style_def, cb){ const layer = new mapnik.Layer('tile', PROJ4_STRING); const conf = Object.assign({table: table_def}, DATASOURCE_CONFIG) - const postgis = new mapnik.Datasource(conf); - layer.datasource = postgis; - layer.styles = style_def + var postgis; + try { + postgis = new mapnik.Datasource(conf); + layer.datasource = postgis; + layer.styles = style_def - map.load( - path.join(__dirname, '..', 'map_styles', 'polygon.xml'), - { strict: true }, - function(err, map){ - if (err) throw err + map.load( + path.join(__dirname, '..', 'map_styles', 'polygon.xml'), + { strict: true }, + function(err, map){ + if (err) { + console.error(err); + return + } - map.add_layer(layer) - const im = new mapnik.Image(map.width, map.height) - map.extent = bbox - map.render(im, cb); - } - ) + map.add_layer(layer) + const im = new mapnik.Image(map.width, map.height) + map.extent = bbox + map.render(im, cb); + } + ) + } catch(err) { + console.error(err); + } } export { get_bbox, render_tile }; diff --git a/app/src/tileserver.js b/app/src/tileserver.js index f8215ebe..b306791e 100644 --- a/app/src/tileserver.js +++ b/app/src/tileserver.js @@ -1,6 +1,7 @@ import express from 'express'; import { get_bbox, render_tile } from './tile'; +import { strictParseInt } from './parse'; // tiles router const router = express.Router() @@ -21,8 +22,11 @@ router.get('/outline/:z/:x/:y.png', function(req, res) { // highlight single geometry router.get('/highlight/:z/:x/:y.png', function(req, res) { const { highlight } = req.query - const geometry_id = parseInt(highlight); - if(!geometry_id) res.status(400).send({error:'Bad parameter'}) + const geometry_id = strictParseInt(highlight); + if(isNaN(geometry_id)){ + res.status(400).send({error:'Bad parameter'}) + return + } const bbox = get_bbox(req.params) const table_def = `( SELECT @@ -54,7 +58,7 @@ router.get('/date_year/:z/:x/:y.png', function(req, res) { const table_def = `( SELECT cast( - b.building_doc->>'date_year' + NULLIF(b.building_doc->>'date_year', '') as integer ) as date_year, g.geometry_geom @@ -80,9 +84,14 @@ router.get('/size_storeys/:z/:x/:y.png', function(req, res) { const table_def = `( SELECT cast( - b.building_doc->>'size_storeys' + NULLIF(b.building_doc->>'size_attic', '') as integer - ) as size_storeys, + ) + + cast( + NULLIF(b.building_doc->>'size_core', '') + as integer + ) + as size_storeys, g.geometry_geom FROM geometries as g,