Handle booking flow for dynamic default events (#7094)
* Handle booking flow for default events * Cleanup * Update packages/lib/defaultEvents.ts * Fix naming conventions * Fix prettier error --------- Co-authored-by: zomars <zomars@me.com>
This commit is contained in:
1 parent
9d3540511b
commit
ea34545d72
5 files changed
+109
-9
No files matched your search
@@ -291,6 +291,15 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
}
|
||||
const isDynamicGroup = users.length > 1;
|
||||
|
||||
if (isDynamicGroup) {
|
||||
// sort and be in the same order as usernameList so first user is the first user in the list
|
||||
users.sort((a, b) => {
|
||||
const aIndex = (a.username && usernameList.indexOf(a.username)) || 0;
|
||||
const bIndex = (b.username && usernameList.indexOf(b.username)) || 0;
|
||||
return aIndex - bIndex;
|
||||
});
|
||||
}
|
||||
|
||||
const dynamicNames = isDynamicGroup
|
||||
? users.map((user) => {
|
||||
return user.name || "";
|
||||
|
||||
@@ -3,13 +3,18 @@ import { GetStaticPaths, GetStaticPropsContext } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { privacyFilteredLocations, LocationObject } from "@calcom/app-store/locations";
|
||||
import { getAppFromSlug } from "@calcom/app-store/utils";
|
||||
import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getDefaultEvent, getGroupName, getUsernameList } from "@calcom/lib/defaultEvents";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { User } from "@calcom/prisma/client";
|
||||
import { EventTypeMetaDataSchema, teamMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
import {
|
||||
EventTypeMetaDataSchema,
|
||||
teamMetadataSchema,
|
||||
userMetadata as userMetadataSchema,
|
||||
} from "@calcom/prisma/zod-utils";
|
||||
|
||||
import { isBrandingHidden } from "@lib/isBrandingHidden";
|
||||
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
@@ -215,6 +220,7 @@ async function getDynamicGroupPageProps(context: GetStaticPropsContext) {
|
||||
darkBrandColor: true,
|
||||
defaultScheduleId: true,
|
||||
allowDynamicBooking: true,
|
||||
metadata: true,
|
||||
away: true,
|
||||
schedules: {
|
||||
select: {
|
||||
@@ -233,7 +239,32 @@ async function getDynamicGroupPageProps(context: GetStaticPropsContext) {
|
||||
};
|
||||
}
|
||||
|
||||
const locations = eventType.locations ? (eventType.locations as LocationObject[]) : [];
|
||||
// sort and be in the same order as usernameList so first user is the first user in the list
|
||||
let sortedUsers: typeof users = [];
|
||||
if (users.length > 1) {
|
||||
sortedUsers = users.sort((a, b) => {
|
||||
const aIndex = (a.username && usernameList.indexOf(a.username)) || 0;
|
||||
const bIndex = (b.username && usernameList.indexOf(b.username)) || 0;
|
||||
return aIndex - bIndex;
|
||||
});
|
||||
}
|
||||
|
||||
let locations = eventType.locations ? (eventType.locations as LocationObject[]) : [];
|
||||
|
||||
// Get the prefered location type from the first user
|
||||
const firstUsersMetadata = userMetadataSchema.parse(sortedUsers[0].metadata || {});
|
||||
const preferedLocationType = firstUsersMetadata?.defaultConferencingApp;
|
||||
|
||||
if (preferedLocationType?.appSlug) {
|
||||
const foundApp = getAppFromSlug(preferedLocationType.appSlug);
|
||||
const appType = foundApp?.appData?.location?.type;
|
||||
if (appType) {
|
||||
// Replace the location with the prefered location type
|
||||
// This will still be default to daily if the app is not found
|
||||
locations = [{ type: appType, link: preferedLocationType.appLink }] as LocationObject[];
|
||||
}
|
||||
}
|
||||
|
||||
const eventTypeObject = Object.assign({}, eventType, {
|
||||
metadata: EventTypeMetaDataSchema.parse(eventType.metadata || {}),
|
||||
recurringEvent: parseRecurringEvent(eventType.recurringEvent),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { GetServerSidePropsContext } from "next";
|
||||
|
||||
import { LocationObject, privacyFilteredLocations } from "@calcom/app-store/locations";
|
||||
import { getAppFromSlug } from "@calcom/app-store/utils";
|
||||
import { parseRecurringEvent } from "@calcom/lib";
|
||||
import {
|
||||
getDefaultEvent,
|
||||
@@ -11,7 +12,11 @@ import {
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { bookEventTypeSelect } from "@calcom/prisma";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
import {
|
||||
customInputSchema,
|
||||
EventTypeMetaDataSchema,
|
||||
userMetadata as userMetadataSchema,
|
||||
} from "@calcom/prisma/zod-utils";
|
||||
|
||||
import { asStringOrNull, asStringOrThrow } from "@lib/asStringOrNull";
|
||||
import getBooking, { GetBookingType } from "@lib/getBooking";
|
||||
@@ -85,6 +90,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
darkBrandColor: true,
|
||||
allowDynamicBooking: true,
|
||||
away: true,
|
||||
metadata: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -117,8 +123,38 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
recurringEvent: parseRecurringEvent(eventTypeRaw.recurringEvent),
|
||||
};
|
||||
|
||||
const eventTypeObject = [eventType].map((e) => {
|
||||
const getLocations = () => {
|
||||
let locations = eventTypeRaw.locations || [];
|
||||
if (!isDynamicGroupBooking) return locations;
|
||||
|
||||
let sortedUsers: typeof users = [];
|
||||
// sort and be in the same order as usernameList so first user is the first user in the list
|
||||
if (users.length > 1) {
|
||||
sortedUsers = users.sort((a, b) => {
|
||||
const aIndex = (a.username && usernameList.indexOf(a.username)) || 0;
|
||||
const bIndex = (b.username && usernameList.indexOf(b.username)) || 0;
|
||||
return aIndex - bIndex;
|
||||
});
|
||||
}
|
||||
|
||||
// Get the prefered location type from the first user
|
||||
const firstUsersMetadata = userMetadataSchema.parse(sortedUsers[0].metadata || {});
|
||||
const preferedLocationType = firstUsersMetadata?.defaultConferencingApp;
|
||||
|
||||
if (preferedLocationType?.appSlug) {
|
||||
const foundApp = getAppFromSlug(preferedLocationType.appSlug);
|
||||
const appType = foundApp?.appData?.location?.type;
|
||||
if (appType) {
|
||||
// Replace the location with the prefered location type
|
||||
// This will still be default to daily if the app is not found
|
||||
locations = [{ type: appType, link: preferedLocationType.appLink }] as LocationObject[];
|
||||
}
|
||||
}
|
||||
return locations;
|
||||
};
|
||||
|
||||
const eventTypeObject = [eventType].map((e) => {
|
||||
let locations = getLocations();
|
||||
locations = privacyFilteredLocations(locations as LocationObject[]);
|
||||
return {
|
||||
...e,
|
||||
|
||||
@@ -188,6 +188,10 @@ export function getAppType(name: string): string {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
export function getAppFromSlug(slug: string | undefined): AppMeta | undefined {
|
||||
return ALL_APPS.find((app) => app.slug === slug);
|
||||
}
|
||||
|
||||
export const getEventTypeAppData = <T extends EventTypeAppsList>(
|
||||
eventType: Pick<z.infer<typeof EventTypeModel>, "price" | "currency" | "metadata">,
|
||||
appId: T,
|
||||
|
||||
@@ -19,7 +19,7 @@ import { metadata as GoogleMeetMetadata } from "@calcom/app-store/googlevideo/_m
|
||||
import { getLocationValueForDB, LocationObject } from "@calcom/app-store/locations";
|
||||
import { MeetLocationType } from "@calcom/app-store/locations";
|
||||
import { handleEthSignature } from "@calcom/app-store/rainbow/utils/ethereum";
|
||||
import { EventTypeAppsList, getEventTypeAppData } from "@calcom/app-store/utils";
|
||||
import { EventTypeAppsList, getAppFromSlug, getEventTypeAppData } from "@calcom/app-store/utils";
|
||||
import { cancelScheduledJobs, scheduleTrigger } from "@calcom/app-store/zapier/lib/nodeScheduler";
|
||||
import EventManager from "@calcom/core/EventManager";
|
||||
import { getEventName } from "@calcom/core/event";
|
||||
@@ -50,6 +50,7 @@ import {
|
||||
customInputSchema,
|
||||
EventTypeMetaDataSchema,
|
||||
extendedBookingCreateBody,
|
||||
userMetadata as userMetadataSchema,
|
||||
} from "@calcom/prisma/zod-utils";
|
||||
import type { BufferedBusyTime } from "@calcom/types/BufferedBusyTime";
|
||||
import type { AdditionalInformation, AppsStatus, CalendarEvent } from "@calcom/types/Calendar";
|
||||
@@ -376,7 +377,10 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
||||
in: dynamicUserList,
|
||||
},
|
||||
},
|
||||
...userSelect,
|
||||
select: {
|
||||
...userSelect.select,
|
||||
metadata: true,
|
||||
},
|
||||
})
|
||||
: !!eventType.hosts?.length
|
||||
? eventType.hosts.map(({ user, isFixed }) => ({
|
||||
@@ -385,7 +389,10 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
||||
}))
|
||||
: eventType.users;
|
||||
// loadUsers allows type inferring
|
||||
let users: (Awaited<ReturnType<typeof loadUsers>>[number] & { isFixed?: boolean })[] = await loadUsers();
|
||||
let users: (Awaited<ReturnType<typeof loadUsers>>[number] & {
|
||||
isFixed?: boolean;
|
||||
metadata?: Prisma.JsonValue;
|
||||
})[] = await loadUsers();
|
||||
|
||||
const isDynamicAllowed = !users.some((user) => !user.allowDynamicBooking);
|
||||
if (!isDynamicAllowed && !eventTypeId) {
|
||||
@@ -497,8 +504,21 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
||||
const seed = `${organizerUser.username}:${dayjs(reqBody.start).utc().format()}:${new Date().getTime()}`;
|
||||
const uid = translator.fromUUID(uuidv5(seed, uuidv5.URL));
|
||||
|
||||
const bookingLocation = getLocationValueForDB(reqBody.location, eventType.locations);
|
||||
let locationBodyString = reqBody.location;
|
||||
let defaultLocationUrl = undefined;
|
||||
if (dynamicUserList.length > 1) {
|
||||
users = users.sort((a, b) => {
|
||||
const aIndex = (a.username && dynamicUserList.indexOf(a.username)) || 0;
|
||||
const bIndex = (b.username && dynamicUserList.indexOf(b.username)) || 0;
|
||||
return aIndex - bIndex;
|
||||
});
|
||||
const firstUsersMetadata = userMetadataSchema.parse(users[0].metadata);
|
||||
const app = getAppFromSlug(firstUsersMetadata?.defaultConferencingApp?.appSlug);
|
||||
locationBodyString = app?.appData?.location?.type || locationBodyString;
|
||||
defaultLocationUrl = firstUsersMetadata?.defaultConferencingApp?.appLink;
|
||||
}
|
||||
|
||||
const bookingLocation = getLocationValueForDB(locationBodyString, eventType.locations);
|
||||
const customInputs = {} as NonNullable<CalendarEvent["customInputs"]>;
|
||||
|
||||
const teamMemberPromises =
|
||||
@@ -1040,7 +1060,7 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
||||
metadata.conferenceData = results[0].createdEvent?.conferenceData;
|
||||
metadata.entryPoints = results[0].createdEvent?.entryPoints;
|
||||
handleAppsStatus(results, booking);
|
||||
videoCallUrl = metadata.hangoutLink || videoCallUrl;
|
||||
videoCallUrl = metadata.hangoutLink || defaultLocationUrl || videoCallUrl;
|
||||
}
|
||||
if (noEmail !== true) {
|
||||
await sendScheduledEmails({
|
||||
|
||||
Reference in new issue
Block a user