fix: upload file database extension (#250)

* fix: upload file database

* fix: getFileHeadersBasedOnDbms for default if no dbType compatible

---------

Co-authored-by: charles-gauthereau <charles.gauthereau@soluce-technologies.com>
This commit is contained in:
Charles GTE
2026-04-02 19:47:05 +02:00
committed by GitHub
co-authored by charles-gauthereau
parent be01031501
commit 47c74931d4
3 changed files with 54 additions and 19 deletions
@@ -38,7 +38,7 @@ export const ImportModal = ({database}: ImportModalProps) => {
<Separator className="mt-3 "/> <Separator className="mt-3 "/>
<UploadBackupZone <UploadBackupZone
onSuccessAction={() => setOpen(false)} onSuccessAction={() => setOpen(false)}
databaseId={database.id}/> database={database}/>
</DialogHeader> </DialogHeader>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
@@ -9,13 +9,15 @@ import {ButtonWithLoading} from "@/components/wrappers/common/button/button-with
import {toast} from "sonner"; import {toast} from "sonner";
import {uploadBackupAction} from "@/components/wrappers/dashboard/database/import/upload-backup.action"; import {uploadBackupAction} from "@/components/wrappers/dashboard/database/import/upload-backup.action";
import {Card, CardContent} from "@/components/ui/card"; import {Card, CardContent} from "@/components/ui/card";
import {DatabaseWith} from "@/db/schema/07_database";
import {getFileHeadersBasedOnDbms} from "@/utils/common";
type UploadRetentionZoneProps = { type UploadRetentionZoneProps = {
onSuccessAction?: () => void; onSuccessAction?: () => void;
databaseId: string; database: DatabaseWith;
}; };
export const UploadBackupZone = ({onSuccessAction, databaseId}: UploadRetentionZoneProps) => { export const UploadBackupZone = ({onSuccessAction, database}: UploadRetentionZoneProps) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const router = useRouter(); const router = useRouter();
@@ -30,7 +32,7 @@ export const UploadBackupZone = ({onSuccessAction, databaseId}: UploadRetentionZ
const formData = new FormData(); const formData = new FormData();
formData.append("file", file); formData.append("file", file);
formData.append("databaseId", databaseId); formData.append("databaseId", database.id);
const result = await uploadBackupAction(formData) const result = await uploadBackupAction(formData)
@@ -38,7 +40,7 @@ export const UploadBackupZone = ({onSuccessAction, databaseId}: UploadRetentionZ
if (inner?.success) { if (inner?.success) {
toast.success(inner.actionSuccess?.message); toast.success(inner.actionSuccess?.message);
onSuccessAction?.() onSuccessAction?.()
queryClient.invalidateQueries({queryKey: ["database-data", databaseId]}); queryClient.invalidateQueries({queryKey: ["database-data", database.id]});
router.refresh(); router.refresh();
} else { } else {
toast.error(inner?.actionError?.message); toast.error(inner?.actionError?.message);
@@ -47,19 +49,20 @@ export const UploadBackupZone = ({onSuccessAction, databaseId}: UploadRetentionZ
console.error(err); console.error(err);
toast.error("An error occurred while upload in the backup"); toast.error("An error occurred while upload in the backup");
} finally { } finally {
queryClient.invalidateQueries({queryKey: ["database-data", databaseId]}); queryClient.invalidateQueries({queryKey: ["database-data", database.id]});
setIsProcessing(false); setIsProcessing(false);
} }
}, },
}); });
const acceptDbImportFiles: Record<string, string[]> = { const acceptDbImportFiles = getFileHeadersBasedOnDbms(database.dbms)
"application/sql": [".sql"], console.log(acceptDbImportFiles)
"application/x-sql": [".sql"],
"text/plain": [".sql"], const fileKindDescription = Object.values(acceptDbImportFiles)
"application/octet-stream": [".dump"], .flat()
}; .join(", ");
return ( return (
<> <>
@@ -67,11 +70,11 @@ export const UploadBackupZone = ({onSuccessAction, databaseId}: UploadRetentionZ
<UploadLoader label="Uploading database backup…"/> <UploadLoader label="Uploading database backup…"/>
) : ( ) : (
<DropZoneFile <DropZoneFile
accept={acceptDbImportFiles} accept={getFileHeadersBasedOnDbms(database.dbms)}
maxSize={2 * 1024 * 1024 * 1024} maxSize={2 * 1024 * 1024 * 1024}
maxFiles={1} maxFiles={1}
description="Import database backup" description="Import database backup"
fileKind="Database file (.sql, .dump)" fileKind={`Database file (${fileKindDescription})`}
dragMessage="Click or drag a database dump here" dragMessage="Click or drag a database dump here"
onFileDropAction={(file: File) => setFile(file)} onFileDropAction={(file: File) => setFile(file)}
/> />
@@ -86,8 +89,6 @@ export const UploadBackupZone = ({onSuccessAction, databaseId}: UploadRetentionZ
</ButtonWithLoading> </ButtonWithLoading>
</div> </div>
)} )}
</> </>
); );
}; };
+37 -3
View File
@@ -17,7 +17,7 @@ export function buildOrganizationWithMembers(
const org = rows[0].organization; const org = rows[0].organization;
const invitations : OrganizationInvitation[] = rows const invitations: OrganizationInvitation[] = rows
.filter(r => r.invitation) .filter(r => r.invitation)
.map(r => ({ .map(r => ({
...r.invitation!, ...r.invitation!,
@@ -38,7 +38,6 @@ export function buildOrganizationWithMembers(
} }
export function getFileExtension(dbType: string) { export function getFileExtension(dbType: string) {
switch (dbType) { switch (dbType) {
case "postgresql": case "postgresql":
@@ -48,4 +47,39 @@ export function getFileExtension(dbType: string) {
default: default:
return ".dump"; return ".dump";
} }
} }
export function getFileHeadersBasedOnDbms(dbType: string): Record<string, string[]> {
switch (dbType) {
case "postgresql":
return {
"application/octet-stream": [".dump"],
};
case "mysql":
case "mariadb":
return {
"application/sql": [".sql"],
"application/x-sql": [".sql"],
};
case "mongodb":
return {
"application/gzip": [".archive.gz"],
};
case "firebird":
return {
"application/octet-stream": [".fbk"],
};
case "valkey":
case "redis":
return {
"application/octet-stream": [".rdb"],
};
case "sqlite":
return {
"application/octet-stream": [".backup"],
};
default:
throw new Error(`Unsupported database type: ${dbType}`);
}
}