# 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: `left` en `right`
- 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)
- 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

```js
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 path` per paneel
- `selected item` per paneel
- `active pane` globaal

### Afgeleide helperstate
- `inactivePane = activePane === "left" ? "right" : "left"`
- `canRename/canDelete` op basis van selectie actief paneel
- `canCopy/canMove` alleen als selectie actief paneel een file is

---

## 3) Copy/move van actief paneel naar ander paneel

## Semantiek v2
- Bron komt altijd uit `selectedItem` van `activePane`.
- Doelcontext is standaard het **andere paneel**.
- `destination` blijft volledig doelpad (geen impliciete shell-achtige "copy into" semantics).

### Destination-bepaling
- `targetBasePath = panes[inactivePane].currentPath`
- `destination = targetBasePath + "/" + sourceItem.name`
- UI toont dit voorstel in prompt/confirm en laat aanpassen toe.

### Copy flow
1. User selecteert file in actief paneel.
2. User kiest `Copy`.
3. UI bouwt default destination op basis van inactieve paneel-path + bestandsnaam.
4. UI roept `POST /api/files/copy` met `{source, destination}`.
5. Bij `202`: tasks refresh + taskdetail naar nieuw task_id.
6. Na start: beide panelen refresh (best effort), zodat user contextueel resultaat ziet.

### Move flow
1. Zelfde als copy, maar endpoint `POST /api/files/move`.
2. Bij `202`: tasks refresh + taskdetail selecteren.
3. 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/browse`
- `POST /api/files/mkdir`
- `POST /api/files/rename`
- `POST /api/files/delete`
- `POST /api/files/copy`
- `POST /api/files/move`

Tasks:
- `GET /api/tasks`
- `GET /api/tasks/{task_id}`

Bookmarks:
- `GET /api/bookmarks`
- `POST /api/bookmarks`
- `DELETE /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
- `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 `activePane` niet 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()` en `getInactivePane()`.
- 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)
