feat: add MainContent component with SQL editor and interactive table data viewer
This commit is contained in:
@@ -15,6 +15,7 @@ const MainContent: React.FC = () => {
|
||||
const [loadingSchema, setLoadingSchema] = useState(false);
|
||||
const [loadingData, setLoadingData] = useState(false);
|
||||
const [sqlQuery, setSqlQuery] = useState('');
|
||||
const [isCustomQuery, setIsCustomQuery] = useState(false);
|
||||
const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({
|
||||
page: 0,
|
||||
pageSize: 100,
|
||||
@@ -34,13 +35,14 @@ 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
|
||||
}
|
||||
}, [activeTable, activeDatabase]);
|
||||
|
||||
// Fetch Schema
|
||||
useEffect(() => {
|
||||
const fetchSchema = async () => {
|
||||
if (!activeTable || !activeDatabase) return;
|
||||
if (!activeTable || !activeDatabase || isCustomQuery) return;
|
||||
|
||||
setLoadingSchema(true);
|
||||
try {
|
||||
@@ -71,11 +73,11 @@ const MainContent: React.FC = () => {
|
||||
};
|
||||
|
||||
fetchSchema();
|
||||
}, [activeTable, activeDatabase]);
|
||||
}, [activeTable, activeDatabase, isCustomQuery]);
|
||||
|
||||
// Fetch Data
|
||||
const fetchData = useCallback(async () => {
|
||||
if (!activeTable || !activeDatabase) return;
|
||||
if (!activeTable || !activeDatabase || isCustomQuery) return;
|
||||
|
||||
setLoadingData(true);
|
||||
try {
|
||||
@@ -100,7 +102,7 @@ const MainContent: React.FC = () => {
|
||||
} finally {
|
||||
setLoadingData(false);
|
||||
}
|
||||
}, [activeTable, activeDatabase, paginationModel]);
|
||||
}, [activeTable, activeDatabase, paginationModel, isCustomQuery]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
@@ -109,12 +111,12 @@ const MainContent: React.FC = () => {
|
||||
const handleExecute = async () => {
|
||||
if (!sqlQuery) return;
|
||||
setLoadingData(true);
|
||||
setIsCustomQuery(true); // Switch to custom query mode
|
||||
try {
|
||||
const response = await SchemaService.executeQuery(sqlQuery);
|
||||
const rawData = response.data.data;
|
||||
|
||||
if (rawData && rawData.length > 0) {
|
||||
// Generate dynamic columns from the result set
|
||||
const fields = Object.keys(rawData[0]);
|
||||
const newCols: GridColDef[] = fields.map(field => ({
|
||||
field,
|
||||
@@ -136,7 +138,6 @@ const MainContent: React.FC = () => {
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('Execution error', error);
|
||||
// In a real app, we'd use a nicer toast or error panel
|
||||
alert(error.response?.data?.error || 'Execution failed');
|
||||
} finally {
|
||||
setLoadingData(false);
|
||||
@@ -155,6 +156,7 @@ const MainContent: React.FC = () => {
|
||||
<Box sx={{ flexGrow: 1, p: 3, bgcolor: 'background.default', display: 'flex', flexDirection: 'column', width: '100%', minWidth: 0, overflow: 'hidden', gap: 2 }}>
|
||||
{/* SQL Editor Section */}
|
||||
<Paper elevation={0} sx={{
|
||||
flexShrink: 0, // Prevent editor from collapsing
|
||||
borderRadius: 2,
|
||||
overflow: 'hidden',
|
||||
border: 1,
|
||||
@@ -166,7 +168,9 @@ const MainContent: React.FC = () => {
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 700, opacity: 0.7 }}>SQL EDITOR</Typography>
|
||||
<Divider orientation="vertical" flexItem sx={{ height: 16, my: 'auto' }} />
|
||||
<Typography variant="caption" sx={{ opacity: 0.5 }}>{activeDatabase}.sql</Typography>
|
||||
<Typography variant="caption" sx={{ opacity: 0.5 }}>
|
||||
{isCustomQuery ? 'Custom Query' : `${activeDatabase}.${activeTable}`}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', gap: 1 }}>
|
||||
<Tooltip title="Clear Editor">
|
||||
@@ -212,13 +216,20 @@ const MainContent: React.FC = () => {
|
||||
<Box sx={{ flexGrow: 1, display: 'flex', flexDirection: 'column', minWidth: 0, overflow: 'hidden' }}>
|
||||
<Box sx={{ mb: 1, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: 700 }}>Results</Typography>
|
||||
<Typography variant="h6" sx={{ fontWeight: 700 }}>
|
||||
{isCustomQuery ? 'Query Results' : 'Table Results'}
|
||||
</Typography>
|
||||
<Typography variant="caption" sx={{ opacity: 0.5, mt: 0.5 }}>{rowCount} rows found</Typography>
|
||||
</Box>
|
||||
{isCustomQuery && (
|
||||
<Button size="small" onClick={() => setIsCustomQuery(false)} sx={{ textTransform: 'none' }}>
|
||||
Back to Table View
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Paper sx={{ flexGrow: 1, borderRadius: 2, overflow: 'hidden', display: 'flex', flexDirection: 'column', width: '100%', border: 1, borderColor: 'divider' }}>
|
||||
{loadingSchema ? (
|
||||
{(loadingSchema && !isCustomQuery) ? (
|
||||
<Box sx={{ display: 'flex', height: '100%', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
@@ -228,7 +239,7 @@ const MainContent: React.FC = () => {
|
||||
columns={columns}
|
||||
rowCount={rowCount}
|
||||
loading={loadingData}
|
||||
paginationMode="server"
|
||||
paginationMode={isCustomQuery ? 'client' : 'server'} // Client pagination for SQL results
|
||||
paginationModel={paginationModel}
|
||||
onPaginationModelChange={setPaginationModel}
|
||||
pageSizeOptions={[25, 50, 100]}
|
||||
|
||||
Reference in New Issue
Block a user