feat: Upgrade to Next 15 (#18834)
* wip * update layoutHOC * wip * remove app router related code no longer used * remove more * await cookies, headers, params, serachparams * update yarn.lock * await cookies, headers, params, serachparams more * update yarn lock again * downgrade next-auth to 4.22.1 * update yarn lock * fix * update yarn lock * fix type checks * update yarn lock * await headers and cookies * restore pages folder * restore yarn.lock * update yarn.lock * await headers and cookies * remove * await params in API routes * updates * restore next.config.js * remove i18n from next.config.js * Fixed tests * Fixed types * Removed duplicate favicon.ico * Fixing more types * ImageResponse moved to next/og * Fixed prisma import issues * dynamic import for @ewsjs/xhr * remove deasync dep * dynamic import for @tryvital/vital-node * fix type checks * add back turbopack command * Type fix * Removed unneeded file * fix turbopack relative path errors * add comments * remove unneeded code * Fixed build errors * await apis * use Promise<Params> type in defaultResponderForAppDir util * refactor scim api route * fix type checks * separate app-routing.config into client-config and server-config * wip * refactor routing forms components * revert unneeded changes for easier review * fix * fix * use CustomTrans * fix type * fix unit tests * fix type error * fix build error * fix build error * fix build error * fix warnings * fix warnings * upgrade @tremor/react and tailwindcss * numCols -> numItems * fix forgot-password e2e test * fix 1 more e2e test * fix login e2e test * fix e2e tests * fix e2e tests * clean up * remove error * use tremor/react 2.11.0 * fix * rename CustomTrans to ServerTrans * address comment * fix test * fix ServerTrans * fix * fix type * fix ServerTrans usages 1 * fix translations * fix type checks * fix type checks * link styling * fix --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
This commit is contained in:
co-authored by
Keith Williams
Anik Dhabal Babu
parent
695a4d7a59
commit
8ad442f2be
@@ -357,13 +357,6 @@ E2E_TEST_OIDC_USER_PASSWORD=
|
||||
|
||||
# ***********************************************************************************************************
|
||||
|
||||
# provide a value between 0 and 100 to ensure the percentage of traffic
|
||||
# redirected from the legacy to the future pages
|
||||
AB_TEST_BUCKET_PROBABILITY=50
|
||||
APP_ROUTER_APPS_SLUG_SETUP_ENABLED=0
|
||||
APP_ROUTER_APPS_ENABLED=0
|
||||
APP_ROUTER_TEAM_ENABLED=0
|
||||
|
||||
# disable setry server source maps
|
||||
SENTRY_DISABLE_SERVER_WEBPACK_PLUGIN=1
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import TypePage, { type PageProps as ClientPageProps } from "~/users/views/users
|
||||
const getData = withEmbedSsrAppDir<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
return <TypePage {...props} />;
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { PageProps as LegacyPageProps } from "~/users/views/users-type-publ
|
||||
import LegacyPage from "~/users/views/users-type-public-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(legacyCtx);
|
||||
|
||||
const { booking, isSEOIndexable = true, eventData, isBrandingHidden } = props;
|
||||
@@ -31,7 +31,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
})),
|
||||
],
|
||||
};
|
||||
const decodedParams = decodeParams(params);
|
||||
const decodedParams = decodeParams(await params);
|
||||
const metadata = await generateMeetingMetadata(
|
||||
meeting,
|
||||
(t) => `${rescheduleUid && !!booking ? t("reschedule") : ""} ${title} | ${profileName}`,
|
||||
@@ -52,7 +52,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const getData = withAppDirSsr<LegacyPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(legacyCtx);
|
||||
|
||||
return <LegacyPage {...props} />;
|
||||
|
||||
@@ -11,7 +11,7 @@ import User, { type PageProps as ClientPageProps } from "~/users/views/users-pub
|
||||
const getData = withEmbedSsrAppDir<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
return <User {...props} />;
|
||||
};
|
||||
|
||||
@@ -13,7 +13,9 @@ import type { PageProps as LegacyPageProps } from "~/users/views/users-public-vi
|
||||
import LegacyPage from "~/users/views/users-public-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
|
||||
const { profile, markdownStrippedBio, isOrgSEOIndexable, entity } = props;
|
||||
const isOrg = !!profile?.organization;
|
||||
@@ -31,7 +33,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
() => markdownStrippedBio,
|
||||
false,
|
||||
getOrgFullOrigin(entity.orgSlug ?? null),
|
||||
`/${decodeParams(params).user}`
|
||||
`/${decodeParams(await params).user}`
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -45,7 +47,9 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
|
||||
const getData = withAppDirSsr<LegacyPageProps>(getServerSideProps);
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
|
||||
return <LegacyPage {...props} />;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { headers } from "next/headers";
|
||||
import PageWrapper from "@components/PageWrapperAppDir";
|
||||
|
||||
export default async function BookingPageWrapperLayout({ children }: { children: React.ReactNode }) {
|
||||
const h = headers();
|
||||
const h = await headers();
|
||||
const nonce = h.get("x-nonce") ?? undefined;
|
||||
|
||||
return (
|
||||
|
||||
@@ -15,7 +15,7 @@ const getData = withEmbedSsrAppDir<ClientPageProps>(getServerSideProps);
|
||||
export type ClientPageProps = UserTypePageProps | TeamTypePageProps;
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
if ((props as TeamTypePageProps)?.teamId) return <TeamTypePage {...(props as TeamTypePageProps)} />;
|
||||
return <UserTypePage {...(props as UserTypePageProps)} />;
|
||||
|
||||
@@ -17,7 +17,7 @@ export type OrgTypePageProps = UserTypePageProps | TeamTypePageProps;
|
||||
const getData = withAppDirSsr<OrgTypePageProps>(getServerSideProps);
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(legacyCtx);
|
||||
|
||||
const { booking, isSEOIndexable = true, eventData, isBrandingHidden } = props;
|
||||
@@ -36,7 +36,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
})),
|
||||
],
|
||||
};
|
||||
const decodedParams = decodeParams(params);
|
||||
const decodedParams = decodeParams(await params);
|
||||
const metadata = await generateMeetingMetadata(
|
||||
meeting,
|
||||
(t) => `${rescheduleUid && !!booking ? t("reschedule") : ""} ${title} | ${profileName}`,
|
||||
@@ -56,7 +56,9 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
};
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
if ((props as TeamTypePageProps)?.teamId) {
|
||||
return <TeamTypePage {...(props as TeamTypePageProps)} />;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ const getData = withEmbedSsrAppDir<ClientPageProps>(getServerSideProps);
|
||||
export type ClientPageProps = UserPageProps | TeamPageProps;
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
if ((props as TeamPageProps)?.team) return <TeamPage {...(props as TeamPageProps)} />;
|
||||
return <UserPage {...(props as UserPageProps)} />;
|
||||
|
||||
@@ -18,7 +18,7 @@ export type OrgPageProps = UserPageProps | TeamPageProps;
|
||||
const getData = withAppDirSsr<OrgPageProps>(getServerSideProps);
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(legacyCtx);
|
||||
|
||||
if ((props as TeamPageProps)?.team) {
|
||||
@@ -30,7 +30,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
image: getOrgOrTeamAvatar(team),
|
||||
},
|
||||
};
|
||||
const decodedParams = decodeParams(params);
|
||||
const decodedParams = decodeParams(await params);
|
||||
return {
|
||||
...(await generateMeetingMetadata(
|
||||
meeting,
|
||||
@@ -78,7 +78,9 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
};
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
if ((props as TeamPageProps)?.team) {
|
||||
return <TeamPage {...(props as TeamPageProps)} />;
|
||||
}
|
||||
|
||||
+5
-3
@@ -12,7 +12,7 @@ import type { Props } from "~/org/[orgSlug]/instant-meeting/team/[slug]/[type]/i
|
||||
import Page from "~/org/[orgSlug]/instant-meeting/team/[slug]/[type]/instant-meeting-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: _PageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const { isBrandingHidden, eventData } = await getData(context);
|
||||
|
||||
const profileName = eventData?.profile.name ?? "";
|
||||
@@ -29,7 +29,7 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) =>
|
||||
})),
|
||||
],
|
||||
};
|
||||
const decodedParams = decodeParams(params);
|
||||
const decodedParams = decodeParams(await params);
|
||||
const metadata = await generateMeetingMetadata(
|
||||
meeting,
|
||||
() => `${title} | ${profileName}`,
|
||||
@@ -51,7 +51,9 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) =>
|
||||
const getData = withAppDirSsr<Props>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: _PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
return <Page {...props} />;
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import TypePage, { type PageProps as ClientPageProps } from "~/team/type-view";
|
||||
const getData = withEmbedSsrAppDir<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
return <TypePage {...props} />;
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ import LegacyPage from "~/team/type-view";
|
||||
import type { PageProps as LegacyPageProps } from "~/team/type-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(legacyCtx);
|
||||
const { booking, isSEOIndexable, eventData, isBrandingHidden } = props;
|
||||
|
||||
@@ -29,7 +29,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
})),
|
||||
],
|
||||
};
|
||||
const decodedParams = decodeParams(params);
|
||||
const decodedParams = decodeParams(await params);
|
||||
const metadata = await generateMeetingMetadata(
|
||||
meeting,
|
||||
(t) => `${booking?.uid && !!booking ? t("reschedule") : ""} ${title} | ${profileName}`,
|
||||
@@ -51,7 +51,9 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const getData = withAppDirSsr<LegacyPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
return <LegacyPage {...props} />;
|
||||
};
|
||||
export default ServerPage;
|
||||
|
||||
@@ -10,7 +10,7 @@ import TeamPage, { type PageProps as ClientPageProps } from "~/team/team-view";
|
||||
const getData = withEmbedSsrAppDir<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
return <TeamPage {...props} />;
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ import LegacyPage from "~/team/team-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: _PageProps) => {
|
||||
const { team, markdownStrippedBio, isSEOIndexable, currentOrgDomain } = await getData(
|
||||
buildLegacyCtx(headers(), cookies(), params, searchParams)
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
|
||||
const meeting = {
|
||||
@@ -24,7 +24,7 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) =>
|
||||
image: getOrgOrTeamAvatar(team),
|
||||
},
|
||||
};
|
||||
const decodedParams = decodeParams(params);
|
||||
const decodedParams = decodeParams(await params);
|
||||
const metadata = await generateMeetingMetadata(
|
||||
meeting,
|
||||
(t) => team.name || t("nameless_team"),
|
||||
@@ -45,7 +45,9 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) =>
|
||||
const getData = withAppDirSsr<PageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: _PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
return <LegacyPage {...props} />;
|
||||
};
|
||||
export default ServerPage;
|
||||
|
||||
@@ -17,7 +17,7 @@ export const generateMetadata = async () => {
|
||||
};
|
||||
|
||||
const Page = async () => {
|
||||
// const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
// const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
// const userId = session?.user?.id;
|
||||
// const orgId = session?.user?.org?.id;
|
||||
// if (!userId || !orgId) {
|
||||
|
||||
@@ -18,7 +18,7 @@ export const generateMetadata = async () =>
|
||||
);
|
||||
|
||||
const Page = async ({ params }: PageProps) => {
|
||||
const parsed = querySchema.safeParse(params);
|
||||
const parsed = querySchema.safeParse(await params);
|
||||
if (!parsed.success) {
|
||||
redirect("/bookings/upcoming");
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export const generateMetadata = async () =>
|
||||
);
|
||||
|
||||
const Page = async ({ params, searchParams }: PageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const session = await getServerSession({ req: context.req });
|
||||
|
||||
if (!session?.user?.id) {
|
||||
|
||||
@@ -16,8 +16,9 @@ export const generateMetadata = async () =>
|
||||
(t) => t("create_manage_teams_collaborative")
|
||||
);
|
||||
|
||||
const ServerPage = async ({ searchParams }: ServerPageProps) => {
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const ServerPage = async ({ searchParams: _searchParams }: ServerPageProps) => {
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
const searchParams = await _searchParams;
|
||||
const token = Array.isArray(searchParams?.token) ? searchParams.token[0] : searchParams?.token;
|
||||
const callbackUrl = token ? `/teams?token=${encodeURIComponent(token)}` : null;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ const paramsSchema = z.object({
|
||||
});
|
||||
|
||||
export const generateMetadata = async ({ params }: _PageProps) => {
|
||||
const p = paramsSchema.safeParse(params);
|
||||
const p = paramsSchema.safeParse(await params);
|
||||
|
||||
if (!p.success) {
|
||||
return notFound();
|
||||
@@ -33,7 +33,7 @@ export const generateMetadata = async ({ params }: _PageProps) => {
|
||||
};
|
||||
|
||||
async function Page({ params }: _PageProps) {
|
||||
const p = paramsSchema.safeParse(params);
|
||||
const p = paramsSchema.safeParse(await params);
|
||||
|
||||
if (!p.success) {
|
||||
return notFound();
|
||||
|
||||
@@ -9,7 +9,8 @@ import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
|
||||
import SetupView, { type PageProps as ClientPageProps } from "~/apps/[slug]/setup/setup-view";
|
||||
|
||||
export const generateMetadata = async ({ params }: ServerPageProps) => {
|
||||
export const generateMetadata = async ({ params: _params }: ServerPageProps) => {
|
||||
const params = await _params;
|
||||
const metadata = await _generateMetadata(
|
||||
() => `${params.slug}`,
|
||||
() => ""
|
||||
@@ -26,7 +27,7 @@ export const generateMetadata = async ({ params }: ServerPageProps) => {
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
|
||||
const { dehydratedState, ...props } = await getData(context);
|
||||
return <SetupView {...props} />;
|
||||
|
||||
@@ -10,7 +10,9 @@ import Page from "~/apps/categories/categories-view";
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
async function ServerPage({ params, searchParams }: PageProps) {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
|
||||
return <Page {...props} />;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import type { OnboardingPageProps } from "~/apps/installation/[[...step]]/step-v
|
||||
import Page from "~/apps/installation/[[...step]]/step-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
|
||||
const { appMetadata } = await getData(legacyCtx);
|
||||
return await _generateMetadata(
|
||||
@@ -22,7 +22,9 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const getData = withAppDirSsr<OnboardingPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
return <Page {...props} />;
|
||||
};
|
||||
export default ServerPage;
|
||||
|
||||
@@ -19,7 +19,7 @@ export const generateMetadata = async () => {
|
||||
};
|
||||
|
||||
const InstalledAppsWrapper = async ({ params }: PageProps) => {
|
||||
const parsedParams = querySchema.safeParse(params);
|
||||
const parsedParams = querySchema.safeParse(await params);
|
||||
|
||||
if (!parsedParams.success) {
|
||||
redirect("/apps/installed/calendar");
|
||||
|
||||
@@ -18,7 +18,7 @@ export const generateMetadata = async () => {
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
|
||||
const props = await getData(context);
|
||||
return <AppsPage {...props} />;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { FormProvider as ReactHookFormProvider, useForm } from "react-hook-form";
|
||||
|
||||
export default function FormProvider({ children }: { children: React.ReactNode }) {
|
||||
const methods = useForm();
|
||||
|
||||
return <ReactHookFormProvider {...methods}>{children}</ReactHookFormProvider>;
|
||||
}
|
||||
@@ -3,23 +3,25 @@ import type { PageProps as ServerPageProps } from "app/_types";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import type { routingServerSidePropsConfig } from "@calcom/app-store/routing-forms/pages/app-routing.config";
|
||||
import LayoutHandler from "@calcom/app-store/routing-forms/pages/layout-handler/[...appPages]";
|
||||
import { routingFormsComponents } from "@calcom/app-store/routing-forms/pages/app-routing.client-config";
|
||||
import type { routingServerSidePropsConfig } from "@calcom/app-store/routing-forms/pages/app-routing.server-config";
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
|
||||
import { getServerSideProps } from "@lib/apps/routing-forms/[...pages]/getServerSideProps";
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
|
||||
import FormProvider from "./FormProvider";
|
||||
|
||||
const normalizePages = (pages: string[] | string | undefined) => {
|
||||
const normalizedPages = Array.isArray(pages) ? pages : pages?.split("/") ?? [];
|
||||
return {
|
||||
mainPage: normalizedPages[0],
|
||||
mainPage: normalizedPages[0] ?? "forms",
|
||||
subPages: normalizedPages.slice(1),
|
||||
};
|
||||
};
|
||||
|
||||
export const generateMetadata = async ({ params }: { params: { pages: string[] } }) => {
|
||||
const { mainPage } = normalizePages(params.pages);
|
||||
export const generateMetadata = async ({ params }: { params: Promise<{ pages: string[] }> }) => {
|
||||
const { mainPage } = normalizePages((await params).pages);
|
||||
return await _generateMetadata(
|
||||
// TODO: Need to show the actual form name instead of "Form"
|
||||
(t) => (mainPage === "routing-link" ? `Form | Cal.com Forms` : `${t("routing_forms")} | Cal.com Forms`),
|
||||
@@ -32,22 +34,24 @@ type GetServerSidePropsResult =
|
||||
const getData = withAppDirSsr<GetServerSidePropsResult>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
const { mainPage, subPages } = normalizePages(params.pages);
|
||||
const { mainPage } = normalizePages((await params).pages);
|
||||
|
||||
const componentProps = {
|
||||
...props,
|
||||
pages: subPages,
|
||||
};
|
||||
const Component = await routingFormsComponents[mainPage as keyof typeof routingFormsComponents]();
|
||||
const FinalComponent = () => (
|
||||
<FormProvider>
|
||||
<Component {...props as any} />
|
||||
</FormProvider>
|
||||
);
|
||||
|
||||
if (mainPage === "routing-link") {
|
||||
return <LayoutHandler {...componentProps} />;
|
||||
return <FinalComponent />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Shell withoutMain withoutSeo>
|
||||
<LayoutHandler {...componentProps} />
|
||||
<FinalComponent />
|
||||
</Shell>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ const querySchema = z.object({
|
||||
|
||||
const ServerPage = async ({ searchParams }: PageProps) => {
|
||||
const t = await getTranslate();
|
||||
const { error } = querySchema.parse({ error: searchParams?.error || undefined });
|
||||
const { error } = querySchema.parse({ error: (await searchParams)?.error || undefined });
|
||||
const errorMsg = t("error_during_login") + (error ? ` Error code: ${error}` : "");
|
||||
return (
|
||||
<AuthContainer>
|
||||
|
||||
@@ -19,7 +19,7 @@ export const generateMetadata = async () => {
|
||||
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
|
||||
return <SetNewUserPassword {...props} />;
|
||||
|
||||
@@ -18,7 +18,7 @@ export const generateMetadata = async () => {
|
||||
};
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const session = await getServerSession({ req: context.req });
|
||||
|
||||
if (session) {
|
||||
|
||||
@@ -20,7 +20,9 @@ export const generateMetadata = async () => {
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
return <Login {...props} />;
|
||||
};
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ export const generateMetadata = async () => {
|
||||
|
||||
const Page = async ({ params, searchParams }: PageProps) => {
|
||||
// cookie will be cleared in `/apps/web/middleware.ts`
|
||||
const h = headers();
|
||||
const context = buildLegacyCtx(h, cookies(), params, searchParams);
|
||||
const h = await headers();
|
||||
const context = buildLegacyCtx(h, await cookies(), await params, await searchParams);
|
||||
await ssrInit(context);
|
||||
|
||||
return <Logout query={context.query} />;
|
||||
|
||||
@@ -20,7 +20,9 @@ export const generateMetadata = async () => {
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
return <Setup {...props} />;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import type { PageProps as ClientPageProps } from "~/auth/signin-view";
|
||||
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const session = await getServerSession({ req: context.req });
|
||||
if (session) {
|
||||
redirect("/");
|
||||
|
||||
@@ -11,7 +11,7 @@ import SSOProviderView from "~/auth/sso/provider-view";
|
||||
|
||||
const getData = withAppDirSsr<SSOProviderPageProps>(getServerSideProps);
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
|
||||
return <SSOProviderView {...props} />;
|
||||
|
||||
@@ -11,7 +11,7 @@ import SSODirectView from "~/auth/sso/direct-view";
|
||||
|
||||
const getData = withAppDirSsr<SSODirectPageProps>(getServerSideProps);
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
|
||||
return <SSODirectView {...props} />;
|
||||
|
||||
@@ -19,7 +19,9 @@ export const generateMetadata = async () => {
|
||||
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
return <VerifyEmailChange {...props} />;
|
||||
};
|
||||
export default ServerPage;
|
||||
|
||||
@@ -25,7 +25,7 @@ const querySchema = z.object({
|
||||
const getSchedule = cache((id: number) => ScheduleRepository.findScheduleById({ id }));
|
||||
|
||||
export const generateMetadata = async ({ params }: PageProps) => {
|
||||
const parsed = querySchema.safeParse(params);
|
||||
const parsed = querySchema.safeParse(await params);
|
||||
if (!parsed.success) {
|
||||
notFound();
|
||||
}
|
||||
@@ -43,13 +43,13 @@ export const generateMetadata = async ({ params }: PageProps) => {
|
||||
};
|
||||
|
||||
const Page = async ({ params }: PageProps) => {
|
||||
const parsed = querySchema.safeParse(params);
|
||||
const parsed = querySchema.safeParse(await params);
|
||||
if (!parsed.success) {
|
||||
notFound();
|
||||
}
|
||||
// const scheduleId = Number(params.schedule);
|
||||
// const scheduleId = Number(await params.schedule);
|
||||
|
||||
// const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
// const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
// const userId = session?.user?.id;
|
||||
// if (!userId) {
|
||||
// notFound();
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
const getEmbedData = withEmbedSsrAppDir<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getEmbedData(context);
|
||||
return <OldPage {...props} />;
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: _PageProps) => {
|
||||
const { bookingInfo, eventType, recurringBookings, orgSlug } = await getData(
|
||||
buildLegacyCtx(headers(), cookies(), params, searchParams)
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
const needsConfirmation = bookingInfo.status === BookingStatus.PENDING && eventType.requiresConfirmation;
|
||||
|
||||
@@ -33,7 +33,7 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) =>
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: _PageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(context);
|
||||
return <OldPage {...props} />;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ import { type PageProps } from "@lib/d/[link]/[slug]/getServerSideProps";
|
||||
import Type from "~/d/[link]/d-type-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: _PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const pageProps = await getData(legacyCtx);
|
||||
|
||||
const { booking, eventData, isBrandingHidden } = pageProps;
|
||||
@@ -27,7 +27,7 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) =>
|
||||
|
||||
const getData = withAppDirSsr<PageProps>(getServerSideProps);
|
||||
const ServerPage = async ({ params, searchParams }: _PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const pageProps = await getData(legacyCtx);
|
||||
|
||||
return <Type {...pageProps} />;
|
||||
|
||||
@@ -22,7 +22,7 @@ const querySchema = z.object({
|
||||
});
|
||||
|
||||
export const generateMetadata = async ({ params }: _PageProps) => {
|
||||
const parsed = querySchema.safeParse(params);
|
||||
const parsed = querySchema.safeParse(await params);
|
||||
if (!parsed.success) {
|
||||
return await _generateMetadata(
|
||||
(t) => `${t("event_type")}`,
|
||||
@@ -43,7 +43,7 @@ export const generateMetadata = async ({ params }: _PageProps) => {
|
||||
const getData = withAppDirSsr<EventTypePageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: _PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
const props = await getData(legacyCtx);
|
||||
|
||||
return <EventTypePageWrapper {...props} />;
|
||||
|
||||
@@ -22,7 +22,7 @@ export const generateMetadata = async () => {
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
|
||||
const props = await getData(context);
|
||||
return <Page {...props} />;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { headers } from "next/headers";
|
||||
import PageWrapper from "@components/PageWrapperAppDir";
|
||||
|
||||
export default async function PageWrapperLayout({ children }: { children: React.ReactNode }) {
|
||||
const h = headers();
|
||||
const h = await headers();
|
||||
const nonce = h.get("x-nonce") ?? undefined;
|
||||
|
||||
return (
|
||||
|
||||
@@ -10,7 +10,9 @@ import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
const eventName = props.booking.title;
|
||||
return await _generateMetadata(
|
||||
(t) => `${t("payment")} | ${eventName} | ${APP_NAME}`,
|
||||
@@ -21,7 +23,9 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const getData = withAppDirSsr<PaymentPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const props = await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
const props = await getData(
|
||||
buildLegacyCtx(await headers(), await cookies(), await params, await searchParams)
|
||||
);
|
||||
|
||||
return <PaymentPage {...props} />;
|
||||
};
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import { OrganizationRepository } from "@calcom/lib/server/repository/organizati
|
||||
const orgIdSchema = z.object({ id: z.coerce.number() });
|
||||
|
||||
export const generateMetadata = async ({ params }: { params: Params }) => {
|
||||
const input = orgIdSchema.safeParse(params);
|
||||
const input = orgIdSchema.safeParse(await params);
|
||||
if (!input.success) {
|
||||
return await _generateMetadata(
|
||||
(t) => t("editing_org"),
|
||||
@@ -28,7 +28,7 @@ export const generateMetadata = async ({ params }: { params: Params }) => {
|
||||
};
|
||||
|
||||
const Page = async ({ params }: { params: Params }) => {
|
||||
const input = orgIdSchema.safeParse(params);
|
||||
const input = orgIdSchema.safeParse(await params);
|
||||
|
||||
if (!input.success) notFound();
|
||||
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import { UserRepository } from "@calcom/lib/server/repository/user";
|
||||
const userIdSchema = z.object({ id: z.coerce.number() });
|
||||
|
||||
export const generateMetadata = async ({ params }: { params: Params }) => {
|
||||
const input = userIdSchema.safeParse(params);
|
||||
const input = userIdSchema.safeParse(await params);
|
||||
if (!input.success) {
|
||||
return await _generateMetadata(
|
||||
(t) => t("editing_user"),
|
||||
@@ -28,7 +28,7 @@ export const generateMetadata = async ({ params }: { params: Params }) => {
|
||||
};
|
||||
|
||||
const Page = async ({ params }: { params: Params }) => {
|
||||
const input = userIdSchema.safeParse(params);
|
||||
const input = userIdSchema.safeParse(await params);
|
||||
|
||||
if (!input.success) {
|
||||
notFound();
|
||||
|
||||
@@ -12,7 +12,7 @@ import AdminLayoutAppDirClient from "./AdminLayoutAppDirClient";
|
||||
type AdminLayoutAppDirProps = Omit<AdminLayoutProps, "userRole">;
|
||||
|
||||
export default async function AdminLayoutAppDir(props: AdminLayoutAppDirProps) {
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
const userRole = session?.user?.role;
|
||||
|
||||
return await SettingsLayoutAppDir({ children: <AdminLayoutAppDirClient {...props} userRole={userRole} /> });
|
||||
|
||||
+2
-1
@@ -12,8 +12,9 @@ export const generateMetadata = async () =>
|
||||
(t) => t("add_webhook_description", { appName: APP_NAME })
|
||||
);
|
||||
|
||||
const Page = async ({ params }: PageProps) => {
|
||||
const Page = async ({ params: _params }: PageProps) => {
|
||||
const t = await getTranslate();
|
||||
const params = await _params;
|
||||
const id = typeof params?.id === "string" ? params.id : undefined;
|
||||
|
||||
const webhook = await WebhookRepository.findByWebhookId(id);
|
||||
|
||||
@@ -12,7 +12,7 @@ import SettingsLayoutAppDirClient from "./SettingsLayoutAppDirClient";
|
||||
type SettingsLayoutAppDirProps = Omit<SettingsLayoutProps, "currentOrg" | "otherTeams">;
|
||||
|
||||
export default async function SettingsLayoutAppDir(props: SettingsLayoutAppDirProps) {
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
|
||||
const userId = session?.user?.id ?? -1;
|
||||
const orgId = session?.user?.org?.id ?? -1;
|
||||
|
||||
@@ -19,7 +19,7 @@ export const generateMetadata = async () =>
|
||||
const getData = withAppDirSsr<inferSSRProps<typeof getServerSideProps>>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
await getData(buildLegacyCtx(await headers(), await cookies(), await params, await searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<CreateANewLicenseKeyForm />
|
||||
|
||||
@@ -17,7 +17,7 @@ export const generateMetadata = async () =>
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
await getData(buildLegacyCtx(await headers(), await cookies(), await params, await searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<LegacyPage />
|
||||
|
||||
@@ -17,7 +17,7 @@ export const generateMetadata = async () =>
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
await getData(buildLegacyCtx(await headers(), await cookies(), await params, await searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<LegacyPage />
|
||||
|
||||
@@ -18,7 +18,7 @@ export const generateMetadata = async () =>
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
await getData(buildLegacyCtx(await headers(), await cookies(), await params, await searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<LegacyPage />
|
||||
|
||||
@@ -17,7 +17,7 @@ export const generateMetadata = async () =>
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
await getData(buildLegacyCtx(await headers(), await cookies(), await params, await searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<LegacyPage />
|
||||
|
||||
@@ -23,7 +23,7 @@ type Props = {
|
||||
const getData = withAppDirSsr<Props>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
await getData(buildLegacyCtx(await headers(), await cookies(), await params, await searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<LicenseRequired>
|
||||
|
||||
@@ -17,7 +17,7 @@ export const generateMetadata = async () =>
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
await getData(buildLegacyCtx(await headers(), await cookies(), await params, await searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<LegacyPage />
|
||||
|
||||
@@ -23,7 +23,7 @@ export const generateMetadata = async () =>
|
||||
const getData = withAppDirSsr<Props>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
await getData(buildLegacyCtx(headers(), cookies(), params, searchParams));
|
||||
await getData(buildLegacyCtx(await headers(), await cookies(), await params, await searchParams));
|
||||
return (
|
||||
<LayoutWrapper>
|
||||
<LicenseRequired>
|
||||
|
||||
@@ -18,7 +18,7 @@ export const generateMetadata = async () =>
|
||||
const getData = withAppDirSsr<SignupProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: PageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
|
||||
const props = await getData(context);
|
||||
return <Signup {...props} />;
|
||||
|
||||
@@ -39,7 +39,7 @@ export const generateMetadata = async () => {
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
|
||||
const props = await getData(context);
|
||||
return <VideosSingleView {...props} />;
|
||||
|
||||
@@ -18,7 +18,7 @@ export const generateMetadata = async () =>
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
|
||||
const props = await getData(context);
|
||||
return <MeetingEnded {...props} />;
|
||||
|
||||
@@ -18,7 +18,7 @@ const querySchema = z.object({
|
||||
});
|
||||
|
||||
export const generateMetadata = async ({ params }: ServerPageProps) => {
|
||||
const parsed = querySchema.safeParse(params);
|
||||
const parsed = querySchema.safeParse(await params);
|
||||
if (!parsed.success) {
|
||||
notFound();
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export const generateMetadata = async ({ params }: ServerPageProps) => {
|
||||
const getData = withAppDirSsr<ClientPageProps>(getServerSideProps);
|
||||
|
||||
const ServerPage = async ({ params, searchParams }: ServerPageProps) => {
|
||||
const context = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const context = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
|
||||
const props = await getData(context);
|
||||
return <MeetingNotStarted {...props} />;
|
||||
|
||||
@@ -23,7 +23,7 @@ const querySchema = z.object({
|
||||
const getWorkflow = cache((id: number) => WorkflowRepository.getById({ id }));
|
||||
|
||||
export const generateMetadata = async ({ params }: PageProps): Promise<Metadata | null> => {
|
||||
const parsed = querySchema.safeParse(params);
|
||||
const parsed = querySchema.safeParse(await params);
|
||||
if (!parsed.success) {
|
||||
notFound();
|
||||
}
|
||||
@@ -38,9 +38,9 @@ export const generateMetadata = async ({ params }: PageProps): Promise<Metadata
|
||||
};
|
||||
|
||||
const Page = async ({ params }: PageProps) => {
|
||||
// const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
// const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
// const user = session?.user;
|
||||
const parsed = querySchema.safeParse(params);
|
||||
const parsed = querySchema.safeParse(await params);
|
||||
if (!parsed.success) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export const generateMetadata = async () =>
|
||||
);
|
||||
|
||||
const Page = async ({ params, searchParams }: PageProps) => {
|
||||
// const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
// const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
// const user = session?.user;
|
||||
|
||||
// const filters = getTeamsFiltersFromQuery({ ...searchParams, ...params });
|
||||
|
||||
@@ -7,8 +7,8 @@ export type SearchParams = {
|
||||
};
|
||||
|
||||
export type PageProps = {
|
||||
params: Params;
|
||||
searchParams: SearchParams;
|
||||
params: Promise<Params>;
|
||||
searchParams: Promise<SearchParams>;
|
||||
};
|
||||
|
||||
export type LayoutProps = { params: Params; children: React.ReactElement };
|
||||
export type LayoutProps = { params: Promise<Params>; children: React.ReactElement };
|
||||
|
||||
+7
-39
@@ -1,6 +1,4 @@
|
||||
import { type TFunction } from "i18next";
|
||||
import i18next from "i18next";
|
||||
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { getLocale } from "@calcom/features/auth/lib/getLocale";
|
||||
@@ -8,48 +6,19 @@ import type { AppImageProps, MeetingImageProps } from "@calcom/lib/OgImages";
|
||||
import { constructAppImage, constructGenericImage, constructMeetingImage } from "@calcom/lib/OgImages";
|
||||
import { IS_CALCOM, WEBAPP_URL, APP_NAME, SEO_IMG_OGIMG, CAL_URL } from "@calcom/lib/constants";
|
||||
import { buildCanonical } from "@calcom/lib/next-seo.config";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import { truncateOnWord } from "@calcom/lib/text";
|
||||
//@ts-expect-error no type definitions
|
||||
import config from "@calcom/web/next-i18next.config";
|
||||
|
||||
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
|
||||
|
||||
const i18nInstanceCache: Record<string, any> = {};
|
||||
|
||||
const createI18nInstance = async (locale: string, ns: string) => {
|
||||
const cacheKey = `${locale}-${ns}`;
|
||||
// Check module-level cache first
|
||||
if (i18nInstanceCache[cacheKey]) {
|
||||
return i18nInstanceCache[cacheKey];
|
||||
}
|
||||
|
||||
const { _nextI18Next } = await serverSideTranslations(locale, [ns], config);
|
||||
|
||||
const _i18n = i18next.createInstance();
|
||||
await _i18n.init({
|
||||
lng: locale,
|
||||
resources: _nextI18Next?.initialI18nStore,
|
||||
fallbackLng: _nextI18Next?.userConfig?.i18n.defaultLocale,
|
||||
});
|
||||
|
||||
// Cache the instance
|
||||
i18nInstanceCache[cacheKey] = _i18n;
|
||||
return _i18n;
|
||||
};
|
||||
|
||||
const getTranslationWithCache = async (locale: string, ns = "common") => {
|
||||
const localeWithFallback = locale ?? "en";
|
||||
const i18n = await createI18nInstance(localeWithFallback, ns);
|
||||
return i18n.getFixedT(localeWithFallback, ns);
|
||||
};
|
||||
|
||||
export const getTranslate = async () => {
|
||||
const headersList = await headers();
|
||||
// If "x-locale" does not exist in header,
|
||||
// ensure that config.matcher in middleware includes the page you are testing
|
||||
const locale = headersList.get("x-locale") ?? (await getLocale(buildLegacyRequest(headersList, cookies())));
|
||||
const t = await getTranslationWithCache(locale ?? "en");
|
||||
return t;
|
||||
const locale =
|
||||
headersList.get("x-locale") ?? (await getLocale(buildLegacyRequest(headersList, await cookies())));
|
||||
|
||||
return await getTranslation(locale ?? "en", "common");
|
||||
};
|
||||
|
||||
const _generateMetadataWithoutImage = async (
|
||||
@@ -59,11 +28,10 @@ const _generateMetadataWithoutImage = async (
|
||||
origin?: string,
|
||||
pathname?: string
|
||||
) => {
|
||||
const h = headers();
|
||||
const h = await headers();
|
||||
const _pathname = h.get("x-pathname") ?? pathname ?? "";
|
||||
const canonical = buildCanonical({ path: _pathname, origin: origin ?? CAL_URL });
|
||||
const locale = h.get("x-locale") ?? (await getLocale(buildLegacyRequest(h, cookies()))) ?? "en";
|
||||
const t = await getTranslationWithCache(locale);
|
||||
const t = await getTranslate();
|
||||
|
||||
const title = getTitle(t);
|
||||
const description = getDescription(t);
|
||||
|
||||
@@ -16,7 +16,7 @@ import { buildLegacyRequest } from "@lib/buildLegacyCtx";
|
||||
|
||||
async function handler(req: NextRequest) {
|
||||
const body = await parseRequestData(req);
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
|
||||
if (!session) {
|
||||
return NextResponse.json({ message: "Not authenticated" }, { status: 401 });
|
||||
|
||||
@@ -14,7 +14,7 @@ import { buildLegacyRequest } from "@lib/buildLegacyCtx";
|
||||
|
||||
async function postHandler(req: NextRequest) {
|
||||
const body = await parseRequestData(req);
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
|
||||
if (!session) {
|
||||
return NextResponse.json({ message: "Not authenticated" }, { status: 401 });
|
||||
|
||||
@@ -18,7 +18,7 @@ import { buildLegacyRequest } from "@lib/buildLegacyCtx";
|
||||
|
||||
async function postHandler(req: NextRequest) {
|
||||
const body = await parseRequestData(req);
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
|
||||
if (!session) {
|
||||
return NextResponse.json({ message: "Not authenticated" }, { status: 401 });
|
||||
|
||||
@@ -23,7 +23,7 @@ const selectedCalendarSelectSchema = z.object({
|
||||
});
|
||||
|
||||
async function authMiddleware() {
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
|
||||
if (!session?.user?.id) {
|
||||
throw new HttpError({ statusCode: 401, message: "Not authenticated" });
|
||||
|
||||
@@ -26,8 +26,8 @@ const handleValidationError = (error: z.ZodError): NextResponse => {
|
||||
);
|
||||
};
|
||||
|
||||
async function handler(req: NextRequest, { params }: { params: Params }) {
|
||||
const result = querySchema.safeParse(params);
|
||||
async function handler(req: NextRequest, { params }: { params: Promise<Params> }) {
|
||||
const result = querySchema.safeParse(await params);
|
||||
if (!result.success) {
|
||||
return handleValidationError(result.error);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ async function handler(req: NextRequest) {
|
||||
} catch (error) {
|
||||
return NextResponse.json({ success: false, message: "Invalid JSON" }, { status: 400 });
|
||||
}
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
const result = await handleCancelBooking({
|
||||
appDirRequestBody,
|
||||
userId: session?.user?.id || -1,
|
||||
|
||||
@@ -457,7 +457,7 @@ const inputSchema = z.object({
|
||||
});
|
||||
|
||||
async function handler(request: NextRequest) {
|
||||
const headersList = headers();
|
||||
const headersList = await headers();
|
||||
const requestBody = await request.json();
|
||||
|
||||
// HMAC verification
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Params } from "app/_types";
|
||||
import { NextResponse, type NextRequest } from "next/server";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
@@ -21,7 +22,7 @@ describe("defaultResponderForAppDir", () => {
|
||||
it("should return a JSON response when handler resolves with a result", async () => {
|
||||
const f = vi.fn().mockResolvedValue(NextResponse.json({ success: true }));
|
||||
const req = { method: "GET", url: "/api/test" } as unknown as NextRequest;
|
||||
const params = {};
|
||||
const params = Promise.resolve<Params>({})
|
||||
|
||||
const response = await defaultResponderForAppDir(f)(req, { params });
|
||||
const json = await response.json();
|
||||
@@ -33,7 +34,7 @@ describe("defaultResponderForAppDir", () => {
|
||||
it("should return an empty JSON response when handler resolves with no result", async () => {
|
||||
const f = vi.fn().mockResolvedValue(null);
|
||||
const req = { method: "GET", url: "/api/test" } as unknown as NextRequest;
|
||||
const params = {};
|
||||
const params = Promise.resolve<Params>({})
|
||||
|
||||
const response = await defaultResponderForAppDir(f)(req, { params });
|
||||
const json = await response.json();
|
||||
@@ -45,7 +46,7 @@ describe("defaultResponderForAppDir", () => {
|
||||
it("should respond with status code 409 for NoAvailableUsersFound", async () => {
|
||||
const f = vi.fn().mockRejectedValue(new Error(ErrorCode.NoAvailableUsersFound));
|
||||
const req = { method: "GET", url: "/api/test" } as unknown as NextRequest;
|
||||
const params = {};
|
||||
const params = Promise.resolve<Params>({})
|
||||
|
||||
const response = await defaultResponderForAppDir(f)(req, { params });
|
||||
const json = await response.json();
|
||||
@@ -61,7 +62,7 @@ describe("defaultResponderForAppDir", () => {
|
||||
it("should respond with a 429 status code for rate limit errors", async () => {
|
||||
const f = vi.fn().mockRejectedValue(new TRPCError({ code: "TOO_MANY_REQUESTS" }));
|
||||
const req = { method: "POST", url: "/api/test" } as unknown as NextRequest;
|
||||
const params = {};
|
||||
const params = Promise.resolve<Params>({})
|
||||
|
||||
const response = await defaultResponderForAppDir(f)(req, { params });
|
||||
const json = await response.json();
|
||||
|
||||
@@ -9,14 +9,14 @@ import { performance } from "@calcom/lib/server/perfObserver";
|
||||
|
||||
type Handler<T extends NextResponse | Response = NextResponse> = (
|
||||
req: NextRequest,
|
||||
{ params }: { params: Params }
|
||||
{ params }: { params: Promise<Params> }
|
||||
) => Promise<T>;
|
||||
|
||||
export const defaultResponderForAppDir = <T extends NextResponse | Response = NextResponse>(
|
||||
handler: Handler<T>,
|
||||
endpointRoute?: string
|
||||
) => {
|
||||
return async (req: NextRequest, { params }: { params: Params }) => {
|
||||
return async (req: NextRequest, { params }: { params: Promise<Params> }) => {
|
||||
let ok = false;
|
||||
try {
|
||||
performance.mark("Start");
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
|
||||
import { cookies, headers } from "next/headers";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { FUTURE_ROUTES_OVERRIDE_COOKIE_NAME as COOKIE_NAME } from "@calcom/lib/constants";
|
||||
|
||||
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
|
||||
|
||||
async function getHandler() {
|
||||
const headersList = headers();
|
||||
const cookiesList = cookies();
|
||||
const legacyReq = buildLegacyRequest(headersList, cookiesList);
|
||||
|
||||
const session = await getServerSession({ req: legacyReq });
|
||||
|
||||
if (!session || !session.user || !session.user.email) {
|
||||
return NextResponse.json({ message: "Not authenticated" }, { status: 401 });
|
||||
}
|
||||
|
||||
let redirectUrl = "/";
|
||||
|
||||
// We take you back where you came from if possible
|
||||
const referer = headersList.get("referer");
|
||||
if (referer) redirectUrl = referer;
|
||||
|
||||
const response = NextResponse.redirect(redirectUrl);
|
||||
|
||||
// If has the cookie, Opt-out of V2
|
||||
if (cookiesList.has(COOKIE_NAME) && cookiesList.get(COOKIE_NAME)?.value === "1") {
|
||||
response.cookies.set(COOKIE_NAME, "0", { maxAge: 0, path: "/" });
|
||||
} else {
|
||||
/* Opt-in to V2 */
|
||||
response.cookies.set(COOKIE_NAME, "1", { path: "/" });
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const GET = defaultResponderForAppDir(getHandler);
|
||||
@@ -9,8 +9,8 @@ import prisma from "@calcom/prisma";
|
||||
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
|
||||
|
||||
async function postHandler() {
|
||||
const headersList = headers();
|
||||
const cookiesList = cookies();
|
||||
const headersList = await headers();
|
||||
const cookiesList = await cookies();
|
||||
const legacyReq = buildLegacyRequest(headersList, cookiesList);
|
||||
|
||||
const session = await getServerSession({ req: legacyReq });
|
||||
|
||||
@@ -3,7 +3,7 @@ import { headers } from "next/headers";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
async function getHandler() {
|
||||
const headersList = headers();
|
||||
const headersList = await headers();
|
||||
const country = headersList.get("x-vercel-ip-country") || "Unknown";
|
||||
|
||||
const response = NextResponse.json({ country });
|
||||
|
||||
@@ -8,8 +8,8 @@ import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
|
||||
|
||||
async function getHandler() {
|
||||
const headersList = headers();
|
||||
const cookiesList = cookies();
|
||||
const headersList = await headers();
|
||||
const cookiesList = await cookies();
|
||||
const legacyReq = buildLegacyRequest(headersList, cookiesList);
|
||||
|
||||
const session = await getServerSession({ req: legacyReq });
|
||||
|
||||
@@ -79,7 +79,7 @@ async function handler(request: NextRequest) {
|
||||
try {
|
||||
/** @see https://trpc.io/docs/server-side-calls */
|
||||
// Create a legacy request object for compatibility
|
||||
const legacyReq = buildLegacyRequest(headers(), cookies());
|
||||
const legacyReq = buildLegacyRequest(await headers(), await cookies());
|
||||
const res = {} as any; // Response is still mocked as it's not used in this context
|
||||
|
||||
const ctx = await createContext({ req: legacyReq, res }, sessionGetter);
|
||||
|
||||
@@ -168,7 +168,7 @@ async function getHandler(request: NextRequest) {
|
||||
const parsedQuery = logoApiSchema.parse(Object.fromEntries(searchParams.entries()));
|
||||
|
||||
// Create a legacy request object for compatibility
|
||||
const legacyReq = buildLegacyRequest(headers(), cookies());
|
||||
const legacyReq = buildLegacyRequest(await headers(), await cookies());
|
||||
const { isValidOrgDomain } = orgDomainConfig(legacyReq);
|
||||
|
||||
const hostname = request.headers.get("host");
|
||||
|
||||
@@ -15,7 +15,7 @@ async function getHandler() {
|
||||
const preSessionDate = performance.now();
|
||||
|
||||
// Create a legacy request object for compatibility
|
||||
const legacyReq = buildLegacyRequest(headers(), cookies());
|
||||
const legacyReq = buildLegacyRequest(await headers(), await cookies());
|
||||
|
||||
const session = await getServerSession({ req: legacyReq });
|
||||
if (!session) {
|
||||
|
||||
@@ -26,7 +26,7 @@ async function handler() {
|
||||
return NextResponse.json({ error: "Plain Chat is not enabled" }, { status: 404 });
|
||||
}
|
||||
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
if (!session?.user?.email) {
|
||||
return NextResponse.json({ error: "Unauthorized - No session email found" }, { status: 401 });
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ export async function postHandler(request: NextRequest) {
|
||||
return NextResponse.json({ message: "Test request successful" });
|
||||
}
|
||||
|
||||
const headersList = headers();
|
||||
const headersList = await headers();
|
||||
const testMode = process.env.NEXT_PUBLIC_IS_E2E || process.env.INTEGRATION_TEST_MODE;
|
||||
|
||||
if (!testMode) {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { DirectorySyncEvent, DirectorySyncRequest } from "@boxyhq/saml-jackson";
|
||||
import type { Params } from "app/_types";
|
||||
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
|
||||
import handleGroupEvents from "@calcom/features/ee/dsync/lib/handleGroupEvents";
|
||||
import handleUserEvents from "@calcom/features/ee/dsync/lib/handleUserEvents";
|
||||
@@ -51,35 +53,40 @@ const handleEvents = async (event: DirectorySyncEvent) => {
|
||||
}
|
||||
};
|
||||
|
||||
const querySchema = z.object({
|
||||
directory: z.string().array(),
|
||||
});
|
||||
|
||||
// This is the handler for the SCIM API requests
|
||||
async function getHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
|
||||
return handleScimRequest(request, "GET", params.directory);
|
||||
async function getHandler(request: NextRequest, { params }: { params: Promise<Params> }) {
|
||||
return handleScimRequest(request, "GET", params);
|
||||
}
|
||||
|
||||
async function postHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
|
||||
return handleScimRequest(request, "POST", params.directory);
|
||||
async function postHandler(request: NextRequest, { params }: { params: Promise<Params> }) {
|
||||
return handleScimRequest(request, "POST", params);
|
||||
}
|
||||
|
||||
async function putHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
|
||||
return handleScimRequest(request, "PUT", params.directory);
|
||||
async function putHandler(request: NextRequest, { params }: { params: Promise<Params> }) {
|
||||
return handleScimRequest(request, "PUT", params);
|
||||
}
|
||||
|
||||
async function patchHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
|
||||
return handleScimRequest(request, "PATCH", params.directory);
|
||||
async function patchHandler(request: NextRequest, { params }: { params: Promise<Params> }) {
|
||||
return handleScimRequest(request, "PATCH", params);
|
||||
}
|
||||
|
||||
async function deleteHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
|
||||
return handleScimRequest(request, "DELETE", params.directory);
|
||||
async function deleteHandler(request: NextRequest, { params }: { params: Promise<Params> }) {
|
||||
return handleScimRequest(request, "DELETE", params);
|
||||
}
|
||||
|
||||
async function handleScimRequest(request: NextRequest, method: string, directoryParams?: string[]) {
|
||||
const { dsyncController } = await jackson();
|
||||
|
||||
if (!directoryParams || directoryParams.length === 0) {
|
||||
async function handleScimRequest(request: NextRequest, method: string, params: Promise<Params>) {
|
||||
const parsed = querySchema.safeParse(await params);
|
||||
if (!parsed.success || parsed.data.directory.length === 0) {
|
||||
return NextResponse.json({ error: "Missing directory parameters" }, { status: 400 });
|
||||
}
|
||||
|
||||
const [directoryId, path, resourceId] = directoryParams;
|
||||
const { dsyncController } = await jackson();
|
||||
|
||||
const [directoryId, path, resourceId] = parsed.data.directory;
|
||||
const shouldLog = DIRECTORY_IDS_TO_LOG.includes(directoryId);
|
||||
|
||||
const searchParams = request.nextUrl.searchParams;
|
||||
@@ -90,7 +97,7 @@ async function handleScimRequest(request: NextRequest, method: string, directory
|
||||
safeStringify({
|
||||
method,
|
||||
url: request.url,
|
||||
params: directoryParams,
|
||||
params: parsed.data.directory,
|
||||
searchParams: Object.fromEntries(searchParams.entries()),
|
||||
body: request.body
|
||||
? await request
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
import { ImageResponse } from "next/og";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { ImageResponse } from "next/server";
|
||||
import type { SatoriOptions } from "satori";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Meeting, App, Generic } from "@calcom/lib/OgImages";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
|
||||
const calFont = fetch(new URL("/fonts/cal.ttf", WEBAPP_URL)).then((res) => res.arrayBuffer());
|
||||
|
||||
const interFont = fetch(new URL("/fonts/Inter-Regular.ttf", WEBAPP_URL)).then((res) => res.arrayBuffer());
|
||||
|
||||
const interFontMedium = fetch(new URL("/fonts/Inter-Medium.ttf", WEBAPP_URL)).then((res) =>
|
||||
res.arrayBuffer()
|
||||
);
|
||||
|
||||
export const runtime = "edge";
|
||||
|
||||
const meetingSchema = z.object({
|
||||
@@ -43,9 +35,9 @@ async function handler(req: NextRequest) {
|
||||
const imageType = searchParams.get("type");
|
||||
|
||||
const [calFontData, interFontData, interFontMediumData] = await Promise.all([
|
||||
calFont,
|
||||
interFont,
|
||||
interFontMedium,
|
||||
fetch(new URL("/fonts/cal.ttf", WEBAPP_URL)).then((res) => res.arrayBuffer()),
|
||||
fetch(new URL("/fonts/Inter-Regular.ttf", WEBAPP_URL)).then((res) => res.arrayBuffer()),
|
||||
fetch(new URL("/fonts/Inter-Medium.ttf", WEBAPP_URL)).then((res) => res.arrayBuffer()),
|
||||
]);
|
||||
const ogConfig = {
|
||||
width: 1200,
|
||||
|
||||
@@ -29,7 +29,7 @@ async function postHandler(request: NextRequest) {
|
||||
if (!process.env.CALENDSO_ENCRYPTION_KEY)
|
||||
return NextResponse.json({ message: "Missing encryption key" }, { status: 500 });
|
||||
|
||||
const legacyRequest = buildLegacyRequest(headers(), cookies());
|
||||
const legacyRequest = buildLegacyRequest(await headers(), await cookies());
|
||||
|
||||
// Get the raw request body
|
||||
const rawBody = await getRawBody(legacyRequest);
|
||||
|
||||
@@ -21,11 +21,11 @@ const querySchema = z.object({
|
||||
session_id: z.string().min(1),
|
||||
});
|
||||
|
||||
async function getHandler(req: NextRequest, { params }: { params: Params }) {
|
||||
async function getHandler(req: NextRequest, { params }: { params: Promise<Params> }) {
|
||||
try {
|
||||
const searchParams = req.nextUrl.searchParams;
|
||||
const { team: id, session_id } = querySchema.parse({
|
||||
team: params.team,
|
||||
team: (await params).team,
|
||||
session_id: searchParams.get("session_id"),
|
||||
});
|
||||
|
||||
@@ -86,7 +86,7 @@ async function getHandler(req: NextRequest, { params }: { params: Params }) {
|
||||
}
|
||||
}
|
||||
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
|
||||
if (!session) {
|
||||
return NextResponse.json({ message: "Team upgraded successfully" });
|
||||
|
||||
@@ -20,8 +20,8 @@ const stateSchema = z.object({
|
||||
|
||||
async function getHandler(request: NextRequest) {
|
||||
try {
|
||||
const headersList = headers();
|
||||
const cookiesList = cookies();
|
||||
const headersList = await headers();
|
||||
const cookiesList = await cookies();
|
||||
const legacyReq = buildLegacyRequest(headersList, cookiesList);
|
||||
|
||||
const session = await getServerSession({ req: legacyReq });
|
||||
|
||||
@@ -19,7 +19,7 @@ async function postHandler(request: NextRequest) {
|
||||
const body = await request.json();
|
||||
const { username, orgSlug } = bodySchema.parse(body);
|
||||
|
||||
const legacyReq = buildLegacyRequest(headers(), cookies());
|
||||
const legacyReq = buildLegacyRequest(await headers(), await cookies());
|
||||
|
||||
// Get current org domain from request headers
|
||||
const { currentOrgDomain } = orgDomainConfig(legacyReq);
|
||||
|
||||
@@ -118,7 +118,7 @@ async function handleBookingAction(
|
||||
const createCaller = createCallerFactory(bookingsRouter);
|
||||
|
||||
// Use buildLegacyRequest to create a request object compatible with Pages Router
|
||||
const legacyReq = request ? buildLegacyRequest(headers(), cookies()) : ({} as any);
|
||||
const legacyReq = request ? buildLegacyRequest(await headers(), await cookies()) : ({} as any);
|
||||
const res = {} as any;
|
||||
|
||||
const ctx = await createContext({ req: legacyReq, res }, sessionGetter);
|
||||
|
||||
@@ -44,4 +44,3 @@ export default async function IconsPage() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export const dynamic = "force-static";
|
||||
|
||||
+57
-5
@@ -9,7 +9,6 @@ import { IconSprites } from "@calcom/ui/components/icon";
|
||||
import { NotificationSoundHandler } from "@calcom/web/components/notification-sound-handler";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { prepareRootMetadata } from "@lib/metadata";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
@@ -26,7 +25,60 @@ const calFont = localFont({
|
||||
weight: "600",
|
||||
});
|
||||
|
||||
export const generateMetadata = () => prepareRootMetadata();
|
||||
export const viewport = {
|
||||
width: "device-width",
|
||||
initialScale: 1.0,
|
||||
maximumScale: 1.0,
|
||||
userScalable: false,
|
||||
viewportFit: "cover",
|
||||
themeColor: [
|
||||
{
|
||||
media: "(prefers-color-scheme: light)",
|
||||
color: "#f9fafb",
|
||||
},
|
||||
{
|
||||
media: "(prefers-color-scheme: dark)",
|
||||
color: "#1C1C1C",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const metadata = {
|
||||
icons: {
|
||||
icon: "/favicon.ico",
|
||||
apple: "/api/logo?type=apple-touch-icon",
|
||||
other: [
|
||||
{
|
||||
rel: "icon-mask",
|
||||
url: "/safari-pinned-tab.svg",
|
||||
color: "#000000",
|
||||
},
|
||||
{
|
||||
url: "/api/logo?type=favicon-16",
|
||||
sizes: "16x16",
|
||||
type: "image/png",
|
||||
},
|
||||
{
|
||||
url: "/api/logo?type=favicon-32",
|
||||
sizes: "32x32",
|
||||
type: "image/png",
|
||||
},
|
||||
],
|
||||
},
|
||||
manifest: "/site.webmanifest",
|
||||
other: {
|
||||
"application-TileColor": "#ff0000",
|
||||
},
|
||||
twitter: {
|
||||
site: "@calcom",
|
||||
creator: "@calcom",
|
||||
card: "summary_large_image",
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
const getInitialProps = async (url: string) => {
|
||||
const { pathname, searchParams } = new URL(url);
|
||||
@@ -34,7 +86,7 @@ const getInitialProps = async (url: string) => {
|
||||
const isEmbed = pathname.endsWith("/embed") || (searchParams?.get("embedType") ?? null) !== null;
|
||||
const embedColorScheme = searchParams?.get("ui.color-scheme");
|
||||
|
||||
const req = { headers: headers(), cookies: cookies() };
|
||||
const req = { headers: await headers(), cookies: await cookies() };
|
||||
const newLocale = await getLocale(req);
|
||||
const direction = dir(newLocale);
|
||||
|
||||
@@ -49,7 +101,7 @@ const getFallbackProps = () => ({
|
||||
});
|
||||
|
||||
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
const h = headers();
|
||||
const h = await headers();
|
||||
|
||||
const fullUrl = h.get("x-url") ?? "";
|
||||
const nonce = h.get("x-csp") ?? "";
|
||||
@@ -60,7 +112,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
|
||||
? getFallbackProps()
|
||||
: await getInitialProps(fullUrl);
|
||||
|
||||
const ssr = await ssrInit(buildLegacyCtx(h, cookies(), {}, {}));
|
||||
const ssr = await ssrInit(buildLegacyCtx(h, await cookies(), {}, {}));
|
||||
return (
|
||||
<html
|
||||
lang={locale}
|
||||
|
||||
@@ -221,7 +221,7 @@ function NotFound({ t, headers }: { t: any; headers: ReadonlyHeaders }) {
|
||||
}
|
||||
|
||||
export const generateMetadata = async () => {
|
||||
const headersList = headers();
|
||||
const headersList = await headers();
|
||||
const pathname = headersList.get("x-pathname") ?? "";
|
||||
const isInsights = pathname?.startsWith("/insights");
|
||||
|
||||
@@ -243,7 +243,7 @@ export const generateMetadata = async () => {
|
||||
|
||||
const ServerPage = async () => {
|
||||
const t = await getTranslate();
|
||||
const h = headers();
|
||||
const h = await headers();
|
||||
const nonce = h.get("x-nonce") ?? undefined;
|
||||
return (
|
||||
<PageWrapper requiresLicense={false} nonce={nonce}>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
|
||||
|
||||
const RedirectPage = async () => {
|
||||
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
|
||||
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
|
||||
|
||||
if (!session?.user?.id) {
|
||||
redirect("/auth/login");
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getServerSideProps } from "@lib/reschedule/[uid]/getServerSideProps";
|
||||
const getEmbedData = withEmbedSsrAppDir(getServerSideProps);
|
||||
|
||||
const Page = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
await getEmbedData(legacyCtx);
|
||||
|
||||
return null;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getServerSideProps } from "@lib/reschedule/[uid]/getServerSideProps";
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
|
||||
const Page = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
const legacyCtx = buildLegacyCtx(await headers(), await cookies(), await params, await searchParams);
|
||||
|
||||
await getData(legacyCtx);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ const paramsSchema = z
|
||||
pages: [],
|
||||
});
|
||||
|
||||
export default function RoutingForms({ params }: PageProps) {
|
||||
const { pages } = paramsSchema.parse(params);
|
||||
export default async function RoutingForms({ params }: PageProps) {
|
||||
const { pages } = paramsSchema.parse(await params);
|
||||
redirect(`/apps/routing-forms/${pages.length ? pages.join("/") : ""}`);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import type { SSRConfig } from "next-i18next";
|
||||
import type { SSRConfig } from "next-i18next/dist/types/types";
|
||||
// import I18nLanguageHandler from "@components/I18nLanguageHandler";
|
||||
import { usePathname } from "next/navigation";
|
||||
import Script from "next/script";
|
||||
|
||||
@@ -0,0 +1,376 @@
|
||||
import type { TFunction } from "i18next";
|
||||
import type { ReactNode, ReactElement, FC } from "react";
|
||||
import React, { isValidElement, Fragment, createElement, cloneElement } from "react";
|
||||
|
||||
type ServerTransProps = {
|
||||
i18nKey: string; // Translation key
|
||||
components?: ReactElement[] | Record<string, ReactElement>; // Components to inject
|
||||
t: TFunction;
|
||||
values?: Record<string, string | number>; // Values for interpolation
|
||||
children?: ReactNode; // Children as fallback content
|
||||
parent?: React.ElementType; // Parent element to wrap content in
|
||||
};
|
||||
|
||||
/**
|
||||
* A custom Trans component that doesn't use React Context
|
||||
* Handles HTML tags and component interpolation in translations
|
||||
*/
|
||||
const ServerTrans: FC<ServerTransProps> = ({
|
||||
i18nKey,
|
||||
components = [],
|
||||
t,
|
||||
values = {},
|
||||
children,
|
||||
parent,
|
||||
}) => {
|
||||
const translationOptions = { ...values };
|
||||
// Get translated content
|
||||
const content = t(i18nKey, translationOptions);
|
||||
|
||||
// If no content at all, use children as fallback
|
||||
if (!content && children) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
// If no content, return empty fragment
|
||||
if (!content) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
let result: ReactNode[];
|
||||
|
||||
// Process array-based components like <0>content</0>
|
||||
if (Array.isArray(components) && components.length > 0) {
|
||||
result = parseArrayComponents(content, components);
|
||||
}
|
||||
// Process object-based components like <tag>content</tag> or {{tag}}
|
||||
else if (isObject(components) && Object.keys(components).length > 0) {
|
||||
result = parseObjectComponents(content, components as Record<string, ReactElement>);
|
||||
}
|
||||
// Process just HTML tags
|
||||
else {
|
||||
result = parseHtmlTags(content);
|
||||
}
|
||||
|
||||
// Wrap in parent element if specified
|
||||
if (parent) {
|
||||
const Parent = parent;
|
||||
return <Parent>{result}</Parent>;
|
||||
}
|
||||
|
||||
return <>{result}</>;
|
||||
};
|
||||
|
||||
// Utility function to check if object
|
||||
const isObject = (obj: any): obj is Record<string, unknown> =>
|
||||
obj !== null && typeof obj === "object" && !Array.isArray(obj);
|
||||
|
||||
// Parse array-based components like <0>content</0>
|
||||
const parseArrayComponents = (content: string, components: ReactElement[]): ReactNode[] => {
|
||||
const parts: ReactNode[] = [];
|
||||
let currentText = "";
|
||||
|
||||
// Simple state machine parser to handle nested tags
|
||||
const parseContent = (text: string) => {
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
// Look for opening tag
|
||||
if (text[i] === "<" && /\d/.test(text[i + 1])) {
|
||||
// Found potential component tag
|
||||
let tagIndex = "";
|
||||
let j = i + 1;
|
||||
|
||||
// Read the tag index
|
||||
while (j < text.length && /\d/.test(text[j])) {
|
||||
tagIndex += text[j];
|
||||
j++;
|
||||
}
|
||||
|
||||
// Check if it's a valid tag
|
||||
if (j < text.length && text[j] === ">") {
|
||||
// It's an opening tag, save text before it
|
||||
if (currentText) {
|
||||
// Process any HTML in the text
|
||||
parts.push(...parseHtmlTags(currentText));
|
||||
currentText = "";
|
||||
}
|
||||
|
||||
// Get the content inside the tag
|
||||
const closingTag = `</${tagIndex}>`;
|
||||
const tagContent = getTextBetweenTags(text.substring(j + 1), tagIndex);
|
||||
|
||||
if (tagContent !== null) {
|
||||
// We found the content, now add the component
|
||||
const componentIndex = parseInt(tagIndex, 10);
|
||||
|
||||
if (componentIndex < components.length) {
|
||||
const component = components[componentIndex];
|
||||
|
||||
if (isValidElement(component)) {
|
||||
// Add the component with its content
|
||||
parts.push(
|
||||
cloneElement(
|
||||
component,
|
||||
{
|
||||
...(component.props || {}),
|
||||
key: component.key || `comp-${componentIndex}`,
|
||||
},
|
||||
// Process any HTML in the inner content
|
||||
...parseHtmlTags(tagContent)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
// If not a valid element, just add the content
|
||||
parts.push(...parseHtmlTags(tagContent));
|
||||
}
|
||||
} else {
|
||||
// Component index out of bounds, just add the content
|
||||
parts.push(...parseHtmlTags(tagContent));
|
||||
}
|
||||
|
||||
// Skip to after the closing tag
|
||||
i = j + tagContent.length + closingTag.length;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Regular character, add to current text
|
||||
currentText += text[i];
|
||||
}
|
||||
|
||||
// Add any remaining text
|
||||
if (currentText) {
|
||||
parts.push(...parseHtmlTags(currentText));
|
||||
}
|
||||
};
|
||||
|
||||
// Helper to find matching content between tags
|
||||
const getTextBetweenTags = (text: string, tagIndex: string): string | null => {
|
||||
let depth = 1;
|
||||
let content = "";
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
// Check for nested opening tag
|
||||
if (
|
||||
text[i] === "<" &&
|
||||
text.substring(i + 1, i + 1 + tagIndex.length) === tagIndex &&
|
||||
text[i + 1 + tagIndex.length] === ">"
|
||||
) {
|
||||
depth++;
|
||||
content += text.substring(i, i + 2 + tagIndex.length);
|
||||
i += 1 + tagIndex.length;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for closing tag
|
||||
if (
|
||||
text[i] === "<" &&
|
||||
text.substring(i + 1, i + 2 + tagIndex.length) === `/${tagIndex}` &&
|
||||
text[i + 2 + tagIndex.length] === ">"
|
||||
) {
|
||||
depth--;
|
||||
|
||||
if (depth === 0) {
|
||||
// Found the matching closing tag
|
||||
return content;
|
||||
}
|
||||
|
||||
content += text.substring(i, i + 3 + tagIndex.length);
|
||||
i += 2 + tagIndex.length;
|
||||
continue;
|
||||
}
|
||||
|
||||
content += text[i];
|
||||
}
|
||||
|
||||
return null; // No matching closing tag found
|
||||
};
|
||||
|
||||
// Parse the content
|
||||
parseContent(content);
|
||||
|
||||
return parts.length > 0 ? parts : [content];
|
||||
};
|
||||
|
||||
// Parse object-based components like <tag>content</tag> or {{tag}}
|
||||
const parseObjectComponents = (content: string, components: Record<string, ReactElement>): ReactNode[] => {
|
||||
let processedContent = content;
|
||||
const placeholders: Record<string, ReactNode> = {};
|
||||
|
||||
// First handle {{tag}} interpolation
|
||||
Object.keys(components).forEach((tag) => {
|
||||
const interpolationRegex = new RegExp(`{{\\s*${tag}\\s*}}`, "g");
|
||||
processedContent = processedContent.replace(interpolationRegex, (match) => {
|
||||
const placeholder = `__INTERP_${tag}_${Math.random().toString(36).substring(2)}__`;
|
||||
|
||||
if (isValidElement(components[tag])) {
|
||||
placeholders[placeholder] = cloneElement(components[tag], {
|
||||
...(components[tag].props || {}),
|
||||
key: components[tag].key || `interp-${tag}`,
|
||||
});
|
||||
}
|
||||
|
||||
return placeholder;
|
||||
});
|
||||
});
|
||||
|
||||
// Then handle <tag>content</tag>
|
||||
Object.keys(components).forEach((tag) => {
|
||||
const tagRegex = new RegExp(`<${tag}>(.*?)<\\/${tag}>`, "gs");
|
||||
|
||||
processedContent = processedContent.replace(tagRegex, (match, content) => {
|
||||
const placeholder = `__TAG_${tag}_${Math.random().toString(36).substring(2)}__`;
|
||||
|
||||
if (isValidElement(components[tag])) {
|
||||
// Process any HTML in the content
|
||||
const parsedContent = parseHtmlTags(content);
|
||||
|
||||
placeholders[placeholder] = cloneElement(
|
||||
components[tag],
|
||||
{
|
||||
...(components[tag].props || {}),
|
||||
key: components[tag].key || `tag-${tag}`,
|
||||
},
|
||||
...(parsedContent.length > 1 ? parsedContent : [content])
|
||||
);
|
||||
}
|
||||
|
||||
return placeholder;
|
||||
});
|
||||
});
|
||||
|
||||
// Replace placeholders with components and split text parts
|
||||
const parts: ReactNode[] = [];
|
||||
let lastIndex = 0;
|
||||
|
||||
// Find all placeholders in order
|
||||
const placeholderRegex = /__(?:INTERP|TAG)_[^_]+_[a-z0-9]+__/g;
|
||||
let match;
|
||||
|
||||
while ((match = placeholderRegex.exec(processedContent)) !== null) {
|
||||
const [placeholder] = match;
|
||||
const index = match.index;
|
||||
|
||||
// Add text before placeholder
|
||||
if (index > lastIndex) {
|
||||
const textBefore = processedContent.substring(lastIndex, index);
|
||||
parts.push(...parseHtmlTags(textBefore));
|
||||
}
|
||||
|
||||
// Add the component
|
||||
if (placeholders[placeholder]) {
|
||||
parts.push(placeholders[placeholder]);
|
||||
}
|
||||
|
||||
lastIndex = index + placeholder.length;
|
||||
}
|
||||
|
||||
// Add any remaining text
|
||||
if (lastIndex < processedContent.length) {
|
||||
const textAfter = processedContent.substring(lastIndex);
|
||||
parts.push(...parseHtmlTags(textAfter));
|
||||
}
|
||||
|
||||
return parts.length > 0 ? parts : [processedContent];
|
||||
};
|
||||
|
||||
// Parse HTML tags like <strong>content</strong>
|
||||
const parseHtmlTags = (content: string): ReactNode[] => {
|
||||
if (!content || typeof content !== "string") {
|
||||
return [content].filter(Boolean);
|
||||
}
|
||||
|
||||
// Check if there are any HTML tags
|
||||
if (!/<[a-z][\s\S]*>/i.test(content)) {
|
||||
return [content];
|
||||
}
|
||||
|
||||
// HTML tags to process
|
||||
const htmlTags = [
|
||||
{ tag: "strong", component: "strong" },
|
||||
{ tag: "b", component: "b" },
|
||||
{ tag: "i", component: "i" },
|
||||
{ tag: "em", component: "em" },
|
||||
{ tag: "p", component: "p" },
|
||||
{ tag: "br", component: "br", selfClosing: true },
|
||||
{ tag: "div", component: "div" },
|
||||
{ tag: "span", component: "span" },
|
||||
{ tag: "ul", component: "ul" },
|
||||
{ tag: "ol", component: "ol" },
|
||||
{ tag: "li", component: "li" },
|
||||
];
|
||||
|
||||
let processedContent = content;
|
||||
const placeholders: Record<string, ReactNode> = {};
|
||||
|
||||
// Process each HTML tag
|
||||
htmlTags.forEach(({ tag, component, selfClosing }) => {
|
||||
if (selfClosing) {
|
||||
// Handle self-closing tags like <br/>
|
||||
const selfClosingRegex = new RegExp(`<${tag}\\s*\\/>`, "g");
|
||||
|
||||
processedContent = processedContent.replace(selfClosingRegex, (match) => {
|
||||
const placeholder = `__HTML_${tag}_${Math.random().toString(36).substring(2)}__`;
|
||||
placeholders[placeholder] = createElement(component, { key: placeholder });
|
||||
return placeholder;
|
||||
});
|
||||
} else {
|
||||
// Handle regular tags like <strong>content</strong>
|
||||
const tagRegex = new RegExp(`<${tag}>(.*?)<\\/${tag}>`, "gs");
|
||||
|
||||
processedContent = processedContent.replace(tagRegex, (match, content) => {
|
||||
const placeholder = `__HTML_${tag}_${Math.random().toString(36).substring(2)}__`;
|
||||
|
||||
// Process nested tags recursively
|
||||
const innerContent = parseHtmlTags(content);
|
||||
|
||||
placeholders[placeholder] = createElement(
|
||||
component,
|
||||
{ key: placeholder },
|
||||
...(innerContent.length > 1 ? innerContent : [content])
|
||||
);
|
||||
|
||||
return placeholder;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// If no tags were processed, return the original content
|
||||
if (Object.keys(placeholders).length === 0) {
|
||||
return [processedContent];
|
||||
}
|
||||
|
||||
// Replace placeholders with components and split text parts
|
||||
const parts: ReactNode[] = [];
|
||||
let lastIndex = 0;
|
||||
|
||||
// Find all placeholders in order
|
||||
const placeholderRegex = /__HTML_[^_]+_[a-z0-9]+__/g;
|
||||
let match;
|
||||
|
||||
while ((match = placeholderRegex.exec(processedContent)) !== null) {
|
||||
const [placeholder] = match;
|
||||
const index = match.index;
|
||||
|
||||
// Add text before placeholder
|
||||
if (index > lastIndex) {
|
||||
parts.push(processedContent.substring(lastIndex, index));
|
||||
}
|
||||
|
||||
// Add the component
|
||||
if (placeholders[placeholder]) {
|
||||
parts.push(placeholders[placeholder]);
|
||||
}
|
||||
|
||||
lastIndex = index + placeholder.length;
|
||||
}
|
||||
|
||||
// Add any remaining text
|
||||
if (lastIndex < processedContent.length) {
|
||||
parts.push(processedContent.substring(lastIndex));
|
||||
}
|
||||
|
||||
return parts.length > 0 ? parts : [processedContent];
|
||||
};
|
||||
|
||||
export default ServerTrans;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user