Bookdrop: auto-check row when fetched metadata is copied (bookshelf-j8pvj) #1424
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "bd-bookshelf-j8pvj"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
bookdrop_file_editor_controller.jsnow auto-checks the proposal row's checkbox — mirroring the existing auto-select-on-library-assign behavior from bookshelf-fvug6.bookdrop:metadatacopiedCustomEvent (detail:{proposalId}) dispatched from_autoSave()(the shared tail of copyField/copyAll/copyMissing), listened for bybookdrop_review_controller.jswhich mapsproposalIdto the matching row viadata-proposal-id, checks its checkbox, and calls_updateUI().docs/content/docs/importing/bookdrop.mdto describe the new auto-check-on-copy behavior.Test plan
npm run coverage— 100% JS coverage, all 4740 tests pass (new unit tests in both controller test files cover the dispatch + listener + edge cases: unknown proposalId, missing detail, already-checked row, disconnect teardown)go build -tags e2e ./e2e/...compilesgo vet ./...,make e2e-policy-check,make test-policy-check,bash scripts/check-css-vars.shall passCloses bead bookshelf-j8pvj on merge.
acdcbd1567c1c20f2adaSecurity Review — PR #1424 (bookshelf-j8pvj)
Reviewed the diff:
static/js/controllers/bookdrop_file_editor_controller.js,static/js/controllers/bookdrop_review_controller.js, their Vitest specs, onee2e journey addition, and a docs tweak. No server-side code, no new endpoint,
no new authz surface.
Checked:
bookdrop:metadatacopiedCustomEventcarries onlydetail: { proposalId }— a single ID, no PII/tokens/sensitive payload. It's dispatched with
bubbles: trueonthis.elementand listened for viadocument.addEventListener— same-document only, nopostMessage/BroadcastChannel/cross-origin exposure.proposalIdis Stimulus'sproposalIdValue, sourced from a server-rendereddata-*attribute on the row — the same trust boundary as every otherStimulus value binding in this codebase, not new attacker-controlled input.
_onMetadataCopied(bookdrop_review_controller.js) usesparseInt(row.getAttribute("data-proposal-id"), 10) === proposalIdinsideArray.prototype.findIndex— a numeric equality comparison, neverinterpolated into a
querySelectorstring or any DOM sink (innerHTML,insertAdjacentHTML, etc.). No selector-injection or XSS vector.disconnect()is a net-new method (verified against pre-PR file) that justremoves the listener added in
connect()— no double-registration/leak, nooverwritten existing lifecycle hook.
calls — purely a client-side UX convenience (auto-check a checkbox).
No BLOCKER/MAJOR/MINOR findings.
REVIEW VERDICT: 0 blocker, 0 major, 0 minor
Code Review — PR #1424 (bookshelf-j8pvj)
Reviewed the diff (bookdrop_file_editor_controller.js, bookdrop_review_controller.js, Vitest specs, e2e journey, docs). No blockers or majors found.
[MINOR] static/js/controllers/bookdrop_file_editor_controller.js:390-397 —
_autoSavedispatchesbookdrop:metadatacopiedunconditionally, even if the underlying_doSave()request later fails. The row gets auto-checked even when the copy wasn't actually persisted server-side. Low impact (save failure surfaces via the status indicator, and Accept flushes/gates on save success before submitting), but worth a comment noting this is deliberate optimistic-UI behavior, or moving the dispatch to the save-success path if strictness is wanted.Verified as sound:
_autoSave()call sites are exactly the 5 branches ofcopyField+copyAll+copyMissing(grep-verified) — no triple-dispatch risk.connect()storesthis._boundMetadataCopied = this._onMetadataCopied.bind(this)and adds it;disconnect()removes the same bound reference — no leak. Vitest's MutationObserver-driven disconnect test covers this.proposalId: NumberStimulus value vs review'sparseInt(row.getAttribute('data-proposal-id'), 10) === proposalId— types match.if (!rowCheckbox || rowCheckbox.checked) return;guards re-running_updateUI()on an already-checked row — covered by a dedicated Vitest spec asserting_updateUIis not called again.detail.proposalIdboth handled gracefully (no throw, no-op) — covered by tests.Describe("Auto-save on copy (bookshelf-qgd90.12)", Ordered, ...)journey's existingItstep (no new top-level Describe), and thatItalready callspage = refreshPageTimeout(page)at its start — satisfying the per-It page.Timeout reset convention.docs/content/docs/importing/bookdrop.mdis end-user framed (no source/route/internal references), and the "← Copy Missing" label matches the template exactly.REVIEW VERDICT: 0 blocker, 0 major, 1 minor
c1c20f2ada370a2d7e50