Skip to content

feature: Reduce bundle size#883

Open
santipalenque wants to merge 4 commits intomasterfrom
feature/lazy-load-layouts
Open

feature: Reduce bundle size#883
santipalenque wants to merge 4 commits intomasterfrom
feature/lazy-load-layouts

Conversation

@santipalenque
Copy link
Copy Markdown

@santipalenque santipalenque commented Apr 17, 2026

https://app.clickup.com/t/86b9595px

Summary by CodeRabbit

Release Notes

  • New Features

    • Implemented code-splitting with lazy-loaded components to improve initial page load performance and reduce bundle size.
  • Chores

    • Optimized import statements across components for better tree-shaking and reduced bundle footprint.
    • Updated build configuration to improve chunk asset naming.
    • Updated dependency package version.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 898f4bee-1d07-45e5-86e7-be6153cd4080

📥 Commits

Reviewing files that changed from the base of the PR and between 8fe0a3b and 74b56a1.

📒 Files selected for processing (1)
  • src/app.js
✅ Files skipped from review due to trivial changes (1)
  • src/app.js

📝 Walkthrough

Walkthrough

This PR implements code splitting via React.lazy/Suspense in layout components while refactoring imports across the codebase to use specific module paths instead of barrel exports. It includes lodash import optimizations for tree-shaking and updates webpack configuration to support chunked output.

Changes

Cohort / File(s) Summary
Layout Code Splitting
src/layouts/primary-layout.js, src/layouts/summit-id-layout.js, src/layouts/event-id-layout.js, src/layouts/location-id-layout.js, src/layouts/selection-plan-id-layout.js, src/layouts/sponsor-id-layout.js, src/layouts/track-chairs-layout.js
Converted static component imports to React.lazy() with Suspense boundaries and AjaxLoader fallback. Routes now load asynchronously, reducing initial bundle size.
Layout Refactoring
src/layouts/event-layout.js
Converted class component to functional component, added lazy loading for route targets, and wrapped Switch in Suspense with AjaxLoader fallback.
Webpack Configuration
webpack.prod.js
Added output.chunkFilename configuration to support code-split chunk naming alongside filename patterns; normalized formatting and quotes.
Lodash Import Optimization
src/actions/attendee-actions.js, src/actions/badge-actions.js, src/actions/company-actions.js, src/actions/email-actions.js, src/actions/event-actions.js, src/actions/filter-criteria-actions.js, src/actions/media-upload-actions.js, src/actions/selection-plan-actions.js, src/actions/sponsor-actions.js, src/actions/sponsorship-actions.js, src/actions/track-chair-actions.js
Replaced lodash namespace imports with direct lodash/debounce imports for tree-shaking support; updated debounced function calls from _.debounce(...) to debounce(...).
Barrel Import Refactoring
src/app.js, src/components/forms/..., src/components/inputs/..., src/components/reports/..., src/components/tables/..., src/pages/..., src/reducers/... (150+ files)
Replaced aggregated named imports from openstack-uicore-foundation/lib/components with targeted default imports from specific submodule paths (e.g., .../inputs/dropdown, .../table, .../free-text-search). Consistent pattern applied across forms, inputs, pages, and reports for smaller bundle impact via tree-shaking.
Cleanup
src/actions/reg-feed-metadata-actions.js
Removed unused lodash import.
Lodash Utility Optimization
src/pages/sponsors/sponsor-users-list-page/components/edit-user-popup/access-rights-lists.js, src/reducers/orders/purchase-order-reducer.js, src/reducers/track_chairs/team-lists-reducer.js
Replaced _.cloneDeep(...) with direct cloneDeep import from lodash/cloneDeep for tree-shaking.
Dependency Update
package.json
Updated openstack-uicore-foundation from 5.0.8 to 5.0.9-beta.22 to align with new component module structure.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Possibly related PRs

  • PR #859: Modifies sponsor layout route structure alongside lazy-loading refactoring in src/layouts/sponsor-id-layout.js and src/layouts/sponsor-layout.js.
  • PR #698: Changes sponsor route sub-paths in src/layouts/sponsor-id-layout.js concurrently with code-splitting updates.
  • PR #797: Alters src/actions/sponsor-actions.js export signatures while this PR updates their debounce implementations.

Suggested reviewers

  • smarcet

🐰 Lazy routes now hop into view,
Tree-shaking trims the bundle true,
Suspense shows loaders while they creep,
Smaller chunks make performance leap!

🚥 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 title 'feature: Reduce bundle size' accurately reflects the primary objective of this changeset, which implements code-splitting via lazy loading and optimizes imports across the codebase.
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 feature/lazy-load-layouts
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feature/lazy-load-layouts

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.

🧹 Nitpick comments (3)
src/layouts/summit-id-layout.js (1)

147-318: Same error boundary recommendation applies here.

This layout has many lazy-loaded chunks. A chunk loading failure without an error boundary would crash the entire admin UI. Consider implementing a shared error boundary component that both layout files can use.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layouts/summit-id-layout.js` around lines 147 - 318, The Suspense block
in summit-id-layout.js currently wraps many lazy-loaded Route components
(Suspense, Switch, Route, NoMatchPage, SummitDashboardPage, EditSummitPage,
etc.) but has no error boundary, so chunk load failures can crash the app; add a
shared ErrorBoundary component (or use react-error-boundary's ErrorBoundary) and
wrap the Suspense (or wrap each lazy route group) with it, providing a fallback
UI and retry logic so lazy import errors are caught and the admin UI doesn't
crash.
src/layouts/primary-layout.js (1)

66-97: Consider adding an error boundary around Suspense for resilience.

If a chunk fails to load (e.g., network error, deployment of new assets), the app will crash without an error boundary. For production readiness, wrap the Suspense in an error boundary component that can display a retry UI or graceful fallback.

This is especially important for admin applications where users may have long-lived sessions spanning deployments.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layouts/primary-layout.js` around lines 66 - 97, Wrap the Suspense block
in a React error boundary so chunk/load failures don't crash the app: create or
import an ErrorBoundary component (e.g., RouteErrorBoundary or
PrimaryErrorBoundary) and replace the current Suspense usage in PrimaryLayout by
nesting Suspense inside <ErrorBoundary> (keeping the AjaxLoader fallback for
loading) and render a recovery UI with retry/navigation in the boundary's
fallback; ensure the ErrorBoundary catches rendering errors from the lazy-loaded
routes (SummitDirectoryPage, SpeakerLayout, CompanyLayout, etc.) and provides a
retry handler that re-mounts the Suspense children.
webpack.prod.js (1)

11-12: Minor: Inconsistent naming separator between JS and CSS.

JS files use underscore ([name]_[contenthash].js) while CSS uses dot ([name].[contenthash].css). This doesn't affect functionality but could be aligned for consistency.

Also applies to: 37-37

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@webpack.prod.js` around lines 11 - 12, The JS output naming uses underscores
("filename" and "chunkFilename" set to "[name]_[contenthash].js") while CSS uses
dots ("[name].[contenthash].css"); update the JS templates to use dots to match
CSS (or vice versa if you prefer underscores) by changing the values of filename
and chunkFilename to "[name].[contenthash].js" so the asset naming is consistent
with the CSS filename pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/layouts/primary-layout.js`:
- Around line 66-97: Wrap the Suspense block in a React error boundary so
chunk/load failures don't crash the app: create or import an ErrorBoundary
component (e.g., RouteErrorBoundary or PrimaryErrorBoundary) and replace the
current Suspense usage in PrimaryLayout by nesting Suspense inside
<ErrorBoundary> (keeping the AjaxLoader fallback for loading) and render a
recovery UI with retry/navigation in the boundary's fallback; ensure the
ErrorBoundary catches rendering errors from the lazy-loaded routes
(SummitDirectoryPage, SpeakerLayout, CompanyLayout, etc.) and provides a retry
handler that re-mounts the Suspense children.

In `@src/layouts/summit-id-layout.js`:
- Around line 147-318: The Suspense block in summit-id-layout.js currently wraps
many lazy-loaded Route components (Suspense, Switch, Route, NoMatchPage,
SummitDashboardPage, EditSummitPage, etc.) but has no error boundary, so chunk
load failures can crash the app; add a shared ErrorBoundary component (or use
react-error-boundary's ErrorBoundary) and wrap the Suspense (or wrap each lazy
route group) with it, providing a fallback UI and retry logic so lazy import
errors are caught and the admin UI doesn't crash.

