Skip to content

feat(speakers): display unique activities count on speakers/submitter…#921

Open
mulldug wants to merge 1 commit intomasterfrom
feat/speakers-submitters-activities-count
Open

feat(speakers): display unique activities count on speakers/submitter…#921
mulldug wants to merge 1 commit intomasterfrom
feat/speakers-submitters-activities-count

Conversation

@mulldug
Copy link
Copy Markdown

@mulldug mulldug commented May 7, 2026

…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

    • Added speaker and submitter activities count tracking
    • Enhanced UI to display combined speaker/submitter and activities counts in list views
  • Bug Fixes

    • Improved defensive handling for missing server responses
    • Corrected dev server configuration
  • Chores

    • Updated translation strings to support activities labels and quantity displays

…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.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

PR 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.

Changes

Activities Count Feature

Layer / File(s) Summary
Action Types and Thunks
src/actions/speaker-actions.js, src/actions/submitter-actions.js
Exports new action constants REQUEST_SPEAKERS_ACTIVITIES_COUNT, RECEIVE_SPEAKERS_ACTIVITIES_COUNT, REQUEST_SUBMITTERS_ACTIVITIES_COUNT, and RECEIVE_SUBMITTERS_ACTIVITIES_COUNT. Adds getSpeakersActivitiesCount and getSubmittersActivitiesCount thunks that call /speakers/all/events/count and /submitters/all/events/count endpoints with optional filtering.
Action Dispatch Integration
src/actions/speaker-actions.js, src/actions/submitter-actions.js
getSpeakersBySummit and getSubmittersBySummit now dispatch their respective activities-count thunks alongside existing list requests using resolved filter and access token. Removes duplicate initSubmittersList definition.
State Management
src/reducers/summit_speakers/summit-speakers-list-reducer.js, src/reducers/summit_submitters/summit-submitters-list-reducer.js
Both reducers add totalActivities: 0 to DEFAULT_STATE and handle new activities-count action types by extracting payload.response.count into state.
UI Rendering
src/pages/summit_speakers/summit-speakers-list-page.js
Imports are corrected with semicolons. Page computes selectedActivities by aggregating presentation IDs from selected/relevant items. Page title and items-quantity header are updated to display totalActivities and activitiesQty alongside speaker/submitter counts.
Translations
src/i18n/en.json
Adds general.activities key. Updates summit_speakers_list.items_qty and summit_submitters_list.items_qty to include activitiesQty placeholder for combined display.
Defensive Checks & Config
src/reducers/summits/current-summit-reducer.js, webpack.dev.js
Adds early returns in RECEIVE_REG_LITE_SETTINGS and RECEIVE_PRINT_APP_SETTINGS cases when payload.response is falsy. Changes webpack dev server from type: "https" to type: "http".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • caseylocker
  • martinquiroga-exo
  • smarcet

Poem

🐰 Count the speakers, count the speakers bright,
Their activities shimmer in the dashboard light,
Redux flows and reducers align,
UI renders the totals so fine,
One more feature that helps the admins shine! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main feature being added: displaying unique activities count on speakers and submitter views, which aligns with the primary objectives and changes across all modified files.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 feat/speakers-submitters-activities-count

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between c008e20 and b7dc10d.

📒 Files selected for processing (8)
  • src/actions/speaker-actions.js
  • src/actions/submitter-actions.js
  • src/i18n/en.json
  • src/pages/summit_speakers/summit-speakers-list-page.js
  • src/reducers/summit_speakers/summit-speakers-list-reducer.js
  • src/reducers/summit_submitters/summit-submitters-list-reducer.js
  • src/reducers/summits/current-summit-reducer.js
  • webpack.dev.js

Comment on lines +719 to +731
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;
})();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

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.

Comment on lines +210 to +212
case RECEIVE_SPEAKERS_ACTIVITIES_COUNT: {
return { ...state, totalActivities: payload.response.count };
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

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.

Comment on lines +198 to +200
case RECEIVE_SUBMITTERS_ACTIVITIES_COUNT: {
return { ...state, totalActivities: payload.response.count };
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

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.

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.

1 participant