import { DrawerLogs } from "@/components/shared/drawer-logs"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, } from "@/components/ui/command"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { ScrollArea } from "@/components/ui/scroll-area"; import { cn } from "@/lib/utils"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; import copy from "copy-to-clipboard"; import { debounce } from "lodash"; import { CheckIcon, ChevronsUpDown, Copy, RotateCcw } from "lucide-react"; import { useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; import type { ServiceType } from "../../application/advanced/show-resources"; import { type LogLine, parseLogs } from "../../docker/logs/utils"; interface Props { databaseId: string; databaseType: Exclude; serverId: string | null; } const RestoreBackupSchema = z.object({ destinationId: z .string({ required_error: "Please select a destination", }) .min(1, { message: "Destination is required", }), backupFile: z .string({ required_error: "Please select a backup file", }) .min(1, { message: "Backup file is required", }), databaseName: z .string({ required_error: "Please enter a database name", }) .min(1, { message: "Database name is required", }), }); type RestoreBackup = z.infer; export const RestoreBackup = ({ databaseId, databaseType, serverId, }: Props) => { const [isOpen, setIsOpen] = useState(false); const [search, setSearch] = useState(""); const { data: destinations = [] } = api.destination.all.useQuery(); const form = useForm({ defaultValues: { destinationId: "", backupFile: "", databaseName: "", }, resolver: zodResolver(RestoreBackupSchema), }); const destionationId = form.watch("destinationId"); const debouncedSetSearch = debounce((value: string) => { setSearch(value); }, 300); const { data: files = [], isLoading } = api.backup.listBackupFiles.useQuery( { destinationId: destionationId, search, serverId: serverId ?? "", }, { enabled: isOpen && !!destionationId, }, ); const [isDrawerOpen, setIsDrawerOpen] = useState(false); const [filteredLogs, setFilteredLogs] = useState([]); const [isDeploying, setIsDeploying] = useState(false); // const { mutateAsync: restore, isLoading: isRestoring } = // api.backup.restoreBackup.useMutation(); api.backup.restoreBackupWithLogs.useSubscription( { databaseId, databaseType, databaseName: form.watch("databaseName"), backupFile: form.watch("backupFile"), destinationId: form.watch("destinationId"), }, { enabled: isDeploying, onData(log) { if (!isDrawerOpen) { setIsDrawerOpen(true); } if (log === "Restore completed successfully!") { setIsDeploying(false); } const parsedLogs = parseLogs(log); setFilteredLogs((prev) => [...prev, ...parsedLogs]); }, onError(error) { console.error("Restore logs error:", error); setIsDeploying(false); }, }, ); const onSubmit = async (_data: RestoreBackup) => { setIsDeploying(true); }; return ( Restore Backup Select a destination and search for backup files
( Destination No destinations found. {destinations.map((destination) => ( { form.setValue( "destinationId", destination.destinationId, ); }} > {destination.name} ))} )} /> ( Search Backup Files {field.value && ( {field.value} { e.stopPropagation(); e.preventDefault(); copy(field.value); toast.success("Backup file copied to clipboard"); }} /> )} {isLoading ? (
Loading backup files...
) : files.length === 0 && search ? (
No backup files found for "{search}"
) : files.length === 0 ? (
No backup files available
) : ( {files.map((file) => ( { form.setValue("backupFile", file); }} >
{file}
))}
)}
)} /> ( Database Name )} /> { setIsDrawerOpen(false); setFilteredLogs([]); setIsDeploying(false); // refetch(); }} filteredLogs={filteredLogs} />
); };