feat: platform toggle calendar event creation (#21788)
* feat: add areCalendarEventsEnabled to PlatformOAuthClient table * feat: areCalendarEvents enabled in handleNewBooking and v2 * feat: v2 handle areCalendarEventsEnabled * feat: toggle areCalendarEventsEnabled on frontend * feat: enable areCalendarEventsEnabled for recurring,confirm,paid * refactor: use placeholder calendar event * remove merge conflicts * chore: bump libraries * chore: bump libraries
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
"@axiomhq/winston": "^1.2.0",
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-enums": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.220",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.222",
|
||||
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
|
||||
@@ -77,6 +77,7 @@ type OAuthRequestParams = {
|
||||
platformBookingUrl: string;
|
||||
platformBookingLocation?: string;
|
||||
arePlatformEmailsEnabled: boolean;
|
||||
areCalendarEventsEnabled: boolean;
|
||||
};
|
||||
|
||||
const DEFAULT_PLATFORM_PARAMS = {
|
||||
@@ -86,6 +87,7 @@ const DEFAULT_PLATFORM_PARAMS = {
|
||||
platformBookingUrl: "",
|
||||
arePlatformEmailsEnabled: false,
|
||||
platformBookingLocation: undefined,
|
||||
areCalendarEventsEnabled: false,
|
||||
};
|
||||
|
||||
@Controller({
|
||||
@@ -195,6 +197,7 @@ export class BookingsController_2024_04_15 {
|
||||
platformCancelUrl: bookingRequest.platformCancelUrl,
|
||||
platformBookingUrl: bookingRequest.platformBookingUrl,
|
||||
platformBookingLocation: bookingRequest.platformBookingLocation,
|
||||
areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
|
||||
});
|
||||
if (booking.userId && booking.uid && booking.startTime) {
|
||||
void (await this.billingService.increaseUsageByUserId(booking.userId, {
|
||||
@@ -428,7 +431,7 @@ export class BookingsController_2024_04_15 {
|
||||
|
||||
if (isEmbed) {
|
||||
// embed should ignore oauth client settings and enable emails by default
|
||||
return { ...res, arePlatformEmailsEnabled: true };
|
||||
return { ...res, arePlatformEmailsEnabled: true, areCalendarEventsEnabled: true };
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -440,6 +443,7 @@ export class BookingsController_2024_04_15 {
|
||||
res.platformRescheduleUrl = client.bookingRescheduleRedirectUri ?? "";
|
||||
res.platformBookingUrl = client.bookingRedirectUri ?? "";
|
||||
res.arePlatformEmailsEnabled = client.areEmailsEnabled ?? false;
|
||||
res.areCalendarEventsEnabled = client.areCalendarEventsEnabled;
|
||||
}
|
||||
return res;
|
||||
} catch (err) {
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
X_CAL_CLIENT_ID,
|
||||
} from "@calcom/platform-constants";
|
||||
import { AttendeeScheduledEmail, OrganizerScheduledEmail } from "@calcom/platform-libraries/emails";
|
||||
import { EventManager } from "@calcom/platform-libraries/event-types";
|
||||
import {
|
||||
CreateEventTypeInput_2024_06_14,
|
||||
FAILED_EVENT_TYPE_IDENTIFICATION_ERROR_MESSAGE,
|
||||
@@ -78,6 +79,8 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
const eventTypeSlug = `user-bookings-event-type-${randomString()}`;
|
||||
let recurringEventTypeId: number;
|
||||
const recurringEventTypeSlug = `user-bookings-event-type-${randomString()}`;
|
||||
let eventTypeRequiresConfirmationId: number;
|
||||
const eventTypeRequiresConfirmationSlug = `user-bookings-event-type-requires-confirmation-${randomString()}`;
|
||||
|
||||
let createdBooking: BookingOutput_2024_08_13;
|
||||
let rescheduledBooking: BookingOutput_2024_08_13;
|
||||
@@ -153,6 +156,17 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
);
|
||||
recurringEventTypeId = recurringEvent.id;
|
||||
|
||||
const eventTypeRequiresConfirmation = await eventTypesRepositoryFixture.create(
|
||||
{
|
||||
title: `user-bookings-2024-08-13-event-type-requires-confirmation-${randomString()}`,
|
||||
slug: eventTypeRequiresConfirmationSlug,
|
||||
length: 60,
|
||||
requiresConfirmation: true,
|
||||
},
|
||||
user.id
|
||||
);
|
||||
eventTypeRequiresConfirmationId = eventTypeRequiresConfirmation.id;
|
||||
|
||||
bookingInThePast = await bookingsRepositoryFixture.create({
|
||||
user: {
|
||||
connect: {
|
||||
@@ -2539,6 +2553,285 @@ describe("Bookings Endpoints 2024-08-13", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("calendar events", () => {
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
jest
|
||||
.spyOn(EventManager.prototype, "create")
|
||||
.mockImplementation(() => Promise.resolve({ results: [], referencesToCreate: [] }));
|
||||
});
|
||||
|
||||
describe("platform oAuth client has calendar events enabled", () => {
|
||||
beforeAll(async () => {
|
||||
await oauthClientRepositoryFixture.update(oAuthClient.id, {
|
||||
areCalendarEventsEnabled: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("should create calendar event when booking normal event", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 9, 0, 0)).toISOString(),
|
||||
eventTypeId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.id).toBeDefined();
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(EventManager.prototype.create).toHaveBeenCalledTimes(1);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibly recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should create calendar events when booking recurring event", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 10, 9, 0, 0)).toISOString(),
|
||||
eventTypeId: recurringEventTypeId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(EventManager.prototype.create).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("event type requires confirmation", () => {
|
||||
let bookingThatRequiresConfirmationUid: string;
|
||||
|
||||
it("should not create calendar event when booking event that requires confirmation", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 12, 9, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeRequiresConfirmationId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.id).toBeDefined();
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(EventManager.prototype.create).toHaveBeenCalledTimes(0);
|
||||
bookingThatRequiresConfirmationUid = data.uid;
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibly recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should create calendar event when confirming event that requires confirmation", async () => {
|
||||
return request(app.getHttpServer())
|
||||
.post(`/v2/bookings/${bookingThatRequiresConfirmationUid}/confirm`)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(200)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.id).toBeDefined();
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(EventManager.prototype.create).toHaveBeenCalledTimes(1);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibly recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("platform oAuth client has calendar events disabled", () => {
|
||||
beforeAll(async () => {
|
||||
await oauthClientRepositoryFixture.update(oAuthClient.id, {
|
||||
areCalendarEventsEnabled: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("should not create calendar event when booking", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 9, 10, 0, 0)).toISOString(),
|
||||
eventTypeId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
};
|
||||
|
||||
const beforeCreate = new Date();
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const afterCreate = new Date();
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.id).toBeDefined();
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(EventManager.prototype.create).toHaveBeenCalledTimes(0);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibly recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should not create calendar events when booking recurring event", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 11, 10, 0, 0)).toISOString(),
|
||||
eventTypeId: recurringEventTypeId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(EventManager.prototype.create).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("event type requires confirmation", () => {
|
||||
let bookingThatRequiresConfirmationUid: string;
|
||||
|
||||
it("should not create calendar event when booking event that requires confirmation", async () => {
|
||||
const body: CreateBookingInput_2024_08_13 = {
|
||||
start: new Date(Date.UTC(2040, 0, 12, 10, 0, 0)).toISOString(),
|
||||
eventTypeId: eventTypeRequiresConfirmationId,
|
||||
attendee: {
|
||||
name: "Mr Proper",
|
||||
email: "mr_proper@gmail.com",
|
||||
timeZone: "Europe/Rome",
|
||||
language: "it",
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/v2/bookings")
|
||||
.send(body)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.id).toBeDefined();
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(EventManager.prototype.create).toHaveBeenCalledTimes(0);
|
||||
bookingThatRequiresConfirmationUid = data.uid;
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibly recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should not create calendar event when confirming event that requires confirmation", async () => {
|
||||
return request(app.getHttpServer())
|
||||
.post(`/v2/bookings/${bookingThatRequiresConfirmationUid}/confirm`)
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
|
||||
.expect(200)
|
||||
.then(async (response) => {
|
||||
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(responseDataIsBooking(responseBody.data)).toBe(true);
|
||||
|
||||
if (responseDataIsBooking(responseBody.data)) {
|
||||
const data: BookingOutput_2024_08_13 = responseBody.data;
|
||||
expect(data.id).toBeDefined();
|
||||
expect(data.uid).toBeDefined();
|
||||
expect(EventManager.prototype.create).toHaveBeenCalledTimes(0);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Invalid response data - expected booking but received array of possibly recurring bookings"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function responseDataIsRecurranceBooking(data: any): data is RecurringBookingOutput_2024_08_13 {
|
||||
return (
|
||||
!Array.isArray(data) &&
|
||||
|
||||
@@ -404,6 +404,7 @@ export class BookingsService_2024_08_13 {
|
||||
platformBookingUrl: bookingRequest.platformBookingUrl,
|
||||
platformBookingLocation: bookingRequest.platformBookingLocation,
|
||||
noEmail: bookingRequest.noEmail,
|
||||
areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
|
||||
});
|
||||
const ids = bookings.map((booking) => booking.id || 0);
|
||||
return this.outputService.getOutputRecurringBookings(ids);
|
||||
@@ -424,6 +425,7 @@ export class BookingsService_2024_08_13 {
|
||||
platformCancelUrl: bookingRequest.platformCancelUrl,
|
||||
platformBookingUrl: bookingRequest.platformBookingUrl,
|
||||
platformBookingLocation: bookingRequest.platformBookingLocation,
|
||||
areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
|
||||
});
|
||||
return this.outputService.getOutputCreateRecurringSeatedBookings(
|
||||
bookings.map((booking) => ({ uid: booking.uid || "", seatUid: booking.seatReferenceUid || "" }))
|
||||
@@ -445,6 +447,7 @@ export class BookingsService_2024_08_13 {
|
||||
platformCancelUrl: bookingRequest.platformCancelUrl,
|
||||
platformBookingUrl: bookingRequest.platformBookingUrl,
|
||||
platformBookingLocation: bookingRequest.platformBookingLocation,
|
||||
areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
|
||||
});
|
||||
|
||||
if (!booking.uid) {
|
||||
@@ -475,6 +478,7 @@ export class BookingsService_2024_08_13 {
|
||||
platformCancelUrl: bookingRequest.platformCancelUrl,
|
||||
platformBookingUrl: bookingRequest.platformBookingUrl,
|
||||
platformBookingLocation: bookingRequest.platformBookingLocation,
|
||||
areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
|
||||
});
|
||||
|
||||
if (!booking.uid) {
|
||||
@@ -652,6 +656,7 @@ export class BookingsService_2024_08_13 {
|
||||
platformCancelUrl: bookingRequest.platformCancelUrl,
|
||||
platformBookingUrl: bookingRequest.platformBookingUrl,
|
||||
platformBookingLocation: bookingRequest.platformBookingLocation,
|
||||
areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
|
||||
});
|
||||
if (!booking.uid) {
|
||||
throw new Error("Booking missing uid");
|
||||
|
||||
@@ -59,6 +59,7 @@ type OAuthRequestParams = {
|
||||
platformBookingUrl: string;
|
||||
platformBookingLocation?: string;
|
||||
arePlatformEmailsEnabled: boolean;
|
||||
areCalendarEventsEnabled: boolean;
|
||||
};
|
||||
|
||||
export enum Frequency {
|
||||
|
||||
@@ -54,6 +54,7 @@ export class PlatformBookingsService {
|
||||
platformRescheduleUrl: oAuthClient.bookingRescheduleRedirectUri,
|
||||
platformBookingUrl: oAuthClient.bookingRedirectUri,
|
||||
arePlatformEmailsEnabled: oAuthClient.areEmailsEnabled,
|
||||
areCalendarEventsEnabled: oAuthClient.areCalendarEventsEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -78,6 +79,7 @@ export class PlatformBookingsService {
|
||||
platformRescheduleUrl: oAuthClient.bookingRescheduleRedirectUri,
|
||||
platformBookingUrl: oAuthClient.bookingRedirectUri,
|
||||
arePlatformEmailsEnabled: oAuthClient.areEmailsEnabled,
|
||||
areCalendarEventsEnabled: oAuthClient.areCalendarEventsEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ export class OAuthClientsOutputService {
|
||||
bookingRescheduleRedirectUri: client.bookingRescheduleRedirectUri ?? undefined,
|
||||
areEmailsEnabled: client.areEmailsEnabled,
|
||||
areDefaultEventTypesEnabled: client.areDefaultEventTypesEnabled,
|
||||
areCalendarEventsEnabled: client.areCalendarEventsEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13912,6 +13912,11 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "If true, when creating a managed user the managed user will have 4 default event types: 30 and 60 minutes without Cal video, 30 and 60 minutes with Cal video. Set this as false if you want to create a managed user and then manually create event types for the user."
|
||||
},
|
||||
"areCalendarEventsEnabled": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "If true and if managed user has calendar connected, calendar events will be created. Disable it if you manually create calendar events. Default to true."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -14034,6 +14039,11 @@
|
||||
"example": true,
|
||||
"description": "If enabled, when creating a managed user the managed user will have 4 default event types: 30 and 60 minutes without Cal video, 30 and 60 minutes with Cal video. Leave this disabled if you want to create a managed user and then manually create event types for the user."
|
||||
},
|
||||
"areCalendarEventsEnabled": {
|
||||
"type": "boolean",
|
||||
"example": true,
|
||||
"description": "If true and if managed user has calendar connected, calendar events will be created. Disable it if you manually create calendar events. Default to true."
|
||||
},
|
||||
"bookingRedirectUri": {
|
||||
"type": "string",
|
||||
"example": "https://example.com/booking-redirect"
|
||||
@@ -14056,7 +14066,8 @@
|
||||
"organizationId",
|
||||
"createdAt",
|
||||
"areEmailsEnabled",
|
||||
"areDefaultEventTypesEnabled"
|
||||
"areDefaultEventTypesEnabled",
|
||||
"areCalendarEventsEnabled"
|
||||
]
|
||||
},
|
||||
"GetOAuthClientsResponseDto": {
|
||||
@@ -14132,6 +14143,10 @@
|
||||
"areDefaultEventTypesEnabled": {
|
||||
"type": "boolean",
|
||||
"description": "If true, when creating a managed user the managed user will have 4 default event types: 30 and 60 minutes without Cal video, 30 and 60 minutes with Cal video. Set this as false if you want to create a managed user and then manually create event types for the user."
|
||||
},
|
||||
"areCalendarEventsEnabled": {
|
||||
"type": "boolean",
|
||||
"description": "If true and if managed user has calendar connected, calendar events will be created. Disable it if you manually create calendar events. Default to true."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -47,6 +47,13 @@ export class OAuthClientRepositoryFixture {
|
||||
});
|
||||
}
|
||||
|
||||
async update(clientId: PlatformOAuthClient["id"], data: Prisma.PlatformOAuthClientUpdateInput) {
|
||||
return this.prismaWriteClient.platformOAuthClient.update({
|
||||
where: { id: clientId },
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
async delete(clientId: PlatformOAuthClient["id"]) {
|
||||
return this.prismaWriteClient.platformOAuthClient.delete({ where: { id: clientId } });
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ export const OAuthClientsList = ({ oauthClients, isDeleting, handleDelete }: OAu
|
||||
onDelete={handleDelete}
|
||||
areEmailsEnabled={client.areEmailsEnabled}
|
||||
areDefaultEventTypesEnabled={client.areDefaultEventTypesEnabled}
|
||||
areCalendarEventsEnabled={client.areCalendarEventsEnabled}
|
||||
organizationId={client.organizationId}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -18,6 +18,7 @@ type OAuthClientCardProps = {
|
||||
bookingRescheduleRedirectUri: string | null | undefined;
|
||||
areEmailsEnabled: boolean | undefined;
|
||||
areDefaultEventTypesEnabled: boolean;
|
||||
areCalendarEventsEnabled: boolean;
|
||||
permissions: Array<keyof typeof PERMISSION_MAP>;
|
||||
lastItem: boolean;
|
||||
id: string;
|
||||
@@ -42,6 +43,7 @@ export const OAuthClientCard = ({
|
||||
isLoading,
|
||||
areEmailsEnabled,
|
||||
areDefaultEventTypesEnabled,
|
||||
areCalendarEventsEnabled,
|
||||
organizationId,
|
||||
}: OAuthClientCardProps) => {
|
||||
const router = useRouter();
|
||||
@@ -173,6 +175,10 @@ export const OAuthClientCard = ({
|
||||
<span className="text-sm font-semibold">Default event types enabled:</span>{" "}
|
||||
{areDefaultEventTypesEnabled ? "Yes" : "No"}
|
||||
</div>
|
||||
<div className="flex gap-1 text-sm">
|
||||
<span className="text-sm font-semibold">Calendar events enabled:</span>{" "}
|
||||
{areCalendarEventsEnabled ? "Yes" : "No"}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-4">
|
||||
<Button
|
||||
|
||||
@@ -37,6 +37,7 @@ export type FormValues = {
|
||||
bookingRescheduleRedirectUri?: string;
|
||||
areEmailsEnabled?: boolean;
|
||||
areDefaultEventTypesEnabled?: boolean;
|
||||
areCalendarEventsEnabled?: boolean;
|
||||
};
|
||||
|
||||
export const OAuthClientForm = ({
|
||||
@@ -236,6 +237,27 @@ export const OAuthClientForm = ({
|
||||
Enable emails
|
||||
</label>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
{...register("areCalendarEventsEnabled")}
|
||||
id="areCalendarEventsEnabled"
|
||||
className="bg-default border-default h-4 w-4 shrink-0 cursor-pointer rounded-[4px] border ring-offset-2 transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed"
|
||||
type="checkbox"
|
||||
disabled={isFormDisabled}
|
||||
/>
|
||||
<label htmlFor="areCalendarEventsEnabled" className="cursor-pointer px-2 text-base font-semibold">
|
||||
Enable calendar events
|
||||
</label>
|
||||
<Tooltip
|
||||
className="max-w-[400px] whitespace-normal"
|
||||
content="If enabled and the managed user has calendar connected, an event in the calendar will be created. By default true. Disable it if you want to create events in the calendar manually.">
|
||||
<div className="ml-1">
|
||||
<Icon name="info" className="h-4 w-4 text-gray-500" aria-hidden="true" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
|
||||
@@ -60,6 +60,7 @@ export default function EditOAuthClient() {
|
||||
bookingRescheduleRedirectUri: data.bookingRescheduleRedirectUri,
|
||||
areEmailsEnabled: data.areEmailsEnabled,
|
||||
areDefaultEventTypesEnabled: data.areDefaultEventTypesEnabled,
|
||||
areCalendarEventsEnabled: data.areCalendarEventsEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -87,6 +88,7 @@ export default function EditOAuthClient() {
|
||||
name: data?.name ?? "",
|
||||
areEmailsEnabled: data.areEmailsEnabled ?? false,
|
||||
areDefaultEventTypesEnabled: data.areDefaultEventTypesEnabled ?? false,
|
||||
areCalendarEventsEnabled: data.areCalendarEventsEnabled,
|
||||
redirectUris: data?.redirectUris?.map((uri) => ({ uri })) ?? [{ uri: "" }],
|
||||
bookingRedirectUri: data?.bookingRedirectUri ?? "",
|
||||
bookingCancelRedirectUri: data?.bookingCancelRedirectUri ?? "",
|
||||
|
||||
@@ -56,6 +56,7 @@ export default function CreateOAuthClient() {
|
||||
bookingRescheduleRedirectUri: data.bookingRescheduleRedirectUri,
|
||||
areEmailsEnabled: data.areEmailsEnabled,
|
||||
areDefaultEventTypesEnabled: data.areDefaultEventTypesEnabled,
|
||||
areCalendarEventsEnabled: data.areCalendarEventsEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -76,7 +77,24 @@ export default function CreateOAuthClient() {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<OAuthClientForm isPending={isSaving} onSubmit={onSubmit} />
|
||||
<OAuthClientForm
|
||||
isPending={isSaving}
|
||||
onSubmit={onSubmit}
|
||||
defaultValues={{
|
||||
areCalendarEventsEnabled: true,
|
||||
areEmailsEnabled: true,
|
||||
eventTypeRead: true,
|
||||
eventTypeWrite: true,
|
||||
bookingRead: true,
|
||||
bookingWrite: true,
|
||||
scheduleRead: true,
|
||||
scheduleWrite: true,
|
||||
appsRead: true,
|
||||
appsWrite: true,
|
||||
profileRead: true,
|
||||
profileWrite: true,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Shell>
|
||||
</div>
|
||||
|
||||
@@ -13254,6 +13254,11 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "If true, when creating a managed user the managed user will have 4 default event types: 30 and 60 minutes without Cal video, 30 and 60 minutes with Cal video. Set this as false if you want to create a managed user and then manually create event types for the user."
|
||||
},
|
||||
"areCalendarEventsEnabled": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "If true and if managed user has calendar connected, calendar events will be created. Disable it if you manually create calendar events. Default to true."
|
||||
}
|
||||
},
|
||||
"required": ["name", "redirectUris", "permissions"]
|
||||
@@ -13358,6 +13363,11 @@
|
||||
"example": true,
|
||||
"description": "If enabled, when creating a managed user the managed user will have 4 default event types: 30 and 60 minutes without Cal video, 30 and 60 minutes with Cal video. Leave this disabled if you want to create a managed user and then manually create event types for the user."
|
||||
},
|
||||
"areCalendarEventsEnabled": {
|
||||
"type": "boolean",
|
||||
"example": true,
|
||||
"description": "If true and if managed user has calendar connected, calendar events will be created. Disable it if you manually create calendar events. Default to true."
|
||||
},
|
||||
"bookingRedirectUri": {
|
||||
"type": "string",
|
||||
"example": "https://example.com/booking-redirect"
|
||||
@@ -13380,7 +13390,8 @@
|
||||
"organizationId",
|
||||
"createdAt",
|
||||
"areEmailsEnabled",
|
||||
"areDefaultEventTypesEnabled"
|
||||
"areDefaultEventTypesEnabled",
|
||||
"areCalendarEventsEnabled"
|
||||
]
|
||||
},
|
||||
"GetOAuthClientsResponseDto": {
|
||||
@@ -13444,6 +13455,10 @@
|
||||
"areDefaultEventTypesEnabled": {
|
||||
"type": "boolean",
|
||||
"description": "If true, when creating a managed user the managed user will have 4 default event types: 30 and 60 minutes without Cal video, 30 and 60 minutes with Cal video. Set this as false if you want to create a managed user and then manually create event types for the user."
|
||||
},
|
||||
"areCalendarEventsEnabled": {
|
||||
"type": "boolean",
|
||||
"description": "If true and if managed user has calendar connected, calendar events will be created. Disable it if you manually create calendar events. Default to true."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@ import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload";
|
||||
import type { EventPayloadType, EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser";
|
||||
import type { EventManagerUser } from "@calcom/lib/EventManager";
|
||||
import EventManager from "@calcom/lib/EventManager";
|
||||
import EventManager, { placeholderCreatedEvent } from "@calcom/lib/EventManager";
|
||||
import { getBookerBaseUrl } from "@calcom/lib/getBookerUrl/server";
|
||||
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
||||
import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType";
|
||||
@@ -88,7 +88,8 @@ export async function handleConfirmation(args: {
|
||||
const eventTypeMetadata = EventTypeMetaDataSchema.parse(eventType?.metadata || {});
|
||||
const apps = eventTypeAppMetadataOptionalSchema.parse(eventTypeMetadata?.apps);
|
||||
const eventManager = new EventManager(user, apps);
|
||||
const scheduleResult = await eventManager.create(evt);
|
||||
const areCalendarEventsEnabled = platformClientParams?.areCalendarEventsEnabled ?? true;
|
||||
const scheduleResult = areCalendarEventsEnabled ? await eventManager.create(evt) : placeholderCreatedEvent;
|
||||
const results = scheduleResult.results;
|
||||
const metadata: AdditionalInformation = {};
|
||||
const workflows = await getAllWorkflowsFromEventType(eventType, booking.userId);
|
||||
|
||||
@@ -43,7 +43,7 @@ import {
|
||||
scheduleTrigger,
|
||||
} from "@calcom/features/webhooks/lib/scheduleTrigger";
|
||||
import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser";
|
||||
import EventManager from "@calcom/lib/EventManager";
|
||||
import EventManager, { placeholderCreatedEvent } from "@calcom/lib/EventManager";
|
||||
import { handleAnalyticsEvents } from "@calcom/lib/analyticsManager/handleAnalyticsEvents";
|
||||
import { shouldIgnoreContactOwner } from "@calcom/lib/bookings/routing/utils";
|
||||
import { getUsernameList } from "@calcom/lib/defaultEvents";
|
||||
@@ -373,6 +373,7 @@ export type PlatformParams = {
|
||||
platformBookingUrl?: string;
|
||||
platformRescheduleUrl?: string;
|
||||
platformBookingLocation?: string;
|
||||
areCalendarEventsEnabled?: boolean;
|
||||
};
|
||||
|
||||
export type BookingHandlerInput = {
|
||||
@@ -397,6 +398,7 @@ async function handler(
|
||||
platformBookingLocation,
|
||||
hostname,
|
||||
forcedSlug,
|
||||
areCalendarEventsEnabled = true,
|
||||
} = input;
|
||||
|
||||
const isPlatformBooking = !!platformClientId;
|
||||
@@ -1737,7 +1739,7 @@ async function handler(
|
||||
// Create a booking
|
||||
} else if (isConfirmedByDefault) {
|
||||
// Use EventManager to conditionally use all needed integrations.
|
||||
const createManager = await eventManager.create(evt);
|
||||
const createManager = areCalendarEventsEnabled ? await eventManager.create(evt) : placeholderCreatedEvent;
|
||||
if (evt.location) {
|
||||
booking.location = evt.location;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ export type PlatformParams = {
|
||||
platformBookingUrl?: string;
|
||||
platformRescheduleUrl?: string;
|
||||
platformBookingLocation?: string;
|
||||
areCalendarEventsEnabled?: boolean;
|
||||
};
|
||||
|
||||
export type BookingHandlerInput = {
|
||||
@@ -45,6 +46,7 @@ export const handleNewRecurringBooking = async (input: BookingHandlerInput): Pro
|
||||
platformCancelUrl: input.platformCancelUrl,
|
||||
platformBookingUrl: input.platformBookingUrl,
|
||||
platformBookingLocation: input.platformBookingLocation,
|
||||
areCalendarEventsEnabled: input.areCalendarEventsEnabled,
|
||||
};
|
||||
|
||||
if (isRoundRobin) {
|
||||
|
||||
@@ -8,7 +8,9 @@ import { doesBookingRequireConfirmation } from "@calcom/features/bookings/lib/do
|
||||
import { getAllCredentialsIncludeServiceAccountKey } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { handleConfirmation } from "@calcom/features/bookings/lib/handleConfirmation";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import EventManager from "@calcom/lib/EventManager";
|
||||
import { getPlatformParams } from "@calcom/features/platform-oauth-client/get-platform-params";
|
||||
import { PlatformOAuthClientRepository } from "@calcom/features/platform-oauth-client/platform-oauth-client.repository";
|
||||
import EventManager, { placeholderCreatedEvent } from "@calcom/lib/EventManager";
|
||||
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
import { HttpError as HttpCode } from "@calcom/lib/http-error";
|
||||
@@ -80,9 +82,18 @@ const handleSetupSuccess = async (event: Stripe.Event) => {
|
||||
metadata,
|
||||
});
|
||||
|
||||
const platformOAuthClientRepository = new PlatformOAuthClientRepository();
|
||||
const platformOAuthClient = user.isPlatformManaged
|
||||
? await platformOAuthClientRepository.getByUserId(user.id)
|
||||
: null;
|
||||
const areCalendarEventsEnabled = platformOAuthClient?.areCalendarEventsEnabled ?? true;
|
||||
const areEmailsEnabled = platformOAuthClient?.areEmailsEnabled ?? true;
|
||||
|
||||
if (!requiresConfirmation) {
|
||||
const eventManager = new EventManager({ ...user, credentials: allCredentials }, metadata?.apps);
|
||||
const scheduleResult = await eventManager.create(evt);
|
||||
const scheduleResult = areCalendarEventsEnabled
|
||||
? await eventManager.create(evt)
|
||||
: placeholderCreatedEvent;
|
||||
bookingData.references = { create: scheduleResult.referencesToCreate };
|
||||
bookingData.status = BookingStatus.ACCEPTED;
|
||||
}
|
||||
@@ -114,8 +125,9 @@ const handleSetupSuccess = async (event: Stripe.Event) => {
|
||||
bookingId: booking.id,
|
||||
booking,
|
||||
paid: true,
|
||||
platformClientParams: platformOAuthClient ? getPlatformParams(platformOAuthClient) : undefined,
|
||||
});
|
||||
} else {
|
||||
} else if (areEmailsEnabled) {
|
||||
await sendOrganizerRequestEmail({ ...evt }, eventType.metadata);
|
||||
await sendAttendeeRequestEmailAndSMS({ ...evt }, evt.attendees[0], eventType.metadata);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { PlatformOAuthClient } from "@prisma/client";
|
||||
|
||||
export function getPlatformParams(platformOAuthClient: PlatformOAuthClient) {
|
||||
return {
|
||||
platformClientId: platformOAuthClient.id,
|
||||
platformCancelUrl: platformOAuthClient.bookingCancelRedirectUri,
|
||||
platformRescheduleUrl: platformOAuthClient.bookingRescheduleRedirectUri,
|
||||
platformBookingUrl: platformOAuthClient.bookingRedirectUri,
|
||||
arePlatformEmailsEnabled: platformOAuthClient.areEmailsEnabled,
|
||||
areCalendarEventsEnabled: platformOAuthClient.areCalendarEventsEnabled,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { PlatformOAuthClient } from "@prisma/client";
|
||||
|
||||
export interface IPlatformOAuthClientRepository {
|
||||
getByUserId(userId: number): Promise<PlatformOAuthClient | null>;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { captureException } from "@sentry/nextjs";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import type { IPlatformOAuthClientRepository } from "./platform-oauth-client.repository.interface";
|
||||
|
||||
export class PlatformOAuthClientRepository implements IPlatformOAuthClientRepository {
|
||||
async getByUserId(userId: number) {
|
||||
try {
|
||||
return prisma.platformOAuthClient.findFirst({
|
||||
where: {
|
||||
users: {
|
||||
some: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
captureException(err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1142,3 +1142,5 @@ export default class EventManager {
|
||||
return this.appOptions[credential.appId as keyof typeof this.appOptions];
|
||||
}
|
||||
}
|
||||
|
||||
export const placeholderCreatedEvent = { results: [], referencesToCreate: [] };
|
||||
|
||||
@@ -91,6 +91,7 @@ export async function getBooking(bookingId: number) {
|
||||
name: true,
|
||||
locale: true,
|
||||
destinationCalendar: true,
|
||||
isPlatformManaged: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -5,7 +5,9 @@ import { doesBookingRequireConfirmation } from "@calcom/features/bookings/lib/do
|
||||
import { getAllCredentialsIncludeServiceAccountKey } from "@calcom/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials";
|
||||
import { handleBookingRequested } from "@calcom/features/bookings/lib/handleBookingRequested";
|
||||
import { handleConfirmation } from "@calcom/features/bookings/lib/handleConfirmation";
|
||||
import EventManager from "@calcom/lib/EventManager";
|
||||
import { getPlatformParams } from "@calcom/features/platform-oauth-client/get-platform-params";
|
||||
import { PlatformOAuthClientRepository } from "@calcom/features/platform-oauth-client/platform-oauth-client.repository";
|
||||
import EventManager, { placeholderCreatedEvent } from "@calcom/lib/EventManager";
|
||||
import { HttpError as HttpCode } from "@calcom/lib/http-error";
|
||||
import { getBooking } from "@calcom/lib/payment/getBooking";
|
||||
import prisma from "@calcom/prisma";
|
||||
@@ -33,10 +35,20 @@ export async function handlePaymentSuccess(paymentId: number, bookingId: number)
|
||||
});
|
||||
|
||||
const isConfirmed = booking.status === BookingStatus.ACCEPTED;
|
||||
|
||||
const platformOAuthClientRepository = new PlatformOAuthClientRepository();
|
||||
const platformOAuthClient = userWithCredentials.isPlatformManaged
|
||||
? await platformOAuthClientRepository.getByUserId(userWithCredentials.id)
|
||||
: null;
|
||||
const areCalendarEventsEnabled = platformOAuthClient?.areCalendarEventsEnabled ?? true;
|
||||
const areEmailsEnabled = platformOAuthClient?.areEmailsEnabled ?? true;
|
||||
|
||||
if (isConfirmed) {
|
||||
const apps = eventTypeAppMetadataOptionalSchema.parse(eventType?.metadata?.apps);
|
||||
const eventManager = new EventManager({ ...userWithCredentials, credentials: allCredentials }, apps);
|
||||
const scheduleResult = await eventManager.create(evt);
|
||||
const scheduleResult = areCalendarEventsEnabled
|
||||
? await eventManager.create(evt)
|
||||
: placeholderCreatedEvent;
|
||||
bookingData.references = { create: scheduleResult.referencesToCreate };
|
||||
}
|
||||
|
||||
@@ -76,6 +88,7 @@ export async function handlePaymentSuccess(paymentId: number, bookingId: number)
|
||||
bookingId: booking.id,
|
||||
booking,
|
||||
paid: true,
|
||||
platformClientParams: platformOAuthClient ? getPlatformParams(platformOAuthClient) : undefined,
|
||||
});
|
||||
} else {
|
||||
await handleBookingRequested({
|
||||
@@ -84,7 +97,7 @@ export async function handlePaymentSuccess(paymentId: number, bookingId: number)
|
||||
});
|
||||
log.debug(`handling booking request for eventId ${eventType.id}`);
|
||||
}
|
||||
} else {
|
||||
} else if (areEmailsEnabled) {
|
||||
await sendScheduledEmailsAndSMS({ ...evt }, undefined, undefined, undefined, eventType.metadata);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import EventManager from "@calcom/lib/EventManager";
|
||||
|
||||
export { getPublicEvent, type PublicEventType } from "@calcom/features/eventtypes/lib/getPublicEvent";
|
||||
|
||||
export { getBulkUserEventTypes, getBulkTeamEventTypes } from "@calcom/lib/event-types/getBulkEventTypes";
|
||||
@@ -17,7 +19,7 @@ export {
|
||||
} from "@calcom/prisma/zod-utils";
|
||||
|
||||
export { validateCustomEventName } from "@calcom/lib/event";
|
||||
|
||||
export { EventManager };
|
||||
export { getEventTypeById } from "@calcom/lib/event-types/getEventTypeById";
|
||||
export { getEventTypesByViewer } from "@calcom/lib/event-types/getEventTypesByViewer";
|
||||
export type { EventType } from "@calcom/lib/event-types/getEventTypeById";
|
||||
|
||||
@@ -6,6 +6,10 @@ import { PERMISSION_MAP } from "@calcom/platform-constants";
|
||||
|
||||
export const ARE_DEFAULT_EVENT_TYPES_ENABLED_DOCS =
|
||||
"If true, when creating a managed user the managed user will have 4 default event types: 30 and 60 minutes without Cal video, 30 and 60 minutes with Cal video. Set this as false if you want to create a managed user and then manually create event types for the user.";
|
||||
|
||||
export const ARE_CALENDAR_EVENTS_ENABLED_DOCS =
|
||||
"If true and if managed user has calendar connected, calendar events will be created. Disable it if you manually create calendar events. Default to true.";
|
||||
|
||||
export class CreateOAuthClientInput {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@@ -60,4 +64,14 @@ export class CreateOAuthClientInput {
|
||||
description: ARE_DEFAULT_EVENT_TYPES_ENABLED_DOCS,
|
||||
})
|
||||
areDefaultEventTypesEnabled? = false;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@Transform(({ value }) => value ?? true)
|
||||
@ApiPropertyOptional({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
description: ARE_CALENDAR_EVENTS_ENABLED_DOCS,
|
||||
})
|
||||
areCalendarEventsEnabled? = true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsArray, IsBoolean, IsOptional, IsString } from "class-validator";
|
||||
|
||||
import { ARE_DEFAULT_EVENT_TYPES_ENABLED_DOCS } from "./create-oauth-client.input";
|
||||
import {
|
||||
ARE_CALENDAR_EVENTS_ENABLED_DOCS,
|
||||
ARE_DEFAULT_EVENT_TYPES_ENABLED_DOCS,
|
||||
} from "./create-oauth-client.input";
|
||||
|
||||
export class UpdateOAuthClientInput {
|
||||
@IsOptional()
|
||||
@@ -47,4 +50,12 @@ export class UpdateOAuthClientInput {
|
||||
description: ARE_DEFAULT_EVENT_TYPES_ENABLED_DOCS,
|
||||
})
|
||||
areDefaultEventTypesEnabled?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@ApiPropertyOptional({
|
||||
type: Boolean,
|
||||
description: ARE_CALENDAR_EVENTS_ENABLED_DOCS,
|
||||
})
|
||||
areCalendarEventsEnabled?: boolean;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ import { IsArray, IsEnum, IsString, IsNumber, IsOptional, IsDate, IsBoolean, IsU
|
||||
|
||||
import { PERMISSION_MAP } from "@calcom/platform-constants";
|
||||
|
||||
import { ARE_CALENDAR_EVENTS_ENABLED_DOCS } from "../inputs";
|
||||
|
||||
export class PlatformOAuthClientDto {
|
||||
@ApiProperty({ example: "clsx38nbl0001vkhlwin9fmt0" })
|
||||
@IsString()
|
||||
@@ -56,6 +58,10 @@ export class PlatformOAuthClientDto {
|
||||
})
|
||||
areDefaultEventTypesEnabled!: boolean;
|
||||
|
||||
@IsBoolean()
|
||||
@ApiProperty({ example: true, description: ARE_CALENDAR_EVENTS_ENABLED_DOCS })
|
||||
areCalendarEventsEnabled!: boolean;
|
||||
|
||||
@ApiPropertyOptional({ example: "https://example.com/booking-redirect" })
|
||||
@IsOptional()
|
||||
@IsUrl()
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "PlatformOAuthClient" ADD COLUMN "areCalendarEventsEnabled" BOOLEAN NOT NULL DEFAULT true;
|
||||
@@ -1786,6 +1786,7 @@ model PlatformOAuthClient {
|
||||
bookingRescheduleRedirectUri String?
|
||||
areEmailsEnabled Boolean @default(false)
|
||||
areDefaultEventTypesEnabled Boolean @default(true)
|
||||
areCalendarEventsEnabled Boolean @default(true)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
@@ -259,6 +259,7 @@ const PlatformClientParamsSchema = z.object({
|
||||
platformCancelUrl: z.string().nullable().optional(),
|
||||
platformBookingUrl: z.string().nullable().optional(),
|
||||
platformBookingLocation: z.string().optional(),
|
||||
areCalendarEventsEnabled: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export type PlatformClientParams = z.infer<typeof PlatformClientParamsSchema>;
|
||||
|
||||
@@ -2736,7 +2736,7 @@ __metadata:
|
||||
"@axiomhq/winston": ^1.2.0
|
||||
"@calcom/platform-constants": "*"
|
||||
"@calcom/platform-enums": "*"
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.218"
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.222"
|
||||
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2"
|
||||
"@calcom/platform-types": "*"
|
||||
"@calcom/platform-utils": "*"
|
||||
@@ -3831,13 +3831,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.218":
|
||||
version: 0.0.218
|
||||
resolution: "@calcom/platform-libraries@npm:0.0.218"
|
||||
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.222":
|
||||
version: 0.0.222
|
||||
resolution: "@calcom/platform-libraries@npm:0.0.222"
|
||||
dependencies:
|
||||
"@calcom/features": "*"
|
||||
"@calcom/lib": "*"
|
||||
checksum: 8f73aeffaec3b15707aeaab40d0f056e0156e162d22ba44a19e537d897f654adc32f4bafaa0f7bab846b94211cebeaadc7bb7180ce98204c646c24ed48bdf3ef
|
||||
checksum: c02cc43e0726cb2587bac6424d69af1cb42f48f5de725ec5096c5c5397c85928409ecf0c7fbc23092ef6ccf6235501f59449c6f89383d2874c794bf2259c0c1b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user