Add toggleable wire:navigate SPA navigation with prefetching

Implement instance-wide SPA navigation toggle that enables smooth page transitions with prefetching on hover. Excludes terminal links which require full page lifecycle for WebSocket connections. Adds defensive checks to global-search component for SPA navigation compatibility.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2025-12-17 12:09:13 +01:00
parent 254b0a15e3
commit e709e2c131
78 changed files with 286 additions and 216 deletions

View File

@@ -289,7 +289,7 @@
</div>
@else
<div>Metrics are disabled for this server. Enable them in <a class="underline dark:text-white"
href="{{ route('server.show', ['server_uuid' => $server->uuid]) }}">General</a> settings.</div>
href="{{ route('server.show', ['server_uuid' => $server->uuid]) }}" {{ wireNavigate() }}>General</a> settings.</div>
@endif
</div>
</div>

View File

@@ -20,12 +20,12 @@
<h4 class="pt-4 pb-2">Available Destinations</h4>
<div class="flex gap-2">
@foreach ($server->standaloneDockers as $docker)
<a href="{{ route('destination.show', ['destination_uuid' => data_get($docker, 'uuid')]) }}">
<a href="{{ route('destination.show', ['destination_uuid' => data_get($docker, 'uuid')]) }}" {{ wireNavigate() }}>
<x-forms.button>{{ data_get($docker, 'network') }} </x-forms.button>
</a>
@endforeach
@foreach ($server->swarmDockers as $docker)
<a href="{{ route('destination.show', ['destination_uuid' => data_get($docker, 'uuid')]) }}">
<a href="{{ route('destination.show', ['destination_uuid' => data_get($docker, 'uuid')]) }}" {{ wireNavigate() }}>
<x-forms.button>{{ data_get($docker, 'network') }} </x-forms.button>
</a>
@endforeach

View File

@@ -13,7 +13,7 @@
<div class="subtitle">All your servers are here.</div>
<div class="grid gap-4 lg:grid-cols-2 -mt-1">
@forelse ($servers as $server)
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}" {{ wireNavigate() }}
@class([
'gap-2 border cursor-pointer coolbox group',
'border-red-500' =>

View File

@@ -65,14 +65,14 @@
class="flex items-center gap-6 overflow-x-scroll sm:overflow-x-hidden scrollbar min-h-10 whitespace-nowrap pt-2">
<a class="{{ request()->routeIs('server.show') ? 'dark:text-white' : '' }}" href="{{ route('server.show', [
'server_uuid' => data_get($server, 'uuid'),
]) }}">
]) }}" {{ wireNavigate() }}>
Configuration
</a>
@if (!$server->isSwarmWorker() && !$server->settings->is_build_server)
<a class="{{ request()->routeIs('server.proxy') ? 'dark:text-white' : '' }} flex items-center gap-1" href="{{ route('server.proxy', [
'server_uuid' => data_get($server, 'uuid'),
]) }}">
]) }}" {{ wireNavigate() }}>
Proxy
@if ($this->hasTraefikOutdated)
<svg class="w-4 h-4 text-warning" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
@@ -84,7 +84,7 @@
@endif
<a class="{{ request()->routeIs('server.resources') ? 'dark:text-white' : '' }}" href="{{ route('server.resources', [
'server_uuid' => data_get($server, 'uuid'),
]) }}">
]) }}" {{ wireNavigate() }}>
Resources
</a>
@can('canAccessTerminal')
@@ -97,7 +97,7 @@
@can('update', $server)
<a class="{{ request()->routeIs('server.security.patches') ? 'dark:text-white' : '' }}" href="{{ route('server.security.patches', [
'server_uuid' => data_get($server, 'uuid'),
]) }}">
]) }}" {{ wireNavigate() }}>
Security
</a>
@endcan

View File

@@ -68,7 +68,7 @@
{{ data_get($resource, 'environment.name') }}
</td>
<td class="px-5 py-4 text-sm whitespace-nowrap hover:underline">
<a class=""
<a class="" {{ wireNavigate() }}
href="{{ $resource->link() }}">{{ $resource->name }}
<x-internal-link /></a>
</td>

View File

@@ -19,7 +19,7 @@
<span class="text-xs text-neutral-500">(experimental)</span>
<x-helper
helper="Only available for apt, dnf and zypper package managers atm, more coming
soon.<br/>Status notifications sent every week.<br/>You can disable notifications in the <a class='dark:text-white underline' href='{{ route('notifications.email') }}'>notification settings</a>." />
soon.<br/>Status notifications sent every week.<br/>You can disable notifications in the <a class='dark:text-white underline' href='{{ route('notifications.email') }}' {{ wireNavigate() }}>notification settings</a>." />
@if (isDev())
<x-forms.button type="button" wire:click="sendTestEmail">
Send Test Email (dev only)</x-forms.button>