fix: dashboard layout styles (#86)

* fix: dashboard layout scroll

* feat: dashboard nav style animation

* chore: code input font

* style: format code

* pref: alert component extraction

* fix: global font var not found

* fix: code path beak line

* chore: remove framer-motion

* fix: status color
This commit is contained in:
木头981
2024-05-18 11:43:52 +08:00
committed by GitHub
parent b4c07ce6d1
commit d539b80ef7
57 changed files with 502 additions and 536 deletions

View File

@@ -26,11 +26,11 @@ interface Props {
applicationId: string;
}
const AddRedirectchema = z.object({
const AddRedirectSchema = z.object({
command: z.string(),
});
type AddCommand = z.infer<typeof AddRedirectchema>;
type AddCommand = z.infer<typeof AddRedirectSchema>;
export const AddCommand = ({ applicationId }: Props) => {
const { data } = api.application.one.useQuery(
@@ -48,7 +48,7 @@ export const AddCommand = ({ applicationId }: Props) => {
defaultValues: {
command: "",
},
resolver: zodResolver(AddRedirectchema),
resolver: zodResolver(AddRedirectSchema),
});
useEffect(() => {

View File

@@ -18,8 +18,8 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -33,7 +33,7 @@ import {
} from "@/components/ui/select";
import { z } from "zod";
const AddPortchema = z.object({
const AddPortSchema = z.object({
publishedPort: z.number().int().min(1).max(65535),
targetPort: z.number().int().min(1).max(65535),
protocol: z.enum(["tcp", "udp"], {
@@ -41,7 +41,7 @@ const AddPortchema = z.object({
}),
});
type AddPort = z.infer<typeof AddPortchema>;
type AddPort = z.infer<typeof AddPortSchema>;
interface Props {
applicationId: string;
@@ -62,7 +62,7 @@ export const AddPort = ({
publishedPort: 0,
targetPort: 0,
},
resolver: zodResolver(AddPortchema),
resolver: zodResolver(AddPortSchema),
});
useEffect(() => {
@@ -100,14 +100,7 @@ export const AddPort = ({
Ports are used to expose your application to the internet.
</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -18,8 +18,9 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, Pencil } from "lucide-react";
import { Pencil } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -106,14 +107,7 @@ export const UpdatePort = ({ portId }: Props) => {
<DialogTitle>Update</DialogTitle>
<DialogDescription>Update the port</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -19,8 +19,8 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -98,14 +98,7 @@ export const AddRedirect = ({
Redirects are used to redirect requests to another url.
</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -19,8 +19,9 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, Pencil } from "lucide-react";
import { Pencil } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -101,14 +102,7 @@ export const UpdateRedirect = ({ redirectId }: Props) => {
<DialogTitle>Update</DialogTitle>
<DialogDescription>Update the redirect</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -18,8 +18,8 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -90,14 +90,7 @@ export const AddSecurity = ({
Add security to your application
</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -18,8 +18,9 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, Pencil } from "lucide-react";
import { Pencil } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -96,14 +97,7 @@ export const UpdateSecurity = ({ securityId }: Props) => {
<DialogTitle>Update</DialogTitle>
<DialogDescription>Update the security</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -18,8 +18,8 @@ import {
} from "@/components/ui/form";
import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -116,14 +116,7 @@ export const UpdateTraefikConfig = ({ applicationId }: Props) => {
<DialogTitle>Update traefik config</DialogTitle>
<DialogDescription>Update the traefik config</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form
@@ -140,7 +133,7 @@ export const UpdateTraefikConfig = ({ applicationId }: Props) => {
<FormLabel>Traefik config</FormLabel>
<FormControl>
<Textarea
className="h-[35rem]"
className="h-[35rem] font-mono"
placeholder={`http:
routers:
router-name:

View File

@@ -147,7 +147,7 @@ export const AddVolumes = ({
<DialogTitle>Volumes / Mounts</DialogTitle>
</DialogHeader>
{/* {isError && (
<div className="flex flex-row gap-4 rounded-lg bg-red-50 p-2 dark:bg-red-950">
<div className="flex items-center 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}

View File

@@ -27,8 +27,9 @@ import {
} from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, PlusIcon } from "lucide-react";
import { PlusIcon } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -106,14 +107,7 @@ export const AddDomain = ({
In this section you can add custom domains
</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -27,8 +27,9 @@ import {
} from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, PenBoxIcon } from "lucide-react";
import { PenBoxIcon } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -125,14 +126,7 @@ export const UpdateDomain = ({ domainId }: Props) => {
In this section you can add custom domains
</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -96,7 +96,7 @@ export const ShowEnvironment = ({ applicationId }: Props) => {
<FormControl>
<Textarea
placeholder="NODE_ENV=production"
className="h-96"
className="h-96 font-mono"
{...field}
/>
</FormControl>

View File

@@ -18,6 +18,7 @@ import {
} from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
@@ -97,14 +98,7 @@ export const UpdateApplication = ({ applicationId }: Props) => {
<DialogTitle>Modify Application</DialogTitle>
<DialogDescription>Update the application data</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<div className="grid gap-4">
<div className="grid items-center gap-4">

View File

@@ -32,14 +32,14 @@ export const ShowContainerConfig = ({ containerId }: Props) => {
View Config
</DropdownMenuItem>
</DialogTrigger>
<DialogContent className={"sm:max-w-5xl overflow-y-auto max-h-screen"}>
<DialogContent className={"w-full md:w-[70vw] max-w-max"}>
<DialogHeader>
<DialogTitle>Container Config</DialogTitle>
<DialogDescription>
See in detail the config of this container
</DialogDescription>
</DialogHeader>
<div className="text-wrap rounded-lg border p-4 text-sm sm:max-w-[59rem] bg-card">
<div className="text-wrap rounded-lg border p-4 text-sm bg-card overflow-y-auto max-h-[80vh]">
<code>
<pre className="whitespace-pre-wrap break-words">
{JSON.stringify(data, null, 2)}

View File

@@ -24,11 +24,12 @@ export const DockerLogsId: React.FC<Props> = ({ id, containerId }) => {
cols: 80,
rows: 30,
lineHeight: 1.4,
fontWeight: 400,
convertEol: true,
theme: {
cursor: "transparent",
background: "#19191A",
background: "rgba(0, 0, 0, 0)",
},
});
@@ -81,8 +82,8 @@ export const DockerLogsId: React.FC<Props> = ({ id, containerId }) => {
/>
</div>
<div className="w-full h-full bg-input rounded-lg p-2 ">
<div id={id} className="rounded-xl" />
<div className="w-full h-full rounded-lg p-2 bg-[#19191A]">
<div id={id} />
</div>
</div>
);

View File

@@ -1,4 +1,3 @@
import React from "react";
import {
Dialog,
DialogContent,

View File

@@ -3,7 +3,7 @@ import { Terminal } from "@xterm/xterm";
import { FitAddon } from "xterm-addon-fit";
import "@xterm/xterm/css/xterm.css";
import { AttachAddon } from "@xterm/addon-attach";
import { Button } from "@/components/ui/button";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
interface Props {
id: string;
@@ -12,7 +12,7 @@ interface Props {
export const DockerTerminal: React.FC<Props> = ({ id, containerId }) => {
const termRef = useRef(null);
const [activeWay, setActiveWay] = React.useState<string | null>("bash");
const [activeWay, setActiveWay] = React.useState<string | undefined>("bash");
useEffect(() => {
const container = document.getElementById(id);
if (container) {
@@ -26,7 +26,7 @@ export const DockerTerminal: React.FC<Props> = ({ id, containerId }) => {
convertEol: true,
theme: {
cursor: "transparent",
background: "#19191A",
background: "rgba(0, 0, 0, 0)",
},
});
const addonFit = new FitAddon();
@@ -54,14 +54,15 @@ export const DockerTerminal: React.FC<Props> = ({ id, containerId }) => {
<span>
Select way to connect to <b>{containerId}</b>
</span>
<div className="flex flex-row gap-4 w-fit">
<Button onClick={() => setActiveWay("sh")}>SH</Button>
<Button onClick={() => setActiveWay("bash")}>Bash</Button>
<Button onClick={() => setActiveWay("sh")}>/bin/sh</Button>
</div>
<Tabs value={activeWay} onValueChange={setActiveWay}>
<TabsList>
<TabsTrigger value="bash">Bash</TabsTrigger>
<TabsTrigger value="sh">/bin/sh</TabsTrigger>
</TabsList>
</Tabs>
</div>
<div className="w-full h-full bg-input rounded-lg p-2 ">
<div id={id} ref={termRef} className="rounded-xl" />
<div className="w-full h-full rounded-lg p-2 bg-[#19191A]">
<div id={id} ref={termRef} />
</div>
</div>
);

View File

@@ -11,6 +11,7 @@ import {
} from "@/components/ui/form";
import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect, useState } from "react";
@@ -86,19 +87,12 @@ export const ShowTraefikFile = ({ path }: Props) => {
return (
<div>
{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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="grid w-full py-4 relative"
className="grid w-full relative"
>
<div className="flex flex-col">
<FormField
@@ -107,10 +101,12 @@ export const ShowTraefikFile = ({ path }: Props) => {
render={({ field }) => (
<FormItem className="relative">
<FormLabel>Traefik config</FormLabel>
<FormDescription>{path}</FormDescription>
<FormDescription className="break-all">
{path}
</FormDescription>
<FormControl>
<Textarea
className="h-[35rem]"
className="h-[35rem] font-mono"
placeholder={`http:
routers:
router-name:
@@ -128,8 +124,9 @@ routers:
<pre>
<FormMessage />
</pre>
<div className="flex justify-end absolute z-50 right-6 top-10">
<div className="flex justify-end absolute z-50 right-6 top-8">
<Button
className="shadow-sm"
variant="secondary"
type="button"
onClick={async () => {

View File

@@ -13,7 +13,7 @@ export const ShowTraefikSystem = () => {
const { data: directories } = api.settings.readDirectories.useQuery();
return (
<div className={cn("mt-6 grid gap-4 pb-20")}>
<div className={cn("mt-6 md:grid gap-4")}>
<div className="flex flex-col md:flex-row gap-4 md:gap-10 w-full">
{directories?.length === 0 && (
<div className="w-full flex-col gap-2 flex items-center justify-center h-[55vh]">

View File

@@ -95,7 +95,7 @@ export const ShowMariadbEnvironment = ({ mariadbId }: Props) => {
<FormControl>
<Textarea
placeholder="MARIADB_PASSWORD=1234567678"
className="h-96"
className="h-96 font-mono"
{...field}
/>
</FormControl>

View File

@@ -18,6 +18,7 @@ import {
} from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
@@ -97,14 +98,7 @@ export const UpdateMariadb = ({ mariadbId }: Props) => {
<DialogTitle>Modify MariaDB</DialogTitle>
<DialogDescription>Update the MariaDB data</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<div className="grid gap-4">
<div className="grid items-center gap-4">

View File

@@ -95,7 +95,7 @@ export const ShowMongoEnvironment = ({ mongoId }: Props) => {
<FormControl>
<Textarea
placeholder="MONGO_PASSWORD=1234567678"
className="h-96"
className="h-96 font-mono"
{...field}
/>
</FormControl>

View File

@@ -18,6 +18,7 @@ import {
} from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
@@ -97,14 +98,7 @@ export const UpdateMongo = ({ mongoId }: Props) => {
<DialogTitle>Modify MongoDB</DialogTitle>
<DialogDescription>Update the MongoDB data</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<div className="grid gap-4">
<div className="grid items-center gap-4">

View File

@@ -95,7 +95,7 @@ export const ShowMysqlEnvironment = ({ mysqlId }: Props) => {
<FormControl>
<Textarea
placeholder="MYSQL_PASSWORD=1234567678"
className="h-96"
className="h-96 font-mono"
{...field}
/>
</FormControl>

View File

@@ -18,6 +18,7 @@ import {
} from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
@@ -97,14 +98,7 @@ export const UpdateMysql = ({ mysqlId }: Props) => {
<DialogTitle>Modify MySQL</DialogTitle>
<DialogDescription>Update the MySQL data</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<div className="grid gap-4">
<div className="grid items-center gap-4">

View File

@@ -95,7 +95,7 @@ export const ShowPostgresEnvironment = ({ postgresId }: Props) => {
<FormControl>
<Textarea
placeholder="POSTGRES_PASSWORD=1234567678"
className="h-96"
className="h-96 font-mono"
{...field}
/>
</FormControl>

View File

@@ -18,6 +18,7 @@ import {
} from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
@@ -97,14 +98,7 @@ export const UpdatePostgres = ({ postgresId }: Props) => {
<DialogTitle>Modify Postgres</DialogTitle>
<DialogDescription>Update the Postgres data</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<div className="grid gap-4">
<div className="grid items-center gap-4">

View File

@@ -18,9 +18,10 @@ import {
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { AlertBlock } from "@/components/shared/alert-block";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, Folder } from "lucide-react";
import { Folder } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -93,14 +94,7 @@ export const AddApplication = ({ projectId }: Props) => {
Assign a name and description to your application
</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -235,7 +235,7 @@ export const AddDatabase = ({ projectId }: Props) => {
<DialogTitle>Databases</DialogTitle>
</DialogHeader>
{/* {isError && (
<div className="flex flex-row gap-4 rounded-lg bg-red-50 p-2 dark:bg-red-950">
<div className="flex items-center 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}

View File

@@ -19,8 +19,9 @@ import {
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, PlusIcon } from "lucide-react";
import { PlusIcon } from "lucide-react";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
@@ -85,14 +86,7 @@ export const AddProject = () => {
<DialogTitle>Add a project</DialogTitle>
<DialogDescription>The home of something big!</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form
id="hook-form-add-project"

View File

@@ -48,9 +48,9 @@ export const ShowProjects = () => {
return (
<>
{data?.length === 0 && (
<div className="mt-6 flex h-[50vh] w-full flex-col items-center justify-center ">
<FolderInput className="size-10 md:size-28 text-muted" />
<span className="text-center font-medium text-muted-foreground">
<div className="mt-6 flex h-[50vh] w-full flex-col items-center justify-center space-y-4">
<FolderInput className="size-10 md:size-28 text-muted-foreground" />
<span className="text-center font-medium text-muted-foreground">
No projects added yet. Click on Create project.
</span>
</div>

View File

@@ -18,6 +18,7 @@ import {
} from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
@@ -101,14 +102,7 @@ export const UpdateProject = ({ projectId }: Props) => {
Update the details of the project
</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<div className="grid gap-4">
<div className="grid items-center gap-4">

View File

@@ -18,6 +18,7 @@ import {
} from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
@@ -97,14 +98,7 @@ export const UpdateRedis = ({ redisId }: Props) => {
<DialogTitle>Modify Redis</DialogTitle>
<DialogDescription>Update the redis data</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<div className="grid gap-4">
<div className="grid items-center gap-4">

View File

@@ -1,24 +1,25 @@
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
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 { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect } from "react";
@@ -26,140 +27,135 @@ import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const certificateDataHolder = `-----BEGIN CERTIFICATE-----\nMIIFRDCCAyygAwIBAgIUEPOR47ys6VDwMVB9tYoeEka83uQwDQYJKoZIhvcNAQELBQAwGTEXMBUGA1UEAwwObWktZG9taW5pby5jb20wHhcNMjQwMzExMDQyNzU3WhcN\n------END CERTIFICATE-----`;
const addCertificate = z.object({
name: z.string().min(1, "Name is required"),
certificateData: z.string().min(1, "Certificate data is required"),
privateKey: z.string().min(1, "Private key is required"),
autoRenew: z.boolean().optional(),
name: z.string().min(1, "Name is required"),
certificateData: z.string().min(1, "Certificate data is required"),
privateKey: z.string().min(1, "Private key is required"),
autoRenew: z.boolean().optional(),
});
type AddCertificate = z.infer<typeof addCertificate>;
export const AddCertificate = () => {
const utils = api.useUtils();
const utils = api.useUtils();
const { mutateAsync, isError, error, isLoading } =
api.certificates.create.useMutation();
const { mutateAsync, isError, error, isLoading } =
api.certificates.create.useMutation();
const form = useForm<AddCertificate>({
defaultValues: {
name: "",
certificateData: "",
privateKey: "",
autoRenew: false,
},
resolver: zodResolver(addCertificate),
});
useEffect(() => {
form.reset();
}, [form, form.formState.isSubmitSuccessful, form.reset]);
const form = useForm<AddCertificate>({
defaultValues: {
name: "",
certificateData: "",
privateKey: "",
autoRenew: false,
},
resolver: zodResolver(addCertificate),
});
useEffect(() => {
form.reset();
}, [form, form.formState.isSubmitSuccessful, form.reset]);
const onSubmit = async (data: AddCertificate) => {
await mutateAsync({
name: data.name,
certificateData: data.certificateData,
privateKey: data.privateKey,
autoRenew: data.autoRenew,
})
.then(async () => {
toast.success("Certificate Created");
await utils.certificates.all.invalidate();
})
.catch(() => {
toast.error("Error to create the Certificate");
});
};
return (
<Dialog>
<DialogTrigger className="" asChild>
<Button>Add Certificate</Button>
</DialogTrigger>
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-2xl">
<DialogHeader>
<DialogTitle>Add Certificate</DialogTitle>
<DialogDescription>Add a new certificate</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>
)}
const onSubmit = async (data: AddCertificate) => {
await mutateAsync({
name: data.name,
certificateData: data.certificateData,
privateKey: data.privateKey,
autoRenew: data.autoRenew,
})
.then(async () => {
toast.success("Certificate Created");
await utils.certificates.all.invalidate();
})
.catch(() => {
toast.error("Error to create the Certificate");
});
};
return (
<Dialog>
<DialogTrigger className="" asChild>
<Button>Add Certificate</Button>
</DialogTrigger>
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-2xl">
<DialogHeader>
<DialogTitle>Add Certificate</DialogTitle>
<DialogDescription>Add a new certificate</DialogDescription>
</DialogHeader>
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form
id="hook-form-add-certificate"
onSubmit={form.handleSubmit(onSubmit)}
className="grid w-full gap-4 "
>
<FormField
control={form.control}
name="name"
render={({ field }) => {
return (
<FormItem>
<FormLabel>Certificate Name</FormLabel>
<FormControl>
<Input placeholder={"My Certificate"} {...field} />
</FormControl>
<FormMessage />
</FormItem>
);
}}
/>
<FormField
control={form.control}
name="certificateData"
render={({ field }) => (
<FormItem>
<div className="space-y-0.5">
<FormLabel>Certificate Data</FormLabel>
</div>
<FormControl>
<Textarea
className="h-32"
placeholder={`-----BEGIN CERTIFICATE-----\nMIIFRDCCAyygAwIBAgIUEPOR47ys6VDwMVB9tYoeEka83uQwDQYJKoZIhvcNAQELBQAwGTEXMBUGA1UEAwwObWktZG9taW5pby5jb20wHhcNMjQwMzExMDQyNzU3WhcN\n------END CERTIFICATE-----`}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="privateKey"
render={({ field }) => (
<FormItem>
<div className="space-y-0.5">
<FormLabel>Private Key</FormLabel>
</div>
<FormControl>
<Textarea
className="h-32"
placeholder={`-----BEGIN CERTIFICATE-----\nMIIFRDCCAyygAwIBAgIUEPOR47ys6VDwMVB9tYoeEka83uQwDQYJKoZIhvcNAQELBQAwGTEXMBUGA1UEAwwObWktZG9taW5pby5jb20wHhcNMjQwMzExMDQyNzU3WhcN\n------END CERTIFICATE-----`}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
<Form {...form}>
<form
id="hook-form-add-certificate"
onSubmit={form.handleSubmit(onSubmit)}
className="grid w-full gap-4 "
>
<FormField
control={form.control}
name="name"
render={({ field }) => {
return (
<FormItem>
<FormLabel>Certificate Name</FormLabel>
<FormControl>
<Input placeholder={"My Certificate"} {...field} />
</FormControl>
<FormMessage />
</FormItem>
);
}}
/>
<FormField
control={form.control}
name="certificateData"
render={({ field }) => (
<FormItem>
<div className="space-y-0.5">
<FormLabel>Certificate Data</FormLabel>
</div>
<FormControl>
<Textarea
className="h-32"
placeholder={certificateDataHolder}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="privateKey"
render={({ field }) => (
<FormItem>
<div className="space-y-0.5">
<FormLabel>Private Key</FormLabel>
</div>
<FormControl>
<Textarea
className="h-32"
placeholder={certificateDataHolder}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
<DialogFooter className="flex w-full flex-row !justify-between pt-3">
<Button
isLoading={isLoading}
form="hook-form-add-certificate"
type="submit"
>
Create
</Button>
</DialogFooter>
</Form>
</DialogContent>
</Dialog>
);
<DialogFooter className="flex w-full flex-row !justify-between pt-3">
<Button
isLoading={isLoading}
form="hook-form-add-certificate"
type="submit"
>
Create
</Button>
</DialogFooter>
</Form>
</DialogContent>
</Dialog>
);
};

View File

@@ -18,8 +18,8 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -87,14 +87,7 @@ export const AddDestination = () => {
In this section you can add destinations for your backups.
</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -18,8 +18,9 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, PenBoxIcon } from "lucide-react";
import { PenBoxIcon } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -111,14 +112,7 @@ export const UpdateDestination = ({ destinationId }: Props) => {
Update the current destination config
</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -21,8 +21,9 @@ import {
import { Switch } from "@/components/ui/switch";
import { extractServices } from "@/pages/dashboard/project/[projectId]";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, ListTodo } from "lucide-react";
import { ListTodo } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -115,14 +116,7 @@ export const AddUserPermissions = ({ userId }: Props) => {
<DialogTitle>Permissions</DialogTitle>
<DialogDescription>Add or remove permissions</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -19,8 +19,8 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -73,14 +73,7 @@ export const AddUser = () => {
<DialogTitle>Add User</DialogTitle>
<DialogDescription>Invite a new user</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form

View File

@@ -47,7 +47,7 @@ export const ShowUsers = () => {
key={user.userId}
className="flex gap-2 flex-col justify-start border p-4 rounded-lg"
>
<span className="text-sm text-muted-foreground">
<span className="text-sm text-foreground">
{user.auth.email}
</span>
{!user.isRegistered && (

View File

@@ -18,11 +18,12 @@ import {
} from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
import { Input } from "@/components/ui/input";
import { AlertTriangle, SquarePen } from "lucide-react";
import { SquarePen } from "lucide-react";
import { api } from "@/utils/api";
const updateUserSchema = z.object({
@@ -100,14 +101,7 @@ export const UpdateUser = ({ authId }: Props) => {
<DialogTitle>Update User</DialogTitle>
<DialogDescription>Update the user</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<div className="grid gap-4">
<div className="grid items-center gap-4">

View File

@@ -18,8 +18,8 @@ import {
} from "@/components/ui/form";
import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -89,14 +89,7 @@ export const ShowMainTraefikConfig = ({ children }: Props) => {
<DialogTitle>Update traefik config</DialogTitle>
<DialogDescription>Update the traefik config</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form
@@ -113,7 +106,7 @@ export const ShowMainTraefikConfig = ({ children }: Props) => {
<FormLabel>Traefik config</FormLabel>
<FormControl>
<Textarea
className="h-[35rem]"
className="h-[35rem] font-mono"
placeholder={`providers:
docker:
defaultRule: 'Host('dokploy.com')'
@@ -136,8 +129,10 @@ export const ShowMainTraefikConfig = ({ children }: Props) => {
<pre>
<FormMessage />
</pre>
<div className="flex justify-end absolute z-50 right-6 top-10">
<div className="flex justify-end absolute z-50 right-6 top-0">
<Button
className="shadow-sm"
variant="secondary"
type="button"
onClick={async () => {
setCanEdit(!canEdit);

View File

@@ -18,8 +18,8 @@ import {
} from "@/components/ui/form";
import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -92,14 +92,7 @@ export const ShowServerMiddlewareConfig = ({ children }: Props) => {
<DialogTitle>Update Middleware config</DialogTitle>
<DialogDescription>Update the middleware config</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form
@@ -116,7 +109,7 @@ export const ShowServerMiddlewareConfig = ({ children }: Props) => {
<FormLabel>Traefik config</FormLabel>
<FormControl>
<Textarea
className="h-[35rem]"
className="h-[35rem] font-mono"
placeholder={`http:
routers:
router-name:
@@ -134,8 +127,10 @@ routers:
<pre>
<FormMessage />
</pre>
<div className="flex justify-end absolute z-50 right-6 top-10">
<div className="flex justify-end absolute z-50 right-6 top-0">
<Button
className="shadow-sm"
variant="secondary"
type="button"
onClick={async () => {
setCanEdit(!canEdit);

View File

@@ -18,8 +18,8 @@ import {
} from "@/components/ui/form";
import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
@@ -92,14 +92,7 @@ export const ShowServerTraefikConfig = ({ children }: Props) => {
<DialogTitle>Update traefik config</DialogTitle>
<DialogDescription>Update the traefik config</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>
)}
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
<Form {...form}>
<form
@@ -116,7 +109,7 @@ export const ShowServerTraefikConfig = ({ children }: Props) => {
<FormLabel>Traefik config</FormLabel>
<FormControl>
<Textarea
className="h-[35rem]"
className="h-[35rem] font-mono"
placeholder={`http:
routers:
router-name:
@@ -134,8 +127,10 @@ routers:
<pre>
<FormMessage />
</pre>
<div className="flex justify-end absolute z-50 right-6 top-10">
<div className="flex justify-end absolute z-50 right-6 top-0">
<Button
className="shadow-sm"
variant="secondary"
type="button"
onClick={async () => {
setCanEdit(!canEdit);