From c2b84fbe9f9a7625f71a6240546c68f7739942fd Mon Sep 17 00:00:00 2001 From: Derock Date: Wed, 24 Jan 2024 22:19:07 -0500 Subject: [PATCH] wip: domains page --- .../containers/_components/ContainerEntry.tsx | 59 ++++++++++------ .../service/[serviceId]/containers/page.tsx | 8 +-- .../[serviceId]/domains/DomainsList.tsx | 68 +++++++++++++++++++ .../service/[serviceId]/domains/page.tsx | 7 ++ src/server/docker/stack.ts | 3 +- 5 files changed, 119 insertions(+), 26 deletions(-) create mode 100644 src/app/(dashboard)/project/[projectId]/service/[serviceId]/domains/DomainsList.tsx create mode 100644 src/app/(dashboard)/project/[projectId]/service/[serviceId]/domains/page.tsx diff --git a/src/app/(dashboard)/project/[projectId]/service/[serviceId]/containers/_components/ContainerEntry.tsx b/src/app/(dashboard)/project/[projectId]/service/[serviceId]/containers/_components/ContainerEntry.tsx index fa574c5..dac3c3e 100644 --- a/src/app/(dashboard)/project/[projectId]/service/[serviceId]/containers/_components/ContainerEntry.tsx +++ b/src/app/(dashboard)/project/[projectId]/service/[serviceId]/containers/_components/ContainerEntry.tsx @@ -2,6 +2,7 @@ import { formatDistanceToNowStrict } from "date-fns"; import { ClipboardIcon } from "lucide-react"; +import { useEffect, useState } from "react"; import { CgSpinner } from "react-icons/cg"; import { FaGear } from "react-icons/fa6"; import { toast } from "sonner"; @@ -17,16 +18,28 @@ import { TableCell, TableRow } from "~/components/ui/table"; import { type RouterOutputs } from "~/trpc/shared"; export function ContainerEntry({ - data: { container, previous, task, slot }, + data: { container, previous, task }, }: { data: RouterOutputs["projects"]["services"]["containers"]["latest"][number]; }) { const mainContainer = container ?? previous[0]?.container; - const isRedeploying = container === undefined; + const isRedeploying = + container === undefined || task.taskState === "starting"; + + const [uptimeText, setUptimeText] = useState(null); + useEffect(() => { + if (!mainContainer) return; + const interval = setInterval(() => { + setUptimeText( + formatDistanceToNowStrict(mainContainer.containerCreatedAt), + ); + }, 1000); + return () => clearInterval(interval); + }, [mainContainer]); return ( <> - + { @@ -65,30 +78,17 @@ export function ContainerEntry({ strokeWidth={1.5} className="py-auto mr-2 inline-block animate-spin stroke-muted-foreground" /> - Redeploying - {previous[0]?.container?.error && ( - - {" "} - (previous container errored with:{" "} - {previous[0]?.container?.error}) - - )} + Container Deploying ) : ( - task.taskState ?? task.taskMessage ?? "unknown" - )} - - {container?.error && ( - - {" "} - (errored with: {container.error}) + + {task.taskState ?? task.taskMessage ?? "unknown"} )} + + {uptimeText ?? "N/A"} {mainContainer?.node ?? "unknown"} - - {formatDistanceToNowStrict(mainContainer?.containerCreatedAt ?? 0)} - {mainContainer?.cpu ?? "?"} {mainContainer?.memory ?? "?"} @@ -110,6 +110,23 @@ export function ContainerEntry({ + + {container?.error !== undefined || + previous[0]?.container?.error !== undefined ? ( + + + + {container?.error + ? "Container exited with:" + : "Previous container exited with:"}{" "} +
+
+              {container?.error ?? previous[0]?.container?.error}
+            
+
+
+
+ ) : undefined} ); } diff --git a/src/app/(dashboard)/project/[projectId]/service/[serviceId]/containers/page.tsx b/src/app/(dashboard)/project/[projectId]/service/[serviceId]/containers/page.tsx index 6da8a46..3d7ddde 100644 --- a/src/app/(dashboard)/project/[projectId]/service/[serviceId]/containers/page.tsx +++ b/src/app/(dashboard)/project/[projectId]/service/[serviceId]/containers/page.tsx @@ -30,11 +30,11 @@ export default function Containers() { Container ID - Status - Node + Status Uptime - CPU Usage - Memory Usage + Node + CPU + Memory Network (RX/TX) Actions diff --git a/src/app/(dashboard)/project/[projectId]/service/[serviceId]/domains/DomainsList.tsx b/src/app/(dashboard)/project/[projectId]/service/[serviceId]/domains/DomainsList.tsx new file mode 100644 index 0000000..d29cba4 --- /dev/null +++ b/src/app/(dashboard)/project/[projectId]/service/[serviceId]/domains/DomainsList.tsx @@ -0,0 +1,68 @@ +"use client"; + +import { useFieldArray } from "react-hook-form"; +import { z } from "zod"; +import { Form } from "~/components/ui/form"; +import { FormSubmit, SimpleFormField, useForm } from "~/hooks/forms"; + +const formValidator = z.object({ + domains: z.array( + z.object({ + domain: z + .string() + .regex( + /(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]/, + { message: "Invalid domain name" }, + ), + + internalPort: z.number().int().min(1).max(65535), + https: z.boolean(), + forceSSL: z.boolean(), + }), + ), +}); + +export default function DomainsList( + { + // service, + }: { + // service: RouterOutputs["projects"]["services"]["get"]; + }, +) { + const form = useForm(formValidator, { + defaultValues: {}, + }); + const { fields, append, prepend, remove, swap, move, insert } = useFieldArray( + { + control: form.control, + name: "domains", + }, + ); + + return ( +
+ { + console.log(data); + })} + className="grid grid-cols-2 gap-4" + > +

Domains

+ + {fields.map((field, index) => ( +
+ +
+ ))} + + + + + ); +} diff --git a/src/app/(dashboard)/project/[projectId]/service/[serviceId]/domains/page.tsx b/src/app/(dashboard)/project/[projectId]/service/[serviceId]/domains/page.tsx new file mode 100644 index 0000000..862d8c6 --- /dev/null +++ b/src/app/(dashboard)/project/[projectId]/service/[serviceId]/domains/page.tsx @@ -0,0 +1,7 @@ +export default function DomainsPage() { + return ( +
+
+ ) +} \ No newline at end of file diff --git a/src/server/docker/stack.ts b/src/server/docker/stack.ts index 651374f..7b13851 100644 --- a/src/server/docker/stack.ts +++ b/src/server/docker/stack.ts @@ -110,7 +110,8 @@ export async function buildDockerStackFile( logging: { driver: "json-file", options: { - "max-size": service.loggingMaxSize, + "max-size": + service.loggingMaxSize === "-1" ? null : service.loggingMaxSize, "max-file": service.loggingMaxFiles, }, },