From 68568e5a250fcc4cbf27515e3ea437cd54a5593d Mon Sep 17 00:00:00 2001 From: Amit Sharma <74371312+Amit91848@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:06:11 +0530 Subject: [PATCH] feat: round robin: show avatar and name of person on success page (#14245) * feat: round robin: show avatar and name of person on success page * fix: add background border * fix: e2e tests * fix: remove avatar on select, use proper border variables * fix: bookings-list e2e round robin title * chore: change name --------- Co-authored-by: Peer Richelsen Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: Udit Takkar --- apps/web/lib/booking.ts | 1 + .../bookings/views/bookings-single-view.tsx | 61 ++++++++++++------- .../playwright/organization/booking.e2e.ts | 21 +++++-- apps/web/playwright/teams.e2e.ts | 9 ++- apps/web/public/static/locales/en/common.json | 2 + packages/config/tailwind-preset.js | 2 + packages/features/auth/SAMLLogin.tsx | 2 +- .../OverlayCalendarSettingsModal.tsx | 1 - .../features/bookings/lib/getUserBooking.ts | 2 + .../components/heading/SchedulerHeading.tsx | 2 +- .../ee/dsync/components/DirectoryInfo.tsx | 1 - .../pages/components/MemberListItem.tsx | 8 +-- .../components/ChildrenEventTypeSelect.tsx | 2 +- .../insights/filters/Download/index.tsx | 2 +- .../schedules/components/DateOverrideList.tsx | 2 +- .../components/AvailabilityEditSheet.tsx | 6 +- .../components/AvailabilitySliderTable.tsx | 2 +- .../components/TroubleshooterHeader.tsx | 2 +- .../components/WebhookTestDisclosure.tsx | 2 +- .../availability/AvailabilitySettings.tsx | 11 +--- 20 files changed, 82 insertions(+), 59 deletions(-) diff --git a/apps/web/lib/booking.ts b/apps/web/lib/booking.ts index 8a73958603..6447a260eb 100644 --- a/apps/web/lib/booking.ts +++ b/apps/web/lib/booking.ts @@ -72,6 +72,7 @@ export const getEventTypesFromDB = async (id: number) => { seatsPerTimeSlot: true, seatsShowAttendees: true, seatsShowAvailabilityCount: true, + schedulingType: true, periodStartDate: true, periodEndDate: true, }, diff --git a/apps/web/modules/bookings/views/bookings-single-view.tsx b/apps/web/modules/bookings/views/bookings-single-view.tsx index 3d1367bb02..606a649b79 100644 --- a/apps/web/modules/bookings/views/bookings-single-view.tsx +++ b/apps/web/modules/bookings/views/bookings-single-view.tsx @@ -44,11 +44,12 @@ import useTheme from "@calcom/lib/hooks/useTheme"; import { getEveryFreqFor } from "@calcom/lib/recurringStrings"; import { getIs24hClockFromLocalStorage, isBrowserLocale24h } from "@calcom/lib/timeFormat"; import { localStorage } from "@calcom/lib/webstorage"; -import { BookingStatus } from "@calcom/prisma/enums"; +import { BookingStatus, SchedulingType } from "@calcom/prisma/enums"; import { bookingMetadataSchema } from "@calcom/prisma/zod-utils"; import { trpc } from "@calcom/trpc/react"; import { Alert, + Avatar, Badge, Button, EmailInput, @@ -225,6 +226,7 @@ export default function Success(props: PageProps) { const giphyAppData = getEventTypeAppData(eventType, "giphy"); const giphyImage = giphyAppData?.thankYouPage; + const isRoundRobin = eventType.schedulingType === SchedulingType.ROUND_ROBIN; const eventName = getEventName(eventNameObject, true); // Confirmation can be needed in two cases as of now @@ -294,6 +296,7 @@ export default function Success(props: PageProps) { function getTitle(): string { const titleSuffix = props.recurringBookings ? "_recurring" : ""; + const titlePrefix = isRoundRobin ? "round_robin_" : ""; if (isCancelled) { return ""; } @@ -305,6 +308,11 @@ export default function Success(props: PageProps) { } return t(`needs_to_be_confirmed_or_rejected${titleSuffix}`); } + if (bookingInfo.user) { + return t(`${titlePrefix}emailed_you_and_attendees${titleSuffix}`, { + user: bookingInfo.user.name || bookingInfo.user.email, + }); + } return t(`emailed_you_and_attendees${titleSuffix}`); } @@ -396,27 +404,36 @@ export default function Success(props: PageProps) { {!isFeedbackMode && ( <>
- {giphyImage && !needsConfirmation && !isCancelled && ( - // eslint-disable-next-line @next/next/no-img-element - Gif from Giphy + className={classNames(isRoundRobin && "min-w-32 min-h-24 relative mx-auto h-24 w-32")}> + {isRoundRobin && bookingInfo.user && ( + )} - {!giphyImage && !needsConfirmation && !isCancelled && ( - - )} - {needsConfirmation && !isCancelled && ( - - )} - {isCancelled && } +
+ {giphyImage && !needsConfirmation && !isCancelled && ( + // eslint-disable-next-line @next/next/no-img-element + Gif from Giphy + )} + {!giphyImage && !needsConfirmation && !isCancelled && ( + + )} + {needsConfirmation && !isCancelled && ( + + )} + {isCancelled && } +

{t("what")}

- {eventName} + {isRoundRobin ? bookingInfo.title : eventName}
{t("when")}
diff --git a/apps/web/playwright/organization/booking.e2e.ts b/apps/web/playwright/organization/booking.e2e.ts index 68c3410cc0..4c0cc0d2e3 100644 --- a/apps/web/playwright/organization/booking.e2e.ts +++ b/apps/web/playwright/organization/booking.e2e.ts @@ -103,7 +103,7 @@ test.describe("Bookings", () => { page, }, async () => { - await bookTeamEvent({ page, team, event: teamEvent }); + await bookTeamEvent({ page, team, event: teamEvent, teamMatesObj }); // Since all the users have the same leastRecentlyBooked value // Anyone of the teammates could be the Host of the booking. @@ -421,13 +421,15 @@ async function bookTeamEvent({ page, team, event, + teamMatesObj, }: { page: Page; team: { slug: string | null; name: string | null; }; - event: { slug: string; title: string }; + event: { slug: string; title: string; schedulingType: SchedulingType | null }; + teamMatesObj?: { name: string }[]; }) { // Note that even though the default way to access a team booking in an organization is to not use /team in the URL, but it isn't testable with playwright as the rewrite is taken care of by Next.js config which can't handle on the fly org slug's handling // So, we are using /team in the URL to access the team booking @@ -440,8 +442,19 @@ async function bookTeamEvent({ await expect(page.getByTestId("success-page")).toBeVisible(); // The title of the booking - const BookingTitle = `${event.title} between ${team.name} and ${testName}`; - await expect(page.getByTestId("booking-title")).toHaveText(BookingTitle); + if (event.schedulingType === SchedulingType.ROUND_ROBIN) { + const bookingTitle = await page.getByTestId("booking-title").textContent(); + + expect( + teamMatesObj?.some((teamMate) => { + const BookingTitle = `${event.title} between ${teamMate.name} and ${testName}`; + return BookingTitle === bookingTitle; + }) + ).toBe(true); + } else { + const BookingTitle = `${event.title} between ${team.name} and ${testName}`; + await expect(page.getByTestId("booking-title")).toHaveText(BookingTitle); + } // The booker should be in the attendee list await expect(page.getByTestId(`attendee-name-${testName}`)).toHaveText(testName); } diff --git a/apps/web/playwright/teams.e2e.ts b/apps/web/playwright/teams.e2e.ts index ee310d762b..f9b6558c96 100644 --- a/apps/web/playwright/teams.e2e.ts +++ b/apps/web/playwright/teams.e2e.ts @@ -147,8 +147,13 @@ testBothFutureAndLegacyRoutes.describe("Teams - NonOrg", (routeVariant) => { await expect(page.locator(`[data-testid="attendee-name-${testName}"]`)).toHaveText(testName); // The title of the booking - const BookingTitle = `${teamEventTitle} between ${team.name} and ${testName}`; - await expect(page.locator("[data-testid=booking-title]")).toHaveText(BookingTitle); + const bookingTitle = await page.getByTestId("booking-title").textContent(); + expect( + teamMatesObj?.some((teamMate) => { + const BookingTitle = `${teamEventTitle} between ${teamMate.name} and ${testName}`; + return BookingTitle === bookingTitle; + }) + ).toBe(true); // Since all the users have the same leastRecentlyBooked value // Anyone of the teammates could be the Host of the booking. diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 25280e65cd..22d94f0951 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -326,8 +326,10 @@ "add_another_calendar": "Add another calendar", "other": "Other", "email_sign_in_subject": "Your sign-in link for {{appName}}", + "round_robin_emailed_you_and_attendees": "You are meeting with {{user}}. We sent an email with a calendar invitation with the details to everyone.", "emailed_you_and_attendees": "We sent an email with a calendar invitation with the details to everyone.", "emailed_you_and_attendees_recurring": "We sent an email with a calendar invitation with the details to everyone for the first of these recurring events.", + "round_robin_emailed_you_and_attendees_recurring": "You are meeting with {{user}}.We sent an email with a calendar invitation with the details to everyone for the first of these recurring events.", "emailed_you_and_any_other_attendees": "We sent an email to everyone with this information.", "needs_to_be_confirmed_or_rejected": "Your booking still needs to be confirmed or rejected.", "needs_to_be_confirmed_or_rejected_recurring": "Your recurring meeting still needs to be confirmed or rejected.", diff --git a/packages/config/tailwind-preset.js b/packages/config/tailwind-preset.js index c186db13df..b5ca2bbbf6 100644 --- a/packages/config/tailwind-preset.js +++ b/packages/config/tailwind-preset.js @@ -67,6 +67,8 @@ module.exports = { booker: `var(--cal-border-booker, ${subtleColor})`, error: "var(--cal-border-error, #AA2E26)", focus: "var(--cal-border-focus, #1A1A1A)", + "cal-bg": "var(--cal-bg, white)", + "cal-bg-muted": "var(--cal-bg-muted)", }, textColor: { emphasis: "var(--cal-text-emphasis, #111827)", diff --git a/packages/features/auth/SAMLLogin.tsx b/packages/features/auth/SAMLLogin.tsx index b0d9973d5f..2c74571f4f 100644 --- a/packages/features/auth/SAMLLogin.tsx +++ b/packages/features/auth/SAMLLogin.tsx @@ -6,7 +6,7 @@ import z from "zod"; import { HOSTED_CAL_FEATURES } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { trpc } from "@calcom/trpc/react"; -import { Button, Icon } from "@calcom/ui"; +import { Button } from "@calcom/ui"; interface Props { samlTenantID: string; diff --git a/packages/features/bookings/Booker/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx b/packages/features/bookings/Booker/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx index ab4eeaef6f..642af0dac3 100644 --- a/packages/features/bookings/Booker/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx +++ b/packages/features/bookings/Booker/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx @@ -9,7 +9,6 @@ import { DialogClose, DialogContent, EmptyScreen, - Icon, ListItem, ListItemText, ListItemTitle, diff --git a/packages/features/bookings/lib/getUserBooking.ts b/packages/features/bookings/lib/getUserBooking.ts index 7aaab4fc40..0f78882b97 100644 --- a/packages/features/bookings/lib/getUserBooking.ts +++ b/packages/features/bookings/lib/getUserBooking.ts @@ -29,6 +29,7 @@ const getUserBooking = async (uid: string) => { email: true, username: true, timeZone: true, + avatarUrl: true, }, }, attendees: { @@ -44,6 +45,7 @@ const getUserBooking = async (uid: string) => { eventName: true, slug: true, timeZone: true, + schedulingType: true, }, }, seatsReferences: { diff --git a/packages/features/calendars/weeklyview/components/heading/SchedulerHeading.tsx b/packages/features/calendars/weeklyview/components/heading/SchedulerHeading.tsx index 4ff86c79fe..17832275cc 100644 --- a/packages/features/calendars/weeklyview/components/heading/SchedulerHeading.tsx +++ b/packages/features/calendars/weeklyview/components/heading/SchedulerHeading.tsx @@ -1,5 +1,5 @@ import dayjs from "@calcom/dayjs"; -import { Button, ButtonGroup, Icon } from "@calcom/ui"; +import { Button, ButtonGroup } from "@calcom/ui"; import { useCalendarStore } from "../../state/store"; diff --git a/packages/features/ee/dsync/components/DirectoryInfo.tsx b/packages/features/ee/dsync/components/DirectoryInfo.tsx index 43f47653a3..005cbc412b 100644 --- a/packages/features/ee/dsync/components/DirectoryInfo.tsx +++ b/packages/features/ee/dsync/components/DirectoryInfo.tsx @@ -2,7 +2,6 @@ import type { Directory } from "@boxyhq/saml-jackson"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Button, showToast, Label, Tooltip } from "@calcom/ui"; -import { Icon } from "@calcom/ui"; const DirectoryInfo = ({ directory }: { directory: Directory }) => { const { t } = useLocale(); diff --git a/packages/features/ee/organizations/pages/components/MemberListItem.tsx b/packages/features/ee/organizations/pages/components/MemberListItem.tsx index f48e62fa64..94158465be 100644 --- a/packages/features/ee/organizations/pages/components/MemberListItem.tsx +++ b/packages/features/ee/organizations/pages/components/MemberListItem.tsx @@ -11,7 +11,6 @@ import { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, - Icon, Tooltip, UserAvatar, } from "@calcom/ui"; @@ -82,12 +81,7 @@ export default function MemberListItem(props: Props) {
- } diff --git a/packages/features/timezone-buddy/components/AvailabilitySliderTable.tsx b/packages/features/timezone-buddy/components/AvailabilitySliderTable.tsx index 97bf068eac..2e5b04e6bd 100644 --- a/packages/features/timezone-buddy/components/AvailabilitySliderTable.tsx +++ b/packages/features/timezone-buddy/components/AvailabilitySliderTable.tsx @@ -9,7 +9,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { MembershipRole } from "@calcom/prisma/enums"; import { trpc } from "@calcom/trpc"; import type { UserProfile } from "@calcom/types/UserProfile"; -import { Button, ButtonGroup, DataTable, Icon, UserAvatar } from "@calcom/ui"; +import { Button, ButtonGroup, DataTable, UserAvatar } from "@calcom/ui"; import { UpgradeTip } from "../../tips/UpgradeTip"; import { createTimezoneBuddyStore, TBContext } from "../store"; diff --git a/packages/features/troubleshooter/components/TroubleshooterHeader.tsx b/packages/features/troubleshooter/components/TroubleshooterHeader.tsx index 063f74cbe9..a781f0495e 100644 --- a/packages/features/troubleshooter/components/TroubleshooterHeader.tsx +++ b/packages/features/troubleshooter/components/TroubleshooterHeader.tsx @@ -2,7 +2,7 @@ import { useMemo } from "react"; import dayjs from "@calcom/dayjs"; import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Button, ButtonGroup, Icon } from "@calcom/ui"; +import { Button, ButtonGroup } from "@calcom/ui"; import { useTroubleshooterStore } from "../store"; diff --git a/packages/features/webhooks/components/WebhookTestDisclosure.tsx b/packages/features/webhooks/components/WebhookTestDisclosure.tsx index e8b448a969..5bf6d048d0 100644 --- a/packages/features/webhooks/components/WebhookTestDisclosure.tsx +++ b/packages/features/webhooks/components/WebhookTestDisclosure.tsx @@ -4,7 +4,7 @@ import { ZodError } from "zod"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { trpc } from "@calcom/trpc/react"; import { ZTestTriggerInputSchema } from "@calcom/trpc/server/routers/viewer/webhook/testTrigger.schema"; -import { Badge, Button, Icon, showToast } from "@calcom/ui"; +import { Badge, Button, showToast } from "@calcom/ui"; export default function WebhookTestDisclosure() { const [subscriberUrl, webhookSecret]: [string, string] = useWatch({ name: ["subscriberUrl", "secret"] }); diff --git a/packages/platform/atoms/availability/AvailabilitySettings.tsx b/packages/platform/atoms/availability/AvailabilitySettings.tsx index 1cacbd026e..142a36257f 100644 --- a/packages/platform/atoms/availability/AvailabilitySettings.tsx +++ b/packages/platform/atoms/availability/AvailabilitySettings.tsx @@ -183,10 +183,7 @@ const DateOverride = ({ onChange={(ranges) => ranges.forEach((range) => append({ ranges: [range] }))} userTimeFormat={userTimeFormat} Trigger={ - } @@ -330,11 +327,7 @@ export function AvailabilitySettings({ openSidebar ? "translate-x-0 opacity-100" : "translate-x-full opacity-0" )}>
-