fix(sentinel): refresh server nav after toggles

Dispatch server show refreshes after Sentinel and metrics toggles, preserve editable Sentinel form fields during restart events, and gate custom image editing by update permission.
This commit is contained in:
Andras Bacsai 2026-06-03 11:10:13 +02:00
parent 2d2634f87b
commit d892d0ad10
7 changed files with 43 additions and 19 deletions

View file

@ -32,7 +32,7 @@ public function mount(string $server_uuid)
}
}
public function toggleMetrics()
public function toggleMetrics(): void
{
try {
$this->authorize('update', $this->server);
@ -42,14 +42,16 @@ public function toggleMetrics()
if ($this->server->isMetricsEnabled()) {
StartSentinel::run($this->server, true);
$this->dispatch('success', 'Metrics enabled. Restarting Sentinel.');
$this->dispatch('success', 'Metrics enabled. Starting Sentinel.');
$this->dispatch('refreshServerShow');
$this->redirect(route('server.metrics', ['server_uuid' => $this->server->uuid]), navigate: true);
} else {
$this->server->restartSentinel();
$this->dispatch('success', 'Metrics disabled. Restarting Sentinel.');
$this->dispatch('refreshServerShow');
}
} catch (\Throwable $e) {
return handleError($e, $this);
handleError($e, $this);
}
}

View file

@ -104,7 +104,7 @@ public function restartSentinel()
}
}
public function toggleSentinel()
public function toggleSentinel(): void
{
try {
$this->authorize('manageSentinel', $this->server);
@ -124,8 +124,9 @@ public function toggleSentinel()
StopSentinel::dispatch($this->server);
}
$this->submit();
$this->dispatch('refreshServerShow');
} catch (\Throwable $e) {
return handleError($e, $this);
handleError($e, $this);
}
}

View file

@ -3,28 +3,26 @@
namespace App\Livewire\Server\Sentinel;
use App\Models\Server;
use Illuminate\View\View;
use Livewire\Component;
class Logs extends Component
{
public ?Server $server = null;
public $parameters = [];
public array $parameters = [];
public function mount()
public function mount(): void
{
$this->parameters = get_route_parameters();
try {
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
if (is_null($this->server)) {
return redirect()->route('server.index');
}
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail();
} catch (\Throwable $e) {
return handleError($e, $this);
handleError($e, $this);
}
}
public function render()
public function render(): View
{
return view('livewire.server.sentinel.logs');
}

View file

@ -3,25 +3,26 @@
namespace App\Livewire\Server\Sentinel;
use App\Models\Server;
use Illuminate\View\View;
use Livewire\Component;
class Show extends Component
{
public ?Server $server = null;
public $parameters = [];
public array $parameters = [];
public function mount()
public function mount(): void
{
$this->parameters = get_route_parameters();
try {
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail();
} catch (\Throwable $e) {
return handleError($e, $this);
handleError($e, $this);
}
}
public function render()
public function render(): View
{
return view('livewire.server.sentinel.show');
}

View file

@ -3,7 +3,7 @@
href="{{ route('server.sentinel', $parameters) }}">
<span class="menu-item-label">Configuration</span>
</a>
<a class="{{ request()->routeIs('server.sentinel.logs') ? 'sub-menu-item menu-item-active' : 'sub-menu-item' }}"
<a class="{{ request()->routeIs('server.sentinel.logs') ? 'sub-menu-item menu-item-active' : 'sub-menu-item' }}" {{ wireNavigate() }}
href="{{ route('server.sentinel.logs', $parameters) }}">
<span class="menu-item-label">Logs</span>
</a>

View file

@ -35,7 +35,8 @@
$wire.set('sentinelCustomDockerImage', this.customImage);
}
}" x-init="$wire.set('sentinelCustomDockerImage', customImage)">
<x-forms.input x-model="customImage" @input.debounce.500ms="saveCustomImage()"
<x-forms.input canGate="update" :canResource="$server" x-model="customImage"
@input.debounce.500ms="saveCustomImage()"
placeholder="e.g., sentinel:latest or myregistry/sentinel:dev"
label="Custom Sentinel Docker Image (Dev Only)"
helper="Override the default Sentinel Docker image for testing. Leave empty to use the default." />

View file

@ -0,0 +1,21 @@
<?php
it('keeps sentinel restarted events from re-syncing editable form fields', function () {
$componentSource = file_get_contents(app_path('Livewire/Server/Sentinel.php'));
preg_match('/public function handleSentinelRestarted\([^)]*\)\s*\{(?<body>.*?)\n \}/s', $componentSource, $matches);
expect($matches['body'] ?? '')
->toContain('$this->sentinelUpdatedAt = $this->server->sentinel_updated_at;')
->not->toContain('$this->syncData();');
});
it('dispatches a server navbar refresh after toggling sentinel', function () {
$componentSource = file_get_contents(app_path('Livewire/Server/Sentinel.php'));
preg_match('/public function toggleSentinel\([^)]*\).*?\{(?<body>.*?)
\}/s', $componentSource, $matches);
expect($matches['body'] ?? '')
->toContain("\$this->dispatch('refreshServerShow');");
});