In `@webpack.prod.js`:
- Around line 11-12: The JS output naming uses underscores ("filename" and
"chunkFilename" set to "[name]_[contenthash].js") while CSS uses dots
("[name].[contenthash].css"); update the JS templates to use dots to match CSS
(or vice versa if you prefer underscores) by changing the values of filename and
chunkFilename to "[name].[contenthash].js" so the asset naming is consistent
with the CSS filename pattern.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ed040fbc-ecd3-46ca-8708-71f5b24d935a

📥 Commits

Reviewing files that changed from the base of the PR and between 0ca3f92 and 3f4d612.

📒 Files selected for processing (3)
  • src/layouts/primary-layout.js
  • src/layouts/summit-id-layout.js
  • webpack.prod.js

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: 2

🧹 Nitpick comments (1)
src/layouts/location-id-layout.js (1)

115-119: Consider adding numeric constraint to :room_id for consistency.

Other routes in this file (e.g., :floor_id(\\d+) on line 90) use (\\d+) to restrict the parameter to digits. The :room_id, :image_id, and :map_id parameters lack this constraint. If these IDs are always numeric, adding the constraint would prevent accidental matches on non-numeric paths.

♻️ Proposed fix
                 <Route
                   strict
                   exact
-                  path={`${props.match.url}/:room_id`}
+                  path={`${props.match.url}/:room_id(\\d+)`}
                   component={EditRoomPage}
                 />

Apply similar changes to :image_id (line 146) and :map_id (line 174).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layouts/location-id-layout.js` around lines 115 - 119, Update the Route
paths that use numeric IDs to enforce digit-only params: change the path for the
Route rendering EditRoomPage (currently using `${props.match.url}/:room_id`) to
`${props.match.url}/:room_id(\\d+)`, and likewise add `(\\d+)` to the
`:image_id` and `:map_id` route path strings so they become
`${props.match.url}/:image_id(\\d+)` and `${props.match.url}/:map_id(\\d+)`,
ensuring the routes only match numeric IDs while preserving the existing
props.match.url composition and component props (EditRoomPage and the components
for image_id/map_id).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/layouts/event-id-layout.js`:
- Around line 101-113: The Route for EditEventCommentPage is unreachable because
it duplicates the same paramized path as the EditEventMaterialPage route under
this layout; remove the Route element whose component is EditEventCommentPage
(the Route using path={`${props.match.url}/:comment_id`}) so only the
EditEventMaterialPage route and the fallback NoMatchPage remain, ensuring
comment editing routes stay defined under the dedicated /comments routes
elsewhere.

In `@src/layouts/sponsor-layout.js`:
- Around line 86-101: The Route currently passes both render and component which
causes the render block with Breadcrumb to be ignored; update the Route so it
uses only the render prop: remove the component={ShowPagesListPage} prop and
inside the render callback return both the Breadcrumb and the ShowPagesListPage
component (render ShowPagesListPage within the same render function and forward
props via props or {...props} so routing props are preserved), referencing
Route, Breadcrumb, ShowPagesListPage, and match.url to locate the code.

---

Nitpick comments:
In `@src/layouts/location-id-layout.js`:
- Around line 115-119: Update the Route paths that use numeric IDs to enforce
digit-only params: change the path for the Route rendering EditRoomPage
(currently using `${props.match.url}/:room_id`) to
`${props.match.url}/:room_id(\\d+)`, and likewise add `(\\d+)` to the
`:image_id` and `:map_id` route path strings so they become
`${props.match.url}/:image_id(\\d+)` and `${props.match.url}/:map_id(\\d+)`,
ensuring the routes only match numeric IDs while preserving the existing
props.match.url composition and component props (EditRoomPage and the components
for image_id/map_id).
🪄 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: d5e133a5-ba11-4d8a-9550-08515a4ca8be

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4d612 and 0d552d8.

📒 Files selected for processing (7)
  • src/layouts/event-id-layout.js
  • src/layouts/event-layout.js
  • src/layouts/location-id-layout.js
  • src/layouts/selection-plan-id-layout.js
  • src/layouts/sponsor-id-layout.js
  • src/layouts/sponsor-layout.js
  • src/layouts/track-chairs-layout.js

Comment on lines +101 to +113
<Route
strict
exact
path={`${props.match.url}/:material_id`}
component={EditEventMaterialPage}
/>
<Route
strict
exact
path={`${props.match.url}/:comment_id`}
component={EditEventCommentPage}
/>
<Route component={NoMatchPage} />
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

Route for EditEventCommentPage is unreachable under /materials.

Both routes on lines 104 and 110 match the same URL pattern (${props.match.url}/:param). React Router matches the first one, so EditEventCommentPage will never render via this path. This appears to be a misplaced route—comment editing routes exist separately under /comments (lines 150-157).

🐛 Proposed fix: remove the unreachable route
                   <Route
                     strict
                     exact
                     path={`${props.match.url}/:material_id`}
                     component={EditEventMaterialPage}
                   />
-                  <Route
-                    strict
-                    exact
-                    path={`${props.match.url}/:comment_id`}
-                    component={EditEventCommentPage}
-                  />
                   <Route component={NoMatchPage} />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Route
strict
exact
path={`${props.match.url}/:material_id`}
component={EditEventMaterialPage}
/>
<Route
strict
exact
path={`${props.match.url}/:comment_id`}
component={EditEventCommentPage}
/>
<Route component={NoMatchPage} />
<Route
strict
exact
path={`${props.match.url}/:material_id`}
component={EditEventMaterialPage}
/>
<Route component={NoMatchPage} />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layouts/event-id-layout.js` around lines 101 - 113, The Route for
EditEventCommentPage is unreachable because it duplicates the same paramized
path as the EditEventMaterialPage route under this layout; remove the Route
element whose component is EditEventCommentPage (the Route using
path={`${props.match.url}/:comment_id`}) so only the EditEventMaterialPage route
and the fallback NoMatchPage remain, ensuring comment editing routes stay
defined under the dedicated /comments routes elsewhere.

Comment on lines +86 to +101
<Route
path={`${match.url}/pages`}
render={(props) => (
<div>
<Breadcrumb
data={{
title: T.translate("show_pages.pages"),
pathname: props.match.url
}}
/>
<Route
path={`${props.match.url}/:promocode_id(\\d+)`}
component={EditPromocodePage}
</div>
)}
strict
exact
component={ShowPagesListPage}
/>
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

Route has both render and component props—render will be ignored.

React Router v5 prioritizes component over render when both are provided. The Breadcrumb inside the render prop (lines 88-97) will never be rendered, and ShowPagesListPage will be displayed without the breadcrumb.

🐛 Proposed fix: use only `render` prop to include the Breadcrumb
         <Route
           path={`${match.url}/pages`}
           render={(props) => (
             <div>
               <Breadcrumb
                 data={{
                   title: T.translate("show_pages.pages"),
                   pathname: props.match.url
                 }}
               />
+              <ShowPagesListPage {...props} />
             </div>
           )}
-          strict
-          exact
-          component={ShowPagesListPage}
         />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Route
path={`${match.url}/pages`}
render={(props) => (
<div>
<Breadcrumb
data={{
title: T.translate("show_pages.pages"),
pathname: props.match.url
}}
/>
<Route
path={`${props.match.url}/:promocode_id(\\d+)`}
component={EditPromocodePage}
</div>
)}
strict
exact
component={ShowPagesListPage}
/>
<Route
path={`${match.url}/pages`}
render={(props) => (
<div>
<Breadcrumb
data={{
title: T.translate("show_pages.pages"),
pathname: props.match.url
}}
/>
<ShowPagesListPage {...props} />
</div>
)}
/>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layouts/sponsor-layout.js` around lines 86 - 101, The Route currently
passes both render and component which causes the render block with Breadcrumb
to be ignored; update the Route so it uses only the render prop: remove the
component={ShowPagesListPage} prop and inside the render callback return both
the Breadcrumb and the ShowPagesListPage component (render ShowPagesListPage
within the same render function and forward props via props or {...props} so
routing props are preserved), referencing Route, Breadcrumb, ShowPagesListPage,
and match.url to locate the code.

