diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-server-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-server-actions.tsx index 41156d35b..ea2300cc5 100644 --- a/apps/dokploy/components/dashboard/settings/servers/actions/show-server-actions.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-server-actions.tsx @@ -1,3 +1,4 @@ +import { Activity } from "lucide-react"; import { useState } from "react"; import { Dialog, @@ -6,6 +7,7 @@ import { DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; import { DropdownMenuItem } from "@/components/ui/dropdown-menu"; import { ShowStorageActions } from "./show-storage-actions"; import { ShowTraefikActions } from "./show-traefik-actions"; @@ -13,20 +15,30 @@ import { ToggleDockerCleanup } from "./toggle-docker-cleanup"; interface Props { serverId: string; + asButton?: boolean; } -export const ShowServerActions = ({ serverId }: Props) => { +export const ShowServerActions = ({ serverId, asButton = false }: Props) => { const [isOpen, setIsOpen] = useState(false); return ( - + {asButton ? ( + + + + ) : ( e.preventDefault()} + onSelect={(e) => { + e.preventDefault(); + setIsOpen(true); + }} > View Actions - + )}
Web server settings diff --git a/apps/dokploy/components/dashboard/settings/servers/handle-servers.tsx b/apps/dokploy/components/dashboard/settings/servers/handle-servers.tsx index b36aec7c4..d9d1977a7 100644 --- a/apps/dokploy/components/dashboard/settings/servers/handle-servers.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/handle-servers.tsx @@ -1,5 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod"; -import { PlusIcon } from "lucide-react"; +import { PlusIcon, Pencil } from "lucide-react"; import Link from "next/link"; import { useTranslation } from "next-i18next"; import { useEffect, useState } from "react"; @@ -59,9 +59,10 @@ type Schema = z.infer; interface Props { serverId?: string; + asButton?: boolean; } -export const HandleServers = ({ serverId }: Props) => { +export const HandleServers = ({ serverId, asButton = false }: Props) => { const { t } = useTranslation("settings"); const utils = api.useUtils(); @@ -137,21 +138,32 @@ export const HandleServers = ({ serverId }: Props) => { return ( - - {serverId ? ( + {serverId ? ( + asButton ? ( + + + + ) : ( e.preventDefault()} + onSelect={(e) => { + e.preventDefault(); + setIsOpen(true); + }} > Edit Server - ) : ( + ) + ) : ( + - )} - + + )} {serverId ? "Edit" : "Create"} Server diff --git a/apps/dokploy/components/dashboard/settings/servers/setup-server.tsx b/apps/dokploy/components/dashboard/settings/servers/setup-server.tsx index 95899f20a..d88e9a3e4 100644 --- a/apps/dokploy/components/dashboard/settings/servers/setup-server.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/setup-server.tsx @@ -1,5 +1,5 @@ import copy from "copy-to-clipboard"; -import { CopyIcon, ExternalLinkIcon, ServerIcon } from "lucide-react"; +import { CopyIcon, ExternalLinkIcon, ServerIcon, Settings } from "lucide-react"; import Link from "next/link"; import { useState } from "react"; import { toast } from "sonner"; @@ -36,9 +36,10 @@ import { ValidateServer } from "./validate-server"; interface Props { serverId: string; + asButton?: boolean; } -export const SetupServer = ({ serverId }: Props) => { +export const SetupServer = ({ serverId, asButton = false }: Props) => { const [isOpen, setIsOpen] = useState(false); const { data: server } = api.server.one.useQuery( { @@ -81,14 +82,23 @@ export const SetupServer = ({ serverId }: Props) => { return ( - + {asButton ? ( + + + + ) : ( e.preventDefault()} + onSelect={(e) => { + e.preventDefault(); + setIsOpen(true); + }} > Setup Server - + )}
diff --git a/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx b/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx index 2f8ac24e2..111f10e28 100644 --- a/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx @@ -1,5 +1,18 @@ import { format } from "date-fns"; -import { KeyIcon, Loader2, MoreHorizontal, ServerIcon } from "lucide-react"; +import { + KeyIcon, + Loader2, + MoreHorizontal, + ServerIcon, + Clock, + User, + Key, + Network, + Terminal, + Settings, + Pencil, + Trash2, +} from "lucide-react"; import Link from "next/link"; import { useRouter } from "next/router"; import { useTranslation } from "next-i18next"; @@ -24,14 +37,11 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { - Table, - TableBody, - TableCaption, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { api } from "@/utils/api"; import { ShowNodesModal } from "../cluster/nodes/show-nodes-modal"; import { TerminalModal } from "../web-server/terminal-modal"; @@ -59,7 +69,7 @@ export const ShowServers = () => { return (
{query?.success && isCloud && } - +
@@ -114,240 +124,309 @@ export const ShowServers = () => {
) : ( -
- - -
- See all servers -
-
- - - Name - {isCloud && ( - - Status - - )} - - Type - - - IP Address - - - Port - - - Username - - - SSH Key - - - Created - - - Actions - - - - - {data?.map((server) => { - const canDelete = server.totalSum === 0; - const isActive = server.serverStatus === "active"; - const isBuildServer = - server.serverType === "build"; - return ( - - - {server.name} - - {isCloud && ( - +
+
+ {data?.map((server) => { + const canDelete = server.totalSum === 0; + const isActive = server.serverStatus === "active"; + const isBuildServer = server.serverType === "build"; + return ( + + +
+
+ + + {server.name} + +
+ {isActive && + server.sshKeyId && + !isBuildServer && ( + + + + + + + Advanced + + + + {isCloud && ( + + )} + + + + + + )} +
+ +
+ {isCloud && ( + <> + {server.serverStatus === "active" ? ( + + {server.serverStatus} + + ) : ( + + + + + {server.serverStatus} + + + + +

+ This server is deactivated due + to lack of payment. Please pay + your invoice to reactivate it. + If you think this is an error, + please contact support. +

+
+
+ )} + + )} - {server.serverStatus} + {server.serverType} - - )} - - - {server.serverType} +
+
+
+ +
+ + + IP: + + + {server.ipAddress} - - - {server.ipAddress} - - - {server.port} - - - {server.username} - - - + + Port: + + + {server.port} + +
+
+ + + User: + + + {server.username} + +
+
+ + + SSH Key: + + {server.sshKeyId ? "Yes" : "No"} - - - +
+
+ + + Created{" "} {format( new Date(server.createdAt), - "PPpp", + "PPp", )} - +
- - - - - - - - Actions - - - {isActive && ( - <> - {server.sshKeyId && ( - - - {t( - "settings.common.enterTerminal", - )} - - - )} - - - - - {server.sshKeyId && - !isBuildServer && ( - + + {server.sshKeyId && ( + + +
+ - )} - + asButton={true} + > + + +
+
+ +

Terminal

+
+
)} - - You can not delete this server - because it has active services. - - You have active services - associated with this server, - please delete them first. - -
- ) - } - onClick={async () => { - await mutateAsync({ - serverId: server.serverId, - }) - .then(() => { - refetch(); - toast.success( - `Server ${server.name} deleted successfully`, - ); - }) - .catch((err) => { - toast.error(err.message); - }); - }} - > - e.preventDefault()} - > - Delete Server - - - - {isActive && - server.sshKeyId && - !isBuildServer && ( - <> - - - Extra - - - + +
+ - + + +

Setup Server

+
+ + + + +
+ - {isCloud && ( - + + +

Edit Server

+
+ + + {server.sshKeyId && !isBuildServer && ( + + +
+ - )} +
+
+ +

Web Server Actions

+
+
+ )} - - +
- - - )} - - - - - ); - })} - -
+ + +
+ + You can not delete this + server because it has + active services. + + You have active services + associated with this + server, please delete + them first. + +
+ ) + } + onClick={async () => { + await mutateAsync({ + serverId: server.serverId, + }) + .then(() => { + refetch(); + toast.success( + `Server ${server.name} deleted successfully`, + ); + }) + .catch((err) => { + toast.error(err.message); + }); + }} + > + + +
+ + +

+ {canDelete + ? "Delete Server" + : "Cannot delete - has active services"} +

+
+ + +
+ )} + + + ); + })} +
-
+
{data && data?.length > 0 && (
diff --git a/apps/dokploy/components/dashboard/settings/web-server/terminal-modal.tsx b/apps/dokploy/components/dashboard/settings/web-server/terminal-modal.tsx index 58e4c9d4e..2647e1dc0 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/terminal-modal.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/terminal-modal.tsx @@ -24,10 +24,16 @@ const getTerminalKey = () => { interface Props { children?: React.ReactNode; serverId: string; + asButton?: boolean; } -export const TerminalModal = ({ children, serverId }: Props) => { +export const TerminalModal = ({ + children, + serverId, + asButton = false, +}: Props) => { const [terminalKey, setTerminalKey] = useState(getTerminalKey()); + const [isOpen, setIsOpen] = useState(false); const isLocalServer = serverId === "local"; const { data } = api.server.one.useQuery( @@ -43,15 +49,20 @@ export const TerminalModal = ({ children, serverId }: Props) => { }; return ( - - + + {asButton ? ( + {children} + ) : ( e.preventDefault()} + onSelect={(e) => { + e.preventDefault(); + setIsOpen(true); + }} > {children} - + )} event.preventDefault()}