Add Flemish bathymetry partition workflow
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-17 16:15:29 +02:00
parent 8ef42a23e5
commit 132c4feed8
34 changed files with 1862 additions and 27 deletions
+1 -1
View File
@@ -806,7 +806,7 @@ function App(): JSX.Element {
{activeWorkspace === 'data' ? (
<div className="workspace-grid workspace-grid-data">
<SourceCatalogPanel datasets={datasets} />
<SourceCatalogPanel datasets={datasets} projectId={selectedProjectId ?? undefined} />
<ProjectPanel
projects={projects}
selectedProjectId={selectedProjectId}
@@ -1,4 +1,6 @@
import type { DatasetCreateResponse } from '../../types'
import { useState } from 'react'
import { datasetsApi } from '../../services/api'
import type { BathymetrySourceProbeRead, DatasetCreateResponse } from '../../types'
import { getDatasetSourceDisplayName } from '../../lib/datasetDisplay'
import {
OFFICIAL_SOURCE_PORTFOLIO,
@@ -10,6 +12,7 @@ import {
interface SourceCatalogPanelProps {
datasets: DatasetCreateResponse[]
projectId?: string
}
const THEME_LABELS: Record<string, string> = {
@@ -63,7 +66,19 @@ function timelineSummary(
].filter(Boolean).join(' · ')
}
export function SourceCatalogPanel({ datasets }: SourceCatalogPanelProps): JSX.Element {
function mdkStatusLabel(status: BathymetrySourceProbeRead['status']): string {
if (status === 'reachable') return 'Service bereikbaar'
if (status === 'tls_error') return 'Geblokkeerd: certificaat'
if (status === 'endpoint_unavailable') return 'Service niet bereikbaar'
if (status === 'invalid_capabilities') return 'Ongeldige service-informatie'
if (status === 'disabled') return 'Controle uitgeschakeld'
return 'Configuratie controleren'
}
export function SourceCatalogPanel({ datasets, projectId }: SourceCatalogPanelProps): JSX.Element {
const [mdkProbe, setMdkProbe] = useState<BathymetrySourceProbeRead | null>(null)
const [mdkProbeLoading, setMdkProbeLoading] = useState(false)
const [mdkProbeError, setMdkProbeError] = useState<string | null>(null)
const ready = datasets.filter((dataset) => dataset.status === 'ready')
const waterinfoDatasets = ready.filter((dataset) => dataset.source_name === 'waterinfo')
const historicalOrthophotos = ready.filter(
@@ -135,6 +150,19 @@ export function SourceCatalogPanel({ datasets }: SourceCatalogPanelProps): JSX.E
}
})
const checkMdkReadiness = async (): Promise<void> => {
if (!projectId || mdkProbeLoading) return
setMdkProbeLoading(true)
setMdkProbeError(null)
try {
setMdkProbe(await datasetsApi.probeMdkBathymetry(projectId))
} catch (error) {
setMdkProbeError(error instanceof Error ? error.message : 'De Noordzee-bron kon niet worden gecontroleerd.')
} finally {
setMdkProbeLoading(false)
}
}
return (
<section className="workspace-panel source-catalog-panel" aria-label="Beschikbare databronnen">
<div className="panel-title-row">
@@ -264,6 +292,29 @@ export function SourceCatalogPanel({ datasets }: SourceCatalogPanelProps): JSX.E
</details>
) : null}
<details className="source-loaded-disclosure">
<summary>Maritieme bronstatus</summary>
<div className="source-catalog-loaded">
<article>
<strong>MDK-dieptemodel Belgische Noordzee</strong>
<span>{mdkProbe ? mdkStatusLabel(mdkProbe.status) : 'Nog niet live gecontroleerd'}</span>
<p>
{mdkProbe?.message ??
'Controleert uitsluitend de officiële service-informatie met geldige TLS. Er wordt geen raster gedownload.'}
</p>
{mdkProbeError ? <small className="error-text">{mdkProbeError}</small> : null}
<button
className="secondary-button"
type="button"
disabled={!projectId || mdkProbeLoading}
onClick={() => void checkMdkReadiness()}
>
{mdkProbeLoading ? 'Controleren...' : 'Controleer Noordzee-bron'}
</button>
</article>
</div>
</details>
<details className="source-opportunity-list">
<summary>Officiële bronnen die hierna kunnen worden ingeladen</summary>
<div className="source-opportunity-domains">
+5
View File
@@ -23,6 +23,7 @@ import type {
FloodHazardProductRead,
FloodHazardSelectionResponse,
BathymetryProfileAcquireRequest,
BathymetrySourceProbeRead,
BathymetrySourceRead,
DhmvProductRead,
TerrainSelectionResponse,
@@ -173,6 +174,10 @@ export const datasetsApi = {
apiGet<{ items: BathymetrySourceRead[]; total: number }>(
`/api/v1/projects/${projectId}/datasets/bathymetry/sources`,
),
probeMdkBathymetry: (projectId: string): Promise<BathymetrySourceProbeRead> =>
apiGet<BathymetrySourceProbeRead>(
`/api/v1/projects/${projectId}/datasets/bathymetry/sources/mdk_bcp_bathymetry/readiness`,
),
acquireBathymetryProfiles: (projectId: string, payload: BathymetryProfileAcquireRequest): Promise<JobRead> =>
apiPost<JobRead>(`/api/v1/projects/${projectId}/datasets/bathymetry/profiles/acquire`, payload),
acquireThematicRaster: (projectId: string, payload: ThematicRasterAcquireRequest): Promise<JobRead> =>
+25 -1
View File
@@ -459,7 +459,7 @@ export interface BathymetrySourceRead {
vertical_reference: string
horizontal_crs: string
native_resolution?: string | null
integration_status: 'operational' | 'available_not_integrated' | 'catalog_only'
integration_status: 'operational' | 'probe_only' | 'available_not_integrated' | 'catalog_only'
acquisition_supported: boolean
configured: boolean
service_url?: string | null
@@ -469,6 +469,30 @@ export interface BathymetrySourceRead {
limitation_message: string
}
export interface BathymetrySourceProbeRead {
source_key: 'mdk_bcp_bathymetry'
status:
| 'disabled'
| 'invalid_configuration'
| 'tls_error'
| 'endpoint_unavailable'
| 'invalid_capabilities'
| 'reachable'
configured_url: string
capabilities_url?: string | null
tls_verified: boolean
capabilities_reachable: boolean
acquisition_supported: false
wcs_version?: string | null
coverage_identifiers: string[]
advertised_formats: string[]
advertised_crs: string[]
response_sha256?: string | null
checked_at: string
message: string
limitation_message: string
}
export interface ThematicRasterAcquireRequest {
bbox: VectorSelectionBBox
area_id?: string | null