6.7 KiB
6.7 KiB
UI_DUAL_PANE_DESIGN.md
Doel van deze notitie
Deze notitie beschrijft de ontwerpstap voor Dual-pane UI v2 op basis van de huidige v1.1 UI en UI_VISION_MC.md.
Randvoorwaarden voor deze stap:
- geen backendwijzigingen
- geen nieuwe dependencies
- geen multi-select
- geen viewer/editor
- geen keyboard-uitbreiding (behalve als latere notitie)
1) Ombouw van single-page UI naar twee panelen
Huidige situatie (v1.1)
- één browsepaneel met één
currentPath - globale selectie voor dat paneel
- acties (mkdir/rename/delete/copy/move) vanuit die ene context
Doelsituatie (v2)
- twee browsepanelen naast elkaar:
leftenright - elk paneel heeft:
- eigen path input + go
- eigen breadcrumbs
- eigen directory/file lijst
- eigen geselecteerd item
- één paneel is altijd actief
- acties worden contextueel uitgevoerd vanuit actief paneel
- tasks- en bookmarks-sectie blijven gedeeld (onder of naast de panelen)
UI-structuur op hoog niveau
- Header: algemene status
- Main layout:
- Paneel links (
left-pane) - Paneel rechts (
right-pane) - Utility-kolom (tasks + bookmarks)
- Paneel links (
- Actieknoppen:
- per paneel (mkdir)
- actieve-paneelacties (rename/delete/copy/move)
Bookmark-open gedrag (expliciete keuze)
- Een klik op een bookmark opent altijd in het actieve paneel.
- Motivatie (kort): dit is het meest voorspelbaar, sluit aan op het active/inactive-pane model, en voorkomt verborgen side-effects in het niet-actieve paneel.
2) Benodigde state per paneel
State-model
state = {
panes: {
left: {
currentPath: "storage1",
showHidden: false,
selectedItem: null, // { path, name, kind: "file"|"directory" }
entries: { directories: [], files: [] }
},
right: {
currentPath: "storage1",
showHidden: false,
selectedItem: null,
entries: { directories: [], files: [] }
}
},
activePane: "left", // "left" | "right"
selectedTaskId: null,
pollHandle: null
}
Verplichte kernstate
current pathper paneelselected itemper paneelactive paneglobaal
Afgeleide helperstate
inactivePane = activePane === "left" ? "right" : "left"canRename/canDeleteop basis van selectie actief paneelcanCopy/canMovealleen als selectie actief paneel een file is
3) Copy/move van actief paneel naar ander paneel
Semantiek v2
- Bron komt altijd uit
selectedItemvanactivePane. - Doelcontext is standaard het andere paneel.
destinationblijft volledig doelpad (geen impliciete shell-achtige "copy into" semantics).
Destination-bepaling
targetBasePath = panes[inactivePane].currentPathdestination = targetBasePath + "/" + sourceItem.name- UI toont dit voorstel in prompt/confirm en laat aanpassen toe.
Copy flow
- User selecteert file in actief paneel.
- User kiest
Copy. - UI bouwt default destination op basis van inactieve paneel-path + bestandsnaam.
- UI roept
POST /api/files/copymet{source, destination}. - Bij
202: tasks refresh + taskdetail naar nieuw task_id. - Na start: beide panelen refresh (best effort), zodat user contextueel resultaat ziet.
Move flow
- Zelfde als copy, maar endpoint
POST /api/files/move. - Bij
202: tasks refresh + taskdetail selecteren. - Beide panelen refreshen (source kan verdwijnen, destination verschijnen).
Refresh-semantiek per actie (expliciet)
mkdir: refresh alleen het actieve paneel.rename: refresh alleen het actieve paneel.delete: refresh alleen het actieve paneel.copy: refresh beide panelen.move: refresh beide panelen.
Rationale (kort):
- Lokale mutaties (
mkdir/rename/delete) zijn paneelgebonden en blijven daardoor snel en voorspelbaar. - Transfer-acties (
copy/move) raken bron- en doelcontext, dus beide panelen verversen voorkomt stale state.
Foutafhandeling
- Validatiefouten vóór task-creatie direct tonen op actiegebied actief paneel.
- Runtime-fouten via task-status (
failed) zichtbaar in tasklijst/detail.
4) Bestaande backend-endpoints die hergebruikt worden
Geen contractwijzigingen; hergebruik van bestaande endpoints:
Browse/file ops:
GET /api/browsePOST /api/files/mkdirPOST /api/files/renamePOST /api/files/deletePOST /api/files/copyPOST /api/files/move
Tasks:
GET /api/tasksGET /api/tasks/{task_id}
Bookmarks:
GET /api/bookmarksPOST /api/bookmarksDELETE /api/bookmarks/{bookmark_id}
5) Waarschijnlijk te wijzigen bestanden
Primair frontend:
webui/html/index.html- layout naar dual-pane
- pane-specifieke controls/containers
webui/html/app.js- state refactor naar
panes.left/right - browse/render/actions per pane
- active-pane switching
- copy/move destination vanuit ander pane
- state refactor naar
webui/html/style.css- twee panelen visueel gelijkwaardig
- actieve-paneel-highlight
- responsieve fallback (mobiel: gestapeld)
Tests:
webui/backend/tests/golden/test_ui_smoke_golden.py- assertions bijwerken naar dual-pane markup/ids
Niet gepland in deze stap:
- backend python-bestanden
- API schemas/routes/services
6) Regressierisico
Hoog risico
- Stateverwarring tussen links/rechts paneel (actie op verkeerde paneelcontext).
- Onjuiste destination-opbouw bij copy/move (per ongeluk vanuit actief i.p.v. inactief pad).
Middel risico
- Disable/enable logica van knoppen niet synchroon met actieve paneelselectie.
- Refresh-volgorde na acties waardoor UI tijdelijk stale data toont.
- Bookmarks die per ongeluk in het verkeerde paneel openen als
activePaneniet consequent wordt gebruikt.
Laag risico
- CSS regressies in mobile layout.
- Kleine tekst/label inconsistenties in error/statusweergave.
Mitigatie
- Duidelijke pane-identifiers in DOM en handlers (
left/right). - Eén centrale helper voor
getActivePane()engetInactivePane(). - Eén centrale helper voor copy/move destination-opbouw.
- Smoke tests expliciet op dual-pane hoofdstructuur.
7) Aan te passen/toe te voegen UI smoke tests
Aanpassen bestaande smoke test
test_ui_smoke_golden.py:
- huidige checks op enkel browsepaneel vervangen door dual-pane checks.
Nieuwe/gewijzigde assertions:
- UI mount bestaat op
/ui. - HTML bevat beide hoofdpanelen:
id="left-pane"id="right-pane"
- HTML bevat actieve-paneel-indicator/container (bijv. class of data-attribute).
- Assets blijven gemapt:
/ui/app.js/ui/style.css
Kleine extra smoke checks (zonder backenduitbreiding)
- basisactieknoppen aanwezig voor actieve-paneelacties.
- tasks- en bookmarks-panelen blijven aanwezig in HTML.
Geen end-to-end browserautomatisering in deze stap.
Niet in scope voor deze implementatieslice
- multi-select
- viewer/editor
- cancel/retry
- history UI
- nieuwe backend endpoints
- keyboard mapping uitbreiding (eventueel later)