From 1b34394ed4f70fb99b165e9de50eefee3dedf308 Mon Sep 17 00:00:00 2001 From: RenHai Wen <70972819+people-sea@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:25:59 +0800 Subject: [PATCH] fix: preserve configuration context when mounting navigation (#20250) * fix: preserve configuration context when mounting navigation * test: cover navigation mounting with active configurations * consistency and more tests --------- Co-authored-by: Dan Harrin --- .../src/Navigation/NavigationManager.php | 53 ++++++++++------- .../Panels/Configuration/NavigationTest.php | 58 +++++++++++++++++++ 2 files changed, 90 insertions(+), 21 deletions(-) diff --git a/packages/panels/src/Navigation/NavigationManager.php b/packages/panels/src/Navigation/NavigationManager.php index 0076525ca3..54a5e27223 100644 --- a/packages/panels/src/Navigation/NavigationManager.php +++ b/packages/panels/src/Navigation/NavigationManager.php @@ -183,31 +183,42 @@ class NavigationManager public function mountNavigation(): void { - foreach ($this->panel->getPages() as $page) { - $page::registerNavigationItems(); - } - - foreach ($this->panel->getPageConfigurations() as $configuration) { - Filament::setCurrentPageConfigurationKey($configuration->getKey()); - - $configuration->page::registerNavigationItems(); + $previousPageConfigurationKey = Filament::getCurrentPageConfigurationKey(); + $previousResourceConfigurationKey = Filament::getCurrentResourceConfigurationKey(); + try { Filament::setCurrentPageConfigurationKey(null); - } - - foreach ($this->panel->getResources() as $resource) { - $resource::registerNavigationItems(); - } - - foreach ($this->panel->getResourceConfigurations() as $configuration) { - Filament::setCurrentResourceConfigurationKey($configuration->getKey()); - - $configuration->resource::registerNavigationItems(); - Filament::setCurrentResourceConfigurationKey(null); - } - $this->isNavigationMounted = true; + foreach ($this->panel->getPages() as $page) { + $page::registerNavigationItems(); + } + + foreach ($this->panel->getPageConfigurations() as $configuration) { + Filament::setCurrentPageConfigurationKey($configuration->getKey()); + + $configuration->page::registerNavigationItems(); + + Filament::setCurrentPageConfigurationKey(null); + } + + foreach ($this->panel->getResources() as $resource) { + $resource::registerNavigationItems(); + } + + foreach ($this->panel->getResourceConfigurations() as $configuration) { + Filament::setCurrentResourceConfigurationKey($configuration->getKey()); + + $configuration->resource::registerNavigationItems(); + + Filament::setCurrentResourceConfigurationKey(null); + } + + $this->isNavigationMounted = true; + } finally { + Filament::setCurrentPageConfigurationKey($previousPageConfigurationKey); + Filament::setCurrentResourceConfigurationKey($previousResourceConfigurationKey); + } } /** diff --git a/tests/src/Panels/Configuration/NavigationTest.php b/tests/src/Panels/Configuration/NavigationTest.php index e30b112aef..8135c1cd9c 100644 --- a/tests/src/Panels/Configuration/NavigationTest.php +++ b/tests/src/Panels/Configuration/NavigationTest.php @@ -28,6 +28,35 @@ describe('resource configuration navigation', function (): void { expect($urls)->toContain(ConfigurablePostResource::getUrl(configuration: 'archived')); }); + it('registers separate navigation items for each resource configuration when one is active', function (): void { + $defaultUrl = ConfigurablePostResource::getUrl(); + + ConfigurablePostResource::withConfiguration('featured', static function () use ($defaultUrl): void { + $items = collect(Filament::getNavigation()) + ->flatMap(static fn ($group) => $group->getItems()) + ->filter(static fn (NavigationItem $item) => str_contains($item->getUrl(), 'posts')) + ->values(); + + expect($items)->toHaveCount(3); + + $urls = $items->map(static fn (NavigationItem $item) => $item->getUrl())->all(); + + expect($urls)->toContain($defaultUrl); + expect($urls)->toContain(ConfigurablePostResource::getUrl(configuration: 'featured')); + expect($urls)->toContain(ConfigurablePostResource::getUrl(configuration: 'archived')); + + expect(ConfigurablePostResource::getConfiguration()?->getKey())->toBe('featured'); + }); + }); + + it('preserves the active resource configuration key when mounting navigation', function (): void { + Filament::forResourceConfiguration(ConfigurablePostResource::class, 'featured'); + + Filament::getNavigation(); + + expect(Filament::getCurrentResourceConfigurationKey())->toBe('featured'); + }); + it('shows correct navigation labels for resource configurations', function (): void { $navigation = Filament::getNavigation(); @@ -84,6 +113,35 @@ describe('page configuration navigation', function (): void { expect($urls)->toContain(ConfigurableSettings::withConfiguration('advanced', fn () => ConfigurableSettings::getUrl())); }); + it('registers separate navigation items for each page configuration when one is active', function (): void { + $defaultUrl = ConfigurableSettings::getUrl(); + + ConfigurableSettings::withConfiguration('general', static function () use ($defaultUrl): void { + $items = collect(Filament::getNavigation()) + ->flatMap(static fn ($group) => $group->getItems()) + ->filter(static fn (NavigationItem $item) => str_contains($item->getUrl(), 'settings')) + ->values(); + + expect($items)->toHaveCount(3); + + $urls = $items->map(static fn (NavigationItem $item) => $item->getUrl())->all(); + + expect($urls)->toContain($defaultUrl); + expect($urls)->toContain(ConfigurableSettings::getUrl(configuration: 'general')); + expect($urls)->toContain(ConfigurableSettings::getUrl(configuration: 'advanced')); + + expect(ConfigurableSettings::getConfiguration()?->getKey())->toBe('general'); + }); + }); + + it('preserves the active page configuration key when mounting navigation', function (): void { + Filament::forPageConfiguration(ConfigurableSettings::class, 'general'); + + Filament::getNavigation(); + + expect(Filament::getCurrentPageConfigurationKey())->toBe('general'); + }); + it('shows correct navigation labels for page configurations', function (): void { $navigation = Filament::getNavigation();