diff --git a/app/Console/Commands/Schedule/ProcessRunnableCommand.php b/app/Console/Commands/Schedule/ProcessRunnableCommand.php
index 0ebda2cdb..d1d71ae02 100644
--- a/app/Console/Commands/Schedule/ProcessRunnableCommand.php
+++ b/app/Console/Commands/Schedule/ProcessRunnableCommand.php
@@ -24,7 +24,7 @@ class ProcessRunnableCommand extends Command
->whereRelation('server', fn (Builder $builder) => $builder->whereNull('status'))
->where('is_active', true)
->where('is_processing', false)
- ->whereDate('next_run_at', '<=', Carbon::now()->toDateTimeString())
+ ->where('next_run_at', '<=', Carbon::now()->toDateTimeString())
->get();
if ($schedules->count() < 1) {
diff --git a/app/Enums/ContainerStatus.php b/app/Enums/ContainerStatus.php
index b3b57d2b0..d78004652 100644
--- a/app/Enums/ContainerStatus.php
+++ b/app/Enums/ContainerStatus.php
@@ -6,12 +6,14 @@ enum ContainerStatus: string
{
// Docker Based
case Created = 'created';
+ case Starting = 'starting';
case Running = 'running';
case Restarting = 'restarting';
case Exited = 'exited';
case Paused = 'paused';
case Dead = 'dead';
case Removing = 'removing';
+ case Stopping = 'stopping';
case Offline = 'offline';
// HTTP Based
@@ -20,15 +22,17 @@ enum ContainerStatus: string
public function icon(): string
{
return match ($this) {
+
self::Created => 'tabler-heart-plus',
+ self::Starting => 'tabler-heart-up',
self::Running => 'tabler-heartbeat',
self::Restarting => 'tabler-heart-bolt',
self::Exited => 'tabler-heart-exclamation',
self::Paused => 'tabler-heart-pause',
- self::Dead => 'tabler-heart-x',
+ self::Dead, self::Offline => 'tabler-heart-x',
self::Removing => 'tabler-heart-down',
- self::Missing => 'tabler-heart-question',
- self::Offline => 'tabler-heart-bolt',
+ self::Missing => 'tabler-heart-search',
+ self::Stopping => 'tabler-heart-minus',
};
}
@@ -36,6 +40,7 @@ enum ContainerStatus: string
{
return match ($this) {
self::Created => 'primary',
+ self::Starting => 'warning',
self::Running => 'success',
self::Restarting => 'info',
self::Exited => 'danger',
@@ -43,6 +48,7 @@ enum ContainerStatus: string
self::Dead => 'danger',
self::Removing => 'warning',
self::Missing => 'danger',
+ self::Stopping => 'warning',
self::Offline => 'gray',
};
}
diff --git a/app/Filament/Resources/ApiKeyResource.php b/app/Filament/Resources/ApiKeyResource.php
index 0d7817cd9..2243e7ff1 100644
--- a/app/Filament/Resources/ApiKeyResource.php
+++ b/app/Filament/Resources/ApiKeyResource.php
@@ -11,6 +11,7 @@ class ApiKeyResource extends Resource
protected static ?string $model = ApiKey::class;
protected static ?string $label = 'API Key';
protected static ?string $navigationIcon = 'tabler-key';
+ protected static ?string $navigationGroup = 'Advanced';
public static function getNavigationBadge(): ?string
{
diff --git a/app/Filament/Resources/ApiKeyResource/Pages/CreateApiKey.php b/app/Filament/Resources/ApiKeyResource/Pages/CreateApiKey.php
index a864660dd..11e1fae03 100644
--- a/app/Filament/Resources/ApiKeyResource/Pages/CreateApiKey.php
+++ b/app/Filament/Resources/ApiKeyResource/Pages/CreateApiKey.php
@@ -4,9 +4,13 @@ namespace App\Filament\Resources\ApiKeyResource\Pages;
use App\Filament\Resources\ApiKeyResource;
use App\Models\ApiKey;
+use Filament\Forms\Components\Fieldset;
+use Filament\Forms\Components\Hidden;
+use Filament\Forms\Components\TagsInput;
+use Filament\Forms\Components\Textarea;
+use Filament\Forms\Components\ToggleButtons;
use Filament\Forms\Form;
use Filament\Resources\Pages\CreateRecord;
-use Filament\Forms;
class CreateApiKey extends CreateRecord
{
@@ -18,26 +22,26 @@ class CreateApiKey extends CreateRecord
{
return $form
->schema([
- Forms\Components\Hidden::make('identifier')->default(ApiKey::generateTokenIdentifier(ApiKey::TYPE_APPLICATION)),
- Forms\Components\Hidden::make('token')->default(str_random(ApiKey::KEY_LENGTH)),
+ Hidden::make('identifier')->default(ApiKey::generateTokenIdentifier(ApiKey::TYPE_APPLICATION)),
+ Hidden::make('token')->default(str_random(ApiKey::KEY_LENGTH)),
- Forms\Components\Hidden::make('user_id')
+ Hidden::make('user_id')
->default(auth()->user()->id)
->required(),
- Forms\Components\Hidden::make('key_type')
+ Hidden::make('key_type')
->inlineLabel()
->default(ApiKey::TYPE_APPLICATION)
->required(),
- Forms\Components\Fieldset::make('Permissions')
+ Fieldset::make('Permissions')
->columns([
'default' => 1,
'sm' => 1,
'md' => 2,
])
->schema(
- collect(ApiKey::RESOURCES)->map(fn ($resource) => Forms\Components\ToggleButtons::make("r_$resource")
+ collect(ApiKey::RESOURCES)->map(fn ($resource) => ToggleButtons::make("r_$resource")
->label(str($resource)->replace('_', ' ')->title())->inline()
->options([
0 => 'None',
@@ -67,13 +71,13 @@ class CreateApiKey extends CreateRecord
)->all(),
),
- Forms\Components\TagsInput::make('allowed_ips')
+ TagsInput::make('allowed_ips')
->placeholder('Example: 127.0.0.1 or 192.168.1.1')
->label('Whitelisted IPv4 Addresses')
->helperText('Press enter to add a new IP address or leave blank to allow any IP address')
->columnSpanFull(),
- Forms\Components\Textarea::make('memo')
+ Textarea::make('memo')
->required()
->label('Description')
->helperText('
diff --git a/app/Filament/Resources/ApiKeyResource/Pages/ListApiKeys.php b/app/Filament/Resources/ApiKeyResource/Pages/ListApiKeys.php
index e1f5ac436..045a1f217 100644
--- a/app/Filament/Resources/ApiKeyResource/Pages/ListApiKeys.php
+++ b/app/Filament/Resources/ApiKeyResource/Pages/ListApiKeys.php
@@ -6,8 +6,9 @@ use App\Filament\Resources\ApiKeyResource;
use App\Models\ApiKey;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
+use Filament\Tables\Actions\DeleteAction;
+use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
-use Filament\Tables;
class ListApiKeys extends ListRecords
{
@@ -19,37 +20,37 @@ class ListApiKeys extends ListRecords
->searchable(false)
->modifyQueryUsing(fn ($query) => $query->where('key_type', ApiKey::TYPE_APPLICATION))
->columns([
- Tables\Columns\TextColumn::make('key')
+ TextColumn::make('key')
->copyable()
->icon('tabler-clipboard-text')
->state(fn (ApiKey $key) => $key->identifier . $key->token),
- Tables\Columns\TextColumn::make('memo')
+ TextColumn::make('memo')
->label('Description')
->wrap()
->limit(50),
- Tables\Columns\TextColumn::make('identifier')
+ TextColumn::make('identifier')
->hidden()
->searchable(),
- Tables\Columns\TextColumn::make('last_used_at')
+ TextColumn::make('last_used_at')
->label('Last Used')
->placeholder('Not Used')
->dateTime()
->sortable(),
- Tables\Columns\TextColumn::make('created_at')
+ TextColumn::make('created_at')
->label('Created')
->dateTime()
->sortable(),
- Tables\Columns\TextColumn::make('user.username')
+ TextColumn::make('user.username')
->label('Created By')
->url(fn (ApiKey $apiKey): string => route('filament.admin.resources.users.edit', ['record' => $apiKey->user])),
])
->actions([
- Tables\Actions\DeleteAction::make(),
+ DeleteAction::make(),
]);
}
diff --git a/app/Filament/Resources/DatabaseHostResource.php b/app/Filament/Resources/DatabaseHostResource.php
index baf8e7937..64eb4e267 100644
--- a/app/Filament/Resources/DatabaseHostResource.php
+++ b/app/Filament/Resources/DatabaseHostResource.php
@@ -13,6 +13,7 @@ class DatabaseHostResource extends Resource
protected static ?string $label = 'Databases';
protected static ?string $navigationIcon = 'tabler-database';
+ protected static ?string $navigationGroup = 'Advanced';
public static function getNavigationBadge(): ?string
{
diff --git a/app/Filament/Resources/DatabaseHostResource/Pages/CreateDatabaseHost.php b/app/Filament/Resources/DatabaseHostResource/Pages/CreateDatabaseHost.php
index 38f8e9698..5f8386dfe 100644
--- a/app/Filament/Resources/DatabaseHostResource/Pages/CreateDatabaseHost.php
+++ b/app/Filament/Resources/DatabaseHostResource/Pages/CreateDatabaseHost.php
@@ -5,6 +5,8 @@ namespace App\Filament\Resources\DatabaseHostResource\Pages;
use App\Filament\Resources\DatabaseHostResource;
use App\Models\Objects\Endpoint;
use App\Services\Databases\Hosts\HostCreationService;
+use Filament\Forms\Components\Select;
+use Filament\Forms\Components\TextInput;
use Filament\Resources\Pages\CreateRecord;
use Filament\Forms;
use Filament\Forms\Components\Section;
@@ -35,14 +37,14 @@ class CreateDatabaseHost extends CreateRecord
'lg' => 4,
])
->schema([
- Forms\Components\TextInput::make('host')
+ TextInput::make('host')
->columnSpan(2)
->helperText('The IP address or Domain name that should be used when attempting to connect to this MySQL host from this Panel to create new databases.')
->required()
->live(onBlur: true)
->afterStateUpdated(fn ($state, Forms\Set $set) => $set('name', $state))
->maxLength(255),
- Forms\Components\TextInput::make('port')
+ TextInput::make('port')
->columnSpan(1)
->helperText('The port that MySQL is running on for this host.')
->required()
@@ -50,26 +52,26 @@ class CreateDatabaseHost extends CreateRecord
->default(3306)
->minValue(0)
->maxValue(Endpoint::PORT_CEIL),
- Forms\Components\TextInput::make('max_databases')
+ TextInput::make('max_databases')
->label('Max databases')
->helpertext('Blank is unlimited.')
->numeric(),
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->label('Display Name')
->helperText('A short identifier used to distinguish this location from others. Must be between 1 and 60 characters, for example, us.nyc.lvl3.')
->required()
->maxLength(60),
- Forms\Components\TextInput::make('username')
+ TextInput::make('username')
->helperText('The username of an account that has enough permissions to create new users and databases on the system.')
->required()
->maxLength(255),
- Forms\Components\TextInput::make('password')
+ TextInput::make('password')
->helperText('The password for the database user.')
->password()
->revealable()
->maxLength(255)
->required(),
- Forms\Components\Select::make('node_id')
+ Select::make('node_id')
->searchable()
->preload()
->helperText('This setting only defaults to this database host when adding a database to a server on the selected node.')
diff --git a/app/Filament/Resources/DatabaseHostResource/Pages/EditDatabaseHost.php b/app/Filament/Resources/DatabaseHostResource/Pages/EditDatabaseHost.php
index dd11e6ed1..c31b16c53 100644
--- a/app/Filament/Resources/DatabaseHostResource/Pages/EditDatabaseHost.php
+++ b/app/Filament/Resources/DatabaseHostResource/Pages/EditDatabaseHost.php
@@ -3,10 +3,13 @@
namespace App\Filament\Resources\DatabaseHostResource\Pages;
use App\Filament\Resources\DatabaseHostResource;
+use App\Filament\Resources\DatabaseHostResource\RelationManagers\DatabasesRelationManager;
use App\Models\DatabaseHost;
use App\Models\Objects\Endpoint;
use App\Services\Databases\Hosts\HostUpdateService;
use Filament\Actions;
+use Filament\Forms\Components\Select;
+use Filament\Forms\Components\TextInput;
use Filament\Resources\Pages\EditRecord;
use Filament\Forms;
use Filament\Forms\Components\Section;
@@ -31,40 +34,40 @@ class EditDatabaseHost extends EditRecord
'lg' => 4,
])
->schema([
- Forms\Components\TextInput::make('host')
+ TextInput::make('host')
->columnSpan(2)
->helperText('The IP address or Domain name that should be used when attempting to connect to this MySQL host from this Panel to create new databases.')
->required()
->live(onBlur: true)
->afterStateUpdated(fn ($state, Forms\Set $set) => $set('name', $state))
->maxLength(255),
- Forms\Components\TextInput::make('port')
+ TextInput::make('port')
->columnSpan(1)
->helperText('The port that MySQL is running on for this host.')
->required()
->numeric()
->minValue(0)
->maxValue(Endpoint::PORT_CEIL),
- Forms\Components\TextInput::make('max_databases')
+ TextInput::make('max_databases')
->label('Max databases')
->helpertext('Blank is unlimited.')
->numeric(),
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->label('Display Name')
->helperText('A short identifier used to distinguish this location from others. Must be between 1 and 60 characters, for example, us.nyc.lvl3.')
->required()
->maxLength(60),
- Forms\Components\TextInput::make('username')
+ TextInput::make('username')
->helperText('The username of an account that has enough permissions to create new users and databases on the system.')
->required()
->maxLength(255),
- Forms\Components\TextInput::make('password')
+ TextInput::make('password')
->helperText('The password for the database user.')
->password()
->revealable()
->maxLength(255)
->required(),
- Forms\Components\Select::make('node_id')
+ Select::make('node_id')
->searchable()
->preload()
->helperText('This setting only defaults to this database host when adding a database to a server on the selected node.')
@@ -92,7 +95,7 @@ class EditDatabaseHost extends EditRecord
public function getRelationManagers(): array
{
return [
- DatabaseHostResource\RelationManagers\DatabasesRelationManager::class,
+ DatabasesRelationManager::class,
];
}
diff --git a/app/Filament/Resources/DatabaseHostResource/Pages/ListDatabaseHosts.php b/app/Filament/Resources/DatabaseHostResource/Pages/ListDatabaseHosts.php
index 769c546f3..9307488f8 100644
--- a/app/Filament/Resources/DatabaseHostResource/Pages/ListDatabaseHosts.php
+++ b/app/Filament/Resources/DatabaseHostResource/Pages/ListDatabaseHosts.php
@@ -5,7 +5,10 @@ namespace App\Filament\Resources\DatabaseHostResource\Pages;
use App\Filament\Resources\DatabaseHostResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
-use Filament\Tables;
+use Filament\Tables\Actions\BulkActionGroup;
+use Filament\Tables\Actions\DeleteBulkAction;
+use Filament\Tables\Actions\EditAction;
+use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
class ListDatabaseHosts extends ListRecords
@@ -19,30 +22,27 @@ class ListDatabaseHosts extends ListRecords
return $table
->searchable(false)
->columns([
- Tables\Columns\TextColumn::make('name')
+ TextColumn::make('name')
->searchable(),
- Tables\Columns\TextColumn::make('host')
+ TextColumn::make('host')
->searchable(),
- Tables\Columns\TextColumn::make('port')
+ TextColumn::make('port')
->sortable(),
- Tables\Columns\TextColumn::make('username')
+ TextColumn::make('username')
->searchable(),
- Tables\Columns\TextColumn::make('max_databases')
+ TextColumn::make('max_databases')
->numeric()
->sortable(),
- Tables\Columns\TextColumn::make('node.name')
+ TextColumn::make('node.name')
->numeric()
->sortable(),
])
- ->filters([
- //
- ])
->actions([
- Tables\Actions\EditAction::make(),
+ EditAction::make(),
])
->bulkActions([
- Tables\Actions\BulkActionGroup::make([
- Tables\Actions\DeleteBulkAction::make(),
+ BulkActionGroup::make([
+ DeleteBulkAction::make(),
]),
]);
}
diff --git a/app/Filament/Resources/DatabaseHostResource/RelationManagers/DatabasesRelationManager.php b/app/Filament/Resources/DatabaseHostResource/RelationManagers/DatabasesRelationManager.php
index e61d19625..4dfcdd955 100644
--- a/app/Filament/Resources/DatabaseHostResource/RelationManagers/DatabasesRelationManager.php
+++ b/app/Filament/Resources/DatabaseHostResource/RelationManagers/DatabasesRelationManager.php
@@ -4,11 +4,14 @@ namespace App\Filament\Resources\DatabaseHostResource\RelationManagers;
use App\Models\Database;
use App\Services\Databases\DatabasePasswordService;
-use Filament\Forms;
use Filament\Forms\Components\Actions\Action;
+use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
+use Filament\Forms\Get;
use Filament\Resources\RelationManagers\RelationManager;
-use Filament\Tables;
+use Filament\Tables\Actions\DeleteAction;
+use Filament\Tables\Actions\ViewAction;
+use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
class DatabasesRelationManager extends RelationManager
@@ -19,9 +22,9 @@ class DatabasesRelationManager extends RelationManager
{
return $form
->schema([
- Forms\Components\TextInput::make('database')->columnSpanFull(),
- Forms\Components\TextInput::make('username'),
- Forms\Components\TextInput::make('password')
+ TextInput::make('database')->columnSpanFull(),
+ TextInput::make('username'),
+ TextInput::make('password')
->hintAction(
Action::make('rotate')
->icon('tabler-refresh')
@@ -29,12 +32,12 @@ class DatabasesRelationManager extends RelationManager
->action(fn (DatabasePasswordService $service, Database $database, $set, $get) => $this->rotatePassword($service, $database, $set, $get))
)
->formatStateUsing(fn (Database $database) => $database->password),
- Forms\Components\TextInput::make('remote')->label('Connections From'),
- Forms\Components\TextInput::make('max_connections'),
- Forms\Components\TextInput::make('JDBC')
+ TextInput::make('remote')->label('Connections From'),
+ TextInput::make('max_connections'),
+ TextInput::make('JDBC')
->label('JDBC Connection String')
->columnSpanFull()
- ->formatStateUsing(fn (Forms\Get $get, Database $database) => 'jdbc:mysql://' . $get('username') . ':' . urlencode($database->password) . '@' . $database->host->host . ':' . $database->host->port . '/' . $get('database')),
+ ->formatStateUsing(fn (Get $get, Database $database) => 'jdbc:mysql://' . $get('username') . ':' . urlencode($database->password) . '@' . $database->host->host . ':' . $database->host->port . '/' . $get('database')),
]);
}
public function table(Table $table): Table
@@ -42,18 +45,18 @@ class DatabasesRelationManager extends RelationManager
return $table
->recordTitleAttribute('servers')
->columns([
- Tables\Columns\TextColumn::make('database')->icon('tabler-database'),
- Tables\Columns\TextColumn::make('username')->icon('tabler-user'),
- Tables\Columns\TextColumn::make('remote'),
- Tables\Columns\TextColumn::make('server.name')
+ TextColumn::make('database')->icon('tabler-database'),
+ TextColumn::make('username')->icon('tabler-user'),
+ TextColumn::make('remote'),
+ TextColumn::make('server.name')
->icon('tabler-brand-docker')
->url(fn (Database $database) => route('filament.admin.resources.servers.edit', ['record' => $database->server_id])),
- Tables\Columns\TextColumn::make('max_connections'),
- Tables\Columns\TextColumn::make('created_at')->dateTime(),
+ TextColumn::make('max_connections'),
+ TextColumn::make('created_at')->dateTime(),
])
->actions([
- Tables\Actions\DeleteAction::make(),
- Tables\Actions\ViewAction::make()->color('primary'),
+ DeleteAction::make(),
+ ViewAction::make()->color('primary'),
]);
}
diff --git a/app/Filament/Resources/DatabaseResource.php b/app/Filament/Resources/DatabaseResource.php
index cda7fb234..716857fdc 100644
--- a/app/Filament/Resources/DatabaseResource.php
+++ b/app/Filament/Resources/DatabaseResource.php
@@ -13,6 +13,7 @@ class DatabaseResource extends Resource
protected static ?string $navigationIcon = 'tabler-database';
protected static bool $shouldRegisterNavigation = false;
+ protected static ?string $navigationGroup = 'Advanced';
public static function getNavigationBadge(): ?string
{
diff --git a/app/Filament/Resources/DatabaseResource/Pages/CreateDatabase.php b/app/Filament/Resources/DatabaseResource/Pages/CreateDatabase.php
index c56b5f586..0e85e0a6a 100644
--- a/app/Filament/Resources/DatabaseResource/Pages/CreateDatabase.php
+++ b/app/Filament/Resources/DatabaseResource/Pages/CreateDatabase.php
@@ -3,9 +3,10 @@
namespace App\Filament\Resources\DatabaseResource\Pages;
use App\Filament\Resources\DatabaseResource;
+use Filament\Forms\Components\Select;
+use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Resources\Pages\CreateRecord;
-use Filament\Forms;
class CreateDatabase extends CreateRecord
{
@@ -15,29 +16,29 @@ class CreateDatabase extends CreateRecord
{
return $form
->schema([
- Forms\Components\Select::make('server_id')
+ Select::make('server_id')
->relationship('server', 'name')
->searchable()
->preload()
->required(),
- Forms\Components\TextInput::make('database_host_id')
+ TextInput::make('database_host_id')
->required()
->numeric(),
- Forms\Components\TextInput::make('database')
+ TextInput::make('database')
->required()
->maxLength(255),
- Forms\Components\TextInput::make('remote')
+ TextInput::make('remote')
->required()
->maxLength(255)
->default('%'),
- Forms\Components\TextInput::make('username')
+ TextInput::make('username')
->required()
->maxLength(255),
- Forms\Components\TextInput::make('password')
+ TextInput::make('password')
->password()
->revealable()
->required(),
- Forms\Components\TextInput::make('max_connections')
+ TextInput::make('max_connections')
->numeric()
->minValue(0)
->default(0),
diff --git a/app/Filament/Resources/DatabaseResource/Pages/EditDatabase.php b/app/Filament/Resources/DatabaseResource/Pages/EditDatabase.php
index aa8754ce1..2e1540e98 100644
--- a/app/Filament/Resources/DatabaseResource/Pages/EditDatabase.php
+++ b/app/Filament/Resources/DatabaseResource/Pages/EditDatabase.php
@@ -4,9 +4,10 @@ namespace App\Filament\Resources\DatabaseResource\Pages;
use App\Filament\Resources\DatabaseResource;
use Filament\Actions;
+use Filament\Forms\Components\Select;
+use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Resources\Pages\EditRecord;
-use Filament\Forms;
class EditDatabase extends EditRecord
{
@@ -16,29 +17,29 @@ class EditDatabase extends EditRecord
{
return $form
->schema([
- Forms\Components\Select::make('server_id')
+ Select::make('server_id')
->relationship('server', 'name')
->searchable()
->preload()
->required(),
- Forms\Components\TextInput::make('database_host_id')
+ TextInput::make('database_host_id')
->required()
->numeric(),
- Forms\Components\TextInput::make('database')
+ TextInput::make('database')
->required()
->maxLength(255),
- Forms\Components\TextInput::make('remote')
+ TextInput::make('remote')
->required()
->maxLength(255)
->default('%'),
- Forms\Components\TextInput::make('username')
+ TextInput::make('username')
->required()
->maxLength(255),
- Forms\Components\TextInput::make('password')
+ TextInput::make('password')
->password()
->revealable()
->required(),
- Forms\Components\TextInput::make('max_connections')
+ TextInput::make('max_connections')
->numeric()
->minValue(0)
->default(0),
diff --git a/app/Filament/Resources/DatabaseResource/Pages/ListDatabases.php b/app/Filament/Resources/DatabaseResource/Pages/ListDatabases.php
index fa10aa015..45df4a597 100644
--- a/app/Filament/Resources/DatabaseResource/Pages/ListDatabases.php
+++ b/app/Filament/Resources/DatabaseResource/Pages/ListDatabases.php
@@ -4,9 +4,12 @@ namespace App\Filament\Resources\DatabaseResource\Pages;
use App\Filament\Resources\DatabaseResource;
use Filament\Actions;
+use Filament\Tables\Actions\EditAction;
use Filament\Resources\Pages\ListRecords;
+use Filament\Tables\Actions\BulkActionGroup;
+use Filament\Tables\Actions\DeleteBulkAction;
+use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
-use Filament\Tables;
class ListDatabases extends ListRecords
{
@@ -16,39 +19,36 @@ class ListDatabases extends ListRecords
{
return $table
->columns([
- Tables\Columns\TextColumn::make('server.name')
+ TextColumn::make('server.name')
->numeric()
->sortable(),
- Tables\Columns\TextColumn::make('database_host_id')
+ TextColumn::make('database_host_id')
->numeric()
->sortable(),
- Tables\Columns\TextColumn::make('database')
+ TextColumn::make('database')
->searchable(),
- Tables\Columns\TextColumn::make('username')
+ TextColumn::make('username')
->searchable(),
- Tables\Columns\TextColumn::make('remote')
+ TextColumn::make('remote')
->searchable(),
- Tables\Columns\TextColumn::make('max_connections')
+ TextColumn::make('max_connections')
->numeric()
->sortable(),
- Tables\Columns\TextColumn::make('created_at')
+ TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
- Tables\Columns\TextColumn::make('updated_at')
+ TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
- ->filters([
- //
- ])
->actions([
- Tables\Actions\EditAction::make(),
+ EditAction::make(),
])
->bulkActions([
- Tables\Actions\BulkActionGroup::make([
- Tables\Actions\DeleteBulkAction::make(),
+ BulkActionGroup::make([
+ DeleteBulkAction::make(),
]),
]);
}
diff --git a/app/Filament/Resources/EggResource/Pages/CreateEgg.php b/app/Filament/Resources/EggResource/Pages/CreateEgg.php
index c16ab26a1..5dd15695c 100644
--- a/app/Filament/Resources/EggResource/Pages/CreateEgg.php
+++ b/app/Filament/Resources/EggResource/Pages/CreateEgg.php
@@ -3,6 +3,18 @@
namespace App\Filament\Resources\EggResource\Pages;
use App\Filament\Resources\EggResource;
+use Filament\Forms\Components\Checkbox;
+use Filament\Forms\Components\Fieldset;
+use Filament\Forms\Components\Hidden;
+use Filament\Forms\Components\KeyValue;
+use Filament\Forms\Components\Repeater;
+use Filament\Forms\Components\Select;
+use Filament\Forms\Components\Tabs;
+use Filament\Forms\Components\Tabs\Tab;
+use Filament\Forms\Components\TagsInput;
+use Filament\Forms\Components\Textarea;
+use Filament\Forms\Components\TextInput;
+use Filament\Forms\Components\Toggle;
use Filament\Resources\Pages\CreateRecord;
use AbdelhamidErrahmouni\FilamentMonacoEditor\MonacoEditor;
use Filament\Forms;
@@ -19,26 +31,26 @@ class CreateEgg extends CreateRecord
{
return $form
->schema([
- Forms\Components\Tabs::make()->tabs([
- Forms\Components\Tabs\Tab::make('Configuration')
+ Tabs::make()->tabs([
+ Tab::make('Configuration')
->columns(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 4])
->schema([
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->required()
->maxLength(255)
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2])
->helperText('A simple, human-readable name to use as an identifier for this Egg.'),
- Forms\Components\TextInput::make('author')
+ TextInput::make('author')
->maxLength(255)
->required()
->email()
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2])
->helperText('The author of this version of the Egg.'),
- Forms\Components\Textarea::make('description')
+ Textarea::make('description')
->rows(3)
->columnSpanFull()
->helperText('A description of this Egg that will be displayed throughout the Panel as needed.'),
- Forms\Components\Textarea::make('startup')
+ Textarea::make('startup')
->rows(3)
->columnSpanFull()
->required()
@@ -46,26 +58,26 @@ class CreateEgg extends CreateRecord
'java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}',
]))
->helperText('The default startup command that should be used for new servers using this Egg.'),
- Forms\Components\TagsInput::make('features')
+ TagsInput::make('features')
->placeholder('Add Feature')
->helperText('')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2]),
- Forms\Components\Toggle::make('force_outgoing_ip')
+ Toggle::make('force_outgoing_ip')
->hintIcon('tabler-question-mark')
->hintIconTooltip("Forces all outgoing network traffic to have its Source IP NATed to the IP of the server's primary endpoint.
Required for certain games to work properly when the Node has multiple public IP addresses.
Enabling this option will disable internal networking for any servers using this egg, causing them to be unable to internally access other servers on the same node."),
- Forms\Components\Hidden::make('script_is_privileged')
+ Hidden::make('script_is_privileged')
->default(1),
- Forms\Components\TagsInput::make('tags')
+ TagsInput::make('tags')
->placeholder('Add Tags')
->helperText('')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2]),
- Forms\Components\TextInput::make('update_url')
+ TextInput::make('update_url')
->disabled()
->helperText('Not implemented.')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2]),
- Forms\Components\KeyValue::make('docker_images')
+ KeyValue::make('docker_images')
->live()
->columnSpanFull()
->required()
@@ -77,37 +89,37 @@ class CreateEgg extends CreateRecord
->helperText('The docker images available to servers using this egg.'),
]),
- Forms\Components\Tabs\Tab::make('Process Management')
+ Tab::make('Process Management')
->columns()
->schema([
- Forms\Components\Hidden::make('config_from')
+ Hidden::make('config_from')
->default(null)
->label('Copy Settings From')
// ->placeholder('None')
// ->relationship('configFrom', 'name', ignoreRecord: true)
->helperText('If you would like to default to settings from another Egg select it from the menu above.'),
- Forms\Components\TextInput::make('config_stop')
+ TextInput::make('config_stop')
->required()
->maxLength(255)
->label('Stop Command')
->helperText('The command that should be sent to server processes to stop them gracefully. If you need to send a SIGINT you should enter ^C here.'),
- Forms\Components\Textarea::make('config_startup')->rows(10)->json()
+ Textarea::make('config_startup')->rows(10)->json()
->label('Start Configuration')
->default('{}')
->helperText('List of values the daemon should be looking for when booting a server to determine completion.'),
- Forms\Components\Textarea::make('config_files')->rows(10)->json()
+ Textarea::make('config_files')->rows(10)->json()
->label('Configuration Files')
->default('{}')
->helperText('This should be a JSON representation of configuration files to modify and what parts should be changed.'),
- Forms\Components\Textarea::make('config_logs')->rows(10)->json()
+ Textarea::make('config_logs')->rows(10)->json()
->label('Log Configuration')
->default('{}')
->helperText('This should be a JSON representation of where log files are stored, and whether or not the daemon should be creating custom logs.'),
]),
- Forms\Components\Tabs\Tab::make('Egg Variables')
+ Tab::make('Egg Variables')
->columnSpanFull()
->schema([
- Forms\Components\Repeater::make('variables')
+ Repeater::make('variables')
->label('')
->addActionLabel('Add New Egg Variable')
->grid()
@@ -137,7 +149,7 @@ class CreateEgg extends CreateRecord
return $data;
})
->schema([
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->live()
->debounce(750)
->maxLength(255)
@@ -145,8 +157,8 @@ class CreateEgg extends CreateRecord
->afterStateUpdated(fn (Forms\Set $set, $state) => $set('env_variable', str($state)->trim()->snake()->upper()->toString())
)
->required(),
- Forms\Components\Textarea::make('description')->columnSpanFull(),
- Forms\Components\TextInput::make('env_variable')
+ Textarea::make('description')->columnSpanFull(),
+ TextInput::make('env_variable')
->label('Environment Variable')
->maxLength(255)
->prefix('{{')
@@ -154,29 +166,29 @@ class CreateEgg extends CreateRecord
->hintIcon('tabler-code')
->hintIconTooltip(fn ($state) => "{{{$state}}}")
->required(),
- Forms\Components\TextInput::make('default_value')->maxLength(255),
- Forms\Components\Fieldset::make('User Permissions')
+ TextInput::make('default_value')->maxLength(255),
+ Fieldset::make('User Permissions')
->schema([
- Forms\Components\Checkbox::make('user_viewable')->label('Viewable'),
- Forms\Components\Checkbox::make('user_editable')->label('Editable'),
+ Checkbox::make('user_viewable')->label('Viewable'),
+ Checkbox::make('user_editable')->label('Editable'),
]),
- Forms\Components\Textarea::make('rules')->columnSpanFull(),
+ Textarea::make('rules')->columnSpanFull(),
]),
]),
- Forms\Components\Tabs\Tab::make('Install Script')
+ Tab::make('Install Script')
->columns(3)
->schema([
- Forms\Components\Hidden::make('copy_script_from'),
+ Hidden::make('copy_script_from'),
//->placeholder('None')
//->relationship('scriptFrom', 'name', ignoreRecord: true),
- Forms\Components\TextInput::make('script_container')
+ TextInput::make('script_container')
->required()
->maxLength(255)
->default('alpine:3.4'),
- Forms\Components\Select::make('script_entry')
+ Select::make('script_entry')
->selectablePlaceholder(false)
->default('bash')
->options(['bash', 'ash', '/bin/bash'])
diff --git a/app/Filament/Resources/EggResource/Pages/EditEgg.php b/app/Filament/Resources/EggResource/Pages/EditEgg.php
index a5c41266f..f4c906c3b 100644
--- a/app/Filament/Resources/EggResource/Pages/EditEgg.php
+++ b/app/Filament/Resources/EggResource/Pages/EditEgg.php
@@ -3,11 +3,25 @@
namespace App\Filament\Resources\EggResource\Pages;
use App\Filament\Resources\EggResource;
+use App\Filament\Resources\EggResource\RelationManagers\ServersRelationManager;
use App\Models\Egg;
use App\Services\Eggs\Sharing\EggImporterService;
use Exception;
use Filament\Actions;
+use Filament\Forms\Components\Checkbox;
+use Filament\Forms\Components\Fieldset;
+use Filament\Forms\Components\FileUpload;
+use Filament\Forms\Components\Hidden;
+use Filament\Forms\Components\KeyValue;
+use Filament\Forms\Components\Placeholder;
+use Filament\Forms\Components\Repeater;
+use Filament\Forms\Components\Select;
use Filament\Forms\Components\Tabs;
+use Filament\Forms\Components\Tabs\Tab;
+use Filament\Forms\Components\TagsInput;
+use Filament\Forms\Components\Textarea;
+use Filament\Forms\Components\TextInput;
+use Filament\Forms\Components\Toggle;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
use AbdelhamidErrahmouni\FilamentMonacoEditor\MonacoEditor;
@@ -23,64 +37,64 @@ class EditEgg extends EditRecord
{
return $form
->schema([
- Forms\Components\Tabs::make()->tabs([
- Forms\Components\Tabs\Tab::make('Configuration')
+ Tabs::make()->tabs([
+ Tab::make('Configuration')
->columns(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 4])
->schema([
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->required()
->maxLength(255)
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 1])
->helperText('A simple, human-readable name to use as an identifier for this Egg.'),
- Forms\Components\TextInput::make('uuid')
+ TextInput::make('uuid')
->label('Egg UUID')
->disabled()
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 2])
->helperText('This is the globally unique identifier for this Egg which Wings uses as an identifier.'),
- Forms\Components\TextInput::make('id')
+ TextInput::make('id')
->label('Egg ID')
->disabled(),
- Forms\Components\Textarea::make('description')
+ Textarea::make('description')
->rows(3)
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2])
->helperText('A description of this Egg that will be displayed throughout the Panel as needed.'),
- Forms\Components\TextInput::make('author')
+ TextInput::make('author')
->required()
->maxLength(255)
->email()
->disabled()
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2])
->helperText('The author of this version of the Egg. Uploading a new Egg configuration from a different author will change this.'),
- Forms\Components\Textarea::make('startup')
+ Textarea::make('startup')
->rows(2)
->columnSpanFull()
->required()
->helperText('The default startup command that should be used for new servers using this Egg.'),
- Forms\Components\TagsInput::make('file_denylist')
+ TagsInput::make('file_denylist')
->hidden() // latest wings breaks it.
->placeholder('denied-file.txt')
->helperText('A list of files that the end user is not allowed to edit.')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2]),
- Forms\Components\TagsInput::make('features')
+ TagsInput::make('features')
->placeholder('Add Feature')
->helperText('')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2]),
- Forms\Components\Toggle::make('force_outgoing_ip')
+ Toggle::make('force_outgoing_ip')
->hintIcon('tabler-question-mark')
->hintIconTooltip("Forces all outgoing network traffic to have its Source IP NATed to the IP of the server's endpoint.
Required for certain games to work properly when the Node has multiple public IP addresses.
Enabling this option will disable internal networking for any servers using this egg, causing them to be unable to internally access other servers on the same node."),
- Forms\Components\Hidden::make('script_is_privileged')
+ Hidden::make('script_is_privileged')
->helperText('The docker images available to servers using this egg.'),
- Forms\Components\TagsInput::make('tags')
+ TagsInput::make('tags')
->placeholder('Add Tags')
->helperText('')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2]),
- Forms\Components\TextInput::make('update_url')
+ TextInput::make('update_url')
->disabled()
->helperText('Not implemented.')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2]),
- Forms\Components\KeyValue::make('docker_images')
+ KeyValue::make('docker_images')
->live()
->columnSpanFull()
->required()
@@ -90,32 +104,32 @@ class EditEgg extends EditRecord
->helperText('The docker images available to servers using this egg.'),
]),
- Forms\Components\Tabs\Tab::make('Process Management')
+ Tab::make('Process Management')
->columns()
->schema([
- Forms\Components\Select::make('config_from')
+ Select::make('config_from')
->label('Copy Settings From')
->placeholder('None')
->relationship('configFrom', 'name', ignoreRecord: true)
->helperText('If you would like to default to settings from another Egg select it from the menu above.'),
- Forms\Components\TextInput::make('config_stop')
+ TextInput::make('config_stop')
->maxLength(255)
->label('Stop Command')
->helperText('The command that should be sent to server processes to stop them gracefully. If you need to send a SIGINT you should enter ^C here.'),
- Forms\Components\Textarea::make('config_startup')->rows(10)->json()
+ Textarea::make('config_startup')->rows(10)->json()
->label('Start Configuration')
->helperText('List of values the daemon should be looking for when booting a server to determine completion.'),
- Forms\Components\Textarea::make('config_files')->rows(10)->json()
+ Textarea::make('config_files')->rows(10)->json()
->label('Configuration Files')
->helperText('This should be a JSON representation of configuration files to modify and what parts should be changed.'),
- Forms\Components\Textarea::make('config_logs')->rows(10)->json()
+ Textarea::make('config_logs')->rows(10)->json()
->label('Log Configuration')
->helperText('This should be a JSON representation of where log files are stored, and whether or not the daemon should be creating custom logs.'),
]),
- Forms\Components\Tabs\Tab::make('Egg Variables')
+ Tab::make('Egg Variables')
->columnSpanFull()
->schema([
- Forms\Components\Repeater::make('variables')
+ Repeater::make('variables')
->label('')
->grid()
->relationship('variables')
@@ -144,7 +158,7 @@ class EditEgg extends EditRecord
return $data;
})
->schema([
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->live()
->debounce(750)
->maxLength(255)
@@ -152,8 +166,8 @@ class EditEgg extends EditRecord
->afterStateUpdated(fn (Forms\Set $set, $state) => $set('env_variable', str($state)->trim()->snake()->upper()->toString())
)
->required(),
- Forms\Components\Textarea::make('description')->columnSpanFull(),
- Forms\Components\TextInput::make('env_variable')
+ Textarea::make('description')->columnSpanFull(),
+ TextInput::make('env_variable')
->label('Environment Variable')
->maxLength(255)
->prefix('{{')
@@ -161,29 +175,29 @@ class EditEgg extends EditRecord
->hintIcon('tabler-code')
->hintIconTooltip(fn ($state) => "{{{$state}}}")
->required(),
- Forms\Components\TextInput::make('default_value')->maxLength(255),
- Forms\Components\Fieldset::make('User Permissions')
+ TextInput::make('default_value')->maxLength(255),
+ Fieldset::make('User Permissions')
->schema([
- Forms\Components\Checkbox::make('user_viewable')->label('Viewable'),
- Forms\Components\Checkbox::make('user_editable')->label('Editable'),
+ Checkbox::make('user_viewable')->label('Viewable'),
+ Checkbox::make('user_editable')->label('Editable'),
]),
- Forms\Components\TextInput::make('rules')->columnSpanFull(),
+ TextInput::make('rules')->columnSpanFull(),
]),
]),
- Forms\Components\Tabs\Tab::make('Install Script')
+ Tab::make('Install Script')
->columns(3)
->schema([
- Forms\Components\Select::make('copy_script_from')
+ Select::make('copy_script_from')
->placeholder('None')
->relationship('scriptFrom', 'name', ignoreRecord: true),
- Forms\Components\TextInput::make('script_container')
+ TextInput::make('script_container')
->required()
->maxLength(255)
->default('alpine:3.4'),
- Forms\Components\TextInput::make('script_entry')
+ TextInput::make('script_entry')
->required()
->maxLength(255)
->default('ash'),
@@ -217,23 +231,23 @@ class EditEgg extends EditRecord
Actions\Action::make('importEgg')
->label('Import')
->form([
- Forms\Components\Placeholder::make('warning')
+ Placeholder::make('warning')
->label('This will overwrite the current egg to the one you upload.'),
Tabs::make('Tabs')
->tabs([
- Tabs\Tab::make('From File')
+ Tab::make('From File')
->icon('tabler-file-upload')
->schema([
- Forms\Components\FileUpload::make('egg')
+ FileUpload::make('egg')
->label('Egg')
->hint('eg. minecraft.json')
->acceptedFileTypes(['application/json'])
->storeFiles(false),
]),
- Tabs\Tab::make('From URL')
+ Tab::make('From URL')
->icon('tabler-world-upload')
->schema([
- Forms\Components\TextInput::make('url')
+ TextInput::make('url')
->label('URL')
->hint('Link to the egg file (eg. minecraft.json)')
->url(),
@@ -302,7 +316,7 @@ class EditEgg extends EditRecord
public function getRelationManagers(): array
{
return [
- EggResource\RelationManagers\ServersRelationManager::class,
+ ServersRelationManager::class,
];
}
}
diff --git a/app/Filament/Resources/EggResource/Pages/ListEggs.php b/app/Filament/Resources/EggResource/Pages/ListEggs.php
index 2547ce2cd..947d2231a 100644
--- a/app/Filament/Resources/EggResource/Pages/ListEggs.php
+++ b/app/Filament/Resources/EggResource/Pages/ListEggs.php
@@ -8,10 +8,16 @@ use App\Services\Eggs\Sharing\EggExporterService;
use App\Services\Eggs\Sharing\EggImporterService;
use Exception;
use Filament\Actions;
-use Filament\Forms;
+use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Tabs;
+use Filament\Forms\Components\Tabs\Tab;
+use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\ListRecords;
+use Filament\Tables\Actions\BulkActionGroup;
+use Filament\Tables\Actions\DeleteBulkAction;
+use Filament\Tables\Actions\EditAction;
+use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Filament\Tables;
@@ -27,22 +33,22 @@ class ListEggs extends ListRecords
->defaultPaginationPageOption(25)
->checkIfRecordIsSelectableUsing(fn (Egg $egg) => $egg->servers_count <= 0)
->columns([
- Tables\Columns\TextColumn::make('id')
+ TextColumn::make('id')
->label('Id')
->hidden(),
- Tables\Columns\TextColumn::make('name')
+ TextColumn::make('name')
->icon('tabler-egg')
->description(fn ($record): ?string => (strlen($record->description) > 120) ? substr($record->description, 0, 120).'...' : $record->description)
->wrap()
->searchable()
->sortable(),
- Tables\Columns\TextColumn::make('servers_count')
+ TextColumn::make('servers_count')
->counts('servers')
->icon('tabler-server')
->label('Servers'),
])
->actions([
- Tables\Actions\EditAction::make(),
+ EditAction::make(),
Tables\Actions\Action::make('export')
->icon('tabler-download')
->label('Export')
@@ -52,8 +58,8 @@ class ListEggs extends ListRecords
}, 'egg-' . $egg->getKebabName() . '.json')),
])
->bulkActions([
- Tables\Actions\BulkActionGroup::make([
- Tables\Actions\DeleteBulkAction::make(),
+ BulkActionGroup::make([
+ DeleteBulkAction::make(),
]),
]);
}
@@ -67,20 +73,20 @@ class ListEggs extends ListRecords
->form([
Tabs::make('Tabs')
->tabs([
- Tabs\Tab::make('From File')
+ Tab::make('From File')
->icon('tabler-file-upload')
->schema([
- Forms\Components\FileUpload::make('egg')
+ FileUpload::make('egg')
->label('Egg')
->hint('This should be the json file ( egg-minecraft.json )')
->acceptedFileTypes(['application/json'])
->storeFiles(false)
->multiple(),
]),
- Tabs\Tab::make('From URL')
+ Tab::make('From URL')
->icon('tabler-world-upload')
->schema([
- Forms\Components\TextInput::make('url')
+ TextInput::make('url')
->label('URL')
->hint('This URL should point to a single json file')
->url(),
diff --git a/app/Filament/Resources/EggResource/RelationManagers/ServersRelationManager.php b/app/Filament/Resources/EggResource/RelationManagers/ServersRelationManager.php
index 5f94523a0..1e2f62d7b 100644
--- a/app/Filament/Resources/EggResource/RelationManagers/ServersRelationManager.php
+++ b/app/Filament/Resources/EggResource/RelationManagers/ServersRelationManager.php
@@ -4,7 +4,8 @@ namespace App\Filament\Resources\EggResource\RelationManagers;
use App\Models\Server;
use Filament\Resources\RelationManagers\RelationManager;
-use Filament\Tables;
+use Filament\Tables\Columns\SelectColumn;
+use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
class ServersRelationManager extends RelationManager
@@ -18,19 +19,19 @@ class ServersRelationManager extends RelationManager
->emptyStateDescription('No Servers')->emptyStateHeading('No servers are assigned this egg.')
->searchable(false)
->columns([
- Tables\Columns\TextColumn::make('user.username')
+ TextColumn::make('user.username')
->label('Owner')
->icon('tabler-user')
->url(fn (Server $server): string => route('filament.admin.resources.users.edit', ['record' => $server->user]))
->sortable(),
- Tables\Columns\TextColumn::make('name')
+ TextColumn::make('name')
->icon('tabler-brand-docker')
->url(fn (Server $server): string => route('filament.admin.resources.servers.edit', ['record' => $server]))
->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])),
- Tables\Columns\TextColumn::make('image')
+ TextColumn::make('image')
->label('Docker Image'),
]);
}
diff --git a/app/Filament/Resources/MountResource.php b/app/Filament/Resources/MountResource.php
index 7763ed0c7..a3b8c9ce9 100644
--- a/app/Filament/Resources/MountResource.php
+++ b/app/Filament/Resources/MountResource.php
@@ -11,6 +11,7 @@ class MountResource extends Resource
protected static ?string $model = Mount::class;
protected static ?string $navigationIcon = 'tabler-layers-linked';
+ protected static ?string $navigationGroup = 'Advanced';
public static function getNavigationBadge(): ?string
{
diff --git a/app/Filament/Resources/MountResource/Pages/CreateMount.php b/app/Filament/Resources/MountResource/Pages/CreateMount.php
index 0aec8981f..c736bf758 100644
--- a/app/Filament/Resources/MountResource/Pages/CreateMount.php
+++ b/app/Filament/Resources/MountResource/Pages/CreateMount.php
@@ -4,11 +4,14 @@ namespace App\Filament\Resources\MountResource\Pages;
use App\Filament\Resources\MountResource;
use Filament\Forms\Components\Group;
+use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
+use Filament\Forms\Components\Textarea;
+use Filament\Forms\Components\TextInput;
+use Filament\Forms\Components\ToggleButtons;
use Filament\Forms\Form;
use Filament\Resources\Pages\CreateRecord;
-use Filament\Forms;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
@@ -23,11 +26,11 @@ class CreateMount extends CreateRecord
return $form
->schema([
Section::make()->schema([
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->required()
->helperText('Unique name used to separate this mount from another.')
->maxLength(64),
- Forms\Components\ToggleButtons::make('read_only')
+ ToggleButtons::make('read_only')
->label('Read only?')
->helperText('Is the mount read only inside the container?')
->options([
@@ -45,15 +48,15 @@ class CreateMount extends CreateRecord
->inline()
->default(false)
->required(),
- Forms\Components\TextInput::make('source')
+ TextInput::make('source')
->required()
->helperText('File path on the host system to mount to a container.')
->maxLength(255),
- Forms\Components\TextInput::make('target')
+ TextInput::make('target')
->required()
->helperText('Where the mount will be accessible inside a container.')
->maxLength(255),
- Forms\Components\ToggleButtons::make('user_mountable')
+ ToggleButtons::make('user_mountable')
->hidden()
->label('User mountable?')
->options([
@@ -71,10 +74,10 @@ class CreateMount extends CreateRecord
->default(false)
->inline()
->required(),
- Forms\Components\Textarea::make('description')
+ Textarea::make('description')
->helperText('A longer description for this mount.')
->columnSpanFull(),
- Forms\Components\Hidden::make('user_mountable')->default(1),
+ Hidden::make('user_mountable')->default(1),
])->columnSpan(1)->columns([
'default' => 1,
'lg' => 2,
diff --git a/app/Filament/Resources/MountResource/Pages/EditMount.php b/app/Filament/Resources/MountResource/Pages/EditMount.php
index 6e838ed32..d004f15eb 100644
--- a/app/Filament/Resources/MountResource/Pages/EditMount.php
+++ b/app/Filament/Resources/MountResource/Pages/EditMount.php
@@ -4,8 +4,10 @@ namespace App\Filament\Resources\MountResource\Pages;
use App\Filament\Resources\MountResource;
use Filament\Actions;
+use Filament\Forms\Components\Textarea;
+use Filament\Forms\Components\TextInput;
+use Filament\Forms\Components\ToggleButtons;
use Filament\Resources\Pages\EditRecord;
-use Filament\Forms;
use Filament\Forms\Components\Group;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
@@ -20,11 +22,11 @@ class EditMount extends EditRecord
return $form
->schema([
Section::make()->schema([
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->required()
->helperText('Unique name used to separate this mount from another.')
->maxLength(64),
- Forms\Components\ToggleButtons::make('read_only')
+ ToggleButtons::make('read_only')
->label('Read only?')
->helperText('Is the mount read only inside the container?')
->options([
@@ -42,15 +44,15 @@ class EditMount extends EditRecord
->inline()
->default(false)
->required(),
- Forms\Components\TextInput::make('source')
+ TextInput::make('source')
->required()
->helperText('File path on the host system to mount to a container.')
->maxLength(255),
- Forms\Components\TextInput::make('target')
+ TextInput::make('target')
->required()
->helperText('Where the mount will be accessible inside a container.')
->maxLength(255),
- Forms\Components\ToggleButtons::make('user_mountable')
+ ToggleButtons::make('user_mountable')
->hidden()
->label('User mountable?')
->options([
@@ -68,7 +70,7 @@ class EditMount extends EditRecord
->default(false)
->inline()
->required(),
- Forms\Components\Textarea::make('description')
+ Textarea::make('description')
->helperText('A longer description for this mount.')
->columnSpanFull(),
])->columnSpan(1)->columns([
diff --git a/app/Filament/Resources/MountResource/Pages/ListMounts.php b/app/Filament/Resources/MountResource/Pages/ListMounts.php
index 8e58f4595..ea3970df5 100644
--- a/app/Filament/Resources/MountResource/Pages/ListMounts.php
+++ b/app/Filament/Resources/MountResource/Pages/ListMounts.php
@@ -6,9 +6,13 @@ use App\Filament\Resources\MountResource;
use App\Models\Mount;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
+use Filament\Tables\Actions\BulkActionGroup;
use Filament\Tables\Actions\CreateAction;
+use Filament\Tables\Actions\DeleteBulkAction;
+use Filament\Tables\Actions\EditAction;
+use Filament\Tables\Columns\IconColumn;
+use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
-use Filament\Tables;
class ListMounts extends ListRecords
{
@@ -18,31 +22,28 @@ class ListMounts extends ListRecords
return $table
->searchable(false)
->columns([
- Tables\Columns\TextColumn::make('name')
+ TextColumn::make('name')
->searchable(),
- Tables\Columns\TextColumn::make('source')
+ TextColumn::make('source')
->searchable(),
- Tables\Columns\TextColumn::make('target')
+ TextColumn::make('target')
->searchable(),
- Tables\Columns\IconColumn::make('read_only')
+ IconColumn::make('read_only')
->icon(fn (bool $state) => $state ? 'tabler-circle-check-filled' : 'tabler-circle-x-filled')
->color(fn (bool $state) => $state ? 'success' : 'danger')
->sortable(),
- Tables\Columns\IconColumn::make('user_mountable')
+ IconColumn::make('user_mountable')
->hidden()
->icon(fn (bool $state) => $state ? 'tabler-circle-check-filled' : 'tabler-circle-x-filled')
->color(fn (bool $state) => $state ? 'success' : 'danger')
->sortable(),
])
- ->filters([
- //
- ])
->actions([
- Tables\Actions\EditAction::make(),
+ EditAction::make(),
])
->bulkActions([
- Tables\Actions\BulkActionGroup::make([
- Tables\Actions\DeleteBulkAction::make(),
+ BulkActionGroup::make([
+ DeleteBulkAction::make(),
]),
])
->emptyStateIcon('tabler-layers-linked')
diff --git a/app/Filament/Resources/NodeResource.php b/app/Filament/Resources/NodeResource.php
index 14b3d1bce..d9e3a3ff3 100644
--- a/app/Filament/Resources/NodeResource.php
+++ b/app/Filament/Resources/NodeResource.php
@@ -3,7 +3,8 @@
namespace App\Filament\Resources;
use App\Filament\Resources\NodeResource\Pages;
-use App\Filament\Resources\NodeResource\RelationManagers;
+use App\Filament\Resources\NodeResource\RelationManagers\AllocationsRelationManager;
+use App\Filament\Resources\NodeResource\RelationManagers\NodesRelationManager;
use App\Models\Node;
use Filament\Resources\Resource;
@@ -23,7 +24,7 @@ class NodeResource extends Resource
public static function getRelations(): array
{
return [
- RelationManagers\NodesRelationManager::class,
+ NodesRelationManager::class,
];
}
diff --git a/app/Filament/Resources/NodeResource/Pages/CreateNode.php b/app/Filament/Resources/NodeResource/Pages/CreateNode.php
index 34611416e..0e5075e75 100644
--- a/app/Filament/Resources/NodeResource/Pages/CreateNode.php
+++ b/app/Filament/Resources/NodeResource/Pages/CreateNode.php
@@ -3,9 +3,16 @@
namespace App\Filament\Resources\NodeResource\Pages;
use App\Filament\Resources\NodeResource;
-use Filament\Forms;
use Filament\Forms\Components\Actions\Action;
+use Filament\Forms;
+use Filament\Forms\Components\Grid;
+use Filament\Forms\Components\TagsInput;
+use Filament\Forms\Components\TextInput;
+use Filament\Forms\Components\ToggleButtons;
use Filament\Forms\Components\Wizard;
+use Filament\Forms\Components\Wizard\Step;
+use Filament\Forms\Get;
+use Filament\Forms\Set;
use Filament\Resources\Pages\CreateRecord;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
@@ -23,7 +30,7 @@ class CreateNode extends CreateRecord
return $form
->schema([
Wizard::make([
- Wizard\Step::make('basic')
+ Step::make('basic')
->label('Basic Settings')
->icon('tabler-server')
->columnSpanFull()
@@ -34,7 +41,7 @@ class CreateNode extends CreateRecord
'lg' => 4,
])
->schema([
- Forms\Components\TextInput::make('fqdn')
+ TextInput::make('fqdn')
->columnSpan(2)
->required()
->autofocus()
@@ -67,7 +74,7 @@ class CreateNode extends CreateRecord
return '';
})
- ->afterStateUpdated(function (Forms\Set $set, ?string $state) {
+ ->afterStateUpdated(function (Set $set, ?string $state) {
$set('dns', null);
$set('ip', null);
@@ -95,17 +102,17 @@ class CreateNode extends CreateRecord
})
->maxLength(255),
- Forms\Components\TextInput::make('ip')
+ TextInput::make('ip')
->disabled()
->hidden(),
- Forms\Components\ToggleButtons::make('dns')
+ 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'))
+ ->hint(fn (Get $get) => $get('ip'))
->hintColor('success')
->options([
true => 'Valid',
@@ -122,7 +129,7 @@ class CreateNode extends CreateRecord
'lg' => 1,
]),
- Forms\Components\TextInput::make('daemon_listen')
+ TextInput::make('daemon_listen')
->columnSpan([
'default' => 1,
'sm' => 1,
@@ -137,7 +144,7 @@ class CreateNode extends CreateRecord
->required()
->integer(),
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->label('Display Name')
->columnSpan([
'default' => 1,
@@ -150,7 +157,7 @@ class CreateNode extends CreateRecord
->helperText('This name is for display only and can be changed later.')
->maxLength(100),
- Forms\Components\ToggleButtons::make('scheme')
+ ToggleButtons::make('scheme')
->label('Communicate over SSL')
->columnSpan([
'default' => 1,
@@ -159,7 +166,7 @@ class CreateNode extends CreateRecord
'lg' => 1,
])
->inline()
- ->helperText(function (Forms\Get $get) {
+ ->helperText(function (Get $get) {
if (request()->isSecure()) {
return new HtmlString('Your Panel is using a secure SSL connection,
so your Daemon must too.');
}
@@ -185,7 +192,7 @@ class CreateNode extends CreateRecord
])
->default(fn () => request()->isSecure() ? 'https' : 'http'),
]),
- Wizard\Step::make('advanced')
+ Step::make('advanced')
->label('Advanced Settings')
->icon('tabler-server-cog')
->columnSpanFull()
@@ -196,7 +203,7 @@ class CreateNode extends CreateRecord
'lg' => 4,
])
->schema([
- Forms\Components\ToggleButtons::make('maintenance_mode')
+ ToggleButtons::make('maintenance_mode')
->label('Maintenance Mode')->inline()
->columnSpan(1)
->default(false)
@@ -210,7 +217,7 @@ class CreateNode extends CreateRecord
true => 'danger',
false => 'success',
]),
- Forms\Components\ToggleButtons::make('public')
+ ToggleButtons::make('public')
->default(true)
->columnSpan(1)
->label('Automatic Allocation')->inline()
@@ -222,15 +229,14 @@ class CreateNode extends CreateRecord
true => 'success',
false => 'danger',
]),
- Forms\Components\TagsInput::make('tags')
+ TagsInput::make('tags')
->label('Tags')
->disabled()
->placeholder('Not Implemented')
->hintIcon('tabler-question-mark')
->hintIconTooltip('Not Implemented')
->columnSpan(2),
-
- Forms\Components\TextInput::make('upload_size')
+ TextInput::make('upload_size')
->label('Upload Limit')
->helperText('Enter the maximum size of files that can be uploaded through the web-based file manager.')
->columnSpan(1)
@@ -239,7 +245,7 @@ class CreateNode extends CreateRecord
->minValue(1)
->maxValue(1024)
->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB'),
- Forms\Components\TextInput::make('daemon_sftp')
+ TextInput::make('daemon_sftp')
->columnSpan(1)
->label('SFTP Port')
->minValue(1)
@@ -247,19 +253,19 @@ class CreateNode extends CreateRecord
->default(2022)
->required()
->integer(),
- Forms\Components\TextInput::make('daemon_sftp_alias')
+ TextInput::make('daemon_sftp_alias')
->columnSpan(2)
->label('SFTP Alias')
->helperText('Display alias for the SFTP address. Leave empty to use the Node FQDN.'),
- Forms\Components\Grid::make()
+ Grid::make()
->columns(6)
->columnSpanFull()
->schema([
- Forms\Components\ToggleButtons::make('unlimited_mem')
+ 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)
+ ->afterStateUpdated(fn (Set $set) => $set('memory', 0))
+ ->afterStateUpdated(fn (Set $set) => $set('memory_overallocate', 0))
+ ->formatStateUsing(fn (Get $get) => $get('memory') == 0)
->live()
->options([
true => 'Unlimited',
@@ -270,9 +276,9 @@ class CreateNode extends CreateRecord
false => 'warning',
])
->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')
->columnSpan(2)
@@ -280,10 +286,10 @@ class CreateNode extends CreateRecord
->minValue(0)
->default(0)
->required(),
- Forms\Components\TextInput::make('memory_overallocate')
+ TextInput::make('memory_overallocate')
->dehydratedWhenHidden()
->label('Overallocate')->inlineLabel()
- ->hidden(fn (Forms\Get $get) => $get('unlimited_mem'))
+ ->hidden(fn (Get $get) => $get('unlimited_mem'))
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
->columnSpan(2)
@@ -294,16 +300,16 @@ class CreateNode extends CreateRecord
->suffix('%')
->required(),
]),
- Forms\Components\Grid::make()
+ Grid::make()
->columns(6)
->columnSpanFull()
->schema([
- Forms\Components\ToggleButtons::make('unlimited_disk')
+ 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)
+ ->afterStateUpdated(fn (Set $set) => $set('disk', 0))
+ ->afterStateUpdated(fn (Set $set) => $set('disk_overallocate', 0))
+ ->formatStateUsing(fn (Get $get) => $get('disk') == 0)
->options([
true => 'Unlimited',
false => 'Limited',
@@ -313,9 +319,9 @@ class CreateNode extends CreateRecord
false => 'warning',
])
->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 Limit')->inlineLabel()
->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB')
->columnSpan(2)
@@ -323,9 +329,9 @@ class CreateNode extends CreateRecord
->minValue(0)
->default(0)
->required(),
- Forms\Components\TextInput::make('disk_overallocate')
+ TextInput::make('disk_overallocate')
->dehydratedWhenHidden()
- ->hidden(fn (Forms\Get $get) => $get('unlimited_disk'))
+ ->hidden(fn (Get $get) => $get('unlimited_disk'))
->label('Overallocate')->inlineLabel()
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
@@ -337,16 +343,16 @@ class CreateNode extends CreateRecord
->suffix('%')
->required(),
]),
- Forms\Components\Grid::make()
+ Grid::make()
->columns(6)
->columnSpanFull()
->schema([
- Forms\Components\ToggleButtons::make('unlimited_cpu')
+ ToggleButtons::make('unlimited_cpu')
->label('CPU')->inlineLabel()->inline()
->live()
- ->afterStateUpdated(fn (Forms\Set $set) => $set('cpu', 0))
- ->afterStateUpdated(fn (Forms\Set $set) => $set('cpu_overallocate', 0))
- ->formatStateUsing(fn (Forms\Get $get) => $get('cpu') == 0)
+ ->afterStateUpdated(fn (Set $set) => $set('cpu', 0))
+ ->afterStateUpdated(fn (Set $set) => $set('cpu_overallocate', 0))
+ ->formatStateUsing(fn (Get $get) => $get('cpu') == 0)
->options([
true => 'Unlimited',
false => 'Limited',
@@ -356,9 +362,9 @@ class CreateNode extends CreateRecord
false => 'warning',
])
->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('%')
->columnSpan(2)
@@ -366,9 +372,9 @@ class CreateNode extends CreateRecord
->default(0)
->minValue(0)
->required(),
- Forms\Components\TextInput::make('cpu_overallocate')
+ TextInput::make('cpu_overallocate')
->dehydratedWhenHidden()
- ->hidden(fn (Forms\Get $get) => $get('unlimited_cpu'))
+ ->hidden(fn (Get $get) => $get('unlimited_cpu'))
->label('Overallocate')->inlineLabel()
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
diff --git a/app/Filament/Resources/NodeResource/Pages/EditNode.php b/app/Filament/Resources/NodeResource/Pages/EditNode.php
index ccd2e97bb..94ea3a8a4 100644
--- a/app/Filament/Resources/NodeResource/Pages/EditNode.php
+++ b/app/Filament/Resources/NodeResource/Pages/EditNode.php
@@ -9,7 +9,16 @@ use App\Models\Node;
use App\Services\Nodes\NodeUpdateService;
use Filament\Actions;
use Filament\Forms;
+use Filament\Forms\Components\Grid;
+use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Tabs;
+use Filament\Forms\Components\Tabs\Tab;
+use Filament\Forms\Components\TagsInput;
+use Filament\Forms\Components\Textarea;
+use Filament\Forms\Components\TextInput;
+use Filament\Forms\Components\ToggleButtons;
+use Filament\Forms\Get;
+use Filament\Forms\Set;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\EditRecord;
use Illuminate\Support\HtmlString;
@@ -32,10 +41,10 @@ class EditNode extends EditRecord
->persistTabInQueryString()
->columnSpanFull()
->tabs([
- Tabs\Tab::make('Basic Settings')
+ Tab::make('Basic Settings')
->icon('tabler-server')
->schema([
- Forms\Components\TextInput::make('fqdn')
+ TextInput::make('fqdn')
->columnSpan(2)
->required()
->autofocus()
@@ -68,7 +77,7 @@ class EditNode extends EditRecord
return '';
})
- ->afterStateUpdated(function (Forms\Set $set, ?string $state) {
+ ->afterStateUpdated(function (Set $set, ?string $state) {
$set('dns', null);
$set('ip', null);
@@ -96,17 +105,17 @@ class EditNode extends EditRecord
})
->maxLength(255),
- Forms\Components\TextInput::make('ip')
+ TextInput::make('ip')
->disabled()
->hidden(),
- Forms\Components\ToggleButtons::make('dns')
+ 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'))
+ ->hint(fn (Get $get) => $get('ip'))
->hintColor('success')
->options([
true => 'Valid',
@@ -123,7 +132,7 @@ class EditNode extends EditRecord
'lg' => 1,
]),
- Forms\Components\TextInput::make('daemon_listen')
+ TextInput::make('daemon_listen')
->columnSpan([
'default' => 1,
'sm' => 1,
@@ -138,7 +147,7 @@ class EditNode extends EditRecord
->required()
->integer(),
- Forms\Components\TextInput::make('name')
+ TextInput::make('name')
->label('Display Name')
->columnSpan([
'default' => 1,
@@ -151,7 +160,7 @@ class EditNode extends EditRecord
->helperText('This name is for display only and can be changed later.')
->maxLength(100),
- Forms\Components\ToggleButtons::make('scheme')
+ ToggleButtons::make('scheme')
->label('Communicate over SSL')
->columnSpan([
'default' => 1,
@@ -160,7 +169,7 @@ class EditNode extends EditRecord
'lg' => 1,
])
->inline()
- ->helperText(function (Forms\Get $get) {
+ ->helperText(function (Get $get) {
if (request()->isSecure()) {
return new HtmlString('Your Panel is using a secure SSL connection,
so your Daemon must too.');
}
@@ -185,27 +194,27 @@ class EditNode extends EditRecord
'https' => 'tabler-lock',
])
->default(fn () => request()->isSecure() ? 'https' : 'http'), ]),
- Tabs\Tab::make('Advanced Settings')
+ Tab::make('Advanced Settings')
->columns(['default' => 1, 'sm' => 1, 'md' => 4, 'lg' => 6])
->icon('tabler-server-cog')
->schema([
- Forms\Components\TextInput::make('id')
+ TextInput::make('id')
->label('Node ID')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 1])
->disabled(),
- Forms\Components\TextInput::make('uuid')
+ TextInput::make('uuid')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2])
->label('Node UUID')
->hintAction(CopyAction::make())
->disabled(),
- Forms\Components\TagsInput::make('tags')
+ TagsInput::make('tags')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 2])
->label('Tags')
->disabled()
->placeholder('Not Implemented')
->hintIcon('tabler-question-mark')
->hintIconTooltip('Not Implemented'),
- Forms\Components\TextInput::make('upload_size')
+ TextInput::make('upload_size')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 1])
->label('Upload Limit')
->hintIcon('tabler-question-mark')
@@ -214,7 +223,7 @@ class EditNode extends EditRecord
->minValue(1)
->maxValue(1024)
->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB'),
- Forms\Components\TextInput::make('daemon_sftp')
+ TextInput::make('daemon_sftp')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 3])
->label('SFTP Port')
->minValue(1)
@@ -222,11 +231,11 @@ class EditNode extends EditRecord
->default(2022)
->required()
->integer(),
- Forms\Components\TextInput::make('daemon_sftp_alias')
+ TextInput::make('daemon_sftp_alias')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 3])
->label('SFTP Alias')
->helperText('Display alias for the SFTP address. Leave empty to use the Node FQDN.'),
- Forms\Components\ToggleButtons::make('public')
+ ToggleButtons::make('public')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 3])
->label('Automatic Allocation')->inline()
->options([
@@ -237,7 +246,7 @@ class EditNode extends EditRecord
true => 'success',
false => 'danger',
]),
- Forms\Components\ToggleButtons::make('maintenance_mode')
+ ToggleButtons::make('maintenance_mode')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 3])
->label('Maintenance Mode')->inline()
->hinticon('tabler-question-mark')
@@ -250,15 +259,15 @@ class EditNode extends EditRecord
false => 'success',
true => 'danger',
]),
- Forms\Components\Grid::make()
+ Grid::make()
->columns(['default' => 1, 'sm' => 1, 'md' => 3, 'lg' => 6])
->columnSpanFull()
->schema([
- Forms\Components\ToggleButtons::make('unlimited_mem')
+ 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)
+ ->afterStateUpdated(fn (Set $set) => $set('memory', 0))
+ ->afterStateUpdated(fn (Set $set) => $set('memory_overallocate', 0))
+ ->formatStateUsing(fn (Get $get) => $get('memory') == 0)
->live()
->options([
true => 'Unlimited',
@@ -269,20 +278,20 @@ class EditNode extends EditRecord
false => 'warning',
])
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 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()
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 2])
->numeric()
->minValue(0),
- Forms\Components\TextInput::make('memory_overallocate')
+ TextInput::make('memory_overallocate')
->dehydratedWhenHidden()
->label('Overallocate')->inlineLabel()
->required()
- ->hidden(fn (Forms\Get $get) => $get('unlimited_mem'))
+ ->hidden(fn (Get $get) => $get('unlimited_mem'))
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 2])
@@ -291,15 +300,15 @@ class EditNode extends EditRecord
->maxValue(100)
->suffix('%'),
]),
- Forms\Components\Grid::make()
+ Grid::make()
->columns(['default' => 1, 'sm' => 1, 'md' => 3, 'lg' => 6])
->schema([
- Forms\Components\ToggleButtons::make('unlimited_disk')
+ 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)
+ ->afterStateUpdated(fn (Set $set) => $set('disk', 0))
+ ->afterStateUpdated(fn (Set $set) => $set('disk_overallocate', 0))
+ ->formatStateUsing(fn (Get $get) => $get('disk') == 0)
->options([
true => 'Unlimited',
false => 'Limited',
@@ -309,18 +318,18 @@ class EditNode extends EditRecord
false => 'warning',
])
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 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 Limit')->inlineLabel()
->suffix(config('panel.use_binary_prefix') ? 'MiB' : 'MB')
->required()
->columnSpan(['default' => 1, 'sm' => 1, 'md' => 1, 'lg' => 2])
->numeric()
->minValue(0),
- Forms\Components\TextInput::make('disk_overallocate')
+ TextInput::make('disk_overallocate')
->dehydratedWhenHidden()
- ->hidden(fn (Forms\Get $get) => $get('unlimited_disk'))
+ ->hidden(fn (Get $get) => $get('unlimited_disk'))
->label('Overallocate')->inlineLabel()
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
@@ -331,16 +340,16 @@ class EditNode extends EditRecord
->maxValue(100)
->suffix('%'),
]),
- Forms\Components\Grid::make()
+ Grid::make()
->columns(6)
->columnSpanFull()
->schema([
- Forms\Components\ToggleButtons::make('unlimited_cpu')
+ ToggleButtons::make('unlimited_cpu')
->label('CPU')->inlineLabel()->inline()
->live()
- ->afterStateUpdated(fn (Forms\Set $set) => $set('cpu', 0))
- ->afterStateUpdated(fn (Forms\Set $set) => $set('cpu_overallocate', 0))
- ->formatStateUsing(fn (Forms\Get $get) => $get('cpu') == 0)
+ ->afterStateUpdated(fn (Set $set) => $set('cpu', 0))
+ ->afterStateUpdated(fn (Set $set) => $set('cpu_overallocate', 0))
+ ->formatStateUsing(fn (Get $get) => $get('cpu') == 0)
->options([
true => 'Unlimited',
false => 'Limited',
@@ -350,18 +359,18 @@ class EditNode extends EditRecord
false => 'warning',
])
->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()
->columnSpan(2)
->numeric()
->minValue(0),
- Forms\Components\TextInput::make('cpu_overallocate')
+ TextInput::make('cpu_overallocate')
->dehydratedWhenHidden()
- ->hidden(fn (Forms\Get $get) => $get('unlimited_cpu'))
+ ->hidden(fn (Get $get) => $get('unlimited_cpu'))
->label('Overallocate')->inlineLabel()
->hintIcon('tabler-question-mark')
->hintIconTooltip('The % allowable to go over the set limit.')
@@ -373,15 +382,15 @@ class EditNode extends EditRecord
->suffix('%'),
]),
]),
- Tabs\Tab::make('Configuration File')
+ Tab::make('Configuration File')
->icon('tabler-code')
->schema([
- Forms\Components\Placeholder::make('instructions')
+ Placeholder::make('instructions')
->columnSpanFull()
->content(new HtmlString('
Save this file to your daemon\'s root directory, named config.yml
')),
- Forms\Components\Textarea::make('config')
+ Textarea::make('config')
->label('/etc/pelican/config.yml')
->disabled()
->rows(19)
diff --git a/app/Filament/Resources/NodeResource/Pages/ListNodes.php b/app/Filament/Resources/NodeResource/Pages/ListNodes.php
index 81dd52fb0..6ecb6b690 100644
--- a/app/Filament/Resources/NodeResource/Pages/ListNodes.php
+++ b/app/Filament/Resources/NodeResource/Pages/ListNodes.php
@@ -6,9 +6,13 @@ use App\Filament\Resources\NodeResource;
use App\Models\Node;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
+use Filament\Tables\Actions\BulkActionGroup;
use Filament\Tables\Actions\CreateAction;
+use Filament\Tables\Actions\DeleteBulkAction;
+use Filament\Tables\Actions\EditAction;
+use Filament\Tables\Columns\IconColumn;
+use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
-use Filament\Tables;
class ListNodes extends ListRecords
{
@@ -20,70 +24,67 @@ class ListNodes extends ListRecords
->searchable(false)
->checkIfRecordIsSelectableUsing(fn (Node $node) => $node->servers_count <= 0)
->columns([
- Tables\Columns\TextColumn::make('uuid')
+ TextColumn::make('uuid')
->label('UUID')
->searchable()
->hidden(),
- Tables\Columns\IconColumn::make('health')
+ IconColumn::make('health')
->alignCenter()
->state(fn (Node $node) => $node)
->view('livewire.columns.version-column'),
- Tables\Columns\TextColumn::make('name')
+ TextColumn::make('name')
->icon('tabler-server-2')
->sortable()
->searchable(),
- Tables\Columns\TextColumn::make('fqdn')
+ TextColumn::make('fqdn')
->visibleFrom('md')
->label('Address')
->icon('tabler-network')
->sortable()
->searchable(),
- Tables\Columns\TextColumn::make('memory')
+ TextColumn::make('memory')
->visibleFrom('sm')
->icon('tabler-device-desktop-analytics')
->numeric()
->suffix(config('panel.use_binary_prefix') ? ' GiB' : ' GB')
->formatStateUsing(fn ($state) => number_format($state / (config('panel.use_binary_prefix') ? 1024 : 1000), 2))
->sortable(),
- Tables\Columns\TextColumn::make('disk')
+ TextColumn::make('disk')
->visibleFrom('sm')
->icon('tabler-file')
->numeric()
->suffix(config('panel.use_binary_prefix') ? ' GiB' : ' GB')
->formatStateUsing(fn ($state) => number_format($state / (config('panel.use_binary_prefix') ? 1024 : 1000), 2))
->sortable(),
- Tables\Columns\TextColumn::make('cpu')
+ TextColumn::make('cpu')
->visibleFrom('sm')
->icon('tabler-file')
->numeric()
->suffix(' %')
->sortable(),
- Tables\Columns\IconColumn::make('scheme')
+ IconColumn::make('scheme')
->visibleFrom('xl')
->label('SSL')
->trueIcon('tabler-lock')
->falseIcon('tabler-lock-open-off')
->state(fn (Node $node) => $node->scheme === 'https'),
- Tables\Columns\IconColumn::make('public')
+ IconColumn::make('public')
->visibleFrom('lg')
->trueIcon('tabler-eye-check')
->falseIcon('tabler-eye-cancel'),
- Tables\Columns\TextColumn::make('servers_count')
+ TextColumn::make('servers_count')
->visibleFrom('sm')
->counts('servers')
->label('Servers')
->sortable()
->icon('tabler-brand-docker'),
])
- ->filters([
- //
- ])
->actions([
- Tables\Actions\EditAction::make(),
+ EditAction::make(),
])
->bulkActions([
- Tables\Actions\BulkActionGroup::make([
- Tables\Actions\DeleteBulkAction::make(),
+ BulkActionGroup::make([
+ DeleteBulkAction::make(),
]),
])
->emptyStateIcon('tabler-server-2')
diff --git a/app/Filament/Resources/NodeResource/RelationManagers/NodesRelationManager.php b/app/Filament/Resources/NodeResource/RelationManagers/NodesRelationManager.php
index 8fe609428..59f023d7a 100644
--- a/app/Filament/Resources/NodeResource/RelationManagers/NodesRelationManager.php
+++ b/app/Filament/Resources/NodeResource/RelationManagers/NodesRelationManager.php
@@ -3,7 +3,8 @@
namespace App\Filament\Resources\NodeResource\RelationManagers;
use App\Models\Server;
-use Filament\Tables;
+use Filament\Tables\Columns\SelectColumn;
+use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Resources\RelationManagers\RelationManager;
@@ -18,29 +19,29 @@ class NodesRelationManager extends RelationManager
return $table
->searchable(false)
->columns([
- Tables\Columns\TextColumn::make('user.username')
+ TextColumn::make('user.username')
->label('Owner')
->icon('tabler-user')
->url(fn (Server $server): string => route('filament.admin.resources.users.edit', ['record' => $server->user]))
->searchable(),
- Tables\Columns\TextColumn::make('name')
+ TextColumn::make('name')
->icon('tabler-brand-docker')
->url(fn (Server $server): string => route('filament.admin.resources.servers.edit', ['record' => $server]))
->searchable()
->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->user]))
->sortable(),
- Tables\Columns\TextColumn::make('memory')->icon('tabler-device-desktop-analytics'),
- Tables\Columns\TextColumn::make('cpu')->icon('tabler-cpu'),
- Tables\Columns\TextColumn::make('databases_count')
+ TextColumn::make('memory')->icon('tabler-device-desktop-analytics'),
+ TextColumn::make('cpu')->icon('tabler-cpu'),
+ 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')
diff --git a/app/Filament/Resources/ServerResource/Pages/CreateServer.php b/app/Filament/Resources/ServerResource/Pages/CreateServer.php
index 6993a6bdd..b55e06aff 100644
--- a/app/Filament/Resources/ServerResource/Pages/CreateServer.php
+++ b/app/Filament/Resources/ServerResource/Pages/CreateServer.php
@@ -6,8 +6,10 @@ use App\Filament\Resources\ServerResource;
use App\Models\Egg;
use App\Models\Node;
use App\Models\Objects\Endpoint;
+use App\Models\User;
use App\Services\Servers\RandomWordService;
use App\Services\Servers\ServerCreationService;
+use App\Services\Users\UserCreationService;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Form;
use Filament\Resources\Pages\CreateRecord;
@@ -68,6 +70,7 @@ class CreateServer extends CreateRecord
->maxLength(255),
Forms\Components\Select::make('owner_id')
+ ->preload()
->prefixIcon('tabler-user')
->default(auth()->user()->id)
->label('Owner')
@@ -78,8 +81,44 @@ class CreateServer extends CreateRecord
'lg' => 3,
])
->relationship('user', 'username')
- ->searchable()
- ->preload()
+ ->searchable(['user', 'username', 'email'])
+ ->getOptionLabelFromRecordUsing(fn (User $user) => "$user->email | $user->username " . ($user->root_admin ? '(admin)' : ''))
+ ->createOptionForm([
+ Forms\Components\TextInput::make('username')
+ ->alphaNum()
+ ->required()
+ ->maxLength(255),
+
+ Forms\Components\TextInput::make('email')
+ ->email()
+ ->required()
+ ->unique()
+ ->maxLength(255),
+
+ Forms\Components\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(),
+
+ Forms\Components\ToggleButtons::make('root_admin')
+ ->label('Administrator (Root)')
+ ->options([
+ false => 'No',
+ true => 'Admin',
+ ])
+ ->colors([
+ false => 'primary',
+ true => 'danger',
+ ])
+ ->inline()
+ ->required()
+ ->default(false)
+ ->hidden(),
+ ])
+ ->createOptionUsing(function ($data) {
+ resolve(UserCreationService::class)->handle($data);
+ $this->refreshForm();
+ })
->required(),
Forms\Components\Select::make('node_id')
@@ -617,6 +656,11 @@ class CreateServer extends CreateRecord
]);
}
+ public function refreshForm(): void
+ {
+ $this->fillForm();
+ }
+
protected function getFormActions(): array
{
return [];
diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php
index 4c164cfff..f22b42a81 100644
--- a/app/Filament/Resources/UserResource.php
+++ b/app/Filament/Resources/UserResource.php
@@ -3,7 +3,7 @@
namespace App\Filament\Resources;
use App\Filament\Resources\UserResource\Pages;
-use App\Filament\Resources\UserResource\RelationManagers;
+use App\Filament\Resources\UserResource\RelationManagers\ServersRelationManager;
use App\Models\User;
use Filament\Resources\Resource;
@@ -23,7 +23,7 @@ class UserResource extends Resource
public static function getRelations(): array
{
return [
- RelationManagers\ServersRelationManager::class,
+ ServersRelationManager::class,
];
}
diff --git a/app/Http/Requests/Api/Application/Users/StoreUserRequest.php b/app/Http/Requests/Api/Application/Users/StoreUserRequest.php
index 1c5244ece..24e6e8940 100644
--- a/app/Http/Requests/Api/Application/Users/StoreUserRequest.php
+++ b/app/Http/Requests/Api/Application/Users/StoreUserRequest.php
@@ -25,6 +25,7 @@ class StoreUserRequest extends ApplicationApiRequest
'username',
'password',
'language',
+ 'timezone',
'root_admin',
])->toArray();
diff --git a/app/Models/User.php b/app/Models/User.php
index 6639a6a79..fc96ed0f6 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -5,6 +5,7 @@ namespace App\Models;
use App\Exceptions\DisplayException;
use App\Rules\Username;
use App\Facades\Activity;
+use DateTimeZone;
use Filament\Models\Contracts\FilamentUser;
use Filament\Models\Contracts\HasAvatar;
use Filament\Models\Contracts\HasName;
@@ -38,6 +39,7 @@ use App\Notifications\SendPasswordReset as ResetPasswordNotification;
* @property string $password
* @property string|null $remember_token
* @property string $language
+ * @property string $timezone
* @property bool $root_admin
* @property bool $use_totp
* @property string|null $totp_secret
@@ -70,6 +72,7 @@ use App\Notifications\SendPasswordReset as ResetPasswordNotification;
* @method static Builder|User whereGravatar($value)
* @method static Builder|User whereId($value)
* @method static Builder|User whereLanguage($value)
+ * @method static Builder|User whereTimezone($value)
* @method static Builder|User whereNameFirst($value)
* @method static Builder|User whereNameLast($value)
* @method static Builder|User wherePassword($value)
@@ -144,6 +147,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
'external_id' => null,
'root_admin' => false,
'language' => 'en',
+ 'timezone' => 'UTC',
'use_totp' => false,
'totp_secret' => null,
'name_first' => '',
@@ -164,6 +168,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
'password' => 'sometimes|nullable|string',
'root_admin' => 'boolean',
'language' => 'string',
+ 'timezone' => 'string',
'use_totp' => 'boolean',
'totp_secret' => 'nullable|string',
'oauth' => 'array|nullable',
@@ -210,6 +215,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
$rules = parent::getRules();
$rules['language'][] = new In(array_keys((new self())->getAvailableLanguages()));
+ $rules['timezone'][] = new In(array_values(DateTimeZone::listIdentifiers()));
$rules['username'][] = new Username();
return $rules;
diff --git a/readme.md b/readme.md
index 1d79e32d8..74b0c7998 100644
--- a/readme.md
+++ b/readme.md
@@ -3,9 +3,11 @@
# Pelican Panel
&color=rgba(255%2C%20255%2C%20255%2C%201))
-&color=rgba(255%2C%20255%2C%20255%2C%201))
+&color=rgba(255%2C%20255%2C%20255%2C%201))
+
+
Pelican Panel is an open-source, web-based application designed for easy management of game servers.
It offers a user-friendly interface for deploying, configuring, and managing servers, with features like real-time resource monitoring, Docker container isolation, and extensive customization options.
Ideal for both individual gamers and hosting companies, it simplifies server administration without requiring deep technical knowledge.
@@ -24,7 +26,7 @@ Fly High, Game On: Pelican's pledge for unrivaled game servers.
Pelican supports a wide variety of games by utilizing Docker containers to isolate each instance.
This gives you the power to run game servers without bloating machines with a host of additional dependencies.
-Some of our popular eggs include but are not limited to:
+Some of our popular eggs include:
| Category | Eggs | | | |
|----------------------------------------------------------------------|-----------------|---------------|--------------------|----------------|