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
+5 -3
View File
@@ -32,7 +32,7 @@ class Charts extends Component
}
}
public function toggleMetrics()
public function toggleMetrics(): void
{
try {
$this->authorize('update', $this->server);
@@ -42,14 +42,16 @@ class Charts extends Component
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);
}
}
+3 -2
View File
@@ -104,7 +104,7 @@ class Sentinel extends Component
}
}
public function toggleSentinel()
public function toggleSentinel(): void
{
try {
$this->authorize('manageSentinel', $this->server);
@@ -124,8 +124,9 @@ class Sentinel extends Component
StopSentinel::dispatch($this->server);
}
$this->submit();
$this->dispatch('refreshServerShow');
} catch (\Throwable $e) {
return handleError($e, $this);
handleError($e, $this);
}
}
+6 -8
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');
}
+5 -4
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');
}
@@ -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>
@@ -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." />
@@ -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');");
});