import { Button } from '@/components/button/button'; import { CodeSnippet } from '@/components/code-snippet/code-snippet'; import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogInternalContent, DialogTitle, } from '@/components/dialog/dialog'; import { Label } from '@/components/label/label'; import { Spinner } from '@/components/spinner/spinner'; import { useChartDB } from '@/hooks/use-chartdb'; import { useDialog } from '@/hooks/use-dialog'; import { exportBaseSQL, exportSQL, } from '@/lib/data/export-metadata/export-sql-script'; import { databaseTypeToLabelMap } from '@/lib/databases'; import { DatabaseType } from '@/lib/domain/database-type'; import { Annoyed, Sparkles } from 'lucide-react'; import React, { useCallback, useEffect, useRef } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import type { BaseDialogProps } from '../common/base-dialog-props'; import type { Diagram } from '@/lib/domain/diagram'; import { useDiagramFilter } from '@/context/diagram-filter-context/use-diagram-filter'; import { filterDependency, filterRelationship, filterTable, } from '@/lib/domain/diagram-filter/filter'; import { defaultSchemas } from '@/lib/data/default-schemas'; export interface ExportSQLDialogProps extends BaseDialogProps { targetDatabaseType: DatabaseType; } export const ExportSQLDialog: React.FC = ({ dialog, targetDatabaseType, }) => { const { closeExportSQLDialog } = useDialog(); const { currentDiagram } = useChartDB(); const { filter } = useDiagramFilter(); const { t } = useTranslation(); const [script, setScript] = React.useState(); const [error, setError] = React.useState(false); const [isScriptLoading, setIsScriptLoading] = React.useState(false); const abortControllerRef = useRef(null); const exportSQLScript = useCallback(async () => { const filteredDiagram: Diagram = { ...currentDiagram, tables: currentDiagram.tables?.filter((table) => filterTable({ table: { id: table.id, schema: table.schema, }, filter, options: { defaultSchema: defaultSchemas[targetDatabaseType], }, }) ), relationships: currentDiagram.relationships?.filter((rel) => { const sourceTable = currentDiagram.tables?.find( (t) => t.id === rel.sourceTableId ); const targetTable = currentDiagram.tables?.find( (t) => t.id === rel.targetTableId ); return ( sourceTable && targetTable && filterRelationship({ tableA: { id: sourceTable.id, schema: sourceTable.schema, }, tableB: { id: targetTable.id, schema: targetTable.schema, }, filter, options: { defaultSchema: defaultSchemas[targetDatabaseType], }, }) ); }), dependencies: currentDiagram.dependencies?.filter((dep) => { const table = currentDiagram.tables?.find( (t) => t.id === dep.tableId ); const dependentTable = currentDiagram.tables?.find( (t) => t.id === dep.dependentTableId ); return ( table && dependentTable && filterDependency({ tableA: { id: table.id, schema: table.schema, }, tableB: { id: dependentTable.id, schema: dependentTable.schema, }, filter, options: { defaultSchema: defaultSchemas[targetDatabaseType], }, }) ); }), }; if (targetDatabaseType === DatabaseType.GENERIC) { return Promise.resolve( exportBaseSQL({ diagram: filteredDiagram, targetDatabaseType, }) ); } else { return exportSQL(filteredDiagram, targetDatabaseType, { stream: true, onResultStream: (text) => setScript((prev) => (prev ? prev + text : text)), signal: abortControllerRef.current?.signal, }); } }, [targetDatabaseType, currentDiagram, filter]); useEffect(() => { if (!dialog.open) { abortControllerRef.current?.abort(); return; } abortControllerRef.current = new AbortController(); setScript(undefined); setError(false); const fetchScript = async () => { try { setIsScriptLoading(true); const script = await exportSQLScript(); setScript(script); setIsScriptLoading(false); } catch { setError(true); } }; fetchScript(); return () => { abortControllerRef.current?.abort(); }; }, [dialog.open, setScript, exportSQLScript, setError]); const renderError = useCallback( () => (
), [] ); const renderLoader = useCallback( () => (
), [targetDatabaseType, t] ); return ( { if (!open) { closeExportSQLDialog(); } }} > {t('export_sql_dialog.title')} {t('export_sql_dialog.description', { databaseType: targetDatabaseType === DatabaseType.GENERIC ? 'SQL' : databaseTypeToLabelMap[ targetDatabaseType ], })}
{error ? ( renderError() ) : script === undefined ? ( renderLoader() ) : script.length === 0 ? ( renderError() ) : ( )}
); };