How to Hide Panel Icons Based on User Roles and Order Panels

I'm working on a Laravel Filament project with multiple panels, and I need to customize the visibility of these panels based on user roles. Specifically, I want to: Hide panel icons if a user’s role doesn’t have access to that panel. Maintain a specific order for the panel display.(admin, doctorants,.) Here’s my current setup: I'm using the bezhansalleh/filament-shield package for role management. Each user can have access to multiple panels, and I store panel access information in a panel_accesses table, which associates roles with panel IDs.
class User extends Authenticatable implements FilamentUser
{
use HasRoles; // from spatie/laravel-permission

public function canAccessPanel(Panel $panel): bool
{
if ($this->hasRole('super_admin')) {
return true;
}

foreach ($this->roles as $role) {
if (PanelAccess::where('role_id', $role->id)
->where('panel_id', $panel->getId())
->exists()) {
return true;
}
}

return false;
}
}
class User extends Authenticatable implements FilamentUser
{
use HasRoles; // from spatie/laravel-permission

public function canAccessPanel(Panel $panel): bool
{
if ($this->hasRole('super_admin')) {
return true;
}

foreach ($this->roles as $role) {
if (PanelAccess::where('role_id', $role->id)
->where('panel_id', $panel->getId())
->exists()) {
return true;
}
}

return false;
}
}
PanelSwitch::configureUsing(function (PanelSwitch $panelSwitch) {
$panelSwitch->modalHeading('Available Panels')
->iconSize(16)
->modalWidth('sm')
->labels([
'admin' => 'Home',
'service_commun' => "Service Commun",
'notifications' => "Notifications",
'laboratoires' => "Laboratoires",
'doctorants' => "Doctorants",
])
->icons([
'admin' => 'heroicon-o-home',
'service_commun' => 'heroicon-o-queue-list',
'notifications' => 'heroicon-o-bell-alert',
'laboratoires' => 'heroicon-o-beaker',
'doctorants' => 'heroicon-o-academic-cap',
], $asImage = false);
});
PanelSwitch::configureUsing(function (PanelSwitch $panelSwitch) {
$panelSwitch->modalHeading('Available Panels')
->iconSize(16)
->modalWidth('sm')
->labels([
'admin' => 'Home',
'service_commun' => "Service Commun",
'notifications' => "Notifications",
'laboratoires' => "Laboratoires",
'doctorants' => "Doctorants",
])
->icons([
'admin' => 'heroicon-o-home',
'service_commun' => 'heroicon-o-queue-list',
'notifications' => 'heroicon-o-bell-alert',
'laboratoires' => 'heroicon-o-beaker',
'doctorants' => 'heroicon-o-academic-cap',
], $asImage = false);
});
Could anyone please provide guidance or examples on how to achieve this? Any help would be greatly appreciated!
Solution:
Finally: ), The solution was to use the excludes() method, https://filamentphp.com/plugins/bezhansalleh-panel-switch#panel-exclusion AppServiceProvider: ...
Filament
Panel Switch by Bezhan Salleh - Filament
Easily switch between panels in Filament.
Jump to solution
7 Replies
awcodes
awcodes4mo ago
Maybe I’m just not getting it, but why would the icon for a model/resource ever be different? Like, an icon represents a thing, does the permissions change the context of the thing?
ROOT-LEE
ROOT-LEEOP4mo ago
Hi, The icon of a panel represents its resources. I want to hide entire panel (including the icon) if a user’s role doesn’t have access to that panel. The goal is to control visibility dynamically based on user roles.
awcodes
awcodes4mo ago
Sounds like you need specific panels. And middle ware to direct the user on login. But I still don’t understand the use case. Sorry.
ROOT-LEE
ROOT-LEEOP4mo ago
sorry , example: super-admin can have access to all panels (can switch all panel) establishment can have access to only 3 panels, but I do not want him to see the other panels that he does not have access to, knowing that when he clicks on a panel that he does not have authorization it displays 403 forbidden White image=> super admin Black image>. establishment
No description
No description
awcodes
awcodes4mo ago
Can probably wrap them in @can() directive and hide them based on the user role.
Dennis Koch
Dennis Koch4mo ago
I guess this is a question for #bezhansalleh-panel-switch
Solution
ROOT-LEE
ROOT-LEE4mo ago
Finally: ), The solution was to use the excludes() method, https://filamentphp.com/plugins/bezhansalleh-panel-switch#panel-exclusion AppServiceProvider:
use BezhanSalleh\PanelSwitch\PanelSwitch;
....
use App\Models\PanelAccess;
use Filament\Facades\Filament;

PanelSwitch::configureUsing(function (PanelSwitch $panelSwitch) {
$panelSwitch->excludes(function () {
$user = auth()->user();

if ($user && $user->isAdmin()) {
return [];
}

$panels = Filament::getPanels();
$excludedPanels = [];

foreach ($panels as $panel) {
if (!$user->hasPanelAccess($panel->getId())) {
$excludedPanels[] = $panel->getId();
}
}
return $excludedPanels;
});
//...
});

use BezhanSalleh\PanelSwitch\PanelSwitch;
....
use App\Models\PanelAccess;
use Filament\Facades\Filament;

PanelSwitch::configureUsing(function (PanelSwitch $panelSwitch) {
$panelSwitch->excludes(function () {
$user = auth()->user();

if ($user && $user->isAdmin()) {
return [];
}

$panels = Filament::getPanels();
$excludedPanels = [];

foreach ($panels as $panel) {
if (!$user->hasPanelAccess($panel->getId())) {
$excludedPanels[] = $panel->getId();
}
}
return $excludedPanels;
});
//...
});

User:
public function hasPanelAccess($panelId)
{
if ($this->hasRole('super_admin')) {
return true;
}

foreach ($this->roles as $role) {
if (PanelAccess::where('role_id', $role->id)
->whereJsonContains('panel_id', $panelId)
->exists()) {
return true;
}
}

return false;
}

public function hasPanelAccess($panelId)
{
if ($this->hasRole('super_admin')) {
return true;
}

foreach ($this->roles as $role) {
if (PanelAccess::where('role_id', $role->id)
->whereJsonContains('panel_id', $panelId)
->exists()) {
return true;
}
}

return false;
}

PanelAccess
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Spatie\Permission\Models\Role;

class PanelAccess extends Model
{
protected $fillable = ['role_id', 'panel_id'];
protected $casts = [
'panel_id' => 'array',
];
public function role()
{
return $this->belongsTo(Role::class);
}

}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Spatie\Permission\Models\Role;

class PanelAccess extends Model
{
protected $fillable = ['role_id', 'panel_id'];
protected $casts = [
'panel_id' => 'array',
];
public function role()
{
return $this->belongsTo(Role::class);
}

}
Thank you! 🙏 :fi:
Filament
Panel Switch by Bezhan Salleh - Filament
Easily switch between panels in Filament.
Want results from more Discord servers?
Add your server