Federate official Belgium data sources
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useRef, useState, type KeyboardEvent } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, type KeyboardEvent } from 'react'
|
||||
import GeoMap from '../GeoMap'
|
||||
import type { AreaRead, CoverageResolveResponse, CoverageStatus, DatasetCreateResponse, DetectionQaResult, MapResultExportRequest, MapViewportState, OrthophotoAcquisitionResult, OrthophotoProductRead, ProjectRead, QaComparisonResult, VectorSelectionBBox, VectorSelectionMetric, VectorSelectionResponse } from '../../types'
|
||||
import { useMapThemeSelectionInsights, type MapThemeAcquisition, type MapThemeQuery } from '../../hooks/useMapThemeSelectionInsights'
|
||||
@@ -30,10 +30,12 @@ import {
|
||||
normalizeBboxFromCorners,
|
||||
operationalScopeProjectLabel,
|
||||
parseBboxInput,
|
||||
productCoversZones,
|
||||
readablePropertyName,
|
||||
resultCountLabel,
|
||||
resultMetricLabel,
|
||||
safeFileStem,
|
||||
selectedAreaCoverageZones,
|
||||
selectedFeatureCollection,
|
||||
selectionAreaSquareMetres,
|
||||
selectionMetricLabel,
|
||||
@@ -43,7 +45,26 @@ const DEFAULT_SELECTED_FEATURE_FILENAME = 'selected-feature.geojson'
|
||||
const DEFAULT_AREA_SELECTION_FILENAME = 'area-selection.geojson'
|
||||
const EMPTY_TEMPORAL_SERIES: DatasetCreateResponse[] = []
|
||||
|
||||
type DataThemeId = 'buildings' | 'space_occupation' | 'open_space' | 'population' | 'forest' | 'nature_value' | 'agriculture' | 'soil' | 'water' | 'bathymetry' | 'flood_hazard' | 'elevation' | 'accessibility' | 'services' | 'roads' | 'parcels'
|
||||
type DataThemeId =
|
||||
| 'administrative'
|
||||
| 'buildings'
|
||||
| 'space_occupation'
|
||||
| 'open_space'
|
||||
| 'population'
|
||||
| 'forest'
|
||||
| 'nature_value'
|
||||
| 'agriculture'
|
||||
| 'soil'
|
||||
| 'water'
|
||||
| 'bathymetry'
|
||||
| 'flood_hazard'
|
||||
| 'elevation'
|
||||
| 'accessibility'
|
||||
| 'services'
|
||||
| 'roads'
|
||||
| 'parcels'
|
||||
| 'maritime_planning'
|
||||
| 'marine_environment'
|
||||
|
||||
interface DataTheme {
|
||||
id: DataThemeId
|
||||
@@ -67,6 +88,13 @@ interface OnDemandMapProduct extends MapThemeAcquisition {
|
||||
}
|
||||
|
||||
const DATA_THEMES: DataTheme[] = [
|
||||
{
|
||||
id: 'administrative',
|
||||
label: 'Bestuurlijke indeling',
|
||||
shortLabel: 'Bestuursgebieden',
|
||||
description: 'Officiële lands-, gewest-, provincie- en gemeentegrenzen van het NGI.',
|
||||
tokens: ['administrative', 'adminvector', 'belgium_land_boundary', 'belgium_regions', 'belgium_provinces', 'belgium_municipalities'],
|
||||
},
|
||||
{
|
||||
id: 'buildings',
|
||||
label: 'Bebouwing',
|
||||
@@ -179,9 +207,24 @@ const DATA_THEMES: DataTheme[] = [
|
||||
description: 'Kadastrale of administratieve perceelcontouren.',
|
||||
tokens: ['parcels', 'parcel', 'percelen', 'perceel', 'cadastre', 'kadaster'],
|
||||
},
|
||||
{
|
||||
id: 'maritime_planning',
|
||||
label: 'Maritieme planning',
|
||||
shortLabel: 'Plan- en gebruikszones',
|
||||
description: 'Officiële gebruiks- en beschermingszones uit het Belgisch Marien Ruimtelijk Plan 2026-2034.',
|
||||
tokens: ['maritime_planning', 'marine_spatial_plan', 'rbins_msp', 'bmsp', 'imsp26'],
|
||||
},
|
||||
{
|
||||
id: 'marine_environment',
|
||||
label: 'Mariene rapportagezones',
|
||||
shortLabel: 'Zeegebieden',
|
||||
description: 'Officiële juridische en mariene rapportagegebieden voor het Belgische deel van de Noordzee.',
|
||||
tokens: ['marine_environment', 'marine_legal_scopes', 'marine_reporting_units', 'rbins_marine_reporting'],
|
||||
},
|
||||
]
|
||||
|
||||
const COVERAGE_THEME_BY_MAP_THEME: Record<DataThemeId, string> = {
|
||||
administrative: 'admin',
|
||||
buildings: 'buildings',
|
||||
space_occupation: 'land_cover_use',
|
||||
open_space: 'land_cover_use',
|
||||
@@ -198,6 +241,8 @@ const COVERAGE_THEME_BY_MAP_THEME: Record<DataThemeId, string> = {
|
||||
services: 'population',
|
||||
roads: 'roads',
|
||||
parcels: 'parcels',
|
||||
maritime_planning: 'maritime_planning',
|
||||
marine_environment: 'marine_environment',
|
||||
}
|
||||
|
||||
function coverageStatusLabel(status: CoverageStatus): string {
|
||||
@@ -225,6 +270,7 @@ function coverageZoneLabel(zone: string): string {
|
||||
}
|
||||
|
||||
const DATA_THEME_MAP_STYLES: Record<DataThemeId, { fill: string; line: string }> = {
|
||||
administrative: { fill: '#5f6f7f', line: '#344554' },
|
||||
buildings: { fill: '#d45f3d', line: '#9f3e24' },
|
||||
space_occupation: { fill: '#be3e33', line: '#8f2c24' },
|
||||
open_space: { fill: '#267a46', line: '#175c32' },
|
||||
@@ -241,6 +287,8 @@ const DATA_THEME_MAP_STYLES: Record<DataThemeId, { fill: string; line: string }>
|
||||
services: { fill: '#b66d16', line: '#854d0e' },
|
||||
roads: { fill: '#6b7280', line: '#4b5563' },
|
||||
parcels: { fill: '#a7792f', line: '#7d571f' },
|
||||
maritime_planning: { fill: '#2f7f8f', line: '#145d6a' },
|
||||
marine_environment: { fill: '#3475a3', line: '#1c557d' },
|
||||
}
|
||||
|
||||
function datasetAvailabilityLabel(
|
||||
@@ -274,6 +322,15 @@ function datasetAvailabilityLabel(
|
||||
const resolutionLabel = Number.isFinite(resolution) ? `${resolution.toLocaleString('nl-BE')} m` : 'Raster'
|
||||
return `${resolutionLabel} officiële bron${Number.isFinite(year) ? ` · ${year}` : ''}`
|
||||
}
|
||||
if (dataset.source_name === 'ngi_adminvector') {
|
||||
return `${(dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0).toLocaleString('nl-BE')} officiële bestuursgebieden`
|
||||
}
|
||||
if (dataset.source_name === 'rbins_msp_2026') {
|
||||
return `${(dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0).toLocaleString('nl-BE')} officiële planobjecten · 2026-2034`
|
||||
}
|
||||
if (dataset.source_name === 'rbins_marine_reporting_units') {
|
||||
return `${(dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0).toLocaleString('nl-BE')} officiële zeegebieden`
|
||||
}
|
||||
return `${(dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0).toLocaleString('nl-BE')} objecten beschikbaar`
|
||||
}
|
||||
|
||||
@@ -313,6 +370,15 @@ function datasetMatchesTheme(dataset: DatasetCreateResponse, theme: DataTheme):
|
||||
if (dataset.source_name === 'dov_soil_map') {
|
||||
return theme.id === 'soil'
|
||||
}
|
||||
if (dataset.source_name === 'ngi_adminvector') {
|
||||
return theme.id === 'administrative'
|
||||
}
|
||||
if (dataset.source_name === 'rbins_msp_2026') {
|
||||
return theme.id === 'maritime_planning'
|
||||
}
|
||||
if (dataset.source_name === 'rbins_marine_reporting_units') {
|
||||
return theme.id === 'marine_environment'
|
||||
}
|
||||
const searchText = datasetSearchText(dataset)
|
||||
return theme.tokens.some((token) => searchText.includes(token))
|
||||
}
|
||||
@@ -342,8 +408,17 @@ function datasetProductKey(dataset: DatasetCreateResponse): string {
|
||||
function datasetCoversSelectedArea(
|
||||
dataset: DatasetCreateResponse,
|
||||
selectedAreaId: string | null,
|
||||
selectedAreaName: string | null | undefined,
|
||||
regionalScope = false,
|
||||
): boolean {
|
||||
const selectedZones = selectedAreaCoverageZones(selectedAreaName)
|
||||
const configuredZones = dataset.source_metadata?.['coverage_zones']
|
||||
if (selectedZones && Array.isArray(configuredZones) && configuredZones.length > 0) {
|
||||
const datasetZones = configuredZones.map((zone) => String(zone))
|
||||
if (!selectedZones.some((zone) => datasetZones.includes(zone))) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
const coverageScope = String(dataset.source_metadata?.['coverage_scope'] ?? '')
|
||||
if (isPartitionedBathymetry(dataset)) {
|
||||
return regionalScope
|
||||
@@ -363,6 +438,7 @@ function rasterPartitionsForDataset(
|
||||
datasets: DatasetCreateResponse[],
|
||||
representative: DatasetCreateResponse | null,
|
||||
selectedAreaId: string | null,
|
||||
selectedAreaName: string | null | undefined,
|
||||
regionalScope: boolean,
|
||||
): DatasetCreateResponse[] {
|
||||
if (!representative) {
|
||||
@@ -382,7 +458,7 @@ function rasterPartitionsForDataset(
|
||||
? String(dataset.source_metadata?.['partition_manifest_sha256'] ?? '') === manifestSha256
|
||||
: datasetProductKey(dataset) === productKey
|
||||
)
|
||||
&& datasetCoversSelectedArea(dataset, selectedAreaId, true),
|
||||
&& datasetCoversSelectedArea(dataset, selectedAreaId, selectedAreaName, true),
|
||||
)
|
||||
.sort((left, right) => String(left.area_id ?? '').localeCompare(String(right.area_id ?? '')))
|
||||
}
|
||||
@@ -391,12 +467,13 @@ function pickThemeDataset(
|
||||
datasets: DatasetCreateResponse[],
|
||||
theme: DataTheme,
|
||||
selectedAreaId: string | null,
|
||||
selectedAreaName: string | null | undefined,
|
||||
regionalScope = false,
|
||||
): DatasetCreateResponse | null {
|
||||
const candidates = datasets.filter(
|
||||
(dataset) =>
|
||||
datasetMatchesTheme(dataset, theme)
|
||||
&& datasetCoversSelectedArea(dataset, selectedAreaId, regionalScope),
|
||||
&& datasetCoversSelectedArea(dataset, selectedAreaId, selectedAreaName, regionalScope),
|
||||
)
|
||||
candidates.sort((left, right) => {
|
||||
const priorityScore = (dataset: DatasetCreateResponse) =>
|
||||
@@ -723,7 +800,15 @@ export function MapWorkspace({
|
||||
})
|
||||
const activeScopeProject = projects.find((project) => project.id === selectedProjectId) ?? null
|
||||
const activeScopeLabel = activeScopeProject ? operationalScopeProjectLabel(activeScopeProject) : 'Werkgebied'
|
||||
const flandersScopeSelected = activeScopeProject?.name === FLANDERS_WORKSPACE_PROJECT_NAME
|
||||
const selectedMapArea = areas.find((area) => area.id === selectedMapAreaId)
|
||||
const selectedCoverageZones = useMemo(
|
||||
() => selectedAreaCoverageZones(selectedMapArea?.name),
|
||||
[selectedMapArea?.name],
|
||||
)
|
||||
const flandersScopeSelected = Boolean(
|
||||
selectedCoverageZones?.includes('flanders')
|
||||
|| (!selectedCoverageZones && activeScopeProject?.name === FLANDERS_WORKSPACE_PROJECT_NAME),
|
||||
)
|
||||
const {
|
||||
themeInsights,
|
||||
themeInsightsLoading: themeResultsLoading,
|
||||
@@ -735,7 +820,8 @@ export function MapWorkspace({
|
||||
products: officialMapProducts,
|
||||
loading: officialMapProductsLoading,
|
||||
error: officialMapProductsError,
|
||||
} = useOfficialMapProducts(flandersScopeSelected ? selectedProjectId : null)
|
||||
resolveCoverage,
|
||||
} = useOfficialMapProducts(selectedProjectId)
|
||||
const {
|
||||
temporalComparison,
|
||||
temporalComparisonLoading,
|
||||
@@ -759,7 +845,6 @@ export function MapWorkspace({
|
||||
const [fullWorkflowMode, setFullWorkflowMode] = useState<'new' | 'reuse'>('new')
|
||||
const [mapAnalysisDurationMs, setMapAnalysisDurationMs] = useState<number | null>(null)
|
||||
const mapAnalysisRequestSequence = useRef(0)
|
||||
const selectedMapArea = areas.find((area) => area.id === selectedMapAreaId)
|
||||
const regionalScopeSelected = Boolean(selectedMapArea && !isMunicipalityAreaName(selectedMapArea.name))
|
||||
const featureProperties = selectedMapFeature?.properties ?? null
|
||||
const isBathymetryProfile = featureProperties?.['provider'] === 'vmm_vha_bathymetry_profiles'
|
||||
@@ -794,7 +879,7 @@ export function MapWorkspace({
|
||||
.filter(
|
||||
(dataset) =>
|
||||
dataset.source_name === 'vmm_flood_hazard'
|
||||
&& datasetCoversSelectedArea(dataset, selectedMapAreaId, regionalScopeSelected),
|
||||
&& datasetCoversSelectedArea(dataset, selectedMapAreaId, selectedMapArea?.name, regionalScopeSelected),
|
||||
)
|
||||
.sort((left, right) => floodScenarioLabel(left).localeCompare(floodScenarioLabel(right), 'nl'))
|
||||
if (!regionalScopeSelected) {
|
||||
@@ -809,13 +894,19 @@ export function MapWorkspace({
|
||||
}
|
||||
return Array.from(products.values())
|
||||
},
|
||||
[availableMapDatasets, regionalScopeSelected, selectedMapAreaId],
|
||||
[availableMapDatasets, regionalScopeSelected, selectedMapArea?.name, selectedMapAreaId],
|
||||
)
|
||||
const themeDatasetMap = useMemo(() => {
|
||||
const result = Object.fromEntries(
|
||||
DATA_THEMES.map((theme) => [
|
||||
theme.id,
|
||||
pickThemeDataset(availableMapDatasets, theme, selectedMapAreaId, regionalScopeSelected),
|
||||
pickThemeDataset(
|
||||
availableMapDatasets,
|
||||
theme,
|
||||
selectedMapAreaId,
|
||||
selectedMapArea?.name,
|
||||
regionalScopeSelected,
|
||||
),
|
||||
]),
|
||||
) as Record<DataThemeId, DatasetCreateResponse | null>
|
||||
const selectedFloodHazard = floodHazardDatasets.find(
|
||||
@@ -833,7 +924,7 @@ export function MapWorkspace({
|
||||
(dataset) =>
|
||||
dataset.source_name === 'digitaal_vlaanderen_dhmv'
|
||||
&& datasetProductKey(dataset) === selectedDhmvProductKey
|
||||
&& datasetCoversSelectedArea(dataset, selectedMapAreaId, regionalScopeSelected),
|
||||
&& datasetCoversSelectedArea(dataset, selectedMapAreaId, selectedMapArea?.name, regionalScopeSelected),
|
||||
) ?? null
|
||||
}
|
||||
if (flandersScopeSelected && officialMapProducts.thematic.length > 0) {
|
||||
@@ -846,8 +937,10 @@ export function MapWorkspace({
|
||||
result[product.key] = null
|
||||
}
|
||||
}
|
||||
if (flandersScopeSelected && officialMapProducts.officialVector.length > 0) {
|
||||
for (const product of officialMapProducts.officialVector) {
|
||||
if (officialMapProducts.officialVector.length > 0) {
|
||||
for (const product of officialMapProducts.officialVector.filter((item) =>
|
||||
productCoversZones(item.coverage_zones, selectedCoverageZones),
|
||||
)) {
|
||||
result[product.theme] = null
|
||||
}
|
||||
}
|
||||
@@ -865,7 +958,9 @@ export function MapWorkspace({
|
||||
selectedDhmvProductKey,
|
||||
selectedFloodHazardDatasetId,
|
||||
selectedFloodHazardProductKey,
|
||||
selectedMapArea?.name,
|
||||
selectedMapAreaId,
|
||||
selectedCoverageZones,
|
||||
])
|
||||
const themePartitionMap = useMemo(
|
||||
() =>
|
||||
@@ -876,11 +971,12 @@ export function MapWorkspace({
|
||||
availableMapDatasets,
|
||||
themeDatasetMap[theme.id],
|
||||
selectedMapAreaId,
|
||||
selectedMapArea?.name,
|
||||
regionalScopeSelected,
|
||||
),
|
||||
]),
|
||||
) as Record<DataThemeId, DatasetCreateResponse[]>,
|
||||
[availableMapDatasets, regionalScopeSelected, selectedMapAreaId, themeDatasetMap],
|
||||
[availableMapDatasets, regionalScopeSelected, selectedMapArea?.name, selectedMapAreaId, themeDatasetMap],
|
||||
)
|
||||
const activeTheme = DATA_THEMES.find((theme) => theme.id === activeThemeId) ?? DATA_THEMES[0]
|
||||
const activeCoverageTheme = COVERAGE_THEME_BY_MAP_THEME[activeTheme.id]
|
||||
@@ -892,14 +988,16 @@ export function MapWorkspace({
|
||||
) ?? { operational: 0, partial: 0, not_configured: 0, unsupported: 0 },
|
||||
[coverage],
|
||||
)
|
||||
const onDemandProductMap = useMemo(
|
||||
() => {
|
||||
const result = new Map<DataThemeId, OnDemandMapProduct>()
|
||||
if (!flandersScopeSelected) {
|
||||
return result
|
||||
}
|
||||
const onDemandProductsForZones = useCallback((zones: string[] | null): OnDemandMapProduct[] => {
|
||||
const result: OnDemandMapProduct[] = []
|
||||
const effectiveZones = zones ?? selectedCoverageZones
|
||||
const includesFlanders = Boolean(
|
||||
effectiveZones?.includes('flanders')
|
||||
|| (!effectiveZones && activeScopeProject?.name === FLANDERS_WORKSPACE_PROJECT_NAME),
|
||||
)
|
||||
if (includesFlanders) {
|
||||
for (const product of officialMapProducts.thematic) {
|
||||
result.set(product.theme, {
|
||||
result.push({
|
||||
kind: 'thematic_raster',
|
||||
productKey: product.key,
|
||||
displayName: product.display_name,
|
||||
@@ -910,7 +1008,7 @@ export function MapWorkspace({
|
||||
})
|
||||
}
|
||||
for (const product of officialMapProducts.grb) {
|
||||
result.set(product.key, {
|
||||
result.push({
|
||||
kind: 'grb',
|
||||
productKey: product.key,
|
||||
displayName: product.display_name,
|
||||
@@ -920,52 +1018,65 @@ export function MapWorkspace({
|
||||
limitationMessage: product.limitation_message,
|
||||
})
|
||||
}
|
||||
for (const product of officialMapProducts.officialVector) {
|
||||
result.set(product.theme, {
|
||||
kind: 'official_vector',
|
||||
productKey: product.key,
|
||||
displayName: product.display_name,
|
||||
theme: product.theme,
|
||||
availabilityLabel: `${product.observation_label} · officiële vectorbron · laad bij selectie`,
|
||||
attribution: product.attribution,
|
||||
limitationMessage: product.limitation_message,
|
||||
})
|
||||
}
|
||||
const dhmvProduct = officialMapProducts.dhmv.find((product) => product.key === selectedDhmvProductKey)
|
||||
if (dhmvProduct) {
|
||||
result.set('elevation', {
|
||||
kind: 'dhmv',
|
||||
productKey: dhmvProduct.key,
|
||||
displayName: dhmvProduct.display_name,
|
||||
theme: 'elevation',
|
||||
availabilityLabel: `${dhmvProduct.native_resolution_m} m · ${dhmvProduct.acquisition_period} · laad bij selectie`,
|
||||
attribution: dhmvProduct.attribution,
|
||||
limitationMessage: dhmvProduct.limitation_message,
|
||||
})
|
||||
}
|
||||
const floodProduct = officialMapProducts.floodHazard.find(
|
||||
(product) => product.key === selectedFloodHazardProductKey,
|
||||
)
|
||||
if (floodProduct) {
|
||||
result.set('flood_hazard', {
|
||||
kind: 'flood_hazard',
|
||||
productKey: floodProduct.key,
|
||||
displayName: floodProduct.display_name,
|
||||
theme: 'flood_hazard',
|
||||
availabilityLabel: `${floodProduct.native_resolution_m} m · ${floodProduct.climate_context} · T${floodProduct.return_period_years} · laad bij selectie`,
|
||||
attribution: floodProduct.attribution,
|
||||
limitationMessage: floodProduct.limitation_message,
|
||||
})
|
||||
}
|
||||
return result
|
||||
},
|
||||
[
|
||||
flandersScopeSelected,
|
||||
officialMapProducts,
|
||||
selectedDhmvProductKey,
|
||||
selectedFloodHazardProductKey,
|
||||
],
|
||||
)
|
||||
}
|
||||
for (const product of officialMapProducts.officialVector.filter((item) =>
|
||||
productCoversZones(item.coverage_zones, effectiveZones),
|
||||
)) {
|
||||
result.push({
|
||||
kind: 'official_vector',
|
||||
productKey: product.key,
|
||||
displayName: product.display_name,
|
||||
theme: product.theme,
|
||||
availabilityLabel: `${product.observation_label} · officiële vectorbron · laad bij selectie`,
|
||||
attribution: product.attribution,
|
||||
limitationMessage: product.limitation_message,
|
||||
})
|
||||
}
|
||||
const dhmvProduct = includesFlanders
|
||||
? officialMapProducts.dhmv.find((product) => product.key === selectedDhmvProductKey)
|
||||
: null
|
||||
if (dhmvProduct) {
|
||||
result.push({
|
||||
kind: 'dhmv',
|
||||
productKey: dhmvProduct.key,
|
||||
displayName: dhmvProduct.display_name,
|
||||
theme: 'elevation',
|
||||
availabilityLabel: `${dhmvProduct.native_resolution_m} m · ${dhmvProduct.acquisition_period} · laad bij selectie`,
|
||||
attribution: dhmvProduct.attribution,
|
||||
limitationMessage: dhmvProduct.limitation_message,
|
||||
})
|
||||
}
|
||||
const floodProduct = includesFlanders
|
||||
? officialMapProducts.floodHazard.find(
|
||||
(product) => product.key === selectedFloodHazardProductKey,
|
||||
)
|
||||
: null
|
||||
if (floodProduct) {
|
||||
result.push({
|
||||
kind: 'flood_hazard',
|
||||
productKey: floodProduct.key,
|
||||
displayName: floodProduct.display_name,
|
||||
theme: 'flood_hazard',
|
||||
availabilityLabel: `${floodProduct.native_resolution_m} m · ${floodProduct.climate_context} · T${floodProduct.return_period_years} · laad bij selectie`,
|
||||
attribution: floodProduct.attribution,
|
||||
limitationMessage: floodProduct.limitation_message,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}, [
|
||||
activeScopeProject?.name,
|
||||
officialMapProducts,
|
||||
selectedCoverageZones,
|
||||
selectedDhmvProductKey,
|
||||
selectedFloodHazardProductKey,
|
||||
])
|
||||
const onDemandProductMap = useMemo(() => {
|
||||
const result = new Map<DataThemeId, OnDemandMapProduct>()
|
||||
for (const product of onDemandProductsForZones(selectedCoverageZones)) {
|
||||
result.set(product.theme, product)
|
||||
}
|
||||
return result
|
||||
}, [onDemandProductsForZones, selectedCoverageZones])
|
||||
const activeOnDemandMapProduct = onDemandProductMap.get(activeTheme.id) ?? null
|
||||
const activeThemeMapStyle = DATA_THEME_MAP_STYLES[activeTheme.id]
|
||||
const analysisOverlayActive = mapContentMode === 'analysis' && analysisLayerAvailable && Boolean(mapFeatureCollection)
|
||||
@@ -993,15 +1104,20 @@ export function MapWorkspace({
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!flandersScopeSelected
|
||||
|| analysisMode !== 'current'
|
||||
analysisMode !== 'current'
|
||||
|| activeThemeAvailable
|
||||
|| (onDemandProductMap.size === 0 && !officialMapProductsError)
|
||||
|| (
|
||||
selectedProjectId
|
||||
&& officialMapProductsLoading
|
||||
&& onDemandProductMap.size === 0
|
||||
&& !officialMapProductsError
|
||||
)
|
||||
) {
|
||||
return
|
||||
}
|
||||
const fallbackTheme = DATA_THEMES.find((theme) =>
|
||||
theme.id === 'space_occupation'
|
||||
flandersScopeSelected
|
||||
&& theme.id === 'space_occupation'
|
||||
&& Boolean(themeDatasetMap[theme.id] || onDemandProductMap.get(theme.id)),
|
||||
) ?? DATA_THEMES.find((theme) =>
|
||||
Boolean(themeDatasetMap[theme.id] || onDemandProductMap.get(theme.id)),
|
||||
@@ -1019,8 +1135,10 @@ export function MapWorkspace({
|
||||
analysisMode,
|
||||
flandersScopeSelected,
|
||||
officialMapProductsError,
|
||||
officialMapProductsLoading,
|
||||
onDemandProductMap,
|
||||
onOpenDatasetInMap,
|
||||
selectedProjectId,
|
||||
themeDatasetMap,
|
||||
])
|
||||
|
||||
@@ -1528,20 +1646,37 @@ export function MapWorkspace({
|
||||
}
|
||||
|
||||
const loadAllThemeResults = async (bbox: VectorSelectionBBox, areaId?: string) => {
|
||||
let resolvedZones = selectedCoverageZones
|
||||
if (analysisMode === 'current' && selectedProjectId) {
|
||||
const resolvedCoverage = await resolveCoverage({
|
||||
minx: bbox.min_x,
|
||||
miny: bbox.min_y,
|
||||
maxx: bbox.max_x,
|
||||
maxy: bbox.max_y,
|
||||
})
|
||||
if (!resolvedCoverage) {
|
||||
clearThemeInsights()
|
||||
return
|
||||
}
|
||||
resolvedZones = resolvedCoverage.intersected_zones
|
||||
}
|
||||
const resolvedProducts = analysisMode === 'current'
|
||||
? onDemandProductsForZones(resolvedZones)
|
||||
: []
|
||||
const availableThemes: Array<MapThemeQuery<DataThemeId>> = []
|
||||
for (const theme of DATA_THEMES) {
|
||||
const onDemandProduct = analysisMode === 'current'
|
||||
? onDemandProductMap.get(theme.id)
|
||||
: null
|
||||
if (onDemandProduct) {
|
||||
availableThemes.push({
|
||||
themeId: theme.id,
|
||||
acquisition: {
|
||||
kind: onDemandProduct.kind,
|
||||
productKey: onDemandProduct.productKey,
|
||||
displayName: onDemandProduct.displayName,
|
||||
},
|
||||
})
|
||||
const onDemandProducts = resolvedProducts.filter((product) => product.theme === theme.id)
|
||||
if (onDemandProducts.length > 0) {
|
||||
for (const onDemandProduct of onDemandProducts) {
|
||||
availableThemes.push({
|
||||
themeId: theme.id,
|
||||
acquisition: {
|
||||
kind: onDemandProduct.kind,
|
||||
productKey: onDemandProduct.productKey,
|
||||
displayName: onDemandProduct.displayName,
|
||||
},
|
||||
})
|
||||
}
|
||||
continue
|
||||
}
|
||||
const dataset = themeDatasetMap[theme.id]
|
||||
@@ -1856,10 +1991,10 @@ export function MapWorkspace({
|
||||
: activeTheme.description}
|
||||
</small>
|
||||
</div>
|
||||
{officialMapProductsLoading && flandersScopeSelected ? (
|
||||
{officialMapProductsLoading && selectedProjectId ? (
|
||||
<p className="geo-data-notice">Beschikbare Vlaamse kaartbronnen worden gecontroleerd…</p>
|
||||
) : null}
|
||||
{officialMapProductsError && flandersScopeSelected ? (
|
||||
{officialMapProductsError && selectedProjectId ? (
|
||||
<p className="error">{officialMapProductsError}</p>
|
||||
) : null}
|
||||
|
||||
@@ -1877,7 +2012,12 @@ export function MapWorkspace({
|
||||
(item) =>
|
||||
item.source_name === 'digitaal_vlaanderen_dhmv'
|
||||
&& datasetProductKey(item) === productKey
|
||||
&& datasetCoversSelectedArea(item, selectedMapAreaId, regionalScopeSelected),
|
||||
&& datasetCoversSelectedArea(
|
||||
item,
|
||||
selectedMapAreaId,
|
||||
selectedMapArea?.name,
|
||||
regionalScopeSelected,
|
||||
),
|
||||
)
|
||||
if (dataset) {
|
||||
onOpenDatasetInMap(dataset)
|
||||
|
||||
Reference in New Issue
Block a user