Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

INT-2227 chore: Migrate all pages in /video directory #136

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,4 @@ APP_ROUTER_EVENT_TYPES_ENABLED=1
APP_ROUTER_SETTINGS_ADMIN_ENABLED=1
APP_ROUTER_APPS_SLUG_ENABLED=1
APP_ROUTER_APPS_SLUG_SETUP_ENABLED=1
APP_ROUTER_VIDEO_ENABLED=1
1 change: 1 addition & 0 deletions apps/web/abTest/middlewareFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const ROUTES: [URLPattern, boolean][] = [
["/settings/admin/:path*", process.env.APP_ROUTER_SETTINGS_ADMIN_ENABLED === "1"] as const,
["/apps/:slug", Boolean(process.env.APP_ROUTER_APPS_SLUG_ENABLED)] as const,
["/apps/:slug/setup", Boolean(process.env.APP_ROUTER_APPS_SLUG_SETUP_ENABLED)] as const,
["/video/:path*", process.env.APP_ROUTER_VIDEO_ENABLED === "1"] as const,
].map(([pathname, enabled]) => [
new URLPattern({
pathname,
Expand Down
64 changes: 64 additions & 0 deletions apps/web/app/future/(individual-page-wrapper)/teams/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import OldPage from "@pages/teams/index";
import { ssrInit } from "app/_trpc/ssrInit";
import { type Params } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { type GetServerSidePropsContext } from "next";
import { headers, cookies } from "next/headers";
import { redirect } from "next/navigation";

import { getLayout } from "@calcom/features/MainLayoutAppDir";
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";

import { buildLegacyCtx } from "@lib/buildLegacyCtx";

import PageWrapper from "@components/PageWrapperAppDir";

export const generateMetadata = async () =>
await _generateMetadata(
(t) => t("teams"),
(t) => t("create_manage_teams_collaborative")
);

type PageProps = {
params: Params;
};

async function getData(context: Omit<GetServerSidePropsContext, "res" | "resolvedUrl">) {
const ssr = await ssrInit();
await ssr.viewer.me.prefetch();

const session = await getServerSession({
req: context.req,
});

if (!session) {
const token = Array.isArray(context.query.token) ? context.query.token[0] : context.query.token;

const callbackUrl = token ? `/teams?token=${encodeURIComponent(token)}` : null;
return redirect(callbackUrl ? `/auth/login?callbackUrl=${callbackUrl}` : "/auth/login");
}

return { dehydratedState: await ssr.dehydrate() };
}

const Page = async ({ params }: PageProps) => {
const h = headers();
const nonce = h.get("x-nonce") ?? undefined;

const legacyCtx = buildLegacyCtx(h, cookies(), params);
// @ts-expect-error `req` of type '{ headers: ReadonlyHeaders; cookies: ReadonlyRequestCookies; }' is not assignable to `req` in `GetServerSidePropsContext`
const props = await getData(legacyCtx);

return (
<PageWrapper
getLayout={getLayout}
requiresLicense={false}
nonce={nonce}
themeBasis={null}
dehydratedState={props.dehydratedState}>
<OldPage />
</PageWrapper>
);
};

export default Page;
130 changes: 130 additions & 0 deletions apps/web/app/future/(individual-page-wrapper)/video/[uid]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import OldPage from "@pages/video/[uid]";
import { ssrInit } from "app/_trpc/ssrInit";
import { type Params } from "app/_types";
import { _generateMetadata } from "app/_utils";
import MarkdownIt from "markdown-it";
import { type GetServerSidePropsContext } from "next";
import { headers, cookies } from "next/headers";
import { redirect } from "next/navigation";

import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { APP_NAME } from "@calcom/lib/constants";
import prisma, { bookingMinimalSelect } from "@calcom/prisma";

import { buildLegacyCtx } from "@lib/buildLegacyCtx";

import PageWrapper from "@components/PageWrapperAppDir";

export const generateMetadata = async () =>
await _generateMetadata(
() => `${APP_NAME} Video`,
(t) => t("quick_video_meeting")
);

type PageProps = Readonly<{
params: Params;
}>;

const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });

async function getData(context: Omit<GetServerSidePropsContext, "res" | "resolvedUrl">) {
const ssr = await ssrInit();

const booking = await prisma.booking.findUnique({
where: {
uid: context.query.uid as string,
},
select: {
...bookingMinimalSelect,
uid: true,
description: true,
isRecorded: true,
user: {
select: {
id: true,
timeZone: true,
name: true,
email: true,
organization: {
select: {
calVideoLogo: true,
},
},
},
},
references: {
select: {
uid: true,
type: true,
meetingUrl: true,
meetingPassword: true,
},
where: {
type: "daily_video",
},
},
},
});

if (!booking || booking.references.length === 0 || !booking.references[0].meetingUrl) {
return redirect("/video/no-meeting-found");
}

//daily.co calls have a 60 minute exit buffer when a user enters a call when it's not available it will trigger the modals
const now = new Date();
const exitDate = new Date(now.getTime() - 60 * 60 * 1000);

//find out if the meeting is in the past
const isPast = booking?.endTime <= exitDate;
if (isPast) {
return redirect(`/video/meeting-ended/${booking?.uid}`);
}

const bookingObj = Object.assign({}, booking, {
startTime: booking.startTime.toString(),
endTime: booking.endTime.toString(),
});

const session = await getServerSession({ req: context.req });

// set meetingPassword to null for guests
if (session?.user.id !== bookingObj.user?.id) {
bookingObj.references.forEach((bookRef: any) => {
bookRef.meetingPassword = null;
});
}

return {
meetingUrl: bookingObj.references[0].meetingUrl ?? "",
...(typeof bookingObj.references[0].meetingPassword === "string" && {
meetingPassword: bookingObj.references[0].meetingPassword,
}),
booking: {
...bookingObj,
...(bookingObj.description && { description: md.render(bookingObj.description) }),
},
dehydratedState: await ssr.dehydrate(),
};
}

const Page = async ({ params }: PageProps) => {
const h = headers();
const nonce = h.get("x-nonce") ?? undefined;

const legacyCtx = buildLegacyCtx(headers(), cookies(), params);
// @ts-expect-error `req` of type '{ headers: ReadonlyHeaders; cookies: ReadonlyRequestCookies; }' is not assignable to `req` in `GetServerSidePropsContext`
const { dehydratedState, ...restProps } = await getData(legacyCtx);

return (
<PageWrapper
getLayout={null}
requiresLicense={false}
nonce={nonce}
themeBasis={null}
dehydratedState={dehydratedState}>
<OldPage {...restProps} />
</PageWrapper>
);
};

export default Page;
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import OldPage from "@pages/video/meeting-ended/[uid]";
import { type Params } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { type GetServerSidePropsContext } from "next";
import { headers, cookies } from "next/headers";
import { redirect } from "next/navigation";

import prisma, { bookingMinimalSelect } from "@calcom/prisma";

import { buildLegacyCtx } from "@lib/buildLegacyCtx";

import PageWrapper from "@components/PageWrapperAppDir";

export const generateMetadata = async () =>
await _generateMetadata(
() => "Meeting Unavailable",
() => "Meeting Unavailable"
);

type PageProps = Readonly<{
params: Params;
}>;

async function getData(context: Omit<GetServerSidePropsContext, "res" | "resolvedUrl">) {
const booking = await prisma.booking.findUnique({
where: {
uid: typeof context?.params?.uid === "string" ? context.params.uid : "",
},
select: {
...bookingMinimalSelect,
uid: true,
user: {
select: {
credentials: true,
},
},
references: {
select: {
uid: true,
type: true,
meetingUrl: true,
},
},
},
});

if (!booking) {
return redirect("/video/no-meeting-found");
}

const bookingObj = Object.assign({}, booking, {
startTime: booking.startTime.toString(),
endTime: booking.endTime.toString(),
});

return {
booking: bookingObj,
};
}

const Page = async ({ params }: PageProps) => {
const h = headers();
const nonce = h.get("x-nonce") ?? undefined;

const legacyCtx = buildLegacyCtx(headers(), cookies(), params);
// @ts-expect-error `req` of type '{ headers: ReadonlyHeaders; cookies: ReadonlyRequestCookies; }' is not assignable to `req` in `GetServerSidePropsContext`
const props = await getData(legacyCtx);

return (
<PageWrapper getLayout={null} requiresLicense={false} nonce={nonce} themeBasis={null}>
<OldPage {...props} />
</PageWrapper>
);
};

export default Page;
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import OldPage from "@pages/video/meeting-not-started/[uid]";
import { type Params } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { type GetServerSidePropsContext } from "next";
import { headers, cookies } from "next/headers";
import { redirect } from "next/navigation";

import prisma, { bookingMinimalSelect } from "@calcom/prisma";

import { buildLegacyCtx } from "@lib/buildLegacyCtx";

import PageWrapper from "@components/PageWrapperAppDir";

type PageProps = Readonly<{
params: Params;
}>;

export const generateMetadata = async ({ params }: PageProps) => {
const booking = await prisma.booking.findUnique({
where: {
uid: typeof params?.uid === "string" ? params.uid : "",
},
select: bookingMinimalSelect,
});

return await _generateMetadata(
(t) => t("this_meeting_has_not_started_yet"),
() => booking?.title ?? ""
);
};

async function getData(context: Omit<GetServerSidePropsContext, "res" | "resolvedUrl">) {
const booking = await prisma.booking.findUnique({
where: {
uid: typeof context?.params?.uid === "string" ? context.params.uid : "",
},
select: bookingMinimalSelect,
});

if (!booking) {
return redirect("/video/no-meeting-found");
}

const bookingObj = Object.assign({}, booking, {
startTime: booking.startTime.toString(),
endTime: booking.endTime.toString(),
});

return {
booking: bookingObj,
};
}

const Page = async ({ params }: PageProps) => {
const h = headers();
const nonce = h.get("x-nonce") ?? undefined;

const legacyCtx = buildLegacyCtx(headers(), cookies(), params);
// @ts-expect-error `req` of type '{ headers: ReadonlyHeaders; cookies: ReadonlyRequestCookies; }' is not assignable to `req` in `GetServerSidePropsContext`
const props = await getData(legacyCtx);

return (
<PageWrapper getLayout={null} requiresLicense={false} nonce={nonce} themeBasis={null}>
<OldPage {...props} />
</PageWrapper>
);
};

export default Page;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Page from "@pages/video/no-meeting-found";
import { _generateMetadata } from "app/_utils";

export const generateMetadata = async () =>
await _generateMetadata(
() => "",
() => ""
);

export default Page;
23 changes: 23 additions & 0 deletions apps/web/lib/buildLegacyCtx.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { type Params } from "app/_types";
import { type ReadonlyHeaders } from "next/dist/server/web/spec-extension/adapters/headers";
import { type ReadonlyRequestCookies } from "next/dist/server/web/spec-extension/adapters/request-cookies";

// returns query object same as ctx.query but for app dir
export const getQuery = (url: string, params: Params) => {
if (!url.length) {
return params;
}

const { searchParams } = new URL(url);
const searchParamsObj = Object.fromEntries(searchParams.entries());

return { ...searchParamsObj, ...params };
};

export const buildLegacyCtx = (headers: ReadonlyHeaders, cookies: ReadonlyRequestCookies, params: Params) => {
return {
query: getQuery(headers.get("x-url") ?? "", params),
params,
req: { headers, cookies },
};
};
Loading
Loading