Skip to content

feat: add D3 gauge components with dashboard table, card, and detail … - #35

Merged
JuanCF merged 2 commits into
mainfrom
feat/d3-gauges
Jun 11, 2026
Merged

JuanCF merged 2 commits into
mainfrom
feat/d3-gauges

Conversation

@JuanCF

@JuanCF JuanCF commented Jun 11, 2026 •

Copy link
Copy Markdown
Owner

…views

Replace horizontal metric bars with D3 270° donut arc gauges across the frontend.

  • New Gauge component (src/components/Gauge.jsx) renders a configurable 270° donut arc with percentage display, label, custom size/color, and value clamping.
  • Dashboard UPS table now shows compact battery/load gauges per device, fetched via a second useEffect for per-UPS detail data.
  • UpsCard replaces horizontal bar metrics with compact 76px gauges.
  • UpsDetail displays large 100px gauges in a metrics bar for charge and load, with those fields filtered out of the grouped grid sections.
  • CSS additions: gauge wrapper/container/value/label, dash-ups-table grid layout, detail-metrics bar with gradient border, card-metrics-row-gauges.
  • Tests cover Gauge (10 cases), Dashboard (7 cases), UpsCard (7 cases), and UpsDetail (6 cases). d3 added as a dependency.

Summary by CodeRabbit

  • New Features

    • Added Gauge component for visualizing battery charge and load metrics across the application
    • Dashboard now displays per-UPS battery charge and load gauges in the overview section
    • UpsCard and UpsDetail pages updated to show gauge-based metric visualizations
  • Tests

    • Added comprehensive test suites for Dashboard, Gauge, UpsCard, and UpsDetail components
  • Style

    • Updated dashboard and detail page layouts with new gauge-based metric card styling
  • Chores

    • Updated dependency configuration in package.json

…views

Replace horizontal metric bars with D3 270° donut arc gauges across the frontend.

- New Gauge component (src/components/Gauge.jsx) renders a configurable 270° donut arc
  with percentage display, label, custom size/color, and value clamping.
- Dashboard UPS table now shows compact battery/load gauges per device, fetched via
  a second useEffect for per-UPS detail data.
- UpsCard replaces horizontal bar metrics with compact 76px gauges.
- UpsDetail displays large 100px gauges in a metrics bar for charge and load, with
  those fields filtered out of the grouped grid sections.
- CSS additions: gauge wrapper/container/value/label, dash-ups-table grid layout,
  detail-metrics bar with gradient border, card-metrics-row-gauges.
- Tests cover Gauge (10 cases), Dashboard (7 cases), UpsCard (7 cases), and
  UpsDetail (6 cases). d3 added as a dependency.
@coderabbitai

coderabbitai Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@JuanCF, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 43 minutes and 34 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ba106103-bef6-4b6e-986b-01c89b86f4f2

📥 Commits

Reviewing files that changed from the base of the PR and between 2cdd76c and 2f62bab.

📒 Files selected for processing (5)
  • src/frontend/src/__tests__/components/Gauge.test.jsx
  • src/frontend/src/components/Gauge.jsx
  • src/frontend/src/components/UpsCard.jsx
  • src/frontend/src/components/UpsDetail.jsx
  • src/frontend/src/utils/metrics.js
📝 Walkthrough

Walkthrough

This PR introduces a new SVG gauge visualization component and integrates it into the UPS monitoring dashboard. The Gauge component renders customizable arc-based meters using D3 geometry. It is then used in Dashboard's overview table, UpsCard's metric display, and UpsDetail's dedicated metric section, with all components tested and styled consistently.

Changes

Gauge Component & Integration

Layer / File(s) Summary
Gauge component foundation with styling and tests
src/frontend/package.json, src/frontend/src/components/Gauge.jsx, src/frontend/src/__tests__/components/Gauge.test.jsx, src/frontend/src/styles/components.css
d3 added to project dependencies. New Gauge component uses D3 arc geometry to render SVG gauges with configurable size and color, displays rounded percentage text, and optionally renders a label. Tests verify percentage rendering, label display, SVG structure, size styling, value clamping, and custom colors. Gauge wrapper and container styles added to CSS.
Dashboard gauge table integration and tests
src/frontend/src/components/Dashboard.jsx, src/frontend/src/__tests__/components/Dashboard.test.jsx, src/frontend/src/styles/components.css
Dashboard imports Gauge component and adds details state. New useEffect fetches API.upsDetail() for each UPS in parallel, stores results in a name-keyed object, and uses cancellation guards. UPS overview rendering changes from a simple list to a table layout that conditionally displays Gauge components for battery charge and load metrics based on detail availability. Dashboard CSS refactored to separate service-cell styling (.dash-svc-item) and add table layout rules (.dash-ups-table, .dash-ups-tr, .dash-ups-th). Tests verify stat card counts, table gauge rendering, empty state, service names, user count, and health status labels for degraded/failed scenarios.
UpsCard gauge rendering and tests
src/frontend/src/components/UpsCard.jsx, src/frontend/src/__tests__/components/UpsCard.test.jsx
UpsCard imports Gauge and replaces previous battery/load bar UI with conditional Gauge components (rendered only when detail fields are non-null). Runtime and voltage metric text remains. Tests verify UPS metadata, status badge display, conditional gauge rendering, edit/delete interaction callbacks, and directive formatting.
UpsDetail gauge metrics section and tests
src/frontend/src/components/UpsDetail.jsx, src/frontend/src/__tests__/components/UpsDetail.test.jsx, src/frontend/src/styles/components.css
UpsDetail imports Gauge and extracts battery charge, load, runtime, and voltage values from detail data. New detail-metrics section renders Gauge visuals for charge and load and text for runtime and voltage. Main variables grid filters out battery.charge and ups.load to prevent duplication. Detail page CSS adds metric card layout (.detail-metrics, .detail-metric-card) with responsive adjustments; .detail-grid changed from grid to column-count layout, .detail-section includes break-inside: avoid. Tests verify loading state, successful metric/grid rendering, grouped sections, error handling, and UI toggle presence ("Live", "Show all variables (raw)").

