diff --git a/apps/dokploy/components/dashboard/application/advanced/cluster/show-cluster-settings.tsx b/apps/dokploy/components/dashboard/application/advanced/cluster/show-cluster-settings.tsx index 1eadf8ba..57f851c9 100644 --- a/apps/dokploy/components/dashboard/application/advanced/cluster/show-cluster-settings.tsx +++ b/apps/dokploy/components/dashboard/application/advanced/cluster/show-cluster-settings.tsx @@ -40,7 +40,7 @@ interface Props { } const AddRedirectchema = z.object({ - replicas: z.number(), + replicas: z.number().min(1, "Replicas must be at least 1"), registryId: z.string(), }); @@ -130,9 +130,11 @@ export const ShowClusterSettings = ({ applicationId }: Props) => { placeholder="1" {...field} onChange={(e) => { - field.onChange(Number(e.target.value)); + const value = e.target.value; + field.onChange(value === "" ? 0 : Number(value)); }} type="number" + value={field.value || ""} /> diff --git a/apps/dokploy/components/dashboard/settings/cluster/nodes/add-node.tsx b/apps/dokploy/components/dashboard/settings/cluster/nodes/add-node.tsx index eaa9851f..a59681ba 100644 --- a/apps/dokploy/components/dashboard/settings/cluster/nodes/add-node.tsx +++ b/apps/dokploy/components/dashboard/settings/cluster/nodes/add-node.tsx @@ -56,10 +56,10 @@ export const AddNode = ({ serverId }: Props) => { Worker Manager - + - + diff --git a/apps/dokploy/components/dashboard/settings/cluster/nodes/manager/add-manager.tsx b/apps/dokploy/components/dashboard/settings/cluster/nodes/manager/add-manager.tsx index 055c3f1c..bb2064d4 100644 --- a/apps/dokploy/components/dashboard/settings/cluster/nodes/manager/add-manager.tsx +++ b/apps/dokploy/components/dashboard/settings/cluster/nodes/manager/add-manager.tsx @@ -1,3 +1,4 @@ +import { AlertBlock } from "@/components/shared/alert-block"; import { CardContent } from "@/components/ui/card"; import { DialogDescription, @@ -6,7 +7,7 @@ import { } from "@/components/ui/dialog"; import { api } from "@/utils/api"; import copy from "copy-to-clipboard"; -import { CopyIcon } from "lucide-react"; +import { CopyIcon, Loader2 } from "lucide-react"; import { toast } from "sonner"; interface Props { @@ -14,56 +15,66 @@ interface Props { } export const AddManager = ({ serverId }: Props) => { - const { data } = api.cluster.addManager.useQuery({ serverId }); + const { data, isLoading, error, isError } = api.cluster.addManager.useQuery({ + serverId, + }); return ( <> -
- - - Add a new manager - Add a new manager - -
- 1. Go to your new server and run the following command - - curl https://get.docker.com | sh -s -- --version {data?.version} - - -
+ + + Add a new manager + Add a new manager + + {isError && {error?.message}} + {isLoading ? ( + + ) : ( + <> +
+ + 1. Go to your new server and run the following command + + + curl https://get.docker.com | sh -s -- --version {data?.version} + + +
-
- - 2. Run the following command to add the node(manager) to your - cluster - - - {data?.command} - - -
-
-
+
+ + 2. Run the following command to add the node(manager) to your + cluster + + + + {data?.command} + + +
+ + )} + ); }; diff --git a/apps/dokploy/components/dashboard/settings/cluster/nodes/show-nodes-modal.tsx b/apps/dokploy/components/dashboard/settings/cluster/nodes/show-nodes-modal.tsx index 32339e66..82e6e1f9 100644 --- a/apps/dokploy/components/dashboard/settings/cluster/nodes/show-nodes-modal.tsx +++ b/apps/dokploy/components/dashboard/settings/cluster/nodes/show-nodes-modal.tsx @@ -17,7 +17,7 @@ export const ShowNodesModal = ({ serverId }: Props) => { className="w-full cursor-pointer " onSelect={(e) => e.preventDefault()} > - Show Nodes + Show Swarm Nodes diff --git a/apps/dokploy/components/dashboard/settings/cluster/nodes/workers/add-worker.tsx b/apps/dokploy/components/dashboard/settings/cluster/nodes/workers/add-worker.tsx index 05f9838e..2623081b 100644 --- a/apps/dokploy/components/dashboard/settings/cluster/nodes/workers/add-worker.tsx +++ b/apps/dokploy/components/dashboard/settings/cluster/nodes/workers/add-worker.tsx @@ -1,3 +1,4 @@ +import { AlertBlock } from "@/components/shared/alert-block"; import { CardContent } from "@/components/ui/card"; import { DialogDescription, @@ -6,7 +7,7 @@ import { } from "@/components/ui/dialog"; import { api } from "@/utils/api"; import copy from "copy-to-clipboard"; -import { CopyIcon } from "lucide-react"; +import { CopyIcon, Loader2 } from "lucide-react"; import { toast } from "sonner"; interface Props { @@ -14,54 +15,62 @@ interface Props { } export const AddWorker = ({ serverId }: Props) => { - const { data } = api.cluster.addWorker.useQuery({ serverId }); + const { data, isLoading, error, isError } = api.cluster.addWorker.useQuery({ + serverId, + }); return ( -
- - - Add a new worker - Add a new worker - -
- 1. Go to your new server and run the following command - - curl https://get.docker.com | sh -s -- --version {data?.version} - - -
+ + + Add a new worker + Add a new worker + + {isError && {error?.message}} + {isLoading ? ( + + ) : ( + <> +
+ 1. Go to your new server and run the following command + + curl https://get.docker.com | sh -s -- --version {data?.version} + + +
-
- - 2. Run the following command to add the node(worker) to your cluster - +
+ + 2. Run the following command to add the node(worker) to your + cluster + - - {data?.command} - - -
- -
+ + {data?.command} + + +
+ + )} + ); }; diff --git a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx index 7a3e286e..e0476529 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx @@ -663,13 +663,16 @@ export const HandleNotifications = ({ notificationId }: Props) => { {...field} onChange={(e) => { const value = e.target.value; - if (value) { + if (value === "") { + field.onChange(undefined); + } else { const port = Number.parseInt(value); if (port > 0 && port < 65536) { field.onChange(port); } } }} + value={field.value || ""} type="number" /> diff --git a/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx b/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx index 92ef9f12..d20b7c91 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx @@ -159,9 +159,11 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => { - field.onChange(Number(e.target.value)) - } + onChange={(e) => { + const value = e.target.value; + field.onChange(value === "" ? undefined : Number(value)); + }} + value={field.value || ""} className="w-full dark:bg-black" placeholder="e.g. 8080" /> @@ -185,9 +187,11 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => { - field.onChange(Number(e.target.value)) - } + onChange={(e) => { + const value = e.target.value; + field.onChange(value === "" ? undefined : Number(value)); + }} + value={field.value || ""} className="w-full dark:bg-black" placeholder="e.g. 80" /> diff --git a/apps/dokploy/components/ui/input.tsx b/apps/dokploy/components/ui/input.tsx index 7339d21a..18b713af 100644 --- a/apps/dokploy/components/ui/input.tsx +++ b/apps/dokploy/components/ui/input.tsx @@ -39,7 +39,7 @@ const NumberInput = React.forwardRef( className={cn("text-left", className)} ref={ref} {...props} - value={props.value === undefined || props.value === "" ? "" : String(props.value)} + value={props.value === undefined ? undefined : String(props.value)} onChange={(e) => { const value = e.target.value; if (value === "") { @@ -60,21 +60,6 @@ const NumberInput = React.forwardRef( } } }} - onBlur={(e) => { - // If input is empty, make 0 when focus is lost - if (e.target.value === "") { - const syntheticEvent = { - ...e, - target: { - ...e.target, - value: "0", - }, - }; - props.onChange?.( - syntheticEvent as unknown as React.ChangeEvent, - ); - } - }} /> ); }, diff --git a/apps/dokploy/package.json b/apps/dokploy/package.json index cf46d3ac..1d7ad131 100644 --- a/apps/dokploy/package.json +++ b/apps/dokploy/package.json @@ -1,6 +1,6 @@ { "name": "dokploy", - "version": "v0.20.6", + "version": "v0.20.7", "private": true, "license": "Apache-2.0", "type": "module", diff --git a/packages/server/src/setup/server-setup.ts b/packages/server/src/setup/server-setup.ts index 677ce74a..aaacdb33 100644 --- a/packages/server/src/setup/server-setup.ts +++ b/packages/server/src/setup/server-setup.ts @@ -361,7 +361,7 @@ const installUtilities = () => ` alpine) sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories apk update >/dev/null - apk add curl wget git jq openssl >/dev/null + apk add curl wget git jq openssl sudo unzip tar >/dev/null ;; ubuntu | debian | raspbian) DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null