-
Notifications
You must be signed in to change notification settings - Fork 12k
Recurring event improvements #2750
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
Changes from all commits
28e7559
f8d6e22
cbf67d3
0a977ce
9a008db
624f42b
be14429
f5a6403
ad0957c
fe42380
2f370fb
b42ab5f
ce060f1
faf2f78
d1703f4
d19985d
e386911
e700bd8
052723a
c156235
4e3be33
e306f6a
da6c619
c2b5b51
b87ab98
0e2456e
36f6a99
22554d2
25e8266
c0e159a
acfe4a5
4e00ce7
2229332
ddddcb0
00bca27
f744093
499be42
827849b
c2894de
facdd39
ff020c0
305d43a
59754df
4398ca8
47c371b
d5389f5
f00012d
20117a9
5042c7c
47f0896
9c974f0
0a1fcf0
1b41c0c
9d15097
6c8cabf
37d4db6
e898329
a44554a
f187ede
2345740
6d065b0
abf8751
5b87d05
2226d88
0ef3c1a
1722e47
3ded649
ae0e60b
c5ce155
ba0685e
1095d52
56bee4b
44ed7ab
1cca638
f858677
547d944
0eb8c1c
fc0e552
bd2da91
de1eccc
d17c9cd
a79303a
a2e2e13
92e7769
b4ba27c
2131572
90694c8
fba41d0
bfd4984
b615135
2fa47ec
6377aee
4194b1e
9151037
b98362b
a73bef2
5d090bb
546eec7
eed2059
1a6d549
07f19a7
bf3bf97
e60aa9a
5098a44
cea572d
83961f8
30ccdd4
239597d
e2d74ac
ddbf7ca
334572c
f5336e3
5b727fb
720860e
185f0a9
b0ea666
f46389c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,7 @@ import { parseRecurringEvent } from "@calcom/lib"; | |
| import classNames from "@calcom/lib/classNames"; | ||
| import { useLocale } from "@calcom/lib/hooks/useLocale"; | ||
| import showToast from "@calcom/lib/notification"; | ||
| import { Frequency } from "@calcom/prisma/zod-utils"; | ||
| import { getEveryFreqFor } from "@calcom/lib/recurringStrings"; | ||
| import Button from "@calcom/ui/Button"; | ||
| import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader } from "@calcom/ui/Dialog"; | ||
| import { Tooltip } from "@calcom/ui/Tooltip"; | ||
|
|
@@ -63,9 +63,9 @@ function BookingListItem(booking: BookingItemProps) { | |
| }; | ||
| /** | ||
| * Only pass down the recurring event id when we need to confirm the entire series, which happens in | ||
| * the "Upcoming" tab, to support confirming discretionally in the "Recurring" tab. | ||
| * the "Recurring" tab, to support confirming discretionally in the "Recurring" tab. | ||
| */ | ||
| if (booking.listingStatus === "upcoming" && booking.recurringEventId !== null) { | ||
| if (booking.listingStatus === "recurring" && booking.recurringEventId !== null) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is now a behavior desired for the recurring tab, not upcoming |
||
| body = Object.assign({}, body, { recurringEventId: booking.recurringEventId }); | ||
| } | ||
| const res = await fetch("/api/book/confirm", { | ||
|
|
@@ -96,7 +96,7 @@ function BookingListItem(booking: BookingItemProps) { | |
| { | ||
| id: "reject", | ||
| label: | ||
| booking.listingStatus === "upcoming" && booking.recurringEventId !== null | ||
| booking.listingStatus === "recurring" && booking.recurringEventId !== null | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's extract this repeated condition to |
||
| ? t("reject_all") | ||
| : t("reject"), | ||
| onClick: () => { | ||
|
|
@@ -108,7 +108,7 @@ function BookingListItem(booking: BookingItemProps) { | |
| { | ||
| id: "confirm", | ||
| label: | ||
| booking.listingStatus === "upcoming" && booking.recurringEventId !== null | ||
| booking.listingStatus === "recurring" && booking.recurringEventId !== null | ||
| ? t("confirm_all") | ||
| : t("confirm"), | ||
| onClick: () => { | ||
|
|
@@ -120,10 +120,13 @@ function BookingListItem(booking: BookingItemProps) { | |
| }, | ||
| ]; | ||
|
|
||
| const bookedActions: ActionType[] = [ | ||
| let bookedActions: ActionType[] = [ | ||
| { | ||
| id: "cancel", | ||
| label: t("cancel"), | ||
| label: | ||
| booking.listingStatus === "recurring" && booking.recurringEventId !== null | ||
| ? t("cancel_all_remaining") | ||
| : t("cancel"), | ||
| href: `/cancel/${booking.uid}`, | ||
| icon: XIcon, | ||
| }, | ||
|
|
@@ -159,6 +162,10 @@ function BookingListItem(booking: BookingItemProps) { | |
| }, | ||
| ]; | ||
|
|
||
| if (booking.listingStatus === "recurring" && booking.recurringEventId !== null) { | ||
| bookedActions = bookedActions.filter((action) => action.id !== "edit_booking"); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In case we are dealing with a recurring booking, no edition available |
||
| } | ||
|
|
||
| const RequestSentMessage = () => { | ||
| return ( | ||
| <div className="ml-1 mr-8 flex text-gray-500" data-testid="request_reschedule_sent"> | ||
|
|
@@ -191,17 +198,24 @@ function BookingListItem(booking: BookingItemProps) { | |
| setLocationMutation.mutate({ bookingId: booking.id, newLocation }); | ||
| }; | ||
|
|
||
| // Calculate the booking date(s) | ||
| // Calculate the booking date(s) and setup recurring event data to show | ||
| let recurringStrings: string[] = []; | ||
| if (booking.recurringCount && booking.eventType.recurringEvent?.freq !== null) { | ||
| [recurringStrings] = parseRecurringDates( | ||
| let recurringDates: Date[] = []; | ||
| const today = new Date(); | ||
| if (booking.recurringCount && booking.eventType.recurringEvent?.freq !== undefined) { | ||
| [recurringStrings, recurringDates] = parseRecurringDates( | ||
| { | ||
| startDate: booking.startTime, | ||
| recurringEvent: parseRecurringEvent(booking.eventType.recurringEvent), | ||
| recurringCount: booking.recurringCount, | ||
| }, | ||
| i18n | ||
| ); | ||
| if (booking.status === BookingStatus.PENDING) { | ||
| // Only take into consideration next up instances if booking is confirmed | ||
| recurringDates = recurringDates.filter((aDate) => aDate >= today); | ||
| recurringStrings = recurringDates.map((_, key) => recurringStrings[key]); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is to support the "X remaining events" copy in confirmed recurring events showing in the recurring tab |
||
| } | ||
| } | ||
|
|
||
| let location = booking.location || ""; | ||
|
|
@@ -285,9 +299,7 @@ function BookingListItem(booking: BookingItemProps) { | |
| </Dialog> | ||
|
|
||
| <tr className="flex hover:bg-neutral-50"> | ||
| <td | ||
| className="hidden whitespace-nowrap align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:w-56" | ||
| onClick={onClick}> | ||
| <td className="hidden align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:w-64" onClick={onClick}> | ||
| <div className="cursor-pointer py-4"> | ||
| <div className="text-sm leading-6 text-gray-900">{startTime}</div> | ||
| <div className="text-sm text-gray-500"> | ||
|
|
@@ -297,24 +309,27 @@ function BookingListItem(booking: BookingItemProps) { | |
| <div className="text-sm text-gray-400"> | ||
| {booking.recurringCount && | ||
| booking.eventType?.recurringEvent?.freq && | ||
| booking.listingStatus === "upcoming" && ( | ||
| (booking.listingStatus === "recurring" || booking.listingStatus === "cancelled") && ( | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We want to show recurring information both in recurring and cancelled tabs |
||
| <div className="underline decoration-gray-400 decoration-dashed underline-offset-2"> | ||
| <div className="flex"> | ||
| <Tooltip | ||
| content={recurringStrings.map((aDate, key) => ( | ||
| <p key={key}>{aDate}</p> | ||
| ))}> | ||
| <p className="text-gray-600 dark:text-white"> | ||
| <RefreshIcon className="mr-1 -mt-1 inline-block h-4 w-4 text-gray-400" /> | ||
| {`${t("every_for_freq", { | ||
| freq: t( | ||
| `${Frequency[booking.eventType.recurringEvent.freq].toString().toLowerCase()}` | ||
| ), | ||
| })} ${booking.recurringCount} ${t( | ||
| `${Frequency[booking.eventType.recurringEvent.freq].toString().toLowerCase()}`, | ||
| { count: booking.recurringCount } | ||
| )}`} | ||
| </p> | ||
| <div className="text-gray-600 dark:text-white"> | ||
| <RefreshIcon className="float-left mr-1 mt-[2px] inline-block h-4 w-4 text-gray-400" /> | ||
| <p className="pl-[21px]"> | ||
| {booking.status === BookingStatus.ACCEPTED | ||
| ? `${t("event_remaining", { | ||
| count: recurringDates.length, | ||
| })}` | ||
| : getEveryFreqFor({ | ||
| t, | ||
| recurringEvent: booking.eventType.recurringEvent, | ||
| recurringCount: booking.recurringCount, | ||
| })} | ||
| </p> | ||
| </div> | ||
| </Tooltip> | ||
| </div> | ||
| </div> | ||
|
|
||
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.
A repeated string for recurring events was refactored into its own util