feat: file edit added
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
# UI_EDIT_V1_DESIGN.md
|
||||
|
||||
## 1. Scope
|
||||
|
||||
`Edit v1` is een eenvoudige teksteditor in de webui, gekoppeld aan de functiebalkactie `Edit`.
|
||||
|
||||
In scope:
|
||||
- alleen tekstbestanden
|
||||
- alleen files, geen directories
|
||||
- openen, wijzigen en opslaan van tekstinhoud
|
||||
- eenvoudige modal-editor
|
||||
|
||||
Out of scope:
|
||||
- geen binary files
|
||||
- geen PDF
|
||||
- geen rich text
|
||||
- geen collaborative editing
|
||||
- geen autosave
|
||||
|
||||
---
|
||||
|
||||
## 2. Ondersteunde bestandstypen in v1
|
||||
|
||||
Voorstel v1:
|
||||
|
||||
- `txt`: ja
|
||||
- `log`: ja
|
||||
- `md`: ja
|
||||
- `yml` / `yaml`: ja
|
||||
- `json`: ja
|
||||
- `js`: ja
|
||||
- `css`: ja
|
||||
- `html`: ja
|
||||
- `Dockerfile`: ja
|
||||
- `Containerfile`: ja
|
||||
|
||||
De allowlist blijft gelijk aan `View v1`, zodat `View` en `Edit` inhoudelijk consistent zijn.
|
||||
|
||||
---
|
||||
|
||||
## 3. UI/UX
|
||||
|
||||
### Openen
|
||||
- `Edit` opent via de functiebalk
|
||||
- alleen geldig bij exact 1 geselecteerde file
|
||||
- alleen bij ondersteund teksttype
|
||||
|
||||
### Modal
|
||||
- openen in modal boven de bestaande dual-pane UI
|
||||
- modal bevat:
|
||||
- titel/header
|
||||
- bestandsnaam
|
||||
- volledig pad
|
||||
- bewerkbaar tekstgebied
|
||||
- `Save`
|
||||
- `Cancel`
|
||||
- rechtsboven `X`
|
||||
|
||||
### Sluiten
|
||||
- `Cancel` sluit zonder opslaan
|
||||
- `X` sluit zonder opslaan
|
||||
- `Escape`:
|
||||
- als geen onopgeslagen wijzigingen: direct sluiten
|
||||
- als wel onopgeslagen wijzigingen: waarschuwing/bevestiging tonen
|
||||
|
||||
### Inhoud
|
||||
- scrollbaar tekstgebied
|
||||
- monospace presentatie
|
||||
- selecteerbaar en bewerkbaar
|
||||
- geen syntax highlighting als dat extra dependencies vraagt
|
||||
|
||||
### Dirty state
|
||||
- modal houdt een eenvoudige `isDirty` status bij
|
||||
- verschil tussen originele inhoud en huidige inhoud bepaalt of waarschuwing nodig is
|
||||
|
||||
---
|
||||
|
||||
## 4. Backend
|
||||
|
||||
### Nieuwe endpoint(s)
|
||||
|
||||
Voorstel:
|
||||
- hergebruik `GET /api/files/view?path=...` voor initial read
|
||||
- nieuw write-endpoint:
|
||||
- `POST /api/files/save`
|
||||
|
||||
Voorstel request shape:
|
||||
- `path`
|
||||
- `content`
|
||||
- `expected_modified` of vergelijkbare timestamp/hash alleen als conflictcheck in v1 wordt gekozen
|
||||
|
||||
Voorstel response shape:
|
||||
- `path`
|
||||
- `size`
|
||||
- `modified`
|
||||
|
||||
### Relatie met bestaand view-model
|
||||
|
||||
`Edit` gebruikt dezelfde type-allowlist en dezelfde padvalidatie als `View`.
|
||||
|
||||
Pragmatische lijn:
|
||||
- `View` blijft read-only preview
|
||||
- `Edit` leest initieel via `View` of een gedeelde servicefunctie
|
||||
- `Save` schrijft alleen naar hetzelfde pad binnen whitelist
|
||||
|
||||
### Validatie
|
||||
|
||||
- alle paden via bestaand `path_guard`
|
||||
- directories afwijzen
|
||||
- unsupported types afwijzen
|
||||
- write alleen binnen whitelisted roots
|
||||
|
||||
### Grote bestanden
|
||||
|
||||
Voorstel:
|
||||
- dezelfde leeslimiet als `View` is **niet** voldoende voor edit
|
||||
- `Edit v1` moet alleen openen tot een veilige editorlimiet, bijvoorbeeld `256 KiB` of `512 KiB`
|
||||
- boven die limiet:
|
||||
- openen blokkeren met duidelijke foutmelding
|
||||
- geen partial edit voor grote bestanden in v1
|
||||
|
||||
Reden:
|
||||
- partial content bewerken zonder volledige file-context is onveilig en verwarrend
|
||||
|
||||
---
|
||||
|
||||
## 5. Veiligheid en conflictgedrag
|
||||
|
||||
### Wijziging intussen op schijf
|
||||
|
||||
Voorstel v1:
|
||||
- **wel** eenvoudige optimistic locking / modified timestamp check
|
||||
|
||||
Mechaniek:
|
||||
- read-response bevat `modified`
|
||||
- save-request stuurt `expected_modified`
|
||||
- backend vergelijkt actuele `mtime`
|
||||
- mismatch geeft conflictfout
|
||||
|
||||
Voordeel:
|
||||
- beperkt risico op stil overschrijven
|
||||
- technisch klein genoeg voor v1
|
||||
|
||||
### Readonly/permissieproblemen
|
||||
|
||||
Bij save:
|
||||
- permissieprobleem of readonly file -> `io_error` of specifieker `permission_denied` als we die foutcode toevoegen
|
||||
|
||||
Voorstel:
|
||||
- als bestaande foutset compact moet blijven, map dit in v1 naar `io_error` met duidelijke boodschap
|
||||
|
||||
### Foutmodel
|
||||
|
||||
Minimaal:
|
||||
- `path_not_found`
|
||||
- `path_traversal_detected`
|
||||
- `invalid_root_alias`
|
||||
- `type_conflict`
|
||||
- `unsupported_type`
|
||||
- `conflict`
|
||||
- `io_error`
|
||||
|
||||
`conflict` wordt gebruikt voor modified-timestamp mismatch.
|
||||
|
||||
---
|
||||
|
||||
## 6. Scopebeperking
|
||||
|
||||
Niet in v1:
|
||||
- geen syntax highlighting als dat extra dependencies vraagt
|
||||
- geen undo/redo systeem buiten browser-native textarea gedrag
|
||||
- geen find/replace
|
||||
- geen multi-file edit
|
||||
- geen directory edit
|
||||
- geen split view diff
|
||||
|
||||
---
|
||||
|
||||
## 7. Impactanalyse
|
||||
|
||||
Waarschijnlijk te wijzigen backendbestanden:
|
||||
- `webui/backend/app/api/routes_files.py`
|
||||
- `webui/backend/app/api/schemas.py`
|
||||
- `webui/backend/app/services/file_ops_service.py`
|
||||
- `webui/backend/app/fs/filesystem_adapter.py`
|
||||
- nieuwe golden tests voor save/edit flow
|
||||
|
||||
Waarschijnlijk te wijzigen frontendbestanden:
|
||||
- `webui/html/index.html`
|
||||
- `webui/html/app.js`
|
||||
- `webui/html/style.css`
|
||||
- `webui/backend/tests/golden/test_ui_smoke_golden.py`
|
||||
|
||||
### Regressierisico
|
||||
|
||||
- `Edit` enabled/disabled toestand kan verkeerd meelopen met huidige selectie
|
||||
- modal-keyboardgedrag kan botsen met paneelnavigatie
|
||||
- save-conflict of dirty-state kan leiden tot onduidelijk UX-gedrag
|
||||
- onveilige overschrijving zonder conflictcheck moet vermeden worden
|
||||
|
||||
Mitigatie:
|
||||
- dezelfde selectievoorwaarden als `View`
|
||||
- keyboard shortcuts blokkeren zolang editor open is
|
||||
- expliciete dirty-state en save-conflict handling
|
||||
|
||||
---
|
||||
|
||||
## 8. Teststrategie
|
||||
|
||||
### Golden tests
|
||||
|
||||
Voor backend:
|
||||
- edit/open success voor ondersteund tekstbestand
|
||||
- save success
|
||||
- unsupported type
|
||||
- directory -> type conflict
|
||||
- path not found
|
||||
- traversal attempt
|
||||
- conflict bij gewijzigde file
|
||||
- io_error bij write failure
|
||||
|
||||
### UI smoke/regressietests
|
||||
|
||||
Aanpassen:
|
||||
- `Edit` knop aanwezig in functiebalk
|
||||
- edit-modal container aanwezig in HTML
|
||||
- save/cancel controls aanwezig
|
||||
|
||||
### Handmatige validatie
|
||||
|
||||
- `Edit` enabled bij exact 1 ondersteunde file
|
||||
- `Edit` disabled bij:
|
||||
- geen selectie
|
||||
- meerdere selectie
|
||||
- directoryselectie
|
||||
- unsupported filetype
|
||||
- modal opent met juiste inhoud
|
||||
- `Save` schrijft wijziging correct weg
|
||||
- `Cancel` sluit zonder opslaan
|
||||
- `Escape` sluit alleen veilig volgens dirty-state regel
|
||||
- conflictmelding bij tussentijdse externe wijziging
|
||||
Reference in New Issue
Block a user