Skip to content

improve: app flow — registry component loaders + useClickAction hook - #281

Merged
alfredo1996 merged 11 commits into
release/1.0from
improve/app-flow-integration
Mar 31, 2026
Merged

improve: app flow — registry component loaders + useClickAction hook#281
alfredo1996 merged 11 commits into
release/1.0from
improve/app-flow-integration

Conversation

@alfredo1996

@alfredo1996 alfredo1996 commented Mar 31, 2026

Copy link
Copy Markdown
Owner

Summary

Integration branch for app-flow improvements. Contains:

PRs included

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Centralized click-action handling for widget/chart interactions.
    • Lazy-loaded chart components to improve initial load and reduce bundle size.
  • Refactor

    • Moved click-action resolution out of individual components into a shared handler, simplifying interaction wiring.
  • Tests

    • Added tests covering click-action behavior, parameter setting, navigation flows, and chart component registry.

alfredo1996 and others added 2 commits March 31, 2026 01:53
Closes #255

- Extract click action handling (resolveClickActions, setParameter,
  deriveClickableColumns) into reusable useClickAction hook
- card-container.tsx reduced by 25 lines — uses hook instead of inline logic
- Remove unused imports (ClickAction type, resolveClickActions, etc.)
- 7 unit tests for the hook logic (TDD: RED → GREEN)

Co-authored-by: alfredorubin96 <alfredo.rubin@neotechnology.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Closes #254

Each ChartConfig now has a `component` field — a lazy loader function
that returns the chart's React component. This is the first step toward
eliminating the switch statement in chart-renderer.tsx.

Currently: registry owns component references + chart-renderer switch.
Next step: chart-renderer uses registry.component via next/dynamic to
render, removing the switch entirely.

- Add `component` field to ChartConfig interface
- Add lazy loaders for all 17 chart types
- Add test verifying every chart type has a component field

Co-authored-by: alfredorubin96 <alfredo.rubin@neotechnology.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 31, 2026

Copy link
Copy Markdown

Walkthrough

Centralized widget click-action handling into a new useClickAction hook, updated CardContainer to consume it and conditionally wire chart click props, extended chart registry with lazy component loaders, and added tests for the hook and chart registry.

Changes

Cohort / File(s) Summary
Click-action hook & usage
app/src/hooks/use-click-action.ts, app/src/components/card-container.tsx
Added useClickAction(widget, onNavigateToPage) that resolves click actions, sets parameters, and optionally navigates; replaced in-component click resolution in CardContainer to consume hook outputs and only pass click props when hasClickAction.
Hook tests
app/src/hooks/__tests__/use-click-action.test.ts
New Vitest/JSDOM test suite validating resolveClickActions, deriveClickableColumns, store wiring (setParameter), handleChartClick behaviors (no-op, navigate, set-parameter, combined).
Chart registry types & entries
app/src/lib/chart-registry.ts
Added optional component?: () => Promise<{ default: React.ComponentType<any> }> to ChartConfig and populated many registry entries with lazy component loaders (dynamic imports).
Chart registry tests
app/src/lib/__tests__/chart-registry.test.ts
Updated mocks and assertions; added test iterating chartRegistry to ensure each getChartConfig(type) exposes a component loader that resolves to a module with a default export.

Sequence Diagram(s)

sequenceDiagram
  participant User as User
  participant Card as CardContainer
  participant Hook as useClickAction
  participant Store as ParameterStore
  participant Nav as Navigation
  participant Chart as ChartRenderer

  User->>Card: click chart point
  Card->>Hook: handleChartClick(point)
  Hook->>Hook: resolveClickActions(widget, point)
  alt result.setParameter exists
    Hook->>Store: setParameter(name, value, metadata)
  end
  alt result.navigateToPageId exists
    Hook->>Nav: onNavigateToPage(pageId, scrollToWidgetId?)
  end
  Hook->>Card: (returns)
  Card->>Chart: (click handled) update UI as needed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

enhancement, pkg:app, pkg:component, area:charts, area:widgets

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: adding component loaders to the registry and introducing the useClickAction hook.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch improve/app-flow-integration

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
app/src/lib/chart-registry.ts (1)

