Skip to content

[CSM][Web] fix Time Cards table blocking on the full project catalogue - #1295

Merged
cloby99 merged 4 commits into
wso2-open-operations:mainfrom
Hesara2003:fix/timecards-project-filter-lazy-load
Jul 30, 2026
Merged

cloby99 merged 4 commits into
wso2-open-operations:mainfrom
Hesara2003:fix/timecards-project-filter-lazy-load

Conversation

@Hesara2003

@Hesara2003 Hesara2003 commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

The Time Cards page's table stayed stuck on its loading spinner until the entire project catalogue had loaded, even after the actual time-card search had already resolved — because the Project filter dropdown was fed by an eager, all-pages fetch whose isLoading was folded into the table's own loading state.

Goals

  • Time Cards tables (My time sheets / All / Approvals) render as soon as their own data is ready, independent of how large the project catalogue is or how slow that fetch is.
  • The Project filter keeps working exactly as before — no functional regression for users.

Approach

  • Replaced the SearchableMultiSelect + useProjectOptions() (blocking, sequential all-pages fetch) combo with AsyncProjectMultiSelect, the same lazy/scroll-paginated project search CasesFilterBar already uses elsewhere in the portal — first page loads on dropdown-open, further pages load only as the user scrolls, and typing narrows the search server-side.
  • Dropped || projects.isLoading from the three tabs' isLoading expressions so the table's loading state only reflects the actual time-card query.
  • Added a small projectNameSeedFrom helper (mirrors the existing engineerOptionsFrom/workItemOptionsFrom helpers in the same file) so an already-selected project chip still shows its real name immediately, seeded from whatever cards are already loaded, instead of a raw id while the async search catches up.

User stories

As an engineer or approver, I can open Time Cards and see my time cards immediately, without waiting on an unrelated project-list fetch to finish first.

Release note

Fixed: the Time Cards page could appear stuck loading when the project catalogue was large or slow to fetch, even though the time-card data itself was already ready.

Documentation

N/A — internal CSM portal UI, no external doc surface affected.

Automation tests

  • Unit tests: no existing test exercises this component's DOM directly (only util/hook-level tests exist under csm-timecards). Full suite run locally: 519 passed, 9 pre-existing failures unrelated to this change (confirmed identical on unmodified main — in CaseActivitiesFeed.test.tsx, CaseActionBar.test.tsx, CsmAnnouncementsPage.test.tsx; none touch Time Cards).
  • Verified against staging: tsc -b and vite build both pass clean.

Security checks

Test environment

  • pnpm run lint, pnpm run test, pnpm run build all passing locally (via the ./node_modules/.bin/ workaround for the local pnpm CLI issue).

Summary by CodeRabbit

  • Improvements
    • Enhanced the Project filter on time cards so selected project chips persist across Mine/All/Approvals and retain correct display names.
    • Project names now populate from already-loaded time-card data, reducing reliance on a fully loaded project list.
    • Updated each time-cards tab so loading indicators and empty states reflect only that tab’s time-card data, not the Project dropdown.

The Project filter loaded every project up front via useProjectOptions
(a sequential, all-pages fetch), and the table's own loading state was
folded into that fetch finishing — so a slow or large project catalogue
kept the table stuck on its spinner even after the actual time-card
search had already resolved. Swap the filter to AsyncProjectMultiSelect,
the same lazy/scroll-paginated search CasesFilterBar already uses, and
drop the project fetch from the table's loading state entirely.
@coderabbitai

coderabbitai Bot commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 76c91429-e0bc-48be-90f6-88b8c7449459

📥 Commits

Reviewing files that changed from the base of the PR and between 08f18a3 and 7e8c55f.

📒 Files selected for processing (1)
  • apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx

📝 Walkthrough

Walkthrough

The timecards page accumates project names from loaded tab data and uses an asynchronous Project filter. Project-directory loading no longer gates table loading across Mine, All, and Approvals.

Changes

Timecard project filtering

Layer / File(s) Summary
Project name cache
apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx
Project ID-to-name pairs are accumulated from loaded Mine, All, and Approvals card datasets, replacing project-options fetching.
Async project picker contract
apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx
FilterBar accepts the cross-tab projectNameSeed cache and passes it to AsyncProjectMultiSelect.
Tab wiring and loading states
apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx
Each tab receives the shared project cache, and table loading uses only the relevant timecard or queue query.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: Type/Bug

