diff --git a/.env.example b/.env.example index fd299f8..2cd53ec 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,7 @@ NODE_ENV=production -APP_ENV=DEV +NEXT_PUBLIC_APP_ENV=DEV # auth -NEXTAUTH_URL=http://localhost:8080 +NEXTAUTH_URL=http://localhost:3000 NEXTAUTH_SECRET=tZuoxOlhNxw7Q/r3DCiuVKZJ7op1dX/XTLYqG3rEurA= # ai diff --git a/.github/workflows/devs.yml b/.github/workflows/devs.yml index 12b293a..cc32d98 100644 --- a/.github/workflows/devs.yml +++ b/.github/workflows/devs.yml @@ -33,8 +33,9 @@ jobs: # 2) generate a full .env before starting anything: - name: Generate Env File run: | - cat < .env - APP_ENV=TEST + cat < .env + NEXT_PUBLIC_APP_ENV=TEST + DCUP_PARSER=http://localhost:9000 NEXTAUTH_URL=http://localhost:3000 REDIS_DB_ADDRESS=localhost REDIS_DB_PORT=6379 @@ -43,6 +44,18 @@ jobs: OPENAI_KEY="my key" NEXTAUTH_SECRET=tZuoxOlhNxw7Q/r3DCiuVKZJ7op1dX/XTLYqG3rEurA= DRIZZLE_DATABASE_URL=postgres://postgres:root@localhost:5432/dcup + NODE_ENV=production + OPENAI_ENDPOINT=https://models.inference.ai.azure.com + OPENAI_EMBEDDINGS_MODEL=text-embedding-3-small + OPENAI_AGENT_MODEL=gpt-4o-mini + QDRANT_DB_URL=http://localhost:6333 + NEXT_PUBLIC_GOOGLE_CLIENT_ID= + GOOGLE_CLIENT_SECRET= + NEXT_PUBLIC_GOOGLE_API_KEY= + AUTH_GITHUB_ID= + AUTH_GITHUB_SECRET= + API_SECRET=xOAsKzZlYeGqaLiZNv6esJ + API_ACCESS_SECRET=fafkldsajfkldsjfoajFDIOASJFOfdlfja EOF # 3) spin up your other services (redis, postgres, etc): diff --git a/DataSource/Aws/setAwsConnection.ts b/DataSource/Aws/setAwsConnection.ts index f5230c4..5d25f0a 100644 --- a/DataSource/Aws/setAwsConnection.ts +++ b/DataSource/Aws/setAwsConnection.ts @@ -7,13 +7,12 @@ import { connectionConfig } from "../utils"; export const setAWSConnection = async (formData: FormData) => { const config = connectionConfig.safeParse({ connectionId: formData.get("connectionId"), - identifier: formData.get("connectionName"), + identifier: formData.get("identifier"), folderName: formData.get("folderName"), folderId: formData.get("folderId"), metadata: formData.get("metadata"), pageLimit: formData.get("pageLimit"), - documentLimit: formData.get("documentLimit"), - maxPages: formData.get("maxPages") + fileLimit: formData.get("fileLimit"), }) if (!config.success) { @@ -36,14 +35,14 @@ export const setAWSConnection = async (formData: FormData) => { isConfigSet: true, isSyncing: true, limitPages:config.data.pageLimit, - limitFiles: config.data.documentLimit, + limitFiles: config.data.fileLimit, }).where(eq(connections.id, config.data.connectionId)) return { connectionId: config.data.connectionId, service: "AWS", - pageLimit: config.data.maxPages, - fileLimit: config.data.documentLimit, + pageLimit: config.data.pageLimit, + fileLimit: config.data.fileLimit, metadata: config.data.metadata, files: [], links: [] diff --git a/DataSource/DirectUpload/SetNewConfigDirect/SetNewConfigDirect.tsx b/DataSource/DirectUpload/SetNewConfigDirect/SetNewConfigDirect.tsx index 3360715..642759b 100644 --- a/DataSource/DirectUpload/SetNewConfigDirect/SetNewConfigDirect.tsx +++ b/DataSource/DirectUpload/SetNewConfigDirect/SetNewConfigDirect.tsx @@ -16,7 +16,7 @@ export const SetNewConfigDirect = () => { return ( - + diff --git a/DataSource/DirectUpload/UpdateConfigDirect/UpdateConfigDirect.tsx b/DataSource/DirectUpload/UpdateConfigDirect/UpdateConfigDirect.tsx index 0dd6198..de3aa7c 100644 --- a/DataSource/DirectUpload/UpdateConfigDirect/UpdateConfigDirect.tsx +++ b/DataSource/DirectUpload/UpdateConfigDirect/UpdateConfigDirect.tsx @@ -19,7 +19,7 @@ export const UpdateConfigDirect = ({ connection, status }: { connection: Connect return ( - diff --git a/DataSource/DirectUpload/setDirectUploadConnection.ts b/DataSource/DirectUpload/setDirectUploadConnection.ts index 7170549..65ac264 100644 --- a/DataSource/DirectUpload/setDirectUploadConnection.ts +++ b/DataSource/DirectUpload/setDirectUploadConnection.ts @@ -6,7 +6,7 @@ import { z } from "zod"; const directUploadConfig = z.object({ userId: z.string().min(5), - uploadName: z.string().min(1, { message: "Upload Name is required" }), + identifier: z.string().min(2), metadata: z.string() .transform((str, ctx): string => { try { @@ -20,7 +20,7 @@ const directUploadConfig = z.object({ return z.NEVER } }), - pageLimit: z.string().transform((str, ctx): number | null => { + pageLimit: z.string().nullable().transform((str, ctx): number | null => { try { if (str) return parseInt(str) return null @@ -29,7 +29,7 @@ const directUploadConfig = z.object({ return z.NEVER } }), - documentLimit: z.string().nullable().transform((str, ctx): number | null => { + fileLimit: z.string().nullable().transform((str, ctx): number | null => { try { if (str) return parseInt(str) return null @@ -38,14 +38,6 @@ const directUploadConfig = z.object({ return z.NEVER } }), - maxPages: z.string().transform((str, ctx): number => { - try { - return parseInt(str) - } catch (error) { - ctx.addIssue({ code: 'invalid_date', message: "invalid page limit" }) - return z.NEVER - } - }), files: z.array(z.any().refine((file) => { return ( file || @@ -61,14 +53,23 @@ const directUploadConfig = z.object({ const updateDirectUploadConfig = z.object({ connectionId: z.string().min(5), - metadata: z.string() - .transform((str, ctx): string => { + pageLimit: z.string().nullable().transform((str, ctx): number | null => { + try { + if (str) return parseInt(str) + return null + } catch (error) { + ctx.addIssue({ code: 'invalid_date', message: "invalid page limit" }) + return z.NEVER + } + }), + identifier: z.string().min(2).optional(), + metadata: z.string().optional() + .transform((str, ctx): string | undefined => { try { if (str) { JSON.parse(str) return str } - return "{}" } catch (e) { ctx.addIssue({ code: 'custom', message: 'Invalid JSON' }) return z.NEVER @@ -84,27 +85,19 @@ const updateDirectUploadConfig = z.object({ message: "Invalid File", }) ), - maxPages: z.string().transform((str, ctx): number => { - try { - return parseInt(str) - } catch (error) { - ctx.addIssue({ code: 'invalid_date', message: "invalid page limit" }) - return z.NEVER - } - }), links: z.array(z.string().min(5)), removedFiles: z.array(z.string().min(5)) }) export const updateDirectUploadConnection = async (formData: FormData) => { - const config = updateDirectUploadConfig.safeParse({ connectionId: formData.get("connectionId"), + identifier: formData.get("identifier"), metadata: formData.get("metadata") || "{}", files: formData.getAll("files") || [], links: formData.getAll("links") || [], removedFiles: formData.getAll("removedFiles") || [], - maxPages: formData.get("maxPages") + pageLimit: formData.get("pageLimit") }) if (!config.success) { @@ -119,6 +112,13 @@ export const updateDirectUploadConnection = async (formData: FormData) => { const connectionChunksIds: { chunksIds: string[] }[] = []; + await databaseDrizzle + .update(connections) + .set({ + metadata: config.data.metadata, + identifier: config.data.identifier + }).where(eq(connections.id, config.data.connectionId)) + for (const fileName of config.data.removedFiles) { const files = await databaseDrizzle .delete(processedFiles) @@ -146,10 +146,10 @@ export const updateDirectUploadConnection = async (formData: FormData) => { return { connectionId: config.data.connectionId, service: "DIRECT_UPLOAD", - metadata: config.data.metadata, + metadata: config.data.metadata ?? "{}", files: await Promise.all(files), links: config.data.links, - pageLimit: config.data.maxPages, + pageLimit: config.data.pageLimit, fileLimit: null } } @@ -158,11 +158,10 @@ export const setDirectUploadConnection = async (formData: FormData) => { const config = directUploadConfig.safeParse({ userId: formData.get("userId"), - uploadName: formData.get("uploadName"), + identifier: formData.get("identifier"), metadata: formData.get("metadata") || "{}", pageLimit: formData.get("pageLimit"), - documentLimit: formData.get("documentLimit"), - maxPages: formData.get("maxPages"), + fileLimit: formData.get("fileLimit"), files: formData.getAll("files"), links: formData.getAll("links"), }) @@ -177,7 +176,7 @@ export const setDirectUploadConnection = async (formData: FormData) => { throw new Error(`Validation errors - ${errors}`) } - const { files, links, userId, uploadName, metadata, documentLimit, pageLimit } = config.data; + const { files, links, userId, identifier, metadata, fileLimit, pageLimit } = config.data; if (files.length === 0 && links.length === 0) { throw new Error('Please provide at least one file or link to proceed.') @@ -185,13 +184,13 @@ export const setDirectUploadConnection = async (formData: FormData) => { const conn = await databaseDrizzle.insert(connections).values({ userId: userId, - identifier: uploadName, + identifier: identifier, service: 'DIRECT_UPLOAD', metadata: metadata, isConfigSet: true, isSyncing: true, limitPages: pageLimit, - limitFiles: documentLimit, + limitFiles: fileLimit, }).returning({ id: connections.id }) const allFiles = files.map(async (file) => ({ @@ -208,8 +207,8 @@ export const setDirectUploadConnection = async (formData: FormData) => { metadata: metadata, files: await Promise.all(allFiles), links: links, - pageLimit: config.data.maxPages, - fileLimit: documentLimit + pageLimit: config.data.pageLimit, + fileLimit: fileLimit } } diff --git a/DataSource/Dropbox/setDropboxConnection.ts b/DataSource/Dropbox/setDropboxConnection.ts index 28a66b7..a7fd848 100644 --- a/DataSource/Dropbox/setDropboxConnection.ts +++ b/DataSource/Dropbox/setDropboxConnection.ts @@ -7,13 +7,12 @@ import { connectionConfig } from "../utils"; export const setDropboxConnection = async (formData: FormData) => { const config = connectionConfig.safeParse({ connectionId: formData.get("connectionId"), - identifier: formData.get("connectionName"), + identifier: formData.get("identifier"), folderName: formData.get("folderName"), folderId: formData.get("folderId"), metadata: formData.get("metadata"), pageLimit: formData.get("pageLimit"), - documentLimit: formData.get("documentLimit"), - maxPages: formData.get("maxPages"), + fileLimit: formData.get("fileLimit"), }) if (!config.success) { @@ -35,15 +34,15 @@ export const setDropboxConnection = async (formData: FormData) => { metadata: config.data.metadata, isConfigSet: true, isSyncing: true, - limitFiles: config.data.documentLimit, + limitFiles: config.data.fileLimit, limitPages: config.data.pageLimit, }).where(eq(connections.id, config.data.connectionId)) return { connectionId: config.data.connectionId, service: "DROPBOX", - pageLimit: config.data.maxPages, - fileLimit: config.data.documentLimit, + pageLimit: config.data.pageLimit, + fileLimit: config.data.fileLimit, metadata: config.data.metadata, files: [], links: [] diff --git a/DataSource/GoogleDrive/setGoogleDriveConnection.ts b/DataSource/GoogleDrive/setGoogleDriveConnection.ts index ce2c24a..eb4df16 100644 --- a/DataSource/GoogleDrive/setGoogleDriveConnection.ts +++ b/DataSource/GoogleDrive/setGoogleDriveConnection.ts @@ -6,13 +6,12 @@ import { connectionConfig } from "../utils"; export const setGoogleDriveConnection = async (formData: FormData) => { const config = connectionConfig.safeParse({ connectionId: formData.get("connectionId"), - identifier: formData.get("connectionName"), + identifier: formData.get("identifier"), folderName: formData.get("folderName"), folderId: formData.get("folderId"), metadata: formData.get("metadata"), pageLimit: formData.get("pageLimit"), - documentLimit: formData.get("documentLimit"), - maxPages: formData.get("maxPages") + fileLimit: formData.get("fileLimit"), }) if (!config.success) { @@ -33,7 +32,7 @@ export const setGoogleDriveConnection = async (formData: FormData) => { } : undefined, metadata: config.data.metadata, limitPages: config.data.pageLimit, - limitFiles: config.data.documentLimit, + limitFiles: config.data.fileLimit, isConfigSet: true, isSyncing: true, }).where(eq(connections.id, config.data.connectionId)) @@ -41,8 +40,8 @@ export const setGoogleDriveConnection = async (formData: FormData) => { return { connectionId: config.data.connectionId, service: "GOOGLE_DRIVE", - pageLimit: config.data.maxPages, - fileLimit: config.data.documentLimit, + pageLimit: config.data.pageLimit, + fileLimit: config.data.fileLimit, metadata: config.data.metadata, files: [], links: [] diff --git a/DataSource/index.tsx b/DataSource/index.tsx index dcd29aa..8949011 100644 --- a/DataSource/index.tsx +++ b/DataSource/index.tsx @@ -18,7 +18,6 @@ export const DataSource = ({ connection, token, status }: { connection: Connecti case "DIRECT_UPLOAD": return <> - {connection.isConfigSet && } diff --git a/DataSource/utils.ts b/DataSource/utils.ts index a6f968b..0b65c10 100644 --- a/DataSource/utils.ts +++ b/DataSource/utils.ts @@ -30,15 +30,7 @@ export const connectionConfig = z.object({ return z.NEVER } }), - maxPages: z.string().transform((str, ctx): number => { - try { - return parseInt(str) - } catch (error) { - ctx.addIssue({ code: 'invalid_date', message: "invalid page limit" }) - return z.NEVER - } - }), - documentLimit: z.string().nullable().transform((str, ctx): number | null => { + fileLimit: z.string().nullable().transform((str, ctx): number | null => { try { if (str) return parseInt(str) return null diff --git a/actions/connctions/set/index.ts b/actions/connctions/set/index.ts index 383994a..b82b968 100644 --- a/actions/connctions/set/index.ts +++ b/actions/connctions/set/index.ts @@ -1,8 +1,6 @@ "use server" import { authOptions } from "@/auth"; -import { databaseDrizzle } from "@/db"; import { setConnectionToProcess } from "@/fileProcessors/connectors"; -import { Plans } from "@/lib/Plans"; import { fromErrorToFormState, toFormState } from "@/lib/zodErrorHandle"; import { addToProcessFilesQueue } from "@/workers/queues/jobs/processFiles.job"; import { getServerSession } from "next-auth"; @@ -14,64 +12,8 @@ type FormState = { export async function setConnectionConfig(_: FormState, formData: FormData) { const session = await getServerSession(authOptions); - const service = formData.get("service") - const connectionId = formData.get("connectionId") try { if (!session?.user?.id) throw new Error("forbidden"); - const user = await databaseDrizzle.query.users.findFirst({ - where: (u, ops) => ops.eq(u.id, session.user.id!), - columns: { - plan: true, - }, - with: { - connections: { - columns: { - id: true, - }, - with: { - files: { - columns: { - totalPages: true, - } - } - } - } - } - }) - if (!user) throw new Error("no such account") - const plan = Plans[user.plan] - - if (service === "DIRECT_UPLOAD") { - const used = user.connections.length; - if (used >= plan.connections) { - throw new Error( - `You’ve reached your connection limit for the ${user.plan.toLowerCase()} plan (` + - `${used}/${plan.connections}). ` + - `To add more connections, please upgrade your subscription.` - ); - } - } - - const pageProcessed = user.connections - .filter(c => c.id !== connectionId) - .flatMap(conn => conn.files || []) - .reduce((sum, file) => sum + (file.totalPages || 0), 0); - const pageLimit = formData.get("pageLimit") - const remainingPages = plan.pages - pageProcessed; - - if (pageLimit) { - if (Number(pageLimit) > remainingPages) { - throw new Error( - `You requested to process ${pageLimit} pages, but your ` + - `${user.plan.toLowerCase()} plan only allows ${remainingPages} ` + - `more pages this billing period. Please lower the page count or upgrade your plan.` - ); - } else { - formData.set("maxPages", pageLimit) - } - } else { - formData.set("maxPages", remainingPages.toString()) - } formData.set("userId", session.user.id) const config = await setConnectionToProcess(formData) diff --git a/app/api/connections/[id]/files/route.ts b/app/api/connections/[id]/files/route.ts new file mode 100644 index 0000000..097ebe9 --- /dev/null +++ b/app/api/connections/[id]/files/route.ts @@ -0,0 +1,147 @@ +import { databaseDrizzle } from "@/db" +import { processedFiles } from "@/db/schemas/connections" +import { checkAuth } from "@/lib/api_key" +import { tryAndCatch } from "@/lib/try-catch" +import { qdrant_collection_name, qdrantCLient } from "@/qdrant" +import { and, eq } from "drizzle-orm" +import { NextRequest, NextResponse } from "next/server" +import { APIError } from "openai" +import { z } from 'zod' + + +type Params = { + params: Promise<{ + id: string + }> +} + +const FilesName = z.object({ + files: z.array(z.string().min(2)).optional(), + file: z.string().min(2).optional() +}).superRefine((val, ctx) => { + // Check for both fields present + if (val.file && val.files) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "Cannot provide both 'file' and 'files' fields", + path: ["file"], + }); + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "Cannot provide both 'files' and 'file' fields", + path: ["files"], + }); + } + + // Check for neither field present + if (!val.file && !val.files) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "Must provide either 'file' or 'files' field", + path: ["file"], + }); + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "Must provide either 'file' or 'files' field", + path: ["files"], + }); + } +}); + +export async function DELETE(request: NextRequest, { params }: Params) { + const wait = request.nextUrl.searchParams.get("wait") + const isWait = wait === "true" || wait === null + + try { + const { + data: userId, + error: authError, + } = await tryAndCatch(checkAuth(request)) + if (authError) { + return NextResponse.json({ + code: authError.code, + message: authError.message, + }, { status: authError.status }) + } + + + const body = await request.json() + const validation = FilesName.safeParse(body) + + if (!validation.success) { + return NextResponse.json({ + code: "invalid_request", + message: validation.error.errors.map(e => e.message).join(". "), + example: { + validFormat1: { file: "document.pdf" }, + validFormat2: { files: ["doc1.pdf", "doc2.pdf"] } + } + }, { status: 400 }); + } + + const { id } = await params + const connectionChunksIds: { chunksIds: string[] }[] = []; + const connection = await databaseDrizzle.query.connections.findFirst({ + where: (c, ops) => ops.and(ops.eq(c.userId, userId), ops.eq(c.id, id)), + columns: { + id: true, + }, + }) + + if (!connection) { + return NextResponse.json({ + code: "unauthorized", + message: "Connection not found or access denied", + }, { status: 403 }) + } + const filesToDelete = validation.data.file + ? [validation.data.file] + : validation.data.files ?? []; + + + for (const fileName of filesToDelete) { + const { data, error } = await tryAndCatch(databaseDrizzle + .delete(processedFiles) + .where(and( + eq(processedFiles.connectionId, id), + eq(processedFiles.name, fileName) + )).returning({ chunksIds: processedFiles.chunksIds })) + + if (error) { + return NextResponse.json({ + code: "deletion_failed", + message: "Failed to remove file(s) from database" + }, { status: 500 }); + } + connectionChunksIds.push(...data) + } + + for (const { chunksIds } of connectionChunksIds) { + const { error } = await tryAndCatch(qdrantCLient.delete(qdrant_collection_name, { + points: chunksIds, + wait: isWait + })) + if (error) { + return NextResponse.json({ + code: "vector_cleanup_failed", + message: "Failed to delete associated vector data" + }, { status: 500 }); + } + } + + return NextResponse.json({ + code: "ok", + message: `Deleted ${validation.data.file + ? `'${validation.data.file}'` + : validation.data.files?.join(", ") + } successfully${isWait ? "" : " and queued for vector database removal" + }` + }, { status: 200 }); + + } catch (error: any) { + return NextResponse.json( + { code: "internal_server_error", message: error.message }, + { status: 500 }, + ); + } +} diff --git a/app/api/upload/route.ts b/app/api/upload/route.ts index 3fa82c8..d8adeee 100644 --- a/app/api/upload/route.ts +++ b/app/api/upload/route.ts @@ -1,10 +1,10 @@ -import { setDirectUploadConnection } from "@/DataSource/DirectUpload/setDirectUploadConnection"; import { directProcessFiles } from "@/fileProcessors"; import { checkAuth } from "@/lib/api_key"; import { tryAndCatch } from "@/lib/try-catch"; import { addToProcessFilesQueue } from "@/workers/queues/jobs/processFiles.job"; import { NextRequest, NextResponse } from "next/server"; import { APIError } from "@/lib/APIError"; +import { setConnectionToProcess } from "@/fileProcessors/connectors"; export async function POST(request: NextRequest) { const wait = request.nextUrl.searchParams.get("wait") @@ -27,22 +27,23 @@ export async function POST(request: NextRequest) { }, { status: 400 }) formData.set("userId", userId) + formData.set("service", "DIRECT_UPLOAD") const { data: filesConfig, error: errorConfig - } = await tryAndCatch(setDirectUploadConnection(formData)) + } = await tryAndCatch(setConnectionToProcess(formData)) if (errorConfig) return NextResponse.json({ code: "bad_request", message: errorConfig.message, }, { status: 400 }) - if (wait === "true") { + if (wait === "true" || wait === null) { const { error } = await tryAndCatch(directProcessFiles(filesConfig)) if (error) return NextResponse.json({ - code: "internal_server_error", + code: "bad_request", message: error.message - }, { status: 500 }); + }, { status: 400 }); return NextResponse.json({ code: "ok", diff --git a/app/layout.tsx b/app/layout.tsx index 99b7e29..de90952 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -29,9 +29,9 @@ export const metadata: Metadata = { }, }; -if (process.env.APP_ENV === 'TEST') { +if (process.env.NEXT_PUBLIC_APP_ENV === 'TEST') { if (!(global as any).__MSW_SERVER_STARTED__) { - console.log('🔧 MSW mock server starting...'); + console.log('🔧 MSW mock server starting...'); mockServer.listen(); (global as any).__MSW_SERVER_STARTED__ = true; } diff --git a/components/ConfigConnection/ConfigConnection.tsx b/components/ConfigConnection/ConfigConnection.tsx index ef0d7a0..94e46de 100644 --- a/components/ConfigConnection/ConfigConnection.tsx +++ b/components/ConfigConnection/ConfigConnection.tsx @@ -109,10 +109,10 @@ export const ConfigConnection = ({ connection, directory, status, open, setOpen,
- + @@ -166,8 +166,8 @@ export const ConfigConnection = ({ connection, directory, status, open, setOpen,
{getServiceIcon(connection.service)} - + {connection.service.toLowerCase().replace('_', ' ')}
@@ -57,9 +57,9 @@ export default function Connections({ connections, tokens }: { connections: Conn {connection.identifier}

- {connection.folderName || 'Untitled'} - {progress?.processedFile ?? connection.files.length} - {progress?.processedPage ?? connection.files.reduce((sum, file) => sum + file.totalPages, 0)} + {connection.folderName || 'Untitled'} + {progress?.processedFile ?? connection.files.length} + {progress?.processedPage ?? connection.files.reduce((sum, file) => sum + file.totalPages, 0)} {!isMounted ? "Loading..." : timeAgo(connection.createdAt)} @@ -82,7 +82,6 @@ export default function Connections({ connections, tokens }: { connections: Conn } ) - }); } diff --git a/components/UploadFileForm/UploadFileForm.tsx b/components/UploadFileForm/UploadFileForm.tsx index ded86b1..3e7510e 100644 --- a/components/UploadFileForm/UploadFileForm.tsx +++ b/components/UploadFileForm/UploadFileForm.tsx @@ -73,12 +73,11 @@ export const UploadFileForm = ({ setOpen, connection }: TFileForm) => { return (
- +
@@ -89,7 +88,7 @@ export const UploadFileForm = ({ setOpen, connection }: TFileForm) => { id="metadata" name="metadata" placeholder='{"company": "dcup"}' - defaultValue={"{}"} + defaultValue={connection?.metadata ?? ""} className="max-h-10" />
@@ -119,7 +118,7 @@ export const UploadFileForm = ({ setOpen, connection }: TFileForm) => {
-