From 784566d06bf0af25927307458cb275ea339ff71f Mon Sep 17 00:00:00 2001 From: boban Date: Sun, 14 Jun 2026 19:24:56 +0200 Subject: [PATCH] fix(ui): keep the sidebar server-switcher in sync with the viewed server Two "current server" notions diverged: the sidebar switcher (session active_server_id) vs the server-details URL. Now viewing a server's details sets it active (sidebar always matches the page), and switching the sidebar while on a details page navigates to the chosen server (instead of reloading the old one). One current server, in sync. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/Livewire/ServerSwitcher.php | 14 ++++++- app/Livewire/Servers/Show.php | 5 +++ tests/Feature/ServerContextSyncTest.php | 51 +++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/Feature/ServerContextSyncTest.php diff --git a/app/Livewire/ServerSwitcher.php b/app/Livewire/ServerSwitcher.php index fd29a30..1c3a086 100644 --- a/app/Livewire/ServerSwitcher.php +++ b/app/Livewire/ServerSwitcher.php @@ -18,7 +18,19 @@ class ServerSwitcher extends Component session(['active_server_id' => $server->id]); - $this->redirect($this->safeReturnUrl(), navigate: true); + $this->redirect($this->targetFor($server, $this->safeReturnUrl()), navigate: true); + } + + /** + * Where to land after selecting a server. On a server-details page, switching should + * VIEW the chosen server (so the URL, sidebar and scoped context never diverge); + * everywhere else just reload the current page so the active context updates. + */ + public function targetFor(Server $server, string $current): string + { + return preg_match('#^/servers/[^/]+#', $current) === 1 + ? route('servers.show', $server) + : $current; } /** diff --git a/app/Livewire/Servers/Show.php b/app/Livewire/Servers/Show.php index cb0dad5..04460e1 100644 --- a/app/Livewire/Servers/Show.php +++ b/app/Livewire/Servers/Show.php @@ -61,6 +61,11 @@ class Show extends Component */ public function mount(): void { + // Viewing a server's details makes it the ACTIVE server, so the sidebar switcher + // (and the server-scoped sections) always reflect the server on screen — no drift + // between the URL subject and the sidebar selection. + session(['active_server_id' => $this->server->id]); + // identity + gauges render from the persisted row immediately; // the live snapshot loads lazily via wire:init -> load(). } diff --git a/tests/Feature/ServerContextSyncTest.php b/tests/Feature/ServerContextSyncTest.php new file mode 100644 index 0000000..cd4610b --- /dev/null +++ b/tests/Feature/ServerContextSyncTest.php @@ -0,0 +1,51 @@ + $name, 'ip' => '10.0.0.'.rand(2, 250), 'ssh_port' => 22, 'status' => 'online']); + } + + public function test_viewing_server_details_sets_it_active(): void + { + $this->actingAs(User::factory()->create()); + $b = $this->server('B'); + + Livewire::test(Show::class, ['server' => $b]); + + $this->assertSame($b->id, session('active_server_id')); + } + + public function test_switching_on_a_details_page_targets_the_new_server(): void + { + $a = $this->server('A'); + $b = $this->server('B'); + $switcher = new ServerSwitcher; + + // On A's details page, selecting B targets B's details (not a reload of A). + $this->assertSame(route('servers.show', $b), $switcher->targetFor($b, '/servers/'.$a->uuid)); + } + + public function test_switching_elsewhere_keeps_the_current_page(): void + { + $b = $this->server('B'); + $switcher = new ServerSwitcher; + + // Off a server-details page, the current page is reloaded as-is. + $this->assertSame('/files', $switcher->targetFor($b, '/files')); + $this->assertSame('/servers', $switcher->targetFor($b, '/servers')); // fleet list, not a details page + } +}