feat: Ability to set a locked timezone for event type (#20425)
* feat: ability to set locked timezone * update * Update update-event-type.input.ts * Update get-event-type-public.output.ts * Update documentation.json * revert * nit
This commit is contained in:
1 parent
7ee451ca02
commit
03240709dc
19 files changed
+65
-11
No files matched your search
@@ -59,6 +59,7 @@ type UserPageProps = {
|
||||
| "length"
|
||||
| "hidden"
|
||||
| "lockTimeZoneToggleOnBookingPage"
|
||||
| "lockedTimeZone"
|
||||
| "requiresConfirmation"
|
||||
| "canSendCalVideoTranscriptionEmails"
|
||||
| "requiresBookerEmailVerification"
|
||||
|
||||
@@ -111,6 +111,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
timeZone,
|
||||
requiresBookerEmailVerification,
|
||||
lockTimeZoneToggleOnBookingPage,
|
||||
lockedTimeZone,
|
||||
useEventTypeDestinationCalendarEmail,
|
||||
secondaryEmailId,
|
||||
autoTranslateDescriptionEnabled,
|
||||
@@ -136,6 +137,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
parentId: 1,
|
||||
users: { connect: [{ id: 4 }] },
|
||||
lockTimeZoneToggleOnBookingPage: false,
|
||||
lockedTimeZone: "Europe/London",
|
||||
requiresBookerEmailVerification: false,
|
||||
instantMeetingScheduleId: undefined,
|
||||
bookingLimits: undefined,
|
||||
@@ -168,6 +170,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
scheduleId,
|
||||
requiresBookerEmailVerification,
|
||||
lockTimeZoneToggleOnBookingPage,
|
||||
lockedTimeZone,
|
||||
useEventTypeDestinationCalendarEmail,
|
||||
secondaryEmailId,
|
||||
...evType
|
||||
@@ -198,6 +201,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
locations: [],
|
||||
scheduleId: null,
|
||||
lockTimeZoneToggleOnBookingPage: false,
|
||||
lockedTimeZone: "Europe/London",
|
||||
requiresBookerEmailVerification: false,
|
||||
hashedLink: {
|
||||
deleteMany: {},
|
||||
@@ -272,6 +276,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
timeZone,
|
||||
requiresBookerEmailVerification,
|
||||
lockTimeZoneToggleOnBookingPage,
|
||||
lockedTimeZone,
|
||||
useEventTypeDestinationCalendarEmail,
|
||||
secondaryEmailId,
|
||||
autoTranslateDescriptionEnabled,
|
||||
@@ -304,6 +309,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
customReplyToEmail: null,
|
||||
instantMeetingScheduleId: undefined,
|
||||
lockTimeZoneToggleOnBookingPage: false,
|
||||
lockedTimeZone: "Europe/London",
|
||||
requiresBookerEmailVerification: false,
|
||||
userId: 4,
|
||||
workflows: undefined,
|
||||
@@ -330,6 +336,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
userId,
|
||||
requiresBookerEmailVerification,
|
||||
lockTimeZoneToggleOnBookingPage,
|
||||
lockedTimeZone,
|
||||
useEventTypeDestinationCalendarEmail,
|
||||
secondaryEmailId,
|
||||
...evType
|
||||
@@ -363,6 +370,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
deleteMany: {},
|
||||
},
|
||||
lockTimeZoneToggleOnBookingPage: false,
|
||||
lockedTimeZone: "Europe/London",
|
||||
requiresBookerEmailVerification: false,
|
||||
instantMeetingScheduleId: undefined,
|
||||
},
|
||||
@@ -393,6 +401,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
requiresBookerEmailVerification,
|
||||
lockTimeZoneToggleOnBookingPage,
|
||||
lockedTimeZone,
|
||||
useEventTypeDestinationCalendarEmail,
|
||||
secondaryEmailId,
|
||||
autoTranslateDescriptionEnabled,
|
||||
@@ -418,6 +427,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
schedulingType: SchedulingType.MANAGED,
|
||||
requiresBookerEmailVerification: false,
|
||||
lockTimeZoneToggleOnBookingPage: false,
|
||||
lockedTimeZone: "Europe/London",
|
||||
useEventTypeDestinationCalendarEmail: false,
|
||||
workflows: [],
|
||||
parentId: 1,
|
||||
@@ -452,6 +462,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
instantMeetingScheduleId: undefined,
|
||||
locations: [],
|
||||
lockTimeZoneToggleOnBookingPage: false,
|
||||
lockedTimeZone: "Europe/London",
|
||||
requiresBookerEmailVerification: false,
|
||||
parentId: 1,
|
||||
userId: 5,
|
||||
@@ -478,6 +489,7 @@ describe("handleChildrenEventTypes", () => {
|
||||
customReplyToEmail: null,
|
||||
rrSegmentQueryValue: undefined,
|
||||
lockTimeZoneToggleOnBookingPage: false,
|
||||
lockedTimeZone: "Europe/London",
|
||||
requiresBookerEmailVerification: false,
|
||||
hashedLink: {
|
||||
deleteMany: {},
|
||||
|
||||
@@ -245,4 +245,4 @@ export default function TeamEvent(){
|
||||
</Step>
|
||||
|
||||
|
||||
</Steps>
|
||||
</Steps>
|
||||
@@ -13,7 +13,6 @@ import { useTimePreferences } from "@calcom/features/bookings/lib";
|
||||
import type { BookerEvent } from "@calcom/features/bookings/types";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { markdownToSafeHTMLClient } from "@calcom/lib/markdownToSafeHTMLClient";
|
||||
import { CURRENT_TIMEZONE } from "@calcom/lib/timezoneConstants";
|
||||
import type { EventTypeTranslation } from "@calcom/prisma/client";
|
||||
import { EventTypeAutoTranslatedField } from "@calcom/prisma/enums";
|
||||
|
||||
@@ -57,6 +56,7 @@ export const EventMeta = ({
|
||||
event?: Pick<
|
||||
BookerEvent,
|
||||
| "lockTimeZoneToggleOnBookingPage"
|
||||
| "lockedTimeZone"
|
||||
| "schedule"
|
||||
| "seatsPerTimeSlot"
|
||||
| "subsetOfUsers"
|
||||
@@ -109,9 +109,9 @@ export const EventMeta = ({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
//In case the event has lockTimeZone enabled ,set the timezone to event's attached availability timezone
|
||||
if (event && event?.lockTimeZoneToggleOnBookingPage && event?.schedule?.timeZone) {
|
||||
setTimezone(event.schedule?.timeZone);
|
||||
//In case the event has lockTimeZone enabled ,set the timezone to event's locked timezone
|
||||
if (event && event?.lockTimeZoneToggleOnBookingPage && event?.lockedTimeZone) {
|
||||
setTimezone(event?.lockedTimeZone);
|
||||
}
|
||||
}, [event, setTimezone]);
|
||||
|
||||
@@ -225,7 +225,7 @@ export const EventMeta = ({
|
||||
indicatorsContainer: () => "ml-auto",
|
||||
container: () => "max-w-full",
|
||||
}}
|
||||
value={event.lockTimeZoneToggleOnBookingPage ? CURRENT_TIMEZONE : timezone}
|
||||
value={event.lockTimeZoneToggleOnBookingPage ? event.lockedTimeZone : timezone}
|
||||
onChange={({ value }) => {
|
||||
setTimezone(value);
|
||||
setBookerStoreTimezone(value);
|
||||
|
||||
@@ -58,6 +58,7 @@ export const getEventTypesFromDB = async (eventTypeId: number) => {
|
||||
periodDays: true,
|
||||
periodCountCalendarDays: true,
|
||||
lockTimeZoneToggleOnBookingPage: true,
|
||||
lockedTimeZone: true,
|
||||
requiresConfirmation: true,
|
||||
requiresConfirmationForFreeEmail: true,
|
||||
requiresBookerEmailVerification: true,
|
||||
|
||||
@@ -46,6 +46,7 @@ export type BookerEvent = Pick<
|
||||
| "price"
|
||||
| "currency"
|
||||
| "lockTimeZoneToggleOnBookingPage"
|
||||
| "lockedTimeZone"
|
||||
| "schedule"
|
||||
| "seatsPerTimeSlot"
|
||||
| "title"
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from "@calcom/atoms/selected-calendars/wrappers/SelectedCalendarsSettingsWebWrapper";
|
||||
import getLocationsOptionsForSelect from "@calcom/features/bookings/lib/getLocationOptionsForSelect";
|
||||
import DestinationCalendarSelector from "@calcom/features/calendars/DestinationCalendarSelector";
|
||||
import { TimezoneSelect } from "@calcom/features/components/timezone-select";
|
||||
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
|
||||
import {
|
||||
allowDisablingAttendeeConfirmationEmails,
|
||||
@@ -1002,7 +1003,8 @@ export const EventAdvancedTab = ({
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
customClassNames?.timezoneLock?.container
|
||||
customClassNames?.timezoneLock?.container,
|
||||
formMethods.getValues("lockTimeZoneToggleOnBookingPage") && "rounded-b-none"
|
||||
)}
|
||||
title={t("lock_timezone_toggle_on_booking_page")}
|
||||
{...lockTimeZoneToggleOnBookingPageLocked}
|
||||
@@ -1010,7 +1012,31 @@ export const EventAdvancedTab = ({
|
||||
checked={value}
|
||||
onCheckedChange={(e) => onChange(e)}
|
||||
data-testid="lock-timezone-toggle"
|
||||
/>
|
||||
childrenClassName="lg:ml-0">
|
||||
<div className="border-subtle flex flex-col gap-6 rounded-b-lg border border-t-0 p-6">
|
||||
<div>
|
||||
<Controller
|
||||
name="lockedTimeZone"
|
||||
control={formMethods.control}
|
||||
render={({ field: { value } }) => (
|
||||
<>
|
||||
<Label className="text-default mb-2 block text-sm font-medium">
|
||||
<>{t("timezone")}</>
|
||||
</Label>
|
||||
<TimezoneSelect
|
||||
id="lockedTimeZone"
|
||||
value={value}
|
||||
onChange={(event) => {
|
||||
if (event)
|
||||
formMethods.setValue("lockedTimeZone", event.value, { shouldDirty: true });
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsToggle>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
|
||||
@@ -67,6 +67,7 @@ const getPublicEventSelect = (fetchAllUsers: boolean) => {
|
||||
disableGuests: true,
|
||||
metadata: true,
|
||||
lockTimeZoneToggleOnBookingPage: true,
|
||||
lockedTimeZone: true,
|
||||
requiresConfirmation: true,
|
||||
autoTranslateDescriptionEnabled: true,
|
||||
fieldTranslations: {
|
||||
|
||||
@@ -80,6 +80,7 @@ export type FormValues = {
|
||||
description: string;
|
||||
disableGuests: boolean;
|
||||
lockTimeZoneToggleOnBookingPage: boolean;
|
||||
lockedTimeZone: string;
|
||||
requiresConfirmation: boolean;
|
||||
requiresConfirmationWillBlockSlot: boolean;
|
||||
requiresConfirmationForFreeEmail: boolean;
|
||||
|
||||
@@ -100,6 +100,7 @@ const commons = {
|
||||
destinationCalendar: null,
|
||||
team: null,
|
||||
lockTimeZoneToggleOnBookingPage: false,
|
||||
lockedTimeZone: "Europe/London",
|
||||
requiresConfirmation: false,
|
||||
requiresConfirmationForFreeEmail: false,
|
||||
requiresBookerEmailVerification: false,
|
||||
|
||||
@@ -35,14 +35,14 @@ const getEventTypesWithHiddenFromDB = async (userId: number) => {
|
||||
const eventTypes = await prisma.$queryRaw<RawEventType[]>`
|
||||
SELECT data."id", data."title", data."description", data."length", data."schedulingType"::text,
|
||||
data."recurringEvent", data."slug", data."hidden", data."price", data."currency",
|
||||
data."lockTimeZoneToggleOnBookingPage", data."requiresConfirmation", data."requiresBookerEmailVerification",
|
||||
data."lockTimeZoneToggleOnBookingPage", data."lockedTimeZone", data."requiresConfirmation", data."requiresBookerEmailVerification",
|
||||
data."metadata", data."canSendCalVideoTranscriptionEmails"
|
||||
FROM (
|
||||
SELECT "EventType"."id", "EventType"."title", "EventType"."description",
|
||||
"EventType"."position", "EventType"."length", "EventType"."schedulingType"::text,
|
||||
"EventType"."recurringEvent", "EventType"."slug", "EventType"."hidden",
|
||||
"EventType"."price", "EventType"."currency",
|
||||
"EventType"."lockTimeZoneToggleOnBookingPage", "EventType"."requiresConfirmation",
|
||||
"EventType"."lockTimeZoneToggleOnBookingPage", "EventType"."lockedTimeZone", "EventType"."requiresConfirmation",
|
||||
"EventType"."requiresBookerEmailVerification", "EventType"."metadata",
|
||||
"EventType"."canSendCalVideoTranscriptionEmails"
|
||||
FROM "EventType"
|
||||
@@ -52,7 +52,7 @@ const getEventTypesWithHiddenFromDB = async (userId: number) => {
|
||||
"EventType"."position", "EventType"."length", "EventType"."schedulingType"::text,
|
||||
"EventType"."recurringEvent", "EventType"."slug", "EventType"."hidden",
|
||||
"EventType"."price", "EventType"."currency",
|
||||
"EventType"."lockTimeZoneToggleOnBookingPage", "EventType"."requiresConfirmation",
|
||||
"EventType"."lockTimeZoneToggleOnBookingPage", "EventType"."lockedTimeZone", "EventType"."requiresConfirmation",
|
||||
"EventType"."requiresBookerEmailVerification", "EventType"."metadata",
|
||||
"EventType"."canSendCalVideoTranscriptionEmails"
|
||||
FROM "EventType"
|
||||
|
||||
@@ -28,6 +28,7 @@ export const eventTypeSelect = Prisma.validator<Prisma.EventTypeSelect>()({
|
||||
periodDays: true,
|
||||
periodCountCalendarDays: true,
|
||||
lockTimeZoneToggleOnBookingPage: true,
|
||||
lockedTimeZone: true,
|
||||
requiresBookerEmailVerification: true,
|
||||
disableGuests: true,
|
||||
disableCancelling: true,
|
||||
|
||||
@@ -487,6 +487,7 @@ export class EventTypeRepository {
|
||||
periodEndDate: true,
|
||||
periodCountCalendarDays: true,
|
||||
lockTimeZoneToggleOnBookingPage: true,
|
||||
lockedTimeZone: true,
|
||||
requiresConfirmation: true,
|
||||
requiresConfirmationForFreeEmail: true,
|
||||
canSendCalVideoTranscriptionEmails: true,
|
||||
|
||||
@@ -111,6 +111,7 @@ export const buildEventType = (eventType?: Partial<EventType>): EventType => {
|
||||
periodCountCalendarDays: null,
|
||||
recurringEvent: null,
|
||||
lockTimeZoneToggleOnBookingPage: false,
|
||||
lockedTimeZone: "Europe/London",
|
||||
requiresConfirmation: false,
|
||||
requiresConfirmationForFreeEmail: false,
|
||||
requiresConfirmationWillBlockSlot: false,
|
||||
|
||||
@@ -53,6 +53,7 @@ export const useEventTypeForm = ({
|
||||
seatsShowAttendees: eventType.seatsShowAttendees,
|
||||
seatsShowAvailabilityCount: eventType.seatsShowAvailabilityCount,
|
||||
lockTimeZoneToggleOnBookingPage: eventType.lockTimeZoneToggleOnBookingPage,
|
||||
lockedTimeZone: eventType.lockedTimeZone,
|
||||
locations: eventType.locations || [],
|
||||
destinationCalendar: eventType.destinationCalendar,
|
||||
recurringEvent: eventType.recurringEvent || null,
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "EventType" ADD COLUMN "lockedTimeZone" TEXT NOT NULL DEFAULT 'Europe/London';
|
||||
@@ -108,6 +108,7 @@ model EventType {
|
||||
periodDays Int?
|
||||
periodCountCalendarDays Boolean?
|
||||
lockTimeZoneToggleOnBookingPage Boolean @default(false)
|
||||
lockedTimeZone String @default("Europe/London")
|
||||
requiresConfirmation Boolean @default(false)
|
||||
requiresConfirmationWillBlockSlot Boolean @default(false)
|
||||
requiresConfirmationForFreeEmail Boolean @default(false)
|
||||
|
||||
@@ -12,6 +12,7 @@ export const baseEventTypeSelect = Prisma.validator<Prisma.EventTypeSelect>()({
|
||||
price: true,
|
||||
currency: true,
|
||||
lockTimeZoneToggleOnBookingPage: true,
|
||||
lockedTimeZone: true,
|
||||
requiresConfirmation: true,
|
||||
requiresBookerEmailVerification: true,
|
||||
canSendCalVideoTranscriptionEmails: true,
|
||||
@@ -31,6 +32,7 @@ export const bookEventTypeSelect = Prisma.validator<Prisma.EventTypeSelect>()({
|
||||
periodEndDate: true,
|
||||
recurringEvent: true,
|
||||
lockTimeZoneToggleOnBookingPage: true,
|
||||
lockedTimeZone: true,
|
||||
requiresConfirmation: true,
|
||||
canSendCalVideoTranscriptionEmails: true,
|
||||
requiresBookerEmailVerification: true,
|
||||
|
||||
@@ -660,6 +660,7 @@ export const allManagedEventTypeProps: { [k in keyof Omit<Prisma.EventTypeSelect
|
||||
bookingFields: true,
|
||||
durationLimits: true,
|
||||
lockTimeZoneToggleOnBookingPage: true,
|
||||
lockedTimeZone: true,
|
||||
requiresBookerEmailVerification: true,
|
||||
assignAllTeamMembers: true,
|
||||
isRRWeightsEnabled: true,
|
||||
|
||||
Reference in new issue
Block a user