Skip to content

Commit

Permalink
Migrate /team/* page group
Browse files Browse the repository at this point in the history
improve

import type

Finalize

support isBookingPage

finalize

fix

Fix build error

fix type errors

finalize

fix embed pages
  • Loading branch information
hbjORbj committed Jan 17, 2024
1 parent df91dac commit 965579b
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 137 deletions.
8 changes: 4 additions & 4 deletions apps/web/app/future/apps/categories/[category]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import CategoryPage from "@pages/apps/categories/[category]";
import { Prisma } from "@prisma/client";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { type GetServerSidePropsContext } from "next";
import { notFound } from "next/navigation";
import z from "zod";

Expand Down Expand Up @@ -38,8 +39,8 @@ const querySchema = z.object({
category: z.nativeEnum(AppCategories),
});

const getPageProps = async ({ params }: { params: Record<string, string | string[]> }) => {
const p = querySchema.safeParse(params);
const getPageProps = async (context: GetServerSidePropsContext) => {
const p = querySchema.safeParse(context.params);

if (!p.success) {
return notFound();
Expand All @@ -66,6 +67,5 @@ const getPageProps = async ({ params }: { params: Record<string, string | string
};
};

// @ts-expect-error getData arg
export default WithLayout({ getData: getPageProps, Page: CategoryPage })<"P">;
export default WithLayout({ getData: getPageProps, Page: CategoryPage, getLayout: null })<"P">;
export const dynamic = "force-static";
9 changes: 9 additions & 0 deletions apps/web/app/future/team/[slug]/[type]/embed/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import LegacyPage from "@pages/team/[slug]/[type]/embed";
import withEmbedSsrAppDir from "app/WithEmbedSSR";
import { WithLayout } from "app/layoutHOC";

import { getData } from "../page";

const getEmbedData = withEmbedSsrAppDir(getData);

export default WithLayout({ getLayout: null, getData: getEmbedData, Page: LegacyPage })<"P">;
35 changes: 35 additions & 0 deletions apps/web/app/future/team/[slug]/[type]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import LegacyPage, { type PageProps, getServerSideProps } from "@pages/team/[slug]/[type]";
import { withAppDir } from "app/AppDirSSRHOC";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { type GetServerSidePropsContext } from "next";
import { cookies, headers } from "next/headers";

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

export const generateMetadata = async ({ params }: { params: Record<string, string | string[]> }) => {
const legacyCtx = buildLegacyCtx(headers(), cookies(), params);
const props = await getData(legacyCtx as unknown as GetServerSidePropsContext);
const { entity, user, slug, booking } = props;
const { trpc } = await import("@calcom/trpc");
const { data: event } = trpc.viewer.public.event.useQuery(
{ username: user, eventSlug: slug, isTeamEvent: false, org: entity.orgSlug ?? null },
{ refetchOnWindowFocus: false }
);

const profileName = event?.profile?.name ?? "";
const title = event?.title ?? "";

return await _generateMetadata(
(t) => `${booking?.uid && !!booking ? t("reschedule") : ""} ${title} | ${profileName}`,
(t) => `${booking?.uid ? t("reschedule") : ""} ${title}`
);
};
export const getData = withAppDir<PageProps>(getServerSideProps);

export default WithLayout({
Page: LegacyPage,
getData,
getLayout: null,
isBookingPage: true,
})<"P">;
9 changes: 9 additions & 0 deletions apps/web/app/future/team/[slug]/embed/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import LegacyPage from "@pages/team/[slug]/embed";
import withEmbedSsrAppDir from "app/WithEmbedSSR";
import { WithLayout } from "app/layoutHOC";

import { getData } from "../page";

const getEmbedData = withEmbedSsrAppDir(getData);

export default WithLayout({ getLayout: null, getData: getEmbedData, Page: LegacyPage })<"P">;
29 changes: 29 additions & 0 deletions apps/web/app/future/team/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import LegacyPage, { type PageProps, getServerSideProps } from "@pages/team/[slug]";
import { withAppDir } from "app/AppDirSSRHOC";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { type GetServerSidePropsContext } from "next";
import { cookies, headers } from "next/headers";

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

export const generateMetadata = async ({ params }: { params: Record<string, string | string[]> }) => {
const props = await getData(
buildLegacyCtx(headers(), cookies(), params) as unknown as GetServerSidePropsContext
);
const teamName = props.team.name || "Nameless Team";

return await _generateMetadata(
() => teamName,
() => teamName
);
};

export const getData = withAppDir<PageProps>(getServerSideProps);

export default WithLayout({
Page: LegacyPage,
getData,
getLayout: null,
isBookingPage: true,
})<"P">;
137 changes: 137 additions & 0 deletions apps/web/lib/team/[slug]/getServerSideProps.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import type { GetServerSidePropsContext } from "next";

import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
import { getFeatureFlagMap } from "@calcom/features/flags/server/utils";
import { getBookerBaseUrlSync } from "@calcom/lib/getBookerUrl/client";
import logger from "@calcom/lib/logger";
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
import { getTeamWithMembers } from "@calcom/lib/server/queries/teams";
import slugify from "@calcom/lib/slugify";
import { stripMarkdown } from "@calcom/lib/stripMarkdown";
import prisma from "@calcom/prisma";
import { RedirectType } from "@calcom/prisma/client";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";

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

import { ssrInit } from "@server/lib/ssr";

const log = logger.getSubLogger({ prefix: ["team/[slug]"] });

export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const slug = Array.isArray(context.query?.slug) ? context.query.slug.pop() : context.query.slug;
const { isValidOrgDomain, currentOrgDomain } = orgDomainConfig(context.req, context.params?.orgSlug);
const isOrgContext = isValidOrgDomain && currentOrgDomain;

// Provided by Rewrite from next.config.js
const isOrgProfile = context.query?.isOrgProfile === "1";
const flags = await getFeatureFlagMap(prisma);
const isOrganizationFeatureEnabled = flags["organizations"];

log.debug("getServerSideProps", {
isOrgProfile,
isOrganizationFeatureEnabled,
isValidOrgDomain,
currentOrgDomain,
});

const team = await getTeamWithMembers({
slug: slugify(slug ?? ""),
orgSlug: currentOrgDomain,
isTeamView: true,
isOrgView: isValidOrgDomain && isOrgProfile,
});

if (!isOrgContext && slug) {
const redirect = await getTemporaryOrgRedirect({
slugs: slug,
redirectType: RedirectType.Team,
eventTypeSlug: null,
currentQuery: context.query,
});

if (redirect) {
return redirect;
}
}

const ssr = await ssrInit(context);
const metadata = teamMetadataSchema.parse(team?.metadata ?? {});

// Taking care of sub-teams and orgs
if (
(!isValidOrgDomain && team?.parent) ||
(!isValidOrgDomain && !!metadata?.isOrganization) ||
!isOrganizationFeatureEnabled
) {
return { notFound: true } as const;
}

if (!team || (team.parent && !team.parent.slug)) {
const unpublishedTeam = await prisma.team.findFirst({
where: {
...(team?.parent
? { id: team.parent.id }
: {
metadata: {
path: ["requestedSlug"],
equals: slug,
},
}),
},
});

if (!unpublishedTeam) return { notFound: true } as const;

return {
props: {
isUnpublished: true,
team: { ...unpublishedTeam, createdAt: null },
trpcState: ssr.dehydrate(),
},
} as const;
}

team.eventTypes =
team.eventTypes?.map((type) => ({
...type,
users: type.users.map((user) => ({
...user,
avatar: `/${user.username}/avatar.png`,
})),
descriptionAsSafeHTML: markdownToSafeHTML(type.description),
})) ?? null;

const safeBio = markdownToSafeHTML(team.bio) || "";

const members = !team.isPrivate
? team.members.map((member) => {
return {
name: member.name,
id: member.id,
bio: member.bio,
subteams: member.subteams,
username: member.username,
accepted: member.accepted,
organizationId: member.organizationId,
safeBio: markdownToSafeHTML(member.bio || ""),
bookerUrl: getBookerBaseUrlSync(member.organization?.slug || ""),
};
})
: [];

const markdownStrippedBio = stripMarkdown(team?.bio || "");

const { inviteToken: _inviteToken, ...serializableTeam } = team;

return {
props: {
team: { ...serializableTeam, safeBio, members, metadata },
themeBasis: serializableTeam.slug,
trpcState: ssr.dehydrate(),
markdownStrippedBio,
isValidOrgDomain,
currentOrgDomain,
},
} as const;
};
Loading

0 comments on commit 965579b

Please sign in to comment.