Skip to content

Conversation

@PRoIISHAAN
Copy link
Contributor

@PRoIISHAAN PRoIISHAAN commented Jan 21, 2026

Checklist

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • I have updated the documentation.

Reference to Existing Issue

Closes #863

Description of Changes

Added react-circular-progressbar package for circular progress visualization
Replaced linear bars with circular progress indicators (CircularProgressbarWithChildren)
Added new CSS classes for the redesigned usage overview section
New Helper Methods in status.js:
getUserCheckFormattedValue() - Updated to calculate and format remaining quota
getUserCheckUsedValue() - New method to format "used of total" display
getResetTimeRemaining() - New method to calculate time until quota reset
getUsageColorAndIcons() - New method to determine color and icons based on usage percentage

Screenshot

Screenshot 2026-01-21 at 2 39 54 PM

@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

Caution

Review failed

An error occurred during the review process. Please try again later.

📝 Walkthrough

Walkthrough

Adds a daily "usage" UI to the status page: new CSS for a usage-overview widget and a React implementation using react-circular-progressbar to render radial progress bars. The Status component gains helpers to format used/remaining values, compute reset time remaining, and choose colors/icons; it renders per-check usage cards, optional daily reset messaging, and an upgrade CTA. The feature is enabled by default in internals/config/default.yml, package.json updated, and multiple i18n keys/translations were added.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant StatusComponent
  participant API_Server
  participant RADIUS_Backend

  Browser->>StatusComponent: Load status page
  StatusComponent->>API_Server: GET /status (request usage checks)
  API_Server->>RADIUS_Backend: Query counters and reset timestamps
  RADIUS_Backend-->>API_Server: Return counters + reset info
  API_Server-->>StatusComponent: Return usage checks + reset timestamps
  StatusComponent->>StatusComponent: compute colors, icons, remaining time, formatted values
  StatusComponent->>Browser: render usage-overview (radial progress bars, labels, reset line)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~35 minutes

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Make progress bar in status page more user friendly' directly summarizes the main change—replacing linear progress bars with circular progress indicators and enhancing the UI.
Description check ✅ Passed The PR description includes all key template sections: completed checklist, reference to issue #863, clear description of changes, and a screenshot demonstrating the new UI.
Linked Issues check ✅ Passed The PR implements all primary objectives from issue #863: circular progress visualization with improved UX, explicit time/traffic display, helper methods for formatting, and enables radius_usage_enabled by default.
Out of Scope Changes check ✅ Passed All changes directly support the linked issue's objectives: circular progress implementation, new CSS styling, helper methods, i18n translations for the new UI, and dependency updates align with the feature requirements.

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


🧹 Recent nitpick comments
client/components/status/status.js (1)

1166-1249: Defensive guards properly implemented.

The helper methods now include proper validation using Number() and Number.isFinite() checks, returning t\N/A`` for invalid inputs. This addresses the concerns about malformed API data causing broken rendering.

Minor DRY opportunity: The time formatting logic (hours/minutes calculation) at lines 1185-1196 and 1214-1227 is duplicated. Consider extracting a shared formatTime helper to reduce redundancy.

♻️ Optional: Extract shared formatTime helper
+  // eslint-disable-next-line class-methods-use-this
+  formatTime = (seconds) => {
+    const hours = Math.floor(seconds / 3600);
+    const minutes = Math.floor((seconds % 3600) / 60);
+    if (hours > 0 && minutes > 0) {
+      return `${hours}${t`TIME_HOUR_ABBR`} ${minutes}${t`TIME_MINUTE_ABBR`}`;
+    }
+    if (hours > 0) {
+      return `${hours}${t`TIME_HOUR_ABBR`}`;
+    }
+    if (minutes > 0) {
+      return `${minutes}${t`TIME_MINUTE_ABBR`}`;
+    }
+    return t`TIME_LESS_THAN_MINUTE`;
+  };

   // eslint-disable-next-line class-methods-use-this
   getUserCheckFormattedValue = (value, type, result) => {
     // ... validation ...
     case "seconds": {
       if (remaining === 0) {
         return t`0`;
       }
-      const hours = Math.floor(remaining / 3600);
-      const minutes = Math.floor((remaining % 3600) / 60);
-      // ... rest of formatting
+      return this.formatTime(remaining);
     }
📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6899790 and e24510f.

⛔ Files ignored due to path filters (1)
  • client/components/status/__snapshots__/status.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • client/components/status/status.js
  • i18n/de.po
  • i18n/en.po
  • i18n/es.po
  • i18n/fur.po
  • i18n/it.po
  • i18n/ru.po
  • i18n/sl.po
🚧 Files skipped from review as they are similar to previous changes (3)
  • i18n/en.po
  • i18n/ru.po
  • i18n/sl.po
🧰 Additional context used
🧬 Code graph analysis (1)
client/components/status/status.js (1)
client/reducers/plan-exhausted.js (1)
  • planExhausted (3-10)
⏰ 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). (1)
  • GitHub Check: Tests and Coverage
