Skip to content

Commit b562728

Browse files
authored
Merge pull request #1384 from Dokploy/mauricio/feature
Feat/AI
2 parents 0e81a02 + 1ffdebf commit b562728

File tree

27 files changed

+8372
-53
lines changed

27 files changed

+8372
-53
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { TemplateGenerator } from "@/components/dashboard/project/ai/template-generator";
2+
3+
interface Props {
4+
projectId: string;
5+
projectName?: string;
6+
}
7+
8+
export const AddAiAssistant = ({ projectId }: Props) => {
9+
return <TemplateGenerator projectId={projectId} />;
10+
};
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
"use client";
2+
3+
import { Button } from "@/components/ui/button";
4+
import { Label } from "@/components/ui/label";
5+
import {
6+
Select,
7+
SelectContent,
8+
SelectGroup,
9+
SelectItem,
10+
SelectLabel,
11+
SelectTrigger,
12+
SelectValue,
13+
} from "@/components/ui/select";
14+
import { Textarea } from "@/components/ui/textarea";
15+
import { api } from "@/utils/api";
16+
import { useState } from "react";
17+
18+
const examples = [
19+
"Make a personal blog",
20+
"Add a photo studio portfolio",
21+
"Create a personal ad blocker",
22+
"Build a social media dashboard",
23+
"Sendgrid service opensource analogue",
24+
];
25+
26+
export const StepOne = ({ nextStep, setTemplateInfo, templateInfo }: any) => {
27+
// Get servers from the API
28+
const { data: servers } = api.server.withSSHKey.useQuery();
29+
30+
const handleExampleClick = (example: string) => {
31+
setTemplateInfo({ ...templateInfo, userInput: example });
32+
};
33+
return (
34+
<div className="flex flex-col h-full gap-4">
35+
<div className="">
36+
<div className="space-y-4 ">
37+
<h2 className="text-lg font-semibold">Step 1: Describe Your Needs</h2>
38+
<div className="space-y-2">
39+
<Label htmlFor="user-needs">Describe your template needs</Label>
40+
<Textarea
41+
id="user-needs"
42+
placeholder="Describe the type of template you need, its purpose, and any specific features you'd like to include."
43+
value={templateInfo?.userInput}
44+
onChange={(e) =>
45+
setTemplateInfo({ ...templateInfo, userInput: e.target.value })
46+
}
47+
className="min-h-[100px]"
48+
/>
49+
</div>
50+
51+
<div className="space-y-2">
52+
<Label htmlFor="server-deploy">
53+
Select the server where you want to deploy (optional)
54+
</Label>
55+
<Select
56+
value={templateInfo.server?.serverId}
57+
onValueChange={(value) => {
58+
const server = servers?.find((s) => s.serverId === value);
59+
if (server) {
60+
setTemplateInfo({
61+
...templateInfo,
62+
server: server,
63+
});
64+
}
65+
}}
66+
>
67+
<SelectTrigger className="w-full">
68+
<SelectValue placeholder="Select a server" />
69+
</SelectTrigger>
70+
<SelectContent>
71+
<SelectGroup>
72+
{servers?.map((server) => (
73+
<SelectItem key={server.serverId} value={server.serverId}>
74+
{server.name}
75+
</SelectItem>
76+
))}
77+
<SelectLabel>Servers ({servers?.length})</SelectLabel>
78+
</SelectGroup>
79+
</SelectContent>
80+
</Select>
81+
</div>
82+
83+
<div className="space-y-2">
84+
<Label>Examples:</Label>
85+
<div className="flex flex-wrap gap-2">
86+
{examples.map((example, index) => (
87+
<Button
88+
key={index}
89+
variant="outline"
90+
size="sm"
91+
onClick={() => handleExampleClick(example)}
92+
>
93+
{example}
94+
</Button>
95+
))}
96+
</div>
97+
</div>
98+
</div>
99+
</div>
100+
</div>
101+
);
102+
};
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { CodeEditor } from "@/components/shared/code-editor";
2+
import ReactMarkdown from "react-markdown";
3+
import type { StepProps } from "./step-two";
4+
5+
export const StepThree = ({ templateInfo }: StepProps) => {
6+
return (
7+
<div className="flex flex-col h-full">
8+
<div className="flex-grow">
9+
<div className="space-y-6">
10+
<h2 className="text-lg font-semibold">Step 3: Review and Finalize</h2>
11+
<div className="space-y-4">
12+
<div>
13+
<h3 className="text-sm font-semibold">Name</h3>
14+
<p className="text-sm text-muted-foreground">
15+
{templateInfo?.details?.name}
16+
</p>
17+
</div>
18+
<div>
19+
<h3 className="text-sm font-semibold">Description</h3>
20+
<ReactMarkdown className="text-sm text-muted-foreground">
21+
{templateInfo?.details?.description}
22+
</ReactMarkdown>
23+
</div>
24+
<div>
25+
<h3 className="text-md font-semibold">Server</h3>
26+
<p className="text-sm text-muted-foreground">
27+
{templateInfo?.server?.name || "Dokploy Server"}
28+
</p>
29+
</div>
30+
<div className="space-y-2">
31+
<h3 className="text-sm font-semibold">Docker Compose</h3>
32+
<CodeEditor
33+
lineWrapping
34+
value={templateInfo?.details?.dockerCompose}
35+
disabled
36+
className="font-mono"
37+
/>
38+
</div>
39+
<div>
40+
<h3 className="text-sm font-semibold">Environment Variables</h3>
41+
<ul className="list-disc pl-5">
42+
{templateInfo?.details?.envVariables.map(
43+
(
44+
env: {
45+
name: string;
46+
value: string;
47+
},
48+
index: number,
49+
) => (
50+
<li key={index}>
51+
<strong className="text-sm font-semibold">
52+
{env.name}
53+
</strong>
54+
:
55+
<span className="text-sm ml-2 text-muted-foreground">
56+
{env.value}
57+
</span>
58+
</li>
59+
),
60+
)}
61+
</ul>
62+
</div>
63+
<div>
64+
<h3 className="text-sm font-semibold">Domains</h3>
65+
<ul className="list-disc pl-5">
66+
{templateInfo?.details?.domains.map(
67+
(
68+
domain: {
69+
host: string;
70+
port: number;
71+
serviceName: string;
72+
},
73+
index: number,
74+
) => (
75+
<li key={index}>
76+
<strong className="text-sm font-semibold">
77+
{domain.host}
78+
</strong>
79+
:
80+
<span className="text-sm ml-2 text-muted-foreground">
81+
{domain.port} - {domain.serviceName}
82+
</span>
83+
</li>
84+
),
85+
)}
86+
</ul>
87+
</div>
88+
<div>
89+
<h3 className="text-sm font-semibold">Configuration Files</h3>
90+
<ul className="list-disc pl-5">
91+
{templateInfo?.details?.configFiles.map((file, index) => (
92+
<li key={index}>
93+
<strong className="text-sm font-semibold">
94+
{file.filePath}
95+
</strong>
96+
:
97+
<span className="text-sm ml-2 text-muted-foreground">
98+
{file.content}
99+
</span>
100+
</li>
101+
))}
102+
</ul>
103+
</div>
104+
</div>
105+
</div>
106+
</div>
107+
</div>
108+
);
109+
};

0 commit comments

Comments
 (0)