Suggested reviewers: rksk, rashmika998, cloby99

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main change: removing project-catalog loading from Time Cards rendering.
Description check ✅ Passed The description covers purpose, goals, approach, user story, release note, docs, tests, security, and environment, with only optional sections omitted.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@Hesara2003
Hesara2003 requested a review from Rashmika998 July 30, 2026 07:06

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 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
`@apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx`:
- Around line 104-113: Update CsmTimeCardsPage and projectNameSeedFrom so
selected project names persist at page/filter scope instead of being derived
only from the currently loaded tab cards. Reuse or merge a persistent
projectId-to-projectName cache across tab changes and empty result pages, and
pass that cache to every conditional FilterBar/AsyncProjectMultiSelect instance
so chips retain names after remounts. Add coverage for selecting a project on
All, switching to Mine or Approvals with no matching cards, and rendering the
selected chip without an async rediscovery.
🪄 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 Plus

Run ID: 1260485d-3000-45aa-95f0-18cf205c29be

📥 Commits

Reviewing files that changed from the base of the PR and between 71e2b3e and df0a923.

📒 Files selected for processing (1)
  • apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx

Comment thread apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx Outdated
… switches

Each tab's FilterBar/AsyncProjectMultiSelect instance unmounts on tab
switch (conditional rendering per tab), which dropped a selected
project's name the moment the newly active tab's own loaded cards
didn't happen to include it (or were empty) -- the chip fell back to a
raw id until the dropdown was reopened and re-searched. Replace the
three per-tab name derivations with one page-level cache that
accumulates project names across every tab's cards over the page's
lifetime and never shrinks, shared by all three FilterBar instances.
@s-sandali

Copy link
Copy Markdown

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

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 comments (1)
apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx (1)

17-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid suppressing set-state-in-effect for derived cache state.

Reconcile the project-name cache during render (or otherwise express it as a derivation/persistence store) instead of mutating it from this effect. That removes the lint suppression and avoids an extra render after data changes.

🤖 Prompt for 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.

In `@apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx`
at line 17, Update the project-name cache logic in CsmTimeCardsPage to reconcile
derived cache state during render, or represent it through a
derivation/persistence store, rather than calling setState from the effect.
Remove the set-state-in-effect lint suppression while preserving the cache’s
behavior when project data changes and avoiding an extra render.

Source: Learnings

🤖 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.

Nitpick comments:
In
`@apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx`:
- Line 17: Update the project-name cache logic in CsmTimeCardsPage to reconcile
derived cache state during render, or represent it through a
derivation/persistence store, rather than calling setState from the effect.
Remove the set-state-in-effect lint suppression while preserving the cache’s
behavior when project data changes and avoiding an extra render.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1bd820d1-3629-4eb3-b1a0-c65202b306a8

📥 Commits

Reviewing files that changed from the base of the PR and between df0a923 and ee93622.

📒 Files selected for processing (1)
  • apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx

…render

Replace the useEffect + setState (with a set-state-in-effect lint
suppression) with React's documented previous-renders pattern: a ref
tracks the last-seen query data, and the cache only updates during
render when it actually changed. Same accumulating behavior, but the
new name is available in the same render the data arrived in instead
of a render later, and no lint suppression is needed.
@madubashinii

Copy link
Copy Markdown

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 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
`@apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx`:
- Around line 344-368: Replace the render-time writes to lastSeenCardsRef in
CsmTimeCardsPage with useState-managed last-seen card data, initializing it
lazily and updating it idempotently during the existing comparison flow.
Preserve the current mine/all/queue identity checks and projectNameCache
synchronization while ensuring React Strict Mode double-rendering does not cause
an uncontrolled mutation.
🪄 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 Plus

Run ID: c96a7998-3006-4143-ab25-54e86b82c954

📥 Commits

Reviewing files that changed from the base of the PR and between ee93622 and 08f18a3.

📒 Files selected for processing (1)
  • apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx

Comment thread apps/csm-portal/webapp/src/features/csm-timecards/pages/CsmTimeCardsPage.tsx Outdated
… a ref

A ref mutated during render isn't reset between React Strict Mode's
double-invocation of a render pass, so the second invocation would see
the ref already updated and silently skip reconciling the project-name
cache. useState's set function is safe here -- calling it twice with
the same target value during the double-invoke is a no-op bail-out --
matching React's own documented pattern for this exact "compare against
last-seen data" case.
@cloby99
cloby99 merged commit a4782f7 into wso2-open-operations:main Jul 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants