From 93640552837a0b3fd96cd087b09b29bb9f514f2d Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Wed, 25 Oct 2023 21:26:22 +0400 Subject: [PATCH 1/7] fix: typefix for webhook and rename oldBookingid to rescheduleId (#12084) * add rescheduleId to type * update oldBookingId to rescheduleId * Remove old remnant --- packages/features/bookings/lib/handleNewBooking.ts | 3 ++- packages/features/webhooks/lib/sendPayload.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/features/bookings/lib/handleNewBooking.ts b/packages/features/bookings/lib/handleNewBooking.ts index fa810f1bf8..3488442086 100644 --- a/packages/features/bookings/lib/handleNewBooking.ts +++ b/packages/features/bookings/lib/handleNewBooking.ts @@ -1851,6 +1851,7 @@ async function handler( ...eventTypeInfo, uid: resultBooking?.uid || uid, bookingId: booking?.id, + rescheduleId: originalRescheduledBooking?.id || undefined, rescheduleUid, rescheduleStartTime: originalRescheduledBooking?.startTime ? dayjs(originalRescheduledBooking?.startTime).utc().format() @@ -2377,8 +2378,8 @@ async function handler( ...evt, ...eventTypeInfo, bookingId: booking?.id, + rescheduleId: originalRescheduledBooking?.id || undefined, rescheduleUid, - oldBookingId: originalRescheduledBooking?.id || undefined, rescheduleStartTime: originalRescheduledBooking?.startTime ? dayjs(originalRescheduledBooking?.startTime).utc().format() : undefined, diff --git a/packages/features/webhooks/lib/sendPayload.ts b/packages/features/webhooks/lib/sendPayload.ts index e0211a6a71..7ff22d9577 100644 --- a/packages/features/webhooks/lib/sendPayload.ts +++ b/packages/features/webhooks/lib/sendPayload.ts @@ -22,6 +22,7 @@ export type WebhookDataType = CalendarEvent & bookingId?: number; status?: string; smsReminderNumber?: string; + rescheduleId?: number; rescheduleUid?: string; rescheduleStartTime?: string; rescheduleEndTime?: string; From 0fb75b715dabc337d12fc603a293d51f1f10129b Mon Sep 17 00:00:00 2001 From: Aldrin <53973174+Dhoni77@users.noreply.github.com> Date: Wed, 25 Oct 2023 22:59:41 +0530 Subject: [PATCH 2/7] fix: event type invalidation (#12077) --- .../features/eventtypes/components/CreateEventTypeDialog.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/features/eventtypes/components/CreateEventTypeDialog.tsx b/packages/features/eventtypes/components/CreateEventTypeDialog.tsx index 7032079c13..6fd6483d65 100644 --- a/packages/features/eventtypes/components/CreateEventTypeDialog.tsx +++ b/packages/features/eventtypes/components/CreateEventTypeDialog.tsx @@ -79,6 +79,7 @@ export default function CreateEventTypeDialog({ membershipRole: MembershipRole | null | undefined; }[]; }) { + const utils = trpc.useContext(); const { t } = useLocale(); const router = useRouter(); const [firstRender, setFirstRender] = useState(true); @@ -116,6 +117,7 @@ export default function CreateEventTypeDialog({ const createMutation = trpc.viewer.eventTypes.create.useMutation({ onSuccess: async ({ eventType }) => { + await utils.viewer.eventTypes.getByViewer.invalidate(); await router.replace(`/event-types/${eventType.id}`); showToast( t("event_type_created_successfully", { From 1c65f5c150a964da4d32106dd77bbbf21e96fa65 Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Wed, 25 Oct 2023 19:00:14 +0100 Subject: [PATCH 3/7] v3.4.4 --- apps/web/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/package.json b/apps/web/package.json index 829f47e542..429b56feb3 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@calcom/web", - "version": "3.4.3", + "version": "3.4.4", "private": true, "scripts": { "analyze": "ANALYZE=true next build", From f9ad99e5728e317739c0b744696f6925c0b0ed75 Mon Sep 17 00:00:00 2001 From: Siddharth Movaliya Date: Wed, 25 Oct 2023 23:46:01 +0530 Subject: [PATCH 4/7] feat: Lock timezone on booking page (#11891) Co-authored-by: CarinaWolli --- .../components/eventtype/EventAdvancedTab.tsx | 17 ++++++++ apps/web/pages/[user].tsx | 1 + apps/web/pages/event-types/[type]/index.tsx | 1 + apps/web/public/static/locales/en/common.json | 2 + .../test/lib/handleChildrenEventTypes.test.ts | 41 +++++++++++++------ .../bookings/Booker/components/EventMeta.tsx | 7 +++- .../features/bookings/lib/handleNewBooking.ts | 2 + .../features/eventtypes/lib/getPublicEvent.ts | 1 + packages/lib/defaultEvents.ts | 1 + packages/lib/getEventTypeById.ts | 1 + packages/lib/test/builder.ts | 1 + .../migration.sql | 2 + packages/prisma/schema.prisma | 1 + packages/prisma/selects/event-types.ts | 2 + 14 files changed, 67 insertions(+), 13 deletions(-) create mode 100644 packages/prisma/migrations/20231020090443_add_lock_timezone_toggle/migration.sql diff --git a/apps/web/components/eventtype/EventAdvancedTab.tsx b/apps/web/components/eventtype/EventAdvancedTab.tsx index 563250a671..6ddba9b78b 100644 --- a/apps/web/components/eventtype/EventAdvancedTab.tsx +++ b/apps/web/components/eventtype/EventAdvancedTab.tsx @@ -433,6 +433,23 @@ export const EventAdvancedTab = ({ eventType, team }: Pick )} /> + ( + onChange(e)} + /> + )} + /> {allowDisablingAttendeeConfirmationEmails(workflows) && ( <> { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line - const { schedulingType, id, teamId, timeZone, users, requiresBookerEmailVerification, ...evType } = - mockFindFirstEventType({ - id: 123, - metadata: { managedEventConfig: {} }, - locations: [], - }); + const { + schedulingType, + id, + teamId, + timeZone, + requiresBookerEmailVerification, + lockTimeZoneToggleOnBookingPage, + ...evType + } = mockFindFirstEventType({ + id: 123, + metadata: { managedEventConfig: {} }, + locations: [], + }); const result = await updateChildrenEventTypes({ eventTypeId: 1, oldEventType: { children: [], team: { name: "" } }, @@ -145,6 +152,7 @@ describe("handleChildrenEventTypes", () => { userId, scheduleId, requiresBookerEmailVerification, + lockTimeZoneToggleOnBookingPage, ...evType } = mockFindFirstEventType({ metadata: { managedEventConfig: {} }, @@ -230,12 +238,19 @@ describe("handleChildrenEventTypes", () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line - const { schedulingType, id, teamId, timeZone, users, requiresBookerEmailVerification, ...evType } = - mockFindFirstEventType({ - id: 123, - metadata: { managedEventConfig: {} }, - locations: [], - }); + const { + schedulingType, + id, + teamId, + timeZone, + requiresBookerEmailVerification, + lockTimeZoneToggleOnBookingPage, + ...evType + } = mockFindFirstEventType({ + id: 123, + metadata: { managedEventConfig: {} }, + locations: [], + }); prismaMock.eventType.deleteMany.mockResolvedValue([123] as unknown as Prisma.BatchPayload); const result = await updateChildrenEventTypes({ eventTypeId: 1, @@ -277,6 +292,7 @@ describe("handleChildrenEventTypes", () => { parentId, userId, requiresBookerEmailVerification, + lockTimeZoneToggleOnBookingPage, ...evType } = mockFindFirstEventType({ metadata: { managedEventConfig: {} }, @@ -327,6 +343,7 @@ describe("handleChildrenEventTypes", () => { userId: _userId, // eslint-disable-next-line @typescript-eslint/no-unused-vars requiresBookerEmailVerification, + lockTimeZoneToggleOnBookingPage, ...evType } = mockFindFirstEventType({ metadata: { managedEventConfig: {} }, diff --git a/packages/features/bookings/Booker/components/EventMeta.tsx b/packages/features/bookings/Booker/components/EventMeta.tsx index 83bcfc6312..f282e48d5e 100644 --- a/packages/features/bookings/Booker/components/EventMeta.tsx +++ b/packages/features/bookings/Booker/components/EventMeta.tsx @@ -105,6 +105,7 @@ export const EventMeta = () => { )} + { {bookerState === "booking" ? ( <>{timezone} ) : ( - + { }} value={timezone} onChange={(tz) => setTimezone(tz.value)} + isDisabled={event.lockTimeZoneToggleOnBookingPage} /> )} diff --git a/packages/features/bookings/lib/handleNewBooking.ts b/packages/features/bookings/lib/handleNewBooking.ts index 3488442086..997b318bf4 100644 --- a/packages/features/bookings/lib/handleNewBooking.ts +++ b/packages/features/bookings/lib/handleNewBooking.ts @@ -276,6 +276,7 @@ const getEventTypesFromDB = async (eventTypeId: number) => { periodEndDate: true, periodDays: true, periodCountCalendarDays: true, + lockTimeZoneToggleOnBookingPage: true, requiresConfirmation: true, requiresBookerEmailVerification: true, userId: true, @@ -2686,6 +2687,7 @@ const findBookingQuery = async (bookingId: number) => { description: true, currency: true, length: true, + lockTimeZoneToggleOnBookingPage: true, requiresConfirmation: true, requiresBookerEmailVerification: true, price: true, diff --git a/packages/features/eventtypes/lib/getPublicEvent.ts b/packages/features/eventtypes/lib/getPublicEvent.ts index 3b6d8f704f..85bab2e26f 100644 --- a/packages/features/eventtypes/lib/getPublicEvent.ts +++ b/packages/features/eventtypes/lib/getPublicEvent.ts @@ -33,6 +33,7 @@ const publicEventSelect = Prisma.validator()({ customInputs: true, disableGuests: true, metadata: true, + lockTimeZoneToggleOnBookingPage: true, requiresConfirmation: true, requiresBookerEmailVerification: true, recurringEvent: true, diff --git a/packages/lib/defaultEvents.ts b/packages/lib/defaultEvents.ts index 5aba14feaa..5243b63ebd 100644 --- a/packages/lib/defaultEvents.ts +++ b/packages/lib/defaultEvents.ts @@ -86,6 +86,7 @@ const commons = { recurringEvent: null, destinationCalendar: null, team: null, + lockTimeZoneToggleOnBookingPage: false, requiresConfirmation: false, requiresBookerEmailVerification: false, bookingLimits: null, diff --git a/packages/lib/getEventTypeById.ts b/packages/lib/getEventTypeById.ts index 7ce86719fd..be26508d9f 100644 --- a/packages/lib/getEventTypeById.ts +++ b/packages/lib/getEventTypeById.ts @@ -89,6 +89,7 @@ export default async function getEventTypeById({ periodStartDate: true, periodEndDate: true, periodCountCalendarDays: true, + lockTimeZoneToggleOnBookingPage: true, requiresConfirmation: true, requiresBookerEmailVerification: true, recurringEvent: true, diff --git a/packages/lib/test/builder.ts b/packages/lib/test/builder.ts index 7769023a59..bd9e9fc516 100644 --- a/packages/lib/test/builder.ts +++ b/packages/lib/test/builder.ts @@ -85,6 +85,7 @@ export const buildEventType = (eventType?: Partial): EventType => { periodDays: null, periodCountCalendarDays: null, recurringEvent: null, + lockTimeZoneToggleOnBookingPage: false, requiresConfirmation: false, disableGuests: false, hideCalendarNotes: false, diff --git a/packages/prisma/migrations/20231020090443_add_lock_timezone_toggle/migration.sql b/packages/prisma/migrations/20231020090443_add_lock_timezone_toggle/migration.sql new file mode 100644 index 0000000000..c97b6146c5 --- /dev/null +++ b/packages/prisma/migrations/20231020090443_add_lock_timezone_toggle/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "EventType" ADD COLUMN "lockTimeZoneToggleOnBookingPage" BOOLEAN NOT NULL DEFAULT false; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 7eee884084..6356442fa9 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -86,6 +86,7 @@ model EventType { periodEndDate DateTime? periodDays Int? periodCountCalendarDays Boolean? + lockTimeZoneToggleOnBookingPage Boolean @default(false) requiresConfirmation Boolean @default(false) requiresBookerEmailVerification Boolean @default(false) /// @zod.custom(imports.recurringEventType) diff --git a/packages/prisma/selects/event-types.ts b/packages/prisma/selects/event-types.ts index c47e148dde..35733ede28 100644 --- a/packages/prisma/selects/event-types.ts +++ b/packages/prisma/selects/event-types.ts @@ -11,6 +11,7 @@ export const baseEventTypeSelect = Prisma.validator()({ hidden: true, price: true, currency: true, + lockTimeZoneToggleOnBookingPage: true, requiresConfirmation: true, requiresBookerEmailVerification: true, }); @@ -28,6 +29,7 @@ export const bookEventTypeSelect = Prisma.validator()({ periodStartDate: true, periodEndDate: true, recurringEvent: true, + lockTimeZoneToggleOnBookingPage: true, requiresConfirmation: true, requiresBookerEmailVerification: true, metadata: true, From 158da51a5d9b3de3dcaa7210f1a77f495515ad06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20L=C3=B3pez?= Date: Wed, 25 Oct 2023 12:33:22 -0700 Subject: [PATCH 5/7] fix: embed rewrites post dotted usernames (#12087) --- apps/web/next.config.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 22da1946e5..dc4cbdafa2 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -226,6 +226,14 @@ const nextConfig = { }, async rewrites() { const beforeFiles = [ + { + /** + * Needed due to the introduction of dotted usernames + * @see https://github.com/calcom/cal.com/pull/11706 + */ + source: "/embed.js", + destination: "/embed/embed.js", + }, { source: "/login", destination: "/auth/login", From 139a7c8249b82fe86f92d9a1bf2c27f26ee59516 Mon Sep 17 00:00:00 2001 From: DmytroHryshyn <125881252+DmytroHryshyn@users.noreply.github.com> Date: Wed, 25 Oct 2023 23:58:08 +0300 Subject: [PATCH 6/7] chore: [app dir bootstrapping 5] add RootLayout (#11982) Co-authored-by: zomars Co-authored-by: Greg Pabian <35925521+grzpab@users.noreply.github.com> --- ...honenumber-js-npm-1.10.12-51c84f8bf1.patch | 15 + apps/web/app/layout.tsx | 109 +++++++ apps/web/components/PageWrapperAppDir.tsx | 88 ++++++ apps/web/lib/app-providers-app-dir.tsx | 291 ++++++++++++++++++ package.json | 3 +- yarn.lock | 15 +- 6 files changed, 516 insertions(+), 5 deletions(-) create mode 100644 .yarn/patches/libphonenumber-js-npm-1.10.12-51c84f8bf1.patch create mode 100644 apps/web/app/layout.tsx create mode 100644 apps/web/components/PageWrapperAppDir.tsx create mode 100644 apps/web/lib/app-providers-app-dir.tsx diff --git a/.yarn/patches/libphonenumber-js-npm-1.10.12-51c84f8bf1.patch b/.yarn/patches/libphonenumber-js-npm-1.10.12-51c84f8bf1.patch new file mode 100644 index 0000000000..7cfa242404 --- /dev/null +++ b/.yarn/patches/libphonenumber-js-npm-1.10.12-51c84f8bf1.patch @@ -0,0 +1,15 @@ +diff --git a/index.cjs b/index.cjs +index b645707a3549fc298508726e404243499bbed499..f34b0891e99b275a9218e253f303f43d31ef3f73 100644 +--- a/index.cjs ++++ b/index.cjs +@@ -13,8 +13,8 @@ function withMetadataArgument(func, _arguments) { + // https://github.com/babel/babel/issues/2212#issuecomment-131827986 + // An alternative approach: + // https://www.npmjs.com/package/babel-plugin-add-module-exports +-exports = module.exports = min.parsePhoneNumberFromString +-exports['default'] = min.parsePhoneNumberFromString ++// exports = module.exports = min.parsePhoneNumberFromString ++// exports['default'] = min.parsePhoneNumberFromString + + // `parsePhoneNumberFromString()` named export is now considered legacy: + // it has been promoted to a default export due to being too verbose. diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx new file mode 100644 index 0000000000..23d224b6e1 --- /dev/null +++ b/apps/web/app/layout.tsx @@ -0,0 +1,109 @@ +import type { Metadata } from "next"; +import { headers as nextHeaders, cookies as nextCookies } from "next/headers"; +import Script from "next/script"; +import React from "react"; + +import { getLocale } from "@calcom/features/auth/lib/getLocale"; +import { IS_PRODUCTION } from "@calcom/lib/constants"; + +import "../styles/globals.css"; + +export const metadata: Metadata = { + icons: { + icon: [ + { + sizes: "32x32", + url: "/api/logo?type=favicon-32", + }, + { + sizes: "16x16", + url: "/api/logo?type=favicon-16", + }, + ], + apple: { + sizes: "180x180", + url: "/api/logo?type=apple-touch-icon", + }, + other: [ + { + url: "/safari-pinned-tab.svg", + rel: "mask-icon", + }, + ], + }, + manifest: "/site.webmanifest", + themeColor: [ + { media: "(prefers-color-scheme: light)", color: "#f9fafb" }, + { media: "(prefers-color-scheme: dark)", color: "#1C1C1C" }, + ], + other: { + "msapplication-TileColor": "#000000", + }, +}; + +const getInitialProps = async ( + url: string, + headers: ReturnType, + cookies: ReturnType +) => { + const { pathname, searchParams } = new URL(url); + + const isEmbed = pathname.endsWith("/embed") || (searchParams?.get("embedType") ?? null) !== null; + const embedColorScheme = searchParams?.get("ui.color-scheme"); + + // @ts-expect-error we cannot access ctx.req in app dir, however headers and cookies are only properties needed to extract the locale + const newLocale = await getLocale({ headers, cookies }); + let direction = "ltr"; + + try { + const intlLocale = new Intl.Locale(newLocale); + // @ts-expect-error INFO: Typescript does not know about the Intl.Locale textInfo attribute + direction = intlLocale.textInfo?.direction; + } catch (e) { + console.error(e); + } + + return { isEmbed, embedColorScheme, locale: newLocale, direction }; +}; + +export default async function RootLayout({ children }: { children: React.ReactNode }) { + const headers = nextHeaders(); + const cookies = nextCookies(); + + const fullUrl = headers.get("x-url") ?? ""; + const nonce = headers.get("x-csp") ?? ""; + + const { locale, direction, isEmbed, embedColorScheme } = await getInitialProps(fullUrl, headers, cookies); + return ( + + + {!IS_PRODUCTION && process.env.VERCEL_ENV === "preview" && ( + // eslint-disable-next-line @next/next/no-sync-scripts +