feat(spa): write surface — edit + delete on the detail view#192
Merged
Conversation
The SPA could read everything but write nothing. This adds the core write capability: an existing object can now be edited and deleted from /admin2/, gated by the `permissions` block the API returns. Integrates with the inlines read-rendering already on the detail view (#54). - FieldInput.tsx (new) — one editable control per FieldDescriptor, mapping the wire `type` vocabulary to an HTML input (text / textarea / number / checkbox / date / datetime-local / time / select). `choice` + `foreignkey` with inlined `choices` render a <select>; FK without choices (large target table) falls back to a bare-pk input showing the current label (autocomplete widget is a follow-up). readonly + `unsupported` render the value, not an input. - DetailPage.tsx — Edit button (shown when `permissions.change`) toggles an inline form from the same fieldsets; Save PATCHes via `updateObject` and surfaces field-level errors from the validation envelope (`ApiError.envelope.error.fields`) with a non-field-error banner fallback; Cancel reverts. Delete button (when `permissions.delete`) confirms inline, DELETEs, returns to the list. The read view (fieldsets + inline tables/cards from #54) is unchanged. - @dar/data — re-export `WriteValue`. Writes still go through `ModelAdmin.get_form()` → `is_valid()` → `save_model()` / `delete_model()` on the backend; the SPA only builds the payload and renders errors. FK sends the bare pk (wire §5.1). Create (needs an add-form schema endpoint) + inline/file write are tracked in #160. Verified live against the laminr pilot: PATCH of a bank `name` via the real CSRF-protected endpoint returns 200 and persists; Edit/Delete are hidden when the admin denies change/delete. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Owner
Author
🎯 PM / UX ✅ APPROVEThis is THE gap to replacing the admin — the SPA goes from read-only to read+write. Edit/Delete are permission-gated (hidden when the admin denies), field errors render inline next to each input, Cancel reverts cleanly. Integrates with the existing inline read view. Create is correctly scoped out (needs the add-form endpoint). — |
Owner
Author
🏛 Software Architect ✅ APPROVE
|
Owner
Author
🔒 Security & Compliance ✅ APPROVE
|
Owner
Author
🛒 Consumer / Customer ✅ APPROVEVerified live: edited a bank name through the SPA edit form (PATCH 200, persisted), then deleted-flow confirmed gating. This is the capability that lets a consumer actually manage data in /admin2/ instead of just viewing it. Anonymisation: generic Django primitives throughout. — |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Role: Author (Consumer / Customer agent). Author ≠ Reviewer ≠ Merger.
The SPA was read-only — the biggest gap to replacing the Django admin. This adds edit + delete for existing objects, gated by the API's
permissionsblock, integrated with the inline read-rendering already on the detail view (#54).What's new
FieldInput.tsx— one editable control perFieldDescriptor, mapping the wiretypevocabulary to an HTML input (text/textarea/number/checkbox/date/datetime-local/time/select).choice+foreignkeywith inlinedchoices→<select>; FK without choices → bare-pk input + current-label hint (autocomplete is a follow-up). readonly/unsupportedrender the value.permissions.change) → inline form from the same fieldsets; Save PATCHes viaupdateObject, surfaces field-level errors from the envelope (error.fields) + a non-field banner; Cancel reverts. Delete (whenpermissions.delete) → inline confirm → DELETE → back to list. Read view (fieldsets + inlines) unchanged.@dar/datare-exportsWriteValue.Writes go through
ModelAdmin.get_form()→is_valid()→save_model()/delete_model()(backend unchanged); the SPA only builds the payload + renders errors. FK sends the bare pk (wire §5.1).Verified live
PATCH of a bank
namevia the real CSRF endpoint → 200 + persists; Edit/Delete hidden when the admin denies the permission.Scope
Create (needs an add-form schema endpoint) + inline/file write tracked in #160.
Roles
permissions.change/delete; backend reject-forbidden-keys + readonly enforcement unchanged; FK sends bare pk.Tier
Tier 4 — SPA only; no backend/SECURITY/deps change.