mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat: add show cluster
This commit is contained in:
parent
6c792564ae
commit
c45017e204
@ -62,8 +62,6 @@ export const AddRegistry = () => {
|
||||
resolver: zodResolver(AddRegistrySchema),
|
||||
});
|
||||
|
||||
console.log(form.formState.errors);
|
||||
|
||||
const password = form.watch("password");
|
||||
const username = form.watch("username");
|
||||
const registryUrl = form.watch("registryUrl");
|
||||
|
@ -23,8 +23,8 @@ export const ShowRegistry = () => {
|
||||
<Card className="bg-transparent h-full">
|
||||
<CardHeader className="flex flex-row gap-2 justify-between w-full items-center">
|
||||
<div className="flex flex-col gap-2">
|
||||
<CardTitle className="text-xl">Clusters</CardTitle>
|
||||
<CardDescription>Add cluster to your application.</CardDescription>
|
||||
<CardTitle className="text-xl">Registry</CardTitle>
|
||||
<CardDescription>Add registry to your application.</CardDescription>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row gap-2">
|
||||
|
80
components/dashboard/settings/cluster/worker/add-worker.tsx
Normal file
80
components/dashboard/settings/cluster/worker/add-worker.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { api } from "@/utils/api";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { AlertTriangle, PlusIcon } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
|
||||
const AddWorkerSchema = z.object({
|
||||
name: z.string().min(1, {
|
||||
message: "Name is required",
|
||||
}),
|
||||
description: z.string().optional(),
|
||||
});
|
||||
|
||||
type AddWorker = z.infer<typeof AddWorkerSchema>;
|
||||
|
||||
export const AddWorker = () => {
|
||||
const utils = api.useUtils();
|
||||
|
||||
const { data, isLoading } = api.cluster.addWorker.useQuery();
|
||||
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Worker
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-4xl max-h-screen overflow-y-auto ">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add a new worker</DialogTitle>
|
||||
<DialogDescription>Add a new worker</DialogDescription>
|
||||
</DialogHeader>
|
||||
{/* {isError && (
|
||||
<div className="flex flex-row gap-4 rounded-lg bg-red-50 p-2 dark:bg-red-950">
|
||||
<AlertTriangle className="text-red-600 dark:text-red-400" />
|
||||
<span className="text-sm text-red-600 dark:text-red-400">
|
||||
{error?.message}
|
||||
</span>
|
||||
</div>
|
||||
)} */}
|
||||
<div className="flex flex-col gap-4 text-sm">
|
||||
<span>1. Go to your new server and run the following command</span>
|
||||
<span className="bg-muted rounded-lg p-2">
|
||||
curl https://get.docker.com | sh -s -- --version 24.0
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4 text-sm">
|
||||
<span>
|
||||
2. Run the following command to add the node(server) to your cluster
|
||||
</span>
|
||||
<span className="bg-muted rounded-lg p-2 ">{data}</span>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
@ -0,0 +1,62 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
|
||||
import { api } from "@/utils/api";
|
||||
import { AddWorker } from "./add-worker";
|
||||
import { DateTooltip } from "@/components/shared/date-tooltip";
|
||||
|
||||
export const ShowCluster = () => {
|
||||
const { data, isLoading } = api.cluster.getWorkers.useQuery();
|
||||
// console.log(data)
|
||||
return (
|
||||
<Card className="bg-transparent h-full">
|
||||
<CardHeader className="flex flex-row gap-2 justify-between w-full items-center flex-wrap">
|
||||
<div className="flex flex-col gap-2">
|
||||
<CardTitle className="text-xl">Cluster</CardTitle>
|
||||
<CardDescription>Add nodes to your cluster</CardDescription>
|
||||
</div>
|
||||
<AddWorker />
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
<div className="grid md:grid-cols-1 gap-4">
|
||||
{isLoading && <div>Loading...</div>}
|
||||
{data?.map((worker, index) => (
|
||||
<div
|
||||
key={`key-${index}`}
|
||||
className="flex flex-row gap-4 w-full flex-wrap"
|
||||
>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{worker.Description.Hostname}
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{worker.Status.State}
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{worker.Spec.Availability}
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{worker.ManagerStatus.Reachability}
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{worker?.Spec?.Role}
|
||||
</span>
|
||||
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{worker?.Description.Engine.EngineVersion}
|
||||
</span>
|
||||
<DateTooltip date={worker.CreatedAt} className="text-sm">
|
||||
{/* <span className="text-sm text-muted-foreground">Created</span> */}
|
||||
</DateTooltip>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
@ -4,19 +4,26 @@ import {
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { format, formatDistanceToNow } from "date-fns";
|
||||
|
||||
interface Props {
|
||||
date: string;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const DateTooltip = ({ date, children }: Props) => {
|
||||
export const DateTooltip = ({ date, children, className }: Props) => {
|
||||
return (
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<span className="flex items-center text-muted-foreground text-left">
|
||||
<span
|
||||
className={cn(
|
||||
"flex items-center text-muted-foreground text-left",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}{" "}
|
||||
{formatDistanceToNow(new Date(date), {
|
||||
addSuffix: true,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ShowCertificates } from "@/components/dashboard/settings/certificates/show-certificates";
|
||||
import { ShowRegistry } from "@/components/dashboard/settings/cluster/registry/show-registry";
|
||||
import { ShowCluster } from "@/components/dashboard/settings/cluster/worker/show-workers";
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
import { SettingsLayout } from "@/components/layouts/settings-layout";
|
||||
import { validateRequest } from "@/server/auth/auth";
|
||||
@ -10,6 +11,7 @@ const Page = () => {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
<ShowRegistry />
|
||||
<ShowCluster />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -21,6 +21,7 @@ import { portRouter } from "./routers/port";
|
||||
import { adminRouter } from "./routers/admin";
|
||||
import { dockerRouter } from "./routers/docker";
|
||||
import { registryRouter } from "./routers/registry";
|
||||
import { clusterRouter } from "./routers/cluster";
|
||||
/**
|
||||
* This is the primary router for your server.
|
||||
*
|
||||
@ -49,6 +50,7 @@ export const appRouter = createTRPCRouter({
|
||||
redirects: redirectsRouter,
|
||||
port: portRouter,
|
||||
registry: registryRouter,
|
||||
cluster: clusterRouter,
|
||||
});
|
||||
|
||||
// export type definition of API
|
||||
|
17
server/api/routers/cluster.ts
Normal file
17
server/api/routers/cluster.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { docker } from "@/server/constants";
|
||||
import { createTRPCRouter, protectedProcedure } from "../trpc";
|
||||
import { getPublicIpWithFallback } from "@/server/wss/terminal";
|
||||
|
||||
export const clusterRouter = createTRPCRouter({
|
||||
getWorkers: protectedProcedure.query(async () => {
|
||||
const workers = await docker.listNodes();
|
||||
// console.log(workers);
|
||||
return workers;
|
||||
}),
|
||||
addWorker: protectedProcedure.query(async ({ input }) => {
|
||||
const result = await docker.swarmInspect();
|
||||
return `docker swarm join --token ${
|
||||
result.JoinTokens.Worker
|
||||
} ${await getPublicIpWithFallback()}:2377`;
|
||||
}),
|
||||
});
|
Loading…
Reference in New Issue
Block a user