perf: Fetch data server-side for Webhook Create page (#20675)
* perf: fetch data server-side for create webhooks page * refactor * refactor * refactor * improve skeleton styling * fix styling
This commit is contained in:
+2
-11
@@ -1,14 +1,5 @@
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { SkeletonLoader } from "@calcom/features/webhooks/pages/webhooks-view";
|
||||
import { SkeletonLoader } from "@calcom/features/webhooks/pages/webhooks-skeleton";
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
<SettingsHeader
|
||||
title="Webhooks"
|
||||
description="Receive meeting data in real-time when something happens in Cal.com"
|
||||
borderInShellHeader={true}
|
||||
CTA={null}>
|
||||
<SkeletonLoader />
|
||||
</SettingsHeader>
|
||||
);
|
||||
return <SkeletonLoader />;
|
||||
}
|
||||
|
||||
+2
-13
@@ -1,11 +1,9 @@
|
||||
import { createRouterCaller } from "app/_trpc/context";
|
||||
import { _generateMetadata, getTranslate } from "app/_utils";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
import { cookies, headers } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { CreateNewWebhookButton } from "@calcom/features/webhooks/components";
|
||||
import WebhooksView from "@calcom/features/webhooks/pages/webhooks-view";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { UserPermissionRole } from "@calcom/prisma/enums";
|
||||
@@ -25,20 +23,11 @@ const WebhooksViewServerWrapper = async () => {
|
||||
redirect("/auth/login");
|
||||
}
|
||||
|
||||
const t = await getTranslate();
|
||||
const isAdmin = session.user.role === UserPermissionRole.ADMIN;
|
||||
const caller = await createRouterCaller(webhookRouter);
|
||||
const data = await caller.getByViewer();
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("webhooks")}
|
||||
description={t("add_webhook_description", { appName: APP_NAME })}
|
||||
CTA={data && data.webhookGroups.length > 0 ? <CreateNewWebhookButton isAdmin={isAdmin} /> : null}
|
||||
borderInShellHeader={(data && data.profiles.length === 1) || !data?.webhookGroups?.length}>
|
||||
<WebhooksView data={data} isAdmin={isAdmin} />
|
||||
</SettingsHeader>
|
||||
);
|
||||
return <WebhooksView data={data} isAdmin={isAdmin} />;
|
||||
};
|
||||
|
||||
export default WebhooksViewServerWrapper;
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { SkeletonLoader } from "@calcom/features/webhooks/pages/webhook-new-skeleton";
|
||||
|
||||
export default function Loading() {
|
||||
return <SkeletonLoader />;
|
||||
}
|
||||
+15
-16
@@ -1,9 +1,10 @@
|
||||
import { getTranslate, _generateMetadata } from "app/_utils";
|
||||
import { Suspense } from "react";
|
||||
import { createRouterCaller } from "app/_trpc/context";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { NewWebhookView, SkeletonLoader } from "@calcom/features/webhooks/pages/webhook-new-view";
|
||||
import { NewWebhookView } from "@calcom/features/webhooks/pages/webhook-new-view";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { appsRouter } from "@calcom/trpc/server/routers/viewer/apps/_router";
|
||||
import { webhookRouter } from "@calcom/trpc/server/routers/viewer/webhook/_router";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
@@ -12,19 +13,17 @@ export const generateMetadata = async () =>
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const t = await getTranslate();
|
||||
const [appsCaller, webhookCaller] = await Promise.all([
|
||||
createRouterCaller(appsRouter),
|
||||
createRouterCaller(webhookRouter),
|
||||
]);
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("add_webhook")}
|
||||
description={t("add_webhook_description", { appName: APP_NAME })}
|
||||
borderInShellHeader={true}
|
||||
backButton>
|
||||
<Suspense fallback={<SkeletonLoader />}>
|
||||
<NewWebhookView />
|
||||
</Suspense>
|
||||
</SettingsHeader>
|
||||
);
|
||||
const [installedApps, webhooks] = await Promise.all([
|
||||
appsCaller.integrations({ variant: "other", onlyInstalled: true }),
|
||||
webhookCaller.list(),
|
||||
]);
|
||||
|
||||
return <NewWebhookView webhooks={webhooks} installedApps={installedApps} />;
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
"use client";
|
||||
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { SkeletonText, SkeletonContainer } from "@calcom/ui/components/skeleton";
|
||||
|
||||
export const SkeletonLoader = () => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("add_webhook")}
|
||||
description={t("add_webhook_description", { appName: APP_NAME })}
|
||||
borderInShellHeader={true}
|
||||
backButton={true}>
|
||||
<SkeletonContainer>
|
||||
<div className="divide-subtle border-subtle space-y-6 rounded-b-lg border border-t-0 px-6 py-4">
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
</div>
|
||||
</SkeletonContainer>
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
@@ -3,10 +3,12 @@
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
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 { SkeletonText, SkeletonContainer } from "@calcom/ui/components/skeleton";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { showToast } from "@calcom/ui/components/toast";
|
||||
import { revalidateWebhooksList } from "@calcom/web/app/(use-page-wrapper)/settings/(settings-layout)/developer/webhooks/(with-loader)/actions";
|
||||
|
||||
@@ -14,18 +16,12 @@ import type { WebhookFormSubmitData } from "../components/WebhookForm";
|
||||
import WebhookForm from "../components/WebhookForm";
|
||||
import { subscriberUrlReserved } from "../lib/subscriberUrlReserved";
|
||||
|
||||
export const SkeletonLoader = () => {
|
||||
return (
|
||||
<SkeletonContainer>
|
||||
<div className="divide-subtle border-subtle space-y-6 rounded-b-lg border border-t-0 px-6 py-4">
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
</div>
|
||||
</SkeletonContainer>
|
||||
);
|
||||
type Props = {
|
||||
webhooks: RouterOutputs["viewer"]["webhook"]["list"];
|
||||
installedApps: RouterOutputs["viewer"]["apps"]["integrations"];
|
||||
};
|
||||
|
||||
export const NewWebhookView = () => {
|
||||
export const NewWebhookView = ({ webhooks, installedApps }: Props) => {
|
||||
const searchParams = useCompatSearchParams();
|
||||
const { t } = useLocale();
|
||||
const utils = trpc.useUtils();
|
||||
@@ -35,18 +31,6 @@ export const NewWebhookView = () => {
|
||||
const teamId = searchParams?.get("teamId") ? Number(searchParams.get("teamId")) : undefined;
|
||||
const platform = searchParams?.get("platform") ? Boolean(searchParams.get("platform")) : false;
|
||||
|
||||
const { data: installedApps, isPending } = trpc.viewer.apps.integrations.useQuery(
|
||||
{ variant: "other", onlyInstalled: true },
|
||||
{
|
||||
suspense: true,
|
||||
enabled: session.status === "authenticated",
|
||||
}
|
||||
);
|
||||
const { data: webhooks } = trpc.viewer.webhook.list.useQuery(undefined, {
|
||||
suspense: true,
|
||||
enabled: session.status === "authenticated",
|
||||
});
|
||||
|
||||
const createWebhookMutation = trpc.viewer.webhook.create.useMutation({
|
||||
async onSuccess() {
|
||||
showToast(t("webhook_created_successfully"), "success");
|
||||
@@ -91,14 +75,18 @@ export const NewWebhookView = () => {
|
||||
});
|
||||
};
|
||||
|
||||
if (isPending) return null;
|
||||
|
||||
return (
|
||||
<WebhookForm
|
||||
noRoutingFormTriggers={false}
|
||||
onSubmit={onCreateWebhook}
|
||||
apps={installedApps?.items.map((app) => app.slug)}
|
||||
/>
|
||||
<SettingsHeader
|
||||
title={t("add_webhook")}
|
||||
description={t("add_webhook_description", { appName: APP_NAME })}
|
||||
borderInShellHeader={true}
|
||||
backButton={true}>
|
||||
<WebhookForm
|
||||
noRoutingFormTriggers={false}
|
||||
onSubmit={onCreateWebhook}
|
||||
apps={installedApps?.items.map((app) => app.slug)}
|
||||
/>
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
"use client";
|
||||
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { SkeletonText, SkeletonContainer } from "@calcom/ui/components/skeleton";
|
||||
|
||||
export const SkeletonLoader = () => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("webhooks")}
|
||||
description={t("add_webhook_description", { appName: APP_NAME })}
|
||||
borderInShellHeader={false}
|
||||
CTA={null}>
|
||||
<SkeletonContainer>
|
||||
<div className="divide-subtle border-subtle mt-6 space-y-6 rounded-lg border px-6 py-4">
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
</div>
|
||||
</SkeletonContainer>
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { APP_NAME, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { useBookerUrl } from "@calcom/lib/hooks/useBookerUrl";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
@@ -10,21 +11,9 @@ import type { WebhooksByViewer } from "@calcom/trpc/server/routers/viewer/webhoo
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
import { Avatar } from "@calcom/ui/components/avatar";
|
||||
import { EmptyScreen } from "@calcom/ui/components/empty-screen";
|
||||
import { SkeletonText, SkeletonContainer } from "@calcom/ui/components/skeleton";
|
||||
|
||||
import { WebhookListItem, CreateNewWebhookButton } from "../components";
|
||||
|
||||
export const SkeletonLoader = () => {
|
||||
return (
|
||||
<SkeletonContainer>
|
||||
<div className="divide-subtle border-subtle space-y-6 rounded-b-lg border border-t-0 px-6 py-4">
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
</div>
|
||||
</SkeletonContainer>
|
||||
);
|
||||
};
|
||||
|
||||
type Props = {
|
||||
data: RouterOutputs["viewer"]["webhook"]["getByViewer"];
|
||||
isAdmin: boolean;
|
||||
@@ -53,9 +42,13 @@ const WebhooksList = ({
|
||||
const hasTeams = profiles && profiles.length > 1;
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsHeader
|
||||
title={t("webhooks")}
|
||||
description={t("add_webhook_description", { appName: APP_NAME })}
|
||||
CTA={webhooksByViewer.webhookGroups.length > 0 ? <CreateNewWebhookButton isAdmin={isAdmin} /> : null}
|
||||
borderInShellHeader={false}>
|
||||
{!!webhookGroups.length ? (
|
||||
<div className={classNames("mt-0", hasTeams && "mt-6")}>
|
||||
<div className={classNames("mt-6")}>
|
||||
{webhookGroups.map((group) => (
|
||||
<div key={group.teamId}>
|
||||
{hasTeams && (
|
||||
@@ -72,11 +65,7 @@ const WebhooksList = ({
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col" key={group.profile.slug}>
|
||||
<div
|
||||
className={classNames(
|
||||
"border-subtle rounded-lg rounded-t-none border border-t-0",
|
||||
hasTeams && "mb-8 mt-3 rounded-t-lg border-t"
|
||||
)}>
|
||||
<div className={classNames("border-subtle mb-8 mt-3 rounded-lg border border-t")}>
|
||||
{group.webhooks.map((webhook, index) => (
|
||||
<WebhookListItem
|
||||
key={webhook.id}
|
||||
@@ -98,12 +87,12 @@ const WebhooksList = ({
|
||||
Icon="link"
|
||||
headline={t("create_your_first_webhook")}
|
||||
description={t("create_your_first_webhook_description", { appName: APP_NAME })}
|
||||
className="rounded-b-lg rounded-t-none border-t-0"
|
||||
className="mt-6 rounded-b-lg"
|
||||
buttonRaw={<CreateNewWebhookButton isAdmin={isAdmin} />}
|
||||
border={true}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user