@santipalenque santipalenque changed the title chore: lazy load components - WIP feature: Reduce bundle size Apr 17, 2026
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: 20

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/actions/ably-actions.js (1)

36-43: ⚠️ Potential issue | 🟠 Major

Remove subscription from publish function and add proper error handling.

Publishing a message should not create a new subscriber on every call. Additionally, publish() returns a Promise in Ably v1.2.39 but the current code doesn't await it or handle failures—it unconditionally returns true regardless of whether the publish succeeded.

Proposed fix
  const ablyChannel = client.channels.get(channel);
-
-  ablyChannel.subscribe((msg) => {
-    console.log(`Received: ${JSON.stringify(msg.data)}`);
-  });
-
-  ablyChannel.publish(key, message);
-
-  return true;
+  try {
+    await ablyChannel.publish(key, message);
+    return true;
+  } catch (error) {
+    Swal.fire("Publish failed", "Unable to publish message", "error");
+    return false;
+  }
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/actions/ably-actions.js` around lines 36 - 43, The publish function
currently subscribes on every call and doesn't await or handle publish failures;
remove the ablyChannel.subscribe call from the publish flow so publishing does
not create a new subscriber, then change the call to ablyChannel.publish(key,
message) to be awaited and wrapped in try/catch; on success return true, on
error log the error (use existing logger) and return false. Locate the logic
using the ablyChannel variable and the publish invocation to implement this
change and ensure no subscription is created inside the publish function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/actions/ably-actions.js`:
- Line 14: The two exported thunk factories declare an unused dispatch parameter
causing lint errors; in subscribeToAblyChannel and the other thunk at the same
file (the one starting on line ~29), remove the unused dispatch parameter by
replacing the arrow parameter list "(dispatch) =>" with an empty parameter list
"()" (or eliminate the outer thunk wrapper entirely if dispatch is not needed)
so the functions become e.g. export const subscribeToAblyChannel = (channel,
callback) => async () => { ... } and do the same for the other thunk.
- Around line 6-12: The getAblyClient function can race and propagate
import/constructor errors; fix it by adding a module-level initialization
promise (e.g., initializationPromise) that is set when starting the
import/construct sequence so concurrent callers await the same promise, wrap the
import and new Ably.Realtime(AblyApiKey) in a try/catch to handle failures,
ensure realtimeAbly is assigned only on success and cleared/set to null on
failure, clear initializationPromise on failure or success accordingly, and
always return realtimeAbly or null (never let the raw thrown error escape) so
callers get the controlled null instead of rejected promises.

In `@src/components/forms/promocode-form/forms/discount-base-pc-form.js`:
- Around line 3-4: Reorder the import statements so external package imports
come before local relative imports to satisfy ESLint import/order: move the
Input import (openstack-uicore-foundation/lib/components/inputs/text-input)
above the BasePCForm relative import; update the top of the file where
BasePCForm and Input are imported so Input is imported first.

In `@src/components/forms/schedule-settings-form/index.js`:
- Line 31: The import ordering for SortableTable is wrong; move the external
module import "SortableTable" (SortableTable from
openstack-uicore-foundation/lib/components/table-sortable) so that it appears
before local/project utility imports in index.js to satisfy import/order linting
— locate the current SortableTable import and reposition it above any
relative/local imports (utilities/helpers/components) in the file.

In `@src/components/forms/schedule-settings-form/pre-filter-input.js`:
- Around line 7-9: Move the external library imports (CompanyInput,
SpeakerInput, TagInput from "openstack-uicore-foundation/...") so they appear
before any local relative imports in pre-filter-input.js to satisfy
import/order; locate the lines importing CompanyInput, SpeakerInput, and
TagInput and place them above the local module imports in that file.

In `@src/components/forms/submission-invitation-form.js`:
- Line 15: Remove the unused import of TicketTypesInput from the top of the
file: locate the import statement that reads TicketTypesInput from
"openstack-uicore-foundation/lib/components/inputs/ticket-types-input" and
delete it so the component no longer imports an unused symbol and avoids
increasing bundle size.

In `@src/components/reports/attendee-report.js`:
- Around line 15-18: Move the non-ESM require for Query so all import statements
are first: replace or relocate the const Query =
require("graphql-query-builder") line to come after the imports block or convert
it to an import (e.g., import Query from "graphql-query-builder") so that Query
is imported using an import declaration and occurs before any other executable
code; update references to Query in this file (attendee-report.js) accordingly
to satisfy the import/first ESLint rule.

In `@src/components/reports/metrics-report.js`:
- Around line 16-22: The file has an ESLint import/newline-after-import error
because the CommonJS require for Query sits immediately after ES module import
statements; insert a single blank line before the non-import statement "const
Query = require('graphql-query-builder')" so all import statements are grouped
and the require is separated, resolving the lint rule violation.

In `@src/components/reports/presentation-video-report.js`:
- Around line 15-16: Add a blank line after the ES module import statement so
the import of Table (import Table from
"openstack-uicore-foundation/lib/components/table") is separated from the
CommonJS require for Query (const Query = require("graphql-query-builder"));
update the top of the file (around the Table import and Query declaration) to
insert one empty line between them to satisfy the import/newline-after-import
ESLint rule.

In `@src/components/reports/room-report.js`:
- Around line 16-18: Move the CommonJS require for Query out of the middle of ES
module imports: group all import statements together (e.g., the imports of Table
and wrapReport) and then add a blank line followed by the const Query =
require("graphql-query-builder") statement; ensure Query remains named the same
and only its position changes to satisfy the import/newline-after-import ESLint
rule.

In `@src/components/reports/rsvp-event-report.js`:
- Around line 15-17: The require statement breaks the import grouping and causes
the lint error; move the CommonJS require for Query after the ES module imports
and add a single blank line between the import block (Table, wrapReport) and the
const Query = require("graphql-query-builder") line, or replace it with an ES
import (import Query from "graphql-query-builder") to keep all imports together;
adjust the top of rsvp-event-report.js around the Table, wrapReport and Query
symbols accordingly.

In `@src/components/reports/tag-report.js`:
- Around line 15-17: The ES6 imports (Table, wrapReport) should be grouped
together and the CommonJS require for Query must come after them with a blank
line to satisfy import/newline-after-import; move `const Query =
require("graphql-query-builder");` below the ES6 import statements and add a
separating blank line, keeping references to Table and wrapReport intact in
tag-report.js.

In `@src/components/reports/tag-single-report.js`:
- Around line 15-17: The lint failure is caused by the CommonJS require for
Query breaking the import group; replace the require with an ES module import
(e.g., import Query from "graphql-query-builder") or at minimum move the `const
Query = require("graphql-query-builder")` so it comes after the other import
statements with a blank line separating groups; update the symbol `Query` usage
accordingly in this file (`tag-single-report.js`) so imports are consistently
grouped and the `import/newline-after-import` rule is satisfied.

In `@src/components/schedule-builder/schedule-admin-dashboard.js`:
- Around line 71-74: The new direct imports Dropdown, OperatorInput,
BulkActionsSelector, and ScheduleBuilderView are placed after local action
imports and violate the import/order rule; move these four import statements so
they appear with the other external/library imports (i.e., grouped before the
local imports such as any ../../actions/...) to satisfy ESLint and avoid CI/lint
failures.

In `@src/components/SentryErrorBoundary/index.js`:
- Around line 12-15: The dynamic import of ../../sentry-init in
componentDidMount (import("../../sentry-init").then(({ initSentry }) => { const
Sentry = initSentry(); this.setState({ ErrorBoundary: Sentry.ErrorBoundary });
})) can reject and is missing error handling; add a .catch handler on the import
promise that logs the error (or reports it) and sets a safe fallback by calling
this.setState with a default/local ErrorBoundary (or null) so the component
won't cause an unhandled promise rejection and will continue to render safely;
reference the dynamic import, initSentry, Sentry.ErrorBoundary and this.setState
when applying the change.

