diff --git a/backend/tests/test_sprint186_map_first_geographic_explorer.py b/backend/tests/test_sprint186_map_first_geographic_explorer.py index e91301d3..f1fcf2bc 100644 --- a/backend/tests/test_sprint186_map_first_geographic_explorer.py +++ b/backend/tests/test_sprint186_map_first_geographic_explorer.py @@ -23,6 +23,8 @@ def test_map_first_explorer_is_the_default_product_flow() -> None: assert "Bron nog niet ingeladen" in workspace assert "useMapThemeSelectionInsights" in workspace assert "datasetsApi.selectVectorFeatures" in read("frontend/src/hooks/useMapThemeSelectionInsights.ts") + assert "activeSelectionResult" in workspace + assert "bboxesEqual(mapSelectionBbox, selectedAreaBbox)" in workspace def test_map_rectangle_drag_is_wired_to_automatic_analysis() -> None: diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f8069336..38e5ea58 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -735,7 +735,7 @@ function App(): JSX.Element {
-
+ {activeWorkspace !== 'map' ?

{selectedProject?.region ?? 'Mol, Kempen'}

{activeWorkspaceItem.label}

@@ -754,7 +754,7 @@ function App(): JSX.Element { ) : null}
-
+
: null}
{workspaceNavItems.slice(0, 5).map((item) => ( diff --git a/frontend/src/components/map/MapWorkspace.tsx b/frontend/src/components/map/MapWorkspace.tsx index 00dc1ff7..b20da1f2 100644 --- a/frontend/src/components/map/MapWorkspace.tsx +++ b/frontend/src/components/map/MapWorkspace.tsx @@ -106,6 +106,19 @@ function selectionAreaSquareMetres(bbox: VectorSelectionBBox | null): number | n return Math.max(0, widthMetres * heightMetres) } +function bboxesEqual(left: VectorSelectionBBox | null, right: VectorSelectionBBox | null): boolean { + if (!left || !right) { + return false + } + const tolerance = 1e-9 + return ( + Math.abs(left.min_x - right.min_x) < tolerance && + Math.abs(left.min_y - right.min_y) < tolerance && + Math.abs(left.max_x - right.max_x) < tolerance && + Math.abs(left.max_y - right.max_y) < tolerance + ) +} + function formatArea(areaSquareMetres: number | null): string { if (areaSquareMetres === null) { return 'Nog niet geselecteerd' @@ -469,14 +482,29 @@ export function MapWorkspace({ ) const activeTheme = DATA_THEMES.find((theme) => theme.id === activeThemeId) ?? DATA_THEMES[0] const activeThemeDataset = themeDatasetMap[activeTheme.id] - const selectedAreaSquareMetres = useMemo(() => selectionAreaSquareMetres(mapSelectionBbox), [mapSelectionBbox]) - const selectedResultTotal = mapSelectionResult?.total_feature_count ?? mapSelectionResult?.feature_count ?? 0 + const themeResults = useMemo( + () => + themeInsights.flatMap((insight) => { + const theme = DATA_THEMES.find((candidate) => candidate.id === insight.themeId) + return theme ? [{ theme, dataset: insight.dataset, result: insight.result }] : [] + }), + [themeInsights], + ) + const activeSelectionResult = themeResults.find((item) => item.theme.id === activeThemeId)?.result ?? mapSelectionResult + const selectedAreaSquareMetres = useMemo( + () => + bboxesEqual(mapSelectionBbox, selectedAreaBbox) && selectedMapArea?.area_m2 + ? selectedMapArea.area_m2 + : selectionAreaSquareMetres(mapSelectionBbox), + [mapSelectionBbox, selectedAreaBbox, selectedMapArea?.area_m2], + ) + const selectedResultTotal = activeSelectionResult?.total_feature_count ?? activeSelectionResult?.feature_count ?? 0 const selectedDensity = selectedAreaSquareMetres && selectedAreaSquareMetres > 0 ? selectedResultTotal / (selectedAreaSquareMetres / 1_000_000) : null const selectedResultProperties = useMemo(() => { const keys = new Map>() - for (const feature of mapSelectionResult?.geojson.features ?? []) { + for (const feature of activeSelectionResult?.geojson.features ?? []) { for (const [key, value] of Object.entries(feature.properties ?? {})) { if (value === null || value === undefined || typeof value === 'object' || key.endsWith('_id')) { continue @@ -492,26 +520,18 @@ export function MapWorkspace({ .filter(([, values]) => values.size > 0) .slice(0, 8) .map(([key, values]) => ({ key, values: Array.from(values) })) - }, [mapSelectionResult]) - const themeResults = useMemo( - () => - themeInsights.flatMap((insight) => { - const theme = DATA_THEMES.find((candidate) => candidate.id === insight.themeId) - return theme ? [{ theme, dataset: insight.dataset, result: insight.result }] : [] - }), - [themeInsights], - ) + }, [activeSelectionResult]) useEffect(() => { setBboxInput(bboxToInputState(mapSelectionBbox)) }, [mapSelectionBbox]) useEffect(() => { - if (selectedMapDatasetId || !themeDatasetMap.buildings) { + if (advancedMode || !activeThemeDataset || (selectedMapDataset && datasetMatchesTheme(selectedMapDataset, activeTheme))) { return } - onOpenDatasetInMap(themeDatasetMap.buildings) - }, [onOpenDatasetInMap, selectedMapDatasetId, themeDatasetMap.buildings]) + onOpenDatasetInMap(activeThemeDataset) + }, [activeTheme, activeThemeDataset, advancedMode, onOpenDatasetInMap, selectedMapDataset]) useEffect(() => { if (!selectedMapDataset) { @@ -883,7 +903,7 @@ export function MapWorkspace({
{activeTheme.shortLabel} - {mapSelectionResult ? resultCountLabel(mapSelectionResult) : 'Geen resultaat'} + {activeSelectionResult ? resultCountLabel(activeSelectionResult) : 'Geen resultaat'}
Dichtheid @@ -912,8 +932,8 @@ export function MapWorkspace({ })}
- {mapSelectionResult?.truncated ? ( -

De telling is volledig; op de kaart en in de tabel worden maximaal {mapSelectionResult.limit.toLocaleString('nl-BE')} objecten getoond.

+ {activeSelectionResult?.truncated ? ( +

De telling is volledig; op de kaart en in de tabel worden maximaal {activeSelectionResult.limit.toLocaleString('nl-BE')} objecten getoond.

) : null} {mapSelectionError ?

{mapSelectionError}

: null} {themeResultsError ?

{themeResultsError}

: null}