mirror of
https://github.com/bellingcat/ukraine-timemap.git
synced 2026-06-12 13:28:36 +03:00
Broken onClick clusters working after validating longitude and latitude and only allowing locations to contain valid coordinates
This commit is contained in:
@@ -172,6 +172,14 @@ export function calcClusterSize (pointCount, numClusters) {
|
||||
return Math.min(50, 10 + (pointCount / numClusters) * 10)
|
||||
}
|
||||
|
||||
export function isLatitude(lat) {
|
||||
return !!lat && isFinite(lat) && Math.abs(lat) <= 90;
|
||||
}
|
||||
|
||||
export function isLongitude(lng) {
|
||||
return !!lng && isFinite(lng) && Math.abs(lng) <= 180;
|
||||
}
|
||||
|
||||
export const dateMin = function () {
|
||||
return Array.prototype.slice.call(arguments).reduce(function (a, b) {
|
||||
return a < b ? a : b
|
||||
|
||||
@@ -239,7 +239,6 @@ class Dashboard extends React.Component {
|
||||
|
||||
render () {
|
||||
const { actions, app, domain, ui, features } = this.props
|
||||
|
||||
if (isMobile || window.innerWidth < 600) {
|
||||
const msg = 'This platform is not suitable for mobile. Please re-visit the site on a device with a larger screen.'
|
||||
return (
|
||||
@@ -260,7 +259,7 @@ class Dashboard extends React.Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<div >
|
||||
<div>
|
||||
<Toolbar
|
||||
isNarrative={!!app.associations.narrative}
|
||||
methods={{
|
||||
@@ -365,7 +364,7 @@ export default connect(
|
||||
...state,
|
||||
narrativeIdx: selectors.selectNarrativeIdx(state),
|
||||
narratives: selectors.selectNarratives(state),
|
||||
selected: selectors.selectSelected(state)
|
||||
selected: selectors.selectSelected(state),
|
||||
}),
|
||||
mapDispatchToProps
|
||||
)(Dashboard)
|
||||
|
||||
@@ -26,7 +26,6 @@ class Map extends React.Component {
|
||||
constructor () {
|
||||
super()
|
||||
this.projectPoint = this.projectPoint.bind(this)
|
||||
this.locationToGeoJSON = this.locationToGeoJSON.bind(this)
|
||||
this.onClusterSelect = this.onClusterSelect.bind(this)
|
||||
this.svgRef = React.createRef()
|
||||
this.map = null
|
||||
@@ -92,6 +91,8 @@ class Map extends React.Component {
|
||||
minZoom: mapConf.minZoom
|
||||
})
|
||||
|
||||
this.index = index
|
||||
|
||||
let firstLayer
|
||||
|
||||
if ((supportedMapboxMap.indexOf(this.props.ui.tiles) !== -1) && process.env.MAPBOX_TOKEN && process.env.MAPBOX_TOKEN !== defaultToken) {
|
||||
@@ -116,13 +117,13 @@ class Map extends React.Component {
|
||||
this.update()
|
||||
this.alignLayers()
|
||||
})
|
||||
map.on('load', () => this.update())
|
||||
map.on('move zoomend viewreset', () => this.alignLayers())
|
||||
map.on('zoomstart', () => { if (this.svgRef.current !== null) this.svgRef.current.classList.add('hide') })
|
||||
map.on('zoomend', () => { if (this.svgRef.current !== null) this.svgRef.current.classList.remove('hide') })
|
||||
window.addEventListener('resize', () => { this.alignLayers() })
|
||||
|
||||
this.map = map
|
||||
this.index = index
|
||||
}
|
||||
|
||||
getMapDetails () {
|
||||
@@ -143,7 +144,26 @@ class Map extends React.Component {
|
||||
|
||||
loadClusterData (locations) {
|
||||
if (locations && locations.length !== 0 && this.index) {
|
||||
this.index.load(locations.map(this.locationToGeoJSON))
|
||||
const convertedLocations = locations.reduce((acc, loc) => {
|
||||
const { longitude, latitude } = loc
|
||||
const validCoordinates = !!latitude && !!longitude
|
||||
if (validCoordinates) {
|
||||
const feature = {
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
cluster: false,
|
||||
id: loc.label
|
||||
},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [longitude, latitude]
|
||||
}
|
||||
}
|
||||
acc.push(feature)
|
||||
}
|
||||
return acc
|
||||
}, [])
|
||||
this.index.load(convertedLocations)
|
||||
this.setState({indexLoaded: true})
|
||||
this.update()
|
||||
}
|
||||
@@ -174,21 +194,6 @@ class Map extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
locationToGeoJSON (location) {
|
||||
const feature = {
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
cluster: false,
|
||||
id: location.label
|
||||
},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [location.longitude, location.latitude]
|
||||
}
|
||||
}
|
||||
return feature
|
||||
}
|
||||
|
||||
onClusterSelect (e) {
|
||||
const { id } = e.target
|
||||
const { longitude, latitude } = e.target.attributes
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createSelector } from 'reselect'
|
||||
import { insetSourceFrom, dateMin, dateMax } from '../common/utilities'
|
||||
import { insetSourceFrom, dateMin, dateMax, isLatitude, isLongitude } from '../common/utilities'
|
||||
import { isTimeRangedIn } from './helpers'
|
||||
import { FILTER_MODE, NARRATIVE_MODE } from '../common/constants'
|
||||
|
||||
@@ -64,7 +64,6 @@ export const selectEvents = createSelector(
|
||||
if (isActiveTime && isActiveFilter && isActiveCategory) {
|
||||
acc[event.id] = { ...event }
|
||||
}
|
||||
|
||||
return acc
|
||||
}, [])
|
||||
})
|
||||
@@ -159,6 +158,9 @@ export const selectLocations = createSelector(
|
||||
(events) => {
|
||||
const activeLocations = {}
|
||||
events.forEach(event => {
|
||||
const { latitude, longitude } = event
|
||||
if (!isLatitude(latitude) || !isLongitude(longitude)) return
|
||||
|
||||
const location = `${event.location}$_${event.latitude}_${event.longitude}`
|
||||
|
||||
if (activeLocations[location]) {
|
||||
|
||||
@@ -11,7 +11,7 @@ const initial = {
|
||||
*/
|
||||
domain: {
|
||||
events: [],
|
||||
locations: [],
|
||||
// locations: [],
|
||||
categories: [],
|
||||
associations: [],
|
||||
sources: {},
|
||||
@@ -49,7 +49,7 @@ const initial = {
|
||||
map: {
|
||||
anchor: [31.356397, 34.784818],
|
||||
startZoom: 11,
|
||||
minZoom: 2,
|
||||
minZoom: 0,
|
||||
maxZoom: 18,
|
||||
bounds: null,
|
||||
maxBounds: [[180, -180], [-180, 180]],
|
||||
|
||||
Reference in New Issue
Block a user