692-787: ⚠️ Potential issue | 🟠 Major

Use the charts sub-barrel instead of the main package barrel to avoid pulling unnecessary heavy dependencies.

The main @neoboard/components barrel re-exports all charts including MapChart and GraphChart. Since component/src/charts/map-chart.tsx imports Leaflet and component/src/charts/graph-chart.tsx imports NVL, lazy-loading any chart through the main barrel will pull both heavy dependencies into every async chunk, negating the lazy-load benefit.

Change loaders to import from @neoboard/components/charts (or specify the leaf paths) so that BarChart, LineChart, etc. don't bundle map and graph code:

component: () =>
  import("@neoboard/components/charts").then((m) => ({ default: m.BarChart })),

This ensures heavy deps load only when their respective widgets are present on the dashboard.

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

In `@app/src/lib/chart-registry.ts` around lines 692 - 787, The component loaders
in chart registry (e.g., the component arrow functions that import
"@neoboard/components" for BarChart, LineChart, PieChart, TableRenderer,
SingleValueChart, MapChart, GraphChart) are pulling the full package barrel and
thus bundling heavy Map/Graph deps; update those lazy imports to use the charts
sub-barrel (import "@neoboard/components/charts") or direct chart leaf paths for
lightweight charts (BarChart, LineChart, PieChart, TableRenderer,
SingleValueChart) while keeping MapChart and GraphChart pointing to their
full/leaf modules so Leaflet/NVL only load when those charts are used; replace
the import specifier in each component: () => import("@neoboard/components")...
with () => import("@neoboard/components/charts")... (or equivalent leaf paths)
for non-map/graph chart entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/hooks/__tests__/use-click-action.test.ts`:
- Around line 7-89: The tests currently only assert mocked outputs of
resolveClickActions and deriveClickableColumns and never import or exercise the
hook logic; update the test to actually import useClickAction and call the
returned handler (e.g., the handleChartClick function or whatever handler the
hook returns), wiring a real or mocked parameter store (setParameter) and
ensuring resolveClickActions/deriveClickableColumns are mocked only to drive
inputs — or alternatively convert this file into a pure unit test for the helper
functions (resolveClickActions/deriveClickableColumns) and remove hook mentions;
specifically, import useClickAction, obtain the click handler from
useClickAction, call it with a sample payload, and assert that the handler
invokes setParameter with the expected args or navigates via the returned
navigateToPageId, while still mocking resolveClickActions/deriveClickableColumns
to control behavior.

In `@app/src/lib/__tests__/chart-registry.test.ts`:
- Around line 1833-1836: The test dereferences config.component but
getChartConfig(type) can return undefined; narrow config first by asserting it's
defined or throwing if undefined (e.g., use expect(config).toBeDefined() or if
(!config) fail()) before checking config.component, then assert typeof
config.component === "function"; update the test in chart-registry.test.ts (the
it.each block using getChartConfig and config.component) to include that
null-check/expect to avoid the strict-null error.

---

Outside diff comments:
In `@app/src/lib/chart-registry.ts`:
- Around line 692-787: The component loaders in chart registry (e.g., the
component arrow functions that import "@neoboard/components" for BarChart,
LineChart, PieChart, TableRenderer, SingleValueChart, MapChart, GraphChart) are
pulling the full package barrel and thus bundling heavy Map/Graph deps; update
those lazy imports to use the charts sub-barrel (import
"@neoboard/components/charts") or direct chart leaf paths for lightweight charts
(BarChart, LineChart, PieChart, TableRenderer, SingleValueChart) while keeping
MapChart and GraphChart pointing to their full/leaf modules so Leaflet/NVL only
load when those charts are used; replace the import specifier in each component:
() => import("@neoboard/components")... with () =>
import("@neoboard/components/charts")... (or equivalent leaf paths) for
non-map/graph chart entries.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4abfb3fc-8de2-4599-88ca-75d890c76506

📥 Commits

Reviewing files that changed from the base of the PR and between 0ed0468 and 5f4018d.

📒 Files selected for processing (5)
  • app/src/components/card-container.tsx
  • app/src/hooks/__tests__/use-click-action.test.ts
  • app/src/hooks/use-click-action.ts
  • app/src/lib/__tests__/chart-registry.test.ts
  • app/src/lib/chart-registry.ts

Comment thread app/src/hooks/__tests__/use-click-action.test.ts Outdated
Comment thread app/src/lib/__tests__/chart-registry.test.ts Outdated
@alfredo1996 alfredo1996 added this to the v1.0 — Community Launch milestone Mar 31, 2026
alfredorubin96 and others added 9 commits March 31, 2026 13:25
- Fix TableRenderer import to use local path (component/ move is in #282)
- Add null guard to getChartConfig() in component field test
- Rewrite useClickAction tests to import actual hook and exercise real
  functions instead of only mocking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add async tests that call each chart registry component() loader and
  verify the resolved module has a default export (mocked via vi.mock to
  avoid pulling real UI dependencies in unit tests)
- Add renderHook tests for useClickAction that exercise the actual hook
  body: useCallback wiring, parameter store integration, and page
  navigation callback
- Covers new lines flagged as 0% by SonarCloud on PR #281

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ow-integration

# Conflicts:
#	app/src/lib/__tests__/chart-registry.test.ts
Graph and map charts now have stylingTargets (added in #282). Update
tests to expect true for chartSupportsStyling and non-empty styling
targets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tyling docs

- Add inline rationale to eslint-disable for any in component type
- Add comment noting component fields will replace chart-renderer.tsx loaders
- Update supportsStyling docstring to reflect graph/map now having styling

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
app/src/hooks/__tests__/use-click-action.test.ts (1)

36-53: These derivation tests are redundant with hook-level coverage.

The block at Line 36-53 only tests boolean casting on local objects, not hook behavior. You already validate hasClickAction through renderHook at Line 151-166. Consider removing this block or converting it to real hook assertions to reduce duplication.

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

In `@app/src/hooks/__tests__/use-click-action.test.ts` around lines 36 - 53,
Remove or replace the redundant standalone boolean-casting tests in the
"useClickAction — hasClickAction derivation" describe block: either delete that
entire describe block (the two it cases that create local ws objects and assert
!!clickAction) or convert them into real hook tests that call the useClickAction
hook via renderHook and assert the hasClickAction output; reference the hook
name useClickAction, the derived value hasClickAction, and the ClickAction
shape/variable used in the current tests when implementing the replacement.
app/src/lib/__tests__/chart-registry.test.ts (1)

1097-1100: Add the matching map styling-target assertion.

graph is pinned exactly now, but app/src/lib/chart-registry.ts also gives map an explicit [{ value: "color", label: "Marker Color" }]. Without the paired assertion, regressions in getStylingTargets("map") still slip through.

Suggested addition
   it("returns styling targets for graph", () => {
     expect(getStylingTargets("graph")).toEqual([
       { value: "color", label: "Node Color" },
     ]);
   });
+
+  it("returns styling targets for map", () => {
+    expect(getStylingTargets("map")).toEqual([
+      { value: "color", label: "Marker Color" },
+    ]);
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/lib/__tests__/chart-registry.test.ts` around lines 1097 - 1100, The
test currently asserts getStylingTargets("graph") but misses a paired assertion
for getStylingTargets("map"); update the test in chart-registry.test.ts to also
call getStylingTargets("map") and expect it toEqual([{ value: "color", label:
"Marker Color" }]) so the explicit "map" entry defined in
app/src/lib/chart-registry.ts is covered and future regressions are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/hooks/__tests__/use-click-action.test.ts`:
- Around line 61-77: The test for resolveClickActions uses a conditional guard
(if (result?.setParameter)) which can hide failures; update the test to assert
the result shape directly by removing the if and adding explicit expectations
such as expecting result and result.setParameter to be defined (or use
toHaveProperty), then assert result.setParameter.parameterName and
result.setParameter.value equal the expected values so missing or null returns
fail the test; target the resolveClickActions call and the result/setParameter
properties in your assertions.

---

Nitpick comments:
In `@app/src/hooks/__tests__/use-click-action.test.ts`:
- Around line 36-53: Remove or replace the redundant standalone boolean-casting
tests in the "useClickAction — hasClickAction derivation" describe block: either
delete that entire describe block (the two it cases that create local ws objects
and assert !!clickAction) or convert them into real hook tests that call the
useClickAction hook via renderHook and assert the hasClickAction output;
reference the hook name useClickAction, the derived value hasClickAction, and
the ClickAction shape/variable used in the current tests when implementing the
replacement.

In `@app/src/lib/__tests__/chart-registry.test.ts`:
- Around line 1097-1100: The test currently asserts getStylingTargets("graph")
but misses a paired assertion for getStylingTargets("map"); update the test in
chart-registry.test.ts to also call getStylingTargets("map") and expect it
toEqual([{ value: "color", label: "Marker Color" }]) so the explicit "map" entry
defined in app/src/lib/chart-registry.ts is covered and future regressions are
caught.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b4eb8020-a5f3-40e0-854c-3231008fd9ec

📥 Commits

Reviewing files that changed from the base of the PR and between 5f4018d and 95a3e89.

📒 Files selected for processing (4)
  • app/src/components/card-container.tsx
  • app/src/hooks/__tests__/use-click-action.test.ts
  • app/src/lib/__tests__/chart-registry.test.ts
  • app/src/lib/chart-registry.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/components/card-container.tsx
  • app/src/lib/chart-registry.ts

Comment on lines +61 to +77
it("resolveClickActions returns setParameter with parameterName and value", () => {
const widget = {
id: "w1",
settings: {
clickAction: {
type: "set-parameter",
parameterMapping: { parameterName: "region", sourceField: "name" },
},
},
} as unknown as DashboardWidget;

const result = resolveClickActions(widget, { name: "US", value: 100 });
if (result?.setParameter) {
expect(result.setParameter.parameterName).toBe("region");
expect(result.setParameter.value).toBe("US");
}
});

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

Avoid conditional assertions that can silently pass.

At Line 73, the if (result?.setParameter) guard can make the test pass even when resolveClickActions returns null or misses setParameter. Assert the shape directly so failures are surfaced.

Suggested fix
   const result = resolveClickActions(widget, { name: "US", value: 100 });
-  if (result?.setParameter) {
-    expect(result.setParameter.parameterName).toBe("region");
-    expect(result.setParameter.value).toBe("US");
-  }
+  expect(result).toEqual(
+    expect.objectContaining({
+      setParameter: expect.objectContaining({
+        parameterName: "region",
+        value: "US",
+      }),
+    }),
+  );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/hooks/__tests__/use-click-action.test.ts` around lines 61 - 77, The
test for resolveClickActions uses a conditional guard (if
(result?.setParameter)) which can hide failures; update the test to assert the
result shape directly by removing the if and adding explicit expectations such
as expecting result and result.setParameter to be defined (or use
toHaveProperty), then assert result.setParameter.parameterName and
result.setParameter.value equal the expected values so missing or null returns
fail the test; target the resolveClickActions call and the result/setParameter
properties in your assertions.

@sonarqubecloud

Copy link
Copy Markdown

@alfredo1996
alfredo1996 merged commit 7c430cf into release/1.0 Mar 31, 2026
20 of 21 checks passed
@alfredo1996
alfredo1996 deleted the improve/app-flow-integration branch April 7, 2026 11:47
alfredo1996 pushed a commit that referenced this pull request May 10, 2026
- Fix TableRenderer import to use local path (component/ move is in #282)
- Add null guard to getChartConfig() in component field test
- Rewrite useClickAction tests to import actual hook and exercise real
  functions instead of only mocking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
alfredo1996 pushed a commit that referenced this pull request May 10, 2026
- Add async tests that call each chart registry component() loader and
  verify the resolved module has a default export (mocked via vi.mock to
  avoid pulling real UI dependencies in unit tests)
- Add renderHook tests for useClickAction that exercise the actual hook
  body: useCallback wiring, parameter store integration, and page
  navigation callback
- Covers new lines flagged as 0% by SonarCloud on PR #281

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
alfredo1996 added a commit that referenced this pull request May 10, 2026
improve: app flow — registry component loaders + useClickAction hook
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants