@@ -94,93 +60,114 @@ export default function SwarmMonitorCard({ serverId }: Props) {
)}
-
-
-
- Total Nodes
-
-
-
-
-
- {totalNodes}
-
-
+ {isPending ? (
+
+ Loading...
+
+
+ ) : !nodes ? (
+
+ Failed to load data
+
+ ) : (
+ <>
+
+
+
+
+ Total Nodes
+
+
+
+
+
+
+ {totalNodes}
+
+
-
-
-
-
- Active Nodes
-
- Online
-
-
-
-
-
-
-
-
- {activeNodesCount} / {totalNodes}
-
-
-
-
- {activeNodes.map((node) => (
-
- {node.Hostname}
+
+
+
+
+ Active Nodes
+
+ Online
+
+
+
+
+
+
+
+
+ {activeNodes.length} / {totalNodes}
- ))}
-
-
-
-
-
-
-
-
-
-
-
- Manager Nodes
-
- Online
-
-
-
-
-
-
-
-
-
-
- {managerNodesCount} / {totalNodes}
-
-
-
-
- {managerNodes.map((node) => (
-
- {node.Hostname}
+
+
+
+ {activeNodes.map((node) => (
+
+ {node.Hostname}
+
+ ))}
- ))}
-
-
-
-
-
-
-
+
+
+
+
+
-
- {nodes.map((node) => (
-
- ))}
-
+
+
+
+
+ Manager Nodes
+
+ Online
+
+
+
+
+
+
+
+
+
+
+ {managerNodes.length} / {totalNodes}
+
+
+
+
+ {managerNodes.map((node) => (
+
+ {node.Hostname}
+
+ ))}
+
+
+
+
+
+
+
+
+
+ {nodes.map((node) => (
+
+ ))}
+
+ >
+ )}
);
diff --git a/apps/dokploy/components/layouts/side.tsx b/apps/dokploy/components/layouts/side.tsx
index e58256c63..3cb9e29a6 100644
--- a/apps/dokploy/components/layouts/side.tsx
+++ b/apps/dokploy/components/layouts/side.tsx
@@ -25,10 +25,8 @@ import {
Loader2,
LogIn,
type LucideIcon,
- Network,
Package,
Palette,
- PieChart,
Rocket,
Server,
ShieldCheck,
@@ -202,28 +200,6 @@ const MENU: Menu = {
// Only enabled for users with access to Docker
isEnabled: ({ permissions }) => !!permissions?.docker.read,
},
- {
- isSingle: true,
- title: "Swarm",
- url: "/dashboard/swarm",
- icon: PieChart,
- // Only enabled for users with access to Docker
- isEnabled: ({ permissions }) => !!permissions?.docker.read,
- },
- {
- isSingle: true,
- title: "Networks",
- url: "/dashboard/networks",
- icon: Network,
- // Only enabled for admins and users with access to Docker in non-cloud environments
- isEnabled: ({ auth, isCloud }) =>
- !!(
- (auth?.role === "owner" ||
- auth?.role === "admin" ||
- auth?.canAccessToDocker) &&
- !isCloud
- ),
- },
{
isSingle: true,
title: "Requests",
diff --git a/apps/dokploy/pages/dashboard/docker.tsx b/apps/dokploy/pages/dashboard/docker.tsx
index df1b2e5ed..11605d963 100644
--- a/apps/dokploy/pages/dashboard/docker.tsx
+++ b/apps/dokploy/pages/dashboard/docker.tsx
@@ -1,17 +1,79 @@
import { validateRequest } from "@dokploy/server/lib/auth";
import { createServerSideHelpers } from "@trpc/react-query/server";
import type { GetServerSidePropsContext } from "next";
+import { useRouter } from "next/router";
import type { ReactElement } from "react";
import superjson from "superjson";
import { ShowContainers } from "@/components/dashboard/docker/show/show-containers";
+import { ShowNetworks } from "@/components/dashboard/networks/show-networks";
+import { ShowSwarmContainers } from "@/components/dashboard/swarm/containers/show-swarm-containers";
+import SwarmMonitorCard from "@/components/dashboard/swarm/monitoring-card";
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
import { ServerFilter } from "@/components/shared/server-filter";
+import { Card } from "@/components/ui/card";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { appRouter } from "@/server/api/root";
+import { api } from "@/utils/api";
+
+const DEFAULT_TAB = "containers";
const Dashboard = () => {
+ const router = useRouter();
+ const { data: isCloud } = api.settings.isCloud.useQuery();
+
+ const queryTab =
+ typeof router.query.tab === "string" ? router.query.tab : DEFAULT_TAB;
+ const activeTab = isCloud && queryTab === "networks" ? DEFAULT_TAB : queryTab;
+
+ const setTab = (value: string) => {
+ const { tab: _current, ...query } = router.query;
+ router.replace(
+ {
+ pathname: router.pathname,
+ query: value === DEFAULT_TAB ? query : { ...query, tab: value },
+ },
+ undefined,
+ { shallow: true },
+ );
+ };
+
return (
- {(serverId) => }
+ {(serverId) => (
+
+
+ Containers
+ Swarm
+ {!isCloud && Networks}
+
+
+
+
+
+
+
+ Overview
+ Containers
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {!isCloud && (
+
+
+
+ )}
+
+ )}
);
};
diff --git a/apps/dokploy/pages/dashboard/networks.tsx b/apps/dokploy/pages/dashboard/networks.tsx
index cf11fcd3d..f19de36ad 100644
--- a/apps/dokploy/pages/dashboard/networks.tsx
+++ b/apps/dokploy/pages/dashboard/networks.tsx
@@ -1,89 +1,21 @@
-import { IS_CLOUD } from "@dokploy/server/constants";
-import { validateRequest } from "@dokploy/server/lib/auth";
-import { createServerSideHelpers } from "@trpc/react-query/server";
import type { GetServerSidePropsContext } from "next";
-import type { ReactElement } from "react";
-import superjson from "superjson";
-import { ShowNetworks } from "@/components/dashboard/networks/show-networks";
-import { DashboardLayout } from "@/components/layouts/dashboard-layout";
-import { ServerFilter } from "@/components/shared/server-filter";
-import { appRouter } from "@/server/api/root";
-const Dashboard = () => {
- return (
-
- {(serverId) => }
-
- );
+const Networks = () => {
+ return null;
};
-export default Dashboard;
+export default Networks;
-Dashboard.getLayout = (page: ReactElement) => {
- return
{page};
-};
+export async function getServerSideProps(ctx: GetServerSidePropsContext) {
+ const serverId =
+ typeof ctx.query.serverId === "string" ? ctx.query.serverId : undefined;
-export async function getServerSideProps(
- ctx: GetServerSidePropsContext<{ serviceId: string }>,
-) {
- if (IS_CLOUD) {
- return {
- redirect: {
- permanent: true,
- destination: "/dashboard/projects",
- },
- };
- }
- const { user, session } = await validateRequest(ctx.req);
- if (!user) {
- return {
- redirect: {
- permanent: true,
- destination: "/",
- },
- };
- }
- const { req } = ctx;
-
- const helpers = createServerSideHelpers({
- router: appRouter,
- ctx: {
- req: req as any,
- res: ctx.res as any,
- db: null as any,
- session: session as any,
- user: user as any,
+ return {
+ redirect: {
+ permanent: false,
+ destination: `/dashboard/docker?tab=networks${
+ serverId ? `&serverId=${encodeURIComponent(serverId)}` : ""
+ }`,
},
- transformer: superjson,
- });
- try {
- await helpers.project.all.prefetch();
-
- if (user.role === "member") {
- const userR = await helpers.user.one.fetch({
- userId: user.id,
- });
-
- if (!userR?.canAccessToDocker) {
- return {
- redirect: {
- permanent: true,
- destination: "/",
- },
- };
- }
- }
-
- await helpers.network.all.prefetch({});
-
- return {
- props: {
- trpcState: helpers.dehydrate(),
- },
- };
- } catch {
- return {
- props: {},
- };
- }
+ };
}
diff --git a/apps/dokploy/pages/dashboard/swarm.tsx b/apps/dokploy/pages/dashboard/swarm.tsx
index 77fc2b309..03e34da45 100644
--- a/apps/dokploy/pages/dashboard/swarm.tsx
+++ b/apps/dokploy/pages/dashboard/swarm.tsx
@@ -1,94 +1,21 @@
-import { validateRequest } from "@dokploy/server/lib/auth";
-import { createServerSideHelpers } from "@trpc/react-query/server";
import type { GetServerSidePropsContext } from "next";
-import type { ReactElement } from "react";
-import superjson from "superjson";
-import { ShowSwarmContainers } from "@/components/dashboard/swarm/containers/show-swarm-containers";
-import SwarmMonitorCard from "@/components/dashboard/swarm/monitoring-card";
-import { DashboardLayout } from "@/components/layouts/dashboard-layout";
-import { ServerFilter } from "@/components/shared/server-filter";
-import { Card } from "@/components/ui/card";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { appRouter } from "@/server/api/root";
-const Dashboard = () => {
- return (
-
- {(serverId) => (
-
-
-
- Overview
- Containers
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
- );
+const Swarm = () => {
+ return null;
};
-export default Dashboard;
+export default Swarm;
-Dashboard.getLayout = (page: ReactElement) => {
- return
{page};
-};
-export async function getServerSideProps(
- ctx: GetServerSidePropsContext<{ serviceId: string }>,
-) {
- const { user, session } = await validateRequest(ctx.req);
- if (!user) {
- return {
- redirect: {
- permanent: false,
- destination: "/",
- },
- };
- }
- const { req, res } = ctx;
+export async function getServerSideProps(ctx: GetServerSidePropsContext) {
+ const serverId =
+ typeof ctx.query.serverId === "string" ? ctx.query.serverId : undefined;
- const helpers = createServerSideHelpers({
- router: appRouter,
- ctx: {
- req: req as any,
- res: res as any,
- db: null as any,
- session: session as any,
- user: user as any,
+ return {
+ redirect: {
+ permanent: false,
+ destination: `/dashboard/docker?tab=swarm${
+ serverId ? `&serverId=${encodeURIComponent(serverId)}` : ""
+ }`,
},
- transformer: superjson,
- });
- try {
- await helpers.project.all.prefetch();
-
- const userPermissions = await helpers.user.getPermissions.fetch();
-
- if (!userPermissions?.docker.read) {
- return {
- redirect: {
- permanent: false,
- destination: "/",
- },
- };
- }
- return {
- props: {
- trpcState: helpers.dehydrate(),
- },
- };
- } catch {
- return {
- props: {},
- };
- }
+ };
}