diff --git a/app/Livewire/Project/Shared/ExecuteContainerCommand.php b/app/Livewire/Project/Shared/ExecuteContainerCommand.php index 13fffea7e..97131c75c 100644 --- a/app/Livewire/Project/Shared/ExecuteContainerCommand.php +++ b/app/Livewire/Project/Shared/ExecuteContainerCommand.php @@ -27,15 +27,9 @@ class ExecuteContainerCommand extends Component public Collection $servers; - public bool $containersLoaded = false; + public bool $hasShell = true; - public bool $autoConnectAttempted = false; - - public bool $isConnecting = false; - - public bool $isConnected = false; - - public string $connectionStatus = 'Loading containers...'; + public bool $isConnecting = true; protected $rules = [ 'server' => 'required', @@ -43,32 +37,22 @@ class ExecuteContainerCommand extends Component 'command' => 'required', ]; - public function getListeners() - { - $teamId = auth()->user()->currentTeam()->id; - - return [ - "echo-private:team.{$teamId},ServiceChecked" => '$refresh', - ]; - } - public function mount() { if (! auth()->user()->isAdmin()) { abort(403); } - $this->parameters = get_route_parameters(); $this->containers = collect(); $this->servers = collect(); if (data_get($this->parameters, 'application_uuid')) { $this->type = 'application'; - $this->resource = Application::whereUuid($this->parameters['application_uuid'])->firstOrFail(); - if ($this->resource->destination->server->isFunctional() && $this->resource->destination->server->isTerminalEnabled()) { + $this->resource = Application::where('uuid', $this->parameters['application_uuid'])->firstOrFail(); + if ($this->resource->destination->server->isFunctional()) { $this->servers = $this->servers->push($this->resource->destination->server); } foreach ($this->resource->additional_servers as $server) { - if ($server->isFunctional() && $server->isTerminalEnabled()) { + if ($server->isFunctional()) { $this->servers = $this->servers->push($server); } } @@ -80,23 +64,21 @@ class ExecuteContainerCommand extends Component abort(404); } $this->resource = $resource; - if ($this->resource->destination->server->isFunctional() && $this->resource->destination->server->isTerminalEnabled()) { + if ($this->resource->destination->server->isFunctional()) { $this->servers = $this->servers->push($this->resource->destination->server); } $this->loadContainers(); } elseif (data_get($this->parameters, 'service_uuid')) { $this->type = 'service'; - $this->resource = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail(); - if ($this->resource->server->isFunctional() && $this->resource->server->isTerminalEnabled()) { + $this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail(); + if ($this->resource->server->isFunctional()) { $this->servers = $this->servers->push($this->resource->server); } $this->loadContainers(); } elseif (data_get($this->parameters, 'server_uuid')) { $this->type = 'server'; - $this->resource = Server::ownedByCurrentTeam()->whereUuid($this->parameters['server_uuid'])->firstOrFail(); + $this->resource = Server::where('uuid', $this->parameters['server_uuid'])->firstOrFail(); $this->server = $this->resource; - $this->containersLoaded = true; // Server doesn't need container loading - $this->connectionStatus = 'Waiting for terminal to be ready...'; } } @@ -161,66 +143,6 @@ class ExecuteContainerCommand extends Component if ($this->containers->count() === 1) { $this->selected_container = data_get($this->containers->first(), 'container.Names'); } - - $this->containersLoaded = true; - $this->connectionStatus = 'Waiting for terminal to be ready...'; - } - - public function initializeTerminalConnection() - { - try { - // Only auto-connect if containers are loaded and we haven't attempted before - if (! $this->containersLoaded || $this->autoConnectAttempted || $this->isConnecting) { - return; - } - - $this->autoConnectAttempted = true; - - // Ensure component is in a stable state before proceeding - $this->skipRender(); - - $this->isConnecting = true; - - if ($this->type === 'server') { - $this->connectionStatus = 'Establishing connection to server terminal...'; - $this->connectToServer(); - } elseif ($this->containers->count() === 1) { - $this->connectionStatus = 'Establishing connection to container terminal...'; - $this->connectToContainer(); - } else { - $this->isConnecting = false; - $this->connectionStatus = ''; - } - } catch (\Throwable $e) { - // Log the error but don't let it bubble up to cause snapshot issues - logger()->error('Terminal auto-connection failed', [ - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - 'component_id' => $this->getId(), - ]); - - // Reset state to allow manual connection - $this->autoConnectAttempted = false; - $this->isConnecting = false; - $this->connectionStatus = 'Auto-connection failed. Please use the reconnect button.'; - } - } - - #[On('terminalConnected')] - public function terminalConnected() - { - $this->isConnected = true; - $this->isConnecting = false; - $this->connectionStatus = ''; - } - - #[On('terminalDisconnected')] - public function terminalDisconnected() - { - $this->isConnected = false; - $this->isConnecting = false; - $this->autoConnectAttempted = false; - $this->connectionStatus = 'Connection lost. Click Reconnect to try again.'; } private function checkShellAvailability(Server $server, string $container): bool @@ -245,11 +167,6 @@ class ExecuteContainerCommand extends Component if ($this->server->isForceDisabled()) { throw new \RuntimeException('Server is disabled.'); } - if (! $this->server->isTerminalEnabled()) { - throw new \RuntimeException('Terminal access is disabled on this server.'); - } - $this->isConnecting = true; - $this->connectionStatus = 'Establishing connection to server terminal...'; $this->dispatch( 'send-terminal-command', false, @@ -257,10 +174,9 @@ class ExecuteContainerCommand extends Component data_get($this->server, 'uuid') ); } catch (\Throwable $e) { - $this->isConnecting = false; - $this->connectionStatus = 'Connection failed.'; - return handleError($e, $this); + } finally { + $this->isConnecting = false; } } @@ -306,8 +222,11 @@ class ExecuteContainerCommand extends Component throw new \RuntimeException('Server ownership verification failed.'); } - $this->isConnecting = true; - $this->connectionStatus = 'Establishing connection to container terminal...'; + $this->hasShell = $this->checkShellAvailability($server, data_get($container, 'container.Names')); + if (! $this->hasShell) { + return; + } + $this->dispatch( 'send-terminal-command', true, @@ -315,10 +234,9 @@ class ExecuteContainerCommand extends Component data_get($container, 'server.uuid') ); } catch (\Throwable $e) { - $this->isConnecting = false; - $this->connectionStatus = 'Connection failed.'; - return handleError($e, $this); + } finally { + $this->isConnecting = false; } } diff --git a/app/Livewire/Project/Shared/Terminal.php b/app/Livewire/Project/Shared/Terminal.php index 521027f49..52b209529 100644 --- a/app/Livewire/Project/Shared/Terminal.php +++ b/app/Livewire/Project/Shared/Terminal.php @@ -44,7 +44,7 @@ class Terminal extends Component public function sendTerminalCommand($isContainer, $identifier, $serverUuid) { $server = Server::ownedByCurrentTeam()->whereUuid($serverUuid)->firstOrFail(); - if (! $server->isTerminalEnabled()) { + if (! $server->isTerminalEnabled() || $server->isForceDisabled()) { throw new \RuntimeException('Terminal access is disabled on this server.'); } diff --git a/resources/views/livewire/project/shared/execute-container-command.blade.php b/resources/views/livewire/project/shared/execute-container-command.blade.php index 9b81b4647..ff0cf619c 100644 --- a/resources/views/livewire/project/shared/execute-container-command.blade.php +++ b/resources/views/livewire/project/shared/execute-container-command.blade.php @@ -17,178 +17,65 @@ @endif - @if ($type === 'server') - @if (!$server->isForceDisabled() && $server->isTerminalEnabled()) -
+ @if (!$hasShell) +
+
+
+ + + +
+

Terminal Not Available

+

No shell (bash/sh) is available in this container. Please + ensure either bash or sh is installed to use the terminal.

+
+
+
+
+ @else + @if ($type === 'server') +

Terminal

- - Reconnect - - {{-- Loading indicator for all connection states --}} - @if (!$containersLoaded || $isConnecting || $connectionStatus) - {{ $connectionStatus }} - @endif + {{ $isConnecting ? 'Connecting...' : 'Reconnect' }}
- +
@else -
Terminal access is disabled on this server.
- @endif - @else - @if (count($containers) === 0) -
No containers are running on this server or terminal access is disabled.
- @else - @if (count($containers) === 1) -
-

Terminal

- - Reconnect - -
- - {{-- Loading indicator for all connection states --}} - @if (!$containersLoaded || $isConnecting || $connectionStatus) - {{ $connectionStatus }} - @endif + @if (count($containers) === 0) +
No containers are running.
@else -
- - @foreach ($containers as $container) - @if ($loop->first) - - @endif - - @endforeach - - - {{ $isConnecting ? 'Connecting...' : 'Connect' }} - -
- - {{-- Loading indicator for manual connection --}} - @if ($isConnecting || $connectionStatus) - {{ $connectionStatus }} + @if (count($containers) === 1) +
+

Terminal

+ {{ $isConnecting ? 'Connecting...' : 'Reconnect' }} +
+ @else +
+ + @foreach ($containers as $container) + @if ($loop->first) + + @endif + + @endforeach + + {{ $isConnecting ? 'Connecting...' : 'Connect' }} +
@endif +
+ +
@endif -
- -
@endif @endif - - @script - - @endscript