feat: add phpMyAdmin service management and UI integration
This commit is contained in:
@@ -21,9 +21,9 @@ export class PhpMyAdminService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await downloadService.downloadAndExtract(this.downloadUrl, this.pmaDir, (p) => {
|
await downloadService.downloadAndExtract(this.downloadUrl, 'phpmyadmin', (p) => {
|
||||||
if (onProgress) onProgress(p)
|
if (onProgress) onProgress(p)
|
||||||
})
|
}, this.pmaDir)
|
||||||
|
|
||||||
// After extraction, the zip usually contains a folder like phpMyAdmin-x.y.z-all-languages
|
// After extraction, the zip usually contains a folder like phpMyAdmin-x.y.z-all-languages
|
||||||
// We should move contents to the root of this.pmaDir if they are nested
|
// We should move contents to the root of this.pmaDir if they are nested
|
||||||
|
|||||||
+107
-91
@@ -65,7 +65,8 @@ import {
|
|||||||
Folder as FolderIcon,
|
Folder as FolderIcon,
|
||||||
Storage as MySQLIcon,
|
Storage as MySQLIcon,
|
||||||
Language as HostIcon,
|
Language as HostIcon,
|
||||||
Launch as LaunchIcon
|
Launch as LaunchIcon,
|
||||||
|
Handyman as ToolsIcon
|
||||||
} from '@mui/icons-material'
|
} from '@mui/icons-material'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
@@ -497,6 +498,12 @@ function App(): JSX.Element {
|
|||||||
<ListItemText primary="Projeler" />
|
<ListItemText primary="Projeler" />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<ListItem disablePadding>
|
||||||
|
<ListItemButton selected={activeTab === 'tools'} onClick={() => setActiveTab('tools')}>
|
||||||
|
<ListItemIcon><ToolsIcon color={activeTab === 'tools' ? 'primary' : 'inherit'} /></ListItemIcon>
|
||||||
|
<ListItemText primary="Araçlar" />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
<Divider />
|
<Divider />
|
||||||
<List>
|
<List>
|
||||||
@@ -577,97 +584,51 @@ function App(): JSX.Element {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{settingsTab === 1 && (
|
{settingsTab === 1 && (
|
||||||
<>
|
<Paper sx={{ bgcolor: 'rgba(255, 255, 255, 0.03)', borderRadius: 2 }}>
|
||||||
<Paper sx={{ bgcolor: 'rgba(255, 255, 255, 0.03)', borderRadius: 2 }}>
|
<Box sx={{ p: 2, borderBottom: '1px solid rgba(255, 255, 255, 0.05)' }}>
|
||||||
<Box sx={{ p: 2, borderBottom: '1px solid rgba(255, 255, 255, 0.05)' }}>
|
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>MySQL Sürümleri</Typography>
|
||||||
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>MySQL Sürümleri</Typography>
|
<Typography variant="body2" color="text.secondary">Farklı MySQL sürümlerini indirebilir ve sunucunuzda kullanabilirsiniz.</Typography>
|
||||||
<Typography variant="body2" color="text.secondary">Farklı MySQL sürümlerini indirebilir ve sunucunuzda kullanabilirsiniz.</Typography>
|
</Box>
|
||||||
</Box>
|
<List sx={{ maxHeight: 500, overflow: 'auto' }}>
|
||||||
<List sx={{ maxHeight: 500, overflow: 'auto' }}>
|
{mySqlVersions.length === 0 && !loadingVersions && (
|
||||||
{mySqlVersions.length === 0 && !loadingVersions && (
|
<ListItem><ListItemText primary="Yükleniyor veya liste boş..." /></ListItem>
|
||||||
<ListItem><ListItemText primary="Yükleniyor veya liste boş..." /></ListItem>
|
|
||||||
)}
|
|
||||||
{mySqlVersions.map((v) => (
|
|
||||||
<ListItem key={v.id} sx={{ py: 2 }}>
|
|
||||||
<ListItemIcon>
|
|
||||||
{v.status === 'installed' ? <InstalledIcon color="success" /> : <AvailableIcon color="action" />}
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText
|
|
||||||
primary={
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
||||||
{`MySQL ${v.version} (${v.cycle})`}
|
|
||||||
{v.description && (
|
|
||||||
<Chip label={v.description} size="small" variant="outlined" sx={{ fontSize: '0.7rem', height: 20 }} />
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
secondary={v.status === 'downloading' ? `İndiriliyor... %${Math.round(v.progress)}` : v.status === 'installed' ? 'Kurulu' : 'İndirilebilir'}
|
|
||||||
sx={{ flexGrow: 1 }}
|
|
||||||
/>
|
|
||||||
<Box sx={{ minWidth: 120, textAlign: 'right' }}>
|
|
||||||
{v.status === 'available' && (
|
|
||||||
<Button variant="outlined" size="small" startIcon={<DownloadIcon />} onClick={() => handleDownloadMySql(v.id)}>
|
|
||||||
İNDİR
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{v.status === 'downloading' && (
|
|
||||||
<Box sx={{ width: '100%', mt: 1 }}>
|
|
||||||
<LinearProgress variant="determinate" value={v.progress} sx={{ height: 8, borderRadius: 5 }} />
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
{v.status === 'installed' && (
|
|
||||||
<Chip label="HAZIR" color="success" variant="outlined" size="small" />
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</ListItem>
|
|
||||||
))}
|
|
||||||
</List>
|
|
||||||
</Paper>
|
|
||||||
|
|
||||||
<Paper sx={{ mt: 3, p: 2, bgcolor: 'rgba(255, 255, 255, 0.03)', borderRadius: 2 }}>
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
||||||
<Box sx={{ p: 1.5, bgcolor: 'rgba(255, 255, 255, 0.05)', borderRadius: 2 }}>
|
|
||||||
<DbIcon color="primary" />
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ flexGrow: 1 }}>
|
|
||||||
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>phpMyAdmin</Typography>
|
|
||||||
<Typography variant="body2" color="text.secondary">
|
|
||||||
{pmaInstalled ? 'Veritabanı yönetimi için phpMyAdmin hazır.' : 'Veritabanlarını web üzerinden yönetmek için phpMyAdmin kurun.'}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
{!pmaInstalled ? (
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
size="small"
|
|
||||||
onClick={handleSetupPma}
|
|
||||||
disabled={pmaLoading}
|
|
||||||
startIcon={pmaLoading ? <CircularProgress size={20} /> : <DownloadIcon />}
|
|
||||||
>
|
|
||||||
{pmaLoading ? 'KURULUYOR...' : 'KURULUMU BAŞLAT'}
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
size="small"
|
|
||||||
onClick={handleOpenPma}
|
|
||||||
startIcon={<OpenIcon />}
|
|
||||||
>
|
|
||||||
AÇ
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
{pmaLoading && (
|
|
||||||
<Box sx={{ mt: 2 }}>
|
|
||||||
<LinearProgress variant="determinate" value={pmaProgress} sx={{ height: 6, borderRadius: 3 }} />
|
|
||||||
<Typography variant="caption" sx={{ mt: 0.5, display: 'block', textAlign: 'center' }}>
|
|
||||||
İndiriliyor... %{Math.round(pmaProgress)}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
)}
|
)}
|
||||||
</Paper>
|
{mySqlVersions.map((v) => (
|
||||||
</>
|
<ListItem key={v.id} sx={{ py: 2 }}>
|
||||||
|
<ListItemIcon>
|
||||||
|
{v.status === 'installed' ? <InstalledIcon color="success" /> : <AvailableIcon color="action" />}
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText
|
||||||
|
primary={
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
|
{`MySQL ${v.version} (${v.cycle})`}
|
||||||
|
{v.description && (
|
||||||
|
<Chip label={v.description} size="small" variant="outlined" sx={{ fontSize: '0.7rem', height: 20 }} />
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
secondary={v.status === 'downloading' ? `İndiriliyor... %${Math.round(v.progress)}` : v.status === 'installed' ? 'Kurulu' : 'İndirilebilir'}
|
||||||
|
sx={{ flexGrow: 1 }}
|
||||||
|
/>
|
||||||
|
<Box sx={{ minWidth: 120, textAlign: 'right' }}>
|
||||||
|
{v.status === 'available' && (
|
||||||
|
<Button variant="outlined" size="small" startIcon={<DownloadIcon />} onClick={() => handleDownloadMySql(v.id)}>
|
||||||
|
İNDİR
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{v.status === 'downloading' && (
|
||||||
|
<Box sx={{ width: '100%', mt: 1 }}>
|
||||||
|
<LinearProgress variant="determinate" value={v.progress} sx={{ height: 8, borderRadius: 5 }} />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{v.status === 'installed' && (
|
||||||
|
<Chip label="HAZIR" color="success" variant="outlined" size="small" />
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Paper>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{settingsTab === 2 && (
|
{settingsTab === 2 && (
|
||||||
@@ -748,6 +709,7 @@ function App(): JSX.Element {
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'dashboard' && (
|
{activeTab === 'dashboard' && (
|
||||||
<>
|
<>
|
||||||
<Typography variant="h5" gutterBottom sx={{ mb: 3, fontWeight: 'medium' }}>
|
<Typography variant="h5" gutterBottom sx={{ mb: 3, fontWeight: 'medium' }}>
|
||||||
@@ -823,6 +785,59 @@ function App(): JSX.Element {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{activeTab === 'tools' && (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h5" sx={{ mb: 3, fontWeight: 'medium' }}>
|
||||||
|
{t('common.tools')}
|
||||||
|
</Typography>
|
||||||
|
<Paper sx={{ mb: 3, p: 3, bgcolor: 'rgba(255, 255, 255, 0.03)', borderRadius: 2, border: '1px solid rgba(255, 255, 255, 0.05)' }}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 3 }}>
|
||||||
|
<Box sx={{ p: 2, bgcolor: 'rgba(255, 255, 255, 0.05)', borderRadius: 3 }}>
|
||||||
|
<DbIcon color="primary" sx={{ fontSize: 32 }} />
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
|
<Typography variant="h6" sx={{ fontWeight: 'bold' }}>phpMyAdmin</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{pmaInstalled ? 'Veritabanı yönetimi için phpMyAdmin hazır.' : 'Veritabanlarını web üzerinden yönetmek için phpMyAdmin kurun.'}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
{!pmaInstalled ? (
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="large"
|
||||||
|
onClick={handleSetupPma}
|
||||||
|
disabled={pmaLoading}
|
||||||
|
startIcon={pmaLoading ? <CircularProgress size={20} /> : <DownloadIcon />}
|
||||||
|
sx={{ borderRadius: 2 }}
|
||||||
|
>
|
||||||
|
{pmaLoading ? 'KURULUYOR...' : 'KURULUMU BAŞLAT'}
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
size="large"
|
||||||
|
onClick={handleOpenPma}
|
||||||
|
startIcon={<OpenIcon />}
|
||||||
|
sx={{ borderRadius: 2 }}
|
||||||
|
>
|
||||||
|
AÇ
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
{pmaLoading && (
|
||||||
|
<Box sx={{ mt: 3 }}>
|
||||||
|
<LinearProgress variant="determinate" value={pmaProgress} sx={{ height: 8, borderRadius: 4 }} />
|
||||||
|
<Typography variant="caption" sx={{ mt: 1, display: 'block', textAlign: 'center', color: 'primary.main', fontWeight: 'bold' }}>
|
||||||
|
İndiriliyor... %{Math.round(pmaProgress)}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
{activeTab === 'projects' && (
|
{activeTab === 'projects' && (
|
||||||
<Box>
|
<Box>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
|
||||||
@@ -958,6 +973,7 @@ function App(): JSX.Element {
|
|||||||
{notification.message}
|
{notification.message}
|
||||||
</Alert>
|
</Alert>
|
||||||
</Snackbar>
|
</Snackbar>
|
||||||
|
|
||||||
{/* Log Viewer Dialog */}
|
{/* Log Viewer Dialog */}
|
||||||
<Dialog
|
<Dialog
|
||||||
open={logDialogOpen}
|
open={logDialogOpen}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"stop": "Stoppen",
|
"stop": "Stoppen",
|
||||||
"restart": "Neustart",
|
"restart": "Neustart",
|
||||||
"settings": "Einstellungen",
|
"settings": "Einstellungen",
|
||||||
|
"tools": "Werkzeuge",
|
||||||
"close": "Schließen",
|
"close": "Schließen",
|
||||||
"quit": "Beenden"
|
"quit": "Beenden"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"stop": "Stop",
|
"stop": "Stop",
|
||||||
"restart": "Restart",
|
"restart": "Restart",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
"tools": "Tools",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"quit": "Quit"
|
"quit": "Quit"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"stop": "Durdur",
|
"stop": "Durdur",
|
||||||
"restart": "Yeniden Başlat",
|
"restart": "Yeniden Başlat",
|
||||||
"settings": "Ayarlar",
|
"settings": "Ayarlar",
|
||||||
|
"tools": "Araçlar",
|
||||||
"close": "Kapat",
|
"close": "Kapat",
|
||||||
"quit": "Çıkış"
|
"quit": "Çıkış"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user