diff --git a/CHANGELOG.md b/CHANGELOG.md index a623dcf4..6d0db121 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,9 @@ metrics, GeoJSON and server-side exports now use the same governed path. - Made the Waterbodem theme report the actual regional totals and partition count instead of the feature/document count of one arbitrary municipality. +- Made the global context bar and visible workspace labels use the same + regional totals and end-user label `Vlaanderen (285 gemeenten)`; technical + project names and one-partition map counts no longer leak into the Map flow. ## Sprint 235 Governed bathymetry profiles and Belgian scale architecture (2026-07-17) diff --git a/backend/tests/test_sprint177_mol_primary_focus.py b/backend/tests/test_sprint177_mol_primary_focus.py index 9f36a51f..f9c85e4c 100644 --- a/backend/tests/test_sprint177_mol_primary_focus.py +++ b/backend/tests/test_sprint177_mol_primary_focus.py @@ -29,7 +29,7 @@ def test_frontend_declares_mol_as_primary_operating_focus() -> None: assert "PRIMARY_FOCUS_AREA_GEOJSON" in project_hook assert "4.35,51.28" not in project_hook assert "center: PRIMARY_FOCUS_CENTER" in map_source - assert "GeoAI-werkruimte · Mol en de Kempen" in app + assert "GeoAI-werkruimte · gebiedsdata en analyse" in app def test_operator_workflows_put_mol_first_and_name_future_projects() -> None: diff --git a/backend/tests/test_sprint236_bathymetry_expansion.py b/backend/tests/test_sprint236_bathymetry_expansion.py index 33876b8f..a7e072cb 100644 --- a/backend/tests/test_sprint236_bathymetry_expansion.py +++ b/backend/tests/test_sprint236_bathymetry_expansion.py @@ -450,6 +450,10 @@ def test_frontend_labels_flanders_scope_without_kempen_mislabeling() -> None: def test_frontend_uses_partitioned_bathymetry_selection_for_regional_scope() -> None: + app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") + focus = ( + ROOT / "frontend" / "src" / "config" / "primaryFocus.ts" + ).read_text(encoding="utf-8") map_workspace = ( ROOT / "frontend" / "src" / "components" / "map" / "MapWorkspace.tsx" ).read_text(encoding="utf-8") @@ -466,3 +470,7 @@ def test_frontend_uses_partitioned_bathymetry_selection_for_regional_scope() -> assert "activeSelectionResult?.geojson ?? null" in map_workspace assert "selectBathymetryProfilePartitions" in theme_hook assert "datasets/bathymetry/profiles/partitions/select" in dataset_api + assert "regionalBathymetryContextActive" in app + assert "regionalBathymetryProfileCount" in app + assert "profielen · ${regionalBathymetryPartitions.length} gemeenten" in app + assert "FLANDERS_WORKSPACE_LABEL = 'Vlaanderen (285 gemeenten)'" in focus diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index 05f17966..1c535d7b 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -10141,3 +10141,16 @@ Validation: - The complete readiness gate passed: 927 backend tests, backend compilation, 116 documented API routes, Alembic head `202607160001`, frontend TypeScript typecheck and the production Vite build. +- Tower deployment passed container health, PostGIS 3.6, schema/index, + Alembic, frontend proxy and icon checks. Live selection returned 828 + profiles from the exact Mol partition in 0.59 seconds, 8,806 profiles from + 22 intersecting partitions in 1.95 seconds and 128,913 profiles from all + 269 data-bearing partitions in 15.89 seconds. +- The live partitioned export persisted a canonical 1,000-feature GeoJSON + sample with `total_feature_count=8806`, all 22 contributing Dataset ids and + `server_recomputed=true`. +- Browser acceptance showed the complete Flemish metric result, all five + configured structured depth/width measurements and the explicit 1,000-item + display limit. A final shell follow-up replaces the representative + municipality count with regional profile/partition totals and uses the + end-user label `Vlaanderen (285 gemeenten)`. diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 6fbc8405..e4ca3a73 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -36,7 +36,12 @@ import { useSourceFreshness } from './hooks/useSourceFreshness' import { useWorkbenchBootstrap } from './hooks/useWorkbenchBootstrap' import { useViewportVectorLayer } from './hooks/useViewportVectorLayer' import { getDatasetDisplayName } from './lib/datasetDisplay' -import { REGIONAL_WORKSPACE_LABEL, REGIONAL_WORKSPACE_PROJECT_NAME } from './config/primaryFocus' +import { + FLANDERS_WORKSPACE_LABEL, + FLANDERS_WORKSPACE_PROJECT_NAME, + REGIONAL_WORKSPACE_LABEL, + REGIONAL_WORKSPACE_PROJECT_NAME, +} from './config/primaryFocus' function isVectorDatasetType(datasetType: string): boolean { return datasetType === 'vector' || datasetType === 'geojson' @@ -664,8 +669,38 @@ function App(): JSX.Element { || segmentationItems.length > 0 const projectContextLabel = selectedProject?.name === REGIONAL_WORKSPACE_PROJECT_NAME ? REGIONAL_WORKSPACE_LABEL - : selectedProject?.name ?? 'Geen werkruimte' + : selectedProject?.name === FLANDERS_WORKSPACE_PROJECT_NAME + ? FLANDERS_WORKSPACE_LABEL + : selectedProject?.name ?? 'Geen werkruimte' const areaContextLabel = selectedArea?.name ?? (areas.length > 0 ? 'Kies een gebied' : 'Geen gebied') + const bathymetryContextActive = Boolean( + activeWorkspace === 'map' + && selectedDataset?.source_name === 'vmm_vha_bathymetry_profiles', + ) + const regionalBathymetryContextActive = Boolean( + bathymetryContextActive + && selectedDataset?.source_metadata?.regional_partitions_complete === true + && selectedArea + && !/^Gemeente\s/i.test(selectedArea.name), + ) + const regionalBathymetryManifest = String( + selectedDataset?.source_metadata?.partition_manifest_sha256 ?? '', + ) + const regionalBathymetryPartitions = regionalBathymetryContextActive + ? availableMapDatasets.filter( + (dataset) => + dataset.source_name === 'vmm_vha_bathymetry_profiles' + && dataset.source_metadata?.regional_partitions_complete === true + && String(dataset.source_metadata?.partition_manifest_sha256 ?? '') === regionalBathymetryManifest, + ) + : [] + const regionalBathymetryProfileCount = regionalBathymetryPartitions.reduce( + (total, dataset) => total + (dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0), + 0, + ) + const bathymetryProfileCount = regionalBathymetryContextActive + ? regionalBathymetryProfileCount + : selectedDataset?.feature_count ?? selectedDataset?.vector_summary?.feature_count ?? 0 const datasetContextLabel = activeWorkspace === 'map' && mapContextSourceLabel ? mapContextSourceLabel : analysisMapLayerActive && mapFeatureCollection @@ -675,7 +710,11 @@ function App(): JSX.Element { : datasets.length > 0 ? 'Kies een bron' : 'Geen bron' - const layerContextLabel = mapFeatureCollection + const layerContextLabel = bathymetryContextActive + ? regionalBathymetryContextActive + ? `${bathymetryProfileCount.toLocaleString('nl-BE')} profielen · ${regionalBathymetryPartitions.length} gemeenten` + : `${bathymetryProfileCount.toLocaleString('nl-BE')} profielen` + : mapFeatureCollection ? `${mapFeatureCount.toLocaleString('nl-BE')} objecten` : viewportVectorLayerActive ? 'Kaartlaag gekozen' @@ -693,7 +732,7 @@ function App(): JSX.Element {

