-
Notifications
You must be signed in to change notification settings - Fork 11.7k
feat: Add download CSV button on bookings page #27107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 issue found across 2 files
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="apps/web/modules/bookings/components/BookingsCsvDownload.tsx">
<violation number="1" location="apps/web/modules/bookings/components/BookingsCsvDownload.tsx:25">
P2: Localize the CSV headers (and filename text) using t() with existing locale keys instead of hardcoded strings so the exported CSV matches the UI language.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Devin AI is addressing Cubic AI's review feedbackA Devin session has been created to address the issues identified by Cubic AI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| while (allBookings.length < totalCount) { | ||
| const offset = allBookings.length; | ||
| const batch = await fetchBatch(offset); | ||
| allBookings = [...allBookings, ...batch.bookings]; | ||
|
|
||
| const currentProgress = Math.min(Math.round((allBookings.length / totalCount) * 100), 99); | ||
| showProgressToast(currentProgress); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 Infinite loop when batch returns empty bookings during CSV download
In the handleDownload function, the while loop at line 89 (while (allBookings.length < totalCount)) can run infinitely if a subsequent batch returns an empty bookings array while totalCount remains greater than allBookings.length.
This can occur in race conditions where bookings are deleted between the first batch fetch and subsequent fetches, or if there's a server-side issue returning empty results.
When batch.bookings is empty, allBookings = [...allBookings, ...batch.bookings] doesn't increase the length of allBookings, causing the condition allBookings.length < totalCount to remain true forever.
The existing similar implementations in Download.tsx:70-78 have a safeguard:
if (!result) break;But BookingsCsvDownload.tsx lacks this protection. The impact is that users clicking the download button could have their browser freeze with an infinite loop making continuous API calls.
Recommendation: Add a break condition when the batch returns empty bookings:
while (allBookings.length < totalCount) {
const offset = allBookings.length;
const batch = await fetchBatch(offset);
if (batch.bookings.length === 0) break; // Prevent infinite loop
allBookings = [...allBookings, ...batch.bookings];
...
}Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DevinAI could you have a go at fixing this edge case?
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
…SV download Co-Authored-By: alex@cal.com <me@alexvanandel.com>
Udit-takkar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
emrysal
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved, it's got progress and i18n, all good to go in.
What does this PR do?
Adds a download bookings CSV button for organization users on the bookings page. The button fetches all bookings matching the current filters in batches and exports them as a CSV file.
Visual Demo
Image Demo:
Download button visible for org users:

Button hidden for non-org users:

Downloaded CSV:

Updates since last revision
t()function instead of hardcoded English strings (addresses Cubic AI review feedback)booking_uid,title,status,start_time,end_time,attendee_name,email,event_type,locationMandatory Tasks (DO NOT REMOVE)
How should this be tested?
Human Review Checklist
apps/web/public/static/locales/en/common.jsonLink to Devin run: https://app.devin.ai/sessions/29e729784b1f40518a404ed9c352ad78
Link to Devin run (infinite loop fix): https://app.devin.ai/sessions/68fa2f67f0db4b38bd0e01622caf635f
Requested by: alex@cal.com (@emrysal)