WIP
This commit is contained in:
parent
46563754ff
commit
e34473971a
|
@ -211,7 +211,7 @@ export const sendTeamInviteEmail = async (teamInviteEvent: TeamInvite) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const sendRescheduleEmail = async (calEvent: CalendarEvent) => {
|
||||
export const sendRequestRescheduleEmail = async (calEvent: CalendarEvent) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
try {
|
||||
const rescheduleEmail = new OrganizerRequestRescheduledEmail(calEvent);
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { BookingStatus } from "@prisma/client";
|
||||
import dayjs from "dayjs";
|
||||
import type { NextApiHandler, NextApiRequest, NextApiResponse } from "next";
|
||||
import { getSession } from "next-auth/react";
|
||||
import { z, ZodError } from "zod";
|
||||
|
||||
import { sendRescheduleEmail } from "@lib/emails/email-manager";
|
||||
import CalendarDirector from "@calcom/core/builders/CalendarEvent/director";
|
||||
|
||||
import { sendRequestRescheduleEmail } from "@lib/emails/email-manager";
|
||||
import OrganizerRequestRescheduledEmail from "@lib/emails/templates/organizer-request-reschedule-email";
|
||||
import { getEventName } from "@lib/event";
|
||||
import prisma from "@lib/prisma";
|
||||
|
@ -14,9 +17,24 @@ const rescheduleSchema = z.object({
|
|||
});
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const session = await getSession({ req });
|
||||
const { bookingId, rescheduleReason: cancellationReason } = req.body;
|
||||
console.log({ bookingId });
|
||||
let userOwner;
|
||||
try {
|
||||
if (session?.user?.id) {
|
||||
userOwner = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: session.user.id,
|
||||
},
|
||||
select: {
|
||||
locale: true,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// Throw error
|
||||
}
|
||||
|
||||
const bookingToReschedule = await prisma.booking.findFirst({
|
||||
select: {
|
||||
id: true,
|
||||
|
@ -24,6 +42,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
endTime: true,
|
||||
userId: true,
|
||||
attendees: true,
|
||||
eventTypeId: true,
|
||||
},
|
||||
where: {
|
||||
uid: bookingId,
|
||||
|
@ -32,8 +51,13 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
},
|
||||
},
|
||||
});
|
||||
if (bookingToReschedule) {
|
||||
await prisma.booking.update({
|
||||
if (bookingToReschedule && bookingToReschedule.eventTypeId) {
|
||||
const event = await prisma.eventType.findFirst({
|
||||
where: {
|
||||
id: bookingToReschedule.eventTypeId,
|
||||
},
|
||||
});
|
||||
const updatedBooking = await prisma.booking.update({
|
||||
where: {
|
||||
id: bookingToReschedule.id,
|
||||
},
|
||||
|
@ -52,8 +76,26 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
});
|
||||
|
||||
// Send email =================
|
||||
const event = new CalendarEventBuilder({});
|
||||
await sendRescheduleEmail(event);
|
||||
const eventCalendar = new CalendarDirector({
|
||||
booking: updatedBooking,
|
||||
attendee: bookingToReschedule.attendees,
|
||||
start: bookingToReschedule.startTime,
|
||||
end: bookingToReschedule.endTime,
|
||||
eventName: event?.eventName,
|
||||
translationAttendees: userOwner.locale,
|
||||
translationGuests: "en_us",
|
||||
translationOwner: "en_us",
|
||||
eventTypeId: bookingToReschedule.eventTypeId,
|
||||
timeZone: event?.timeZone,
|
||||
location: event?.locations,
|
||||
notes: "",
|
||||
customInputs: [],
|
||||
});
|
||||
const resultEvent = await eventCalendar.buildRequiredParams();
|
||||
console.log(resultEvent);
|
||||
console.log(resultEvent.attendees);
|
||||
console.log(resultEvent.organizer);
|
||||
await sendRequestRescheduleEmail(resultEvent);
|
||||
}
|
||||
|
||||
return res.status(200).json(bookingToReschedule);
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { NextApiRequest } from "next";
|
||||
import { NextApiResponse } from "next";
|
||||
|
||||
import { updateSubscription } from "@calcom/stripe/subscriptions";
|
||||
|
||||
import { getSession } from "@lib/auth";
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (req.method === "POST") {
|
||||
const session = await getSession({ req });
|
||||
const userId = session?.user?.id || 23;
|
||||
const newPlanPriceId = req?.body?.newPlanPriceId;
|
||||
if (userId) {
|
||||
const result = await updateSubscription({ userId, newPlanPriceId });
|
||||
return res.status(200).json(result);
|
||||
}
|
||||
}
|
||||
return res.status(204);
|
||||
}
|
|
@ -109,10 +109,10 @@ export const createEvent = async (credential: Credential, calEvent: CalendarEven
|
|||
|
||||
const creationResult = calendar
|
||||
? await calendar.createEvent(calEvent).catch((e) => {
|
||||
log.error("createEvent failed", e, calEvent);
|
||||
success = false;
|
||||
return undefined;
|
||||
})
|
||||
log.error("createEvent failed", e, calEvent);
|
||||
success = false;
|
||||
return undefined;
|
||||
})
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
|
@ -136,10 +136,10 @@ export const updateEvent = async (
|
|||
const updatedResult =
|
||||
calendar && bookingRefUid
|
||||
? await calendar.updateEvent(bookingRefUid, calEvent).catch((e) => {
|
||||
log.error("updateEvent failed", e, calEvent);
|
||||
success = false;
|
||||
return undefined;
|
||||
})
|
||||
log.error("updateEvent failed", e, calEvent);
|
||||
success = false;
|
||||
return undefined;
|
||||
})
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { Booking, Prisma, SchedulingType } from "@prisma/client";
|
||||
import dayjs from "dayjs";
|
||||
import { Attendee } from "ics";
|
||||
import short from "short-uuid";
|
||||
import { v5 as uuidv5 } from "uuid";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { Person } from "@calcom/types/Calendar";
|
||||
import { CalendarEvent, Person } from "@calcom/types/Calendar";
|
||||
|
||||
import { CalendarEventBuilder } from ".";
|
||||
import { ensureArray } from "../../../../apps/web/lib/ensureArray";
|
||||
|
@ -29,13 +30,15 @@ const userSelect = Prisma.validator<Prisma.UserArgs>()({
|
|||
|
||||
type User = Prisma.UserGetPayload<typeof userSelect>;
|
||||
|
||||
interface ICalendarEventDirector extends Booking {
|
||||
interface ICalendarEventDirector {
|
||||
booking: CustomBookingFromSelect;
|
||||
timeZone: any;
|
||||
start: any;
|
||||
end: any;
|
||||
eventTypeId: any;
|
||||
translationAttendees: string;
|
||||
translationOwner: string;
|
||||
translationOwner: any;
|
||||
translationGuests: any;
|
||||
attendee: any;
|
||||
guestAttendees: any;
|
||||
location: any;
|
||||
|
@ -44,29 +47,38 @@ interface ICalendarEventDirector extends Booking {
|
|||
customInputs: any;
|
||||
}
|
||||
|
||||
export class CalendarEventDirector {
|
||||
interface CustomBookingFromSelect {
|
||||
id: number;
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
userId: string;
|
||||
attendees: Partial<Attendee>[];
|
||||
eventTypeId: number | null;
|
||||
}
|
||||
|
||||
export default class CalendarEventDirector {
|
||||
// Required props
|
||||
private booking: Booking;
|
||||
private booking: CustomBookingFromSelect;
|
||||
private attendee: any;
|
||||
private guestsAttendees: any;
|
||||
private start: any;
|
||||
private end: any;
|
||||
private eventName: any;
|
||||
private translationAttendees: string;
|
||||
private translationGuests: string;
|
||||
private translationAttendees: any;
|
||||
private translationGuests: any;
|
||||
private translationOwner: any;
|
||||
private eventTypeId: any;
|
||||
private timeZone: any;
|
||||
private location: any;
|
||||
private notes: string;
|
||||
// private notes: string;
|
||||
private customInputs: any;
|
||||
|
||||
// Internal control
|
||||
private builder: CalendarEventBuilder;
|
||||
private builder: CalendarEvent | null;
|
||||
private eventType: any;
|
||||
private users: any;
|
||||
private organizer: any;
|
||||
private invitee?: Person;
|
||||
private invitee?: Person[];
|
||||
private guests?: Person[];
|
||||
private teamMembers?: Person[];
|
||||
private attendeesList?: Person[];
|
||||
|
@ -81,7 +93,7 @@ export class CalendarEventDirector {
|
|||
private description?: string;
|
||||
|
||||
constructor(props: ICalendarEventDirector) {
|
||||
this.booking = props;
|
||||
this.booking = props.booking;
|
||||
this.attendee = props.attendee;
|
||||
this.guestsAttendees = props.guestAttendees;
|
||||
this.start = props.start;
|
||||
|
@ -93,8 +105,11 @@ export class CalendarEventDirector {
|
|||
this.translationGuests = props.translationAttendees;
|
||||
this.location = props.location;
|
||||
this.eventName = props.eventName;
|
||||
this.notes = props.notes;
|
||||
// this.notes = props.notes;
|
||||
this.customInputs = props.customInputs;
|
||||
this.builder = null;
|
||||
this.guests = [] as Person[];
|
||||
this.attendeesList = [] as Person[];
|
||||
}
|
||||
|
||||
public async buildRequiredParams() {
|
||||
|
@ -102,28 +117,36 @@ export class CalendarEventDirector {
|
|||
throw new Error(`Booking ${this.eventTypeId} failed`);
|
||||
}
|
||||
const eventTypeId = this.booking.eventTypeId;
|
||||
|
||||
await this.buildEventType(eventTypeId);
|
||||
this.buildUsers(this.eventType.users);
|
||||
this.buildOrganizerFromUserId(this.users[0]);
|
||||
this.setOrganizerLanguage(this.organizer.language);
|
||||
|
||||
await this.buildUsers(this.eventType.users);
|
||||
|
||||
await this.buildOrganizerFromUserId(this.users[0].id);
|
||||
|
||||
await this.setOrganizerLanguage(this.organizer?.language);
|
||||
|
||||
this.buildInvitee();
|
||||
this.buildGuest();
|
||||
this.buildUID();
|
||||
this.buildAttendeesList();
|
||||
// this.buildTeam();
|
||||
// this.buildUID();
|
||||
this.buildDescription();
|
||||
this.buildEventNameObject();
|
||||
|
||||
this.builder = new CalendarEventBuilder({
|
||||
type: this.eventType.title,
|
||||
title: getEventName(this.eventNameObject), //this needs to be either forced in english, or fetched for each attendee and organizer separately
|
||||
title: this.eventNameObject ? getEventName(this.eventNameObject) : "Nameless Event", //this needs to be either forced in english, or fetched for each attendee and organizer separately
|
||||
startTime: this.start,
|
||||
endTime: this.end,
|
||||
organizer: {
|
||||
name: this.users[0].name || "Nameless",
|
||||
email: this.users[0].email || "Email-less",
|
||||
timeZone: this.users[0].timeZone,
|
||||
name: this.organizer.name || "Nameless",
|
||||
email: this.organizer.email || "Email-less",
|
||||
timeZone: this.organizer.timeZone,
|
||||
language: { translate: this.translationOwner, locale: this.organizer?.locale ?? "en" },
|
||||
},
|
||||
attendees: this.attendeesList,
|
||||
});
|
||||
attendees: this.attendeesList || [],
|
||||
}).get();
|
||||
return this.builder;
|
||||
}
|
||||
|
||||
|
@ -131,36 +154,41 @@ export class CalendarEventDirector {
|
|||
if (eventTypeId === null) {
|
||||
throw new Error("Event Type Id not received");
|
||||
}
|
||||
const eventType = await prisma.eventType.findUnique({
|
||||
rejectOnNotFound: true,
|
||||
where: {
|
||||
id: eventTypeId,
|
||||
},
|
||||
select: {
|
||||
users: userSelect,
|
||||
team: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
let eventType;
|
||||
try {
|
||||
eventType = await prisma.eventType.findUnique({
|
||||
rejectOnNotFound: true,
|
||||
where: {
|
||||
id: eventTypeId,
|
||||
},
|
||||
title: true,
|
||||
length: true,
|
||||
eventName: true,
|
||||
schedulingType: true,
|
||||
periodType: true,
|
||||
periodStartDate: true,
|
||||
periodEndDate: true,
|
||||
periodDays: true,
|
||||
periodCountCalendarDays: true,
|
||||
requiresConfirmation: true,
|
||||
userId: true,
|
||||
price: true,
|
||||
currency: true,
|
||||
metadata: true,
|
||||
destinationCalendar: true,
|
||||
},
|
||||
});
|
||||
select: {
|
||||
users: userSelect,
|
||||
team: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
title: true,
|
||||
length: true,
|
||||
eventName: true,
|
||||
schedulingType: true,
|
||||
periodType: true,
|
||||
periodStartDate: true,
|
||||
periodEndDate: true,
|
||||
periodDays: true,
|
||||
periodCountCalendarDays: true,
|
||||
requiresConfirmation: true,
|
||||
userId: true,
|
||||
price: true,
|
||||
currency: true,
|
||||
metadata: true,
|
||||
destinationCalendar: true,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
@ -168,16 +196,20 @@ export class CalendarEventDirector {
|
|||
private async buildUsers(_users: User[]) {
|
||||
let users = _users;
|
||||
if (!users.length && this.eventType.userId) {
|
||||
const eventTypeUser = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: this.eventType.userId,
|
||||
},
|
||||
...userSelect,
|
||||
});
|
||||
if (!eventTypeUser) {
|
||||
throw new Error("eventTypeUser.notFound");
|
||||
try {
|
||||
const eventTypeUser = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: this.eventType.userId,
|
||||
},
|
||||
...userSelect,
|
||||
});
|
||||
if (!eventTypeUser) {
|
||||
throw new Error("eventTypeUser.notFound");
|
||||
}
|
||||
users.push(eventTypeUser);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
users.push(eventTypeUser);
|
||||
}
|
||||
|
||||
if (this.eventType.schedulingType === SchedulingType.ROUND_ROBIN) {
|
||||
|
@ -192,14 +224,19 @@ export class CalendarEventDirector {
|
|||
}
|
||||
|
||||
private async buildOrganizerFromUserId(userId: number) {
|
||||
const organizer = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
// select: {
|
||||
// locale: true,
|
||||
// },
|
||||
});
|
||||
let organizer;
|
||||
try {
|
||||
organizer = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
// select: {
|
||||
// locale: true,
|
||||
// },
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
this.organizer = organizer;
|
||||
}
|
||||
|
||||
|
@ -220,38 +257,43 @@ export class CalendarEventDirector {
|
|||
}
|
||||
|
||||
private async getUserNameWithBookingCounts(eventTypeId: number, selectedUserNames: string[]) {
|
||||
const users = await prisma.user.findMany({
|
||||
where: {
|
||||
username: { in: selectedUserNames },
|
||||
eventTypes: {
|
||||
some: {
|
||||
id: eventTypeId,
|
||||
let userNamesWithBookingCounts;
|
||||
try {
|
||||
const users = await prisma.user.findMany({
|
||||
where: {
|
||||
username: { in: selectedUserNames },
|
||||
eventTypes: {
|
||||
some: {
|
||||
id: eventTypeId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
locale: true,
|
||||
},
|
||||
});
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
locale: true,
|
||||
},
|
||||
});
|
||||
|
||||
const userNamesWithBookingCounts = await Promise.all(
|
||||
users.map(async (user) => ({
|
||||
username: user.username,
|
||||
bookingCount: await prisma.booking.count({
|
||||
where: {
|
||||
user: {
|
||||
id: user.id,
|
||||
userNamesWithBookingCounts = await Promise.all(
|
||||
users.map(async (user) => ({
|
||||
username: user.username,
|
||||
bookingCount: await prisma.booking.count({
|
||||
where: {
|
||||
user: {
|
||||
id: user.id,
|
||||
},
|
||||
startTime: {
|
||||
gt: new Date(),
|
||||
},
|
||||
eventTypeId,
|
||||
},
|
||||
startTime: {
|
||||
gt: new Date(),
|
||||
},
|
||||
eventTypeId,
|
||||
},
|
||||
}),
|
||||
}))
|
||||
);
|
||||
}),
|
||||
}))
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
return userNamesWithBookingCounts;
|
||||
}
|
||||
|
@ -259,16 +301,17 @@ export class CalendarEventDirector {
|
|||
private buildInvitee() {
|
||||
this.invitee = [
|
||||
{
|
||||
email: this.attendee.email,
|
||||
name: this.attendee.name,
|
||||
timeZone: this.attendee.timeZone,
|
||||
language: { translate: this.translationAttendees, locale: this.attendee.language ?? "en" },
|
||||
email: this.attendee[0].email,
|
||||
name: this.attendee[0].name,
|
||||
timeZone: this.attendee[0].timeZone,
|
||||
language: { translate: this.translationAttendees, locale: this.attendee[0].language ?? "en" },
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
private buildGuest() {
|
||||
const guests = this.guestsAttendees?.map((currentGuest: any) => {
|
||||
const guests = this.attendee.slice(1);
|
||||
const guestsResult = this.attendeesList?.map((currentGuest: any) => {
|
||||
return {
|
||||
email: currentGuest,
|
||||
name: "",
|
||||
|
@ -276,7 +319,7 @@ export class CalendarEventDirector {
|
|||
language: { translate: this.translationGuests, locale: "en" },
|
||||
};
|
||||
});
|
||||
this.guests = guests;
|
||||
this.guests = guestsResult;
|
||||
}
|
||||
|
||||
private buildUID() {
|
||||
|
@ -295,11 +338,17 @@ export class CalendarEventDirector {
|
|||
}
|
||||
|
||||
private buildEventNameObject() {
|
||||
// @NOTE: if multiple attendees should name be event with owner and attendeeList.map(item=>item.name).join(',')
|
||||
const attendeeNames =
|
||||
this.attendeesList && this.attendeesList?.length > 1
|
||||
? this.attendeesList?.map((item) => item.name).join(", ")
|
||||
: this.attendee[0].name;
|
||||
console.log({ attendeeNames });
|
||||
this.eventNameObject = {
|
||||
attendeeName: this.eventName || "Nameless",
|
||||
attendeeName: attendeeNames || "Nameless",
|
||||
eventType: this.eventType.title,
|
||||
eventName: this.eventType.eventName,
|
||||
host: this.users[0].name || "Nameless",
|
||||
host: this.organizer.name || "Nameless",
|
||||
t: this.translationOwner,
|
||||
};
|
||||
}
|
||||
|
@ -314,6 +363,19 @@ export class CalendarEventDirector {
|
|||
}
|
||||
}
|
||||
|
||||
private buildAttendeesList() {
|
||||
this.attendeesList = [];
|
||||
if (this.invitee) {
|
||||
this.attendeesList.push(...this.invitee);
|
||||
}
|
||||
if (this.guests) {
|
||||
this.attendeesList.push(...this.guests);
|
||||
}
|
||||
if (this.teamMembers) {
|
||||
this.attendeesList.push(...this.teamMembers);
|
||||
}
|
||||
}
|
||||
|
||||
private isTimeInPast(time: string): boolean {
|
||||
return dayjs(time).isBefore(new Date(), "day");
|
||||
}
|
||||
|
|
|
@ -7,57 +7,61 @@ export class CalendarEventBuilder {
|
|||
this.event = props;
|
||||
}
|
||||
|
||||
public buildDescription(description: CalendarEvent["description"]) {
|
||||
public get() {
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public setDescription(description: CalendarEvent["description"]) {
|
||||
this.event.description = description;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildTeam(team: CalendarEvent["team"]) {
|
||||
public setTeam(team: CalendarEvent["team"]) {
|
||||
this.event.team = team;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildLocation(location: CalendarEvent["location"]) {
|
||||
public setLocation(location: CalendarEvent["location"]) {
|
||||
this.event.location = location;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildConferenceData(conferenceData: CalendarEvent["conferenceData"]) {
|
||||
public setConferenceData(conferenceData: CalendarEvent["conferenceData"]) {
|
||||
this.event.conferenceData = conferenceData;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildAdditionalInformation(additionalInformation: CalendarEvent["additionInformation"]) {
|
||||
public setAdditionalInformation(additionalInformation: CalendarEvent["additionInformation"]) {
|
||||
this.event.additionInformation = additionalInformation;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildUID(UID: CalendarEvent["uid"]) {
|
||||
public setUID(UID: CalendarEvent["uid"]) {
|
||||
this.event.uid = UID;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildVideoCallData(videoCallData: CalendarEvent["videoCallData"]) {
|
||||
public setVideoCallData(videoCallData: CalendarEvent["videoCallData"]) {
|
||||
this.event.videoCallData = videoCallData;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildPaymentInfo(paymentInfo: CalendarEvent["paymentInfo"]) {
|
||||
public setPaymentInfo(paymentInfo: CalendarEvent["paymentInfo"]) {
|
||||
this.event.paymentInfo = paymentInfo;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildDestinationCalendar(destinationCalendar: CalendarEvent["destinationCalendar"]) {
|
||||
public setDestinationCalendar(destinationCalendar: CalendarEvent["destinationCalendar"]) {
|
||||
this.event.destinationCalendar = destinationCalendar;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildCancellationReason(cancellationReason: CalendarEvent["cancellationReason"]) {
|
||||
public setCancellationReason(cancellationReason: CalendarEvent["cancellationReason"]) {
|
||||
this.event.cancellationReason = cancellationReason;
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public buildRejectionReason(rejectionReason: CalendarEvent["rejectionReason"]) {
|
||||
public setRejectionReason(rejectionReason: CalendarEvent["rejectionReason"]) {
|
||||
this.event.rejectionReason = rejectionReason;
|
||||
return this.event;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user