fix(ui): re-sync active server on bfcache restore of a details page
wire:navigate restores Back/Forward pages from its client cache without re-running Show::mount(), which could leave active_server_id pointing at a different server than the details page on screen. Add a servers.activate endpoint + a global livewire:navigated hook that re-asserts the on-screen server on every navigation (including cache restores). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>feat/v1-foundation
parent
784566d06b
commit
6e0ec724ca
|
|
@ -198,3 +198,17 @@ document.addEventListener('alpine:init', () => {
|
|||
},
|
||||
}));
|
||||
});
|
||||
|
||||
// Keep the active-server session in sync with the server-details page on screen, even
|
||||
// when wire:navigate restores a page from its bfcache (Back/Forward) without re-running
|
||||
// Show::mount(). The details page tags its root with data-clusev-activate=<activate URL>.
|
||||
document.addEventListener('livewire:navigated', () => {
|
||||
const el = document.querySelector('[data-clusev-activate]');
|
||||
if (!el) return;
|
||||
const token = document.querySelector('meta[name="csrf-token"]')?.content;
|
||||
fetch(el.dataset.clusevActivate, {
|
||||
method: 'POST',
|
||||
headers: { 'X-CSRF-TOKEN': token ?? '', 'X-Requested-With': 'XMLHttpRequest' },
|
||||
keepalive: true,
|
||||
}).catch(() => {});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
];
|
||||
@endphp
|
||||
|
||||
<div class="space-y-5" wire:poll.10s="pollMetrics" wire:init="load">
|
||||
<div class="space-y-5" wire:poll.10s="pollMetrics" wire:init="load" data-clusev-activate="{{ route('servers.activate', $server) }}">
|
||||
<a href="{{ route('servers.index') }}"
|
||||
class="inline-flex min-h-11 items-center gap-1.5 font-mono text-[11px] uppercase tracking-[0.2em] text-ink-3 hover:text-ink-2">
|
||||
<x-icon name="switcher" class="h-3.5 w-3.5 rotate-90" />
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use App\Livewire\Services;
|
|||
use App\Livewire\Settings;
|
||||
use App\Livewire\System;
|
||||
use App\Livewire\Versions;
|
||||
use App\Models\Server;
|
||||
use App\Services\DeploymentService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth as AuthFacade;
|
||||
|
|
@ -80,6 +81,14 @@ Route::middleware('auth')->group(function () {
|
|||
|
||||
Route::get('/servers', Servers\Index::class)->name('servers.index');
|
||||
Route::get('/servers/{server}', Servers\Show::class)->name('servers.show');
|
||||
// Re-assert the active server when a details page is shown — incl. a wire:navigate
|
||||
// bfcache restore (Back/Forward), which never re-runs Show::mount(). A tiny JS hook
|
||||
// on `livewire:navigated` posts here so the session context never drifts.
|
||||
Route::post('/servers/{server}/activate', function (Server $server) {
|
||||
session(['active_server_id' => $server->id]);
|
||||
|
||||
return response()->noContent();
|
||||
})->name('servers.activate');
|
||||
|
||||
Route::get('/services', Services\Index::class)->name('services.index');
|
||||
Route::get('/files', Files\Index::class)->name('files.index');
|
||||
|
|
|
|||
|
|
@ -19,6 +19,16 @@ class ServerContextSyncTest extends TestCase
|
|||
return Server::create(['name' => $name, 'ip' => '10.0.0.'.rand(2, 250), 'ssh_port' => 22, 'status' => 'online']);
|
||||
}
|
||||
|
||||
public function test_activate_endpoint_sets_active_server(): void
|
||||
{
|
||||
$this->actingAs(User::factory()->create());
|
||||
$b = $this->server('B');
|
||||
|
||||
$this->post(route('servers.activate', $b))->assertNoContent();
|
||||
|
||||
$this->assertSame($b->id, session('active_server_id'));
|
||||
}
|
||||
|
||||
public function test_viewing_server_details_sets_it_active(): void
|
||||
{
|
||||
$this->actingAs(User::factory()->create());
|
||||
|
|
|
|||
Loading…
Reference in New Issue