diff --git a/frontend/src/components/MainContent.tsx b/frontend/src/components/MainContent.tsx index e474838..6969f2e 100644 --- a/frontend/src/components/MainContent.tsx +++ b/frontend/src/components/MainContent.tsx @@ -1,6 +1,18 @@ import React, { useEffect, useState, useCallback } from 'react'; -import { Box, Paper, Typography, CircularProgress, Button, Divider, IconButton, Tooltip } from '@mui/material'; -import { PlayArrow, History, Save, CleaningServices } from '@mui/icons-material'; +import { + Box, + Paper, + Typography, + CircularProgress, + Button, + Divider, + IconButton, + Tooltip, + Snackbar, + Alert, + AlertTitle +} from '@mui/material'; +import { PlayArrow, History, Save, CleaningServices, Close } from '@mui/icons-material'; import { DataGrid } from '@mui/x-data-grid'; import type { GridColDef, GridPaginationModel } from '@mui/x-data-grid'; import Editor from '@monaco-editor/react'; @@ -21,6 +33,15 @@ const MainContent: React.FC = () => { pageSize: 100, }); + // Custom Alert State + const [errorInfo, setErrorInfo] = useState<{ open: boolean; message: string; title: string }>({ + open: false, + message: '', + title: '' + }); + + const handleCloseError = () => setErrorInfo({ ...errorInfo, open: false }); + // Helper to map SQL types to MUI X Data Grid types const mapSqlTypeToMuiType = (sqlType: string): 'string' | 'number' | 'date' | 'dateTime' | 'boolean' => { sqlType = sqlType.toLowerCase(); @@ -35,7 +56,7 @@ const MainContent: React.FC = () => { useEffect(() => { if (activeTable && activeDatabase) { setSqlQuery(`SELECT * FROM ${activeDatabase}.${activeTable} LIMIT 1000;`); - setIsCustomQuery(false); // Reset to table mode when a new table is selected + setIsCustomQuery(false); } }, [activeTable, activeDatabase]); @@ -111,7 +132,7 @@ const MainContent: React.FC = () => { const handleExecute = async () => { if (!sqlQuery) return; setLoadingData(true); - setIsCustomQuery(true); // Switch to custom query mode + setIsCustomQuery(true); try { const response = await SchemaService.executeQuery(sqlQuery); const rawData = response.data.data; @@ -138,7 +159,12 @@ const MainContent: React.FC = () => { } } catch (error: any) { console.error('Execution error', error); - alert(error.response?.data?.error || 'Execution failed'); + const msg = error.response?.data?.error || 'An unexpected error occurred during SQL execution.'; + setErrorInfo({ + open: true, + title: 'SQL Execution Error', + message: msg + }); } finally { setLoadingData(false); } @@ -156,19 +182,19 @@ const MainContent: React.FC = () => { {/* SQL Editor Section */} - + - SQL EDITOR + SQL EDITOR - + {isCustomQuery ? 'Custom Query' : `${activeDatabase}.${activeTable}`} @@ -188,47 +214,66 @@ const MainContent: React.FC = () => { onClick={handleExecute} disabled={loadingData} startIcon={loadingData ? : } - sx={{ ml: 1, px: 2, borderRadius: 1.5, textTransform: 'none', fontWeight: 700 }} + sx={{ ml: 1, px: 3, borderRadius: 2, textTransform: 'none', fontWeight: 700, boxShadow: '0 4px 12px rgba(0, 97, 255, 0.3)' }} > Execute setSqlQuery(value || '')} options={{ minimap: { enabled: false }, - fontSize: 13, + fontSize: 14, fontFamily: "'Fira Code', 'Cascadia Code', Consolas, monospace", lineNumbers: 'on', scrollBeyondLastLine: false, automaticLayout: true, - padding: { top: 10, bottom: 10 } + padding: { top: 16, bottom: 16 }, + cursorSmoothCaretAnimation: 'on', + smoothScrolling: true }} /> {/* Data Section */} - - - + + + {isCustomQuery ? 'Query Results' : 'Table Results'} - {rowCount} rows found + + {rowCount} rows found + {isCustomQuery && ( - )} - + {(loadingSchema && !isCustomQuery) ? ( @@ -239,7 +284,7 @@ const MainContent: React.FC = () => { columns={columns} rowCount={rowCount} loading={loadingData} - paginationMode={isCustomQuery ? 'client' : 'server'} // Client pagination for SQL results + paginationMode={isCustomQuery ? 'client' : 'server'} paginationModel={paginationModel} onPaginationModelChange={setPaginationModel} pageSizeOptions={[25, 50, 100]} @@ -255,6 +300,10 @@ const MainContent: React.FC = () => { '& .MuiDataGrid-row:hover': { bgcolor: (theme) => theme.palette.mode === 'light' ? 'rgba(0, 97, 255, 0.04)' : 'rgba(0, 97, 255, 0.08)', }, + '& .MuiDataGrid-columnHeaderTitle': { + fontWeight: 700, + opacity: 0.8 + } }} slotProps={{ loadingOverlay: { @@ -266,6 +315,37 @@ const MainContent: React.FC = () => { )} + + {/* Custom Alert (Snackbar) */} + + + + + } + > + {errorInfo.title} + + {errorInfo.message} + + + ); };