feat: add missing event type fields for advanced settings in api v2 (#25739)
* feat: api v2 add missing event type fields for advanced settings Add 9 event type fields to API v2 that were available in tRPC but missing from the platform API: - disableCancelling: disable cancelling for guests/organizer - disableRescheduling: disable rescheduling for guests/organizer - canSendCalVideoTranscriptionEmails: send Cal Video transcription emails - autoTranslateInstantMeetingTitleEnabled: auto-translate instant meeting titles - interfaceLanguage: preferred booking interface language - allowReschedulingPastBookings: allow rescheduling past events - allowReschedulingCancelledBookings: allow booking via reschedule link - customReplyToEmail: custom reply-to email for confirmations - showOptimizedSlots: optimize time slot arrangement Updated output/input schemas, transformation services, and E2E tests. * fix(api-v2): add proper OpenAPI types for nullable event type fields Add explicit type and nullable properties to @ApiPropertyOptional decorators for fields with `boolean | null` or `string | null` types. Without these, Swagger was generating incorrect "type": "object" instead of the correct types. Fixed fields: - disableCancelling: type: Boolean, nullable: true - disableRescheduling: type: Boolean, nullable: true - interfaceLanguage: type: String, nullable: true - allowReschedulingCancelledBookings: type: Boolean, nullable: true - customReplyToEmail: type: String, nullable: true - showOptimizedSlots: type: Boolean, nullable: true * refactor: customReplyToEmail was intentionally excluded from this PR. The web UI restricts this field to only allow the user's own verified emails via a dropdown, but implementing the same validation in the API requires additional business logic. This will be addressed in a separate PR with proper email ownership validation. * feat(api-v2): add validation for interfaceLanguage field Add @IsIn validation to interfaceLanguage field to only accept supported locales. This ensures API v2 matches the web UI behavior where users can only select from a predefined dropdown of supported languages. Changes: - Add SUPPORTED_LOCALES constant to @calcom/platform-constants - Add @IsIn([...SUPPORTED_LOCALES]) validation to create/update DTOs - Add E2E tests for invalid locale rejection (400 error) - Add cross-reference comments in i18n.json and api.ts to keep in sync * docs(api): add default values to event type input field documentation Added default value documentation to @DocsPropertyOptional decorators for the new event type fields in API v2 (2024_06_14): - disableCancelling: false - disableRescheduling: false - canSendCalVideoTranscriptionEmails: true - autoTranslateInstantMeetingTitleEnabled: false - allowReschedulingPastBookings: false - allowReschedulingCancelledBookings: false - showOptimizedSlots: false This improves API documentation by clearly communicating default values to API consumers in the OpenAPI spec. * feat(api-v2): refactor event type settings to object types for future extensibility - Convert disableRescheduling from boolean to object with disabled and minutesBefore properties - Convert disableCancelling from boolean to object with disabled property - Move canSendCalVideoTranscriptionEmails into CalVideoSettings as sendTranscriptionEmails - Remove autoTranslateInstantMeetingTitleEnabled (Enterprise-only feature) - Add DisableRescheduling_2024_06_14 and DisableCancelling_2024_06_14 input/output types - Add transformation methods for new object types in input and output services - Update E2E tests for new API contract BREAKING CHANGE: disableRescheduling and disableCancelling now accept objects instead of booleans * fix(api-v2): prevent clearing calVideoSettings when only sendTranscriptionEmails is provided Only include calVideoSettings in transformed output if it has properties, avoiding unintentional reset of existing settings during updates.
This commit is contained in:
+102
@@ -432,6 +432,29 @@ describe("Event types Endpoints", () => {
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it("should return an error when creating an event type with invalid interfaceLanguage", async () => {
|
||||
const body: CreateEventTypeInput_2024_06_14 = {
|
||||
title: "Coding class invalid locale",
|
||||
slug: "coding-class-invalid-locale",
|
||||
description: "Let's learn how to code like a pro.",
|
||||
lengthInMinutes: 60,
|
||||
locations: [
|
||||
{
|
||||
type: "integration",
|
||||
integration: "cal-video",
|
||||
},
|
||||
],
|
||||
interfaceLanguage: "invalid-locale-xyz",
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/api/v2/event-types")
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
|
||||
.set("Authorization", `Bearer ${apiKeyString}`)
|
||||
.send(body)
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it("should create an event type", async () => {
|
||||
const nameBookingField: NameDefaultFieldInput_2024_06_14 = {
|
||||
type: "name",
|
||||
@@ -532,6 +555,13 @@ describe("Event types Endpoints", () => {
|
||||
},
|
||||
customName: `{Event type title} between {Organiser} and {Scheduler}`,
|
||||
bookingRequiresAuthentication: true,
|
||||
disableCancelling: { disabled: true },
|
||||
disableRescheduling: { disabled: true },
|
||||
calVideoSettings: { sendTranscriptionEmails: true },
|
||||
interfaceLanguage: "en",
|
||||
allowReschedulingPastBookings: true,
|
||||
allowReschedulingCancelledBookings: true,
|
||||
showOptimizedSlots: true,
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
@@ -606,6 +636,15 @@ describe("Event types Endpoints", () => {
|
||||
|
||||
expect(createdEventType.bookingFields).toEqual(expectedBookingFields);
|
||||
expect(createdEventType.bookingRequiresAuthentication).toEqual(true);
|
||||
expect(createdEventType.disableCancelling).toEqual({ disabled: true });
|
||||
expect(createdEventType.disableRescheduling).toEqual({ disabled: true });
|
||||
expect(createdEventType.calVideoSettings?.sendTranscriptionEmails).toEqual(true);
|
||||
expect(createdEventType.interfaceLanguage).toEqual(body.interfaceLanguage);
|
||||
expect(createdEventType.allowReschedulingPastBookings).toEqual(body.allowReschedulingPastBookings);
|
||||
expect(createdEventType.allowReschedulingCancelledBookings).toEqual(
|
||||
body.allowReschedulingCancelledBookings
|
||||
);
|
||||
expect(createdEventType.showOptimizedSlots).toEqual(body.showOptimizedSlots);
|
||||
eventType = responseBody.data;
|
||||
});
|
||||
});
|
||||
@@ -693,6 +732,19 @@ describe("Event types Endpoints", () => {
|
||||
);
|
||||
expect(fetchedEventType?.color).toEqual(eventType.color);
|
||||
expect(fetchedEventType?.hidden).toEqual(false);
|
||||
expect(fetchedEventType?.disableCancelling).toEqual(eventType.disableCancelling);
|
||||
expect(fetchedEventType?.disableRescheduling).toEqual(eventType.disableRescheduling);
|
||||
expect(fetchedEventType?.calVideoSettings?.sendTranscriptionEmails).toEqual(
|
||||
eventType.calVideoSettings?.sendTranscriptionEmails
|
||||
);
|
||||
expect(fetchedEventType?.interfaceLanguage).toEqual(eventType.interfaceLanguage);
|
||||
expect(fetchedEventType?.allowReschedulingPastBookings).toEqual(
|
||||
eventType.allowReschedulingPastBookings
|
||||
);
|
||||
expect(fetchedEventType?.allowReschedulingCancelledBookings).toEqual(
|
||||
eventType.allowReschedulingCancelledBookings
|
||||
);
|
||||
expect(fetchedEventType?.showOptimizedSlots).toEqual(eventType.showOptimizedSlots);
|
||||
|
||||
expect(fetchedHiddenEventType?.id).toEqual(hiddenEventType.id);
|
||||
expect(fetchedHiddenEventType?.hidden).toEqual(true);
|
||||
@@ -822,6 +874,19 @@ describe("Event types Endpoints", () => {
|
||||
);
|
||||
expect(fetchedEventType?.color).toEqual(eventType.color);
|
||||
expect(fetchedEventType?.hidden).toEqual(false);
|
||||
expect(fetchedEventType?.disableCancelling).toEqual(eventType.disableCancelling);
|
||||
expect(fetchedEventType?.disableRescheduling).toEqual(eventType.disableRescheduling);
|
||||
expect(fetchedEventType?.calVideoSettings?.sendTranscriptionEmails).toEqual(
|
||||
eventType.calVideoSettings?.sendTranscriptionEmails
|
||||
);
|
||||
expect(fetchedEventType?.interfaceLanguage).toEqual(eventType.interfaceLanguage);
|
||||
expect(fetchedEventType?.allowReschedulingPastBookings).toEqual(
|
||||
eventType.allowReschedulingPastBookings
|
||||
);
|
||||
expect(fetchedEventType?.allowReschedulingCancelledBookings).toEqual(
|
||||
eventType.allowReschedulingCancelledBookings
|
||||
);
|
||||
expect(fetchedEventType?.showOptimizedSlots).toEqual(eventType.showOptimizedSlots);
|
||||
});
|
||||
|
||||
it(`/GET/event-types by username and eventSlug should not return hidden event type if auth of non event type owner provided`, async () => {
|
||||
@@ -1209,6 +1274,7 @@ describe("Event types Endpoints", () => {
|
||||
enableAutomaticTranscription: true,
|
||||
disableTranscriptionForGuests: true,
|
||||
disableTranscriptionForOrganizer: true,
|
||||
sendTranscriptionEmails: false,
|
||||
},
|
||||
bookingFields: [
|
||||
nameBookingField,
|
||||
@@ -1268,6 +1334,12 @@ describe("Event types Endpoints", () => {
|
||||
},
|
||||
customName: `{Event type title} betweennnnnnnnnnn {Organiser} and {Scheduler}`,
|
||||
bookingRequiresAuthentication: false,
|
||||
disableCancelling: { disabled: false },
|
||||
disableRescheduling: { disabled: false, minutesBefore: 60 },
|
||||
interfaceLanguage: "es",
|
||||
allowReschedulingPastBookings: false,
|
||||
allowReschedulingCancelledBookings: false,
|
||||
showOptimizedSlots: false,
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
@@ -1374,6 +1446,23 @@ describe("Event types Endpoints", () => {
|
||||
eventType.calVideoSettings = updatedEventType.calVideoSettings;
|
||||
|
||||
expect(updatedEventType.bookingRequiresAuthentication).toEqual(false);
|
||||
expect(updatedEventType.disableCancelling).toEqual({ disabled: false });
|
||||
expect(updatedEventType.disableRescheduling).toEqual({ disabled: false, minutesBefore: 60 });
|
||||
expect(updatedEventType.calVideoSettings?.sendTranscriptionEmails).toEqual(false);
|
||||
expect(updatedEventType.interfaceLanguage).toEqual(body.interfaceLanguage);
|
||||
expect(updatedEventType.allowReschedulingPastBookings).toEqual(body.allowReschedulingPastBookings);
|
||||
expect(updatedEventType.allowReschedulingCancelledBookings).toEqual(
|
||||
body.allowReschedulingCancelledBookings
|
||||
);
|
||||
expect(updatedEventType.showOptimizedSlots).toEqual(body.showOptimizedSlots);
|
||||
|
||||
eventType.disableCancelling = updatedEventType.disableCancelling;
|
||||
eventType.disableRescheduling = updatedEventType.disableRescheduling;
|
||||
eventType.calVideoSettings = updatedEventType.calVideoSettings;
|
||||
eventType.interfaceLanguage = updatedEventType.interfaceLanguage;
|
||||
eventType.allowReschedulingPastBookings = updatedEventType.allowReschedulingPastBookings;
|
||||
eventType.allowReschedulingCancelledBookings = updatedEventType.allowReschedulingCancelledBookings;
|
||||
eventType.showOptimizedSlots = updatedEventType.showOptimizedSlots;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1408,6 +1497,19 @@ describe("Event types Endpoints", () => {
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it("should return an error when updating an event type with invalid interfaceLanguage", async () => {
|
||||
const body: UpdateEventTypeInput_2024_06_14 = {
|
||||
interfaceLanguage: "invalid-locale-xyz",
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.patch(`/api/v2/event-types/${eventType.id}`)
|
||||
.set("Authorization", `Bearer ${apiKeyString}`)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
|
||||
.send(body)
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it(`/GET/:id`, async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.get(`/api/v2/event-types/${eventType.id}`)
|
||||
|
||||
+82
@@ -131,6 +131,9 @@ export class InputEventTypesService_2024_06_14 {
|
||||
disableGuests,
|
||||
bookerActiveBookingsLimit,
|
||||
slug,
|
||||
disableRescheduling,
|
||||
disableCancelling,
|
||||
calVideoSettings,
|
||||
...rest
|
||||
} = inputEventType;
|
||||
const confirmationPolicyTransformed = this.transformInputConfirmationPolicy(confirmationPolicy);
|
||||
@@ -155,6 +158,10 @@ export class InputEventTypesService_2024_06_14 {
|
||||
multipleDuration: lengthInMinutesOptions,
|
||||
};
|
||||
|
||||
const disableReschedulingTransformed = this.transformInputDisableRescheduling(disableRescheduling);
|
||||
const disableCancellingTransformed = this.transformInputDisableCancelling(disableCancelling);
|
||||
const calVideoSettingsTransformed = this.transformInputCalVideoSettings(calVideoSettings);
|
||||
|
||||
const eventType = {
|
||||
...rest,
|
||||
slug: slugifiedSlug,
|
||||
@@ -176,6 +183,9 @@ export class InputEventTypesService_2024_06_14 {
|
||||
eventName: customName,
|
||||
useEventTypeDestinationCalendarEmail: useDestinationCalendarEmail,
|
||||
...maxActiveBookingsPerBooker,
|
||||
...disableReschedulingTransformed,
|
||||
...disableCancellingTransformed,
|
||||
...calVideoSettingsTransformed,
|
||||
};
|
||||
|
||||
return eventType;
|
||||
@@ -215,6 +225,9 @@ export class InputEventTypesService_2024_06_14 {
|
||||
disableGuests,
|
||||
bookerActiveBookingsLimit,
|
||||
slug,
|
||||
disableRescheduling,
|
||||
disableCancelling,
|
||||
calVideoSettings,
|
||||
...rest
|
||||
} = inputEventType;
|
||||
const eventTypeDb = await this.eventTypesRepository.getEventTypeWithMetaData(eventTypeId);
|
||||
@@ -247,6 +260,16 @@ export class InputEventTypesService_2024_06_14 {
|
||||
...(lengthInMinutesOptions !== undefined ? { multipleDuration: lengthInMinutesOptions } : {}),
|
||||
};
|
||||
|
||||
const disableReschedulingTransformed = disableRescheduling
|
||||
? this.transformInputDisableRescheduling(disableRescheduling)
|
||||
: {};
|
||||
const disableCancellingTransformed = disableCancelling
|
||||
? this.transformInputDisableCancelling(disableCancelling)
|
||||
: {};
|
||||
const calVideoSettingsTransformed = calVideoSettings
|
||||
? this.transformInputCalVideoSettings(calVideoSettings)
|
||||
: {};
|
||||
|
||||
const eventType = {
|
||||
...rest,
|
||||
...(slug ? { slug: slugifyLenient(slug) } : {}),
|
||||
@@ -270,6 +293,9 @@ export class InputEventTypesService_2024_06_14 {
|
||||
eventName: customName,
|
||||
useEventTypeDestinationCalendarEmail: useDestinationCalendarEmail,
|
||||
...maxActiveBookingsPerBooker,
|
||||
...disableReschedulingTransformed,
|
||||
...disableCancellingTransformed,
|
||||
...calVideoSettingsTransformed,
|
||||
};
|
||||
|
||||
return eventType;
|
||||
@@ -602,4 +628,60 @@ export class InputEventTypesService_2024_06_14 {
|
||||
}
|
||||
return foundApp.credential;
|
||||
}
|
||||
|
||||
transformInputDisableRescheduling(disableRescheduling: CreateEventTypeInput_2024_06_14["disableRescheduling"]) {
|
||||
if (!disableRescheduling) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// If disabled is true, rescheduling is always disabled
|
||||
if (disableRescheduling.disabled === true) {
|
||||
return {
|
||||
disableRescheduling: true,
|
||||
minimumRescheduleNotice: null,
|
||||
};
|
||||
}
|
||||
|
||||
// If minutesBefore is set, use it for conditional disable
|
||||
if (disableRescheduling.minutesBefore && disableRescheduling.minutesBefore > 0) {
|
||||
return {
|
||||
disableRescheduling: false,
|
||||
minimumRescheduleNotice: disableRescheduling.minutesBefore,
|
||||
};
|
||||
}
|
||||
|
||||
// Otherwise rescheduling is not disabled
|
||||
return {
|
||||
disableRescheduling: false,
|
||||
minimumRescheduleNotice: null,
|
||||
};
|
||||
}
|
||||
|
||||
transformInputDisableCancelling(disableCancelling: CreateEventTypeInput_2024_06_14["disableCancelling"]) {
|
||||
if (!disableCancelling) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
disableCancelling: disableCancelling.disabled === true,
|
||||
};
|
||||
}
|
||||
|
||||
transformInputCalVideoSettings(calVideoSettings: CreateEventTypeInput_2024_06_14["calVideoSettings"]) {
|
||||
if (!calVideoSettings) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Extract sendTranscriptionEmails from calVideoSettings and map to canSendCalVideoTranscriptionEmails
|
||||
const { sendTranscriptionEmails, ...restCalVideoSettings } = calVideoSettings;
|
||||
|
||||
const hasOtherSettings = Object.keys(restCalVideoSettings).length > 0;
|
||||
|
||||
return {
|
||||
...(hasOtherSettings ? { calVideoSettings: restCalVideoSettings } : {}),
|
||||
...(sendTranscriptionEmails !== undefined
|
||||
? { canSendCalVideoTranscriptionEmails: sendTranscriptionEmails }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+69
-2
@@ -40,7 +40,7 @@ type EventTypeRelations = {
|
||||
destinationCalendar?: DestinationCalendar | null;
|
||||
calVideoSettings?: CalVideoSettings | null;
|
||||
};
|
||||
export type DatabaseEventType = Omit<EventType, "allowReschedulingCancelledBookings"> & EventTypeRelations;
|
||||
export type DatabaseEventType = EventType & EventTypeRelations;
|
||||
|
||||
type Input = Pick<
|
||||
DatabaseEventType,
|
||||
@@ -94,6 +94,14 @@ type Input = Pick<
|
||||
| "bookingRequiresAuthentication"
|
||||
| "maxActiveBookingsPerBooker"
|
||||
| "maxActiveBookingPerBookerOfferReschedule"
|
||||
| "disableCancelling"
|
||||
| "disableRescheduling"
|
||||
| "minimumRescheduleNotice"
|
||||
| "canSendCalVideoTranscriptionEmails"
|
||||
| "interfaceLanguage"
|
||||
| "allowReschedulingPastBookings"
|
||||
| "allowReschedulingCancelledBookings"
|
||||
| "showOptimizedSlots"
|
||||
>;
|
||||
|
||||
@Injectable()
|
||||
@@ -134,6 +142,14 @@ export class OutputEventTypesService_2024_06_14 {
|
||||
calVideoSettings,
|
||||
hidden,
|
||||
bookingRequiresAuthentication,
|
||||
disableCancelling,
|
||||
disableRescheduling,
|
||||
minimumRescheduleNotice,
|
||||
canSendCalVideoTranscriptionEmails,
|
||||
interfaceLanguage,
|
||||
allowReschedulingPastBookings,
|
||||
allowReschedulingCancelledBookings,
|
||||
showOptimizedSlots,
|
||||
} = databaseEventType;
|
||||
|
||||
const locations = this.transformLocations(databaseEventType.locations);
|
||||
@@ -168,6 +184,15 @@ export class OutputEventTypesService_2024_06_14 {
|
||||
} as TransformFutureBookingsLimitSchema_2024_06_14);
|
||||
const destinationCalendar = this.transformDestinationCalendar(databaseEventType.destinationCalendar);
|
||||
const bookerActiveBookingsLimit = this.transformBookerActiveBookingsLimit(databaseEventType);
|
||||
const disableReschedulingOutput = this.transformDisableRescheduling(
|
||||
disableRescheduling,
|
||||
minimumRescheduleNotice
|
||||
);
|
||||
const disableCancellingOutput = this.transformDisableCancelling(disableCancelling);
|
||||
const calVideoSettingsOutput = this.transformCalVideoSettings(
|
||||
calVideoSettings,
|
||||
canSendCalVideoTranscriptionEmails
|
||||
);
|
||||
|
||||
return {
|
||||
id,
|
||||
@@ -210,10 +235,16 @@ export class OutputEventTypesService_2024_06_14 {
|
||||
useDestinationCalendarEmail: useEventTypeDestinationCalendarEmail,
|
||||
hideCalendarEventDetails,
|
||||
hideOrganizerEmail,
|
||||
calVideoSettings,
|
||||
calVideoSettings: calVideoSettingsOutput,
|
||||
hidden,
|
||||
bookingRequiresAuthentication,
|
||||
bookerActiveBookingsLimit,
|
||||
disableCancelling: disableCancellingOutput,
|
||||
disableRescheduling: disableReschedulingOutput,
|
||||
interfaceLanguage,
|
||||
allowReschedulingPastBookings,
|
||||
allowReschedulingCancelledBookings,
|
||||
showOptimizedSlots,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -395,4 +426,40 @@ export class OutputEventTypesService_2024_06_14 {
|
||||
bookingFields: visibleBookingFields,
|
||||
};
|
||||
}
|
||||
|
||||
transformDisableRescheduling(
|
||||
disableRescheduling: boolean | null | undefined,
|
||||
minimumRescheduleNotice: number | null | undefined
|
||||
) {
|
||||
// If disableRescheduling is true, rescheduling is always disabled
|
||||
if (disableRescheduling === true) {
|
||||
return { disabled: true };
|
||||
}
|
||||
|
||||
// If minimumRescheduleNotice is set, rescheduling is conditionally disabled
|
||||
if (minimumRescheduleNotice && minimumRescheduleNotice > 0) {
|
||||
return { disabled: false, minutesBefore: minimumRescheduleNotice };
|
||||
}
|
||||
|
||||
// Otherwise rescheduling is not disabled
|
||||
return { disabled: false };
|
||||
}
|
||||
|
||||
transformDisableCancelling(disableCancelling: boolean | null | undefined) {
|
||||
return { disabled: disableCancelling === true };
|
||||
}
|
||||
|
||||
transformCalVideoSettings(
|
||||
calVideoSettings: CalVideoSettings | null | undefined,
|
||||
canSendCalVideoTranscriptionEmails: boolean | null | undefined
|
||||
) {
|
||||
if (!calVideoSettings && canSendCalVideoTranscriptionEmails === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
...calVideoSettings,
|
||||
sendTranscriptionEmails: canSendCalVideoTranscriptionEmails ?? true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+18
-1
@@ -29,6 +29,10 @@ export type InputEventTransformed_2024_06_14 = Omit<
|
||||
| "seats"
|
||||
| "customName"
|
||||
| "useDestinationCalendarEmail"
|
||||
| "disableRescheduling"
|
||||
| "disableCancelling"
|
||||
| "calVideoSettings"
|
||||
| "bookerActiveBookingsLimit"
|
||||
> & {
|
||||
length: number;
|
||||
slug: string;
|
||||
@@ -38,10 +42,23 @@ export type InputEventTransformed_2024_06_14 = Omit<
|
||||
bookingFields?: ReturnType<typeof transformBookingFieldsApiToInternal>;
|
||||
durationLimits?: ReturnType<typeof transformIntervalLimitsApiToInternal>;
|
||||
recurringEvent?: ReturnType<typeof transformRecurrenceApiToInternal>;
|
||||
maxActiveBookingsPerBooker?: number;
|
||||
maxActiveBookingsPerBooker?: number | null;
|
||||
maxActiveBookingPerBookerOfferReschedule?: boolean;
|
||||
eventTypeColor?: ReturnType<typeof transformEventColorsApiToInternal>;
|
||||
useEventTypeDestinationCalendarEmail?: boolean;
|
||||
disableRescheduling?: boolean;
|
||||
disableCancelling?: boolean;
|
||||
minimumRescheduleNotice?: number | null;
|
||||
canSendCalVideoTranscriptionEmails?: boolean;
|
||||
calVideoSettings?: {
|
||||
disableRecordingForOrganizer?: boolean;
|
||||
disableRecordingForGuests?: boolean;
|
||||
redirectUrlOnExit?: string | null;
|
||||
enableAutomaticRecordingForOrganizer?: boolean;
|
||||
enableAutomaticTranscription?: boolean;
|
||||
disableTranscriptionForGuests?: boolean;
|
||||
disableTranscriptionForOrganizer?: boolean;
|
||||
};
|
||||
} & Partial<
|
||||
Pick<ConfirmationPolicyTransformedSchema, "requiresConfirmation" | "requiresConfirmationWillBlockSlot">
|
||||
> &
|
||||
|
||||
@@ -88,6 +88,14 @@ type Input = Pick<
|
||||
| "rescheduleWithSameRoundRobinHost"
|
||||
| "maxActiveBookingPerBookerOfferReschedule"
|
||||
| "maxActiveBookingsPerBooker"
|
||||
| "disableCancelling"
|
||||
| "disableRescheduling"
|
||||
| "minimumRescheduleNotice"
|
||||
| "canSendCalVideoTranscriptionEmails"
|
||||
| "interfaceLanguage"
|
||||
| "allowReschedulingPastBookings"
|
||||
| "allowReschedulingCancelledBookings"
|
||||
| "showOptimizedSlots"
|
||||
| "rrHostSubsetEnabled"
|
||||
>;
|
||||
|
||||
|
||||
@@ -19114,6 +19114,31 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"DisableRescheduling_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"disabled": {
|
||||
"type": "boolean",
|
||||
"description": "If true, rescheduling is always disabled for this event type.",
|
||||
"example": true
|
||||
},
|
||||
"minutesBefore": {
|
||||
"type": "number",
|
||||
"description": "Disable rescheduling when less than the specified number of minutes before the meeting. If set, `disabled` should be false or undefined.",
|
||||
"example": 60
|
||||
}
|
||||
}
|
||||
},
|
||||
"DisableCancelling_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"disabled": {
|
||||
"type": "boolean",
|
||||
"description": "If true, cancelling is always disabled for this event type.",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"CalVideoSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -19144,6 +19169,11 @@
|
||||
"disableTranscriptionForOrganizer": {
|
||||
"type": "boolean",
|
||||
"description": "If true, the organizer will not be able to receive transcription of the meeting"
|
||||
},
|
||||
"sendTranscriptionEmails": {
|
||||
"type": "boolean",
|
||||
"description": "Send emails with the transcription of the Cal Video after the meeting ends.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -19417,6 +19447,88 @@
|
||||
"default": false,
|
||||
"description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type."
|
||||
},
|
||||
"disableCancelling": {
|
||||
"description": "Settings for disabling cancelling of this event type.",
|
||||
"example": {
|
||||
"disabled": true
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableCancelling_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"disableRescheduling": {
|
||||
"description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.",
|
||||
"example": {
|
||||
"disabled": false,
|
||||
"minutesBefore": 60
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableRescheduling_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"interfaceLanguage": {
|
||||
"type": "string",
|
||||
"description": "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).",
|
||||
"enum": [
|
||||
"",
|
||||
"en",
|
||||
"ar",
|
||||
"az",
|
||||
"bg",
|
||||
"bn",
|
||||
"ca",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"el",
|
||||
"es",
|
||||
"es-419",
|
||||
"eu",
|
||||
"et",
|
||||
"fi",
|
||||
"fr",
|
||||
"he",
|
||||
"hu",
|
||||
"it",
|
||||
"ja",
|
||||
"km",
|
||||
"ko",
|
||||
"nl",
|
||||
"no",
|
||||
"pl",
|
||||
"pt-BR",
|
||||
"pt",
|
||||
"ro",
|
||||
"ru",
|
||||
"sk-SK",
|
||||
"sr",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-CN",
|
||||
"zh-TW"
|
||||
]
|
||||
},
|
||||
"allowReschedulingPastBookings": {
|
||||
"type": "boolean",
|
||||
"description": "Enabling this option allows for past events to be rescheduled.",
|
||||
"default": false
|
||||
},
|
||||
"allowReschedulingCancelledBookings": {
|
||||
"type": "boolean",
|
||||
"description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.",
|
||||
"default": false
|
||||
},
|
||||
"showOptimizedSlots": {
|
||||
"type": "boolean",
|
||||
"description": "Arrange time slots to optimize availability.",
|
||||
"default": false
|
||||
},
|
||||
"locations": {
|
||||
"type": "array",
|
||||
"description": "Locations where the event will take place. If not provided, cal video link will be used as the location. Note: Setting a location to a conferencing app does not install the app - the app must already be installed. Via API, only Google Meet (google-meet), Microsoft Teams (office365-video), and Zoom (zoom) can be installed. Cal Video (cal-video) is installed by default. All other conferencing apps must be connected via the Cal.com web app and are not available for Platform plan customers. You can only set an event type location to an app that has already been installed or connected.",
|
||||
@@ -20528,6 +20640,31 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"DisableCancellingOutput_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"disabled": {
|
||||
"type": "boolean",
|
||||
"description": "If true, cancelling is always disabled for this event type.",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"DisableReschedulingOutput_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"disabled": {
|
||||
"type": "boolean",
|
||||
"description": "If true, rescheduling is always disabled for this event type.",
|
||||
"example": true
|
||||
},
|
||||
"minutesBefore": {
|
||||
"type": "number",
|
||||
"description": "Rescheduling is disabled when less than the specified number of minutes before the meeting.",
|
||||
"example": 60
|
||||
}
|
||||
}
|
||||
},
|
||||
"EventTypeOutput_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -20796,6 +20933,41 @@
|
||||
"type": "boolean",
|
||||
"description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type."
|
||||
},
|
||||
"disableCancelling": {
|
||||
"description": "Settings for disabling cancelling of this event type.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableCancellingOutput_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"disableRescheduling": {
|
||||
"description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableReschedulingOutput_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"interfaceLanguage": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Set preferred language for the booking interface."
|
||||
},
|
||||
"allowReschedulingPastBookings": {
|
||||
"type": "boolean",
|
||||
"description": "Enabling this option allows for past events to be rescheduled."
|
||||
},
|
||||
"allowReschedulingCancelledBookings": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking."
|
||||
},
|
||||
"showOptimizedSlots": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"description": "Arrange time slots to optimize availability."
|
||||
},
|
||||
"ownerId": {
|
||||
"type": "number",
|
||||
"example": 10
|
||||
@@ -21162,6 +21334,41 @@
|
||||
"type": "boolean",
|
||||
"description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type."
|
||||
},
|
||||
"disableCancelling": {
|
||||
"description": "Settings for disabling cancelling of this event type.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableCancellingOutput_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"disableRescheduling": {
|
||||
"description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableReschedulingOutput_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"interfaceLanguage": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "Set preferred language for the booking interface."
|
||||
},
|
||||
"allowReschedulingPastBookings": {
|
||||
"type": "boolean",
|
||||
"description": "Enabling this option allows for past events to be rescheduled."
|
||||
},
|
||||
"allowReschedulingCancelledBookings": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking."
|
||||
},
|
||||
"showOptimizedSlots": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"description": "Arrange time slots to optimize availability."
|
||||
},
|
||||
"teamId": {
|
||||
"type": "number"
|
||||
},
|
||||
@@ -21550,6 +21757,88 @@
|
||||
"default": false,
|
||||
"description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type."
|
||||
},
|
||||
"disableCancelling": {
|
||||
"description": "Settings for disabling cancelling of this event type.",
|
||||
"example": {
|
||||
"disabled": true
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableCancelling_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"disableRescheduling": {
|
||||
"description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.",
|
||||
"example": {
|
||||
"disabled": false,
|
||||
"minutesBefore": 60
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableRescheduling_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"interfaceLanguage": {
|
||||
"type": "string",
|
||||
"description": "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).",
|
||||
"enum": [
|
||||
"",
|
||||
"en",
|
||||
"ar",
|
||||
"az",
|
||||
"bg",
|
||||
"bn",
|
||||
"ca",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"el",
|
||||
"es",
|
||||
"es-419",
|
||||
"eu",
|
||||
"et",
|
||||
"fi",
|
||||
"fr",
|
||||
"he",
|
||||
"hu",
|
||||
"it",
|
||||
"ja",
|
||||
"km",
|
||||
"ko",
|
||||
"nl",
|
||||
"no",
|
||||
"pl",
|
||||
"pt-BR",
|
||||
"pt",
|
||||
"ro",
|
||||
"ru",
|
||||
"sk-SK",
|
||||
"sr",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-CN",
|
||||
"zh-TW"
|
||||
]
|
||||
},
|
||||
"allowReschedulingPastBookings": {
|
||||
"type": "boolean",
|
||||
"description": "Enabling this option allows for past events to be rescheduled.",
|
||||
"default": false
|
||||
},
|
||||
"allowReschedulingCancelledBookings": {
|
||||
"type": "boolean",
|
||||
"description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.",
|
||||
"default": false
|
||||
},
|
||||
"showOptimizedSlots": {
|
||||
"type": "boolean",
|
||||
"description": "Arrange time slots to optimize availability.",
|
||||
"default": false
|
||||
},
|
||||
"locations": {
|
||||
"type": "array",
|
||||
"description": "Locations where the event will take place. If not provided, cal video link will be used as the location. Note: Setting a location to a conferencing app does not install the app - the app must already be installed. Via API, only Google Meet (google-meet), Microsoft Teams (office365-video), and Zoom (zoom) can be installed. Cal Video (cal-video) is installed by default. All other conferencing apps must be connected via the Cal.com web app and are not available for Platform plan customers. You can only set an event type location to an app that has already been installed or connected.",
|
||||
@@ -23451,6 +23740,88 @@
|
||||
"default": false,
|
||||
"description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type."
|
||||
},
|
||||
"disableCancelling": {
|
||||
"description": "Settings for disabling cancelling of this event type.",
|
||||
"example": {
|
||||
"disabled": true
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableCancelling_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"disableRescheduling": {
|
||||
"description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.",
|
||||
"example": {
|
||||
"disabled": false,
|
||||
"minutesBefore": 60
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableRescheduling_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"interfaceLanguage": {
|
||||
"type": "string",
|
||||
"description": "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).",
|
||||
"enum": [
|
||||
"",
|
||||
"en",
|
||||
"ar",
|
||||
"az",
|
||||
"bg",
|
||||
"bn",
|
||||
"ca",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"el",
|
||||
"es",
|
||||
"es-419",
|
||||
"eu",
|
||||
"et",
|
||||
"fi",
|
||||
"fr",
|
||||
"he",
|
||||
"hu",
|
||||
"it",
|
||||
"ja",
|
||||
"km",
|
||||
"ko",
|
||||
"nl",
|
||||
"no",
|
||||
"pl",
|
||||
"pt-BR",
|
||||
"pt",
|
||||
"ro",
|
||||
"ru",
|
||||
"sk-SK",
|
||||
"sr",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-CN",
|
||||
"zh-TW"
|
||||
]
|
||||
},
|
||||
"allowReschedulingPastBookings": {
|
||||
"type": "boolean",
|
||||
"description": "Enabling this option allows for past events to be rescheduled.",
|
||||
"default": false
|
||||
},
|
||||
"allowReschedulingCancelledBookings": {
|
||||
"type": "boolean",
|
||||
"description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.",
|
||||
"default": false
|
||||
},
|
||||
"showOptimizedSlots": {
|
||||
"type": "boolean",
|
||||
"description": "Arrange time slots to optimize availability.",
|
||||
"default": false
|
||||
},
|
||||
"schedulingType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -23962,6 +24333,88 @@
|
||||
"default": false,
|
||||
"description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type."
|
||||
},
|
||||
"disableCancelling": {
|
||||
"description": "Settings for disabling cancelling of this event type.",
|
||||
"example": {
|
||||
"disabled": true
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableCancelling_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"disableRescheduling": {
|
||||
"description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.",
|
||||
"example": {
|
||||
"disabled": false,
|
||||
"minutesBefore": 60
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DisableRescheduling_2024_06_14"
|
||||
}
|
||||
]
|
||||
},
|
||||
"interfaceLanguage": {
|
||||
"type": "string",
|
||||
"description": "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).",
|
||||
"enum": [
|
||||
"",
|
||||
"en",
|
||||
"ar",
|
||||
"az",
|
||||
"bg",
|
||||
"bn",
|
||||
"ca",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"el",
|
||||
"es",
|
||||
"es-419",
|
||||
"eu",
|
||||
"et",
|
||||
"fi",
|
||||
"fr",
|
||||
"he",
|
||||
"hu",
|
||||
"it",
|
||||
"ja",
|
||||
"km",
|
||||
"ko",
|
||||
"nl",
|
||||
"no",
|
||||
"pl",
|
||||
"pt-BR",
|
||||
"pt",
|
||||
"ro",
|
||||
"ru",
|
||||
"sk-SK",
|
||||
"sr",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-CN",
|
||||
"zh-TW"
|
||||
]
|
||||
},
|
||||
"allowReschedulingPastBookings": {
|
||||
"type": "boolean",
|
||||
"description": "Enabling this option allows for past events to be rescheduled.",
|
||||
"default": false
|
||||
},
|
||||
"allowReschedulingCancelledBookings": {
|
||||
"type": "boolean",
|
||||
"description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.",
|
||||
"default": false
|
||||
},
|
||||
"showOptimizedSlots": {
|
||||
"type": "boolean",
|
||||
"description": "Arrange time slots to optimize availability.",
|
||||
"default": false
|
||||
},
|
||||
"schedulingType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"version": 1.2,
|
||||
"_comment": "When adding new locales, also update SUPPORTED_LOCALES in packages/platform/constants/api.ts",
|
||||
"locale": {
|
||||
"source": "en",
|
||||
"targets": [
|
||||
|
||||
@@ -71,3 +71,47 @@ export type API_VERSIONS_ENUM = (typeof API_VERSIONS)[number];
|
||||
export type API_VERSIONS_TYPE = typeof API_VERSIONS;
|
||||
export const CAL_API_VERSION_HEADER = "cal-api-version";
|
||||
export const MAX_SEATS_PER_TIME_SLOT = 1000;
|
||||
|
||||
// Keep in sync with i18n.json locale.targets
|
||||
export const SUPPORTED_LOCALES = [
|
||||
"",
|
||||
"en",
|
||||
"ar",
|
||||
"az",
|
||||
"bg",
|
||||
"bn",
|
||||
"ca",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"el",
|
||||
"es",
|
||||
"es-419",
|
||||
"eu",
|
||||
"et",
|
||||
"fi",
|
||||
"fr",
|
||||
"he",
|
||||
"hu",
|
||||
"it",
|
||||
"ja",
|
||||
"km",
|
||||
"ko",
|
||||
"nl",
|
||||
"no",
|
||||
"pl",
|
||||
"pt-BR",
|
||||
"pt",
|
||||
"ro",
|
||||
"ru",
|
||||
"sk-SK",
|
||||
"sr",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-CN",
|
||||
"zh-TW",
|
||||
] as const;
|
||||
|
||||
export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
|
||||
|
||||
+71
-1
@@ -18,12 +18,16 @@ import {
|
||||
ValidateNested,
|
||||
ArrayNotEmpty,
|
||||
ArrayUnique,
|
||||
IsIn,
|
||||
} from "class-validator";
|
||||
|
||||
import { SUPPORTED_LOCALES } from "@calcom/platform-constants";
|
||||
import { SchedulingType } from "@calcom/platform-enums";
|
||||
|
||||
import { RequiresAtLeastOnePropertyWhenNotDisabled } from "../../../utils/RequiresOneOfPropertiesWhenNotDisabled";
|
||||
import { BookerActiveBookingsLimit_2024_06_14 } from "./booker-active-booking-limit.input";
|
||||
import { DisableCancelling_2024_06_14 } from "./disable-cancelling.input";
|
||||
import { DisableRescheduling_2024_06_14 } from "./disable-rescheduling.input";
|
||||
import { BookerLayouts_2024_06_14 } from "./booker-layouts.input";
|
||||
import {
|
||||
AddressFieldInput_2024_06_14,
|
||||
@@ -129,7 +133,9 @@ export const CREATE_EVENT_SLUG_EXAMPLE = "learn-the-secrets-of-masterchief";
|
||||
GuestsDefaultFieldInput_2024_06_14,
|
||||
RescheduleReasonDefaultFieldInput_2024_06_14,
|
||||
InputOrganizersDefaultApp_2024_06_14,
|
||||
EmailSettings_2024_06_14
|
||||
EmailSettings_2024_06_14,
|
||||
DisableRescheduling_2024_06_14,
|
||||
DisableCancelling_2024_06_14
|
||||
)
|
||||
export class CalVideoSettings {
|
||||
@IsOptional()
|
||||
@@ -180,6 +186,14 @@ export class CalVideoSettings {
|
||||
description: "If true, the organizer will not be able to receive transcription of the meeting",
|
||||
})
|
||||
disableTranscriptionForOrganizer?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@DocsPropertyOptional({
|
||||
description: "Send emails with the transcription of the Cal Video after the meeting ends.",
|
||||
default: true,
|
||||
})
|
||||
sendTranscriptionEmails?: boolean;
|
||||
}
|
||||
|
||||
@CantHaveRecurrenceAndBookerActiveBookingsLimit()
|
||||
@@ -513,6 +527,62 @@ export class BaseCreateEventTypeInput {
|
||||
"Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type.",
|
||||
})
|
||||
bookingRequiresAuthentication?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateNested()
|
||||
@Type(() => DisableCancelling_2024_06_14)
|
||||
@DocsPropertyOptional({
|
||||
description: "Settings for disabling cancelling of this event type.",
|
||||
type: DisableCancelling_2024_06_14,
|
||||
example: { disabled: true },
|
||||
})
|
||||
disableCancelling?: DisableCancelling_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateNested()
|
||||
@Type(() => DisableRescheduling_2024_06_14)
|
||||
@DocsPropertyOptional({
|
||||
description:
|
||||
"Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.",
|
||||
type: DisableRescheduling_2024_06_14,
|
||||
example: { disabled: false, minutesBefore: 60 },
|
||||
})
|
||||
disableRescheduling?: DisableRescheduling_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@IsIn([...SUPPORTED_LOCALES])
|
||||
@DocsPropertyOptional({
|
||||
description:
|
||||
"Set preferred language for the booking interface. Use empty string for visitor's browser language (default).",
|
||||
enum: SUPPORTED_LOCALES,
|
||||
})
|
||||
interfaceLanguage?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@DocsPropertyOptional({
|
||||
description: "Enabling this option allows for past events to be rescheduled.",
|
||||
default: false,
|
||||
})
|
||||
allowReschedulingPastBookings?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@DocsPropertyOptional({
|
||||
description:
|
||||
"When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.",
|
||||
default: false,
|
||||
})
|
||||
allowReschedulingCancelledBookings?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@DocsPropertyOptional({
|
||||
description: "Arrange time slots to optimize availability.",
|
||||
default: false,
|
||||
})
|
||||
showOptimizedSlots?: boolean;
|
||||
}
|
||||
export class CreateEventTypeInput_2024_06_14 extends BaseCreateEventTypeInput {
|
||||
@IsOptional()
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsBoolean, IsOptional } from "class-validator";
|
||||
|
||||
export class DisableCancelling_2024_06_14 {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiPropertyOptional({
|
||||
description: "If true, cancelling is always disabled for this event type.",
|
||||
example: true,
|
||||
})
|
||||
disabled?: boolean;
|
||||
|
||||
// Note: minutesBefore can be added later when the feature is implemented for cancelling
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsBoolean, IsInt, IsOptional, Min } from "class-validator";
|
||||
|
||||
export class DisableRescheduling_2024_06_14 {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiPropertyOptional({
|
||||
description: "If true, rescheduling is always disabled for this event type.",
|
||||
example: true,
|
||||
})
|
||||
disabled?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
"Disable rescheduling when less than the specified number of minutes before the meeting. If set, `disabled` should be false or undefined.",
|
||||
example: 60,
|
||||
})
|
||||
minutesBefore?: number;
|
||||
}
|
||||
|
||||
@@ -14,3 +14,5 @@ export * from "./event-type-color.input";
|
||||
export * from "./seats.input";
|
||||
export * from "./destination-calendar.input";
|
||||
export * from "./disabled.input";
|
||||
export * from "./disable-rescheduling.input";
|
||||
export * from "./disable-cancelling.input";
|
||||
|
||||
+62
-1
@@ -19,6 +19,7 @@ import {
|
||||
IsIn,
|
||||
} from "class-validator";
|
||||
|
||||
import { SUPPORTED_LOCALES } from "@calcom/platform-constants";
|
||||
import { SchedulingType } from "@calcom/platform-enums";
|
||||
|
||||
import { RequiresAtLeastOnePropertyWhenNotDisabled } from "../../../utils/RequiresOneOfPropertiesWhenNotDisabled";
|
||||
@@ -70,6 +71,8 @@ import {
|
||||
Host,
|
||||
CalVideoSettings,
|
||||
} from "./create-event-type.input";
|
||||
import { DisableCancelling_2024_06_14 } from "./disable-cancelling.input";
|
||||
import { DisableRescheduling_2024_06_14 } from "./disable-rescheduling.input";
|
||||
import { DestinationCalendar_2024_06_14 } from "./destination-calendar.input";
|
||||
import { Disabled_2024_06_14 } from "./disabled.input";
|
||||
import { EmailSettings_2024_06_14 } from "./email-settings.input";
|
||||
@@ -127,7 +130,9 @@ import { CantHaveRecurrenceAndBookerActiveBookingsLimit } from "./validators/Can
|
||||
GuestsDefaultFieldInput_2024_06_14,
|
||||
RescheduleReasonDefaultFieldInput_2024_06_14,
|
||||
BookerActiveBookingsLimit_2024_06_14,
|
||||
EmailSettings_2024_06_14
|
||||
EmailSettings_2024_06_14,
|
||||
DisableRescheduling_2024_06_14,
|
||||
DisableCancelling_2024_06_14
|
||||
)
|
||||
@CantHaveRecurrenceAndBookerActiveBookingsLimit()
|
||||
class BaseUpdateEventTypeInput {
|
||||
@@ -461,6 +466,62 @@ class BaseUpdateEventTypeInput {
|
||||
"Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type.",
|
||||
})
|
||||
bookingRequiresAuthentication?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateNested()
|
||||
@Type(() => DisableCancelling_2024_06_14)
|
||||
@DocsPropertyOptional({
|
||||
description: "Settings for disabling cancelling of this event type.",
|
||||
type: DisableCancelling_2024_06_14,
|
||||
example: { disabled: true },
|
||||
})
|
||||
disableCancelling?: DisableCancelling_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateNested()
|
||||
@Type(() => DisableRescheduling_2024_06_14)
|
||||
@DocsPropertyOptional({
|
||||
description:
|
||||
"Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.",
|
||||
type: DisableRescheduling_2024_06_14,
|
||||
example: { disabled: false, minutesBefore: 60 },
|
||||
})
|
||||
disableRescheduling?: DisableRescheduling_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@IsIn([...SUPPORTED_LOCALES])
|
||||
@DocsPropertyOptional({
|
||||
description:
|
||||
"Set preferred language for the booking interface. Use empty string for visitor's browser language (default).",
|
||||
enum: SUPPORTED_LOCALES,
|
||||
})
|
||||
interfaceLanguage?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@DocsPropertyOptional({
|
||||
description: "Enabling this option allows for past events to be rescheduled.",
|
||||
default: false,
|
||||
})
|
||||
allowReschedulingPastBookings?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@DocsPropertyOptional({
|
||||
description:
|
||||
"When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.",
|
||||
default: false,
|
||||
})
|
||||
allowReschedulingCancelledBookings?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@DocsPropertyOptional({
|
||||
description: "Arrange time slots to optimize availability.",
|
||||
default: false,
|
||||
})
|
||||
showOptimizedSlots?: boolean;
|
||||
}
|
||||
export class UpdateEventTypeInput_2024_06_14 extends BaseUpdateEventTypeInput {
|
||||
@IsOptional()
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsBoolean, IsOptional } from "class-validator";
|
||||
|
||||
export class DisableCancellingOutput_2024_06_14 {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiPropertyOptional({
|
||||
description: "If true, cancelling is always disabled for this event type.",
|
||||
example: true,
|
||||
})
|
||||
disabled?: boolean;
|
||||
|
||||
// Note: minutesBefore can be added later when the feature is implemented for cancelling
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsBoolean, IsInt, IsOptional, Min } from "class-validator";
|
||||
|
||||
export class DisableReschedulingOutput_2024_06_14 {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiPropertyOptional({
|
||||
description: "If true, rescheduling is always disabled for this event type.",
|
||||
example: true,
|
||||
})
|
||||
disabled?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
"Rescheduling is disabled when less than the specified number of minutes before the meeting.",
|
||||
example: 60,
|
||||
})
|
||||
minutesBefore?: number;
|
||||
}
|
||||
|
||||
+56
@@ -59,6 +59,8 @@ import {
|
||||
UrlFieldOutput_2024_06_14,
|
||||
} from "../outputs/booking-fields.output";
|
||||
import { BookerActiveBookingsLimitOutput_2024_06_14 } from "./booker-active-bookings-limit.output";
|
||||
import { DisableCancellingOutput_2024_06_14 } from "./disable-cancelling.output";
|
||||
import { DisableReschedulingOutput_2024_06_14 } from "./disable-rescheduling.output";
|
||||
import type { OutputBookingField_2024_06_14 } from "./booking-fields.output";
|
||||
import { ValidateOutputBookingFields_2024_06_14 } from "./booking-fields.output";
|
||||
import type { OutputLocation_2024_06_14 } from "./locations.output";
|
||||
@@ -461,6 +463,60 @@ class BaseEventTypeOutput_2024_06_14 {
|
||||
"Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type.",
|
||||
})
|
||||
bookingRequiresAuthentication?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateNested()
|
||||
@Type(() => DisableCancellingOutput_2024_06_14)
|
||||
@ApiPropertyOptional({
|
||||
type: DisableCancellingOutput_2024_06_14,
|
||||
description: "Settings for disabling cancelling of this event type.",
|
||||
})
|
||||
disableCancelling?: DisableCancellingOutput_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateNested()
|
||||
@Type(() => DisableReschedulingOutput_2024_06_14)
|
||||
@ApiPropertyOptional({
|
||||
type: DisableReschedulingOutput_2024_06_14,
|
||||
description:
|
||||
"Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.",
|
||||
})
|
||||
disableRescheduling?: DisableReschedulingOutput_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiPropertyOptional({
|
||||
type: String,
|
||||
nullable: true,
|
||||
description: "Set preferred language for the booking interface.",
|
||||
})
|
||||
interfaceLanguage?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiPropertyOptional({
|
||||
description: "Enabling this option allows for past events to be rescheduled.",
|
||||
})
|
||||
allowReschedulingPastBookings?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiPropertyOptional({
|
||||
type: Boolean,
|
||||
nullable: true,
|
||||
description:
|
||||
"When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.",
|
||||
})
|
||||
allowReschedulingCancelledBookings?: boolean | null;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiPropertyOptional({
|
||||
type: Boolean,
|
||||
nullable: true,
|
||||
description: "Arrange time slots to optimize availability.",
|
||||
})
|
||||
showOptimizedSlots?: boolean | null;
|
||||
}
|
||||
|
||||
export class TeamEventTypeResponseHost extends TeamEventTypeHostInput {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export * from "./event-type.output";
|
||||
export * from "./booking-fields.output";
|
||||
export * from "./locations.output";
|
||||
export * from "./disable-rescheduling.output";
|
||||
export * from "./disable-cancelling.output";
|
||||
|
||||
Reference in New Issue
Block a user