Add traits for customizing tabs (#2101)

This commit is contained in:
Boy132
2026-01-18 22:32:18 +01:00
committed by GitHub
parent b79511568e
commit 9f744d39a2
10 changed files with 3033 additions and 2908 deletions

View File

@@ -0,0 +1,9 @@
<?php
namespace App\Enums;
enum TabPosition: string
{
case Before = 'before';
case After = 'after';
}

View File

@@ -10,6 +10,7 @@ use App\Notifications\MailTested;
use App\Traits\EnvironmentWriterTrait;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use App\Traits\Filament\CanCustomizeTabs;
use BackedEnum;
use Exception;
use Filament\Actions\Action;
@@ -53,6 +54,7 @@ class Settings extends Page implements HasSchemas
CanCustomizeHeaderActions::getHeaderActions insteadof InteractsWithHeaderActions;
}
use CanCustomizeHeaderWidgets;
use CanCustomizeTabs;
use EnvironmentWriterTrait;
use InteractsWithForms;
@@ -96,11 +98,7 @@ class Settings extends Page implements HasSchemas
return trans('admin/setting.title');
}
/**
* @return array<Component>
*
* @throws Exception
*/
/** @return array<Component> */
protected function getFormSchema(): array
{
return [
@@ -108,7 +106,18 @@ class Settings extends Page implements HasSchemas
->columns()
->persistTabInQueryString()
->disabled(fn () => !user()?->can('update settings'))
->tabs([
->tabs($this->getTabs()),
];
}
/**
* @return Tab[]
*
* @throws Exception
*/
protected function getDefaultTabs(): array
{
return [
Tab::make('general')
->label(trans('admin/setting.navigation.general'))
->icon('tabler-home')
@@ -135,7 +144,6 @@ class Settings extends Page implements HasSchemas
->label(trans('admin/setting.navigation.misc'))
->icon('tabler-tool')
->schema($this->miscSettings()),
]),
];
}

View File

@@ -9,7 +9,7 @@ use App\Filament\Components\Forms\Fields\MonacoEditor;
use App\Models\EggVariable;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use Exception;
use App\Traits\Filament\CanCustomizeTabs;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Forms\Components\Checkbox;
@@ -37,6 +37,7 @@ class CreateEgg extends CreateRecord
{
use CanCustomizeHeaderActions;
use CanCustomizeHeaderWidgets;
use CanCustomizeTabs;
protected static string $resource = EggResource::class;
@@ -57,14 +58,21 @@ class CreateEgg extends CreateRecord
return [];
}
/**
* @throws Exception
*/
public function form(Schema $schema): Schema
{
return $schema
->components([
Tabs::make()->tabs([
Tabs::make()
->tabs($this->getTabs())
->columnSpanFull()
->persistTabInQueryString(),
]);
}
/** @return Tab[] */
protected function getDefaultTabs(): array
{
return [
Tab::make('configuration')
->label(trans('admin/egg.tabs.configuration'))
->columns(['default' => 1, 'sm' => 1, 'md' => 2, 'lg' => 4])
@@ -131,7 +139,6 @@ class CreateEgg extends CreateRecord
->valuePlaceholder('ghcr.io/pelican-eggs/yolks:java_21')
->helperText(trans('admin/egg.docker_help')),
]),
Tab::make('process_management')
->label(trans('admin/egg.tabs.process_management'))
->columns()
@@ -275,9 +282,7 @@ class CreateEgg extends CreateRecord
->columnSpanFull()
->lazy(),
]),
])->columnSpanFull()->persistTabInQueryString(),
]);
];
}
protected function handleRecordCreation(array $data): Model

View File

@@ -12,6 +12,7 @@ use App\Models\Egg;
use App\Models\EggVariable;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use App\Traits\Filament\CanCustomizeTabs;
use Exception;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
@@ -47,17 +48,25 @@ class EditEgg extends EditRecord
{
use CanCustomizeHeaderActions;
use CanCustomizeHeaderWidgets;
use CanCustomizeTabs;
protected static string $resource = EggResource::class;
/**
* @throws Exception
*/
public function form(Schema $schema): Schema
{
return $schema
->components([
Tabs::make()->tabs([
Tabs::make()
->tabs($this->getTabs())
->columnSpanFull()
->persistTabInQueryString(),
]);
}
/** @return Tab[] */
protected function getDefaultTabs(): array
{
return [
Tab::make('configuration')
->label(trans('admin/egg.tabs.configuration'))
->columns(['default' => 2, 'sm' => 2, 'md' => 4, 'lg' => 6])
@@ -430,8 +439,7 @@ class EditEgg extends EditRecord
->language(EditorLanguages::shell)
->columnSpanFull(),
]),
])->columnSpanFull()->persistTabInQueryString(),
]);
];
}
/** @return array<Action|ActionGroup> */

