[CSM Portal] add CSV export of the filtered result set to the listing pages - #1300
Conversation
Adds an Export CSV action to the cases/service-requests, incidents, and change-requests listings. Client-side over paged fetches of the existing list-search endpoints (no new backend endpoint): it pages the currently applied filters and sort to exhaustion, mapping the same columns/display values the table already shows, and downloads one CSV. A safety row cap stops a runaway export, but the result is never silently short — the filename and an on-screen notice both flag a truncated file and tell the engineer to narrow their filters. Extracts the cases search filter-building, assignee-id resolution, and row mapping out of useGetCsmCases into a shared module so the export pages with the exact same query the listing itself sends, instead of a second, driftable copy of it. Refactors the time-card CSV export to share the new csvField/rowsToCsvText helpers instead of duplicating them.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds a shared paginated CSV export flow with progress, truncation handling, and download utilities. Integrates export controls into cases, change requests, and incidents, centralizes case-search mapping, and updates timecard CSV generation. ChangesCSV export flow
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/csm-portal/webapp/src/utils/csvExport.ts (1)
38-42: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winConsider prepending a UTF-8 BOM for Excel compatibility.
downloadCsvwrites plain UTF-8 without a byte-order mark. This is the shared download path for every CSV export on the portal (timecards today, and cases/incidents/change-requests once this stack lands), so it's worth fixing once here. Excel on Windows guesses the legacy code page when no BOM is present, and any non-ASCII characters in exported data (accented customer/engineer names, etc.) will render as mojibake on double-click-open, even though the underlying bytes are valid UTF-8.♻️ Proposed fix
export function downloadCsv(header: string[], rows: string[][], filename: string): void { const csv = rowsToCsvText(header, rows); - saveBlob(new Blob([csv], { type: "text/csv;charset=utf-8;" }), filename); + saveBlob(new Blob(["\uFEFF" + csv], { type: "text/csv;charset=utf-8;" }), filename); }🤖 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/utils/csvExport.ts` around lines 38 - 42, Update downloadCsv to prepend a UTF-8 BOM to the generated CSV content before creating the Blob, while preserving the existing rowsToCsvText conversion, text/csv charset, and saveBlob download flow.
🤖 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-operations/components/ChangeRequestsTab.tsx`:
- Around line 136-148: Guard both fetchChangeRequestsPage in
ChangeRequestsTab.tsx (lines 136-148) and fetchIncidentsPage in IncidentsTab.tsx
(lines 118-131) against missing search-response fields by defaulting the
returned items arrays to [] and totals to 0. Update each return value
consistently so useFilteredCsvExport always receives valid pagination data.
---
Nitpick comments:
In `@apps/csm-portal/webapp/src/utils/csvExport.ts`:
- Around line 38-42: Update downloadCsv to prepend a UTF-8 BOM to the generated
CSV content before creating the Blob, while preserving the existing
rowsToCsvText conversion, text/csv charset, and saveBlob download flow.
🪄 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: 8ae19bd1-669d-42f9-a725-084bc56a4faa
📒 Files selected for processing (12)
apps/csm-portal/webapp/src/components/FilteredCsvExportButton.test.tsxapps/csm-portal/webapp/src/components/FilteredCsvExportButton.tsxapps/csm-portal/webapp/src/features/csm-cases/api/useGetCsmCases.tsapps/csm-portal/webapp/src/features/csm-cases/components/CsmIssuesView.tsxapps/csm-portal/webapp/src/features/csm-cases/utils/caseSearchPayload.tsapps/csm-portal/webapp/src/features/csm-operations/components/ChangeRequestsTab.tsxapps/csm-portal/webapp/src/features/csm-operations/components/IncidentsTab.tsxapps/csm-portal/webapp/src/features/csm-timecards/utils/timeCardCsvExport.tsapps/csm-portal/webapp/src/hooks/__tests__/useFilteredCsvExport.test.tsapps/csm-portal/webapp/src/hooks/useFilteredCsvExport.tsapps/csm-portal/webapp/src/utils/__tests__/csvExport.test.tsapps/csm-portal/webapp/src/utils/csvExport.ts
…y or total The change-request and incident export page fetchers returned the search response's array and total straight through, unlike the rest of the export code and the case list hook, which both fall back with `?? []` / `?? 0` on the same class of response. `fetchAllPages` reads `page.items.length` to advance its offset, so an omitted array would throw mid-export instead of terminating the loop cleanly.
|
@coderabbitai resume |
✅ Action performedReviews resumed. |
What
Adds an Export CSV action to the CSM portal's listing pages: cases and service requests (plus engagements, security reports and the project-scoped issues tab, which share the same list component), incidents, and change requests.
The export covers the entire currently-filtered, currently-sorted result set — not just the page on screen — by paging the existing search endpoints client side. No new backend endpoint.
Why
CS engineers need the filtered list out of the portal for periodic reporting (for example, every incident created in a given month for one product). Today the only options are paging through the UI and copying by hand, or asking someone to pull the data from the backing data source.
How, and the part worth reviewing closely
The risk with a client-side export is a file that looks complete and is not. Guards against that:
*-partial.csvand a banner tells the user the export was truncated and to narrow the filter. It never silently stops short.To stop the export drifting from what the screen shows, the filter-payload builder and row mapper were extracted out of the list hook into a shared module and used by both, rather than duplicated.
timeCardCsvExportwas also refactored onto the shared CSV helpers instead of its own private copy (behaviour and tests unchanged).Known limitation, deliberately not worked around
The incident listing currently supports only free-text search, priority and parent as filters — there is no created-date range and no product filter yet. So the export faithfully exports what the filter bar can express today, which is less than the reporting use case needs. Adding those filters is tracked separately; this change does not paper over the gap.
Client-side paging is also inherently chatty: page size below is capped at 50, so a few hundred rows means several sequential round trips before the download begins. That trade was chosen deliberately over adding a server-side export endpoint.
Verification
npx tsc -b— cleannpx eslint .— 0 errors; 1 pre-existing warning inCsmCaseDetailPage.tsx, confirmed present onmainnpx vitest run— 551 passed, 9 failed; the 9 are pre-existing failures onmainin three files this branch does not touchNot exercised against a running backend.
Summary by CodeRabbit