Update
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:
Jens
2026-07-27 23:28:43 +02:00
parent 21015757bd
commit c76a746cd7
39 changed files with 3268 additions and 519 deletions
+65 -37
View File
@@ -697,6 +697,7 @@ function floodScenarioLabel(dataset: DatasetCreateResponse): string {
}
interface MapWorkspaceProps {
readOnly?: boolean
selectedProjectId: string | null
projects: ProjectRead[]
areas: AreaRead[]
@@ -791,6 +792,7 @@ interface MapWorkspaceProps {
}
export function MapWorkspace({
readOnly = false,
selectedProjectId,
projects,
areas,
@@ -884,6 +886,9 @@ export function MapWorkspace({
onOpenExports,
}: MapWorkspaceProps): JSX.Element {
const [advancedMode, setAdvancedMode] = useState(false)
useEffect(() => {
if (readOnly && advancedMode) setAdvancedMode(false)
}, [advancedMode, readOnly])
const [activeThemeId, setActiveThemeId] = useState<DataThemeId>(() => {
const selectedDataset = availableMapDatasets.find((dataset) => dataset.id === selectedMapDatasetId) ?? null
return themeIdForDataset(selectedDataset) ?? 'buildings'
@@ -2213,27 +2218,39 @@ export function MapWorkspace({
Evolutie
</button>
</div>
<button
className="secondary-action geo-explorer-advanced"
type="button"
onClick={() => setAdvancedMode(true)}
aria-expanded={advancedMode}
aria-controls="geo-advanced-workbench"
aria-label="Geavanceerde werkbank"
title="Geavanceerde werkbank"
>
<SlidersHorizontal aria-hidden="true" />
<span>Geavanceerde werkbank</span>
</button>
{!readOnly ? (
<button
className="secondary-action geo-explorer-advanced"
type="button"
onClick={() => setAdvancedMode(true)}
aria-expanded={advancedMode}
aria-controls="geo-advanced-workbench"
aria-label="Geavanceerde werkbank"
title="Geavanceerde werkbank"
>
<SlidersHorizontal aria-hidden="true" />
<span>Geavanceerde werkbank</span>
</button>
) : null}
</div>
</header>
<MunicipalitySearch
projectId={selectedProjectId}
activeArea={selectedMapArea ?? null}
disabled={workspaceLoading}
onActivate={onActivateMunicipality}
/>
{readOnly ? (
<div className="geo-guest-preview-note" role="note">
<MapPinned aria-hidden="true" />
<div>
<strong>Interactieve demo met bewaarde voorbeelddata</strong>
<span>U kunt kaartlagen verkennen, een selectie meten en kwaliteitsbewijs bekijken. Nieuwe gebieden, bronimports en bewaarde analyses zijn uitgeschakeld.</span>
</div>
</div>
) : (
<MunicipalitySearch
projectId={selectedProjectId}
activeArea={selectedMapArea ?? null}
disabled={workspaceLoading}
onActivate={onActivateMunicipality}
/>
)}
{workspaceLoading ? (
<div className="geo-bootstrap-status" role="status" aria-live="polite">
@@ -2266,6 +2283,8 @@ export function MapWorkspace({
<small>
{workspaceLoading
? 'Gebieden en bronnen worden geladen'
: readOnly
? `${municipalityAreaCount || 1} vooraf ingestelde demogrens; vrije kaartselectie blijft beschikbaar`
: municipalityAreaCount > 0
? `${municipalityAreaCount} geactiveerde gemeentegrenzen; vrij tekenen blijft mogelijk`
: 'Zoek optioneel een gemeente of teken vrij op de kaart'}
@@ -2280,7 +2299,7 @@ export function MapWorkspace({
const temporalGroup = temporalGroups[0]
const evolutionAvailable = temporalGroups.some((group) => group.items.length >= 2)
const available = !workspaceLoading && (analysisMode === 'current'
? Boolean(dataset || onDemandProduct)
? Boolean(dataset || (!readOnly && onDemandProduct))
: Boolean(dataset) && evolutionAvailable)
const active = activeThemeId === theme.id
const temporalRange = temporalGroup ? temporalRangeLabel(temporalGroup.items) : null
@@ -2308,7 +2327,7 @@ export function MapWorkspace({
: dataset
? `${datasetAvailabilityLabel(dataset, partitions)}${onDemandProduct ? ' · zo nodig automatisch aangevuld' : ''}`
: onDemandProduct
? onDemandProduct.availabilityLabel
? readOnly ? 'Niet opgenomen in deze demo' : onDemandProduct.availabilityLabel
: 'Bron nog niet ingeladen'}
</small>
</span>
@@ -2317,7 +2336,7 @@ export function MapWorkspace({
? 'Laden'
: analysisMode === 'evolution'
? evolutionAvailable ? 'Tijdreeks' : dataset ? 'Alleen huidig' : 'Ontbreekt'
: dataset ? 'Beschikbaar' : onDemandProduct ? 'Automatisch' : 'Ontbreekt'}
: dataset ? 'Beschikbaar' : onDemandProduct ? readOnly ? 'Niet in demo' : 'Automatisch' : 'Ontbreekt'}
</i>
</button>
)
@@ -2648,7 +2667,7 @@ export function MapWorkspace({
</div>
</div>
{analysisMode === 'current' && activeTheme.id === 'buildings' && mapSelectionBbox ? (
{!readOnly && analysisMode === 'current' && activeTheme.id === 'buildings' && mapSelectionBbox ? (
<div className={`geo-image-analysis geo-image-analysis-${orthophotoAnalysisStage}`}>
<div>
<span>Beeldanalyse</span>
@@ -2914,21 +2933,30 @@ export function MapWorkspace({
) : null}
{activeSelectionResult || temporalComparison ? (
<div className="geo-result-next-actions" aria-label="Volgende stap">
<span>
<strong>Analyse klaar</strong>
<small>Stel een vraag over dit gebied of open je bewaarde resultaten.</small>
</span>
<button className="primary-action" type="button" onClick={onOpenAssistant}>Stel AI-vraag</button>
<button
className="secondary-action"
type="button"
disabled={selectionExporting}
onClick={() => void persistActiveResultAndOpenDownloads()}
>
{selectionExporting ? 'Resultaat bewaren…' : 'Bewaar in downloads'}
</button>
</div>
readOnly ? (
<div className="geo-result-next-actions geo-result-next-actions-readonly" aria-label="Gastresultaat">
<span>
<strong>Analyse klaar</strong>
<small>Dit resultaat blijft tijdelijk in de browser. Meld u aan als operator om analyses te bewaren of verder te verwerken.</small>
</span>
</div>
) : (
<div className="geo-result-next-actions" aria-label="Volgende stap">
<span>
<strong>Analyse klaar</strong>
<small>Stel een vraag over dit gebied of open je bewaarde resultaten.</small>
</span>
<button className="primary-action" type="button" onClick={onOpenAssistant}>Stel AI-vraag</button>
<button
className="secondary-action"
type="button"
disabled={selectionExporting}
onClick={() => void persistActiveResultAndOpenDownloads()}
>
{selectionExporting ? 'Resultaat bewaren…' : 'Bewaar in downloads'}
</button>
</div>
)
) : null}
</>
)}