From 3cf7c697b8fe9146ed9d65e2d4367712ecc7f1c5 Mon Sep 17 00:00:00 2001 From: David Tanasescu Date: Sun, 16 Mar 2025 13:36:42 +0100 Subject: [PATCH] Fix: Consistent Component Styling and Server URL --- .../dashboard/application/general/show.tsx | 543 +++++++++--------- .../dashboard/compose/general/actions.tsx | 411 ++++++------- .../show-external-mariadb-credentials.tsx | 261 +++++---- .../mariadb/general/show-general-mariadb.tsx | 447 +++++++------- .../show-external-mongo-credentials.tsx | 257 +++++---- .../mongo/general/show-general-mongo.tsx | 455 +++++++-------- .../show-external-mysql-credentials.tsx | 259 +++++---- .../mysql/general/show-general-mysql.tsx | 447 +++++++------- .../show-external-postgres-credentials.tsx | 259 +++++---- .../general/show-general-postgres.tsx | 449 +++++++-------- .../show-internal-postgres-credentials.tsx | 98 ++-- .../dashboard/postgres/update-postgres.tsx | 245 ++++---- .../show-external-redis-credentials.tsx | 245 ++++---- .../redis/general/show-general-redis.tsx | 447 +++++++------- 14 files changed, 2423 insertions(+), 2400 deletions(-) diff --git a/apps/dokploy/components/dashboard/application/general/show.tsx b/apps/dokploy/components/dashboard/application/general/show.tsx index 2f066280..b8ebca50 100644 --- a/apps/dokploy/components/dashboard/application/general/show.tsx +++ b/apps/dokploy/components/dashboard/application/general/show.tsx @@ -10,289 +10,304 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; -import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { api } from "@/utils/api"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { Ban, CheckCircle2, Hammer, - HelpCircle, RefreshCcw, + Rocket, Terminal, } from "lucide-react"; import { useRouter } from "next/router"; import { toast } from "sonner"; import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal"; interface Props { - applicationId: string; + applicationId: string; } export const ShowGeneralApplication = ({ applicationId }: Props) => { - const router = useRouter(); - const { data, refetch } = api.application.one.useQuery( - { - applicationId, - }, - { enabled: !!applicationId }, - ); - const { mutateAsync: update } = api.application.update.useMutation(); - const { mutateAsync: start, isLoading: isStarting } = - api.application.start.useMutation(); - const { mutateAsync: stop, isLoading: isStopping } = - api.application.stop.useMutation(); + const router = useRouter(); + const { data, refetch } = api.application.one.useQuery( + { + applicationId, + }, + { enabled: !!applicationId } + ); + const { mutateAsync: update } = api.application.update.useMutation(); + const { mutateAsync: start, isLoading: isStarting } = + api.application.start.useMutation(); + const { mutateAsync: stop, isLoading: isStopping } = + api.application.stop.useMutation(); - const { mutateAsync: deploy } = api.application.deploy.useMutation(); + const { mutateAsync: deploy } = api.application.deploy.useMutation(); - const { mutateAsync: reload, isLoading: isReloading } = - api.application.reload.useMutation(); + const { mutateAsync: reload, isLoading: isReloading } = + api.application.reload.useMutation(); - const { mutateAsync: redeploy } = api.application.redeploy.useMutation(); + const { mutateAsync: redeploy } = api.application.redeploy.useMutation(); - return ( - <> - - - Deploy Settings - - - - { - await deploy({ - applicationId: applicationId, - }) - .then(() => { - toast.success("Application deployed successfully"); - refetch(); - router.push( - `/dashboard/project/${data?.projectId}/services/application/${applicationId}?tab=deployments`, - ); - }) - .catch(() => { - toast.error("Error deploying application"); - }); - }} - > - - - { - await reload({ - applicationId: applicationId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Application reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading application"); - }); - }} - > - - - { - await redeploy({ - applicationId: applicationId, - }) - .then(() => { - toast.success("Application rebuilt successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error rebuilding application"); - }); - }} - > - - + return ( + <> + + + Deploy Settings + + + + { + await deploy({ + applicationId: applicationId, + }) + .then(() => { + toast.success("Application deployed successfully"); + refetch(); + router.push( + `/dashboard/project/${data?.projectId}/services/application/${applicationId}?tab=deployments` + ); + }) + .catch(() => { + toast.error("Error deploying application"); + }); + }} + > + + + + + + +

+ Downloads the source code and performs a complete build +

+
+
+
+
+ { + await reload({ + applicationId: applicationId, + appName: data?.appName || "", + }) + .then(() => { + toast.success("Application reloaded successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error reloading application"); + }); + }} + > + + + + + + +

+ Reload the application when you change configuration or + environment variables +

+
+
+
+
+ { + await redeploy({ + applicationId: applicationId, + }) + .then(() => { + toast.success("Application rebuilt successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error rebuilding application"); + }); + }} + > + + + + + + +

+ Only rebuilds the application without downloading new code +

+
+
+
+
- {data?.applicationStatus === "idle" ? ( - { - await start({ - applicationId: applicationId, - }) - .then(() => { - toast.success("Application started successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error starting application"); - }); - }} - > - - - ) : ( - { - await stop({ - applicationId: applicationId, - }) - .then(() => { - toast.success("Application stopped successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error stopping application"); - }); - }} - > - - - )} -
- - - -
- Autodeploy - { - await update({ - applicationId, - autoDeploy: enabled, - }) - .then(async () => { - toast.success("Auto Deploy Updated"); - await refetch(); - }) - .catch(() => { - toast.error("Error updating Auto Deploy"); - }); - }} - className="flex flex-row gap-2 items-center" - /> -
+ {data?.applicationStatus === "idle" ? ( + { + await start({ + applicationId: applicationId, + }) + .then(() => { + toast.success("Application started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting application"); + }); + }} + > + + + + + + +

+ Start the application (requires a previous successful + build) +

+
+
+
+
+ ) : ( + { + await stop({ + applicationId: applicationId, + }) + .then(() => { + toast.success("Application stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping application"); + }); + }} + > + + + + + + +

Stop the currently running application

