diff --git a/app/Filament/Resources/EggResource/Pages/CreateEgg.php b/app/Filament/Resources/EggResource/Pages/CreateEgg.php index 5dfa3b05f..1870fd3c2 100644 --- a/app/Filament/Resources/EggResource/Pages/CreateEgg.php +++ b/app/Filament/Resources/EggResource/Pages/CreateEgg.php @@ -15,9 +15,9 @@ use Filament\Forms\Components\TagsInput; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; +use Filament\Forms\Set; use Filament\Resources\Pages\CreateRecord; use AbdelhamidErrahmouni\FilamentMonacoEditor\MonacoEditor; -use Filament\Forms; use Filament\Forms\Form; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; @@ -155,7 +155,7 @@ class CreateEgg extends CreateRecord ->debounce(750) ->maxLength(255) ->columnSpanFull() - ->afterStateUpdated(fn (Forms\Set $set, $state) => $set('env_variable', str($state)->trim()->snake()->upper()->toString()) + ->afterStateUpdated(fn (Set $set, $state) => $set('env_variable', str($state)->trim()->snake()->upper()->toString()) ) ->required(), Textarea::make('description')->columnSpanFull(), diff --git a/app/Filament/Resources/EggResource/Pages/EditEgg.php b/app/Filament/Resources/EggResource/Pages/EditEgg.php index 212aec8f2..b9d34b0df 100644 --- a/app/Filament/Resources/EggResource/Pages/EditEgg.php +++ b/app/Filament/Resources/EggResource/Pages/EditEgg.php @@ -10,7 +10,6 @@ use App\Services\Eggs\Sharing\EggExporterService; use App\Services\Eggs\Sharing\EggImporterService; use Exception; use Filament\Actions; -use Filament\Forms; use Filament\Forms\Components\Checkbox; use Filament\Forms\Components\Fieldset; use Filament\Forms\Components\FileUpload; @@ -26,6 +25,7 @@ use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; use Filament\Forms\Form; +use Filament\Forms\Set; use Filament\Notifications\Notification; use Filament\Resources\Pages\EditRecord; @@ -165,7 +165,7 @@ class EditEgg extends EditRecord ->debounce(750) ->maxLength(255) ->columnSpanFull() - ->afterStateUpdated(fn (Forms\Set $set, $state) => $set('env_variable', str($state)->trim()->snake()->upper()->toString()) + ->afterStateUpdated(fn (Set $set, $state) => $set('env_variable', str($state)->trim()->snake()->upper()->toString()) ) ->required(), Textarea::make('description')->columnSpanFull(), @@ -212,21 +212,17 @@ class EditEgg extends EditRecord Tab::make('Install Script') ->columns(3) ->schema([ - Select::make('copy_script_from') ->placeholder('None') ->relationship('scriptFrom', 'name', ignoreRecord: true), - TextInput::make('script_container') ->required() ->maxLength(255) ->default('alpine:3.4'), - TextInput::make('script_entry') ->required() ->maxLength(255) ->default('ash'), - MonacoEditor::make('script_install') ->label('Install Script') ->columnSpanFull() diff --git a/app/Filament/Resources/ServerResource/Pages/CreateServer.php b/app/Filament/Resources/ServerResource/Pages/CreateServer.php index acdbcab4d..3c48f7395 100644 --- a/app/Filament/Resources/ServerResource/Pages/CreateServer.php +++ b/app/Filament/Resources/ServerResource/Pages/CreateServer.php @@ -12,7 +12,24 @@ use App\Services\Servers\RandomWordService; use App\Services\Servers\ServerCreationService; use App\Services\Users\UserCreationService; use Filament\Forms\Components\Actions\Action; +use Filament\Forms\Components\CheckboxList; +use Filament\Forms\Components\Component; +use Filament\Forms\Components\Fieldset; +use Filament\Forms\Components\Grid; +use Filament\Forms\Components\Hidden; +use Filament\Forms\Components\KeyValue; +use Filament\Forms\Components\Placeholder; +use Filament\Forms\Components\Repeater; +use Filament\Forms\Components\Section; +use Filament\Forms\Components\Select; +use Filament\Forms\Components\TagsInput; +use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TextInput; +use Filament\Forms\Components\ToggleButtons; +use Filament\Forms\Components\Wizard\Step; use Filament\Forms\Form; +use Filament\Forms\Get; +use Filament\Forms\Set; use Filament\Resources\Pages\CreateRecord; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; @@ -35,7 +52,7 @@ class CreateServer extends CreateRecord return $form ->schema([ Wizard::make([ - Wizard\Step::make('Information') + Step::make('Information') ->label('Information') ->icon('tabler-info-circle') ->completedIcon('tabler-check') @@ -46,12 +63,12 @@ class CreateServer extends CreateRecord 'lg' => 6, ]) ->schema([ - Forms\Components\TextInput::make('name') + TextInput::make('name') ->prefixIcon('tabler-server') ->label('Name') ->suffixAction(Forms\Components\Actions\Action::make('random') ->icon('tabler-dice-' . random_int(1, 6)) - ->action(function (Forms\Set $set, Forms\Get $get) { + ->action(function (Set $set, Get $get) { $egg = Egg::find($get('egg_id')); $prefix = $egg ? str($egg->name)->lower()->kebab() . '-' : ''; @@ -68,7 +85,7 @@ class CreateServer extends CreateRecord ->required() ->maxLength(255), - Forms\Components\Select::make('owner_id') + Select::make('owner_id') ->preload() ->prefixIcon('tabler-user') ->default(auth()->user()->id) @@ -83,18 +100,18 @@ class CreateServer extends CreateRecord ->searchable(['username', 'email']) ->getOptionLabelFromRecordUsing(fn (User $user) => "$user->email | $user->username " . ($user->isRootAdmin() ? '(admin)' : '')) ->createOptionForm([ - Forms\Components\TextInput::make('username') + TextInput::make('username') ->alphaNum() ->required() ->maxLength(255), - Forms\Components\TextInput::make('email') + TextInput::make('email') ->email() ->required() ->unique() ->maxLength(255), - Forms\Components\TextInput::make('password') + TextInput::make('password') ->hintIcon('tabler-question-mark') ->hintIconTooltip('Providing a user password is optional. New user email will prompt users to create a password the first time they login.') ->password(), @@ -105,7 +122,7 @@ class CreateServer extends CreateRecord }) ->required(), - Forms\Components\Select::make('node_id') + Select::make('node_id') ->disabledOn('edit') ->prefixIcon('tabler-server-2') ->default(fn () => ($this->node = Node::query()->latest()->first())?->id) @@ -119,13 +136,13 @@ class CreateServer extends CreateRecord ->relationship('node', 'name') ->searchable() ->preload() - ->afterStateUpdated(function (Forms\Set $set, $state) { + ->afterStateUpdated(function (Set $set, $state) { $set('allocation_id', null); $this->node = Node::find($state); }) ->required(), - Forms\Components\Select::make('allocation_id') + Select::make('allocation_id') ->preload() ->live() ->prefixIcon('tabler-network') @@ -136,9 +153,9 @@ class CreateServer extends CreateRecord 'md' => 2, 'lg' => 3, ]) - ->disabled(fn (Forms\Get $get) => $get('node_id') === null) + ->disabled(fn (Get $get) => $get('node_id') === null) ->searchable(['ip', 'port', 'ip_alias']) - ->afterStateUpdated(function (Forms\Set $set) { + ->afterStateUpdated(function (Set $set) { $set('allocation_additional', null); $set('allocation_additional.needstobeastringhere.extra_allocations', null); }) @@ -146,7 +163,7 @@ class CreateServer extends CreateRecord fn (Allocation $allocation) => "$allocation->ip:$allocation->port" . ($allocation->ip_alias ? " ($allocation->ip_alias)" : '') ) - ->placeholder(function (Forms\Get $get) { + ->placeholder(function (Get $get) { $node = Node::find($get('node_id')); if ($node?->allocations) { @@ -158,12 +175,12 @@ class CreateServer extends CreateRecord ->relationship( 'allocation', 'ip', - fn (Builder $query, Forms\Get $get) => $query + fn (Builder $query, Get $get) => $query ->where('node_id', $get('node_id')) ->whereNull('server_id'), ) - ->createOptionForm(fn (Forms\Get $get) => [ - Forms\Components\TextInput::make('allocation_ip') + ->createOptionForm(fn (Get $get) => [ + TextInput::make('allocation_ip') ->datalist(Node::find($get('node_id'))?->ipAddresses() ?? []) ->label('IP Address') ->inlineLabel() @@ -171,7 +188,7 @@ class CreateServer extends CreateRecord ->helperText("Usually your machine's public IP unless you are port forwarding.") // ->selectablePlaceholder(false) ->required(), - Forms\Components\TextInput::make('allocation_alias') + TextInput::make('allocation_alias') ->label('Alias') ->inlineLabel() ->default(null) @@ -181,7 +198,7 @@ class CreateServer extends CreateRecord ]) ->helperText('Optional display name to help you remember what these are.') ->required(false), - Forms\Components\TagsInput::make('allocation_ports') + TagsInput::make('allocation_ports') ->placeholder('Examples: 27015, 27017-27019') ->helperText(new HtmlString(' These are the ports that users can connect to this Server through. @@ -191,7 +208,7 @@ class CreateServer extends CreateRecord ->label('Ports') ->inlineLabel() ->live() - ->afterStateUpdated(function ($state, Forms\Set $set) { + ->afterStateUpdated(function ($state, Set $set) { $ports = collect(); $update = false; foreach ($state as $portEntry) { @@ -243,14 +260,14 @@ class CreateServer extends CreateRecord ->splitKeys(['Tab', ' ', ',']) ->required(), ]) - ->createOptionUsing(function (array $data, Forms\Get $get): int { + ->createOptionUsing(function (array $data, Get $get): int { return collect( resolve(AssignmentService::class)->handle(Node::find($get('node_id')), $data) )->first(); }) ->required(), - Forms\Components\Repeater::make('allocation_additional') + Repeater::make('allocation_additional') ->label('Additional Allocations') ->columnSpan([ 'default' => 2, @@ -259,18 +276,18 @@ class CreateServer extends CreateRecord 'lg' => 3, ]) ->addActionLabel('Add Allocation') - ->disabled(fn (Forms\Get $get) => $get('allocation_id') === null) + ->disabled(fn (Get $get) => $get('allocation_id') === null) // ->addable() TODO disable when all allocations are taken // ->addable() TODO disable until first additional allocation is selected ->simple( - Forms\Components\Select::make('extra_allocations') + Select::make('extra_allocations') ->live() ->preload() ->disableOptionsWhenSelectedInSiblingRepeaterItems() ->prefixIcon('tabler-network') ->label('Additional Allocations') ->columnSpan(2) - ->disabled(fn (Forms\Get $get) => $get('../../node_id') === null) + ->disabled(fn (Get $get) => $get('../../node_id') === null) ->searchable(['ip', 'port', 'ip_alias']) ->getOptionLabelFromRecordUsing( fn (Allocation $allocation) => "$allocation->ip:$allocation->port" . @@ -281,14 +298,14 @@ class CreateServer extends CreateRecord ->relationship( 'allocations', 'ip', - fn (Builder $query, Forms\Get $get, Forms\Components\Select $component, $state) => $query + fn (Builder $query, Get $get, Select $component, $state) => $query ->where('node_id', $get('../../node_id')) ->whereNot('id', $get('../../allocation_id')) ->whereNull('server_id'), ), ), - Forms\Components\Textarea::make('description') + Textarea::make('description') ->placeholder('Description') ->rows(3) ->columnSpan([ @@ -300,7 +317,7 @@ class CreateServer extends CreateRecord ->label('Description'), ]), - Wizard\Step::make('Egg Configuration') + Step::make('Egg Configuration') ->label('Egg Configuration') ->icon('tabler-egg') ->completedIcon('tabler-check') @@ -311,7 +328,7 @@ class CreateServer extends CreateRecord 'lg' => 6, ]) ->schema([ - Forms\Components\Select::make('egg_id') + Select::make('egg_id') ->prefixIcon('tabler-egg') ->relationship('egg', 'name') ->columnSpan([ @@ -323,7 +340,7 @@ class CreateServer extends CreateRecord ->searchable() ->preload() ->live() - ->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get, $old) { + ->afterStateUpdated(function ($state, Set $set, Get $get, $old) { $egg = Egg::query()->find($state); $set('startup', $egg->startup ?? ''); $set('image', ''); @@ -351,7 +368,7 @@ class CreateServer extends CreateRecord }) ->required(), - Forms\Components\ToggleButtons::make('skip_scripts') + ToggleButtons::make('skip_scripts') ->label('Run Egg Install Script?') ->default(false) ->columnSpan([ @@ -375,7 +392,7 @@ class CreateServer extends CreateRecord ->inline() ->required(), - Forms\Components\ToggleButtons::make('start_on_completion') + ToggleButtons::make('start_on_completion') ->label('Start Server After Install?') ->default(true) ->required() @@ -399,10 +416,10 @@ class CreateServer extends CreateRecord ]) ->inline(), - Forms\Components\Textarea::make('startup') + Textarea::make('startup') ->hintIcon('tabler-code') ->label('Startup Command') - ->hidden(fn (Forms\Get $get) => $get('egg_id') === null) + ->hidden(fn (Get $get) => $get('egg_id') === null) ->required() ->live() ->rows(function ($state) { @@ -418,24 +435,24 @@ class CreateServer extends CreateRecord 'lg' => 6, ]), - Forms\Components\Hidden::make('environment')->default([]), + Hidden::make('environment')->default([]), - Forms\Components\Section::make('Variables') + Section::make('Variables') ->icon('tabler-eggs') ->iconColor('primary') - ->hidden(fn (Forms\Get $get) => $get('egg_id') === null) + ->hidden(fn (Get $get) => $get('egg_id') === null) ->collapsible() ->columnSpanFull() ->schema([ - Forms\Components\Placeholder::make('Select an egg first to show its variables!') - ->hidden(fn (Forms\Get $get) => $get('egg_id')), + Placeholder::make('Select an egg first to show its variables!') + ->hidden(fn (Get $get) => $get('egg_id')), - Forms\Components\Placeholder::make('The selected egg has no variables!') - ->hidden(fn (Forms\Get $get) => !$get('egg_id') || + Placeholder::make('The selected egg has no variables!') + ->hidden(fn (Get $get) => !$get('egg_id') || Egg::query()->find($get('egg_id'))?->variables()?->count() ), - Forms\Components\Repeater::make('server_variables') + Repeater::make('server_variables') ->label('') ->relationship('serverVariables') ->saveRelationshipsBeforeChildrenUsing(null) @@ -448,11 +465,11 @@ class CreateServer extends CreateRecord ->hidden(fn ($state) => empty($state)) ->schema(function () { - $text = Forms\Components\TextInput::make('variable_value') + $text = TextInput::make('variable_value') ->hidden($this->shouldHideComponent(...)) - ->required(fn (Forms\Get $get) => in_array('required', $get('rules'))) + ->required(fn (Get $get) => in_array('required', $get('rules'))) ->rules( - fn (Forms\Get $get): Closure => function (string $attribute, $value, Closure $fail) use ($get) { + fn (Get $get): Closure => function (string $attribute, $value, Closure $fail) use ($get) { $validator = Validator::make(['validatorkey' => $value], [ 'validatorkey' => $get('rules'), ]); @@ -465,7 +482,7 @@ class CreateServer extends CreateRecord }, ); - $select = Forms\Components\Select::make('variable_value') + $select = Select::make('variable_value') ->hidden($this->shouldHideComponent(...)) ->options($this->getSelectOptionsFromRules(...)) ->selectablePlaceholder(false); @@ -476,11 +493,11 @@ class CreateServer extends CreateRecord $component = $component ->live(onBlur: true) ->hintIcon('tabler-code') - ->label(fn (Forms\Get $get) => $get('name')) - ->hintIconTooltip(fn (Forms\Get $get) => implode('|', $get('rules'))) - ->prefix(fn (Forms\Get $get) => '{{' . $get('env_variable') . '}}') - ->helperText(fn (Forms\Get $get) => empty($get('description')) ? '—' : $get('description')) - ->afterStateUpdated(function (Forms\Set $set, Forms\Get $get, $state) { + ->label(fn (Get $get) => $get('name')) + ->hintIconTooltip(fn (Get $get) => implode('|', $get('rules'))) + ->prefix(fn (Get $get) => '{{' . $get('env_variable') . '}}') + ->helperText(fn (Get $get) => empty($get('description')) ? '—' : $get('description')) + ->afterStateUpdated(function (Set $set, Get $get, $state) { $environment = $get($envPath = '../../environment'); $environment[$get('env_variable')] = $state; $set($envPath, $environment); @@ -492,12 +509,12 @@ class CreateServer extends CreateRecord ->columnSpan(2), ]), ]), - Wizard\Step::make('Environment Configuration') + Step::make('Environment Configuration') ->label('Environment Configuration') ->icon('tabler-brand-docker') ->completedIcon('tabler-check') ->schema([ - Forms\Components\Fieldset::make('Resource Limits') + Fieldset::make('Resource Limits') ->columnSpan(6) ->columns([ 'default' => 1, @@ -506,14 +523,14 @@ class CreateServer extends CreateRecord 'lg' => 3, ]) ->schema([ - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('unlimited_mem') + ToggleButtons::make('unlimited_mem') ->label('Memory')->inlineLabel()->inline() ->default(true) - ->afterStateUpdated(fn (Forms\Set $set) => $set('memory', 0)) + ->afterStateUpdated(fn (Set $set) => $set('memory', 0)) ->live() ->options([ true => 'Unlimited', @@ -525,9 +542,9 @@ class CreateServer extends CreateRecord ]) ->columnSpan(2), - Forms\Components\TextInput::make('memory') + TextInput::make('memory') ->dehydratedWhenHidden() - ->hidden(fn (Forms\Get $get) => $get('unlimited_mem')) + ->hidden(fn (Get $get) => $get('unlimited_mem')) ->label('Memory Limit')->inlineLabel() ->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB') ->default(0) @@ -537,15 +554,15 @@ class CreateServer extends CreateRecord ->minValue(0), ]), - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('unlimited_disk') + ToggleButtons::make('unlimited_disk') ->label('Disk Space')->inlineLabel()->inline() ->default(true) ->live() - ->afterStateUpdated(fn (Forms\Set $set) => $set('disk', 0)) + ->afterStateUpdated(fn (Set $set) => $set('disk', 0)) ->options([ true => 'Unlimited', false => 'Limited', @@ -556,9 +573,9 @@ class CreateServer extends CreateRecord ]) ->columnSpan(2), - Forms\Components\TextInput::make('disk') + TextInput::make('disk') ->dehydratedWhenHidden() - ->hidden(fn (Forms\Get $get) => $get('unlimited_disk')) + ->hidden(fn (Get $get) => $get('unlimited_disk')) ->label('Disk Space Limit')->inlineLabel() ->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB') ->default(0) @@ -568,14 +585,14 @@ class CreateServer extends CreateRecord ->minValue(0), ]), - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('unlimited_cpu') + ToggleButtons::make('unlimited_cpu') ->label('CPU')->inlineLabel()->inline() ->default(true) - ->afterStateUpdated(fn (Forms\Set $set) => $set('cpu', 0)) + ->afterStateUpdated(fn (Set $set) => $set('cpu', 0)) ->live() ->options([ true => 'Unlimited', @@ -587,9 +604,9 @@ class CreateServer extends CreateRecord ]) ->columnSpan(2), - Forms\Components\TextInput::make('cpu') + TextInput::make('cpu') ->dehydratedWhenHidden() - ->hidden(fn (Forms\Get $get) => $get('unlimited_cpu')) + ->hidden(fn (Get $get) => $get('unlimited_cpu')) ->label('CPU Limit')->inlineLabel() ->suffix('%') ->default(0) @@ -600,18 +617,18 @@ class CreateServer extends CreateRecord ->helperText('100% equals one CPU core.'), ]), - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('swap_support') + ToggleButtons::make('swap_support') ->live() ->label('Enable Swap Memory') ->inlineLabel() ->inline() ->columnSpan(2) ->default('disabled') - ->afterStateUpdated(function ($state, Forms\Set $set) { + ->afterStateUpdated(function ($state, Set $set) { $value = match ($state) { 'unlimited' => -1, 'disabled' => 0, @@ -632,9 +649,9 @@ class CreateServer extends CreateRecord 'disabled' => 'danger', ]), - Forms\Components\TextInput::make('swap') + TextInput::make('swap') ->dehydratedWhenHidden() - ->hidden(fn (Forms\Get $get) => match ($get('swap_support')) { + ->hidden(fn (Get $get) => match ($get('swap_support')) { 'disabled', 'unlimited' => true, default => false, }) @@ -648,16 +665,16 @@ class CreateServer extends CreateRecord ->integer(), ]), - Forms\Components\Hidden::make('io') + Hidden::make('io') ->helperText('The IO performance relative to other running containers') ->label('Block IO Proportion') ->default(500), - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('oom_killer') + ToggleButtons::make('oom_killer') ->label('OOM Killer') ->inlineLabel()->inline() ->default(false) @@ -671,12 +688,12 @@ class CreateServer extends CreateRecord true => 'danger', ]), - Forms\Components\TextInput::make('oom_disabled_hidden') + TextInput::make('oom_disabled_hidden') ->hidden(), ]), ]), - Forms\Components\Fieldset::make('Feature Limits') + Fieldset::make('Feature Limits') ->inlineLabel() ->columnSpan(6) ->columns([ @@ -686,21 +703,21 @@ class CreateServer extends CreateRecord 'lg' => 3, ]) ->schema([ - Forms\Components\TextInput::make('allocation_limit') + TextInput::make('allocation_limit') ->label('Allocations') ->suffixIcon('tabler-network') ->required() ->numeric() ->minValue(0) ->default(0), - Forms\Components\TextInput::make('database_limit') + TextInput::make('database_limit') ->label('Databases') ->suffixIcon('tabler-database') ->required() ->numeric() ->minValue(0) ->default(0), - Forms\Components\TextInput::make('backup_limit') + TextInput::make('backup_limit') ->label('Backups') ->suffixIcon('tabler-copy-check') ->required() @@ -708,7 +725,7 @@ class CreateServer extends CreateRecord ->minValue(0) ->default(0), ]), - Forms\Components\Fieldset::make('Docker Settings') + Fieldset::make('Docker Settings') ->columns([ 'default' => 1, 'sm' => 2, @@ -717,10 +734,10 @@ class CreateServer extends CreateRecord ]) ->columnSpan(6) ->schema([ - Forms\Components\Select::make('select_image') + Select::make('select_image') ->label('Image Name') - ->afterStateUpdated(fn (Forms\Set $set, $state) => $set('image', $state)) - ->options(function ($state, Forms\Get $get, Forms\Set $set) { + ->afterStateUpdated(fn (Set $set, $state) => $set('image', $state)) + ->options(function ($state, Get $get, Set $set) { $egg = Egg::query()->find($get('egg_id')); $images = $egg->docker_images ?? []; @@ -741,10 +758,10 @@ class CreateServer extends CreateRecord 'lg' => 2, ]), - Forms\Components\TextInput::make('image') + TextInput::make('image') ->label('Image') ->debounce(500) - ->afterStateUpdated(function ($state, Forms\Get $get, Forms\Set $set) { + ->afterStateUpdated(function ($state, Get $get, Set $set) { $egg = Egg::query()->find($get('egg_id')); $images = $egg->docker_images ?? []; @@ -762,13 +779,13 @@ class CreateServer extends CreateRecord 'lg' => 2, ]), - Forms\Components\KeyValue::make('docker_labels') + KeyValue::make('docker_labels') ->label('Container Labels') ->keyLabel('Title') ->valueLabel('Description') ->columnSpanFull(), - Forms\Components\CheckboxList::make('mounts') + CheckboxList::make('mounts') ->live() ->relationship('mounts') ->options(fn () => $this->node?->mounts->mapWithKeys(fn ($mount) => [$mount->id => $mount->name]) ?? []) @@ -812,24 +829,24 @@ class CreateServer extends CreateRecord return $service->handle($data); } - private function shouldHideComponent(Forms\Get $get, Forms\Components\Component $component): bool + private function shouldHideComponent(Get $get, Component $component): bool { $containsRuleIn = collect($get('rules'))->reduce( fn ($result, $value) => $result === true && !str($value)->startsWith('in:'), true ); - if ($component instanceof Forms\Components\Select) { + if ($component instanceof Select) { return $containsRuleIn; } - if ($component instanceof Forms\Components\TextInput) { + if ($component instanceof TextInput) { return !$containsRuleIn; } throw new \Exception('Component type not supported: ' . $component::class); } - private function getSelectOptionsFromRules(Forms\Get $get): array + private function getSelectOptionsFromRules(Get $get): array { $inRule = collect($get('rules'))->reduce( fn ($result, $value) => str($value)->startsWith('in:') ? $value : $result, '' diff --git a/app/Filament/Resources/ServerResource/Pages/EditServer.php b/app/Filament/Resources/ServerResource/Pages/EditServer.php index 043f5f6e4..d21786c8b 100644 --- a/app/Filament/Resources/ServerResource/Pages/EditServer.php +++ b/app/Filament/Resources/ServerResource/Pages/EditServer.php @@ -6,7 +6,15 @@ use App\Models\Database; use App\Services\Databases\DatabaseManagementService; use App\Services\Databases\DatabasePasswordService; use Filament\Forms\Components\Actions\Action; +use Filament\Forms\Components\CheckboxList; +use Filament\Forms\Components\Fieldset; +use Filament\Forms\Components\Grid; use Filament\Forms\Components\Repeater; +use Filament\Forms\Components\Select; +use Filament\Forms\Components\Tabs\Tab; +use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TextInput; +use Filament\Forms\Components\ToggleButtons; use Filament\Forms\Get; use Filament\Forms\Set; use LogicException; @@ -50,15 +58,15 @@ class EditServer extends EditRecord ]) ->columnSpanFull() ->tabs([ - Tabs\Tab::make('Information') + Tab::make('Information') ->icon('tabler-info-circle') ->schema([ - Forms\Components\TextInput::make('name') + TextInput::make('name') ->prefixIcon('tabler-server') ->label('Display Name') - ->suffixAction(Forms\Components\Actions\Action::make('random') + ->suffixAction(Action::make('random') ->icon('tabler-dice-' . random_int(1, 6)) - ->action(function (Forms\Set $set, Forms\Get $get) { + ->action(function (Set $set, Get $get) { $egg = Egg::find($get('egg_id')); $prefix = $egg ? str($egg->name)->lower()->kebab() . '-' : ''; @@ -75,7 +83,7 @@ class EditServer extends EditRecord ->required() ->maxLength(255), - Forms\Components\Select::make('owner_id') + Select::make('owner_id') ->prefixIcon('tabler-user') ->label('Owner') ->columnSpan([ @@ -89,7 +97,7 @@ class EditServer extends EditRecord ->preload() ->required(), - Forms\Components\ToggleButtons::make('condition') + ToggleButtons::make('condition') ->label('Server Status') ->formatStateUsing(fn (Server $server) => $server->condition) ->options(fn ($state) => collect(array_merge(ContainerStatus::cases(), ServerState::cases())) @@ -109,11 +117,11 @@ class EditServer extends EditRecord 'lg' => 1, ]), - Forms\Components\Textarea::make('description') + Textarea::make('description') ->label('Description') ->columnSpanFull(), - Forms\Components\TextInput::make('uuid') + TextInput::make('uuid') ->hintAction(CopyAction::make()) ->columnSpan([ 'default' => 2, @@ -123,7 +131,7 @@ class EditServer extends EditRecord ]) ->readOnly() ->dehydrated(false), - Forms\Components\TextInput::make('uuid_short') + TextInput::make('uuid_short') ->label('Short UUID') ->hintAction(CopyAction::make()) ->columnSpan([ @@ -134,7 +142,7 @@ class EditServer extends EditRecord ]) ->readOnly() ->dehydrated(false), - Forms\Components\TextInput::make('external_id') + TextInput::make('external_id') ->label('External ID') ->columnSpan([ 'default' => 2, @@ -143,7 +151,7 @@ class EditServer extends EditRecord 'lg' => 3, ]) ->maxLength(255), - Forms\Components\Select::make('node_id') + Select::make('node_id') ->label('Node') ->relationship('node', 'name') ->columnSpan([ @@ -154,10 +162,10 @@ class EditServer extends EditRecord ]) ->disabled(), ]), - Tabs\Tab::make('Environment') + Tab::make('Environment') ->icon('tabler-brand-docker') ->schema([ - Forms\Components\Fieldset::make('Resource Limits') + Fieldset::make('Resource Limits') ->columns([ 'default' => 1, 'sm' => 2, @@ -165,14 +173,14 @@ class EditServer extends EditRecord 'lg' => 3, ]) ->schema([ - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('unlimited_mem') + ToggleButtons::make('unlimited_mem') ->label('Memory')->inlineLabel()->inline() - ->afterStateUpdated(fn (Forms\Set $set) => $set('memory', 0)) - ->formatStateUsing(fn (Forms\Get $get) => $get('memory') == 0) + ->afterStateUpdated(fn (Set $set) => $set('memory', 0)) + ->formatStateUsing(fn (Get $get) => $get('memory') == 0) ->live() ->options([ true => 'Unlimited', @@ -184,9 +192,9 @@ class EditServer extends EditRecord ]) ->columnSpan(2), - Forms\Components\TextInput::make('memory') + TextInput::make('memory') ->dehydratedWhenHidden() - ->hidden(fn (Forms\Get $get) => $get('unlimited_mem')) + ->hidden(fn (Get $get) => $get('unlimited_mem')) ->label('Memory Limit')->inlineLabel() ->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB') ->required() @@ -195,15 +203,15 @@ class EditServer extends EditRecord ->minValue(0), ]), - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('unlimited_disk') + ToggleButtons::make('unlimited_disk') ->label('Disk Space')->inlineLabel()->inline() ->live() - ->afterStateUpdated(fn (Forms\Set $set) => $set('disk', 0)) - ->formatStateUsing(fn (Forms\Get $get) => $get('disk') == 0) + ->afterStateUpdated(fn (Set $set) => $set('disk', 0)) + ->formatStateUsing(fn (Get $get) => $get('disk') == 0) ->options([ true => 'Unlimited', false => 'Limited', @@ -214,9 +222,9 @@ class EditServer extends EditRecord ]) ->columnSpan(2), - Forms\Components\TextInput::make('disk') + TextInput::make('disk') ->dehydratedWhenHidden() - ->hidden(fn (Forms\Get $get) => $get('unlimited_disk')) + ->hidden(fn (Get $get) => $get('unlimited_disk')) ->label('Disk Space Limit')->inlineLabel() ->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB') ->required() @@ -225,14 +233,14 @@ class EditServer extends EditRecord ->minValue(0), ]), - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('unlimited_cpu') + ToggleButtons::make('unlimited_cpu') ->label('CPU')->inlineLabel()->inline() - ->afterStateUpdated(fn (Forms\Set $set) => $set('cpu', 0)) - ->formatStateUsing(fn (Forms\Get $get) => $get('cpu') == 0) + ->afterStateUpdated(fn (Set $set) => $set('cpu', 0)) + ->formatStateUsing(fn (Get $get) => $get('cpu') == 0) ->live() ->options([ true => 'Unlimited', @@ -244,9 +252,9 @@ class EditServer extends EditRecord ]) ->columnSpan(2), - Forms\Components\TextInput::make('cpu') + TextInput::make('cpu') ->dehydratedWhenHidden() - ->hidden(fn (Forms\Get $get) => $get('unlimited_cpu')) + ->hidden(fn (Get $get) => $get('unlimited_cpu')) ->label('CPU Limit')->inlineLabel() ->suffix('%') ->required() @@ -255,15 +263,15 @@ class EditServer extends EditRecord ->minValue(0), ]), - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('swap_support') + ToggleButtons::make('swap_support') ->live() ->label('Enable Swap Memory')->inlineLabel()->inline() ->columnSpan(2) - ->afterStateUpdated(function ($state, Forms\Set $set) { + ->afterStateUpdated(function ($state, Set $set) { $value = match ($state) { 'unlimited' => -1, 'disabled' => 0, @@ -273,7 +281,7 @@ class EditServer extends EditRecord $set('swap', $value); }) - ->formatStateUsing(function (Forms\Get $get) { + ->formatStateUsing(function (Get $get) { return match (true) { $get('swap') > 0 => 'limited', $get('swap') == 0 => 'disabled', @@ -292,9 +300,9 @@ class EditServer extends EditRecord 'disabled' => 'danger', ]), - Forms\Components\TextInput::make('swap') + TextInput::make('swap') ->dehydratedWhenHidden() - ->hidden(fn (Forms\Get $get) => match ($get('swap_support')) { + ->hidden(fn (Get $get) => match ($get('swap_support')) { 'disabled', 'unlimited', true => true, default => false, }) @@ -310,11 +318,11 @@ class EditServer extends EditRecord ->helperText('The IO performance relative to other running containers') ->label('Block IO Proportion'), - Forms\Components\Grid::make() + Grid::make() ->columns(4) ->columnSpanFull() ->schema([ - Forms\Components\ToggleButtons::make('oom_killer') + ToggleButtons::make('oom_killer') ->label('OOM Killer')->inlineLabel()->inline() ->columnSpan(2) ->options([ @@ -326,12 +334,12 @@ class EditServer extends EditRecord true => 'danger', ]), - Forms\Components\TextInput::make('oom_disabled_hidden') + TextInput::make('oom_disabled_hidden') ->hidden(), ]), ]), - Forms\Components\Fieldset::make('Feature Limits') + Fieldset::make('Feature Limits') ->inlineLabel() ->columns([ 'default' => 1, @@ -340,23 +348,23 @@ class EditServer extends EditRecord 'lg' => 3, ]) ->schema([ - Forms\Components\TextInput::make('allocation_limit') + TextInput::make('allocation_limit') ->suffixIcon('tabler-network') ->required() ->minValue(0) ->numeric(), - Forms\Components\TextInput::make('database_limit') + TextInput::make('database_limit') ->suffixIcon('tabler-database') ->required() ->minValue(0) ->numeric(), - Forms\Components\TextInput::make('backup_limit') + TextInput::make('backup_limit') ->suffixIcon('tabler-copy-check') ->required() ->minValue(0) ->numeric(), ]), - Forms\Components\Fieldset::make('Docker Settings') + Fieldset::make('Docker Settings') ->columns([ 'default' => 1, 'sm' => 2, @@ -364,10 +372,10 @@ class EditServer extends EditRecord 'lg' => 3, ]) ->schema([ - Forms\Components\Select::make('select_image') + Select::make('select_image') ->label('Image Name') - ->afterStateUpdated(fn (Forms\Set $set, $state) => $set('image', $state)) - ->options(function ($state, Forms\Get $get, Forms\Set $set) { + ->afterStateUpdated(fn (Set $set, $state) => $set('image', $state)) + ->options(function ($state, Get $get, Set $set) { $egg = Egg::query()->find($get('egg_id')); $images = $egg->docker_images ?? []; @@ -383,10 +391,10 @@ class EditServer extends EditRecord ->selectablePlaceholder(false) ->columnSpan(1), - Forms\Components\TextInput::make('image') + TextInput::make('image') ->label('Image') ->debounce(500) - ->afterStateUpdated(function ($state, Forms\Get $get, Forms\Set $set) { + ->afterStateUpdated(function ($state, Get $get, Set $set) { $egg = Egg::query()->find($get('egg_id')); $images = $egg->docker_images ?? []; @@ -406,7 +414,7 @@ class EditServer extends EditRecord ->columnSpanFull(), ]), ]), - Tabs\Tab::make('Egg') + Tab::make('Egg') ->icon('tabler-egg') ->columns([ 'default' => 1, @@ -415,7 +423,7 @@ class EditServer extends EditRecord 'lg' => 5, ]) ->schema([ - Forms\Components\Select::make('egg_id') + Select::make('egg_id') ->disabledOn('edit') ->prefixIcon('tabler-egg') ->columnSpan([ @@ -429,7 +437,7 @@ class EditServer extends EditRecord ->preload() ->required(), - Forms\Components\ToggleButtons::make('skip_scripts') + ToggleButtons::make('skip_scripts') ->label('Run Egg Install Script?')->inline() ->columnSpan([ 'default' => 6, @@ -451,7 +459,7 @@ class EditServer extends EditRecord ]) ->required(), - Forms\Components\Textarea::make('startup') + Textarea::make('startup') ->label('Startup Command') ->required() ->columnSpan(6) @@ -462,18 +470,18 @@ class EditServer extends EditRecord ); }), - Forms\Components\Textarea::make('defaultStartup') + Textarea::make('defaultStartup') ->hintAction(CopyAction::make()) ->label('Default Startup Command') ->disabled() - ->formatStateUsing(function ($state, Get $get, Set $set) { + ->formatStateUsing(function ($state, Get $get) { $egg = Egg::query()->find($get('egg_id')); return $egg->startup; }) ->columnSpan(6), - Forms\Components\Repeater::make('server_variables') + Repeater::make('server_variables') ->relationship('serverVariables', function (Builder $query) { /** @var Server $server */ $server = $this->getRecord(); @@ -502,7 +510,7 @@ class EditServer extends EditRecord ->reorderable(false)->addable(false)->deletable(false) ->schema(function () { - $text = Forms\Components\TextInput::make('variable_value') + $text = TextInput::make('variable_value') ->hidden($this->shouldHideComponent(...)) ->required(fn (ServerVariable $serverVariable) => $serverVariable->variable->getRequiredAttribute()) ->rules([ @@ -519,7 +527,7 @@ class EditServer extends EditRecord }, ]); - $select = Forms\Components\Select::make('variable_value') + $select = Select::make('variable_value') ->hidden($this->shouldHideComponent(...)) ->options($this->getSelectOptionsFromRules(...)) ->selectablePlaceholder(false); @@ -540,10 +548,10 @@ class EditServer extends EditRecord }) ->columnSpan(6), ]), - Tabs\Tab::make('Mounts') + Tab::make('Mounts') ->icon('tabler-layers-linked') ->schema([ - Forms\Components\CheckboxList::make('mounts') + CheckboxList::make('mounts') ->relationship('mounts') ->options(fn (Server $server) => $server->node->mounts->mapWithKeys(fn ($mount) => [$mount->id => $mount->name])) ->descriptions(fn (Server $server) => $server->node->mounts->mapWithKeys(fn ($mount) => [$mount->id => "$mount->source -> $mount->target"])) @@ -551,7 +559,7 @@ class EditServer extends EditRecord ->helperText(fn (Server $server) => $server->node->mounts->isNotEmpty() ? '' : 'No Mounts exist for this Node') ->columnSpanFull(), ]), - Tabs\Tab::make('Databases') + Tab::make('Databases') ->icon('tabler-database') ->schema([ Repeater::make('databases') @@ -559,7 +567,7 @@ class EditServer extends EditRecord ->helperText(fn (Server $server) => $server->databases->isNotEmpty() ? '' : 'No Databases exist for this Server') ->columns(2) ->schema([ - Forms\Components\TextInput::make('database') + TextInput::make('database') ->columnSpan(2) ->label('Database Name') ->disabled() @@ -570,11 +578,11 @@ class EditServer extends EditRecord ->icon('tabler-trash') ->action(fn (DatabaseManagementService $databaseManagementService, $record) => $databaseManagementService->delete($record)) ), - Forms\Components\TextInput::make('username') + TextInput::make('username') ->disabled() ->formatStateUsing(fn ($record) => $record->username) ->columnSpan(2), - Forms\Components\TextInput::make('password') + TextInput::make('password') ->disabled() ->hintAction( Action::make('rotate') @@ -584,30 +592,30 @@ class EditServer extends EditRecord ) ->formatStateUsing(fn (Database $database) => $database->password) ->columnSpan(2), - Forms\Components\TextInput::make('remote') + TextInput::make('remote') ->disabled() ->formatStateUsing(fn ($record) => $record->remote) ->columnSpan(1) ->label('Connections From'), - Forms\Components\TextInput::make('max_connections') + TextInput::make('max_connections') ->disabled() ->formatStateUsing(fn ($record) => $record->max_connections) ->columnSpan(1), - Forms\Components\TextInput::make('JDBC') + TextInput::make('JDBC') ->disabled() ->label('JDBC Connection String') ->columnSpan(2) - ->formatStateUsing(fn (Forms\Get $get, $record) => 'jdbc:mysql://' . $get('username') . ':' . urlencode($record->password) . '@' . $record->host->host . ':' . $record->host->port . '/' . $get('database')), + ->formatStateUsing(fn (Get $get, $record) => 'jdbc:mysql://' . $get('username') . ':' . urlencode($record->password) . '@' . $record->host->host . ':' . $record->host->port . '/' . $get('database')), ]) ->relationship('databases') ->deletable(false) ->addable(false) ->columnSpan(4), ])->columns(4), - Tabs\Tab::make('Actions') + Tab::make('Actions') ->icon('tabler-settings') ->schema([ - Forms\Components\Fieldset::make('Server Actions') + Fieldset::make('Server Actions') ->columns([ 'default' => 1, 'sm' => 2, @@ -615,11 +623,11 @@ class EditServer extends EditRecord 'lg' => 6, ]) ->schema([ - Forms\Components\Grid::make() + Grid::make() ->columnSpan(3) ->schema([ Forms\Components\Actions::make([ - Forms\Components\Actions\Action::make('toggleInstall') + Action::make('toggleInstall') ->label('Toggle Install Status') ->disabled(fn (Server $server) => $server->isSuspended()) ->action(function (ServersController $serversController, Server $server) { @@ -628,14 +636,14 @@ class EditServer extends EditRecord $this->refreshFormData(['status', 'docker']); }), ])->fullWidth(), - Forms\Components\ToggleButtons::make('') + ToggleButtons::make('') ->hint('If you need to change the install status from uninstalled to installed, or vice versa, you may do so with this button.'), ]), - Forms\Components\Grid::make() + Grid::make() ->columnSpan(3) ->schema([ Forms\Components\Actions::make([ - Forms\Components\Actions\Action::make('toggleSuspend') + Action::make('toggleSuspend') ->label('Suspend') ->color('warning') ->hidden(fn (Server $server) => $server->isSuspended()) @@ -645,7 +653,7 @@ class EditServer extends EditRecord $this->refreshFormData(['status', 'docker']); }), - Forms\Components\Actions\Action::make('toggleUnsuspend') + Action::make('toggleUnsuspend') ->label('Unsuspend') ->color('success') ->hidden(fn (Server $server) => !$server->isSuspended()) @@ -656,37 +664,37 @@ class EditServer extends EditRecord $this->refreshFormData(['status', 'docker']); }), ])->fullWidth(), - Forms\Components\ToggleButtons::make('') + ToggleButtons::make('') ->hidden(fn (Server $server) => $server->isSuspended()) ->hint('This will suspend the server, stop any running processes, and immediately block the user from being able to access their files or otherwise manage the server through the panel or API.'), - Forms\Components\ToggleButtons::make('') + ToggleButtons::make('') ->hidden(fn (Server $server) => !$server->isSuspended()) ->hint('This will unsuspend the server and restore normal user access.'), ]), - Forms\Components\Grid::make() + Grid::make() ->columnSpan(3) ->schema([ Forms\Components\Actions::make([ - Forms\Components\Actions\Action::make('transfer') + Action::make('transfer') ->label('Transfer Soon™') ->action(fn (TransferServerService $transfer, Server $server) => $transfer->handle($server, [])) ->disabled() //TODO! ->form([ //TODO! - Forms\Components\Select::make('newNode') + Select::make('newNode') ->label('New Node') ->required() ->options([ true => 'on', false => 'off', ]), - Forms\Components\Select::make('newMainAllocation') + Select::make('newMainAllocation') ->label('New Main Allocation') ->required() ->options([ true => 'on', false => 'off', ]), - Forms\Components\Select::make('newAdditionalAllocation') + Select::make('newAdditionalAllocation') ->label('New Additional Allocations') ->options([ true => 'on', @@ -695,14 +703,14 @@ class EditServer extends EditRecord ]) ->modalHeading('Transfer'), ])->fullWidth(), - Forms\Components\ToggleButtons::make('') + ToggleButtons::make('') ->hint('Transfer this server to another node connected to this panel. Warning! This feature has not been fully tested and may have bugs.'), ]), - Forms\Components\Grid::make() + Grid::make() ->columnSpan(3) ->schema([ Forms\Components\Actions::make([ - Forms\Components\Actions\Action::make('reinstall') + Action::make('reinstall') ->label('Reinstall') ->color('danger') ->requiresConfirmation() @@ -711,7 +719,7 @@ class EditServer extends EditRecord ->disabled(fn (Server $server) => $server->isSuspended()) ->action(fn (ServersController $serversController, Server $server) => $serversController->reinstallServer($server)), ])->fullWidth(), - Forms\Components\ToggleButtons::make('') + ToggleButtons::make('') ->hint('This will reinstall the server with the assigned egg install script.'), ]), ]), @@ -725,9 +733,9 @@ class EditServer extends EditRecord return $form ->columns() ->schema([ - Forms\Components\Select::make('toNode') + Select::make('toNode') ->label('New Node'), - Forms\Components\TextInput::make('newAllocation') + TextInput::make('newAllocation') ->label('Allocation'), ]); @@ -780,11 +788,11 @@ class EditServer extends EditRecord { $containsRuleIn = array_first($serverVariable->variable->rules, fn ($value) => str($value)->startsWith('in:'), false); - if ($component instanceof Forms\Components\Select) { + if ($component instanceof Select) { return !$containsRuleIn; } - if ($component instanceof Forms\Components\TextInput) { + if ($component instanceof TextInput) { return $containsRuleIn; } diff --git a/app/Filament/Resources/ServerResource/Pages/ListServers.php b/app/Filament/Resources/ServerResource/Pages/ListServers.php index b0bc6ef9b..a906f6704 100644 --- a/app/Filament/Resources/ServerResource/Pages/ListServers.php +++ b/app/Filament/Resources/ServerResource/Pages/ListServers.php @@ -7,10 +7,13 @@ use App\Models\Server; use App\Models\User; use Filament\Actions; use Filament\Resources\Pages\ListRecords; +use Filament\Tables\Actions\Action; use Filament\Tables\Actions\CreateAction; +use Filament\Tables\Actions\EditAction; +use Filament\Tables\Columns\SelectColumn; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Grouping\Group; use Filament\Tables\Table; -use Filament\Tables; class ListServers extends ListRecords { @@ -27,47 +30,47 @@ class ListServers extends ListRecords Group::make('egg.name')->getDescriptionFromRecordUsing(fn (Server $server): string => str($server->egg->description)->limit(150)), ]) ->columns([ - Tables\Columns\TextColumn::make('condition') + TextColumn::make('condition') ->default('unknown') ->badge() ->icon(fn (Server $server) => $server->conditionIcon()) ->color(fn (Server $server) => $server->conditionColor()), - Tables\Columns\TextColumn::make('uuid') + TextColumn::make('uuid') ->hidden() ->label('UUID') ->searchable(), - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->icon('tabler-brand-docker') ->searchable() ->sortable(), - Tables\Columns\TextColumn::make('node.name') + TextColumn::make('node.name') ->icon('tabler-server-2') ->url(fn (Server $server): string => route('filament.admin.resources.nodes.edit', ['record' => $server->node])) ->hidden(fn (Table $table) => $table->getGrouping()?->getId() === 'node.name') ->sortable() ->searchable(), - Tables\Columns\TextColumn::make('egg.name') + TextColumn::make('egg.name') ->icon('tabler-egg') ->url(fn (Server $server): string => route('filament.admin.resources.eggs.edit', ['record' => $server->egg])) ->hidden(fn (Table $table) => $table->getGrouping()?->getId() === 'egg.name') ->sortable() ->searchable(), - Tables\Columns\TextColumn::make('user.username') + TextColumn::make('user.username') ->icon('tabler-user') ->label('Owner') ->url(fn (Server $server): string => route('filament.admin.resources.users.edit', ['record' => $server->user])) ->hidden(fn (Table $table) => $table->getGrouping()?->getId() === 'user.username') ->sortable() ->searchable(), - Tables\Columns\SelectColumn::make('allocation_id') + SelectColumn::make('allocation_id') ->label('Primary Allocation') ->options(fn (Server $server) => $server->allocations->mapWithKeys( fn ($allocation) => [$allocation->id => $allocation->address]) ) ->selectablePlaceholder(false) ->sortable(), - Tables\Columns\TextColumn::make('image')->hidden(), - Tables\Columns\TextColumn::make('backups_count') + TextColumn::make('image')->hidden(), + TextColumn::make('backups_count') ->counts('backups') ->label('Backups') ->icon('tabler-file-download') @@ -75,7 +78,7 @@ class ListServers extends ListRecords ->sortable(), ]) ->actions([ - Tables\Actions\Action::make('View') + Action::make('View') ->icon('tabler-terminal') ->url(fn (Server $server) => "/server/$server->uuid_short") ->visible(function (Server $server) { @@ -84,7 +87,7 @@ class ListServers extends ListRecords return $user->isRootAdmin() || $user->id === $server->owner_id; }), - Tables\Actions\EditAction::make(), + EditAction::make(), ]) ->emptyStateIcon('tabler-brand-docker') ->searchable() diff --git a/app/Filament/Resources/ServerResource/RelationManagers/AllocationsRelationManager.php b/app/Filament/Resources/ServerResource/RelationManagers/AllocationsRelationManager.php index cbac9bf92..d125773dd 100644 --- a/app/Filament/Resources/ServerResource/RelationManagers/AllocationsRelationManager.php +++ b/app/Filament/Resources/ServerResource/RelationManagers/AllocationsRelationManager.php @@ -11,6 +11,12 @@ use Filament\Forms\Set; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; use Filament\Tables; +use Filament\Tables\Actions\Action; +use Filament\Tables\Actions\AssociateAction; +use Filament\Tables\Actions\CreateAction; +use Filament\Tables\Columns\IconColumn; +use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Columns\TextInputColumn; use Filament\Tables\Table; use Illuminate\Support\HtmlString; @@ -41,10 +47,10 @@ class AllocationsRelationManager extends RelationManager // ->groups ->inverseRelationship('server') ->columns([ - Tables\Columns\TextColumn::make('ip')->label('IP'), - Tables\Columns\TextColumn::make('port')->label('Port'), - Tables\Columns\TextInputColumn::make('ip_alias')->label('Alias'), - Tables\Columns\IconColumn::make('primary') + TextColumn::make('ip')->label('IP'), + TextColumn::make('port')->label('Port'), + TextInputColumn::make('ip_alias')->label('Alias'), + IconColumn::make('primary') ->icon(fn ($state) => match ($state) { true => 'tabler-star-filled', default => 'tabler-star', @@ -61,12 +67,12 @@ class AllocationsRelationManager extends RelationManager // ]) ->actions([ - Tables\Actions\Action::make('make-primary') + Action::make('make-primary') ->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id])) ->label(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id ? '' : 'Make Primary'), ]) ->headerActions([ - Tables\Actions\CreateAction::make()->label('Create Allocation') + CreateAction::make()->label('Create Allocation') ->createAnother(false) ->form(fn () => [ TextInput::make('allocation_ip') @@ -144,7 +150,7 @@ class AllocationsRelationManager extends RelationManager ->required(), ]) ->action(fn (array $data) => resolve(AssignmentService::class)->handle($this->getOwnerRecord()->node, $data, $this->getOwnerRecord())), - Tables\Actions\AssociateAction::make() + AssociateAction::make() ->multiple() ->associateAnother(false) ->preloadRecordSelect() diff --git a/app/Filament/Resources/UserResource/Pages/EditProfile.php b/app/Filament/Resources/UserResource/Pages/EditProfile.php index d8eb7274f..d1516fc2b 100644 --- a/app/Filament/Resources/UserResource/Pages/EditProfile.php +++ b/app/Filament/Resources/UserResource/Pages/EditProfile.php @@ -57,7 +57,6 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile ->maxLength(255) ->unique(ignoreRecord: true) ->autofocus(), - TextInput::make('email') ->prefixIcon('tabler-mail') ->label(trans('strings.email')) @@ -65,7 +64,6 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile ->required() ->maxLength(255) ->unique(ignoreRecord: true), - TextInput::make('password') ->label(trans('strings.password')) ->password() @@ -77,7 +75,6 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile ->dehydrateStateUsing(fn ($state): string => Hash::make($state)) ->live(debounce: 500) ->same('passwordConfirmation'), - TextInput::make('passwordConfirmation') ->label(trans('strings.password_confirmation')) ->password() @@ -86,13 +83,11 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile ->required() ->visible(fn (Get $get): bool => filled($get('password'))) ->dehydrated(false), - Select::make('timezone') ->required() ->prefixIcon('tabler-clock-pin') ->options(fn () => collect(DateTimeZone::listIdentifiers())->mapWithKeys(fn ($tz) => [$tz => $tz])) ->searchable(), - Select::make('language') ->label(trans('strings.language')) ->required() @@ -111,7 +106,6 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile Tab::make('2FA') ->icon('tabler-shield-lock') ->schema(function () { - if ($this->getUser()->use_totp) { return [ Placeholder::make('2fa-already-enabled') @@ -196,16 +190,13 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile ->helperText('Enter your current password to verify.'), ]; }), - Tab::make('API Keys') ->icon('tabler-key') ->schema([ Grid::make('asdf')->columns(5)->schema([ Section::make('Create API Key')->columnSpan(3)->schema([ - TextInput::make('description') ->live(), - TagsInput::make('allowed_ips') ->live() ->splitKeys([',', ' ', 'Tab']) @@ -222,12 +213,10 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile $get('description'), $get('allowed_ips'), ); - Activity::event('user:api-key.create') ->subject($token->accessToken) ->property('identifier', $token->accessToken->identifier) ->log(); - $action->success(); }), ]), @@ -256,13 +245,11 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile ]), ]), ]), - Tab::make('SSH Keys') ->icon('tabler-lock-code') ->schema([ Placeholder::make('Coming soon!'), ]), - Tab::make('Activity') ->icon('tabler-history') ->schema([ diff --git a/app/Filament/Resources/UserResource/RelationManagers/ServersRelationManager.php b/app/Filament/Resources/UserResource/RelationManagers/ServersRelationManager.php index ce198e2d0..668853b0d 100644 --- a/app/Filament/Resources/UserResource/RelationManagers/ServersRelationManager.php +++ b/app/Filament/Resources/UserResource/RelationManagers/ServersRelationManager.php @@ -6,7 +6,8 @@ use App\Enums\ServerState; use App\Models\Server; use App\Models\User; use App\Services\Servers\SuspensionService; -use Filament\Tables; +use Filament\Tables\Columns\SelectColumn; +use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; use Filament\Tables\Actions; use Filament\Resources\RelationManagers\RelationManager; @@ -36,7 +37,6 @@ class ServersRelationManager extends RelationManager resolve(SuspensionService::class)->toggle($server); } }), - Actions\Action::make('toggleUnsuspend') ->hidden(fn () => $user->servers()->where('status', ServerState::Suspended)->count() === 0) ->label('Unsuspend All Servers') @@ -48,37 +48,37 @@ class ServersRelationManager extends RelationManager }), ]) ->columns([ - Tables\Columns\TextColumn::make('uuid') + TextColumn::make('uuid') ->hidden() ->label('UUID') ->searchable(), - Tables\Columns\TextColumn::make('name') + TextColumn::make('name') ->icon('tabler-brand-docker') ->label(trans('strings.name')) ->url(fn (Server $server): string => route('filament.admin.resources.servers.edit', ['record' => $server])) ->searchable() ->sortable(), - Tables\Columns\TextColumn::make('node.name') + TextColumn::make('node.name') ->icon('tabler-server-2') ->url(fn (Server $server): string => route('filament.admin.resources.nodes.edit', ['record' => $server->node])) ->sortable(), - Tables\Columns\TextColumn::make('egg.name') + TextColumn::make('egg.name') ->icon('tabler-egg') ->url(fn (Server $server): string => route('filament.admin.resources.eggs.edit', ['record' => $server->egg])) ->sortable(), - Tables\Columns\SelectColumn::make('allocation.id') + SelectColumn::make('allocation.id') ->label('Primary Allocation') ->options(fn (Server $server) => [$server->allocation->id => $server->allocation->address]) ->selectablePlaceholder(false) ->sortable(), - Tables\Columns\TextColumn::make('image')->hidden(), - Tables\Columns\TextColumn::make('databases_count') + TextColumn::make('image')->hidden(), + TextColumn::make('databases_count') ->counts('databases') ->label('Databases') ->icon('tabler-database') ->numeric() ->sortable(), - Tables\Columns\TextColumn::make('backups_count') + TextColumn::make('backups_count') ->counts('backups') ->label('Backups') ->icon('tabler-file-download')