In `@src/pages/registration/registration-stats-page.js`:
- Around line 26-27: The two external imports AjaxLoader and SteppedSelect are
placed after local relative imports, violating the import/order lint rule; move
the lines importing AjaxLoader and SteppedSelect so they appear with the other
external (third-party) imports—i.e., above any local or relative imports—to
restore the correct import grouping and satisfy the linter.

In `@src/pages/speakers/merge-speakers-page.js`:
- Around line 19-21: The import ordering currently places the external package
import SpeakerInput after local imports (MergeSpeakerForm, getSummitById);
reorder imports so external/third-party modules come before local relative
imports to satisfy ESLint import/order. Specifically, move the import for
SpeakerInput (from
"openstack-uicore-foundation/lib/components/inputs/speaker-input") above the
local imports for MergeSpeakerForm and getSummitById so the file groups
third-party imports (e.g., SpeakerInput) first, then project-local imports like
MergeSpeakerForm and getSummitById.

In `@src/pages/summit_speakers/featured-speakers-page.js`:
- Line 21: The file contains an unused import "Table" (import Table from
"openstack-uicore-foundation/lib/components/table";) which should be removed to
avoid dead code and reduce bundle size—delete that import statement and ensure
no other references to the Table symbol remain in the module (check for "Table"
usage in functions or JSX such as FeaturedSpeakersPage or any exported
components).

In `@src/reducers/orders/order-extra-question-list-reducer.js`:
- Line 14: Remove the unused import RawHTML from the top of the reducer file:
delete the line importing RawHTML ("import RawHTML from
\"openstack-uicore-foundation/lib/components/raw-html\";") so the unused symbol
is no longer present and lint will pass.

In `@src/sentry-init.js`:
- Around line 11-12: Convert the runtime Sentry config values before calling
Sentry.init: parse window.SENTRY_TRACE_SAMPLE_RATE into a number (e.g.
Number(...) or parseFloat and fall back to undefined/null if NaN) and normalize
window.SENTRY_TRACE_PROPAGATION_TARGETS by splitting the string on commas,
trimming each entry and filtering out empty strings (optionally converting
entries like "/regex/" to RegExp if your app expects regexes), then pass the
numeric tracesSampleRate and the resulting array to Sentry.init for
tracesSampleRate and tracePropagationTargets respectively.

---

Outside diff comments:
In `@src/actions/ably-actions.js`:
- Around line 36-43: The publish function currently subscribes on every call and
doesn't await or handle publish failures; remove the ablyChannel.subscribe call
from the publish flow so publishing does not create a new subscriber, then
change the call to ablyChannel.publish(key, message) to be awaited and wrapped
in try/catch; on success return true, on error log the error (use existing
logger) and return false. Locate the logic using the ablyChannel variable and
the publish invocation to implement this change and ensure no subscription is
created inside the publish function.
🪄 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: 4e363ee2-0bd3-4334-872c-a11e0281f3a9

📥 Commits

