Skip to content

refactor: reduce cognitive complexity - web batch 2#394

Merged
BillChirico merged 2 commits intomainfrom
fix/sonarcloud-complexity-web-2
Mar 26, 2026
Merged

refactor: reduce cognitive complexity - web batch 2#394
BillChirico merged 2 commits intomainfrom
fix/sonarcloud-complexity-web-2

Conversation

@BillChirico
Copy link
Copy Markdown
Collaborator

Refactors three dashboard components to reduce SonarCloud cognitive complexity to ≤15:

  • health-cards.tsx (23 → ~10): Extract MetricCard, ProgressBar, computeHeapMetrics, computeCpuMetrics, formatErrorValue, errorValueColor helpers
  • performance-dashboard.tsx (21 → ~12): Extract extractErrorMessage, buildMemChartData, buildCpuChartData, buildRtHistogram helpers
  • analytics-dashboard.tsx (20 → ~10): Extract KpiCardItem, DeltaIcon, getDeltaColor, formatNullableMetric helpers

No behavior changes. TypeScript compiles clean.

Copilot AI review requested due to automatic review settings March 26, 2026 11:22
@github-project-automation github-project-automation bot moved this to Backlog in Volvox.Bot Mar 26, 2026
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a7e5b159-b489-4e3c-854c-f8754426429b

📥 Commits

Reviewing files that changed from the base of the PR and between 188c53e and b1fd637.

📒 Files selected for processing (3)
  • web/src/components/dashboard/analytics-dashboard.tsx
  • web/src/components/dashboard/health-cards.tsx
  • web/src/components/dashboard/performance-dashboard.tsx

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling and display of missing/null metric values.
    • Made error message extraction and display consistent across performance views.
  • Refactor

    • Standardized KPI card layout and progress bars for consistent visuals.
    • Consolidated metric computations and chart-data builders to simplify dashboard logic.

Walkthrough

Small formatting change in analytics-dashboard and refactors in HealthCards and PerformanceDashboard: HealthCards gains MetricCard, ProgressBar, and metric/computation helpers; PerformanceDashboard extracts error/series/histogram builders and centralizes error message extraction. No public API/signature changes.

Changes

Cohort / File(s) Summary
Analytics Dashboard
web/src/components/dashboard/analytics-dashboard.tsx
Formatting-only change: inserted a single blank line after the RANGE_PRESETS constant; no behavior or API changes.
Health Cards Dashboard
web/src/components/dashboard/health-cards.tsx
Introduces MetricCard and MetricCardProps, ProgressBar, helpers computeHeapMetrics, computeCpuMetrics, formatErrorValue, errorValueColor, and refactors HealthCards to use these helpers and components; imports type React for prop typing.
Performance Dashboard
web/src/components/dashboard/performance-dashboard.tsx
Adds extractErrorMessage to normalize error extraction from JSON bodies and buildMemChartData, buildCpuChartData, buildRtHistogram to build chart series/histogram; replaces inline logic with these helpers and updates non-OK response handling to use extractErrorMessage.

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title 'refactor: reduce cognitive complexity - web batch 2' directly and specifically describes the main change: refactoring three dashboard components to reduce SonarCloud cognitive complexity.
Description check ✅ Passed The description provides a clear, detailed explanation of the refactoring work across three components with specific complexity reduction goals, matching the changeset perfectly.

✏️ 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 fix/sonarcloud-complexity-web-2
  • 🛠️ Publish Changes: Commit on current branch
  • 🛠️ Publish Changes: Create PR

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.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 26, 2026

⚠️ No Changeset found

Latest commit: b1fd637

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@railway-app
Copy link
Copy Markdown

railway-app bot commented Mar 26, 2026

🚅 Deployed to the volvox-bot-pr-394 environment in volvox-bot

Service Status Web Updated (UTC)
web ✅ Success (View Logs) Mar 26, 2026 at 11:56 am
bot ✅ Success (View Logs) Web Mar 26, 2026 at 11:55 am

