As Google Meet is always installed, this fixes the doubling (#3093)
* As Google Meet is always installed, this fixes the doubling * Make entire Google link clickable, fix extraData * Attempt at type fixing :) * AdditionalInformation for the booking page? * Update packages/emails/src/components/LocationInfo.tsx Being explicit :) * Exclude AdditionalInformation as it is irrelevant here Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: Omar López <zomars@me.com>
This commit is contained in:
co-authored by
Peer Richelsen
Omar López
parent
b9b3fef202
commit
159c026533
@@ -568,7 +568,7 @@ async function handler(req: NextApiRequest) {
|
||||
return prisma.booking.create(createBookingObj);
|
||||
}
|
||||
|
||||
let results: EventResult[] = [];
|
||||
let results: EventResult<AdditionalInformation>[] = [];
|
||||
let referencesToCreate: PartialReference[] = [];
|
||||
let user: User | null = null;
|
||||
|
||||
|
||||
@@ -25,7 +25,13 @@ import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||
// Probably don't need
|
||||
// import { CALENDAR_INTEGRATIONS_TYPES } from "@calcom/lib/integrations/calendar/constants/generals";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { Calendar, CalendarEvent, EventBusyDate, IntegrationCalendar } from "@calcom/types/Calendar";
|
||||
import {
|
||||
Calendar,
|
||||
CalendarEvent,
|
||||
EventBusyDate,
|
||||
IntegrationCalendar,
|
||||
NewCalendarEventType,
|
||||
} from "@calcom/types/Calendar";
|
||||
|
||||
export default class ExchangeCalendarService implements Calendar {
|
||||
private url = "";
|
||||
@@ -55,7 +61,7 @@ export default class ExchangeCalendarService implements Calendar {
|
||||
this.exchangeVersion = ExchangeVersion.Exchange2013;
|
||||
}
|
||||
|
||||
async createEvent(event: CalendarEvent) {
|
||||
async createEvent(event: CalendarEvent): Promise<NewCalendarEventType> {
|
||||
try {
|
||||
const appointment = new Appointment(this.getExchangeService()); // service instance of ExchangeService
|
||||
appointment.Subject = event.title;
|
||||
@@ -76,7 +82,7 @@ export default class ExchangeCalendarService implements Calendar {
|
||||
password: "",
|
||||
type: "",
|
||||
url: "",
|
||||
additionalInfo: [],
|
||||
additionalInfo: {},
|
||||
};
|
||||
} catch (reason) {
|
||||
this.log.error(reason);
|
||||
@@ -84,7 +90,7 @@ export default class ExchangeCalendarService implements Calendar {
|
||||
}
|
||||
}
|
||||
|
||||
async updateEvent(uid: string, event: CalendarEvent) {
|
||||
async updateEvent(uid: string, event: CalendarEvent): Promise<any> {
|
||||
try {
|
||||
const appointment = await Appointment.Bind(
|
||||
this.getExchangeService(),
|
||||
|
||||
@@ -83,7 +83,7 @@ export default class ExchangeCalendarService implements Calendar {
|
||||
password: "",
|
||||
type: "",
|
||||
url: "",
|
||||
additionalInfo: [],
|
||||
additionalInfo: {},
|
||||
};
|
||||
} catch (reason) {
|
||||
this.log.error(reason);
|
||||
|
||||
@@ -22,8 +22,6 @@ export const metadata = {
|
||||
url: "https://cal.com/",
|
||||
verified: true,
|
||||
email: "help@cal.com",
|
||||
locationType: LocationType.GoogleMeet,
|
||||
locationLabel: "Google Meet",
|
||||
} as App;
|
||||
|
||||
export default metadata;
|
||||
|
||||
@@ -7,7 +7,8 @@ import { getUid } from "@calcom/lib/CalEventParser";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import notEmpty from "@calcom/lib/notEmpty";
|
||||
import type { CalendarEvent, EventBusyDate } from "@calcom/types/Calendar";
|
||||
import type { CalendarEvent, EventBusyDate, NewCalendarEventType } from "@calcom/types/Calendar";
|
||||
import type { Event } from "@calcom/types/Event";
|
||||
import type { EventResult } from "@calcom/types/EventManager";
|
||||
|
||||
const log = logger.getChildLogger({ prefix: ["CalendarManager"] });
|
||||
@@ -97,7 +98,10 @@ export const getBusyCalendarTimes = async (
|
||||
return results.reduce((acc, availability) => acc.concat(availability), []);
|
||||
};
|
||||
|
||||
export const createEvent = async (credential: Credential, calEvent: CalendarEvent): Promise<EventResult> => {
|
||||
export const createEvent = async (
|
||||
credential: Credential,
|
||||
calEvent: CalendarEvent
|
||||
): Promise<EventResult<NewCalendarEventType>> => {
|
||||
const uid: string = getUid(calEvent);
|
||||
const calendar = getCalendar(credential);
|
||||
let success = true;
|
||||
@@ -130,7 +134,7 @@ export const updateEvent = async (
|
||||
calEvent: CalendarEvent,
|
||||
bookingRefUid: string | null,
|
||||
externalCalendarId: string | null
|
||||
): Promise<EventResult> => {
|
||||
): Promise<EventResult<NewCalendarEventType>> => {
|
||||
const uid = getUid(calEvent);
|
||||
const calendar = getCalendar(credential);
|
||||
let success = false;
|
||||
@@ -141,7 +145,10 @@ export const updateEvent = async (
|
||||
calendar && bookingRefUid
|
||||
? await calendar
|
||||
.updateEvent(bookingRefUid, calEvent, externalCalendarId)
|
||||
.then(() => (success = true))
|
||||
.then((event) => {
|
||||
success = true;
|
||||
return event;
|
||||
})
|
||||
.catch((e) => {
|
||||
log.error("updateEvent failed", e, calEvent);
|
||||
return undefined;
|
||||
|
||||
@@ -6,21 +6,14 @@ import { v5 as uuidv5 } from "uuid";
|
||||
import { FAKE_DAILY_CREDENTIAL } from "@calcom/app-store/dailyvideo/lib/VideoApiAdapter";
|
||||
import getApps from "@calcom/app-store/utils";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { AdditionalInformation, CalendarEvent } from "@calcom/types/Calendar";
|
||||
import type {
|
||||
CreateUpdateResult,
|
||||
EventResult,
|
||||
PartialBooking,
|
||||
PartialReference,
|
||||
} from "@calcom/types/EventManager";
|
||||
import type { VideoCallData } from "@calcom/types/VideoApiAdapter";
|
||||
import type { AdditionalInformation, CalendarEvent, NewCalendarEventType } from "@calcom/types/Calendar";
|
||||
import type { Event } from "@calcom/types/Event";
|
||||
import type { CreateUpdateResult, EventResult, PartialBooking } from "@calcom/types/EventManager";
|
||||
|
||||
import { createEvent, updateEvent } from "./CalendarManager";
|
||||
import { LocationType } from "./location";
|
||||
import { createMeeting, updateMeeting } from "./videoClient";
|
||||
|
||||
export type Event = AdditionalInformation & VideoCallData;
|
||||
|
||||
export const isZoom = (location: string): boolean => {
|
||||
return location === "integrations:zoom";
|
||||
};
|
||||
@@ -126,7 +119,7 @@ export default class EventManager {
|
||||
const evt = processLocation(event);
|
||||
const isDedicated = evt.location ? isDedicatedIntegration(evt.location) : null;
|
||||
|
||||
const results: Array<EventResult> = [];
|
||||
const results: Array<EventResult<Exclude<Event, AdditionalInformation>>> = [];
|
||||
// If and only if event type is a dedicated meeting, create a dedicated video meeting.
|
||||
if (isDedicated) {
|
||||
const result = await this.createVideoEvent(evt);
|
||||
@@ -140,7 +133,7 @@ export default class EventManager {
|
||||
// Create the calendar event with the proper video call data
|
||||
results.push(...(await this.createAllCalendarEvents(evt)));
|
||||
|
||||
const referencesToCreate: Array<PartialReference> = results.map((result: EventResult) => {
|
||||
const referencesToCreate = results.map((result) => {
|
||||
return {
|
||||
type: result.type,
|
||||
uid: result.createdEvent?.id.toString() ?? "",
|
||||
@@ -214,7 +207,7 @@ export default class EventManager {
|
||||
});
|
||||
|
||||
const isDedicated = evt.location ? isDedicatedIntegration(evt.location) : null;
|
||||
const results: Array<EventResult> = [];
|
||||
const results: Array<EventResult<Event>> = [];
|
||||
// If and only if event type is a dedicated meeting, update the dedicated video meeting.
|
||||
if (isDedicated) {
|
||||
const result = await this.updateVideoEvent(evt, booking);
|
||||
@@ -285,7 +278,7 @@ export default class EventManager {
|
||||
* @param noMail
|
||||
* @private
|
||||
*/
|
||||
private async createAllCalendarEvents(event: CalendarEvent): Promise<Array<EventResult>> {
|
||||
private async createAllCalendarEvents(event: CalendarEvent) {
|
||||
/** Can I use destinationCalendar here? */
|
||||
/* How can I link a DC to a cred? */
|
||||
if (event.destinationCalendar) {
|
||||
@@ -341,7 +334,7 @@ export default class EventManager {
|
||||
* @param event
|
||||
* @private
|
||||
*/
|
||||
private createVideoEvent(event: CalendarEvent): Promise<EventResult> {
|
||||
private createVideoEvent(event: CalendarEvent) {
|
||||
const credential = this.getVideoCredential(event);
|
||||
|
||||
if (credential) {
|
||||
@@ -366,7 +359,7 @@ export default class EventManager {
|
||||
private updateAllCalendarEvents(
|
||||
event: CalendarEvent,
|
||||
booking: PartialBooking
|
||||
): Promise<Array<EventResult>> {
|
||||
): Promise<Array<EventResult<NewCalendarEventType>>> {
|
||||
return async.mapLimit(this.calendarCredentials, 5, async (credential: Credential) => {
|
||||
try {
|
||||
// HACK:
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getUid } from "@calcom/lib/CalEventParser";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
import type { EventResult, PartialReference } from "@calcom/types/EventManager";
|
||||
import type { VideoApiAdapter, VideoApiAdapterFactory } from "@calcom/types/VideoApiAdapter";
|
||||
import type { VideoApiAdapter, VideoApiAdapterFactory, VideoCallData } from "@calcom/types/VideoApiAdapter";
|
||||
|
||||
const log = logger.getChildLogger({ prefix: ["[lib] videoClient"] });
|
||||
|
||||
@@ -32,7 +32,7 @@ const getBusyVideoTimes = (withCredentials: Credential[]) =>
|
||||
results.reduce((acc, availability) => acc.concat(availability), [])
|
||||
);
|
||||
|
||||
const createMeeting = async (credential: Credential, calEvent: CalendarEvent): Promise<EventResult> => {
|
||||
const createMeeting = async (credential: Credential, calEvent: CalendarEvent) => {
|
||||
const uid: string = getUid(calEvent);
|
||||
|
||||
if (!credential) {
|
||||
@@ -69,7 +69,7 @@ const updateMeeting = async (
|
||||
credential: Credential,
|
||||
calEvent: CalendarEvent,
|
||||
bookingRef: PartialReference | null
|
||||
): Promise<EventResult> => {
|
||||
): Promise<EventResult<VideoCallData>> => {
|
||||
const uid = translator.fromUUID(uuidv5(JSON.stringify(calEvent), uuidv5.URL));
|
||||
|
||||
let success = true;
|
||||
|
||||
@@ -30,19 +30,18 @@ export function LocationInfo(props: { calEvent: CalendarEvent; t: TFunction }) {
|
||||
label={t("where")}
|
||||
withSpacer
|
||||
description={
|
||||
<>
|
||||
{providerName}
|
||||
{meetingUrl && (
|
||||
<a
|
||||
href={meetingUrl}
|
||||
target="_blank"
|
||||
title={t("meeting_url")}
|
||||
style={{ color: "#3E3E3E" }}
|
||||
rel="noreferrer">
|
||||
<LinkIcon />
|
||||
</a>
|
||||
)}
|
||||
</>
|
||||
meetingUrl ? (
|
||||
<a
|
||||
href={meetingUrl}
|
||||
target="_blank"
|
||||
title={t("meeting_url")}
|
||||
style={{ color: "#3E3E3E" }}
|
||||
rel="noreferrer">
|
||||
{providerName} <LinkIcon />
|
||||
</a>
|
||||
) : (
|
||||
<>{t("something_went_wrong")}</>
|
||||
)
|
||||
}
|
||||
extraInfo={
|
||||
<>
|
||||
@@ -84,26 +83,15 @@ export function LocationInfo(props: { calEvent: CalendarEvent; t: TFunction }) {
|
||||
label={t("where")}
|
||||
withSpacer
|
||||
description={
|
||||
<>
|
||||
{providerName}
|
||||
{hangoutLink && (
|
||||
<a
|
||||
href={hangoutLink}
|
||||
target="_blank"
|
||||
title={t("meeting_url")}
|
||||
style={{ color: "#3E3E3E" }}
|
||||
rel="noreferrer">
|
||||
<LinkIcon />
|
||||
</a>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
extraInfo={
|
||||
providerName === "Zoom" || providerName === "Google" ? (
|
||||
<p style={{ color: "#494949", fontWeight: 400, lineHeight: "24px" }}>
|
||||
<>{t("meeting_url_provided_after_confirmed")}</>
|
||||
</p>
|
||||
) : null
|
||||
<a
|
||||
href={hangoutLink}
|
||||
target="_blank"
|
||||
title={t("meeting_url")}
|
||||
style={{ color: "#3E3E3E" }}
|
||||
rel="noreferrer">
|
||||
Google <LinkIcon />
|
||||
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -145,7 +145,10 @@ export default abstract class BaseCalendarService implements Calendar {
|
||||
}
|
||||
}
|
||||
|
||||
async updateEvent(uid: string, event: CalendarEvent) {
|
||||
async updateEvent(
|
||||
uid: string,
|
||||
event: CalendarEvent
|
||||
): Promise<NewCalendarEventType | NewCalendarEventType[]> {
|
||||
try {
|
||||
const events = await this.getEventsByUID(uid);
|
||||
|
||||
@@ -166,10 +169,12 @@ export default abstract class BaseCalendarService implements Calendar {
|
||||
this.log.debug("Error creating iCalString");
|
||||
|
||||
return {
|
||||
uid,
|
||||
type: event.type,
|
||||
id: typeof event.uid === "string" ? event.uid : "-1",
|
||||
password: "",
|
||||
url: typeof event.location === "string" ? event.location : "-1",
|
||||
additionalInfo: {},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -186,7 +191,7 @@ export default abstract class BaseCalendarService implements Calendar {
|
||||
headers: this.headers,
|
||||
});
|
||||
})
|
||||
).then((p) => p.map((r) => r.json() as unknown as Event));
|
||||
).then((p) => p.map((r) => r.json() as unknown as NewCalendarEventType));
|
||||
} catch (reason) {
|
||||
this.log.error(reason);
|
||||
|
||||
@@ -290,7 +295,7 @@ export default abstract class BaseCalendarService implements Calendar {
|
||||
if (vtimezone) {
|
||||
const zone = new ICAL.Timezone(vtimezone);
|
||||
currentEvent.startDate = currentEvent.startDate.convertToZone(zone);
|
||||
currentEvent.endDate = currentEvent.endDate.convertToZone(zone);
|
||||
currentEvent.endDate = currentEvent.endDate.convertToZone(zone);
|
||||
}
|
||||
currentStart = dayjs(currentEvent.startDate.toJSDate());
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -34,7 +34,7 @@ export type NewCalendarEventType = {
|
||||
type: string;
|
||||
password: string;
|
||||
url: string;
|
||||
additionalInfo: Record<string, any>;
|
||||
additionalInfo: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type CalendarEventType = {
|
||||
@@ -154,7 +154,7 @@ export interface Calendar {
|
||||
uid: string,
|
||||
event: CalendarEvent,
|
||||
externalCalendarId?: string | null
|
||||
): Promise<Event | Event[]>;
|
||||
): Promise<NewCalendarEventType | NewCalendarEventType[]>;
|
||||
|
||||
deleteEvent(uid: string, event: CalendarEvent, externalCalendarId?: string | null): Promise<unknown>;
|
||||
|
||||
|
||||
Vendored
+3
-2
@@ -1,4 +1,5 @@
|
||||
import type { PartialReference } from "./EventManager";
|
||||
import type { NewCalendarEventType, AdditionalInformation } from "@calcom/types/Calendar";
|
||||
|
||||
import type { VideoCallData } from "./VideoApiAdapter";
|
||||
|
||||
export type Event = AdditionalInformation & VideoCallData;
|
||||
export type Event = AdditionalInformation | NewCalendarEventType | VideoCallData;
|
||||
|
||||
Vendored
+3
-3
@@ -11,12 +11,12 @@ export interface PartialReference {
|
||||
externalCalendarId?: string | null;
|
||||
}
|
||||
|
||||
export interface EventResult {
|
||||
export interface EventResult<T> {
|
||||
type: string;
|
||||
success: boolean;
|
||||
uid: string;
|
||||
createdEvent?: Event;
|
||||
updatedEvent?: Event | Event[];
|
||||
createdEvent?: T;
|
||||
updatedEvent?: T | T[];
|
||||
originalEvent: CalendarEvent;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user