feat: implement ConfirmDialog component and add table truncation functionality to MainContent
This commit is contained in:
@@ -0,0 +1,116 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
|
DialogActions,
|
||||||
|
Button,
|
||||||
|
Typography,
|
||||||
|
Box,
|
||||||
|
IconButton,
|
||||||
|
Paper
|
||||||
|
} from '@mui/material';
|
||||||
|
import {
|
||||||
|
Warning,
|
||||||
|
Close,
|
||||||
|
CleaningServices
|
||||||
|
} from '@mui/icons-material';
|
||||||
|
|
||||||
|
interface ConfirmDialogProps {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onConfirm: () => void;
|
||||||
|
title: string;
|
||||||
|
message: string;
|
||||||
|
confirmLabel?: string;
|
||||||
|
cancelLabel?: string;
|
||||||
|
loading?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
onConfirm,
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
confirmLabel = 'Confirm',
|
||||||
|
cancelLabel = 'Cancel',
|
||||||
|
loading = false
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
onClose={onClose}
|
||||||
|
PaperProps={{
|
||||||
|
sx: {
|
||||||
|
borderRadius: 4,
|
||||||
|
p: 1,
|
||||||
|
maxWidth: 400,
|
||||||
|
border: 1,
|
||||||
|
borderColor: 'divider',
|
||||||
|
boxShadow: '0 24px 48px rgba(0,0,0,0.2)',
|
||||||
|
bgcolor: 'background.paper',
|
||||||
|
backgroundImage: 'none'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogTitle sx={{ display: 'flex', alignItems: 'center', gap: 1.5, pb: 1 }}>
|
||||||
|
<Box sx={{
|
||||||
|
p: 1,
|
||||||
|
borderRadius: 2,
|
||||||
|
bgcolor: 'error.main',
|
||||||
|
color: 'white',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
boxShadow: '0 4px 12px rgba(211, 47, 47, 0.4)'
|
||||||
|
}}>
|
||||||
|
<Warning fontSize="small" />
|
||||||
|
</Box>
|
||||||
|
<Typography variant="h6" sx={{ fontWeight: 800 }}>{title}</Typography>
|
||||||
|
<Box sx={{ flexGrow: 1 }} />
|
||||||
|
<IconButton size="small" onClick={onClose} disabled={loading}>
|
||||||
|
<Close fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</DialogTitle>
|
||||||
|
|
||||||
|
<DialogContent sx={{ pb: 2 }}>
|
||||||
|
<DialogContentText sx={{ color: 'text.secondary', fontWeight: 500, lineHeight: 1.6 }}>
|
||||||
|
{message}
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
|
||||||
|
<DialogActions sx={{ p: 2, pt: 0 }}>
|
||||||
|
<Button
|
||||||
|
onClick={onClose}
|
||||||
|
color="inherit"
|
||||||
|
disabled={loading}
|
||||||
|
sx={{ borderRadius: 2, textTransform: 'none', fontWeight: 700, px: 3 }}
|
||||||
|
>
|
||||||
|
{cancelLabel}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={onConfirm}
|
||||||
|
variant="contained"
|
||||||
|
color="error"
|
||||||
|
autoFocus
|
||||||
|
disabled={loading}
|
||||||
|
startIcon={<CleaningServices />}
|
||||||
|
sx={{
|
||||||
|
borderRadius: 2,
|
||||||
|
textTransform: 'none',
|
||||||
|
fontWeight: 700,
|
||||||
|
px: 3,
|
||||||
|
boxShadow: '0 8px 16px rgba(211, 47, 47, 0.25)',
|
||||||
|
'&:hover': { boxShadow: '0 12px 20px rgba(211, 47, 47, 0.35)' }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{confirmLabel}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ConfirmDialog;
|
||||||
@@ -32,6 +32,7 @@ import Editor from '@monaco-editor/react';
|
|||||||
import { useAppStore } from '../store/useAppStore';
|
import { useAppStore } from '../store/useAppStore';
|
||||||
import { SchemaService } from '../services/api';
|
import { SchemaService } from '../services/api';
|
||||||
import TransferContent from './TransferContent';
|
import TransferContent from './TransferContent';
|
||||||
|
import ConfirmDialog from './ConfirmDialog';
|
||||||
|
|
||||||
const MainContent: React.FC = () => {
|
const MainContent: React.FC = () => {
|
||||||
const { activeTable, activeDatabase, darkMode, dbTab, setDbTab } = useAppStore();
|
const { activeTable, activeDatabase, darkMode, dbTab, setDbTab } = useAppStore();
|
||||||
@@ -200,6 +201,7 @@ const MainContent: React.FC = () => {
|
|||||||
const [meta, setMeta] = useState<any>(null);
|
const [meta, setMeta] = useState<any>(null);
|
||||||
const [loadingMeta, setLoadingMeta] = useState(true);
|
const [loadingMeta, setLoadingMeta] = useState(true);
|
||||||
const [truncating, setTruncating] = useState(false);
|
const [truncating, setTruncating] = useState(false);
|
||||||
|
const [showConfirm, setShowConfirm] = useState(false);
|
||||||
|
|
||||||
const fetchMeta = useCallback(async () => {
|
const fetchMeta = useCallback(async () => {
|
||||||
setLoadingMeta(true);
|
setLoadingMeta(true);
|
||||||
@@ -220,11 +222,10 @@ const MainContent: React.FC = () => {
|
|||||||
}, [fetchMeta]);
|
}, [fetchMeta]);
|
||||||
|
|
||||||
const handleTruncate = async () => {
|
const handleTruncate = async () => {
|
||||||
if (!table || !window.confirm(`Are you sure you want to truncate table "${table}"? This will delete all data!`)) return;
|
|
||||||
|
|
||||||
setTruncating(true);
|
setTruncating(true);
|
||||||
|
setShowConfirm(false);
|
||||||
try {
|
try {
|
||||||
await SchemaService.truncateTable(table);
|
await SchemaService.truncateTable(table!);
|
||||||
setErrorInfo({
|
setErrorInfo({
|
||||||
open: true,
|
open: true,
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
@@ -271,7 +272,7 @@ const MainContent: React.FC = () => {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="error"
|
color="error"
|
||||||
startIcon={truncating ? <CircularProgress size={16} color="inherit" /> : <CleaningServices />}
|
startIcon={truncating ? <CircularProgress size={16} color="inherit" /> : <CleaningServices />}
|
||||||
onClick={handleTruncate}
|
onClick={() => setShowConfirm(true)}
|
||||||
disabled={truncating}
|
disabled={truncating}
|
||||||
sx={{ borderRadius: 2, textTransform: 'none', fontWeight: 700 }}
|
sx={{ borderRadius: 2, textTransform: 'none', fontWeight: 700 }}
|
||||||
>
|
>
|
||||||
@@ -279,6 +280,16 @@ const MainContent: React.FC = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
open={showConfirm}
|
||||||
|
onClose={() => setShowConfirm(false)}
|
||||||
|
onConfirm={handleTruncate}
|
||||||
|
title="Truncate Table"
|
||||||
|
message={`Are you sure you want to truncate table "${table}"? This action will permanently delete all ${meta?.rows || ''} records. This cannot be undone.`}
|
||||||
|
confirmLabel="Truncate Now"
|
||||||
|
loading={truncating}
|
||||||
|
/>
|
||||||
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 3 }}>
|
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 3 }}>
|
||||||
{stats.map((stat, i) => (
|
{stats.map((stat, i) => (
|
||||||
<Paper key={i} sx={{
|
<Paper key={i} sx={{
|
||||||
|
|||||||
Reference in New Issue
Block a user