From 1a9f131d398e95fe1b7f1b2d1fbbf34081016fef Mon Sep 17 00:00:00 2001
From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com>
Date: Mon, 1 Sep 2025 21:18:56 -0600
Subject: [PATCH] refactor: enhance environment selector with service presence
checks and alert notifications; update navigation links to include
environment context for improved user experience
---
.../project/advanced-environment-selector.tsx | 14 +++++++++++++-
.../dokploy/components/dashboard/projects/show.tsx | 2 +-
.../components/shared/breadcrumb-sidebar.tsx | 8 ++++----
.../[projectId]/environment/[environmentId].tsx | 1 -
.../services/application/[applicationId].tsx | 1 -
.../services/compose/[composeId].tsx | 1 -
.../services/mariadb/[mariadbId].tsx | 1 -
.../[environmentId]/services/mongo/[mongoId].tsx | 1 -
.../[environmentId]/services/mysql/[mysqlId].tsx | 1 -
.../services/postgres/[postgresId].tsx | 2 --
.../[environmentId]/services/redis/[redisId].tsx | 1 -
packages/server/src/services/environment.ts | 12 ++++++++++--
12 files changed, 28 insertions(+), 17 deletions(-)
diff --git a/apps/dokploy/components/dashboard/project/advanced-environment-selector.tsx b/apps/dokploy/components/dashboard/project/advanced-environment-selector.tsx
index fa7ab47e9..5246df5dd 100644
--- a/apps/dokploy/components/dashboard/project/advanced-environment-selector.tsx
+++ b/apps/dokploy/components/dashboard/project/advanced-environment-selector.tsx
@@ -24,6 +24,7 @@ import { Textarea } from "@/components/ui/textarea";
import { toast } from "sonner";
import { ChevronDownIcon, PlusIcon, PencilIcon, TrashIcon } from "lucide-react";
import { Badge } from "@/components/ui/badge";
+import { AlertBlock } from "@/components/shared/alert-block";
interface Environment {
environmentId: string;
@@ -54,6 +55,11 @@ export const AdvancedEnvironmentSelector = ({
const [description, setDescription] = useState("");
// API mutations
+ const { data: environment } = api.environment.one.useQuery({ environmentId: currentEnvironmentId || "" },{
+ enabled: !!currentEnvironmentId,
+ });
+
+ const haveServices = environment && (environment?.mariadb?.length > 0 || environment?.mongo?.length > 0 || environment?.mysql?.length > 0 || environment?.postgres?.length > 0 || environment?.redis?.length > 0 || environment?.applications?.length > 0 || environment?.compose?.length > 0);
const createEnvironment = api.environment.create.useMutation();
const updateEnvironment = api.environment.update.useMutation();
const deleteEnvironment = api.environment.remove.useMutation();
@@ -356,6 +362,12 @@ export const AdvancedEnvironmentSelector = ({
This action cannot be undone and will also delete all services in this environment.
+
+ {haveServices && (
+
+ This environment have active services, please delete them first.
+
+ )}
diff --git a/apps/dokploy/components/dashboard/projects/show.tsx b/apps/dokploy/components/dashboard/projects/show.tsx
index bba892857..a3b5d1ff9 100644
--- a/apps/dokploy/components/dashboard/projects/show.tsx
+++ b/apps/dokploy/components/dashboard/projects/show.tsx
@@ -216,7 +216,7 @@ export const ShowProjects = () => {
className="w-full lg:max-w-md"
>
{haveServicesWithDomains ? (
diff --git a/apps/dokploy/components/shared/breadcrumb-sidebar.tsx b/apps/dokploy/components/shared/breadcrumb-sidebar.tsx
index ed30dfaad..7bde4761e 100644
--- a/apps/dokploy/components/shared/breadcrumb-sidebar.tsx
+++ b/apps/dokploy/components/shared/breadcrumb-sidebar.tsx
@@ -13,7 +13,7 @@ import { SidebarTrigger } from "@/components/ui/sidebar";
interface Props {
list: {
name: string;
- href: string;
+ href?: string;
}[];
}
@@ -29,11 +29,11 @@ export const BreadcrumbSidebar = ({ list }: Props) => {
{list.map((item, index) => (
-
+
{item.href ? (
- {item.name}
+ {item?.name}
) : (
- item.name
+ item?.name
)}
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx
index 7a6e69867..5586d90fe 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId].tsx
@@ -757,7 +757,6 @@ const EnvironmentPage = (
},
{
name: currentEnvironment.name,
- href: `/dashboard/project/${projectId}/environment/${environmentId}`,
},
]}
/>
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/application/[applicationId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/application/[applicationId].tsx
index 2a1c22b1b..b88f1ad3e 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/application/[applicationId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/application/[applicationId].tsx
@@ -106,7 +106,6 @@ const Service = (
},
{
name: data?.name || "",
- href: `/dashboard/project/${projectId}/environment/${environmentId}/services/application/${applicationId}`,
},
]}
/>
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/compose/[composeId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/compose/[composeId].tsx
index c586dc66c..23ddb34e4 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/compose/[composeId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/compose/[composeId].tsx
@@ -97,7 +97,6 @@ const Service = (
},
{
name: data?.name || "",
- href: `/dashboard/project/${projectId}/environment/${environmentId}/services/compose/${composeId}`,
},
]}
/>
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mariadb/[mariadbId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mariadb/[mariadbId].tsx
index 3bb18fe4e..b268beec8 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mariadb/[mariadbId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mariadb/[mariadbId].tsx
@@ -78,7 +78,6 @@ const Mariadb = (
},
{
name: data?.name || "",
- href: `/dashboard/project/${projectId}/environment/${environmentId}/services/mariadb/${mariadbId}`,
},
]}
/>
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mongo/[mongoId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mongo/[mongoId].tsx
index 8d250a7d3..046666550 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mongo/[mongoId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mongo/[mongoId].tsx
@@ -78,7 +78,6 @@ const Mongo = (
},
{
name: data?.name || "",
- href: `/dashboard/project/${projectId}/environment/${environmentId}/services/mongo/${mongoId}`,
},
]}
/>
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mysql/[mysqlId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mysql/[mysqlId].tsx
index 093453a0d..d940c21b8 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mysql/[mysqlId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mysql/[mysqlId].tsx
@@ -77,7 +77,6 @@ const MySql = (
},
{
name: data?.name || "",
- href: `/dashboard/project/${projectId}/environment/${environmentId}/services/mysql/${mysqlId}`,
},
]}
/>
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/postgres/[postgresId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/postgres/[postgresId].tsx
index 41522516e..ed04f8205 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/postgres/[postgresId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/postgres/[postgresId].tsx
@@ -78,8 +78,6 @@ const Postgresql = (
},
{
name: data?.name || "",
- href:
- `/dashboard/project/${projectId}/environment/${environmentId}/services/postgres/${postgresId}`,
},
]}
/>
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/redis/[redisId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/redis/[redisId].tsx
index c7c79237f..891df9dac 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/redis/[redisId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/redis/[redisId].tsx
@@ -78,7 +78,6 @@ const Redis = (
},
{
name: data?.name || "",
- href: `/dashboard/project/${projectId}/environment/${environmentId}/services/redis/${redisId}`,
},
]}
/>
diff --git a/packages/server/src/services/environment.ts b/packages/server/src/services/environment.ts
index b88cfe2f2..45341fecf 100644
--- a/packages/server/src/services/environment.ts
+++ b/packages/server/src/services/environment.ts
@@ -62,13 +62,21 @@ export const findEnvironmentsByProjectId = async (projectId: string) => {
};
export const deleteEnvironment = async (environmentId: string) => {
- const environment = await db
+
+ const currentEnvironment = await findEnvironmentById(environmentId);
+ if (currentEnvironment.name === "production") {
+ throw new TRPCError({
+ code: "BAD_REQUEST",
+ message: "You cannot delete the production environment",
+ });
+ }
+ const deletedEnvironment = await db
.delete(environments)
.where(eq(environments.environmentId, environmentId))
.returning()
.then((value) => value[0]);
- return environment;
+ return deletedEnvironment;
};
export const updateEnvironmentById = async (