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");
- });
- }}
- >
-
- Deploy
-
-
-
-
-
-
-
- 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
-
-
-
- {
- await redeploy({
- applicationId: applicationId,
- })
- .then(() => {
- toast.success("Application rebuilt successfully");
- refetch();
- })
- .catch(() => {
- toast.error("Error rebuilding application");
- });
- }}
- >
-
- Rebuild
-
-
-
-
-
-
-
-
- Only rebuilds the application without downloading new
- code
-
-
-
-
-
-
+ 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");
+ });
+ }}
+ >
+
+
+
+
+ Deploy
+
+
+
+
+
+ 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
+
+
+
+
+
+ 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");
+ });
+ }}
+ >
+
+
+
+
+ Rebuild
+
+
+
+
+
+ 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");
- });
- }}
- >
-
- Start
-
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
- Stop the currently running application
-
-
-
-
-
- )}
-
-
-
-
- Open Terminal
-
-
-
- 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
+
+
+
+
+
+ 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
+
+
+
+
+ Stop the currently running application
+
+
+
+
+ )}
+
+
+
+
+ Open Terminal
+
+
+
+ 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");
- });
- }}
- >
-
- Deploy
-
-
-
-
-
-
- Downloads the source code and performs a complete build
-
-
-
-
-
- {
- await redeploy({
- composeId: composeId,
- })
- .then(() => {
- toast.success("Compose rebuilt successfully");
- refetch();
- })
- .catch(() => {
- toast.error("Error rebuilding compose");
- });
- }}
- >
-
- Rebuild
-
-
-
-
-
-
-
- Only rebuilds the compose without downloading new code
-
-
-
-
-
- {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
-
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
- Stop the currently running compose
-
-
-
-
-
- )}
-
-
-
-
- Open Terminal
-
-
-
- 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");
+ });
+ }}
+ >
+
+
+
+
+ Deploy
+
+
+
+
+ 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
+
+
+
+
+
+ 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
+
+
+
+
+
+ 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
+
+
+
+
+ Stop the currently running compose
+
+
+
+
+ )}
+
+
+
+
+ Open Terminal
+
+
+
+ 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.
-
- )}
-
+
+
+
+
+ >
+ );
};
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();
- }}
- >
-
- Deploy
-
-
-
-
-
-
- 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");
- });
- }}
- >
-
- Reload
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
- Stop the currently running MariaDB database
-
-
-
-
-
- )}
-
-
-
-
- Open Terminal
-
-
-
-
-
{
- setIsDrawerOpen(false);
- setFilteredLogs([]);
- setIsDeploying(false);
- refetch();
- }}
- filteredLogs={filteredLogs}
- />
-
- >
- );
+ return (
+ <>
+
+
+
+ Deploy Settings
+
+
+
+ {
+ setIsDeploying(true);
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+ refetch();
+ }}
+ >
+
+
+
+
+ Deploy
+
+
+
+
+ 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");
+ });
+ }}
+ >
+
+
+
+
+ Reload
+
+
+
+
+ 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
+
+
+
+
+
+ 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
+
+
+
+
+ Stop the currently running MariaDB database
+
+
+
+
+ )}
+
+
+
+
+
+
+ Open Terminal
+
+
+
+
+ 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 && (
+
+ )}
-
-
- Save
-
-
-
-
-
-
-
- >
- );
+
+
+ Save
+
+
+
+
+
+
+
+ >
+ );
};
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();
- }}
- >
-
- Deploy
-
-
-
-
-
-
- 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");
- });
- }}
- >
-
- Reload
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
- Stop the currently running MongoDB database
-
-
-
-
-
- )}
-
-
-
-
- Open Terminal
-
-
-
-
-
{
- 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();
+ }}
+ >
+
+
+
+
+ Deploy
+
+
+
+
+ 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");
+ });
+ }}
+ >
+
+
+
+
+ Reload
+
+
+
+
+ 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
+
+
+
+
+
+ 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
+
+
+
+
+ Stop the currently running MongoDB database
+
+
+
+
+ )}
+
+
+
+
+
+
+ Open Terminal
+
+
+
+
+ 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 && (
+
+ )}
-
-
- Save
-
-
-
-
-
-
-
- >
- );
+
+
+ Save
+
+
+
+
+
+
+
+ >
+ );
};
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();
- }}
- >
-
- Deploy
-
-
-
-
-
-
- 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");
- });
- }}
- >
-
- Reload
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
- Stop the currently running MySQL database
-
-
-
-
-
- )}
-
-
-
-
- Open Terminal
-
-
-
-
-
{
- 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();
+ }}
+ >
+
+
+
+
+ Deploy
+
+
+
+
+ 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");
+ });
+ }}
+ >
+
+
+
+
+ Reload
+
+
+
+
+ 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
+
+
+
+
+
+ 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
+
+
+
+
+ Stop the currently running MySQL database
+
+
+
+
+ )}
+
+
+
+
+
+
+ Open Terminal
+
+
+
+
+ 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 && (
+
+ )}
-
-
- Save
-
-
-
-
-
-
-
- >
- );
+
+
+ Save
+
+
+
+
+
+
+
+ >
+ );
};
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();
- }}
- >
-
- Deploy
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
- Restart the PostgreSQL service without rebuilding
-
-
-
-
-
- {data?.applicationStatus === "idle" ? (
- {
- await start({
- postgresId: postgresId,
- })
- .then(() => {
- toast.success("Postgres started successfully");
- refetch();
- })
- .catch(() => {
- toast.error("Error starting Postgres");
- });
- }}
- >
-
- Start
-
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
- Stop the currently running PostgreSQL database
-
-
-
-
-
- )}
-
-
-
-
- Open Terminal
-
-
-
-
-
{
- setIsDrawerOpen(false);
- setFilteredLogs([]);
- setIsDeploying(false);
- refetch();
- }}
- filteredLogs={filteredLogs}
- />
-
- >
- );
+ return (
+ <>
+
+
+
+ Deploy Settings
+
+
+
+ {
+ setIsDeploying(true);
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+ refetch();
+ }}
+ >
+
+
+
+
+ Deploy
+
+
+
+
+ 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
+
+
+
+
+
+ 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
+
+
+
+
+
+ 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
+
+
+
+
+ Stop the currently running PostgreSQL database
+
+
+
+
+ )}
+
+
+
+
+ Open Terminal
+
+
+
+
+
{
+ 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
-
-
-
-
- User
-
-
-
- Database Name
-
-
-
-
- Internal Port (Container)
-
-
+ const { data } = api.postgres.one.useQuery({ postgresId });
+ return (
+ <>
+
+
+
+ Internal Credentials
+
+
+
-
-
-
- >
- );
+
+ Internal Connection URL
+
+
+
+
+
+
+ >
+ );
};
// 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} }
-
+
+
+ );
};
diff --git a/apps/dokploy/components/dashboard/redis/general/show-external-redis-credentials.tsx b/apps/dokploy/components/dashboard/redis/general/show-external-redis-credentials.tsx
index 5abf0bc1..75b5478a 100644
--- a/apps/dokploy/components/dashboard/redis/general/show-external-redis-credentials.tsx
+++ b/apps/dokploy/components/dashboard/redis/general/show-external-redis-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,146 +20,145 @@ 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 {
- redisId: string;
+ redisId: string;
}
export const ShowExternalRedisCredentials = ({ redisId }: Props) => {
- const { data: ip } = api.settings.getIp.useQuery();
- const { data, refetch } = api.redis.one.useQuery({ redisId });
- const { mutateAsync, isLoading } = api.redis.saveExternalPort.useMutation();
- const [connectionUrl, setConnectionUrl] = useState("");
- const getIp = data?.server?.ipAddress || ip;
+ const { data: ip } = api.settings.getIp.useQuery();
+ const { data, refetch } = api.redis.one.useQuery({ redisId });
+ const { mutateAsync, isLoading } = api.redis.saveExternalPort.useMutation();
+ const [connectionUrl, setConnectionUrl] = useState("");
+ const getIp = data?.server?.ipAddress || ip;
- 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,
- redisId,
- })
- .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,
+ redisId,
+ })
+ .then(async () => {
+ toast.success("External Port updated");
+ await refetch();
+ })
+ .catch(() => {
+ toast.error("Error saving the external port");
+ });
+ };
- useEffect(() => {
- const buildConnectionUrl = () => {
- const _hostname = window.location.hostname;
- const port = form.watch("externalPort") || data?.externalPort;
+ useEffect(() => {
+ const buildConnectionUrl = () => {
+ const _hostname = window.location.hostname;
+ const port = form.watch("externalPort") || data?.externalPort;
- return `redis://default:${data?.databasePassword}@${getIp}:${port}`;
- };
+ return `redis://default:${data?.databasePassword}@${getIp}:${port}`;
+ };
- setConnectionUrl(buildConnectionUrl());
- }, [data?.appName, data?.externalPort, data?.databasePassword, 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, 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 && (
+
+ )}
-
-
- Save
-
-
-
-
-
-
-
- >
- );
+
+
+ Save
+
+
+
+
+
+
+
+ >
+ );
};
diff --git a/apps/dokploy/components/dashboard/redis/general/show-general-redis.tsx b/apps/dokploy/components/dashboard/redis/general/show-general-redis.tsx
index d9c2e10a..fabd1026 100644
--- a/apps/dokploy/components/dashboard/redis/general/show-general-redis.tsx
+++ b/apps/dokploy/components/dashboard/redis/general/show-general-redis.tsx
@@ -8,241 +8,244 @@ 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 {
- redisId: string;
+ redisId: string;
}
export const ShowGeneralRedis = ({ redisId }: Props) => {
- const { data, refetch } = api.redis.one.useQuery(
- {
- redisId,
- },
- { enabled: !!redisId },
- );
+ const { data, refetch } = api.redis.one.useQuery(
+ {
+ redisId,
+ },
+ { enabled: !!redisId }
+ );
- const { mutateAsync: reload, isLoading: isReloading } =
- api.redis.reload.useMutation();
- const { mutateAsync: start, isLoading: isStarting } =
- api.redis.start.useMutation();
+ const { mutateAsync: reload, isLoading: isReloading } =
+ api.redis.reload.useMutation();
+ const { mutateAsync: start, isLoading: isStarting } =
+ api.redis.start.useMutation();
- const { mutateAsync: stop, isLoading: isStopping } =
- api.redis.stop.useMutation();
+ const { mutateAsync: stop, isLoading: isStopping } =
+ api.redis.stop.useMutation();
- const [isDrawerOpen, setIsDrawerOpen] = useState(false);
- const [filteredLogs, setFilteredLogs] = useState([]);
- const [isDeploying, setIsDeploying] = useState(false);
- api.redis.deployWithLogs.useSubscription(
- {
- redisId: redisId,
- },
- {
- enabled: isDeploying,
- onData(log) {
- if (!isDrawerOpen) {
- setIsDrawerOpen(true);
- }
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false);
+ const [filteredLogs, setFilteredLogs] = useState([]);
+ const [isDeploying, setIsDeploying] = useState(false);
+ api.redis.deployWithLogs.useSubscription(
+ {
+ redisId: redisId,
+ },
+ {
+ 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();
- }}
- >
-
- Deploy
-
-
-
-
-
-
- Downloads and sets up the Redis database
-
-
-
-
-
- {
- await reload({
- redisId: redisId,
- appName: data?.appName || "",
- })
- .then(() => {
- toast.success("Redis reloaded successfully");
- refetch();
- })
- .catch(() => {
- toast.error("Error reloading Redis");
- });
- }}
- >
-
- Reload
-
-
-
-
-
-
-
- Restart the Redis service without rebuilding
-
-
-
-
-
- {data?.applicationStatus === "idle" ? (
- {
- await start({
- redisId: redisId,
- })
- .then(() => {
- toast.success("Redis started successfully");
- refetch();
- })
- .catch(() => {
- toast.error("Error starting Redis");
- });
- }}
- >
-
- Start
-
-
-
-
-
-
-
-
- Start the Redis database (requires a previous
- successful setup)
-
-
-
-
-
-
- ) : (
- {
- await stop({
- redisId: redisId,
- })
- .then(() => {
- toast.success("Redis stopped successfully");
- refetch();
- })
- .catch(() => {
- toast.error("Error stopping Redis");
- });
- }}
- >
-
- Stop
-
-
-
-
-
-
-
- Stop the currently running Redis database
-
-
-
-
-
- )}
-
-
-
-
- Open Terminal
-
-
-
-
-
{
- setIsDrawerOpen(false);
- setFilteredLogs([]);
- setIsDeploying(false);
- refetch();
- }}
- filteredLogs={filteredLogs}
- />
-
- >
- );
+ return (
+ <>
+
+
+
+ Deploy Settings
+
+
+
+ {
+ setIsDeploying(true);
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+ refetch();
+ }}
+ >
+
+
+
+
+ Deploy
+
+
+
+
+ Downloads and sets up the Redis database
+
+
+
+
+ {
+ await reload({
+ redisId: redisId,
+ appName: data?.appName || "",
+ })
+ .then(() => {
+ toast.success("Redis reloaded successfully");
+ refetch();
+ })
+ .catch(() => {
+ toast.error("Error reloading Redis");
+ });
+ }}
+ >
+
+
+
+
+ Reload
+
+
+
+
+ Restart the Redis service without rebuilding
+
+
+
+
+ {data?.applicationStatus === "idle" ? (
+ {
+ await start({
+ redisId: redisId,
+ })
+ .then(() => {
+ toast.success("Redis started successfully");
+ refetch();
+ })
+ .catch(() => {
+ toast.error("Error starting Redis");
+ });
+ }}
+ >
+
+
+
+
+ Start
+
+
+
+
+
+ Start the Redis database (requires a previous
+ successful setup)
+
+
+
+
+
+ ) : (
+ {
+ await stop({
+ redisId: redisId,
+ })
+ .then(() => {
+ toast.success("Redis stopped successfully");
+ refetch();
+ })
+ .catch(() => {
+ toast.error("Error stopping Redis");
+ });
+ }}
+ >
+
+
+
+
+ Stop
+
+
+
+
+ Stop the currently running Redis database
+
+
+
+
+ )}
+
+
+
+
+
+
+ Open Terminal
+
+
+
+
+ Open a terminal to the Redis container
+
+
+
+
+
+
+
{
+ setIsDrawerOpen(false);
+ setFilteredLogs([]);
+ setIsDeploying(false);
+ refetch();
+ }}
+ filteredLogs={filteredLogs}
+ />
+
+ >
+ );
};