mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-20 13:25:32 +02:00
Merge pull request #2297 from Dokploy/feat/add-custom-service-field-domains-compose
feat(dashboard): add manual input for service name in domains for docker compose
This commit is contained in:
@@ -1,3 +1,10 @@
|
|||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { DatabaseZap, Dices, RefreshCw } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import z from "zod";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@@ -34,14 +41,6 @@ import {
|
|||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import { DatabaseZap, Dices, RefreshCw } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
|
||||||
import z from "zod";
|
|
||||||
|
|
||||||
export type CacheType = "fetch" | "cache";
|
export type CacheType = "fetch" | "cache";
|
||||||
|
|
||||||
@@ -123,6 +122,7 @@ interface Props {
|
|||||||
export const AddDomain = ({ id, type, domainId = "", children }: Props) => {
|
export const AddDomain = ({ id, type, domainId = "", children }: Props) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [cacheType, setCacheType] = useState<CacheType>("cache");
|
const [cacheType, setCacheType] = useState<CacheType>("cache");
|
||||||
|
const [isManualInput, setIsManualInput] = useState(false);
|
||||||
|
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const { data, refetch } = api.domain.one.useQuery(
|
const { data, refetch } = api.domain.one.useQuery(
|
||||||
@@ -325,46 +325,126 @@ export const AddDomain = ({ id, type, domainId = "", children }: Props) => {
|
|||||||
<FormItem className="w-full">
|
<FormItem className="w-full">
|
||||||
<FormLabel>Service Name</FormLabel>
|
<FormLabel>Service Name</FormLabel>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Select
|
{isManualInput ? (
|
||||||
onValueChange={field.onChange}
|
|
||||||
defaultValue={field.value || ""}
|
|
||||||
>
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<SelectTrigger>
|
<Input
|
||||||
<SelectValue placeholder="Select a service name" />
|
placeholder="Enter service name manually"
|
||||||
</SelectTrigger>
|
{...field}
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
) : (
|
||||||
|
<Select
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
defaultValue={field.value || ""}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a service name" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{services?.map((service, index) => (
|
{services?.map((service, index) => (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
value={service}
|
value={service}
|
||||||
key={`${service}-${index}`}
|
key={`${service}-${index}`}
|
||||||
>
|
>
|
||||||
{service}
|
{service}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
<SelectItem value="none" disabled>
|
||||||
|
Empty
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
</SelectContent>
|
||||||
<SelectItem value="none" disabled>
|
</Select>
|
||||||
Empty
|
)}
|
||||||
</SelectItem>
|
{!isManualInput && (
|
||||||
</SelectContent>
|
<>
|
||||||
</Select>
|
<TooltipProvider delayDuration={0}>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
type="button"
|
||||||
|
isLoading={isLoadingServices}
|
||||||
|
onClick={() => {
|
||||||
|
if (cacheType === "fetch") {
|
||||||
|
refetchServices();
|
||||||
|
} else {
|
||||||
|
setCacheType("fetch");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RefreshCw className="size-4 text-muted-foreground" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent
|
||||||
|
side="left"
|
||||||
|
sideOffset={5}
|
||||||
|
className="max-w-[10rem]"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Fetch: Will clone the repository and
|
||||||
|
load the services
|
||||||
|
</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
<TooltipProvider delayDuration={0}>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
type="button"
|
||||||
|
isLoading={isLoadingServices}
|
||||||
|
onClick={() => {
|
||||||
|
if (cacheType === "cache") {
|
||||||
|
refetchServices();
|
||||||
|
} else {
|
||||||
|
setCacheType("cache");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DatabaseZap className="size-4 text-muted-foreground" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent
|
||||||
|
side="left"
|
||||||
|
sideOffset={5}
|
||||||
|
className="max-w-[10rem]"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Cache: If you previously deployed this
|
||||||
|
compose, it will read the services
|
||||||
|
from the last deployment/fetch from
|
||||||
|
the repository
|
||||||
|
</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<TooltipProvider delayDuration={0}>
|
<TooltipProvider delayDuration={0}>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
type="button"
|
type="button"
|
||||||
isLoading={isLoadingServices}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (cacheType === "fetch") {
|
setIsManualInput(!isManualInput);
|
||||||
refetchServices();
|
if (!isManualInput) {
|
||||||
} else {
|
field.onChange("");
|
||||||
setCacheType("fetch");
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<RefreshCw className="size-4 text-muted-foreground" />
|
{isManualInput ? (
|
||||||
|
<RefreshCw className="size-4 text-muted-foreground" />
|
||||||
|
) : (
|
||||||
|
<span className="text-xs text-muted-foreground">
|
||||||
|
Manual
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent
|
<TooltipContent
|
||||||
@@ -373,40 +453,9 @@ export const AddDomain = ({ id, type, domainId = "", children }: Props) => {
|
|||||||
className="max-w-[10rem]"
|
className="max-w-[10rem]"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Fetch: Will clone the repository and load
|
{isManualInput
|
||||||
the services
|
? "Switch to service selection"
|
||||||
</p>
|
: "Enter service name manually"}
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
<TooltipProvider delayDuration={0}>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
type="button"
|
|
||||||
isLoading={isLoadingServices}
|
|
||||||
onClick={() => {
|
|
||||||
if (cacheType === "cache") {
|
|
||||||
refetchServices();
|
|
||||||
} else {
|
|
||||||
setCacheType("cache");
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<DatabaseZap className="size-4 text-muted-foreground" />
|
|
||||||
</Button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent
|
|
||||||
side="left"
|
|
||||||
sideOffset={5}
|
|
||||||
className="max-w-[10rem]"
|
|
||||||
>
|
|
||||||
<p>
|
|
||||||
Cache: If you previously deployed this
|
|
||||||
compose, it will read the services from
|
|
||||||
the last deployment/fetch from the
|
|
||||||
repository
|
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
@@ -27,7 +27,8 @@
|
|||||||
"noUnsafeOptionalChaining": "off",
|
"noUnsafeOptionalChaining": "off",
|
||||||
"noUnusedImports": "error",
|
"noUnusedImports": "error",
|
||||||
"noUnusedFunctionParameters": "error",
|
"noUnusedFunctionParameters": "error",
|
||||||
"noUnusedVariables": "error"
|
"noUnusedVariables": "error",
|
||||||
|
"useHookAtTopLevel": "off"
|
||||||
},
|
},
|
||||||
"style": {
|
"style": {
|
||||||
"noNonNullAssertion": "off",
|
"noNonNullAssertion": "off",
|
||||||
|
|||||||
Reference in New Issue
Block a user