feat: implement UI components for PHP extension management, server tuning, and MariaDB database operations

This commit is contained in:
Ümit Tunç
2026-04-03 14:23:22 +03:00
parent 499fdef661
commit 2413c19393
9 changed files with 234 additions and 39 deletions
+30 -10
View File
@@ -476,14 +476,27 @@ function App(): JSX.Element {
if ((status[s]?.status || 'stopped') === 'stopped') setStatus(prev => ({ ...prev, [s]: { status: 'starting' } }))
}
await Promise.all([
...criticalServices.filter(s => status[s]?.status !== 'running').map(s => window.api?.startService(s)),
...phpToStart.filter(s => (status[s]?.status || 'stopped') !== 'running').map(s => window.api?.startService(s)),
...mariaDbToStart.filter(s => (status[s]?.status || 'stopped') !== 'running').map(s => window.api?.startService(s))
const results = await Promise.all([
...criticalServices.filter(s => status[s]?.status !== 'running').map(s => window.api?.startService(s).then((r: any) => ({ service: s, ...r }))),
...phpToStart.filter(s => (status[s]?.status || 'stopped') !== 'running').map(s => window.api?.startService(s).then((r: any) => ({ service: s, ...r }))),
...mariaDbToStart.filter(s => (status[s]?.status || 'stopped') !== 'running').map(s => window.api?.startService(s).then((r: any) => ({ service: s, ...r })))
])
const errors = results.filter(r => r && !r.success)
if (errors.length > 0) {
const errorList = errors.map(e => `<b>${e.service}:</b> ${e.message}`).join('<br/>')
Swal.fire({
title: t('common.error'),
html: `<div style="text-align: left; font-size: 0.9rem;">${errorList}</div>`,
icon: 'error',
background: '#1e1e1e',
color: '#fff'
})
} else {
setNotification({ open: true, message: t('dashboard.all_started'), severity: 'success' })
}
fetchStatus()
setNotification({ open: true, message: t('dashboard.all_started'), severity: 'success' })
}
const handleStopAll = async () => {
@@ -498,12 +511,19 @@ function App(): JSX.Element {
const result = await window.api.invoke('services:stop-all')
if (!result.success) {
Swal.fire({
title: t('common.error'),
text: result.message,
icon: 'error',
background: '#1e1e1e',
color: '#fff'
})
} else {
setNotification({ open: true, message: t('dashboard.all_stopped'), severity: 'success' })
}
fetchStatus()
setNotification({
open: true,
message: result.success ? t('dashboard.all_stopped') : result.message,
severity: result.success ? 'success' : 'error'
})
}
const formatMemory = (bytes?: number) => {
@@ -304,12 +304,12 @@ export default function DashboardDetails({
</Tooltip>
)}
<Button
variant="contained"
variant="outlined"
color={isRunning ? 'error' : 'success'}
disabled={isTransitioning}
startIcon={isTransitioning ? <CircularProgress size={20} color="inherit" /> : isRunning ? <StopIcon /> : <StartIcon />}
onClick={() => onToggleService(serviceId)}
sx={{ borderRadius: 3, px: 4, height: 48, fontWeight: 800, fontSize: '1rem', boxShadow: isRunning ? '0 4px 12px rgba(244, 67, 54, 0.2)' : '0 4px 12px rgba(76, 175, 80, 0.2)' }}
sx={{ borderRadius: 3, px: 4, height: 48, fontWeight: 800, fontSize: '1rem', boxShadow: 'none' }}
>
{isStarting ? t('common.starting') : (isStopping ? t('common.stopping') : (isRunning ? t('common.stop') : t('common.start')))}
</Button>
@@ -378,7 +378,7 @@ export default function DashboardDetails({
{activeTab === 'settings_live' ? 'php.ini (Aktif Konfigürasyon)' : getTemplateName()}
</Typography>
<Button
variant="contained"
variant="outlined"
size="large"
startIcon={isLoadingConfig ? <CircularProgress size={20} color="inherit" /> : <SaveIcon />}
disabled={isLoadingConfig}
@@ -414,7 +414,7 @@ export default function DashboardDetails({
{getProjectTemplateNames()[0]}
</Typography>
<Button
variant="contained"
variant="outlined"
size="large"
startIcon={<SaveIcon />}
onClick={() => saveConfig(getProjectTemplateNames()[0], projectConfigContent)}
@@ -222,7 +222,7 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
<Typography variant="subtitle1" sx={{ fontWeight: 800, color: 'primary.light' }}>
{t('mariadb_manager.databases_title')}
</Typography>
<Button variant="contained" size="small" startIcon={<AddIcon />} onClick={handleCreateDb}>
<Button variant="outlined" size="small" startIcon={<AddIcon />} onClick={handleCreateDb}>
{t('mariadb_manager.create_db_btn')}
</Button>
</Box>
@@ -266,7 +266,7 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
<Typography variant="subtitle1" sx={{ fontWeight: 800, color: 'secondary.light' }}>
{t('mariadb_manager.users_title')}
</Typography>
<Button variant="contained" color="secondary" size="small" startIcon={<AddIcon />} onClick={handleCreateUser}>
<Button variant="outlined" color="secondary" size="small" startIcon={<AddIcon />} onClick={handleCreateUser}>
{t('mariadb_manager.create_user_btn')}
</Button>
</Box>
@@ -210,7 +210,7 @@ const MariaDbExportWizard: React.FC<MariaDbExportWizardProps> = ({ open, onClose
),
}}
/>
<Button variant="contained" onClick={handleSelectSavePath} sx={{ minWidth: '120px' }}>{t('common.select')}</Button>
<Button variant="outlined" onClick={handleSelectSavePath} sx={{ minWidth: '120px' }}>{t('common.select')}</Button>
</Box>
</Box>
)
@@ -293,18 +293,18 @@ const MariaDbExportWizard: React.FC<MariaDbExportWizardProps> = ({ open, onClose
<Button onClick={prevStep} disabled={loading}>{t('common.back')}</Button>
)}
{activeStep === 0 && (
<Button variant="contained" onClick={handleStep1Next} disabled={loading}>
<Button variant="outlined" onClick={handleStep1Next} disabled={loading}>
{loading ? <CircularProgress size={24} /> : t('common.next')}
</Button>
)}
{activeStep === 1 && (
<Button variant="contained" onClick={nextStep} disabled={!selectedDb}>{t('common.next')}</Button>
<Button variant="outlined" onClick={nextStep} disabled={!selectedDb}>{t('common.next')}</Button>
)}
{activeStep === 2 && (
<Button variant="contained" onClick={nextStep} disabled={!savePath}>{t('common.next')}</Button>
<Button variant="outlined" onClick={nextStep} disabled={!savePath}>{t('common.next')}</Button>
)}
{activeStep === 3 && !exportResult && (
<Button variant="contained" color="primary" onClick={startExport} disabled={loading}>
<Button variant="outlined" color="primary" onClick={startExport} disabled={loading}>
{loading ? <CircularProgress size={24} /> : t('mariadb.export.btn_start')}
</Button>
)}
@@ -188,7 +188,7 @@ const MariaDbImportWizard: React.FC<MariaDbImportWizardProps> = ({ open, onClose
),
}}
/>
<Button variant="contained" onClick={handleSelectFile} sx={{ minWidth: '120px' }}>{t('common.select')}</Button>
<Button variant="outlined" onClick={handleSelectFile} sx={{ minWidth: '120px' }}>{t('common.select')}</Button>
</Box>
</Box>
)
@@ -337,18 +337,18 @@ const MariaDbImportWizard: React.FC<MariaDbImportWizardProps> = ({ open, onClose
<Button onClick={prevStep} disabled={loading}>{t('common.back')}</Button>
)}
{activeStep === 0 && (
<Button variant="contained" onClick={nextStep} disabled={!filePath}>{t('common.next')}</Button>
<Button variant="outlined" onClick={nextStep} disabled={!filePath}>{t('common.next')}</Button>
)}
{activeStep === 1 && (
<Button variant="contained" onClick={handleStep2Next}>{t('common.next')}</Button>
<Button variant="outlined" onClick={handleStep2Next}>{t('common.next')}</Button>
)}
{activeStep === 2 && (
<Button variant="contained" onClick={handleStep3Next} disabled={loading}>
<Button variant="outlined" onClick={handleStep3Next} disabled={loading}>
{loading ? <CircularProgress size={24} /> : t('mariadb.import.btn_summary')}
</Button>
)}
{activeStep === 3 && !importResult && (
<Button variant="contained" color="primary" onClick={startImport} disabled={loading}>
<Button variant="outlined" color="primary" onClick={startImport} disabled={loading}>
{loading ? <CircularProgress size={24} /> : t('mariadb.import.btn_start')}
</Button>
)}
@@ -266,7 +266,7 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
<Button onClick={fetchExtensions} startIcon={<RefreshIcon />} sx={{ mr: 'auto' }}>
{t('common.refresh').toUpperCase()}
</Button>
<Button onClick={onClose} variant="contained" color="primary">
<Button onClick={onClose} variant="outlined" color="primary">
{t('common.close').toUpperCase()}
</Button>
</DialogActions>
@@ -331,7 +331,6 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
<PhpIniCodeEditor
value={rawConfig}
onChange={setRawConfig}
searchTerm={rawSearchTerm}
/>
</DialogContent>
<DialogActions sx={{ p: 2, bgcolor: 'rgba(0,0,0,0.2)' }}>
@@ -340,7 +339,7 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
</Button>
<Button
onClick={handleSaveRaw}
variant="contained"
variant="outlined"
color="primary"
startIcon={isSavingRaw ? <CircularProgress size={18} color="inherit" /> : <SaveIcon />}
disabled={isSavingRaw}
@@ -242,7 +242,7 @@ export default function ProjectDetails({
<Box sx={{ display: 'flex', gap: 1.5, flexWrap: 'wrap' }}>
<Button
variant="contained"
variant="outlined"
size="medium"
disabled={isTransitioning}
startIcon={isTransitioning ? <CircularProgress size={18} color="inherit" /> : (isRunning ? <StopIcon /> : <StartIcon />)}
@@ -257,7 +257,7 @@ export default function ProjectDetails({
}
}
}}
sx={{ px: 3, height: 44, borderRadius: 2.5, fontWeight: 800, boxShadow: isRunning ? '0 4px 12px rgba(244, 67, 54, 0.2)' : '0 4px 12px rgba(76, 175, 80, 0.2)' }}
sx={{ px: 3, height: 44, borderRadius: 2.5, fontWeight: 800, boxShadow: 'none' }}
>
{isTransitioning ? t('common.processing') : (isRunning ? t('projects.stop_site').toUpperCase() : t('projects.start_site').toUpperCase())}
</Button>
@@ -284,14 +284,14 @@ export default function ProjectDetails({
{!isHostMapped && (
<Button
variant="contained"
variant="outlined"
size="medium"
color="warning"
onClick={() => {
const finalHost = p.host.includes('.') ? p.host : `${p.host}.local`;
onAddHost(finalHost);
}}
sx={{ px: 3, height: 44, borderRadius: 2.5, fontWeight: 800, boxShadow: '0 4px 12px rgba(255, 152, 0, 0.2)' }}
sx={{ px: 3, height: 44, borderRadius: 2.5, fontWeight: 800, boxShadow: 'none' }}
>
HOSTS DOSYASINA EKLE
</Button>
@@ -407,12 +407,12 @@ export default function ProjectDetails({
<Box sx={{ pt: 1, display: 'flex', justifyContent: 'flex-start' }}>
<Button
variant="contained"
variant="outlined"
size="large"
startIcon={isSaving ? <CircularProgress size={20} color="inherit" /> : <SaveIcon />}
onClick={handleProjectUpdate}
disabled={isSaving}
sx={{ px: 6, py: 1.5, borderRadius: 3, fontWeight: 800, fontSize: '1rem', background: 'linear-gradient(45deg, #2196F3 30%, #21CBF3 90%)', boxShadow: '0 8px 20px rgba(33, 150, 243, 0.3)' }}
sx={{ px: 6, py: 1.5, borderRadius: 3, fontWeight: 800, fontSize: '1rem', color: 'primary.main', border: '1px solid rgba(33, 150, 243, 0.5)', '&:hover': { bgcolor: 'rgba(33, 150, 243, 0.05)', borderColor: 'primary.main' } }}
>
{t('common.save').toUpperCase()}
</Button>
@@ -518,7 +518,7 @@ export default function ProjectDetails({
{t('common.refresh')}
</Button>
<Button
variant="contained"
variant="outlined"
size="small"
color="primary"
startIcon={isConfigSaving ? <CircularProgress size={16} color="inherit" /> : <SaveIcon />}
+3 -3
View File
@@ -287,7 +287,7 @@ export default function ServerTuning() {
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>PHP {v.version}</Typography>
<Typography variant="caption" color="text.secondary">php.ini optimization</Typography>
</Box>
<Button variant="contained" size="small" startIcon={<TuneIcon />}>
<Button variant="outlined" size="small" startIcon={<TuneIcon />}>
{t('tuning.tune_btn')}
</Button>
</CardContent>
@@ -318,7 +318,7 @@ export default function ServerTuning() {
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>MariaDB {v.version}</Typography>
<Typography variant="caption" color="text.secondary">Performance variables</Typography>
</Box>
<Button variant="contained" color="secondary" size="small" startIcon={<TuneIcon />}>
<Button variant="outlined" color="secondary" size="small" startIcon={<TuneIcon />}>
{t('tuning.tune_btn')}
</Button>
</CardContent>
@@ -410,7 +410,7 @@ export default function ServerTuning() {
{t('common.cancel')}
</Button>
<Button
variant="contained"
variant="outlined"
color={selectedVersion?.type === 'php' ? 'primary' : 'secondary'}
onClick={handleSave}
startIcon={saving ? <CircularProgress size={20} color="inherit" /> : <SaveIcon />}