Update node pages

This commit is contained in:
notCharles 2024-05-14 19:22:14 -04:00
parent 2d643ec79f
commit 98ba2c1b8b
2 changed files with 422 additions and 151 deletions

View File

@ -4,6 +4,7 @@ namespace App\Filament\Resources\NodeResource\Pages;
use App\Filament\Resources\NodeResource; use App\Filament\Resources\NodeResource;
use Filament\Forms; use Filament\Forms;
use Filament\Forms\Components\Tabs;
use Filament\Resources\Pages\CreateRecord; use Filament\Resources\Pages\CreateRecord;
use Illuminate\Support\HtmlString; use Illuminate\Support\HtmlString;
@ -17,179 +18,298 @@ class CreateNode extends CreateRecord
public function form(Forms\Form $form): Forms\Form public function form(Forms\Form $form): Forms\Form
{ {
return $form return $form->schema([
->columns([ Tabs::make('Tabs')
'default' => 2, ->columns([
'sm' => 3, 'default' => 2,
'md' => 3, 'sm' => 3,
'lg' => 4, 'md' => 3,
]) 'lg' => 4,
->schema([ ])
Forms\Components\TextInput::make('fqdn') ->persistTabInQueryString()
->columnSpan(2) ->columnSpanFull()
->required() ->tabs([
->autofocus() Tabs\Tab::make('Basic Settings')
->live(debounce: 1500) ->icon('tabler-server')
->rule('prohibited', fn ($state) => is_ip($state) && request()->isSecure()) ->schema([
->label(fn ($state) => is_ip($state) ? 'IP Address' : 'Domain Name') Forms\Components\TextInput::make('fqdn')
->placeholder(fn ($state) => is_ip($state) ? '192.168.1.1' : 'node.example.com') ->columnSpan(2)
->helperText(function ($state) { ->required()
if (is_ip($state)) { ->autofocus()
if (request()->isSecure()) { ->live(debounce: 1500)
return ' ->rule('prohibited', fn ($state) => is_ip($state) && request()->isSecure())
->label(fn ($state) => is_ip($state) ? 'IP Address' : 'Domain Name')
->placeholder(fn ($state) => is_ip($state) ? '192.168.1.1' : 'node.example.com')
->helperText(function ($state) {
if (is_ip($state)) {
if (request()->isSecure()) {
return '
Your panel is currently secured via an SSL certificate and that means your nodes require one too. Your panel is currently secured via an SSL certificate and that means your nodes require one too.
You must use a domain name, because you cannot get SSL certificates for IP Addresses You must use a domain name, because you cannot get SSL certificates for IP Addresses
'; ';
} }
return ''; return '';
} }
return " return "
This is the domain name that points to your node's IP Address. This is the domain name that points to your node's IP Address.
If you've already set up this, you can verify it by checking the next field! If you've already set up this, you can verify it by checking the next field!
"; ";
}) })
->hintColor('danger') ->hintColor('danger')
->hint(function ($state) { ->hint(function ($state) {
if (is_ip($state) && request()->isSecure()) { if (is_ip($state) && request()->isSecure()) {
return 'You cannot connect to an IP Address over SSL'; return 'You cannot connect to an IP Address over SSL';
} }
return ''; return '';
}) })
->afterStateUpdated(function (Forms\Set $set, ?string $state) { ->afterStateUpdated(function (Forms\Set $set, ?string $state) {
$set('dns', null); $set('dns', null);
$set('ip', null); $set('ip', null);
[$subdomain] = str($state)->explode('.', 2); [$subdomain] = str($state)->explode('.', 2);
if (!is_numeric($subdomain)) { if (!is_numeric($subdomain)) {
$set('name', $subdomain); $set('name', $subdomain);
} }
if (!$state || is_ip($state)) { if (!$state || is_ip($state)) {
$set('dns', null); $set('dns', null);
return; return;
} }
$validRecords = gethostbynamel($state); $validRecords = gethostbynamel($state);
if ($validRecords) { if ($validRecords) {
$set('dns', true); $set('dns', true);
$set('ip', collect($validRecords)->first()); $set('ip', collect($validRecords)->first());
return; return;
} }
$set('dns', false); $set('dns', false);
}) })
->maxLength(191), ->maxLength(191),
Forms\Components\TextInput::make('ip') Forms\Components\TextInput::make('ip')
->disabled() ->disabled()
->hidden(), ->hidden(),
Forms\Components\ToggleButtons::make('dns') Forms\Components\ToggleButtons::make('dns')
->label('DNS Record Check') ->label('DNS Record Check')
->helperText('This lets you know if your DNS record correctly points to an IP Address.') ->helperText('This lets you know if your DNS record correctly points to an IP Address.')
->disabled() ->disabled()
->inline() ->inline()
->default(null) ->default(null)
->hint(fn (Forms\Get $get) => $get('ip')) ->hint(fn (Forms\Get $get) => $get('ip'))
->hintColor('success') ->hintColor('success')
->options([ ->options([
true => 'Valid', true => 'Valid',
false => 'Invalid', false => 'Invalid',
]) ])
->colors([ ->colors([
true => 'success', true => 'success',
false => 'danger', false => 'danger',
]) ])
->columnSpan([ ->columnSpan([
'default' => 1, 'default' => 1,
'sm' => 1, 'sm' => 1,
'md' => 1, 'md' => 1,
'lg' => 1, 'lg' => 1,
]), ]),
Forms\Components\TextInput::make('daemon_listen') Forms\Components\TextInput::make('daemon_listen')
->columnSpan([ ->columnSpan([
'default' => 1, 'default' => 1,
'sm' => 1, 'sm' => 1,
'md' => 1, 'md' => 1,
'lg' => 1, 'lg' => 1,
]) ])
->label(trans('strings.port')) ->label(trans('strings.port'))
->helperText('If you are running the daemon behind Cloudflare you should set the daemon port to 8443 to allow websocket proxying over SSL.') ->helperText('If you are running the daemon behind Cloudflare you should set the daemon port to 8443 to allow websocket proxying over SSL.')
->minValue(0) ->minValue(0)
->maxValue(65536) ->maxValue(65536)
->default(8080) ->default(8080)
->required() ->required()
->integer(), ->integer(),
Forms\Components\TextInput::make('name') Forms\Components\TextInput::make('name')
->label('Display Name') ->label('Display Name')
->columnSpan([ ->columnSpan([
'default' => 1, 'default' => 1,
'sm' => 1, 'sm' => 1,
'md' => 1, 'md' => 1,
'lg' => 2, 'lg' => 2,
]) ])
->required() ->required()
->regex('/[a-zA-Z0-9_\.\- ]+/') ->regex('/[a-zA-Z0-9_\.\- ]+/')
->helperText('This name is for display only and can be changed later.') ->helperText('This name is for display only and can be changed later.')
->maxLength(100), ->maxLength(100),
Forms\Components\ToggleButtons::make('scheme') Forms\Components\ToggleButtons::make('scheme')
->label('Communicate over SSL') ->label('Communicate over SSL')
->columnSpan([ ->columnSpan([
'default' => 1, 'default' => 1,
'sm' => 1, 'sm' => 1,
'md' => 1, 'md' => 1,
'lg' => 1, 'lg' => 1,
]) ])
->required() ->required()
->inline() ->inline()
->helperText(function (Forms\Get $get) { ->helperText(function (Forms\Get $get) {
if (request()->isSecure()) { if (request()->isSecure()) {
return new HtmlString('Your Panel is using a secure SSL connection,<br>so your Daemon must too.'); return new HtmlString('Your Panel is using a secure SSL connection,<br>so your Daemon must too.');
} }
if (is_ip($get('fqdn'))) { if (is_ip($get('fqdn'))) {
return 'An IP address cannot use SSL.'; return 'An IP address cannot use SSL.';
} }
return ''; return '';
}) })
->disableOptionWhen(fn (string $value): bool => $value === 'http' && request()->isSecure()) ->disableOptionWhen(fn (string $value): bool => $value === 'http' && request()->isSecure())
->options([ ->options([
'http' => 'HTTP', 'http' => 'HTTP',
'https' => 'HTTPS (SSL)', 'https' => 'HTTPS (SSL)',
]) ])
->colors([ ->colors([
'http' => 'warning', 'http' => 'warning',
'https' => 'success', 'https' => 'success',
]) ])
->icons([ ->icons([
'http' => 'tabler-lock-open-off', 'http' => 'tabler-lock-open-off',
'https' => 'tabler-lock', 'https' => 'tabler-lock',
]) ])
->default(fn () => request()->isSecure() ? 'https' : 'http'), ->default(fn () => request()->isSecure() ? 'https' : 'http'),
]),
Forms\Components\Textarea::make('description') Tabs\Tab::make('Advanced Settings')
->label('strings.description') ->icon('tabler-server-cog')
->hidden() ->schema([
->columnSpan([ Forms\Components\TextInput::make('upload_size')
'default' => 1, ->label('Upload Limit')
'sm' => 1, ->helperText('Enter the maximum size of files that can be uploaded through the web-based file manager.')
'md' => 2, ->columnSpan(1)
'lg' => 4, ->numeric()->required()
]) ->default(256)
->rows(5), ->minValue(1)
->maxValue(1024)
Forms\Components\Hidden::make('skipValidation')->default(true), ->suffix('MiB'),
]); Forms\Components\ToggleButtons::make('public')
->label('Automatic Allocation')->inline()
->default(true)
->columnSpan(1)
->options([
true => 'Yes',
false => 'No',
])
->colors([
true => 'success',
false => 'danger',
]),
Forms\Components\ToggleButtons::make('maintenance_mode')
->label('Maintenance Mode')->inline()
->columnSpan(1)
->default(false)
->hinticon('tabler-question-mark')
->hintIconTooltip("If the node is marked 'Under Maintenance' users won't be able to access servers that are on this node.")
->options([
true => 'Enable',
false => 'Disable',
])
->colors([
true => 'danger',
false => 'success',
]),
Forms\Components\TagsInput::make('tags')
->label('Tags')
->disabled()
->placeholder('Not Implemented')
->hintIcon('tabler-question-mark')
->hintIconTooltip('Not Implemented')
->columnSpan(1),
Forms\Components\Grid::make()
->columns(6)
->columnSpanFull()
->schema([
Forms\Components\ToggleButtons::make('unlimited_mem')
->label('Memory')->inlineLabel()->inline()
->afterStateUpdated(fn (Forms\Set $set) => $set('memory', 0))
->afterStateUpdated(fn (Forms\Set $set) => $set('memory_overallocate', 0))
->formatStateUsing(fn (Forms\Get $get) => $get('memory') == 0)
->live()
->options([
true => 'Unlimited',
false => 'Limited',
])
->colors([
true => 'primary',
false => 'warning',
])
->columnSpan(2),
Forms\Components\TextInput::make('memory')
->dehydratedWhenHidden()
->hidden(fn (Forms\Get $get) => $get('unlimited_mem'))
->label('Memory Limit')->inlineLabel()
->suffix('MiB')
->columnSpan(2)
->numeric()
->minValue(0),
Forms\Components\TextInput::make('memory_overallocate')
->dehydratedWhenHidden()
->label('Overallocate')->inlineLabel()
->hidden(fn (Forms\Get $get) => $get('unlimited_mem'))
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
->columnSpan(2)
->numeric()
->minValue(-1)
->maxValue(100)
->suffix('%'),
]),
Forms\Components\Grid::make()
->columns(6)
->columnSpanFull()
->schema([
Forms\Components\ToggleButtons::make('unlimited_disk')
->label('Disk')->inlineLabel()->inline()
->live()
->afterStateUpdated(fn (Forms\Set $set) => $set('disk', 0))
->afterStateUpdated(fn (Forms\Set $set) => $set('disk_overallocate', 0))
->formatStateUsing(fn (Forms\Get $get) => $get('disk') == 0)
->options([
true => 'Unlimited',
false => 'Limited',
])
->colors([
true => 'primary',
false => 'warning',
])
->columnSpan(2),
Forms\Components\TextInput::make('disk')
->dehydratedWhenHidden()
->hidden(fn (Forms\Get $get) => $get('unlimited_disk'))
->label('Disk Limit')->inlineLabel()
->suffix('MiB')
->columnSpan(2)
->numeric()
->minValue(0),
Forms\Components\TextInput::make('disk_overallocate')
->dehydratedWhenHidden()
->hidden(fn (Forms\Get $get) => $get('unlimited_disk'))
->label('Overallocate')->inlineLabel()
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
->columnSpan(2)
->numeric()
->minValue(-1)
->maxValue(100)
->suffix('%'),
]),
]),
]),
]);
} }
protected function getRedirectUrlParameters(): array protected function getRedirectUrlParameters(): array

