#48: move images between markings and covers (both directions)#85
Conversation
Editors can now relate records that already exist, instead of only attaching brand-new covers to the one marking being viewed: - RecordDetail: "Link Existing Cover" dialog (ID or C-42 code) POSTs the existing cover-markings endpoint and refreshes the associated list. - CoverDetail: "Link Existing Marking" dialog, same endpoint, refreshes associated markings + the review link. - Both buttons are gated to editor/admin (isStaff) to match the endpoint's IsEditorOrAdminWrite permission. - ID parsing extracted to lib/recordLinking with unit tests. Ported by hand from the pre-refactor reese/cover-workflow-improvements branch (7ae724a); image-move parts of that branch land separately (#48). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v1 had no cover table, so every uploaded cover photo is stapled to a
marking. Editors can now reassign an image's polymorphic subject:
Backend:
- ImageSerializer update-path validate(): target subject must exist
(subject_id is a bare integer column, nothing else checks) and
image_view must match the new subject_type — 400s instead of the DB
check constraint's 500.
- ImageViewSet.perform_update: on subject change, the moved image lands
at the end of the target's display order (never displacing its
default) and the source subject promotes a new display_order=0
(mirrors perform_destroy).
Frontend:
- RecordDetail: "Move to cover" action on marking-subject thumbnails;
dialog targets covers already linked to the marking, with a cover
image-view select (Ian/Wayne's Charlestown cross-contamination case).
- CoverDetail: reverse "Move to marking" via a new optional onMoveImage
action on EntryAssociatedThumbnailsCard; targets linked markings with
FULL/DETAIL views.
- services/markings.moveImageSubject(): PATCH /images/{id}/ with field
error surfacing.
Tests: +5 backend (both directions, display-order bookkeeping, 400 on
missing target, 400 on view mismatch, 403 for contributors). Suite
135/136 (1 pre-existing staging failure, see PR #83).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Code review overview
Syntax ErrorsMinor issues only; nothing that would prevent the code from running. File: Code Smells1. File: 2. File: 3. File: 4. File: 5. File: Bugs1. File: 2. File: 3. File: 4. File: Security Vulnerabilities1. File: 2. File: |
What
Michael's ask: "You should also be able to move images between existing marking and cover entries, as all uploaded covers are currently attached to the marking as an image since v1 had no cover record table."
Backend —
subject_type/subject_idwere already writable onImageSerializer, but unguarded:validate(): the target subject must actually exist (subject_idis a bare integer column — before this, an image could be PATCHed onto Cover #99999 silently), andimage_viewmust match the new subject type (400 with a field error instead of the DB check constraint's 500).perform_update(): on a subject change, the moved image lands at the end of the target's display order — never displacing the target's default thumbnail — and the source subject promotes a newdisplay_order=0, mirroring the delete path's promotion logic from PR Requested fixes for Ian, 6/28 #74.Frontend
onMoveImageaction onEntryAssociatedThumbnailsCard; targets the cover's linked markings with Full/Detail views.IsEditorOrAdminWrite.Stacked on #84
This branch includes #47 (
reese/issue-47-link-existing) because both features rework the same detail pages — merge #84 first and this diff reduces to the image-move commit (eb62ac8).Tests
+5 backend (
test_image_move): both move directions, display-order bookkeeping on source and target, 400 on missing target, 400 on view mismatch, 403 for contributors. Backend suite 135/136 (the 1 failure is the pre-existingtest_top_search_ignores_catalog_textflagged in #83). jest 53/53, tsc/eslint/ruff/vite build clean.🤖 Generated with Claude Code