Reviewing files that changed from the base of the PR and between 0d552d8 and 8fe0a3b.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (203)
  • package.json
  • src/actions/ably-actions.js
  • src/actions/attendee-actions.js
  • src/actions/badge-actions.js
  • src/actions/company-actions.js
  • src/actions/email-actions.js
  • src/actions/event-actions.js
  • src/actions/filter-criteria-actions.js
  • src/actions/media-file-type-actions.js
  • src/actions/media-upload-actions.js
  • src/actions/reg-feed-metadata-actions.js
  • src/actions/selection-plan-actions.js
  • src/actions/sponsor-actions.js
  • src/actions/sponsorship-actions.js
  • src/actions/track-chair-actions.js
  • src/app.js
  • src/components/SentryErrorBoundary/index.js
  • src/components/audit-logs/index.js
  • src/components/filters/date-interval-filter.js
  • src/components/filters/save-filter-criteria/index.js
  • src/components/forms/admin-access-form.js
  • src/components/forms/attendee-form/attendee-form.js
  • src/components/forms/attendee-form/ticket-component.js
  • src/components/forms/badge-feature-type-form.js
  • src/components/forms/badge-scan-form.js
  • src/components/forms/badge-settings-form.js
  • src/components/forms/company-form.js
  • src/components/forms/email-activity.js
  • src/components/forms/email-flow-event-form/index.js
  • src/components/forms/email-flow-event-settings-form.js
  • src/components/forms/email-template-form.js
  • src/components/forms/event-category-form.js
  • src/components/forms/event-form.js
  • src/components/forms/event-material-form.js
  • src/components/forms/event-rsvp-form.js
  • src/components/forms/extra-question-form/index.js
  • src/components/forms/extra-question-sub-question-form.js
  • src/components/forms/floor-form.js
  • src/components/forms/form-template-meta-field-form.js
  • src/components/forms/image-form.js
  • src/components/forms/inventory-item-meta-field-form.js
  • src/components/forms/location-form.js
  • src/components/forms/marketing-setting-form.js
  • src/components/forms/media-upload-form.js
  • src/components/forms/payment-fee-type-form.js
  • src/components/forms/payment-profile-form.js
  • src/components/forms/promocode-form/forms/base-pc-form.js
  • src/components/forms/promocode-form/forms/discount-base-pc-form.js
  • src/components/forms/promocode-form/forms/generic-base-pc-form.js
  • src/components/forms/promocode-form/forms/speaker-base-pc-form.js
  • src/components/forms/promocode-form/forms/speakers-base-pc-form.js
  • src/components/forms/promocode-form/forms/sponsor-base-pc-form.js
  • src/components/forms/promocode-form/index.js
  • src/components/forms/purchase-order-form.js
  • src/components/forms/push-notification-form.js
  • src/components/forms/question-form.js
  • src/components/forms/rating-type-form.js
  • src/components/forms/reg-feed-metadata-form.js
  • src/components/forms/registration-invitation-form.js
  • src/components/forms/room-booking-attribute-form.js
  • src/components/forms/room-booking-form.js
  • src/components/forms/rsvp-form.js
  • src/components/forms/rsvp-template-form.js
  • src/components/forms/schedule-settings-form/index.js
  • src/components/forms/schedule-settings-form/pre-filter-input.js
  • src/components/forms/score-type-form.js
  • src/components/forms/speaker-attendance-form.js
  • src/components/forms/speaker-form.js
  • src/components/forms/speakers-promo-code-spec-form.js
  • src/components/forms/sponsor-advertisement-form.js
  • src/components/forms/sponsor-form.js
  • src/components/forms/sponsor-material-form.js
  • src/components/forms/sponsor-social-network-form.js
  • src/components/forms/sponsored-project-form.js
  • src/components/forms/sponsored-project-sponsorship-type-form.js
  • src/components/forms/sponsored-project-sponsorship-type-supporting-company-form.js
  • src/components/forms/sponsorship-form.js
  • src/components/forms/submission-invitation-form.js
  • src/components/forms/summit-form.js
  • src/components/forms/summit-sponsorship-form.js
  • src/components/forms/summitdoc-form.js
  • src/components/forms/tag-form.js
  • src/components/forms/ticket-form.js
  • src/components/forms/ticket-type-form.js
  • src/components/forms/view-type-form.js
  • src/components/import-promocodes/index.js
  • src/components/inputs/acceptance-criteria-dropdown.js
  • src/components/inputs/date-interval-input.js
  • src/components/inputs/email-filter/index.js
  • src/components/inputs/event-type-dropdown.js
  • src/components/inputs/invitation-status-dropdown.js
  • src/components/inputs/level-dropdown.js
  • src/components/inputs/location-dropdown.js
  • src/components/inputs/owner-input.js
  • src/components/inputs/question-answers-input.js
  • src/components/inputs/selection-plan-dropdown.js
  • src/components/inputs/text-input-with-counter.js
  • src/components/inputs/track-dropdown.js
  • src/components/inputs/track-group-dropdown.js
  • src/components/inputs/url-input.js
  • src/components/inventory-items-modal.js
  • src/components/menu/menu-item.js
  • src/components/mui/confirm-dialog.js
  • src/components/mui/formik-inputs/mui-formik-upload.js
  • src/components/mui/table/mui-table.js
  • src/components/notes/index.js
  • src/components/reports/attendee-report.js
  • src/components/reports/feedback-group-report.js
  • src/components/reports/feedback-report.js
  • src/components/reports/metrics-report.js
  • src/components/reports/presentation-video-report.js
  • src/components/reports/report-wrapper.js
  • src/components/reports/room-manifest-report.js
  • src/components/reports/room-report.js
  • src/components/reports/rsvp-event-report.js
  • src/components/reports/smart-presentation-report.js
  • src/components/reports/smart-speaker-report.js
  • src/components/reports/tag-report.js
  • src/components/reports/tag-single-report.js
  • src/components/rsvp/event-rsvp-invitation-blast.js
  • src/components/rsvp/event-rsvp-invitation-list.js
  • src/components/rsvp/event-rsvp-list.js
  • src/components/rsvp/event-rsvp-resend.js
  • src/components/schedule-builder/schedule-admin-dashboard.js
  • src/components/schedule-builder/schedule-admin-empty-spots-modal.js
  • src/components/schedule-builder/schedule-event-result.js
  • src/components/schedule-builder/unschedule-event.js
  • src/components/summit-dropdown/index.js
  • src/components/summit-event-bulk-actions/summit-event-bulk-editor-form.js
  • src/components/summit-event-bulk-actions/summit-event-bulk-editor-item.js
  • src/components/tables/affiliationstable/AffiliationsTable.js
  • src/components/tables/dicount-ticket-table/DiscountTicketTable.js
  • src/components/tables/editable-table/EditableTableRow.js
  • src/components/tables/extra-questions-table/index.js
  • src/components/tables/room-occupancy-table/OccupancyTableCell.js
  • src/components/tables/signagebannerstable/BannersTable.js
  • src/components/tables/track-timeframes/DayTimeframeTable.js
  • src/pages/admin_access/admin-access-list-page.js
  • src/pages/attendees/summit-attendees-list-page.js
  • src/pages/badges/access-level-list-page.js
  • src/pages/badges/badge-feature-list-page.js
  • src/pages/badges/badge-type-list-page.js
  • src/pages/badges/edit-access-level-page.js
  • src/pages/badges/view-type-list-page.js
  • src/pages/companies/company-list-page.js
  • src/pages/email_flow_events/email-flow-events-list-page.js
  • src/pages/emails/email-log-list-page.js
  • src/pages/emails/email-template-list-page.js
  • src/pages/events/event-category-group-list-page.js
  • src/pages/events/event-category-list-page.js
  • src/pages/events/event-type-list-page.js
  • src/pages/events/summit-event-list-page.js
  • src/pages/events/summit-presentations-votes-page.js
  • src/pages/locations/location-list-page.js
  • src/pages/marketing/marketing-setting-list-page.js
  • src/pages/media_file_types/edit-media-file-type-page.js
  • src/pages/media_file_types/media-file-type-list-page.js
  • src/pages/media_uploads/media-upload-list-page.js
  • src/pages/orders/edit-ticket-page.js
  • src/pages/orders/order-extra-question-list-page.js
  • src/pages/orders/purchase-order-list-page.js
  • src/pages/promocodes/promocode-list-page.js
  • src/pages/push_notifications/push-notification-list-page.js
  • src/pages/registration/registration-companies-list-page.js
  • src/pages/registration/registration-stats-page.js
  • src/pages/room_bookings/room-booking-list-page.js
  • src/pages/room_occupancy/room-occupancy-page.js
  • src/pages/rsvps/rsvp-template-list-page.js
  • src/pages/schedule_settings/schedule-settings-list-page.js
  • src/pages/selection-plans/selection-plan-list-page.js
  • src/pages/signage/index.js
  • src/pages/speakers/merge-speakers-page.js
  • src/pages/speakers/submission-invitations-list-page.js
  • src/pages/speakers/summit-speakers-list-page.js
  • src/pages/sponsored_projects/sponsored-project-list-page.js
  • src/pages/sponsors-global/form-templates/sponsor-inventory-popup.js
  • src/pages/sponsors/badge-scans-list-page.js
  • src/pages/sponsors/popup/edit-tier-popup.js
  • src/pages/sponsors/sponsor-list-page.js
  • src/pages/sponsors/sponsor-promocodes-list-page.js
  • src/pages/sponsors/sponsor-users-list-page/components/edit-user-popup/access-rights-lists.js
  • src/pages/sponsorship-types/sponsorship-list-page.js
  • src/pages/summit_speakers/featured-speakers-page.js
  • src/pages/summit_speakers/speaker-attendance-list-page.js
  • src/pages/summit_speakers/summit-speakers-list-page.js
  • src/pages/summitdocs/summitdoc-list-page.js
  • src/pages/tag_groups/edit-tag-group-page.js
  • src/pages/tag_groups/tag-group-list-page.js
  • src/pages/tags/tag-list-page.js
  • src/pages/taxes/tax-type-list-page.js
  • src/pages/tickets/payment-profile-list-page.js
  • src/pages/tickets/refund-policy-list-page.js
  • src/pages/tickets/registration-invitations-list-page.js
  • src/pages/tickets/ticket-list-page.js
  • src/pages/tickets/ticket-type-list-page.js
  • src/pages/track_chairs/progress-flags-page.js
  • src/pages/track_chairs/team-lists-page.js
  • src/pages/track_chairs/track-chair-list-page.js
  • src/pages/track_chairs/track-timeframe-list-page.js
  • src/reducers/orders/order-extra-question-list-reducer.js
  • src/reducers/orders/purchase-order-reducer.js
  • src/reducers/track_chairs/team-lists-reducer.js
  • src/sentry-init.js
💤 Files with no reviewable changes (1)
  • src/actions/reg-feed-metadata-actions.js