🔇 Additional comments (8)
i18n/fur.po (1)

183-238: LGTM!

The new Friulian translations for the usage overview UI are complete and properly formatted. All required keys (DAILY_USAGE_OVERVIEW, USAGE_TIME, USAGE_DATA, TIME_HOUR_ABBR, etc.) have been added with appropriate translations and source references.

i18n/it.po (1)

184-239: LGTM!

The Italian translations for the new usage overview UI elements are complete and well-formatted. All keys align with the other locale files and the source references in status.js.

client/components/status/status.js (4)

3-18: Import order looks correct now.

The imports follow the expected pattern: CSS imports first (lines 3-5), then external library imports (lines 6-17), then local imports (line 19 onwards). The react-circular-progressbar imports are correctly placed among other external dependencies.


1269-1304: Division by zero properly handled.

The check at line 1275 (!numValue || Number.isNaN(numValue)) correctly guards against division by zero by returning a default green state when value is 0 or non-numeric. This addresses the previous review concern.


1416-1499: Usage overview implementation looks solid.

The render block properly addresses previous review concerns:

  • Translations use t\`` instead of hardcoded strings (lines 1417-1418, 1449, 1452)
  • Quota validation using Number.isFinite() before rendering (lines 1431-1434)
  • Normalized numeric values passed to child components (lines 1438-1442)
  • Helper method renderUsageCheckContent reduces duplication
  • Reset time message properly translated (line 1475)

1306-1341: Clean extraction of usage check rendering.

The renderUsageCheckContent method provides a well-structured, reusable component for rendering individual usage checks. It correctly expects normalized numeric inputs which are validated by the caller before invocation.

i18n/es.po (1)

188-243: LGTM!

The Spanish translations for the new usage overview UI are complete and properly formatted. All keys are consistent with other locale files.

i18n/de.po (1)

183-238: LGTM!

The German translations for the usage overview UI are complete with appropriate localizations. The time abbreviations ("Std" for hours, "Min" for minutes) and "N/V" for N/A follow standard German conventions.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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: 4