View File

@@ -10,6 +10,7 @@ use App\Services\Nodes\NodeAutoDeployService;
use App\Services\Nodes\NodeUpdateService;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use App\Traits\Filament\CanCustomizeTabs;
use Exception;
use Filament\Actions\Action;
use Filament\Actions\DeleteAction;
@@ -42,12 +43,12 @@ use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\HtmlString;
use Phiki\Grammar\Grammar;
use Throwable;
class EditNode extends EditRecord
{
use CanCustomizeHeaderActions;
use CanCustomizeHeaderWidgets;
use CanCustomizeTabs;
protected static string $resource = NodeResource::class;
@@ -61,9 +62,6 @@ class EditNode extends EditRecord
$this->nodeUpdateService = $nodeUpdateService;
}
/**
* @throws Throwable
*/
public function form(Schema $schema): Schema
{
return $schema->components([
@@ -76,7 +74,14 @@ class EditNode extends EditRecord
])
->persistTabInQueryString()
->columnSpanFull()
->tabs([
->tabs($this->getTabs()),
]);
}
/** @return Tab[] */
protected function getDefaultTabs(): array
{
return [
Tab::make('overview')
->label(trans('admin/node.tabs.overview'))
->icon('tabler-chart-area-line-filled')
@@ -772,8 +777,7 @@ class EditNode extends EditRecord
->rows(35)
->visible(fn (Get $get) => ($get('pulled') ?? false) || ($get('uploaded') ?? false)),
]),
]),
]);
];
}
protected function mutateFormDataBeforeFill(array $data): array

View File

@@ -16,7 +16,6 @@ use App\Models\Egg;
use App\Models\Server;
use App\Models\User;
use App\Repositories\Daemon\DaemonServerRepository;
use App\Services\Backups\DeleteBackupService;
use App\Services\Eggs\EggChangerService;
use App\Services\Servers\RandomWordService;
use App\Services\Servers\ReinstallServerService;
@@ -26,6 +25,7 @@ use App\Services\Servers\ToggleInstallService;
use App\Services\Servers\TransferServerService;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use App\Traits\Filament\CanCustomizeTabs;
use Exception;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
@@ -70,6 +70,7 @@ class EditServer extends EditRecord
{
use CanCustomizeHeaderActions;
use CanCustomizeHeaderWidgets;
use CanCustomizeTabs;
protected static string $resource = ServerResource::class;
@@ -80,10 +81,6 @@ class EditServer extends EditRecord
$this->daemonServerRepository = $daemonServerRepository;
}
/**
* @throws RandomException
* @throws Exception
*/
public function form(Schema $schema): Schema
{
return $schema
@@ -97,7 +94,18 @@ class EditServer extends EditRecord
'lg' => 6,
])
->columnSpanFull()
->tabs([
->tabs($this->getTabs()),
]);
}
/**
* @return Tab[]
*
* @throws RandomException
*/
protected function getDefaultTabs(): array
{
return [
Tab::make('information')
->label(trans('admin/server.tabs.information'))
->icon('tabler-info-circle')
@@ -966,7 +974,7 @@ class EditServer extends EditRecord
->disabled(fn (Server $server) => user()?->accessibleNodes()->count() <= 1 || $server->isInConflictState())
->modalHeading(trans('admin/server.transfer'))
->schema($this->transferServer())
->action(function (TransferServerService $transfer, DeleteBackupService $deleteBackup, Server $server, $data) {
->action(function (TransferServerService $transfer, Server $server, $data) {
try {
$selectedBackupUuids = Arr::get($data, 'backups', []);
$transfer->handle($server, Arr::get($data, 'node_id'), Arr::get($data, 'allocation_id'), Arr::get($data, 'allocation_additional', []), $selectedBackupUuids);
@@ -1029,8 +1037,7 @@ class EditServer extends EditRecord
]),
]),
]),
]),
]);
];
}
/** @return Component[]

View File

@@ -18,6 +18,7 @@ use App\Models\UserSSHKey;
use App\Services\Helpers\LanguageService;
use App\Traits\Filament\CanCustomizePages;
use App\Traits\Filament\CanCustomizeRelations;
use App\Traits\Filament\CanCustomizeStaticTabs;
use App\Traits\Filament\CanModifyForm;
use App\Traits\Filament\CanModifyTable;
use DateTimeZone;
@@ -59,6 +60,7 @@ class UserResource extends Resource
{
use CanCustomizePages;
use CanCustomizeRelations;
use CanCustomizeStaticTabs;
use CanModifyForm;
use CanModifyTable;
@@ -146,7 +148,15 @@ class UserResource extends Resource
->columns(['default' => 1, 'lg' => 3, 'md' => 2])
->components([
Tabs::make()
->schema([
->schema(static::getTabs())
->columnSpanFull(),
]);
}
/** @return Tab[] */
protected static function getDefaultTabs(): array
{
return [
Tab::make('account')
->label(trans('profile.tabs.account'))
->icon('tabler-user-cog')
@@ -332,7 +342,7 @@ class UserResource extends Resource
Tab::make('roles')
->label(trans('admin/user.roles'))
->icon('tabler-users-group')
->components([
->schema([
CheckboxList::make('roles')
->hidden(fn (?User $user) => $user && $user->isRootAdmin())
->relationship('roles', 'name', fn (Builder $query) => $query->whereNot('id', Role::getRootAdmin()->id))
@@ -470,8 +480,7 @@ class UserResource extends Resource
->state(fn (ActivityLog $log) => new HtmlString($log->htmlable())),
]),
]),
])->columnSpanFull(),
]);
];
}
/** @return class-string<RelationManager>[] */