✅ Files skipped from review due to trivial changes (140)
  • package.json
  • src/actions/media-file-type-actions.js
  • src/components/reports/room-manifest-report.js
  • src/actions/company-actions.js
  • src/components/audit-logs/index.js
  • src/components/filters/save-filter-criteria/index.js
  • src/components/forms/admin-access-form.js
  • src/components/forms/attendee-form/attendee-form.js
  • src/components/forms/attendee-form/ticket-component.js
  • src/components/forms/badge-feature-type-form.js
  • src/components/forms/badge-scan-form.js
  • src/components/forms/email-activity.js
  • src/components/forms/email-flow-event-settings-form.js
  • src/components/forms/event-category-form.js
  • src/components/forms/event-rsvp-form.js
  • src/components/forms/extra-question-sub-question-form.js
  • src/components/forms/floor-form.js
  • src/components/forms/form-template-meta-field-form.js
  • src/components/forms/image-form.js
  • src/components/forms/inventory-item-meta-field-form.js
  • src/components/forms/location-form.js
  • src/components/forms/marketing-setting-form.js
  • src/components/forms/media-upload-form.js
  • src/components/forms/payment-fee-type-form.js
  • src/components/forms/payment-profile-form.js
  • src/components/forms/promocode-form/forms/base-pc-form.js
  • src/components/forms/promocode-form/forms/generic-base-pc-form.js
  • src/components/forms/promocode-form/forms/speaker-base-pc-form.js
  • src/components/forms/promocode-form/forms/sponsor-base-pc-form.js
  • src/components/forms/purchase-order-form.js
  • src/components/forms/reg-feed-metadata-form.js
  • src/components/forms/registration-invitation-form.js
  • src/components/forms/room-booking-attribute-form.js
  • src/components/forms/room-booking-form.js
  • src/components/forms/rsvp-form.js
  • src/components/forms/score-type-form.js
  • src/components/forms/speaker-attendance-form.js
  • src/components/forms/sponsor-advertisement-form.js
  • src/components/forms/sponsor-material-form.js
  • src/components/forms/sponsor-social-network-form.js
  • src/components/forms/sponsored-project-form.js
  • src/components/forms/sponsored-project-sponsorship-type-form.js
  • src/components/forms/sponsored-project-sponsorship-type-supporting-company-form.js
  • src/components/forms/sponsorship-form.js
  • src/components/forms/summit-sponsorship-form.js
  • src/components/forms/summitdoc-form.js
  • src/components/forms/ticket-form.js
  • src/components/forms/ticket-type-form.js
  • src/components/inputs/location-dropdown.js
  • src/components/inputs/owner-input.js
  • src/components/inputs/selection-plan-dropdown.js
  • src/components/inputs/text-input-with-counter.js
  • src/components/inputs/track-group-dropdown.js
  • src/components/inputs/url-input.js
  • src/components/mui/confirm-dialog.js
  • src/components/mui/formik-inputs/mui-formik-upload.js
  • src/components/mui/table/mui-table.js
  • src/components/reports/feedback-report.js
  • src/components/reports/smart-presentation-report.js
  • src/components/rsvp/event-rsvp-invitation-blast.js
  • src/components/import-promocodes/index.js
  • src/components/schedule-builder/schedule-event-result.js
  • src/components/schedule-builder/schedule-admin-empty-spots-modal.js
  • src/components/rsvp/event-rsvp-list.js
  • src/components/tables/track-timeframes/DayTimeframeTable.js
  • src/components/rsvp/event-rsvp-invitation-list.js
  • src/components/summit-event-bulk-actions/summit-event-bulk-editor-item.js
  • src/components/tables/editable-table/EditableTableRow.js
  • src/components/tables/room-occupancy-table/OccupancyTableCell.js
  • src/pages/badges/badge-type-list-page.js
  • src/pages/badges/badge-feature-list-page.js
  • src/pages/companies/company-list-page.js
  • src/pages/attendees/summit-attendees-list-page.js
  • src/pages/events/event-category-list-page.js
  • src/pages/events/event-type-list-page.js
  • src/pages/media_file_types/media-file-type-list-page.js
  • src/pages/media_file_types/edit-media-file-type-page.js
  • src/pages/media_uploads/media-upload-list-page.js
  • src/pages/events/summit-presentations-votes-page.js
  • src/pages/registration/registration-companies-list-page.js
  • src/pages/push_notifications/push-notification-list-page.js
  • src/pages/room_bookings/room-booking-list-page.js
  • src/pages/selection-plans/selection-plan-list-page.js
  • src/pages/sponsors/popup/edit-tier-popup.js
  • src/pages/speakers/submission-invitations-list-page.js
  • src/pages/admin_access/admin-access-list-page.js
  • src/components/tables/affiliationstable/AffiliationsTable.js
  • src/components/notes/index.js
  • src/components/tables/signagebannerstable/BannersTable.js
  • src/components/summit-event-bulk-actions/summit-event-bulk-editor-form.js
  • src/pages/badges/view-type-list-page.js
  • src/components/tables/dicount-ticket-table/DiscountTicketTable.js
  • src/pages/badges/access-level-list-page.js
  • src/pages/events/event-category-group-list-page.js
  • src/pages/emails/email-template-list-page.js
  • src/pages/email_flow_events/email-flow-events-list-page.js
  • src/pages/taxes/tax-type-list-page.js
  • src/pages/sponsors/sponsor-users-list-page/components/edit-user-popup/access-rights-lists.js
  • src/components/rsvp/event-rsvp-resend.js
  • src/pages/emails/email-log-list-page.js
  • src/pages/tickets/registration-invitations-list-page.js
  • src/pages/tags/tag-list-page.js
  • src/pages/track_chairs/team-lists-page.js
  • src/pages/tag_groups/tag-group-list-page.js
  • src/pages/track_chairs/progress-flags-page.js
  • src/pages/tickets/ticket-type-list-page.js
  • src/pages/speakers/summit-speakers-list-page.js
  • src/pages/sponsored_projects/sponsored-project-list-page.js
  • src/pages/promocodes/promocode-list-page.js
  • src/pages/schedule_settings/schedule-settings-list-page.js
  • src/pages/orders/purchase-order-list-page.js
  • src/components/forms/rating-type-form.js
  • src/pages/badges/edit-access-level-page.js
  • src/pages/sponsors/sponsor-promocodes-list-page.js
  • src/pages/orders/order-extra-question-list-page.js
  • src/actions/attendee-actions.js
  • src/actions/email-actions.js
  • src/actions/selection-plan-actions.js
  • src/components/forms/badge-settings-form.js
  • src/components/forms/email-template-form.js
  • src/components/forms/promocode-form/forms/speakers-base-pc-form.js
  • src/components/forms/question-form.js
  • src/components/forms/speakers-promo-code-spec-form.js
  • src/components/reports/report-wrapper.js
  • src/pages/tickets/ticket-list-page.js
  • src/pages/summit_speakers/speaker-attendance-list-page.js
  • src/pages/tickets/payment-profile-list-page.js
  • src/pages/track_chairs/track-chair-list-page.js
  • src/reducers/track_chairs/team-lists-reducer.js
  • src/actions/sponsor-actions.js
  • src/pages/track_chairs/track-timeframe-list-page.js
  • src/components/forms/event-form.js
  • src/pages/sponsors/badge-scans-list-page.js
  • src/pages/signage/index.js
  • src/components/schedule-builder/unschedule-event.js
  • src/components/forms/extra-question-form/index.js
  • src/actions/event-actions.js
  • src/components/inventory-items-modal.js
  • src/pages/summit_speakers/summit-speakers-list-page.js
  • src/actions/media-upload-actions.js

Comment thread src/actions/ably-actions.js Outdated
Comment on lines +6 to +12
const getAblyClient = async () => {
if (!AblyApiKey) return null;
if (realtimeAbly) return realtimeAbly;
const Ably = (await import("ably")).default;
realtimeAbly = new Ably.Realtime(AblyApiKey);
return realtimeAbly;
};
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

🧩 Analysis chain

🌐 Web query:

For ably@1.2.39, what is the recommended browser dynamic-import interop for Realtime (module.defaultvsmodule) and singleton initialization pattern?

💡 Result:

For ably@1.2.39 in browsers, the recommended dynamic-import interop for Realtime uses module.default because the browser bundle (e.g., ably/build/ably-commonjs.js or CDN) exports the Ably object as a default export in CommonJS style, compatible with IE9+. Recommended pattern: const loadAbly = async => { const module = await import('ably'); return module.default; }; const Ably = await loadAbly; const realtime = new Ably.Realtime({ key: 'your-key' }); For singleton initialization, create a single shared Realtime instance and reuse it across the application, exporting from a module to avoid multiples during HMR/page reloads. Official docs recommend one instance per connection state (using recover for persistence), e.g.: let realtime = null; export const getAblyRealtime = async (options) => { if (!realtime) { const Ably = await loadAbly; realtime = new Ably.Realtime(options); } return realtime; }; This ensures a singleton-like pattern while preserving connection recovery.

Citations:


Harden Ably singleton initialization against concurrent races and import failures.

Concurrent first calls can create multiple Ably.Realtime instances because the uninitialized realtimeAbly check doesn't prevent parallel execution of the import and constructor. Import or constructor failures are also unhandled, so callers receive rejected promises instead of the controlled null return value. The proposed fix uses promise-based locking to serialize initialization and properly catches failures.

Proposed fix
 let realtimeAbly = null;
