Skip to content

fix(locations): send venue/room ids when resyncing a room to the materializer - #1026

Open
caseylocker wants to merge 1 commit into
masterfrom
fix/resync-room-id-route
Open

fix(locations): send venue/room ids when resyncing a room to the materializer#1026
caseylocker wants to merge 1 commit into
masterfrom
fix/resync-room-id-route

Conversation

@caseylocker

@caseylocker caseylocker commented Jul 28, 2026

Copy link
Copy Markdown

ref: https://app.clickup.com/t/86bb4r5df

What's broken

The Resync Room action on the Locations page has been 404ing in production since the materializer's destination-path restructure deployed.

We send the venue and room by name:

POST /api/v1/sync/materialize/{summitId}/{encodeURIComponent(venueName)}/{encodeURIComponent(roomName)}/

The materializer only accepts integers:

sync/materialize/<int:summit_id>/<int:venue_id>/<int:room_id>/

Django's int converter refuses a non-numeric segment, so the URL does not resolve. There is no name-based fallback. uicore's authErrorHandler renders a "Not Found" dialog on the 404, so the user sees an error and the resync never runs.

How it happened

dropbox-materializer PR #24 (5bb2d5e, merged 2026-06-15) replaced <str:venue>/<str:room> with <int:venue_id>/<int:room_id>. Its own commit message asked for this change:

"Resync Room route now takes integer IDs and builds a 'venue_id/room_id' room_filter to match the ID-keyed schedule. summit-admin's Resync Room button needs a coordinated change to call the new route."

It was never made. This repo last touched that URL in PR #833, months before the contract changed. It stayed invisible because production ran pre-#24 materializer code until recently; the deployed container now has the ID-based build, so the mismatch is live.

The change

LocationForm was already handed the room id and threw it away to look the room's name back up, so no new data is needed.

  • location-form.js::handleRoomResync now passes this.props.entity.id and roomId. Reading the venue id off props (not state) keeps an unsaved rename in the form from becoming the target, matching what the old code did with persistedVenueName. Guarded so a never-saved venue (id: 0) does not fire.
  • edit-location-page.js::handleRoomResync and dropbox-sync-actions.js::resyncRoom renamed to venueId/roomId; the URL drops the encodeURIComponent name interpolation.

Prettier reflowed the body of resyncRoom because the shortened signature now fits on one line. That is lint-staged's own output, not a hand edit.

No materializer change is needed. It has accepted and tested integer ids since #24: MaterializeRoomView builds room_filter = "{venue_id}/{room_id}", which matches build_schedule's keys.

Tests

The existing action tests only asserted that postRequest was called, never the URL — which is exactly why they stayed green through this regression. Added:

  • an action test pinning the built URL to .../sync/materialize/1/12/345/
  • a LocationForm test that opens the Rooms panel, clicks the real resync action, and asserts onRoomResync receives the two ids

Both were mutation-tested: restoring the old name-based behavior fails them (Expected: 781, 5002 / Received: "International Barcelona Convention Center", "Room A").

The existing inline props in location-form.test.js were lifted into a buildProps() factory so both describes share them; the pre-existing test is otherwise untouched.

Full suite: 154 suites, 1410 tests, green.

Worth a manual check

Nothing automated crosses the two repos, so a click-through on staging after merge would be worth it.

Summary by CodeRabbit

  • Bug Fixes

    • Updated room resynchronization to use venue and room IDs, improving compatibility with the current sync endpoint.
    • Fixed the location management flow to pass the correct identifiers when triggering a room resync.
  • Tests

    • Added coverage confirming room resynchronization sends the expected IDs and endpoint request.
    • Added UI coverage for triggering room resynchronization from the Rooms panel.

Convention pass

Run against skills/react-frontend.md §§1–7 and patterns/show-admin/summit-admin-testing-patterns.md, by grep rather than eyeball.

Clean on §1 (no URL/query built in a component — this change moves toward it, deleting the name lookup from the form), §2 (no new utils/ files), §3/§4 (no reimplemented formatters, no hand-rolled date/money, no new strings), §5 magic numbers (the only literals are VENUE_ID/ROOM_ID named constants in a test), §6 (no .css), §7 (full suite, not just the focused files).

