From dd645aed68730f9f503d10804939a9e407ae47bb Mon Sep 17 00:00:00 2001 From: boban Date: Tue, 28 Oct 2025 18:53:11 +0100 Subject: [PATCH] =?UTF-8?q?Fix:=20Mailbox=20Stats=20=C3=BCber=20Dovecot=20?= =?UTF-8?q?mit=20config/mailpool.php?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Commands/StorageProbe.php | 53 ++- app/Livewire/Ui/System/StorageCard.php | 433 +++++++++++------- .../livewire/ui/system/storage-card.blade.php | 14 +- 3 files changed, 310 insertions(+), 190 deletions(-) diff --git a/app/Console/Commands/StorageProbe.php b/app/Console/Commands/StorageProbe.php index a92e5cd..ad3bc1a 100644 --- a/app/Console/Commands/StorageProbe.php +++ b/app/Console/Commands/StorageProbe.php @@ -26,9 +26,9 @@ class StorageProbe extends Command $data['free_gb'], $data['free_plus_reserve_gb'], $data['percent_used_total'], - $data['breakdown']['system_gb'], - $data['breakdown']['mails_gb'], - $data['breakdown']['backup_gb'], + $data['breakdown_bytes']['system'], + $data['breakdown_bytes']['mails'], + $data['breakdown_bytes']['backup'], )); return self::SUCCESS; @@ -64,21 +64,40 @@ class StorageProbe extends Command $percentUsed = $totalGb > 0 ? (int)round($usedGb * 100 / $totalGb) : 0; // --- du: reale Verbräuche bestimmter Bäume (KB) ----------------------- - $duKb = function (string $path): int { +// $duKb = function (string $path): int { +// if (!is_dir($path)) return 0; +// $kb = (int)trim((string)@shell_exec('LC_ALL=C du -sk --apparent-size ' . escapeshellarg($path) . ' 2>/dev/null | cut -f1')); +// return max(0, $kb); +// }; +// +// $kbMails = $duKb('/var/mail/vhosts'); +// $kbBackup = $duKb('/var/backups/mailwolt'); +// +// // „System“ = alles übrige, was nicht Mails/Backups ist (OS, App, Logs, DB-Daten, …) +// $gbMails = $toGiB_f($kbMails); +// $gbBackup = $toGiB_f($kbBackup); +// +// // system_gb aus „usedGb – (mails+backup)“, nie negativ +// $gbSystem = max(0, round($usedGb - ($gbMails + $gbBackup), 1)); + + $duBytes = function (string $path): int { if (!is_dir($path)) return 0; - $kb = (int)trim((string)@shell_exec('LC_ALL=C du -sk --apparent-size ' . escapeshellarg($path) . ' 2>/dev/null | cut -f1')); - return max(0, $kb); + $b = (int) trim((string) @shell_exec( + 'LC_ALL=C du -sb --apparent-size ' . escapeshellarg($path) . ' 2>/dev/null | cut -f1' + )); + return max(0, $b); }; - $kbMails = $duKb('/var/mail/vhosts'); - $kbBackup = $duKb('/var/backups/mailwolt'); + $bytesMails = $duBytes('/var/mail/vhosts'); + $bytesBackup = $duBytes('/var/backups/mailwolt'); - // „System“ = alles übrige, was nicht Mails/Backups ist (OS, App, Logs, DB-Daten, …) - $gbMails = $toGiB_f($kbMails); - $gbBackup = $toGiB_f($kbBackup); +// used_gb in Bytes nachrechnen (aus df) + $totalBytes = (int) $totalKb * 1024; + $freeBytes = (int) $availKb * 1024; + $usedBytes = max(0, $totalBytes - $freeBytes); - // system_gb aus „usedGb – (mails+backup)“, nie negativ - $gbSystem = max(0, round($usedGb - ($gbMails + $gbBackup), 1)); +// „System“ = Rest + $bytesSystem = max(0, $usedBytes - ($bytesMails + $bytesBackup)); return [ 'device' => $device ?: 'unknown', @@ -93,10 +112,10 @@ class StorageProbe extends Command 'percent_used_total' => $percentUsed, // Reale Breakdown-Werte - 'breakdown' => [ - 'system_gb' => $gbSystem, - 'mails_gb' => $gbMails, - 'backup_gb' => $gbBackup, + 'breakdown_bytes' => [ + 'system' => $bytesSystem, + 'mails' => $bytesMails, + 'backup' => $bytesBackup, ], ]; } diff --git a/app/Livewire/Ui/System/StorageCard.php b/app/Livewire/Ui/System/StorageCard.php index 76a5d70..aa59dd3 100644 --- a/app/Livewire/Ui/System/StorageCard.php +++ b/app/Livewire/Ui/System/StorageCard.php @@ -11,22 +11,25 @@ class StorageCard extends Component { public string $target = '/'; - // Summen + // Summen für die Zahlenanzeige (GB) public ?int $diskTotalGb = null; public ?int $diskUsedGb = null; public ?int $diskFreeGb = null; // Donut - public array $diskSegments = []; + public array $diskSegments = []; // [{angle,class}] public int $diskSegOuterRadius = 92; public int $diskInnerSize = 160; public array $diskCenterText = ['percent' => '–', 'label' => 'SPEICHER BELEGT']; - // Stacked-Bar + Legende - public array $barSegments = []; // [{label,color,gb,percent}] + // Legende/Bar (GENAU wie dein Blade es erwartet) + // [{label,color,gb,percent}] + public array $barSegments = []; + public ?string $measuredAt = null; - protected int $segCount = 100; + protected int $segCount = 100; // Donut-Segmente + private int $legendMinBytes = 1_048_576; // 1 MiB – darunter blenden wir aus public function mount(string $target = '/'): void { @@ -45,118 +48,87 @@ class StorageCard extends Component $this->loadFromSettings(); } -// protected function loadFromSettings(): void -// { -// $disk = Setting::get('health.disk', []); -// if (!is_array($disk) || empty($disk)) { -// $this->resetUi(); -// return; -// } -// -// $this->diskTotalGb = self::intOrNull($disk['total_gb'] ?? null); -// $this->diskUsedGb = self::intOrNull($disk['used_gb'] ?? null); -// $this->diskFreeGb = self::intOrNull($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? null)); -// -// $percent = $disk['percent_used_total'] ?? null; -// $this->diskCenterText = [ -// 'percent' => is_numeric($percent) ? (string)round($percent) . '%' : '–', -// 'label' => 'SPEICHER BELEGT', -// ]; -// $this->diskSegments = $this->buildSegments(is_numeric($percent) ? (int)$percent : null); -// -// $this->barSegments = $this->buildBar($disk); -// $this->measuredAt = Setting::get('health.disk_updated_at', null); -// } + // ───────────────────────────────────────────────────────────── protected function loadFromSettings(): void { $disk = Setting::get('health.disk', []); - if (!is_array($disk) || empty($disk)) { $this->resetUi(); return; } + if (!is_array($disk) || empty($disk)) { + $this->resetUi(); + return; + } + // Summen (GB) – so wie dein Blade sie zeigt $this->diskTotalGb = self::intOrNull($disk['total_gb'] ?? null); - $this->diskUsedGb = self::intOrNull($disk['used_gb'] ?? null); - $this->diskFreeGb = self::intOrNull($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? null)); + $this->diskUsedGb = self::intOrNull($disk['used_gb'] ?? null); + $this->diskFreeGb = self::intOrNull($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? null)); $percent = $disk['percent_used_total'] ?? null; $this->diskCenterText = [ - 'percent' => is_numeric($percent) ? (string)round($percent).'%' : '–', - 'label' => 'SPEICHER BELEGT', + 'percent' => is_numeric($percent) ? (string)round($percent) . '%' : '–', + 'label' => 'SPEICHER BELEGT', ]; - // Donut farbig aus Breakdown - $this->diskSegments = $this->buildDonutSegmentsFromBreakdown($disk); + // Breakdown in BYTES (kommt aus StorageProbe) + $bdBytes = $disk['breakdown_bytes'] ?? ['system' => 0, 'mails' => 0, 'backup' => 0]; - // Legende unten (gleiche Farben wie Donut) - $total = max(1, (float)($disk['total_gb'] ?? 1)); - $bd = $disk['breakdown'] ?? []; - $sys = (float)($bd['system_gb'] ?? 0); - $mails = (float)($bd['mails_gb'] ?? 0); - $backup = (float)($bd['backup_gb'] ?? 0); - $free = (float)($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? 0)); - $p = fn(float $gb) => max(0, min(100, round($gb * 100 / $total))); + // Total/Free in BYTES ableiten + $totalBytes = (int)round(((int)($disk['total_gb'] ?? 0)) * 1024 ** 3); + $freeGb = $disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? 0); + $freeBytes = (int)round(((float)$freeGb) * 1024 ** 3); - $this->barSegments = [ - ['label' => 'System', 'gb' => round($sys,1), 'percent' => $p($sys), 'color' => 'bg-emerald-400'], - ['label' => 'Mails', 'gb' => round($mails,1), 'percent' => $p($mails), 'color' => 'bg-rose-400'], - ['label' => 'Backups', 'gb' => round($backup,1),'percent' => $p($backup), 'color' => 'bg-sky-400'], - ['label' => 'Frei', 'gb' => round($free,1), 'percent' => $p($free), 'color' => 'bg-white/20'], - ]; + // reportetes Used (Bytes) + $usedReportedBytes = max(0, $totalBytes - $freeBytes); - $this->barSegments = array_values(array_filter( - $this->barSegments, - fn($b) => ($b['gb'] ?? 0) > 0 // nur Einträge mit realer Größe - )); + // Summe Breakdown angleichen (Rest → System), damit Donut/Prozente stimmig sind + $sumUsedBreakdown = max(0, (int)$bdBytes['system'] + (int)$bdBytes['mails'] + (int)$bdBytes['backup']); + if ($usedReportedBytes > $sumUsedBreakdown) { + $bdBytes['system'] += ($usedReportedBytes - $sumUsedBreakdown); + } + + // Donut färben + $this->diskSegments = $this->buildDonutSegmentsFromBytes($bdBytes, $totalBytes, $freeBytes); + + // Legende/Bar (GB + Prozent; KEIN „text“-Feld) + $this->barSegments = $this->buildLegendGbFromBytes($bdBytes, $totalBytes, $freeBytes); $this->measuredAt = Setting::get('health.disk_updated_at', null); } - // NEU: ersetzt buildSegments() + nutzt Breakdown - protected function buildDonutSegmentsFromBreakdown(array $disk): array + protected function buildDonutSegmentsFromBytes(array $bdBytes, int $totalBytes, int $freeBytes): array { - $total = (float)($disk['total_gb'] ?? 0); - if ($total <= 0) return []; + if ($totalBytes <= 0) return []; - // Breakdown lesen - $bd = $disk['breakdown'] ?? []; - $sys = (float)($bd['system_gb'] ?? 0); - $mails = (float)($bd['mails_gb'] ?? 0); - $backup = (float)($bd['backup_gb'] ?? 0); - $free = (float)($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? 0)); + $order = [ + ['key' => 'system', 'class' => 'bg-emerald-400'], + ['key' => 'mails', 'class' => 'bg-rose-400'], + ['key' => 'backup', 'class' => 'bg-sky-400'], + ]; - // Robust machen: falls used aus Settings größer ist als Breakdown-Summe → auf System draufschlagen - $usedReported = (float)($disk['used_gb'] ?? ($total - $free)); - $sumUsedBd = $sys + $mails + $backup; - if ($usedReported > $sumUsedBd && $usedReported <= $total) { - $sys += ($usedReported - $sumUsedBd); + $counts = []; + foreach ($order as $d) { + $bytes = max(0, (int)($bdBytes[$d['key']] ?? 0)); + $cnt = (int)round($this->segCount * ($bytes / $totalBytes)); + if ($bytes > 0 && $cnt === 0) $cnt = 1; // min. 1 Segment, wenn vorhanden + $counts[$d['key']] = $cnt; } - // Grenzen - $sys = max(0, min($sys, $total)); - $mails = max(0, min($mails, $total)); - $backup = max(0, min($backup, $total)); - $free = max(0, min($free, $total)); - // Segmente verteilen - $mkCount = function (float $gb) use ($total) { - return (int) round($this->segCount * $gb / $total); - }; + $usedCount = array_sum($counts); + $freeCount = max(0, $this->segCount - $usedCount); $segments = []; - $add = function (int $count, string $class) use (&$segments) { - for ($i = 0; $i < $count; $i++) { - $segments[] = ['class' => $class]; + foreach ($order as $d) { + for ($i = 0; $i < $counts[$d['key']]; $i++) { + $segments[] = ['class' => $d['class']]; } - }; - - $add($mkCount($sys), 'bg-emerald-400'); // System - $add($mkCount($mails), 'bg-rose-400'); // Mails - $add($mkCount($backup), 'bg-sky-400'); // Backups - - // Rest = Frei (grau) + } + for ($i = 0; $i < $freeCount; $i++) { + $segments[] = ['class' => 'bg-white/15']; + } while (count($segments) < $this->segCount) { $segments[] = ['class' => 'bg-white/15']; } - // Winkel setzen (gleich wie vorher) $out = []; for ($i = 0; $i < $this->segCount; $i++) { $angle = (360 / $this->segCount) * $i - 90; @@ -165,67 +137,41 @@ class StorageCard extends Component return $out; } -// protected function buildSegments(?int $percent): array -// { -// $segments = []; -// $active = is_int($percent) ? (int)round($this->segCount * $percent / 100) : 0; -// -// $activeClass = match (true) { -// !is_int($percent) => 'bg-white/15', -// $percent >= 90 => 'bg-rose-400', -// $percent >= 70 => 'bg-amber-300', -// default => 'bg-emerald-400', -// }; -// -// for ($i = 0; $i < $this->segCount; $i++) { -// $angle = (360 / $this->segCount) * $i - 90; -// $segments[] = [ -// 'angle' => $angle, -// 'class' => $i < $active ? $activeClass : 'bg-white/15' -// ]; -// } -// return $segments; -// } - - protected function buildBar(array $disk): array + protected function buildLegendGbFromBytes(array $bdBytes, int $totalBytes, int $freeBytes): array { - $total = (float)($disk['total_gb'] ?? 0); - if ($total <= 0) return []; + $defs = [ + ['key' => 'system', 'label' => 'System', 'class' => 'bg-emerald-400'], + ['key' => 'mails', 'label' => 'Mails', 'class' => 'bg-rose-400'], + ['key' => 'backup', 'label' => 'Backups', 'class' => 'bg-sky-400'], + ]; - // Breakdown lesen + normalisieren - [$sys, $mails, $backups] = $this->readBreakdown($disk); + $toPercent = function (int $bytes) use ($totalBytes): int { + if ($totalBytes <= 0) return 0; + return (int)max(0, min(100, round($bytes * 100 / $totalBytes))); + }; + $toGb = fn(int $bytes) => round($bytes / (1024 ** 3), 1); - $free = max(0.0, (float)($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? 0))); - $used = min($total, $sys + $mails + $backups); // robust bei Messrauschen - - // Falls Breakdown kleiner ist als used_gb: Rest als “System” draufschlagen, - // damit die Prozent-Summe 100 ergibt. - $usedReported = (float)($disk['used_gb'] ?? ($total - $free)); - if ($usedReported > 0 && $used < $usedReported) { - $sys += ($usedReported - $used); - $used = $usedReported; + $out = []; + foreach ($defs as $d) { + $val = max(0, (int)($bdBytes[$d['key']] ?? 0)); + if ($val < $this->legendMinBytes) continue; // zu klein → nicht anzeigen + $out[] = [ + 'label' => $d['label'], + 'color' => $d['class'], + 'gb' => $toGb($val), // ← genau das Feld, das dein Blade nutzt + 'percent' => $toPercent($val), + ]; } - // Prozent berechnen - $p = fn(float $gb) => max(0, min(100, round($gb * 100 / $total))); - - return [ - ['label' => 'System', 'gb' => round($sys, 1), 'percent' => $p($sys), 'color' => 'bg-emerald-400'], - ['label' => 'Mails', 'gb' => round($mails, 1), 'percent' => $p($mails), 'color' => 'bg-rose-400'], - ['label' => 'Backups', 'gb' => round($backups, 1), 'percent' => $p($backups), 'color' => 'bg-sky-400'], - ['label' => 'Frei', 'gb' => round($free, 1), 'percent' => $p($free), 'color' => 'bg-white/20'], + // „Frei“ immer anzeigen + $out[] = [ + 'label' => 'Frei', + 'color' => 'bg-white/20', + 'gb' => $toGb($freeBytes), + 'percent' => $toPercent($freeBytes), ]; - } - protected function readBreakdown(array $disk): array - { - // Deine Keys ggf. hier mappen - $bd = $disk['breakdown'] ?? []; - $sys = (float)($bd['system_gb'] ?? 0); - $mails = (float)($bd['mails_gb'] ?? 0); - $backup = (float)($bd['backup_gb'] ?? 0); - - return [$sys, $mails, $backup]; + return $out; } protected function resetUi(): void @@ -244,7 +190,8 @@ class StorageCard extends Component return is_numeric($v) ? (int)round($v) : null; } } - +// +// //namespace App\Livewire\Ui\System; // //use Livewire\Component; @@ -255,17 +202,24 @@ class StorageCard extends Component //{ // public string $target = '/'; // +// // Summen // public ?int $diskTotalGb = null; -// public ?int $diskUsedGb = null; // inkl. Reserve (passt zum Donut) -// public ?int $diskFreeGb = null; // wird unten auf free_plus_reserve_gb gesetzt +// public ?int $diskUsedGb = null; +// public ?int $diskFreeGb = null; // +// // Donut // public array $diskSegments = []; -// public int $diskSegOuterRadius = 92; -// public int $diskInnerSize = 160; -// public array $diskCenterText = ['percent' => '–', 'label' => 'SPEICHER BELEGT']; +// public int $diskSegOuterRadius = 92; +// public int $diskInnerSize = 160; +// public array $diskCenterText = ['percent' => '–', 'label' => 'SPEICHER BELEGT']; +// +// private int $legendMinBytes = 1 * 1024 * 1024; // 1 MiB Schwelle +// +// // Stacked-Bar + Legende +// public array $barSegments = []; // [{label,color,gb,percent}] // public ?string $measuredAt = null; // -// protected int $segCount = 48; +// protected int $segCount = 100; // // public function mount(string $target = '/'): void // { @@ -273,7 +227,10 @@ class StorageCard extends Component // $this->loadFromSettings(); // } // -// public function render() { return view('livewire.ui.system.storage-card'); } +// public function render() +// { +// return view('livewire.ui.system.storage-card'); +// } // // public function refresh(): void // { @@ -281,41 +238,187 @@ class StorageCard extends Component // $this->loadFromSettings(); // } // +// private function humanSize(int $bytes): string +// { +// if ($bytes >= 1024**3) return number_format($bytes / 1024**3, 1) . ' GB'; +// if ($bytes >= 1024**2) return number_format($bytes / 1024**2, 2) . ' MiB'; +// if ($bytes >= 1024) return number_format($bytes / 1024, 0) . ' KiB'; +// return $bytes . ' B'; +// } +// // protected function loadFromSettings(): void // { // $disk = Setting::get('health.disk', []); -// if (!is_array($disk) || empty($disk)) return; +// if (!is_array($disk) || empty($disk)) { $this->resetUi(); return; } // -// $this->diskTotalGb = $disk['total_gb'] ?? null; -// $this->diskUsedGb = $disk['used_gb'] ?? null; -// $this->diskFreeGb = $disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? null); +// $this->diskTotalGb = self::intOrNull($disk['total_gb'] ?? null); +// $this->diskUsedGb = self::intOrNull($disk['used_gb'] ?? null); +// $this->diskFreeGb = self::intOrNull($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? null)); // // $percent = $disk['percent_used_total'] ?? null; // $this->diskCenterText = [ -// 'percent' => is_numeric($percent) ? $percent.'%' : '–', +// 'percent' => is_numeric($percent) ? (string)round($percent).'%' : '–', // 'label' => 'SPEICHER BELEGT', // ]; -// $this->diskSegments = $this->buildSegments($percent); +// +// // Donut farbig aus Breakdown +// $this->diskSegments = $this->buildDonutSegmentsFromBreakdown($disk); +// +// // Legende unten (gleiche Farben wie Donut) +// $total = max(1, (float)($disk['total_gb'] ?? 1)); +// $bd = $disk['breakdown'] ?? []; +// $sys = (float)($bd['system_gb'] ?? 0); +// $mails = (float)($bd['mails_gb'] ?? 0); +// $backup = (float)($bd['backup_gb'] ?? 0); +// $free = (float)($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? 0)); +// $p = fn(float $gb) => max(0, min(100, round($gb * 100 / $total))); +// +// $this->barSegments = [ +// ['label' => 'System', 'gb' => round($sys,1), 'percent' => $p($sys), 'color' => 'bg-emerald-400'], +// ['label' => 'Mails', 'gb' => round($mails,1), 'percent' => $p($mails), 'color' => 'bg-rose-400'], +// ['label' => 'Backups', 'gb' => round($backup,1),'percent' => $p($backup), 'color' => 'bg-sky-400'], +// ['label' => 'Frei', 'gb' => round($free,1), 'percent' => $p($free), 'color' => 'bg-white/20'], +// ]; +// +// $this->barSegments = array_values(array_filter( +// $this->barSegments, +// fn($b) => ($b['gb'] ?? 0) > 0 // nur Einträge mit realer Größe +// )); // // $this->measuredAt = Setting::get('health.disk_updated_at', null); // } // -// protected function buildSegments(?int $percent): array +// // NEU: ersetzt buildSegments() + nutzt Breakdown +// protected function buildDonutSegmentsFromBreakdown(array $disk): array // { -// $segments = []; -// $active = is_int($percent) ? (int) round($this->segCount * $percent / 100) : 0; +// $total = (float)($disk['total_gb'] ?? 0); +// if ($total <= 0) return []; // -// $activeClass = match (true) { -// !is_int($percent) => 'bg-white/15', -// $percent >= 90 => 'bg-rose-400', -// $percent >= 70 => 'bg-amber-300', -// default => 'bg-emerald-400', +// // Breakdown lesen +// $bd = $disk['breakdown'] ?? []; +// $sys = (float)($bd['system_gb'] ?? 0); +// $mails = (float)($bd['mails_gb'] ?? 0); +// $backup = (float)($bd['backup_gb'] ?? 0); +// $free = (float)($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? 0)); +// +// // Robust machen: falls used aus Settings größer ist als Breakdown-Summe → auf System draufschlagen +// $usedReported = (float)($disk['used_gb'] ?? ($total - $free)); +// $sumUsedBd = $sys + $mails + $backup; +// if ($usedReported > $sumUsedBd && $usedReported <= $total) { +// $sys += ($usedReported - $sumUsedBd); +// } +// // Grenzen +// $sys = max(0, min($sys, $total)); +// $mails = max(0, min($mails, $total)); +// $backup = max(0, min($backup, $total)); +// $free = max(0, min($free, $total)); +// +// // Segmente verteilen +// $mkCount = function (float $gb) use ($total) { +// return (int) round($this->segCount * $gb / $total); // }; // +// $segments = []; +// $add = function (int $count, string $class) use (&$segments) { +// for ($i = 0; $i < $count; $i++) { +// $segments[] = ['class' => $class]; +// } +// }; +// +// $add($mkCount($sys), 'bg-emerald-400'); // System +// $add($mkCount($mails), 'bg-rose-400'); // Mails +// $add($mkCount($backup), 'bg-sky-400'); // Backups +// +// // Rest = Frei (grau) +// while (count($segments) < $this->segCount) { +// $segments[] = ['class' => 'bg-white/15']; +// } +// +// // Winkel setzen (gleich wie vorher) +// $out = []; // for ($i = 0; $i < $this->segCount; $i++) { // $angle = (360 / $this->segCount) * $i - 90; -// $segments[] = ['angle' => $angle, 'class' => $i < $active ? $activeClass : 'bg-white/15']; +// $out[] = ['angle' => $angle, 'class' => $segments[$i]['class']]; // } -// return $segments; +// return $out; +// } +// +//// protected function buildSegments(?int $percent): array +//// { +//// $segments = []; +//// $active = is_int($percent) ? (int)round($this->segCount * $percent / 100) : 0; +//// +//// $activeClass = match (true) { +//// !is_int($percent) => 'bg-white/15', +//// $percent >= 90 => 'bg-rose-400', +//// $percent >= 70 => 'bg-amber-300', +//// default => 'bg-emerald-400', +//// }; +//// +//// for ($i = 0; $i < $this->segCount; $i++) { +//// $angle = (360 / $this->segCount) * $i - 90; +//// $segments[] = [ +//// 'angle' => $angle, +//// 'class' => $i < $active ? $activeClass : 'bg-white/15' +//// ]; +//// } +//// return $segments; +//// } +// +// protected function buildBar(array $disk): array +// { +// $total = (float)($disk['total_gb'] ?? 0); +// if ($total <= 0) return []; +// +// // Breakdown lesen + normalisieren +// [$sys, $mails, $backups] = $this->readBreakdown($disk); +// +// $free = max(0.0, (float)($disk['free_gb'] ?? ($disk['free_plus_reserve_gb'] ?? 0))); +// $used = min($total, $sys + $mails + $backups); // robust bei Messrauschen +// +// // Falls Breakdown kleiner ist als used_gb: Rest als “System” draufschlagen, +// // damit die Prozent-Summe 100 ergibt. +// $usedReported = (float)($disk['used_gb'] ?? ($total - $free)); +// if ($usedReported > 0 && $used < $usedReported) { +// $sys += ($usedReported - $used); +// $used = $usedReported; +// } +// +// // Prozent berechnen +// $p = fn(float $gb) => max(0, min(100, round($gb * 100 / $total))); +// +// return [ +// ['label' => 'System', 'gb' => round($sys, 1), 'percent' => $p($sys), 'color' => 'bg-emerald-400'], +// ['label' => 'Mails', 'gb' => round($mails, 1), 'percent' => $p($mails), 'color' => 'bg-rose-400'], +// ['label' => 'Backups', 'gb' => round($backups, 1), 'percent' => $p($backups), 'color' => 'bg-sky-400'], +// ['label' => 'Frei', 'gb' => round($free, 1), 'percent' => $p($free), 'color' => 'bg-white/20'], +// ]; +// } +// +// protected function readBreakdown(array $disk): array +// { +// // Deine Keys ggf. hier mappen +// $bd = $disk['breakdown'] ?? []; +// $sys = (float)($bd['system_gb'] ?? 0); +// $mails = (float)($bd['mails_gb'] ?? 0); +// $backup = (float)($bd['backup_gb'] ?? 0); +// +// return [$sys, $mails, $backup]; +// } +// +// protected function resetUi(): void +// { +// $this->diskTotalGb = null; +// $this->diskUsedGb = null; +// $this->diskFreeGb = null; +// $this->diskSegments = []; +// $this->barSegments = []; +// $this->diskCenterText = ['percent' => '–', 'label' => 'SPEICHER BELEGT']; +// $this->measuredAt = null; +// } +// +// protected static function intOrNull($v): ?int +// { +// return is_numeric($v) ? (int)round($v) : null; // } //} diff --git a/resources/views/livewire/ui/system/storage-card.blade.php b/resources/views/livewire/ui/system/storage-card.blade.php index 7525952..df9e192 100644 --- a/resources/views/livewire/ui/system/storage-card.blade.php +++ b/resources/views/livewire/ui/system/storage-card.blade.php @@ -20,20 +20,18 @@
- {{ $diskCenterText['percent'] }} / {{ is_numeric($diskTotalGb) ? $diskTotalGb.' GB' : '–' }} + {{ $diskCenterText['percent'] }} +{{-- / {{ is_numeric($diskTotalGb) ? $diskTotalGb.' GB' : '–' }}--}}
{{ $diskCenterText['label'] }}
{{-- @if($measuredAt)--}} -{{--
--}} -{{--
Gesamt
--}} -{{--
{{ is_numeric($diskTotalGb) ? $diskTotalGb.' GB' : '–' }}
--}} - -{{-- --}}{{----}} -{{-- zuletzt aktualisiert:
{{ \Carbon\Carbon::parse($measuredAt)->diffForHumans() }}--}} -{{--
--}} +
+
Gesamt
+
{{ is_numeric($diskTotalGb) ? $diskTotalGb.' GB' : '–' }}
+
{{-- @endif--}}