+let realtimeAblyInitPromise = null;

 const getAblyClient = async () => {
   if (!AblyApiKey) return null;
   if (realtimeAbly) return realtimeAbly;
-  const Ably = (await import("ably")).default;
-  realtimeAbly = new Ably.Realtime(AblyApiKey);
-  return realtimeAbly;
+  if (realtimeAblyInitPromise) return realtimeAblyInitPromise;
+
+  realtimeAblyInitPromise = import("ably")
+    .then((ablyModule) => {
+      const Ably = ablyModule.default ?? ablyModule;
+      realtimeAbly = new Ably.Realtime(AblyApiKey);
+      return realtimeAbly;
+    })
+    .catch(() => null)
+    .finally(() => {
+      realtimeAblyInitPromise = null;
+    });
+
+  return realtimeAblyInitPromise;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/actions/ably-actions.js` around lines 6 - 12, The getAblyClient function
can race and propagate import/constructor errors; fix it by adding a
module-level initialization promise (e.g., initializationPromise) that is set
when starting the import/construct sequence so concurrent callers await the same
promise, wrap the import and new Ably.Realtime(AblyApiKey) in a try/catch to
handle failures, ensure realtimeAbly is assigned only on success and cleared/set
to null on failure, clear initializationPromise on failure or success
accordingly, and always return realtimeAbly or null (never let the raw thrown
error escape) so callers get the controlled null instead of rejected promises.

Comment thread src/actions/ably-actions.js Outdated
Comment on lines 3 to +4
import BasePCForm from "./base-pc-form";
import { Input } from "openstack-uicore-foundation/lib/components";
import Input from "openstack-uicore-foundation/lib/components/inputs/text-input";
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 | 🟡 Minor

Fix import ordering to satisfy ESLint import/order.

Line 4 should be grouped before the local relative import on Line 3; otherwise lint may fail.

Proposed fix
 import React from "react";
 import T from "i18n-react";
-import BasePCForm from "./base-pc-form";
 import Input from "openstack-uicore-foundation/lib/components/inputs/text-input";
+import BasePCForm from "./base-pc-form";
 import { DiscountTicketTable } from "../../../tables/dicount-ticket-table";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import BasePCForm from "./base-pc-form";
import { Input } from "openstack-uicore-foundation/lib/components";
import Input from "openstack-uicore-foundation/lib/components/inputs/text-input";
import React from "react";
import T from "i18n-react";
import Input from "openstack-uicore-foundation/lib/components/inputs/text-input";
import BasePCForm from "./base-pc-form";
import { DiscountTicketTable } from "../../../tables/dicount-ticket-table";
🧰 Tools
🪛 ESLint

[error] 4-4: openstack-uicore-foundation/lib/components/inputs/text-input import should occur before import of ./base-pc-form

(import/order)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/forms/promocode-form/forms/discount-base-pc-form.js` around
lines 3 - 4, Reorder the import statements so external package imports come
before local relative imports to satisfy ESLint import/order: move the Input
import (openstack-uicore-foundation/lib/components/inputs/text-input) above the
BasePCForm relative import; update the top of the file where BasePCForm and
Input are imported so Input is imported first.

import EditLabelSlider from "../../inputs/edit-label-slider";
import PreFilterInput from "./pre-filter-input";
import { SortableTable } from "openstack-uicore-foundation/lib/components";
import SortableTable from "openstack-uicore-foundation/lib/components/table-sortable";
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 | 🟡 Minor

Move SortableTable import above local utility imports.

At Line 31, import ordering violates import/order and can fail lint checks.

Proposed fix
 import React from "react";
 import T from "i18n-react/dist/i18n-react";
 import "awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css";
+import SortableTable from "openstack-uicore-foundation/lib/components/table-sortable";
 import {
   Dropdown,
   Input,
   SimpleLinkList
 } from "openstack-uicore-foundation/lib/components";
@@
 import EditLabelSlider from "../../inputs/edit-label-slider";
 import PreFilterInput from "./pre-filter-input";
-import SortableTable from "openstack-uicore-foundation/lib/components/table-sortable";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import SortableTable from "openstack-uicore-foundation/lib/components/table-sortable";
import React from "react";
import T from "i18n-react/dist/i18n-react";
import "awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css";
import SortableTable from "openstack-uicore-foundation/lib/components/table-sortable";
import {
Dropdown,
Input,
SimpleLinkList
} from "openstack-uicore-foundation/lib/components";
import EditLabelSlider from "../../inputs/edit-label-slider";
import PreFilterInput from "./pre-filter-input";
🧰 Tools
🪛 ESLint

[error] 31-31: openstack-uicore-foundation/lib/components/table-sortable import should occur before import of ../../../utils/methods

(import/order)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/forms/schedule-settings-form/index.js` at line 31, The import
ordering for SortableTable is wrong; move the external module import
"SortableTable" (SortableTable from
openstack-uicore-foundation/lib/components/table-sortable) so that it appears
before local/project utility imports in index.js to satisfy import/order linting
— locate the current SortableTable import and reposition it above any
relative/local imports (utilities/helpers/components) in the file.

Comment on lines +7 to +9
import CompanyInput from "openstack-uicore-foundation/lib/components/inputs/company-input"
import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input"
import TagInput from "openstack-uicore-foundation/lib/components/inputs/tag-input";
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 | 🟡 Minor

Reorder imports to pass import/order.

At Line 7-9, these external imports should be placed before local relative imports.

Proposed fix
 import React from "react";
+import CompanyInput from "openstack-uicore-foundation/lib/components/inputs/company-input";
+import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input";
+import TagInput from "openstack-uicore-foundation/lib/components/inputs/tag-input";
 import { FILTER_TYPES } from "../../../actions/schedule-settings-actions";
 import LevelDropdown from "../../inputs/level-dropdown";
 import EventTypeDropdown from "../../inputs/event-type-dropdown";
 import TrackDropdown from "../../inputs/track-dropdown";
 import TrackGroupDropdown from "../../inputs/track-group-dropdown";
-import CompanyInput from "openstack-uicore-foundation/lib/components/inputs/company-input"
-import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input"
-import TagInput from "openstack-uicore-foundation/lib/components/inputs/tag-input";
 import LocationDropdown from "../../inputs/location-dropdown";
 import T from "i18n-react";
🧰 Tools
🪛 ESLint

[error] 7-7: openstack-uicore-foundation/lib/components/inputs/company-input import should occur before import of ../../../actions/schedule-settings-actions

(import/order)


[error] 8-8: openstack-uicore-foundation/lib/components/inputs/speaker-input import should occur before import of ../../../actions/schedule-settings-actions

(import/order)


[error] 9-9: openstack-uicore-foundation/lib/components/inputs/tag-input import should occur before import of ../../../actions/schedule-settings-actions

(import/order)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/forms/schedule-settings-form/pre-filter-input.js` around lines
7 - 9, Move the external library imports (CompanyInput, SpeakerInput, TagInput
from "openstack-uicore-foundation/...") so they appear before any local relative
imports in pre-filter-input.js to satisfy import/order; locate the lines
importing CompanyInput, SpeakerInput, and TagInput and place them above the
local module imports in that file.

Comment on lines +26 to +27
import AjaxLoader from "openstack-uicore-foundation/lib/components/ajaxloader"
import SteppedSelect from "openstack-uicore-foundation/lib/components/inputs/stepped-select";
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 | 🟡 Minor

Fix import order to satisfy lint checks.

At Line 26 and Line 27, these external imports are placed after local relative imports, which violates import/order.

Proposed fix
 import React, { useEffect, useState } from "react";
 import { connect } from "react-redux";
 import T from "i18n-react";
+import AjaxLoader from "openstack-uicore-foundation/lib/components/ajaxloader";
+import SteppedSelect from "openstack-uicore-foundation/lib/components/inputs/stepped-select";
 import { trim } from "../../utils/methods";
 import { formatCurrency } from "../../helpers/formatCurrency";
 import { Breadcrumb } from "react-breadcrumbs";
@@
 import {
   getRegistrationData,
   changeTimeUnit
 } from "../../actions/summit-stats-actions";
 import PieGraph from "../../components/graphs/registration-pie-graph";
-import AjaxLoader from "openstack-uicore-foundation/lib/components/ajaxloader"
-import SteppedSelect from "openstack-uicore-foundation/lib/components/inputs/stepped-select";
 import LineGraph from "../../components/graphs/registration-line-graph";
🧰 Tools
🪛 ESLint

[error] 26-26: openstack-uicore-foundation/lib/components/ajaxloader import should occur before import of ../../utils/methods

(import/order)


[error] 27-27: openstack-uicore-foundation/lib/components/inputs/stepped-select import should occur before import of ../../utils/methods

(import/order)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/registration/registration-stats-page.js` around lines 26 - 27, The
two external imports AjaxLoader and SteppedSelect are placed after local
relative imports, violating the import/order lint rule; move the lines importing
AjaxLoader and SteppedSelect so they appear with the other external
(third-party) imports—i.e., above any local or relative imports—to restore the
correct import grouping and satisfy the linter.

Comment on lines 19 to 21
import MergeSpeakerForm from "../../components/forms/merge-speaker-form/merge-speaker-form";
import { SpeakerInput } from "openstack-uicore-foundation/lib/components";
import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input";
import { getSummitById } from "../../actions/summit-actions";
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

Fix import ordering to satisfy ESLint.

Line 20 places an external-package import after a local import, which violates the configured import/order rule and can break CI linting.

Suggested fix
 import { Breadcrumb } from "react-breadcrumbs";
+import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input";
 import MergeSpeakerForm from "../../components/forms/merge-speaker-form/merge-speaker-form";
-import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input";
 import { getSummitById } from "../../actions/summit-actions";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import MergeSpeakerForm from "../../components/forms/merge-speaker-form/merge-speaker-form";
import { SpeakerInput } from "openstack-uicore-foundation/lib/components";
import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input";
import { getSummitById } from "../../actions/summit-actions";
import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input";
import MergeSpeakerForm from "../../components/forms/merge-speaker-form/merge-speaker-form";
import { getSummitById } from "../../actions/summit-actions";
🧰 Tools
🪛 ESLint

[error] 20-20: openstack-uicore-foundation/lib/components/inputs/speaker-input import should occur before import of ../../components/forms/merge-speaker-form/merge-speaker-form

(import/order)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/speakers/merge-speakers-page.js` around lines 19 - 21, The import
ordering currently places the external package import SpeakerInput after local
imports (MergeSpeakerForm, getSummitById); reorder imports so
external/third-party modules come before local relative imports to satisfy
ESLint import/order. Specifically, move the import for SpeakerInput (from
"openstack-uicore-foundation/lib/components/inputs/speaker-input") above the
local imports for MergeSpeakerForm and getSummitById so the file groups
third-party imports (e.g., SpeakerInput) first, then project-local imports like
MergeSpeakerForm and getSummitById.

import FreeTextSearch from "openstack-uicore-foundation/lib/components/free-text-search"
import SpeakerInput from "openstack-uicore-foundation/lib/components/inputs/speaker-input"
import SortableTable from "openstack-uicore-foundation/lib/components/table-sortable"
import Table from "openstack-uicore-foundation/lib/components/table";
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 | 🟡 Minor

Remove unused Table import.

The Table import is never used in this file, which contradicts the PR objective of reducing bundle size. ESLint correctly flags this unused import.

🧹 Proposed fix to remove unused import
-import Table from "openstack-uicore-foundation/lib/components/table";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import Table from "openstack-uicore-foundation/lib/components/table";
🧰 Tools
🪛 ESLint

[error] 21-21: 'Table' is defined but never used.

(unused-imports/no-unused-imports)


[error] 21-21: 'Table' is defined but never used.

(no-unused-vars)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/summit_speakers/featured-speakers-page.js` at line 21, The file
contains an unused import "Table" (import Table from
"openstack-uicore-foundation/lib/components/table";) which should be removed to
avoid dead code and reduce bundle size—delete that import statement and ensure
no other references to the Table symbol remain in the module (check for "Table"
usage in functions or JSX such as FeaturedSpeakersPage or any exported
components).

**/
import React from "react";
import { RawHTML } from "openstack-uicore-foundation/lib/components";
import RawHTML from "openstack-uicore-foundation/lib/components/raw-html";
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

Remove unused RawHTML import (lint-blocking).

RawHTML is not used anywhere in this reducer (Line 14), and static analysis already flags it as unused. This can break CI lint checks.

Proposed fix
-import RawHTML from "openstack-uicore-foundation/lib/components/raw-html";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import RawHTML from "openstack-uicore-foundation/lib/components/raw-html";
🧰 Tools
🪛 ESLint

[error] 14-14: 'RawHTML' is defined but never used.

(unused-imports/no-unused-imports)


[error] 14-14: 'RawHTML' is defined but never used.

(no-unused-vars)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/reducers/orders/order-extra-question-list-reducer.js` at line 14, Remove
the unused import RawHTML from the top of the reducer file: delete the line
importing RawHTML ("import RawHTML from
\"openstack-uicore-foundation/lib/components/raw-html\";") so the unused symbol
is no longer present and lint will pass.

Comment thread src/sentry-init.js Outdated
Comment on lines +11 to +12
tracesSampleRate: window.SENTRY_TRACE_SAMPLE_RATE,
tracePropagationTargets: [window.SENTRY_TRACE_PROPAGATION_TARGETS],
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

🧩 Analysis chain

🌐 Web query:

In @sentry/react8.32.0, what are the expected types fortracesSampleRateandtracePropagationTargetsinSentry.init, and are string env values accepted without parsing?

💡 Result:

In @sentry/react 8.32.0, the expected type for tracesSampleRate in Sentry.init is number (a floating point value between 0.0 and 1.0). The expected type for tracePropagationTargets is an array of strings and/or RegExp objects (e.g., ["https://example.com", /^https://api//]). String environment values are not explicitly accepted without parsing. The official documentation shows numeric literals (e.g., 0.25) and does not mention automatic string-to-number parsing for tracesSampleRate. For tracePropagationTargets, strings and regex patterns are natively supported as shown in examples. Users typically parse env vars manually (e.g., parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE || '0')) before passing to Sentry.init, as the types expect number and string | RegExp | (string | RegExp)[], not raw strings for rates.

Citations:


🏁 Script executed:

#!/bin/bash
# Check the actual sentry-init.js file
echo "=== src/sentry-init.js ==="
cat -n src/sentry-init.js

# Check how SENTRY_ values are set in src/app.js
echo ""
echo "=== Checking src/app.js for SENTRY_* assignments ==="
rg -n "SENTRY_TRACE_SAMPLE_RATE|SENTRY_TRACE_PROPAGATION_TARGETS|window\.SENTRY" src/app.js -A 2 -B 2

Repository: fntechgit/summit-admin

Length of output: 1264


Normalize Sentry runtime config types before initialization.

At lines 11–12, environment variable values (which are always strings) are passed directly to Sentry.init() without type conversion. tracesSampleRate expects a number, and tracePropagationTargets expects an array of strings/RegExp, not a single raw value wrapped in an array.

Parse the sample rate as a number and split propagation targets by comma:

Proposed fix
 export const initSentry = () => {
+  const tracesSampleRate = Number(window.SENTRY_TRACE_SAMPLE_RATE);
+  const tracePropagationTargets = String(
+    window.SENTRY_TRACE_PROPAGATION_TARGETS || ""
+  )
+    .split(",")
+    .map((v) => v.trim())
+    .filter(Boolean);
+
   Sentry.init({
     dsn: window.SENTRY_DSN,
     integrations: [
       Sentry.browserTracingIntegration(),
       Sentry.browserProfilingIntegration(),
       Sentry.replayIntegration()
     ],
-    tracesSampleRate: window.SENTRY_TRACE_SAMPLE_RATE,
-    tracePropagationTargets: [window.SENTRY_TRACE_PROPAGATION_TARGETS],
+    tracesSampleRate: Number.isFinite(tracesSampleRate)
+      ? tracesSampleRate
+      : undefined,
+    tracePropagationTargets,
     profilesSampleRate: 1.0,
     replaysSessionSampleRate: 0.1,
     replaysOnErrorSampleRate: 1.0
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tracesSampleRate: window.SENTRY_TRACE_SAMPLE_RATE,
tracePropagationTargets: [window.SENTRY_TRACE_PROPAGATION_TARGETS],
export const initSentry = () => {
const tracesSampleRate = Number(window.SENTRY_TRACE_SAMPLE_RATE);
const tracePropagationTargets = String(
window.SENTRY_TRACE_PROPAGATION_TARGETS || ""
)
.split(",")
.map((v) => v.trim())
.filter(Boolean);
Sentry.init({
dsn: window.SENTRY_DSN,
integrations: [
Sentry.browserTracingIntegration(),
Sentry.browserProfilingIntegration(),
Sentry.replayIntegration()
],
tracesSampleRate: Number.isFinite(tracesSampleRate)
? tracesSampleRate
: undefined,
tracePropagationTargets,
profilesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0
});
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/sentry-init.js` around lines 11 - 12, Convert the runtime Sentry config
values before calling Sentry.init: parse window.SENTRY_TRACE_SAMPLE_RATE into a
number (e.g. Number(...) or parseFloat and fall back to undefined/null if NaN)
and normalize window.SENTRY_TRACE_PROPAGATION_TARGETS by splitting the string on
commas, trimming each entry and filtering out empty strings (optionally
converting entries like "/regex/" to RegExp if your app expects regexes), then
pass the numeric tracesSampleRate and the resulting array to Sentry.init for
tracesSampleRate and tracePropagationTargets respectively.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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