Two notes for the reviewer, both deliberate:

The bare return guard in resyncRoom is not a §5 violation. §5 asks thunks to return a thenable on every branch, and the diff shows if (!baseUrl || !summitId) return; as an added line — but only because prettier reindented the body when the shortened signature collapsed onto one line. Every thunk in this file is async, so a bare return already yields a resolved promise; the rule's concern (undefined returned synchronously while the happy path returns a Promise) does not arise. I confirmed this by mutation: changing it to Promise.resolve() and back leaves behavior and tests identical. Left as-is rather than adding a no-op.

The new component test queries by data-tip, not role/name. The testing playbook prefers getByRole("button", { name }). uicore's Table renders custom row actions as <a href="" data-tip={tooltip}><i className="fa fa-refresh" /></a> — icon-only, no accessible name — so role/name is not reachable without adding an aria-label to production markup purely for the test, which the same playbook rules out. The selector is commented in place.

…rializer

The Resync Room button sent venue and room NAMES. The materializer's per-room
route stopped accepting names in dropbox-materializer PR #24 (merged
2026-06-15), which replaced

  sync/materialize/<int:summit_id>/<str:venue>/<str:room>/

with

  sync/materialize/<int:summit_id>/<int:venue_id>/<int:room_id>/

and shipped no name-based fallback. That PR's own commit message called for a
coordinated change here; it was never made. Since the materializer deployed,
every click has 404'd and shown a "Not Found" dialog instead of resyncing.

LocationForm already receives the room id and was discarding it to look the
room's name back up, so no new data is needed. It now passes
this.props.entity.id (the persisted venue, so an unsaved rename in the form
cannot become the target) and the room id straight through, guarding against a
venue that has never been saved (id 0).

The existing action tests only asserted that postRequest was called, never the
URL, which is why they stayed green through the regression. Added a test
pinning the built URL, and a LocationForm test that opens the Rooms panel,
clicks the real resync action and asserts the ids reach onRoomResync. Both fail
if the old behavior is restored.

Full suite: 154 suites, 1410 tests, green.

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The room resync flow now uses integer venue and room IDs throughout LocationForm, EditLocationPage, and resyncRoom. The action builds the materializer URL with those IDs, and tests cover UI callback arguments and exact request routing.

Changes

Room resync ID contract

Layer / File(s) Summary
Materializer route contract
src/actions/dropbox-sync-actions.js, src/actions/__tests__/dropbox-sync-actions.test.js
resyncRoom uses integer IDs in the materializer URL, with updated success, failure, and routing assertions.
UI ID propagation
src/components/forms/location-form.js, src/pages/locations/edit-location-page.js, src/components/forms/__tests__/location-form.test.js
LocationForm sends persisted venue and room IDs, while EditLocationPage forwards them to the action; UI behavior is tested with user-event.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: tomrndom, smarcet

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: resyncing rooms now sends venue and room IDs to the materializer.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/resync-room-id-route

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes the “Resync Room” action on the Locations page by aligning summit-admin’s request shape with the materializer’s updated route contract (integer venue/room IDs instead of names), preventing production 404s after the materializer’s destination-path restructure.

Changes:

  • Updated the resync call chain (LocationForm → EditLocationPage → Redux action) to pass venueId/roomId instead of venueName/roomName.
  • Updated the materializer URL construction to use integer IDs (and removed encodeURIComponent name interpolation).
  • Added tests to pin the exact resync URL and verify the UI callback receives the correct IDs.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/pages/locations/edit-location-page.js Updates handleRoomResync to forward venue/room IDs to the thunk.
src/components/forms/location-form.js Sends persisted venue ID + room ID when invoking onRoomResync (no name lookup).
src/components/forms/tests/location-form.test.js Adds UI test asserting the resync action calls onRoomResync(venueId, roomId).
src/actions/dropbox-sync-actions.js Changes resyncRoom thunk signature and URL to /materialize/{summitId}/{venueId}/{roomId}/.
src/actions/tests/dropbox-sync-actions.test.js Adds assertion pinning the constructed resync URL to the integer-ID route.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@caseylocker
caseylocker requested a review from smarcet July 28, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants