thedevdojo / voyager

Voyager - The Missing Laravel Admin
https://voyager.devdojo.com
MIT License
11.77k stars 2.67k forks source link

Allow Custom Admin sidebar menu for different user roles. #5305

Open pmavila opened 3 years ago

pmavila commented 3 years ago

Version information

Description of problem

This is a Feature Request. I would like to be able to create separate admin sidebar menu using the Menu Builder for different user roles. You can easily do this in the sidebar.blade.php however, links won't work and menu items are unclickable.

Proposed solution

Add an option in Menu.php model. See example below.

in sidebar.blade.php notice conditions in user role, identified by role id.

    <div id="adminmenu">
      @if ( Auth::user()->role_id == 1)
        <admin-menu :items="{{ menu('admin', '_json') }}"></admin-menu>
      @endif
      @if ( Auth::user()->role_id == 3 || Auth::user()->role_id == 5)
        <admin-menu :items="{{ menu('ppsadmin', '_json', ['sidebar' => true]) }}"></admin-menu>
      @endif
    </div>

in src/Models/Menu.php - I added this in the condition: $options->sidebar == true

    public static function display($menuName, $type = null, array $options = [])
    {
            // GET THE MENU - sort collection in blade
            ...
            if (($menuName == 'admin' || (isset($options->sidebar) && $options->sidebar == true)) && $type == '_json') {
                    $items = static::processItems($items);
            }
            ...
    }
fletch3555 commented 3 years ago

We strongly urge the use of permissions instead of roles as the means for changing that menu. You would add all items to the admin menu then assign permissions to roles. When a user with role 1 logs in, they'll only see their menu items. This approach has the added benefit of allowing users to have multiple roles and letting the menu items be combined. This may not be needed for your use-case, but it can certainly be useful for others.

howdu commented 3 years ago

Me too needed a custom admin menu for each role but you also need to overwrite the menu model display method due to hard coded references to 'admin' menu name: https://github.com/the-control-group/voyager/blob/1.4/src/Models/Menu.php#L76

I've replaced this logic

if ($menuName == 'admin' && $type == '_json') {
    $items = static::processItems($items);
}

if ($type == 'admin') {
    $type = 'voyager::menu.'.$type;
} else {
    if (is_null($type)) {
        $type = 'voyager::menu.default';
    } elseif ($type == 'bootstrap' && !view()->exists($type)) {
        $type = 'voyager::menu.bootstrap';
    }
}

if (!isset($options->locale)) {
    $options->locale = app()->getLocale();
}

if ($type === '_json') {
    return $items;
}

With this to suit my needs better:

if ($type == '_json') {
    return static::processItems($items);
}

if (view()->exists('voyager::menu.' . $type)) {
    $type = 'voyager::menu.'.$type;
} else {
    $type = 'voyager::menu.default';
}