feat: add operator landing and login
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-22 20:10:21 +02:00
parent 36d137e224
commit 115f9850a7
27 changed files with 1448 additions and 8 deletions
+49 -1
View File
@@ -1,4 +1,5 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import { LogOut, UserRound } from 'lucide-react'
import '@fontsource/manrope/latin-500.css'
import '@fontsource/manrope/latin-600.css'
import '@fontsource/manrope/latin-700.css'
@@ -8,6 +9,7 @@ import '@fontsource/public-sans/latin-600.css'
import './styles/app.css'
import './styles/premium.css'
import './styles/atlas-workbench.css'
import { LandingPage } from './components/auth/LandingPage'
import { ChangeDetectionPanel } from './components/analysis/ChangeDetectionPanel'
import { GeoAssistantPanel } from './components/assistant/GeoAssistantPanel'
import { DatasetPanel } from './components/datasets/DatasetPanel'
@@ -38,6 +40,7 @@ import { useExportWorkflow } from './hooks/useExportWorkflow'
import { useMapSelectionDataset } from './hooks/useMapSelectionDataset'
import { useMapSelectionQa } from './hooks/useMapSelectionQa'
import { useMapWorkspaceState } from './hooks/useMapWorkspaceState'
import { useOperatorSession } from './hooks/useOperatorSession'
import { useMapSelectionExtract } from './hooks/useMapSelectionExtract'
import { useMapOrthophotoAnalysis } from './hooks/useMapOrthophotoAnalysis'
import { isDetectionImageryDataset, isMapRasterDataset } from './lib/datasetCapabilities'
@@ -81,7 +84,13 @@ const workspaceNavGroups: WorkspaceNavigationGroup[] = [
{ label: 'Beheer', keys: ['overview', 'system'] },
]
function App(): JSX.Element {
interface WorkbenchAppProps {
username: string | null
loggingOut: boolean
onLogout: () => void
}
function WorkbenchApp({ username, loggingOut, onLogout }: WorkbenchAppProps): JSX.Element {
const [activeWorkspace, setActiveWorkspace] = useState<WorkspaceKey>('map')
const [inspectorOpen, setInspectorOpen] = useState(false)
const [mapContentMode, setMapContentMode] = useState<'dataset' | 'analysis'>('dataset')
@@ -818,6 +827,16 @@ function App(): JSX.Element {
<span aria-hidden="true" />
<strong>{workspaceDataLoading ? 'Laden' : errorMessage ? 'Aandacht' : 'Gereed'}</strong>
</div>
{username ? (
<div className="context-account" aria-label="Aangemelde gebruiker">
<UserRound aria-hidden="true" />
<span title={username}>{username}</span>
<button type="button" onClick={onLogout} disabled={loggingOut}>
<LogOut aria-hidden="true" />
<span>{loggingOut ? 'Uitloggen…' : 'Uitloggen'}</span>
</button>
</div>
) : null}
</header>
<div className="workbench-content">
@@ -1300,4 +1319,33 @@ function App(): JSX.Element {
)
}
function App(): JSX.Element {
const { session, sessionError, loggingOut, handleAuthenticated, handleLogout } = useOperatorSession()
if (session === null) {
return (
<div className="landing-auth-loading" role="status" aria-live="polite">
<div><span aria-hidden="true" /><strong>GeoIntel wordt voorbereid</strong></div>
</div>
)
}
if (!session.authenticated) {
return (
<LandingPage
serviceError={sessionError}
onAuthenticated={handleAuthenticated}
/>
)
}
return (
<WorkbenchApp
username={session.authentication_required ? session.username : null}
loggingOut={loggingOut}
onLogout={handleLogout}
/>
)
}
export default App