+
+
+
+
+ )} +
+ + + +
+ Autodeploy + { + await update({ + applicationId, + autoDeploy: enabled, + }) + .then(async () => { + toast.success("Auto Deploy Updated"); + await refetch(); + }) + .catch(() => { + toast.error("Error updating Auto Deploy"); + }); + }} + className="flex flex-row gap-2 items-center data-[state=checked]:bg-primary" + /> +
-
- Clean Cache - { - await update({ - applicationId, - cleanCache: enabled, - }) - .then(async () => { - toast.success("Clean Cache Updated"); - await refetch(); - }) - .catch(() => { - toast.error("Error updating Clean Cache"); - }); - }} - className="flex flex-row gap-2 items-center" - /> -
-
-
- - - - ); +
+ Clean Cache + { + await update({ + applicationId, + cleanCache: enabled, + }) + .then(async () => { + toast.success("Clean Cache Updated"); + await refetch(); + }) + .catch(() => { + toast.error("Error updating Clean Cache"); + }); + }} + className="flex flex-row gap-2 items-center data-[state=checked]:bg-primary" + /> +
+ + + + + + ); }; diff --git a/apps/dokploy/components/dashboard/compose/general/actions.tsx b/apps/dokploy/components/dashboard/compose/general/actions.tsx index f7761920..5fda2ba5 100644 --- a/apps/dokploy/components/dashboard/compose/general/actions.tsx +++ b/apps/dokploy/components/dashboard/compose/general/actions.tsx @@ -7,216 +7,219 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; -import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { api } from "@/utils/api"; -import { Ban, CheckCircle2, Hammer, HelpCircle, Terminal } from "lucide-react"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; +import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react"; import { useRouter } from "next/router"; import { toast } from "sonner"; import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal"; interface Props { - composeId: string; + composeId: string; } export const ComposeActions = ({ composeId }: Props) => { - const router = useRouter(); - const { data, refetch } = api.compose.one.useQuery( - { - composeId, - }, - { enabled: !!composeId }, - ); - const { mutateAsync: update } = api.compose.update.useMutation(); - const { mutateAsync: deploy } = api.compose.deploy.useMutation(); - const { mutateAsync: redeploy } = api.compose.redeploy.useMutation(); - const { mutateAsync: start, isLoading: isStarting } = - api.compose.start.useMutation(); - const { mutateAsync: stop, isLoading: isStopping } = - api.compose.stop.useMutation(); - return ( -
- - { - await deploy({ - composeId: composeId, - }) - .then(() => { - toast.success("Compose deployed successfully"); - refetch(); - router.push( - `/dashboard/project/${data?.project.projectId}/services/compose/${composeId}?tab=deployments`, - ); - }) - .catch(() => { - toast.error("Error deploying compose"); - }); - }} - > - - - { - await redeploy({ - composeId: composeId, - }) - .then(() => { - toast.success("Compose rebuilt successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error rebuilding compose"); - }); - }} - > - - - {data?.composeType === "docker-compose" && - data?.composeStatus === "idle" ? ( - { - await start({ - composeId: composeId, - }) - .then(() => { - toast.success("Compose started successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error starting compose"); - }); - }} - > - - - ) : ( - { - await stop({ - composeId: composeId, - }) - .then(() => { - toast.success("Compose stopped successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error stopping compose"); - }); - }} - > - - - )} - - - - -
- Autodeploy - { - await update({ - composeId, - autoDeploy: enabled, - }) - .then(async () => { - toast.success("Auto Deploy Updated"); - await refetch(); - }) - .catch(() => { - toast.error("Error updating Auto Deploy"); - }); - }} - className="flex flex-row gap-2 items-center" - /> -
-
- ); + const router = useRouter(); + const { data, refetch } = api.compose.one.useQuery( + { + composeId, + }, + { enabled: !!composeId } + ); + const { mutateAsync: update } = api.compose.update.useMutation(); + const { mutateAsync: deploy } = api.compose.deploy.useMutation(); + const { mutateAsync: redeploy } = api.compose.redeploy.useMutation(); + const { mutateAsync: start, isLoading: isStarting } = + api.compose.start.useMutation(); + const { mutateAsync: stop, isLoading: isStopping } = + api.compose.stop.useMutation(); + return ( +
+ + { + await deploy({ + composeId: composeId, + }) + .then(() => { + toast.success("Compose deployed successfully"); + refetch(); + router.push( + `/dashboard/project/${data?.project.projectId}/services/compose/${composeId}?tab=deployments` + ); + }) + .catch(() => { + toast.error("Error deploying compose"); + }); + }} + > + + + + + + +

Downloads the source code and performs a complete build

+
+
+
+
+ { + await redeploy({ + composeId: composeId, + }) + .then(() => { + toast.success("Compose reloaded successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error reloading compose"); + }); + }} + > + + + + + + +

+ Reload the compose when you change configuration or + environment variables +

+
+
+
+
+ {data?.composeType === "docker-compose" && + data?.composeStatus === "idle" ? ( + { + await start({ + composeId: composeId, + }) + .then(() => { + toast.success("Compose started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting compose"); + }); + }} + > + + + + + + +

+ Start the compose (requires a previous successful build) +

+
+
+
+
+ ) : ( + { + await stop({ + composeId: composeId, + }) + .then(() => { + toast.success("Compose stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping compose"); + }); + }} + > + + + + + + +

Stop the currently running compose

