Skip to content

Commit 3e356e6

Browse files
committed
feat: being able to switch environments in sidebar
1 parent 72cc7a2 commit 3e356e6

File tree

8 files changed

+106
-16
lines changed

8 files changed

+106
-16
lines changed

apps/dokploy/components/shared/breadcrumb-sidebar.tsx

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
import Link from "next/link";
22
import { Fragment } from "react";
3+
import { ChevronDown } from "lucide-react";
34
import {
45
Breadcrumb,
56
BreadcrumbItem,
67
BreadcrumbLink,
78
BreadcrumbList,
89
BreadcrumbSeparator,
10+
BreadcrumbPage,
911
} from "@/components/ui/breadcrumb";
12+
import {
13+
DropdownMenu,
14+
DropdownMenuContent,
15+
DropdownMenuItem,
16+
DropdownMenuTrigger,
17+
} from "@/components/ui/dropdown-menu";
1018
import { Separator } from "@/components/ui/separator";
1119
import { SidebarTrigger } from "@/components/ui/sidebar";
1220

13-
interface Props {
14-
list: {
21+
interface BreadcrumbEntry {
22+
name: string;
23+
href?: string;
24+
dropdownItems?: {
1525
name: string;
16-
href?: string;
26+
href: string;
1727
}[];
1828
}
1929

30+
interface Props {
31+
list: BreadcrumbEntry[];
32+
}
33+
2034
export const BreadcrumbSidebar = ({ list }: Props) => {
2135
return (
2236
<header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
@@ -29,13 +43,29 @@ export const BreadcrumbSidebar = ({ list }: Props) => {
2943
{list.map((item, index) => (
3044
<Fragment key={item.name}>
3145
<BreadcrumbItem className="block">
32-
<BreadcrumbLink href={item?.href} asChild={!!item?.href}>
33-
{item.href ? (
34-
<Link href={item?.href}>{item?.name}</Link>
35-
) : (
36-
item?.name
37-
)}
38-
</BreadcrumbLink>
46+
{item.dropdownItems && item.dropdownItems.length > 0 ? (
47+
<DropdownMenu>
48+
<DropdownMenuTrigger className="flex items-center gap-1 hover:text-foreground transition-colors outline-none">
49+
{item.name}
50+
<ChevronDown className="h-4 w-4 opacity-50" />
51+
</DropdownMenuTrigger>
52+
<DropdownMenuContent align="start">
53+
{item.dropdownItems.map((subItem) => (
54+
<DropdownMenuItem key={subItem.href} asChild>
55+
<Link href={subItem.href}>{subItem.name}</Link>
56+
</DropdownMenuItem>
57+
))}
58+
</DropdownMenuContent>
59+
</DropdownMenu>
60+
) : (
61+
<BreadcrumbLink href={item?.href} asChild={!!item?.href}>
62+
{item.href ? (
63+
<Link href={item?.href}>{item?.name}</Link>
64+
) : (
65+
<BreadcrumbPage>{item?.name}</BreadcrumbPage>
66+
)}
67+
</BreadcrumbLink>
68+
)}
3969
</BreadcrumbItem>
4070
{index + 1 < list.length && (
4171
<BreadcrumbSeparator className="block" />

apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,16 @@ const EnvironmentPage = (
279279
const [isBulkActionLoading, setIsBulkActionLoading] = useState(false);
280280
const { projectId, environmentId } = props;
281281
const { data: auth } = api.user.get.useQuery();
282+
283+
const { data: environments } = api.environment.byProjectId.useQuery({
284+
projectId: projectId,
285+
});
286+
const environmentDropdownItems =
287+
environments?.map((env) => ({
288+
name: env.name,
289+
href: `/dashboard/project/${projectId}/environment/${env.environmentId}`,
290+
})) || [];
291+
282292
const [sortBy, setSortBy] = useState<string>(() => {
283293
if (typeof window !== "undefined") {
284294
return localStorage.getItem("servicesSort") || "lastDeploy-desc";
@@ -863,6 +873,7 @@ const EnvironmentPage = (
863873
},
864874
{
865875
name: currentEnvironment.name,
876+
dropdownItems: environmentDropdownItems,
866877
},
867878
]}
868879
/>

apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/compose/[composeId].tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ const Service = (
8080

8181
const { data: auth } = api.user.get.useQuery();
8282
const { data: isCloud } = api.settings.isCloud.useQuery();
83+
const { data: environments } = api.environment.byProjectId.useQuery({
84+
projectId: data?.environment?.projectId || "",
85+
});
86+
const environmentDropdownItems =
87+
environments?.map((env) => ({
88+
name: env.name,
89+
href: `/dashboard/project/${projectId}/environment/${env.environmentId}`,
90+
})) || [];
8391

8492
return (
8593
<div className="pb-10">
@@ -92,7 +100,7 @@ const Service = (
92100
},
93101
{
94102
name: data?.environment?.name || "",
95-
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
103+
dropdownItems: environmentDropdownItems,
96104
},
97105
{
98106
name: data?.name || "",

apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mariadb/[mariadbId].tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ const Mariadb = (
6262

6363
const { data: isCloud } = api.settings.isCloud.useQuery();
6464

65+
const { data: environments } = api.environment.byProjectId.useQuery({
66+
projectId: data?.environment?.projectId || "",
67+
});
68+
const environmentDropdownItems =
69+
environments?.map((env) => ({
70+
name: env.name,
71+
href: `/dashboard/project/${projectId}/environment/${env.environmentId}`,
72+
})) || [];
73+
6574
return (
6675
<div className="pb-10">
6776
<UseKeyboardNav forPage="mariadb" />
@@ -73,7 +82,7 @@ const Mariadb = (
7382
},
7483
{
7584
name: data?.environment?.name || "",
76-
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
85+
dropdownItems: environmentDropdownItems,
7786
},
7887
{
7988
name: data?.name || "",

apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mongo/[mongoId].tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ const Mongo = (
6161
const { data: auth } = api.user.get.useQuery();
6262

6363
const { data: isCloud } = api.settings.isCloud.useQuery();
64+
const { data: environments } = api.environment.byProjectId.useQuery({
65+
projectId: data?.environment?.projectId || "",
66+
});
67+
const environmentDropdownItems =
68+
environments?.map((env) => ({
69+
name: env.name,
70+
href: `/dashboard/project/${projectId}/environment/${env.environmentId}`,
71+
})) || [];
6472

6573
return (
6674
<div className="pb-10">
@@ -73,7 +81,7 @@ const Mongo = (
7381
},
7482
{
7583
name: data?.environment?.name || "",
76-
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
84+
dropdownItems: environmentDropdownItems,
7785
},
7886
{
7987
name: data?.name || "",

apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mysql/[mysqlId].tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ const MySql = (
6060
const { data: auth } = api.user.get.useQuery();
6161

6262
const { data: isCloud } = api.settings.isCloud.useQuery();
63+
const { data: environments } = api.environment.byProjectId.useQuery({
64+
projectId: data?.environment?.projectId || "",
65+
});
66+
const environmentDropdownItems =
67+
environments?.map((env) => ({
68+
name: env.name,
69+
href: `/dashboard/project/${projectId}/environment/${env.environmentId}`,
70+
})) || [];
6371

6472
return (
6573
<div className="pb-10">
@@ -72,7 +80,7 @@ const MySql = (
7280
},
7381
{
7482
name: data?.environment?.name || "",
75-
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
83+
dropdownItems: environmentDropdownItems,
7684
},
7785
{
7886
name: data?.name || "",

apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/postgres/[postgresId].tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ const Postgresql = (
6060
const { data: auth } = api.user.get.useQuery();
6161

6262
const { data: isCloud } = api.settings.isCloud.useQuery();
63+
const { data: environments } = api.environment.byProjectId.useQuery({
64+
projectId: data?.environment?.projectId || "",
65+
});
66+
const environmentDropdownItems =
67+
environments?.map((env) => ({
68+
name: env.name,
69+
href: `/dashboard/project/${projectId}/environment/${env.environmentId}`,
70+
})) || [];
6371

6472
return (
6573
<div className="pb-10">
@@ -72,7 +80,7 @@ const Postgresql = (
7280
},
7381
{
7482
name: data?.environment?.name || "",
75-
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
83+
dropdownItems: environmentDropdownItems,
7684
},
7785
{
7886
name: data?.name || "",

apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/redis/[redisId].tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ const Redis = (
6060
const { data: auth } = api.user.get.useQuery();
6161

6262
const { data: isCloud } = api.settings.isCloud.useQuery();
63+
const { data: environments } = api.environment.byProjectId.useQuery({
64+
projectId: data?.environment?.projectId || "",
65+
});
66+
const environmentDropdownItems =
67+
environments?.map((env) => ({
68+
name: env.name,
69+
href: `/dashboard/project/${projectId}/environment/${env.environmentId}`,
70+
})) || [];
6371

6472
return (
6573
<div className="pb-10">
@@ -72,7 +80,7 @@ const Redis = (
7280
},
7381
{
7482
name: data?.environment?.name || "",
75-
href: `/dashboard/project/${projectId}/environment/${environmentId}`,
83+
dropdownItems: environmentDropdownItems,
7684
},
7785
{
7886
name: data?.name || "",

0 commit comments

Comments
 (0)