diff --git a/src/common/data/copy.json b/src/common/data/copy.json index ee9cb24..d811f9f 100644 --- a/src/common/data/copy.json +++ b/src/common/data/copy.json @@ -126,10 +126,9 @@ "filters": "Filters", "filters_label": "Filters", "explore_by_filter__title": "Explore by filter", - "explore_by_filter__description": "Selecting a filter will show you only those events that are annotated with the filter. If you select nothing, as well as everything, all data will be displayed.", + "explore_by_filter__description": "‘Filters’ refer to the types of incident. Select multiple filters to introduce colour-coding, up to a maximum of six filters. If no filters are selected, all datapoints are displayed.", "explore_by_category__title": "Explore events by category", - "explore_by_category__description": "" - + "explore_by_category__description": "‘Categories’ refer to the victims of a given incident. If no categories are selected, all datapoints are displayed." }, "timeline": { "zooms": [ diff --git a/src/common/utilities.js b/src/common/utilities.js index 651797a..1b94098 100644 --- a/src/common/utilities.js +++ b/src/common/utilities.js @@ -283,6 +283,15 @@ export function calcClusterSize (pointCount, totalPoints) { return Math.min(maxSize, 10 + (pointCount / totalPoints) * 150) } +export function calculateTotalClusterPoints (clusters) { + return clusters.reduce((total, cl) => { + if (cl && cl.properties && cl.properties.cluster) { + total += cl.properties.point_count + } + return total + }, 0) +} + export function isLatitude (lat) { return !!lat && isFinite(lat) && Math.abs(lat) <= 90 } diff --git a/src/components/Layout.js b/src/components/Layout.js index ab87b1f..e8b175b 100644 --- a/src/components/Layout.js +++ b/src/components/Layout.js @@ -261,7 +261,7 @@ class Dashboard extends React.Component { } const popupStyles = { - fontSize: 24, + fontSize: 20, height: `calc(100vh - ${app.timeline.dimensions.height}px)`, width: '40vw', bottom: app.timeline.dimensions.height diff --git a/src/components/Map.jsx b/src/components/Map.jsx index 326950f..8a0692f 100644 --- a/src/components/Map.jsx +++ b/src/components/Map.jsx @@ -17,7 +17,7 @@ import Narratives from './presentational/Map/Narratives' import DefsMarkers from './presentational/Map/DefsMarkers.jsx' import LoadingOverlay from '../components/Overlay/Loading' -import { mapClustersToLocations, isIdentical, isLatitude, isLongitude } from '../common/utilities' +import { mapClustersToLocations, isIdentical, isLatitude, isLongitude, calculateTotalClusterPoints, calcClusterSize } from '../common/utilities' // NB: important constants for map, TODO: make statics const supportedMapboxMap = ['streets', 'satellite'] @@ -183,6 +183,29 @@ class Map extends React.Component { return [] } + getSelectedClusters () { + const { selected } = this.props.app + const selectedIds = selected.map(sl => sl.id) + + if (this.state.clusters && this.state.clusters.length > 0) { + return this.state.clusters.reduce((acc, cl) => { + if (cl.properties.cluster) { + const children = this.getClusterChildren(cl.properties.cluster_id) + if (children && children.length > 0) { + children.forEach(child => { + const clusterPresent = acc.findIndex(item => item.id === cl.id) >= 0 + if (selectedIds.includes(child.id) && !clusterPresent) { + acc.push(cl) + } + }) + } + } + return acc + }, []) + } + return [] + } + alignLayers () { const mapNode = document.querySelector('.leaflet-map-pane') if (mapNode === null) return { transformX: 0, transformY: 0 } @@ -341,10 +364,35 @@ class Map extends React.Component { } renderSelected () { + const selectedClusters = this.getSelectedClusters() + const totalMarkers = [] + + this.props.app.selected.forEach(s => { + const { latitude, longitude } = s + totalMarkers.push({ + latitude, + longitude, + radius: this.props.ui.eventRadius + }) + }) + + const totalClusterPoints = calculateTotalClusterPoints(this.state.clusters) + + selectedClusters.forEach(cl => { + if (cl.properties.cluster) { + const { coordinates } = cl.geometry + totalMarkers.push({ + latitude: String(coordinates[1]), + longitude: String(coordinates[0]), + radius: calcClusterSize(cl.properties.point_count, totalClusterPoints) + }) + } + }) + return ( diff --git a/src/components/presentational/Map/Clusters.jsx b/src/components/presentational/Map/Clusters.jsx index e3aad3a..3a16bae 100644 --- a/src/components/presentational/Map/Clusters.jsx +++ b/src/components/presentational/Map/Clusters.jsx @@ -8,7 +8,8 @@ import { isLatitude, isLongitude, calculateColorPercentages, - zipColorsToPercentages } from '../../../common/utilities' + zipColorsToPercentages, + calculateTotalClusterPoints } from '../../../common/utilities' const DefsClusters = () => ( @@ -74,14 +75,10 @@ function ClusterEvents ({ isRadial, svg, clusters, - filterColors + filterColors, + selected }) { - const totalPoints = clusters.reduce((total, cl) => { - if (cl && cl.properties) { - total += cl.properties.point_count - } - return total - }, 0) + const totalPoints = calculateTotalClusterPoints(clusters) const styles = { fill: isRadial ? "url('#clusterGradient')" : colors.fallbackEventColor, diff --git a/src/components/presentational/Map/SelectedEvents.jsx b/src/components/presentational/Map/SelectedEvents.jsx index d5c3b43..58dd848 100644 --- a/src/components/presentational/Map/SelectedEvents.jsx +++ b/src/components/presentational/Map/SelectedEvents.jsx @@ -3,10 +3,10 @@ import { Portal } from 'react-portal' import colors from '../../../common/global.js' class MapSelectedEvents extends React.Component { - renderMarker (event) { - const { x, y } = this.props.projectPoint([event.latitude, event.longitude]) + renderMarker (marker) { + const { x, y } = this.props.projectPoint([marker.latitude, marker.longitude]) const styles = this.props.styles - const r = styles ? styles.r : 24 + const r = marker.radius ? marker.radius + 5 : 24 return (