mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
refactor: enhance ManageTraefikPorts with ScrollArea for better UI and port management display
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -114,7 +115,15 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-base w-full">
|
||||
<div className="flex items-center justify-between">
|
||||
{t("settings.server.webServer.traefik.managePortsDescription")}
|
||||
<div className="flex flex-col gap-1">
|
||||
{t(
|
||||
"settings.server.webServer.traefik.managePortsDescription",
|
||||
)}
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{fields.length} port mapping{fields.length !== 1 ? "s" : ""}{" "}
|
||||
configured
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
onClick={handleAddPort}
|
||||
variant="default"
|
||||
@@ -141,109 +150,111 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid gap-4">
|
||||
{fields.map((field, index) => (
|
||||
<Card key={field.id}>
|
||||
<CardContent className="grid grid-cols-[1fr_1fr_1.5fr_auto] gap-4 p-4 transparent">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`ports.${index}.targetPort`}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="text-sm font-medium text-muted-foreground">
|
||||
{t(
|
||||
"settings.server.webServer.traefik.targetPort",
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type="number"
|
||||
{...field}
|
||||
onChange={(e) =>
|
||||
field.onChange(Number(e.target.value))
|
||||
}
|
||||
className="w-full dark:bg-black"
|
||||
placeholder="e.g. 8080"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`ports.${index}.publishedPort`}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="text-sm font-medium text-muted-foreground">
|
||||
{t(
|
||||
"settings.server.webServer.traefik.publishedPort",
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type="number"
|
||||
{...field}
|
||||
onChange={(e) =>
|
||||
field.onChange(Number(e.target.value))
|
||||
}
|
||||
className="w-full dark:bg-black"
|
||||
placeholder="e.g. 80"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`ports.${index}.publishMode`}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="text-sm font-medium text-muted-foreground">
|
||||
{t(
|
||||
"settings.server.webServer.traefik.publishMode",
|
||||
)}
|
||||
</FormLabel>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
<ScrollArea className="h-[400px] pr-4">
|
||||
<div className="grid gap-4">
|
||||
{fields.map((field, index) => (
|
||||
<Card key={field.id}>
|
||||
<CardContent className="grid grid-cols-[1fr_1fr_1.5fr_auto] gap-4 p-4 transparent">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`ports.${index}.targetPort`}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="text-sm font-medium text-muted-foreground">
|
||||
{t(
|
||||
"settings.server.webServer.traefik.targetPort",
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<SelectTrigger className="dark:bg-black">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<Input
|
||||
type="number"
|
||||
{...field}
|
||||
onChange={(e) =>
|
||||
field.onChange(Number(e.target.value))
|
||||
}
|
||||
className="w-full dark:bg-black"
|
||||
placeholder="e.g. 8080"
|
||||
/>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="host">
|
||||
Host Mode
|
||||
</SelectItem>
|
||||
<SelectItem value="ingress">
|
||||
Ingress Mode
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex items-end">
|
||||
<Button
|
||||
onClick={() => remove(index)}
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="text-muted-foreground hover:text-destructive"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`ports.${index}.publishedPort`}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="text-sm font-medium text-muted-foreground">
|
||||
{t(
|
||||
"settings.server.webServer.traefik.publishedPort",
|
||||
)}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type="number"
|
||||
{...field}
|
||||
onChange={(e) =>
|
||||
field.onChange(Number(e.target.value))
|
||||
}
|
||||
className="w-full dark:bg-black"
|
||||
placeholder="e.g. 80"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`ports.${index}.publishMode`}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="text-sm font-medium text-muted-foreground">
|
||||
{t(
|
||||
"settings.server.webServer.traefik.publishMode",
|
||||
)}
|
||||
</FormLabel>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger className="dark:bg-black">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="host">
|
||||
Host Mode
|
||||
</SelectItem>
|
||||
<SelectItem value="ingress">
|
||||
Ingress Mode
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex items-end">
|
||||
<Button
|
||||
onClick={() => remove(index)}
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="text-muted-foreground hover:text-destructive"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
)}
|
||||
|
||||
{fields.length > 0 && (
|
||||
@@ -281,7 +292,6 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
|
||||
</AlertBlock>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type="submit"
|
||||
|
||||
Reference in New Issue
Block a user