From f8b7e17fdaea0dc478f014e4169ccc675cab054c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20L=C3=B3pez?= Date: Tue, 5 Apr 2022 12:03:22 -0600 Subject: [PATCH] Fixes/locations (#2383) * Moves locations to App Store and Core * LocationType fixes * Update App.d.ts * Re-add Google Meet * Moves location labels to the app store * Renames labels to locationLabels * Update utils.ts Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../components/booking/pages/BookingPage.tsx | 17 +--------- apps/web/lib/location.ts | 2 +- apps/web/pages/[user]/book.tsx | 6 ++++ apps/web/pages/team/[slug]/book.tsx | 7 +++++ packages/app-store/_example/index.ts | 1 - packages/app-store/applecalendar/index.ts | 1 - packages/app-store/caldavcalendar/index.ts | 1 - packages/app-store/dailyvideo/index.ts | 5 +-- packages/app-store/googlecalendar/index.ts | 4 ++- packages/app-store/googlevideo/index.ts | 5 +-- packages/app-store/huddle01video/index.ts | 5 +-- packages/app-store/jitsivideo/index.ts | 5 +-- .../location.ts => app-store/locations.ts} | 10 ++++-- packages/app-store/office365calendar/index.ts | 1 - packages/app-store/office365video/index.ts | 5 +-- packages/app-store/stripepayment/index.ts | 1 - packages/app-store/tandemvideo/index.ts | 5 +-- packages/app-store/utils.ts | 31 +++++++++++++------ packages/app-store/zoomvideo/index.ts | 5 +-- packages/core/EventManager.ts | 2 +- packages/core/location.ts | 1 + packages/prisma/zod-utils.ts | 2 +- packages/types/App.d.ts | 9 ++++-- 23 files changed, 78 insertions(+), 53 deletions(-) rename packages/{lib/location.ts => app-store/locations.ts} (52%) create mode 100644 packages/core/location.ts diff --git a/apps/web/components/booking/pages/BookingPage.tsx b/apps/web/components/booking/pages/BookingPage.tsx index ed0e2bd3cd..fd6128b187 100644 --- a/apps/web/components/booking/pages/BookingPage.tsx +++ b/apps/web/components/booking/pages/BookingPage.tsx @@ -52,7 +52,7 @@ type BookingFormValues = { }; }; -const BookingPage = ({ eventType, booking, profile }: BookingPageProps) => { +const BookingPage = ({ eventType, booking, profile, locationLabels }: BookingPageProps) => { const { t, i18n } = useLocale(); const router = useRouter(); const { contracts } = useContracts(); @@ -130,21 +130,6 @@ const BookingPage = ({ eventType, booking, profile }: BookingPageProps) => { const telemetry = useTelemetry(); const locationInfo = (type: LocationType) => locations.find((location) => location.type === type); - - // TODO: Move to translations - // Also TODO: Get these dynamically from App Store - const locationLabels = { - [LocationType.InPerson]: t("in_person_meeting"), - [LocationType.Phone]: t("phone_call"), - [LocationType.Link]: t("link_meeting"), - [LocationType.GoogleMeet]: "Google Meet", - [LocationType.Zoom]: "Zoom Video", - [LocationType.Jitsi]: "Jitsi Meet", - [LocationType.Daily]: "Cal Video", - [LocationType.Huddle01]: "Huddle01 Video", - [LocationType.Tandem]: "Tandem Video", - [LocationType.Teams]: "MS Teams", - }; const loggedInIsOwner = eventType?.users[0]?.name === session?.user?.name; const defaultValues = () => { if (!rescheduleUid) { diff --git a/apps/web/lib/location.ts b/apps/web/lib/location.ts index 16e4265982..1f632382b7 100644 --- a/apps/web/lib/location.ts +++ b/apps/web/lib/location.ts @@ -1 +1 @@ -export * from "@calcom/lib/location"; +export * from "@calcom/core/location"; diff --git a/apps/web/pages/[user]/book.tsx b/apps/web/pages/[user]/book.tsx index 3c3b297809..3e8bd5b6f7 100644 --- a/apps/web/pages/[user]/book.tsx +++ b/apps/web/pages/[user]/book.tsx @@ -5,12 +5,15 @@ import utc from "dayjs/plugin/utc"; import { GetServerSidePropsContext } from "next"; import { JSONObject } from "superjson/dist/types"; +import { getLocationLabels } from "@calcom/app-store/utils"; + import { asStringOrThrow } from "@lib/asStringOrNull"; import prisma from "@lib/prisma"; import { inferSSRProps } from "@lib/types/inferSSRProps"; import BookingPage from "@components/booking/pages/BookingPage"; +import { getTranslation } from "@server/lib/i18n"; import { ssrInit } from "@server/lib/ssr"; dayjs.extend(utc); @@ -133,8 +136,11 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { booking = await getBooking(); } + const t = await getTranslation(context.locale ?? "en", "common"); + return { props: { + locationLabels: getLocationLabels(t), profile: { slug: user.username, name: user.name, diff --git a/apps/web/pages/team/[slug]/book.tsx b/apps/web/pages/team/[slug]/book.tsx index bb161076b5..fc63c0e413 100644 --- a/apps/web/pages/team/[slug]/book.tsx +++ b/apps/web/pages/team/[slug]/book.tsx @@ -2,12 +2,16 @@ import { Prisma } from "@prisma/client"; import { GetServerSidePropsContext } from "next"; import { JSONObject } from "superjson/dist/types"; +import { getLocationLabels } from "@calcom/app-store/utils"; + import { asStringOrThrow } from "@lib/asStringOrNull"; import prisma from "@lib/prisma"; import { inferSSRProps } from "@lib/types/inferSSRProps"; import BookingPage from "@components/booking/pages/BookingPage"; +import { getTranslation } from "@server/lib/i18n"; + export type TeamBookingPageProps = inferSSRProps; export default function TeamBookingPage(props: TeamBookingPageProps) { @@ -94,8 +98,11 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { booking = await getBooking(); } + const t = await getTranslation(context.locale ?? "en", "common"); + return { props: { + locationLabels: getLocationLabels(t), profile: { ...eventTypeObject.team, slug: "team/" + eventTypeObject.slug, diff --git a/packages/app-store/_example/index.ts b/packages/app-store/_example/index.ts index 3a507a7965..a0465e2b98 100644 --- a/packages/app-store/_example/index.ts +++ b/packages/app-store/_example/index.ts @@ -10,7 +10,6 @@ export const metadata = { // If using static next public folder, can then be referenced from the base URL (/). imageSrc: "/api/app-store/_example/icon.svg", logo: "/api/app-store/_example/icon.svg", - label: "Example App", publisher: "Cal.com", rating: 5, reviews: 69, diff --git a/packages/app-store/applecalendar/index.ts b/packages/app-store/applecalendar/index.ts index a8d3c0299f..1e68615932 100644 --- a/packages/app-store/applecalendar/index.ts +++ b/packages/app-store/applecalendar/index.ts @@ -11,7 +11,6 @@ export const metadata = { imageSrc: "/api/app-store/applecalendar/icon.svg", variant: "calendar", category: "calendar", - label: "Apple Calendar", logo: "/api/app-store/applecalendar/icon.svg", publisher: "Cal.com", rating: 5, diff --git a/packages/app-store/caldavcalendar/index.ts b/packages/app-store/caldavcalendar/index.ts index 4240a55878..c3978a9998 100644 --- a/packages/app-store/caldavcalendar/index.ts +++ b/packages/app-store/caldavcalendar/index.ts @@ -11,7 +11,6 @@ export const metadata = { imageSrc: "/api/app-store/caldavcalendar/icon.svg", variant: "calendar", category: "calendar", - label: "CalDav Calendar", logo: "/api/app-store/caldavcalendar/icon.svg", publisher: "Cal.com", rating: 5, diff --git a/packages/app-store/dailyvideo/index.ts b/packages/app-store/dailyvideo/index.ts index 42f4a69bcb..a326c1e94b 100644 --- a/packages/app-store/dailyvideo/index.ts +++ b/packages/app-store/dailyvideo/index.ts @@ -1,5 +1,6 @@ import type { App } from "@calcom/types/App"; +import { LocationType } from "../locations"; import _package from "./package.json"; export const metadata = { @@ -17,12 +18,12 @@ export const metadata = { rating: 4.3, // TODO: placeholder for now, pull this from TrustPilot or G2 reviews: 69, // TODO: placeholder for now, pull this from TrustPilot or G2 category: "video", - label: "Cal Video", slug: "dailyvideo", title: "Cal Video", isGlobal: true, email: "help@cal.com", - locationType: "integrations:daily", + locationType: LocationType.Daily, + locationLabel: "Cal Video", key: { apikey: process.env.DAILY_API_KEY }, } as App; diff --git a/packages/app-store/googlecalendar/index.ts b/packages/app-store/googlecalendar/index.ts index c36ea91fb6..115050efe2 100644 --- a/packages/app-store/googlecalendar/index.ts +++ b/packages/app-store/googlecalendar/index.ts @@ -1,6 +1,7 @@ import { validJson } from "@calcom/lib/jsonUtils"; import type { App } from "@calcom/types/App"; +import { LocationType } from "../locations"; import _package from "./package.json"; export const metadata = { @@ -12,7 +13,6 @@ export const metadata = { imageSrc: "/api/app-store/googlecalendar/icon.svg", variant: "calendar", category: "calendar", - label: "Google Calendar", logo: "/api/app-store/googlecalendar/icon.svg", publisher: "Cal.com", rating: 5, @@ -22,6 +22,8 @@ export const metadata = { url: "https://cal.com/", verified: true, email: "help@cal.com", + locationType: LocationType.GoogleMeet, + locationLabel: "Google Meet", } as App; export * as api from "./api"; diff --git a/packages/app-store/googlevideo/index.ts b/packages/app-store/googlevideo/index.ts index 85f6f925a4..a197886243 100644 --- a/packages/app-store/googlevideo/index.ts +++ b/packages/app-store/googlevideo/index.ts @@ -1,6 +1,7 @@ import { validJson } from "@calcom/lib/jsonUtils"; import type { App } from "@calcom/types/App"; +import { LocationType } from "../locations"; import _package from "./package.json"; export const metadata = { @@ -13,7 +14,6 @@ export const metadata = { title: "Google Meet", imageSrc: "https://cdn.iconscout.com/icon/free/png-256/google-meet-2923654-2416657.png", variant: "conferencing", - label: "Google Meet", logo: "https://cdn.iconscout.com/icon/free/png-256/google-meet-2923654-2416657.png", publisher: "Cal.com", rating: 5, @@ -22,7 +22,8 @@ export const metadata = { url: "https://cal.com/", verified: true, email: "help@cal.com", - locationType: "integrations:google:meet", + locationType: LocationType.GoogleMeet, + locationLabel: "Google Meet", } as App; // export * as api from "./api"; diff --git a/packages/app-store/huddle01video/index.ts b/packages/app-store/huddle01video/index.ts index c77f8ee9c7..281f47b842 100644 --- a/packages/app-store/huddle01video/index.ts +++ b/packages/app-store/huddle01video/index.ts @@ -1,6 +1,7 @@ import { randomString } from "@calcom/lib/random"; import type { App } from "@calcom/types/App"; +import { LocationType } from "../locations"; import _package from "./package.json"; export const metadata = { @@ -17,13 +18,13 @@ export const metadata = { rating: 0, // TODO: placeholder for now, pull this from TrustPilot or G2 reviews: 0, // TODO: placeholder for now, pull this from TrustPilot or G2 category: "web3", - label: "Huddle01 Video", slug: "huddle01_video", title: "Huddle01", trending: true, isGlobal: true, email: "support@huddle01.com", - locationType: "integrations:huddle01", + locationType: LocationType.Huddle01, + locationLabel: "Huddle01 Video", key: { apikey: randomString(12) }, } as App; diff --git a/packages/app-store/jitsivideo/index.ts b/packages/app-store/jitsivideo/index.ts index fd3a324cc9..7af5e09624 100644 --- a/packages/app-store/jitsivideo/index.ts +++ b/packages/app-store/jitsivideo/index.ts @@ -1,5 +1,6 @@ import type { App } from "@calcom/types/App"; +import { LocationType } from "../locations"; import _package from "./package.json"; export const metadata = { @@ -10,19 +11,19 @@ export const metadata = { imageSrc: "/api/app-store/jitsivideo/icon.svg", variant: "conferencing", logo: "/api/app-store/jitsivideo/icon.svg", - locationType: "integrations:jitsi", publisher: "Cal.com", url: "https://jitsi.org/", verified: true, rating: 0, // TODO: placeholder for now, pull this from TrustPilot or G2 reviews: 0, // TODO: placeholder for now, pull this from TrustPilot or G2 category: "video", - label: "Jitsi Video", slug: "jitsi_video", title: "Jitsi Meet", trending: true, isGlobal: true, email: "help@cal.com", + locationType: LocationType.Jitsi, + locationLabel: "Jitsi Video", } as App; export * as lib from "./lib"; diff --git a/packages/lib/location.ts b/packages/app-store/locations.ts similarity index 52% rename from packages/lib/location.ts rename to packages/app-store/locations.ts index 39905ea75d..681d52b77b 100644 --- a/packages/lib/location.ts +++ b/packages/app-store/locations.ts @@ -1,8 +1,11 @@ -/** TODO: These should all come from each individual App Store package, and merge them here. */ -export enum LocationType { +export enum DefaultLocationType { InPerson = "inPerson", Phone = "phone", Link = "link", +} + +/** If your App has a location option, add it here */ +export enum AppStoreLocationType { GoogleMeet = "integrations:google:meet", Zoom = "integrations:zoom", Daily = "integrations:daily", @@ -11,3 +14,6 @@ export enum LocationType { Tandem = "integrations:tandem", Teams = "integrations:office365_video", } + +export const LocationType = { ...DefaultLocationType, ...AppStoreLocationType }; +export type LocationType = DefaultLocationType | AppStoreLocationType; diff --git a/packages/app-store/office365calendar/index.ts b/packages/app-store/office365calendar/index.ts index a0f2db1625..3221105175 100644 --- a/packages/app-store/office365calendar/index.ts +++ b/packages/app-store/office365calendar/index.ts @@ -11,7 +11,6 @@ export const metadata = { imageSrc: "/api/app-store/office365calendar/icon.svg", variant: "calendar", category: "calendar", - label: "Example App", logo: "/api/app-store/office365calendar/icon.svg", publisher: "Cal.com", rating: 5, diff --git a/packages/app-store/office365video/index.ts b/packages/app-store/office365video/index.ts index 03884f02e6..f35b6ec0eb 100644 --- a/packages/app-store/office365video/index.ts +++ b/packages/app-store/office365video/index.ts @@ -1,5 +1,6 @@ import type { App } from "@calcom/types/App"; +import { LocationType } from "../locations"; import _package from "./package.json"; export const metadata = { @@ -16,12 +17,12 @@ export const metadata = { rating: 4.3, // TODO: placeholder for now, pull this from TrustPilot or G2 reviews: 69, // TODO: placeholder for now, pull this from TrustPilot or G2 category: "video", - label: "MS Teams", slug: "msteams", title: "MS Teams", trending: true, email: "help@cal.com", - locationType: "integrations:office365_video", + locationType: LocationType.Teams, + locationLabel: "MS Teams", } as App; export * as api from "./api"; diff --git a/packages/app-store/stripepayment/index.ts b/packages/app-store/stripepayment/index.ts index 834c77c663..3d675763a5 100644 --- a/packages/app-store/stripepayment/index.ts +++ b/packages/app-store/stripepayment/index.ts @@ -17,7 +17,6 @@ export const metadata = { trending: true, reviews: 69, imageSrc: "/api/app-store/stripepayment/icon.svg", - label: "Stripe", publisher: "Cal.com", title: "Stripe", type: "stripe_payment", diff --git a/packages/app-store/tandemvideo/index.ts b/packages/app-store/tandemvideo/index.ts index 8e9b28db61..ca870fa868 100644 --- a/packages/app-store/tandemvideo/index.ts +++ b/packages/app-store/tandemvideo/index.ts @@ -1,5 +1,6 @@ import type { App } from "@calcom/types/App"; +import { LocationType } from "../locations"; import _package from "./package.json"; export const metadata = { @@ -10,7 +11,6 @@ export const metadata = { title: "Tandem Video", imageSrc: "/api/app-store/tandemvideo/icon.svg", variant: "conferencing", - label: "", slug: "tandem", category: "video", logo: "/api/app-store/tandemvideo/icon.svg", @@ -22,7 +22,8 @@ export const metadata = { reviews: 0, isGlobal: false, email: "help@cal.com", - locationType: "integrations:tandem", + locationType: LocationType.Tandem, + locationLabel: "Tandem Video", } as App; export * as api from "./api"; diff --git a/packages/app-store/utils.ts b/packages/app-store/utils.ts index 56fba2f333..923eac25d3 100644 --- a/packages/app-store/utils.ts +++ b/packages/app-store/utils.ts @@ -1,10 +1,10 @@ import { Prisma } from "@prisma/client"; import { TFunction } from "next-i18next"; -import { LocationType } from "@calcom/lib/location"; import type { App } from "@calcom/types/App"; import appStore from "."; +import { LocationType } from "./locations"; const ALL_APPS_MAP = Object.keys(appStore).reduce((store, key) => { store[key] = appStore[key as keyof typeof appStore].metadata; @@ -31,14 +31,13 @@ function translateLocations(locations: OptionTypeBase[], t: TFunction) { label: t(l.label), })); } +const defaultLocations: OptionTypeBase[] = [ + { value: LocationType.InPerson, label: "in_person_meeting" }, + { value: LocationType.Link, label: "link_meeting" }, + { value: LocationType.Phone, label: "phone_call" }, +]; export function getLocationOptions(integrations: AppMeta, t: TFunction) { - const defaultLocations: OptionTypeBase[] = [ - { value: LocationType.InPerson, label: "in_person_meeting" }, - { value: LocationType.Link, label: "link_meeting" }, - { value: LocationType.Phone, label: "phone_call" }, - ]; - integrations.forEach((app) => { if (app.locationOption) { defaultLocations.push(app.locationOption); @@ -70,8 +69,8 @@ function getApps(userCredentials: CredentialData[]) { /** Check if app has location option AND add it if user has credentials for it */ if (credentials.length > 0 && appMeta?.locationType) { locationOption = { - value: appMeta.locationType as LocationType, - label: appMeta.label, + value: appMeta.locationType, + label: appMeta.locationLabel || "No label set", disabled: false, }; } @@ -112,6 +111,20 @@ export function getLocationTypes(): string[] { }, [] as string[]); } +export function getLocationLabels(t: TFunction) { + const defaultLocationLabels = defaultLocations.reduce((locations, location) => { + locations[location.value] = t(location.label); + return locations; + }, {} as Record); + + return ALL_APPS.reduce((locations, app) => { + if (typeof app.locationType === "string") { + locations[app.locationType] = t(app.locationLabel || "No label set"); + } + return locations; + }, defaultLocationLabels); +} + export function getAppName(name: string) { return ALL_APPS_MAP[name as keyof typeof ALL_APPS_MAP]?.name || "No App Name"; } diff --git a/packages/app-store/zoomvideo/index.ts b/packages/app-store/zoomvideo/index.ts index 51075183e8..7fcc9929da 100644 --- a/packages/app-store/zoomvideo/index.ts +++ b/packages/app-store/zoomvideo/index.ts @@ -1,5 +1,6 @@ import type { App } from "@calcom/types/App"; +import { LocationType } from "../locations"; import _package from "./package.json"; export const metadata = { @@ -16,12 +17,12 @@ export const metadata = { rating: 4.3, // TODO: placeholder for now, pull this from TrustPilot or G2 reviews: 69, // TODO: placeholder for now, pull this from TrustPilot or G2 category: "video", - label: "Zoom Video", slug: "zoom", title: "Zoom Video", trending: true, email: "help@cal.com", - locationType: "integrations:zoom", + locationType: LocationType.Zoom, + locationLabel: "Zoom Video", } as App; export * as api from "./api"; diff --git a/packages/core/EventManager.ts b/packages/core/EventManager.ts index f8b98454c0..bf1289ac58 100644 --- a/packages/core/EventManager.ts +++ b/packages/core/EventManager.ts @@ -4,7 +4,6 @@ import merge from "lodash/merge"; import { v5 as uuidv5 } from "uuid"; import getApps from "@calcom/app-store/utils"; -import { LocationType } from "@calcom/lib/location"; import prisma from "@calcom/prisma"; import type { AdditionInformation, CalendarEvent } from "@calcom/types/Calendar"; import type { @@ -16,6 +15,7 @@ import type { import type { VideoCallData } from "@calcom/types/VideoApiAdapter"; import { createEvent, updateEvent } from "./CalendarManager"; +import { LocationType } from "./location"; import { createMeeting, updateMeeting } from "./videoClient"; export type Event = AdditionInformation & VideoCallData; diff --git a/packages/core/location.ts b/packages/core/location.ts new file mode 100644 index 0000000000..3c5493f967 --- /dev/null +++ b/packages/core/location.ts @@ -0,0 +1 @@ +export * from "@calcom/app-store/locations"; diff --git a/packages/prisma/zod-utils.ts b/packages/prisma/zod-utils.ts index 293cc30421..c19a9824c8 100644 --- a/packages/prisma/zod-utils.ts +++ b/packages/prisma/zod-utils.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -import { LocationType } from "@calcom/lib/location"; +import { LocationType } from "@calcom/core/location"; import { slugify } from "@calcom/lib/slugify"; export const eventTypeLocations = z.array( diff --git a/packages/types/App.d.ts b/packages/types/App.d.ts index 0a8243af15..8cfb31ef46 100644 --- a/packages/types/App.d.ts +++ b/packages/types/App.d.ts @@ -1,4 +1,6 @@ -import { Prisma } from "@prisma/client"; +import type { Prisma } from "@prisma/client"; + +import type { LocationType } from "@calcom/app-store/locations"; /** * This is the definition for an app store's app metadata. @@ -22,7 +24,6 @@ export interface App { imageSrc: string; /** TODO determine if we should use this instead of category */ variant: "calendar" | "payment" | "conferencing"; - label: string; /** The slug for the app store public page inside `/apps/[slug] */ slug: string; /** The category to which this app belongs, currently we have `calendar`, `payment` or `video` */ @@ -51,7 +52,9 @@ export interface App { /** A contact email, mainly to ask for support */ email: string; /** Add this value as a posible location option in event types */ - locationType?: string; + locationType?: LocationType; + /** If the app adds a location, how should it be displayed? */ + locationLabel?: string; /** Needed API Keys (usually for global apps) */ key?: Prisma.JsonValue; /** Needed API Keys (usually for global apps) */