diff --git a/apps/web/app/future/[user]/[type]/page.tsx b/apps/web/app/future/[user]/[type]/page.tsx index 1ac9364f4f..2c5ebe4559 100644 --- a/apps/web/app/future/[user]/[type]/page.tsx +++ b/apps/web/app/future/[user]/[type]/page.tsx @@ -24,7 +24,13 @@ export const generateMetadata = async ({ const rescheduleUid = booking?.uid; const { trpc } = await import("@calcom/trpc"); const { data: event } = trpc.viewer.public.event.useQuery( - { username: user, eventSlug: slug, isTeamEvent: false, org: eventData.entity.orgSlug ?? null }, + { + username: user, + eventSlug: slug, + isTeamEvent: false, + org: eventData.entity.orgSlug ?? null, + fromRedirectOfNonOrgLink: eventData.entity.fromRedirectOfNonOrgLink, + }, { refetchOnWindowFocus: false } ); diff --git a/apps/web/app/future/d/[link]/[slug]/page.tsx b/apps/web/app/future/d/[link]/[slug]/page.tsx index 4e380ce756..5ac2b4886e 100644 --- a/apps/web/app/future/d/[link]/[slug]/page.tsx +++ b/apps/web/app/future/d/[link]/[slug]/page.tsx @@ -21,7 +21,13 @@ export const generateMetadata = async ({ const rescheduleUid = booking?.uid; const { trpc } = await import("@calcom/trpc"); const { data: event } = trpc.viewer.public.event.useQuery( - { username: user ?? "", eventSlug: slug ?? "", isTeamEvent, org: entity.orgSlug ?? null }, + { + username: user ?? "", + eventSlug: slug ?? "", + isTeamEvent, + org: entity.orgSlug ?? null, + fromRedirectOfNonOrgLink: entity.fromRedirectOfNonOrgLink, + }, { refetchOnWindowFocus: false } ); const profileName = event?.profile?.name ?? ""; diff --git a/apps/web/app/future/org/[orgSlug]/team/[slug]/[type]/page.tsx b/apps/web/app/future/org/[orgSlug]/team/[slug]/[type]/page.tsx index 72713f9d31..af76fb0016 100644 --- a/apps/web/app/future/org/[orgSlug]/team/[slug]/[type]/page.tsx +++ b/apps/web/app/future/org/[orgSlug]/team/[slug]/[type]/page.tsx @@ -22,7 +22,13 @@ export const generateMetadata = async ({ const entity = eventData.entity; const { trpc } = await import("@calcom/trpc"); const { data: event } = trpc.viewer.public.event.useQuery( - { username: user, eventSlug: slug, isTeamEvent: false, org: entity.orgSlug ?? null }, + { + username: user, + eventSlug: slug, + isTeamEvent: false, + org: entity.orgSlug ?? null, + fromRedirectOfNonOrgLink: entity.fromRedirectOfNonOrgLink, + }, { refetchOnWindowFocus: false } ); diff --git a/apps/web/app/future/team/[slug]/[type]/page.tsx b/apps/web/app/future/team/[slug]/[type]/page.tsx index e46cc9f14a..043af611b5 100644 --- a/apps/web/app/future/team/[slug]/[type]/page.tsx +++ b/apps/web/app/future/team/[slug]/[type]/page.tsx @@ -20,7 +20,13 @@ export const generateMetadata = async ({ const entity = eventData.entity; const { trpc } = await import("@calcom/trpc"); const { data: event } = trpc.viewer.public.event.useQuery( - { username: user, eventSlug: slug, isTeamEvent: false, org: entity.orgSlug ?? null }, + { + username: user, + eventSlug: slug, + isTeamEvent: false, + org: entity.orgSlug ?? null, + fromRedirectOfNonOrgLink: entity.fromRedirectOfNonOrgLink, + }, { refetchOnWindowFocus: false } ); diff --git a/apps/web/playwright/booking-pages.e2e.ts b/apps/web/playwright/booking-pages.e2e.ts index 80c72fa48b..e86d8f6863 100644 --- a/apps/web/playwright/booking-pages.e2e.ts +++ b/apps/web/playwright/booking-pages.e2e.ts @@ -1,4 +1,5 @@ import { expect } from "@playwright/test"; +import { JSDOM } from "jsdom"; import { randomString } from "@calcom/lib/random"; import { SchedulingType } from "@calcom/prisma/client"; @@ -14,6 +15,7 @@ import { selectFirstAvailableTimeSlotNextMonth, testEmail, testName, + todo, } from "./lib/testUtils"; const freeUserObj = { name: `Free-user-${randomString(3)}` }; @@ -22,6 +24,36 @@ test.afterEach(async ({ users }) => { await users.deleteAll(); }); +test("check SSR and OG - User Event Type", async ({ page, users }) => { + const name = "Test User"; + const user = await users.create({ + name, + }); + const [response] = await Promise.all([ + // This promise resolves to the main resource response + page.waitForResponse( + (response) => response.url().includes(`/${user.username}/30-min`) && response.status() === 200 + ), + + // Trigger the page navigation + page.goto(`/${user.username}/30-min`), + ]); + const ssrResponse = await response.text(); + const document = new JSDOM(ssrResponse).window.document; + + const titleText = document.querySelector("title")?.textContent; + const ogImage = document.querySelector('meta[property="og:image"]')?.getAttribute("content"); + expect(titleText).toContain(name); + // Verify that there is correct URL that would generate the awesome OG image + expect(ogImage).toContain( + "/_next/image?w=1200&q=100&url=%2Fapi%2Fsocial%2Fog%2Fimage%3Ftype%3Dmeeting%26title%3D" + ); + // Verify Organizer Name in the URL + expect(ogImage).toContain("meetingProfileName%3DTest%2520User%26"); +}); + +todo("check SSR and OG - Team Event Type"); + testBothFutureAndLegacyRoutes.describe("free user", () => { test.beforeEach(async ({ page, users }) => { const free = await users.create(freeUserObj); diff --git a/packages/features/bookings/Booker/utils/event.ts b/packages/features/bookings/Booker/utils/event.ts index 6ffaf86486..a41d4e5181 100644 --- a/packages/features/bookings/Booker/utils/event.ts +++ b/packages/features/bookings/Booker/utils/event.ts @@ -25,7 +25,12 @@ export const useEvent = () => { const org = useBookerStore((state) => state.org); const event = trpc.viewer.public.event.useQuery( - { username: username ?? "", eventSlug: eventSlug ?? "", isTeamEvent, org: org ?? null }, + { + username: username ?? "", + eventSlug: eventSlug ?? "", + isTeamEvent, + org: org ?? null, + }, { refetchOnWindowFocus: false, enabled: Boolean(username) && Boolean(eventSlug) } ); diff --git a/packages/features/bookings/components/BookerSeo.tsx b/packages/features/bookings/components/BookerSeo.tsx index 94ee6bfa87..a1f7534d19 100644 --- a/packages/features/bookings/components/BookerSeo.tsx +++ b/packages/features/bookings/components/BookerSeo.tsx @@ -11,6 +11,7 @@ interface BookerSeoProps { isSEOIndexable?: boolean; isTeamEvent?: boolean; entity: { + fromRedirectOfNonOrgLink: boolean; orgSlug?: string | null; teamSlug?: string | null; name?: string | null; @@ -31,7 +32,13 @@ export const BookerSeo = (props: BookerSeoProps) => { } = props; const { t } = useLocale(); const { data: event } = trpc.viewer.public.event.useQuery( - { username, eventSlug, isTeamEvent, org: entity.orgSlug ?? null }, + { + username, + eventSlug, + isTeamEvent, + org: entity.orgSlug ?? null, + fromRedirectOfNonOrgLink: entity.fromRedirectOfNonOrgLink, + }, { refetchOnWindowFocus: false } ); diff --git a/packages/features/eventtypes/lib/getPublicEvent.ts b/packages/features/eventtypes/lib/getPublicEvent.ts index 387bfac37c..5db4fe9bc1 100644 --- a/packages/features/eventtypes/lib/getPublicEvent.ts +++ b/packages/features/eventtypes/lib/getPublicEvent.ts @@ -189,6 +189,7 @@ export const getPublicEvent = async ( }, entity: { considerUnpublished: !fromRedirectOfNonOrgLink && unPublishedOrgUser !== undefined, + fromRedirectOfNonOrgLink, orgSlug: org, name: unPublishedOrgUser?.profile?.organization?.name ?? null, }, @@ -291,6 +292,7 @@ export const getPublicEvent = async ( profile: getProfileFromEvent(eventWithUserProfiles), users, entity: { + fromRedirectOfNonOrgLink, considerUnpublished: !fromRedirectOfNonOrgLink && (eventWithUserProfiles.team?.slug === null || diff --git a/packages/trpc/server/routers/viewer/organizations/createTeams.handler.ts b/packages/trpc/server/routers/viewer/organizations/createTeams.handler.ts index c236a5851b..aa02ce03a2 100644 --- a/packages/trpc/server/routers/viewer/organizations/createTeams.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/createTeams.handler.ts @@ -1,3 +1,5 @@ +import type { Prisma } from "@prisma/client"; + import { getOrgFullOrigin } from "@calcom/ee/organizations/lib/orgDomains"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; @@ -172,10 +174,10 @@ async function moveTeam({ org: { id: number; slug: string | null; + metadata: Prisma.JsonValue; }; ctx: CreateTeamsOptions["ctx"]; }) { - log.debug("Moving team", safeStringify({ teamId, newSlug, org })); const team = await prisma.team.findUnique({ where: { id: teamId, @@ -203,7 +205,10 @@ async function moveTeam({ }); } + log.debug("Moving team", safeStringify({ teamId, newSlug, org, oldSlug: team.slug })); + newSlug = newSlug ?? team.slug; + const orgMetadata = teamMetadataSchema.parse(org.metadata); await prisma.team.update({ where: { id: teamId, @@ -234,7 +239,7 @@ async function moveTeam({ await addTeamRedirect({ oldTeamSlug: team.slug, teamSlug: newSlug, - orgSlug: org.slug, + orgSlug: org.slug || (orgMetadata?.requestedSlug ?? null), }); }