Sequence Diagram(s)

sequenceDiagram
  participant Dashboard
  participant API
  participant Gauge
  Dashboard->>API: fetch API.upsDetail(name) for each UPS
  API-->>Dashboard: return detail with battery.charge, ups.load
  Dashboard->>Dashboard: store in details state (name-keyed)
  Dashboard->>Gauge: render Gauge with charge/load values
  Gauge-->>Dashboard: display arc meter and percentage
Loading
flowchart TD
  Detail["detail object from API"]
  Extract["Extract: charge, load, runtime, voltage"]
  MetricsSection["detail-metrics section"]
  GridVars["detail-grid variables"]
  Detail --> Extract
  Extract --> MetricsSection
  Extract --> GridVars
  MetricsSection --> GaugeCharge["Gauge: battery.charge"]
  MetricsSection --> GaugeLoad["Gauge: ups.load"]
  MetricsSection --> TextMetrics["Text: runtime, voltage"]
  GridVars --> FilteredGrid["Filter out charge/load, render rest"]
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • JuanCF/nutwatch#25: Modifies src/frontend/src/components/Dashboard.jsx dashboard API calls and service badge class logic, directly overlapping with this PR's Dashboard gauge table integration.
  • JuanCF/nutwatch#29: Also modifies src/frontend/src/components/UpsCard.jsx and UpsDetail.jsx to render battery/load detail metrics, directly overlapping with this PR's Gauge component integration in those files.

Poem

🎯 A gauge spins round with arc and grace,
D3 draws metrics into place,
Battery charge and load align,
Dashboard, card, detail—they shine!
📊✨

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding D3 gauge components to the dashboard table, card, and detail views.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/d3-gauges

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/frontend/src/__tests__/components/Gauge.test.jsx`:
- Around line 33-36: Add two boundary tests to Gauge.test.jsx to assert the
normalization contract: one that renders Gauge with value={-10} and max={100}
(expecting to find "0%") and another that renders Gauge with a non-positive max
(e.g., value={50} max={0} and also try max={-10}) expecting "0%". Use the same
pattern as the existing "clamps value to max" test (render(<Gauge ... />) and
expect(screen.getByText('0%')).toBeInTheDocument()) so the Gauge component's
negative-value and non-positive-max behavior is explicitly covered.

In `@src/frontend/src/components/Gauge.jsx`:
- Line 8: Clamp and sanitize the percentage calculation in Gauge.jsx: validate
that max is a finite positive number and that value is finite, then compute pct
= Math.min(Math.max(value / max, 0), 1) (or set pct = 0 when max is invalid) so
pct is always in [0,1] and not NaN/Infinity; update usages of pct (text
rendering and arc geometry) to rely on this sanitized value (refer to the pct
variable and the value/max inputs in the render function that builds the arc and
label).

In `@src/frontend/src/components/UpsDetail.jsx`:
- Around line 175-200: Duplicate color-threshold logic in UpsDetail and UpsCard
should be extracted to shared utility functions; create two functions (e.g.,
getBatteryChargeColor(charge) and getLoadColor(load)) that encapsulate the
existing threshold logic (charge: <=20 red, <=50 orange, else green; load: >=80
red, >=60 orange, else accent), add them to a new module (e.g.,
utils/metrics.js), then replace the inline ternaries in the UpsDetail component
(inside the Gauge props for Battery and Load) and the similar logic in UpsCard
to import and call these utilities so both components use the single source of
truth.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 04b735b1-58a0-470c-a43e-07dd2c4bc9b2

📥 Commits

Reviewing files that changed from the base of the PR and between e9762ba and 2cdd76c.

⛔ Files ignored due to path filters (1)
  • src/frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • src/frontend/package.json
  • src/frontend/src/__tests__/components/Dashboard.test.jsx
  • src/frontend/src/__tests__/components/Gauge.test.jsx
  • src/frontend/src/__tests__/components/UpsCard.test.jsx
  • src/frontend/src/__tests__/components/UpsDetail.test.jsx
  • src/frontend/src/components/Dashboard.jsx
  • src/frontend/src/components/Gauge.jsx
  • src/frontend/src/components/UpsCard.jsx
  • src/frontend/src/components/UpsDetail.jsx
  • src/frontend/src/styles/components.css

Comment thread src/frontend/src/__tests__/components/Gauge.test.jsx
Comment thread src/frontend/src/components/Gauge.jsx Outdated
Comment thread src/frontend/src/components/UpsDetail.jsx
Guard Gauge.jsx against NaN, Infinity, and negative percentages by validating
that max is positive and value is finite before computing pct, defaulting to 0
otherwise. This prevents "-10%" text rendering and broken arc geometry when
upstream data is malformed.

Extract duplicate color-threshold logic from UpsCard and UpsDetail into
shared getBatteryChargeColor() and getLoadColor() in utils/metrics.js so both
components use a single source of truth for the charge and load color mapping.

Add boundary tests for negative values and non-positive max to codify the
normalization contract.
@JuanCF
JuanCF merged commit 8395df9 into main Jun 11, 2026
4 checks passed
@JuanCF
JuanCF deleted the feat/d3-gauges branch June 11, 2026 08:51
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