feat: add governed agricultural parcel history
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-15 14:49:52 +02:00
parent 2f3445aa5b
commit 7f1064ff1e
16 changed files with 1194 additions and 5 deletions
+8
View File
@@ -476,6 +476,14 @@ separate official value classes, PHAB-derived Natura 2000 and regional-biotope
hectares, uncertain habitat knowledge gaps and source provenance. This single
edition is not exposed as a fabricated annual series in Evolution.
When definitive ALZ datasets are loaded, the Map explorer adds `Landbouw` as a
separate theme rather than mixing it with cadastral parcels. Current mode shows
declared-use hectares and official main-crop group hectares. Evolution mode
compares any two persisted annual editions and charts the complete series.
Object additions/removals stay hidden because annual parcel identity is not
stable. The Sources inventory only labels the series available after real
Datasets exist.
## Useful repository scripts
- `bash scripts/frontend_install.sh`
@@ -9,6 +9,7 @@ const THEME_LABELS: Record<string, string> = {
population: 'Bevolking',
forest: 'Bos',
nature_value: 'Natuurwaarde',
agriculture: 'Landbouw',
water: 'Water',
roads: 'Wegen en transport',
parcels: 'Percelen',
@@ -105,10 +106,14 @@ export function SourceCatalogPanel({ datasets }: SourceCatalogPanelProps): JSX.E
String(dataset.source_metadata?.['product_key'] ?? 'most_recent') !== 'most_recent',
)
const bwkDatasets = ready.filter((dataset) => dataset.source_name === 'inbo_bwk_natura2000')
const agricultureDatasets = ready.filter((dataset) => dataset.source_name === 'agentschap_landbouw_zeevisserij_agricultural_parcels')
const agricultureYears = agricultureDatasets
.flatMap((dataset) => dataset.observed_at ? [new Date(dataset.observed_at).getUTCFullYear()] : [])
const pendingSources = AVAILABLE_SOURCES.filter((source) => {
if (source.key === 'waterinfo') return waterinfoDatasets.length === 0
if (source.key === 'historical_orthophoto') return historicalOrthophotos.length === 0
if (source.key === 'bwk') return bwkDatasets.length === 0
if (source.key === 'agriculture') return agricultureDatasets.length === 0
return true
})
const themes = Object.keys(THEME_LABELS).map((theme) => {
@@ -168,7 +173,7 @@ export function SourceCatalogPanel({ datasets }: SourceCatalogPanelProps): JSX.E
))}
</div>
{waterinfoDatasets.length > 0 || historicalOrthophotos.length > 0 || bwkDatasets.length > 0 ? (
{waterinfoDatasets.length > 0 || historicalOrthophotos.length > 0 || bwkDatasets.length > 0 || agricultureDatasets.length > 0 ? (
<div className="source-catalog-loaded" aria-label="Aanvullende ingeladen bronnen">
{waterinfoDatasets.length > 0 ? (
<article>
@@ -191,6 +196,13 @@ export function SourceCatalogPanel({ datasets }: SourceCatalogPanelProps): JSX.E
<p>Biologische waardering en habitataandelen blijven afzonderlijke, brongetrouwe metingen met herkomstinformatie.</p>
</article>
) : null}
{agricultureDatasets.length > 0 ? (
<article>
<strong>Landbouwgebruikspercelen</strong>
<span>{agricultureDatasets.length} definitieve jaargangen{agricultureYears.length ? ` · ${Math.min(...agricultureYears)}-${Math.max(...agricultureYears)}` : ''}</span>
<p>Oppervlakte en officiele hoofdteeltgroepen zijn historisch vergelijkbaar; perceelidentiteiten blijven bewust niet gekoppeld tussen jaren.</p>
</article>
) : null}
</div>
) : null}
+10 -1
View File
@@ -13,7 +13,7 @@ const EMPTY_TEMPORAL_SERIES: DatasetCreateResponse[] = []
const MOL_PROJECT_NAME = 'Mol Municipality Workbench'
const KEMPEN_PROJECT_NAME = 'Kempen Regional Workbench'
type DataThemeId = 'buildings' | 'population' | 'forest' | 'nature_value' | 'water' | 'roads' | 'parcels'
type DataThemeId = 'buildings' | 'population' | 'forest' | 'nature_value' | 'agriculture' | 'water' | 'roads' | 'parcels'
interface DataTheme {
id: DataThemeId
@@ -58,6 +58,13 @@ const DATA_THEMES: DataTheme[] = [
description: 'Biologische waardering, Natura 2000-habitat en regionaal belangrijke biotopen uit de BWK.',
tokens: ['nature_value', 'nature value', 'natuurwaarde', 'bwk', 'natura2000', 'natura 2000', 'biodiversity'],
},
{
id: 'agriculture',
label: 'Landbouw',
shortLabel: 'Landbouwgebruik',
description: 'Jaarlijkse officiele landbouwgebruikspercelen en hoofdteeltgroepen.',
tokens: ['agriculture', 'agricultural', 'landbouw', 'landbouwgebruik', 'agpa'],
},
{
id: 'water',
label: 'Water',
@@ -86,6 +93,7 @@ const DATA_THEME_MAP_STYLES: Record<DataThemeId, { fill: string; line: string }>
population: { fill: '#7559a6', line: '#5b3f88' },
forest: { fill: '#347950', line: '#225f3b' },
nature_value: { fill: '#9a4f64', line: '#74364a' },
agriculture: { fill: '#7b8f32', line: '#53671d' },
water: { fill: '#2676a8', line: '#155b85' },
roads: { fill: '#6b7280', line: '#4b5563' },
parcels: { fill: '#a7792f', line: '#7d571f' },
@@ -120,6 +128,7 @@ function pickThemeDataset(datasets: DatasetCreateResponse[], theme: DataTheme):
(dataset.source_name === 'grb' ? 100_000 : 0) +
(dataset.source_name === 'department_omgeving_land_use' ? 90_000 : 0) +
(dataset.source_name === 'inbo_bwk_natura2000' ? 95_000 : 0) +
(dataset.source_name === 'agentschap_landbouw_zeevisserij_agricultural_parcels' ? 98_000 : 0) +
(dataset.dataset_role === 'reference' ? 10_000 : 0) +
(dataset.observed_at ? new Date(dataset.observed_at).getTime() / 100_000_000 : 0) +
(dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0)
+1
View File
@@ -5754,6 +5754,7 @@ section {
.geo-theme-symbol-population { background: #7559a6; }
.geo-theme-symbol-forest { background: #347950; }
.geo-theme-symbol-nature_value { background: #9a4f64; }
.geo-theme-symbol-agriculture { background: #7b8f32; }
.geo-theme-symbol-water { background: #2676a8; }
.geo-theme-symbol-roads { background: #6b7280; }
.geo-theme-symbol-parcels { background: #a7792f; }