Skip to content

Commit

Permalink
feat: API Key page improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
rflihxyz committed Dec 23, 2024
1 parent 4a8efcf commit 31f8bb3
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 31 deletions.
29 changes: 26 additions & 3 deletions apps/webapp/src/app/(Dashboard)/api-keys/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ import { useForm } from "react-hook-form"
import { DataTableLoading } from "@/components/shared/data-table-loading";
import {CustomHeading} from "@/components/shared/custom-heading";
import { useColumns } from "@/components/ApiKeys/columns";
import { PlusCircle } from "lucide-react";
import { PlusCircle, Copy, Check } from "lucide-react";
import { toast } from "sonner";
import { Badge } from "@/components/ui/badge";
import { useQueryClient } from "@tanstack/react-query";
import { cn } from "@/lib/utils";

const formSchema = z.object({
apiKeyIdentifier: z.string().min(2, {
Expand Down Expand Up @@ -251,8 +252,30 @@ export default function Page() {
This key will only be shown for the next minute. Please save it now.
</DialogDescription>
</DialogHeader>
<div className="mt-4">
<strong>API Key:</strong> <p>{newApiKey?.key}</p>
<div className="mt-4 flex items-center justify-between gap-2 rounded-md border p-2">
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold">
{newApiKey?.key}
</code>
<Button
variant="ghost"
size="icon"
onClick={() => {
if (newApiKey?.key) {
navigator.clipboard.writeText(newApiKey.key);
toast.success("API key copied to clipboard");
}
}}
className={cn(
"h-8 w-8",
"hover:bg-muted",
"focus-visible:ring-1",
"focus-visible:ring-ring",
"focus-visible:ring-offset-0"
)}
>
<Copy className="h-4 w-4" />
<span className="sr-only">Copy API key</span>
</Button>
</div>
<DialogFooter>
<Button size="sm" className="h-7 gap-1" onClick={() => setIsKeyModalOpen(false)}>Close</Button>
Expand Down
112 changes: 84 additions & 28 deletions apps/webapp/src/components/ApiKeys/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,23 @@ import { ColumnDef } from "@tanstack/react-table"
import { Badge } from "@/components/ui/badge"
import { ApiKey } from "./schema"
import { DataTableColumnHeader } from "../shared/data-table-column-header"
import { DataTableRowActions } from "../shared/data-table-row-actions"
import { PasswordInput } from "../ui/password-input"
import { useState } from "react"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip"
import { Button } from "../ui/button"
import { toast } from "sonner"
import { Card } from "antd"
import { Button } from "../ui/button"
import { TrashIcon } from "@radix-ui/react-icons"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import useDeleteApiKey from "@/hooks/delete/useDeleteApiKey"
import { useQueryClient } from "@tanstack/react-query"

export function useColumns() {
const [copiedState, setCopiedState] = useState<{ [key: string]: boolean }>({});

const handleCopy = (token: string) => {
navigator.clipboard.writeText(token);
setCopiedState((prevState) => ({
...prevState,
[token]: true,
}));
toast.success("Api key copied", {
action: {
label: "Close",
onClick: () => console.log("Close"),
},
})
setTimeout(() => {
setCopiedState((prevState) => ({
...prevState,
[token]: false,
}));
}, 2000); // Reset copied state after 2 seconds
};

return [
{
accessorKey: "name",
Expand All @@ -47,7 +33,77 @@ export function useColumns() {
},
{
id: "actions",
cell: ({ row }) => <DataTableRowActions row={row} object={"api-key"}/>,
cell: ({ row }) => {
const [dialogOpen, setDialogOpen] = useState(false);
const [confirmText, setConfirmText] = useState('');
const { deleteApiKeyPromise } = useDeleteApiKey();
const queryClient = useQueryClient();

const handleDelete = async () => {
if (confirmText.toLowerCase() === 'delete') {
try {
await toast.promise(
deleteApiKeyPromise({
id_api_key: row.original.id_api_key,
}),
{
loading: 'Deleting API key...',
success: 'API key deleted successfully',
error: 'Failed to delete API key'
}
);
queryClient.invalidateQueries({ queryKey: ['api-keys'] });
setDialogOpen(false);
} catch (error) {
console.error('Failed to delete API key:', error);
}
}
};

return (
<>
<Button
variant="ghost"
className="flex h-8 w-8 p-0 data-[state=open]:bg-muted"
onClick={() => setDialogOpen(true)}
>
<TrashIcon className="h-4 w-4 text-destructive" />
<span className="sr-only">Delete API key</span>
</Button>

<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Confirm API Key Deletion</DialogTitle>
<DialogDescription>
This will permanently delete this API key. To confirm, please type "delete" below.
</DialogDescription>
</DialogHeader>
<Input
value={confirmText}
onChange={(e) => setConfirmText(e.target.value)}
placeholder="Type 'delete' to confirm"
/>
<DialogFooter>
<Button
variant="ghost"
onClick={() => setDialogOpen(false)}
>
Cancel
</Button>
<Button
variant="destructive"
onClick={handleDelete}
disabled={confirmText.toLowerCase() !== 'delete'}
>
Delete API Key
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
},
},
] as ColumnDef<ApiKey>[];
}

0 comments on commit 31f8bb3

Please sign in to comment.