refactor: enhance environment selector component and database schema to support new environment field, improving clarity and functionality in project management

This commit is contained in:
Mauricio Siu
2025-09-03 21:19:12 -06:00
parent d67644e52f
commit 7e1de62ab1
6 changed files with 6546 additions and 41 deletions

View File

@@ -1,15 +1,16 @@
import { useState } from "react";
import { useRouter } from "next/router";
import { api } from "@/utils/api";
import { Button } from "@/components/ui/button";
import type { findEnvironmentById } from "@dokploy/server";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
ChevronDownIcon,
PencilIcon,
PlusIcon,
Terminal,
TrashIcon,
} from "lucide-react";
import { useRouter } from "next/router";
import { useState } from "react";
import { toast } from "sonner";
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
@@ -18,20 +19,18 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { toast } from "sonner";
import {
ChevronDownIcon,
PlusIcon,
PencilIcon,
TrashIcon,
CopyIcon,
} from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { AlertBlock } from "@/components/shared/alert-block";
import { findEnvironmentById } from "@dokploy/server";
import { api } from "@/utils/api";
type Environment = Omit<
Awaited<ReturnType<typeof findEnvironmentById>>,
@@ -198,12 +197,12 @@ export const AdvancedEnvironmentSelector = ({
<>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="min-w-[200px] justify-between">
<div className="flex items-center gap-2">
<Button variant="ghost" className="h-auto p-2 font-normal">
<div className="flex items-center gap-1">
<span className="text-muted-foreground">/</span>
<span>{currentEnv?.name || "Select Environment"}</span>
{currentEnv?.name === "production" && <Badge>Prod</Badge>}
<ChevronDownIcon className="h-4 w-4 text-muted-foreground" />
</div>
<ChevronDownIcon className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-[300px]" align="start">
@@ -221,10 +220,7 @@ export const AdvancedEnvironmentSelector = ({
}}
>
<div className="flex items-center justify-between w-full">
<div className="flex items-center gap-2">
<span>{environment.name}</span>
{environment.name === "production" && <Badge>Prod</Badge>}
</div>
<span>{environment.name}</span>
{environment.environmentId === currentEnvironmentId && (
<div className="w-2 h-2 bg-blue-500 rounded-full" />
)}
@@ -245,6 +241,16 @@ export const AdvancedEnvironmentSelector = ({
>
<PencilIcon className="h-3 w-3" />
</Button>
<Button
variant="ghost"
size="sm"
className="h-6 w-6 p-0"
onClick={(e) => {
e.stopPropagation();
}}
>
<Terminal className="h-3 w-3" />
</Button>
<Button
variant="ghost"
size="sm"

View File

@@ -0,0 +1 @@
ALTER TABLE "environment" ADD COLUMN "env" text DEFAULT '' NOT NULL;

File diff suppressed because it is too large Load Diff

View File

@@ -757,6 +757,13 @@
"when": 1756793713380,
"tag": "0107_loud_kang",
"breakpoints": true
},
{
"idx": 108,
"version": "7",
"when": 1756955718127,
"tag": "0108_lazy_next_avengers",
"breakpoints": true
}
]
}

View File

@@ -47,7 +47,6 @@ import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
import { DateTooltip } from "@/components/shared/date-tooltip";
import { DialogAction } from "@/components/shared/dialog-action";
import { StatusTooltip } from "@/components/shared/status-tooltip";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
@@ -770,12 +769,13 @@ const EnvironmentPage = (
<div className="rounded-xl bg-background shadow-md">
<div className="flex justify-between gap-4 w-full items-center flex-wrap p-6">
<CardHeader className="p-0">
<CardTitle className="text-xl flex flex-row gap-2">
<CardTitle className="text-xl flex flex-row gap-2 items-center">
<FolderInput className="size-6 text-muted-foreground self-center" />
{currentEnvironment.project.name}
{currentEnvironment.name === "production" && (
<Badge>Production</Badge>
)}
<AdvancedEnvironmentSelector
projectId={projectId}
currentEnvironmentId={environmentId}
/>
</CardTitle>
<CardDescription>
{currentEnvironment.description || "No description provided"}
@@ -786,10 +786,6 @@ const EnvironmentPage = (
<ProjectEnvironment projectId={projectId}>
<Button variant="outline">Project Environment</Button>
</ProjectEnvironment>
<AdvancedEnvironmentSelector
projectId={projectId}
currentEnvironmentId={environmentId}
/>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button>
@@ -995,7 +991,10 @@ const EnvironmentPage = (
<>
{/* Step 1: Select Project */}
<div className="flex flex-col gap-2">
<label className="text-sm font-medium">
<label
htmlFor="target-project"
className="text-sm font-medium"
>
Target Project
</label>
<Select
@@ -1028,7 +1027,10 @@ const EnvironmentPage = (
{/* Step 2: Select Environment (only show if project is selected) */}
{selectedTargetProject && (
<div className="flex flex-col gap-2">
<label className="text-sm font-medium">
<label
htmlFor="target-environment"
className="text-sm font-medium"
>
Target Environment
</label>
<Select

View File

@@ -22,6 +22,7 @@ export const environments = pgTable("environment", {
createdAt: text("createdAt")
.notNull()
.$defaultFn(() => new Date().toISOString()),
env: text("env").notNull().default(""),
projectId: text("projectId")
.notNull()
.references(() => projects.projectId, { onDelete: "cascade" }),