From 7e2b5b12b484a25fcc8bad2c2ae1a5c35330ca80 Mon Sep 17 00:00:00 2001 From: Benny Joo Date: Wed, 4 Dec 2024 11:00:37 -0500 Subject: [PATCH] chore: `settings/developer` - remove pages router and use app router (#16794) * remove pages router and use app router * remove Meta / improve code quality * remove isAppDir * refactor code for better code * fix test * remove meta * improve tests --- .env.example | 1 - apps/web/abTest/middlewareFactory.ts | 1 - .../developer/api-keys/page.tsx | 5 +- .../developer/webhooks/[id]/page.tsx | 2 +- .../developer/webhooks/new/page.tsx | 0 .../developer/webhooks/page.tsx | 8 +-- .../settings/developer/api-keys-view.tsx | 67 +++++++++---------- .../components/CreateApiKeyButton.tsx | 38 ----------- .../web/pages/settings/developer/api-keys.tsx | 14 ---- .../developer/webhooks/[id]/index.tsx | 43 ------------ .../settings/developer/webhooks/index.tsx | 38 ----------- .../pages/settings/developer/webhooks/new.tsx | 27 -------- apps/web/playwright/fixtures/webhooks.ts | 3 +- apps/web/playwright/webhook.e2e.ts | 10 ++- apps/web/scripts/vercel-app-router-deploy.sh | 1 - .../webhooks/components/WebhookForm.tsx | 1 + .../webhooks/pages/webhook-new-view.tsx | 14 +--- .../features/webhooks/pages/webhooks-view.tsx | 63 +++-------------- turbo.json | 1 - 19 files changed, 60 insertions(+), 277 deletions(-) rename apps/web/app/{future/settings/(settings) => settings/(settings-layout)}/developer/api-keys/page.tsx (83%) rename apps/web/app/{future/settings/(settings) => settings/(settings-layout)}/developer/webhooks/[id]/page.tsx (96%) rename apps/web/app/{future/settings/(settings) => settings/(settings-layout)}/developer/webhooks/new/page.tsx (100%) rename apps/web/app/{future/settings/(settings) => settings/(settings-layout)}/developer/webhooks/page.tsx (62%) delete mode 100644 apps/web/modules/settings/developer/components/CreateApiKeyButton.tsx delete mode 100644 apps/web/pages/settings/developer/api-keys.tsx delete mode 100644 apps/web/pages/settings/developer/webhooks/[id]/index.tsx delete mode 100644 apps/web/pages/settings/developer/webhooks/index.tsx delete mode 100644 apps/web/pages/settings/developer/webhooks/new.tsx diff --git a/.env.example b/.env.example index 962ac7267c..4555a8d72c 100644 --- a/.env.example +++ b/.env.example @@ -347,7 +347,6 @@ E2E_TEST_OIDC_USER_PASSWORD= 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_SETTINGS_DEVELOPER_ENABLED=0 APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED=0 APP_ROUTER_APPS_SLUG_ENABLED=0 APP_ROUTER_APPS_SLUG_SETUP_ENABLED=0 diff --git a/apps/web/abTest/middlewareFactory.ts b/apps/web/abTest/middlewareFactory.ts index d4ac233869..2b687f0969 100644 --- a/apps/web/abTest/middlewareFactory.ts +++ b/apps/web/abTest/middlewareFactory.ts @@ -7,7 +7,6 @@ import { FUTURE_ROUTES_ENABLED_COOKIE_NAME, FUTURE_ROUTES_OVERRIDE_COOKIE_NAME } const ROUTES: [URLPattern, boolean][] = [ ["/event-types", process.env.APP_ROUTER_EVENT_TYPES_ENABLED === "1"] as const, - ["/settings/developer/:path*", process.env.APP_ROUTER_SETTINGS_DEVELOPER_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, diff --git a/apps/web/app/future/settings/(settings)/developer/api-keys/page.tsx b/apps/web/app/settings/(settings-layout)/developer/api-keys/page.tsx similarity index 83% rename from apps/web/app/future/settings/(settings)/developer/api-keys/page.tsx rename to apps/web/app/settings/(settings-layout)/developer/api-keys/page.tsx index bf82270f1a..0d519de2e0 100644 --- a/apps/web/app/future/settings/(settings)/developer/api-keys/page.tsx +++ b/apps/web/app/settings/(settings-layout)/developer/api-keys/page.tsx @@ -4,8 +4,7 @@ import { getServerSessionForAppDir } from "@calcom/feature-auth/lib/get-server-s import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; import { APP_NAME } from "@calcom/lib/constants"; -import ApiKeysView from "~/settings/developer/api-keys-view"; -import NewApiKeyButton from "~/settings/developer/components/CreateApiKeyButton"; +import ApiKeysView, { NewApiKeyButton } from "~/settings/developer/api-keys-view"; export const generateMetadata = async () => await _generateMetadata( @@ -25,7 +24,7 @@ const Page = async () => { description={t("create_first_api_key_description", { appName: APP_NAME })} CTA={} borderInShellHeader={true}> - + ); }; diff --git a/apps/web/app/future/settings/(settings)/developer/webhooks/[id]/page.tsx b/apps/web/app/settings/(settings-layout)/developer/webhooks/[id]/page.tsx similarity index 96% rename from apps/web/app/future/settings/(settings)/developer/webhooks/[id]/page.tsx rename to apps/web/app/settings/(settings-layout)/developer/webhooks/[id]/page.tsx index 718fd1faf4..7eea6fcbf8 100644 --- a/apps/web/app/future/settings/(settings)/developer/webhooks/[id]/page.tsx +++ b/apps/web/app/settings/(settings-layout)/developer/webhooks/[id]/page.tsx @@ -20,7 +20,7 @@ const Page = async ({ params }: PageProps) => { const id = typeof params?.id === "string" ? params.id : undefined; const webhook = await WebhookRepository.findByWebhookId(id); - console.log("This is the webhook", webhook); + return ( @@ -9,8 +9,4 @@ export const generateMetadata = async () => (t) => t("add_webhook_description", { appName: APP_NAME }) ); -const Page = () => { - return ; -}; - -export default Page; +export default WebhooksView; diff --git a/apps/web/modules/settings/developer/api-keys-view.tsx b/apps/web/modules/settings/developer/api-keys-view.tsx index c85d9f6a01..a5ec587782 100644 --- a/apps/web/modules/settings/developer/api-keys-view.tsx +++ b/apps/web/modules/settings/developer/api-keys-view.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import type { TApiKeys } from "@calcom/ee/api-keys/components/ApiKeyListItem"; import LicenseRequired from "@calcom/ee/common/components/LicenseRequired"; @@ -19,18 +19,9 @@ import { SkeletonText, } from "@calcom/ui"; -const SkeletonLoader = ({ - title, - description, - isAppDir, -}: { - title: string; - description: string; - isAppDir?: boolean; -}) => { +const SkeletonLoader = ({ title, description }: { title: string; description: string }) => { return ( - {!isAppDir ? : null}
@@ -39,7 +30,29 @@ const SkeletonLoader = ({ ); }; -const ApiKeysView = ({ isAppDir }: { isAppDir?: boolean }) => { +export const apiKeyModalRef = { + current: null as null | ((show: boolean) => void), +}; +export const apiKeyToEditRef = { + current: null as null | ((apiKey: (TApiKeys & { neverExpires?: boolean }) | undefined) => void), +}; + +export const NewApiKeyButton = () => { + const { t } = useLocale(); + return ( + + ); +}; + +const ApiKeysView = () => { const { t } = useLocale(); const { data, isPending } = trpc.viewer.apiKeys.list.useQuery(); @@ -49,24 +62,18 @@ const ApiKeysView = ({ isAppDir }: { isAppDir?: boolean }) => { undefined ); - const NewApiKeyButton = () => { - return ( - - ); - }; + useEffect(() => { + apiKeyModalRef.current = setApiKeyModal; + apiKeyToEditRef.current = setApiKeyToEdit; + return () => { + apiKeyModalRef.current = null; + apiKeyToEditRef.current = null; + }; + }, []); if (isPending || !data) { return ( @@ -75,14 +82,6 @@ const ApiKeysView = ({ isAppDir }: { isAppDir?: boolean }) => { return ( <> - {!isAppDir ? ( - } - borderInShellHeader={true} - /> - ) : null}
{data?.length ? ( diff --git a/apps/web/modules/settings/developer/components/CreateApiKeyButton.tsx b/apps/web/modules/settings/developer/components/CreateApiKeyButton.tsx deleted file mode 100644 index 18a0171d07..0000000000 --- a/apps/web/modules/settings/developer/components/CreateApiKeyButton.tsx +++ /dev/null @@ -1,38 +0,0 @@ -"use client"; - -import { useState } from "react"; - -import type { TApiKeys } from "@calcom/ee/api-keys/components/ApiKeyListItem"; -import ApiKeyDialogForm from "@calcom/features/ee/api-keys/components/ApiKeyDialogForm"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Button, Dialog, DialogContent } from "@calcom/ui"; - -const NewApiKeyButton = () => { - const { t } = useLocale(); - const [apiKeyModal, setApiKeyModal] = useState(false); - const [apiKeyToEdit, setApiKeyToEdit] = useState<(TApiKeys & { neverExpires?: boolean }) | undefined>( - undefined - ); - - return ( - <> - - - - - setApiKeyModal(false)} defaultValues={apiKeyToEdit} /> - - - - ); -}; - -export default NewApiKeyButton; diff --git a/apps/web/pages/settings/developer/api-keys.tsx b/apps/web/pages/settings/developer/api-keys.tsx deleted file mode 100644 index a10eb1bb02..0000000000 --- a/apps/web/pages/settings/developer/api-keys.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; - -import PageWrapper from "@components/PageWrapper"; - -import ApiKeysView from "~/settings/developer/api-keys-view"; - -const Page = () => { - return ; -}; - -Page.getLayout = getLayout; -Page.PageWrapper = PageWrapper; - -export default Page; diff --git a/apps/web/pages/settings/developer/webhooks/[id]/index.tsx b/apps/web/pages/settings/developer/webhooks/[id]/index.tsx deleted file mode 100644 index b9d17fe6d5..0000000000 --- a/apps/web/pages/settings/developer/webhooks/[id]/index.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; -import EditWebhookView from "@calcom/features/webhooks/pages/webhook-edit-view"; -import { APP_NAME } from "@calcom/lib/constants"; -import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { trpc } from "@calcom/trpc/react"; -import { SkeletonContainer, Meta } from "@calcom/ui"; - -import PageWrapper from "@components/PageWrapper"; - -const Page = () => { - const searchParams = useCompatSearchParams(); - const id = searchParams?.get("id") ?? undefined; - const { t } = useLocale(); - - const { data: webhook } = trpc.viewer.webhook.get.useQuery( - { webhookId: id }, - { - suspense: true, - enabled: !!id, - } - ); - - if (!id) return ; - - // I think we should do SSR for this page - return ( - <> - - - - ); -}; - -Page.getLayout = getLayout; -Page.PageWrapper = PageWrapper; - -export default Page; diff --git a/apps/web/pages/settings/developer/webhooks/index.tsx b/apps/web/pages/settings/developer/webhooks/index.tsx deleted file mode 100644 index e23bb64712..0000000000 --- a/apps/web/pages/settings/developer/webhooks/index.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useSession } from "next-auth/react"; - -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; -import { CreateNewWebhookButton } from "@calcom/features/webhooks/components"; -import WebhooksView from "@calcom/features/webhooks/pages/webhooks-view"; -import { APP_NAME } from "@calcom/lib/constants"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { UserPermissionRole } from "@calcom/prisma/enums"; -import { trpc } from "@calcom/trpc/react"; -import { Meta } from "@calcom/ui"; - -import PageWrapper from "@components/PageWrapper"; - -const Page = () => { - const { t } = useLocale(); - const session = useSession(); - const isAdmin = session.data?.user.role === UserPermissionRole.ADMIN; - - const { data, isPending } = trpc.viewer.webhook.getByViewer.useQuery(undefined, { - enabled: session.status === "authenticated", - }); - - return ( - <> - 0 ? : <>} - borderInShellHeader={(data && data.profiles.length === 1) || !data?.webhookGroups?.length} - /> - - - ); -}; -Page.getLayout = getLayout; -Page.PageWrapper = PageWrapper; - -export default Page; diff --git a/apps/web/pages/settings/developer/webhooks/new.tsx b/apps/web/pages/settings/developer/webhooks/new.tsx deleted file mode 100644 index 981ddd73e7..0000000000 --- a/apps/web/pages/settings/developer/webhooks/new.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; -import WebhookNewView from "@calcom/features/webhooks/pages/webhook-new-view"; -import { APP_NAME } from "@calcom/lib/constants"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Meta } from "@calcom/ui"; - -import PageWrapper from "@components/PageWrapper"; - -const Page = () => { - const { t } = useLocale(); - return ( - <> - - - - ); -}; - -Page.PageWrapper = PageWrapper; -Page.getLayout = getLayout; - -export default Page; diff --git a/apps/web/playwright/fixtures/webhooks.ts b/apps/web/playwright/fixtures/webhooks.ts index de5b0b37fc..18a65dea99 100644 --- a/apps/web/playwright/fixtures/webhooks.ts +++ b/apps/web/playwright/fixtures/webhooks.ts @@ -12,9 +12,9 @@ export function createWebhookPageFixture(page: Page) { await page.waitForURL((u) => u.pathname === "/settings/developer/webhooks/new"); const url = page.url(); const teamId = Number(new URL(url).searchParams.get("teamId")) as number; - await page.click('[data-testid="new_webhook"]'); await page.fill('[name="subscriberUrl"]', webhookReceiver.url); await page.fill('[name="secret"]', "secret"); + await expect(page.locator('[data-testid="create_webhook"]')).toBeEnabled(); await Promise.all([ page.click("[type=submit]"), page.waitForURL((url) => url.pathname.endsWith("/settings/developer/webhooks")), @@ -28,6 +28,7 @@ export function createWebhookPageFixture(page: Page) { await page.click('[data-testid="new_webhook"]'); await page.fill('[name="subscriberUrl"]', webhookReceiver.url); await page.fill('[name="secret"]', "secret"); + await expect(page.locator('[data-testid="create_webhook"]')).toBeEnabled(); await Promise.all([ page.click("[type=submit]"), page.waitForURL((url) => url.pathname.endsWith("/settings/developer/webhooks")), diff --git a/apps/web/playwright/webhook.e2e.ts b/apps/web/playwright/webhook.e2e.ts index f710dd2c9b..01376987fb 100644 --- a/apps/web/playwright/webhook.e2e.ts +++ b/apps/web/playwright/webhook.e2e.ts @@ -490,7 +490,6 @@ test.describe("MEETING_ENDED, MEETING_STARTED", async () => { }, _testInfo) => { const user = await users.create(); await user.apiLogin(); - const tomorrow = dayjs().add(1, "day"); const [eventType] = user.eventTypes; bookings.create(user.id, user.name, eventType.id); bookings.create(user.id, user.name, eventType.id, { startTime: dayjs().add(2, "day").toDate() }); @@ -659,7 +658,12 @@ test.describe("FORM_SUBMITTED", async () => { webhookReceiver.close(); }); - test("on submitting team form, triggers team webhook", async ({ page, users, routingForms, webhooks }) => { + test("on submitting team form, triggers team webhook @test", async ({ + page, + users, + routingForms, + webhooks, + }) => { const user = await users.create(null, { hasTeam: true, }); @@ -814,7 +818,7 @@ test.describe("OOO_CREATED", async () => { hasTeam: true, }); await user.apiLogin(); - const { webhookReceiver, teamId } = await webhooks.createTeamReceiver(); + const { webhookReceiver } = await webhooks.createTeamReceiver(); await page.goto("/settings/my-account/out-of-office"); diff --git a/apps/web/scripts/vercel-app-router-deploy.sh b/apps/web/scripts/vercel-app-router-deploy.sh index ada94c4fe0..147732b27c 100755 --- a/apps/web/scripts/vercel-app-router-deploy.sh +++ b/apps/web/scripts/vercel-app-router-deploy.sh @@ -8,7 +8,6 @@ checkRoute () { # 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_AVAILABILITY_ENABLED" app/future/availability -checkRoute "$APP_ROUTER_SETTINGS_DEVELOPER_ENABLED" app/future/settings/developer 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 diff --git a/packages/features/webhooks/components/WebhookForm.tsx b/packages/features/webhooks/components/WebhookForm.tsx index 9301e911c7..8138021297 100644 --- a/packages/features/webhooks/components/WebhookForm.tsx +++ b/packages/features/webhooks/components/WebhookForm.tsx @@ -346,6 +346,7 @@ const WebhookForm = (props: {