diff --git a/config/menu.php b/config/menu.php index 4f0f434..b4cce0d 100755 --- a/config/menu.php +++ b/config/menu.php @@ -15,6 +15,20 @@ 'enabled' => env('MENU_MIDDLEWARE_ENABLED', true), + /* + |-------------------------------------------------------------------------- + | Menu Item Sorting + |-------------------------------------------------------------------------- + | + | This option controls the default sorting direction of menu items. + | Supported values are: + | + | - 'asc' : Sort menu items in ascending order + | - 'desc' : Sort menu items in descending order + | + */ + 'order_by' => 'asc', + /* |-------------------------------------------------------------------------- | Include Route List diff --git a/resources/lang/en/menus.php b/resources/lang/en/menus.php index 5250f12..d31e26f 100755 --- a/resources/lang/en/menus.php +++ b/resources/lang/en/menus.php @@ -25,6 +25,7 @@ 'icon' => 'Icon', 'class' => 'Class', 'attr' => 'Attributes', + 'position' => 'Position', 'privilege' => 'Privilege', 'visible' => 'Status', 'visible_1' => 'Visible', diff --git a/resources/views/menus/form.blade.php b/resources/views/menus/form.blade.php index a7f57ea..c8e73c2 100755 --- a/resources/views/menus/form.blade.php +++ b/resources/views/menus/form.blade.php @@ -69,6 +69,14 @@ class="hide"> +
+ {!! Form::label('position', __('menu-maker::menus.position'), ['class' => 'col-md-4 col-form-label text-md-right']) !!} +
+ {!! Form::number('position', null, ['class' => $errors->has('position') ? 'form-control is-invalid' : 'form-control', 'step' => '1']) !!} + {!! $errors->first('position', ':message') !!} +
+
+
{!! Form::label('privilege', __('menu-maker::menus.privilege'), ['class' => 'col-md-4 col-form-label text-md-right']) !!}
diff --git a/resources/views/menus/tree.blade.php b/resources/views/menus/tree.blade.php index d7067c8..5264374 100755 --- a/resources/views/menus/tree.blade.php +++ b/resources/views/menus/tree.blade.php @@ -1,21 +1,31 @@ ancestors->count() ? '
'; + + echo ''; echo ''; - echo $menu->ancestors->count() ? '' : ''; } }; - -$traverse($tree); +?> + diff --git a/resources/views/roles/menus.blade.php b/resources/views/roles/menus.blade.php index 85bfac8..78563da 100755 --- a/resources/views/roles/menus.blade.php +++ b/resources/views/roles/menus.blade.php @@ -47,6 +47,7 @@
+
{!! Form::submit(__('menu-maker::buttons.update'), ['class' => 'btn btn-primary']) !!} @@ -62,10 +63,38 @@
+ @endsection @push('scripts') + @endpush diff --git a/src/Http/Controllers/MenuController.php b/src/Http/Controllers/MenuController.php index 2ac89a9..50f6475 100755 --- a/src/Http/Controllers/MenuController.php +++ b/src/Http/Controllers/MenuController.php @@ -65,7 +65,7 @@ public function create() public function store(Request $request) { $data = $request->only([ - 'name', 'alias', 'link', 'icon', 'class', 'attr', 'privilege', 'visible' + 'name', 'alias', 'link', 'icon', 'class', 'attr', 'privilege', 'visible', 'position' ]); $data['routes'] = $request->route_list; $data['parent_id'] = Menu::findParent(); @@ -113,7 +113,7 @@ public function edit(Menu $menu) public function update(Request $request, Menu $menu) { $data = $request->only([ - 'name', 'alias', 'link', 'icon', 'class', 'attr', 'privilege', 'visible' + 'name', 'alias', 'link', 'icon', 'class', 'attr', 'privilege', 'visible', 'position' ]); $data['routes'] = $request->route_list; $data['parent_id'] = Menu::findParent(); @@ -155,13 +155,17 @@ public function destroy(Menu $menu) */ public function tree(Menu $node) { - $tree = Menu::descendantsOf($node) + $tree = Menu::whereDescendantOf($node) ->where('privilege', 'PROTECTED') + ->orderBy('position', config('menu.order_by', 'asc')) + ->get() ->toTree($node); $selected = []; - if(request()->has('g') && request('g') > 0) - { - $selected = Role::findOrFail(request('g'))->menus()->descendantsOf($node)->pluck('id')->toArray(); + if (request()->has('g') && request('g') > 0) { + $selected = \DB::table('pcmm_menu_role') + ->where('role_id', request('g')) + ->pluck('menu_id') + ->toArray(); } return view('menu-maker::menus.tree', compact('tree', 'selected')); } @@ -170,8 +174,10 @@ public function selected() { if (request()->ajax()) { $group_id = request('g'); - $parent_id = request('p'); - $selected = Role::findOrFail($group_id)->menus()->descendantsOf($parent_id)->pluck('id')->toArray(); + $selected = \DB::table('pcmm_menu_role') + ->where('role_id', $group_id) + ->pluck('menu_id') + ->toArray(); return response()->json(compact('selected'), 200); } return response()->json([ diff --git a/src/Http/Controllers/RoleController.php b/src/Http/Controllers/RoleController.php index 551f7f1..e0a5b69 100755 --- a/src/Http/Controllers/RoleController.php +++ b/src/Http/Controllers/RoleController.php @@ -132,6 +132,27 @@ public function assign(MenuRoleRequest $request) } $role->menus()->attach($request->menu_ids); + // Update menu order if provided + if ($request->has('menu_order')) { + $order = json_decode($request->menu_order, true); + if (is_array($order)) { + $updatePosition = function ($items, $parentId) use (&$updatePosition) { + foreach ($items as $index => $item) { + $menu = Menu::find($item['id']); + if ($menu) { + $menu->position = $index; + $menu->parent_id = $parentId; + $menu->save(); + } + if (!empty($item['children'])) { + $updatePosition($item['children'], $item['id']); + } + } + }; + $updatePosition($order, $request->section_id); + } + } + $role->users->each(function ($user) { RemoveUserMenuCache::dispatch($user); }); diff --git a/src/MenuMaker.php b/src/MenuMaker.php index 0cf1987..44ba7f7 100755 --- a/src/MenuMaker.php +++ b/src/MenuMaker.php @@ -69,7 +69,8 @@ private function getAdminMenuItems() { $this->section->load([ 'descendants' => function ($query) { - $query->visible(); + $query->visible() + ->orderBy('position', config('menu.order_by', 'asc')); } ]); @@ -97,7 +98,8 @@ private function getUserMenuItems() ->where('pcmm_roles.is_active', true) ->where($this->getTable() . '.id', $this->id); }); - }); + }) + ->orderBy('position', config('menu.order_by', 'asc')); } ]);