diff --git a/resources/views/filament/components/brand-with-tenant-switcher.blade.php b/resources/views/filament/components/brand-with-tenant-switcher.blade.php new file mode 100644 index 0000000..3582c29 --- /dev/null +++ b/resources/views/filament/components/brand-with-tenant-switcher.blade.php @@ -0,0 +1,62 @@ +@if ($shouldShowDropdown()) +
+ + + + + + + + + + + @if ($canSwitchTenants()) + @foreach ($getTenants() as $tenant) + + {{ filament()->getTenantName($tenant) }} + + @endforeach + @endif + + + @if ($hasFrontend()) + @if ($canSwitchTenants()) + + @endif + + +
+ + Frontend + +
+
+ @endif +
+
+
+@else + +@endif diff --git a/src/EclipseServiceProvider.php b/src/EclipseServiceProvider.php index 13a2f18..ba6a910 100644 --- a/src/EclipseServiceProvider.php +++ b/src/EclipseServiceProvider.php @@ -27,6 +27,7 @@ use Eclipse\Core\Providers\HorizonServiceProvider; use Eclipse\Core\Providers\TelescopeServiceProvider; use Eclipse\Core\Services\Registry; +use Eclipse\Frontend\Providers\FrontendPanelProvider; use Filament\Facades\Filament; use Filament\Resources\Resource; use Filament\Support\Facades\FilamentAsset; @@ -103,6 +104,10 @@ public function register(): self $this->app->register(AdminPanelProvider::class); } + if (class_exists(FrontendPanelProvider::class)) { + $this->app->register(FrontendPanelProvider::class); + } + if ($this->app->environment('local')) { $this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class); $this->app->register(TelescopeServiceProvider::class); diff --git a/src/Providers/AdminPanelProvider.php b/src/Providers/AdminPanelProvider.php index 5d6e90f..cc01045 100644 --- a/src/Providers/AdminPanelProvider.php +++ b/src/Providers/AdminPanelProvider.php @@ -5,7 +5,6 @@ use BezhanSalleh\FilamentShield\Facades\FilamentShield; use BezhanSalleh\FilamentShield\FilamentShieldPlugin; use BezhanSalleh\FilamentShield\Middleware\SyncShieldTenant; -use BezhanSalleh\PanelSwitch\PanelSwitch; use DutchCodingCompany\FilamentDeveloperLogins\FilamentDeveloperLoginsPlugin; use Eclipse\Common\CommonPlugin; use Eclipse\Common\Providers\GlobalSearchProvider; @@ -16,6 +15,7 @@ use Eclipse\Core\Models\Site; use Eclipse\Core\Models\User; use Eclipse\Core\Services\Registry; +use Eclipse\Core\View\Components\BrandWithTenantSwitcher; use Eclipse\World\EclipseWorld; use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\DisableBladeIconComponents; @@ -41,7 +41,6 @@ use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Schema; use Illuminate\View\Middleware\ShareErrorsFromSession; -use Illuminate\View\View; use LaraZeus\SpatieTranslatable\SpatieTranslatablePlugin; use pxlrbt\FilamentEnvironmentIndicator\EnvironmentIndicatorPlugin; use pxlrbt\FilamentSpotlight\SpotlightPlugin; @@ -77,7 +76,7 @@ public function panel(Panel $panel): Panel ]) ->topNavigation() ->brandLogo( - fn (): View => view('eclipse::filament.components.brand') + fn () => app(BrandWithTenantSwitcher::class) ) ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources') ->discoverResources(in: $package_src.'Filament/Resources', for: 'Eclipse\\Core\\Filament\\Resources') @@ -169,13 +168,6 @@ public function panel(Panel $panel): Panel fn () => view('eclipse::filament.components.my-settings') ); - if ($hasTenantMenu) { - $panel->renderHook( - PanelsRenderHook::GLOBAL_SEARCH_END, - fn () => view('eclipse::filament.components.tenant-menu') - ); - } - // If the Pro version of the Spotlight plugin is installed, use that, otherwise use the free version if (class_exists(\pxlrbt\FilamentSpotlightPro\SpotlightPlugin::class)) { /** @noinspection PhpFullyQualifiedNameUsageInspection */ @@ -240,20 +232,5 @@ public function boot(): void // Load customized translations for Filament Shield $this->loadTranslationsFrom(__DIR__.'/../../resources/lang/vendor/filament-shield', 'filament-shield'); - - // Configure Panel Switch - PanelSwitch::configureUsing(function (PanelSwitch $panelSwitch) { - $panelSwitch - ->simple() - ->icons([ - 'admin' => 'heroicon-s-cog-6-tooth', - 'frontend' => 'heroicon-s-globe-alt', - ]) - ->labels([ - 'admin' => 'Admin Panel', - 'frontend' => 'Frontend', - ]) - ->visible(fn (): bool => auth()->check()); - }); } } diff --git a/src/View/Components/BrandWithTenantSwitcher.php b/src/View/Components/BrandWithTenantSwitcher.php new file mode 100644 index 0000000..0b4ac43 --- /dev/null +++ b/src/View/Components/BrandWithTenantSwitcher.php @@ -0,0 +1,93 @@ +name ?? config('app.name'); + } + + public function hasSpaMode(): bool + { + return Filament::getCurrentPanel()->hasSpaMode(); + } + + public function getDashboardUrl(): string + { + return '/'.trim(Filament::getCurrentPanel()->getPath(), '/'); + } + + public function getCurrentTenant(): ?Model + { + return filament()->getTenant(); + } + + public function getCurrentTenantName(): ?string + { + $currentTenant = $this->getCurrentTenant(); + + return $currentTenant ? filament()->getTenantName($currentTenant) : null; + } + + public function getTenants(): array + { + if (! $this->isMultiSiteEnabled() || ! filament()->auth()->check()) { + return []; + } + + $currentTenant = $this->getCurrentTenant(); + + return array_filter( + filament()->getUserTenants(filament()->auth()->user()), + fn (Model $tenant): bool => ! $tenant->is($currentTenant), + ); + } + + public function canSwitchTenants(): bool + { + return count($this->getTenants()) > 0; + } + + public function hasFrontend(): bool + { + return collect(Filament::getPanels())->has('frontend'); + } + + public function getFrontendUrl(): string + { + if (! $this->hasFrontend()) { + return config('app.url'); + } + + try { + $currentTenant = $this->getCurrentTenant(); + if ($currentTenant?->domain) { + return "https://{$currentTenant->domain}"; + } else { + return config('app.url'); + } + } catch (Exception $e) { + return config('app.url'); + } + } + + public function shouldShowDropdown(): bool + { + return $this->canSwitchTenants() || $this->hasFrontend(); + } + + private function isMultiSiteEnabled(): bool + { + return config('eclipse.multi_site', false); + } +} diff --git a/tests/Feature/Filament/BrandWithTenantSwitcherTest.php b/tests/Feature/Filament/BrandWithTenantSwitcherTest.php new file mode 100644 index 0000000..c60a346 --- /dev/null +++ b/tests/Feature/Filament/BrandWithTenantSwitcherTest.php @@ -0,0 +1,62 @@ +get('/admin/login'); + + $response->assertStatus(200); + $response->assertSee(config('app.name')); +}); + +test('brand component renders with multi-site enabled', function () { + config(['eclipse.multi_site' => true]); + + $response = $this->get('/admin/login'); + $response->assertStatus(200); + $response->assertSee(config('app.name')); +}); + +test('brand component dropdown behavior depends on frontend and tenant availability', function () { + $component = new BrandWithTenantSwitcher; + + $hasFrontend = $component->hasFrontend(); + $canSwitchTenants = $component->canSwitchTenants(); + $shouldShowDropdown = $component->shouldShowDropdown(); + + expect($shouldShowDropdown)->toBe($hasFrontend || $canSwitchTenants); + + expect($hasFrontend)->toBeBool(); + expect($canSwitchTenants)->toBeBool(); + expect($shouldShowDropdown)->toBeBool(); +}); + +test('tenant switcher logic handles multiple and single tenant scenarios', function () { + config(['eclipse.multi_site' => true]); + + $user = User::factory()->create(); + $site1 = Site::factory()->create(['name' => 'Primary Site']); + $site2 = Site::factory()->create(['name' => 'Secondary Site']); + + $user->sites()->attach([$site1->id, $site2->id]); + + expect($user->sites)->toHaveCount(2); + expect($user->sites->pluck('name'))->toContain('Primary Site', 'Secondary Site'); + + $singleSiteUser = User::factory()->create(); + $singleSite = Site::factory()->create(['name' => 'Only Site']); + $singleSiteUser->sites()->attach($singleSite->id); + + expect($singleSiteUser->sites)->toHaveCount(1); + expect($singleSiteUser->sites->first()->name)->toBe('Only Site'); +}); + +test('brand component renders app name correctly', function () { + $component = new BrandWithTenantSwitcher; + + $appName = $component->getAppName(); + + expect($appName)->toBe(config('app.name')); +}); diff --git a/workbench/app/Providers/WorkbenchServiceProvider.php b/workbench/app/Providers/WorkbenchServiceProvider.php index d683933..a8c3f83 100644 --- a/workbench/app/Providers/WorkbenchServiceProvider.php +++ b/workbench/app/Providers/WorkbenchServiceProvider.php @@ -2,8 +2,11 @@ namespace Workbench\App\Providers; +use Eclipse\Common\CommonServiceProvider; use Eclipse\Core\Providers\AdminPanelProvider; +use Eclipse\Frontend\Providers\FrontendPanelProvider; use Illuminate\Support\ServiceProvider; +use Nben\FilamentRecordNav\FilamentRecordNavServiceProvider; class WorkbenchServiceProvider extends ServiceProvider { @@ -12,7 +15,19 @@ class WorkbenchServiceProvider extends ServiceProvider */ public function register(): void { + if (class_exists(CommonServiceProvider::class)) { + $this->app->register(CommonServiceProvider::class); + } + + if (class_exists(FilamentRecordNavServiceProvider::class)) { + $this->app->register(FilamentRecordNavServiceProvider::class); + } + $this->app->register(AdminPanelProvider::class); + + if (class_exists(FrontendPanelProvider::class)) { + $this->app->register(FrontendPanelProvider::class); + } } /**