request('/cluster/resources', data: [ 'type' => 'node', ])->json()['data'] ?? []; return collect($nodes)->map(function ($node) { return [ 'label' => $node['node'], 'value' => $node['node'], ]; })->pluck('label', 'value'); } catch (\Throwable $e) { \Log::error('Failed to fetch Proxmox nodes: ' . $e->getMessage()); return collect(); } }); return $form ->schema([ Forms\Components\Select::make('name') ->label('Node') ->required() ->searchable() ->options($nodes) ->disabledOn('edit') ->live(onBlur: true) ->reactive(), Forms\Components\Select::make('location_id') ->label('Location') ->relationship('location', 'name') ->preload() ->searchable() ->required() ->disabled(fn (Get $get) => !$get('name')) ->helperText('Select a node group to assign this node to it.'), Forms\Components\TextInput::make('memory') ->label('RAM (MiB)') ->numeric() ->default(0) ->required() ->helperText('0 means no limit') ->disabled(fn (Get $get) => !$get('name')), Forms\Components\TextInput::make('disk') ->label('Disk (GiB)') ->numeric() ->default(0) ->required() ->helperText('0 means no limit') ->disabled(fn (Get $get) => !$get('name')), Forms\Components\TextInput::make('cpu') ->label('CPU Cores') ->numeric() ->default(0) ->required() ->helperText('0 means no limit') ->disabled(fn (Get $get) => !$get('name')), Forms\Components\TextInput::make('storage_location') ->label('Storage Location') ->required() ->default('local') ->maxLength(255) ->helperText('The storage location to use for this node, e.g., local, local-lvm') ->disabled(fn (Get $get) => !$get('name')), Forms\Components\TextInput::make('notes') ->label('Common Name') ->required() ->default('local') ->maxLength(255) ->disabled(fn (Get $get) => !$get('name')), Forms\Components\TextInput::make('backup_location') ->label('Backup Location') ->required() ->default('local') ->maxLength(255) ->helperText('The backup location to use for this node, e.g., local, local-lvm') ->disabled(fn (Get $get) => !$get('name')), Forms\Components\Toggle::make('vnc_enabled') ->label('VNC Enabled') ->default(true) ->helperText('Enable or disable VNC access for this node. (this requires the Proxmox instance to be on the same domain as the Paymenter installation)') ->required(), Forms\Components\Checkbox::make('is_lxc') ->label('LXC Container Node') ->default(false) ->helperText('Check to deploy LXC containers instead of KVM virtual machines on this node. Existing KVM nodes are unaffected.') ->disabled(fn (string $operation): bool => $operation === 'edit'), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('name') ->label('Node') ->sortable() ->searchable() ->toggleable(), Tables\Columns\TextColumn::make('notes') ->label('Common Name') ->sortable() ->searchable() ->toggleable(), Tables\Columns\TextColumn::make('location.name') ->label('Location') ->sortable() ->searchable() ->toggleable(), Tables\Columns\TextColumn::make('servers_count') ->label('Servers') ->counts('servers') ->sortable() ->searchable() ->toggleable(), Tables\Columns\IconColumn::make('is_lxc') ->label('Type') ->boolean() ->trueIcon('ri-checkbox-circle-fill') ->falseIcon('ri-close-circle-fill') ->trueColor('info') ->falseColor('gray') ->formatStateUsing(fn (bool $state): string => $state ? 'LXC' : 'KVM') ->toggleable(), ]) ->filters([ // ]) ->actions([ Tables\Actions\EditAction::make(), ]); } public static function getRelations(): array { return [ // ]; } public static function getPages(): array { return [ 'index' => Pages\ListNodes::route('/'), 'create' => Pages\CreateNode::route('/create'), 'edit' => Pages\EditNode::route('/{record}/edit'), ]; } }