+
+
+
+
+ )} +
+ + + +
+ Autodeploy + { + await update({ + composeId, + autoDeploy: enabled, + }) + .then(async () => { + toast.success("Auto Deploy Updated"); + await refetch(); + }) + .catch(() => { + toast.error("Error updating Auto Deploy"); + }); + }} + className="flex flex-row gap-2 items-center data-[state=checked]:bg-primary" + /> +
+
+ ); }; diff --git a/apps/dokploy/components/dashboard/mariadb/general/show-external-mariadb-credentials.tsx b/apps/dokploy/components/dashboard/mariadb/general/show-external-mariadb-credentials.tsx index a281f125..9f5b63c3 100644 --- a/apps/dokploy/components/dashboard/mariadb/general/show-external-mariadb-credentials.tsx +++ b/apps/dokploy/components/dashboard/mariadb/general/show-external-mariadb-credentials.tsx @@ -1,6 +1,6 @@ +import { AlertBlock } from "@/components/shared/alert-block"; import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import { Button } from "@/components/ui/button"; -import { AlertBlock } from "@/components/shared/alert-block"; import { Card, CardContent, @@ -20,153 +20,152 @@ import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; +import Link from "next/link"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; -import Link from "next/link"; const DockerProviderSchema = z.object({ - externalPort: z.preprocess((a) => { - if (a !== null) { - const parsed = Number.parseInt(z.string().parse(a), 10); - return Number.isNaN(parsed) ? null : parsed; - } - return null; - }, z - .number() - .gte(0, "Range must be 0 - 65535") - .lte(65535, "Range must be 0 - 65535") - .nullable()), + externalPort: z.preprocess((a) => { + if (a !== null) { + const parsed = Number.parseInt(z.string().parse(a), 10); + return Number.isNaN(parsed) ? null : parsed; + } + return null; + }, z.number().gte(0, "Range must be 0 - 65535").lte(65535, "Range must be 0 - 65535").nullable()), }); type DockerProvider = z.infer; interface Props { - mariadbId: string; + mariadbId: string; } export const ShowExternalMariadbCredentials = ({ mariadbId }: Props) => { - const { data: ip } = api.settings.getIp.useQuery(); - const { data, refetch } = api.mariadb.one.useQuery({ mariadbId }); - const { mutateAsync, isLoading } = api.mariadb.saveExternalPort.useMutation(); - const [connectionUrl, setConnectionUrl] = useState(""); - const getIp = data?.server?.ipAddress || ip; - const form = useForm({ - defaultValues: {}, - resolver: zodResolver(DockerProviderSchema), - }); + const { data: ip } = api.settings.getIp.useQuery(); + const { data, refetch } = api.mariadb.one.useQuery({ mariadbId }); + const { mutateAsync, isLoading } = api.mariadb.saveExternalPort.useMutation(); + const [connectionUrl, setConnectionUrl] = useState(""); + const getIp = data?.server?.ipAddress || ip; + const form = useForm({ + defaultValues: {}, + resolver: zodResolver(DockerProviderSchema), + }); - useEffect(() => { - if (data?.externalPort) { - form.reset({ - externalPort: data.externalPort, - }); - } - }, [form.reset, data, form]); + useEffect(() => { + if (data?.externalPort) { + form.reset({ + externalPort: data.externalPort, + }); + } + }, [form.reset, data, form]); - const onSubmit = async (values: DockerProvider) => { - await mutateAsync({ - externalPort: values.externalPort, - mariadbId, - }) - .then(async () => { - toast.success("External Port updated"); - await refetch(); - }) - .catch(() => { - toast.error("Error saving the external port"); - }); - }; + const onSubmit = async (values: DockerProvider) => { + await mutateAsync({ + externalPort: values.externalPort, + mariadbId, + }) + .then(async () => { + toast.success("External Port updated"); + await refetch(); + }) + .catch(() => { + toast.error("Error saving the external port"); + }); + }; - useEffect(() => { - const buildConnectionUrl = () => { - const port = form.watch("externalPort") || data?.externalPort; + useEffect(() => { + const buildConnectionUrl = () => { + const port = form.watch("externalPort") || data?.externalPort; - return `mariadb://${data?.databaseUser}:${data?.databasePassword}@${getIp}:${port}/${data?.databaseName}`; - }; + return `mariadb://${data?.databaseUser}:${data?.databasePassword}@${getIp}:${port}/${data?.databaseName}`; + }; - setConnectionUrl(buildConnectionUrl()); - }, [ - data?.appName, - data?.externalPort, - data?.databasePassword, - form, - data?.databaseName, - data?.databaseUser, - getIp, - ]); - return ( - <> -
- - - External Credentials - - In order to make the database reachable trought internet is - required to set a port, make sure the port is not used by another - application or database - - - - {!getIp && ( - - You need to set an IP address in your{" "} - - {data?.serverId - ? "Remote Servers -> Server -> Edit Server -> Update IP Address" - : "Web Server -> Server -> Update Server IP"} - {" "} - to fix the database url connection. - - )} -
- -
-
- { - return ( - - External Port (Internet) - - - - - - ); - }} - /> -
-
- {!!data?.externalPort && ( -
-
- {/* jdbc:mariadb://5.161.59.207:3306/pixel-calculate?user=mariadb&password=HdVXfq6hM7W7F1 */} - - -
-
- )} + setConnectionUrl(buildConnectionUrl()); + }, [ + data?.appName, + data?.externalPort, + data?.databasePassword, + form, + data?.databaseName, + data?.databaseUser, + getIp, + ]); + return ( + <> +
+ + + External Credentials + + In order to make the database reachable trought internet is + required to set a port, make sure the port is not used by another + application or database + + + + {!getIp && ( + + You need to set an IP address in your{" "} + + {data?.serverId + ? "Remote Servers -> Server -> Edit Server -> Update IP Address" + : "Web Server -> Server -> Update Server IP"} + {" "} + to fix the database url connection. + + )} + + +
+
+ { + return ( + + External Port (Internet) + + + + + + ); + }} + /> +
+
+ {!!data?.externalPort && ( +
+
+ {/* jdbc:mariadb://5.161.59.207:3306/pixel-calculate?user=mariadb&password=HdVXfq6hM7W7F1 */} + + +
+
+ )} -
- -
- - -
-
-
- - ); +
+ +
+ + +
+
+
+ + ); }; diff --git a/apps/dokploy/components/dashboard/mariadb/general/show-general-mariadb.tsx b/apps/dokploy/components/dashboard/mariadb/general/show-general-mariadb.tsx index f4489ca2..c222b256 100644 --- a/apps/dokploy/components/dashboard/mariadb/general/show-general-mariadb.tsx +++ b/apps/dokploy/components/dashboard/mariadb/general/show-general-mariadb.tsx @@ -8,242 +8,245 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; -import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { api } from "@/utils/api"; -import { - Ban, - CheckCircle2, - HelpCircle, - RefreshCcw, - Terminal, -} from "lucide-react"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; +import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; import { type LogLine, parseLogs } from "../../docker/logs/utils"; import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal"; interface Props { - mariadbId: string; + mariadbId: string; } export const ShowGeneralMariadb = ({ mariadbId }: Props) => { - const { data, refetch } = api.mariadb.one.useQuery( - { - mariadbId, - }, - { enabled: !!mariadbId }, - ); + const { data, refetch } = api.mariadb.one.useQuery( + { + mariadbId, + }, + { enabled: !!mariadbId } + ); - const { mutateAsync: reload, isLoading: isReloading } = - api.mariadb.reload.useMutation(); + const { mutateAsync: reload, isLoading: isReloading } = + api.mariadb.reload.useMutation(); - const { mutateAsync: start, isLoading: isStarting } = - api.mariadb.start.useMutation(); + const { mutateAsync: start, isLoading: isStarting } = + api.mariadb.start.useMutation(); - const { mutateAsync: stop, isLoading: isStopping } = - api.mariadb.stop.useMutation(); + const { mutateAsync: stop, isLoading: isStopping } = + api.mariadb.stop.useMutation(); - const [isDrawerOpen, setIsDrawerOpen] = useState(false); - const [filteredLogs, setFilteredLogs] = useState([]); - const [isDeploying, setIsDeploying] = useState(false); - api.mariadb.deployWithLogs.useSubscription( - { - mariadbId: mariadbId, - }, - { - enabled: isDeploying, - onData(log) { - if (!isDrawerOpen) { - setIsDrawerOpen(true); - } + const [isDrawerOpen, setIsDrawerOpen] = useState(false); + const [filteredLogs, setFilteredLogs] = useState([]); + const [isDeploying, setIsDeploying] = useState(false); + api.mariadb.deployWithLogs.useSubscription( + { + mariadbId: mariadbId, + }, + { + enabled: isDeploying, + onData(log) { + if (!isDrawerOpen) { + setIsDrawerOpen(true); + } - if (log === "Deployment completed successfully!") { - setIsDeploying(false); - } - const parsedLogs = parseLogs(log); - setFilteredLogs((prev) => [...prev, ...parsedLogs]); - }, - onError(error) { - console.error("Deployment logs error:", error); - setIsDeploying(false); - }, - }, - ); + if (log === "Deployment completed successfully!") { + setIsDeploying(false); + } + const parsedLogs = parseLogs(log); + setFilteredLogs((prev) => [...prev, ...parsedLogs]); + }, + onError(error) { + console.error("Deployment logs error:", error); + setIsDeploying(false); + }, + } + ); - return ( - <> -
- - - Deploy Settings - - - - { - setIsDeploying(true); - await new Promise((resolve) => setTimeout(resolve, 1000)); - refetch(); - }} - > - - - { - await reload({ - mariadbId: mariadbId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Mariadb reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading Mariadb"); - }); - }} - > - - - {data?.applicationStatus === "idle" ? ( - { - await start({ - mariadbId: mariadbId, - }) - .then(() => { - toast.success("Mariadb started successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error starting Mariadb"); - }); - }} - > - - - ) : ( - { - await stop({ - mariadbId: mariadbId, - }) - .then(() => { - toast.success("Mariadb stopped successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error stopping Mariadb"); - }); - }} - > - - - )} - - - - - - - { - setIsDrawerOpen(false); - setFilteredLogs([]); - setIsDeploying(false); - refetch(); - }} - filteredLogs={filteredLogs} - /> -
- - ); + return ( + <> +
+ + + Deploy Settings + + + + { + setIsDeploying(true); + await new Promise((resolve) => setTimeout(resolve, 1000)); + refetch(); + }} + > + + + + + + +

Downloads and sets up the MariaDB database

+
+
+
+
+ { + await reload({ + mariadbId: mariadbId, + appName: data?.appName || "", + }) + .then(() => { + toast.success("Mariadb reloaded successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error reloading Mariadb"); + }); + }} + > + + + + + + +

Restart the MariaDB service without rebuilding

+
+
+
+
+ {data?.applicationStatus === "idle" ? ( + { + await start({ + mariadbId: mariadbId, + }) + .then(() => { + toast.success("Mariadb started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting Mariadb"); + }); + }} + > + + + + + + +

+ Start the MariaDB database (requires a previous + successful setup) +

+
+
+
+
+ ) : ( + { + await stop({ + mariadbId: mariadbId, + }) + .then(() => { + toast.success("Mariadb stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping Mariadb"); + }); + }} + > + + + + + + +

Stop the currently running MariaDB database

+
+
+
+
+ )} +
+ + + + + + + +

