feat: implement dynamic database connection service with MySQL driver and API schema endpoints

This commit is contained in:
Ümit Tunç
2026-04-24 07:21:59 +03:00
parent 1a75c32469
commit ce67df1067
12 changed files with 417 additions and 78 deletions
+86 -42
View File
@@ -1,59 +1,103 @@
import React from 'react';
import { Box, Paper, Typography } from '@mui/material';
import React, { useEffect, useState } from 'react';
import { Box, Paper, Typography, CircularProgress } from '@mui/material';
import DataGrid, {
Column,
Editing,
Scrolling,
Paging,
FilterRow,
HeaderFilter
HeaderFilter,
SearchPanel,
GroupPanel,
Export
} from 'devextreme-react/data-grid';
import { useAppStore } from '../store/useAppStore';
import { SchemaService } from '../services/api';
const MainContent: React.FC = () => {
const { activeDatabase } = useAppStore();
const { activeTable, activeDatabase } = useAppStore();
const [data, setData] = useState<any[]>([]);
const [columns, setColumns] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
// Mock data for initial UI
const dummyData = [
{ id: 1, name: 'Users', type: 'BASE TABLE', engine: 'InnoDB', rows: 1500, size: '256 KB' },
{ id: 2, name: 'Products', type: 'BASE TABLE', engine: 'InnoDB', rows: 54200, size: '12 MB' },
{ id: 3, name: 'Orders', type: 'BASE TABLE', engine: 'InnoDB', rows: 120400, size: '45 MB' },
{ id: 4, name: 'Order_Items', type: 'BASE TABLE', engine: 'InnoDB', rows: 450000, size: '120 MB' },
];
useEffect(() => {
const fetchTableData = async () => {
if (!activeTable || !activeDatabase) return;
setLoading(true);
try {
// Fetch schema for columns
const schemaRes = await SchemaService.getTableSchema(activeTable);
const cols = schemaRes.data.map((col: any) => ({
dataField: col.Field,
caption: col.Field,
dataType: mapSqlTypeToDxType(col.Type)
}));
setColumns(cols);
// Fetch actual data
const dataRes = await SchemaService.getTableData(activeTable, activeDatabase);
setData(dataRes.data);
} catch (error) {
console.error('Failed to fetch table data', error);
} finally {
setLoading(false);
}
};
fetchTableData();
}, [activeTable, activeDatabase]);
// Helper to map SQL types to DevExtreme types
const mapSqlTypeToDxType = (sqlType: string) => {
sqlType = sqlType.toLowerCase();
if (sqlType.includes('int') || sqlType.includes('decimal') || sqlType.includes('float')) return 'number';
if (sqlType.includes('date') || sqlType.includes('time')) return 'date';
if (sqlType.includes('bool')) return 'boolean';
return 'string';
};
if (!activeTable) {
return (
<Box sx={{ flexGrow: 1, p: 3, display: 'flex', alignItems: 'center', justifyContent: 'center', bgcolor: 'background.default' }}>
<Typography variant="h6" color="text.secondary">Select a table to view data</Typography>
</Box>
);
}
return (
<Box sx={{ flexGrow: 1, p: 3, overflow: 'hidden', display: 'flex', flexDirection: 'column', gap: 2 }}>
<Box>
<Box sx={{ flexGrow: 1, p: 3, bgcolor: 'background.default', overflow: 'hidden' }}>
<Box sx={{ mb: 2, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Typography variant="h5" sx={{ fontWeight: 700 }}>
{activeDatabase ? `Tables in ${activeDatabase}` : 'Welcome to Mariavel'}
</Typography>
<Typography variant="body2" color="text.secondary">
Manage your database tables with high-performance tools.
{activeDatabase}.{activeTable}
</Typography>
</Box>
<Paper sx={{ flexGrow: 1, p: 0, overflow: 'hidden', borderRadius: 3 }}>
<DataGrid
dataSource={dummyData}
keyExpr="id"
showBorders={false}
focusedRowEnabled={true}
height="100%"
width="100%"
>
<Paging enabled={false} />
<Scrolling mode="virtual" />
<FilterRow visible={true} />
<HeaderFilter visible={true} />
<Editing mode="cell" allowUpdating={true} allowDeleting={true} />
<Column dataField="id" width={50} />
<Column dataField="name" caption="Table Name" />
<Column dataField="type" />
<Column dataField="engine" width={100} />
<Column dataField="rows" dataType="number" format="fixedPoint" width={100} />
<Column dataField="size" width={100} />
</DataGrid>
<Paper sx={{ height: 'calc(100vh - 180px)', borderRadius: 2, overflow: 'hidden' }}>
{loading ? (
<Box sx={{ display: 'flex', height: '100%', alignItems: 'center', justifyContent: 'center' }}>
<CircularProgress />
</Box>
) : (
<DataGrid
dataSource={data}
showBorders={true}
focusedRowEnabled={true}
columnAutoWidth={true}
allowColumnReordering={true}
rowAlternationEnabled={true}
height="100%"
>
<Scrolling mode="virtual" />
<FilterRow visible={true} />
<HeaderFilter visible={true} />
<SearchPanel visible={true} width={240} placeholder="Search..." />
<GroupPanel visible={true} />
<Export enabled={true} allowExportSelectedData={true} />
{columns.map(col => (
<Column key={col.dataField} {...col} />
))}
</DataGrid>
)}
</Paper>
</Box>
);