From cb23d726fe7970eca8cb68f65855ef50cd38781d Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 5 Jul 2026 16:34:35 -0600 Subject: [PATCH] feat(databases): add copy button to User and Database Name fields (#4735) * feat(databases): add copy button to User and Database Name fields Adds an enableCopyButton prop to the Input component and uses it on the User, Database Name, and Internal Host fields across Postgres, MySQL, MariaDB, MongoDB, Redis, and Libsql credential views. Closes #4495 * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../show-internal-libsql-credentials.tsx | 4 +- .../show-internal-mariadb-credentials.tsx | 6 +- .../show-internal-mongo-credentials.tsx | 4 +- .../show-internal-mysql-credentials.tsx | 6 +- .../show-internal-postgres-credentials.tsx | 6 +- .../show-internal-redis-credentials.tsx | 4 +- apps/dokploy/components/ui/input.tsx | 99 ++++++++++++------- apps/dokploy/server/api/routers/deployment.ts | 4 +- 8 files changed, 79 insertions(+), 54 deletions(-) diff --git a/apps/dokploy/components/dashboard/libsql/general/show-internal-libsql-credentials.tsx b/apps/dokploy/components/dashboard/libsql/general/show-internal-libsql-credentials.tsx index bcdc75a25..dbd344d99 100644 --- a/apps/dokploy/components/dashboard/libsql/general/show-internal-libsql-credentials.tsx +++ b/apps/dokploy/components/dashboard/libsql/general/show-internal-libsql-credentials.tsx @@ -28,7 +28,7 @@ export const ShowInternalLibsqlCredentials = ({ libsqlId }: Props) => {
- +
@@ -71,7 +71,7 @@ export const ShowInternalLibsqlCredentials = ({ libsqlId }: Props) => {
- +
diff --git a/apps/dokploy/components/dashboard/mariadb/general/show-internal-mariadb-credentials.tsx b/apps/dokploy/components/dashboard/mariadb/general/show-internal-mariadb-credentials.tsx index 04d431fa1..7e649224e 100644 --- a/apps/dokploy/components/dashboard/mariadb/general/show-internal-mariadb-credentials.tsx +++ b/apps/dokploy/components/dashboard/mariadb/general/show-internal-mariadb-credentials.tsx @@ -25,11 +25,11 @@ export const ShowInternalMariadbCredentials = ({ mariadbId }: Props) => {
- +
- +
@@ -79,7 +79,7 @@ export const ShowInternalMariadbCredentials = ({ mariadbId }: Props) => {
- +
diff --git a/apps/dokploy/components/dashboard/mongo/general/show-internal-mongo-credentials.tsx b/apps/dokploy/components/dashboard/mongo/general/show-internal-mongo-credentials.tsx index ef38fe3cb..e9fa28d96 100644 --- a/apps/dokploy/components/dashboard/mongo/general/show-internal-mongo-credentials.tsx +++ b/apps/dokploy/components/dashboard/mongo/general/show-internal-mongo-credentials.tsx @@ -25,7 +25,7 @@ export const ShowInternalMongoCredentials = ({ mongoId }: Props) => {
- +
@@ -55,7 +55,7 @@ export const ShowInternalMongoCredentials = ({ mongoId }: Props) => {
- +
diff --git a/apps/dokploy/components/dashboard/mysql/general/show-internal-mysql-credentials.tsx b/apps/dokploy/components/dashboard/mysql/general/show-internal-mysql-credentials.tsx index 39937badd..eb578871b 100644 --- a/apps/dokploy/components/dashboard/mysql/general/show-internal-mysql-credentials.tsx +++ b/apps/dokploy/components/dashboard/mysql/general/show-internal-mysql-credentials.tsx @@ -25,11 +25,11 @@ export const ShowInternalMysqlCredentials = ({ mysqlId }: Props) => {
- +
- +
@@ -79,7 +79,7 @@ export const ShowInternalMysqlCredentials = ({ mysqlId }: Props) => {
- +
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 3d1b1032e..d58a835d4 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 @@ -25,11 +25,11 @@ export const ShowInternalPostgresCredentials = ({ postgresId }: Props) => {
- +
- +
@@ -57,7 +57,7 @@ export const ShowInternalPostgresCredentials = ({ postgresId }: Props) => {
- +
diff --git a/apps/dokploy/components/dashboard/redis/general/show-internal-redis-credentials.tsx b/apps/dokploy/components/dashboard/redis/general/show-internal-redis-credentials.tsx index 3dd6814a2..1913d2b68 100644 --- a/apps/dokploy/components/dashboard/redis/general/show-internal-redis-credentials.tsx +++ b/apps/dokploy/components/dashboard/redis/general/show-internal-redis-credentials.tsx @@ -25,7 +25,7 @@ export const ShowInternalRedisCredentials = ({ redisId }: Props) => {
- +
@@ -53,7 +53,7 @@ export const ShowInternalRedisCredentials = ({ redisId }: Props) => {
- +
diff --git a/apps/dokploy/components/ui/input.tsx b/apps/dokploy/components/ui/input.tsx index 6ff6e2a1d..baf64d599 100644 --- a/apps/dokploy/components/ui/input.tsx +++ b/apps/dokploy/components/ui/input.tsx @@ -1,13 +1,17 @@ -import { EyeIcon, EyeOffIcon, RefreshCcw } from "lucide-react"; +import copy from "copy-to-clipboard"; +import { Clipboard, EyeIcon, EyeOffIcon, RefreshCcw } from "lucide-react"; import * as React from "react"; +import { toast } from "sonner"; import { generateRandomPassword } from "@/lib/password-utils"; import { cn } from "@/lib/utils"; +import { Button } from "./button"; export interface InputProps extends React.ComponentProps<"input"> { errorMessage?: string; enablePasswordGenerator?: boolean; passwordGeneratorLength?: number; + enableCopyButton?: boolean; } function Input({ @@ -16,6 +20,7 @@ function Input({ errorMessage, enablePasswordGenerator = false, passwordGeneratorLength, + enableCopyButton = false, ref, ...props }: InputProps) { @@ -65,49 +70,67 @@ function Input({ input.dispatchEvent(new Event("input", { bubbles: true })); }; - return ( - <> -
- - {isPassword && ( -
- {shouldShowGenerator && ( - - )} + const handleCopy = () => { + copy(inputRef.current?.value || ""); + toast.success("Value is copied to clipboard"); + }; + + const inputElement = ( +
+ + {isPassword && ( +
+ {shouldShowGenerator && ( -
- )} -
+ )} + +
+ )} +
+ ); + + return ( + <> + {enableCopyButton ? ( +
+ {inputElement} + +
+ ) : ( + inputElement + )} {errorMessage && ( {errorMessage} diff --git a/apps/dokploy/server/api/routers/deployment.ts b/apps/dokploy/server/api/routers/deployment.ts index 1df784063..dcc74226a 100644 --- a/apps/dokploy/server/api/routers/deployment.ts +++ b/apps/dokploy/server/api/routers/deployment.ts @@ -136,7 +136,9 @@ export const deploymentRouter = createTRPCRouter({ }); } else if (schedule.serverId) { const targetServer = await findServerById(schedule.serverId); - if (targetServer.organizationId !== ctx.session.activeOrganizationId) { + if ( + targetServer.organizationId !== ctx.session.activeOrganizationId + ) { throw new TRPCError({ code: "UNAUTHORIZED", message: "You don't have access to this schedule.",