parent
529979f078
commit
65b3259048
|
|
@ -1,38 +1,46 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
namespace App\Livewire\Ui\System;
|
namespace App\Livewire\Ui\System;
|
||||||
|
|
||||||
use Livewire\Component;
|
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
class UpdateCard extends Component
|
class UpdateCard extends Component
|
||||||
{
|
{
|
||||||
public ?string $current = null; // installierte Version
|
public ?string $current = null; // installed (pretty)
|
||||||
public ?string $latest = null; // verfügbare Version (oder null)
|
public ?string $latest = null; // available (pretty or null)
|
||||||
public string $state = 'idle'; // idle | running
|
public string $state = 'idle'; // idle|running
|
||||||
|
|
||||||
// UI-Textausgabe nach einer Prüfung / Aktion
|
public ?string $message = null; // inline message
|
||||||
public ?string $message = null; // z.B. "Du bist auf dem neuesten Stand (v1.0.16)"
|
public ?bool $messagePositive = null;
|
||||||
public ?bool $messagePositive = null; // true = grün, false = neutral/weiß
|
|
||||||
|
|
||||||
// low-level (falls du sie später brauchst)
|
// low-level
|
||||||
public bool $running = false; // aus /var/lib/mailwolt/update/state
|
public bool $running = false;
|
||||||
public ?int $rc = null;
|
public ?int $rc = null;
|
||||||
|
|
||||||
|
// ---- lifecycle ---------------------------------------------------------
|
||||||
|
|
||||||
public function mount(): void
|
public function mount(): void
|
||||||
{
|
{
|
||||||
|
$this->readLowLevel();
|
||||||
$this->current = $this->readCurrentVersion();
|
$this->current = $this->readCurrentVersion();
|
||||||
$this->latest = Cache::get('mailwolt.update_available');
|
$this->latest = $this->readCachedLatest();
|
||||||
$this->refreshLowLevelState();
|
|
||||||
|
|
||||||
// Starttext, falls nichts geprüft wurde
|
|
||||||
if ($this->message === null) {
|
if ($this->message === null) {
|
||||||
$this->message = $this->latest && $this->hasUpdate()
|
if ($this->hasUpdate()) {
|
||||||
? "Neue Version verfügbar: {$this->latest}"
|
$this->message = "Neue Version verfügbar: {$this->latest}";
|
||||||
: ($this->current ? "Du bist auf dem neuesten Stand ({$this->current})" : "Status unbekannt");
|
$this->messagePositive = false;
|
||||||
$this->messagePositive = !$this->hasUpdate();
|
} else {
|
||||||
|
$cur = $this->current ?? '–';
|
||||||
|
$this->message = "Du bist auf dem neuesten Stand ({$cur})";
|
||||||
|
$this->messagePositive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if wrapper is already running when page loads, reflect that
|
||||||
|
if ($this->running) {
|
||||||
|
$this->state = 'running';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,12 +49,9 @@ class UpdateCard extends Component
|
||||||
return view('livewire.ui.system.update-card');
|
return view('livewire.ui.system.update-card');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ---- UI actions --------------------------------------------------------
|
||||||
* „Erneut prüfen“ – ohne Toast:
|
|
||||||
* - Progress anzeigen
|
/** Button: „Erneut prüfen“ (no toast; shows inline progress) */
|
||||||
* - Check-Command laufen lassen
|
|
||||||
* - Message in der Box aktualisieren
|
|
||||||
*/
|
|
||||||
public function refreshState(): void
|
public function refreshState(): void
|
||||||
{
|
{
|
||||||
$this->state = 'running';
|
$this->state = 'running';
|
||||||
|
|
@ -54,41 +59,37 @@ class UpdateCard extends Component
|
||||||
$this->messagePositive = null;
|
$this->messagePositive = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Passe den Namen hier an dein tatsächliches Command an:
|
// your checker should update the cache key below
|
||||||
Artisan::call('mailwolt:check-updates');
|
Artisan::call('mailwolt:check-updates');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
// weich fallen
|
// swallow but still continue to show something meaningful
|
||||||
}
|
}
|
||||||
|
|
||||||
// Daten neu einlesen
|
|
||||||
$this->current = $this->readCurrentVersion();
|
$this->current = $this->readCurrentVersion();
|
||||||
$this->latest = Cache::get('mailwolt.update_available');
|
$this->latest = $this->readCachedLatest();
|
||||||
|
$this->readLowLevel();
|
||||||
|
|
||||||
if ($this->hasUpdate()) {
|
if ($this->hasUpdate()) {
|
||||||
$this->message = "Neue Version verfügbar: {$this->latest}";
|
$this->message = "Neue Version verfügbar: {$this->latest}";
|
||||||
$this->messagePositive = false; // neutral
|
$this->messagePositive = false;
|
||||||
} else {
|
} else {
|
||||||
$cur = $this->current ?: '–';
|
$this->message = "Du bist auf dem neuesten Stand ($this->current ?? '–')";
|
||||||
$this->message = "Du bist auf dem neuesten Stand ({$cur})";
|
$this->messagePositive = true;
|
||||||
$this->messagePositive = true; // grün
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->refreshLowLevelState();
|
|
||||||
$this->state = 'idle';
|
$this->state = 'idle';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Button: „Jetzt aktualisieren“ (no toast; start wrapper + progress) */
|
||||||
* „Jetzt aktualisieren“ – ohne Toast:
|
|
||||||
* - Hinweis sofort aus Cache entfernen (Badge weg)
|
|
||||||
* - Update-Wrapper starten
|
|
||||||
* - Running + Text in der Box anzeigen
|
|
||||||
*/
|
|
||||||
public function runUpdate(): void
|
public function runUpdate(): void
|
||||||
{
|
{
|
||||||
|
// Hide the yellow badges immediately
|
||||||
Cache::forget('mailwolt.update_available');
|
Cache::forget('mailwolt.update_available');
|
||||||
|
|
||||||
|
// spawn wrapper in the background
|
||||||
@shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &');
|
@shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &');
|
||||||
|
|
||||||
|
// reflect “running” in UI
|
||||||
$this->latest = null;
|
$this->latest = null;
|
||||||
$this->state = 'running';
|
$this->state = 'running';
|
||||||
$this->running = true;
|
$this->running = true;
|
||||||
|
|
@ -96,16 +97,65 @@ class UpdateCard extends Component
|
||||||
$this->messagePositive = null;
|
$this->messagePositive = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** --------------------- helpers --------------------- */
|
/**
|
||||||
|
* Called from the blade with `wire:poll.1200ms="tick"` – but **only**
|
||||||
|
* when $state === 'running'. This finishes the UX once the wrapper ends.
|
||||||
|
*/
|
||||||
|
public function tick(): void
|
||||||
|
{
|
||||||
|
if ($this->state !== 'running') return;
|
||||||
|
|
||||||
|
$this->readLowLevel();
|
||||||
|
|
||||||
|
if (!$this->running) { // wrapper finished
|
||||||
|
// give build.info a split second to land on slow disks
|
||||||
|
usleep(150000);
|
||||||
|
|
||||||
|
$this->current = $this->readCurrentVersion();
|
||||||
|
$this->latest = $this->readCachedLatest();
|
||||||
|
|
||||||
|
if ($this->rc === 0) {
|
||||||
|
// success path
|
||||||
|
if ($this->hasUpdate()) {
|
||||||
|
// very unlikely right after success, but handle anyway
|
||||||
|
$this->message = "Neue Version verfügbar: {$this->latest}";
|
||||||
|
$this->messagePositive = false;
|
||||||
|
} else {
|
||||||
|
$this->message = "Update erfolgreich – jetzt: {$this->current}";
|
||||||
|
$this->messagePositive = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// failure path
|
||||||
|
$rc = $this->rc ?? 1;
|
||||||
|
$this->message = "Update fehlgeschlagen (rc={$rc})";
|
||||||
|
$this->messagePositive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->state = 'idle';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- helpers -----------------------------------------------------------
|
||||||
|
|
||||||
|
public function getHasUpdateProperty(): bool
|
||||||
|
{
|
||||||
|
// gleiche Logik wie in deiner Klasse:
|
||||||
|
$cur = $this->normalizeVersion($this->current ?? null);
|
||||||
|
$lat = $this->normalizeVersion($this->latest ?? null);
|
||||||
|
if ($lat === null || $cur === null) return false;
|
||||||
|
return version_compare($lat, $cur, '>');
|
||||||
|
}
|
||||||
|
|
||||||
protected function hasUpdate(): bool
|
protected function hasUpdate(): bool
|
||||||
{
|
{
|
||||||
if (!$this->latest) return false;
|
$cur = $this->normalizeVersion($this->current);
|
||||||
$cur = $this->current ?: '0.0.0';
|
$lat = $this->normalizeVersion($this->latest);
|
||||||
return version_compare($this->latest, $cur, '>');
|
|
||||||
|
if ($lat === null || $cur === null) return false;
|
||||||
|
return version_compare($lat, $cur, '>');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function refreshLowLevelState(): void
|
protected function readLowLevel(): void
|
||||||
{
|
{
|
||||||
$state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: '');
|
$state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: '');
|
||||||
$this->running = ($state === 'running');
|
$this->running = ($state === 'running');
|
||||||
|
|
@ -116,21 +166,183 @@ class UpdateCard extends Component
|
||||||
|
|
||||||
protected function readCurrentVersion(): ?string
|
protected function readCurrentVersion(): ?string
|
||||||
{
|
{
|
||||||
// bevorzugt /etc/mailwolt/build.info (wird im Installer/Updater gepflegt)
|
// Prefer the installer/updater stamp
|
||||||
$build = @file_get_contents('/etc/mailwolt/build.info');
|
$build = @file_get_contents('/etc/mailwolt/build.info');
|
||||||
if ($build) {
|
if ($build) {
|
||||||
foreach (preg_split('/\R+/', $build) as $line) {
|
foreach (preg_split('/\R+/', $build) as $line) {
|
||||||
if (str_starts_with($line, 'version=')) {
|
if (str_starts_with($line, 'version=')) {
|
||||||
$v = trim(substr($line, 8));
|
$v = trim(substr($line, 8));
|
||||||
if ($v !== '') return $v;
|
if ($v !== '') return $this->prettyVersion($v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$v = config('app.version');
|
$v = trim((string)config('app.version', ''));
|
||||||
return $v !== '' ? $v : null;
|
return $v !== '' ? $this->prettyVersion($v) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function readCachedLatest(): ?string
|
||||||
|
{
|
||||||
|
$v = Cache::get('mailwolt.update_available');
|
||||||
|
if (!is_string($v) || $v === '') return null;
|
||||||
|
return $this->prettyVersion($v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a “compare-safe” semver string: e.g. `v1.0.18` → `1.0.18`.
|
||||||
|
* Accepts tags like `release-1.0.18` too.
|
||||||
|
*/
|
||||||
|
protected function normalizeVersion(?string $v): ?string
|
||||||
|
{
|
||||||
|
if (!$v) return null;
|
||||||
|
// keep only the first x.y.z like portion
|
||||||
|
if (preg_match('/(\d+\.\d+\.\d+)/', $v, $m)) {
|
||||||
|
return $m[1];
|
||||||
|
}
|
||||||
|
// fallback: bare digits (x.y)
|
||||||
|
if (preg_match('/(\d+\.\d+)/', $v, $m)) {
|
||||||
|
return $m[1];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Always render with a single leading `v` (no “vv…”) */
|
||||||
|
protected function prettyVersion(string $v): string
|
||||||
|
{
|
||||||
|
$n = $this->normalizeVersion($v);
|
||||||
|
return $n ? 'v' . $n : $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//namespace App\Livewire\Ui\System;
|
||||||
|
//
|
||||||
|
//use Livewire\Component;
|
||||||
|
//use Illuminate\Support\Facades\Artisan;
|
||||||
|
//use Illuminate\Support\Facades\Cache;
|
||||||
|
//
|
||||||
|
//class UpdateCard extends Component
|
||||||
|
//{
|
||||||
|
// public ?string $current = null; // installierte Version
|
||||||
|
// public ?string $latest = null; // verfügbare Version (oder null)
|
||||||
|
// public string $state = 'idle'; // idle | running
|
||||||
|
//
|
||||||
|
// // UI-Textausgabe nach einer Prüfung / Aktion
|
||||||
|
// public ?string $message = null; // z.B. "Du bist auf dem neuesten Stand (v1.0.16)"
|
||||||
|
// public ?bool $messagePositive = null; // true = grün, false = neutral/weiß
|
||||||
|
//
|
||||||
|
// // low-level (falls du sie später brauchst)
|
||||||
|
// public bool $running = false; // aus /var/lib/mailwolt/update/state
|
||||||
|
// public ?int $rc = null;
|
||||||
|
//
|
||||||
|
// public function mount(): void
|
||||||
|
// {
|
||||||
|
// $this->current = $this->readCurrentVersion();
|
||||||
|
// $this->latest = Cache::get('mailwolt.update_available');
|
||||||
|
// $this->refreshLowLevelState();
|
||||||
|
//
|
||||||
|
// // Starttext, falls nichts geprüft wurde
|
||||||
|
// if ($this->message === null) {
|
||||||
|
// $this->message = $this->latest && $this->hasUpdate()
|
||||||
|
// ? "Neue Version verfügbar: {$this->latest}"
|
||||||
|
// : ($this->current ? "Du bist auf dem neuesten Stand ({$this->current})" : "Status unbekannt");
|
||||||
|
// $this->messagePositive = !$this->hasUpdate();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public function render()
|
||||||
|
// {
|
||||||
|
// return view('livewire.ui.system.update-card');
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * „Erneut prüfen“ – ohne Toast:
|
||||||
|
// * - Progress anzeigen
|
||||||
|
// * - Check-Command laufen lassen
|
||||||
|
// * - Message in der Box aktualisieren
|
||||||
|
// */
|
||||||
|
// public function refreshState(): void
|
||||||
|
// {
|
||||||
|
// $this->state = 'running';
|
||||||
|
// $this->message = 'Prüfe auf Updates …';
|
||||||
|
// $this->messagePositive = null;
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// // Passe den Namen hier an dein tatsächliches Command an:
|
||||||
|
// Artisan::call('mailwolt:check-updates');
|
||||||
|
// } catch (\Throwable $e) {
|
||||||
|
// // weich fallen
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Daten neu einlesen
|
||||||
|
// $this->current = $this->readCurrentVersion();
|
||||||
|
// $this->latest = Cache::get('mailwolt.update_available');
|
||||||
|
//
|
||||||
|
// if ($this->hasUpdate()) {
|
||||||
|
// $this->message = "Neue Version verfügbar: {$this->latest}";
|
||||||
|
// $this->messagePositive = false; // neutral
|
||||||
|
// } else {
|
||||||
|
// $cur = $this->current ?: '–';
|
||||||
|
// $this->message = "Du bist auf dem neuesten Stand ({$cur})";
|
||||||
|
// $this->messagePositive = true; // grün
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $this->refreshLowLevelState();
|
||||||
|
// $this->state = 'idle';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * „Jetzt aktualisieren“ – ohne Toast:
|
||||||
|
// * - Hinweis sofort aus Cache entfernen (Badge weg)
|
||||||
|
// * - Update-Wrapper starten
|
||||||
|
// * - Running + Text in der Box anzeigen
|
||||||
|
// */
|
||||||
|
// public function runUpdate(): void
|
||||||
|
// {
|
||||||
|
// Cache::forget('mailwolt.update_available');
|
||||||
|
//
|
||||||
|
// @shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &');
|
||||||
|
//
|
||||||
|
// $this->latest = null;
|
||||||
|
// $this->state = 'running';
|
||||||
|
// $this->running = true;
|
||||||
|
// $this->message = 'Update läuft …';
|
||||||
|
// $this->messagePositive = null;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /** --------------------- helpers --------------------- */
|
||||||
|
//
|
||||||
|
// protected function hasUpdate(): bool
|
||||||
|
// {
|
||||||
|
// if (!$this->latest) return false;
|
||||||
|
// $cur = $this->current ?: '0.0.0';
|
||||||
|
// return version_compare($this->latest, $cur, '>');
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// protected function refreshLowLevelState(): void
|
||||||
|
// {
|
||||||
|
// $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: '');
|
||||||
|
// $this->running = ($state === 'running');
|
||||||
|
//
|
||||||
|
// $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: '');
|
||||||
|
// $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// protected function readCurrentVersion(): ?string
|
||||||
|
// {
|
||||||
|
// // bevorzugt /etc/mailwolt/build.info (wird im Installer/Updater gepflegt)
|
||||||
|
// $build = @file_get_contents('/etc/mailwolt/build.info');
|
||||||
|
// if ($build) {
|
||||||
|
// foreach (preg_split('/\R+/', $build) as $line) {
|
||||||
|
// if (str_starts_with($line, 'version=')) {
|
||||||
|
// $v = trim(substr($line, 8));
|
||||||
|
// if ($v !== '') return $v;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// $v = config('app.version');
|
||||||
|
// return $v !== '' ? $v : null;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//namespace App\Livewire\Ui\System;
|
//namespace App\Livewire\Ui\System;
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,60 @@
|
||||||
@php
|
{{--@php--}}
|
||||||
$hasUpdate = $latest && $current && version_compare($latest, $current, '>');
|
{{-- $hasUpdate = $latest && $current && version_compare($latest, $current, '>');--}}
|
||||||
@endphp
|
{{--@endphp--}}
|
||||||
|
|
||||||
<div class="glass-card rounded-2xl p-4 border border-white/10 bg-white/5 max-h-fit">
|
{{--<div class="glass-card rounded-2xl p-4 border border-white/10 bg-white/5 max-h-fit">--}}
|
||||||
<div class="flex items-start gap-2">
|
{{-- <div class="flex items-start gap-2">--}}
|
||||||
{{-- Shield-Bot --}}
|
{{-- --}}{{-- Shield-Bot --}}
|
||||||
<div class="relative shrink-0">
|
{{-- <div class="relative shrink-0">--}}
|
||||||
<div class="shrink-0 relative">
|
{{-- <div class="shrink-0 relative">--}}
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
|
{{-- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">--}}
|
||||||
<defs>
|
{{-- <defs>--}}
|
||||||
<linearGradient id="shieldGradient" x1="0" y1="0" x2="0" y2="1">
|
{{-- <linearGradient id="shieldGradient" x1="0" y1="0" x2="0" y2="1">--}}
|
||||||
<stop offset="0" stop-color="#4ade80"></stop>
|
{{-- <stop offset="0" stop-color="#4ade80"></stop>--}}
|
||||||
<stop offset="1" stop-color="#15803d"></stop>
|
{{-- <stop offset="1" stop-color="#15803d"></stop>--}}
|
||||||
</linearGradient>
|
{{-- </linearGradient>--}}
|
||||||
<radialGradient id="shine" cx="30%" cy="20%" r="70%">
|
{{-- <radialGradient id="shine" cx="30%" cy="20%" r="70%">--}}
|
||||||
<stop offset="0%" stop-color="rgba(255,255,255,0.4)"></stop>
|
{{-- <stop offset="0%" stop-color="rgba(255,255,255,0.4)"></stop>--}}
|
||||||
<stop offset="100%" stop-color="rgba(255,255,255,0)"></stop>
|
{{-- <stop offset="100%" stop-color="rgba(255,255,255,0)"></stop>--}}
|
||||||
</radialGradient>
|
{{-- </radialGradient>--}}
|
||||||
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
|
{{-- <filter id="glow" x="-20%" y="-20%" width="140%" height="140%">--}}
|
||||||
<feDropShadow dx="0" dy="0" stdDeviation="3" flood-color="#22c55e" flood-opacity="0.6"></feDropShadow>
|
{{-- <feDropShadow dx="0" dy="0" stdDeviation="3" flood-color="#22c55e" flood-opacity="0.6"></feDropShadow>--}}
|
||||||
</filter>
|
{{-- </filter>--}}
|
||||||
</defs>
|
{{-- </defs>--}}
|
||||||
<path d="M32 6l20 8v12c0 13.5-8.7 22.7-20 27-11.3-4.3-20-13.5-20-27V14l20-8z" fill="url(#shieldGradient)" filter="url(#glow)"></path>
|
{{-- <path d="M32 6l20 8v12c0 13.5-8.7 22.7-20 27-11.3-4.3-20-13.5-20-27V14l20-8z" fill="url(#shieldGradient)" filter="url(#glow)"></path>--}}
|
||||||
<path d="M32 6l20 8v12c0 13.5-8.7 22.7-20 27-11.3-4.3-20-13.5-20-27V14l20-8z" fill="url(#shine)"></path>
|
{{-- <path d="M32 6l20 8v12c0 13.5-8.7 22.7-20 27-11.3-4.3-20-13.5-20-27V14l20-8z" fill="url(#shine)"></path>--}}
|
||||||
<i class="ph-bold ph-arrows-clockwise absolute top-1/2 left-1/2 -translate-1/2 text-2xl {{ $state === 'running' ? 'animate-spin' : '' }}"></i>
|
{{-- <i class="ph-bold ph-arrows-clockwise absolute top-1/2 left-1/2 -translate-1/2 text-2xl {{ $state === 'running' ? 'animate-spin' : '' }}"></i>--}}
|
||||||
</svg>
|
{{-- </svg>--}}
|
||||||
</div>
|
{{-- </div>--}}
|
||||||
</div>
|
{{-- </div>--}}
|
||||||
|
|
||||||
<div class="min-w-0 flex-1">
|
{{-- <div class="min-w-0 flex-1">--}}
|
||||||
<div class="flex items-center justify-between gap-3">
|
{{-- <div class="flex items-center justify-between gap-3">--}}
|
||||||
<div class="min-w-0">
|
{{-- <div class="min-w-0">--}}
|
||||||
<div class="text-white/90 font-semibold">MailWolt Update</div>
|
{{-- <div class="text-white/90 font-semibold">MailWolt Update</div>--}}
|
||||||
{{-- kleine Statuszeile mit Versionen, wenn vorhanden --}}
|
{{-- --}}{{-- kleine Statuszeile mit Versionen, wenn vorhanden --}}
|
||||||
<div class="text-xs text-white/70">
|
{{-- <div class="text-xs text-white/70">--}}
|
||||||
@if($current)
|
{{-- @if($current)--}}
|
||||||
aktuell: <span class="text-white/90">v{{ $current }}</span>
|
{{-- aktuell: <span class="text-white/90">{{ $current }}</span>--}}
|
||||||
@else
|
{{-- @else--}}
|
||||||
aktuell: <span class="text-white/60">–</span>
|
{{-- aktuell: <span class="text-white/60">–</span>--}}
|
||||||
@endif
|
{{-- @endif--}}
|
||||||
@if($latest)
|
{{-- @if($latest)--}}
|
||||||
<span class="mx-1 text-white/30">•</span>
|
{{-- <span class="mx-1 text-white/30">•</span>--}}
|
||||||
verfügbar: <span class="text-emerald-200">v{{ $latest }}</span>
|
{{-- verfügbar: <span class="text-emerald-200">{{ $latest }}</span>--}}
|
||||||
@endif
|
{{-- @endif--}}
|
||||||
</div>
|
{{-- </div>--}}
|
||||||
</div>
|
{{-- </div>--}}
|
||||||
<div>
|
{{-- <div>--}}
|
||||||
{{-- Badge rechts --}}
|
{{-- --}}{{-- Badge rechts --}}
|
||||||
<span class="shrink-0 inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[11px] border px-3 py-1
|
{{-- <span class="shrink-0 inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[11px] border px-3 py-1--}}
|
||||||
{{ $hasUpdate
|
{{-- {{ $hasUpdate--}}
|
||||||
? 'text-yellow-200 bg-yellow-500/10 border-yellow-400/30'
|
{{-- ? 'text-yellow-200 bg-yellow-500/10 border-yellow-400/30'--}}
|
||||||
: 'text-emerald-200 bg-emerald-500/10 border-emerald-400/30' }}">
|
{{-- : 'text-emerald-200 bg-emerald-500/10 border-emerald-400/30' }}">--}}
|
||||||
<i class="ph {{ $hasUpdate ? 'ph-arrow-fat-line-up' : 'ph-check-circle' }} text-[12px]"></i>
|
{{-- <i class="ph {{ $hasUpdate ? 'ph-arrow-fat-line-up' : 'ph-check-circle' }} text-[12px]"></i>--}}
|
||||||
{{ $hasUpdate ? 'Update verfügbar' : 'Aktuell' }}
|
{{-- {{ $hasUpdate ? 'Update verfügbar' : 'Aktuell' }}--}}
|
||||||
</span>
|
{{-- </span>--}}
|
||||||
{{-- <button wire:click="refreshState"--}}
|
{{-- <button wire:click="refreshState"--}}
|
||||||
{{-- @disabled($state==='running')--}}
|
{{-- @disabled($state==='running')--}}
|
||||||
{{-- class="inline-flex items-center gap-2 rounded p-1.5--}}
|
{{-- class="inline-flex items-center gap-2 rounded p-1.5--}}
|
||||||
|
|
@ -63,10 +63,100 @@
|
||||||
{{-- <i class="ph ph-arrow-clockwise text-[11px]"></i>--}}
|
{{-- <i class="ph ph-arrow-clockwise text-[11px]"></i>--}}
|
||||||
{{-- </button>--}}
|
{{-- </button>--}}
|
||||||
|
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- <div class="mt-4 flex items-center gap-2">--}}
|
||||||
|
{{-- @if($hasUpdate)--}}
|
||||||
|
{{-- <button wire:click="runUpdate"--}}
|
||||||
|
{{-- @disabled($state==='running')--}}
|
||||||
|
{{-- class="inline-flex items-center gap-2 rounded-lg px-3 py-1.5--}}
|
||||||
|
{{-- text-emerald-200 bg-emerald-500/10 border border-emerald-400/30--}}
|
||||||
|
{{-- hover:bg-emerald-500/15 hover:border-emerald-300/50--}}
|
||||||
|
{{-- disabled:opacity-60">--}}
|
||||||
|
{{-- <i class="ph ph-arrow-fat-lines-up text-[14px]"></i> Jetzt aktualisieren--}}
|
||||||
|
{{-- </button>--}}
|
||||||
|
{{-- @endif--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
|
||||||
|
{{-- --}}{{-- Progress-Bar, wenn running --}}
|
||||||
|
{{-- @if($state === 'running')--}}
|
||||||
|
{{-- <div class="mt-3 h-1.5 rounded bg-white/10 overflow-hidden">--}}
|
||||||
|
{{-- <div class="h-full bg-emerald-400/70 animate-[progress_1.4s_infinite]" style="width:40%"></div>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- <style>@keyframes progress {--}}
|
||||||
|
{{-- 0% {--}}
|
||||||
|
{{-- transform: translateX(-100%)--}}
|
||||||
|
{{-- }--}}
|
||||||
|
{{-- 100% {--}}
|
||||||
|
{{-- transform: translateX(260%)--}}
|
||||||
|
{{-- }--}}
|
||||||
|
{{-- }</style>--}}
|
||||||
|
{{-- @endif--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{--</div>--}}
|
||||||
|
<div
|
||||||
|
class="glass-card rounded-2xl p-4 border border-white/10 bg-white/5 max-h-fit"
|
||||||
|
@if($state === 'running') wire:poll.1200ms="tick" @endif
|
||||||
|
>
|
||||||
|
<div class="flex items-start gap-2">
|
||||||
|
{{-- Shield + Update-Icon --}}
|
||||||
|
<div class="relative shrink-0">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="shieldGradient" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#4ade80"/>
|
||||||
|
<stop offset="1" stop-color="#15803d"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="shine" cx="30%" cy="20%" r="70%">
|
||||||
|
<stop offset="0%" stop-color="rgba(255,255,255,0.35)"/>
|
||||||
|
<stop offset="100%" stop-color="rgba(255,255,255,0)"/>
|
||||||
|
</radialGradient>
|
||||||
|
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
|
||||||
|
<feDropShadow dx="0" dy="0" stdDeviation="3" flood-color="#22c55e" flood-opacity="0.6"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Schild -->
|
||||||
|
<path d="M32 6l20 8v12c0 13.5-8.7 22.7-20 27-11.3-4.3-20-13.5-20-27V14l20-8z"
|
||||||
|
fill="url(#shieldGradient)" filter="url(#glow)"/>
|
||||||
|
<path d="M32 6l20 8v12c0 13.5-8.7 22.7-20 27-11.3-4.3-20-13.5-20-27V14l20-8z"
|
||||||
|
fill="url(#shine)"/>
|
||||||
|
<i class="ph-bold ph-arrows-clockwise absolute top-1/2 left-1/2 -translate-1/2 text-2xl {{ $state === 'running' ? 'animate-spin' : '' }}"></i>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="min-w-0 flex-1">
|
||||||
|
<div class="flex items-center justify-between gap-3">
|
||||||
|
<div class="min-w-0">
|
||||||
|
<div class="text-white/90 font-semibold">MailWolt Update</div>
|
||||||
|
|
||||||
|
<div class="text-xs text-white/70">
|
||||||
|
@if($current)
|
||||||
|
aktuell: <span class="text-white/90">{{ $current }}</span>
|
||||||
|
@else
|
||||||
|
aktuell: <span class="text-white/60">–</span>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($latest)
|
||||||
|
<span class="mx-1 text-white/30">•</span>
|
||||||
|
verfügbar: <span class="text-emerald-200">{{ $latest }}</span>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- Badge rechts --}}
|
||||||
|
<span class="shrink-0 inline-flex items-center gap-1.5 rounded-full text-[11px] border px-3 py-1
|
||||||
|
{{ $this->hasUpdate
|
||||||
|
? 'text-yellow-200 bg-yellow-500/10 border-yellow-400/30'
|
||||||
|
: 'text-emerald-200 bg-emerald-500/10 border-emerald-400/30' }}">
|
||||||
|
<i class="ph {{ $this->hasUpdate ? 'ph-arrow-fat-line-up' : 'ph-check-circle' }} text-[12px]"></i>
|
||||||
|
{{ $this->hasUpdate ? 'Update verfügbar' : 'Aktuell' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mt-4 flex items-center gap-2">
|
<div class="mt-4 flex items-center gap-2">
|
||||||
@if($hasUpdate)
|
@if($this->hasUpdate)
|
||||||
<button wire:click="runUpdate"
|
<button wire:click="runUpdate"
|
||||||
@disabled($state==='running')
|
@disabled($state==='running')
|
||||||
class="inline-flex items-center gap-2 rounded-lg px-3 py-1.5
|
class="inline-flex items-center gap-2 rounded-lg px-3 py-1.5
|
||||||
|
|
@ -78,19 +168,17 @@
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Progress-Bar, wenn running --}}
|
{{-- Fortschritt nur während running --}}
|
||||||
@if($state === 'running')
|
@if($state === 'running')
|
||||||
<div class="mt-3 h-1.5 rounded bg-white/10 overflow-hidden">
|
<div class="mt-3 h-1.5 rounded bg-white/10 overflow-hidden">
|
||||||
<div class="h-full bg-emerald-400/70 animate-[progress_1.4s_infinite]" style="width:40%"></div>
|
<div class="h-full bg-emerald-400/70 animate-[mwprogress_1.4s_infinite]" style="width:40%"></div>
|
||||||
</div>
|
</div>
|
||||||
<style>@keyframes progress {
|
<style>
|
||||||
0% {
|
@keyframes mwprogress {
|
||||||
transform: translateX(-100%)
|
0% { transform: translateX(-100%) }
|
||||||
|
100% { transform: translateX(260%) }
|
||||||
}
|
}
|
||||||
100% {
|
</style>
|
||||||
transform: translateX(260%)
|
|
||||||
}
|
|
||||||
}</style>
|
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue