From 0db2eae8deb29fd4d9786ef4baec0e2f3a545041 Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Sat, 26 Sep 2026 00:17:55 +0200
Subject: [PATCH] feat(proxy): show sidebar warning icon when proxy is not
running
Add a proxyNotRunning flag to the server sidebar state. The Proxy menu
item's warning icon now also appears when a proxy is configured but its
status is not "running". The navbar sends the flag in the
proxy-configuration-state-changed event, so the icon updates live.
Add tests for the dispatched flag and the sidebar bindings.
---
app/Livewire/Server/Navbar.php | 1 +
.../views/components/server/sidebar.blade.php | 5 ++++-
tests/Feature/Proxy/RestartProxyTest.php | 20 +++++++++++++++++++
tests/Feature/ServerSidebarIconsTest.php | 3 +++
4 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/app/Livewire/Server/Navbar.php b/app/Livewire/Server/Navbar.php
index b64adf10a3..545494db51 100644
--- a/app/Livewire/Server/Navbar.php
+++ b/app/Livewire/Server/Navbar.php
@@ -258,6 +258,7 @@ class Navbar extends Component
'proxy-configuration-state-changed',
pending: $this->server->hasPendingProxyConfiguration(),
traefikOutdated: $this->server->hasCurrentTraefikOutdatedInfo(),
+ proxyNotRunning: $this->server->proxySet() && ($this->server->proxy->status ?? 'unknown') !== 'running',
);
}
diff --git a/resources/views/components/server/sidebar.blade.php b/resources/views/components/server/sidebar.blade.php
index 65fe3cabbc..3645dd2a27 100644
--- a/resources/views/components/server/sidebar.blade.php
+++ b/resources/views/components/server/sidebar.blade.php
@@ -3,6 +3,7 @@
@php
$serverRouteParameters = ['server_uuid' => $server->uuid];
$sentinelStatus = $server->sentinelStatus();
+ $proxyNotRunning = $server->proxySet() && ($server->proxy->status ?? 'unknown') !== 'running';
$sentinelStatusStartedAt = $server->sentinel_waiting_since ?? \Illuminate\Support\Carbon::parse($server->sentinel_updated_at);
$sentinelTimeoutSeconds = $server->sentinel_waiting_since !== null
? $server->firstSentinelReportTimeoutSeconds()
@@ -199,6 +200,7 @@
x-data="{
proxyConfigurationPending: @js($server->hasPendingProxyConfiguration()),
traefikOutdated: @js($server->hasCurrentTraefikOutdatedInfo()),
+ proxyNotRunning: @js($proxyNotRunning),
sentinelOutOfSync: @js($server->isSentinelEnabled() && $sentinelStatus === 'out_of_sync'),
sentinelExpiryTimer: null,
scheduleSentinelExpiry(delay) {
@@ -212,6 +214,7 @@
@proxy-configuration-state-changed.window="
proxyConfigurationPending = $event.detail.pending;
traefikOutdated = $event.detail.traefikOutdated;
+ proxyNotRunning = $event.detail.proxyNotRunning;
"
@sentinel-status-changed.window="
sentinelOutOfSync = $event.detail.outOfSync;
@@ -247,7 +250,7 @@
@if ($menuItem['tracks_proxy_configuration'] ?? false)
@elseif ($menuItem['tracks_sentinel_status'] ?? false)
assertSee('Your configuration changed, please restart the proxy.');
});
+test('navbar tells the sidebar when the proxy is not running', function () {
+ [$user, $team, $server] = setupProxyUser('admin');
+ makeServerProxyRunning($server);
+
+ $this->actingAs($user);
+ session(['currentTeam' => $team]);
+
+ $component = Livewire::test('server.navbar', ['server' => $server->fresh()]);
+
+ $component->call('showNotification')
+ ->assertDispatched('proxy-configuration-state-changed', proxyNotRunning: false);
+
+ $server->refresh();
+ $server->proxy->status = 'exited';
+ $server->save();
+
+ $component->call('showNotification')
+ ->assertDispatched('proxy-configuration-state-changed', proxyNotRunning: true);
+});
+
test('admin can stop a proxy while it is starting', function () {
[$user, $team, $server] = setupProxyUser('admin');
diff --git a/tests/Feature/ServerSidebarIconsTest.php b/tests/Feature/ServerSidebarIconsTest.php
index bdc9cdaddd..9592105ef2 100644
--- a/tests/Feature/ServerSidebarIconsTest.php
+++ b/tests/Feature/ServerSidebarIconsTest.php
@@ -62,6 +62,9 @@ it('shows a warning icon when a server menu item requires attention', function (
->toContain('proxyConfigurationPending: @js($server->hasPendingProxyConfiguration()),')
->toContain('traefikOutdated: @js($server->hasCurrentTraefikOutdatedInfo())')
->toContain('@proxy-configuration-state-changed.window')
+ ->toContain('proxyNotRunning: @js($proxyNotRunning)')
+ ->toContain('proxyNotRunning = $event.detail.proxyNotRunning')
+ ->toContain('x-show="proxyConfigurationPending || traefikOutdated || proxyNotRunning"')
->toContain('@sentinel-status-changed.window')
->toContain('sentinelOutOfSync = $event.detail.outOfSync')
->toContain('scheduleSentinelExpiry($event.detail.expiresInMilliseconds)')