Merge branch 'main' into copilot/bulk-update-allocation-ips

This commit is contained in:
Charles 2025-11-01 05:18:52 -04:00
commit 8aef425c65
28 changed files with 461 additions and 111 deletions

View File

@ -18,7 +18,7 @@ enum CustomizationKey: string
self::ConsoleFont => 'monospace',
self::ConsoleFontSize => 14,
self::ConsoleGraphPeriod => 30,
self::TopNavigation => false,
self::TopNavigation => config('panel.filament.default-navigation', 'sidebar'),
self::DashboardLayout => 'grid',
};
}

View File

@ -56,8 +56,7 @@ class JavaVersionSchema implements FeatureSchemaInterface
->default(fn () => $server->image)
->notIn(fn () => $server->image)
->required()
->preload()
->native(false),
->preload(),
])
->action(function (array $data, DaemonServerRepository $serverRepository) use ($server) {
try {

View File

@ -4,6 +4,10 @@ namespace App\Extensions\OAuth\Schemas;
use Filament\Forms\Components\ColorPicker;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Wizard\Step;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
use SocialiteProviders\Authentik\Provider;
final class AuthentikSchema extends OAuthSchema
@ -20,11 +24,27 @@ final class AuthentikSchema extends OAuthSchema
public function getServiceConfig(): array
{
return [
return array_merge(parent::getServiceConfig(), [
'base_url' => env('OAUTH_AUTHENTIK_BASE_URL'),
'client_id' => env('OAUTH_AUTHENTIK_CLIENT_ID'),
'client_secret' => env('OAUTH_AUTHENTIK_CLIENT_SECRET'),
];
]);
}
public function getSetupSteps(): array
{
return array_merge([
Step::make('Create Authentik Application')
->schema([
TextEntry::make('create_application')
->hiddenLabel()
->state(new HtmlString(Blade::render('<p>On your Authentik dashboard select <b>Applications</b>, then select <b>Create with Provider</b>.</p><p>On the creation step select <b>OAuth2/OpenID Provider</b> and on the configure step set <b>Redirect URIs/Origins</b> to the value below.</p>'))),
TextInput::make('_noenv_callback')
->label('Callback URL')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('/auth/oauth/callback/authentik')),
]),
], parent::getSetupSteps());
}
public function getSettingsForm(): array

View File

@ -0,0 +1,45 @@
<?php
namespace App\Extensions\OAuth\Schemas;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Wizard\Step;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
final class BitbucketSchema extends OAuthSchema
{
public function getId(): string
{
return 'bitbucket';
}
public function getSetupSteps(): array
{
return array_merge([
Step::make('Register new Bitbucket Consumer')
->schema([
TextEntry::make('create_application')
->hiddenLabel()
->state(new HtmlString(Blade::render('<p>Visit the <x-filament::link href="https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud" target="_blank">Bitbucket OAuth Documentation</x-filament::link> and follow the steps in <b>Create a consumer</b>.</p><p>For the <b>Callback URL</b> use the value below.</p>'))),
TextInput::make('_noenv_callback')
->label('Callback URL')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('/auth/oauth/callback/bitbucket')),
]),
], parent::getSetupSteps());
}
public function getIcon(): string
{
return 'tabler-brand-bitbucket-f';
}
public function getHexColor(): string
{
return '#205081';
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace App\Extensions\OAuth\Schemas;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Wizard\Step;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
final class FacebookSchema extends OAuthSchema
{
public function getId(): string
{
return 'facebook';
}
public function getSetupSteps(): array
{
return array_merge([
Step::make('Register new Facebook Application')
->schema([
TextEntry::make('create_application')
->hiddenLabel()
->state(new HtmlString(Blade::render('<p>Visit the <x-filament::link href="https://developers.facebook.com/apps" target="_blank">Facebook Developer Dashboard</x-filament::link> and select or create a new app you will use for authentication. Make sure to have "Authenticate and request data from users with Facebook Login" as one of the Use Cases.</p><p>Once selected go to <b>Use Cases</b> and customize "Authenticate and request data from users with Facebook Login", from there go to <b>Settings</b> and add <b>Valid OAuth Redirect URIs</b> using the value below.</p>'))),
TextInput::make('_noenv_callback')
->label('Valid OAuth Redirect URIs')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('/auth/oauth/callback/facebook')),
TextEntry::make('get_app_info')
->hiddenLabel()
->state(new HtmlString(Blade::render('<p>To obtain the OAuth values go to <b>App Settings > Basic</b>.</p>'))),
]),
], parent::getSetupSteps());
}
public function getIcon(): string
{
return 'tabler-brand-facebook-f';
}
public function getHexColor(): string
{
return '#1877f2';
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace App\Extensions\OAuth\Schemas;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Wizard\Step;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
final class GoogleSchema extends OAuthSchema
{
public function getId(): string
{
return 'google';
}
public function getSetupSteps(): array
{
return array_merge([
Step::make('Register new OAuth client')
->schema([
TextEntry::make('create_application')
->hiddenLabel()
->state(new HtmlString(Blade::render('<p>Visit the <x-filament::link href="https://console.developers.google.com/" target="_blank">Google API Console</x-filament::link> and create or select the project you want to use.</p><p>Navigate or search <b>Credentials</b>, click on the <b>Create Credentials</b> button and select <b>OAuth client ID</b>. On the Application type select <b>Web Application</b>.</p><p>On <b>Authorized JavaScript origins</b> and <b>Authorized redirect URIs</b> add and use the values below.</p>'))),
TextInput::make('_noenv_origin')
->label('Authorized JavaScript origins')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('')),
TextInput::make('_noenv_callback')
->label('Authorized redirect URIs')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('/auth/oauth/callback/google')),
TextEntry::make('register_application')
->hiddenLabel()
->state(new HtmlString('<p>When you filled all fields click on <b>Create</b>.</p>')),
]),
], parent::getSetupSteps());
}
public function getIcon(): string
{
return 'tabler-brand-google-f';
}
public function getHexColor(): string
{
return '#4285f4';
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Extensions\OAuth\Schemas;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Wizard\Step;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
final class LinkedinSchema extends OAuthSchema
{
public function getId(): string
{
return 'linkedin';
}
public function getSetupSteps(): array
{
return array_merge([
Step::make('Obtain Linkedin App OAuth Config')
->schema([
TextEntry::make('create_application')
->hiddenLabel()
->state(new HtmlString(Blade::render('<p><x-filament::link href="https://www.linkedin.com/developers/apps/new" target="_blank">Create</x-filament::link> or <x-filament::link href="https://www.linkedin.com/developers/apps" target="_blank">select</x-filament::link> the one you will be using for authentication.</p><p>Select the <b>Auth</b> tab and set <b>Authorized redirect URLs for your app</b> to the value below.</p>'))),
TextInput::make('_noenv_callback')
->label('Authorized redirect URL')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('/auth/oauth/callback/linkedin')),
]),
], parent::getSetupSteps());
}
public function getIcon(): string
{
return 'tabler-brand-linkedin-f';
}
public function getHexColor(): string
{
return '#0a66c2';
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Extensions\OAuth\Schemas;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Wizard\Step;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
final class SlackSchema extends OAuthSchema
{
public function getId(): string
{
return 'slack';
}
public function getSetupSteps(): array
{
return array_merge([
Step::make('Register new Slack OAuth')
->schema([
TextEntry::make('create_application')
->hiddenLabel()
->state(new HtmlString(Blade::render('<p><x-filament::link href="https://api.slack.com/apps?new_app=1" target="_blank">Create</x-filament::link> a slack app or <x-filament::link href="https://api.slack.com/apps" target="_blank">select</x-filament::link> the one you will be using for authentication.</p><p>Navigate to the <b>OAuth & Permissions</b> section and configure the <b>Redirect URL</b> using the value below.</p>'))),
TextInput::make('_noenv_callback')
->label('Redirect URL')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('/auth/oauth/callback/slack')),
]),
], parent::getSetupSteps());
}
public function getIcon(): string
{
return 'tabler-brand-slack';
}
public function getHexColor(): string
{
return '#6ecadc';
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace App\Extensions\OAuth\Schemas;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Wizard\Step;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
final class XSchema extends OAuthSchema
{
public function getId(): string
{
return 'x';
}
public function getSetupSteps(): array
{
return array_merge([
Step::make('Register new X App')
->schema([
TextEntry::make('create_application')
->hiddenLabel()
->state(new HtmlString(Blade::render('<p>Visit the <x-filament::link href="https://developer.x.com/en/portal/dashboard" target="_blank">X Developer Dashboard</x-filament::link> and create or select the project app you want to use.</p><p>Go to the app\'s settings and set up <b>User authentication</b> if not yet. Make sure to select <b>Web App</b> as the type of app.</p><p>For the <b>Callback URI / Redirect URL</b> and <b>Website URL</b> set it using the value below.</p>'))),
TextInput::make('_noenv_origin')
->label('Website URL')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('')),
TextInput::make('_noenv_callback')
->label('Callback URI / Redirect URL')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('/auth/oauth/callback/x')),
TextEntry::make('register_application')
->hiddenLabel()
->state(new HtmlString('<p>If you have already set this up go to your app\'s <b>Keys and tokens</b> and obtain the Client ID and Secret there.</p>')),
]),
], parent::getSetupSteps());
}
public function getIcon(): string
{
return 'tabler-brand-x';
}
public function getHexColor(): string
{
return '#1da1f2';
}
}

View File

@ -181,7 +181,6 @@ class Settings extends Page implements HasSchemas
->schema([
Select::make('FILAMENT_AVATAR_PROVIDER')
->label(trans('admin/setting.general.avatar_provider'))
->native(false)
->options($this->avatarService->getMappings())
->selectablePlaceholder(false)
->default(env('FILAMENT_AVATAR_PROVIDER', config('panel.filament.avatar-provider'))),
@ -204,6 +203,15 @@ class Settings extends Page implements HasSchemas
])
->stateCast(new BooleanStateCast(false, true))
->default(env('PANEL_USE_BINARY_PREFIX', config('panel.use_binary_prefix'))),
ToggleButtons::make('FILAMENT_DEFAULT_NAVIGATION')
->label(trans('admin/setting.general.default_navigation'))
->inline()
->options([
'sidebar' => trans('admin/setting.general.sidebar'),
'topbar' => trans('admin/setting.general.topbar'),
'mixed' => trans('admin/setting.general.mixed'),
])
->default(env('FILAMENT_DEFAULT_NAVIGATION', config('panel.filament.default-navigation'))),
ToggleButtons::make('APP_2FA_REQUIRED')
->label(trans('admin/setting.general.2fa_requirement'))
->inline()
@ -217,7 +225,6 @@ class Settings extends Page implements HasSchemas
->default(env('APP_2FA_REQUIRED', config('panel.auth.2fa_required'))),
Select::make('FILAMENT_WIDTH')
->label(trans('admin/setting.general.display_width'))
->native(false)
->options(Width::class)
->selectablePlaceholder(false)
->default(env('FILAMENT_WIDTH', config('panel.filament.display-width'))),

View File

@ -257,7 +257,6 @@ class CreateEgg extends CreateRecord
->default('ghcr.io/pelican-eggs/installers:debian'),
Select::make('script_entry')
->label(trans('admin/egg.script_entry'))
->native(false)
->selectablePlaceholder(false)
->default('bash')
->options([

View File

@ -248,7 +248,6 @@ class EditEgg extends EditRecord
->placeholder('ghcr.io/pelican-eggs/installers:debian'),
Select::make('script_entry')
->label(trans('admin/egg.script_entry'))
->native(false)
->selectablePlaceholder(false)
->options([
'bash' => 'bash',

View File

@ -24,6 +24,7 @@ use Filament\Resources\Pages\PageRegistration;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Group;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\StateCasts\BooleanStateCast;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
@ -125,6 +126,7 @@ class MountResource extends Resource
ToggleButtons::make('read_only')
->label(trans('admin/mount.read_only'))
->helperText(trans('admin/mount.read_only_help'))
->stateCast(new BooleanStateCast(false))
->options([
false => trans('admin/mount.toggles.writable'),
true => trans('admin/mount.toggles.read_only'),

View File

@ -236,8 +236,7 @@ class UserResource extends Resource
->default(fn () => config('app.timezone', 'UTC'))
->selectablePlaceholder(false)
->options(fn () => collect(DateTimeZone::listIdentifiers())->mapWithKeys(fn ($tz) => [$tz => $tz]))
->searchable()
->native(false),
->searchable(),
Select::make('language')
->label(trans('profile.language'))
->columnSpan([
@ -251,8 +250,7 @@ class UserResource extends Resource
->default('en')
->searchable()
->selectablePlaceholder(false)
->options(fn (LanguageService $languageService) => $languageService->getAvailableLanguages())
->native(false),
->options(fn (LanguageService $languageService) => $languageService->getAvailableLanguages()),
FileUpload::make('avatar')
->visible(fn (?User $user, FileUpload $fileUpload) => $user ? $fileUpload->getDisk()->exists($fileUpload->getDirectory() . '/' . $user->id . '.png') : false)
->avatar()

View File

@ -21,8 +21,6 @@ class CopyFrom extends Select
$this->searchable();
$this->native(false);
$this->live();
}

View File

@ -34,7 +34,6 @@ use Filament\Schemas\Components\Actions;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Components\Group;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\StateCasts\BooleanStateCast;
use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
use Filament\Schemas\Components\Utilities\Get;
@ -132,8 +131,7 @@ class EditProfile extends BaseEditProfile
->default(config('app.timezone', 'UTC'))
->selectablePlaceholder(false)
->options(fn () => collect(DateTimeZone::listIdentifiers())->mapWithKeys(fn ($tz) => [$tz => $tz]))
->searchable()
->native(false),
->searchable(),
Select::make('language')
->label(trans('profile.language'))
->required()
@ -143,8 +141,7 @@ class EditProfile extends BaseEditProfile
->selectablePlaceholder(false)
->helperText(fn ($state, LanguageService $languageService) => new HtmlString($languageService->isLanguageTranslated($state) ? ''
: trans('profile.language_help', ['state' => $state]) . ' <u><a href="https://crowdin.com/project/pelican-dev/">Update On Crowdin</a></u>'))
->options(fn (LanguageService $languageService) => $languageService->getAvailableLanguages())
->native(false),
->options(fn (LanguageService $languageService) => $languageService->getAvailableLanguages()),
FileUpload::make('avatar')
->visible(fn () => config('panel.filament.uploadable-avatars'))
->avatar()
@ -442,10 +439,10 @@ class EditProfile extends BaseEditProfile
->label(trans('profile.navigation'))
->inline()
->options([
1 => trans('profile.top'),
0 => trans('profile.side'),
])
->stateCast(new BooleanStateCast(false, true)),
'sidebar' => trans('profile.sidebar'),
'topbar' => trans('profile.topbar'),
'mixed' => trans('profile.mixed'),
]),
]),
Section::make(trans('profile.console'))
->collapsible()
@ -585,7 +582,14 @@ class EditProfile extends BaseEditProfile
$data['console_rows'] = (int) $this->getUser()->getCustomization(CustomizationKey::ConsoleRows);
$data['console_graph_period'] = (int) $this->getUser()->getCustomization(CustomizationKey::ConsoleGraphPeriod);
$data['dashboard_layout'] = $this->getUser()->getCustomization(CustomizationKey::DashboardLayout);
$data['top_navigation'] = (bool) $this->getUser()->getCustomization(CustomizationKey::TopNavigation);
// Handle migration from boolean to string navigation types
$topNavigation = $this->getUser()->getCustomization(CustomizationKey::TopNavigation);
if (is_bool($topNavigation)) {
$data['top_navigation'] = $topNavigation ? 'topbar' : 'sidebar';
} else {
$data['top_navigation'] = $topNavigation;
}
return $data;
}

View File

@ -308,7 +308,6 @@ class ListFiles extends ListRecords
Select::make('extension')
->label(trans('server/file.actions.archive.extension'))
->selectablePlaceholder(false)
->native(false)
->options([
'tar.gz' => 'tar.gz',
'zip' => 'zip',
@ -417,7 +416,6 @@ class ListFiles extends ListRecords
Select::make('extension')
->label(trans('server/file.actions.archive.extension'))
->selectablePlaceholder(false)
->native(false)
->options([
'tar.gz' => 'tar.gz',
'zip' => 'zip',

View File

@ -255,8 +255,7 @@ class ScheduleResource extends Resource
'6' => trans('server/schedule.time.saturday'),
'0' => trans('server/schedule.time.sunday'),
])
->selectablePlaceholder(false)
->native(false),
->selectablePlaceholder(false),
])
->action(function (Set $set, $data) {
$set('cron_minute', '0');

View File

@ -117,7 +117,6 @@ class PanelInstaller extends SimplePage implements HasForms
->selectablePlaceholder(false)
->options(fn (LanguageService $languageService) => $languageService->getAvailableLanguages())
->afterStateUpdated(fn ($state, Application $app) => $app->setLocale($state ?? config('app.locale')))
->native(false)
->columnStart(4);
}

View File

@ -26,30 +26,18 @@ use App\Services\Helpers\SoftwareVersionService;
use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
use Filament\Forms\Components\Field;
use Filament\Forms\Components\TextInput\Actions\CopyAction;
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentColor;
use Filament\Support\Facades\FilamentView;
use Filament\View\PanelsRenderHook;
use Illuminate\Config\Repository;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Console\AboutCommand;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Laravel\Sanctum\Sanctum;
use Livewire\Component;
use Livewire\Livewire;
use Spatie\Health\Facades\Health;
use function Livewire\on;
use function Livewire\store;
class AppServiceProvider extends ServiceProvider
{
/**
@ -104,57 +92,6 @@ class AppServiceProvider extends ServiceProvider
Scramble::registerApi('application', ['api_path' => 'api/application', 'info' => ['version' => '1.0']])->afterOpenApiGenerated($bearerTokens);
Scramble::registerApi('client', ['api_path' => 'api/client', 'info' => ['version' => '1.0']])->afterOpenApiGenerated($bearerTokens);
FilamentColor::register([
'danger' => Color::Red,
'gray' => Color::Zinc,
'info' => Color::Sky,
'primary' => Color::Blue,
'success' => Color::Green,
'warning' => Color::Amber,
'blurple' => Color::hex('#5865F2'),
]);
FilamentView::registerRenderHook(
PanelsRenderHook::PAGE_START,
fn () => Blade::render('@livewire(\App\Livewire\AlertBannerContainer::class)'),
);
FilamentView::registerRenderHook(
PanelsRenderHook::FOOTER,
fn () => Blade::render('filament.layouts.footer'),
);
FilamentView::registerRenderHook(
PanelsRenderHook::STYLES_BEFORE,
fn () => Blade::render("@vite(['resources/css/app.css'])")
);
FilamentView::registerRenderHook(
PanelsRenderHook::SCRIPTS_AFTER,
fn () => Blade::render("@vite(['resources/js/app.js'])"),
);
on('dehydrate', function (Component $component) {
if (!Livewire::isLivewireRequest()) {
return;
}
if (store($component)->has('redirect')) {
return;
}
if (count(session()->get('alert-banners') ?? []) <= 0) {
return;
}
$component->dispatch('alertBannerSent');
});
Field::macro('hintCopy', function () {
/** @var Field $this */
return $this->hintAction(CopyAction::make()); // @phpstan-ignore varTag.nativeType
});
// Don't run any health checks during tests
if (!$app->runningUnitTests()) {
Health::checks([

View File

@ -4,11 +4,16 @@ namespace App\Providers\Extensions;
use App\Extensions\OAuth\OAuthService;
use App\Extensions\OAuth\Schemas\AuthentikSchema;
use App\Extensions\OAuth\Schemas\CommonSchema;
use App\Extensions\OAuth\Schemas\BitbucketSchema;
use App\Extensions\OAuth\Schemas\DiscordSchema;
use App\Extensions\OAuth\Schemas\FacebookSchema;
use App\Extensions\OAuth\Schemas\GithubSchema;
use App\Extensions\OAuth\Schemas\GitlabSchema;
use App\Extensions\OAuth\Schemas\GoogleSchema;
use App\Extensions\OAuth\Schemas\LinkedinSchema;
use App\Extensions\OAuth\Schemas\SlackSchema;
use App\Extensions\OAuth\Schemas\SteamSchema;
use App\Extensions\OAuth\Schemas\XSchema;
use Illuminate\Support\ServiceProvider;
class OAuthServiceProvider extends ServiceProvider
@ -19,14 +24,14 @@ class OAuthServiceProvider extends ServiceProvider
$service = new OAuthService();
// Default OAuth providers included with Socialite
$service->register(new CommonSchema('facebook', icon: 'tabler-brand-facebook-f', hexColor: '#1877f2'));
$service->register(new CommonSchema('x', icon: 'tabler-brand-x-f', hexColor: '#1da1f2'));
$service->register(new CommonSchema('linkedin', icon: 'tabler-brand-linkedin-f', hexColor: '#0a66c2'));
$service->register(new CommonSchema('google', icon: 'tabler-brand-google-f', hexColor: '#4285f4'));
$service->register(new FacebookSchema());
$service->register(new XSchema());
$service->register(new LinkedinSchema());
$service->register(new GoogleSchema());
$service->register(new GithubSchema());
$service->register(new GitlabSchema());
$service->register(new CommonSchema('bitbucket', icon: 'tabler-brand-bitbucket-f', hexColor: '#205081'));
$service->register(new CommonSchema('slack', icon: 'tabler-brand-slack', hexColor: '#6ecadc'));
$service->register(new BitbucketSchema());
$service->register(new SlackSchema());
// Additional OAuth providers from socialiteproviders.com
$service->register(new AuthentikSchema());

View File

@ -0,0 +1,82 @@
<?php
namespace App\Providers\Filament;
use Filament\Forms\Components\Field;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput\Actions\CopyAction;
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentColor;
use Filament\Support\Facades\FilamentView;
use Filament\View\PanelsRenderHook;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Livewire\Component;
use Livewire\Livewire;
use function Livewire\on;
use function Livewire\store;
class FilamentServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
FilamentColor::register([
'danger' => Color::Red,
'gray' => Color::Zinc,
'info' => Color::Sky,
'primary' => Color::Blue,
'success' => Color::Green,
'warning' => Color::Amber,
'blurple' => Color::hex('#5865F2'),
]);
FilamentView::registerRenderHook(
PanelsRenderHook::PAGE_START,
fn () => Blade::render('@livewire(\App\Livewire\AlertBannerContainer::class)'),
);
FilamentView::registerRenderHook(
PanelsRenderHook::FOOTER,
fn () => Blade::render('filament.layouts.footer'),
);
FilamentView::registerRenderHook(
PanelsRenderHook::STYLES_BEFORE,
fn () => Blade::render("@vite(['resources/css/app.css'])")
);
FilamentView::registerRenderHook(
PanelsRenderHook::SCRIPTS_AFTER,
fn () => Blade::render("@vite(['resources/js/app.js'])"),
);
on('dehydrate', function (Component $component) {
if (!Livewire::isLivewireRequest()) {
return;
}
if (store($component)->has('redirect')) {
return;
}
if (count(session()->get('alert-banners') ?? []) <= 0) {
return;
}
$component->dispatch('alertBannerSent');
});
Field::macro('hintCopy', function () {
/** @var Field $this */
return $this->hintAction(CopyAction::make()); // @phpstan-ignore varTag.nativeType
});
Select::configureUsing(fn (Select $select) => $select->native(false));
}
public function register(): void {}
}

View File

@ -34,8 +34,16 @@ abstract class PanelProvider extends BasePanelProvider
->brandLogo(config('app.logo'))
->brandLogoHeight('2rem')
->favicon(config('app.favicon', '/pelican.ico'))
->topNavigation(fn () => user()?->getCustomization(CustomizationKey::TopNavigation))
->topbar(fn () => user()?->getCustomization(CustomizationKey::TopNavigation))
->topNavigation(function () {
$navigationType = user()?->getCustomization(CustomizationKey::TopNavigation);
return $navigationType === 'topbar' || $navigationType === true;
})
->topbar(function () {
$navigationType = user()?->getCustomization(CustomizationKey::TopNavigation);
return $navigationType === 'topbar' || $navigationType === 'mixed' || $navigationType === true;
})
->maxContentWidth(config('panel.filament.display-width', 'screen-2xl'))
->profile(EditProfile::class, false)
->userMenuItems([

View File

@ -5,13 +5,14 @@ return [
App\Providers\AppServiceProvider::class,
App\Providers\BackupsServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\Filament\AdminPanelProvider::class,
App\Providers\Filament\AppPanelProvider::class,
App\Providers\Filament\ServerPanelProvider::class,
App\Providers\Extensions\AvatarServiceProvider::class,
App\Providers\Extensions\CaptchaServiceProvider::class,
App\Providers\Extensions\FeatureServiceProvider::class,
App\Providers\Extensions\OAuthServiceProvider::class,
App\Providers\Filament\AdminPanelProvider::class,
App\Providers\Filament\AppPanelProvider::class,
App\Providers\Filament\FilamentServiceProvider::class,
App\Providers\Filament\ServerPanelProvider::class,
App\Providers\RouteServiceProvider::class,
SocialiteProviders\Manager\ServiceProvider::class,
];

4
composer.lock generated
View File

@ -15231,7 +15231,7 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"stability-flags": [],
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
@ -15242,7 +15242,7 @@
"ext-pdo": "*",
"ext-zip": "*"
},
"platform-dev": {},
"platform-dev": [],
"platform-overrides": {
"php": "8.2"
},

View File

@ -53,6 +53,7 @@ return [
'display-width' => env('FILAMENT_WIDTH', 'screen-2xl'),
'avatar-provider' => env('FILAMENT_AVATAR_PROVIDER', 'gravatar'),
'uploadable-avatars' => env('FILAMENT_UPLOADABLE_AVATARS', false),
'default-navigation' => env('FILAMENT_DEFAULT_NAVIGATION', 'sidebar'),
],
'use_binary_prefix' => env('PANEL_USE_BINARY_PREFIX', true),

View File

@ -20,8 +20,10 @@ return [
'app_favicon_help' => 'Favicon should be placed in the public folder located in the root panel directory.',
'debug_mode' => 'Debug Mode',
'navigation' => 'Navigation',
'default_navigation' => 'Default Navigation Type',
'sidebar' => 'Sidebar',
'topbar' => 'Topbar',
'mixed' => 'Mixed',
'unit_prefix' => 'Unit Prefix',
'decimal_prefix' => 'Decimal Prefix (MB/GB)',
'binary_prefix' => 'Binary Prefix (MiB/GiB)',

View File

@ -61,8 +61,9 @@ return [
'graph_period' => 'Graph Period',
'graph_period_helper' => 'The amount of data points, seconds, shown on the console graphs.',
'navigation' => 'Navigation Type',
'top' => 'Topbar',
'side' => 'Sidebar',
'sidebar' => 'Sidebar',
'topbar' => 'Topbar',
'mixed' => 'Mixed',
'no_oauth' => 'No Accounts Linked',
'no_api_keys' => 'No API Keys',
'no_ssh_keys' => 'No SSH Keys',