feat(multi-server): add actions to the server

This commit is contained in:
Mauricio Siu
2024-09-21 00:06:41 -06:00
parent 0b22b694e6
commit 497d45129c
15 changed files with 684 additions and 134 deletions

View File

@@ -49,13 +49,7 @@ export const SetupServer = ({ serverId }: Props) => {
},
);
const { mutateAsync, isLoading } = api.server.setup.useMutation({
onMutate: async (variables) => {
console.log("Running....");
refetch();
// refetch();
},
});
const { mutateAsync, isLoading } = api.server.setup.useMutation();
return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
@@ -99,7 +93,7 @@ export const SetupServer = ({ serverId }: Props) => {
serverId: server?.serverId || "",
})
.then(async () => {
// refetch();
refetch();
toast.success("Server setup successfully");
})
.catch(() => {

View File

@@ -6,6 +6,7 @@ import {
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
@@ -26,11 +27,45 @@ import { TerminalModal } from "../web-server/terminal-modal";
import { AddServer } from "./add-server";
import { SetupServer } from "./setup-server";
import { UpdateServer } from "./update-server";
import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal";
import { ShowModalLogs } from "../web-server/show-modal-logs";
export const ShowServers = () => {
const { data, refetch } = api.server.all.useQuery();
const { mutateAsync } = api.server.remove.useMutation();
const { data: sshKeys } = api.sshKey.all.useQuery();
const { mutateAsync: toggleDashboard, isLoading: toggleDashboardIsLoading } =
api.settings.toggleDashboard.useMutation();
const {
mutateAsync: cleanDockerBuilder,
isLoading: cleanDockerBuilderIsLoading,
} = api.settings.cleanDockerBuilder.useMutation();
const {
mutateAsync: cleanUnusedImages,
isLoading: cleanUnusedImagesIsLoading,
} = api.settings.cleanUnusedImages.useMutation();
const { mutateAsync: reloadTraefik, isLoading: reloadTraefikIsLoading } =
api.settings.reloadTraefik.useMutation();
const {
mutateAsync: cleanUnusedVolumes,
isLoading: cleanUnusedVolumesIsLoading,
} = api.settings.cleanUnusedVolumes.useMutation();
const {
mutateAsync: cleanStoppedContainers,
isLoading: cleanStoppedContainersIsLoading,
} = api.settings.cleanStoppedContainers.useMutation();
const { mutateAsync: cleanAll, isLoading: cleanAllIsLoading } =
api.settings.cleanAll.useMutation();
const { data: haveTraefikDashboardPortEnabled, refetch: refetchDashboard } =
api.settings.haveTraefikDashboardPortEnabled.useQuery();
return (
<div className="p-6 space-y-6">
<div className="space-y-2 flex flex-row justify-between items-end">
@@ -116,7 +151,17 @@ export const ShowServers = () => {
<TableCell className="text-right flex justify-end">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<DropdownMenuTrigger
asChild
disabled={
cleanAllIsLoading ||
cleanDockerBuilderIsLoading ||
cleanUnusedImagesIsLoading ||
cleanUnusedVolumesIsLoading ||
cleanStoppedContainersIsLoading ||
reloadTraefikIsLoading
}
>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
<MoreHorizontal className="h-4 w-4" />
@@ -128,6 +173,7 @@ export const ShowServers = () => {
<span>Enter the terminal</span>
</TerminalModal>
<SetupServer serverId={server.serverId} />
<UpdateServer serverId={server.serverId} />
<DialogAction
title={"Delete Server"}
@@ -154,6 +200,150 @@ export const ShowServers = () => {
Delete Server
</DropdownMenuItem>
</DialogAction>
<DropdownMenuSeparator />
<DropdownMenuLabel>Traefik</DropdownMenuLabel>
<DropdownMenuItem
onClick={async () => {
await reloadTraefik({
serverId: server.serverId,
})
.then(async () => {
toast.success("Traefik Reloaded");
})
.catch(() => {
toast.error("Error to reload the traefik");
});
}}
>
<span>Reload</span>
</DropdownMenuItem>
<ShowTraefikFileSystemModal
serverId={server.serverId}
/>
<ShowModalLogs
appName="dokploy-traefik"
serverId={server.serverId}
>
<span>Watch logs</span>
</ShowModalLogs>
{/* <DropdownMenuItem
onClick={async () => {
await toggleDashboard({
enableDashboard:
!haveTraefikDashboardPortEnabled,
serverId: server.serverId,
})
.then(async () => {
toast.success(
`${haveTraefikDashboardPortEnabled ? "Disabled" : "Enabled"} Dashboard`,
);
refetchDashboard();
})
.catch(() => {
toast.error(
`${haveTraefikDashboardPortEnabled ? "Disabled" : "Enabled"} Dashboard`,
);
});
}}
className="w-full cursor-pointer space-x-3"
>
<span>
{haveTraefikDashboardPortEnabled
? "Disable"
: "Enable"}{" "}
Dashboard
</span>
</DropdownMenuItem> */}
<DropdownMenuSeparator />
<DropdownMenuLabel>Storage</DropdownMenuLabel>
<DropdownMenuItem
className="w-full cursor-pointer"
onClick={async () => {
await cleanUnusedImages({
serverId: server?.serverId,
})
.then(async () => {
toast.success("Cleaned images");
})
.catch(() => {
toast.error("Error to clean images");
});
}}
>
<span>Clean unused images</span>
</DropdownMenuItem>
<DropdownMenuItem
className="w-full cursor-pointer"
onClick={async () => {
await cleanUnusedVolumes({
serverId: server?.serverId,
})
.then(async () => {
toast.success("Cleaned volumes");
})
.catch(() => {
toast.error("Error to clean volumes");
});
}}
>
<span>Clean unused volumes</span>
</DropdownMenuItem>
<DropdownMenuItem
className="w-full cursor-pointer"
onClick={async () => {
await cleanStoppedContainers({
serverId: server?.serverId,
})
.then(async () => {
toast.success("Stopped containers cleaned");
})
.catch(() => {
toast.error(
"Error to clean stopped containers",
);
});
}}
>
<span>Clean stopped containers</span>
</DropdownMenuItem>
<DropdownMenuItem
className="w-full cursor-pointer"
onClick={async () => {
await cleanDockerBuilder({
serverId: server?.serverId,
})
.then(async () => {
toast.success("Cleaned Docker Builder");
})
.catch(() => {
toast.error(
"Error to clean Docker Builder",
);
});
}}
>
<span>Clean Docker Builder & System</span>
</DropdownMenuItem>
<DropdownMenuItem
className="w-full cursor-pointer"
onClick={async () => {
await cleanAll({
serverId: server?.serverId,
})
.then(async () => {
toast.success("Cleaned all");
})
.catch(() => {
toast.error("Error to clean all");
});
}}
>
<span>Clean all</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</TableCell>

View File

@@ -0,0 +1,48 @@
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
import { FileTextIcon } from "lucide-react";
import { useState } from "react";
import { ShowTraefikSystem } from "../../file-system/show-traefik-system";
interface Props {
serverId: string;
}
export const ShowTraefikFileSystemModal = ({ serverId }: Props) => {
const [isOpen, setIsOpen] = useState(false);
return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>
<DropdownMenuItem
className="w-full cursor-pointer "
onSelect={(e) => e.preventDefault()}
>
Show Traefik File System
</DropdownMenuItem>
</DialogTrigger>
<DialogContent className="sm:max-w-7xl overflow-y-auto max-h-screen ">
<DialogHeader>
<div className="flex flex-col gap-1.5">
<DialogTitle className="flex items-center gap-2">
<FileTextIcon className="size-5" /> Traefik File System
</DialogTitle>
<p className="text-muted-foreground text-sm">
See all the files and directories of your traefik configuration
</p>
</div>
</DialogHeader>
<div id="hook-form-add-gitlab" className="grid w-full gap-1">
<ShowTraefikSystem serverId={serverId} />
</div>
</DialogContent>
</Dialog>
);
};

View File

@@ -33,12 +33,15 @@ type Schema = z.infer<typeof schema>;
interface Props {
children?: React.ReactNode;
serverId?: string;
}
export const EditTraefikEnv = ({ children }: Props) => {
export const EditTraefikEnv = ({ children, serverId }: Props) => {
const [canEdit, setCanEdit] = useState(true);
const { data } = api.settings.readTraefikEnv.useQuery();
const { data } = api.settings.readTraefikEnv.useQuery({
serverId,
});
const { mutateAsync, isLoading, error, isError } =
api.settings.writeTraefikEnv.useMutation();

View File

@@ -36,12 +36,14 @@ export const DockerLogsId = dynamic(
interface Props {
appName: string;
children?: React.ReactNode;
serverId?: string;
}
export const ShowModalLogs = ({ appName, children }: Props) => {
export const ShowModalLogs = ({ appName, children, serverId }: Props) => {
const { data, isLoading } = api.docker.getContainersByAppLabel.useQuery(
{
appName,
serverId,
},
{
enabled: !!appName,
@@ -96,7 +98,11 @@ export const ShowModalLogs = ({ appName, children }: Props) => {
</SelectGroup>
</SelectContent>
</Select>
<DockerLogsId id="terminal" containerId={containerId || ""} />
<DockerLogsId
id="terminal"
containerId={containerId || ""}
serverId={serverId}
/>
</div>
</DialogContent>
</Dialog>