Skip to content

T-324V-dashboard-entity-body-editing

State: planning/draft · Impact: medium · Complexity: medium

Phase 12 (M-VBZB) ported the desktop app’s read surfaces into a new static dashboard SPA (packages/ts/dashboard-spa), but deliberately left out body EDITING — entity/task detail views render markdown read-only. The old desktop app’s EntityBodySection.vue/MdSurface editor (edit/save, conflict resolution, contract-finding markers) has no equivalent in the new SPA. The dashboard JSON API already has the write endpoint (PUT /api/entities/:type/:id/body, DashboardClient.updateEntityBody) fully implemented and unused by the SPA — this task wires a UI onto it, closing a real capability gap relative to the desktop app it replaces.

  • packages/ts/dashboard-spa/src/components/EntityBodyViewer.vue renders an entity’s markdown body read-only (marked + DOMPurify).
  • packages/ts/dashboard-client’s DashboardClient.updateEntityBody(type, id, body, etag, project?) is fully implemented, tested, and typed (EntityBodySave result: ok / conflict (etag mismatch) / invalid (contract-validation failure) — see packages/ts/dashboard-client/src/index.ts).
  • Nothing in the SPA calls it. There is no edit affordance, no etag tracking on the read side, no conflict or validation-failure UI.
  • The desktop app’s EntityBodySection.vue (not ported, and not required to be copied verbatim) is the prior art for what a full edit flow looks like: edit/save, an etag-based compare-and-swap, and rendering EntityBodyValidationFailure’s per-finding messages inline.

EntityDetail.vue (and the task/milestone detail views that render a body) gain an edit mode: a textarea or lightweight markdown editor, a Save action that calls updateEntityBody with the etag from the last read, and UI for all three EntityBodySave outcomes — a successful write, a lost compare-and-swap (etag conflict — show the current server value and let the user retry), and a contract-validation failure (render the findings, block the save). A body with body_etag: null (the read seam says “not body-editable”) shows read-only with no Edit affordance, per EntityDetail’s existing documented contract in contract.ts.

  1. Add a useEntityBodySave composable (or similar) in packages/ts/dashboard-spa/src/composables/, mirroring the desktop app’s useEntityBodySave.ts in shape but calling @sdlc/dashboard-client directly (no Nuxt auto-imports).
  2. Extend EntityBodyViewer.vue (or add a sibling edit component) with an edit/view toggle, gated on body_etag !== null.
  3. Wire the three EntityBodySave outcomes into visible UI: success (update the etag, exit edit mode), conflict (surface the new etag/value, offer retry), invalid (render findings, keep edit mode open).
  4. Extend to task/milestone detail views if they render bodies through the same component; otherwise scope this task to the generic entity browser only and file a follow-up for the others.
  5. Tests: component tests for all three save outcomes against a mocked client, following the existing pattern in packages/ts/dashboard-spa/src/views/ConfigView.test.ts (which already covers an analogous success/validation-failure pair for setConfigKey).
AreaNote
packages/ts/dashboard-spa/src/components/EntityBodyViewer.vueCurrently read-only; needs an edit mode
packages/ts/dashboard-spa/src/views/EntityDetail.vueHosts the body viewer; needs edit-mode wiring
packages/ts/dashboard-client/src/index.tsupdateEntityBody/EntityBodySave already exist, unused by the SPA
solutions/ontological/lib/services/dashboard/contract.tsEntityBodyUpdate/EntityBodyUpdateResult/EntityBodyValidationFailure — no changes expected, already correct
  • AC-1: An entity with a non-null body_etag shows an Edit affordance; one with a null body_etag does not.
  • AC-2: Editing and saving a body end-to-end (via updateEntityBody) against a real project updates the file on disk and the etag shown in the UI, verified live against a real checkout (not just a mocked client).
  • AC-3: A lost compare-and-swap (another writer changed the body first) surfaces the conflict to the user rather than silently overwriting or throwing an unhandled error.
  • AC-4: A contract-validation failure (an edit that would introduce a markdown-contract error) renders the returned findings and does not write anything.
  • Any richer markdown editing experience (live preview, WYSIWYG, @sksizer/markdown-ui’s MdSurface itself) — a plain textarea + Save is sufficient to close the capability gap; a nicer editor is a separate, later enhancement.
  • Frontmatter editing (only the body is in scope, matching the existing PUT /api/entities/:type/:id/body endpoint’s own scope).
  • none
  • Flagged during M-VBZB (Phase 12, “Bring over the current UI”) as a deliberate scope-out of the initial SPA port: the milestone’s completion note records this gap and points here.

← Back to Tasks