2024-03-24 01:48:03 -04:00
< ? php
namespace App\Filament\Resources\ServerResource\Pages ;
2024-06-16 14:21:25 -04:00
use App\Models\Database ;
2024-06-16 13:50:28 -04:00
use App\Services\Databases\DatabaseManagementService ;
2024-06-16 14:21:25 -04:00
use App\Services\Databases\DatabasePasswordService ;
2024-06-16 13:50:28 -04:00
use Filament\Forms\Components\Actions\Action ;
2024-10-01 04:37:21 -04:00
use Filament\Forms\Components\CheckboxList ;
use Filament\Forms\Components\Fieldset ;
use Filament\Forms\Components\Grid ;
2024-06-16 13:50:28 -04:00
use Filament\Forms\Components\Repeater ;
2024-10-01 04:37:21 -04:00
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 ;
2024-07-30 10:43:24 -04:00
use Filament\Forms\Get ;
use Filament\Forms\Set ;
2024-06-11 21:00:51 +02:00
use LogicException ;
2024-03-24 01:48:03 -04:00
use App\Filament\Resources\ServerResource ;
2024-05-27 20:02:13 -04:00
use App\Http\Controllers\Admin\ServersController ;
2024-05-10 20:24:01 -04:00
use App\Services\Servers\RandomWordService ;
2024-05-27 20:02:13 -04:00
use App\Services\Servers\SuspensionService ;
2024-05-29 18:27:54 -04:00
use App\Services\Servers\TransferServerService ;
2024-04-23 19:45:11 -04:00
use Filament\Actions ;
use Filament\Forms ;
use App\Enums\ContainerStatus ;
use App\Enums\ServerState ;
use App\Models\Egg ;
2024-04-14 02:31:06 -04:00
use App\Models\Server ;
2024-04-23 19:45:11 -04:00
use App\Models\ServerVariable ;
2024-04-14 02:31:06 -04:00
use App\Services\Servers\ServerDeletionService ;
2024-05-27 20:02:13 -04:00
use Filament\Forms\Components\Tabs ;
2024-04-23 19:45:11 -04:00
use Filament\Forms\Form ;
2024-05-27 21:51:24 -04:00
use Filament\Notifications\Notification ;
2024-03-24 01:48:03 -04:00
use Filament\Resources\Pages\EditRecord ;
2024-04-23 19:45:11 -04:00
use Illuminate\Support\Facades\Validator ;
use Closure ;
2024-08-22 22:19:38 +02:00
use Illuminate\Database\Eloquent\Builder ;
2024-05-27 20:02:13 -04:00
use Webbingbrasil\FilamentCopyActions\Forms\Actions\CopyAction ;
2024-03-24 01:48:03 -04:00
class EditServer extends EditRecord
{
protected static string $resource = ServerResource :: class ;
2024-04-23 19:45:11 -04:00
public function form ( Form $form ) : Form
{
return $form
-> schema ([
2024-05-27 20:02:13 -04:00
Tabs :: make ( 'Tabs' )
-> persistTabInQueryString ()
-> columns ([
2024-04-23 19:45:11 -04:00
'default' => 2 ,
'sm' => 2 ,
'md' => 4 ,
'lg' => 6 ,
])
2024-07-30 10:43:24 -04:00
-> columnSpanFull ()
2024-05-27 20:02:13 -04:00
-> tabs ([
2024-10-01 04:37:21 -04:00
Tab :: make ( 'Information' )
2024-06-02 15:05:45 -04:00
-> icon ( 'tabler-info-circle' )
2024-05-27 20:02:13 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'name' )
2024-05-27 20:02:13 -04:00
-> prefixIcon ( 'tabler-server' )
-> label ( 'Display Name' )
2024-10-01 04:37:21 -04:00
-> suffixAction ( Action :: make ( 'random' )
2024-05-27 20:02:13 -04:00
-> icon ( 'tabler-dice-' . random_int ( 1 , 6 ))
2024-10-01 04:37:21 -04:00
-> action ( function ( Set $set , Get $get ) {
2024-05-27 20:02:13 -04:00
$egg = Egg :: find ( $get ( 'egg_id' ));
$prefix = $egg ? str ( $egg -> name ) -> lower () -> kebab () . '-' : '' ;
$word = ( new RandomWordService ()) -> word ();
$set ( 'name' , $prefix . $word );
}))
-> columnSpan ([
'default' => 2 ,
2024-06-25 20:30:06 -04:00
'sm' => 1 ,
2024-05-27 20:02:13 -04:00
'md' => 2 ,
'lg' => 3 ,
])
-> required ()
2024-06-16 19:56:18 +02:00
-> maxLength ( 255 ),
2024-05-27 20:02:13 -04:00
2024-10-01 04:37:21 -04:00
Select :: make ( 'owner_id' )
2024-05-27 20:02:13 -04:00
-> prefixIcon ( 'tabler-user' )
-> label ( 'Owner' )
-> columnSpan ([
'default' => 2 ,
2024-06-25 20:30:06 -04:00
'sm' => 1 ,
2024-05-27 20:02:13 -04:00
'md' => 2 ,
2024-06-25 20:30:06 -04:00
'lg' => 2 ,
2024-05-27 20:02:13 -04:00
])
-> relationship ( 'user' , 'username' )
-> searchable ()
-> preload ()
-> required (),
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( 'condition' )
2024-06-25 20:30:06 -04:00
-> label ( 'Server Status' )
-> formatStateUsing ( fn ( Server $server ) => $server -> condition )
-> options ( fn ( $state ) => collect ( array_merge ( ContainerStatus :: cases (), ServerState :: cases ()))
-> filter ( fn ( $condition ) => $condition -> value === $state )
-> mapWithKeys ( fn ( $state ) => [ $state -> value => str ( $state -> value ) -> replace ( '_' , ' ' ) -> ucwords ()])
)
-> colors ( collect ( array_merge ( ContainerStatus :: cases (), ServerState :: cases ())) -> mapWithKeys (
fn ( $status ) => [ $status -> value => $status -> color ()]
))
-> icons ( collect ( array_merge ( ContainerStatus :: cases (), ServerState :: cases ())) -> mapWithKeys (
fn ( $status ) => [ $status -> value => $status -> icon ()]
))
-> columnSpan ([
'default' => 2 ,
'sm' => 1 ,
'md' => 1 ,
'lg' => 1 ,
]),
2024-10-01 04:37:21 -04:00
Textarea :: make ( 'description' )
2024-05-27 20:02:13 -04:00
-> label ( 'Description' )
-> columnSpanFull (),
2024-04-23 19:45:11 -04:00
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'uuid' )
2024-05-27 20:02:13 -04:00
-> hintAction ( CopyAction :: make ())
-> columnSpan ([
'default' => 2 ,
2024-06-25 20:30:06 -04:00
'sm' => 1 ,
2024-05-27 20:02:13 -04:00
'md' => 2 ,
'lg' => 3 ,
])
2024-07-20 17:38:34 +02:00
-> readOnly ()
-> dehydrated ( false ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'uuid_short' )
2024-05-27 20:02:13 -04:00
-> label ( 'Short UUID' )
-> hintAction ( CopyAction :: make ())
-> columnSpan ([
'default' => 2 ,
2024-06-25 20:30:06 -04:00
'sm' => 1 ,
2024-05-27 20:02:13 -04:00
'md' => 2 ,
'lg' => 3 ,
])
2024-07-20 17:38:34 +02:00
-> readOnly ()
-> dehydrated ( false ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'external_id' )
2024-05-27 20:02:13 -04:00
-> label ( 'External ID' )
-> columnSpan ([
'default' => 2 ,
2024-06-25 20:30:06 -04:00
'sm' => 1 ,
2024-05-27 20:02:13 -04:00
'md' => 2 ,
'lg' => 3 ,
])
2024-06-16 19:56:18 +02:00
-> maxLength ( 255 ),
2024-10-01 04:37:21 -04:00
Select :: make ( 'node_id' )
2024-05-27 20:02:13 -04:00
-> label ( 'Node' )
-> relationship ( 'node' , 'name' )
-> columnSpan ([
'default' => 2 ,
2024-06-25 20:30:06 -04:00
'sm' => 1 ,
2024-05-27 20:02:13 -04:00
'md' => 2 ,
'lg' => 3 ,
])
-> disabled (),
]),
2024-10-01 04:37:21 -04:00
Tab :: make ( 'Environment' )
2024-06-02 15:05:45 -04:00
-> icon ( 'tabler-brand-docker' )
2024-05-07 21:44:44 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
Fieldset :: make ( 'Resource Limits' )
2024-05-27 20:02:13 -04:00
-> columns ([
'default' => 1 ,
'sm' => 2 ,
'md' => 3 ,
'lg' => 3 ,
])
2024-05-19 21:15:43 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
Grid :: make ()
2024-05-27 20:02:13 -04:00
-> columns ( 4 )
-> columnSpanFull ()
-> schema ([
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( 'unlimited_mem' )
2024-05-27 20:02:13 -04:00
-> label ( 'Memory' ) -> inlineLabel () -> inline ()
2024-10-01 04:37:21 -04:00
-> afterStateUpdated ( fn ( Set $set ) => $set ( 'memory' , 0 ))
-> formatStateUsing ( fn ( Get $get ) => $get ( 'memory' ) == 0 )
2024-05-27 20:02:13 -04:00
-> live ()
-> options ([
true => 'Unlimited' ,
false => 'Limited' ,
])
-> colors ([
true => 'primary' ,
false => 'warning' ,
])
-> columnSpan ( 2 ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'memory' )
2024-05-27 20:02:13 -04:00
-> dehydratedWhenHidden ()
2024-10-01 04:37:21 -04:00
-> hidden ( fn ( Get $get ) => $get ( 'unlimited_mem' ))
2024-05-27 20:02:13 -04:00
-> label ( 'Memory Limit' ) -> inlineLabel ()
2024-06-13 08:22:29 +02:00
-> suffix ( config ( 'panel.use_binary_prefix' ) ? 'MiB' : 'MB' )
2024-05-27 20:02:13 -04:00
-> required ()
-> columnSpan ( 2 )
-> numeric ()
-> minValue ( 0 ),
]),
2024-05-19 21:15:43 -04:00
2024-10-01 04:37:21 -04:00
Grid :: make ()
2024-05-27 20:02:13 -04:00
-> columns ( 4 )
-> columnSpanFull ()
-> schema ([
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( 'unlimited_disk' )
2024-05-27 20:02:13 -04:00
-> label ( 'Disk Space' ) -> inlineLabel () -> inline ()
-> live ()
2024-10-01 04:37:21 -04:00
-> afterStateUpdated ( fn ( Set $set ) => $set ( 'disk' , 0 ))
-> formatStateUsing ( fn ( Get $get ) => $get ( 'disk' ) == 0 )
2024-05-27 20:02:13 -04:00
-> options ([
true => 'Unlimited' ,
false => 'Limited' ,
])
-> colors ([
true => 'primary' ,
false => 'warning' ,
])
-> columnSpan ( 2 ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'disk' )
2024-05-27 20:02:13 -04:00
-> dehydratedWhenHidden ()
2024-10-01 04:37:21 -04:00
-> hidden ( fn ( Get $get ) => $get ( 'unlimited_disk' ))
2024-05-27 20:02:13 -04:00
-> label ( 'Disk Space Limit' ) -> inlineLabel ()
2024-06-13 08:22:29 +02:00
-> suffix ( config ( 'panel.use_binary_prefix' ) ? 'MiB' : 'MB' )
2024-05-27 20:02:13 -04:00
-> required ()
-> columnSpan ( 2 )
-> numeric ()
-> minValue ( 0 ),
]),
2024-05-07 21:44:44 -04:00
2024-10-01 04:37:21 -04:00
Grid :: make ()
2024-05-27 20:02:13 -04:00
-> columns ( 4 )
-> columnSpanFull ()
-> schema ([
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( 'unlimited_cpu' )
2024-05-27 20:02:13 -04:00
-> label ( 'CPU' ) -> inlineLabel () -> inline ()
2024-10-01 04:37:21 -04:00
-> afterStateUpdated ( fn ( Set $set ) => $set ( 'cpu' , 0 ))
-> formatStateUsing ( fn ( Get $get ) => $get ( 'cpu' ) == 0 )
2024-05-27 20:02:13 -04:00
-> live ()
-> options ([
true => 'Unlimited' ,
false => 'Limited' ,
])
-> colors ([
true => 'primary' ,
false => 'warning' ,
])
-> columnSpan ( 2 ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'cpu' )
2024-05-27 20:02:13 -04:00
-> dehydratedWhenHidden ()
2024-10-01 04:37:21 -04:00
-> hidden ( fn ( Get $get ) => $get ( 'unlimited_cpu' ))
2024-05-27 20:02:13 -04:00
-> label ( 'CPU Limit' ) -> inlineLabel ()
-> suffix ( '%' )
-> required ()
-> columnSpan ( 2 )
-> numeric ()
-> minValue ( 0 ),
]),
2024-05-19 21:15:43 -04:00
2024-10-01 04:37:21 -04:00
Grid :: make ()
2024-05-27 20:02:13 -04:00
-> columns ( 4 )
-> columnSpanFull ()
-> schema ([
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( 'swap_support' )
2024-05-27 20:02:13 -04:00
-> live ()
-> label ( 'Enable Swap Memory' ) -> inlineLabel () -> inline ()
-> columnSpan ( 2 )
2024-10-01 04:37:21 -04:00
-> afterStateUpdated ( function ( $state , Set $set ) {
2024-05-27 20:02:13 -04:00
$value = match ( $state ) {
'unlimited' => - 1 ,
'disabled' => 0 ,
'limited' => 128 ,
2024-06-11 21:00:51 +02:00
default => throw new LogicException ( 'Invalid state' )
2024-05-27 20:02:13 -04:00
};
$set ( 'swap' , $value );
})
2024-10-01 04:37:21 -04:00
-> formatStateUsing ( function ( Get $get ) {
2024-05-27 20:02:13 -04:00
return match ( true ) {
$get ( 'swap' ) > 0 => 'limited' ,
$get ( 'swap' ) == 0 => 'disabled' ,
$get ( 'swap' ) < 0 => 'unlimited' ,
2024-06-11 21:00:51 +02:00
default => throw new LogicException ( 'Invalid state' )
2024-05-27 20:02:13 -04:00
};
})
-> options ([
'unlimited' => 'Unlimited' ,
'limited' => 'Limited' ,
'disabled' => 'Disabled' ,
])
-> colors ([
'unlimited' => 'primary' ,
'limited' => 'warning' ,
'disabled' => 'danger' ,
]),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'swap' )
2024-05-27 20:02:13 -04:00
-> dehydratedWhenHidden ()
2024-10-01 04:37:21 -04:00
-> hidden ( fn ( Get $get ) => match ( $get ( 'swap_support' )) {
2024-05-27 20:02:13 -04:00
'disabled' , 'unlimited' , true => true ,
2024-06-11 21:00:51 +02:00
default => false ,
2024-05-27 20:02:13 -04:00
})
-> label ( 'Swap Memory' ) -> inlineLabel ()
2024-06-13 08:22:29 +02:00
-> suffix ( config ( 'panel.use_binary_prefix' ) ? 'MiB' : 'MB' )
2024-05-27 20:02:13 -04:00
-> minValue ( - 1 )
-> columnSpan ( 2 )
-> required ()
-> integer (),
]),
Forms\Components\Hidden :: make ( 'io' )
-> helperText ( 'The IO performance relative to other running containers' )
-> label ( 'Block IO Proportion' ),
2024-10-01 04:37:21 -04:00
Grid :: make ()
2024-05-27 20:02:13 -04:00
-> columns ( 4 )
-> columnSpanFull ()
-> schema ([
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( 'oom_killer' )
2024-05-27 20:02:13 -04:00
-> label ( 'OOM Killer' ) -> inlineLabel () -> inline ()
-> columnSpan ( 2 )
-> options ([
false => 'Disabled' ,
true => 'Enabled' ,
])
-> colors ([
false => 'success' ,
true => 'danger' ,
]),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'oom_disabled_hidden' )
2024-05-27 20:02:13 -04:00
-> hidden (),
]),
2024-05-19 21:15:43 -04:00
]),
2024-04-23 19:45:11 -04:00
2024-10-01 04:37:21 -04:00
Fieldset :: make ( 'Feature Limits' )
2024-05-27 20:02:13 -04:00
-> inlineLabel ()
-> columns ([
'default' => 1 ,
'sm' => 2 ,
'md' => 3 ,
'lg' => 3 ,
])
2024-05-19 21:15:43 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'allocation_limit' )
2024-05-27 20:02:13 -04:00
-> suffixIcon ( 'tabler-network' )
-> required ()
2024-06-15 12:33:33 -04:00
-> minValue ( 0 )
2024-05-27 20:02:13 -04:00
-> numeric (),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'database_limit' )
2024-05-27 20:02:13 -04:00
-> suffixIcon ( 'tabler-database' )
-> required ()
2024-06-15 12:33:33 -04:00
-> minValue ( 0 )
2024-05-27 20:02:13 -04:00
-> numeric (),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'backup_limit' )
2024-05-27 20:02:13 -04:00
-> suffixIcon ( 'tabler-copy-check' )
2024-05-19 21:15:43 -04:00
-> required ()
2024-06-15 12:33:33 -04:00
-> minValue ( 0 )
2024-05-27 20:02:13 -04:00
-> numeric (),
2024-05-19 21:15:43 -04:00
]),
2024-10-01 04:37:21 -04:00
Fieldset :: make ( 'Docker Settings' )
2024-05-27 20:02:13 -04:00
-> columns ([
'default' => 1 ,
'sm' => 2 ,
'md' => 3 ,
'lg' => 3 ,
])
2024-05-19 21:15:43 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
Select :: make ( 'select_image' )
2024-05-27 20:02:13 -04:00
-> label ( 'Image Name' )
2024-10-01 04:37:21 -04:00
-> afterStateUpdated ( fn ( Set $set , $state ) => $set ( 'image' , $state ))
-> options ( function ( $state , Get $get , Set $set ) {
2024-05-27 20:02:13 -04:00
$egg = Egg :: query () -> find ( $get ( 'egg_id' ));
$images = $egg -> docker_images ? ? [];
$currentImage = $get ( 'image' );
if ( ! $currentImage && $images ) {
$defaultImage = collect ( $images ) -> first ();
$set ( 'image' , $defaultImage );
$set ( 'select_image' , $defaultImage );
}
return array_flip ( $images ) + [ 'ghcr.io/custom-image' => 'Custom Image' ];
2024-05-19 21:15:43 -04:00
})
2024-05-27 20:02:13 -04:00
-> selectablePlaceholder ( false )
-> columnSpan ( 1 ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'image' )
2024-05-27 20:02:13 -04:00
-> label ( 'Image' )
-> debounce ( 500 )
2024-10-01 04:37:21 -04:00
-> afterStateUpdated ( function ( $state , Get $get , Set $set ) {
2024-05-27 20:02:13 -04:00
$egg = Egg :: query () -> find ( $get ( 'egg_id' ));
$images = $egg -> docker_images ? ? [];
if ( in_array ( $state , $images )) {
$set ( 'select_image' , $state );
} else {
$set ( 'select_image' , 'ghcr.io/custom-image' );
}
2024-05-19 21:15:43 -04:00
})
2024-05-27 20:02:13 -04:00
-> placeholder ( 'Enter a custom Image' )
-> columnSpan ( 2 ),
2024-05-19 21:15:43 -04:00
2024-05-27 20:02:13 -04:00
Forms\Components\KeyValue :: make ( 'docker_labels' )
-> label ( 'Container Labels' )
-> keyLabel ( 'Label Name' )
-> valueLabel ( 'Label Description' )
-> columnSpanFull (),
2024-05-19 21:15:43 -04:00
]),
2024-05-09 19:43:46 -04:00
]),
2024-10-01 04:37:21 -04:00
Tab :: make ( 'Egg' )
2024-06-02 15:05:45 -04:00
-> icon ( 'tabler-egg' )
2024-05-09 19:43:46 -04:00
-> columns ([
'default' => 1 ,
2024-05-27 20:02:13 -04:00
'sm' => 3 ,
2024-05-09 19:43:46 -04:00
'md' => 3 ,
2024-05-27 20:02:13 -04:00
'lg' => 5 ,
2024-04-23 19:45:11 -04:00
])
2024-05-09 19:43:46 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
Select :: make ( 'egg_id' )
2024-05-27 20:02:13 -04:00
-> disabledOn ( 'edit' )
-> prefixIcon ( 'tabler-egg' )
-> columnSpan ([
2024-07-30 10:43:24 -04:00
'default' => 6 ,
2024-05-27 20:02:13 -04:00
'sm' => 3 ,
'md' => 3 ,
2024-07-30 10:43:24 -04:00
'lg' => 4 ,
2024-05-27 20:02:13 -04:00
])
-> relationship ( 'egg' , 'name' )
-> searchable ()
-> preload ()
-> required (),
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( 'skip_scripts' )
2024-05-27 20:02:13 -04:00
-> label ( 'Run Egg Install Script?' ) -> inline ()
2024-07-30 10:43:24 -04:00
-> columnSpan ([
'default' => 6 ,
'sm' => 1 ,
'md' => 1 ,
'lg' => 2 ,
])
2024-05-27 20:02:13 -04:00
-> options ([
false => 'Yes' ,
true => 'Skip' ,
])
-> colors ([
false => 'primary' ,
true => 'danger' ,
])
-> icons ([
false => 'tabler-code' ,
true => 'tabler-code-off' ,
])
-> required (),
2024-10-01 04:37:21 -04:00
Textarea :: make ( 'startup' )
2024-05-27 20:02:13 -04:00
-> label ( 'Startup Command' )
2024-05-09 19:43:46 -04:00
-> required ()
2024-07-30 10:43:24 -04:00
-> columnSpan ( 6 )
2024-05-27 20:02:13 -04:00
-> rows ( function ( $state ) {
return str ( $state ) -> explode ( " \n " ) -> reduce (
fn ( int $carry , $line ) => $carry + floor ( strlen ( $line ) / 125 ),
0
);
}),
2024-10-01 04:37:21 -04:00
Textarea :: make ( 'defaultStartup' )
2024-05-27 20:02:13 -04:00
-> hintAction ( CopyAction :: make ())
-> label ( 'Default Startup Command' )
-> disabled ()
2024-10-01 04:37:21 -04:00
-> formatStateUsing ( function ( $state , Get $get ) {
2024-05-19 21:15:43 -04:00
$egg = Egg :: query () -> find ( $get ( 'egg_id' ));
2024-05-27 20:02:13 -04:00
return $egg -> startup ;
})
2024-07-30 10:43:24 -04:00
-> columnSpan ( 6 ),
2024-05-27 20:02:13 -04:00
2024-10-01 04:37:21 -04:00
Repeater :: make ( 'server_variables' )
2024-08-22 22:19:38 +02:00
-> relationship ( 'serverVariables' , function ( Builder $query ) {
/** @var Server $server */
$server = $this -> getRecord ();
foreach ( $server -> variables as $variable ) {
ServerVariable :: query () -> firstOrCreate ([
'server_id' => $server -> id ,
'variable_id' => $variable -> id ,
], [
'variable_value' => $variable -> server_value ? ? '' ,
]);
}
return $query ;
})
2024-05-27 20:02:13 -04:00
-> grid ()
-> mutateRelationshipDataBeforeSaveUsing ( function ( array & $data ) : array {
foreach ( $data as $key => $value ) {
if ( ! isset ( $data [ 'variable_value' ])) {
$data [ 'variable_value' ] = '' ;
}
2024-05-19 21:15:43 -04:00
}
2024-05-27 20:02:13 -04:00
return $data ;
2024-05-19 21:15:43 -04:00
})
2024-05-27 20:02:13 -04:00
-> reorderable ( false ) -> addable ( false ) -> deletable ( false )
-> schema ( function () {
2024-10-01 04:37:21 -04:00
$text = TextInput :: make ( 'variable_value' )
2024-05-27 20:02:13 -04:00
-> hidden ( $this -> shouldHideComponent ( ... ))
2024-08-19 08:33:53 +02:00
-> required ( fn ( ServerVariable $serverVariable ) => $serverVariable -> variable -> getRequiredAttribute ())
2024-05-27 20:02:13 -04:00
-> rules ([
fn ( ServerVariable $serverVariable ) : Closure => function ( string $attribute , $value , Closure $fail ) use ( $serverVariable ) {
$validator = Validator :: make ([ 'validatorkey' => $value ], [
'validatorkey' => $serverVariable -> variable -> rules ,
]);
if ( $validator -> fails ()) {
$message = str ( $validator -> errors () -> first ()) -> replace ( 'validatorkey' , $serverVariable -> variable -> name );
$fail ( $message );
}
},
]);
2024-05-19 21:15:43 -04:00
2024-10-01 04:37:21 -04:00
$select = Select :: make ( 'variable_value' )
2024-05-27 20:02:13 -04:00
-> hidden ( $this -> shouldHideComponent ( ... ))
-> options ( $this -> getSelectOptionsFromRules ( ... ))
-> selectablePlaceholder ( false );
$components = [ $text , $select ];
foreach ( $components as & $component ) {
$component = $component
-> live ( onBlur : true )
-> hintIcon ( 'tabler-code' )
-> label ( fn ( ServerVariable $serverVariable ) => $serverVariable -> variable -> name )
2024-08-19 08:33:53 +02:00
-> hintIconTooltip ( fn ( ServerVariable $serverVariable ) => implode ( '|' , $serverVariable -> variable -> rules ))
2024-05-27 20:02:13 -04:00
-> prefix ( fn ( ServerVariable $serverVariable ) => '{{' . $serverVariable -> variable -> env_variable . '}}' )
-> helperText ( fn ( ServerVariable $serverVariable ) => empty ( $serverVariable -> variable -> description ) ? '—' : $serverVariable -> variable -> description );
2024-05-19 21:15:43 -04:00
}
2024-05-27 20:02:13 -04:00
return $components ;
})
-> columnSpan ( 6 ),
]),
2024-10-01 04:37:21 -04:00
Tab :: make ( 'Mounts' )
2024-06-02 15:05:45 -04:00
-> icon ( 'tabler-layers-linked' )
2024-05-29 19:18:09 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
CheckboxList :: make ( 'mounts' )
2024-06-02 15:05:45 -04:00
-> 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 " ]))
-> label ( 'Mounts' )
2024-06-06 10:18:05 +02:00
-> helperText ( fn ( Server $server ) => $server -> node -> mounts -> isNotEmpty () ? '' : 'No Mounts exist for this Node' )
2024-06-02 15:05:45 -04:00
-> columnSpanFull (),
2024-05-29 19:18:09 -04:00
]),
2024-10-01 04:37:21 -04:00
Tab :: make ( 'Databases' )
2024-06-02 15:05:45 -04:00
-> icon ( 'tabler-database' )
2024-05-29 19:18:09 -04:00
-> schema ([
2024-06-16 13:50:28 -04:00
Repeater :: make ( 'databases' )
-> grid ()
2024-06-16 14:21:25 -04:00
-> helperText ( fn ( Server $server ) => $server -> databases -> isNotEmpty () ? '' : 'No Databases exist for this Server' )
-> columns ( 2 )
2024-06-16 13:50:28 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'database' )
2024-06-16 14:21:25 -04:00
-> columnSpan ( 2 )
2024-06-16 13:50:28 -04:00
-> label ( 'Database Name' )
2024-06-16 14:21:25 -04:00
-> disabled ()
-> formatStateUsing ( fn ( $record ) => $record -> database )
2024-06-16 13:50:28 -04:00
-> hintAction (
Action :: make ( 'Delete' )
-> color ( 'danger' )
-> icon ( 'tabler-trash' )
-> action ( fn ( DatabaseManagementService $databaseManagementService , $record ) => $databaseManagementService -> delete ( $record ))
2024-06-16 14:21:25 -04:00
),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'username' )
2024-06-16 14:21:25 -04:00
-> disabled ()
2024-06-16 13:50:28 -04:00
-> formatStateUsing ( fn ( $record ) => $record -> username )
2024-06-16 14:21:25 -04:00
-> columnSpan ( 2 ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'password' )
2024-06-16 14:21:25 -04:00
-> disabled ()
-> hintAction (
Action :: make ( 'rotate' )
-> icon ( 'tabler-refresh' )
-> requiresConfirmation ()
-> action ( fn ( DatabasePasswordService $service , $record , $set , $get ) => $this -> rotatePassword ( $service , $record , $set , $get ))
)
-> formatStateUsing ( fn ( Database $database ) => $database -> password )
-> columnSpan ( 2 ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'remote' )
2024-06-16 14:21:25 -04:00
-> disabled ()
-> formatStateUsing ( fn ( $record ) => $record -> remote )
-> columnSpan ( 1 )
-> label ( 'Connections From' ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'max_connections' )
2024-06-16 14:21:25 -04:00
-> disabled ()
-> formatStateUsing ( fn ( $record ) => $record -> max_connections )
-> columnSpan ( 1 ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'JDBC' )
2024-06-16 14:21:25 -04:00
-> disabled ()
-> label ( 'JDBC Connection String' )
-> columnSpan ( 2 )
2024-10-01 04:37:21 -04:00
-> formatStateUsing ( fn ( Get $get , $record ) => 'jdbc:mysql://' . $get ( 'username' ) . ':' . urlencode ( $record -> password ) . '@' . $record -> host -> host . ':' . $record -> host -> port . '/' . $get ( 'database' )),
2024-06-16 13:50:28 -04:00
])
-> relationship ( 'databases' )
-> deletable ( false )
-> addable ( false )
-> columnSpan ( 4 ),
]) -> columns ( 4 ),
2024-10-01 04:37:21 -04:00
Tab :: make ( 'Actions' )
2024-06-02 15:05:45 -04:00
-> icon ( 'tabler-settings' )
2024-05-27 20:02:13 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
Fieldset :: make ( 'Server Actions' )
2024-05-27 20:02:13 -04:00
-> columns ([
'default' => 1 ,
'sm' => 2 ,
'md' => 2 ,
'lg' => 6 ,
])
-> schema ([
2024-10-01 04:37:21 -04:00
Grid :: make ()
2024-05-27 20:02:13 -04:00
-> columnSpan ( 3 )
-> schema ([
Forms\Components\Actions :: make ([
2024-10-01 04:37:21 -04:00
Action :: make ( 'toggleInstall' )
2024-05-29 18:27:54 -04:00
-> label ( 'Toggle Install Status' )
2024-05-27 21:51:24 -04:00
-> disabled ( fn ( Server $server ) => $server -> isSuspended ())
-> action ( function ( ServersController $serversController , Server $server ) {
$serversController -> toggleInstall ( $server );
2024-06-11 21:00:51 +02:00
$this -> refreshFormData ([ 'status' , 'docker' ]);
2024-05-27 21:51:24 -04:00
}),
2024-05-27 20:02:13 -04:00
]) -> fullWidth (),
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( '' )
2024-05-27 20:02:13 -04:00
-> hint ( 'If you need to change the install status from uninstalled to installed, or vice versa, you may do so with this button.' ),
]),
2024-10-01 04:37:21 -04:00
Grid :: make ()
2024-05-27 20:02:13 -04:00
-> columnSpan ( 3 )
-> schema ([
Forms\Components\Actions :: make ([
2024-10-01 04:37:21 -04:00
Action :: make ( 'toggleSuspend' )
2024-05-27 20:02:13 -04:00
-> label ( 'Suspend' )
-> color ( 'warning' )
-> hidden ( fn ( Server $server ) => $server -> isSuspended ())
2024-05-27 21:51:24 -04:00
-> action ( function ( SuspensionService $suspensionService , Server $server ) {
$suspensionService -> toggle ( $server , 'suspend' );
Notification :: make () -> success () -> title ( 'Server Suspended!' ) -> send ();
2024-06-11 21:00:51 +02:00
$this -> refreshFormData ([ 'status' , 'docker' ]);
2024-05-27 21:51:24 -04:00
}),
2024-10-01 04:37:21 -04:00
Action :: make ( 'toggleUnsuspend' )
2024-05-27 20:02:13 -04:00
-> label ( 'Unsuspend' )
-> color ( 'success' )
-> hidden ( fn ( Server $server ) => ! $server -> isSuspended ())
2024-05-27 21:51:24 -04:00
-> action ( function ( SuspensionService $suspensionService , Server $server ) {
$suspensionService -> toggle ( $server , 'unsuspend' );
Notification :: make () -> success () -> title ( 'Server Unsuspended!' ) -> send ();
2024-06-11 21:00:51 +02:00
$this -> refreshFormData ([ 'status' , 'docker' ]);
2024-05-27 21:51:24 -04:00
}),
2024-05-27 20:02:13 -04:00
]) -> fullWidth (),
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( '' )
2024-05-27 20:02:13 -04:00
-> 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.' ),
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( '' )
2024-05-27 20:02:13 -04:00
-> hidden ( fn ( Server $server ) => ! $server -> isSuspended ())
-> hint ( 'This will unsuspend the server and restore normal user access.' ),
]),
2024-10-01 04:37:21 -04:00
Grid :: make ()
2024-05-27 20:02:13 -04:00
-> columnSpan ( 3 )
-> schema ([
Forms\Components\Actions :: make ([
2024-10-01 04:37:21 -04:00
Action :: make ( 'transfer' )
2024-05-29 19:18:09 -04:00
-> label ( 'Transfer Soon™' )
2024-06-11 21:00:51 +02:00
-> action ( fn ( TransferServerService $transfer , Server $server ) => $transfer -> handle ( $server , []))
2024-05-29 19:18:09 -04:00
-> disabled () //TODO!
-> form ([ //TODO!
2024-10-01 04:37:21 -04:00
Select :: make ( 'newNode' )
2024-05-29 18:27:54 -04:00
-> label ( 'New Node' )
-> required ()
-> options ([
true => 'on' ,
false => 'off' ,
]),
2024-10-01 04:37:21 -04:00
Select :: make ( 'newMainAllocation' )
2024-05-29 18:27:54 -04:00
-> label ( 'New Main Allocation' )
-> required ()
-> options ([
true => 'on' ,
false => 'off' ,
]),
2024-10-01 04:37:21 -04:00
Select :: make ( 'newAdditionalAllocation' )
2024-05-29 18:27:54 -04:00
-> label ( 'New Additional Allocations' )
-> options ([
true => 'on' ,
false => 'off' ,
]),
])
-> modalHeading ( 'Transfer' ),
2024-05-27 20:02:13 -04:00
]) -> fullWidth (),
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( '' )
2024-05-27 20:02:13 -04:00
-> hint ( 'Transfer this server to another node connected to this panel. Warning! This feature has not been fully tested and may have bugs.' ),
]),
2024-10-01 04:37:21 -04:00
Grid :: make ()
2024-05-27 20:02:13 -04:00
-> columnSpan ( 3 )
-> schema ([
Forms\Components\Actions :: make ([
2024-10-01 04:37:21 -04:00
Action :: make ( 'reinstall' )
2024-05-27 20:02:13 -04:00
-> label ( 'Reinstall' )
-> color ( 'danger' )
-> requiresConfirmation ()
2024-05-29 18:27:54 -04:00
-> modalHeading ( 'Are you sure you want to reinstall this server?' )
-> modalDescription ( '!! This can result in unrecoverable data loss !!' )
2024-05-27 21:51:24 -04:00
-> disabled ( fn ( Server $server ) => $server -> isSuspended ())
2024-05-27 20:02:13 -04:00
-> action ( fn ( ServersController $serversController , Server $server ) => $serversController -> reinstallServer ( $server )),
]) -> fullWidth (),
2024-10-01 04:37:21 -04:00
ToggleButtons :: make ( '' )
2024-05-29 18:27:54 -04:00
-> hint ( 'This will reinstall the server with the assigned egg install script.' ),
2024-05-27 20:02:13 -04:00
]),
]),
2024-05-19 21:15:43 -04:00
]),
2024-04-23 19:45:11 -04:00
]),
]);
}
2024-05-29 18:27:54 -04:00
protected function transferServer ( Form $form ) : Form
{
return $form
2024-06-16 13:50:28 -04:00
-> columns ()
2024-05-29 18:27:54 -04:00
-> schema ([
2024-10-01 04:37:21 -04:00
Select :: make ( 'toNode' )
2024-05-29 18:27:54 -04:00
-> label ( 'New Node' ),
2024-10-01 04:37:21 -04:00
TextInput :: make ( 'newAllocation' )
2024-05-29 18:27:54 -04:00
-> label ( 'Allocation' ),
]);
}
2024-03-24 01:48:03 -04:00
protected function getHeaderActions () : array
{
return [
2024-09-27 14:28:32 -04:00
Actions\Action :: make ( 'Delete' )
2024-04-23 20:33:54 -04:00
-> successRedirectUrl ( route ( 'filament.admin.resources.servers.index' ))
2024-04-23 20:03:57 -04:00
-> color ( 'danger' )
2024-07-02 19:31:35 +02:00
-> label ( 'Delete' )
2024-09-27 14:28:32 -04:00
-> requiresConfirmation ()
-> action ( function ( Server $server ) {
resolve ( ServerDeletionService :: class ) -> handle ( $server );
return redirect ( ListServers :: getUrl ());
}),
2024-04-29 22:13:54 -04:00
Actions\Action :: make ( 'console' )
-> label ( 'Console' )
-> icon ( 'tabler-terminal' )
-> url ( fn ( Server $server ) => " /server/ $server->uuid_short " ),
$this -> getSaveFormAction () -> formId ( 'form' ),
2024-03-24 01:48:03 -04:00
];
2024-04-28 14:25:40 -04:00
}
2024-04-30 19:49:18 -04:00
protected function getFormActions () : array
{
return [];
}
2024-04-25 19:48:46 -04:00
protected function mutateFormDataBeforeSave ( array $data ) : array
{
2024-05-27 20:02:13 -04:00
if ( ! isset ( $data [ 'description' ])) {
$data [ 'description' ] = '' ;
}
2024-04-25 19:48:46 -04:00
unset ( $data [ 'docker' ], $data [ 'status' ]);
return $data ;
}
2024-04-25 22:36:59 -04:00
public function getRelationManagers () : array
{
return [
ServerResource\RelationManagers\AllocationsRelationManager :: class ,
];
}
2024-05-12 22:37:40 -04:00
2024-08-19 08:33:53 +02:00
private function shouldHideComponent ( ServerVariable $serverVariable , Forms\Components\Component $component ) : bool
2024-05-12 22:37:40 -04:00
{
2024-08-19 08:33:53 +02:00
$containsRuleIn = array_first ( $serverVariable -> variable -> rules , fn ( $value ) => str ( $value ) -> startsWith ( 'in:' ), false );
2024-05-12 22:37:40 -04:00
2024-10-01 04:37:21 -04:00
if ( $component instanceof Select ) {
2024-08-19 08:33:53 +02:00
return ! $containsRuleIn ;
2024-05-12 22:37:40 -04:00
}
2024-10-01 04:37:21 -04:00
if ( $component instanceof TextInput ) {
2024-08-19 08:33:53 +02:00
return $containsRuleIn ;
2024-05-12 22:37:40 -04:00
}
throw new \Exception ( 'Component type not supported: ' . $component :: class );
}
2024-08-19 08:33:53 +02:00
private function getSelectOptionsFromRules ( ServerVariable $serverVariable ) : array
2024-05-12 22:37:40 -04:00
{
2024-08-19 08:33:53 +02:00
$inRule = array_first ( $serverVariable -> variable -> rules , fn ( $value ) => str ( $value ) -> startsWith ( 'in:' ));
2024-05-12 22:37:40 -04:00
return str ( $inRule )
-> after ( 'in:' )
-> explode ( ',' )
-> each ( fn ( $value ) => str ( $value ) -> trim ())
-> mapWithKeys ( fn ( $value ) => [ $value => $value ])
-> all ();
}
2024-06-16 14:21:25 -04:00
protected function rotatePassword ( DatabasePasswordService $service , $record , $set , $get ) : void
{
$newPassword = $service -> handle ( $record );
$jdbcString = 'jdbc:mysql://' . $get ( 'username' ) . ':' . urlencode ( $newPassword ) . '@' . $record -> host -> host . ':' . $record -> host -> port . '/' . $get ( 'database' );
$set ( 'password' , $newPassword );
$set ( 'JDBC' , $jdbcString );
}
2024-03-24 01:48:03 -04:00
}