Skip to content

Commit d768be3

Browse files
committed
make "create server" its own page
1 parent 622df9d commit d768be3

File tree

3 files changed

+204
-117
lines changed

3 files changed

+204
-117
lines changed

user-creatable-servers/lang/en/strings.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
'left' => 'left',
1616
'variables' => 'Startup variables',
1717

18+
'create_server' => 'Create server',
19+
1820
'modals' => [
1921
'delete_server_confirm' => 'Are you sure you want to delete this server?',
2022
'delete_server_warning' => 'This action cannot be undone and all data will be permanently lost.',
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
<?php
2+
3+
namespace Boy132\UserCreatableServers\Filament\App\Pages;
4+
5+
use App\Exceptions\Service\Deployment\NoViableAllocationException;
6+
use App\Exceptions\Service\Deployment\NoViableNodeException;
7+
use App\Filament\Components\Forms\Fields\StartupVariable;
8+
use App\Filament\Server\Pages\Console;
9+
use App\Models\Egg;
10+
use App\Services\Servers\RandomWordService;
11+
use BackedEnum;
12+
use Boy132\UserCreatableServers\Filament\App\Widgets\UserResourceLimitsOverview;
13+
use Boy132\UserCreatableServers\Models\UserResourceLimits;
14+
use Exception;
15+
use Filament\Actions\Action;
16+
use Filament\Forms\Components\Repeater;
17+
use Filament\Forms\Components\Select;
18+
use Filament\Forms\Components\TextInput;
19+
use Filament\Forms\Concerns\InteractsWithForms;
20+
use Filament\Notifications\Notification;
21+
use Filament\Pages\Concerns\InteractsWithFormActions;
22+
use Filament\Pages\Page;
23+
use Filament\Schemas\Components\Utilities\Get;
24+
use Filament\Schemas\Components\Utilities\Set;
25+
use Filament\Schemas\Schema;
26+
use Filament\Support\Facades\FilamentView;
27+
use Illuminate\Support\Arr;
28+
29+
/**
30+
* @property Schema $form
31+
*/
32+
class CreateServerPage extends Page
33+
{
34+
use InteractsWithFormActions;
35+
use InteractsWithForms;
36+
37+
protected static string|BackedEnum|null $navigationIcon = 'tabler-cube-plus';
38+
39+
protected static ?string $slug = 'create-server';
40+
41+
protected string $view = 'filament.server.pages.server-form-page';
42+
43+
/** @var array<string, mixed>|null */
44+
public ?array $data = [];
45+
46+
public function getTitle(): string
47+
{
48+
return trans('user-creatable-servers::strings.create_server');
49+
}
50+
51+
public static function getNavigationLabel(): string
52+
{
53+
return trans('user-creatable-servers::strings.create_server');
54+
}
55+
56+
public static function canAccess(): bool
57+
{
58+
return UserResourceLimits::where('user_id', auth()->user()->id)->exists();
59+
}
60+
61+
public function mount(): void
62+
{
63+
$this->form->fill();
64+
}
65+
66+
public function form(Schema $schema): Schema
67+
{
68+
/** @var UserResourceLimits $userResourceLimits */
69+
$userResourceLimits = UserResourceLimits::where('user_id', auth()->user()->id)->firstOrFail();
70+
71+
return $schema
72+
->statePath('data')
73+
->columns(3)
74+
->schema([
75+
TextInput::make('name')
76+
->label(trans('user-creatable-servers::strings.name'))
77+
->required()
78+
->default(fn () => (new RandomWordService())->word())
79+
->columnSpanFull(),
80+
Select::make('egg_id')
81+
->label(trans('user-creatable-servers::strings.egg'))
82+
->prefixIcon('tabler-egg')
83+
->options(fn () => Egg::all()->mapWithKeys(fn (Egg $egg) => [$egg->id => $egg->name]))
84+
->required()
85+
->searchable()
86+
->preload()
87+
->live()
88+
->afterStateUpdated(function ($state, Set $set) {
89+
$egg = Egg::find($state);
90+
91+
$variables = $egg->variables ?? [];
92+
$serverVariables = collect();
93+
foreach ($variables as $variable) {
94+
$serverVariables->add($variable->toArray());
95+
}
96+
97+
$set('variables', $serverVariables->sortBy(['sort'])->all());
98+
for ($i = 0; $i < $serverVariables->count(); $i++) {
99+
$set("variables.$i.variable_value", $serverVariables[$i]['default_value']);
100+
$set("variables.$i.variable_id", $serverVariables[$i]['id']);
101+
}
102+
})
103+
->columnSpanFull(),
104+
TextInput::make('cpu')
105+
->label(trans('user-creatable-servers::strings.cpu'))
106+
->required()
107+
->numeric()
108+
->minValue($userResourceLimits->cpu > 0 ? 1 : 0)
109+
->maxValue($userResourceLimits->getCpuLeft())
110+
->suffix('%'),
111+
TextInput::make('memory')
112+
->label(trans('user-creatable-servers::strings.memory'))
113+
->required()
114+
->numeric()
115+
->minValue($userResourceLimits->memory > 0 ? 1 : 0)
116+
->maxValue($userResourceLimits->getMemoryLeft())
117+
->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB'),
118+
TextInput::make('disk')
119+
->label(trans('user-creatable-servers::strings.disk'))
120+
->required()
121+
->numeric()
122+
->minValue($userResourceLimits->disk > 0 ? 1 : 0)
123+
->maxValue($userResourceLimits->getDiskLeft())
124+
->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB'),
125+
Repeater::make('variables')
126+
->label(trans('user-creatable-servers::strings.variables'))
127+
->hidden(fn (Get $get) => !$get('egg_id'))
128+
->grid(2)
129+
->columnSpanFull()
130+
->reorderable(false)
131+
->addable(false)
132+
->deletable(false)
133+
->default([])
134+
->hidden(fn ($state) => empty($state))
135+
->schema([
136+
StartupVariable::make('variable_value')
137+
->fromForm()
138+
->disabled(false),
139+
]),
140+
]);
141+
}
142+
143+
protected function getHeaderActions(): array
144+
{
145+
return [
146+
Action::make('save')
147+
->hiddenLabel()
148+
->action('save')
149+
->keyBindings(['mod+s'])
150+
->tooltip(trans('filament-panels::resources/pages/edit-record.form.actions.save.label'))
151+
->icon('tabler-device-floppy'),
152+
];
153+
}
154+
155+
protected function getHeaderWidgets(): array
156+
{
157+
return [
158+
UserResourceLimitsOverview::class,
159+
];
160+
}
161+
162+
public function save(): void
163+
{
164+
$data = $this->form->getState();
165+
166+
try {
167+
/** @var UserResourceLimits $userResourceLimits */
168+
$userResourceLimits = UserResourceLimits::where('user_id', auth()->user()->id)->firstOrFail();
169+
170+
if ($server = $userResourceLimits->createServer($data['name'], $data['egg_id'], $data['cpu'], $data['memory'], $data['disk'], Arr::mapWithKeys($data['variables'], fn ($value) => [$value['env_variable'] => $value['variable_value']]))) {
171+
$redirectUrl = Console::getUrl(panel: 'server', tenant: $server);
172+
$this->redirect($redirectUrl, navigate: FilamentView::hasSpaMode($redirectUrl));
173+
}
174+
} catch (Exception $exception) {
175+
report($exception);
176+
177+
if ($exception instanceof NoViableNodeException) {
178+
Notification::make()
179+
->title(trans('user-creatable-servers::strings.notifications.server_creation_failed'))
180+
->body(trans('user-creatable-servers::strings.notifications.no_viable_node_found'))
181+
->danger()
182+
->send();
183+
} elseif ($exception instanceof NoViableAllocationException) {
184+
Notification::make()
185+
->title(trans('user-creatable-servers::strings.notifications.server_creation_failed'))
186+
->body(trans('user-creatable-servers::strings.notifications.no_viable_allocation_found'))
187+
->danger()
188+
->send();
189+
} else {
190+
Notification::make()
191+
->title(trans('user-creatable-servers::strings.notifications.server_creation_failed'))
192+
->body(trans('user-creatable-servers::strings.notifications.unknown_server_creation_error'))
193+
->danger()
194+
->send();
195+
}
196+
}
197+
}
198+
}

user-creatable-servers/src/Filament/Components/Actions/CreateServerAction.php

Lines changed: 4 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,9 @@
22

33
namespace Boy132\UserCreatableServers\Filament\Components\Actions;
44

5-
use App\Exceptions\Service\Deployment\NoViableAllocationException;
6-
use App\Exceptions\Service\Deployment\NoViableNodeException;
7-
use App\Filament\Components\Forms\Fields\StartupVariable;
8-
use App\Filament\Server\Pages\Console;
9-
use App\Models\Egg;
10-
use App\Services\Servers\RandomWordService;
5+
use Boy132\UserCreatableServers\Filament\App\Pages\CreateServerPage;
116
use Boy132\UserCreatableServers\Models\UserResourceLimits;
12-
use Exception;
137
use Filament\Actions\Action;
14-
use Filament\Forms\Components\Repeater;
15-
use Filament\Forms\Components\Select;
16-
use Filament\Forms\Components\TextInput;
17-
use Filament\Notifications\Notification;
18-
use Filament\Schemas\Components\Utilities\Get;
19-
use Filament\Schemas\Components\Utilities\Set;
20-
use Illuminate\Support\Arr;
218

229
class CreateServerAction extends Action
2310
{
@@ -30,6 +17,8 @@ protected function setUp(): void
3017
{
3118
parent::setUp();
3219

20+
$this->label(fn () => trans('user-creatable-servers::strings.create_server'));
21+
3322
$this->visible(fn () => UserResourceLimits::where('user_id', auth()->user()->id)->exists());
3423

3524
$this->disabled(function () {
@@ -43,108 +32,6 @@ protected function setUp(): void
4332
return !$userResourceLimits->canCreateServer(1, 1, 1);
4433
});
4534

46-
$this->schema(function () {
47-
/** @var UserResourceLimits $userResourceLimits */
48-
$userResourceLimits = UserResourceLimits::where('user_id', auth()->user()->id)->firstOrFail();
49-
50-
return [
51-
TextInput::make('name')
52-
->label(trans('user-creatable-servers::strings.name'))
53-
->required()
54-
->default(fn () => (new RandomWordService())->word())
55-
->columnSpanFull(),
56-
Select::make('egg_id')
57-
->label(trans('user-creatable-servers::strings.egg'))
58-
->prefixIcon('tabler-egg')
59-
->options(fn () => Egg::all()->mapWithKeys(fn (Egg $egg) => [$egg->id => $egg->name]))
60-
->required()
61-
->searchable()
62-
->preload()
63-
->live()
64-
->afterStateUpdated(function ($state, Set $set) {
65-
$egg = Egg::find($state);
66-
67-
$variables = $egg->variables ?? [];
68-
$serverVariables = collect();
69-
foreach ($variables as $variable) {
70-
$serverVariables->add($variable->toArray());
71-
}
72-
73-
$set('variables', $serverVariables->sortBy(['sort'])->all());
74-
for ($i = 0; $i < $serverVariables->count(); $i++) {
75-
$set("variables.$i.variable_value", $serverVariables[$i]['default_value']);
76-
$set("variables.$i.variable_id", $serverVariables[$i]['id']);
77-
}
78-
}),
79-
TextInput::make('cpu')
80-
->label(trans('user-creatable-servers::strings.cpu'))
81-
->required()
82-
->numeric()
83-
->minValue($userResourceLimits->cpu > 0 ? 1 : 0)
84-
->maxValue($userResourceLimits->getCpuLeft())
85-
->suffix('%'),
86-
TextInput::make('memory')
87-
->label(trans('user-creatable-servers::strings.memory'))
88-
->required()
89-
->numeric()
90-
->minValue($userResourceLimits->memory > 0 ? 1 : 0)
91-
->maxValue($userResourceLimits->getMemoryLeft())
92-
->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB'),
93-
TextInput::make('disk')
94-
->label(trans('user-creatable-servers::strings.disk'))
95-
->required()
96-
->numeric()
97-
->minValue($userResourceLimits->disk > 0 ? 1 : 0)
98-
->maxValue($userResourceLimits->getDiskLeft())
99-
->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB'),
100-
Repeater::make('variables')
101-
->label(trans('user-creatable-servers::strings.variables'))
102-
->hidden(fn (Get $get) => !$get('egg_id'))
103-
->grid(2)
104-
->reorderable(false)
105-
->addable(false)
106-
->deletable(false)
107-
->default([])
108-
->hidden(fn ($state) => empty($state))
109-
->schema([
110-
StartupVariable::make('variable_value')
111-
->fromForm()
112-
->disabled(false),
113-
]),
114-
];
115-
});
116-
117-
$this->action(function (array $data) {
118-
try {
119-
/** @var UserResourceLimits $userResourceLimits */
120-
$userResourceLimits = UserResourceLimits::where('user_id', auth()->user()->id)->firstOrFail();
121-
122-
if ($server = $userResourceLimits->createServer($data['name'], $data['egg_id'], $data['cpu'], $data['memory'], $data['disk'], Arr::mapWithKeys($data['variables'], fn ($value) => [$value['env_variable'] => $value['variable_value']]))) {
123-
redirect(Console::getUrl(panel: 'server', tenant: $server));
124-
}
125-
} catch (Exception $exception) {
126-
report($exception);
127-
128-
if ($exception instanceof NoViableNodeException) {
129-
Notification::make()
130-
->title(trans('user-creatable-servers::strings.notifications.server_creation_failed'))
131-
->body(trans('user-creatable-servers::strings.notifications.no_viable_node_found'))
132-
->danger()
133-
->send();
134-
} elseif ($exception instanceof NoViableAllocationException) {
135-
Notification::make()
136-
->title(trans('user-creatable-servers::strings.notifications.server_creation_failed'))
137-
->body(trans('user-creatable-servers::strings.notifications.no_viable_allocation_found'))
138-
->danger()
139-
->send();
140-
} else {
141-
Notification::make()
142-
->title(trans('user-creatable-servers::strings.notifications.server_creation_failed'))
143-
->body(trans('user-creatable-servers::strings.notifications.unknown_server_creation_error'))
144-
->danger()
145-
->send();
146-
}
147-
}
148-
});
35+
$this->url(fn () => CreateServerPage::getUrl());
14936
}
15037
}

0 commit comments

Comments
 (0)