@coveralls
Copy link
Copy Markdown

coveralls commented Mar 26, 2026

Coverage Status

coverage: 90.661% (-0.01%) from 90.671%
when pulling b1fd637 on fix/sonarcloud-complexity-web-2
into a8cde7d on main.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 26, 2026

Greptile Summary

This PR refactors three dashboard components (health-cards.tsx, performance-dashboard.tsx, and analytics-dashboard.tsx) by extracting focused helper functions and sub-components to reduce SonarCloud cognitive complexity scores. All extracted helpers are pure functions or small stateless components that mirror the original inline logic exactly — no behavior changes are introduced.\n\n- health-cards.tsx: Extracts MetricCard, ProgressBar, computeHeapMetrics, computeCpuMetrics, formatErrorValue, and errorValueColor. All equivalences were verified: null-guard paths, clamping, and color selection logic are preserved.\n- performance-dashboard.tsx: Extracts extractErrorMessage, buildMemChartData, buildCpuChartData, and buildRtHistogram. Both call-sites of extractErrorMessage (data fetch and threshold save) are correctly updated.\n- analytics-dashboard.tsx: Only a cosmetic blank line is added; the substantive analytics helper extractions (KpiCardItem, etc.) appear to have been done previously in analytics-dashboard-sections.tsx.\n\nOne minor style note in health-cards.tsx: computeCpuMetrics returns cpuPct as a string (via .toFixed(1)), which forces the caller to convert it back with Number(cpu.cpuPct) when passing to ProgressBar. Returning a number and formatting at display time would be cleaner.

Confidence Score: 5/5

Safe to merge — pure structural refactoring with all behavior preserved and TypeScript clean.

Every extracted helper was verified to produce identical outputs to the original inline code across all input cases (null health, zero values, clamped CPU percentages). No new API calls, state, or side effects were introduced. The one flagged issue (cpuPct type round-trip) is cosmetic and does not affect runtime behavior.

No files require special attention beyond the minor cpuPct string/number inconsistency in health-cards.tsx.

Important Files Changed

Filename Overview
web/src/components/dashboard/health-cards.tsx Extracts MetricCard, ProgressBar, computeHeapMetrics, computeCpuMetrics, formatErrorValue, and errorValueColor helpers — behavior-preserving refactor with one minor type inconsistency (cpuPct returned as string)
web/src/components/dashboard/performance-dashboard.tsx Extracts extractErrorMessage, buildMemChartData, buildCpuChartData, and buildRtHistogram helpers from the main component body — clean, behavior-preserving refactor with no issues
web/src/components/dashboard/analytics-dashboard.tsx Only change is a single blank line added between the RANGE_PRESETS constant and the AnalyticsDashboard export — no logic changes

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    HC[HealthCards] --> MC[MetricCard\nreusable card wrapper]
    HC --> PB[ProgressBar\nshared progress bar]
    HC --> CHM[computeHeapMetrics\nheap MB + %]
    HC --> CCM[computeCpuMetrics\nuser/sys sec + %]
    HC --> FEV[formatErrorValue\nnull-safe toLocaleString]
    HC --> EVC[errorValueColor\nnull-safe errorColor]

    PD[PerformanceDashboard] --> EEM[extractErrorMessage\nparse JSON error body]
    PD --> BMC[buildMemChartData\nheap + RSS series]
    PD --> BCC[buildCpuChartData\nCPU series]
    PD --> BRH[buildRtHistogram\n500ms buckets]

    AD[AnalyticsDashboard] -->|blank line only| AD2[No logic change]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: web/src/components/dashboard/health-cards.tsx
Line: 103-104

Comment:
**`cpuPct` returned as `string`, forcing a `Number()` round-trip at call site**

