Feat: Einstellungs-Tabs auf Deutsch (sicherung/meldungen) + Sidebars für alle Tabs

main v1.1.412
boban 2026-04-27 03:40:40 +02:00
parent ff6002ca0b
commit eb77ec3342
2 changed files with 91 additions and 13 deletions

View File

@ -17,6 +17,8 @@ class SettingsForm extends Component
#[Url] #[Url]
public string $tab = 'allgemein'; public string $tab = 'allgemein';
private const VALID_TABS = ['allgemein', 'domains', 'sicherung', 'meldungen'];
// Allgemein // Allgemein
public string $instance_name = ''; public string $instance_name = '';
public string $locale = 'de'; public string $locale = 'de';
@ -498,7 +500,12 @@ class SettingsForm extends Component
public function render() public function render()
{ {
$timezones = \DateTimeZone::listIdentifiers(\DateTimeZone::ALL); if (!in_array($this->tab, self::VALID_TABS, true)) {
return view('livewire.ui.system.settings-form', compact('timezones')); $this->tab = 'allgemein';
}
$timezones = \DateTimeZone::listIdentifiers(\DateTimeZone::ALL);
$backupMeta = BackupPolicy::first();
return view('livewire.ui.system.settings-form', compact('timezones', 'backupMeta'));
} }
} }

View File

