From 47a8fd6b62f30757ee7b4e849743e289a1f887f7 Mon Sep 17 00:00:00 2001 From: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com> Date: Fri, 11 Aug 2023 20:53:59 +0530 Subject: [PATCH] Rewrite Api Key Settings to React Server Components (#654) * moved apikey settings to server component * rename ZApiKeyData to ZApiKeyCreateInput * Make smaller improvements --------- Co-authored-by: Matthias Nannt --- .../settings/api-keys/ApiKeyList.tsx | 29 ++++----- .../settings/api-keys/EditApiKeys.tsx | 42 ++++++------- .../settings/api-keys/actions.ts | 11 ++++ .../settings/api-keys/loading.tsx | 50 +++++++++++++++ .../settings/api-keys/page.tsx | 3 + packages/lib/services/apiKey.ts | 63 ++++++++++++++++++- packages/types/v1/apiKeys.ts | 6 ++ 7 files changed, 163 insertions(+), 41 deletions(-) create mode 100644 apps/web/app/(app)/environments/[environmentId]/settings/api-keys/actions.ts create mode 100644 apps/web/app/(app)/environments/[environmentId]/settings/api-keys/loading.tsx diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/api-keys/ApiKeyList.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/api-keys/ApiKeyList.tsx index bd61103bce..a485d3586e 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/api-keys/ApiKeyList.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/settings/api-keys/ApiKeyList.tsx @@ -1,19 +1,15 @@ -"use client"; - -import LoadingSpinner from "@/components/shared/LoadingSpinner"; -import { useProduct } from "@/lib/products/products"; -import { ErrorComponent } from "@formbricks/ui"; import EditApiKeys from "./EditApiKeys"; +import { getProductByEnvironmentId } from "@formbricks/lib/services/product"; +import { getApiKeys } from "@formbricks/lib/services/apiKey"; +import { getEnvironments } from "@formbricks/lib/services/environment"; -export default function ApiKeyList({ +export default async function ApiKeyList({ environmentId, environmentType, }: { environmentId: string; environmentType: string; }) { - const { product, isLoadingProduct, isErrorProduct } = useProduct(environmentId); - const findEnvironmentByType = (environments, targetType) => { for (const environment of environments) { if (environment.type === targetType) { @@ -23,15 +19,12 @@ export default function ApiKeyList({ return null; }; - if (isLoadingProduct) { - return ; - } + const product = await getProductByEnvironmentId(environmentId); + const environments = await getEnvironments(product.id); + const environmentTypeId = findEnvironmentByType(environments, environmentType); + const apiKeys = await getApiKeys(environmentTypeId); - if (isErrorProduct) { - ; - } - - const environmentTypeId = findEnvironmentByType(product?.environments, environmentType); - - return ; + return ( + + ); } diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/api-keys/EditApiKeys.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/api-keys/EditApiKeys.tsx index c698f169e1..89ec83521c 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/api-keys/EditApiKeys.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/settings/api-keys/EditApiKeys.tsx @@ -1,28 +1,28 @@ "use client"; import DeleteDialog from "@/components/shared/DeleteDialog"; -import LoadingSpinner from "@/components/shared/LoadingSpinner"; -import { createApiKey, deleteApiKey, useApiKeys } from "@/lib/apiKeys"; import { capitalizeFirstLetter } from "@/lib/utils"; import { timeSince } from "@formbricks/lib/time"; -import { Button, ErrorComponent } from "@formbricks/ui"; +import { TApiKey } from "@formbricks/types/v1/apiKeys"; +import { Button } from "@formbricks/ui"; import { TrashIcon } from "@heroicons/react/24/outline"; import { useState } from "react"; import toast from "react-hot-toast"; import AddAPIKeyModal from "./AddApiKeyModal"; +import { createApiKeyAction, deleteApiKeyAction } from "./actions"; export default function EditAPIKeys({ environmentTypeId, environmentType, + apiKeys, }: { environmentTypeId: string; environmentType: string; + apiKeys: TApiKey[]; }) { - const { apiKeys, mutateApiKeys, isLoadingApiKeys, isErrorApiKeys } = useApiKeys(environmentTypeId); - const [isAddAPIKeyModalOpen, setOpenAddAPIKeyModal] = useState(false); const [isDeleteKeyModalOpen, setOpenDeleteKeyModal] = useState(false); - + const [apiKeysLocal, setApiKeysLocal] = useState(apiKeys); const [activeKey, setActiveKey] = useState({} as any); const handleOpenDeleteKeyModal = (e, apiKey) => { @@ -32,26 +32,21 @@ export default function EditAPIKeys({ }; const handleDeleteKey = async () => { - await deleteApiKey(environmentTypeId, activeKey); - mutateApiKeys(); + await deleteApiKeyAction(activeKey.id); + const updatedApiKeys = apiKeysLocal?.filter((apiKey) => apiKey.id !== activeKey.id) || []; + setApiKeysLocal(updatedApiKeys); setOpenDeleteKeyModal(false); toast.success("API Key deleted"); }; const handleAddAPIKey = async (data) => { - const apiKey = await createApiKey(environmentTypeId, { label: data.label }); - mutateApiKeys([...JSON.parse(JSON.stringify(apiKeys)), apiKey], false); + const apiKey = await createApiKeyAction(environmentTypeId, { label: data.label }); + const updatedApiKeys = [...apiKeysLocal!, apiKey]; + setApiKeysLocal(updatedApiKeys); setOpenAddAPIKeyModal(false); + toast.success("API key created"); }; - if (isLoadingApiKeys) { - return ; - } - - if (isErrorApiKeys) { - ; - } - return ( <>
@@ -72,19 +67,22 @@ export default function EditAPIKeys({
- {apiKeys.length === 0 ? ( + {apiKeysLocal && apiKeysLocal.length === 0 ? (
You don't have any API keys yet
) : ( - apiKeys.map((apiKey) => ( + apiKeysLocal && + apiKeysLocal.map((apiKey) => (
{apiKey.label}
{apiKey.apiKey || secret}
-
{apiKey.lastUsed && timeSince(apiKey.lastUsed)}
-
{timeSince(apiKey.createdAt)}
+
+ {apiKey.lastUsedAt && timeSince(apiKey.lastUsedAt.toString())} +
+
{timeSince(apiKey.createdAt.toString())}