`computeCpuMetrics` returns `cpuPct` as a `string` (via `.toFixed(1)`), which makes the return type `{ cpuUserSec: number; cpuSystemSec: number; cpuPct: string }`. This forces the caller to convert it back to a number with `Number(cpu.cpuPct)` when passing to `ProgressBar` (line 216). Returning `cpuPct` as a raw `number` and formatting it at display time is cleaner and avoids the implicit type mismatch:

```suggestion
  const cpuPct = Math.min(Math.max(rawPct, 0), 100);
  return { cpuUserSec, cpuSystemSec, cpuPct };
```

Then the display value becomes `` `${cpu.cpuPct.toFixed(1)}%` `` and the `ProgressBar` call simply uses `cpu.cpuPct` directly.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (3): Last reviewed commit: "style: fix Biome lint formatting" | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors several Next.js dashboard components to reduce SonarCloud cognitive complexity while keeping behavior the same by extracting repeated logic into small helpers/components.

Changes:

  • Extracted helper functions in performance-dashboard.tsx for error parsing and derived chart data building.
  • Extracted reusable card/presentation helpers in health-cards.tsx to simplify KPI rendering.
  • Extracted KPI rendering helpers in analytics-dashboard.tsx (card item, delta display, nullable metric formatting).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
web/src/components/dashboard/performance-dashboard.tsx Extracts error/derived-data helper functions to simplify the main component logic.
web/src/components/dashboard/health-cards.tsx Introduces MetricCard/ProgressBar and metric computation helpers to reduce repeated JSX/logic.
web/src/components/dashboard/analytics-dashboard.tsx Extracts KPI card rendering + delta helpers and centralizes nullable metric formatting.

const heapUsedMb = health.memory.heapUsed / 1_048_576;
const heapTotalMb = health.memory.heapTotal / 1_048_576;
const heapPct = heapTotalMb > 0 ? (heapUsedMb / heapTotalMb) * 100 : 0;
return { heapUsedMb, heapTotalMb, heapPct };
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

computeHeapMetrics() returns heapUsedMb and heapTotalMb, but those properties aren’t used anywhere in this component (only heapPct is). Consider returning only the values that are actually consumed, or use the extra fields in the UI to avoid carrying dead code in this refactor.

Suggested change
return { heapUsedMb, heapTotalMb, heapPct };
return { heapPct };

Copilot uses AI. Check for mistakes.
const cpuSystemSec = health.system.cpuUsage.system / 1_000_000;
const cpuTotalSec = cpuUserSec + cpuSystemSec;
const rawPct = health.uptime > 0 ? (cpuTotalSec / health.uptime) * 100 : 0;
const cpuPct = Math.min(Math.max(rawPct, 0), 100).toFixed(1);
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

computeCpuMetrics() formats cpuPct with toFixed(), which makes it a string, but later it needs to be converted back to a number for the progress bar (Number(cpu.cpuPct)). Returning cpuPct as a number (and formatting only at render time) would avoid this string↔number churn and keep the data shape consistent.

Suggested change
const cpuPct = Math.min(Math.max(rawPct, 0), 100).toFixed(1);
const cpuPct = Math.min(Math.max(rawPct, 0), 100);

Copilot uses AI. Check for mistakes.
@BillChirico BillChirico enabled auto-merge (squash) March 26, 2026 11:55
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

return String((json as Record<string, unknown>).error);
}
return fallback;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Duplicated extractErrorMessage utility across two files

Low Severity

