diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(general)/import/EngineImportPage.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(general)/import/EngineImportPage.tsx index 478e773efd6..4fb245b7a77 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(general)/import/EngineImportPage.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(general)/import/EngineImportPage.tsx @@ -1,6 +1,5 @@ "use client"; -import { FormControl } from "@chakra-ui/react"; import { zodResolver } from "@hookform/resolvers/zod"; import { useMutation } from "@tanstack/react-query"; import { CircleAlertIcon, DownloadIcon, ExternalLinkIcon } from "lucide-react"; @@ -12,6 +11,7 @@ import { apiServerProxy } from "@/actions/proxies"; import { Button } from "@/components/ui/button"; import { Form, + FormControl, FormField, FormItem, FormLabel, diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/access-tokens-table.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/access-tokens-table.tsx index cde5a34614a..4cf61d3ee53 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/access-tokens-table.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/access-tokens-table.tsx @@ -1,33 +1,28 @@ -import { - Flex, - FormControl, - Input, - Modal, - ModalBody, - ModalCloseButton, - ModalContent, - ModalFooter, - ModalHeader, - ModalOverlay, - type UseDisclosureReturn, - useDisclosure, -} from "@chakra-ui/react"; import { createColumnHelper } from "@tanstack/react-table"; -import { Button } from "chakra/button"; -import { FormLabel } from "chakra/form"; -import { Text } from "chakra/text"; import { PencilIcon, Trash2Icon } from "lucide-react"; import { useMemo, useState } from "react"; +import { toast } from "sonner"; import type { ThirdwebClient } from "thirdweb"; import { TWTable } from "@/components/blocks/TWTable"; import { WalletAddress } from "@/components/blocks/wallet-address"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Spinner } from "@/components/ui/Spinner/Spinner"; import { type AccessToken, useEngineRevokeAccessToken, useEngineUpdateAccessToken, } from "@/hooks/useEngine"; -import { useTxNotifications } from "@/hooks/useTxNotifications"; import { toDateTimeLocal } from "@/utils/date-utils"; +import { parseError } from "@/utils/errorParser"; interface AccessTokensTableProps { instanceUrl: string; @@ -40,36 +35,32 @@ interface AccessTokensTableProps { const columnHelper = createColumnHelper(); -export const AccessTokensTable: React.FC = ({ +export function AccessTokensTable({ instanceUrl, accessTokens, isPending, isFetched, authToken, client, -}) => { - const editDisclosure = useDisclosure(); - const removeDisclosure = useDisclosure(); +}: AccessTokensTableProps) { + const [editOpen, setEditOpen] = useState(false); + const [removeOpen, setRemoveOpen] = useState(false); const [selectedAccessToken, setSelectedAccessToken] = useState(); const columns = useMemo(() => { return [ columnHelper.accessor("tokenMask", { - cell: (cell) => { - return ( -

{cell.getValue()}

- ); - }, + cell: (cell) => ( +

{cell.getValue()}

+ ), header: "Access Token", }), columnHelper.accessor("label", { - cell: (cell) => { - return ( - - {cell.getValue()} - - ); - }, + cell: (cell) => ( + + {cell.getValue()} + + ), header: "Label", }), columnHelper.accessor("walletAddress", { @@ -82,11 +73,8 @@ export const AccessTokensTable: React.FC = ({ columnHelper.accessor("createdAt", { cell: (cell) => { const value = cell.getValue(); - - if (!value) { - return; - } - return {toDateTimeLocal(value)}; + if (!value) return null; + return {toDateTimeLocal(value)}; }, header: "Created At", }), @@ -105,7 +93,7 @@ export const AccessTokensTable: React.FC = ({ icon: , onClick: (accessToken) => { setSelectedAccessToken(accessToken); - editDisclosure.onOpen(); + setEditOpen(true); }, text: "Edit", }, @@ -114,181 +102,201 @@ export const AccessTokensTable: React.FC = ({ isDestructive: true, onClick: (accessToken) => { setSelectedAccessToken(accessToken); - removeDisclosure.onOpen(); + setRemoveOpen(true); }, text: "Delete", }, ]} title="access tokens" /> - - {selectedAccessToken && editDisclosure.isOpen && ( + {selectedAccessToken && ( )} - {selectedAccessToken && removeDisclosure.isOpen && ( + {selectedAccessToken && ( )} ); -}; +} -const EditModal = ({ +function EditModal({ + open, + onOpenChange, accessToken, - disclosure, instanceUrl, authToken, }: { + open: boolean; + onOpenChange: (open: boolean) => void; accessToken: AccessToken; - disclosure: UseDisclosureReturn; instanceUrl: string; authToken: string; -}) => { - const { mutate: updateAccessToken } = useEngineUpdateAccessToken({ +}) { + const updateToken = useEngineUpdateAccessToken({ authToken, instanceUrl, }); - const { onSuccess, onError } = useTxNotifications( - "Successfully updated access token", - "Failed to update access token", - ); - const [label, setLabel] = useState(accessToken.label ?? ""); - const onClick = () => { - updateAccessToken( + updateToken.mutate( { id: accessToken.id, label, }, { onError: (error) => { - onError(error); + toast.error("Failed to update access token", { + description: parseError(error), + }); console.error(error); }, onSuccess: () => { - onSuccess(); - disclosure.onClose(); + toast.success("Successfully updated access token"); + onOpenChange(false); }, }, ); }; - return ( - - - - Update Access Token - - -
- - Access Token - {accessToken.tokenMask} - - - Label - setLabel(e.target.value)} - placeholder="Enter a description for this access token" - type="text" - value={label} - /> - + + + + Update Access Token + + +
+
+

Access Token

+
+ {accessToken.tokenMask} +
+
+ +
+ + setLabel(e.target.value)} + placeholder="Enter a description for this access token" + className="bg-card" + type="text" + value={label} + />
- +
- - - - - - +
+ + ); -}; +} -const RemoveModal = ({ +function RemoveModal({ + open, + onOpenChange, accessToken, - disclosure, instanceUrl, authToken, }: { + open: boolean; + onOpenChange: (open: boolean) => void; accessToken: AccessToken; - disclosure: UseDisclosureReturn; instanceUrl: string; authToken: string; -}) => { - const { mutate: deleteAccessToken } = useEngineRevokeAccessToken({ +}) { + const deleteToken = useEngineRevokeAccessToken({ authToken, instanceUrl, }); - const { onSuccess, onError } = useTxNotifications( - "Successfully deleted access token", - "Failed to delete access token", - ); - const onClick = () => { - deleteAccessToken( + deleteToken.mutate( { id: accessToken.id, }, { onError: (error) => { - onError(error); + toast.error("Failed to delete access token", { + description: parseError(error), + }); console.error(error); }, onSuccess: () => { - onSuccess(); - disclosure.onClose(); + toast.success("Successfully deleted access token"); + onOpenChange(false); }, }, ); }; - return ( - - - - Delete Access Token - - -
- Are you sure you want to delete this access token? - - Access Token - {accessToken.tokenMask} - - - Label - {accessToken.label ?? N/A} - + + + + Delete access token + + Are you sure you want to delete this access token? + + + +
+
+

Access Token

+
+ {accessToken.tokenMask} +
- +
+ +
+ {accessToken.label ?? No Label } +
+
+
- - - - - - +
+ + ); -}; +} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-access-token-button.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-access-token-button.tsx index 9e1b02c7064..50ffda101d7 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-access-token-button.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-access-token-button.tsx @@ -1,111 +1,102 @@ -import { - Flex, - Modal, - ModalBody, - ModalContent, - ModalFooter, - ModalHeader, - ModalOverlay, - useDisclosure, -} from "@chakra-ui/react"; -import { Button } from "chakra/button"; -import { Text } from "chakra/text"; -import { CirclePlusIcon } from "lucide-react"; +import { PlusIcon } from "lucide-react"; import { useState } from "react"; +import { toast } from "sonner"; +import { Button } from "@/components/ui/button"; import { Checkbox, CheckboxWithLabel } from "@/components/ui/checkbox"; import { PlainTextCodeBlock } from "@/components/ui/code/plaintext-code"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Spinner } from "@/components/ui/Spinner/Spinner"; import { useEngineCreateAccessToken } from "@/hooks/useEngine"; -import { useTxNotifications } from "@/hooks/useTxNotifications"; +import { parseError } from "@/utils/errorParser"; -interface AddAccessTokenButtonProps { - instanceUrl: string; - authToken: string; -} - -export const AddAccessTokenButton: React.FC = ({ +export function AddAccessTokenButton({ instanceUrl, authToken, -}) => { - const [accessToken, setAccessToken] = useState(""); - const { isOpen, onOpen, onClose } = useDisclosure(); - const { mutate: createAccessToken } = useEngineCreateAccessToken({ +}: { + instanceUrl: string; + authToken: string; +}) { + const [accessToken, setAccessToken] = useState(""); + const [isOpen, setIsOpen] = useState(false); + const createAccessToken = useEngineCreateAccessToken({ authToken, instanceUrl, }); - - const [hasStoredToken, setHasStoredToken] = useState(false); - - const { onSuccess, onError } = useTxNotifications( - "Access token created successfully.", - "Failed to create Access Token.", - ); + const [hasStoredToken, setHasStoredToken] = useState(false); return ( <> - { + setIsOpen(open); + if (!open) setAccessToken(""); + }} > - - - Access token - -
- - - This access token will not be shown again. - - - setHasStoredToken(!!val)} - /> - I have securely stored this access token. - -
-
+ + + Access token + + This access token will not be shown again. + + + +
+ + + setHasStoredToken(!!val)} + /> + I have securely stored this access token. + +
- +
- - - +
+
+ ); -}; +} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-keypair-button.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-keypair-button.tsx index 78a69675f79..f88130eb48f 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-keypair-button.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/engine/dedicated/(instance)/[engineId]/access-tokens/components/add-keypair-button.tsx @@ -1,26 +1,27 @@ +import { InfoIcon, PlusIcon } from "lucide-react"; +import { useState } from "react"; +import { toast } from "sonner"; +import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; +import { Button } from "@/components/ui/button"; +import { CodeClient } from "@/components/ui/code/code.client"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Spinner } from "@/components/ui/Spinner/Spinner"; import { - Alert, - Flex, - FormControl, - Input, - Modal, - ModalBody, - ModalContent, - ModalFooter, - ModalHeader, - ModalOverlay, Select, - Textarea, - useDisclosure, -} from "@chakra-ui/react"; -import { Button } from "chakra/button"; -import { FormLabel } from "chakra/form"; -import { Text } from "chakra/text"; -import { CirclePlusIcon } from "lucide-react"; -import { useState } from "react"; -import { PlainTextCodeBlock } from "@/components/ui/code/plaintext-code"; + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Textarea } from "@/components/ui/textarea"; import { type KeypairAlgorithm, useEngineAddKeypair } from "@/hooks/useEngine"; -import { useTxNotifications } from "@/hooks/useTxNotifications"; +import { parseError } from "@/utils/errorParser"; const KEYPAIR_ALGORITHM_DETAILS: Record< KeypairAlgorithm, @@ -52,168 +53,162 @@ const KEYPAIR_ALGORITHM_DETAILS: Record< }, }; -interface AddKeypairButtonProps { - instanceUrl: string; - authToken: string; -} - -export const AddKeypairButton: React.FC = ({ +export function AddKeypairButton({ instanceUrl, authToken, -}) => { - const [publicKey, setPublicKey] = useState(""); +}: { + instanceUrl: string; + authToken: string; +}) { + const [publicKey, setPublicKey] = useState(""); const [algorithm, setAlgorithm] = useState("ES256"); - const [label, setLabel] = useState(""); - const { isOpen, onOpen, onClose } = useDisclosure(); - const { mutateAsync: importKeypair } = useEngineAddKeypair({ + const [label, setLabel] = useState(""); + const [isOpen, setIsOpen] = useState(false); + const importKeypairMutation = useEngineAddKeypair({ authToken, instanceUrl, }); - const { onSuccess, onError } = useTxNotifications( - "Public key added successfully.", - "Failed to add public key.", - ); - const onClick = async () => { try { - await importKeypair({ + await importKeypairMutation.mutateAsync({ algorithm, label, publicKey, }); - - onSuccess(); - + toast.success("Public key added successfully."); setPublicKey(""); - onClose(); + setIsOpen(false); } catch (error) { - onError(error); + toast.error("Failed to add public key.", { + description: parseError(error), + }); console.error(error); } }; return ( <> - - - - - Add Public Key - - -
-
- Create a private key using: - setAlgorithm(v as KeypairAlgorithm)} + > + + + + {( Object.keys( KEYPAIR_ALGORITHM_DETAILS, ) as KeypairAlgorithm[] ).map((key) => ( - + ))} - -
+ + - - Extract the public key. - - Print the public key. -
-
+ - - - Public Key ({KEYPAIR_ALGORITHM_DETAILS[algorithm].name}) - + {/* public key input */} +
+