fix: clear stale regional map results
This commit is contained in:
@@ -744,6 +744,11 @@ export function MapWorkspace({
|
||||
onClearMapSelectionExtract()
|
||||
}
|
||||
|
||||
const handleSelectMapArea = (areaId: string) => {
|
||||
clearAreaSelection()
|
||||
onSelectMapArea(areaId)
|
||||
}
|
||||
|
||||
const downloadAreaSelection = () => {
|
||||
if (!mapSelectionResult) {
|
||||
return
|
||||
@@ -1061,7 +1066,7 @@ export function MapWorkspace({
|
||||
|
||||
<label className="geo-scope-select">
|
||||
Werkgebied
|
||||
<select aria-label="Werkgebied" value={selectedMapAreaId} onChange={(event) => onSelectMapArea(event.target.value)} disabled={areas.length === 0}>
|
||||
<select aria-label="Werkgebied" value={selectedMapAreaId} onChange={(event) => handleSelectMapArea(event.target.value)} disabled={areas.length === 0}>
|
||||
<option value="">Geen werkgebied</option>
|
||||
{areas.map((area) => (
|
||||
<option key={area.id} value={area.id}>{area.name}</option>
|
||||
@@ -1389,7 +1394,7 @@ export function MapWorkspace({
|
||||
<select
|
||||
aria-label="Werkgebied"
|
||||
value={selectedMapAreaId}
|
||||
onChange={(event) => onSelectMapArea(event.target.value)}
|
||||
onChange={(event) => handleSelectMapArea(event.target.value)}
|
||||
disabled={areas.length === 0}
|
||||
data-testid="map-area-select"
|
||||
>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { datasetsApi } from '../services/api'
|
||||
import { formatError } from '../lib/formatError'
|
||||
import type { DatasetCreateResponse, VectorSelectionBBox, VectorSelectionResponse } from '../types'
|
||||
@@ -18,14 +18,19 @@ export function useMapSelectionExtract({
|
||||
const [mapSelectionResult, setMapSelectionResult] = useState<VectorSelectionResponse | null>(null)
|
||||
const [mapSelectionLoading, setMapSelectionLoading] = useState(false)
|
||||
const [mapSelectionError, setMapSelectionError] = useState<string | null>(null)
|
||||
const requestSequence = useRef(0)
|
||||
|
||||
useEffect(() => {
|
||||
requestSequence.current += 1
|
||||
setMapSelectionBbox(null)
|
||||
setMapSelectionLoading(false)
|
||||
}, [selectedProjectId])
|
||||
|
||||
useEffect(() => {
|
||||
requestSequence.current += 1
|
||||
setMapSelectionResult(null)
|
||||
setMapSelectionError(null)
|
||||
setMapSelectionLoading(false)
|
||||
}, [selectedProjectId, selectedDataset?.id])
|
||||
|
||||
const runMapSelectionExtract = async (bbox: VectorSelectionBBox, areaId?: string) => {
|
||||
@@ -38,6 +43,8 @@ export function useMapSelectionExtract({
|
||||
return null
|
||||
}
|
||||
|
||||
const sequence = requestSequence.current + 1
|
||||
requestSequence.current = sequence
|
||||
setMapSelectionLoading(true)
|
||||
setMapSelectionError(null)
|
||||
setMapSelectionBbox(bbox)
|
||||
@@ -47,21 +54,31 @@ export function useMapSelectionExtract({
|
||||
area_id: areaId,
|
||||
limit: 1000,
|
||||
})
|
||||
if (requestSequence.current !== sequence) {
|
||||
return null
|
||||
}
|
||||
setMapSelectionResult(response)
|
||||
return response
|
||||
} catch (error) {
|
||||
if (requestSequence.current !== sequence) {
|
||||
return null
|
||||
}
|
||||
setMapSelectionResult(null)
|
||||
setMapSelectionError(formatError(error, 'Area extraction failed'))
|
||||
return null
|
||||
} finally {
|
||||
setMapSelectionLoading(false)
|
||||
if (requestSequence.current === sequence) {
|
||||
setMapSelectionLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const resetMapSelectionExtract = () => {
|
||||
requestSequence.current += 1
|
||||
setMapSelectionBbox(null)
|
||||
setMapSelectionResult(null)
|
||||
setMapSelectionError(null)
|
||||
setMapSelectionLoading(false)
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { formatError } from '../lib/formatError'
|
||||
import { datasetsApi } from '../services/api/datasets'
|
||||
import type { DatasetCreateResponse, VectorSelectionBBox, VectorSelectionResponse } from '../types'
|
||||
@@ -18,15 +18,20 @@ export function useMapThemeSelectionInsights<TThemeId extends string>(
|
||||
const [themeInsights, setThemeInsights] = useState<Array<MapThemeInsight<TThemeId>>>([])
|
||||
const [themeInsightsLoading, setThemeInsightsLoading] = useState(false)
|
||||
const [themeInsightsError, setThemeInsightsError] = useState<string | null>(null)
|
||||
const requestSequence = useRef(0)
|
||||
|
||||
useEffect(() => {
|
||||
requestSequence.current += 1
|
||||
setThemeInsights([])
|
||||
setThemeInsightsError(null)
|
||||
setThemeInsightsLoading(false)
|
||||
}, [selectedProjectId])
|
||||
|
||||
const clearThemeInsights = () => {
|
||||
requestSequence.current += 1
|
||||
setThemeInsights([])
|
||||
setThemeInsightsError(null)
|
||||
setThemeInsightsLoading(false)
|
||||
}
|
||||
|
||||
const loadThemeInsights = async (
|
||||
@@ -40,6 +45,8 @@ export function useMapThemeSelectionInsights<TThemeId extends string>(
|
||||
return []
|
||||
}
|
||||
|
||||
const sequence = requestSequence.current + 1
|
||||
requestSequence.current = sequence
|
||||
setThemeInsightsLoading(true)
|
||||
setThemeInsightsError(null)
|
||||
try {
|
||||
@@ -56,6 +63,9 @@ export function useMapThemeSelectionInsights<TThemeId extends string>(
|
||||
)
|
||||
const successful = settled.flatMap((item) => (item.status === 'fulfilled' ? [item.value] : []))
|
||||
const failureCount = settled.length - successful.length
|
||||
if (requestSequence.current !== sequence) {
|
||||
return []
|
||||
}
|
||||
setThemeInsights(successful)
|
||||
if (failureCount > 0) {
|
||||
setThemeInsightsError(
|
||||
@@ -64,11 +74,16 @@ export function useMapThemeSelectionInsights<TThemeId extends string>(
|
||||
}
|
||||
return successful
|
||||
} catch (error) {
|
||||
if (requestSequence.current !== sequence) {
|
||||
return []
|
||||
}
|
||||
setThemeInsights([])
|
||||
setThemeInsightsError(formatError(error, 'De gebiedsanalyse is mislukt.'))
|
||||
return []
|
||||
} finally {
|
||||
setThemeInsightsLoading(false)
|
||||
if (requestSequence.current === sequence) {
|
||||
setThemeInsightsLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ export function useViewportVectorLayer({
|
||||
)
|
||||
const zoom = viewport?.zoom ?? null
|
||||
const zoomRequired = enabled && (zoom === null || zoom < VECTOR_VIEWPORT_MIN_ZOOM)
|
||||
const layerLabel = selectedDataset?.reference_layer_name?.trim() || 'features'
|
||||
|
||||
useEffect(() => {
|
||||
requestSequence.current += 1
|
||||
@@ -103,7 +104,7 @@ export function useViewportVectorLayer({
|
||||
return null
|
||||
}
|
||||
if (zoomRequired) {
|
||||
return `Zoom in to level ${VECTOR_VIEWPORT_MIN_ZOOM} to load buildings from PostGIS.`
|
||||
return `Zoom in to level ${VECTOR_VIEWPORT_MIN_ZOOM} to load ${layerLabel} from PostGIS.`
|
||||
}
|
||||
if (loading) {
|
||||
return 'Loading visible features from PostGIS...'
|
||||
@@ -115,7 +116,7 @@ export function useViewportVectorLayer({
|
||||
return `${loadedFeatureCount.toLocaleString()} visible features loaded; zoom in further because this view exceeds the ${VECTOR_VIEWPORT_FEATURE_LIMIT.toLocaleString()} feature limit.`
|
||||
}
|
||||
return `${loadedFeatureCount.toLocaleString()} visible of ${(featureCount ?? 0).toLocaleString()} total features loaded from PostGIS.`
|
||||
}, [enabled, error, featureCount, loadedFeatureCount, loading, truncated, zoomRequired])
|
||||
}, [enabled, error, featureCount, layerLabel, loadedFeatureCount, loading, truncated, zoomRequired])
|
||||
|
||||
return {
|
||||
enabled,
|
||||
|
||||
Reference in New Issue
Block a user