diff --git a/src/components/Map.jsx b/src/components/Map.jsx index 1c37b53..c8c0a4e 100644 --- a/src/components/Map.jsx +++ b/src/components/Map.jsx @@ -10,6 +10,7 @@ import 'leaflet'; import { isNotNullNorUndefined } from '../js/utilities'; import MapSites from './MapSites.jsx'; +import MapShapes from './MapShapes.jsx'; import MapEvents from './MapEvents.jsx'; import MapSelectedEvents from './MapSelectedEvents.jsx'; import MapNarratives from './MapNarratives.jsx'; @@ -147,6 +148,17 @@ class Map extends React.Component { ); } + renderShapes() { + return ( + + ) + } + renderNarratives() { return ( + {this.renderTiles()} + {this.renderMarkers()} + {isShowingSites ? this.renderSites() : null} + {this.renderShapes()} + {this.renderEvents()} + {this.renderNarratives()} + {this.renderSelected()} + + ) : null return (
- {(this.map !== null) ? this.renderTiles() : ''} - {(this.map !== null) ? this.renderMarkers() : ''} - {(this.map !== null) && isShowingSites ? this.renderSites() : ''} - {(this.map !== null) ? this.renderEvents() : ''} - {(this.map !== null) ? this.renderNarratives() : ''} - {(this.map !== null) ? this.renderSelected() : ''} + {innerMap}
); } @@ -244,7 +262,8 @@ function mapStateToProps(state) { locations: selectors.selectLocations(state), narratives: selectors.selectNarratives(state), categories: selectors.selectCategories(state), - sites: selectors.getSites(state) + sites: selectors.getSites(state), + shapes: selectors.getShapes(state) }, app: { views: state.app.filters.views, diff --git a/src/components/MapShapes.jsx b/src/components/MapShapes.jsx new file mode 100644 index 0000000..19a842c --- /dev/null +++ b/src/components/MapShapes.jsx @@ -0,0 +1,33 @@ +import React from 'react'; + +function MapShapes({ map, shapes, mapTransformX, mapTransformY }) { + function projectPoint(location) { + const latLng = new L.LatLng(location[0], location[1]); + return { + x: map.latLngToLayerPoint(latLng).x + mapTransformX, + y: map.latLngToLayerPoint(latLng).y + mapTransformY + }; + } + + function renderShape(shape) { + const coords = shape.points.map(projectPoint) + return coords.map(pt => ( +
+ {shape.name} +
+ )); + } + + if (!shapes || !shapes.length) return null; + + return ( +
+ {shapes.map(renderShape)} +
+ ) + +} + +export default MapShapes; diff --git a/src/components/MapSites.jsx b/src/components/MapSites.jsx index 16d4a92..948d883 100644 --- a/src/components/MapSites.jsx +++ b/src/components/MapSites.jsx @@ -1,36 +1,33 @@ import React from 'react'; -class MapSites extends React.Component { - - projectPoint(location) { +function MapSites({ map, sites, mapTransformX, mapTransformY }) { + function projectPoint(location) { const latLng = new L.LatLng(location[0], location[1]); return { - x: this.props.map.latLngToLayerPoint(latLng).x + this.props.mapTransformX, - y: this.props.map.latLngToLayerPoint(latLng).y + this.props.mapTransformY + x: map.latLngToLayerPoint(latLng).x + mapTransformX, + y: map.latLngToLayerPoint(latLng).y + mapTransformY }; } - renderSite(site) { - const { x, y } = this.projectPoint([site.latitude, site.longitude]); + function renderSite(site) { + const { x, y } = projectPoint([site.latitude, site.longitude]); return (
- {site.site} -
+ className="leaflet-tooltip site-label leaflet-zoom-animated leaflet-tooltip-top" + style={{ opacity: 1, transform: `translate3d(calc(${x}px - 50%), ${y - 25}px, 0px)`}}> + {site.site} +
); } - render () { - if (!this.props.sites || !this.props.sites.length) return
; + if (!sites || !sites.length) return null; - return ( -
- {this.props.sites.map(site => { return this.renderSite(site); })} -
- ) - } + return ( +
+ {sites.map(renderSite)} +
+ ) } -export default MapSites; \ No newline at end of file +export default MapSites; diff --git a/src/reducers/utils/validators.js b/src/reducers/utils/validators.js index 057d048..cbd13fd 100644 --- a/src/reducers/utils/validators.js +++ b/src/reducers/utils/validators.js @@ -119,19 +119,14 @@ export function validateDomain (domain) { validateObject(domain.sources, 'sources', sourceSchema) validateObject(domain.shapes, 'shapes', shapeSchema) - sanitizedDomain.shapes = sanitizedDomain.shapes.map(shape => { - const points = shape.items.map(coords => { - const _coords = coords.replace(/\s/g, '').split(',') - return { - lat: parseFloat(_coords[0]), - lon: parseFloat(_coords[1]) - } - }) - return { + // NB: [lat, lon] array is best format for projecting into map + sanitizedDomain.shapes = sanitizedDomain.shapes.map(shape => ({ name: shape.name, - points - } - }) + points: shape.items.map(coords => ( + coords.replace(/\s/g, '').split(',') + )) + }) + ) // Message the number of failed items in domain Object.keys(discardedDomain).forEach(disc => { diff --git a/src/scss/map.scss b/src/scss/map.scss index a1d90b2..5d47661 100644 --- a/src/scss/map.scss +++ b/src/scss/map.scss @@ -65,14 +65,14 @@ } } - .sites-layer { + .sites-layer, .shapes-layer { position: fixed; top: 0px; left: 110px; } &.narrative-mode { - .sites-layer { + .sites-layer, .shapes-layer { position: fixed; top: 0px; left: 0px; diff --git a/src/selectors/index.js b/src/selectors/index.js index 53cae3f..e9dfab2 100644 --- a/src/selectors/index.js +++ b/src/selectors/index.js @@ -15,6 +15,10 @@ export const getSites = (state) => { } export const getSources = state => { if (process.env.features.USE_SOURCES) return state.domain.sources + return {} +} +export const getShapes = state => { + if (process.env.features.USE_SHAPES) return state.domain.shapes return [] } export const getNotifications = state => state.domain.notifications