Open a terminal to the MariaDB container

+
+
+
+
+
+
+ { + setIsDrawerOpen(false); + setFilteredLogs([]); + setIsDeploying(false); + refetch(); + }} + filteredLogs={filteredLogs} + /> +
+ + ); }; diff --git a/apps/dokploy/components/dashboard/mongo/general/show-external-mongo-credentials.tsx b/apps/dokploy/components/dashboard/mongo/general/show-external-mongo-credentials.tsx index b845004f..b5ed9f86 100644 --- a/apps/dokploy/components/dashboard/mongo/general/show-external-mongo-credentials.tsx +++ b/apps/dokploy/components/dashboard/mongo/general/show-external-mongo-credentials.tsx @@ -1,6 +1,6 @@ +import { AlertBlock } from "@/components/shared/alert-block"; import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import { Button } from "@/components/ui/button"; -import { AlertBlock } from "@/components/shared/alert-block"; import { Card, CardContent, @@ -20,152 +20,151 @@ import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; +import Link from "next/link"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; -import Link from "next/link"; const DockerProviderSchema = z.object({ - externalPort: z.preprocess((a) => { - if (a !== null) { - const parsed = Number.parseInt(z.string().parse(a), 10); - return Number.isNaN(parsed) ? null : parsed; - } - return null; - }, z - .number() - .gte(0, "Range must be 0 - 65535") - .lte(65535, "Range must be 0 - 65535") - .nullable()), + externalPort: z.preprocess((a) => { + if (a !== null) { + const parsed = Number.parseInt(z.string().parse(a), 10); + return Number.isNaN(parsed) ? null : parsed; + } + return null; + }, z.number().gte(0, "Range must be 0 - 65535").lte(65535, "Range must be 0 - 65535").nullable()), }); type DockerProvider = z.infer; interface Props { - mongoId: string; + mongoId: string; } export const ShowExternalMongoCredentials = ({ mongoId }: Props) => { - const { data: ip } = api.settings.getIp.useQuery(); - const { data, refetch } = api.mongo.one.useQuery({ mongoId }); - const { mutateAsync, isLoading } = api.mongo.saveExternalPort.useMutation(); - const [connectionUrl, setConnectionUrl] = useState(""); - const getIp = data?.server?.ipAddress || ip; - const form = useForm({ - defaultValues: {}, - resolver: zodResolver(DockerProviderSchema), - }); + const { data: ip } = api.settings.getIp.useQuery(); + const { data, refetch } = api.mongo.one.useQuery({ mongoId }); + const { mutateAsync, isLoading } = api.mongo.saveExternalPort.useMutation(); + const [connectionUrl, setConnectionUrl] = useState(""); + const getIp = data?.server?.ipAddress || ip; + const form = useForm({ + defaultValues: {}, + resolver: zodResolver(DockerProviderSchema), + }); - useEffect(() => { - if (data?.externalPort) { - form.reset({ - externalPort: data.externalPort, - }); - } - }, [form.reset, data, form]); + useEffect(() => { + if (data?.externalPort) { + form.reset({ + externalPort: data.externalPort, + }); + } + }, [form.reset, data, form]); - const onSubmit = async (values: DockerProvider) => { - await mutateAsync({ - externalPort: values.externalPort, - mongoId, - }) - .then(async () => { - toast.success("External Port updated"); - await refetch(); - }) - .catch(() => { - toast.error("Error saving the external port"); - }); - }; + const onSubmit = async (values: DockerProvider) => { + await mutateAsync({ + externalPort: values.externalPort, + mongoId, + }) + .then(async () => { + toast.success("External Port updated"); + await refetch(); + }) + .catch(() => { + toast.error("Error saving the external port"); + }); + }; - useEffect(() => { - const buildConnectionUrl = () => { - const port = form.watch("externalPort") || data?.externalPort; + useEffect(() => { + const buildConnectionUrl = () => { + const port = form.watch("externalPort") || data?.externalPort; - return `mongodb://${data?.databaseUser}:${data?.databasePassword}@${getIp}:${port}`; - }; + return `mongodb://${data?.databaseUser}:${data?.databasePassword}@${getIp}:${port}`; + }; - setConnectionUrl(buildConnectionUrl()); - }, [ - data?.appName, - data?.externalPort, - data?.databasePassword, - form, - data?.databaseUser, - getIp, - ]); + setConnectionUrl(buildConnectionUrl()); + }, [ + data?.appName, + data?.externalPort, + data?.databasePassword, + form, + data?.databaseUser, + getIp, + ]); - return ( - <> -
- - - External Credentials - - In order to make the database reachable trought internet is - required to set a port, make sure the port is not used by another - application or database - - - - {!getIp && ( - - You need to set an IP address in your{" "} - - {data?.serverId - ? "Remote Servers -> Server -> Edit Server -> Update IP Address" - : "Web Server -> Server -> Update Server IP"} - {" "} - to fix the database url connection. - - )} -
- -
-
- { - return ( - - External Port (Internet) - - - - - - ); - }} - /> -
-
- {!!data?.externalPort && ( -
-
- - -
-
- )} + return ( + <> +
+ + + External Credentials + + In order to make the database reachable trought internet is + required to set a port, make sure the port is not used by another + application or database + + + + {!getIp && ( + + You need to set an IP address in your{" "} + + {data?.serverId + ? "Remote Servers -> Server -> Edit Server -> Update IP Address" + : "Web Server -> Server -> Update Server IP"} + {" "} + to fix the database url connection. + + )} + + +
+
+ { + return ( + + External Port (Internet) + + + + + + ); + }} + /> +
+
+ {!!data?.externalPort && ( +
+
+ + +
+
+ )} -
- -
- - -
-
-
- - ); +
+ +
+ + +
+
+
+ + ); }; diff --git a/apps/dokploy/components/dashboard/mongo/general/show-general-mongo.tsx b/apps/dokploy/components/dashboard/mongo/general/show-general-mongo.tsx index 644d1a26..dfbf501e 100644 --- a/apps/dokploy/components/dashboard/mongo/general/show-general-mongo.tsx +++ b/apps/dokploy/components/dashboard/mongo/general/show-general-mongo.tsx @@ -3,246 +3,249 @@ import { DrawerLogs } from "@/components/shared/drawer-logs"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, } from "@/components/ui/tooltip"; -import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { api } from "@/utils/api"; -import { - Ban, - CheckCircle2, - HelpCircle, - RefreshCcw, - Terminal, -} from "lucide-react"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; +import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; import { type LogLine, parseLogs } from "../../docker/logs/utils"; import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal"; interface Props { - mongoId: string; + mongoId: string; } export const ShowGeneralMongo = ({ mongoId }: Props) => { - const { data, refetch } = api.mongo.one.useQuery( - { - mongoId, - }, - { enabled: !!mongoId }, - ); + const { data, refetch } = api.mongo.one.useQuery( + { + mongoId, + }, + { enabled: !!mongoId } + ); - const { mutateAsync: reload, isLoading: isReloading } = - api.mongo.reload.useMutation(); + const { mutateAsync: reload, isLoading: isReloading } = + api.mongo.reload.useMutation(); - const { mutateAsync: start, isLoading: isStarting } = - api.mongo.start.useMutation(); + const { mutateAsync: start, isLoading: isStarting } = + api.mongo.start.useMutation(); - const { mutateAsync: stop, isLoading: isStopping } = - api.mongo.stop.useMutation(); + const { mutateAsync: stop, isLoading: isStopping } = + api.mongo.stop.useMutation(); - const [isDrawerOpen, setIsDrawerOpen] = useState(false); - const [filteredLogs, setFilteredLogs] = useState([]); - const [isDeploying, setIsDeploying] = useState(false); - api.mongo.deployWithLogs.useSubscription( - { - mongoId: mongoId, - }, - { - enabled: isDeploying, - onData(log) { - if (!isDrawerOpen) { - setIsDrawerOpen(true); - } + const [isDrawerOpen, setIsDrawerOpen] = useState(false); + const [filteredLogs, setFilteredLogs] = useState([]); + const [isDeploying, setIsDeploying] = useState(false); + api.mongo.deployWithLogs.useSubscription( + { + mongoId: mongoId, + }, + { + enabled: isDeploying, + onData(log) { + if (!isDrawerOpen) { + setIsDrawerOpen(true); + } - if (log === "Deployment completed successfully!") { - setIsDeploying(false); - } + if (log === "Deployment completed successfully!") { + setIsDeploying(false); + } - const parsedLogs = parseLogs(log); - setFilteredLogs((prev) => [...prev, ...parsedLogs]); - }, - onError(error) { - console.error("Deployment logs error:", error); - setIsDeploying(false); - }, - }, - ); - return ( - <> -
- - - Deploy Settings - - - - { - setIsDeploying(true); - await new Promise((resolve) => setTimeout(resolve, 1000)); - refetch(); - }} - > - - - { - await reload({ - mongoId: mongoId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Mongo reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading Mongo"); - }); - }} - > - - - {data?.applicationStatus === "idle" ? ( - { - await start({ - mongoId: mongoId, - }) - .then(() => { - toast.success("Mongo started successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error starting Mongo"); - }); - }} - > - - - ) : ( - { - await stop({ - mongoId: mongoId, - }) - .then(() => { - toast.success("Mongo stopped successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error stopping Mongo"); - }); - }} - > - - - )} - - - - - - - { - setIsDrawerOpen(false); - setFilteredLogs([]); - setIsDeploying(false); - refetch(); - }} - filteredLogs={filteredLogs} - /> -
- - ); + const parsedLogs = parseLogs(log); + setFilteredLogs((prev) => [...prev, ...parsedLogs]); + }, + onError(error) { + console.error("Deployment logs error:", error); + setIsDeploying(false); + }, + } + ); + return ( + <> +
+ + + Deploy Settings + + + + { + setIsDeploying(true); + await new Promise((resolve) => setTimeout(resolve, 1000)); + refetch(); + }} + > + + + + + + +