@ -13,7 +13,7 @@
</div> </div>
<div class="mbx-page-actions"> <div class="mbx-page-actions">
@if($tab === 'domains') @if($tab === 'domains')
<button wire:click="saveDomains" class="mbx-btn-primary"> <button wire:click="saveDomains" wire:loading.attr="disabled" wire:target="saveDomains" class="mbx-btn-primary">
<svg width="12" height="12" viewBox="0 0 14 14" fill="none"><path d="M2 2h8l2 2v8a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1Z" stroke="currentColor" stroke-width="1.2"/><path d="M5 2v3h4V2" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg> <svg width="12" height="12" viewBox="0 0 14 14" fill="none"><path d="M2 2h8l2 2v8a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1Z" stroke="currentColor" stroke-width="1.2"/><path d="M5 2v3h4V2" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>
<span wire:loading.remove wire:target="saveDomains">Domains speichern</span> <span wire:loading.remove wire:target="saveDomains">Domains speichern</span>
<span wire:loading wire:target="saveDomains">Speichert…</span> <span wire:loading wire:target="saveDomains">Speichert…</span>
@ -32,10 +32,10 @@
<div style="display:flex;gap:2px;border-bottom:1px solid var(--mw-b2);margin-bottom:20px"> <div style="display:flex;gap:2px;border-bottom:1px solid var(--mw-b2);margin-bottom:20px">
@php @php
$tabs = [ $tabs = [
'allgemein' => ['label' => 'Allgemein', 'icon' => '<circle cx="8" cy="8" r="2.2" stroke="currentColor" stroke-width="1.3"/><path d="M8 1.5v1.3M8 13.2v1.3M1.5 8h1.3M13.2 8h1.3M3.2 3.2l.9.9M11.9 11.9l.9.9M3.2 12.8l.9-.9M11.9 4.1l.9-.9" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>'], 'allgemein' => ['label' => 'Allgemein', 'icon' => '<circle cx="8" cy="8" r="2.2" stroke="currentColor" stroke-width="1.3"/><path d="M8 1.5v1.3M8 13.2v1.3M1.5 8h1.3M13.2 8h1.3M3.2 3.2l.9.9M11.9 11.9l.9.9M3.2 12.8l.9-.9M11.9 4.1l.9-.9" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>'],
'domains' => ['label' => 'Domains & SSL', 'icon' => '<circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.3"/><path d="M8 2C6 4.5 5 6.2 5 8s1 3.5 3 6M8 2c2 2.5 3 4.2 3 6s-1 3.5-3 6M2 8h12" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>'], 'domains' => ['label' => 'Domains & SSL','icon' => '<circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.3"/><path d="M8 2C6 4.5 5 6.2 5 8s1 3.5 3 6M8 2c2 2.5 3 4.2 3 6s-1 3.5-3 6M2 8h12" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>'],
'backup' => ['label' => 'Backup', 'icon' => '<ellipse cx="8" cy="4" rx="5" ry="2" stroke="currentColor" stroke-width="1.3"/><path d="M3 4v4c0 1.1 2.24 2 5 2s5-.9 5-2V4" stroke="currentColor" stroke-width="1.3"/><path d="M3 8v4c0 1.1 2.24 2 5 2s5-.9 5-2V8" stroke="currentColor" stroke-width="1.3"/>'], 'sicherung' => ['label' => 'Sicherung', 'icon' => '<ellipse cx="8" cy="4" rx="5" ry="2" stroke="currentColor" stroke-width="1.3"/><path d="M3 4v4c0 1.1 2.24 2 5 2s5-.9 5-2V4" stroke="currentColor" stroke-width="1.3"/><path d="M3 8v4c0 1.1 2.24 2 5 2s5-.9 5-2V8" stroke="currentColor" stroke-width="1.3"/>'],
'benachrichtigungen' => ['label' => 'Benachrichtigungen', 'icon' => '<path d="M8 14a1.5 1.5 0 0 0 3 0M8 2a4 4 0 0 1 4 4v3l1 1H3l1-1V6a4 4 0 0 1 4-4Z" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/>'], 'meldungen' => ['label' => 'Meldungen', 'icon' => '<path d="M8 14a1.5 1.5 0 0 0 3 0M8 2a4 4 0 0 1 4 4v3l1 1H3l1-1V6a4 4 0 0 1 4-4Z" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/>'],
]; ];
@endphp @endphp
@foreach($tabs as $key => $cfg) @foreach($tabs as $key => $cfg)
@ -227,9 +227,10 @@
</div> </div>
@endif @endif
{{-- ═══ Tab: Backup ═══ --}} {{-- ═══ Tab: Sicherung ═══ --}}
@if($tab === 'backup') @if($tab === 'sicherung')
<div class="mbx-sections" style="max-width:680px"> <div class="sec-layout">
<div style="min-width:0"><div class="mbx-sections">
<div class="mbx-section" id="backup"> <div class="mbx-section" id="backup">
<div class="mbx-domain-head"> <div class="mbx-domain-head">
<div class="mbx-domain-info"><span class="mbx-badge-mute">Backup-Zeitplan</span></div> <div class="mbx-domain-info"><span class="mbx-badge-mute">Backup-Zeitplan</span></div>
@ -354,12 +355,56 @@
</div> </div>
</div> </div>
</div></div>
{{-- Sidebar: Sicherung --}}
<div><div class="mbx-sections">
<div class="mbx-section">
<div class="mbx-domain-head">
<div class="mbx-domain-info"><span class="mbx-badge-mute">Letztes Backup</span></div>
</div>
<div style="padding:12px 14px;display:flex;flex-direction:column;gap:8px;font-size:11.5px">
@if($backupMeta && $backupMeta->last_run_at)
@php
$statusColor = $backupMeta->last_status === 'ok' ? '#22c55e' : '#f87171';
$statusLabel = $backupMeta->last_status === 'ok' ? 'Erfolgreich' : 'Fehler';
$sizeKb = $backupMeta->last_size_bytes ? round($backupMeta->last_size_bytes / 1024) : null;
@endphp
<div style="display:flex;justify-content:space-between">
<span style="color:var(--mw-t4)">Status</span>
<span style="color:{{ $statusColor }}">{{ $statusLabel }}</span>
</div>
<div style="display:flex;justify-content:space-between">
<span style="color:var(--mw-t4)">Zuletzt</span>
<span style="color:var(--mw-t2)">{{ \Carbon\Carbon::parse($backupMeta->last_run_at)->format('d.m.Y H:i') }}</span>
</div>
@if($sizeKb)
<div style="display:flex;justify-content:space-between">
<span style="color:var(--mw-t4)">Größe</span>
<span style="color:var(--mw-t2)">{{ $sizeKb < 1024 ? $sizeKb.' KB' : round($sizeKb/1024,1).' MB' }}</span>
</div>
@endif
<div style="display:flex;justify-content:space-between">
<span style="color:var(--mw-t4)">Aufbewahrung</span>
<span style="color:var(--mw-t2)">{{ $backupMeta->retention_count }} Stück</span>
</div>
@else
<span style="color:var(--mw-t4)">Noch kein Backup ausgeführt.</span>
@endif
<a href="{{ route('ui.system.backups') }}" style="display:flex;align-items:center;gap:5px;font-size:11px;color:var(--mw-v);padding:4px 0;text-decoration:none;margin-top:2px">
<svg width="10" height="10" viewBox="0 0 14 14" fill="none"><ellipse cx="7" cy="3.5" rx="5" ry="2" stroke="currentColor" stroke-width="1.3"/><path d="M2 3.5v7c0 1.1 2.24 2 5 2s5-.9 5-2v-7" stroke="currentColor" stroke-width="1.3"/></svg>
Backup-Verlauf
</a>
</div>
</div>
</div></div>
</div> </div>
@endif @endif
{{-- ═══ Tab: Benachrichtigungen ═══ --}} {{-- ═══ Tab: Meldungen ═══ --}}
@if($tab === 'benachrichtigungen') @if($tab === 'meldungen')
<div class="mbx-sections" style="max-width:680px"> <div class="sec-layout">
<div style="min-width:0"><div class="mbx-sections">
<div class="mbx-section"> <div class="mbx-section">
<div class="mbx-domain-head"> <div class="mbx-domain-head">
<div class="mbx-domain-info"><span class="mbx-badge-mute">Benachrichtigungen</span></div> <div class="mbx-domain-info"><span class="mbx-badge-mute">Benachrichtigungen</span></div>
@ -388,6 +433,32 @@
</div> </div>
</div> </div>
</div> </div>
</div></div>
{{-- Sidebar: Meldungen --}}
<div><div class="mbx-sections">
<div class="mbx-section">
<div class="mbx-domain-head">
<div class="mbx-domain-info"><span class="mbx-badge-mute">Meldungstypen</span></div>
</div>
<div style="padding:12px 14px;display:flex;flex-direction:column;gap:6px;font-size:11.5px">
@foreach([
['Update verfügbar', 'Neue App-Version erkannt'],
['Update abgeschlossen', 'Nach erfolgreichem Update'],
['Backup-Fehler', 'Wenn ein Backup fehlschlägt'],
['SSL läuft ab', 'Zertifikat < 14 Tage gültig'],
] as [$title, $desc])
<div style="display:flex;align-items:flex-start;gap:8px;padding:7px 10px;border-radius:6px;background:var(--mw-bg3);border:1px solid var(--mw-b2)">
<svg width="10" height="10" viewBox="0 0 14 14" fill="none" style="flex-shrink:0;margin-top:2px;color:var(--mw-v)"><circle cx="7" cy="7" r="5.5" stroke="currentColor" stroke-width="1.3"/><path d="M7 4.5v3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/><circle cx="7" cy="9.5" r=".6" fill="currentColor"/></svg>
<div>
<div style="color:var(--mw-t2);font-weight:500">{{ $title }}</div>
<div style="color:var(--mw-t4);font-size:11px;margin-top:1px">{{ $desc }}</div>
</div>
</div>
@endforeach
</div>
</div>
</div></div>
</div> </div>
@endif @endif