Skip to content

Fix UI freeze and timestamp format in Usage Report (Issue #4787)#1275

Open
Kavindu21123 wants to merge 1 commit intowso2:mainfrom
Kavindu21123:fix-usage-report-bug-4787
Open

Fix UI freeze and timestamp format in Usage Report (Issue #4787)#1275
Kavindu21123 wants to merge 1 commit intowso2:mainfrom
Kavindu21123:fix-usage-report-bug-4787

Conversation

@Kavindu21123
Copy link
Copy Markdown

@Kavindu21123 Kavindu21123 commented Mar 13, 2026

Description

This PR fixes two bugs in the Admin Portal's Usage Report component that prevented the "View" button from functioning correctly, addressing Issue #4787.

Root Causes & Fixes:

  1. Timestamp Format: The fetchTransactionData function was using dayjs().unix(), which sends the timestamp to the backend in seconds. The backend requires milliseconds. Changed .unix() to .valueOf() to send the correct millisecond epoch.
  2. Infinite Loading State: If the date picker inputs were null/empty, setLoading(true) was triggered, but the API call was skipped. This caused the UI to hang indefinitely because the finally block was never reached. Added a guard clause if (!selectedStartDate || !selectedEndDate) { return; } at the beginning of the function to prevent this.

Related Issue

Fixes wso2/api-manager#4787

How to Test

  1. Enable [apim.transaction_counter] in deployment.toml.
  2. Generate API invocations to create transaction data.
  3. Navigate to Admin Portal -> Settings -> Usage Report.
  4. Select a date range and click "View". The data will now load successfully without freezing the UI.

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced transaction data fetching by adding proper validation to ensure both start and end dates are selected before retrieving transaction data, effectively preventing incomplete or invalid queries.
    • Improved error handling and loading state management during transaction data retrieval to provide more consistent user feedback and deliver better overall application reliability.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 13, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 13, 2026

Walkthrough

Modified the fetchTransactionData function in UsageReport.jsx to add an early guard clause requiring both start and end dates, replaced date conversion method from unix() to valueOf(), and restructured promise handling with inlined error and completion logic.

Changes

Cohort / File(s) Summary
Transaction Data Fetching Logic
portals/admin/src/main/webapp/source/src/app/components/APISettings/UsageReport.jsx
Added early guard clause to validate both date selections before API call; replaced unix().toString() date conversion with valueOf().toString(); restructured promise chain from multiple then blocks with separate finally to single then with inlined catch and finally for improved error handling and loading state management.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit hopped through buggy dates,
With promises that would not wait,
A guard clause fixed what broke before,
Now valueOf() opens transaction's door—
The view button dances once more! 🎉

🚥 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 clearly and specifically describes the main changes: fixing UI freeze and timestamp format issues in the Usage Report component, with the linked issue reference.
Linked Issues check ✅ Passed The code changes directly address the two core objectives from issue #4787: replacing unix() with valueOf() for correct timestamp format and adding early guard clauses to prevent UI freeze when dates are missing.
Out of Scope Changes check ✅ Passed All changes are contained within UsageReport.jsx and directly address the fetchTransactionData logic issues identified in issue #4787; no out-of-scope modifications detected.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

You can get early access to new features in CodeRabbit.

Enable the early_access setting to enable early access features such as new models, tools, and more.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
portals/admin/src/main/webapp/source/src/app/components/APISettings/UsageReport.jsx (1)

239-248: Add defensive validation with isValid() before calling valueOf().

The current null/empty check at line 239 is insufficient. MUI X DatePicker v7 can invoke onChange with an invalid Dayjs object (where isValid() === false) during partial date input, causing lines 247–248 to send "NaN" timestamps. The proposed guard prevents this:

Recommended fix
-        if (!selectedStartDate || !selectedEndDate) {
+        if (
+            !selectedStartDate
+            || !selectedEndDate
+            || !selectedStartDate.isValid?.()
+            || !selectedEndDate.isValid?.()
+        ) {
             return;
         }

Alternatively, update the onChange handlers to leverage MUI's context parameter (more idiomatic for v7):

onChange={(newValue, context) => {
  if (context.validationError == null && newValue?.isValid?.()) {
    setSelectedStartDate(newValue);
  }
}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@portals/admin/src/main/webapp/source/src/app/components/APISettings/UsageReport.jsx`
around lines 239 - 248, The null/empty checks before calling valueOf() are
insufficient because MUI X DatePicker v7 can pass invalid Dayjs objects; update
the guard around selectedStartDate/selectedEndDate used before calling valueOf()
(the block that constructs startTime/endTime for API.getTransactionCount) to
also verify each has an isValid() === true (e.g., only call
selectedStartDate.valueOf() and selectedEndDate.valueOf() when the Dayjs object
exists and isValid()); alternatively, fix the DatePicker onChange handlers that
set selectedStartDate/selectedEndDate to only set when the provided newValue has
no validation errors (use the context param) and newValue?.isValid?.() so
invalid dates never reach the API call.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@portals/admin/src/main/webapp/source/src/app/components/APISettings/UsageReport.jsx`:
- Around line 253-256: In fetchTransactionData, remove the rethrow inside the
catch for the api.getTransactionCount() promise: currently the catch logs the
error then does "throw error", which causes an unhandled rejection because
fetchTransactionData()'s promise is not awaited/returned from the useEffect
call; update the catch in the api.getTransactionCount() chain to only log the
error (console.error) and not rethrow so the promise resolves and the finally
block still runs (i.e., edit the catch in the fetchTransactionData function that
wraps api.getTransactionCount()).

---

Nitpick comments:
In
`@portals/admin/src/main/webapp/source/src/app/components/APISettings/UsageReport.jsx`:
- Around line 239-248: The null/empty checks before calling valueOf() are
insufficient because MUI X DatePicker v7 can pass invalid Dayjs objects; update
the guard around selectedStartDate/selectedEndDate used before calling valueOf()
(the block that constructs startTime/endTime for API.getTransactionCount) to
also verify each has an isValid() === true (e.g., only call
selectedStartDate.valueOf() and selectedEndDate.valueOf() when the Dayjs object
exists and isValid()); alternatively, fix the DatePicker onChange handlers that
set selectedStartDate/selectedEndDate to only set when the provided newValue has
no validation errors (use the context param) and newValue?.isValid?.() so
invalid dates never reach the API call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2aebe8c9-350d-4786-bacd-ab5209c7b47a

📥 Commits

Reviewing files that changed from the base of the PR and between 8d8a57c and de7343c.

📒 Files selected for processing (1)
  • portals/admin/src/main/webapp/source/src/app/components/APISettings/UsageReport.jsx

Comment on lines +253 to +256
.catch((error) => {
console.error('Error fetching transaction count:', error);
throw error;
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In JavaScript Promises, what happens when an error is thrown inside catch() and the resulting Promise is not awaited or otherwise handled?

💡 Result:

If you throw inside a .catch() handler, the promise returned by that .catch() becomes rejected with the thrown error (equivalent to returning a rejected promise). [1]

If you then don’t await it or attach another rejection handler (e.g. another .catch()), it becomes an unhandled promise rejection:

  • Browsers: the global unhandledrejection event fires, and if it isn’t handled, you’ll typically see an error logged to the console. [2]
  • Node.js: by default (--unhandled-rejections=throw, the default since Node 15), Node emits unhandledRejection, and if you don’t handle that event, it raises it as an uncaught exception (which commonly terminates the process). [3]

Sources: [1] MDN Promise.prototype.catch() (www-igm.univ-mlv.fr), [2] MDN unhandledrejection event (developer.mozilla.org), [3] Node.js CLI --unhandled-rejections docs (nodejs.org)

Citations:


🏁 Script executed:

cat -n portals/admin/src/main/webapp/source/src/app/components/APISettings/UsageReport.jsx | sed -n '240,270p'

Repository: wso2/apim-apps

Length of output: 1166


Remove the rethrow in this catch block to prevent unhandled Promise rejections.

The promise chain from api.getTransactionCount() (line 246) is not awaited or returned by fetchTransactionData(). When useEffect calls fetchTransactionData() at line 264 without awaiting, the promise becomes unhandled. Rethrowing in the catch block at line 255 creates a rejected promise that has no handler, resulting in an unhandled rejection error at runtime.

Since the error is already logged, simply removing the throw allows the promise to resolve, preventing the unhandled rejection while preserving the error logging and the finally block execution.

Proposed fix
             .catch((error) => {
                 console.error('Error fetching transaction count:', error);
-                throw error;
             })
📝 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
.catch((error) => {
console.error('Error fetching transaction count:', error);
throw error;
})
.catch((error) => {
console.error('Error fetching transaction count:', error);
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@portals/admin/src/main/webapp/source/src/app/components/APISettings/UsageReport.jsx`
around lines 253 - 256, In fetchTransactionData, remove the rethrow inside the
catch for the api.getTransactionCount() promise: currently the catch logs the
error then does "throw error", which causes an unhandled rejection because
fetchTransactionData()'s promise is not awaited/returned from the useEffect
call; update the catch in the api.getTransactionCount() chain to only log the
error (console.error) and not rethrow so the promise resolves and the finally
block still runs (i.e., edit the catch in the fetchTransactionData function that
wraps api.getTransactionCount()).

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.

[4.7.0] View button of the transaction counter is not working

2 participants