import { VALID_BRANCH_REGEX } from "@dokploy/server/utils/git-branch-validation"; import { standardSchemaResolver as zodResolver } from "@hookform/resolvers/standard-schema"; import { CheckIcon, ChevronsUpDown, HelpCircle, Plus, X } from "lucide-react"; import Link from "next/link"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; import { GiteaIcon } from "@/components/icons/data-tools-icons"; import { AlertBlock } from "@/components/shared/alert-block"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, } from "@/components/ui/command"; 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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; import { api } from "@/utils/api"; import type { Repository } from "@/utils/gitea-utils"; const GiteaProviderSchema = z.object({ composePath: z.string().min(1), repository: z .object({ repo: z.string().min(1, "Repo is required"), owner: z.string().min(1, "Owner is required"), }) .required(), branch: z .string() .min(1, "Branch is required") .regex(VALID_BRANCH_REGEX, "Invalid branch name"), giteaId: z.string().min(1, "Gitea Provider is required"), watchPaths: z.array(z.string()).optional(), enableSubmodules: z.boolean().default(false), }); type GiteaProvider = z.infer; interface Props { composeId: string; } export const SaveGiteaProviderCompose = ({ composeId }: Props) => { const { data: giteaProviders } = api.gitea.giteaProviders.useQuery(); const { data, refetch } = api.compose.one.useQuery({ composeId }); const { mutateAsync, isPending: isSavingGiteaProvider } = api.compose.update.useMutation(); const form = useForm({ defaultValues: { composePath: "./docker-compose.yml", repository: { owner: "", repo: "", }, giteaId: "", branch: "", watchPaths: [], enableSubmodules: false, }, resolver: zodResolver(GiteaProviderSchema), }); const repository = form.watch("repository"); const giteaId = form.watch("giteaId"); const { data: giteaUrl } = api.gitea.getGiteaUrl.useQuery( { giteaId }, { enabled: !!giteaId, }, ); const { data: repositories, isLoading: isLoadingRepositories, error, } = api.gitea.getGiteaRepositories.useQuery( { giteaId, }, { enabled: !!giteaId, }, ); const { data: branches, fetchStatus, status, } = api.gitea.getGiteaBranches.useQuery( { owner: repository?.owner, repositoryName: repository?.repo, giteaId: giteaId, }, { enabled: !!repository?.owner && !!repository?.repo && !!giteaId, }, ); useEffect(() => { if (data) { form.reset({ branch: data.giteaBranch || "", repository: { repo: data.giteaRepository || "", owner: data.giteaOwner || "", }, composePath: data.composePath || "./docker-compose.yml", giteaId: data.giteaId || "", watchPaths: data.watchPaths || [], enableSubmodules: data.enableSubmodules ?? false, }); } }, [form.reset, data?.composeId, form]); const onSubmit = async (data: GiteaProvider) => { await mutateAsync({ giteaBranch: data.branch, giteaRepository: data.repository.repo, giteaOwner: data.repository.owner, composePath: data.composePath, giteaId: data.giteaId, composeId, sourceType: "gitea", composeStatus: "idle", watchPaths: data.watchPaths, enableSubmodules: data.enableSubmodules, } as any) .then(async () => { toast.success("Service Provider Saved"); await refetch(); }) .catch(() => { toast.error("Error saving the Gitea provider"); }); }; return (
{error && {error?.message}}
( Gitea Account )} /> (
Repository {field.value.owner && field.value.repo && ( View Repository )}
{!giteaId ? ( Select a Gitea account first ) : isLoadingRepositories ? ( Loading Repositories.... ) : null} No repositories found. {repositories?.map((repo) => ( { form.setValue("repository", { owner: repo.owner.username, repo: repo.name, }); form.setValue("branch", ""); }} > {repo.name} {repo.owner.username} ))} {form.formState.errors.repository && (

Repository is required

)}
)} /> ( Branch No branches found. {branches?.map((branch) => ( form.setValue("branch", branch.name) } > {branch.name} ))} {form.formState.errors.branch && (

Branch is required

)}
)} /> ( Compose Path )} /> (
Watch Paths

Add paths to watch for changes. When files in these paths change, a new deployment will be triggered.

{field.value?.map((path, index) => ( {path} ))}
{ if (e.key === "Enter") { e.preventDefault(); const input = e.currentTarget; const value = input.value.trim(); if (value) { const newPaths = [...(field.value || []), value]; form.setValue("watchPaths", newPaths); input.value = ""; } } }} />
)} /> ( Enable Submodules )} />
); };