Skip to content

Commit b5d1990

Browse files
authored
Merge pull request #1532 from Dokploy/canary
🚀 Release v0.20.7
2 parents bfb6baf + 6e28196 commit b5d1990

File tree

10 files changed

+137
-123
lines changed

10 files changed

+137
-123
lines changed

apps/dokploy/components/dashboard/application/advanced/cluster/show-cluster-settings.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ interface Props {
4040
}
4141

4242
const AddRedirectchema = z.object({
43-
replicas: z.number(),
43+
replicas: z.number().min(1, "Replicas must be at least 1"),
4444
registryId: z.string(),
4545
});
4646

@@ -130,9 +130,11 @@ export const ShowClusterSettings = ({ applicationId }: Props) => {
130130
placeholder="1"
131131
{...field}
132132
onChange={(e) => {
133-
field.onChange(Number(e.target.value));
133+
const value = e.target.value;
134+
field.onChange(value === "" ? 0 : Number(value));
134135
}}
135136
type="number"
137+
value={field.value || ""}
136138
/>
137139
</FormControl>
138140

apps/dokploy/components/dashboard/settings/cluster/nodes/add-node.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ export const AddNode = ({ serverId }: Props) => {
5656
<TabsTrigger value="worker">Worker</TabsTrigger>
5757
<TabsTrigger value="manager">Manager</TabsTrigger>
5858
</TabsList>
59-
<TabsContent value="worker" className="pt-4">
59+
<TabsContent value="worker" className="pt-4 overflow-hidden">
6060
<AddWorker serverId={serverId} />
6161
</TabsContent>
62-
<TabsContent value="manager" className="pt-4">
62+
<TabsContent value="manager" className="pt-4 overflow-hidden">
6363
<AddManager serverId={serverId} />
6464
</TabsContent>
6565
</Tabs>
Lines changed: 58 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { AlertBlock } from "@/components/shared/alert-block";
12
import { CardContent } from "@/components/ui/card";
23
import {
34
DialogDescription,
@@ -6,64 +7,74 @@ import {
67
} from "@/components/ui/dialog";
78
import { api } from "@/utils/api";
89
import copy from "copy-to-clipboard";
9-
import { CopyIcon } from "lucide-react";
10+
import { CopyIcon, Loader2 } from "lucide-react";
1011
import { toast } from "sonner";
1112

1213
interface Props {
1314
serverId?: string;
1415
}
1516

1617
export const AddManager = ({ serverId }: Props) => {
17-
const { data } = api.cluster.addManager.useQuery({ serverId });
18+
const { data, isLoading, error, isError } = api.cluster.addManager.useQuery({
19+
serverId,
20+
});
1821

1922
return (
2023
<>
21-
<div>
22-
<CardContent className="sm:max-w-4xl max-h-screen overflow-y-auto flex flex-col gap-4 px-0">
23-
<DialogHeader>
24-
<DialogTitle>Add a new manager</DialogTitle>
25-
<DialogDescription>Add a new manager</DialogDescription>
26-
</DialogHeader>
27-
<div className="flex flex-col gap-2.5 text-sm">
28-
<span>1. Go to your new server and run the following command</span>
29-
<span className="bg-muted rounded-lg p-2 flex justify-between">
30-
curl https://get.docker.com | sh -s -- --version {data?.version}
31-
<button
32-
type="button"
33-
className="self-center"
34-
onClick={() => {
35-
copy(
36-
`curl https://get.docker.com | sh -s -- --version ${data?.version}`,
37-
);
38-
toast.success("Copied to clipboard");
39-
}}
40-
>
41-
<CopyIcon className="h-4 w-4 cursor-pointer" />
42-
</button>
43-
</span>
44-
</div>
24+
<CardContent className="sm:max-w-4xl flex flex-col gap-4 px-0">
25+
<DialogHeader>
26+
<DialogTitle>Add a new manager</DialogTitle>
27+
<DialogDescription>Add a new manager</DialogDescription>
28+
</DialogHeader>
29+
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
30+
{isLoading ? (
31+
<Loader2 className="w-full animate-spin text-muted-foreground" />
32+
) : (
33+
<>
34+
<div className="flex flex-col gap-2.5 text-sm">
35+
<span>
36+
1. Go to your new server and run the following command
37+
</span>
38+
<span className="bg-muted rounded-lg p-2 flex justify-between">
39+
curl https://get.docker.com | sh -s -- --version {data?.version}
40+
<button
41+
type="button"
42+
className="self-center"
43+
onClick={() => {
44+
copy(
45+
`curl https://get.docker.com | sh -s -- --version ${data?.version}`,
46+
);
47+
toast.success("Copied to clipboard");
48+
}}
49+
>
50+
<CopyIcon className="h-4 w-4 cursor-pointer" />
51+
</button>
52+
</span>
53+
</div>
4554

46-
<div className="flex flex-col gap-2.5 text-sm">
47-
<span>
48-
2. Run the following command to add the node(manager) to your
49-
cluster
50-
</span>
51-
<span className="bg-muted rounded-lg p-2 flex">
52-
{data?.command}
53-
<button
54-
type="button"
55-
className="self-start"
56-
onClick={() => {
57-
copy(data?.command || "");
58-
toast.success("Copied to clipboard");
59-
}}
60-
>
61-
<CopyIcon className="h-4 w-4 cursor-pointer" />
62-
</button>
63-
</span>
64-
</div>
65-
</CardContent>
66-
</div>
55+
<div className="flex flex-col gap-2.5 text-sm">
56+
<span>
57+
2. Run the following command to add the node(manager) to your
58+
cluster
59+
</span>
60+
61+
<span className="bg-muted rounded-lg p-2 flex">
62+
{data?.command}
63+
<button
64+
type="button"
65+
className="self-start"
66+
onClick={() => {
67+
copy(data?.command || "");
68+
toast.success("Copied to clipboard");
69+
}}
70+
>
71+
<CopyIcon className="h-4 w-4 cursor-pointer" />
72+
</button>
73+
</span>
74+
</div>
75+
</>
76+
)}
77+
</CardContent>
6778
</>
6879
);
6980
};

apps/dokploy/components/dashboard/settings/cluster/nodes/show-nodes-modal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const ShowNodesModal = ({ serverId }: Props) => {
1717
className="w-full cursor-pointer "
1818
onSelect={(e) => e.preventDefault()}
1919
>
20-
Show Nodes
20+
Show Swarm Nodes
2121
</DropdownMenuItem>
2222
</DialogTrigger>
2323
<DialogContent className="sm:max-w-5xl overflow-y-auto max-h-screen ">
Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { AlertBlock } from "@/components/shared/alert-block";
12
import { CardContent } from "@/components/ui/card";
23
import {
34
DialogDescription,
@@ -6,62 +7,70 @@ import {
67
} from "@/components/ui/dialog";
78
import { api } from "@/utils/api";
89
import copy from "copy-to-clipboard";
9-
import { CopyIcon } from "lucide-react";
10+
import { CopyIcon, Loader2 } from "lucide-react";
1011
import { toast } from "sonner";
1112

1213
interface Props {
1314
serverId?: string;
1415
}
1516

1617
export const AddWorker = ({ serverId }: Props) => {
17-
const { data } = api.cluster.addWorker.useQuery({ serverId });
18+
const { data, isLoading, error, isError } = api.cluster.addWorker.useQuery({
19+
serverId,
20+
});
1821

1922
return (
20-
<div>
21-
<CardContent className="sm:max-w-4xl max-h-screen overflow-y-auto flex flex-col gap-4 px-0">
22-
<DialogHeader>
23-
<DialogTitle>Add a new worker</DialogTitle>
24-
<DialogDescription>Add a new worker</DialogDescription>
25-
</DialogHeader>
26-
<div className="flex flex-col gap-2.5 text-sm">
27-
<span>1. Go to your new server and run the following command</span>
28-
<span className="bg-muted rounded-lg p-2 flex justify-between">
29-
curl https://get.docker.com | sh -s -- --version {data?.version}
30-
<button
31-
type="button"
32-
className="self-center"
33-
onClick={() => {
34-
copy(
35-
`curl https://get.docker.com | sh -s -- --version ${data?.version}`,
36-
);
37-
toast.success("Copied to clipboard");
38-
}}
39-
>
40-
<CopyIcon className="h-4 w-4 cursor-pointer" />
41-
</button>
42-
</span>
43-
</div>
23+
<CardContent className="sm:max-w-4xl flex flex-col gap-4 px-0">
24+
<DialogHeader>
25+
<DialogTitle>Add a new worker</DialogTitle>
26+
<DialogDescription>Add a new worker</DialogDescription>
27+
</DialogHeader>
28+
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
29+
{isLoading ? (
30+
<Loader2 className="w-full animate-spin text-muted-foreground" />
31+
) : (
32+
<>
33+
<div className="flex flex-col gap-2.5 text-sm">
34+
<span>1. Go to your new server and run the following command</span>
35+
<span className="bg-muted rounded-lg p-2 flex justify-between">
36+
curl https://get.docker.com | sh -s -- --version {data?.version}
37+
<button
38+
type="button"
39+
className="self-center"
40+
onClick={() => {
41+
copy(
42+
`curl https://get.docker.com | sh -s -- --version ${data?.version}`,
43+
);
44+
toast.success("Copied to clipboard");
45+
}}
46+
>
47+
<CopyIcon className="h-4 w-4 cursor-pointer" />
48+
</button>
49+
</span>
50+
</div>
4451

45-
<div className="flex flex-col gap-2.5 text-sm">
46-
<span>
47-
2. Run the following command to add the node(worker) to your cluster
48-
</span>
52+
<div className="flex flex-col gap-2.5 text-sm">
53+
<span>
54+
2. Run the following command to add the node(worker) to your
55+
cluster
56+
</span>
4957

50-
<span className="bg-muted rounded-lg p-2 flex">
51-
{data?.command}
52-
<button
53-
type="button"
54-
className="self-start"
55-
onClick={() => {
56-
copy(data?.command || "");
57-
toast.success("Copied to clipboard");
58-
}}
59-
>
60-
<CopyIcon className="h-4 w-4 cursor-pointer" />
61-
</button>
62-
</span>
63-
</div>
64-
</CardContent>
65-
</div>
58+
<span className="bg-muted rounded-lg p-2 flex">
59+
{data?.command}
60+
<button
61+
type="button"
62+
className="self-start"
63+
onClick={() => {
64+
copy(data?.command || "");
65+
toast.success("Copied to clipboard");
66+
}}
67+
>
68+
<CopyIcon className="h-4 w-4 cursor-pointer" />
69+
</button>
70+
</span>
71+
</div>
72+
</>
73+
)}
74+
</CardContent>
6675
);
6776
};

apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,13 +663,16 @@ export const HandleNotifications = ({ notificationId }: Props) => {
663663
{...field}
664664
onChange={(e) => {
665665
const value = e.target.value;
666-
if (value) {
666+
if (value === "") {
667+
field.onChange(undefined);
668+
} else {
667669
const port = Number.parseInt(value);
668670
if (port > 0 && port < 65536) {
669671
field.onChange(port);
670672
}
671673
}
672674
}}
675+
value={field.value || ""}
673676
type="number"
674677
/>
675678
</FormControl>

apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,11 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
159159
<Input
160160
type="number"
161161
{...field}
162-
onChange={(e) =>
163-
field.onChange(Number(e.target.value))
164-
}
162+
onChange={(e) => {
163+
const value = e.target.value;
164+
field.onChange(value === "" ? undefined : Number(value));
165+
}}
166+
value={field.value || ""}
165167
className="w-full dark:bg-black"
166168
placeholder="e.g. 8080"
167169
/>
@@ -185,9 +187,11 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
185187
<Input
186188
type="number"
187189
{...field}
188-
onChange={(e) =>
189-
field.onChange(Number(e.target.value))
190-
}
190+
onChange={(e) => {
191+
const value = e.target.value;
192+
field.onChange(value === "" ? undefined : Number(value));
193+
}}
194+
value={field.value || ""}
191195
className="w-full dark:bg-black"
192196
placeholder="e.g. 80"
193197
/>

apps/dokploy/components/ui/input.tsx

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const NumberInput = React.forwardRef<HTMLInputElement, InputProps>(
3939
className={cn("text-left", className)}
4040
ref={ref}
4141
{...props}
42-
value={props.value === undefined || props.value === "" ? "" : String(props.value)}
42+
value={props.value === undefined ? undefined : String(props.value)}
4343
onChange={(e) => {
4444
const value = e.target.value;
4545
if (value === "") {
@@ -60,21 +60,6 @@ const NumberInput = React.forwardRef<HTMLInputElement, InputProps>(
6060
}
6161
}
6262
}}
63-
onBlur={(e) => {
64-
// If input is empty, make 0 when focus is lost
65-
if (e.target.value === "") {
66-
const syntheticEvent = {
67-
...e,
68-
target: {
69-
...e.target,
70-
value: "0",
71-
},
72-
};
73-
props.onChange?.(
74-
syntheticEvent as unknown as React.ChangeEvent<HTMLInputElement>,
75-
);
76-
}
77-
}}
7863
/>
7964
);
8065
},

apps/dokploy/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dokploy",
3-
"version": "v0.20.6",
3+
"version": "v0.20.7",
44
"private": true,
55
"license": "Apache-2.0",
66
"type": "module",

packages/server/src/setup/server-setup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ const installUtilities = () => `
361361
alpine)
362362
sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories
363363
apk update >/dev/null
364-
apk add curl wget git jq openssl >/dev/null
364+
apk add curl wget git jq openssl sudo unzip tar >/dev/null
365365
;;
366366
ubuntu | debian | raspbian)
367367
DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null

0 commit comments

Comments
 (0)