Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ The plugin automatically adds navigation items under "Resource Library":
- **Created by Me** - Items you created
- **Favorites** - Items you've marked as favorites

To hide those links for some users (for example roles that may enter the panel but should not see the library), use `navigationVisibleUsing()`:

```php
use Tapp\FilamentLibrary\FilamentLibraryPlugin;

public function panel(Panel $panel): Panel
{
return $panel
->plugins([
FilamentLibraryPlugin::make()
->navigationVisibleUsing(fn (): bool => auth()->user()?->can('view-any library-item') ?? false),
]);
}
```

When unset, navigation items remain visible (backward compatible). Direct library URLs are still authorized by your library item policies.

## Permissions System

The plugin features a sophisticated permissions system inspired by Google Drive.
Expand Down
49 changes: 47 additions & 2 deletions src/FilamentLibraryPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Tapp\FilamentLibrary;

use App\Models\User;
use Closure;
use Filament\Contracts\Plugin;
use Filament\Navigation\NavigationItem;
use Filament\Panel;
Expand All @@ -18,6 +19,11 @@ class FilamentLibraryPlugin implements Plugin

protected static bool $personalFolderListenerRegistered = false;

/**
* @var (Closure(): bool)|bool|null
*/
protected Closure | bool | null $navigationVisibleUsing = null;

/**
* @var array<string, class-string>
*/
Expand All @@ -32,6 +38,20 @@ public function getId(): string
return 'filament-library';
}

/**
* Control whether Resource Library navigation items are shown.
*
* Defaults to always visible when unset (backward compatible).
*
* @param (Closure(): bool)|bool $condition
*/
public function navigationVisibleUsing(Closure | bool $condition): static
{
$this->navigationVisibleUsing = $condition;

return $this;
}

/**
* Set a custom callback to determine if a user is a library admin.
*
Expand Down Expand Up @@ -147,7 +167,7 @@ public function register(Panel $panel): void
LibraryItemResource::class,
])),
)
->navigationItems([
->navigationItems($this->applyNavigationVisibility([
NavigationItem::make('Library')
->url(fn () => $libraryItemResourceClass::getUrl('index'))
->icon('heroicon-o-building-library')
Expand Down Expand Up @@ -179,7 +199,7 @@ public function register(Panel $panel): void
->group('Resource Library')
->sort(6)
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.favorites")),
]);
]));
}

public function boot(Panel $panel): void
Expand Down Expand Up @@ -225,6 +245,31 @@ protected static function sharedWithMeNavigationItem(string $panelId, string $li
];
}

public function isNavigationVisible(): bool
{
if ($this->navigationVisibleUsing === null) {
return true;
}

if (is_bool($this->navigationVisibleUsing)) {
return $this->navigationVisibleUsing;
}

return (bool) ($this->navigationVisibleUsing)();
}

/**
* @param list<NavigationItem> $items
* @return list<NavigationItem>
*/
protected function applyNavigationVisibility(array $items): array
{
return array_map(
fn (NavigationItem $item): NavigationItem => $item->visible(fn (): bool => $this->isNavigationVisible()),
$items,
);
}

public static function make(): static
{
return app(static::class);
Expand Down
28 changes: 28 additions & 0 deletions tests/Unit/FilamentLibraryPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,32 @@
expect(LibraryItemResource::getModel())->toBe(CustomLibraryItemStub::class);
});

test('navigation is visible by default', function (): void {
$plugin = FilamentLibraryPlugin::make();

expect($plugin->isNavigationVisible())->toBeTrue();
});

test('navigationVisibleUsing accepts a boolean', function (): void {
$plugin = FilamentLibraryPlugin::make()
->navigationVisibleUsing(false);

expect($plugin->isNavigationVisible())->toBeFalse();
});

test('navigationVisibleUsing accepts a closure', function (): void {
$visible = false;

$plugin = FilamentLibraryPlugin::make()
->navigationVisibleUsing(function () use (&$visible): bool {
return $visible;
});

expect($plugin->isNavigationVisible())->toBeFalse();

$visible = true;

expect($plugin->isNavigationVisible())->toBeTrue();
});

final class CustomLibraryItemStub extends LibraryItem {}