Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { useCallback, useEffect, useMemo } from 'react'
import { LayerGroup, LayersControl } from 'react-leaflet'
import PropTypes from 'prop-types'

import * as NodeDef from '@core/survey/nodeDef'
import { useSystemConfigExperimentalFeatures } from '@webapp/store/system'
import { ClusterMarker, useFlyToPoint } from '../common'
import { CoordinateAttributeMarker } from './CoordinateAttributeMarker'
import { useGeoAttributeDataLayer } from './useGeoAttributeDataLayer'
Expand All @@ -23,6 +24,7 @@ export const GeoAttributeDataLayer = (props) => {
points,
} = useGeoAttributeDataLayer(props)

const experimentalFeatures = useSystemConfigExperimentalFeatures()
const { registerLayer, unregisterLayer, selectPoint, layerSortOrders } = useMapLayersPanel()
const layerKey = NodeDef.getUuid(attributeDef)
const sortOrder = layerSortOrders[layerKey] ?? 'none'
Expand All @@ -42,20 +44,13 @@ export const GeoAttributeDataLayer = (props) => {
const onMarkerPopupOpen = useCallback((key) => selectPoint(key), [selectPoint])
const onMarkerPopupClose = useCallback(() => selectPoint(null), [selectPoint])

// Stable wrapper so the panel always calls the latest flyToPoint without re-registering on popup state changes
const flyToPointRef = useRef(flyToPoint)
useEffect(() => {
flyToPointRef.current = flyToPoint
}, [flyToPoint])
const stableFlyToPoint = useCallback((point) => flyToPointRef.current(point), [])

useEffect(() => {
if (points.length === 0) {
if (!experimentalFeatures || points.length === 0) {
unregisterLayer({ key: layerKey })
return
}
registerLayer({ key: layerKey, layerName: layerInnerName, points, flyToPoint: stableFlyToPoint })
}, [layerKey, layerInnerName, points, registerLayer, stableFlyToPoint, unregisterLayer])
registerLayer({ key: layerKey, layerName: layerInnerName, points, flyToPoint })
}, [experimentalFeatures, flyToPoint, layerKey, layerInnerName, points, registerLayer, unregisterLayer])