The newly extracted extractErrorMessage function in performance-dashboard.tsx duplicates an existing extractErrorMessage in moderation-store.ts with the same name, signature, and near-identical logic. Extracting inline code into a named function is the ideal moment to consolidate into a shared utility instead of creating a second copy.

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/components/dashboard/analytics-dashboard.tsx`:
- Around line 133-146: Mark the props objects as readonly to indicate
immutability: update DeltaIcon's props signature from ({ delta }: { delta:
number | null }) to use a readonly property (e.g., { readonly delta: number |
null }) and update KpiCardItem's props type so each field is readonly (e.g., {
readonly card: KpiCard; readonly analytics: DashboardAnalytics | null; readonly
compareMode: boolean }). This keeps intent explicit and resolves the Sonar
warning for both DeltaIcon and KpiCardItem.

In `@web/src/components/dashboard/health-cards.tsx`:
- Around line 57-62: Make the props interfaces immutable by marking their
properties readonly: update MetricCardProps and ProgressBarProps so every field
(e.g., title, icon, iconBg, children in MetricCardProps and whatever fields
exist in ProgressBarProps) are declared readonly to satisfy the immutability
contract and silence Sonar warnings; locate the interface declarations in
web/src/components/dashboard/health-cards.tsx (MetricCardProps and
ProgressBarProps) and change each property to readonly while keeping types
unchanged.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5381cf96-9082-45d4-a882-b7d973016507

📥 Commits

Reviewing files that changed from the base of the PR and between ac8a108 and 188c53e.

📒 Files selected for processing (3)
  • web/src/components/dashboard/analytics-dashboard.tsx
  • web/src/components/dashboard/health-cards.tsx
  • web/src/components/dashboard/performance-dashboard.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Greptile Review
  • GitHub Check: Cursor Bugbot
  • GitHub Check: Lint
  • GitHub Check: E2E Tests (1/2)
  • GitHub Check: E2E Tests (2/2)
  • GitHub Check: Test
  • GitHub Check: Docker Build Validation
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,ts,tsx}: Use single quotes for strings (except in JSON files); no double quotes
Always include semicolons at the end of statements
Use 2-space indentation (spaces, not tabs)
Always include trailing commas in multi-line arrays, objects, and function parameters
Maintain a maximum line width of 100 characters

Files:

  • web/src/components/dashboard/performance-dashboard.tsx
  • web/src/components/dashboard/analytics-dashboard.tsx
  • web/src/components/dashboard/health-cards.tsx
web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Never use console.* methods in web dashboard code; use appropriate logging mechanisms for React applications

Files:

  • web/src/components/dashboard/performance-dashboard.tsx
  • web/src/components/dashboard/analytics-dashboard.tsx
  • web/src/components/dashboard/health-cards.tsx
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: ESM only - do not use CommonJS modules
Use src/logger.js; do not use console.*

Files:

  • web/src/components/dashboard/performance-dashboard.tsx
  • web/src/components/dashboard/analytics-dashboard.tsx
  • web/src/components/dashboard/health-cards.tsx
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-03-12T02:03:36.493Z
Learning: Applies to web/tests/**/*.test.{ts,tsx} : Maintain test coverage thresholds of 85% across all metrics (statements, branches, functions, lines) for web dashboard tests
📚 Learning: 2026-03-11T06:42:38.728Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-11T06:42:38.728Z
Learning: Applies to web/src/pages/dashboard/**/*.{ts,tsx} : Use shared title helpers from web/src/lib/page-titles.ts for setting browser titles in dashboard pages

Applied to files:

  • web/src/components/dashboard/performance-dashboard.tsx
  • web/src/components/dashboard/health-cards.tsx
📚 Learning: 2026-03-11T05:32:46.325Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-11T05:32:46.325Z
Learning: Applies to web/src/app/**/*.{ts,tsx} : Apply static metadata to server-rendered dashboard entry pages and use title template format for root app metadata

Applied to files:

  • web/src/components/dashboard/performance-dashboard.tsx
  • web/src/components/dashboard/analytics-dashboard.tsx
  • web/src/components/dashboard/health-cards.tsx
📚 Learning: 2026-03-12T02:03:36.493Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-03-12T02:03:36.493Z
Learning: Applies to web/src/app/dashboard/**/*.tsx : For dashboard routes, add a matcher entry to `dashboardTitleMatchers` in `web/src/lib/page-titles.ts`: use exact equality for leaf routes (`pathname === '/dashboard/my-route'`) and subtree checks (`pathname.startsWith('/dashboard/my-route/')`); export `metadata` using `createPageMetadata(title)` for SSR entry points

Applied to files:

  • web/src/components/dashboard/performance-dashboard.tsx
  • web/src/components/dashboard/analytics-dashboard.tsx
  • web/src/components/dashboard/health-cards.tsx
📚 Learning: 2026-03-26T00:04:14.673Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-26T00:04:14.673Z
Learning: Applies to {web/src/lib/page-titles.ts,web/src/**/+page.ts,web/src/**/+page.svelte} : New dashboard routes need title wiring in web/src/lib/page-titles.ts: use createPageMetadata() for SSR and keep DashboardTitleSync aligned for client navigation.

Applied to files:

  • web/src/components/dashboard/performance-dashboard.tsx
📚 Learning: 2026-03-12T02:03:36.493Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-03-12T02:03:36.493Z
Learning: Applies to web/tests/**/*.test.{ts,tsx} : Maintain test coverage thresholds of 85% across all metrics (statements, branches, functions, lines) for web dashboard tests

Applied to files:

  • web/src/components/dashboard/performance-dashboard.tsx
📚 Learning: 2026-03-10T23:21:49.730Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T23:21:49.730Z
Learning: Applies to web/src/components/layout/dashboard-shell.tsx : Dashboard page titles should sync with route changes using DashboardTitleSync component mounted in dashboard-shell.tsx and canonical title string 'Volvox.Bot - AI Powered Discord Bot'

Applied to files:

  • web/src/components/dashboard/performance-dashboard.tsx
  • web/src/components/dashboard/analytics-dashboard.tsx
📚 Learning: 2026-03-12T02:03:36.493Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-03-12T02:03:36.493Z
Learning: Applies to web/src/**/*.{ts,tsx} : Never use `console.*` methods in web dashboard code; use appropriate logging mechanisms for React applications

Applied to files:

  • web/src/components/dashboard/performance-dashboard.tsx
📚 Learning: 2026-03-10T23:21:49.730Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-10T23:21:49.730Z
Learning: Applies to web/src/components/dashboard/config-workspace/**/*.{ts,tsx} : Web dashboard config editor should use category workspace navigation with reusable SettingsFeatureCard pattern (header + master toggle + Basic/Advanced blocks)

Applied to files:

  • web/src/components/dashboard/health-cards.tsx
🪛 GitHub Check: SonarCloud Code Analysis
web/src/components/dashboard/analytics-dashboard.tsx

[warning] 138-146: Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=VolvoxLLC_volvox-bot&issues=AZ0p4oVp2Y8HYmqWNVqv&open=AZ0p4oVp2Y8HYmqWNVqv&pullRequest=394


[warning] 133-133: Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=VolvoxLLC_volvox-bot&issues=AZ0p4oVp2Y8HYmqWNVqu&open=AZ0p4oVp2Y8HYmqWNVqu&pullRequest=394

web/src/components/dashboard/health-cards.tsx

[warning] 80-80: Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=VolvoxLLC_volvox-bot&issues=AZ0p4oS72Y8HYmqWNVqs&open=AZ0p4oS72Y8HYmqWNVqs&pullRequest=394


[warning] 64-64: Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=VolvoxLLC_volvox-bot&issues=AZ0p4oS72Y8HYmqWNVqr&open=AZ0p4oS72Y8HYmqWNVqr&pullRequest=394


[warning] 112-112: Unexpected negated condition.

See more on https://sonarcloud.io/project/issues?id=VolvoxLLC_volvox-bot&issues=AZ0p4oS72Y8HYmqWNVqt&open=AZ0p4oS72Y8HYmqWNVqt&pullRequest=394

🔇 Additional comments (4)
web/src/components/dashboard/performance-dashboard.tsx (2)

123-162: Helper extraction is clean and behavior-preserving.

The extracted error/message and chart-data helpers keep logic equivalent while reducing cognitive complexity and duplication.


195-196: Call-site integration looks correct.

Using the new helpers in fetch/save error handling and derived chart data wiring is consistent and improves maintainability.

Also applies to: 239-240, 257-259

web/src/components/dashboard/analytics-dashboard.tsx (1)

109-113: Nice refactor on KPI/realtime rendering.

formatNullableMetric plus KpiCardItem keeps display logic consistent and reduces repeated conditional branches without changing output behavior.

Also applies to: 607-614, 638-655

web/src/components/dashboard/health-cards.tsx (1)

91-113: Refactor quality is solid here.

The extracted metric/error helpers and shared card primitives reduce duplication and keep the health KPI rendering straightforward.

Also applies to: 126-229

Comment on lines +133 to +146
function DeltaIcon({ delta }: { delta: number | null }) {
if (delta === null || delta === 0) return <Minus className="h-3 w-3" />;
return delta > 0 ? <ArrowUp className="h-3 w-3" /> : <ArrowDown className="h-3 w-3" />;
}

function KpiCardItem({
card,
analytics,
compareMode,
}: {
card: KpiCard;
analytics: DashboardAnalytics | null;
compareMode: boolean;
}) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Mark component props as readonly.

DeltaIcon and KpiCardItem props are immutable by design; marking them readonly will satisfy the Sonar warning and tighten intent.

♻️ Suggested update
-function DeltaIcon({ delta }: { delta: number | null }) {
+function DeltaIcon({ delta }: Readonly<{ delta: number | null }>) {
   if (delta === null || delta === 0) return <Minus className="h-3 w-3" />;
   return delta > 0 ? <ArrowUp className="h-3 w-3" /> : <ArrowDown className="h-3 w-3" />;
 }

+type KpiCardItemProps = Readonly<{
+  card: KpiCard;
+  analytics: DashboardAnalytics | null;
+  compareMode: boolean;
+}>;
+
 function KpiCardItem({
   card,
   analytics,
   compareMode,
-}: {
-  card: KpiCard;
-  analytics: DashboardAnalytics | null;
-  compareMode: boolean;
-}) {
+}: KpiCardItemProps) {
📝 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
function DeltaIcon({ delta }: { delta: number | null }) {
if (delta === null || delta === 0) return <Minus className="h-3 w-3" />;
return delta > 0 ? <ArrowUp className="h-3 w-3" /> : <ArrowDown className="h-3 w-3" />;
}
function KpiCardItem({
card,
analytics,
compareMode,
}: {
card: KpiCard;
analytics: DashboardAnalytics | null;
compareMode: boolean;
}) {
function DeltaIcon({ delta }: Readonly<{ delta: number | null }>) {
if (delta === null || delta === 0) return <Minus className="h-3 w-3" />;
return delta > 0 ? <ArrowUp className="h-3 w-3" /> : <ArrowDown className="h-3 w-3" />;
}
type KpiCardItemProps = Readonly<{
card: KpiCard;
analytics: DashboardAnalytics | null;
compareMode: boolean;
}>;
function KpiCardItem({
card,
analytics,
compareMode,
}: KpiCardItemProps) {
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[warning] 138-146: Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=VolvoxLLC_volvox-bot&issues=AZ0p4oVp2Y8HYmqWNVqv&open=AZ0p4oVp2Y8HYmqWNVqv&pullRequest=394


[warning] 133-133: Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=VolvoxLLC_volvox-bot&issues=AZ0p4oVp2Y8HYmqWNVqu&open=AZ0p4oVp2Y8HYmqWNVqu&pullRequest=394

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

In `@web/src/components/dashboard/analytics-dashboard.tsx` around lines 133 - 146,
Mark the props objects as readonly to indicate immutability: update DeltaIcon's
props signature from ({ delta }: { delta: number | null }) to use a readonly
property (e.g., { readonly delta: number | null }) and update KpiCardItem's
props type so each field is readonly (e.g., { readonly card: KpiCard; readonly
analytics: DashboardAnalytics | null; readonly compareMode: boolean }). This
keeps intent explicit and resolves the Sonar warning for both DeltaIcon and
KpiCardItem.

Comment on lines +57 to +62
interface MetricCardProps {
title: string;
icon: React.ReactNode;
iconBg: string;
children: React.ReactNode;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Use readonly props for extracted components.

MetricCard and ProgressBar props should be readonly to match the immutability contract and clear the Sonar warnings.

♻️ Suggested update
-interface MetricCardProps {
+interface MetricCardProps {
   title: string;
   icon: React.ReactNode;
   iconBg: string;
   children: React.ReactNode;
 }
 
-function MetricCard({ title, icon, iconBg, children }: MetricCardProps) {
+function MetricCard({ title, icon, iconBg, children }: Readonly<MetricCardProps>) {
   return (
     <Card className="kpi-card rounded-2xl">
@@
-function ProgressBar({ percent }: { percent: number }) {
+function ProgressBar({ percent }: Readonly<{ percent: number }>) {
   return (

Also applies to: 64-80

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

In `@web/src/components/dashboard/health-cards.tsx` around lines 57 - 62, Make the
props interfaces immutable by marking their properties readonly: update
MetricCardProps and ProgressBarProps so every field (e.g., title, icon, iconBg,
children in MetricCardProps and whatever fields exist in ProgressBarProps) are
declared readonly to satisfy the immutability contract and silence Sonar
warnings; locate the interface declarations in
web/src/components/dashboard/health-cards.tsx (MetricCardProps and
ProgressBarProps) and change each property to readonly while keeping types
unchanged.

@github-project-automation github-project-automation bot moved this from Backlog to In Review in Volvox.Bot Mar 26, 2026
- health-cards.tsx: Extract MetricCard, ProgressBar, computeHeapMetrics,
  computeCpuMetrics helpers (complexity 23 → ~10)
- performance-dashboard.tsx: Extract extractErrorMessage, buildMemChartData,
  buildCpuChartData, buildRtHistogram helpers (complexity 21 → ~12)
- analytics-dashboard.tsx: Extract KpiCardItem, DeltaIcon, getDeltaColor,
  formatNullableMetric helpers (complexity 20 → ~10)
Copilot AI review requested due to automatic review settings March 26, 2026 13:34
@BillChirico BillChirico force-pushed the fix/sonarcloud-complexity-web-2 branch from 188c53e to b1fd637 Compare March 26, 2026 13:34
@BillChirico BillChirico merged commit 73d6b30 into main Mar 26, 2026
@BillChirico BillChirico deleted the fix/sonarcloud-complexity-web-2 branch March 26, 2026 13:34
@github-project-automation github-project-automation bot moved this from In Review to Done in Volvox.Bot Mar 26, 2026
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment on lines +133 to +139
return (
data?.timeSeries.memoryHeapMb.map((pt, i) => ({
time: formatTs(pt.timestamp),
heap: pt.value,
rss: data.timeSeries.memoryRssMb[i]?.value ?? 0,
})) ?? []
);
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

buildMemChartData uses data?.timeSeries...map(...) but still references data.timeSeries... inside the map callback. TypeScript won’t narrow data inside the closure, so this typically triggers an "Object is possibly 'null'" type error (and can be avoided without losing readability). Consider returning early when data is null, or capturing the needed arrays in locals (e.g., const rssSeries = data.timeSeries.memoryRssMb) before mapping.

Suggested change
return (
data?.timeSeries.memoryHeapMb.map((pt, i) => ({
time: formatTs(pt.timestamp),
heap: pt.value,
rss: data.timeSeries.memoryRssMb[i]?.value ?? 0,
})) ?? []
);
if (!data) {
return [];
}
const rssSeries = data.timeSeries.memoryRssMb;
return data.timeSeries.memoryHeapMb.map((pt, i) => ({
time: formatTs(pt.timestamp),
heap: pt.value,
rss: rssSeries[i]?.value ?? 0,
}));

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants