feat: implement core renderer components including service monitoring, project management, and dashboard views
This commit is contained in:
+56
-54
@@ -624,10 +624,10 @@ function App(): JSX.Element {
|
||||
const result = await window.api.invoke('nginx:config:test')
|
||||
const errorInfo = !result.success ? parseNginxError(result.message) : null
|
||||
const formattedMessage = result.message
|
||||
.replace(/\[emerg\]/g, '<span style="color: #ff5252; font-weight: bold;">[emerg]</span>')
|
||||
.replace(/\[warn\]/g, '<span style="color: #ffb142; font-weight: bold;">[warn]</span>')
|
||||
.replace(/failed/g, '<span style="color: #ff5252;">failed</span>')
|
||||
.replace(/successful/g, '<span style="color: #33d9b2;">successful</span>')
|
||||
.replace(/\[emerg\]/g, '<span class="text-error font-bold">[emerg]</span>')
|
||||
.replace(/\[warn\]/g, '<span class="text-warning font-bold">[warn]</span>')
|
||||
.replace(/failed/g, '<span class="text-error">failed</span>')
|
||||
.replace(/successful/g, '<span class="text-success">successful</span>')
|
||||
|
||||
Swal.fire({
|
||||
title: result.success ? 'Başarılı' : 'Yapılandırma Hatası',
|
||||
@@ -636,8 +636,8 @@ function App(): JSX.Element {
|
||||
${formattedMessage}
|
||||
</div>
|
||||
${errorInfo?.host ? `
|
||||
<div style="margin-top: 15px; text-align: center;">
|
||||
<p style="font-size: 0.9rem; color: #ffb142;">
|
||||
<div class="mt-4 text-center">
|
||||
<p class="text-sm text-warning">
|
||||
<b>{t('common.error')}:</b> ${errorInfo.host} (Satır: ${errorInfo.line})
|
||||
</p>
|
||||
</div>
|
||||
@@ -793,9 +793,9 @@ function App(): JSX.Element {
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ borderBottom: '1px solid rgba(255,255,255,0.1)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: 800 }}>{t('mariadb_process_monitor.query_details')}</Typography>
|
||||
<IconButton onClick={() => setSelectedQuery(null)} sx={{ color: 'rgba(255,255,255,0.5)' }}>
|
||||
<DialogTitle sx={{ borderBottom: '1px solid var(--color-border-soft)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography variant="h6" className="font-black">{t('mariadb_process_monitor.query_details')}</Typography>
|
||||
<IconButton onClick={() => setSelectedQuery(null)} className="text-secondary">
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</DialogTitle>
|
||||
@@ -818,7 +818,7 @@ function App(): JSX.Element {
|
||||
</pre>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ borderTop: '1px solid rgba(255,255,255,0.1)', p: 2 }}>
|
||||
<DialogActions sx={{ borderTop: '1px solid var(--color-border-soft)', p: 2 }}>
|
||||
<Button
|
||||
startIcon={<ContentCopyIcon />}
|
||||
onClick={() => {
|
||||
@@ -848,7 +848,7 @@ function App(): JSX.Element {
|
||||
width: { sm: `calc(100% - ${drawerWidth}px)` },
|
||||
ml: { sm: `${drawerWidth}px` },
|
||||
zIndex: (theme) => theme.zIndex.drawer - 1,
|
||||
bgcolor: 'rgba(21, 62, 94, 0.85)',
|
||||
bgcolor: 'var(--color-bg-navbar)',
|
||||
backdropFilter: 'blur(10px)'
|
||||
}}
|
||||
>
|
||||
@@ -904,11 +904,11 @@ function App(): JSX.Element {
|
||||
sx={{
|
||||
color: 'white',
|
||||
height: '28px',
|
||||
fontSize: '0.7rem',
|
||||
fontWeight: 700,
|
||||
'.MuiOutlinedInput-notchedOutline': { borderColor: 'rgba(255,255,255,0.1)' },
|
||||
'&:hover .MuiOutlinedInput-notchedOutline': { borderColor: 'rgba(255,255,255,0.2)' },
|
||||
'.MuiSelect-icon': { color: 'rgba(255,255,255,0.5)', fontSize: '1rem' }
|
||||
fontSize: 'var(--font-size-xs)',
|
||||
fontWeight: 'var(--font-weight-bold)',
|
||||
'.MuiOutlinedInput-notchedOutline': { borderColor: 'var(--color-border-soft)' },
|
||||
'&:hover .MuiOutlinedInput-notchedOutline': { borderColor: 'var(--color-border-medium)' },
|
||||
'.MuiSelect-icon': { color: 'var(--color-text-secondary)', fontSize: '1rem' }
|
||||
}}
|
||||
>
|
||||
{supportedLngs.map(lang => (
|
||||
@@ -940,7 +940,7 @@ function App(): JSX.Element {
|
||||
[`& .MuiDrawer-paper`]: {
|
||||
width: drawerWidth,
|
||||
boxSizing: 'border-box',
|
||||
bgcolor: 'rgba(18, 18, 18, 0.95)',
|
||||
bgcolor: 'var(--color-bg-sidebar)',
|
||||
borderRight: '1px solid var(--color-border-soft)'
|
||||
},
|
||||
}}
|
||||
@@ -1349,12 +1349,12 @@ function App(): JSX.Element {
|
||||
|
||||
<Divider />
|
||||
|
||||
<Box sx={{ p: 2, bgcolor: 'rgba(0,0,0,0.2)', borderRadius: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
<Box sx={{ p: 2, bgcolor: 'var(--color-bg-dark)', borderRadius: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
<Box>
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.4)', textTransform: 'uppercase', fontWeight: 800, mb: 0.5, display: 'block' }}>
|
||||
{cliConfig.enabled ? t('settings.cli_path_found') : t('settings.cli_path_not_found')}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ fontFamily: 'monospace', color: cliConfig.enabled ? '#33d9b2' : 'error.main' }}>
|
||||
<Typography variant="body2" sx={{ fontFamily: 'monospace', color: cliConfig.enabled ? 'var(--color-success)' : 'var(--color-error)' }}>
|
||||
{cliConfig.binDir || '...'}
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -1388,9 +1388,9 @@ function App(): JSX.Element {
|
||||
<Table stickyHeader size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 'bold', color: 'rgba(255,255,255,0.4)', fontSize: '0.7rem', textTransform: 'uppercase' }}>{t('settings.cli_table_command')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 'bold', color: 'rgba(255,255,255,0.4)', fontSize: '0.7rem', textTransform: 'uppercase' }}>{t('settings.cli_table_version')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 'bold', color: 'rgba(255,255,255,0.4)', fontSize: '0.7rem', textTransform: 'uppercase' }}>{t('settings.cli_table_path')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-bold)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)', textTransform: 'uppercase' }}>{t('settings.cli_table_command')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-bold)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)', textTransform: 'uppercase' }}>{t('settings.cli_table_version')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-bold)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)', textTransform: 'uppercase' }}>{t('settings.cli_table_path')}</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
@@ -1476,16 +1476,16 @@ function App(): JSX.Element {
|
||||
<Table stickyHeader size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem' }}>ID</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem' }}>USER</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem' }}>HOST</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem' }}>DB</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem' }}>COMMAND</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem' }}>TIME</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem' }}>STATE</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem' }}>INFO</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem' }}>PROGRESS</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#1a1d21', fontWeight: 800, color: 'rgba(255,255,255,0.4)', fontSize: '0.75rem', textAlign: 'right' }}>ACTION</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)' }}>ID</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)' }}>USER</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)' }}>HOST</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)' }}>DB</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)' }}>COMMAND</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)' }}>TIME</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)' }}>STATE</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)' }}>INFO</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)' }}>PROGRESS</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', fontWeight: 'var(--font-weight-black)', color: 'var(--color-text-tertiary)', fontSize: 'var(--font-size-xs)', textAlign: 'right' }}>ACTION</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
@@ -1498,11 +1498,11 @@ function App(): JSX.Element {
|
||||
) : (
|
||||
processList.map((proc) => (
|
||||
<TableRow key={proc.Id} hover sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
|
||||
<TableCell sx={{ borderColor: 'rgba(255,255,255,0.05)', color: 'rgba(255,255,255,0.7)', fontFamily: 'monospace' }}>{proc.Id}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'rgba(255,255,255,0.05)', color: '#39A7FF' }}>{proc.User}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'var(--color-border-soft)', color: 'var(--color-text-secondary)', fontFamily: 'monospace' }}>{proc.Id}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'var(--color-border-soft)', color: 'var(--color-primary)' }}>{proc.User}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'rgba(255,255,255,0.05)', color: 'rgba(255,255,255,0.7)' }}>{proc.Host}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'rgba(255,255,255,0.05)', color: proc.db ? '#ff9f43' : 'rgba(255,255,255,0.3)' }}>{proc.db || 'system'}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'rgba(255,255,255,0.05)', color: '#33d9b2' }}>{proc.Command}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'var(--color-border-soft)', color: proc.db ? 'var(--color-warning)' : 'var(--color-text-tertiary)' }}>{proc.db || 'system'}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'var(--color-border-soft)', color: 'var(--color-success)' }}>{proc.Command}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'rgba(255,255,255,0.05)', color: 'rgba(255,255,255,0.7)' }}>{proc.Time}s</TableCell>
|
||||
<TableCell sx={{ borderColor: 'rgba(255,255,255,0.05)', color: proc.State === 'Query' ? '#39A7FF' : 'rgba(255,255,255,0.5)' }}>{proc.State || '-'}</TableCell>
|
||||
<TableCell sx={{ borderColor: 'rgba(255,255,255,0.05)', color: 'rgba(255,255,255,0.7)', maxWidth: 300, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
@@ -1721,9 +1721,9 @@ function App(): JSX.Element {
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: '#1e1e1e',
|
||||
color: '#d4d4d4',
|
||||
borderRadius: 2,
|
||||
bgcolor: 'var(--color-bg-dark)',
|
||||
color: 'var(--color-text-primary)',
|
||||
borderRadius: 'var(--radius-lg)',
|
||||
boxShadow: '0 8px 32px rgba(0,0,0,0.5)'
|
||||
}
|
||||
}}
|
||||
@@ -1737,7 +1737,7 @@ function App(): JSX.Element {
|
||||
}}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<TerminalIcon color="primary" />
|
||||
<Typography variant="h6" sx={{ fontWeight: 600, color: '#fff' }}>
|
||||
<Typography variant="h6" className="font-bold text-white">
|
||||
{selectedService?.toUpperCase()} - {t('diagnostics.logs', 'Servis Logları')}
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -1745,14 +1745,14 @@ function App(): JSX.Element {
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</DialogTitle>
|
||||
<DialogContent sx={{ p: 0, bgcolor: '#000' }}>
|
||||
<DialogContent sx={{ p: 0, bgcolor: 'black' }}>
|
||||
<Box
|
||||
sx={{
|
||||
height: '400px',
|
||||
overflowY: 'auto',
|
||||
p: 2,
|
||||
fontFamily: '"Fira Code", "Consolas", monospace',
|
||||
fontSize: '0.875rem',
|
||||
fontSize: 'var(--font-size-sm)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '2px'
|
||||
@@ -1810,7 +1810,8 @@ function App(): JSX.Element {
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(logs.join('\n'))
|
||||
}}
|
||||
sx={{ color: '#888', '&:hover': { color: '#fff' } }}
|
||||
className="text-tertiary"
|
||||
sx={{ '&:hover': { color: 'white' } }}
|
||||
>
|
||||
{t('common.copy', 'Kopyala')}
|
||||
</Button>
|
||||
@@ -1954,16 +1955,16 @@ function App(): JSX.Element {
|
||||
<Table stickyHeader size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem' }}>{t('mariadb_process_monitor.columns.id')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem' }}>{t('mariadb_process_monitor.columns.user')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem' }}>{t('mariadb_process_monitor.columns.host')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem' }}>{t('mariadb_process_monitor.columns.db')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem' }}>{t('mariadb_process_monitor.columns.command')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem' }}>{t('mariadb_process_monitor.columns.time')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem' }}>{t('mariadb_process_monitor.columns.state')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem' }}>{t('mariadb_process_monitor.columns.info')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem' }}>{t('mariadb_process_monitor.columns.progress')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: '#24292e', color: 'rgba(255,255,255,0.5)', fontWeight: 'bold', fontSize: '0.75rem', textAlign: 'right' }}>{t('common.actions')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)' }}>{t('mariadb_process_monitor.columns.id')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)' }}>{t('mariadb_process_monitor.columns.user')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)' }}>{t('mariadb_process_monitor.columns.host')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)' }}>{t('mariadb_process_monitor.columns.db')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)' }}>{t('mariadb_process_monitor.columns.command')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)' }}>{t('mariadb_process_monitor.columns.time')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)' }}>{t('mariadb_process_monitor.columns.state')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)' }}>{t('mariadb_process_monitor.columns.info')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)' }}>{t('mariadb_process_monitor.columns.progress')}</TableCell>
|
||||
<TableCell sx={{ bgcolor: 'var(--color-bg-medium)', color: 'var(--color-text-tertiary)', fontWeight: 'var(--font-weight-bold)', fontSize: 'var(--font-size-xs)', textAlign: 'right' }}>{t('common.actions')}</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
@@ -2040,7 +2041,8 @@ function App(): JSX.Element {
|
||||
onClick={handleTestNginxConfig}
|
||||
variant="outlined"
|
||||
startIcon={<RefreshIcon />}
|
||||
sx={{ color: '#fff', borderColor: 'rgba(255,255,255,0.3)' }}
|
||||
className="text-white"
|
||||
sx={{ borderColor: 'var(--color-border-medium)' }}
|
||||
>
|
||||
{t('server.nginx.test_config')}
|
||||
</Button>
|
||||
|
||||
@@ -39,7 +39,6 @@ import 'prismjs/themes/prism-tomorrow.css'
|
||||
import 'prismjs/components/prism-nginx'
|
||||
import 'prismjs/components/prism-apacheconf'
|
||||
import 'prismjs/components/prism-ini'
|
||||
import Editor from 'react-simple-code-editor'
|
||||
import SearchableCodeEditor from '../SearchableCodeEditor'
|
||||
import Prism from 'prismjs'
|
||||
import Swal from 'sweetalert2'
|
||||
@@ -144,8 +143,8 @@ export default function DashboardDetails({
|
||||
position: 'top-end',
|
||||
showConfirmButton: false,
|
||||
timer: 3000,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
background: 'var(--color-bg-dark)',
|
||||
color: 'var(--color-text-primary)'
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -161,8 +160,8 @@ export default function DashboardDetails({
|
||||
position: 'top-end',
|
||||
showConfirmButton: false,
|
||||
timer: 3000,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
background: 'var(--color-bg-dark)',
|
||||
color: 'var(--color-text-primary)'
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -215,7 +214,7 @@ export default function DashboardDetails({
|
||||
if (!serviceId) {
|
||||
return (
|
||||
<Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%', opacity: 0.5 }}>
|
||||
<Typography variant="h6">{t('dashboard.select_service', 'Lütfen bir servis seçin')}</Typography>
|
||||
<Typography variant="h6" className="font-semibold">{t('dashboard.select_service', 'Lütfen bir servis seçin')}</Typography>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -255,19 +254,19 @@ export default function DashboardDetails({
|
||||
<Box sx={{ mt: 2 }}>
|
||||
<Box sx={{ mb: 1.5 }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', mb: 0.5 }}>
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.4)', fontWeight: 600, letterSpacing: 0.5 }}>İşlemci Kullanımı</Typography>
|
||||
<Typography variant="caption" sx={{ color: 'primary.main', fontWeight: 800 }}>{cpu || 0}%</Typography>
|
||||
<Typography variant="caption" className="text-secondary font-semibold" sx={{ letterSpacing: 0.5 }}>İşlemci Kullanımı</Typography>
|
||||
<Typography variant="caption" color="primary.main" className="font-black">{cpu || 0}%</Typography>
|
||||
</Box>
|
||||
<LinearProgress variant="determinate" value={cpu || 0} sx={{ height: 6, borderRadius: 3, bgcolor: 'rgba(255,255,255,0.05)', '.MuiLinearProgress-bar': { borderRadius: 3, background: 'linear-gradient(90deg, #2196F3, #21CBF3)' } }} />
|
||||
<LinearProgress variant="determinate" value={cpu || 0} sx={{ height: 6, borderRadius: 'var(--border-radius-full)', bgcolor: 'rgba(255,255,255,0.05)', '.MuiLinearProgress-bar': { borderRadius: 'var(--border-radius-full)', background: 'linear-gradient(90deg, var(--color-primary), var(--color-secondary))' } }} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', mb: 0.5 }}>
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.4)', fontWeight: 600, letterSpacing: 0.5 }}>Bellek Kullanımı</Typography>
|
||||
<Typography variant="caption" sx={{ color: 'secondary.main', fontWeight: 800 }}>
|
||||
<Typography variant="caption" className="text-secondary font-semibold" sx={{ letterSpacing: 0.5 }}>Bellek Kullanımı</Typography>
|
||||
<Typography variant="caption" color="secondary.main" className="font-black">
|
||||
{memory ? `${Math.round(memory / (1024 * 1024))} MB` : '0 MB'}
|
||||
</Typography>
|
||||
</Box>
|
||||
<LinearProgress variant="determinate" value={Math.min(((memory || 0) / (1024 * 1024) / 1024) * 100, 100)} sx={{ height: 6, borderRadius: 3, bgcolor: 'rgba(255,255,255,0.05)', '.MuiLinearProgress-bar': { borderRadius: 3, background: 'linear-gradient(90deg, #9C27B0, #E91E63)' } }} />
|
||||
<LinearProgress variant="determinate" value={Math.min(((memory || 0) / (1024 * 1024) / 1024) * 100, 100)} sx={{ height: 6, borderRadius: 'var(--border-radius-full)', bgcolor: 'rgba(255,255,255,0.05)', '.MuiLinearProgress-bar': { borderRadius: 'var(--border-radius-full)', background: 'linear-gradient(90deg, var(--color-secondary), #E91E63)' } }} />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
@@ -277,29 +276,29 @@ export default function DashboardDetails({
|
||||
return (
|
||||
<Box sx={{ flexGrow: 1, display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden', bgcolor: 'background.default' }}>
|
||||
<Box sx={{ p: 4, borderBottom: '1px solid rgba(255,255,255,0.05)', display: 'flex', alignItems: 'center', gap: 3 }}>
|
||||
<Paper sx={{ p: 2, bgcolor: 'rgba(255, 255, 255, 0.03)', borderRadius: 4, border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
{serviceType === 'nginx' && <WebIcon color="primary" sx={{ fontSize: 40 }} />}
|
||||
{serviceType === 'apache' && <ServerIcon color="primary" sx={{ fontSize: 40 }} />}
|
||||
{serviceType === 'php' && <PhpIcon color="primary" sx={{ fontSize: 40 }} />}
|
||||
{serviceType === 'mariadb' && <DbIcon color="primary" sx={{ fontSize: 40 }} />}
|
||||
<Paper sx={{ p: 2, bgcolor: 'var(--color-bg-sidebar)', borderColor: 'var(--color-border-soft)' }} className="rounded-xl">
|
||||
{serviceType === 'nginx' && <WebIcon color="primary" sx={{ fontSize: 'var(--font-size-4xl)' }} />}
|
||||
{serviceType === 'apache' && <ServerIcon color="primary" sx={{ fontSize: 'var(--font-size-4xl)' }} />}
|
||||
{serviceType === 'php' && <PhpIcon color="primary" sx={{ fontSize: 'var(--font-size-4xl)' }} />}
|
||||
{serviceType === 'mariadb' && <DbIcon color="primary" sx={{ fontSize: 'var(--font-size-4xl)' }} />}
|
||||
</Paper>
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: 800, letterSpacing: '-0.5px', color: 'primary.main', fontSize: '1.25rem' }}>
|
||||
<Typography variant="h6" className="font-black text-xl" sx={{ letterSpacing: '-0.5px', color: 'primary.main' }}>
|
||||
{serviceId.replace(':', ' ').replace('php', 'PHP').replace('mariadb', 'MariaDB').replace('nginx', 'Nginx').replace('apache', 'Apache')}
|
||||
</Typography>
|
||||
<Typography variant="caption" sx={{ display: 'flex', alignItems: 'center', gap: 1, mt: 0.2 }}>
|
||||
<Box sx={{ width: 6, height: 6, borderRadius: '50%', bgcolor: isRunning ? 'success.main' : 'error.main', boxShadow: isRunning ? '0 0 10px rgba(76, 175, 80, 0.5)' : 'none' }} />
|
||||
{isStarting && <Box component="span" sx={{ color: 'warning.light', fontWeight: 700, letterSpacing: 0.5, fontSize: '0.7rem' }}>{t('common.starting')}</Box>}
|
||||
{isStopping && <Box component="span" sx={{ color: 'warning.light', fontWeight: 700, letterSpacing: 0.5, fontSize: '0.7rem' }}>{t('common.stopping')}</Box>}
|
||||
{isRunning && <Box component="span" sx={{ color: 'success.main', fontWeight: 700, letterSpacing: 0.5, fontSize: '0.7rem' }}>{t('common.running')}</Box>}
|
||||
{!isRunning && !isStarting && !isStopping && <Box component="span" sx={{ opacity: 0.5, fontWeight: 700, letterSpacing: 0.5, fontSize: '0.7rem' }}>{t('common.stopped')}</Box>}
|
||||
{isStarting && <Box component="span" sx={{ color: 'warning.light', letterSpacing: 0.5 }} className="font-bold text-xs">{t('common.starting')}</Box>}
|
||||
{isStopping && <Box component="span" sx={{ color: 'warning.light', letterSpacing: 0.5 }} className="font-bold text-xs">{t('common.stopping')}</Box>}
|
||||
{isRunning && <Box component="span" sx={{ color: 'success.main', letterSpacing: 0.5 }} className="font-bold text-xs">{t('common.running')}</Box>}
|
||||
{!isRunning && !isStarting && !isStopping && <Box component="span" sx={{ letterSpacing: 0.5 }} className="text-secondary font-bold text-xs">{t('common.stopped')}</Box>}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack direction="row" spacing={1.5}>
|
||||
{isRunning && !isTransitioning && (
|
||||
<Tooltip title={t('common.reload')}>
|
||||
<IconButton onClick={() => onReloadService(serviceId)} sx={{ bgcolor: 'rgba(57, 167, 255, 0.05)', color: 'primary.main', border: '1px solid rgba(57, 167, 255, 0.1)', width: 32, height: 32, borderRadius: 2 }}>
|
||||
<RefreshIcon sx={{ fontSize: '1.1rem' }} />
|
||||
<IconButton onClick={() => onReloadService(serviceId)} sx={{ bgcolor: 'rgba(57, 167, 255, 0.05)', color: 'primary.main', border: '1px solid rgba(57, 167, 255, 0.1)', width: 32, height: 32 }} className="rounded-md">
|
||||
<RefreshIcon sx={{ fontSize: 'var(--font-size-lg)' }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
@@ -308,9 +307,10 @@ export default function DashboardDetails({
|
||||
color={isRunning ? 'error' : 'success'}
|
||||
disabled={isTransitioning}
|
||||
size="small"
|
||||
startIcon={isTransitioning ? <CircularProgress size={14} color="inherit" /> : isRunning ? <StopIcon sx={{ fontSize: '1.1rem' }} /> : <StartIcon sx={{ fontSize: '1.1rem' }} />}
|
||||
startIcon={isTransitioning ? <CircularProgress size={14} color="inherit" /> : isRunning ? <StopIcon sx={{ fontSize: 'var(--font-size-lg)' }} /> : <StartIcon sx={{ fontSize: 'var(--font-size-lg)' }} />}
|
||||
onClick={() => onToggleService(serviceId)}
|
||||
sx={{ borderRadius: 2, px: 2, height: 32, fontWeight: 800, fontSize: '0.75rem', boxShadow: 'none' }}
|
||||
sx={{ px: 2, height: 32, boxShadow: 'none' }}
|
||||
className="rounded-md font-black text-sm"
|
||||
>
|
||||
{isStarting ? t('common.starting') : (isStopping ? t('common.stopping') : (isRunning ? t('common.stop') : t('common.start')))}
|
||||
</Button>
|
||||
@@ -319,8 +319,8 @@ export default function DashboardDetails({
|
||||
|
||||
<Box sx={{ borderBottom: 1, borderColor: 'rgba(255,255,255,0.05)', px: 4, bgcolor: 'rgba(255,255,255,0.01)' }}>
|
||||
<Tabs value={activeTab} onChange={(_e, v) => setActiveTab(v)} textColor="primary" indicatorColor="primary" sx={{
|
||||
'.MuiTab-root': { textTransform: 'none', minHeight: 48, fontWeight: 700, fontSize: '0.8rem' }
|
||||
}}>
|
||||
'.MuiTab-root': { textTransform: 'none', minHeight: 48 }
|
||||
}} className="font-bold text-sm">
|
||||
<Tab label={t('dashboard.overview')} value="overview" />
|
||||
<Tab label={isPhp ? 'php.ini (Şablon)' : t('dashboard.service_settings')} value="settings_template" />
|
||||
{isPhp && <Tab label="php.ini" value="settings_live" />}
|
||||
@@ -336,8 +336,8 @@ export default function DashboardDetails({
|
||||
{activeTab === 'overview' && (
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="body2" sx={{ fontWeight: 800, mb: 1.5, color: 'primary.main', display: 'flex', alignItems: 'center', gap: 1, fontSize: '0.8rem' }}>
|
||||
<StatusIcon sx={{ fontSize: '1rem' }} /> {t('dashboard.system_stats', 'Sistem İstatistikleri')}
|
||||
<Typography variant="body2" className="font-black text-sm" sx={{ mb: 1.5, color: 'primary.main', display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<StatusIcon sx={{ fontSize: 'var(--font-size-base)' }} /> {t('dashboard.system_stats', 'Sistem İstatistikleri')}
|
||||
</Typography>
|
||||
<Paper sx={{ p: 2, bgcolor: 'rgba(255,255,255,0.02)', borderRadius: 3, border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
<ResourceMonitor cpu={currentStatus.cpu} memory={currentStatus.memory} />
|
||||
@@ -347,22 +347,23 @@ export default function DashboardDetails({
|
||||
<Typography variant="body2" sx={{ fontWeight: 800, mb: 1.5, color: 'primary.main', display: 'flex', alignItems: 'center', gap: 1, fontSize: '0.8rem' }}>
|
||||
<SettingsIcon sx={{ fontSize: '1rem' }} /> {t('dashboard.service_info', 'Servis Bilgileri')}
|
||||
</Typography>
|
||||
<Paper sx={{ p: 2, bgcolor: 'rgba(255,255,255,0.02)', borderRadius: 3, border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
<Paper sx={{ p: 2, bgcolor: 'var(--color-bg-sidebar)', borderColor: 'var(--color-border-soft)' }} className="rounded-lg">
|
||||
<Stack spacing={1.5}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography variant="caption" sx={{ opacity: 0.5, fontWeight: 700, fontSize: '0.75rem' }}>{t('common.port', 'Port')}</Typography>
|
||||
<Typography variant="body2" sx={{ fontWeight: 800, color: 'primary.main', fontFamily: 'monospace', fontSize: '0.75rem' }}>
|
||||
<Typography variant="caption" className="font-bold text-xs" sx={{ opacity: 0.5 }}>{t('common.port', 'Port')}</Typography>
|
||||
<Typography variant="body2" className="font-black text-xs" sx={{ color: 'primary.main', fontFamily: 'monospace' }}>
|
||||
{getPort()}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ opacity: 0.05 }} />
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography variant="caption" sx={{ opacity: 0.5, fontWeight: 700, fontSize: '0.75rem' }}>{t('common.status', 'Durum')}</Typography>
|
||||
<Typography variant="caption" className="font-bold text-xs" sx={{ opacity: 0.5 }}>{t('common.status', 'Durum')}</Typography>
|
||||
<Chip
|
||||
label={isRunning ? t('common.running', 'Çalışıyor') : t('common.stopped', 'Durduruldu')}
|
||||
size="small"
|
||||
color={isRunning ? 'success' : 'error'}
|
||||
sx={{ fontWeight: 900, borderRadius: 1.5, height: 20, fontSize: '0.65rem' }}
|
||||
sx={{ borderRadius: 'var(--border-radius-sm)', height: 20 }}
|
||||
className="font-black text-xs"
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
@@ -380,10 +381,11 @@ export default function DashboardDetails({
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
startIcon={isLoadingConfig ? <CircularProgress size={16} color="inherit" /> : <SaveIcon sx={{ fontSize: '1rem' }} />}
|
||||
startIcon={isLoadingConfig ? <CircularProgress size={16} color="inherit" /> : <SaveIcon sx={{ fontSize: 'var(--font-size-base)' }} />}
|
||||
disabled={isLoadingConfig}
|
||||
onClick={() => activeTab === 'settings_live' ? saveLiveConfig(serviceId!, liveConfigContent) : saveConfig(getTemplateName(), configContent)}
|
||||
sx={{ borderRadius: 2, px: 2, fontWeight: 800, fontSize: '0.75rem' }}
|
||||
sx={{ px: 2 }}
|
||||
className="rounded-md font-black text-sm"
|
||||
>
|
||||
{t('common.save').toUpperCase()}
|
||||
</Button>
|
||||
@@ -476,8 +478,8 @@ export default function DashboardDetails({
|
||||
<List disablePadding>
|
||||
{serviceProjects.length === 0 ? (
|
||||
<Box sx={{ p: 8, textAlign: 'center', opacity: 0.2 }}>
|
||||
<ProjectIcon sx={{ fontSize: 64, mb: 2 }} />
|
||||
<Typography variant="h6">{t('projects.empty')}</Typography>
|
||||
<ProjectIcon sx={{ fontSize: 'var(--font-size-7xl)', mb: 2 }} />
|
||||
<Typography variant="h6" className="text-xl">{t('projects.empty')}</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
serviceProjects.map((p_item, idx) => (
|
||||
|
||||
@@ -49,20 +49,20 @@ export default function DashboardSidebar({
|
||||
selected={selectedServiceId === id}
|
||||
onClick={() => setSelectedServiceId(id)}
|
||||
sx={{
|
||||
borderRadius: 2,
|
||||
mb: 0.5,
|
||||
border: selectedServiceId === id ? '1px solid rgba(57, 167, 255, 0.3)' : '1px solid transparent',
|
||||
'&.Mui-selected': { bgcolor: 'rgba(57, 167, 255, 0.08)' }
|
||||
}}
|
||||
className="rounded-md"
|
||||
>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', width: '100%', gap: 1.5 }}>
|
||||
<Icon sx={{ color: selectedServiceId === id ? 'primary.main' : 'rgba(255,255,255,0.4)', fontSize: '1.2rem' }} />
|
||||
<Icon sx={{ color: selectedServiceId === id ? 'primary.main' : 'var(--color-text-secondary)', fontSize: 'var(--font-size-lg)' }} />
|
||||
<Box sx={{ flexGrow: 1, minWidth: 0 }}>
|
||||
<Typography variant="body2" noWrap sx={{ fontWeight: 600, fontSize: '0.85rem' }}>
|
||||
<Typography variant="body2" noWrap className="font-semibold text-sm">
|
||||
{label}
|
||||
</Typography>
|
||||
{isRunning && status[serviceKey] && (
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.4)', display: 'block', fontSize: '0.6rem', mt: -0.5 }}>
|
||||
<Typography variant="caption" className="text-secondary text-xs" sx={{ display: 'block', mt: -0.5 }}>
|
||||
Port: {status[serviceKey].port || '?'} | CPU: {Math.round(status[serviceKey].cpu || 0)}% | RAM: {Math.round((status[serviceKey].memory || 0) / (1024 * 1024))}MB
|
||||
</Typography>
|
||||
)}
|
||||
@@ -94,21 +94,21 @@ export default function DashboardSidebar({
|
||||
return (
|
||||
<Box sx={{
|
||||
width: 320,
|
||||
borderRight: '1px solid rgba(255, 255, 255, 0.05)',
|
||||
borderRight: '1px solid var(--color-border-soft)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
bgcolor: 'rgba(255, 255, 255, 0.01)',
|
||||
bgcolor: 'var(--color-bg-sidebar)',
|
||||
height: '100%',
|
||||
overflowY: 'auto'
|
||||
}}>
|
||||
<Box sx={{ p: 2, borderBottom: '1px solid rgba(255, 255, 255, 0.05)' }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: 700, fontSize: '1rem' }}>
|
||||
<Box sx={{ p: 2, borderBottom: '1px solid var(--color-border-soft)' }}>
|
||||
<Typography variant="h6" className="font-bold text-md">
|
||||
{t('dashboard.services', 'Servisler')}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ p: 1.5 }}>
|
||||
<Typography variant="caption" sx={{ px: 1, color: 'primary.main', fontWeight: 600, mb: 1, display: 'block', opacity: 0.8 }}>
|
||||
<Typography variant="caption" className="font-semibold" sx={{ px: 1, color: 'primary.main', mb: 1, display: 'block', opacity: 0.8 }}>
|
||||
Web Sunucuları
|
||||
</Typography>
|
||||
<List dense disablePadding sx={{ mb: 3 }}>
|
||||
|
||||
@@ -255,7 +255,7 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
|
||||
{/* Users Section */}
|
||||
<Box>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1.5 }}>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 800, color: 'secondary.light', fontSize: '0.8rem' }}>
|
||||
<Typography variant="subtitle2" className="font-black text-sm" sx={{ color: 'secondary.light' }}>
|
||||
{t('mariadb_manager.users_title')}
|
||||
</Typography>
|
||||
<Button variant="outlined" color="secondary" size="small" startIcon={<AddIcon sx={{ fontSize: 'var(--font-size-base)' }} />} onClick={handleCreateUser} sx={{ height: 28 }} className="text-xs rounded-md">
|
||||
|
||||
@@ -199,9 +199,9 @@ export default function ProjectDetails({
|
||||
|
||||
if (!p) {
|
||||
return (
|
||||
<Box sx={{ flexGrow: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', opacity: 0.3 }}>
|
||||
<ProjectIcon sx={{ fontSize: 80, mb: 2 }} />
|
||||
<Typography variant="h6" className="font-semibold">{t('projects.no_project_selected')}</Typography>
|
||||
<Box sx={{ flexGrow: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', opacity: 0.2 }}>
|
||||
<ProjectIcon sx={{ fontSize: 80, mb: 2, color: 'var(--color-primary)' }} />
|
||||
<Typography variant="h6" className="font-bold text-tertiary">{t('projects.no_project_selected')}</Typography>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -215,10 +215,10 @@ export default function ProjectDetails({
|
||||
const installedMariaDb = mariaDbVersions.filter(v => v.status === 'installed');
|
||||
|
||||
return (
|
||||
<Box sx={{ flexGrow: 1, display: 'flex', flexDirection: 'column', bgcolor: 'rgba(255,255,255,0.01)', height: '100%', overflow: 'hidden', position: 'relative' }}>
|
||||
<Box sx={{ flexGrow: 1, display: 'flex', flexDirection: 'column', bgcolor: 'var(--color-bg-dark)', height: '100%', overflow: 'hidden', position: 'relative' }}>
|
||||
{/* Header */}
|
||||
<Box sx={{ p: 4, borderBottom: '1px solid rgba(255,255,255,0.05)', display: 'flex', alignItems: 'flex-start', gap: 3, position: 'relative' }}>
|
||||
<Avatar sx={{ bgcolor: 'rgba(57, 167, 255, 0.1)', color: 'primary.main', width: 64, height: 64, border: '1px solid var(--color-border-soft)' }} className="rounded-lg">
|
||||
<Box sx={{ p: 4, borderBottom: '1px solid var(--color-border-soft)', display: 'flex', alignItems: 'flex-start', gap: 3, position: 'relative' }}>
|
||||
<Avatar sx={{ bgcolor: 'var(--color-primary-soft)', color: 'var(--color-primary)', width: 64, height: 64, border: '1px solid var(--color-border-soft)' }} className="rounded-lg">
|
||||
<ProjectIcon sx={{ fontSize: 32 }} />
|
||||
</Avatar>
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
@@ -229,7 +229,7 @@ export default function ProjectDetails({
|
||||
{p.path}
|
||||
</Typography>
|
||||
<Tooltip title={t('projects.open_folder')}>
|
||||
<IconButton size="small" onClick={onOpenFolder} sx={{ color: 'rgba(255,255,255,0.2)', p: 0.5, '&:hover': { color: 'primary.main', bgcolor: 'rgba(57, 167, 255, 0.1)' } }}>
|
||||
<IconButton size="small" onClick={onOpenFolder} sx={{ color: 'var(--color-text-tertiary)', p: 0.5, '&:hover': { color: 'var(--color-primary)', bgcolor: 'var(--color-primary-soft)' } }}>
|
||||
<FolderOpenIcon sx={{ fontSize: '1rem' }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
@@ -253,7 +253,8 @@ export default function ProjectDetails({
|
||||
}
|
||||
}
|
||||
}}
|
||||
sx={{ px: 2, height: 32, borderRadius: 1.5, fontWeight: 700, fontSize: '0.75rem', boxShadow: 'none' }}
|
||||
sx={{ px: 2, height: 32, boxShadow: 'none' }}
|
||||
className="rounded-md font-bold text-sm"
|
||||
>
|
||||
{isTransitioning ? t('common.processing') : (isRunning ? t('projects.stop_site').toUpperCase() : t('projects.start_site').toUpperCase())}
|
||||
</Button>
|
||||
@@ -261,7 +262,7 @@ export default function ProjectDetails({
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
startIcon={<LaunchIcon sx={{ fontSize: '1rem !important' }} />}
|
||||
startIcon={<LaunchIcon sx={{ fontSize: 'var(--font-size-base) !important' }} />}
|
||||
onClick={() => onOpenSite(isHostMapped)}
|
||||
sx={{ px: 2, height: 32, borderColor: 'var(--color-border-medium)', '&:hover': { borderColor: 'primary.main', bgcolor: 'rgba(57, 167, 255, 0.05)' } }}
|
||||
className="rounded-md font-semibold text-sm"
|
||||
@@ -274,7 +275,8 @@ export default function ProjectDetails({
|
||||
size="small"
|
||||
startIcon={<CodeIcon sx={{ fontSize: '1rem !important' }} />}
|
||||
onClick={onOpenVSCode}
|
||||
sx={{ px: 2, height: 32, borderRadius: 1.5, borderColor: 'rgba(255,255,255,0.1)', color: 'rgba(255,255,255,0.6)', fontWeight: 600, fontSize: '0.75rem', '&:hover': { borderColor: '#007ACC', color: '#007ACC', bgcolor: 'rgba(0, 122, 204, 0.05)' } }}
|
||||
sx={{ px: 2, height: 32, borderColor: 'var(--color-border-medium)', color: 'var(--color-text-secondary)', '&:hover': { borderColor: '#007ACC', color: '#007ACC', bgcolor: 'rgba(0, 122, 204, 0.05)' } }}
|
||||
className="rounded-md font-semibold text-sm"
|
||||
>
|
||||
VS CODE AÇ
|
||||
</Button>
|
||||
@@ -288,7 +290,8 @@ export default function ProjectDetails({
|
||||
const finalHost = p.host.includes('.') ? p.host : `${p.host}.local`;
|
||||
onAddHost(finalHost);
|
||||
}}
|
||||
sx={{ px: 2, height: 32, borderRadius: 1.5, fontWeight: 700, fontSize: '0.75rem', boxShadow: 'none' }}
|
||||
sx={{ px: 2, height: 32, boxShadow: 'none' }}
|
||||
className="rounded-md font-bold text-sm"
|
||||
>
|
||||
HOSTS DOSYASINA EKLE
|
||||
</Button>
|
||||
@@ -304,11 +307,11 @@ export default function ProjectDetails({
|
||||
sx={{
|
||||
width: 40,
|
||||
height: 40,
|
||||
bgcolor: 'rgba(255, 68, 68, 0.05)',
|
||||
color: 'error.main',
|
||||
border: '1px solid rgba(255, 68, 68, 0.1)',
|
||||
borderRadius: 1.5,
|
||||
'&:hover': { bgcolor: 'error.main', color: '#fff', transform: 'scale(1.05) rotate(5deg)', boxShadow: '0 4px 12px rgba(255, 68, 68, 0.3)' },
|
||||
bgcolor: 'var(--color-error-soft)',
|
||||
color: 'var(--color-error)',
|
||||
border: '1px solid var(--color-error-soft)',
|
||||
borderRadius: 'var(--radius-md)',
|
||||
'&:hover': { bgcolor: 'var(--color-error)', color: '#fff', transform: 'scale(1.05) rotate(5deg)', boxShadow: '0 4px 12px rgba(255, 68, 68, 0.3)' },
|
||||
transition: 'all 0.2s'
|
||||
}}
|
||||
>
|
||||
@@ -319,7 +322,7 @@ export default function ProjectDetails({
|
||||
</Box>
|
||||
|
||||
{/* Tabs */}
|
||||
<Box sx={{ borderBottom: 1, borderColor: 'rgba(255,255,255,0.05)', px: 4, bgcolor: 'rgba(255,255,255,0.01)' }}>
|
||||
<Box sx={{ borderBottom: 1, borderColor: 'var(--color-border-soft)', px: 4, bgcolor: 'var(--color-bg-dark)' }}>
|
||||
<Tabs value={projectDetailTab} onChange={(_e, v) => setProjectDetailTab(v)} textColor="primary" indicatorColor="primary">
|
||||
<Tab label={t('projects.overview').toUpperCase()} className="font-bold text-md" sx={{ py: 2.5, minWidth: 120 }} />
|
||||
<Tab label={t('projects.database').toUpperCase()} className="font-bold text-md" sx={{ py: 2.5, minWidth: 120 }} />
|
||||
@@ -334,8 +337,8 @@ export default function ProjectDetails({
|
||||
<Grid container spacing={4}>
|
||||
{/* Editable Form Side */}
|
||||
<Grid item xs={12} md={7}>
|
||||
<Paper sx={{ p: 3, borderRadius: 4, bgcolor: 'rgba(255,255,255,0.02)', border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
<Typography variant="h6" sx={{ mb: 3, fontWeight: 800, color: 'primary.main', display: 'flex', alignItems: 'center', gap: 1.5, fontSize: '1rem' }}>
|
||||
<Paper sx={{ p: 3, borderRadius: 4, bgcolor: 'var(--color-bg-soft)', border: '1px solid var(--color-border-soft)' }}>
|
||||
<Typography variant="h6" className="font-black text-md" sx={{ mb: 3, color: 'var(--color-primary)', display: 'flex', alignItems: 'center', gap: 1.5 }}>
|
||||
<SettingsIcon sx={{ fontSize: '1.25rem' }} /> {t('projects.edit_details', 'Proje Detaylarını Düzenle')}
|
||||
</Typography>
|
||||
|
||||
@@ -347,7 +350,8 @@ export default function ProjectDetails({
|
||||
size="small"
|
||||
value={editForm.name}
|
||||
onChange={(e) => setEditForm({ ...editForm, name: e.target.value })}
|
||||
sx={{ borderRadius: 2, '& .MuiFilledInput-root': { bgcolor: 'rgba(0,0,0,0.2)' }, '& .MuiInputLabel-root': { fontSize: '0.85rem' }, '& .MuiInputBase-input': { fontSize: '0.85rem' } }}
|
||||
sx={{ borderRadius: 2, '& .MuiFilledInput-root': { bgcolor: 'rgba(0,0,0,0.2)' } }}
|
||||
className="text-sm"
|
||||
/>
|
||||
|
||||
<TextField
|
||||
@@ -358,7 +362,9 @@ export default function ProjectDetails({
|
||||
value={editForm.host}
|
||||
onChange={(e) => setEditForm({ ...editForm, host: e.target.value })}
|
||||
helperText={t('projects.host_helper', 'Domain adı (örn: myproject)')}
|
||||
sx={{ borderRadius: 2, '& .MuiFilledInput-root': { bgcolor: 'rgba(0,0,0,0.2)' }, '& .MuiInputLabel-root': { fontSize: '0.85rem' }, '& .MuiInputBase-input': { fontSize: '0.85rem' }, '& .MuiFormHelperText-root': { fontSize: '0.7rem' } }}
|
||||
sx={{ borderRadius: 2, '& .MuiFilledInput-root': { bgcolor: 'rgba(0,0,0,0.2)' } }}
|
||||
className="text-sm"
|
||||
FormHelperTextProps={{ className: 'text-xs' }}
|
||||
/>
|
||||
|
||||
<Grid container spacing={2}>
|
||||
@@ -411,7 +417,8 @@ export default function ProjectDetails({
|
||||
startIcon={isSaving ? <CircularProgress size={16} color="inherit" /> : <SaveIcon sx={{ fontSize: '1rem !important' }} />}
|
||||
onClick={handleProjectUpdate}
|
||||
disabled={isSaving}
|
||||
sx={{ px: 4, py: 1, borderRadius: 2, fontWeight: 700, fontSize: '0.75rem', color: 'primary.main', border: '1px solid rgba(33, 150, 243, 0.5)', '&:hover': { bgcolor: 'rgba(33, 150, 243, 0.05)', borderColor: 'primary.main' } }}
|
||||
sx={{ px: 4, py: 1, color: 'primary.main', border: '1px solid rgba(33, 150, 243, 0.5)', '&:hover': { bgcolor: 'rgba(33, 150, 243, 0.05)', borderColor: 'primary.main' } }}
|
||||
className="rounded-lg font-bold text-sm"
|
||||
>
|
||||
{t('common.save').toUpperCase()}
|
||||
</Button>
|
||||
@@ -422,9 +429,9 @@ export default function ProjectDetails({
|
||||
|
||||
{/* Status Monitor Side */}
|
||||
<Grid item xs={12} md={5}>
|
||||
<Paper sx={{ p: 3, borderRadius: 4, bgcolor: 'rgba(255,255,255,0.02)', border: '1px solid rgba(255,255,255,0.05)', height: '100%' }}>
|
||||
<Typography variant="subtitle1" sx={{ mb: 4, fontWeight: 800, display: 'flex', alignItems: 'center', gap: 1.5, color: 'rgba(255,255,255,0.6)', fontSize: '0.9rem' }}>
|
||||
<StatusIcon sx={{ color: 'secondary.main', fontSize: '1.25rem' }} /> {t('dashboard.status')}
|
||||
<Paper sx={{ p: 3, borderRadius: 4, bgcolor: 'var(--color-bg-soft)', border: '1px solid var(--color-border-soft)', height: '100%' }}>
|
||||
<Typography variant="subtitle1" className="font-black text-sm" sx={{ mb: 4, display: 'flex', alignItems: 'center', gap: 1.5, color: 'var(--color-text-tertiary)' }}>
|
||||
<StatusIcon sx={{ color: 'var(--color-secondary)', fontSize: '1.25rem' }} /> {t('dashboard.status')}
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ mb: 4 }}>
|
||||
@@ -457,20 +464,21 @@ export default function ProjectDetails({
|
||||
<Paper sx={{ p: 4, borderRadius: 4, bgcolor: 'rgba(255,255,255,0.02)', border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 4 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<Avatar sx={{ bgcolor: 'rgba(57, 167, 255, 0.1)', color: 'secondary.main', width: 48, height: 48 }}>
|
||||
<Avatar sx={{ bgcolor: 'var(--color-primary-soft)', color: 'var(--color-secondary)', width: 48, height: 48 }}>
|
||||
<DbIcon />
|
||||
</Avatar>
|
||||
<Box>
|
||||
<Typography variant="overline" sx={{ color: 'rgba(255,255,255,0.3)', fontWeight: 800, letterSpacing: 1, fontSize: '0.65rem' }}>{t('projects.mariadb_version')}</Typography>
|
||||
<Typography variant="h6" sx={{ fontWeight: 700, fontSize: '1rem' }}>MariaDB {p.mariaDbVersion}</Typography>
|
||||
<Typography variant="overline" className="font-black text-2xs" sx={{ color: 'var(--color-text-tertiary)', letterSpacing: 1 }}>{t('projects.mariadb_version')}</Typography>
|
||||
<Typography variant="h6" className="font-bold text-base">MariaDB {p.mariaDbVersion}</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
startIcon={<OpenIcon sx={{ fontSize: '1rem !important' }} />}
|
||||
startIcon={<OpenIcon sx={{ fontSize: 'var(--font-size-base) !important' }} />}
|
||||
onClick={onManageDb}
|
||||
sx={{ borderRadius: 1.5, px: 2, height: 32, fontWeight: 700, fontSize: '0.75rem' }}
|
||||
sx={{ px: 2, height: 32 }}
|
||||
className="rounded-md font-bold text-sm"
|
||||
>
|
||||
{t('mariadb_manager.title').toUpperCase()}
|
||||
</Button>
|
||||
@@ -486,8 +494,8 @@ export default function ProjectDetails({
|
||||
{ label: 'Password', value: '(no password)', italic: true }
|
||||
].map((item, idx) => (
|
||||
<Grid item xs={6} key={idx}>
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.3)', fontWeight: 700, display: 'block', mb: 0.5, fontSize: '0.65rem' }}>{item.label.toUpperCase()}</Typography>
|
||||
<Typography variant="body1" sx={{ fontWeight: 600, color: item.italic ? 'rgba(255,255,255,0.3)' : '#fff', fontStyle: item.italic ? 'italic' : 'normal', fontSize: '0.85rem' }}>
|
||||
<Typography variant="caption" className="font-bold text-2xs" sx={{ color: 'var(--color-text-tertiary)', display: 'block', mb: 0.5 }}>{item.label.toUpperCase()}</Typography>
|
||||
<Typography variant="body1" className="font-semibold text-sm" sx={{ color: item.italic ? 'var(--color-text-tertiary)' : 'var(--color-text-primary)', fontStyle: item.italic ? 'italic' : 'normal' }}>
|
||||
{item.value}
|
||||
</Typography>
|
||||
</Grid>
|
||||
@@ -500,19 +508,20 @@ export default function ProjectDetails({
|
||||
|
||||
{projectDetailTab === 2 && (
|
||||
<Box sx={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
|
||||
<Box sx={{ p: 2, bgcolor: 'rgba(255,255,255,0.02)', borderBottom: '1px solid rgba(255,255,255,0.05)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Box sx={{ p: 2, bgcolor: 'var(--color-bg-soft)', borderBottom: '1px solid var(--color-border-soft)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<ServerIcon color="primary" sx={{ fontSize: '1.25rem' }} />
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 800, textTransform: 'uppercase', letterSpacing: 1, fontSize: '0.75rem' }}>
|
||||
<Typography variant="subtitle2" className="font-black text-xs" sx={{ textTransform: 'uppercase', letterSpacing: 1 }}>
|
||||
{p.serverType} {t('projects.server_settings')}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', gap: 1.5 }}>
|
||||
<Button
|
||||
size="small"
|
||||
startIcon={<TuningIcon sx={{ fontSize: '1rem !important' }} />}
|
||||
startIcon={<TuningIcon sx={{ fontSize: 'var(--font-size-base) !important' }} />}
|
||||
onClick={loadConfig}
|
||||
sx={{ color: 'rgba(255,255,255,0.5)', borderRadius: 1.5, fontSize: '0.75rem' }}
|
||||
sx={{ color: 'var(--color-text-secondary)' }}
|
||||
className="rounded-md text-sm"
|
||||
>
|
||||
{t('common.refresh')}
|
||||
</Button>
|
||||
@@ -520,10 +529,11 @@ export default function ProjectDetails({
|
||||
variant="outlined"
|
||||
size="small"
|
||||
color="primary"
|
||||
startIcon={isConfigSaving ? <CircularProgress size={14} color="inherit" /> : <SaveIcon sx={{ fontSize: '1rem !important' }} />}
|
||||
startIcon={isConfigSaving ? <CircularProgress size={14} color="inherit" /> : <SaveIcon sx={{ fontSize: 'var(--font-size-base) !important' }} />}
|
||||
disabled={isConfigSaving || isConfigLoading}
|
||||
onClick={handleSaveConfig}
|
||||
sx={{ px: 3, height: 32, borderRadius: 1.5, fontWeight: 800, fontSize: '0.75rem' }}
|
||||
sx={{ px: 3, height: 32 }}
|
||||
className="rounded-md font-black text-sm"
|
||||
>
|
||||
{t('common.save').toUpperCase()}
|
||||
</Button>
|
||||
|
||||
@@ -34,27 +34,23 @@ export default function ProjectResourceMonitor({ serverStats, phpStats, serverTy
|
||||
const ramPercent = Math.min((ramMB / 1024) * 100, 100);
|
||||
|
||||
const getColor = (val: number) => {
|
||||
if (val < 30) return '#33d9b2';
|
||||
if (val < 70) return '#ffb142';
|
||||
return '#ff5252';
|
||||
if (val < 30) return 'var(--color-success)';
|
||||
if (val < 70) return 'var(--color-warning)';
|
||||
return 'var(--color-error)';
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{
|
||||
flex: 1,
|
||||
p: 2,
|
||||
borderRadius: 3,
|
||||
bgcolor: 'rgba(255,255,255,0.02)',
|
||||
border: '1px solid rgba(255,255,255,0.05)',
|
||||
bgcolor: 'var(--color-bg-soft)',
|
||||
border: '1px solid var(--color-border-soft)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: 2
|
||||
}}>
|
||||
<Typography variant="caption" sx={{
|
||||
color: 'rgba(255,255,255,0.6)',
|
||||
fontSize: '0.7rem',
|
||||
fontWeight: 800,
|
||||
}} className="rounded-lg">
|
||||
<Typography variant="caption" className="text-secondary font-black text-xs" sx={{
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.1em'
|
||||
}}>
|
||||
@@ -72,14 +68,14 @@ export default function ProjectResourceMonitor({ serverStats, phpStats, serverTy
|
||||
innerRadius="75%"
|
||||
outerRadius="100%"
|
||||
sx={() => ({
|
||||
[`& .${gaugeClasses.valueText}`]: { fontSize: 14, fontWeight: 800, fill: getColor(cpu) },
|
||||
[`& .${gaugeClasses.valueText}`]: { fontSize: 'var(--font-size-sm)', fontWeight: 'var(--font-weight-black)', fill: getColor(cpu) },
|
||||
[`& .${gaugeClasses.valueArc}`]: { fill: getColor(cpu) },
|
||||
[`& .${gaugeClasses.referenceArc}`]: { fill: 'rgba(255,255,255,0.05)' },
|
||||
[`& .${gaugeClasses.referenceArc}`]: { fill: 'var(--color-bg-medium)' },
|
||||
})}
|
||||
text={({ value }) => `${value}%`}
|
||||
/>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.3)', fontSize: '0.6rem', mt: -1 }}>CPU</Typography>
|
||||
<Typography variant="caption" className="text-secondary font-bold text-xs" sx={{ mt: -1 }}>CPU</Typography>
|
||||
</Box>
|
||||
|
||||
{/* RAM Gauge */}
|
||||
@@ -92,14 +88,14 @@ export default function ProjectResourceMonitor({ serverStats, phpStats, serverTy
|
||||
innerRadius="75%"
|
||||
outerRadius="100%"
|
||||
sx={() => ({
|
||||
[`& .${gaugeClasses.valueText}`]: { fontSize: 12, fontWeight: 800, fill: 'secondary.light' },
|
||||
[`& .${gaugeClasses.valueArc}`]: { fill: 'secondary.main' },
|
||||
[`& .${gaugeClasses.referenceArc}`]: { fill: 'rgba(255,255,255,0.05)' },
|
||||
[`& .${gaugeClasses.valueText}`]: { fontSize: 'var(--font-size-xs)', fontWeight: 'var(--font-weight-black)', fill: 'var(--color-secondary)' },
|
||||
[`& .${gaugeClasses.valueArc}`]: { fill: 'var(--color-secondary)' },
|
||||
[`& .${gaugeClasses.referenceArc}`]: { fill: 'var(--color-bg-medium)' },
|
||||
})}
|
||||
text={() => formatMemory(memory)}
|
||||
/>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.3)', fontSize: '0.6rem', mt: -1 }}>RAM</Typography>
|
||||
<Typography variant="caption" className="text-secondary font-bold text-xs" sx={{ mt: -1 }}>RAM</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@@ -53,15 +53,15 @@ export default function ProjectSidebar({
|
||||
return (
|
||||
<Box sx={{
|
||||
width: 320,
|
||||
borderRight: '1px solid rgba(255, 255, 255, 0.05)',
|
||||
borderRight: '1px solid var(--color-border-soft)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
bgcolor: 'rgba(255, 255, 255, 0.01)',
|
||||
bgcolor: 'var(--color-bg-sidebar)',
|
||||
height: '100%'
|
||||
}}>
|
||||
<Box sx={{ p: 2, borderBottom: '1px solid rgba(255, 255, 255, 0.05)' }}>
|
||||
<Box sx={{ display: 'flex', gap: 1, mb: 2, alignItems: 'center' }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: 700, flexGrow: 1, fontSize: '1.1rem' }}>
|
||||
<Typography variant="h6" className="font-bold text-lg" sx={{ flexGrow: 1 }}>
|
||||
{t('projects.title')}
|
||||
</Typography>
|
||||
<Tooltip title={t('projects.add_new')}>
|
||||
@@ -79,10 +79,11 @@ export default function ProjectSidebar({
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<SearchIcon sx={{ color: 'rgba(255, 255, 255, 0.2)', fontSize: '1.1rem' }} />
|
||||
<SearchIcon sx={{ color: 'var(--color-text-secondary)', fontSize: 'var(--font-size-lg)' }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
sx: { fontSize: '0.85rem', bgcolor: 'rgba(0,0,0,0.2)' }
|
||||
className: 'text-sm',
|
||||
sx: { bgcolor: 'rgba(0,0,0,0.2)' }
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@@ -95,7 +96,7 @@ export default function ProjectSidebar({
|
||||
) : (
|
||||
Object.entries(grouped).sort().map(([version, projs]: [string, any]) => (
|
||||
<Box key={version} sx={{ mb: 2 }}>
|
||||
<Typography variant="overline" sx={{ px: 1.5, color: 'primary.main', fontWeight: 800, letterSpacing: 1 }}>
|
||||
<Typography variant="overline" className="font-black" sx={{ px: 1.5, color: 'primary.main', letterSpacing: 1 }}>
|
||||
{version}
|
||||
</Typography>
|
||||
<List dense disablePadding>
|
||||
@@ -113,11 +114,11 @@ export default function ProjectSidebar({
|
||||
selected={selectedProjectId === p.id}
|
||||
onClick={() => setSelectedProjectId(p.id)}
|
||||
sx={{
|
||||
borderRadius: 2,
|
||||
mb: 0.5,
|
||||
border: selectedProjectId === p.id ? '1px solid rgba(57, 167, 255, 0.3)' : '1px solid transparent',
|
||||
'&.Mui-selected': { bgcolor: 'rgba(57, 167, 255, 0.08)' }
|
||||
}}
|
||||
className="rounded-md"
|
||||
>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', width: '100%', gap: 0.5 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
@@ -128,16 +129,16 @@ export default function ProjectSidebar({
|
||||
bgcolor: isRunning ? 'success.main' : 'error.main',
|
||||
boxShadow: isRunning ? '0 0 8px rgba(76, 175, 80, 0.5)' : 'none'
|
||||
}} />
|
||||
<Typography variant="body2" noWrap sx={{ fontWeight: 600, flexGrow: 1 }}>
|
||||
<Typography variant="body2" noWrap className="font-semibold" sx={{ flexGrow: 1 }}>
|
||||
{p.name}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.4)', fontSize: '0.7rem' }}>
|
||||
<Typography variant="caption" className="text-secondary text-xs">
|
||||
{(p.serverType || '').toUpperCase()} • {p.host}
|
||||
</Typography>
|
||||
{isRunning && (
|
||||
<Typography variant="caption" sx={{ color: 'primary.light', fontSize: '0.65rem', fontWeight: 700 }}>
|
||||
<Typography variant="caption" className="text-sm font-bold" sx={{ color: 'primary.light' }}>
|
||||
{Math.round((serverStats?.cpu || 0) + (phpStats?.cpu || 0))}% CPU
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
@@ -4,8 +4,7 @@ import {
|
||||
IconButton,
|
||||
Typography,
|
||||
Paper,
|
||||
Stack,
|
||||
Tooltip
|
||||
Stack
|
||||
} from '@mui/material'
|
||||
import {
|
||||
Close as CloseIcon,
|
||||
@@ -32,8 +31,7 @@ export default function SearchableCodeEditor({
|
||||
highlight,
|
||||
padding = 20,
|
||||
style,
|
||||
textareaClassName = "editor-textarea",
|
||||
languageLabel
|
||||
textareaClassName = "editor-textarea"
|
||||
}: SearchableCodeEditorProps) {
|
||||
const [isSearchOpen, setIsSearchOpen] = useState(false);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
@@ -139,14 +137,14 @@ export default function SearchableCodeEditor({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
bgcolor: '#2d2d2d',
|
||||
border: '1px solid rgba(255,255,255,0.1)',
|
||||
borderRadius: 2,
|
||||
bgcolor: 'var(--color-bg-dark)',
|
||||
border: '1px solid var(--color-border-medium)',
|
||||
minWidth: 300,
|
||||
boxShadow: '0 8px 32px rgba(0,0,0,0.5)'
|
||||
}}
|
||||
className="rounded-lg"
|
||||
>
|
||||
<SearchIcon sx={{ ml: 1, opacity: 0.5, fontSize: 18 }} />
|
||||
<SearchIcon sx={{ ml: 1, opacity: 0.5, fontSize: 'var(--font-size-lg)' }} />
|
||||
<TextField
|
||||
size="small"
|
||||
placeholder="Bul..."
|
||||
@@ -160,8 +158,7 @@ export default function SearchableCodeEditor({
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
'& .MuiInputBase-root': {
|
||||
fontSize: '0.85rem',
|
||||
color: '#fff'
|
||||
color: 'var(--color-text-primary)'
|
||||
},
|
||||
'& .MuiOutlinedInput-notchedOutline': {
|
||||
border: 'none'
|
||||
@@ -170,7 +167,7 @@ export default function SearchableCodeEditor({
|
||||
/>
|
||||
|
||||
{searchResults.length > 0 && (
|
||||
<Typography variant="caption" sx={{ opacity: 0.5, minWidth: 40, fontWeight: 700 }}>
|
||||
<Typography variant="caption" className="text-secondary font-bold" sx={{ minWidth: 40 }}>
|
||||
{searchIndex + 1} / {searchResults.length}
|
||||
</Typography>
|
||||
)}
|
||||
@@ -197,7 +194,7 @@ export default function SearchableCodeEditor({
|
||||
padding={padding}
|
||||
style={{
|
||||
fontFamily: '"Fira Code", monospace',
|
||||
fontSize: '15px',
|
||||
fontSize: '14px',
|
||||
minHeight: '100%',
|
||||
...style
|
||||
}}
|
||||
|
||||
@@ -258,7 +258,7 @@ export default function ServerTuning() {
|
||||
return (
|
||||
<Box>
|
||||
<Box sx={{ mb: 4 }}>
|
||||
<Typography variant="h4" sx={{ mb: 1, color: 'primary.light' }} className="font-black">
|
||||
<Typography variant="h4" color="primary.light" className="font-black text-3xl" sx={{ mb: 1 }}>
|
||||
{t('tuning.title')}
|
||||
</Typography>
|
||||
<Typography variant="body1" className="text-secondary">
|
||||
@@ -272,7 +272,7 @@ export default function ServerTuning() {
|
||||
<Paper sx={{ p: 3, height: '100%', bgcolor: 'var(--color-bg-soft)', border: '1px solid var(--color-border-soft)' }} className="rounded-xl">
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', mb: 3, gap: 2 }}>
|
||||
<Box sx={{ p: 1.5, borderRadius: 2, bgcolor: 'primary.main', display: 'flex' }}>
|
||||
<PhpIcon sx={{ color: 'white' }} />
|
||||
<PhpIcon className="text-white" />
|
||||
</Box>
|
||||
<Typography variant="h6" className="font-bold">PHP Tuning</Typography>
|
||||
<Chip label={phpVersions.length} size="small" variant="outlined" />
|
||||
@@ -285,7 +285,7 @@ export default function ServerTuning() {
|
||||
<CardContent sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Box>
|
||||
<Typography variant="subtitle1" className="font-bold">PHP {v.version}</Typography>
|
||||
<Typography variant="caption" color="text.secondary">php.ini optimization</Typography>
|
||||
<Typography variant="caption" className="text-secondary">php.ini optimization</Typography>
|
||||
</Box>
|
||||
<Button variant="outlined" size="small" startIcon={<TuneIcon />}>
|
||||
{t('tuning.tune_btn')}
|
||||
@@ -303,7 +303,7 @@ export default function ServerTuning() {
|
||||
<Paper sx={{ p: 3, height: '100%', bgcolor: 'var(--color-bg-soft)', border: '1px solid var(--color-border-soft)' }} className="rounded-xl">
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', mb: 3, gap: 2 }}>
|
||||
<Box sx={{ p: 1.5, borderRadius: 2, bgcolor: 'secondary.main', display: 'flex' }}>
|
||||
<DbIcon sx={{ color: 'white' }} />
|
||||
<DbIcon className="text-white" />
|
||||
</Box>
|
||||
<Typography variant="h6" className="font-bold">MariaDB Tuning</Typography>
|
||||
<Chip label={mariaDbVersions.length} size="small" variant="outlined" />
|
||||
@@ -316,7 +316,7 @@ export default function ServerTuning() {
|
||||
<CardContent sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Box>
|
||||
<Typography variant="subtitle1" className="font-bold">MariaDB {v.version}</Typography>
|
||||
<Typography variant="caption" color="text.secondary">Performance variables</Typography>
|
||||
<Typography variant="caption" className="text-secondary">Performance variables</Typography>
|
||||
</Box>
|
||||
<Button variant="outlined" color="secondary" size="small" startIcon={<TuneIcon />}>
|
||||
{t('tuning.tune_btn')}
|
||||
@@ -340,14 +340,14 @@ export default function ServerTuning() {
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ borderBottom: '1px solid rgba(255,255,255,0.1)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<DialogTitle sx={{ borderBottom: '1px solid var(--color-border-soft)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
|
||||
<TuneIcon color={selectedVersion?.type === 'php' ? 'primary' : 'secondary'} />
|
||||
<Typography variant="h6" className="font-black">
|
||||
{selectedVersion?.type === 'php' ? `PHP ${selectedVersion?.version}` : `MariaDB ${selectedVersion?.version}`} Tuning
|
||||
</Typography>
|
||||
</Box>
|
||||
<IconButton onClick={() => setIsModalOpen(false)} sx={{ color: 'rgba(255,255,255,0.5)' }}>
|
||||
<IconButton onClick={() => setIsModalOpen(false)} className="text-secondary">
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</DialogTitle>
|
||||
@@ -364,7 +364,7 @@ export default function ServerTuning() {
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<Typography variant="subtitle2" className="font-bold">{p.label}</Typography>
|
||||
<Tooltip title={t(p.description)}>
|
||||
<InfoIcon sx={{ fontSize: 16, color: 'rgba(255,255,255,0.3)', cursor: 'help' }} />
|
||||
<InfoIcon className="text-secondary" sx={{ fontSize: 'var(--font-size-md)', cursor: 'help' }} />
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<TextField
|
||||
@@ -391,7 +391,7 @@ export default function ServerTuning() {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Typography variant="caption" className="text-muted" sx={{ mt: -1, display: 'block' }}>
|
||||
<Typography variant="caption" className="text-secondary" sx={{ mt: -1, display: 'block' }}>
|
||||
{t(p.description)}
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -399,7 +399,7 @@ export default function ServerTuning() {
|
||||
</Stack>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 3, borderTop: '1px solid rgba(255,255,255,0.1)' }}>
|
||||
<DialogActions sx={{ p: 3, borderTop: '1px solid var(--color-border-soft)' }}>
|
||||
<Button onClick={() => setIsModalOpen(false)} disabled={saving}>
|
||||
{t('common.cancel')}
|
||||
</Button>
|
||||
|
||||
@@ -5,9 +5,7 @@ import {
|
||||
IconButton,
|
||||
Tooltip,
|
||||
Stack,
|
||||
Button,
|
||||
Paper,
|
||||
Divider,
|
||||
Alert,
|
||||
CircularProgress,
|
||||
Chip
|
||||
@@ -65,11 +63,11 @@ export default function ServiceEventMonitor({ onClose }: { onClose?: () => void
|
||||
title: t('service_monitor.clear_confirm'),
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
confirmButtonColor: 'var(--color-primary)',
|
||||
confirmButtonText: t('common.yes_delete'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
background: '#1a1d21',
|
||||
color: '#fff'
|
||||
background: 'var(--color-bg-dark)',
|
||||
color: 'var(--color-text-primary)'
|
||||
})
|
||||
|
||||
if (result.isConfirmed && window.api) {
|
||||
@@ -105,7 +103,7 @@ export default function ServiceEventMonitor({ onClose }: { onClose?: () => void
|
||||
headerName: t('service_monitor.columns.service'),
|
||||
width: 120,
|
||||
renderCell: (params) => (
|
||||
<Typography variant="body2" sx={{ fontWeight: 'bold' }}>
|
||||
<Typography variant="body2" className="font-bold">
|
||||
{params.value}
|
||||
</Typography>
|
||||
)
|
||||
@@ -125,7 +123,7 @@ export default function ServiceEventMonitor({ onClose }: { onClose?: () => void
|
||||
label={t(`common.${action}`)}
|
||||
color={color as any}
|
||||
variant="outlined"
|
||||
sx={{ fontSize: 10, height: 20 }}
|
||||
sx={{ fontSize: '10px', height: '20px' }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -137,11 +135,11 @@ export default function ServiceEventMonitor({ onClose }: { onClose?: () => void
|
||||
renderCell: (params) => {
|
||||
const status = params.value as string
|
||||
return status === 'success' ? (
|
||||
<SuccessIcon sx={{ color: 'success.main', fontSize: 18 }} />
|
||||
<SuccessIcon sx={{ color: 'success.main', fontSize: 'var(--font-size-md)' }} />
|
||||
) : status === 'failure' ? (
|
||||
<ErrorIcon sx={{ color: 'error.main', fontSize: 18 }} />
|
||||
<ErrorIcon sx={{ color: 'error.main', fontSize: 'var(--font-size-md)' }} />
|
||||
) : (
|
||||
<InfoIcon sx={{ color: 'info.main', fontSize: 18 }} />
|
||||
<InfoIcon sx={{ color: 'info.main', fontSize: 'var(--font-size-md)' }} />
|
||||
)
|
||||
}
|
||||
},
|
||||
@@ -151,7 +149,7 @@ export default function ServiceEventMonitor({ onClose }: { onClose?: () => void
|
||||
flex: 1,
|
||||
renderCell: (params) => (
|
||||
<Tooltip title={params.value || ''}>
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.5)', cursor: 'default' }}>
|
||||
<Typography variant="caption" className="text-secondary" sx={{ cursor: 'default' }}>
|
||||
{params.value || '-'}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
@@ -160,16 +158,16 @@ export default function ServiceEventMonitor({ onClose }: { onClose?: () => void
|
||||
]
|
||||
|
||||
return (
|
||||
<Box sx={{ height: '100%', display: 'flex', flexDirection: 'column', bgcolor: '#111418', color: '#fff' }}>
|
||||
<Box sx={{ height: '100%', display: 'flex', flexDirection: 'column', bgcolor: 'var(--color-bg-dark)', color: 'var(--color-text-primary)' }}>
|
||||
{/* Header */}
|
||||
<Box sx={{ p: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
|
||||
<HistoryIcon color="primary" />
|
||||
<Box>
|
||||
<Typography variant="h6" sx={{ fontWeight: 800, lineHeight: 1 }}>
|
||||
<Typography variant="h6" className="font-black" sx={{ lineHeight: 1 }}>
|
||||
{t('service_monitor.title')}
|
||||
</Typography>
|
||||
<Typography variant="caption" sx={{ color: 'rgba(255,255,255,0.4)' }}>
|
||||
<Typography variant="caption" className="text-secondary">
|
||||
{t('service_monitor.desc')}
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -202,8 +200,8 @@ export default function ServiceEventMonitor({ onClose }: { onClose?: () => void
|
||||
) : (
|
||||
<Stack spacing={3}>
|
||||
{/* Chart Area */}
|
||||
<Paper sx={{ p: 2, bgcolor: 'rgba(255,255,255,0.02)', borderRadius: 3, border: '1px solid rgba(255,255,255,0.05)' }}>
|
||||
<Typography variant="subtitle2" sx={{ mb: 2, px: 1, fontWeight: 'bold', opacity: 0.6 }}>
|
||||
<Paper sx={{ p: 2, bgcolor: 'var(--color-bg-sidebar)', borderColor: 'var(--color-border-soft)' }} className="rounded-lg">
|
||||
<Typography variant="subtitle2" className="font-bold" sx={{ mb: 2, px: 1, opacity: 0.6 }}>
|
||||
{t('service_monitor.chart_title')}
|
||||
</Typography>
|
||||
<Box sx={{ height: 200, width: '100%' }}>
|
||||
@@ -217,10 +215,8 @@ export default function ServiceEventMonitor({ onClose }: { onClose?: () => void
|
||||
]}
|
||||
slotProps={{
|
||||
legend: {
|
||||
labelStyle: { fill: '#fff', fontSize: 10 },
|
||||
direction: 'row',
|
||||
position: { vertical: 'bottom', horizontal: 'middle' },
|
||||
padding: -10,
|
||||
direction: 'horizontal',
|
||||
position: { vertical: 'bottom', horizontal: 'center' }
|
||||
}
|
||||
}}
|
||||
margin={{ top: 10, bottom: 50, left: 30, right: 10 }}
|
||||
@@ -244,12 +240,12 @@ export default function ServiceEventMonitor({ onClose }: { onClose?: () => void
|
||||
hideFooter
|
||||
sx={{
|
||||
border: 'none',
|
||||
color: '#fff',
|
||||
'& .MuiDataGrid-cell': { borderBottom: '1px solid rgba(255,255,255,0.03)', fontSize: 12 },
|
||||
'& .MuiDataGrid-columnHeaders': { bgcolor: 'rgba(255,255,255,0.03)', borderBottom: '1px solid rgba(255,255,255,0.1)' },
|
||||
'& .MuiDataGrid-columnHeaderTitle': { fontWeight: 'bold', fontSize: 11, opacity: 0.5 },
|
||||
color: 'var(--color-text-primary)',
|
||||
'& .MuiDataGrid-cell': { borderBottom: '1px solid var(--color-border-soft)', fontSize: 'var(--font-size-xs)' },
|
||||
'& .MuiDataGrid-columnHeaders': { bgcolor: 'rgba(255,255,255,0.03)', borderBottom: '1px solid var(--color-border-medium)' },
|
||||
'& .MuiDataGrid-columnHeaderTitle': { fontWeight: 'bold', fontSize: 'var(--font-size-xs)', opacity: 0.5 },
|
||||
'& .MuiDataGrid-virtualScroller': { bgcolor: 'transparent' },
|
||||
'& .MuiDataGrid-footerContainer': { borderTop: '1px solid rgba(255,255,255,0.1)' }
|
||||
'& .MuiDataGrid-footerContainer': { borderTop: '1px solid var(--color-border-soft)' }
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -107,9 +107,9 @@ const UserGuide = () => {
|
||||
sx={{ my: 2, '& .MuiAlert-icon': { alignItems: 'center' } }}
|
||||
icon={<Icon />}
|
||||
>
|
||||
{alertTitle && <AlertTitle sx={{ fontWeight: 'bold' }}>{alertTitle}</AlertTitle>}
|
||||
{alertTitle && <AlertTitle className="font-bold">{alertTitle}</AlertTitle>}
|
||||
{alertLines.map((line, i) => (
|
||||
<Typography key={i} variant="body2" sx={{ mb: i === alertLines.length - 1 ? 0 : 0.5 }}>
|
||||
<Typography key={i} variant="body2" className="text-secondary" sx={{ mb: i === alertLines.length - 1 ? 0 : 0.5 }}>
|
||||
{parseInline(line)}
|
||||
</Typography>
|
||||
))}
|
||||
@@ -129,7 +129,7 @@ const UserGuide = () => {
|
||||
return <strong key={i}>{part.slice(2, -2)}</strong>
|
||||
}
|
||||
if (part.startsWith('`') && part.endsWith('`')) {
|
||||
return <code key={i} style={{ backgroundColor: 'rgba(255,255,255,0.05)', padding: '2px 4px', borderRadius: 4 }}>{part.slice(1, -1)}</code>
|
||||
return <code key={i} style={{ backgroundColor: 'var(--color-bg-soft)', padding: '2px 4px', borderRadius: 'var(--border-radius-sm)', border: '1px solid var(--color-border-soft)' }}>{part.slice(1, -1)}</code>
|
||||
}
|
||||
return part
|
||||
})
|
||||
@@ -146,12 +146,13 @@ const UserGuide = () => {
|
||||
key={`code-${index}`}
|
||||
variant="outlined"
|
||||
sx={{
|
||||
bgcolor: '#0d1117',
|
||||
bgcolor: 'var(--color-bg-medium)',
|
||||
p: 2,
|
||||
mb: 2,
|
||||
overflow: 'auto',
|
||||
borderColor: 'rgba(255,255,255,0.1)'
|
||||
borderColor: 'var(--color-border-soft)'
|
||||
}}
|
||||
className="rounded-lg"
|
||||
>
|
||||
<pre style={{ margin: 0 }}>
|
||||
<code className={`language-${codeLang || 'plaintext'}`}>
|
||||
@@ -215,11 +216,11 @@ const UserGuide = () => {
|
||||
sx={{
|
||||
mt: level === 1 ? 0 : 4,
|
||||
mb: 2,
|
||||
fontWeight: level === 1 ? 800 : 700,
|
||||
color: level === 1 ? 'primary.light' : '#fff',
|
||||
borderBottom: level === 1 ? '1px solid rgba(255,255,255,0.1)' : 'none',
|
||||
borderBottom: level === 1 ? '1px solid var(--color-border-soft)' : 'none',
|
||||
pb: level === 1 ? 1 : 0
|
||||
}}
|
||||
className={level === 1 ? 'font-black' : 'font-bold'}
|
||||
>
|
||||
{parseInline(content)}
|
||||
</Typography>
|
||||
@@ -232,7 +233,7 @@ const UserGuide = () => {
|
||||
flushAlert()
|
||||
const content = trimmedLine.slice(2)
|
||||
currentList.push(
|
||||
<Box component="li" key={`li-${index}`} sx={{ mb: 1, color: 'rgba(255,255,255,0.9)' }}>
|
||||
<Box component="li" key={`li-${index}`} sx={{ mb: 1 }} className="text-secondary">
|
||||
<Typography variant="body2">{parseInline(content)}</Typography>
|
||||
</Box>
|
||||
)
|
||||
@@ -254,10 +255,9 @@ const UserGuide = () => {
|
||||
variant="body1"
|
||||
sx={{
|
||||
mb: 2,
|
||||
lineHeight: 1.7,
|
||||
color: 'rgba(255,255,255,0.8)',
|
||||
fontSize: '0.95rem'
|
||||
lineHeight: 1.7
|
||||
}}
|
||||
className="text-secondary text-md"
|
||||
>
|
||||
{parseInline(trimmedLine)}
|
||||
</Typography>
|
||||
@@ -279,12 +279,12 @@ const UserGuide = () => {
|
||||
<Box sx={{ height: 'calc(100vh - 140px)', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
|
||||
{/* Breadcrumbs */}
|
||||
<Box sx={{ mb: 2, display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<Breadcrumbs separator={<ChevronRightIcon sx={{ fontSize: '1rem', color: 'rgba(255,255,255,0.3)' }} />} aria-label="breadcrumb">
|
||||
<Link underline="hover" color="inherit" sx={{ display: 'flex', alignItems: 'center', color: 'rgba(255,255,255,0.5)', fontSize: '0.85rem' }}>
|
||||
<GuideIcon sx={{ mr: 0.5, fontSize: '1.1rem' }} />
|
||||
<Breadcrumbs separator={<ChevronRightIcon sx={{ fontSize: 'var(--font-size-md)', color: 'var(--color-border-medium)' }} />} aria-label="breadcrumb">
|
||||
<Link underline="hover" color="inherit" sx={{ display: 'flex', alignItems: 'center' }} className="text-secondary text-sm">
|
||||
<GuideIcon sx={{ mr: 0.5, fontSize: 'var(--font-size-lg)' }} />
|
||||
{t('common.user_guide')}
|
||||
</Link>
|
||||
<Typography color="primary.light" sx={{ fontSize: '0.85rem', fontWeight: 'bold' }}>
|
||||
<Typography color="primary.light" className="text-sm font-bold">
|
||||
{topics.find(t => t.file === selectedTopic)?.title || selectedTopic}
|
||||
</Typography>
|
||||
</Breadcrumbs>
|
||||
@@ -296,14 +296,10 @@ const UserGuide = () => {
|
||||
<Paper
|
||||
variant="outlined"
|
||||
sx={{
|
||||
bgcolor: 'rgba(255,255,255,0.02)',
|
||||
borderColor: 'rgba(255,255,255,0.05)',
|
||||
borderRadius: 3,
|
||||
overflow: 'hidden',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
bgcolor: 'var(--color-bg-sidebar)',
|
||||
borderColor: 'var(--color-border-soft)'
|
||||
}}
|
||||
className="rounded-lg overflow-hidden flex flex-col h-full"
|
||||
>
|
||||
<Box sx={{ p: 2, pb: 1 }}>
|
||||
<TextField
|
||||
@@ -315,7 +311,7 @@ const UserGuide = () => {
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<SearchIcon sx={{ color: 'rgba(255,255,255,0.3)', fontSize: '1.2rem' }} />
|
||||
<SearchIcon sx={{ color: 'var(--color-text-secondary)', fontSize: 'var(--font-size-lg)' }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
@@ -349,8 +345,7 @@ const UserGuide = () => {
|
||||
primary={topic.title}
|
||||
primaryTypographyProps={{
|
||||
variant: 'body2',
|
||||
fontWeight: selectedTopic === topic.file ? 700 : 500,
|
||||
color: selectedTopic === topic.file ? '#fff' : 'rgba(255,255,255,0.6)'
|
||||
className: selectedTopic === topic.file ? 'font-bold text-white' : 'text-secondary font-medium'
|
||||
}}
|
||||
/>
|
||||
</ListItemButton>
|
||||
@@ -366,12 +361,12 @@ const UserGuide = () => {
|
||||
elevation={0}
|
||||
sx={{
|
||||
p: { xs: 3, md: 5 },
|
||||
bgcolor: 'rgba(0,0,0,0.2)',
|
||||
borderRadius: 4,
|
||||
bgcolor: 'var(--color-bg-soft)',
|
||||
minHeight: '100%',
|
||||
border: '1px solid rgba(255,255,255,0.03)',
|
||||
border: '1px solid var(--color-border-soft)',
|
||||
position: 'relative'
|
||||
}}
|
||||
className="rounded-xl"
|
||||
>
|
||||
{loading ? (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '200px' }}>
|
||||
|
||||
@@ -2,12 +2,16 @@ import { GlobalStyles as MuiGlobalStyles } from '@mui/material'
|
||||
|
||||
const styles = {
|
||||
':root': {
|
||||
'--font-size-xs': '0.65rem',
|
||||
'--font-size-sm': '1rem',
|
||||
'--font-size-md': '0.85rem',
|
||||
'--font-size-2xs': '0.65rem',
|
||||
'--font-size-xs': '0.7rem',
|
||||
'--font-size-sm': '0.8rem',
|
||||
'--font-size-md': '0.9rem',
|
||||
'--font-size-base': '1rem',
|
||||
'--font-size-lg': '1.25rem',
|
||||
'--font-size-xl': '1.5rem',
|
||||
'--font-size-2xl': '2rem',
|
||||
'--font-size-3xl': '3rem',
|
||||
'--font-size-4xl': '4rem',
|
||||
'--font-weight-thin': '300',
|
||||
'--font-weight-normal': '400',
|
||||
'--font-weight-medium': '500',
|
||||
@@ -18,12 +22,27 @@ const styles = {
|
||||
'--radius-md': '8px',
|
||||
'--radius-lg': '12px',
|
||||
'--radius-xl': '16px',
|
||||
'--color-border-soft': 'rgba(255, 255, 255, 0.05)',
|
||||
'--color-border-medium': 'rgba(255, 255, 255, 0.1)',
|
||||
'--color-text-secondary': 'rgba(255, 255, 255, 0.5)',
|
||||
'--color-text-muted': 'rgba(255, 255, 255, 0.3)',
|
||||
'--color-primary': '#39A7FF',
|
||||
'--color-primary-soft': 'rgba(57, 167, 255, 0.1)',
|
||||
'--color-secondary': '#33d9b2',
|
||||
'--color-secondary-soft': 'rgba(51, 217, 178, 0.1)',
|
||||
'--color-success': '#33d9b2',
|
||||
'--color-success-soft': 'rgba(51, 217, 178, 0.1)',
|
||||
'--color-warning': '#ffb142',
|
||||
'--color-warning-soft': 'rgba(255, 177, 66, 0.1)',
|
||||
'--color-error': '#ff5252',
|
||||
'--color-error-soft': 'rgba(255, 82, 82, 0.1)',
|
||||
'--color-bg-dark': '#121212',
|
||||
'--color-bg-navbar': 'rgba(21, 62, 94, 0.85)',
|
||||
'--color-bg-sidebar': 'rgba(18, 18, 18, 0.95)',
|
||||
'--color-bg-soft': 'rgba(255, 255, 255, 0.03)',
|
||||
'--color-bg-medium': 'rgba(0, 0, 0, 0.2)',
|
||||
'--color-border-soft': 'rgba(255, 255, 255, 0.05)',
|
||||
'--color-border-medium': 'rgba(255, 255, 255, 0.1)',
|
||||
'--color-text-primary': '#ffffff',
|
||||
'--color-text-secondary': 'rgba(255, 255, 255, 0.7)',
|
||||
'--color-text-tertiary': 'rgba(255, 255, 255, 0.5)',
|
||||
'--color-text-muted': 'rgba(255, 255, 255, 0.3)',
|
||||
},
|
||||
'.text-xs': { fontSize: 'var(--font-size-xs) !important' },
|
||||
'.text-sm': { fontSize: 'var(--font-size-sm) !important' },
|
||||
|
||||
Reference in New Issue
Block a user