import React, { useState, useRef } from "react"; import { uploadSchemaDB } from "../api"; export default function SchemaUploadModal({ onClose, onUploadSuccess, addToast }) { const [sqlFile, setSqlFile] = useState(null); const [dbFile, setDbFile] = useState(null); const [erdImage, setErdImage] = useState(null); const [erdPreview, setErdPreview] = useState(null); const [isUploading, setIsUploading] = useState(false); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); // Parse details const [parsedTablesCount, setParsedTablesCount] = useState(0); const [parsedKeysCount, setParsedKeysCount] = useState(0); const sqlInputRef = useRef(null); const dbInputRef = useRef(null); const erdInputRef = useRef(null); const handleSqlFileChange = (e) => { const file = e.target.files[0]; if (!file) return; if (!file.name.endsWith(".sql")) { addToast("Schema file must be a .sql file", "error"); return; } setSqlFile(file); // Read and parse sql file with client-side regex const reader = new FileReader(); reader.onload = (evt) => { const content = evt.target.result; // Simple table match const tablesMatch = content.match(/CREATE\s+TABLE\s+\w+/gi) || []; // Simple foreign key match const keysMatch = content.match(/FOREIGN\s+KEY/gi) || []; setParsedTablesCount(tablesMatch.length); setParsedKeysCount(keysMatch.length); }; reader.readAsText(file); }; const handleErdFileChange = (e) => { const file = e.target.files[0]; if (!file) return; const ext = file.name.substring(file.name.lastIndexOf(".")).toLowerCase(); if (![".png", ".jpg", ".jpeg", ".pdf"].includes(ext)) { addToast("ERD image must be a .png, .jpg, .jpeg, or .pdf file.", "error"); return; } setErdImage(file); if (ext !== ".pdf") { setErdPreview(URL.createObjectURL(file)); } else { setErdPreview(null); } }; const handleDbFileChange = (e) => { const file = e.target.files[0]; if (!file) return; if (!file.name.endsWith(".db") && !file.name.endsWith(".sqlite")) { addToast("Database file must be a .db or .sqlite file", "error"); return; } setDbFile(file); }; const handleUploadSubmit = async (e) => { e.preventDefault(); if (!dbFile) { setError("Database file (.db) is required."); addToast("Database file (.db) is required.", "error"); return; } if (!sqlFile && !erdImage) { setError("Please provide either a .sql schema file or an ERD diagram image"); addToast("Please provide either a .sql schema file or an ERD diagram image", "error"); return; } setIsUploading(true); setError(null); setSuccess(false); try { console.log("[SchemaUploadModal] Submitting files to server..."); const result = await uploadSchemaDB(sqlFile, erdImage); setSuccess(true); setIsUploading(false); addToast("Relational database uploaded successfully!", "success"); // Auto-dismiss after 2 seconds setTimeout(() => { if (onUploadSuccess) { onUploadSuccess(result); } onClose(); }, 2000); } catch (err) { console.error("[SchemaUploadModal] Upload failed:", err); setError(err.message || "Failed to upload files."); setIsUploading(false); addToast("Upload failed: " + err.message, "error"); } }; return (
Provide a database file (.db) along with a schema DDL (.sql) or an ERD diagram image to start querying.