Downloads and sets up the MongoDB database

+
+
+
+
+ { + await reload({ + mongoId: mongoId, + appName: data?.appName || "", + }) + .then(() => { + toast.success("Mongo reloaded successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error reloading Mongo"); + }); + }} + > + + + + + + +

Restart the MongoDB service without rebuilding

+
+
+
+
+ {data?.applicationStatus === "idle" ? ( + { + await start({ + mongoId: mongoId, + }) + .then(() => { + toast.success("Mongo started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting Mongo"); + }); + }} + > + + + + + + +

+ Start the MongoDB database (requires a previous + successful setup) +

+
+
+
+
+ ) : ( + { + await stop({ + mongoId: mongoId, + }) + .then(() => { + toast.success("Mongo stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping Mongo"); + }); + }} + > + + + + + + +

Stop the currently running MongoDB database

+
+
+
+
+ )} +
+ + + + + + + +

Open a terminal to the MongoDB container

+
+
+
+
+
+
+ { + setIsDrawerOpen(false); + setFilteredLogs([]); + setIsDeploying(false); + refetch(); + }} + filteredLogs={filteredLogs} + /> +
+ + ); }; diff --git a/apps/dokploy/components/dashboard/mysql/general/show-external-mysql-credentials.tsx b/apps/dokploy/components/dashboard/mysql/general/show-external-mysql-credentials.tsx index 12b3eb06..2c8ed5f5 100644 --- a/apps/dokploy/components/dashboard/mysql/general/show-external-mysql-credentials.tsx +++ b/apps/dokploy/components/dashboard/mysql/general/show-external-mysql-credentials.tsx @@ -1,6 +1,6 @@ +import { AlertBlock } from "@/components/shared/alert-block"; import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import { Button } from "@/components/ui/button"; -import { AlertBlock } from "@/components/shared/alert-block"; import { Card, CardContent, @@ -20,152 +20,151 @@ import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; +import Link from "next/link"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; -import Link from "next/link"; const DockerProviderSchema = z.object({ - externalPort: z.preprocess((a) => { - if (a !== null) { - const parsed = Number.parseInt(z.string().parse(a), 10); - return Number.isNaN(parsed) ? null : parsed; - } - return null; - }, z - .number() - .gte(0, "Range must be 0 - 65535") - .lte(65535, "Range must be 0 - 65535") - .nullable()), + externalPort: z.preprocess((a) => { + if (a !== null) { + const parsed = Number.parseInt(z.string().parse(a), 10); + return Number.isNaN(parsed) ? null : parsed; + } + return null; + }, z.number().gte(0, "Range must be 0 - 65535").lte(65535, "Range must be 0 - 65535").nullable()), }); type DockerProvider = z.infer; interface Props { - mysqlId: string; + mysqlId: string; } export const ShowExternalMysqlCredentials = ({ mysqlId }: Props) => { - const { data: ip } = api.settings.getIp.useQuery(); - const { data, refetch } = api.mysql.one.useQuery({ mysqlId }); - const { mutateAsync, isLoading } = api.mysql.saveExternalPort.useMutation(); - const [connectionUrl, setConnectionUrl] = useState(""); - const getIp = data?.server?.ipAddress || ip; - const form = useForm({ - defaultValues: {}, - resolver: zodResolver(DockerProviderSchema), - }); + const { data: ip } = api.settings.getIp.useQuery(); + const { data, refetch } = api.mysql.one.useQuery({ mysqlId }); + const { mutateAsync, isLoading } = api.mysql.saveExternalPort.useMutation(); + const [connectionUrl, setConnectionUrl] = useState(""); + const getIp = data?.server?.ipAddress || ip; + const form = useForm({ + defaultValues: {}, + resolver: zodResolver(DockerProviderSchema), + }); - useEffect(() => { - if (data?.externalPort) { - form.reset({ - externalPort: data.externalPort, - }); - } - }, [form.reset, data, form]); + useEffect(() => { + if (data?.externalPort) { + form.reset({ + externalPort: data.externalPort, + }); + } + }, [form.reset, data, form]); - const onSubmit = async (values: DockerProvider) => { - await mutateAsync({ - externalPort: values.externalPort, - mysqlId, - }) - .then(async () => { - toast.success("External Port updated"); - await refetch(); - }) - .catch(() => { - toast.error("Error saving the external port"); - }); - }; + const onSubmit = async (values: DockerProvider) => { + await mutateAsync({ + externalPort: values.externalPort, + mysqlId, + }) + .then(async () => { + toast.success("External Port updated"); + await refetch(); + }) + .catch(() => { + toast.error("Error saving the external port"); + }); + }; - useEffect(() => { - const buildConnectionUrl = () => { - const port = form.watch("externalPort") || data?.externalPort; + useEffect(() => { + const buildConnectionUrl = () => { + const port = form.watch("externalPort") || data?.externalPort; - return `mysql://${data?.databaseUser}:${data?.databasePassword}@${getIp}:${port}/${data?.databaseName}`; - }; + return `mysql://${data?.databaseUser}:${data?.databasePassword}@${getIp}:${port}/${data?.databaseName}`; + }; - setConnectionUrl(buildConnectionUrl()); - }, [ - data?.appName, - data?.externalPort, - data?.databasePassword, - data?.databaseName, - data?.databaseUser, - form, - getIp, - ]); - return ( - <> -
- - - External Credentials - - In order to make the database reachable trought internet is - required to set a port, make sure the port is not used by another - application or database - - - - {!getIp && ( - - You need to set an IP address in your{" "} - - {data?.serverId - ? "Remote Servers -> Server -> Edit Server -> Update IP Address" - : "Web Server -> Server -> Update Server IP"} - {" "} - to fix the database url connection. - - )} -
- -
-
- { - return ( - - External Port (Internet) - - - - - - ); - }} - /> -
-
- {!!data?.externalPort && ( -
-
- - -
-
- )} + setConnectionUrl(buildConnectionUrl()); + }, [ + data?.appName, + data?.externalPort, + data?.databasePassword, + data?.databaseName, + data?.databaseUser, + form, + getIp, + ]); + return ( + <> +
+ + + External Credentials + + In order to make the database reachable trought internet is + required to set a port, make sure the port is not used by another + application or database + + + + {!getIp && ( + + You need to set an IP address in your{" "} + + {data?.serverId + ? "Remote Servers -> Server -> Edit Server -> Update IP Address" + : "Web Server -> Server -> Update Server IP"} + {" "} + to fix the database url connection. + + )} + + +
+
+ { + return ( + + External Port (Internet) + + + + + + ); + }} + /> +
+
+ {!!data?.externalPort && ( +
+
+ + +
+
+ )} -
- -
- - -
-
-
- - ); +
+ +
+ + +
+
+
+ + ); }; diff --git a/apps/dokploy/components/dashboard/mysql/general/show-general-mysql.tsx b/apps/dokploy/components/dashboard/mysql/general/show-general-mysql.tsx index 3c8ae3ea..7002ff78 100644 --- a/apps/dokploy/components/dashboard/mysql/general/show-general-mysql.tsx +++ b/apps/dokploy/components/dashboard/mysql/general/show-general-mysql.tsx @@ -8,239 +8,242 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; -import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { api } from "@/utils/api"; -import { - Ban, - CheckCircle2, - HelpCircle, - RefreshCcw, - Terminal, -} from "lucide-react"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; +import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; import { type LogLine, parseLogs } from "../../docker/logs/utils"; import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal"; interface Props { - mysqlId: string; + mysqlId: string; } export const ShowGeneralMysql = ({ mysqlId }: Props) => { - const { data, refetch } = api.mysql.one.useQuery( - { - mysqlId, - }, - { enabled: !!mysqlId }, - ); + const { data, refetch } = api.mysql.one.useQuery( + { + mysqlId, + }, + { enabled: !!mysqlId } + ); - const { mutateAsync: reload, isLoading: isReloading } = - api.mysql.reload.useMutation(); - const { mutateAsync: start, isLoading: isStarting } = - api.mysql.start.useMutation(); + const { mutateAsync: reload, isLoading: isReloading } = + api.mysql.reload.useMutation(); + const { mutateAsync: start, isLoading: isStarting } = + api.mysql.start.useMutation(); - const { mutateAsync: stop, isLoading: isStopping } = - api.mysql.stop.useMutation(); + const { mutateAsync: stop, isLoading: isStopping } = + api.mysql.stop.useMutation(); - const [isDrawerOpen, setIsDrawerOpen] = useState(false); - const [filteredLogs, setFilteredLogs] = useState([]); - const [isDeploying, setIsDeploying] = useState(false); - api.mysql.deployWithLogs.useSubscription( - { - mysqlId: mysqlId, - }, - { - enabled: isDeploying, - onData(log) { - if (!isDrawerOpen) { - setIsDrawerOpen(true); - } + const [isDrawerOpen, setIsDrawerOpen] = useState(false); + const [filteredLogs, setFilteredLogs] = useState([]); + const [isDeploying, setIsDeploying] = useState(false); + api.mysql.deployWithLogs.useSubscription( + { + mysqlId: mysqlId, + }, + { + enabled: isDeploying, + onData(log) { + if (!isDrawerOpen) { + setIsDrawerOpen(true); + } - if (log === "Deployment completed successfully!") { - setIsDeploying(false); - } - const parsedLogs = parseLogs(log); - setFilteredLogs((prev) => [...prev, ...parsedLogs]); - }, - onError(error) { - console.error("Deployment logs error:", error); - setIsDeploying(false); - }, - }, - ); - return ( - <> -
- - - Deploy Settings - - - - { - setIsDeploying(true); - await new Promise((resolve) => setTimeout(resolve, 1000)); - refetch(); - }} - > - - - { - await reload({ - mysqlId: mysqlId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Mysql reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading Mysql"); - }); - }} - > - - - {data?.applicationStatus === "idle" ? ( - { - await start({ - mysqlId: mysqlId, - }) - .then(() => { - toast.success("Mysql started successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error starting Mysql"); - }); - }} - > - - - ) : ( - { - await stop({ - mysqlId: mysqlId, - }) - .then(() => { - toast.success("Mysql stopped successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error stopping Mysql"); - }); - }} - > - - - )} - - - - - - - { - setIsDrawerOpen(false); - setFilteredLogs([]); - setIsDeploying(false); - refetch(); - }} - filteredLogs={filteredLogs} - /> -
- - ); + if (log === "Deployment completed successfully!") { + setIsDeploying(false); + } + const parsedLogs = parseLogs(log); + setFilteredLogs((prev) => [...prev, ...parsedLogs]); + }, + onError(error) { + console.error("Deployment logs error:", error); + setIsDeploying(false); + }, + } + ); + return ( + <> +
+ + + Deploy Settings + + + + { + setIsDeploying(true); + await new Promise((resolve) => setTimeout(resolve, 1000)); + refetch(); + }} + > + + + + + + +

