feat: implement MariaDB export/import wizards, server tuning, and global styling components
This commit is contained in:
@@ -56,12 +56,22 @@ header img.logo {
|
||||
}
|
||||
|
||||
/* For automatic logo switching in dark mode */
|
||||
.logo-light { display: none; }
|
||||
.logo-dark { display: block; }
|
||||
.logo-light {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo-dark {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.logo-dark { display: none; }
|
||||
.logo-light { display: block; }
|
||||
.logo-dark {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo-light {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
@@ -77,7 +87,8 @@ table {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
th, td {
|
||||
th,
|
||||
td {
|
||||
padding: 0.75rem 1rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
@@ -169,4 +180,4 @@ footer {
|
||||
text-align: center;
|
||||
font-size: 0.875rem;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
+45
-66
@@ -389,11 +389,19 @@ function App(): JSX.Element {
|
||||
}
|
||||
}, [logs, logDialogOpen])
|
||||
|
||||
const handleOpenNginxConfig = async () => {
|
||||
if (window.api && window.api.invoke) {
|
||||
const config = await window.api.invoke('nginx:config:get')
|
||||
setNginxConfig(config)
|
||||
setIsNginxConfigOpen(true)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSaveNginxConfig = async () => {
|
||||
if (window.api && window.api.invoke) {
|
||||
const result = await window.api.invoke('nginx:config:save', nginxConfig)
|
||||
if (result.success) {
|
||||
Swal.fire({ title: t('common.success'), text: t('server.nginx.config_saved'), icon: 'success', background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ title: t('common.success'), text: t('server.nginx.config_saved'), icon: 'success' })
|
||||
setIsNginxConfigOpen(false)
|
||||
}
|
||||
}
|
||||
@@ -411,7 +419,7 @@ function App(): JSX.Element {
|
||||
if (window.api && window.api.invoke) {
|
||||
const result = await window.api.invoke('apache:config:save', apacheConfig)
|
||||
if (result.success) {
|
||||
Swal.fire({ title: t('common.success'), text: t('server.apache.config_saved'), icon: 'success', background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ title: t('common.success'), text: t('server.apache.config_saved'), icon: 'success' })
|
||||
setIsApacheConfigOpen(false)
|
||||
}
|
||||
}
|
||||
@@ -420,7 +428,7 @@ function App(): JSX.Element {
|
||||
const handleTestApacheConfig = async () => {
|
||||
if (window.api && window.api.invoke) {
|
||||
const result = await window.api.invoke('apache:config:test')
|
||||
Swal.fire({ title: result.success ? t('common.success') : t('common.error'), text: result.message, icon: result.success ? 'success' : 'error', background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ title: result.success ? t('common.success') : t('common.error'), text: result.message, icon: result.success ? 'success' : 'error' })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,32 +470,36 @@ function App(): JSX.Element {
|
||||
|
||||
const updateSwal = (currentSrv?: string) => {
|
||||
const html = `
|
||||
<div style="text-align: left; font-family: 'Inter', sans-serif; padding-top: 10px;">
|
||||
<div class="swal-service-list">
|
||||
${services.map(srv => {
|
||||
const label = getDisplayLabel(srv);
|
||||
const res = results[srv];
|
||||
let icon = '<span style="color: rgba(255,255,255,0.1); margin-right: 12px; font-size: 0.8rem;">○</span>';
|
||||
let statusColor = 'rgba(255,255,255,0.4)';
|
||||
let iconClass = 'swal-status-icon';
|
||||
let noteClass = 'swal-status-note';
|
||||
let note = operation === 'start' ? t('common.ready') : t('common.running');
|
||||
|
||||
if (res?.success) {
|
||||
icon = '<span style="color: #33d9b2; margin-right: 12px; font-size: 0.8rem;">●</span>';
|
||||
statusColor = '#33d9b2';
|
||||
iconClass += ' success';
|
||||
noteClass += ' success';
|
||||
note = operation === 'start' ? t('common.started') : t('common.stopped');
|
||||
} else if (res?.error) {
|
||||
icon = '<span style="color: #ff5252; margin-right: 12px; font-size: 0.8rem;">●</span>';
|
||||
statusColor = '#ff5252';
|
||||
iconClass += ' error';
|
||||
noteClass += ' error';
|
||||
note = t('common.error');
|
||||
} else if (srv === currentSrv) {
|
||||
icon = '<span style="color: #39A7FF; margin-right: 12px; font-size: 0.8rem;" class="swal2-loading-dots">●</span>';
|
||||
statusColor = '#39A7FF';
|
||||
iconClass += ' loading swal2-loading-dots';
|
||||
noteClass += ' loading';
|
||||
note = operation === 'start' ? t('common.starting') : t('common.stopping');
|
||||
}
|
||||
|
||||
return '<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; padding: 8px 14px; background: rgba(0,0,0,0.2); border: 1px solid rgba(255,255,255,0.03); border-radius: 8px; font-size: 0.8rem;">' +
|
||||
'<span style="font-weight: 600; display: flex; align-items: center;">' + icon + ' ' + label + '</span>' +
|
||||
'<span style="font-size: 0.65rem; color: ' + statusColor + '; font-weight: 800; letter-spacing: 0.5px;">' + note.toUpperCase() + '</span>' +
|
||||
'</div>';
|
||||
return `
|
||||
<div class="swal-service-item">
|
||||
<span class="swal-service-label">
|
||||
<span class="${iconClass}">●</span> ${label}
|
||||
</span>
|
||||
<span class="${noteClass}">${note.toUpperCase()}</span>
|
||||
</div>
|
||||
`;
|
||||
}).join('')}
|
||||
</div>
|
||||
`;
|
||||
@@ -499,8 +511,6 @@ function App(): JSX.Element {
|
||||
html: '<div></div>',
|
||||
allowOutsideClick: false,
|
||||
showConfirmButton: false,
|
||||
background: '#1a1d21',
|
||||
color: '#fff',
|
||||
customClass: {
|
||||
title: 'swal-title-small'
|
||||
},
|
||||
@@ -598,9 +608,7 @@ function App(): JSX.Element {
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: t('common.yes_delete'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
cancelButtonText: t('common.cancel')
|
||||
})
|
||||
|
||||
if (result.isConfirmed) {
|
||||
@@ -639,8 +647,6 @@ function App(): JSX.Element {
|
||||
showCancelButton: !result.success && !!errorInfo?.host,
|
||||
confirmButtonText: !result.success && errorInfo?.host ? t('common.go_to_fix') : t('common.ok'),
|
||||
cancelButtonText: t('common.close'),
|
||||
background: '#1e1e1e',
|
||||
color: '#fff',
|
||||
width: '600px'
|
||||
}).then((alertResult) => {
|
||||
if (alertResult.isConfirmed && !result.success && errorInfo?.host) {
|
||||
@@ -667,10 +673,7 @@ function App(): JSX.Element {
|
||||
Swal.fire({
|
||||
title: t('common.success'),
|
||||
text: t('server.nginx.config_saved'),
|
||||
icon: 'success',
|
||||
background: '#1e1e1e',
|
||||
color: '#fff',
|
||||
customClass: { popup: 'swal2-dark-popup' }
|
||||
icon: 'success'
|
||||
})
|
||||
setIsProjectNginxConfigOpen(false)
|
||||
}
|
||||
@@ -762,9 +765,7 @@ function App(): JSX.Element {
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: t('mariadb_process_monitor.kill_btn'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
background: '#1a1d21',
|
||||
color: '#fff'
|
||||
cancelButtonText: t('common.cancel')
|
||||
})
|
||||
|
||||
if (result.isConfirmed) {
|
||||
@@ -789,13 +790,7 @@ function App(): JSX.Element {
|
||||
maxWidth="lg"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: '#1a1d21',
|
||||
backgroundImage: 'none',
|
||||
color: '#fff',
|
||||
borderRadius: 2,
|
||||
border: '1px solid rgba(255,255,255,0.1)'
|
||||
}
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ borderBottom: '1px solid rgba(255,255,255,0.1)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
@@ -1167,7 +1162,12 @@ function App(): JSX.Element {
|
||||
</Box>
|
||||
)}
|
||||
{v.status === 'installed' && (
|
||||
<Chip label={t('common.ok').toUpperCase()} color="success" variant="outlined" size="small" />
|
||||
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>
|
||||
<Button variant="outlined" size="small" startIcon={<SettingsIcon />} onClick={handleOpenNginxConfig}>
|
||||
{t('common.settings').toUpperCase()}
|
||||
</Button>
|
||||
<Chip label={t('common.ok').toUpperCase()} color="success" variant="outlined" size="small" />
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</ListItem>
|
||||
@@ -1920,11 +1920,7 @@ function App(): JSX.Element {
|
||||
maxWidth="lg"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: '#1a1d21',
|
||||
color: '#fff',
|
||||
borderRadius: 2
|
||||
}
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ borderBottom: '1px solid rgba(255,255,255,0.05)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
@@ -2016,12 +2012,7 @@ function App(): JSX.Element {
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: '#1e1e1e',
|
||||
color: '#fff',
|
||||
borderRadius: 3,
|
||||
border: '1px solid rgba(255,255,255,0.1)'
|
||||
}
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
@@ -2067,12 +2058,7 @@ function App(): JSX.Element {
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: '#1e1e1e',
|
||||
color: '#fff',
|
||||
borderRadius: 3,
|
||||
border: '1px solid rgba(255,255,255,0.1)'
|
||||
}
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
@@ -2112,16 +2098,14 @@ function App(): JSX.Element {
|
||||
${formattedMessage}
|
||||
</div>
|
||||
${!result.success && errorInfo ? `
|
||||
<div style="margin-top: 15px; text-align: center;">
|
||||
<p style="font-size: 0.9rem; color: #ffb142;">
|
||||
<b>{t('server.project_nginx.error_line', { line: errorInfo.line })}</b>
|
||||
<div class="swal-error-footer">
|
||||
<p class="swal-error-line">
|
||||
<b>${t('server.project_nginx.error_line', { line: errorInfo.line })}</b>
|
||||
</p>
|
||||
</div>
|
||||
` : ''}
|
||||
`,
|
||||
icon: result.success ? 'success' : 'error',
|
||||
background: '#1e1e1e',
|
||||
color: '#fff',
|
||||
width: '600px'
|
||||
})
|
||||
}
|
||||
@@ -2150,12 +2134,7 @@ function App(): JSX.Element {
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: '#1e1e1e',
|
||||
color: '#fff',
|
||||
borderRadius: 3,
|
||||
border: '1px solid rgba(255,255,255,0.1)'
|
||||
}
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
|
||||
@@ -88,8 +88,6 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
|
||||
input: 'text',
|
||||
inputLabel: t('mariadb_manager.db_name_label'),
|
||||
showCancelButton: true,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff',
|
||||
inputValidator: (value) => {
|
||||
if (!value) return t('common.error_required')
|
||||
return null
|
||||
@@ -99,10 +97,10 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
|
||||
if (dbName) {
|
||||
const result = await window.api.invoke('mariadb:create-db', { versionId: selectedVersion, dbName })
|
||||
if (result.success) {
|
||||
Swal.fire({ icon: 'success', title: t('common.ok'), background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ icon: 'success', title: t('common.ok') })
|
||||
fetchData()
|
||||
} else {
|
||||
Swal.fire({ icon: 'error', title: t('common.error'), text: result.message, background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ icon: 'error', title: t('common.error'), text: result.message })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,9 +110,7 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
|
||||
title: t('common.are_you_sure'),
|
||||
text: t('mariadb_manager.delete_db_confirm', { db: dbName }),
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
showCancelButton: true
|
||||
})
|
||||
|
||||
if (result.isConfirmed) {
|
||||
@@ -122,7 +118,7 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
|
||||
if (res.success) {
|
||||
fetchData()
|
||||
} else {
|
||||
Swal.fire({ icon: 'error', title: t('common.error'), text: res.message, background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ icon: 'error', title: t('common.error'), text: res.message })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,8 +131,6 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
|
||||
`<input id="swal-host" class="swal2-input" placeholder="Host" value="%">` +
|
||||
`<input id="swal-pass" type="password" class="swal2-input" placeholder="${t('mariadb_manager.password_label')}">`,
|
||||
focusConfirm: false,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff',
|
||||
preConfirm: () => {
|
||||
const user = (document.getElementById('swal-user') as HTMLInputElement).value
|
||||
const host = (document.getElementById('swal-host') as HTMLInputElement).value
|
||||
@@ -152,10 +146,10 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
|
||||
if (formValues) {
|
||||
const result = await window.api.invoke('mariadb:create-user', { versionId: selectedVersion, ...formValues })
|
||||
if (result.success) {
|
||||
Swal.fire({ icon: 'success', title: t('common.ok'), background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ icon: 'success', title: t('common.ok') })
|
||||
fetchData()
|
||||
} else {
|
||||
Swal.fire({ icon: 'error', title: t('common.error'), text: result.message, background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ icon: 'error', title: t('common.error'), text: result.message })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,9 +159,7 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
|
||||
title: t('common.are_you_sure'),
|
||||
text: t('mariadb_manager.delete_user_confirm', { user: `${user}@${host}` }),
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
showCancelButton: true
|
||||
})
|
||||
|
||||
if (result.isConfirmed) {
|
||||
@@ -175,7 +167,7 @@ const MariaDbDatabaseManager: React.FC<MariaDbDatabaseManagerProps> = ({ version
|
||||
if (res.success) {
|
||||
fetchData()
|
||||
} else {
|
||||
Swal.fire({ icon: 'error', title: t('common.error'), text: res.message, background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ icon: 'error', title: t('common.error'), text: res.message })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +272,15 @@ const MariaDbExportWizard: React.FC<MariaDbExportWizardProps> = ({ open, onClose
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={loading ? undefined : onClose} maxWidth="sm" fullWidth>
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={loading ? undefined : onClose}
|
||||
maxWidth="sm"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle>{t('mariadb.export.wizard_title')}</DialogTitle>
|
||||
<DialogContent>
|
||||
<Stepper activeStep={activeStep} orientation="horizontal" sx={{ pt: 2, pb: 4 }}>
|
||||
|
||||
@@ -316,7 +316,15 @@ const MariaDbImportWizard: React.FC<MariaDbImportWizardProps> = ({ open, onClose
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={loading ? undefined : onClose} maxWidth="sm" fullWidth>
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={loading ? undefined : onClose}
|
||||
maxWidth="sm"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle>{t('mariadb.import.wizard_title')}</DialogTitle>
|
||||
<DialogContent>
|
||||
<Stepper activeStep={activeStep} orientation="horizontal" sx={{ pt: 2, pb: 4 }}>
|
||||
|
||||
@@ -79,9 +79,7 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
|
||||
allowOutsideClick: false,
|
||||
didOpen: () => {
|
||||
Swal.showLoading()
|
||||
},
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
@@ -95,15 +93,13 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
|
||||
text: t('php.extensions.success_msg'),
|
||||
icon: 'success',
|
||||
timer: 2000,
|
||||
showConfirmButton: false,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
showConfirmButton: false
|
||||
})
|
||||
setIsRawEditorOpen(false)
|
||||
fetchExtensions()
|
||||
}
|
||||
} catch (error: any) {
|
||||
Swal.fire({ title: 'Hata', text: error.message, icon: 'error', background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ title: 'Hata', text: error.message, icon: 'error' })
|
||||
} finally {
|
||||
setIsSavingRaw(false)
|
||||
}
|
||||
@@ -131,9 +127,7 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
|
||||
allowOutsideClick: false,
|
||||
didOpen: () => {
|
||||
Swal.showLoading()
|
||||
},
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -147,10 +141,10 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
|
||||
Swal.close()
|
||||
}
|
||||
} else {
|
||||
Swal.fire({ title: t('common.error'), text: result.message, icon: 'error', background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ title: t('common.error'), text: result.message, icon: 'error' })
|
||||
}
|
||||
} catch (error: any) {
|
||||
Swal.fire({ title: t('common.error'), text: error.message, icon: 'error', background: '#1e1e1e', color: '#fff' })
|
||||
Swal.fire({ title: t('common.error'), text: error.message, icon: 'error' })
|
||||
} finally {
|
||||
setSaving(null)
|
||||
}
|
||||
@@ -169,13 +163,7 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
|
||||
maxWidth="sm"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: '#1e1e1e',
|
||||
color: '#fff',
|
||||
backgroundImage: 'none',
|
||||
borderRadius: 2,
|
||||
border: '1px solid rgba(255,255,255,0.1)'
|
||||
}
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ m: 0, p: 1.5, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
@@ -280,13 +268,7 @@ const PhpExtensionManager: React.FC<PhpExtensionManagerProps> = ({ open, onClose
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: '#1a1a1a',
|
||||
color: '#fff',
|
||||
borderRadius: 2,
|
||||
backgroundImage: 'none',
|
||||
border: '1px solid rgba(255,255,255,0.1)'
|
||||
}
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ display: 'flex', flexDirection: 'column', gap: 0.5, p: 1.5 }}>
|
||||
|
||||
@@ -150,9 +150,7 @@ export default function ProjectDetails({
|
||||
toast: true,
|
||||
position: 'top-end',
|
||||
showConfirmButton: false,
|
||||
timer: 3000,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
timer: 3000
|
||||
});
|
||||
onRefreshProjects();
|
||||
}
|
||||
@@ -160,9 +158,7 @@ export default function ProjectDetails({
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: t('common.error'),
|
||||
text: e.message,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
text: e.message
|
||||
});
|
||||
} finally {
|
||||
setIsConfigSaving(false);
|
||||
@@ -186,9 +182,7 @@ export default function ProjectDetails({
|
||||
toast: true,
|
||||
position: 'top-end',
|
||||
showConfirmButton: false,
|
||||
timer: 3000,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
timer: 3000
|
||||
});
|
||||
if (onRefreshProjects) onRefreshProjects();
|
||||
}
|
||||
@@ -196,9 +190,7 @@ export default function ProjectDetails({
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: t('common.error'),
|
||||
text: error.message,
|
||||
background: '#1e1e1e',
|
||||
color: '#fff'
|
||||
text: error.message
|
||||
});
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
|
||||
@@ -337,13 +337,7 @@ export default function ServerTuning() {
|
||||
maxWidth="sm"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
bgcolor: '#1a1d21',
|
||||
backgroundImage: 'none',
|
||||
color: '#fff',
|
||||
borderRadius: 4,
|
||||
border: '1px solid rgba(255,255,255,0.1)'
|
||||
}
|
||||
className: 'mui-custom-dialog-paper'
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ borderBottom: '1px solid rgba(255,255,255,0.1)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
{
|
||||
"common": {
|
||||
"actions": "Действие",
|
||||
"start": "Запустить",
|
||||
"stop": "Остановить",
|
||||
"started": "Запущено",
|
||||
"restart": "Перезапустить",
|
||||
"settings": "Настройки",
|
||||
"tools": "Инструменты",
|
||||
"close": "Закрыть",
|
||||
"quit": "Выход",
|
||||
"save": "Сохранить",
|
||||
"user_guide": "Руководство пользователя",
|
||||
"port": "Порт",
|
||||
"all": "Все",
|
||||
"export": "Экспорт",
|
||||
"import": "Импорт",
|
||||
"ok": "ОК",
|
||||
"cancel": "Отмена",
|
||||
"error": "Ошибка!",
|
||||
"success": "Успешно!",
|
||||
"warning": "Предупреждение",
|
||||
"info": "Информация",
|
||||
"delete": "Удалить",
|
||||
"edit": "Редактировать",
|
||||
"refresh": "Обновить",
|
||||
"search": "Поиск",
|
||||
"loading": "Загрузка...",
|
||||
"starting": "Запуск...",
|
||||
"running": "Работает",
|
||||
"stopped": "Остановлено",
|
||||
"stopping": "Остановка...",
|
||||
"ready": "Готово.",
|
||||
"waiting_process": "Ожидание процесса...",
|
||||
"executable_not_found": "Файл не найден",
|
||||
"are_you_sure": "Вы уверены?",
|
||||
"yes_delete": "Да, удалить",
|
||||
"go_to_fix": "Перейти к исправлению",
|
||||
"select": "ВЫБРАТЬ",
|
||||
"next": "ДАЛЕЕ",
|
||||
"back": "НАЗАД",
|
||||
"finish": "ЗАВЕРШИТЬ",
|
||||
"download": "СКАЧАТЬ",
|
||||
"available": "Доступно",
|
||||
"reset": "Сбросить",
|
||||
"copy": "Копировать",
|
||||
"browse": "Обзор",
|
||||
"delete_confirm": "Вы уверены, что хотите удалить этот проект?",
|
||||
"stop_status": "Остановка",
|
||||
"reset_confirm_title": "Вы уверены?",
|
||||
"reset_confirm_text": "Вы хотите сбросить данные {{service}}? Это действие удалит все данные и выполнит чистую установку.",
|
||||
"reset_btn": "Да, сбросить",
|
||||
"operating": "Операция выполняется...",
|
||||
"please_wait": "Пожалуйста, подождите...",
|
||||
"status": "Статус"
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "Панель управления",
|
||||
"status": "Статус сервера",
|
||||
"services": "Сервисы",
|
||||
"active_version": "Активная версия PHP",
|
||||
"quick_look": "Быстрый обзор",
|
||||
"start_all": "Запустить все",
|
||||
"stop_all": "Остановить все",
|
||||
"starting_all": "Запуск всех сервисов",
|
||||
"stopping_all": "Остановка всех сервисов",
|
||||
"all_started": "Все сервисы запущены.",
|
||||
"all_stopped": "Все сервисы остановлены.",
|
||||
"overview": "Обзор",
|
||||
"service_settings": "Настройки сервиса",
|
||||
"project_settings": "Настройки проекта",
|
||||
"select_service": "Пожалуйста, выберите сервис",
|
||||
"system_stats": "СИСТЕМНАЯ СТАТИСТИКА",
|
||||
"service_info": "ИНФОРМАЦИЯ О СЕРВИСЕ"
|
||||
},
|
||||
"projects": {
|
||||
"title": "Мои проекты",
|
||||
"add_new": "Добавить новый проект",
|
||||
"search": "Поиск проекта или хоста...",
|
||||
"edit": "Редактировать проект",
|
||||
"empty": "Проекты пока не добавлены.",
|
||||
"name": "Название проекта",
|
||||
"path": "Путь к папке",
|
||||
"host": "Хост / Домен",
|
||||
"hostname_placeholder": "Имя хоста (напр: local.test)",
|
||||
"php_version": "Версия PHP",
|
||||
"mariadb_version": "Версия MariaDB",
|
||||
"server_type": "Веб-сервер",
|
||||
"apache_htaccess": "Apache (с поддержкой htaccess)",
|
||||
"actions": "Действия",
|
||||
"no_php_warning": "Сначала необходимо скачать версию PHP",
|
||||
"added": "Проект успешно добавлен.",
|
||||
"updated": "Проект успешно обновлен.",
|
||||
"deleted": "Проект удален.",
|
||||
"delete_confirm": "Вы уверены, что хотите удалить этот проект? Ваши файлы не будут удалены, проект просто исчезнет из списка.",
|
||||
"browse": "Обзор",
|
||||
"overview": "Обзор",
|
||||
"database": "База данных",
|
||||
"site_domain": "Адрес сайта",
|
||||
"web_server": "Веб-сервер",
|
||||
"site_path": "Путь к файлам",
|
||||
"open_site": "ОТКРЫТЬ САЙТ",
|
||||
"stop_site": "ОСТАНОВИТЬ САЙТ",
|
||||
"start_site": "ЗАПУСТИТЬ САЙТ",
|
||||
"no_site_selected": "Пожалуйста, сначала выберите сайт.",
|
||||
"server_settings": "НАСТРОЙКИ СЕРВЕРА",
|
||||
"manual_edit_warning": "При ручном редактировании этих настроек в начало добавляется # MANUAL_EDIT, и система прекращает автоматические обновления.",
|
||||
"no_project_selected": "Пожалуйста, выберите проект из списка или создайте новый."
|
||||
},
|
||||
"settings": {
|
||||
"general": "Общие настройки",
|
||||
"saved": "Настройки сохранены.",
|
||||
"save_failed": "Не удалось сохранить настройки.",
|
||||
"language": "Язык",
|
||||
"nginx_port": "Порт Nginx",
|
||||
"apache_port": "Порт Apache",
|
||||
"php_port": "Порт PHP-FPM",
|
||||
"mariadb_port": "Порт MariaDB",
|
||||
"remote_access": "Разрешить удаленный доступ",
|
||||
"server_type_select": "Тип сервера по умолчанию",
|
||||
"php_versions": "Версии PHP",
|
||||
"mariadb_versions": "Версии MariaDB",
|
||||
"nginx_versions": "Версии Nginx",
|
||||
"apache_versions": "Версии Apache",
|
||||
"php_versions_desc": "Здесь вы можете скачивать и управлять необходимыми версиями PHP.",
|
||||
"mariadb_versions_desc": "Управление версиями MariaDB.",
|
||||
"nginx_versions_desc": "Управление версиями Nginx.",
|
||||
"apache_versions_desc": "Управление версиями Apache.",
|
||||
"nginx_port_desc": "Порт, на котором будет работать Nginx (по умолчанию: 80)",
|
||||
"cli_env": "CLI и переменные окружения",
|
||||
"cli_env_desc": "Управляйте настройками PATH, чтобы запускать команды PHP и MariaDB напрямую из любого терминала (CMD, PowerShell).",
|
||||
"cli_enabled": "Интеграция с системным PATH активна",
|
||||
"cli_enabled_desc": "Если включено, папка 'bin' Multi-PHP будет добавлена в переменную PATH пользователя.",
|
||||
"cli_default_php": "Версия PHP по умолчанию (php)",
|
||||
"cli_default_php_desc": "Выберите, какая версия будет использоваться при выполнении команды 'php'.",
|
||||
"cli_default_mariadb": "Версия MariaDB по умолчанию (mysql)",
|
||||
"cli_default_mariadb_desc": "Версия по умолчанию для команд 'mysql' или 'mariadb'.",
|
||||
"cli_sync_btn": "Синхронизировать команды",
|
||||
"cli_path_found": "Настройка PATH найдена:",
|
||||
"cli_path_not_found": "Настройка PATH еще не выполнена",
|
||||
"cli_sync_success": "Команды CLI успешно обновлены.",
|
||||
"cli_aliases_title": "Созданные команды (псевдонимы)",
|
||||
"cli_restart_warning": "Внимание: Чтобы изменения PATH вступили в силу, необходимо закрыть и снова открыть окна терминала/CMD.",
|
||||
"cli_table_command": "Команда",
|
||||
"cli_table_version": "Вызываемая версия",
|
||||
"cli_table_path": "Путь к файлу"
|
||||
},
|
||||
"server": {
|
||||
"nginx": {
|
||||
"title": "Nginx",
|
||||
"config": "Настройки Nginx",
|
||||
"config_title": "Конфигурация Nginx (nginx.conf)",
|
||||
"config_warning": "Внимание: Неправильная конфигурация может остановить работу Nginx. Протестируйте перед сохранением.",
|
||||
"test_config": "Проверить конфигурацию",
|
||||
"save_reload": "Сохранить и перезагрузить",
|
||||
"config_saved": "Конфигурация Nginx успешно сохранена.",
|
||||
"test_failed": "Ошибка конфигурации"
|
||||
},
|
||||
"apache": {
|
||||
"title": "Apache",
|
||||
"config": "Настройки Apache",
|
||||
"config_title": "Конфигурация Apache (httpd.conf)",
|
||||
"config_desc": "Этот файл является основным (глобальным) конфигурационным файлом сервера Apache.",
|
||||
"test_config": "Проверить конфигурацию",
|
||||
"save_reload": "Сохранить и перезагрузить",
|
||||
"config_saved": "Конфигурация Apache сохранена."
|
||||
},
|
||||
"project_nginx": {
|
||||
"title": "Конфигурация Nginx для {{host}}",
|
||||
"tip": "Совет: Эта конфигурация применима только к проекту {{host}}.",
|
||||
"error_line": "Строка ошибки: {{line}}"
|
||||
}
|
||||
},
|
||||
"pma": {
|
||||
"ready_desc": "phpMyAdmin готов к управлению базами данных.",
|
||||
"install_desc": "Установите phpMyAdmin для управления базами данных через веб-интерфейс.",
|
||||
"installing": "УСТАНОВКА...",
|
||||
"install_button": "НАЧАТЬ УСТАНОВКУ",
|
||||
"open": "ОТКРЫТЬ",
|
||||
"progress": "Загрузка... %{{progress}}"
|
||||
},
|
||||
"mariadb": {
|
||||
"import": {
|
||||
"title": "Импорт данных MariaDB",
|
||||
"desc": "Быстро загрузите выбранный .sql файл или архив в базу данных.",
|
||||
"button": "ИМПОРТ",
|
||||
"wizard_title": "Мастер быстрого дампа/импорта MariaDB",
|
||||
"step1": "Выбор данных",
|
||||
"step2": "Выбор сервера",
|
||||
"step3": "Конфигурация базы данных",
|
||||
"step4": "Итог и выполнение",
|
||||
"step1_desc": "Пожалуйста, выберите файл .sql или архив (.zip, .tar.gz) для загрузки.",
|
||||
"step2_desc": "Выберите сервер MariaDB, на который будет загружен файл.",
|
||||
"step3_desc": "Настройте параметры базы данных и пользователя.",
|
||||
"no_file": "Файл не выбран...",
|
||||
"root_pass": "Пароль Root (если есть)",
|
||||
"root_pass_helper": "Введите текущий пароль пользователя 'root' в MariaDB. Оставьте пустым, если пароля нет.",
|
||||
"db_name": "Имя базы данных",
|
||||
"db_user": "Пользователь БД",
|
||||
"db_pass": "Пароль пользователя",
|
||||
"summary": "Итоговая информация",
|
||||
"file": "Файл",
|
||||
"server": "Сервер",
|
||||
"db": "База данных",
|
||||
"user": "Пользователь",
|
||||
"success_title": "Успешно!",
|
||||
"error_title": "Произошла ошибка!",
|
||||
"access_info": "Информация для доступа",
|
||||
"host": "Хост",
|
||||
"starting": "[Система] Процесс запущен...",
|
||||
"overwrite_title": "База данных уже существует!",
|
||||
"overwrite_desc": "База данных '{{dbName}}' уже существует. Хотите перезаписать её? Все текущие данные будут удалены!",
|
||||
"btn_summary": "ПОСМОТРЕТЬ ИТОГ",
|
||||
"btn_start": "НАЧАТЬ ИМПОРТ"
|
||||
},
|
||||
"export": {
|
||||
"title": "Экспорт данных MariaDB",
|
||||
"desc": "Безопасно создавайте резервные копии баз данных в форматах .sql или .sql.gz.",
|
||||
"button": "ЭКСПОРТ",
|
||||
"wizard_title": "Мастер экспорта базы данных MariaDB",
|
||||
"step1": "Выбор сервера",
|
||||
"step2": "Выбор базы данных",
|
||||
"step3": "Настройки экспорта",
|
||||
"step4": "Итог и выполнение",
|
||||
"step1_desc": "Выберите сервер MariaDB, на котором находится база данных.",
|
||||
"step2_desc": "Выберите базу данных для экспорта.",
|
||||
"step3_desc": "Укажите место сохранения и формат файла.",
|
||||
"placeholder": "Файл для сохранения...",
|
||||
"compress": "Сжать с помощью Gzip (.sql.gz)",
|
||||
"target": "Цель",
|
||||
"compression": "Сжатие",
|
||||
"on": "Включено (.gz)",
|
||||
"off": "Выключено (.sql)",
|
||||
"btn_show_file": "ПОКАЗАТЬ ФАЙЛ",
|
||||
"btn_start": "НАЧАТЬ ЭКСПОРТ",
|
||||
"starting": "[Система] Процесс экспорта запущен...",
|
||||
"no_db_found": "На выбранном сервере не найдено доступных баз данных.",
|
||||
"list_error": "Не удалось получить список баз данных: "
|
||||
},
|
||||
"wizard": {
|
||||
"import_title": "Мастер импорта данных MariaDB",
|
||||
"export_title": "Мастер экспорта данных MariaDB",
|
||||
"select_version": "Выберите версию MariaDB",
|
||||
"select_db": "Выберите базу данных",
|
||||
"select_file": "Выберите файл",
|
||||
"import_success": "Данные успешно импортированы.",
|
||||
"export_success": "Данные успешно экспортированы."
|
||||
}
|
||||
},
|
||||
"diagnostics": {
|
||||
"logs": "Логи ошибок",
|
||||
"noLogs": "Записей в логах пока нет."
|
||||
},
|
||||
"php": {
|
||||
"extensions": {
|
||||
"title": "Расширения PHP {{version}}",
|
||||
"desc": "Управляйте расширениями через php.ini",
|
||||
"search_placeholder": "Поиск расширения... (mysql, gd, mbstring...)",
|
||||
"search_file_placeholder": "Поиск в файле...",
|
||||
"raw_editor": "RAW РЕДАКТОР",
|
||||
"none": "Расширения отсутствуют.",
|
||||
"not_found": "Расширение не найдено.",
|
||||
"active": "Активно",
|
||||
"ini_edit": "Редактировать php.ini ({{version}})",
|
||||
"file_open_tip": "Открыть файл в системе",
|
||||
"saving": "Сохранение конфигурации",
|
||||
"restarting": "Перезапуск сервиса PHP...",
|
||||
"adjusting": "Настройка расширения",
|
||||
"adjusting_desc": "{{extName}}: режим {{mode}}, выполняется перезапуск PHP...",
|
||||
"save_restart_btn": "СОХРАНИТЬ И ПЕРЕЗАПУСТИТЬ",
|
||||
"saving_btn": "СОХРАНЕНИЕ...",
|
||||
"save_error": "Ошибка при сохранении расширений.",
|
||||
"success_msg": "Конфигурация сохранена, сервис перезапущен.",
|
||||
"prev_match": "Пред. (Shift+Enter)",
|
||||
"next_match": "След. (Enter)"
|
||||
}
|
||||
},
|
||||
"mariadb_process_monitor": {
|
||||
"title": "Список процессов БД",
|
||||
"auto_refresh_desc": "Список процессов обновляется автоматически каждые 3 секунды.",
|
||||
"kill_btn": "KILL",
|
||||
"kill_confirm": "Вы уверены, что хотите завершить этот процесс?",
|
||||
"refresh_btn": "Обновить",
|
||||
"click_to_view_sql": "Нажмите, чтобы просмотреть SQL-запрос",
|
||||
"query_details": "Детали запроса",
|
||||
"no_processes": "Активных процессов не найдено.",
|
||||
"columns": {
|
||||
"id": "ID",
|
||||
"user": "Пользователь",
|
||||
"host": "Хост",
|
||||
"db": "База данных",
|
||||
"command": "Команда",
|
||||
"time": "Время",
|
||||
"state": "Статус",
|
||||
"info": "Информация",
|
||||
"progress": "Прогресс"
|
||||
}
|
||||
},
|
||||
"tuning": {
|
||||
"title": "Оптимизация",
|
||||
"desc": "Оптимизируйте производительность PHP и MariaDB с помощью критических лимитов ресурсов.",
|
||||
"php_total": "Экземпляр PHP",
|
||||
"mariadb_total": "Экземпляр MariaDB",
|
||||
"tune_btn": "НАСТРОИТЬ",
|
||||
"saving": "Применение изменений...",
|
||||
"restart_notice": "Для вступления в силу некоторых изменений требуется перезапуск сервисов.",
|
||||
"parameters": {
|
||||
"memory_limit": "Лимит памяти",
|
||||
"memory_limit_desc": "Максимальный объем памяти, который может использовать скрипт.",
|
||||
"max_execution_time": "Макс. время выполнения",
|
||||
"max_execution_time_desc": "Максимальное время работы скрипта в секундах.",
|
||||
"post_max_size": "Макс. размер POST",
|
||||
"post_max_size_desc": "Максимальный объем данных POST, принимаемый PHP.",
|
||||
"upload_max_filesize": "Лимит загрузки файлов",
|
||||
"upload_max_filesize_desc": "Максимальный размер загружаемого файла.",
|
||||
"max_input_vars": "Макс. входных переменных",
|
||||
"max_input_vars_desc": "Количество входных переменных (GET/POST/Cookie), которые могут быть приняты.",
|
||||
"max_connections": "Макс. соединений",
|
||||
"max_connections_desc": "Максимальное количество одновременных клиентских подключений.",
|
||||
"innodb_buffer_pool_size": "Буферный пул InnoDB",
|
||||
"innodb_buffer_pool_size_desc": "Критично для производительности. Хранит индексы и данные в памяти.",
|
||||
"key_buffer_size": "Размер буфера ключей",
|
||||
"key_buffer_size_desc": "Индексные блоки для таблиц MyISAM (общие для всех потоков).",
|
||||
"max_allowed_packet": "Макс. размер пакета",
|
||||
"max_allowed_packet_desc": "Максимальный размер одного SQL-запроса или результата."
|
||||
}
|
||||
},
|
||||
"service_monitor": {
|
||||
"title": "Логи сервисов",
|
||||
"desc": "Отслеживайте историю запуска, остановки и ошибок сервисов.",
|
||||
"event_log": "Журнал событий",
|
||||
"clear_confirm": "Вы уверены, что хотите очистить всю историю событий?",
|
||||
"chart_title": "График активности сервисов",
|
||||
"no_events": "Событий пока не зарегистрировано.",
|
||||
"columns": {
|
||||
"service": "Сервис",
|
||||
"action": "Действие",
|
||||
"status": "Статус",
|
||||
"timestamp": "Время",
|
||||
"details": "Детали"
|
||||
}
|
||||
},
|
||||
"mariadb_manager": {
|
||||
"title": "Управление БД",
|
||||
"databases_title": "Базы данных",
|
||||
"users_title": "Пользователи",
|
||||
"create_db_btn": "Новая база данных",
|
||||
"create_db_title": "Создать новую базу данных",
|
||||
"db_name_label": "Имя базы данных",
|
||||
"db_name": "База данных",
|
||||
"db_size": "Размер",
|
||||
"create_user_btn": "Новый пользователь",
|
||||
"create_user_title": "Создать нового пользователя",
|
||||
"user_label": "Имя пользователя",
|
||||
"password_label": "Пароль",
|
||||
"delete_db_confirm": "Вы уверены, что хотите удалить базу данных '{{db}}'? Это действие необратимо!",
|
||||
"delete_user_confirm": "Вы уверены, что хотите удалить пользователя '{{user}}'?",
|
||||
"no_active_version": "Пожалуйста, сначала выберите установленную версию MariaDB или скачайте её."
|
||||
}
|
||||
}
|
||||
@@ -104,6 +104,75 @@ const styles = {
|
||||
padding: '10px !important',
|
||||
borderRadius: '5px !important',
|
||||
border: '1px solid rgba(255,255,255,0.1) !important'
|
||||
},
|
||||
// Service List Alert Classes
|
||||
'.swal-service-list': {
|
||||
textAlign: 'left',
|
||||
fontFamily: "'Inter', sans-serif",
|
||||
paddingTop: '10px'
|
||||
},
|
||||
'.swal-service-item': {
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: '6px',
|
||||
padding: '8px 14px',
|
||||
background: 'rgba(0,0,0,0.2)',
|
||||
border: '1px solid rgba(255,255,255,0.03)',
|
||||
borderRadius: '8px',
|
||||
fontSize: '0.8rem'
|
||||
},
|
||||
'.swal-service-label': {
|
||||
fontWeight: 600,
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
},
|
||||
'.swal-status-icon': {
|
||||
marginRight: '12px',
|
||||
fontSize: '0.8rem',
|
||||
color: 'rgba(255,255,255,0.1)'
|
||||
},
|
||||
'.swal-status-icon.success': {
|
||||
color: '#33d9b2'
|
||||
},
|
||||
'.swal-status-icon.error': {
|
||||
color: '#ff5252'
|
||||
},
|
||||
'.swal-status-icon.loading': {
|
||||
color: '#39A7FF'
|
||||
},
|
||||
'.swal-status-note': {
|
||||
fontSize: '0.65rem',
|
||||
fontWeight: 800,
|
||||
letterSpacing: '0.5px',
|
||||
textTransform: 'uppercase',
|
||||
color: 'rgba(255,255,255,0.4)'
|
||||
},
|
||||
'.swal-status-note.success': {
|
||||
color: '#33d9b2'
|
||||
},
|
||||
'.swal-status-note.error': {
|
||||
color: '#ff5252'
|
||||
},
|
||||
'.swal-status-note.loading': {
|
||||
color: '#39A7FF'
|
||||
},
|
||||
// Global Dialog Styling (for MUI PaperProps removal)
|
||||
'.mui-custom-dialog-paper': {
|
||||
background: '#1a1d21 !important',
|
||||
backgroundImage: 'none !important',
|
||||
color: '#fff !important',
|
||||
borderRadius: '16px !important',
|
||||
border: '1px solid rgba(255,255,255,0.1) !important',
|
||||
boxShadow: '0 24px 48px rgba(0,0,0,0.5) !important'
|
||||
},
|
||||
'.swal-error-footer': {
|
||||
marginTop: '15px !important',
|
||||
textAlign: 'center !important'
|
||||
},
|
||||
'.swal-error-line': {
|
||||
fontSize: '0.9rem !important',
|
||||
color: '#ffb142 !important'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user