From 178892fc66feb2f8e462d53ce8e39e26ed462e32 Mon Sep 17 00:00:00 2001 From: Jens Date: Fri, 21 Aug 2026 21:50:40 +0200 Subject: [PATCH] add synchronized dual-display workbench --- README.md | 5 + docs/CODEX_EXECUTION_LOG.md | 20 ++ docs/DUAL_DISPLAY_WORKFLOW.md | 30 +++ docs/TODO.md | 7 + frontend/src/App.tsx | 28 ++- frontend/src/components/map/MapWorkspace.tsx | 45 ++-- .../components/shell/SecondaryDisplay.test.ts | 29 +++ .../src/components/shell/SecondaryDisplay.tsx | 166 +++++++++++++ .../shell/secondaryDisplayGeometry.ts | 40 ++++ frontend/src/styles/geointel-system.css | 219 +++++++++++++++++- 10 files changed, 567 insertions(+), 22 deletions(-) create mode 100644 docs/DUAL_DISPLAY_WORKFLOW.md create mode 100644 frontend/src/components/shell/SecondaryDisplay.test.ts create mode 100644 frontend/src/components/shell/SecondaryDisplay.tsx create mode 100644 frontend/src/components/shell/secondaryDisplayGeometry.ts diff --git a/README.md b/README.md index 9c67de5c..7e38294e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # GeoIntel +GeoIntel ondersteunt een gesynchroniseerde tweeschermwerkruimte: de kaart blijft +maximaal zichtbaar op het hoofdscherm terwijl analyses, kwaliteitsbewijs en +resultaten live in een tweede venster staan. Zie +[`docs/DUAL_DISPLAY_WORKFLOW.md`](docs/DUAL_DISPLAY_WORKFLOW.md). +

GeoIntel logo

diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index 2190d024..96645a55 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -1,3 +1,23 @@ +## 2026-08-21 - Gesynchroniseerde tweeschermwerkruimte + +### Opgeleverd + +- Een nieuwe knop in de werkbalk opent een afzonderlijke analyseconsole voor + een tweede monitor. +- De bestaande resultatenlade wordt via een React-portal verplaatst. Kaart en + console delen daardoor exact dezelfde selectie-, analyse- en QA-state zonder + dubbele API-aanvragen. +- Het venster onthoudt positie en afmetingen, meldt popupblokkering en valt bij + sluiten zonder dataverlies terug naar de gewone éénschermlade. +- Operator en demo krijgen dezelfde functie; bestaande rechten wijzigen niet. + +### Verificatie + +- TypeScript typecheck, gerichte Vitest-regressies en productiebuild slagen. +- De live gastwerkstroom is lokaal tegen de Tower-backend doorlopen: tweede + scherm openen, gebied selecteren, thema analyseren en dezelfde resultaten na + sluiten terugvinden in de hoofdinterface. + ## 2026-08-10 - V74 root-cause remediation en authority-first uitvoer ### Opgeleverd diff --git a/docs/DUAL_DISPLAY_WORKFLOW.md b/docs/DUAL_DISPLAY_WORKFLOW.md new file mode 100644 index 00000000..eccd8a00 --- /dev/null +++ b/docs/DUAL_DISPLAY_WORKFLOW.md @@ -0,0 +1,30 @@ +# Tweeschermwerkruimte + +GeoIntel kan de kaart en de analyseconsole over twee browservensters verdelen +zonder een tweede sessie of dubbele analyse te starten. + +## Gebruik + +1. Open de kaartwerkruimte. +2. Kies **Open tweede scherm** in de bovenbalk. +3. Verplaats de analyseconsole naar het tweede beeldscherm wanneer de browser + dit niet automatisch doet. +4. Selecteer gebieden, bronnen en modellen op het hoofdscherm. Voortgang, + resultaten, GRB-controle, grafieken en downloads verschijnen live in de + analyseconsole. +5. Gebruik **Sluit console** in het tweede venster of **Sluit tweede scherm** + in de bovenbalk om terug te keren naar de normale resultatenlade. + +De laatst gebruikte vensterpositie en -afmetingen worden lokaal onthouden. Als +de browser pop-ups blokkeert, toont GeoIntel een concrete melding. Er gaat geen +analyse verloren wanneer het tweede venster wordt gesloten. + +## Technisch contract + +- De console is een React-portal van dezelfde actieve werkruimte. +- Er ontstaat geen tweede API-sessie, modelrun of onafhankelijke statekopie. +- Kaartselectie, modelkeuze, laadstatus, QA-bewijs en resultaten blijven daarom + synchroon. +- De normale éénscherminterface blijft de fail-safe fallback. +- De functie is beschikbaar voor operator- en demosessies; bestaande + autorisatiegrenzen veranderen niet. diff --git a/docs/TODO.md b/docs/TODO.md index 9f7917d3..ba320630 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -1,5 +1,12 @@ # GeoIntel TODO +## Tweeschermwerkruimte (2026-08-21) + +- [x] Voeg een gesynchroniseerde analyseconsole voor een tweede beeldscherm toe. +- [x] Verplaats dezelfde React-resultaatstate zonder dubbele API-calls of runs. +- [x] Onthoud vensterpositie en herstel veilig naar de éénschermlade. +- [x] Voorzie popupfoutmelding, toetsenbordlabels en operator-/demopariteit. + ## V74 authority-first gebouwresultaten (2026-08-10) - [x] Voer een V72-foutanalyse, hard-negative proposal-filter en rehearsal diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4047c342..e5d88b15 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,5 @@ import { useEffect, useMemo, useRef, useState } from 'react' -import { CircleAlert, LogOut, ShieldCheck, UserRound } from 'lucide-react' +import { CircleAlert, LogOut, MonitorUp, ShieldCheck, UserRound } from 'lucide-react' import '@fontsource/manrope/latin-500.css' import '@fontsource/manrope/latin-600.css' import '@fontsource/manrope/latin-700.css' @@ -37,6 +37,7 @@ import { type WorkspaceNavigationItem, } from './components/shell/WorkbenchNavigation' import { WorkspaceSignal } from './components/shell/WorkspaceSignal' +import { useSecondaryDisplay } from './components/shell/SecondaryDisplay' import { useChangeDetectionWorkflow } from './hooks/useChangeDetectionWorkflow' import { useDemoWorkflow } from './hooks/useDemoWorkflow' import { useCoverageResolver } from './hooks/useCoverageResolver' @@ -119,6 +120,7 @@ function WorkbenchApp({ username, accessMode, loggingOut, onLogout }: WorkbenchA const [activeWorkspace, setActiveWorkspace] = useState('map') const [inspectorOpen, setInspectorOpen] = useState(false) const [guestDemoReady, setGuestDemoReady] = useState(!isGuest) + const secondaryDisplay = useSecondaryDisplay() const guestDemoStartedRef = useRef(false) const visibleWorkspaceItems = useMemo( () => isGuest ? workspaceNavItems.filter((item) => guestWorkspaceKeys.has(item.key)) : workspaceNavItems, @@ -830,7 +832,7 @@ function WorkbenchApp({ username, accessMode, loggingOut, onLogout }: WorkbenchA : 'Geen actieve laag' return ( -
+