chore: app router - /event-types pages (#18181)
* refactor event type web wrapper * finish migration * move event-types folder out of future * remove vars * remove pages router * fix * fix * fix test * remove test tag * refactor * remove completely * add withoutSeo prop for event type web page * remove HeadSeo usage from event types listing view * make onboarding e2e test faster * remove useIntercom --------- Co-authored-by: Peer Richelsen <peeroke@gmail.com>
This commit is contained in:
co-authored by
Peer Richelsen
parent
79d51a4989
commit
cc202ed847
@@ -355,8 +355,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
|
||||
# whether we redirect to the future/event-types from event-types or not
|
||||
APP_ROUTER_EVENT_TYPES_ENABLED=0
|
||||
APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED=0
|
||||
APP_ROUTER_APPS_SLUG_ENABLED=0
|
||||
APP_ROUTER_APPS_SLUG_SETUP_ENABLED=0
|
||||
|
||||
@@ -5,7 +5,6 @@ import { NextResponse, URLPattern } from "next/server";
|
||||
import { FUTURE_ROUTES_ENABLED_COOKIE_NAME, FUTURE_ROUTES_OVERRIDE_COOKIE_NAME } from "@calcom/lib/constants";
|
||||
|
||||
const ROUTES: [URLPattern, boolean][] = [
|
||||
["/event-types", process.env.APP_ROUTER_EVENT_TYPES_ENABLED === "1"] as const,
|
||||
["/apps/installed/:category", process.env.APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED === "1"] as const,
|
||||
["/apps/:slug", process.env.APP_ROUTER_APPS_SLUG_ENABLED === "1"] as const,
|
||||
["/apps/:slug/setup", process.env.APP_ROUTER_APPS_SLUG_SETUP_ENABLED === "1"] as const,
|
||||
|
||||
+4
-5
@@ -4,11 +4,10 @@ import { _generateMetadata } from "app/_utils";
|
||||
import { WithLayout } from "app/layoutHOC";
|
||||
import { cookies, headers } from "next/headers";
|
||||
|
||||
import { EventType } from "@calcom/atoms/monorepo";
|
||||
|
||||
import { buildLegacyCtx } from "@lib/buildLegacyCtx";
|
||||
import { getServerSideProps } from "@lib/event-types/[type]/getServerSideProps";
|
||||
import type { PageProps as EventTypePageProps } from "@lib/event-types/[type]/getServerSideProps";
|
||||
|
||||
import EventTypePageWrapper from "~/event-types/views/event-types-single-view";
|
||||
|
||||
export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);
|
||||
@@ -21,5 +20,5 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
|
||||
};
|
||||
|
||||
const getData = withAppDirSsr(getServerSideProps);
|
||||
const Page = ({ type, ...rest }: EventTypePageProps) => <EventType {...rest} id={type} isAppDir={true} />;
|
||||
export default WithLayout({ getLayout: null, getData, Page })<"P">;
|
||||
|
||||
export default WithLayout({ getLayout: null, getData, Page: EventTypePageWrapper })<"P">;
|
||||
@@ -173,8 +173,7 @@ export const config = {
|
||||
*/
|
||||
"/apps/routing_forms/:path*",
|
||||
|
||||
"/event-types",
|
||||
"/future/event-types/",
|
||||
"/event-types/:path*",
|
||||
"/apps/installed/:category/",
|
||||
"/future/apps/installed/:category/",
|
||||
"/apps/:slug/",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { Trans } from "next-i18next";
|
||||
import Link from "next/link";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||
import type { FC } from "react";
|
||||
import { memo, useEffect, useState } from "react";
|
||||
import { z } from "zod";
|
||||
@@ -18,7 +18,6 @@ import { getTeamsFiltersFromQuery } from "@calcom/features/filters/lib/getTeamsF
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { classNames, parseEventTypeColor } from "@calcom/lib";
|
||||
import { APP_NAME, WEBSITE_URL } from "@calcom/lib/constants";
|
||||
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
||||
import { useCopy } from "@calcom/lib/hooks/useCopy";
|
||||
import { useDebounce } from "@calcom/lib/hooks/useDebounce";
|
||||
import { useInViewObserver } from "@calcom/lib/hooks/useInViewObserver";
|
||||
@@ -47,7 +46,6 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
EmptyScreen,
|
||||
HeadSeo,
|
||||
HorizontalTabs,
|
||||
Icon,
|
||||
Label,
|
||||
@@ -60,7 +58,6 @@ import {
|
||||
UserAvatarGroup,
|
||||
} from "@calcom/ui";
|
||||
|
||||
import type { AppProps } from "@lib/app-providers";
|
||||
import useMeQuery from "@lib/hooks/useMeQuery";
|
||||
|
||||
type GetUserEventGroupsResponse = RouterOutputs["viewer"]["eventTypes"]["getUserEventGroups"];
|
||||
@@ -256,7 +253,7 @@ export const InfiniteEventTypeList = ({
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const searchParams = useCompatSearchParams();
|
||||
const searchParams = useSearchParams();
|
||||
const { copyToClipboard } = useCopy();
|
||||
const [parent] = useAutoAnimate<HTMLUListElement>();
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
@@ -373,7 +370,7 @@ export const InfiniteEventTypeList = ({
|
||||
|
||||
// inject selection data into url for correct router history
|
||||
const openDuplicateModal = (eventType: InfiniteEventType, group: InfiniteEventTypeGroup) => {
|
||||
const newSearchParams = new URLSearchParams(searchParams ?? undefined);
|
||||
const newSearchParams = new URLSearchParams(searchParams?.toString() ?? undefined);
|
||||
function setParamsIfDefined(key: string, value: string | number | boolean | null | undefined) {
|
||||
if (value) newSearchParams.set(key, value.toString());
|
||||
if (value === null) newSearchParams.delete(key);
|
||||
@@ -897,7 +894,7 @@ const InfiniteScrollMain = ({
|
||||
eventTypeGroups: GetUserEventGroupsResponse["eventTypeGroups"] | undefined;
|
||||
profiles: GetUserEventGroupsResponse["profiles"] | undefined;
|
||||
}) => {
|
||||
const searchParams = useCompatSearchParams();
|
||||
const searchParams = useSearchParams();
|
||||
const { data } = useTypedQuery(querySchema);
|
||||
const orgBranding = useOrgBranding();
|
||||
|
||||
@@ -945,11 +942,9 @@ const InfiniteScrollMain = ({
|
||||
);
|
||||
};
|
||||
|
||||
const EventTypesPage: React.FC & {
|
||||
PageWrapper?: AppProps["Component"]["PageWrapper"];
|
||||
getLayout?: AppProps["Component"]["getLayout"];
|
||||
} = () => {
|
||||
const EventTypesPage: React.FC = () => {
|
||||
const { t } = useLocale();
|
||||
const searchParams = useSearchParams();
|
||||
const { data: user } = useMeQuery();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [_showProfileBanner, setShowProfileBanner] = useState(false);
|
||||
@@ -1003,18 +998,13 @@ const EventTypesPage: React.FC & {
|
||||
return (
|
||||
<Shell
|
||||
withoutMain={false}
|
||||
title="Event Types"
|
||||
description="Create events to share for people to book on your calendar."
|
||||
title={t("event_types_page_title")}
|
||||
description={t("event_types_page_subtitle")}
|
||||
withoutSeo
|
||||
heading={t("event_types_page_title")}
|
||||
hideHeadingOnMobile
|
||||
subtitle={t("event_types_page_subtitle")}
|
||||
CTA={<CTA profileOptions={profileOptions} isOrganization={!!user?.organizationId} />}>
|
||||
<HeadSeo
|
||||
title="Event Types"
|
||||
description="Create events to share for people to book on your calendar."
|
||||
/>
|
||||
|
||||
<InfiniteScrollMain
|
||||
profiles={getUserEventGroupsData?.profiles}
|
||||
eventTypeGroups={getUserEventGroupsData?.eventTypeGroups}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { EventType } from "@calcom/atoms/monorepo";
|
||||
import type { PageProps } from "@lib/event-types/[type]/getServerSideProps";
|
||||
|
||||
const EventTypePageWrapper = ({ type, ...rest }: PageProps) => {
|
||||
return <EventType {...rest} id={type} isAppDir={false} />;
|
||||
return <EventType {...rest} id={type} />;
|
||||
};
|
||||
|
||||
export default EventTypePageWrapper;
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import type { PageProps } from "@lib/event-types/[type]/getServerSideProps";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
import EventTypePageWrapper from "~/event-types/views/event-types-single-view";
|
||||
|
||||
export type {
|
||||
FormValues,
|
||||
CustomInputParsed,
|
||||
EventTypeSetup,
|
||||
EventTypeSetupProps,
|
||||
Host,
|
||||
} from "@calcom/features/eventtypes/lib/types";
|
||||
|
||||
const Page = (props: PageProps) => <EventTypePageWrapper {...props} />;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export { getServerSideProps } from "@lib/event-types/[type]/getServerSideProps";
|
||||
export default Page;
|
||||
@@ -1,9 +0,0 @@
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
import EventTypesPage from "~/event-types/views/event-types-listing-view";
|
||||
|
||||
export { getServerSideProps } from "@lib/event-types/getServerSideProps";
|
||||
|
||||
EventTypesPage.PageWrapper = PageWrapper;
|
||||
|
||||
export default EventTypesPage;
|
||||
@@ -258,8 +258,6 @@ test.describe("Manage Booking Questions", () => {
|
||||
|
||||
await test.step("Go to First Team Event", async () => {
|
||||
await page.getByTestId(`horizontal-tab-${team?.name}`).click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
const $eventTypes = page.locator("[data-testid=event-types]").locator("li a");
|
||||
const firstEventTypeElement = $eventTypes.first();
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ checkRoute () {
|
||||
|
||||
# These conditionals are used to remove directories from the build that are not needed in production
|
||||
# This is to reduce the size of the build and prevent OOM errors
|
||||
checkRoute "$APP_ROUTER_EVENT_TYPES_ENABLED" app/future/event-types
|
||||
checkRoute "$APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED" app/future/apps/installed
|
||||
checkRoute "$APP_ROUTER_APPS_SLUG_ENABLED" app/future/apps/\[slug\]
|
||||
checkRoute "$APP_ROUTER_APPS_SLUG_SETUP_ENABLED" app/future/apps/\[slug\]/setup
|
||||
|
||||
@@ -101,6 +101,7 @@ function EventTypeSingleLayout({
|
||||
backPath="/event-types"
|
||||
title={`${eventType.title} | ${t("event_type")}`}
|
||||
heading={eventType.title}
|
||||
withoutSeo={!isPlatform} // Metadata is handled by App Router Metadata API for Event Type Web Page
|
||||
CTA={
|
||||
<div className="flex items-center justify-end">
|
||||
{!formMethods.getValues("metadata")?.managedEventConfig && (
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import type { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import dynamic from "next/dynamic";
|
||||
import { usePathname, useRouter as useAppRouter } from "next/navigation";
|
||||
// eslint-disable-next-line @calcom/eslint/deprecated-imports-next-router
|
||||
import { useRouter as usePageRouter } from "next/router";
|
||||
// eslint-disable-next-line @calcom/eslint/deprecated-imports-next-router
|
||||
import type { NextRouter as NextPageRouter } from "next/router";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -89,74 +84,21 @@ const EventAITab = dynamic(() =>
|
||||
|
||||
export type EventTypeWebWrapperProps = {
|
||||
id: number;
|
||||
isAppDir?: boolean;
|
||||
};
|
||||
|
||||
// discriminative factor: isAppDir
|
||||
type EventTypeAppComponentProp = {
|
||||
id: number;
|
||||
isAppDir: true;
|
||||
pathname: string;
|
||||
pageRouter: null;
|
||||
appRouter: AppRouterInstance;
|
||||
};
|
||||
|
||||
// discriminative factor: isAppDir
|
||||
type EventTypePageComponentProp = {
|
||||
id: number;
|
||||
isAppDir: false;
|
||||
pageRouter: NextPageRouter;
|
||||
pathname: null;
|
||||
appRouter: null;
|
||||
};
|
||||
|
||||
type EventTypeAppPageComponentProp = EventTypeAppComponentProp | EventTypePageComponentProp;
|
||||
|
||||
export const EventTypeWebWrapper = ({ id, isAppDir }: EventTypeWebWrapperProps & { isAppDir?: boolean }) => {
|
||||
export const EventTypeWebWrapper = ({ id }: EventTypeWebWrapperProps) => {
|
||||
const { data: eventTypeQueryData } = trpc.viewer.eventTypes.get.useQuery({ id });
|
||||
|
||||
if (!eventTypeQueryData) return null;
|
||||
|
||||
return isAppDir ? (
|
||||
<EventTypeAppWrapper {...eventTypeQueryData} id={id} />
|
||||
) : (
|
||||
<EventTypePageWrapper {...eventTypeQueryData} id={id} />
|
||||
);
|
||||
return <EventTypeWeb {...eventTypeQueryData} id={id} />;
|
||||
};
|
||||
|
||||
const EventTypePageWrapper = ({ id, ...rest }: EventTypeSetupProps & { id: number }) => {
|
||||
const router = usePageRouter();
|
||||
return (
|
||||
<EventTypeWeb {...rest} id={id} isAppDir={false} pageRouter={router} pathname={null} appRouter={null} />
|
||||
);
|
||||
};
|
||||
|
||||
const EventTypeAppWrapper = ({ id, ...rest }: EventTypeSetupProps & { id: number }) => {
|
||||
const pathname = usePathname();
|
||||
const router = useAppRouter();
|
||||
return (
|
||||
<EventTypeWeb
|
||||
{...rest}
|
||||
id={id}
|
||||
isAppDir={true}
|
||||
pathname={pathname ?? ""}
|
||||
pageRouter={null}
|
||||
appRouter={router}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const EventTypeWeb = ({
|
||||
id,
|
||||
isAppDir,
|
||||
pageRouter,
|
||||
appRouter,
|
||||
pathname,
|
||||
...rest
|
||||
}: EventTypeSetupProps & EventTypeAppPageComponentProp) => {
|
||||
const EventTypeWeb = ({ id, ...rest }: EventTypeSetupProps & { id: number }) => {
|
||||
const { t } = useLocale();
|
||||
const utils = trpc.useUtils();
|
||||
|
||||
const pathname = usePathname();
|
||||
const appRouter = useAppRouter();
|
||||
const { data: user, isPending: isLoggedInUserPending } = useMeQuery();
|
||||
const isTeamEventTypeDeleted = useRef(false);
|
||||
const leaveWithoutAssigningHosts = useRef(false);
|
||||
@@ -281,7 +223,7 @@ const EventTypeWeb = ({
|
||||
} as const;
|
||||
|
||||
useHandleRouteChange({
|
||||
watchTrigger: isAppDir ? pageRouter : pathname,
|
||||
watchTrigger: pathname,
|
||||
isTeamEventTypeDeleted: isTeamEventTypeDeleted.current,
|
||||
isleavingWithoutAssigningHosts: leaveWithoutAssigningHosts.current,
|
||||
isTeamEventType: !!team,
|
||||
@@ -292,22 +234,10 @@ const EventTypeWeb = ({
|
||||
onError: (url) => {
|
||||
setIsOpenAssignmentWarnDialog(true);
|
||||
setPendingRoute(url);
|
||||
if (!isAppDir) {
|
||||
pageRouter.events.emit(
|
||||
"routeChangeError",
|
||||
new Error(`Aborted route change to ${url} because none was assigned to team event`)
|
||||
);
|
||||
throw "Aborted";
|
||||
}
|
||||
|
||||
if (isAppDir) throw new Error(`Aborted route change to ${url} because none was assigned to team event`);
|
||||
throw new Error(`Aborted route change to ${url} because none was assigned to team event`);
|
||||
},
|
||||
onStart: (handleRouteChange) => {
|
||||
!isAppDir && pageRouter.events.on("routeChangeStart", handleRouteChange);
|
||||
isAppDir && handleRouteChange(pathname || "");
|
||||
},
|
||||
onEnd: (handleRouteChange) => {
|
||||
!isAppDir && pageRouter.events.off("routeChangeStart", handleRouteChange);
|
||||
handleRouteChange(pathname || "");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -370,7 +300,7 @@ const EventTypeWeb = ({
|
||||
await utils.viewer.eventTypes.invalidate();
|
||||
showToast(t("event_type_deleted_successfully"), "success");
|
||||
isTeamEventTypeDeleted.current = true;
|
||||
isAppDir ? appRouter.push("/event-types") : pageRouter.push("/event-types");
|
||||
appRouter.push("/event-types");
|
||||
setSlugExistsChildrenDialogOpen([]);
|
||||
setIsOpenAssignmentWarnDialog(false);
|
||||
},
|
||||
|
||||
@@ -243,7 +243,6 @@
|
||||
"APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED",
|
||||
"APP_ROUTER_APPS_SLUG_ENABLED",
|
||||
"APP_ROUTER_APPS_SLUG_SETUP_ENABLED",
|
||||
"APP_ROUTER_EVENT_TYPES_ENABLED",
|
||||
"APP_ROUTER_AUTH_FORGOT_PASSWORD_ENABLED",
|
||||
"APP_ROUTER_AUTH_LOGIN_ENABLED",
|
||||
"APP_ROUTER_AUTH_LOGOUT_ENABLED",
|
||||
|
||||
Reference in New Issue
Block a user