loadUpdates(false); } protected function getAgent(): AgentClient { return $this->agent ??= new AgentClient; } public function loadUpdates(bool $refreshTable = true): void { try { $result = $this->getAgent()->updatesList(); $this->packages = $result['packages'] ?? []; $this->updatesLoaded = true; } catch (\Exception $e) { $this->packages = []; $this->updatesLoaded = true; Notification::make() ->title(__('Failed to load updates')) ->body($e->getMessage()) ->danger() ->send(); } if ($refreshTable) { $this->resetTable(); } } public function runUpdates(): void { try { $this->getAgent()->updatesRun(); Notification::make() ->title(__('Updates completed')) ->success() ->send(); } catch (\Exception $e) { Notification::make() ->title(__('Update failed')) ->body($e->getMessage()) ->danger() ->send(); } $this->loadUpdates(); } public function table(Table $table): Table { return $table ->records(function () { if (! $this->updatesLoaded) { $this->loadUpdates(false); } return collect($this->packages) ->mapWithKeys(function (array $package, int $index): array { $keyParts = [ $package['name'] ?? (string) $index, $package['current_version'] ?? '', $package['new_version'] ?? '', ]; $key = implode('|', array_filter($keyParts, fn (string $part): bool => $part !== '')); return [$key !== '' ? $key : (string) $index => $package]; }) ->all(); }) ->columns([ TextColumn::make('name') ->label(__('Package')) ->searchable(), TextColumn::make('current_version') ->label(__('Current Version')), TextColumn::make('new_version') ->label(__('New Version')), ]) ->emptyStateHeading(__('No updates available')) ->emptyStateDescription(__('Your system packages are up to date.')) ->headerActions([ Action::make('refresh') ->label(__('Refresh')) ->icon('heroicon-o-arrow-path') ->action(fn () => $this->loadUpdates()), Action::make('runUpdates') ->label(__('Run Updates')) ->icon('heroicon-o-arrow-path-rounded-square') ->color('primary') ->requiresConfirmation() ->modalHeading(__('Install updates')) ->modalDescription(__('This will run apt-get upgrade on the server. Continue?')) ->action(fn () => $this->runUpdates()), ]); } }