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:
Alex van Andel
2022-06-17 18:34:41 +00:00
committed by GitHub
co-authored by Peer Richelsen Omar López
parent b9b3fef202
commit 159c026533
12 changed files with 72 additions and 74 deletions
+1 -1
View File
@@ -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;
+11 -4
View File
@@ -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;
+9 -16
View File
@@ -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:
+3 -3
View File
@@ -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;
+21 -33
View File
@@ -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>
}
/>
);
+8 -3
View File
@@ -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());
+2 -2
View File
@@ -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>;
+3 -2
View File
@@ -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;
+3 -3
View File
@@ -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;
}