fix: align Mol explorer primary metrics
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-14 13:27:28 +02:00
parent 2958c25b6f
commit b999c54e22
3 changed files with 42 additions and 20 deletions
@@ -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:
+2 -2
View File
@@ -735,7 +735,7 @@ function App(): JSX.Element {
</aside>
<main className="workbench-main" id="workspace-main" tabIndex={-1}>
<div className="workspace-heading">
{activeWorkspace !== 'map' ? <div className="workspace-heading">
<div className="workspace-heading-copy">
<p className="eyebrow">{selectedProject?.region ?? 'Mol, Kempen'}</p>
<h2>{activeWorkspaceItem.label}</h2>
@@ -754,7 +754,7 @@ function App(): JSX.Element {
</button>
) : null}
</div>
</div>
</div> : null}
<div className="workspace-command-bar" aria-label="Workspace shortcuts">
<div className="workspace-nav-cluster">
{workspaceNavItems.slice(0, 5).map((item) => (
+38 -18
View File
@@ -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<string, Set<string>>()
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({
</div>
<div>
<span>{activeTheme.shortLabel}</span>
<strong>{mapSelectionResult ? resultCountLabel(mapSelectionResult) : 'Geen resultaat'}</strong>
<strong>{activeSelectionResult ? resultCountLabel(activeSelectionResult) : 'Geen resultaat'}</strong>
</div>
<div>
<span>Dichtheid</span>
@@ -912,8 +932,8 @@ export function MapWorkspace({
})}
</div>
{mapSelectionResult?.truncated ? (
<p className="geo-data-notice">De telling is volledig; op de kaart en in de tabel worden maximaal {mapSelectionResult.limit.toLocaleString('nl-BE')} objecten getoond.</p>
{activeSelectionResult?.truncated ? (
<p className="geo-data-notice">De telling is volledig; op de kaart en in de tabel worden maximaal {activeSelectionResult.limit.toLocaleString('nl-BE')} objecten getoond.</p>
) : null}
{mapSelectionError ? <p className="error">{mapSelectionError}</p> : null}
{themeResultsError ? <p className="error">{themeResultsError}</p> : null}