GeoIntel

-

GeoAI-werkruimte · Mol en de Kempen

+

GeoAI-werkruimte · gebiedsdata en analyse

diff --git a/frontend/src/components/WorkbenchStatusStrip.tsx b/frontend/src/components/WorkbenchStatusStrip.tsx index 2bbea338..ba128dd0 100644 --- a/frontend/src/components/WorkbenchStatusStrip.tsx +++ b/frontend/src/components/WorkbenchStatusStrip.tsx @@ -1,5 +1,10 @@ import type { AreaRead, DatasetCreateResponse, ExportRead, ProjectRead, QualityCheckRead } from '../types' -import { REGIONAL_WORKSPACE_LABEL, REGIONAL_WORKSPACE_PROJECT_NAME } from '../config/primaryFocus' +import { + FLANDERS_WORKSPACE_LABEL, + FLANDERS_WORKSPACE_PROJECT_NAME, + REGIONAL_WORKSPACE_LABEL, + REGIONAL_WORKSPACE_PROJECT_NAME, +} from '../config/primaryFocus' interface StatusItem { key: string @@ -35,6 +40,7 @@ function statusLabel(state: StatusItem['state']): string { function projectLabel(project: ProjectRead | null): string { if (!project) return 'Geen werkruimte' + if (project.name === FLANDERS_WORKSPACE_PROJECT_NAME) return FLANDERS_WORKSPACE_LABEL return project.name === REGIONAL_WORKSPACE_PROJECT_NAME ? REGIONAL_WORKSPACE_LABEL : project.name } diff --git a/frontend/src/components/map/MapWorkspace.tsx b/frontend/src/components/map/MapWorkspace.tsx index 07f96881..d99980dd 100644 --- a/frontend/src/components/map/MapWorkspace.tsx +++ b/frontend/src/components/map/MapWorkspace.tsx @@ -853,11 +853,17 @@ export function MapWorkspace({ - new Date(activeTemporalSeries[0].observed_at ?? 0).getTime() <= 7 * 24 * 60 * 60 * 1000 useEffect(() => { - onSetContextSourceLabel( - analysisMode === 'evolution' ? activeTemporalSeriesGroup?.label ?? null : null, - ) + const contextSourceLabel = analysisMode === 'evolution' ? activeTemporalSeriesGroup?.label ?? null + : regionalBathymetryThemeActive ? 'VHA-dwarsprofielen Vlaanderen' + : null + onSetContextSourceLabel(contextSourceLabel) return () => onSetContextSourceLabel(null) - }, [activeTemporalSeriesGroup?.label, analysisMode, onSetContextSourceLabel]) + }, [ + activeTemporalSeriesGroup?.label, + analysisMode, + onSetContextSourceLabel, + regionalBathymetryThemeActive, + ]) const themeResults = useMemo( () => diff --git a/frontend/src/components/map/mapWorkspaceUtils.ts b/frontend/src/components/map/mapWorkspaceUtils.ts index 79195427..41912718 100644 --- a/frontend/src/components/map/mapWorkspaceUtils.ts +++ b/frontend/src/components/map/mapWorkspaceUtils.ts @@ -5,6 +5,10 @@ import type { VectorSelectionMetric, VectorSelectionResponse, } from '../../types' +import { + FLANDERS_WORKSPACE_LABEL, + FLANDERS_WORKSPACE_PROJECT_NAME, +} from '../../config/primaryFocus' const MOL_PROJECT_NAME = 'Mol Municipality Workbench' const KEMPEN_PROJECT_NAME = 'Kempen Regional Workbench' @@ -16,6 +20,9 @@ export function operationalScopeProjectLabel(project: ProjectRead): string { if (project.name === KEMPEN_PROJECT_NAME) { return 'Kempen (28 gemeenten)' } + if (project.name === FLANDERS_WORKSPACE_PROJECT_NAME) { + return FLANDERS_WORKSPACE_LABEL + } return project.name } diff --git a/frontend/src/config/primaryFocus.ts b/frontend/src/config/primaryFocus.ts index ae1f6275..e9a3d3dc 100644 --- a/frontend/src/config/primaryFocus.ts +++ b/frontend/src/config/primaryFocus.ts @@ -4,6 +4,8 @@ export const PRIMARY_FOCUS_LABEL = 'Mol' export const PRIMARY_FOCUS_REGION = 'Mol, Kempen' export const REGIONAL_WORKSPACE_PROJECT_NAME = 'Kempen Regional Workbench' export const REGIONAL_WORKSPACE_LABEL = 'Kempen (28 gemeenten)' +export const FLANDERS_WORKSPACE_PROJECT_NAME = 'Flanders Regional Workbench' +export const FLANDERS_WORKSPACE_LABEL = 'Vlaanderen (285 gemeenten)' export const PRIMARY_FOCUS_CENTER: [number, number] = [5.1167, 51.1919] export const PRIMARY_FOCUS_AREA_NAME = 'Mol primary AOI' export const PRIMARY_FOCUS_MUNICIPALITY_PROJECT_NAME = 'Mol Municipality Workbench'