Skip to content

Commit 0db9cb4

Browse files
authored
Merge pull request #1300 from Dokploy/canary
🚀 Release v0.18.3
2 parents 52e34b6 + 030c8a3 commit 0db9cb4

File tree

86 files changed

+10314
-514
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+10314
-514
lines changed
4.07 KB
Loading

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ For detailed documentation, visit [docs.dokploy.com](https://docs.dokploy.com).
9393
<a href="https://cloudblast.io/?ref=dokploy "><img src="https://cloudblast.io/img/logo-icon.193cf13e.svg" width="250px" alt="Cloudblast.io"/></a>
9494
<a href="https://startupfa.me/?ref=dokploy "><img src=".github/sponsors/startupfame.png" width="65px" alt="Startupfame"/></a>
9595
<a href="https://itsdb-center.com?ref=dokploy "><img src=".github/sponsors/its.png" width="65px" alt="Itsdb-center"/></a>
96+
<a href="https://openalternative.co/?ref=dokploy "><img src=".github/sponsors/openalternative.png" width="65px" alt="Openalternative"/></a>
9697
</div>
9798

9899
### Community Backers 🤝

apps/dokploy/components/dashboard/compose/general/compose-file-editor.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { useForm } from "react-hook-form";
1414
import { toast } from "sonner";
1515
import { z } from "zod";
1616
import { validateAndFormatYAML } from "../../application/advanced/traefik/update-traefik-config";
17-
import { RandomizeCompose } from "./randomize-compose";
17+
import { ShowUtilities } from "./show-utilities";
1818

1919
interface Props {
2020
composeId: string;
@@ -125,7 +125,7 @@ services:
125125
</Form>
126126
<div className="flex justify-between flex-col lg:flex-row gap-2">
127127
<div className="w-full flex flex-col lg:flex-row gap-4 items-end">
128-
<RandomizeCompose composeId={composeId} />
128+
<ShowUtilities composeId={composeId} />
129129
</div>
130130
<Button
131131
type="submit"
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import { AlertBlock } from "@/components/shared/alert-block";
2+
import { CodeEditor } from "@/components/shared/code-editor";
3+
import { Button } from "@/components/ui/button";
4+
import {
5+
DialogDescription,
6+
DialogHeader,
7+
DialogTitle,
8+
} from "@/components/ui/dialog";
9+
import {
10+
Form,
11+
FormControl,
12+
FormDescription,
13+
FormField,
14+
FormItem,
15+
FormLabel,
16+
} from "@/components/ui/form";
17+
import { Label } from "@/components/ui/label";
18+
import { Switch } from "@/components/ui/switch";
19+
import { api } from "@/utils/api";
20+
import { zodResolver } from "@hookform/resolvers/zod";
21+
import { AlertTriangle } from "lucide-react";
22+
import { useEffect, useState } from "react";
23+
import { useForm } from "react-hook-form";
24+
import { toast } from "sonner";
25+
import { z } from "zod";
26+
27+
interface Props {
28+
composeId: string;
29+
}
30+
31+
const schema = z.object({
32+
isolatedDeployment: z.boolean().optional(),
33+
});
34+
35+
type Schema = z.infer<typeof schema>;
36+
37+
export const IsolatedDeployment = ({ composeId }: Props) => {
38+
const utils = api.useUtils();
39+
const [compose, setCompose] = useState<string>("");
40+
const { mutateAsync, error, isError } =
41+
api.compose.isolatedDeployment.useMutation();
42+
43+
const { mutateAsync: updateCompose } = api.compose.update.useMutation();
44+
45+
const { data, refetch } = api.compose.one.useQuery(
46+
{ composeId },
47+
{ enabled: !!composeId },
48+
);
49+
50+
console.log(data);
51+
52+
const form = useForm<Schema>({
53+
defaultValues: {
54+
isolatedDeployment: false,
55+
},
56+
resolver: zodResolver(schema),
57+
});
58+
59+
useEffect(() => {
60+
randomizeCompose();
61+
if (data) {
62+
form.reset({
63+
isolatedDeployment: data?.isolatedDeployment || false,
64+
});
65+
}
66+
}, [form, form.reset, form.formState.isSubmitSuccessful, data]);
67+
68+
const onSubmit = async (formData: Schema) => {
69+
await updateCompose({
70+
composeId,
71+
isolatedDeployment: formData?.isolatedDeployment || false,
72+
})
73+
.then(async (data) => {
74+
randomizeCompose();
75+
refetch();
76+
toast.success("Compose updated");
77+
})
78+
.catch(() => {
79+
toast.error("Error updating the compose");
80+
});
81+
};
82+
83+
const randomizeCompose = async () => {
84+
await mutateAsync({
85+
composeId,
86+
suffix: data?.appName || "",
87+
})
88+
.then(async (data) => {
89+
await utils.project.all.invalidate();
90+
setCompose(data);
91+
toast.success("Compose Isolated");
92+
})
93+
.catch(() => {
94+
toast.error("Error isolating the compose");
95+
});
96+
};
97+
98+
return (
99+
<>
100+
<DialogHeader>
101+
<DialogTitle>Isolate Deployment</DialogTitle>
102+
<DialogDescription>
103+
Use this option to isolate the deployment of this compose file.
104+
</DialogDescription>
105+
</DialogHeader>
106+
<div className="text-sm text-muted-foreground flex flex-col gap-2">
107+
<span>
108+
This feature creates an isolated environment for your deployment by
109+
adding unique prefixes to all resources. It establishes a dedicated
110+
network based on your compose file's name, ensuring your services run
111+
in isolation. This prevents conflicts when running multiple instances
112+
of the same template or services with identical names.
113+
</span>
114+
<div className="space-y-4">
115+
<div>
116+
<h4 className="font-medium mb-2">
117+
Resources that will be isolated:
118+
</h4>
119+
<ul className="list-disc list-inside">
120+
<li>Docker volumes</li>
121+
<li>Docker networks</li>
122+
</ul>
123+
</div>
124+
</div>
125+
</div>
126+
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
127+
<Form {...form}>
128+
<form
129+
onSubmit={form.handleSubmit(onSubmit)}
130+
id="hook-form-add-project"
131+
className="grid w-full gap-4"
132+
>
133+
{isError && (
134+
<div className="flex flex-row gap-4 rounded-lg items-center bg-red-50 p-2 dark:bg-red-950">
135+
<AlertTriangle className="text-red-600 dark:text-red-400" />
136+
<span className="text-sm text-red-600 dark:text-red-400">
137+
{error?.message}
138+
</span>
139+
</div>
140+
)}
141+
142+
<div className="flex flex-col lg:flex-col gap-4 w-full ">
143+
<div>
144+
<FormField
145+
control={form.control}
146+
name="isolatedDeployment"
147+
render={({ field }) => (
148+
<FormItem className="mt-4 flex flex-row items-center justify-between rounded-lg border p-3 shadow-sm">
149+
<div className="space-y-0.5">
150+
<FormLabel>Enable Randomize ({data?.appName})</FormLabel>
151+
<FormDescription>
152+
Enable randomize to the compose file.
153+
</FormDescription>
154+
</div>
155+
<FormControl>
156+
<Switch
157+
checked={field.value}
158+
onCheckedChange={field.onChange}
159+
/>
160+
</FormControl>
161+
</FormItem>
162+
)}
163+
/>
164+
</div>
165+
166+
<div className="flex flex-col lg:flex-row gap-4 w-full items-end justify-end">
167+
<Button
168+
form="hook-form-add-project"
169+
type="submit"
170+
className="lg:w-fit"
171+
>
172+
Save
173+
</Button>
174+
</div>
175+
</div>
176+
<div className="flex flex-col gap-4">
177+
<Label>Preview</Label>
178+
<pre>
179+
<CodeEditor
180+
value={compose || ""}
181+
language="yaml"
182+
readOnly
183+
height="50rem"
184+
/>
185+
</pre>
186+
</div>
187+
</form>
188+
</Form>
189+
</>
190+
);
191+
};

0 commit comments

Comments
 (0)