From 29eb490e2defb32555ea25fb2a7948825e19ea02 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Thu, 6 Mar 2025 23:46:21 -0600 Subject: [PATCH] feat(destinations): add createdAt timestamp and display creation date --- .../destination/handle-destinations.tsx | 99 +- .../destination/show-destinations.tsx | 14 +- .../drizzle/0070_useful_serpent_society.sql | 1 + apps/dokploy/drizzle/meta/0070_snapshot.json | 5126 +++++++++++++++++ apps/dokploy/drizzle/meta/_journal.json | 7 + .../dokploy/server/api/routers/destination.ts | 3 +- packages/server/src/db/schema/destination.ts | 3 +- 7 files changed, 5209 insertions(+), 44 deletions(-) create mode 100644 apps/dokploy/drizzle/0070_useful_serpent_society.sql create mode 100644 apps/dokploy/drizzle/meta/0070_snapshot.json diff --git a/apps/dokploy/components/dashboard/settings/destination/handle-destinations.tsx b/apps/dokploy/components/dashboard/settings/destination/handle-destinations.tsx index 4bd78c45..958802e3 100644 --- a/apps/dokploy/components/dashboard/settings/destination/handle-destinations.tsx +++ b/apps/dokploy/components/dashboard/settings/destination/handle-destinations.tsx @@ -39,12 +39,12 @@ import { S3_PROVIDERS } from "./constants"; const addDestination = z.object({ name: z.string().min(1, "Name is required"), - provider: z.string().optional(), - accessKeyId: z.string(), - secretAccessKey: z.string(), - bucket: z.string(), + provider: z.string().min(1, "Provider is required"), + accessKeyId: z.string().min(1, "Access Key Id is required"), + secretAccessKey: z.string().min(1, "Secret Access Key is required"), + bucket: z.string().min(1, "Bucket is required"), region: z.string(), - endpoint: z.string(), + endpoint: z.string().min(1, "Endpoint is required"), serverId: z.string().optional(), }); @@ -129,6 +129,58 @@ export const HandleDestinations = ({ destinationId }: Props) => { ); }); }; + + const handleTestConnection = async (serverId?: string) => { + const result = await form.trigger([ + "provider", + "accessKeyId", + "secretAccessKey", + "bucket", + "endpoint", + ]); + + if (!result) { + const errors = form.formState.errors; + const errorFields = Object.entries(errors) + .map(([field, error]) => `${field}: ${error?.message}`) + .filter(Boolean) + .join("\n"); + + toast.error("Please fill all required fields", { + description: errorFields, + }); + return; + } + + const provider = form.getValues("provider"); + const accessKey = form.getValues("accessKeyId"); + const secretKey = form.getValues("secretAccessKey"); + const bucket = form.getValues("bucket"); + const endpoint = form.getValues("endpoint"); + const region = form.getValues("region"); + + const connectionString = `:s3,provider=${provider},access_key_id=${accessKey},secret_access_key=${secretKey},endpoint=${endpoint}${region ? `,region=${region}` : ""}:${bucket}`; + + await testConnection({ + provider, + accessKey, + bucket, + endpoint, + name: "Test", + region, + secretAccessKey: secretKey, + serverId, + }) + .then(() => { + toast.success("Connection Success"); + }) + .catch((e) => { + toast.error("Error connecting to provider", { + description: `${e.message}\n\nTry manually: rclone ls ${connectionString}`, + }); + }); + }; + return ( @@ -349,26 +401,9 @@ export const HandleDestinations = ({ destinationId }: Props) => {