Downloads and sets up the MySQL database

+
+
+
+
+ { + await reload({ + mysqlId: mysqlId, + appName: data?.appName || "", + }) + .then(() => { + toast.success("Mysql reloaded successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error reloading Mysql"); + }); + }} + > + + + + + + +

Restart the MySQL service without rebuilding

+
+
+
+
+ {data?.applicationStatus === "idle" ? ( + { + await start({ + mysqlId: mysqlId, + }) + .then(() => { + toast.success("Mysql started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting Mysql"); + }); + }} + > + + + + + + +

+ Start the MySQL database (requires a previous + successful setup) +

+
+
+
+
+ ) : ( + { + await stop({ + mysqlId: mysqlId, + }) + .then(() => { + toast.success("Mysql stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping Mysql"); + }); + }} + > + + + + + + +

Stop the currently running MySQL database

+
+
+
+
+ )} +
+ + + + + + + +

Open a terminal to the MySQL container

+
+
+
+
+
+
+ { + setIsDrawerOpen(false); + setFilteredLogs([]); + setIsDeploying(false); + refetch(); + }} + filteredLogs={filteredLogs} + /> +
+ + ); }; diff --git a/apps/dokploy/components/dashboard/postgres/general/show-external-postgres-credentials.tsx b/apps/dokploy/components/dashboard/postgres/general/show-external-postgres-credentials.tsx index 7643be2d..0c87a7bc 100644 --- a/apps/dokploy/components/dashboard/postgres/general/show-external-postgres-credentials.tsx +++ b/apps/dokploy/components/dashboard/postgres/general/show-external-postgres-credentials.tsx @@ -1,6 +1,6 @@ +import { AlertBlock } from "@/components/shared/alert-block"; import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import { Button } from "@/components/ui/button"; -import { AlertBlock } from "@/components/shared/alert-block"; import { Card, CardContent, @@ -20,154 +20,153 @@ import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; +import Link from "next/link"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; -import Link from "next/link"; const DockerProviderSchema = z.object({ - externalPort: z.preprocess((a) => { - if (a !== null) { - const parsed = Number.parseInt(z.string().parse(a), 10); - return Number.isNaN(parsed) ? null : parsed; - } - return null; - }, z - .number() - .gte(0, "Range must be 0 - 65535") - .lte(65535, "Range must be 0 - 65535") - .nullable()), + externalPort: z.preprocess((a) => { + if (a !== null) { + const parsed = Number.parseInt(z.string().parse(a), 10); + return Number.isNaN(parsed) ? null : parsed; + } + return null; + }, z.number().gte(0, "Range must be 0 - 65535").lte(65535, "Range must be 0 - 65535").nullable()), }); type DockerProvider = z.infer; interface Props { - postgresId: string; + postgresId: string; } export const ShowExternalPostgresCredentials = ({ postgresId }: Props) => { - const { data: ip } = api.settings.getIp.useQuery(); - const { data, refetch } = api.postgres.one.useQuery({ postgresId }); - const { mutateAsync, isLoading } = - api.postgres.saveExternalPort.useMutation(); - const getIp = data?.server?.ipAddress || ip; - const [connectionUrl, setConnectionUrl] = useState(""); + const { data: ip } = api.settings.getIp.useQuery(); + const { data, refetch } = api.postgres.one.useQuery({ postgresId }); + const { mutateAsync, isLoading } = + api.postgres.saveExternalPort.useMutation(); + const getIp = data?.server?.ipAddress || ip; + const [connectionUrl, setConnectionUrl] = useState(""); - const form = useForm({ - defaultValues: {}, - resolver: zodResolver(DockerProviderSchema), - }); + const form = useForm({ + defaultValues: {}, + resolver: zodResolver(DockerProviderSchema), + }); - useEffect(() => { - if (data?.externalPort) { - form.reset({ - externalPort: data.externalPort, - }); - } - }, [form.reset, data, form]); + useEffect(() => { + if (data?.externalPort) { + form.reset({ + externalPort: data.externalPort, + }); + } + }, [form.reset, data, form]); - const onSubmit = async (values: DockerProvider) => { - await mutateAsync({ - externalPort: values.externalPort, - postgresId, - }) - .then(async () => { - toast.success("External Port updated"); - await refetch(); - }) - .catch(() => { - toast.error("Error saving the external port"); - }); - }; + const onSubmit = async (values: DockerProvider) => { + await mutateAsync({ + externalPort: values.externalPort, + postgresId, + }) + .then(async () => { + toast.success("External Port updated"); + await refetch(); + }) + .catch(() => { + toast.error("Error saving the external port"); + }); + }; - useEffect(() => { - const buildConnectionUrl = () => { - const port = form.watch("externalPort") || data?.externalPort; + useEffect(() => { + const buildConnectionUrl = () => { + const port = form.watch("externalPort") || data?.externalPort; - return `postgresql://${data?.databaseUser}:${data?.databasePassword}@${getIp}:${port}/${data?.databaseName}`; - }; + return `postgresql://${data?.databaseUser}:${data?.databasePassword}@${getIp}:${port}/${data?.databaseName}`; + }; - setConnectionUrl(buildConnectionUrl()); - }, [ - data?.appName, - data?.externalPort, - data?.databasePassword, - form, - data?.databaseName, - getIp, - ]); + setConnectionUrl(buildConnectionUrl()); + }, [ + data?.appName, + data?.externalPort, + data?.databasePassword, + form, + data?.databaseName, + getIp, + ]); - return ( - <> -
- - - External Credentials - - In order to make the database reachable trought internet is - required to set a port, make sure the port is not used by another - application or database - - - - {!getIp && ( - - You need to set an IP address in your{" "} - - {data?.serverId - ? "Remote Servers -> Server -> Edit Server -> Update IP Address" - : "Web Server -> Server -> Update Server IP"} - {" "} - to fix the database url connection. - - )} -
- -
-
- { - return ( - - External Port (Internet) - - - - - - ); - }} - /> -
-
- {!!data?.externalPort && ( -
-
- - -
-
- )} + return ( + <> +
+ + + External Credentials + + In order to make the database reachable trought internet is + required to set a port, make sure the port is not used by another + application or database + + + + {!getIp && ( + + You need to set an IP address in your{" "} + + {data?.serverId + ? "Remote Servers -> Server -> Edit Server -> Update IP Address" + : "Web Server -> Server -> Update Server IP"} + {" "} + to fix the database url connection. + + )} + + +
+
+ { + return ( + + External Port (Internet) + + + + + + ); + }} + /> +
+
+ {!!data?.externalPort && ( +
+
+ + +
+
+ )} -
- -
- - -
-
-
- - ); +
+ +
+ + +
+
+
+ + ); }; diff --git a/apps/dokploy/components/dashboard/postgres/general/show-general-postgres.tsx b/apps/dokploy/components/dashboard/postgres/general/show-general-postgres.tsx index a2215545..3692e600 100644 --- a/apps/dokploy/components/dashboard/postgres/general/show-general-postgres.tsx +++ b/apps/dokploy/components/dashboard/postgres/general/show-general-postgres.tsx @@ -3,247 +3,244 @@ import { DrawerLogs } from "@/components/shared/drawer-logs"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, } from "@/components/ui/tooltip"; -import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { api } from "@/utils/api"; -import { - Ban, - CheckCircle2, - HelpCircle, - RefreshCcw, - Terminal, -} from "lucide-react"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; +import { Ban, CheckCircle2, RefreshCcw, Rocket, Terminal } from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; import { type LogLine, parseLogs } from "../../docker/logs/utils"; import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal"; interface Props { - postgresId: string; + postgresId: string; } export const ShowGeneralPostgres = ({ postgresId }: Props) => { - const { data, refetch } = api.postgres.one.useQuery( - { - postgresId: postgresId, - }, - { enabled: !!postgresId }, - ); + const { data, refetch } = api.postgres.one.useQuery( + { + postgresId: postgresId, + }, + { enabled: !!postgresId } + ); - const { mutateAsync: reload, isLoading: isReloading } = - api.postgres.reload.useMutation(); + const { mutateAsync: reload, isLoading: isReloading } = + api.postgres.reload.useMutation(); - const { mutateAsync: stop, isLoading: isStopping } = - api.postgres.stop.useMutation(); + const { mutateAsync: stop, isLoading: isStopping } = + api.postgres.stop.useMutation(); - const { mutateAsync: start, isLoading: isStarting } = - api.postgres.start.useMutation(); + const { mutateAsync: start, isLoading: isStarting } = + api.postgres.start.useMutation(); - const [isDrawerOpen, setIsDrawerOpen] = useState(false); - const [filteredLogs, setFilteredLogs] = useState([]); - const [isDeploying, setIsDeploying] = useState(false); - api.postgres.deployWithLogs.useSubscription( - { - postgresId: postgresId, - }, - { - enabled: isDeploying, - onData(log) { - if (!isDrawerOpen) { - setIsDrawerOpen(true); - } + const [isDrawerOpen, setIsDrawerOpen] = useState(false); + const [filteredLogs, setFilteredLogs] = useState([]); + const [isDeploying, setIsDeploying] = useState(false); + api.postgres.deployWithLogs.useSubscription( + { + postgresId: postgresId, + }, + { + enabled: isDeploying, + onData(log) { + if (!isDrawerOpen) { + setIsDrawerOpen(true); + } - if (log === "Deployment completed successfully!") { - setIsDeploying(false); - } - const parsedLogs = parseLogs(log); - setFilteredLogs((prev) => [...prev, ...parsedLogs]); - }, - onError(error) { - console.error("Deployment logs error:", error); - setIsDeploying(false); - }, - }, - ); + if (log === "Deployment completed successfully!") { + setIsDeploying(false); + } + const parsedLogs = parseLogs(log); + setFilteredLogs((prev) => [...prev, ...parsedLogs]); + }, + onError(error) { + console.error("Deployment logs error:", error); + setIsDeploying(false); + }, + } + ); - return ( - <> -
- - - Deploy Settings - - - - { - setIsDeploying(true); - await new Promise((resolve) => setTimeout(resolve, 1000)); - refetch(); - }} - > - - - { - await reload({ - postgresId: postgresId, - appName: data?.appName || "", - }) - .then(() => { - toast.success("Postgres reloaded successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error reloading Postgres"); - }); - }} - > - - - {data?.applicationStatus === "idle" ? ( - { - await start({ - postgresId: postgresId, - }) - .then(() => { - toast.success("Postgres started successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error starting Postgres"); - }); - }} - > - - - ) : ( - { - await stop({ - postgresId: postgresId, - }) - .then(() => { - toast.success("Postgres stopped successfully"); - refetch(); - }) - .catch(() => { - toast.error("Error stopping Postgres"); - }); - }} - > - - - )} - - - - - - - { - setIsDrawerOpen(false); - setFilteredLogs([]); - setIsDeploying(false); - refetch(); - }} - filteredLogs={filteredLogs} - /> -
- - ); + return ( + <> +
+ + + Deploy Settings + + + + { + setIsDeploying(true); + await new Promise((resolve) => setTimeout(resolve, 1000)); + refetch(); + }} + > + + + + + + +

