feat: support updating cal video settings in API v2 (#21784)

* feat: support updating cal video settings in API v2

* chore: update descriptio

* feat: support create event type

* test: add test for updating event type

* test: add test for create event type

* chore: undo openapi

* chore: bump libraries

* Revert "chore: bump libraries"

This reverts commit bdf36d09b021fc531497a7b7ea66ab9c52b7d136.

* chore: bump libraries

---------

Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com>
Co-authored-by: supalarry <laurisskraucis@gmail.com>
This commit is contained in:
Udit Takkar
2025-06-13 12:05:29 +03:00
committed by GitHub
co-authored by Lauris Skraucis supalarry
parent 8de4897042
commit ba8a71bf3a
15 changed files with 669 additions and 2443 deletions
+1 -1
View File
@@ -37,7 +37,7 @@
"@axiomhq/winston": "^1.2.0",
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.215",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.217",
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
@@ -962,6 +962,10 @@ describe("Event types Endpoints", () => {
title: newTitle,
scheduleId: secondSchedule.id,
lengthInMinutesOptions: [15, 30],
calVideoSettings: {
disableRecordingForGuests: true,
disableRecordingForOrganizer: true,
},
bookingFields: [
nameBookingField,
{
@@ -1082,6 +1086,12 @@ describe("Event types Endpoints", () => {
body.lockTimeZoneToggleOnBookingPage
);
expect(updatedEventType.color).toEqual(body.color);
expect(updatedEventType.calVideoSettings?.disableRecordingForGuests).toEqual(
body.calVideoSettings?.disableRecordingForGuests
);
expect(updatedEventType.calVideoSettings?.disableRecordingForOrganizer).toEqual(
body.calVideoSettings?.disableRecordingForOrganizer
);
eventType.title = newTitle;
eventType.scheduleId = secondSchedule.id;
@@ -1841,6 +1851,40 @@ describe("Event types Endpoints", () => {
expect(slug2).not.toEqual(slug);
});
});
it("should create event type with cal video settings", async () => {
const body: CreateEventTypeInput_2024_06_14 = {
title: "event type with cal video settings",
slug: "event-type-with-cal-video-settings",
lengthInMinutes: 60,
calVideoSettings: {
disableRecordingForGuests: true,
disableRecordingForOrganizer: true,
},
locations: [
{
type: "integration",
integration: "cal-video",
},
],
};
return request(app.getHttpServer())
.post("/api/v2/event-types")
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
.send(body)
.expect(201)
.then(async (response) => {
const responseBody: ApiSuccessResponse<EventTypeOutput_2024_06_14> = response.body;
const createdEventType = responseBody.data;
expect(createdEventType).toHaveProperty("id");
expect(createdEventType.title).toEqual(body.title);
expect(createdEventType.locations).toEqual(body.locations);
expect(createdEventType.calVideoSettings?.disableRecordingForGuests).toEqual(true);
expect(createdEventType.calVideoSettings?.disableRecordingForOrganizer).toEqual(true);
firstCreatedEventType = responseBody.data;
});
});
});
afterAll(async () => {
@@ -12,13 +12,20 @@ export class EventTypesRepository_2024_06_14 {
userId: number,
body: Omit<InputEventTransformed_2024_06_14, "destinationCalendar">
) {
const { calVideoSettings, ...restBody } = body;
return this.dbWrite.prisma.eventType.create({
data: {
...body,
...restBody,
userId,
locations: body.locations,
bookingFields: body.bookingFields,
users: { connect: { id: userId } },
...(calVideoSettings && {
calVideoSettings: {
create: calVideoSettings,
},
}),
},
});
}
@@ -71,7 +78,7 @@ export class EventTypesRepository_2024_06_14 {
async getEventTypeById(eventTypeId: number) {
return this.dbRead.prisma.eventType.findUnique({
where: { id: eventTypeId },
include: { users: true, schedule: true, destinationCalendar: true },
include: { users: true, schedule: true, destinationCalendar: true, calVideoSettings: true },
});
}
@@ -15,7 +15,7 @@ import {
BookingFieldSchema,
} from "@/ee/event-types/event-types_2024_06_14/transformers";
import { Injectable } from "@nestjs/common";
import type { EventType, User, Schedule, DestinationCalendar } from "@prisma/client";
import type { EventType, User, Schedule, DestinationCalendar, CalVideoSettings } from "@prisma/client";
import {
userMetadata,
@@ -37,6 +37,7 @@ type EventTypeRelations = {
users: User[];
schedule: Schedule | null;
destinationCalendar?: DestinationCalendar | null;
calVideoSettings?: CalVideoSettings | null;
};
export type DatabaseEventType = Omit<EventType, "allowReschedulingCancelledBookings"> & EventTypeRelations;
@@ -87,6 +88,7 @@ type Input = Pick<
| "useEventTypeDestinationCalendarEmail"
| "hideCalendarEventDetails"
| "hideOrganizerEmail"
| "calVideoSettings"
>;
@Injectable()
@@ -124,6 +126,7 @@ export class OutputEventTypesService_2024_06_14 {
useEventTypeDestinationCalendarEmail,
hideCalendarEventDetails,
hideOrganizerEmail,
calVideoSettings,
} = databaseEventType;
const locations = this.transformLocations(databaseEventType.locations);
@@ -199,6 +202,7 @@ export class OutputEventTypesService_2024_06_14 {
useDestinationCalendarEmail: useEventTypeDestinationCalendarEmail,
hideCalendarEventDetails,
hideOrganizerEmail,
calVideoSettings,
};
}
@@ -2,7 +2,7 @@ import { OutputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types
import { TeamsEventTypesRepository } from "@/modules/teams/event-types/teams-event-types.repository";
import { UsersRepository } from "@/modules/users/users.repository";
import { Injectable } from "@nestjs/common";
import type { EventType, User, Schedule, Host, DestinationCalendar } from "@prisma/client";
import type { EventType, User, Schedule, Host, DestinationCalendar, CalVideoSettings } from "@prisma/client";
import { SchedulingType, Team } from "@prisma/client";
import { HostPriority, TeamEventTypeResponseHost } from "@calcom/platform-types";
@@ -16,6 +16,7 @@ type EventTypeRelations = {
Team,
"bannerUrl" | "name" | "logoUrl" | "slug" | "weekStart" | "brandColor" | "darkBrandColor" | "theme"
> | null;
calVideoSettings?: CalVideoSettings | null;
};
export type DatabaseTeamEventType = EventType & EventTypeRelations;
@@ -72,6 +73,7 @@ type Input = Pick<
| "hideCalendarEventDetails"
| "hideOrganizerEmail"
| "team"
| "calVideoSettings"
>;
@Injectable()
@@ -12,7 +12,13 @@ export class TeamsEventTypesRepository {
id: eventTypeId,
teamId,
},
include: { users: true, schedule: true, hosts: true, destinationCalendar: true },
include: {
users: true,
schedule: true,
hosts: true,
destinationCalendar: true,
calVideoSettings: true,
},
});
}
@@ -33,6 +39,7 @@ export class TeamsEventTypesRepository {
}
: true,
destinationCalendar: true,
calVideoSettings: true,
team: {
select: {
bannerUrl: true,
@@ -82,6 +89,7 @@ export class TeamsEventTypesRepository {
schedule: true,
hosts: true,
destinationCalendar: true,
calVideoSettings: true,
team: {
select: {
bannerUrl: true,
@@ -101,7 +109,13 @@ export class TeamsEventTypesRepository {
async getEventTypeById(eventTypeId: number) {
return this.dbRead.prisma.eventType.findUnique({
where: { id: eventTypeId },
include: { users: true, schedule: true, hosts: true, destinationCalendar: true },
include: {
users: true,
schedule: true,
hosts: true,
destinationCalendar: true,
calVideoSettings: true,
},
});
}
+127 -61
View File
@@ -13757,6 +13757,71 @@
"data"
]
},
"BookerLayouts_2024_06_14": {
"type": "object",
"properties": {
"defaultLayout": {
"type": "string",
"enum": [
"month",
"week",
"column"
]
},
"enabledLayouts": {
"type": "array",
"description": "Array of valid layouts - month, week or column",
"items": {
"type": "string",
"enum": [
"month",
"week",
"column"
]
}
}
},
"required": [
"defaultLayout",
"enabledLayouts"
]
},
"EventTypeColor_2024_06_14": {
"type": "object",
"properties": {
"lightThemeHex": {
"type": "string",
"description": "Color used for event types in light theme",
"example": "#292929"
},
"darkThemeHex": {
"type": "string",
"description": "Color used for event types in dark theme",
"example": "#fafafa"
}
},
"required": [
"lightThemeHex",
"darkThemeHex"
]
},
"DestinationCalendar_2024_06_14": {
"type": "object",
"properties": {
"integration": {
"type": "string",
"description": "The integration type of the destination calendar. Refer to the /api/v2/calendars endpoint to retrieve the integration type of your connected calendars."
},
"externalId": {
"type": "string",
"description": "The external ID of the destination calendar. Refer to the /api/v2/calendars endpoint to retrieve the external IDs of your connected calendars."
}
},
"required": [
"integration",
"externalId"
]
},
"InputAddressLocation_2024_06_14": {
"type": "object",
"properties": {
@@ -14873,70 +14938,22 @@
"type"
]
},
"BookerLayouts_2024_06_14": {
"CalVideoSettings": {
"type": "object",
"properties": {
"defaultLayout": {
"type": "string",
"enum": [
"month",
"week",
"column"
]
"disableRecordingForOrganizer": {
"type": "boolean",
"description": "If true, the organizer will not be able to record the meeting"
},
"enabledLayouts": {
"type": "array",
"description": "Array of valid layouts - month, week or column",
"items": {
"type": "string",
"enum": [
"month",
"week",
"column"
]
}
}
},
"required": [
"defaultLayout",
"enabledLayouts"
]
},
"EventTypeColor_2024_06_14": {
"type": "object",
"properties": {
"lightThemeHex": {
"type": "string",
"description": "Color used for event types in light theme",
"example": "#292929"
"disableRecordingForGuests": {
"type": "boolean",
"description": "If true, the guests will not be able to record the meeting"
},
"darkThemeHex": {
"type": "string",
"description": "Color used for event types in dark theme",
"example": "#fafafa"
"redirectUrlOnExit": {
"type": "object",
"description": "URL to which participants are redirected when they exit the call"
}
},
"required": [
"lightThemeHex",
"darkThemeHex"
]
},
"DestinationCalendar_2024_06_14": {
"type": "object",
"properties": {
"integration": {
"type": "string",
"description": "The integration type of the destination calendar. Refer to the /api/v2/calendars endpoint to retrieve the integration type of your connected calendars."
},
"externalId": {
"type": "string",
"description": "The external ID of the destination calendar. Refer to the /api/v2/calendars endpoint to retrieve the external IDs of your connected calendars."
}
},
"required": [
"integration",
"externalId"
]
}
},
"CreateEventTypeInput_2024_06_14": {
"type": "object",
@@ -15160,7 +15177,7 @@
},
"customName": {
"type": "string",
"description": "Customizable event name with valid variables: \n {Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name}, \n {Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION}, \n {HOST/ATTENDEE}, {HOST}, {ATTENDEE}, {USER}",
"description": "Customizable event name with valid variables:\n {Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name},\n {Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION},\n {HOST/ATTENDEE}, {HOST}, {ATTENDEE}, {USER}",
"example": "{Event type title} between {Organiser} and {Scheduler}"
},
"destinationCalendar": {
@@ -15181,6 +15198,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"locations": {
"type": "array",
"description": "Locations where the event will take place. If not provided, cal video link will be used as the location.",
@@ -16834,6 +16859,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"ownerId": {
"type": "number",
"example": 10
@@ -17175,6 +17208,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"locations": {
"type": "array",
"description": "Locations where the event will take place. If not provided, cal video link will be used as the location.",
@@ -18974,7 +19015,7 @@
},
"customName": {
"type": "string",
"description": "Customizable event name with valid variables: \n {Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name}, \n {Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION}, \n {HOST/ATTENDEE}, {HOST}, {ATTENDEE}, {USER}",
"description": "Customizable event name with valid variables:\n {Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name},\n {Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION},\n {HOST/ATTENDEE}, {HOST}, {ATTENDEE}, {USER}",
"example": "{Event type title} between {Organiser} and {Scheduler}"
},
"destinationCalendar": {
@@ -18995,6 +19036,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"schedulingType": {
"type": "string",
"enum": [
@@ -19420,6 +19469,15 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"nullable": true,
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"teamId": {
"type": "number"
},
@@ -19858,6 +19916,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"hosts": {
"type": "array",
"items": {
+110 -44
View File
@@ -13073,6 +13073,54 @@
},
"required": ["status", "data"]
},
"BookerLayouts_2024_06_14": {
"type": "object",
"properties": {
"defaultLayout": {
"type": "string",
"enum": ["month", "week", "column"]
},
"enabledLayouts": {
"type": "array",
"description": "Array of valid layouts - month, week or column",
"items": {
"type": "string",
"enum": ["month", "week", "column"]
}
}
},
"required": ["defaultLayout", "enabledLayouts"]
},
"EventTypeColor_2024_06_14": {
"type": "object",
"properties": {
"lightThemeHex": {
"type": "string",
"description": "Color used for event types in light theme",
"example": "#292929"
},
"darkThemeHex": {
"type": "string",
"description": "Color used for event types in dark theme",
"example": "#fafafa"
}
},
"required": ["lightThemeHex", "darkThemeHex"]
},
"DestinationCalendar_2024_06_14": {
"type": "object",
"properties": {
"integration": {
"type": "string",
"description": "The integration type of the destination calendar. Refer to the /api/v2/calendars endpoint to retrieve the integration type of your connected calendars."
},
"externalId": {
"type": "string",
"description": "The external ID of the destination calendar. Refer to the /api/v2/calendars endpoint to retrieve the external IDs of your connected calendars."
}
},
"required": ["integration", "externalId"]
},
"InputAddressLocation_2024_06_14": {
"type": "object",
"properties": {
@@ -14000,53 +14048,22 @@
},
"required": ["type"]
},
"BookerLayouts_2024_06_14": {
"CalVideoSettings": {
"type": "object",
"properties": {
"defaultLayout": {
"type": "string",
"enum": ["month", "week", "column"]
"disableRecordingForOrganizer": {
"type": "boolean",
"description": "If true, the organizer will not be able to record the meeting"
},
"enabledLayouts": {
"type": "array",
"description": "Array of valid layouts - month, week or column",
"items": {
"type": "string",
"enum": ["month", "week", "column"]
}
}
},
"required": ["defaultLayout", "enabledLayouts"]
},
"EventTypeColor_2024_06_14": {
"type": "object",
"properties": {
"lightThemeHex": {
"type": "string",
"description": "Color used for event types in light theme",
"example": "#292929"
"disableRecordingForGuests": {
"type": "boolean",
"description": "If true, the guests will not be able to record the meeting"
},
"darkThemeHex": {
"type": "string",
"description": "Color used for event types in dark theme",
"example": "#fafafa"
"redirectUrlOnExit": {
"type": "object",
"description": "URL to which participants are redirected when they exit the call"
}
},
"required": ["lightThemeHex", "darkThemeHex"]
},
"DestinationCalendar_2024_06_14": {
"type": "object",
"properties": {
"integration": {
"type": "string",
"description": "The integration type of the destination calendar. Refer to the /api/v2/calendars endpoint to retrieve the integration type of your connected calendars."
},
"externalId": {
"type": "string",
"description": "The external ID of the destination calendar. Refer to the /api/v2/calendars endpoint to retrieve the external IDs of your connected calendars."
}
},
"required": ["integration", "externalId"]
}
},
"CreateEventTypeInput_2024_06_14": {
"type": "object",
@@ -14266,7 +14283,7 @@
},
"customName": {
"type": "string",
"description": "Customizable event name with valid variables: \n {Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name}, \n {Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION}, \n {HOST/ATTENDEE}, {HOST}, {ATTENDEE}, {USER}",
"description": "Customizable event name with valid variables:\n {Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name},\n {Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION},\n {HOST/ATTENDEE}, {HOST}, {ATTENDEE}, {USER}",
"example": "{Event type title} between {Organiser} and {Scheduler}"
},
"destinationCalendar": {
@@ -14287,6 +14304,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"locations": {
"type": "array",
"description": "Locations where the event will take place. If not provided, cal video link will be used as the location.",
@@ -15757,6 +15782,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"ownerId": {
"type": "number",
"example": 10
@@ -16076,6 +16109,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"locations": {
"type": "array",
"description": "Locations where the event will take place. If not provided, cal video link will be used as the location.",
@@ -17610,7 +17651,7 @@
},
"customName": {
"type": "string",
"description": "Customizable event name with valid variables: \n {Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name}, \n {Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION}, \n {HOST/ATTENDEE}, {HOST}, {ATTENDEE}, {USER}",
"description": "Customizable event name with valid variables:\n {Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name},\n {Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION},\n {HOST/ATTENDEE}, {HOST}, {ATTENDEE}, {USER}",
"example": "{Event type title} between {Organiser} and {Scheduler}"
},
"destinationCalendar": {
@@ -17631,6 +17672,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"schedulingType": {
"type": "string",
"enum": ["collective", "roundRobin", "managed"],
@@ -18025,6 +18074,15 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"nullable": true,
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"teamId": {
"type": "number"
},
@@ -18426,6 +18484,14 @@
"type": "boolean",
"description": "Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events"
},
"calVideoSettings": {
"description": "Cal video settings for the event type",
"allOf": [
{
"$ref": "#/components/schemas/CalVideoSettings"
}
]
},
"hosts": {
"type": "array",
"items": {
@@ -125,6 +125,9 @@ export class EventTypeRepository {
static async create(data: IEventType) {
return await prisma.eventType.create({
data: this.generateCreateEventTypeData(data),
include: {
calVideoSettings: true,
},
});
}
@@ -124,6 +124,29 @@ export const CREATE_EVENT_SLUG_EXAMPLE = "learn-the-secrets-of-masterchief";
RescheduleReasonDefaultFieldInput_2024_06_14,
InputOrganizersDefaultApp_2024_06_14
)
export class CalVideoSettings {
@IsOptional()
@IsBoolean()
@DocsPropertyOptional({
description: "If true, the organizer will not be able to record the meeting",
})
disableRecordingForOrganizer?: boolean;
@IsOptional()
@IsBoolean()
@DocsPropertyOptional({
description: "If true, the guests will not be able to record the meeting",
})
disableRecordingForGuests?: boolean;
@IsOptional()
@IsUrl()
@DocsPropertyOptional({
description: "URL to which participants are redirected when they exit the call",
})
redirectUrlOnExit?: string | null;
}
class BaseCreateEventTypeInput {
@IsInt()
@Min(1)
@@ -369,9 +392,9 @@ class BaseCreateEventTypeInput {
@IsOptional()
@IsString()
@DocsPropertyOptional({
description: `Customizable event name with valid variables:
{Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name},
{Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION},
description: `Customizable event name with valid variables:
{Event type title}, {Organiser}, {Scheduler}, {Location}, {Organiser first name},
{Scheduler first name}, {Scheduler last name}, {Event duration}, {LOCATION},
{HOST/ATTENDEE}, {HOST}, {ATTENDEE}, {USER}`,
example: "{Event type title} between {Organiser} and {Scheduler}",
})
@@ -407,6 +430,15 @@ class BaseCreateEventTypeInput {
"Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events",
})
hideOrganizerEmail?: boolean;
@IsOptional()
@ValidateNested()
@Type(() => CalVideoSettings)
@DocsPropertyOptional({
description: "Cal video settings for the event type",
type: CalVideoSettings,
})
calVideoSettings?: CalVideoSettings;
}
export class CreateEventTypeInput_2024_06_14 extends BaseCreateEventTypeInput {
@IsOptional()
@@ -457,6 +489,7 @@ export class Host {
@DocsPropertyOptional({ enum: HostPriority })
priority?: keyof typeof HostPriority = "medium";
}
export class CreateTeamEventTypeInput_2024_06_14 extends BaseCreateEventTypeInput {
@Transform(({ value }) => {
if (value === "collective") {
@@ -63,6 +63,7 @@ import {
CREATE_EVENT_SLUG_EXAMPLE,
CREATE_EVENT_TITLE_EXAMPLE,
Host,
CalVideoSettings,
} from "./create-event-type.input";
import { DestinationCalendar_2024_06_14 } from "./destination-calendar.input";
import { Disabled_2024_06_14 } from "./disabled.input";
@@ -404,6 +405,15 @@ class BaseUpdateEventTypeInput {
"Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events",
})
hideOrganizerEmail?: boolean;
@IsOptional()
@ValidateNested()
@Type(() => CalVideoSettings)
@DocsPropertyOptional({
description: "Cal video settings for the event type",
type: CalVideoSettings,
})
calVideoSettings?: CalVideoSettings;
}
export class UpdateEventTypeInput_2024_06_14 extends BaseUpdateEventTypeInput {
@IsOptional()
@@ -27,6 +27,7 @@ import {
BusinessDaysWindow_2024_06_14,
CalendarDaysWindow_2024_06_14,
RangeWindow_2024_06_14,
CalVideoSettings,
} from "../inputs";
import { Recurrence_2024_06_14 } from "../inputs";
import { BookerLayouts_2024_06_14 } from "../inputs/booker-layouts.input";
@@ -429,6 +430,15 @@ class BaseEventTypeOutput_2024_06_14 {
"Boolean to Hide organizer's email address from the booking screen, email notifications, and calendar events",
})
hideOrganizerEmail?: boolean;
@IsOptional()
@ValidateNested()
@Type(() => CalVideoSettings)
@ApiPropertyOptional({
description: "Cal video settings for the event type",
type: CalVideoSettings,
})
calVideoSettings?: CalVideoSettings | null;
}
export class TeamEventTypeResponseHost extends TeamEventTypeHostInput {
+11 -1
View File
@@ -5,6 +5,15 @@ import { MIN_EVENT_DURATION_MINUTES, MAX_EVENT_DURATION_MINUTES } from "@calcom/
// TODO: figure out why EventTypeModel is being called even if it's not imported here, causing a circular dependency
// import { _EventTypeModel } from "../eventtype";
const calVideoSettingsSchema = z
.object({
disableRecordingForGuests: z.boolean().optional().nullable(),
disableRecordingForOrganizer: z.boolean().optional().nullable(),
redirectUrlOnExit: z.string().url().optional().nullable(),
})
.optional()
.nullable();
export const createEventTypeInput = z.object({
title: z.string().min(1),
slug: imports.eventTypeSlug,
@@ -20,7 +29,8 @@ export const createEventTypeInput = z.object({
minimumBookingNotice: z.number().int().min(0).optional(),
beforeEventBuffer: z.number().int().min(0).optional(),
afterEventBuffer: z.number().int().min(0).optional(),
scheduleId: z.number().int().optional()
scheduleId: z.number().int().optional(),
calVideoSettings: calVideoSettingsSchema
})
.partial({ hidden: true, locations: true })
.refine((data) => (data.teamId ? data.teamId && data.schedulingType : true), {
@@ -1,6 +1,7 @@
import type { Prisma } from "@prisma/client";
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
import { DailyLocationType } from "@calcom/app-store/locations";
import { getDefaultLocations } from "@calcom/lib/server/getDefaultLocations";
import { EventTypeRepository } from "@calcom/lib/server/repository/eventType";
import type { PrismaClient } from "@calcom/prisma";
@@ -36,7 +37,15 @@ type CreateOptions = {
};
export const createHandler = async ({ ctx, input }: CreateOptions) => {
const { schedulingType, teamId, metadata, locations: inputLocations, scheduleId, ...rest } = input;
const {
schedulingType,
teamId,
metadata,
locations: inputLocations,
scheduleId,
calVideoSettings,
...rest
} = input;
const userId = ctx.user.id;
const isManagedEventType = schedulingType === SchedulingType.MANAGED;
@@ -45,6 +54,8 @@ export const createHandler = async ({ ctx, input }: CreateOptions) => {
const locations: EventTypeLocation[] =
inputLocations && inputLocations.length !== 0 ? inputLocations : await getDefaultLocations(ctx.user);
const isCalVideoLocationActive = locations.some((location) => location.type === DailyLocationType);
const data: Prisma.EventTypeCreateInput = {
...rest,
owner: teamId ? undefined : { connect: { id: userId } },
@@ -55,6 +66,16 @@ export const createHandler = async ({ ctx, input }: CreateOptions) => {
schedule: scheduleId ? { connect: { id: scheduleId } } : undefined,
};
if (isCalVideoLocationActive && calVideoSettings) {
data.calVideoSettings = {
create: {
disableRecordingForGuests: calVideoSettings.disableRecordingForGuests ?? false,
disableRecordingForOrganizer: calVideoSettings.disableRecordingForOrganizer ?? false,
redirectUrlOnExit: calVideoSettings.redirectUrlOnExit ?? null,
},
};
}
if (teamId && schedulingType) {
const hasMembership = await ctx.prisma.membership.findFirst({
where: {
+262 -2326
View File
File diff suppressed because it is too large Load Diff