return (
<LayersControl.Overlay name={layerName}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
import { useCallback, useEffect, useMemo } from 'react'
import { LayersControl, LayerGroup } from 'react-leaflet'
import PropTypes from 'prop-types'

import { useSystemConfigExperimentalFeatures } from '@webapp/store/system'
import { ClusterMarker, useFlyToPoint } from '../common'
import { applySortOrder, useMapLayersPanel } from '../MapLayersPanel/MapLayersPanelContext'
import { useSamplingPointDataLayer } from './useSamplingPointDataLayer'
import { SamplingPointDataMarker } from './SamplingPointDataMarker'

export const SamplingPointDataLayer = (props) => {
const { onRecordEditClick, createRecordFromSamplingPointDataItem } = props
const { levelIndex = 0, onRecordEditClick, createRecordFromSamplingPointDataItem } = props

const {
clusters,
clusterExpansionZoomExtractor,
clusterIconCreator,
getClusterLeaves,
isLayerActive,
overlayInnerName,
overlayName,
currentMarkersColor,
totalPoints,
points,
} = useSamplingPointDataLayer(props)

const experimentalFeatures = useSystemConfigExperimentalFeatures()
const { registerLayer, unregisterLayer, selectPoint, layerSortOrders } = useMapLayersPanel()

const layerKey = `sampling-point-data-${levelIndex}`
const sortOrder = layerSortOrders[layerKey] ?? 'none'
const sortedPoints = useMemo(() => applySortOrder(points, sortOrder), [points, sortOrder])

const {
currentPointShown,
currentPointPopupOpen,
Expand All @@ -28,7 +40,27 @@ export const SamplingPointDataLayer = (props) => {
onCurrentPointPopupClose,
openPopupOfPoint,
setMarkerByKey,
} = useFlyToPoint({ points, onRecordEditClick })
} = useFlyToPoint({ points: sortedPoints, onRecordEditClick })

const onMarkerPopupOpen = useCallback((key) => selectPoint(key), [selectPoint])
const onMarkerPopupClose = useCallback(() => selectPoint(null), [selectPoint])

useEffect(() => {
if (!experimentalFeatures || !isLayerActive || points.length === 0) {
unregisterLayer({ key: layerKey })
return
}
registerLayer({ key: layerKey, layerName: overlayInnerName, points, flyToPoint })
}, [
experimentalFeatures,
flyToPoint,
isLayerActive,
layerKey,
overlayInnerName,
points,
registerLayer,
unregisterLayer,
])

return (
<LayersControl.Overlay name={overlayName}>
Expand Down Expand Up @@ -62,6 +94,8 @@ export const SamplingPointDataLayer = (props) => {
flyToNextPoint={flyToNextPoint}
flyToPreviousPoint={flyToPreviousPoint}
markersColor={currentMarkersColor}
onPopupClose={onMarkerPopupClose}
onPopupOpen={onMarkerPopupOpen}
onRecordEditClick={onRecordEditClick}
pointFeature={cluster}
setMarkerByKey={setMarkerByKey}
Expand All @@ -75,7 +109,11 @@ export const SamplingPointDataLayer = (props) => {
flyToNextPoint={flyToNextPoint}
flyToPreviousPoint={flyToPreviousPoint}
markersColor={currentMarkersColor}
onPopupClose={onCurrentPointPopupClose}
onPopupClose={() => {
onCurrentPointPopupClose()
onMarkerPopupClose()
}}
onPopupOpen={onMarkerPopupOpen}
onRecordEditClick={onRecordEditClick}
pointFeature={currentPointShown}
popupOpen={currentPointPopupOpen}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const SamplingPointDataMarker = (props) => {
flyToPreviousPoint,
markersColor,
onPopupClose,
onPopupOpen,
onRecordEditClick,
pointFeature,
popupOpen,
Expand All @@ -30,6 +31,10 @@ export const SamplingPointDataMarker = (props) => {
flyToPoint(pointFeature)
}, [flyToPoint, pointFeature])

const handlePopupOpen = useCallback(() => {
onPopupOpen?.(key)
}, [key, onPopupOpen])

const pathOptions = useMemo(
() => ({ color: markersColor, fillColor: markersColor, fillOpacity: 0.5 }),
[markersColor]
Expand All @@ -44,7 +49,7 @@ export const SamplingPointDataMarker = (props) => {
markerRef.current = ref
setMarkerByKey({ key, marker: ref })
}}
eventHandlers={{ dblclick: onDoubleClick, popupclose: onPopupClose }}
eventHandlers={{ dblclick: onDoubleClick, popupclose: onPopupClose, popupopen: handlePopupOpen }}
>
{showMarkersLabels && <MarkerTooltip color={markersColor}>{itemCodes.join(' - ')}</MarkerTooltip>}

Expand All @@ -66,6 +71,7 @@ SamplingPointDataMarker.propTypes = {
flyToPreviousPoint: PropTypes.func.isRequired,
markersColor: PropTypes.string,
onPopupClose: PropTypes.func,
onPopupOpen: PropTypes.func,
onRecordEditClick: PropTypes.func.isRequired,
pointFeature: PropTypes.object.isRequired,
popupOpen: PropTypes.bool,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const _convertItemsToPoints = (items) => {
x: long,
y: lat,
properties: {
ancestorsKeys: itemCodes,
cluster: false,
itemUuid,
itemCodes,
Expand Down Expand Up @@ -102,6 +103,7 @@ export const useSamplingPointDataLayer = (props) => {
const map = useMap()

const fetchCancelRef = useRef(null)
const [isLayerActive, setIsLayerActive] = useState(false)
const [state, setState] = useState({ loaded: false, loading: false, points: [], items: [] })
const { loaded, loading, points, items } = state

Expand Down Expand Up @@ -140,12 +142,16 @@ export const useSamplingPointDataLayer = (props) => {
useMapLayerToggle({
layerName: overlayName,
onAdd: () => {
setIsLayerActive(true)
const shouldLoadItems = !loaded && !loading
if (shouldLoadItems) {
fetchItemsAndConvertIntoPoints()
}
setState((statePrev) => ({ ...statePrev, loading: shouldLoadItems }))
},
onRemove: () => {
setIsLayerActive(false)
},
})

// cancel items fetch (if any) on unmount
Comment thread
SteRiccio marked this conversation as resolved.
Expand All @@ -163,6 +169,8 @@ export const useSamplingPointDataLayer = (props) => {
clusterExpansionZoomExtractor,
clusterIconCreator,
getClusterLeaves,
isLayerActive,
overlayInnerName,
overlayName,
currentMarkersColor,
totalPoints: points.length,
Expand Down
11 changes: 9 additions & 2 deletions webapp/views/App/views/Data/MapView/common/useFlyToPoint.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useRef, useState } from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useMap } from 'react-leaflet'

import { Numbers } from '@openforis/arena-core'
Expand Down Expand Up @@ -87,10 +87,17 @@ export const useFlyToPoint = ({ points, onRecordEditClick = null, zoomToMaxLevel
[]
)

// Stable wrapper so the panel always calls the latest flyToPoint without re-registering on popup state changes
const flyToPointRef = useRef(flyToPoint)
useEffect(() => {
flyToPointRef.current = flyToPoint
}, [flyToPoint])
const stableFlyToPoint = useCallback((point) => flyToPointRef.current(point), [])

return {
currentPointShown,
currentPointPopupOpen,
flyToPoint,
flyToPoint: stableFlyToPoint,
flyToNextPoint,
flyToPreviousPoint,
onCurrentPointPopupClose,
Expand Down
Loading