Downloads and sets up the PostgreSQL database

+
+
+
+
+ { + await reload({ + postgresId: postgresId, + appName: data?.appName || "", + }) + .then(() => { + toast.success("Postgres reloaded successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error reloading Postgres"); + }); + }} + > + + + + + + +

+ Reload the PostgreSQL when you change configuration or + environment variables +

+
+
+
+
+ {data?.applicationStatus === "idle" ? ( + { + await start({ + postgresId: postgresId, + }) + .then(() => { + toast.success("Postgres started successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error starting Postgres"); + }); + }} + > + + + + + + +

+ Start the PostgreSQL database (requires a previous + successful setup) +

+
+
+
+
+ ) : ( + { + await stop({ + postgresId: postgresId, + }) + .then(() => { + toast.success("Postgres stopped successfully"); + refetch(); + }) + .catch(() => { + toast.error("Error stopping Postgres"); + }); + }} + > + + + + + + +

Stop the currently running PostgreSQL database

+
+
+
+
+ )} +
+ + + +
+
+ { + setIsDrawerOpen(false); + setFilteredLogs([]); + setIsDeploying(false); + refetch(); + }} + filteredLogs={filteredLogs} + /> +
+ + ); }; diff --git a/apps/dokploy/components/dashboard/postgres/general/show-internal-postgres-credentials.tsx b/apps/dokploy/components/dashboard/postgres/general/show-internal-postgres-credentials.tsx index 545150f8..cff00a99 100644 --- a/apps/dokploy/components/dashboard/postgres/general/show-internal-postgres-credentials.tsx +++ b/apps/dokploy/components/dashboard/postgres/general/show-internal-postgres-credentials.tsx @@ -5,58 +5,58 @@ import { Label } from "@/components/ui/label"; import { api } from "@/utils/api"; interface Props { - postgresId: string; + postgresId: string; } export const ShowInternalPostgresCredentials = ({ postgresId }: Props) => { - const { data } = api.postgres.one.useQuery({ postgresId }); - return ( - <> -
- - - Internal Credentials - - -
-
- - -
-
- - -
-
- -
- -
-
-
- - -
+ const { data } = api.postgres.one.useQuery({ postgresId }); + return ( + <> +
+ + + Internal Credentials + + +
+
+ + +
+
+ + +
+
+ +
+ +
+
+
+ + +
-
- - -
+
+ + +
-
- - -
-
-
-
-
- - ); +
+ + +
+
+
+
+
+ + ); }; // ReplyError: MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-w diff --git a/apps/dokploy/components/dashboard/postgres/update-postgres.tsx b/apps/dokploy/components/dashboard/postgres/update-postgres.tsx index 2b8804a5..33ed7a60 100644 --- a/apps/dokploy/components/dashboard/postgres/update-postgres.tsx +++ b/apps/dokploy/components/dashboard/postgres/update-postgres.tsx @@ -21,145 +21,146 @@ import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; -import { PenBoxIcon } from "lucide-react"; +import { PenBox } from "lucide-react"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; const updatePostgresSchema = z.object({ - name: z.string().min(1, { - message: "Name is required", - }), - description: z.string().optional(), + name: z.string().min(1, { + message: "Name is required", + }), + description: z.string().optional(), }); type UpdatePostgres = z.infer; interface Props { - postgresId: string; + postgresId: string; } export const UpdatePostgres = ({ postgresId }: Props) => { - const [isOpen, setIsOpen] = useState(false); - const utils = api.useUtils(); - const { mutateAsync, error, isError, isLoading } = - api.postgres.update.useMutation(); - const { data } = api.postgres.one.useQuery( - { - postgresId, - }, - { - enabled: !!postgresId, - }, - ); - const form = useForm({ - defaultValues: { - description: data?.description ?? "", - name: data?.name ?? "", - }, - resolver: zodResolver(updatePostgresSchema), - }); - useEffect(() => { - if (data) { - form.reset({ - description: data.description ?? "", - name: data.name, - }); - } - }, [data, form, form.reset]); + const [isOpen, setIsOpen] = useState(false); + const utils = api.useUtils(); + const { mutateAsync, error, isError, isLoading } = + api.postgres.update.useMutation(); + const { data } = api.postgres.one.useQuery( + { + postgresId, + }, + { + enabled: !!postgresId, + } + ); + const form = useForm({ + defaultValues: { + description: data?.description ?? "", + name: data?.name ?? "", + }, + resolver: zodResolver(updatePostgresSchema), + }); + useEffect(() => { + if (data) { + form.reset({ + description: data.description ?? "", + name: data.name, + }); + } + }, [data, form, form.reset]); - const onSubmit = async (formData: UpdatePostgres) => { - await mutateAsync({ - name: formData.name, - postgresId: postgresId, - description: formData.description || "", - }) - .then(() => { - toast.success("Postgres updated successfully"); - utils.postgres.one.invalidate({ - postgresId: postgresId, - }); - setIsOpen(false); - }) - .catch(() => { - toast.error("Error updating Postgres"); - }) - .finally(() => {}); - }; + const onSubmit = async (formData: UpdatePostgres) => { + await mutateAsync({ + name: formData.name, + postgresId: postgresId, + description: formData.description || "", + }) + .then(() => { + toast.success("Postgres updated successfully"); + utils.postgres.one.invalidate({ + postgresId: postgresId, + }); + setIsOpen(false); + }) + .catch(() => { + toast.error("Error updating Postgres"); + }) + .finally(() => {}); + }; - return ( - - - - - - - Modify Postgres - Update the Postgres data - - {isError && {error?.message}} + return ( + + + + + + + Modify Postgres + Update the Postgres data + + {isError && {error?.message}} -
-
-
- - ( - - Name - - - +
+
+ + + ( + + Name + + + - - - )} - /> - ( - - Description - -