feat(speakers): display unique activities count on speakers/submitter…#921
feat(speakers): display unique activities count on speakers/submitter…#921
Conversation
…s list Add total filtered activities count to the page header alongside the speaker count, and selected activities count above the grid, for both the Speakers and Submitters views. Activity counts are deduplicated across accepted, alternate, and rejected presentations using a Set client-side for selections and a dedicated backend endpoint for the filtered total. Also fix null guards in current-summit-reducer for reg-lite and print-app settings payloads, and switch dev server to http.
📝 WalkthroughWalkthroughPR adds speaker and submitter activities count tracking via new Redux actions and thunks, stores counts in reducers, displays totals and selected counts in the UI with translated labels, adds defensive null checks for missing API responses, and switches dev server from HTTPS to HTTP. ChangesActivities Count Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/pages/summit_speakers/summit-speakers-list-page.js`:
- Around line 719-731: The selectedActivities computation in the
selectedActivities IIFE only scans the current-page items, so cross-page
selections (selectedAll with exclusions or selectedItems from other pages) are
missed; update the logic to derive the count from a global selection model of
activity ids instead of page-local items: when selectedAll is true compute count
as totalActivities minus the number of activity ids represented by excludedItems
(or fetch excluded activity ids via the backend), and when selectedAll is false
compute count as the size of the union of activity ids tracked in a global
selectedActivityIds set/state (or an API-provided selected-count), replacing the
current per-page traversal in the selectedActivities calculation and using
symbols selectedActivities, selectedAll, excludedItems, selectedItems, items,
totalActivities to locate and update the code.
In `@src/reducers/summit_speakers/summit-speakers-list-reducer.js`:
- Around line 210-212: The RECEIVE_SPEAKERS_ACTIVITIES_COUNT reducer is
unconditionally writing payload.response.count and can be clobbered by stale
responses; change it to only update totalActivities when the incoming response
matches the current request context (e.g., compare payload.requestId or a
filterHash and payload.summitId against the request-tracking fields stored in
state such as
state.currentRequestId/state.currentFilterHash/state.currentSummitId). Ensure
the action that triggers the async fetch includes a stable identifier (requestId
or filterHash + summitId) and that the reducer for the request start stores that
identifier on state (e.g., in the handler that sets loading state), then in the
RECEIVE_SPEAKERS_ACTIVITIES_COUNT case only set totalActivities =
payload.response.count if payload.requestId === state.currentRequestId (or
payload.filterHash === state.currentFilterHash && payload.summitId ===
state.currentSummitId); otherwise return state unchanged.
In `@src/reducers/summit_submitters/summit-submitters-list-reducer.js`:
- Around line 198-200: The reducer unconditionally sets totalActivities on
RECEIVE_SUBMITTERS_ACTIVITIES_COUNT allowing stale async responses to overwrite
current totals; modify the flow so the count request includes a query context/id
(e.g., requestId or filterHash and currentSummitId) in the action payload and
store the latestRequestId (or latestFilterHash/currentSummitId) on the reducer
state (e.g., state.latestSubmittersCountRequestId); in the
RECEIVE_SUBMITTERS_ACTIVITIES_COUNT branch, compare payload.requestId (or
payload.filterHash + payload.summitId) with state.latestSubmittersCountRequestId
(or state.currentFilterHash/state.currentSummitId) and only set totalActivities
= payload.response.count when they match, otherwise ignore the action.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 811de08d-7885-4f26-b72a-74ce3b5481d9
📒 Files selected for processing (8)
src/actions/speaker-actions.jssrc/actions/submitter-actions.jssrc/i18n/en.jsonsrc/pages/summit_speakers/summit-speakers-list-page.jssrc/reducers/summit_speakers/summit-speakers-list-reducer.jssrc/reducers/summit_submitters/summit-submitters-list-reducer.jssrc/reducers/summits/current-summit-reducer.jswebpack.dev.js
| const selectedActivities = (() => { | ||
| if (selectedAll && excludedItems.length === 0) return totalActivities; | ||
| const relevant = selectedAll | ||
| ? items.filter((item) => !excludedItems.includes(item.id)) | ||
| : items.filter((item) => selectedItems.includes(item.id)); | ||
| const ids = new Set(); | ||
| relevant.forEach((item) => { | ||
| (item.accepted_presentations || []).forEach((p) => ids.add(p.id)); | ||
| (item.alternate_presentations || []).forEach((p) => ids.add(p.id)); | ||
| (item.rejected_presentations || []).forEach((p) => ids.add(p.id)); | ||
| }); | ||
| return ids.size; | ||
| })(); |
There was a problem hiding this comment.
Selected activities count is incorrect for cross-page selections.
At Lines 721-724, the calculation only inspects current-page items. When selections span multiple pages (or selectedAll with exclusions), selectedActivities no longer reflects all selected entities, so the UI shows inaccurate totals.
You’ll need a selection model that tracks activity ids beyond the current page (or a backend selected-count endpoint) to keep this number correct.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/summit_speakers/summit-speakers-list-page.js` around lines 719 -
731, The selectedActivities computation in the selectedActivities IIFE only
scans the current-page items, so cross-page selections (selectedAll with
exclusions or selectedItems from other pages) are missed; update the logic to
derive the count from a global selection model of activity ids instead of
page-local items: when selectedAll is true compute count as totalActivities
minus the number of activity ids represented by excludedItems (or fetch excluded
activity ids via the backend), and when selectedAll is false compute count as
the size of the union of activity ids tracked in a global selectedActivityIds
set/state (or an API-provided selected-count), replacing the current per-page
traversal in the selectedActivities calculation and using symbols
selectedActivities, selectedAll, excludedItems, selectedItems, items,
totalActivities to locate and update the code.
| case RECEIVE_SPEAKERS_ACTIVITIES_COUNT: { | ||
| return { ...state, totalActivities: payload.response.count }; | ||
| } |
There was a problem hiding this comment.
Prevent stale count responses from clobbering current speaker totals.
At Line 211, the reducer accepts whichever count response arrives last. Under rapid filter/search changes, stale responses can overwrite the active query’s totalActivities.
Please gate this update with request context (request id/filter hash/current summit) so only the latest relevant response updates state.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/reducers/summit_speakers/summit-speakers-list-reducer.js` around lines
210 - 212, The RECEIVE_SPEAKERS_ACTIVITIES_COUNT reducer is unconditionally
writing payload.response.count and can be clobbered by stale responses; change
it to only update totalActivities when the incoming response matches the current
request context (e.g., compare payload.requestId or a filterHash and
payload.summitId against the request-tracking fields stored in state such as
state.currentRequestId/state.currentFilterHash/state.currentSummitId). Ensure
the action that triggers the async fetch includes a stable identifier (requestId
or filterHash + summitId) and that the reducer for the request start stores that
identifier on state (e.g., in the handler that sets loading state), then in the
RECEIVE_SPEAKERS_ACTIVITIES_COUNT case only set totalActivities =
payload.response.count if payload.requestId === state.currentRequestId (or
payload.filterHash === state.currentFilterHash && payload.summitId ===
state.currentSummitId); otherwise return state unchanged.
| case RECEIVE_SUBMITTERS_ACTIVITIES_COUNT: { | ||
| return { ...state, totalActivities: payload.response.count }; | ||
| } |
There was a problem hiding this comment.
Guard against stale activity-count responses overwriting current filters.
At Line 199, totalActivities is updated from any arriving response. If users change filters/search quickly, older async responses can land late and replace the latest count, so header totals drift from current results.
Consider attaching query context (e.g., currentSummitId + filter hash/request id) to the count request and ignoring mismatched responses in the reducer.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/reducers/summit_submitters/summit-submitters-list-reducer.js` around
lines 198 - 200, The reducer unconditionally sets totalActivities on
RECEIVE_SUBMITTERS_ACTIVITIES_COUNT allowing stale async responses to overwrite
current totals; modify the flow so the count request includes a query context/id
(e.g., requestId or filterHash and currentSummitId) in the action payload and
store the latestRequestId (or latestFilterHash/currentSummitId) on the reducer
state (e.g., state.latestSubmittersCountRequestId); in the
RECEIVE_SUBMITTERS_ACTIVITIES_COUNT branch, compare payload.requestId (or
payload.filterHash + payload.summitId) with state.latestSubmittersCountRequestId
(or state.currentFilterHash/state.currentSummitId) and only set totalActivities
= payload.response.count when they match, otherwise ignore the action.
…s list
Add total filtered activities count to the page header alongside the speaker count, and selected activities count above the grid, for both the Speakers and Submitters views. Activity counts are deduplicated across accepted, alternate, and rejected presentations using a Set client-side for selections and a dedicated backend endpoint for the filtered total.
Also fix null guards in current-summit-reducer for reg-lite and print-app settings payloads, and switch dev server to http.
Summary by CodeRabbit
New Features
Bug Fixes
Chores