mirror of
https://github.com/andwati/dokploy.git
synced 2026-10-31 09:12:15 +00:00
[autofix.ci] apply automated fixes
This commit is contained in:
@@ -22,12 +22,17 @@ 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 {
|
||||
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";
|
||||
|
||||
|
||||
type Environment = Awaited<ReturnType<typeof findEnvironmentById>>;
|
||||
interface AdvancedEnvironmentSelectorProps {
|
||||
projectId: string;
|
||||
@@ -42,11 +47,15 @@ export const AdvancedEnvironmentSelector = ({
|
||||
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
|
||||
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
|
||||
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
|
||||
const [selectedEnvironment, setSelectedEnvironment] = useState<Environment | null>(null);
|
||||
const [selectedEnvironment, setSelectedEnvironment] =
|
||||
useState<Environment | null>(null);
|
||||
|
||||
const { data: project } = api.project.one.useQuery({ projectId },{
|
||||
enabled: !!projectId,
|
||||
});
|
||||
const { data: project } = api.project.one.useQuery(
|
||||
{ projectId },
|
||||
{
|
||||
enabled: !!projectId,
|
||||
},
|
||||
);
|
||||
const environments = project?.environments || [];
|
||||
|
||||
// Form states
|
||||
@@ -54,20 +63,22 @@ export const AdvancedEnvironmentSelector = ({
|
||||
const [description, setDescription] = useState("");
|
||||
|
||||
// API mutations
|
||||
const { data: environment } = api.environment.one.useQuery({ environmentId: currentEnvironmentId || "" },{
|
||||
enabled: !!currentEnvironmentId,
|
||||
});
|
||||
|
||||
|
||||
const haveServices = selectedEnvironment && (
|
||||
(selectedEnvironment?.mariadb?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.mongo?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.mysql?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.postgres?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.redis?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.applications?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.compose?.length || 0) > 0
|
||||
const { data: environment } = api.environment.one.useQuery(
|
||||
{ environmentId: currentEnvironmentId || "" },
|
||||
{
|
||||
enabled: !!currentEnvironmentId,
|
||||
},
|
||||
);
|
||||
|
||||
const haveServices =
|
||||
selectedEnvironment &&
|
||||
((selectedEnvironment?.mariadb?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.mongo?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.mysql?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.postgres?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.redis?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.applications?.length || 0) > 0 ||
|
||||
(selectedEnvironment?.compose?.length || 0) > 0);
|
||||
const createEnvironment = api.environment.create.useMutation();
|
||||
const updateEnvironment = api.environment.update.useMutation();
|
||||
const deleteEnvironment = api.environment.remove.useMutation();
|
||||
@@ -83,7 +94,7 @@ export const AdvancedEnvironmentSelector = ({
|
||||
name: name.trim(),
|
||||
description: description.trim() || null,
|
||||
});
|
||||
|
||||
|
||||
toast.success("Environment created successfully");
|
||||
utils.project.one.invalidate({ projectId });
|
||||
setIsCreateDialogOpen(false);
|
||||
@@ -103,7 +114,7 @@ export const AdvancedEnvironmentSelector = ({
|
||||
name: name.trim(),
|
||||
description: description.trim() || null,
|
||||
});
|
||||
|
||||
|
||||
toast.success("Environment updated successfully");
|
||||
utils.project.one.invalidate({ projectId });
|
||||
setIsEditDialogOpen(false);
|
||||
@@ -122,7 +133,7 @@ export const AdvancedEnvironmentSelector = ({
|
||||
await deleteEnvironment.mutateAsync({
|
||||
environmentId: selectedEnvironment.environmentId,
|
||||
});
|
||||
|
||||
|
||||
toast.success("Environment deleted successfully");
|
||||
utils.project.one.invalidate({ projectId });
|
||||
setIsDeleteDialogOpen(false);
|
||||
@@ -130,9 +141,13 @@ export const AdvancedEnvironmentSelector = ({
|
||||
|
||||
// Redirect to production if we deleted the current environment
|
||||
if (selectedEnvironment.environmentId === currentEnvironmentId) {
|
||||
const productionEnv = environments.find(env => env.name === "production");
|
||||
const productionEnv = environments.find(
|
||||
(env) => env.name === "production",
|
||||
);
|
||||
if (productionEnv) {
|
||||
router.push(`/dashboard/project/${projectId}/environment/${productionEnv.environmentId}`);
|
||||
router.push(
|
||||
`/dashboard/project/${projectId}/environment/${productionEnv.environmentId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -147,12 +162,14 @@ export const AdvancedEnvironmentSelector = ({
|
||||
name: `${environment.name}-copy`,
|
||||
description: environment.description,
|
||||
});
|
||||
|
||||
|
||||
toast.success("Environment duplicated successfully");
|
||||
utils.project.one.invalidate({ projectId });
|
||||
|
||||
|
||||
// Navigate to the new duplicated environment
|
||||
router.push(`/dashboard/project/${projectId}/environment/${result.environmentId}`);
|
||||
router.push(
|
||||
`/dashboard/project/${projectId}/environment/${result.environmentId}`,
|
||||
);
|
||||
} catch (error) {
|
||||
toast.error("Failed to duplicate environment");
|
||||
}
|
||||
@@ -170,7 +187,9 @@ export const AdvancedEnvironmentSelector = ({
|
||||
setIsDeleteDialogOpen(true);
|
||||
};
|
||||
|
||||
const currentEnv = environments.find(env => env.environmentId === currentEnvironmentId);
|
||||
const currentEnv = environments.find(
|
||||
(env) => env.environmentId === currentEnvironmentId,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -179,11 +198,7 @@ export const AdvancedEnvironmentSelector = ({
|
||||
<Button variant="outline" className="min-w-[200px] justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span>{currentEnv?.name || "Select Environment"}</span>
|
||||
{currentEnv?.name === "production" && (
|
||||
<Badge >
|
||||
Prod
|
||||
</Badge>
|
||||
)}
|
||||
{currentEnv?.name === "production" && <Badge>Prod</Badge>}
|
||||
</div>
|
||||
<ChevronDownIcon className="h-4 w-4" />
|
||||
</Button>
|
||||
@@ -191,30 +206,28 @@ export const AdvancedEnvironmentSelector = ({
|
||||
<DropdownMenuContent className="w-[300px]" align="start">
|
||||
<DropdownMenuLabel>Environments</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
|
||||
{environments.map((environment) => (
|
||||
<div key={environment.environmentId} className="flex items-center">
|
||||
<DropdownMenuItem
|
||||
className="flex-1 cursor-pointer"
|
||||
onClick={() => {
|
||||
router.push(`/dashboard/project/${projectId}/environment/${environment.environmentId}`);
|
||||
router.push(
|
||||
`/dashboard/project/${projectId}/environment/${environment.environmentId}`,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<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>
|
||||
)}
|
||||
{environment.name === "production" && <Badge>Prod</Badge>}
|
||||
</div>
|
||||
{environment.environmentId === currentEnvironmentId && (
|
||||
<div className="w-2 h-2 bg-blue-500 rounded-full" />
|
||||
)}
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
|
||||
|
||||
{/* Action buttons for non-production environments */}
|
||||
{environment.name !== "production" && (
|
||||
<div className="flex items-center gap-1 px-2">
|
||||
@@ -255,7 +268,7 @@ export const AdvancedEnvironmentSelector = ({
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
@@ -275,7 +288,7 @@ export const AdvancedEnvironmentSelector = ({
|
||||
Create a new environment for your project.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="name">Name</Label>
|
||||
@@ -296,7 +309,7 @@ export const AdvancedEnvironmentSelector = ({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -327,7 +340,7 @@ export const AdvancedEnvironmentSelector = ({
|
||||
Update the environment details.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="edit-name">Name</Label>
|
||||
@@ -348,7 +361,7 @@ export const AdvancedEnvironmentSelector = ({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -377,17 +390,18 @@ export const AdvancedEnvironmentSelector = ({
|
||||
<DialogHeader>
|
||||
<DialogTitle>Delete Environment</DialogTitle>
|
||||
<DialogDescription>
|
||||
Are you sure you want to delete the environment "{selectedEnvironment?.name}"?
|
||||
This action cannot be undone and will also delete all services in this environment.
|
||||
Are you sure you want to delete the environment "
|
||||
{selectedEnvironment?.name}"? This action cannot be undone and
|
||||
will also delete all services in this environment.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
{haveServices && (
|
||||
<AlertBlock type="warning">
|
||||
This environment have active services, please delete them first.
|
||||
</AlertBlock>
|
||||
This environment have active services, please delete them first.
|
||||
</AlertBlock>
|
||||
)}
|
||||
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -401,7 +415,11 @@ export const AdvancedEnvironmentSelector = ({
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={handleDeleteEnvironment}
|
||||
disabled={deleteEnvironment.isLoading || haveServices || !selectedEnvironment}
|
||||
disabled={
|
||||
deleteEnvironment.isLoading ||
|
||||
haveServices ||
|
||||
!selectedEnvironment
|
||||
}
|
||||
>
|
||||
{deleteEnvironment.isLoading ? "Deleting..." : "Delete"}
|
||||
</Button>
|
||||
|
||||
@@ -103,7 +103,6 @@ export const TemplateGenerator = ({ environmentId }: Props) => {
|
||||
useState<TemplateInfo>(defaultTemplateInfo);
|
||||
const utils = api.useUtils();
|
||||
|
||||
|
||||
const haveAtleasOneProviderEnabled = aiSettings?.some(
|
||||
(ai) => ai.isEnabled === true,
|
||||
);
|
||||
|
||||
@@ -57,17 +57,20 @@ export const DuplicateProject = ({
|
||||
const [name, setName] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [duplicateType, setDuplicateType] = useState("new-project"); // "new-project" or "existing-environment"
|
||||
const [selectedTargetProject, setSelectedTargetProject] = useState<string>("");
|
||||
const [selectedTargetEnvironment, setSelectedTargetEnvironment] = useState<string>("");
|
||||
const [selectedTargetProject, setSelectedTargetProject] =
|
||||
useState<string>("");
|
||||
const [selectedTargetEnvironment, setSelectedTargetEnvironment] =
|
||||
useState<string>("");
|
||||
const utils = api.useUtils();
|
||||
const router = useRouter();
|
||||
|
||||
// Queries for project and environment selection
|
||||
const { data: allProjects } = api.project.all.useQuery();
|
||||
const { data: selectedProjectEnvironments } = api.environment.byProjectId.useQuery(
|
||||
{ projectId: selectedTargetProject },
|
||||
{ enabled: !!selectedTargetProject }
|
||||
);
|
||||
const { data: selectedProjectEnvironments } =
|
||||
api.environment.byProjectId.useQuery(
|
||||
{ projectId: selectedTargetProject },
|
||||
{ enabled: !!selectedTargetProject },
|
||||
);
|
||||
|
||||
const selectedServices = services.filter((service) =>
|
||||
selectedServiceIds.includes(service.id),
|
||||
@@ -84,7 +87,9 @@ export const DuplicateProject = ({
|
||||
);
|
||||
setOpen(false);
|
||||
if (duplicateType === "new-project") {
|
||||
router.push(`/dashboard/project/${newProject?.projectId}/environment/${newProject?.environmentId}`);
|
||||
router.push(
|
||||
`/dashboard/project/${newProject?.projectId}/environment/${newProject?.environmentId}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
@@ -172,8 +177,13 @@ export const DuplicateProject = ({
|
||||
<Label htmlFor="new-project">New project</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="existing-environment" id="existing-environment" />
|
||||
<Label htmlFor="existing-environment">Existing environment</Label>
|
||||
<RadioGroupItem
|
||||
value="existing-environment"
|
||||
id="existing-environment"
|
||||
/>
|
||||
<Label htmlFor="existing-environment">
|
||||
Existing environment
|
||||
</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
@@ -204,7 +214,8 @@ export const DuplicateProject = ({
|
||||
|
||||
{duplicateType === "existing-environment" && (
|
||||
<>
|
||||
{allProjects?.filter((p) => p.projectId !== environmentId).length === 0 ? (
|
||||
{allProjects?.filter((p) => p.projectId !== environmentId)
|
||||
.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center gap-2 py-4 text-center">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
No other projects available. Create a new project first.
|
||||
@@ -291,12 +302,13 @@ export const DuplicateProject = ({
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleDuplicate}
|
||||
<Button
|
||||
onClick={handleDuplicate}
|
||||
disabled={
|
||||
isLoading ||
|
||||
(duplicateType === "new-project" && !name) ||
|
||||
(duplicateType === "existing-environment" && (!selectedTargetProject || !selectedTargetEnvironment))
|
||||
(duplicateType === "existing-environment" &&
|
||||
(!selectedTargetProject || !selectedTargetEnvironment))
|
||||
}
|
||||
>
|
||||
{isLoading ? (
|
||||
|
||||
@@ -187,28 +187,40 @@ export const ShowProjects = () => {
|
||||
)}
|
||||
<div className="w-full grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 3xl:grid-cols-5 flex-wrap gap-5">
|
||||
{filteredProjects?.map((project) => {
|
||||
const emptyServices =
|
||||
project?.environments.map((env) => env.applications.length === 0 &&
|
||||
env.mariadb.length === 0 &&
|
||||
env.mongo.length === 0 &&
|
||||
env.mysql.length === 0 &&
|
||||
env.postgres.length === 0 &&
|
||||
env.redis.length === 0 &&
|
||||
env.applications.length === 0 &&
|
||||
env.compose.length === 0).every(Boolean);
|
||||
const emptyServices = project?.environments
|
||||
.map(
|
||||
(env) =>
|
||||
env.applications.length === 0 &&
|
||||
env.mariadb.length === 0 &&
|
||||
env.mongo.length === 0 &&
|
||||
env.mysql.length === 0 &&
|
||||
env.postgres.length === 0 &&
|
||||
env.redis.length === 0 &&
|
||||
env.applications.length === 0 &&
|
||||
env.compose.length === 0,
|
||||
)
|
||||
.every(Boolean);
|
||||
|
||||
const totalServices =
|
||||
project?.environments.map((env) => env.mariadb.length +
|
||||
env.mongo.length +
|
||||
env.mysql.length +
|
||||
env.postgres.length +
|
||||
env.redis.length +
|
||||
env.applications.length +
|
||||
env.compose.length ).reduce((acc, curr) => acc + curr, 0);
|
||||
const totalServices = project?.environments
|
||||
.map(
|
||||
(env) =>
|
||||
env.mariadb.length +
|
||||
env.mongo.length +
|
||||
env.mysql.length +
|
||||
env.postgres.length +
|
||||
env.redis.length +
|
||||
env.applications.length +
|
||||
env.compose.length,
|
||||
)
|
||||
.reduce((acc, curr) => acc + curr, 0);
|
||||
|
||||
const haveServicesWithDomains =
|
||||
project?.environments.map((env) => env.applications.length > 0 ||
|
||||
env.compose.length > 0).some(Boolean);
|
||||
const haveServicesWithDomains = project?.environments
|
||||
.map(
|
||||
(env) =>
|
||||
env.applications.length > 0 ||
|
||||
env.compose.length > 0,
|
||||
)
|
||||
.some(Boolean);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -234,12 +246,14 @@ export const ShowProjects = () => {
|
||||
className="w-[200px] space-y-2 overflow-y-auto max-h-[400px]"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{project.environments.some((env) => env.applications.length > 0) && (
|
||||
{project.environments.some(
|
||||
(env) => env.applications.length > 0,
|
||||
) && (
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel>
|
||||
Applications
|
||||
</DropdownMenuLabel>
|
||||
{project.environments.map((env) =>
|
||||
{project.environments.map((env) =>
|
||||
env.applications.map((app) => (
|
||||
<div key={app.applicationId}>
|
||||
<DropdownMenuSeparator />
|
||||
@@ -247,7 +261,9 @@ export const ShowProjects = () => {
|
||||
<DropdownMenuLabel className="font-normal capitalize text-xs flex items-center justify-between">
|
||||
{app.name}
|
||||
<StatusTooltip
|
||||
status={app.applicationStatus}
|
||||
status={
|
||||
app.applicationStatus
|
||||
}
|
||||
/>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
@@ -270,7 +286,7 @@ export const ShowProjects = () => {
|
||||
))}
|
||||
</DropdownMenuGroup>
|
||||
</div>
|
||||
))
|
||||
)),
|
||||
)}
|
||||
</DropdownMenuGroup>
|
||||
)}
|
||||
@@ -445,7 +461,7 @@ export const ShowProjects = () => {
|
||||
<DateTooltip date={project.createdAt}>
|
||||
Created
|
||||
</DateTooltip>
|
||||
<span>
|
||||
<span>
|
||||
{totalServices}{" "}
|
||||
{totalServices === 1
|
||||
? "service"
|
||||
|
||||
@@ -325,7 +325,7 @@ export const AddUserPermissions = ({ userId }: Props) => {
|
||||
<FormLabel className="text-base">Projects</FormLabel>
|
||||
<FormDescription>
|
||||
Select the Projects that the user can access
|
||||
</FormDescription>
|
||||
</FormDescription>
|
||||
</div>
|
||||
{projects?.length === 0 && (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
|
||||
Reference in New Issue
Block a user