View File

@ -32,7 +32,158 @@ class EditNode extends EditRecord
->tabs([ ->tabs([
Tabs\Tab::make('Basic Settings') Tabs\Tab::make('Basic Settings')
->icon('tabler-server') ->icon('tabler-server')
->schema((new CreateNode())->form($form)->getComponents()), ->schema([
Forms\Components\TextInput::make('fqdn')
->columnSpan(2)
->required()
->autofocus()
->live(debounce: 1500)
->rule('prohibited', fn ($state) => is_ip($state) && request()->isSecure())
->label(fn ($state) => is_ip($state) ? 'IP Address' : 'Domain Name')
->placeholder(fn ($state) => is_ip($state) ? '192.168.1.1' : 'node.example.com')
->helperText(function ($state) {
if (is_ip($state)) {
if (request()->isSecure()) {
return '
Your panel is currently secured via an SSL certificate and that means your nodes require one too.
You must use a domain name, because you cannot get SSL certificates for IP Addresses
';
}
return '';
}
return "
This is the domain name that points to your node's IP Address.
If you've already set up this, you can verify it by checking the next field!
";
})
->hintColor('danger')
->hint(function ($state) {
if (is_ip($state) && request()->isSecure()) {
return 'You cannot connect to an IP Address over SSL';
}
return '';
})
->afterStateUpdated(function (Forms\Set $set, ?string $state) {
$set('dns', null);
$set('ip', null);
[$subdomain] = str($state)->explode('.', 2);
if (!is_numeric($subdomain)) {
$set('name', $subdomain);
}
if (!$state || is_ip($state)) {
$set('dns', null);
return;
}
$validRecords = gethostbynamel($state);
if ($validRecords) {
$set('dns', true);
$set('ip', collect($validRecords)->first());
return;
}
$set('dns', false);
})
->maxLength(191),
Forms\Components\TextInput::make('ip')
->disabled()
->hidden(),
Forms\Components\ToggleButtons::make('dns')
->label('DNS Record Check')
->helperText('This lets you know if your DNS record correctly points to an IP Address.')
->disabled()
->inline()
->default(null)
->hint(fn (Forms\Get $get) => $get('ip'))
->hintColor('success')
->options([
true => 'Valid',
false => 'Invalid',
])
->colors([
true => 'success',
false => 'danger',
])
->columnSpan([
'default' => 1,
'sm' => 1,
'md' => 1,
'lg' => 1,
]),
Forms\Components\TextInput::make('daemon_listen')
->columnSpan([
'default' => 1,
'sm' => 1,
'md' => 1,
'lg' => 1,
])
->label(trans('strings.port'))
->helperText('If you are running the daemon behind Cloudflare you should set the daemon port to 8443 to allow websocket proxying over SSL.')
->minValue(0)
->maxValue(65536)
->default(8080)
->required()
->integer(),
Forms\Components\TextInput::make('name')
->label('Display Name')
->columnSpan([
'default' => 1,
'sm' => 1,
'md' => 1,
'lg' => 2,
])
->required()
->regex('/[a-zA-Z0-9_\.\- ]+/')
->helperText('This name is for display only and can be changed later.')
->maxLength(100),
Forms\Components\ToggleButtons::make('scheme')
->label('Communicate over SSL')
->columnSpan([
'default' => 1,
'sm' => 1,
'md' => 1,
'lg' => 1,
])
->required()
->inline()
->helperText(function (Forms\Get $get) {
if (request()->isSecure()) {
return new HtmlString('Your Panel is using a secure SSL connection,<br>so your Daemon must too.');
}
if (is_ip($get('fqdn'))) {
return 'An IP address cannot use SSL.';
}
return '';
})
->disableOptionWhen(fn (string $value): bool => $value === 'http' && request()->isSecure())
->options([
'http' => 'HTTP',
'https' => 'HTTPS (SSL)',
])
->colors([
'http' => 'warning',
'https' => 'success',
])
->icons([
'http' => 'tabler-lock-open-off',
'https' => 'tabler-lock',
])
->default(fn () => request()->isSecure() ? 'https' : 'http'), ]),
Tabs\Tab::make('Advanced Settings') Tabs\Tab::make('Advanced Settings')
->icon('tabler-server-cog') ->icon('tabler-server-cog')
->schema([ ->schema([