View File

@@ -14,6 +14,7 @@ use App\Services\Ssh\KeyCreationService;
use App\Services\Users\UserUpdateService;
use App\Traits\Filament\CanCustomizeHeaderActions;
use App\Traits\Filament\CanCustomizeHeaderWidgets;
use App\Traits\Filament\CanCustomizeTabs;
use DateTimeZone;
use Exception;
use Filament\Actions\Action;
@@ -56,6 +57,7 @@ class EditProfile extends BaseEditProfile
{
use CanCustomizeHeaderActions;
use CanCustomizeHeaderWidgets;
use CanCustomizeTabs;
protected OAuthService $oauthService;
@@ -82,12 +84,24 @@ class EditProfile extends BaseEditProfile
*/
public function form(Schema $schema): Schema
{
$oauthSchemas = $this->oauthService->getEnabled();
return $schema
->components([
Tabs::make()->persistTabInQueryString()
->schema([
Tabs::make()
->persistTabInQueryString()
->tabs($this->getTabs()),
])
->operation('edit')
->model($this->getUser())
->statePath('data')
->inlineLabel(!static::isSimple());
}
/** @return Tab[] */
protected function getDefaultTabs(): array
{
$oauthSchemas = $this->oauthService->getEnabled();
return [
Tab::make('account')
->label(trans('profile.tabs.account'))
->icon('tabler-user-cog')
@@ -540,12 +554,7 @@ class EditProfile extends BaseEditProfile
->default(30),
]),
]),
]),
])
->operation('edit')
->model($this->getUser())
->statePath('data')
->inlineLabel(!static::isSimple());
];
}
protected function getFormActions(): array

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Traits\Filament;
use App\Enums\TabPosition;
use Filament\Schemas\Components\Tabs\Tab;
trait CanCustomizeStaticTabs
{
/** @var array<string, Tab[]> */
protected static array $customTabs = [];
public static function registerCustomTabs(TabPosition $position, Tab ...$customTabs): void
{
static::$customTabs[$position->value] = array_merge(static::$customTabs[$position->value] ?? [], $customTabs);
}
/** @return Tab[] */
protected static function getDefaultTabs(): array
{
return [];
}
/** @return Tab[] */
protected static function getTabs(): array
{
return array_merge(
static::$customTabs[TabPosition::Before->value] ?? [],
static::getDefaultTabs(),
static::$customTabs[TabPosition::After->value] ?? []
);
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Traits\Filament;
use App\Enums\TabPosition;
use Filament\Schemas\Components\Tabs\Tab;
trait CanCustomizeTabs
{
/** @var array<string, Tab[]> */
protected static array $customTabs = [];
public static function registerCustomTabs(TabPosition $position, Tab ...$customTabs): void
{
static::$customTabs[$position->value] = array_merge(static::$customTabs[$position->value] ?? [], $customTabs);
}
/** @return Tab[] */
protected function getDefaultTabs(): array
{
return [];
}
/** @return Tab[] */
protected function getTabs(): array
{
return array_merge(
static::$customTabs[TabPosition::Before->value] ?? [],
$this->getDefaultTabs(),
static::$customTabs[TabPosition::After->value] ?? []
);
}
}