diff --git a/backend/tests/test_sprint186_map_first_geographic_explorer.py b/backend/tests/test_sprint186_map_first_geographic_explorer.py index 9132787a..6c3e1877 100644 --- a/backend/tests/test_sprint186_map_first_geographic_explorer.py +++ b/backend/tests/test_sprint186_map_first_geographic_explorer.py @@ -48,8 +48,8 @@ def test_map_rectangle_drag_is_wired_to_automatic_analysis() -> None: assert "resizeObserver.observe(containerRef.current)" in geomap assert "fitDataOnChangeRef.current" in geomap assert "map.fitBounds(bounds, { padding: 40, duration: 0 })" in geomap - assert "const areaChanged = lastFittedAreaRef.current !== areaData" in geomap - assert "areaChanged && areaData" in geomap + assert "const activeCollection = areaData ?? (fitDataOnChange ? data : null)" in geomap + assert "data && fitDataOnChange && !areaData" in geomap assert "resizeObserver.disconnect()" in geomap assert ".workbench-main .geo-map-canvas .map-container" in styles assert "position: absolute;" in styles diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index 05c0bda3..a96c3e78 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -46,7 +46,8 @@ available only through an exact bounded request. - Live browser verification found that a changed work area was fitted together with the complete active national layer. Area changes now fit the selected - geography first; subsequent layer changes retain the existing fit behavior. + geography first and retain that viewport when a complete national layer is + loaded on the following render or the map container resizes. - Focused backend and frontend suites passed before full release validation; full local and Tower evidence follows in the final P5 gate. diff --git a/frontend/src/components/GeoMap.tsx b/frontend/src/components/GeoMap.tsx index 409b45aa..388b95ec 100644 --- a/frontend/src/components/GeoMap.tsx +++ b/frontend/src/components/GeoMap.tsx @@ -110,11 +110,6 @@ function collectCoordinates(featureCollection: GeoJSON.FeatureCollection): mapli ] } -function mergeFeatureCollections(collections: Array): GeoJSON.FeatureCollection | null { - const features = collections.flatMap((collection) => collection?.features ?? []) - return features.length > 0 ? { type: 'FeatureCollection', features } : null -} - function bboxToFeatureCollection( bbox: { min_x: number; min_y: number; max_x: number; max_y: number } | null | undefined, ): GeoJSON.FeatureCollection { @@ -179,7 +174,6 @@ function GeoMap({ const areaDataRef = useRef(areaData) const dataRef = useRef(data) const fitDataOnChangeRef = useRef(fitDataOnChange) - const lastFittedAreaRef = useRef(null) const imageOverlayIdsRef = useRef([]) const [mapStyleReady, setMapStyleReady] = useState(false) @@ -233,9 +227,8 @@ function GeoMap({ }) const resizeObserver = new ResizeObserver(() => { map.resize() - const fitCollection = fitDataOnChangeRef.current - ? mergeFeatureCollections([areaDataRef.current, dataRef.current]) - : areaDataRef.current + const fitCollection = areaDataRef.current + ?? (fitDataOnChangeRef.current ? dataRef.current : null) const bounds = fitCollection ? collectCoordinates(fitCollection) : null if (bounds && map.isStyleLoaded()) { map.fitBounds(bounds, { padding: 40, duration: 0 }) @@ -428,7 +421,7 @@ function GeoMap({ }) } - if (data && fitDataOnChange) { + if (data && fitDataOnChange && !areaData) { const collection = data if (collection.type === 'FeatureCollection' && collection.features.length > 0) { const bounds = collectCoordinates(collection) @@ -437,7 +430,7 @@ function GeoMap({ } } } - }, [data, dataFillColor, dataLineColor, fitDataOnChange, mapStyleReady]) + }, [areaData, data, dataFillColor, dataLineColor, fitDataOnChange, mapStyleReady]) useEffect(() => { const map = mapRef.current @@ -500,20 +493,13 @@ function GeoMap({ ) } - const areaChanged = lastFittedAreaRef.current !== areaData - const activeCollection = areaChanged && areaData - ? areaData - : fitDataOnChange - ? mergeFeatureCollections([areaData, data]) - : areaData - const shouldFitArea = fitDataOnChange || areaChanged - if (activeCollection && shouldFitArea) { + const activeCollection = areaData ?? (fitDataOnChange ? data : null) + if (activeCollection) { const bounds = collectCoordinates(activeCollection) if (bounds) { map.fitBounds(bounds, { padding: 40 }) } } - lastFittedAreaRef.current = areaData }, [areaData, data, fitDataOnChange, mapStyleReady]) useEffect(() => {