feat(m7-amend): full-bleed scenario table with inline edit + docs

Frontend half of the 2026-05-15 amendment (backend shipped in 447f152).

- `MissionScenarioTable` component: per-scenario <table> with 7 cols
  (Test | Procédure | Exécution | Source de log | Commentaires | Logs
  SIEM | Cyber Incident) + Actions cell. Read mode truncates; double-
  click toggles a row into edit mode where each cell becomes the right
  control. detection_level lives inside the Commentaires cell as a
  pill + select (no 8th column).
- MissionDetailPage Tests tab uses the new component, lifts
  `editingTestId` so only one row across the whole mission is editable
  at a time. Esc reverts (prompt if dirty), double-click on a different
  row with a dirty draft also prompts.
- Full-bleed escape via `calc(50% - 50vw)` (same recipe as the M4 MITRE
  picker). 7 dense columns breathe on wide screens, no horizontal scroll.
- `draftDiff(test, draft)` returns `null` when nothing changed → no PUT
  on a no-op save. The diff carries only touched fields so the server's
  per-field perm gate stays clean.
- Datetime semantics: both datetime-local inputs reuse the M7 verbatim
  recipe (`iso.slice(0, 16)` + `${local}:00Z`), zero TZ shift.

Docs
- tasks/testing-m7.md §3.0 documents the column matrix + edit workflow.
- tasks/lessons.md captures the Pydantic ctx-serialisation pitfall, the
  naïve-datetime guard, the table-edit pattern.
- CHANGELOG section moves "Frontend (in progress)" → "Frontend (shipped)"
  and details the diff.

49 Playwright tests still green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Knacky
2026-05-15 14:51:28 +02:00
parent 447f15213a
commit 9fc78e0832
6 changed files with 775 additions and 109 deletions

View File

@@ -33,8 +33,16 @@ row per test) with double-click inline edit.
- **`tasks/spec.md` amended** — §4 in-scope bullet on blue saisie now lists the 5 fields, §F6 describes the tabular UX (full-bleed, one table per scenario, double-click inline edit), §8 model bullet enumerates the new columns. Header carries a `revised: 2026-05-15` note pointing readers at the amendment.
- **`tasks/todo.md` M7 section** carries a dedicated "Amendement 2026-05-15" sub-block tracking the backend (☑) and frontend (☐) items.
#### Frontend (in progress)
- Tabular layout per scenario, full screen width (escape `max-w-page` like the MITRE picker), columns `Test | Procédure | Exécution | Source de log | Commentaires | Logs SIEM | Cyber Incident`. Double-click row → inline edit gated by red/blue perms. Per-test page kept for evidence upload.
#### Frontend (shipped)
- **`MissionScenarioTable` component** (`frontend/src/pages/MissionScenarioTable.tsx`): per-scenario `<table>` with 7 columns (`Test | Procédure | Exécution | Source de log | Commentaires | Logs SIEM | Cyber Incident`) plus an `Actions` cell that links to the full per-test page. Read mode shows truncated values; double-click toggles a row into edit mode where each cell becomes the right input (text, textarea, datetime-local, select). The `detection_level` lives **inside the Commentaires cell** as a pill + select — no 8th column.
- **Single-row-edit invariant**: `editingTestId` state lives in `MissionDetailPage`'s tests tab so only one row across the whole mission is editable at a time. Double-clicking another row while dirty surfaces a `Discard unsaved changes?` prompt; Esc reverts; Save commits the diff.
- **Diff-only PUT**: `draftDiff(test, draft)` walks every field and only includes the ones that changed; submitting an unchanged form is a no-op `onEditRequest(null)`. Keeps the per-field perm gate on the server cleanly applicable.
- **Full-bleed layout**: the tests tab escapes the layout's `max-w-page` via the canonical `calc(50% - 50vw)` recipe (same as the M4 MITRE picker) so the 7-column table breathes on wide screens without horizontal scroll.
- **Per-test page kept** at `/missions/<id>/tests/<test_id>` for evidence upload and the full procedure view — every row's "open ↗" link routes there.
- **Datetime semantics consistent**: the table's two datetime-local inputs (executed_at + blue_incident_at) reuse the M7 verbatim recipe (`iso.slice(0, 16)` + `${local}:00Z`), no TZ shift on read or write.
#### Tests
- E2E: existing m6 + m7 specs unaffected (all 49 still green). The new table reuses the `mission-add-scenarios` testid for the modal trigger so the wizard test still works. The old `mission-test-${id}` rows are gone but were never wired into any e2e selector.
### Fixed (post-M7 UX feedback — evidence whitelist visibility)
- **Evidence dropzone didn't tell the operator which extensions are accepted, and the OS file picker showed "All files"** (`frontend/src/pages/MissionTestPage.tsx`): an operator could spend the time picking a `.exe` only to receive a 400 back. Surfaced the whitelist in the UI: