Dynamic server status (#803)

* Better readability

* Force refresh the server instance

* Use kebab case for these

* Fix phpstan

* Retry a little longer

* Updates

* Add pint

* Don’t need this

* Pint fix
This commit is contained in:
Lance Pioch 2024-12-10 17:36:14 -05:00 committed by GitHub
parent 3dfdc70790
commit ef1ae72d06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 107 additions and 32 deletions

View File

@ -52,4 +52,35 @@ enum ContainerStatus: string
self::Offline => 'gray',
};
}
public function isStartingOrStopping(): bool
{
return in_array($this, [ContainerStatus::Starting, ContainerStatus::Stopping, ContainerStatus::Restarting]);
}
public function isStartable(): bool
{
return !in_array($this, [ContainerStatus::Running, ContainerStatus::Starting, ContainerStatus::Stopping, ContainerStatus::Restarting]);
}
public function isRestartable(): bool
{
if ($this->isStartable()) {
return true;
}
return !in_array($this, [ContainerStatus::Offline]);
}
public function isStoppable(): bool
{
return !in_array($this, [ContainerStatus::Starting, ContainerStatus::Stopping, ContainerStatus::Restarting, ContainerStatus::Exited, ContainerStatus::Offline]);
}
public function isKillable(): bool
{
// [ContainerStatus::Restarting, ContainerStatus::Removing, ContainerStatus::Dead, ContainerStatus::Created]
return !in_array($this, [ContainerStatus::Offline, ContainerStatus::Running, ContainerStatus::Exited]);
}
}

View File

@ -23,7 +23,7 @@ class Console extends Page
protected static string $view = 'filament.server.pages.console';
public ContainerStatus $status = ContainerStatus::Missing;
public ContainerStatus $status = ContainerStatus::Offline;
public function getWidgetData(): array
{
@ -54,10 +54,12 @@ class Console extends Page
return 3;
}
#[On('powerChanged')]
public function powerChanged(string $state): void
#[On('console-status')]
public function receivedConsoleUpdate(?string $state = null): void
{
$this->status = ContainerStatus::from($state);
if ($state) {
$this->status = ContainerStatus::from($state);
}
$this->cachedHeaderActions = [];
@ -74,18 +76,18 @@ class Console extends Page
->color('primary')
->size(ActionSize::ExtraLarge)
->action(fn () => $this->dispatch('setServerState', state: 'start'))
->disabled(fn () => $server->isInConflictState() || in_array($this->status, [ContainerStatus::Running, ContainerStatus::Starting, ContainerStatus::Stopping, ContainerStatus::Restarting])),
->disabled(fn () => $server->isInConflictState() || !$this->status->isStartable()),
Action::make('restart')
->color('gray')
->size(ActionSize::ExtraLarge)
->action(fn () => $this->dispatch('setServerState', state: 'restart'))
->disabled(fn () => $server->isInConflictState() || $this->status !== ContainerStatus::Running),
->disabled(fn () => $server->isInConflictState() || !$this->status->isRestartable()),
Action::make('stop')
->color('danger')
->size(ActionSize::ExtraLarge)
->action(fn () => $this->dispatch('setServerState', state: 'stop'))
->hidden(fn () => in_array($this->status, [ContainerStatus::Stopping, ContainerStatus::Restarting, ContainerStatus::Starting]))
->disabled(fn () => $server->isInConflictState() || in_array($this->status, [ContainerStatus::Starting, ContainerStatus::Stopping, ContainerStatus::Restarting, ContainerStatus::Exited, ContainerStatus::Offline])),
->hidden(fn () => $this->status->isStartingOrStopping() || $this->status->isKillable())
->disabled(fn () => $server->isInConflictState() || !$this->status->isStoppable()),
Action::make('kill')
->color('danger')
->requiresConfirmation()
@ -94,8 +96,7 @@ class Console extends Page
->modalSubmitActionLabel('Kill Server')
->size(ActionSize::ExtraLarge)
->action(fn () => $this->dispatch('setServerState', state: 'kill'))
->hidden(fn () => $server->isInConflictState() || in_array($this->status, [ContainerStatus::Running, ContainerStatus::Restarting, ContainerStatus::Offline, ContainerStatus::Removing, ContainerStatus::Dead, ContainerStatus::Exited, ContainerStatus::Created]))
->disabled(fn () => $server->isInConflictState() || $this->status === ContainerStatus::Offline),
->hidden(fn () => $server->isInConflictState() || !$this->status->isKillable()),
];
}
}

View File

@ -88,7 +88,7 @@ class ServerConsole extends Widget
}
}
#[On('storeStats')]
#[On('store-stats')]
public function storeStats(string $data): void
{
$data = json_decode($data);

View File

@ -0,0 +1,34 @@
<?php
namespace App\Livewire;
use App\Models\Server;
use Filament\Facades\Filament;
use Illuminate\View\View;
use Livewire\Attributes\On;
use Livewire\Component;
class ServerConflictBanner extends Component
{
public ?Server $server = null;
public function mount(): void
{
/** @var Server $server */
$server = Filament::getTenant();
$this->server = $server;
}
#[On('console-install-completed')]
#[On('console-install-started')]
#[On('console-status')]
public function refresh(?string $state = null): void
{
$this->server->fresh();
}
public function render(): View
{
return view('livewire.server-conflict-banner');
}
}

View File

@ -126,7 +126,7 @@
case 'status':
handlePowerChangeEvent(args[0]);
$wire.dispatch('powerChanged', {state: args[0]})
$wire.dispatch('console-status', {state: args[0]})
break;
case 'transfer status':
handleTransferStatus(args[0]);
@ -135,7 +135,7 @@
handleDaemonErrorOutput(args[0]);
break;
case 'stats':
$wire.dispatchSelf('storeStats', { data: args[0] });
$wire.dispatchSelf('store-stats', { data: args[0] });
break;
case 'auth success':
socket.send(JSON.stringify({
@ -143,6 +143,12 @@
'args': [null]
}));
break;
case 'install started':
$wire.dispatch('console-install-started');
break;
case 'install completed':
$wire.dispatch('console-install-completed');
break;
case 'token expiring':
case 'token expired':
token = '{{ $this->getToken() }}';

View File

@ -1,19 +1 @@
@php
$shouldShow = false;
try {
\Filament\Facades\Filament::getTenant()->validateCurrentState();
} catch (\App\Exceptions\Http\Server\ServerStateConflictException $exception) {
$shouldShow = true;
$message = $exception->getMessage();
}
@endphp
@if ($shouldShow)
<div class="mt-2 p-2 rounded-lg text-white" style="background-color: #D97706;">
<div class="flex items-center">
<x-filament::icon icon="tabler-alert-triangle" class="h-6 w-6 mr-2 text-gray-500 dark:text-gray-400 text-white" />
<p>{!! $message !!}</p>
</div>
</div>
@endif
<livewire:server-conflict-banner />

View File

@ -0,0 +1,21 @@
@php
$shouldShow = false;
try {
$server->validateCurrentState();
} catch (\App\Exceptions\Http\Server\ServerStateConflictException $exception) {
$shouldShow = true;
$message = $exception->getMessage();
}
@endphp
<div id="server-conflict-banner">
@if ($shouldShow)
<div class="mt-2 p-2 rounded-lg text-white" style="background-color: #D97706;">
<div class="flex items-center">
<x-filament::icon icon="tabler-alert-triangle" class="h-6 w-6 mr-2 text-gray-500 dark:text-gray-400 text-white" />
<p>{!! $message !!}</p>
</div>
</div>
@endif
</div>