diff --git a/app/Livewire/Ui/System/Modal/UpdateModal.php b/app/Livewire/Ui/System/Modal/UpdateModal.php new file mode 100644 index 0000000..5c2fc21 --- /dev/null +++ b/app/Livewire/Ui/System/Modal/UpdateModal.php @@ -0,0 +1,77 @@ +refresh(); + } + + public function render() + { + return view('livewire.ui.system.modal.update-modal'); + } + + #[On('update:modal-refresh')] + public function refresh(): void + { + $st = @trim(@file_get_contents(self::STATE_DIR.'/state') ?: ''); + $rcRaw = @trim(@file_get_contents(self::STATE_DIR.'/rc') ?: ''); + + $this->state = $st ?: 'unknown'; + $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; + + // Log einlesen + $lines = @file(self::LOG, FILE_IGNORE_NEW_LINES) ?: []; + $this->tail = array_slice($lines, -30); + + $last = trim($this->tail ? end($this->tail) : ''); + $last = preg_replace('/^\[\w\]\s*/', '', $last); + $last = preg_replace('/^=+ .*? =+\s*$/', 'Update beendet', $last); + $last = preg_replace('/^\d{4}-\d{2}-\d{2}T[^ ]+\s*::\s*/', '', $last); + $this->line = Str::limit($last, 160); + + // ganz simple Fortschritts-Heuristik über bekannte Meilensteine + $text = implode("\n", $this->tail); + $pct = 5; + foreach ([ + 'Update gestartet' => 10, + 'Composer' => 25, + 'npm ci' => 40, + 'npm run build' => 60, + 'migrate' => 75, + 'optimize' => 85, + 'Version aktualisiert' => 95, + 'Update beendet' => 100, + ] as $needle => $val) { + if (stripos($text, $needle) !== false) { $pct = max($pct, $val); } + } + if ($this->state === 'done') { $pct = 100; } + $this->percent = $pct; + + // Auto-Close vorbereiten + if ($this->state === 'done' && $this->rc === 0) { + static::$closingAllowed = true; + } + } + + public static function modalMaxWidth(): string { return '2xl'; } + public static function closeModalOnEscape(): bool { return static::$closingAllowed; } + public static function closeModalOnClickAway(): bool { return static::$closingAllowed; } +} diff --git a/app/Livewire/Ui/System/UpdateCard.php b/app/Livewire/Ui/System/UpdateCard.php index 929a602..2a91b25 100644 --- a/app/Livewire/Ui/System/UpdateCard.php +++ b/app/Livewire/Ui/System/UpdateCard.php @@ -52,6 +52,7 @@ class UpdateCard extends Component if ($this->running) { $this->state = 'running'; + $this->dispatch('openModal', component: 'ui.system.update-modal'); } $this->recomputeUi(); @@ -69,7 +70,7 @@ class UpdateCard extends Component // evtl. alte Einträge aufräumen Cache::forget('mailwolt.update_available'); Cache::put($this->cacheStartedAtKey, time(), now()->addHour()); - + $this->dispatch('openModal', component: 'ui.system.update-modal'); // Wrapper starten (setzt /var/lib/mailwolt/update/{state,rc} und schreibt Versionen) @shell_exec('nohup sudo -n /usr/local/sbin/mailwolt-update >/dev/null 2>&1 &'); @@ -105,10 +106,15 @@ class UpdateCard extends Component if (!$this->running) { Cache::forget($this->cacheStartedAtKey); + usleep(500_000); // Nachlauf: Versionen & Vergleich neu aufbauen $this->reloadVersionsAndStatus(); $this->recompute(); + if ($this->current && $this->latest && version_compare($this->current, $this->latest, '>=')) { + $this->hasUpdate = false; + } + if ($this->rc === 0 && !$this->postActionsDone) { // Dienste neu starten (asynchron) // @shell_exec('nohup php /var/www/mailwolt/artisan mailwolt:restart-services >/dev/null 2>&1 &'); @@ -126,6 +132,9 @@ class UpdateCard extends Component badge: 'System', duration: 4000 ); + + $this->dispatch('reload-page', delay: 5000); + } elseif ($this->rc !== null && $this->rc !== 0 && !$this->postActionsDone) { // Fehlerfall $this->postActionsDone = true; diff --git a/resources/views/livewire/ui/system/modal/update-modal.blade.php b/resources/views/livewire/ui/system/modal/update-modal.blade.php new file mode 100644 index 0000000..046d754 --- /dev/null +++ b/resources/views/livewire/ui/system/modal/update-modal.blade.php @@ -0,0 +1,52 @@ +
+
+
+ +
+
+
+ {{ $state==='done' + ? ($rc===0 ? 'Update abgeschlossen' : 'Update fehlgeschlagen') + : 'Update läuft …' }} +
+
+ {{ $line ?? '–' }} +
+
+
+ + {{-- Progress --}} +
+
+
+
+
{{ $percent }}%
+
+ + {{-- Log Tail --}} +
+ @foreach($tail as $l) + {{ $l }} + @endforeach +
+ +
+ @if($state==='done' && $rc===0) + + @elseif($state==='done' && $rc!==0) + + @else + + @endif +
+
diff --git a/resources/views/livewire/ui/system/storage-card.blade.php b/resources/views/livewire/ui/system/storage-card.blade.php index 5721bc3..4fd53f5 100644 --- a/resources/views/livewire/ui/system/storage-card.blade.php +++ b/resources/views/livewire/ui/system/storage-card.blade.php @@ -50,21 +50,12 @@ {{-- Stacked-Bar (horizontale Leiste) --}} @if(!empty($barSegments))
-{{--
--}} -{{--
--}} -{{-- @foreach($barSegments as $b)--}} -{{--
--}} -{{-- @endforeach--}} -{{--
--}} -{{--
--}} - {{-- Legende --}}
@foreach($barSegments as $b)
{{ $b['label'] }} {{ $b['human'] }} ({{ $b['percent'] }}%) -{{-- {{ $b['label'] }} {{ $b['gb'] }} GB ({{ $b['percent'] }}%)--}}
@endforeach
diff --git a/routes/console.php b/routes/console.php index 6548088..d0f1471 100644 --- a/routes/console.php +++ b/routes/console.php @@ -11,7 +11,6 @@ Artisan::command('inspire', function () { Schedule::job(RunHealthChecks::class)->everyMinute()->withoutOverlapping(); Schedule::command('spamav:collect')->everyFiveMinutes()->withoutOverlapping(); -//Schedule::command('woltguard:collect-services')->everyMinute(); //Schedule::command('mailwolt:check-updates')->dailyAt('04:10'); Schedule::command('mailwolt:check-updates')->everytwoMinutes();