diff --git a/apps/dokploy/components/dashboard/deployments/show-deployments-table.tsx b/apps/dokploy/components/dashboard/deployments/show-deployments-table.tsx index 770d4efd05..f29f3185f7 100644 --- a/apps/dokploy/components/dashboard/deployments/show-deployments-table.tsx +++ b/apps/dokploy/components/dashboard/deployments/show-deployments-table.tsx @@ -94,6 +94,18 @@ function getServiceInfo(d: DeploymentRow) { return null; } +// Sentinel value for deployments whose service has no remote server set, +// meaning it runs on the local Dokploy server. +const LOCAL_SERVER_VALUE = "__local__"; + +function getServerInfo(d: DeploymentRow) { + const server = d.server ?? d.application?.server ?? d.compose?.server ?? null; + if (server) { + return { serverId: server.serverId, name: server.name }; + } + return null; +} + export function ShowDeploymentsTable() { const [sorting, setSorting] = useState([ { id: "createdAt", desc: true }, @@ -102,6 +114,7 @@ export function ShowDeploymentsTable() { const [globalFilter, setGlobalFilter] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); const [typeFilter, setTypeFilter] = useState("all"); + const [serverFilter, setServerFilter] = useState("all"); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 50, @@ -112,6 +125,24 @@ export function ShowDeploymentsTable() { refetchInterval: 5000, }); + const serverOptions = useMemo(() => { + const map = new Map(); + let hasLocal = false; + for (const d of deploymentsList ?? []) { + const info = getServerInfo(d); + if (info) { + map.set(info.serverId, info.name); + } else { + hasLocal = true; + } + } + const options = Array.from(map, ([serverId, name]) => ({ + serverId, + name, + })).sort((a, b) => a.name.localeCompare(b.name)); + return { options, hasLocal }; + }, [deploymentsList]); + const filteredData = useMemo(() => { if (!deploymentsList) return []; let list = deploymentsList; @@ -123,6 +154,13 @@ export function ShowDeploymentsTable() { } else if (typeFilter === "compose") { list = list.filter((d) => d.composeId != null); } + if (serverFilter !== "all") { + list = list.filter((d) => { + const info = getServerInfo(d); + if (serverFilter === LOCAL_SERVER_VALUE) return info === null; + return info?.serverId === serverFilter; + }); + } if (globalFilter.trim()) { const q = globalFilter.toLowerCase(); list = list.filter((d) => { @@ -146,7 +184,7 @@ export function ShowDeploymentsTable() { }); } return list; - }, [deploymentsList, statusFilter, typeFilter, globalFilter]); + }, [deploymentsList, statusFilter, typeFilter, serverFilter, globalFilter]); const columns = useMemo( () => [ @@ -482,6 +520,22 @@ export function ShowDeploymentsTable() { Compose +
{isLoading ? (