🤖 Fix all issues with AI agents
In `@client/components/status/status.js`:
- Around line 1381-1463: The JSX duplicates nearly identical blocks and uses a
nested ternary; extract a helper method (e.g., renderUsageCheck) on the
component class that accepts (check, color, icon, label) and renders the shared
markup while calling existing helpers getUserCheckFormattedValue and
getUserCheckUsedValue; then replace the nested ternary in render with two simple
checks (check.type === "seconds" and check.type === "bytes") that call
renderUsageCheck with timerIcon/"Time" and dataIcon/"Data" respectively,
removing the nested ternary and eliminating the duplicated JSX.
- Around line 17-20: ESLint flagged import order: the external module imports
(react-circular-progressbar's CircularProgressbarWithChildren and buildStyles)
must come before the local import from ../../utils/get-language-headers; reorder
the imports so the lines importing CircularProgressbarWithChildren and
buildStyles appear above the import of get-language-headers (referenced symbol:
CircularProgressbarWithChildren, buildStyles, and the local module import
../../utils/get-language-headers).
- Around line 1260-1283: The getUsageColorAndIcons function computes
usagePercentage as (result / value) * 100 and can divide by zero; update
getUsageColorAndIcons to defensively handle value === 0 (or non-numeric) before
performing the division—coerce value/result to numbers, if value is 0 return a
safe default color/icons (e.g., the low-usage/green set) or a clearly defined
fallback object, otherwise compute usagePercentage and keep the existing
threshold logic; reference getUsageColorAndIcons and its value/result parameters
when making the change.
- Around line 1358-1368: In the Status component render block in
client/components/status/status.js, replace hardcoded English UI strings with
the i18n helper (e.g., wrap them in t`` or gettext()), specifically: change the
"Daily usage overview" text inside the div with className
"usage-overview-title", the paragraph "Track how much time and data you've used
today", and all occurrences of the labels "Time", "Data", and the word
"remaining" within the same render output; ensure you leave conditional logic
using radiusUsageSpinner, this.getSpinner(), settings.subscriptions, and
userPlan.name unchanged and only wrap the literal strings so the component uses
translated text.
🧹 Nitpick comments (3)
client/components/status/index.css (1)

136-142: Consider adding responsive styles for the usage boxes.

The .usage-box has fixed dimensions (width: 174px, height: 236px), but there are no responsive adjustments in the media query for small screens (lines 209-220). On narrow viewports (< 500px), two usage boxes side-by-side would overflow.

Consider adding responsive rules to allow the boxes to resize or stack on smaller screens.

💡 Suggested responsive adjustment
`@media` screen and (min-width: 0px) and (max-width: 500px) {
  /* existing rules... */
  
  .usage-box {
    width: 100%;
    max-width: 174px;
    height: auto;
    min-height: 200px;
  }
  
  .usage-checks-container {
    flex-direction: column;
  }
}
client/components/status/status.js (2)

1469-1474: Minor: getResetTimeRemaining called twice.

The method is called once in the condition (line 1470) and again in the template literal (line 1472). Consider storing the result in a variable.

💡 Suggested optimization
{(() => {
  const resetTime = userChecks[0]?.reset && this.getResetTimeRemaining(userChecks[0].reset);
  return resetTime && (
    <div className="usage-reset-info">
      {t`*Daily limits reset in ${resetTime}`}
    </div>
  );
})()}

Or compute resetTimeRemaining once before the return statement.


1384-1385: Alt text should be translatable for accessibility.

The alt attributes ("Timer Icon", "Data Icon") are hardcoded English strings. For proper i18n/a11y support, these should use translation functions.

-<img src={timerIcon} alt="Timer Icon" />
+<img src={timerIcon} alt={t`TIMER_ICON_ALT`} />
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1eb25ed and e0dbe9b.

⛔ Files ignored due to path filters (2)
  • client/components/status/__snapshots__/status.test.js.snap is excluded by !**/*.snap
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • client/components/status/index.css
  • client/components/status/status.js
  • internals/config/default.yml
  • package.json
🧰 Additional context used
🧬 Code graph analysis (1)
client/components/status/status.js (1)
client/reducers/plan-exhausted.js (1)
  • planExhausted (3-10)
🪛 ESLint
client/components/status/status.js

[error] 17-20: react-circular-progressbar import should occur before import of ../../utils/get-language-headers

(import/order)


[error] 1362-1362: ' can be escaped with &apos;, &lsquo;, &#39;, &rsquo;.

(react/no-unescaped-entities)


[error] 1381-1463: Do not nest ternary expressions.

(no-nested-ternary)

⏰ 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). (1)
  • GitHub Check: Tests and Coverage
🔇 Additional comments (6)
package.json (1)

34-34: LGTM!

The react-circular-progressbar library is a well-maintained choice for this feature. The version and placement in dependencies is appropriate.

internals/config/default.yml (1)

104-104: Verify the intent to enable radius usage by default.

Enabling radius_usage_enabled: true by default will display the new usage overview UI for all organizations. This changes the default behavior for new and existing deployments that haven't explicitly configured this setting.

Per the linked issue #863, this appears intentional ("consider enabling the feature by default"), but please confirm this is the desired rollout strategy.

client/components/status/index.css (1)

144-208: LGTM!

The layout and typography styles for the usage overview section are well-structured with appropriate use of flexbox.

client/components/status/status.js (3)

1168-1197: LGTM with minor observation.

The remaining value calculation and formatting logic is correct. Note that the time formatting logic (hours/minutes calculation) is duplicated in getUserCheckUsedValue below - consider extracting to a shared helper if this pattern grows.


1199-1240: LGTM!

The "used of total" formatting logic correctly caps usage at the total value and handles all type variants appropriately.


1242-1258: LGTM!

The reset time calculation correctly handles edge cases (null timestamp, past timestamps) and provides human-readable remaining time.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@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: 1

🤖 Fix all issues with AI agents
In `@client/components/status/status.js`:
- Around line 1229-1237: The template-literal strings using t`` in
client/components/status/status.js (the `return t\`${usedFormatted} used of
${totalFormatted}\`` / `return t\`${usedFormatted} used of ${totalFormatted}\``
/ `return t\`${used} used of ${intValue}\`` occurrences inside the switch
handling formats) are not present in our .po files; run the translation
extraction to add them to all language catalogs (e.g. run the provided yarn
translations-update commands for each i18n/*.po or run the bulk update to sync
all files) so the "used of" entries are extracted and translations are available
before deployment.
🧹 Nitpick comments (3)
client/components/status/status.js (3)

1173-1191: Time abbreviations may not localize correctly.

The time formatting uses embedded English abbreviations ("h", "m") in template literals. While t\`` is used, different languages have different abbreviations for hours/minutes (e.g., German uses "Std"/"Min", French uses "h"/"min"). Consider using translation keys with placeholders:

// Example approach
const hours = ...;
const minutes = ...;
if (hours > 0 && minutes > 0) {
  return t`TIME_HOURS_MINUTES`.replace('{hours}', hours).replace('{minutes}', minutes);
}

Or leverage the existing Intl.RelativeTimeFormat API for proper locale-aware formatting.

Also, t\0`` on lines 1174 and 1178 is unnecessary since "0" is language-neutral.


1418-1423: Type inconsistency for check.value comparison.

Line 1421 compares check.value === "0" (string), while getUsageColorAndIcons at line 1261 converts it with Number(value). If check.value can be either string or number, consider normalizing:

- if (check.value === "0") {
+ if (Number(check.value) === 0) {

This ensures consistent behavior regardless of the API response type.


1451-1456: Missing translation key for reset time message.

Line 1454's string *Daily limits reset in ${...} has embedded English that won't be translated. Add a translation key like DAILY_LIMITS_RESET_IN to the .po files:

- {t`*Daily limits reset in ${this.getResetTimeRemaining(userChecks[0].reset)}`}
+ {t`DAILY_LIMITS_RESET_IN`.replace('{time}', this.getResetTimeRemaining(userChecks[0].reset))}

And add corresponding entries in .po files:

msgid "DAILY_LIMITS_RESET_IN"
msgstr "*Tägliche Limits werden in {time} zurückgesetzt"
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e0dbe9b and 97bef4f.

📒 Files selected for processing (9)
  • client/components/status/index.css
  • client/components/status/status.js
  • i18n/de.po
  • i18n/en.po
  • i18n/es.po
  • i18n/fur.po
  • i18n/it.po
  • i18n/ru.po
  • i18n/sl.po
✅ Files skipped from review due to trivial changes (1)
  • i18n/sl.po
⏰ 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). (1)
  • GitHub Check: Tests and Coverage
🔇 Additional comments (10)
i18n/fur.po (1)

183-202: Translation additions look good.
Thanks for adding the new usage strings here; this aligns with the UI changes.

i18n/ru.po (1)

189-207: Translation additions look good.
The new usage overview strings are consistent with the UI updates.

i18n/en.po (1)

182-200: Translation additions look good.
These strings match the new usage overview UI.

i18n/it.po (1)

184-202: Translation additions look good.
New usage strings are consistent and complete.

i18n/es.po (1)

188-206: Translation additions look good.
These new usage labels fit the updated status UI.

client/components/status/index.css (1)

144-149: No change needed. The current align-items: start is the modern Box Alignment standard, supported across all modern browsers since 2021-2022. Switching to flex-start would move away from the current standard. Unless your project explicitly targets IE11 (which doesn't appear to be the case based on your configuration), keep the current code as-is.

Likely an incorrect or invalid review comment.

i18n/de.po (1)

183-201: LGTM!

The German translations for the new usage overview UI elements are accurate and consistent with the existing translation style in this file.

client/components/status/status.js (3)

4-18: LGTM!

The import reorganization addresses the previous ESLint import order concern. External dependencies are now properly ordered before local imports.


1259-1294: LGTM!

The division-by-zero concern from the previous review is addressed with the guard at line 1265. The color thresholds (green ≤50%, yellow ≤80%, red >80%) provide clear visual feedback for usage levels.


1296-1331: LGTM!

Good refactor extracting the repeated JSX into renderUsageCheckContent, addressing the previous nested ternary concern. The component is well-structured with proper styling.

Minor note: Line 1299's alt text ${label} Icon has "Icon" hardcoded. For complete i18n, consider a translation key, though this is low priority since screen readers typically handle this adequately.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@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

🤖 Fix all issues with AI agents
In `@client/components/status/status.js`:
- Around line 1166-1239: Both getUserCheckFormattedValue and
getUserCheckUsedValue currently use parseInt on value/result and assume valid
numbers; add defensive guards by converting with Number(...) (or retain parseInt
but then validate) and checking Number.isFinite(...) for intValue and intResult
before using them. If either conversion is not finite, return a safe fallback
(e.g., t`0` or a localized "N/A" string) and avoid calling prettyBytes or
formatTime; update references inside getUserCheckFormattedValue (type
"bytes"/"seconds" and default) and getUserCheckUsedValue (used calculation,
bytes branch using prettyBytes, seconds branch using formatTime, and default) to
short-circuit when inputs are invalid.
- Around line 1418-1446: Normalize and validate quota values before rendering:
at the top of the userChecks.map callback convert check.value to a number (e.g.,
const valueNum = Number(check.value)), then if (!Number.isFinite(valueNum) ||
valueNum <= 0) return null; call this.getUsageColorAndIcons with valueNum
(instead of raw check.value) and pass the normalized valueNum into
this.renderUsageCheckContent so the progress component receives a finite
positive number.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a71aca and b732e2d.

📒 Files selected for processing (8)
  • client/components/status/status.js
  • i18n/de.po
  • i18n/en.po
  • i18n/es.po
  • i18n/fur.po
  • i18n/it.po
  • i18n/ru.po
  • i18n/sl.po
🚧 Files skipped from review as they are similar to previous changes (5)
  • i18n/sl.po
  • i18n/de.po
  • i18n/fur.po
  • i18n/ru.po
  • i18n/en.po
🧰 Additional context used
🧬 Code graph analysis (1)
client/components/status/status.js (1)
client/reducers/plan-exhausted.js (1)
  • planExhausted (3-10)
⏰ 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). (1)
  • GitHub Check: Tests and Coverage
🔇 Additional comments (2)
i18n/it.po (1)

184-208: Translation additions look good.

The new usage overview keys and labels align with the updated status UI.

i18n/es.po (1)

188-213: LGTM for the new usage translations.

These entries correctly cover the new daily-usage UI labels.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@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: 1

🤖 Fix all issues with AI agents
In `@client/components/status/status.js`:
- Around line 1472-1477: The template literal used in the status component for
the reset message (the expression t`*Daily limits reset in
${this.getResetTimeRemaining(userChecks[0].reset)}` inside the usage-reset-info
render) lacks a msgid in the .po files; add a translation entry like "*Daily
limits reset in %s" to all .po files (and update your i18n extraction if used)
so the string uses the translation instead of falling back to English, ensuring
the placeholder matches getResetTimeRemaining output formatting.
🧹 Nitpick comments (1)
client/components/status/status.js (1)

1166-1249: LGTM - defensive guards properly implemented.

The methods now correctly validate inputs using Number() and Number.isFinite() checks before performing calculations. Both methods return t\N/A`for invalid inputs, preventingNaN` propagation.

Optional: Consider extracting the duplicated time formatting logic (hours/minutes calculation pattern appearing in both getUserCheckFormattedValue and getUserCheckUsedValue) into a shared helper to reduce duplication.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b732e2d and 6899790.

⛔ Files ignored due to path filters (1)
  • client/components/status/__snapshots__/status.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • client/components/status/status.js
  • i18n/de.po
  • i18n/en.po
  • i18n/es.po
  • i18n/fur.po
  • i18n/it.po
  • i18n/ru.po
  • i18n/sl.po
🚧 Files skipped from review as they are similar to previous changes (4)
  • i18n/sl.po
  • i18n/ru.po
  • i18n/en.po
  • i18n/fur.po
⏰ 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). (1)
  • GitHub Check: Tests and Coverage
🔇 Additional comments (7)
i18n/de.po (1)

183-212: LGTM!

The new German translation entries for the daily usage overview feature are complete and appropriately translated. All required keys (DAILY_USAGE_OVERVIEW, DAILY_USAGE_OVERVIEW_DESCRIPTION, USAGE_TIME, USAGE_DATA, USAGE_REMAINING, USAGE_USED_OF, N/A) are present with proper German translations.

i18n/es.po (1)

188-217: LGTM!

The Spanish translation entries are complete and linguistically appropriate. All new keys for the usage overview feature are properly translated.

i18n/it.po (1)

184-213: LGTM!

The Italian translation entries are complete and properly translated. All required keys for the daily usage overview feature are present.

client/components/status/status.js (4)

1-18: LGTM!

The imports are now properly organized with the react-circular-progressbar import placed correctly among other external library imports.


1269-1304: LGTM - division by zero guard implemented.

The method now properly handles the case when value is 0 or non-numeric by returning the green (low usage) color scheme as a safe default before the division occurs.


1306-1341: LGTM - well-structured helper method.

The extracted renderUsageCheckContent helper cleanly encapsulates the repeated JSX for rendering usage check cards, addressing the previous nested ternary concern.


1416-1470: LGTM - proper validation and normalization of usage data.

The render logic now properly:

  1. Validates valueNum and resultNum using Number.isFinite() checks
  2. Filters out invalid or zero quota values
  3. Creates a normalized check object with numeric values before passing to the progress bar
  4. Uses proper i18n functions for all user-facing strings

This addresses the previous concerns about filtering invalid quota values.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

[change:ux] Make progress bar in status page more user friendly

1 participant