Harden RC9 UX and performance states
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-18 06:37:54 +02:00
parent 55685ba1bd
commit 9b0239747d
21 changed files with 845 additions and 25 deletions
+44 -4
View File
@@ -76,8 +76,13 @@ function App(): JSX.Element {
const [mapContextSourceLabel, setMapContextSourceLabel] = useState<string | null>(null)
const [mapContextLayerLabel, setMapContextLayerLabel] = useState<string | null>(null)
const workbenchMainRef = useRef<HTMLElement | null>(null)
const previousWorkspaceRef = useRef<WorkspaceKey>(activeWorkspace)
useEffect(() => {
workbenchMainRef.current?.scrollTo({ top: 0, left: 0 })
if (previousWorkspaceRef.current !== activeWorkspace) {
workbenchMainRef.current?.focus({ preventScroll: true })
}
previousWorkspaceRef.current = activeWorkspace
setInspectorOpen(false)
}, [activeWorkspace])
const {
@@ -482,6 +487,8 @@ function App(): JSX.Element {
coverage: mapCoverage,
loadingCoverage: mapCoverageLoading,
coverageError: mapCoverageError,
coverageDurationMs: mapCoverageDurationMs,
coverageBudgetExceeded: mapCoverageBudgetExceeded,
} = useCoverageResolver({
projectId: selectedProjectId,
bbox: mapSelectionBbox,
@@ -715,12 +722,22 @@ function App(): JSX.Element {
const bathymetryProfileCount = regionalBathymetryContextActive
? regionalBathymetryProfileCount
: selectedDataset?.feature_count ?? selectedDataset?.vector_summary?.feature_count ?? 0
const workspaceDataLoading = loadingProjects || loadingAreas || loadingDatasets
const workspaceStatusMessage = errorMessage
? `Werkruimtefout: ${errorMessage}`
: workspaceDataLoading
? 'Werkruimte en databronnen worden geladen.'
: selectedProject
? `${projectContextLabel} is geladen met ${datasets.length} databronnen en ${areas.length} gebieden.`
: 'Geen werkruimte geselecteerd.'
const datasetContextLabel = activeWorkspace === 'map' && mapContextSourceLabel
? mapContextSourceLabel
: analysisMapLayerActive && mapFeatureCollection
? `${mapLayerLabel} · controle vereist`
: selectedDataset
? getDatasetDisplayName(selectedDataset)
: workspaceDataLoading
? 'Bronnen worden geladen'
: datasets.length > 0
? 'Kies een bron'
: 'Geen bron'
@@ -732,6 +749,8 @@ function App(): JSX.Element {
: `${bathymetryProfileCount.toLocaleString('nl-BE')} profielen`
: mapFeatureCollection
? `${mapFeatureCount.toLocaleString('nl-BE')} objecten`
: workspaceDataLoading
? 'Kaart wordt voorbereid'
: viewportVectorLayerActive
? 'Kaartlaag gekozen'
: activeWorkspace === 'map' && selectedDataset?.dataset_type === 'raster'
@@ -740,7 +759,13 @@ function App(): JSX.Element {
return (
<div className="app-shell workbench-shell">
<a className="skip-link" href="#workspace-main">
<a
className="skip-link"
href="#workspace-main"
onClick={() => {
window.requestAnimationFrame(() => workbenchMainRef.current?.focus({ preventScroll: true }))
}}
>
Ga naar de werkruimte
</a>
<header className="workbench-topbar">
@@ -771,7 +796,8 @@ function App(): JSX.Element {
</div>
</header>
{errorMessage ? <p className="error">{errorMessage}</p> : null}
<p className="sr-only" role="status" aria-live="polite">{workspaceStatusMessage}</p>
{errorMessage ? <p className="error" role="alert">{errorMessage}</p> : null}
<div className="workbench-layout">
<aside className="workbench-sidebar" aria-label="Navigatie van de werkruimte">
@@ -804,7 +830,13 @@ function App(): JSX.Element {
</nav>
</aside>
<main ref={workbenchMainRef} className="workbench-main" id="workspace-main" tabIndex={-1}>
<main
ref={workbenchMainRef}
className="workbench-main"
id="workspace-main"
tabIndex={-1}
aria-busy={workspaceDataLoading}
>
{activeWorkspace !== 'map' ? <div className="workspace-heading">
<div className="workspace-heading-copy">
<p className="eyebrow">{selectedProject?.region ?? 'Mol, Kempen'}</p>
@@ -861,7 +893,11 @@ function App(): JSX.Element {
{activeWorkspace === 'data' ? (
<div className="workspace-grid workspace-grid-data">
<SourceCatalogPanel datasets={datasets} projectId={selectedProjectId ?? undefined} />
<SourceCatalogPanel
datasets={datasets}
projectId={selectedProjectId ?? undefined}
loading={loadingDatasets}
/>
<ProjectPanel
projects={projects}
selectedProjectId={selectedProjectId}
@@ -943,6 +979,10 @@ function App(): JSX.Element {
coverage={mapCoverage}
coverageLoading={mapCoverageLoading}
coverageError={mapCoverageError}
coverageDurationMs={mapCoverageDurationMs}
coverageBudgetExceeded={mapCoverageBudgetExceeded}
workspaceLoading={workspaceDataLoading}
workspaceError={errorMessage}
selectionExporting={selectionExporting}
selectionExportError={selectionExportError}
latestSelectionExportPath={latestSelectionExport?.path ?? null}