From e3a0279c0038ef5452c72270e8473391d799c1e2 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 19 Aug 2026 11:09:02 +0200 Subject: [PATCH] fix(ui): flag pending proxy updates and Sentinel outages --- .../views/components/server/sidebar.blade.php | 1 + .../components/server/status-summary.blade.php | 17 ++++++++++++----- resources/views/livewire/dashboard.blade.php | 2 +- resources/views/livewire/server/index.blade.php | 3 ++- tests/Feature/ServerSidebarIconsTest.php | 7 +++++++ .../Feature/ServerStatusIndicatorDesignTest.php | 14 ++++++++++++-- 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/resources/views/components/server/sidebar.blade.php b/resources/views/components/server/sidebar.blade.php index 41cbd7ce9d..46e433e8a5 100644 --- a/resources/views/components/server/sidebar.blade.php +++ b/resources/views/components/server/sidebar.blade.php @@ -70,6 +70,7 @@ 'icon' => 'shield-star', 'group' => 'Platform', 'visible' => $server->isFunctional() && ! $server->isSwarm() && ! $server->settings->is_build_server && auth()->user()?->can('viewSentinel', $server), + 'warning' => $server->isSentinelEnabled() && ! $server->isSentinelLive(), 'children' => [ ['label' => 'Configuration', 'route' => 'server.sentinel', 'active' => request()->routeIs('server.sentinel'), 'icon' => 'settings'], ['label' => 'Logs', 'route' => 'server.sentinel.logs', 'active' => request()->routeIs('server.sentinel.logs'), 'icon' => 'file-content'], diff --git a/resources/views/components/server/status-summary.blade.php b/resources/views/components/server/status-summary.blade.php index 7a5522b541..5e732fade8 100644 --- a/resources/views/components/server/status-summary.blade.php +++ b/resources/views/components/server/status-summary.blade.php @@ -6,7 +6,10 @@ @php $serverReady = $server->isFunctional(); - $proxyNeedsAttention = $server->proxySet() && ! in_array($proxyStatus, ['running'], true); + $proxyUpdateAvailable = $server->proxySet() + && ($server->hasCurrentTraefikOutdatedInfo() || $server->hasPendingProxyConfiguration()); + $proxyNeedsAttention = $server->proxySet() + && (! in_array($proxyStatus, ['running'], true) || $proxyUpdateAvailable); $sentinelNeedsAttention = $showSentinelStatus && ! $server->isSentinelLive(); [$summaryLabel, $summaryType] = match (true) { @@ -58,9 +61,9 @@ class="listbox-option gap-2.5!" @click="open = false" role="menuitem"> $proxyStatus === 'running', - 'bg-warning' => in_array($proxyStatus, ['starting', 'restarting', 'stopping'], true), - 'bg-error' => ! in_array($proxyStatus, ['running', 'starting', 'restarting', 'stopping'], true), + 'bg-success' => $proxyStatus === 'running' && ! $proxyUpdateAvailable, + 'bg-warning' => $proxyNeedsAttention && ($proxyUpdateAvailable || in_array($proxyStatus, ['starting', 'restarting', 'stopping'], true)), + 'bg-error' => $proxyNeedsAttention && ! $proxyUpdateAvailable && ! in_array($proxyStatus, ['starting', 'restarting', 'stopping'], true), ])> Proxy {{ str($proxyStatus ?: 'unknown')->headline() }} @@ -69,7 +72,11 @@ @if ($showSentinelStatus) - + ! $sentinelNeedsAttention, + 'bg-warning' => $sentinelNeedsAttention, + ])> Sentinel {{ $server->isSentinelLive() ? 'In sync' : 'Out of sync' }} diff --git a/resources/views/livewire/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php index 175fdb39a7..a8f4d0369d 100644 --- a/resources/views/livewire/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -175,7 +175,7 @@
@foreach ($dashboardServers as $server) @php - $proxyNeedsAttention = $server->proxySet() && $server->proxy->status !== 'running'; + $proxyNeedsAttention = $server->proxySet() && ($server->proxy->status !== 'running' || $server->hasCurrentTraefikOutdatedInfo()); $sentinelNeedsAttention = $server->isSentinelEnabled() && ! $server->isSentinelLive(); [$serverStatus, $serverStatusType] = match (true) { diff --git a/resources/views/livewire/server/index.blade.php b/resources/views/livewire/server/index.blade.php index d89e8b891f..112e052094 100644 --- a/resources/views/livewire/server/index.blade.php +++ b/resources/views/livewire/server/index.blade.php @@ -33,7 +33,8 @@ && $server->settings->is_usable && ! $server->settings->force_disabled && ! $isTransferredAway; - $proxyNeedsAttention = $isReady && $server->proxySet() && $server->proxy->status !== 'running'; + $proxyNeedsAttention = $isReady && $server->proxySet() + && ($server->proxy->status !== 'running' || $server->hasCurrentTraefikOutdatedInfo()); $sentinelNeedsAttention = $isReady && $server->isSentinelEnabled() && ! $server->isSentinelLive(); $status = match (true) { diff --git a/tests/Feature/ServerSidebarIconsTest.php b/tests/Feature/ServerSidebarIconsTest.php index 205429d678..12d33b6e38 100644 --- a/tests/Feature/ServerSidebarIconsTest.php +++ b/tests/Feature/ServerSidebarIconsTest.php @@ -36,6 +36,13 @@ it('uses the shield-star reicon for sentinel in the server sidebar', function () ->toMatch("/'label' => 'Sentinel',\s*'route' => 'server\.sentinel',\s*'active' => request\(\)->routeIs\('server\.sentinel', 'server\.sentinel\.\*'\),\s*'icon' => 'shield-star'/s"); }); +it('shows a warning icon when sentinel is enabled but not working', function () { + $contents = file_get_contents(resource_path('views/components/server/sidebar.blade.php')); + + expect($contents) + ->toContain("'warning' => \$server->isSentinelEnabled() && ! \$server->isSentinelLive()"); +}); + it('uses the network reicon for proxy in the server sidebar', function () { $contents = file_get_contents(resource_path('views/components/server/sidebar.blade.php')); diff --git a/tests/Feature/ServerStatusIndicatorDesignTest.php b/tests/Feature/ServerStatusIndicatorDesignTest.php index 090d6d816a..5e2b8b5faa 100644 --- a/tests/Feature/ServerStatusIndicatorDesignTest.php +++ b/tests/Feature/ServerStatusIndicatorDesignTest.php @@ -13,7 +13,7 @@ test('server cards use warning icons instead of colored icon borders', function expect(substr_count($serverIndex, 'toBe(1) ->and($serverIndex) - ->toContain("\$proxyNeedsAttention = \$isReady && \$server->proxySet() && \$server->proxy->status !== 'running'") + ->toContain("&& (\$server->proxy->status !== 'running' || \$server->hasCurrentTraefikOutdatedInfo())") ->toContain('$sentinelNeedsAttention = $isReady && $server->isSentinelEnabled() && ! $server->isSentinelLive()') ->toContain("\$proxyNeedsAttention || \$sentinelNeedsAttention => 'warning'") ->toContain("\$isReady => 'success'") @@ -29,11 +29,21 @@ test('dashboard server cards warn when proxy or sentinel needs attention', funct $dashboard = file_get_contents(resource_path('views/livewire/dashboard.blade.php')); expect($dashboard) - ->toContain("\$proxyNeedsAttention = \$server->proxySet() && \$server->proxy->status !== 'running'") + ->toContain("\$proxyNeedsAttention = \$server->proxySet() && (\$server->proxy->status !== 'running' || \$server->hasCurrentTraefikOutdatedInfo())") ->toContain('$sentinelNeedsAttention = $server->isSentinelEnabled() && ! $server->isSentinelLive()') ->toContain("\$proxyNeedsAttention || \$sentinelNeedsAttention => ['Attention required', 'warning']"); }); +test('server status summary uses warning indicators for proxy updates and sentinel outages', function () { + $summary = file_get_contents(resource_path('views/components/server/status-summary.blade.php')); + + expect($summary) + ->toContain('$server->hasCurrentTraefikOutdatedInfo()') + ->toContain("'bg-warning' => \$proxyNeedsAttention && (\$proxyUpdateAvailable") + ->toContain("'bg-warning' => \$sentinelNeedsAttention") + ->not->toContain("\$server->isSentinelLive() ? 'bg-success' : 'bg-error'"); +}); + test('server table keeps status text without a badge', function () { $serverIndex = file_get_contents(resource_path('views/livewire/server/index.blade.php'));