perf: Fetch data server-side for Api Keys page (#20677)
* server-side fetching for api keys page * refactor billing page * fix
This commit is contained in:
+7
@@ -0,0 +1,7 @@
|
||||
"use server";
|
||||
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export async function revalidateApiKeysList() {
|
||||
revalidatePath("/settings/developer/api-keys");
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { SkeletonLoader } from "~/settings/developer/api-keys-skeleton";
|
||||
|
||||
export default function Loading() {
|
||||
return <SkeletonLoader />;
|
||||
}
|
||||
+7
-14
@@ -1,9 +1,10 @@
|
||||
import { getTranslate, _generateMetadata } from "app/_utils";
|
||||
import { createRouterCaller } from "app/_trpc/context";
|
||||
import { _generateMetadata } from "app/_utils";
|
||||
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { apiKeysRouter } from "@calcom/trpc/server/routers/viewer/apiKeys/_router";
|
||||
|
||||
import ApiKeysView, { NewApiKeyButton } from "~/settings/developer/api-keys-view";
|
||||
import ApiKeysView from "~/settings/developer/api-keys-view";
|
||||
|
||||
export const generateMetadata = async () =>
|
||||
await _generateMetadata(
|
||||
@@ -15,17 +16,9 @@ export const generateMetadata = async () =>
|
||||
);
|
||||
|
||||
const Page = async () => {
|
||||
const t = await getTranslate();
|
||||
|
||||
return (
|
||||
<SettingsHeader
|
||||
title={t("api_keys")}
|
||||
description={t("create_first_api_key_description", { appName: APP_NAME })}
|
||||
CTA={<NewApiKeyButton />}
|
||||
borderInShellHeader={true}>
|
||||
<ApiKeysView />
|
||||
</SettingsHeader>
|
||||
);
|
||||
const caller = await createRouterCaller(apiKeysRouter);
|
||||
const apiKeys = await caller.list();
|
||||
return <ApiKeysView apiKeys={apiKeys} />;
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -20,6 +20,7 @@ export const POST_METHODS_ALLOWED_API_ROUTES = ["/api/auth/signup", "/api/trpc/"
|
||||
export const POST_METHODS_ALLOWED_APP_ROUTES = [
|
||||
"/settings/my-account/general",
|
||||
"/settings/developer/webhooks",
|
||||
"/settings/developer/api-keys",
|
||||
];
|
||||
export function checkPostMethod(req: NextRequest) {
|
||||
const pathname = req.nextUrl.pathname;
|
||||
@@ -192,6 +193,7 @@ export const config = {
|
||||
// Routes allowed for POST method (matching `POST_METHODS_ALLOWED_APP_ROUTES` array)
|
||||
"/settings/my-account/general",
|
||||
"/settings/developer/webhooks",
|
||||
"/settings/developer/api-keys",
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -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("api_keys")}
|
||||
description={t("create_first_api_key_description", { appName: APP_NAME })}
|
||||
borderInShellHeader={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>
|
||||
);
|
||||
};
|
||||
@@ -7,24 +7,13 @@ import LicenseRequired from "@calcom/ee/common/components/LicenseRequired";
|
||||
import { Dialog } from "@calcom/features/components/controlled-dialog";
|
||||
import ApiKeyDialogForm from "@calcom/features/ee/api-keys/components/ApiKeyDialogForm";
|
||||
import ApiKeyListItem from "@calcom/features/ee/api-keys/components/ApiKeyListItem";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { Button } from "@calcom/ui/components/button";
|
||||
import { DialogContent } from "@calcom/ui/components/dialog";
|
||||
import { EmptyScreen } from "@calcom/ui/components/empty-screen";
|
||||
import { SkeletonText, SkeletonContainer } from "@calcom/ui/components/skeleton";
|
||||
|
||||
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>
|
||||
);
|
||||
};
|
||||
|
||||
export const apiKeyModalRef = {
|
||||
current: null as null | ((show: boolean) => void),
|
||||
@@ -48,10 +37,12 @@ export const NewApiKeyButton = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const ApiKeysView = () => {
|
||||
const { t } = useLocale();
|
||||
type Props = {
|
||||
apiKeys: RouterOutputs["viewer"]["apiKeys"]["list"];
|
||||
};
|
||||
|
||||
const { data, isPending } = trpc.viewer.apiKeys.list.useQuery();
|
||||
const ApiKeysView = ({ apiKeys: data }: Props) => {
|
||||
const { t } = useLocale();
|
||||
|
||||
const [apiKeyModal, setApiKeyModal] = useState(false);
|
||||
const [apiKeyToEdit, setApiKeyToEdit] = useState<(TApiKeys & { neverExpires?: boolean }) | undefined>(
|
||||
@@ -67,12 +58,12 @@ const ApiKeysView = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (isPending || !data) {
|
||||
return <SkeletonLoader />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsHeader
|
||||
title={t("api_keys")}
|
||||
description={t("create_first_api_key_description", { appName: APP_NAME })}
|
||||
CTA={<NewApiKeyButton />}
|
||||
borderInShellHeader={true}>
|
||||
<LicenseRequired>
|
||||
<div>
|
||||
{data?.length ? (
|
||||
@@ -108,7 +99,7 @@ const ApiKeysView = () => {
|
||||
<ApiKeyDialogForm handleClose={() => setApiKeyModal(false)} defaultValues={apiKeyToEdit} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
</SettingsHeader>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -6,14 +6,15 @@ import type { TApiKeys } from "@calcom/ee/api-keys/components/ApiKeyListItem";
|
||||
import LicenseRequired from "@calcom/ee/common/components/LicenseRequired";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { DialogFooter } from "@calcom/ui/components/dialog";
|
||||
import { Button } from "@calcom/ui/components/button";
|
||||
import { DialogFooter } from "@calcom/ui/components/dialog";
|
||||
import { Form } from "@calcom/ui/components/form";
|
||||
import { TextField } from "@calcom/ui/components/form";
|
||||
import { SelectField } from "@calcom/ui/components/form";
|
||||
import { Switch } from "@calcom/ui/components/form";
|
||||
import { showToast } from "@calcom/ui/components/toast";
|
||||
import { Tooltip } from "@calcom/ui/components/tooltip";
|
||||
import { revalidateApiKeysList } from "@calcom/web/app/(use-page-wrapper)/settings/(settings-layout)/developer/api-keys/actions";
|
||||
|
||||
export default function ApiKeyDialogForm({
|
||||
defaultValues,
|
||||
@@ -28,6 +29,7 @@ export default function ApiKeyDialogForm({
|
||||
const updateApiKeyMutation = trpc.viewer.apiKeys.edit.useMutation({
|
||||
onSuccess() {
|
||||
utils.viewer.apiKeys.list.invalidate();
|
||||
revalidateApiKeysList();
|
||||
showToast(t("api_key_updated"), "success");
|
||||
handleClose();
|
||||
},
|
||||
@@ -131,6 +133,7 @@ export default function ApiKeyDialogForm({
|
||||
setApiKey(apiKey);
|
||||
setApiKeyDetails({ ...event });
|
||||
await utils.viewer.apiKeys.list.invalidate();
|
||||
revalidateApiKeysList();
|
||||
setSuccessfulNewApiKeyModal(true);
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -2,6 +2,9 @@ import dayjs from "@calcom/dayjs";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
import { Badge } from "@calcom/ui/components/badge";
|
||||
import { Button } from "@calcom/ui/components/button";
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
@@ -9,10 +12,8 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@calcom/ui/components/dropdown";
|
||||
import { Badge } from "@calcom/ui/components/badge";
|
||||
import { Button } from "@calcom/ui/components/button";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
import { showToast } from "@calcom/ui/components/toast";
|
||||
import { revalidateApiKeysList } from "@calcom/web/app/(use-page-wrapper)/settings/(settings-layout)/developer/api-keys/actions";
|
||||
|
||||
export type TApiKeys = RouterOutputs["viewer"]["apiKeys"]["list"][number];
|
||||
|
||||
@@ -34,6 +35,7 @@ const ApiKeyListItem = ({
|
||||
const deleteApiKey = trpc.viewer.apiKeys.delete.useMutation({
|
||||
async onSuccess() {
|
||||
await utils.viewer.apiKeys.list.invalidate();
|
||||
revalidateApiKeysList();
|
||||
showToast(t("api_key_deleted"), "success");
|
||||
},
|
||||
onError(err) {
|
||||
|
||||
Reference in New Issue
Block a user