├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── composer.json
├── logs
└── v3.3.5.txt
└── src
├── Commands
└── PackageSetup.php
├── Controllers
├── Admin
│ ├── AdminController.php
│ ├── MenusController.php
│ ├── PagesController.php
│ ├── PermissionsController.php
│ ├── RolesController.php
│ ├── Traits
│ │ ├── MenuOps.php
│ │ ├── PageOps.php
│ │ ├── Paginate.php
│ │ ├── RolePermOps.php
│ │ └── UserPageOps.php
│ └── UsersController.php
├── BaseController.php
└── DummyController.php
├── Facade
└── SimpleMenu.php
├── Middleware
├── PermissionMiddleware.php
└── RoleMiddleware.php
├── Models
├── Menu.php
├── Page.php
└── Traits
│ └── SMUsers.php
├── Observers
├── BaseObserver.php
├── MenuObserver.php
├── PageObserver.php
└── UserObserver.php
├── SimpleMenu.php
├── SimpleMenuServiceProvider.php
├── Traits
├── Menus.php
├── Navigation.php
├── Ops.php
├── PackageRoutes.php
└── Routes.php
├── config
└── simpleMenu.php
├── database
├── migrations
│ ├── 2014_10_12_000000_create_users_table.php
│ ├── 2017_02_28_202951_create_pages_table.php
│ ├── 2017_03_01_232714_create_menus_table.php
│ └── 2017_03_01_232836_create_menu_page_table.php
└── seeds
│ ├── DatabaseSeeder.example
│ ├── MenuPagesTableSeeder.php
│ ├── MenusTableSeeder.php
│ ├── PagesTableSeeder.php
│ └── RolePermSeeder.php
└── resources
├── assets
├── js
│ ├── index.vue
│ ├── manager.js
│ ├── menu.vue
│ ├── menu_child.vue
│ ├── mixins
│ │ ├── menu.js
│ │ └── search.js
│ └── page.vue
└── sass
│ ├── _checkbox.scss
│ └── style.scss
├── lang
└── en
│ └── messages.php
├── pagination
└── bulma.blade.php
└── views
├── admin
├── admin.blade.php
├── editors.blade.php
├── menus
│ ├── create.blade.php
│ ├── edit.blade.php
│ └── index.blade.php
├── pages
│ ├── create.blade.php
│ ├── edit.blade.php
│ └── index.blade.php
├── permissions
│ ├── create.blade.php
│ ├── edit.blade.php
│ └── index.blade.php
├── roles
│ ├── create.blade.php
│ ├── edit.blade.php
│ └── index.blade.php
├── shared.blade.php
└── users
│ ├── create.blade.php
│ ├── edit.blade.php
│ └── index.blade.php
├── breadCrumb.blade.php
├── langSwitcher.blade.php
├── menu
├── example.blade.php
└── partials
│ ├── nested.blade.php
│ └── r_params.blade.php
└── template-example.blade.php
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: ctf0
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .history
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Muah
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | SimpleMenu
3 |
4 |
5 |
6 |
7 | Create menus & pages that support (multiLocale "title, url, body, ...", nesting, template, static & dynamic data, roles & permissions).
8 |
9 | - package requires Laravel v5.5+
10 | - package rely heavily on caching so make sure to install one of the tag enabled drivers [Memcached / Redis](https://laravel.com/docs/5.5/cache)
11 |
12 |
13 |
14 | ## Installation
15 |
16 | - `composer require ctf0/simple-menu`
17 |
18 | - after installation, run `php artisan sm:setup` to add
19 | + package routes to `routes/web.php`
20 | + package assets compiling to `webpack.mix.js`
21 |
22 | - publish the packages assets with `php artisan vendor:publish`
23 | - [simpleMenu](https://github.com/ctf0/simple-menu/wiki/Publish)
24 | - [laravel-permission](https://github.com/spatie/laravel-permission#laravel)
25 | - [laravel-translatable](https://github.com/spatie/laravel-translatable#installation)
26 | - [laravel-localization](https://github.com/mcamara/laravel-localization#config)
27 |
28 | - install JS dependencies
29 |
30 | ```bash
31 | yarn add vue axios vue-tippy@v2 vuedraggable vue-notif vue-multi-ref vue-awesome@v2 list.js
32 | ```
33 |
34 | - add this one liner to your main js file and run `npm run watch` to compile your `js/css` files.
35 | + if you are having issues [Check](https://ctf0.wordpress.com/2017/09/12/laravel-mix-es6/).
36 |
37 | ```js
38 | // app.js
39 |
40 | window.Vue = require('vue')
41 |
42 | require('../vendor/SimpleMenu/js/manager')
43 |
44 | new Vue({
45 | el: '#app'
46 | })
47 | ```
48 |
49 |
50 |
51 | ## Config
52 |
53 | **config/simpleMenu.php**
54 |
55 | ```php
56 | return [
57 | /*
58 | * the menu list classes to be used for "render()"
59 | */
60 | 'listClasses' => [
61 | 'ul' => 'menu-list',
62 | 'li' => 'list-item',
63 | 'a' => 'is-active',
64 | ],
65 |
66 | /*
67 | * the path where we will save the routes list
68 | */
69 | 'routeListPath' => storage_path('logs/simpleMenu.php'),
70 |
71 | /*
72 | * where to redirect when a route is available in one locale "en" but not in another "fr" ?
73 | */
74 | 'unFoundLocalizedRoute' => 'root',
75 |
76 | /*
77 | * package models
78 | */
79 | 'models'=> [
80 | 'user' => App\User::class,
81 | 'page' => \ctf0\SimpleMenu\Models\Page::class,
82 | 'menu' => \ctf0\SimpleMenu\Models\Menu::class,
83 | ],
84 |
85 | /*
86 | * when adding a page which is a nest of a nother to a menu, ex.
87 | *
88 | * root
89 | * | child 1
90 | * | child 2 "add this along with its childrens to another menu"
91 | * | child 3
92 | *
93 | * do you want to clear its parent and make it a root ?
94 | */
95 | 'clearPartialyNestedParent' => true,
96 |
97 | /*
98 | * when removing a root page from a menu, ex.
99 | *
100 | * root "remove"
101 | * | child 1
102 | * | child 2
103 | * | child 3
104 | *
105 | * do you want clear all of its 'Descendants' ?
106 | */
107 | 'clearRootDescendants' => false,
108 |
109 | /*
110 | * when removing a nest from a list, ex.
111 | *
112 | * root
113 | * | child 1
114 | * | child 2 "remove"
115 | * | child 3
116 | *
117 | * do you want to reset its hierarchy ?
118 | */
119 | 'clearNestDescendants'=> false,
120 |
121 | /*
122 | * when deleting a page "from the db", ex.
123 | *
124 | * page "delete/destroy"
125 | * | nested child 1
126 | * | nested child 2
127 | * | nested child 3
128 | *
129 | * do you also want to delete all of its children ?
130 | */
131 | 'deletePageAndNests' => false,
132 |
133 | /*
134 | * package routes url & route name prefix
135 | */
136 | 'crud_prefix' => 'admin',
137 |
138 | /*
139 | * all the package controllers
140 | *
141 | * if you need to change anything, just create new controller
142 | * and extend from the below original
143 | * ex. "class ExampleController extends PagesController"
144 | */
145 | 'controllers'=> [
146 | 'permissions' => '\ctf0\SimpleMenu\Controllers\Admin\PermissionsController',
147 | 'admin' => '\ctf0\SimpleMenu\Controllers\Admin\AdminController@index',
148 | 'users' => '\ctf0\SimpleMenu\Controllers\Admin\UsersController',
149 | 'pages' => '\ctf0\SimpleMenu\Controllers\Admin\PagesController',
150 | 'roles' => '\ctf0\SimpleMenu\Controllers\Admin\RolesController',
151 | 'menus' => '\ctf0\SimpleMenu\Controllers\Admin\MenusController',
152 | ],
153 | ];
154 | ```
155 |
156 |
157 |
158 | ## Usage
159 |
160 | > [Demo](https://github.com/ctf0/demos/tree/simple-menu)
161 | > [Usage](https://github.com/ctf0/simple-menu/wiki/Usage)
162 | > [Views](https://github.com/ctf0/SimpleMenu/wiki/Crud-Views)
163 |
164 | - add `SMUsers` trait to your **User Model**
165 |
166 | ```php
167 | use ctf0\SimpleMenu\Models\Traits\SMUsers;
168 |
169 | // ...
170 |
171 | class User extends Authenticatable
172 | {
173 | use Notifiable, SMUsers;
174 | }
175 | ```
176 |
177 | - visit `localhost:8000/admin`
178 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ctf0/simple-menu",
3 | "description": "create a menu that support page (multiLocale 'title/ url/ prefix', nesting, template, static/dynamic, roles & permissions).",
4 | "homepage": "https://github.com/ctf0/SimpleMenu",
5 | "license": "MIT",
6 | "keywords": [
7 | "ctf0",
8 | "SimpleMenu",
9 | "menu",
10 | "manager",
11 | "laravel",
12 | "gui",
13 | "multi-locale"
14 | ],
15 | "authors": [
16 | {
17 | "name": "Muah",
18 | "email": "muah003@gmail.com"
19 | }
20 | ],
21 | "require": {
22 | "illuminate/support": ">=5.4 <9.0",
23 | "gazsp/baum": "*",
24 | "mcamara/laravel-localization": "*",
25 | "spatie/laravel-permission": "*",
26 | "spatie/laravel-translatable": "*",
27 | "codezero/laravel-unique-translation": "*",
28 | "ctf0/package-changelog": "*",
29 | "laravelcollective/html": "*"
30 | },
31 | "autoload": {
32 | "psr-4": {
33 | "ctf0\\SimpleMenu\\": "src"
34 | }
35 | },
36 | "extra": {
37 | "laravel": {
38 | "providers": [
39 | "ctf0\\SimpleMenu\\SimpleMenuServiceProvider"
40 | ],
41 | "aliases": {
42 | "SimpleMenu": "ctf0\\SimpleMenu\\Facade\\SimpleMenu"
43 | }
44 | },
45 | "changeLog": "logs"
46 | },
47 | "config": {
48 | "sort-packages": true
49 | },
50 | "scripts": {
51 | "post-package-install": [
52 | "@php artisan vendor:publish"
53 | ]
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/logs/v3.3.5.txt:
--------------------------------------------------------------------------------
1 | - use role & perm models from the config instead of spatie
2 | - fix anchor class in render() not using passed className
3 | - cleanup
4 | - fix not working with swoole
--------------------------------------------------------------------------------
/src/Commands/PackageSetup.php:
--------------------------------------------------------------------------------
1 | file = app('files');
20 |
21 | parent::__construct();
22 | }
23 |
24 | /**
25 | * Execute the console command.
26 | *
27 | * @return mixed
28 | */
29 | public function handle()
30 | {
31 | // routes
32 | $route_file = base_path('routes/web.php');
33 | $search = 'SimpleMenu';
34 |
35 | if ($this->checkExist($route_file, $search)) {
36 | $data = "\n// SimpleMenu\nSimpleMenu::menuRoutes();";
37 |
38 | $this->file->append($route_file, $data);
39 | }
40 |
41 | // mix
42 | $mix_file = base_path('webpack.mix.js');
43 | $search = 'SimpleMenu';
44 |
45 | if ($this->checkExist($mix_file, $search)) {
46 | $data = "\n// SimpleMenu\nmix.sass('resources/assets/vendor/SimpleMenu/sass/style.scss', 'public/assets/vendor/SimpleMenu/style.css')";
47 |
48 | $this->file->append($mix_file, $data);
49 | }
50 |
51 | $this->info('All Done');
52 | }
53 |
54 | /**
55 | * [checkExist description].
56 | *
57 | * @param [type] $file [description]
58 | * @param [type] $search [description]
59 | *
60 | * @return [type] [description]
61 | */
62 | protected function checkExist($file, $search)
63 | {
64 | return $this->file->exists($file) && !Str::contains($this->file->get($file), $search);
65 | }
66 | }
--------------------------------------------------------------------------------
/src/Controllers/Admin/AdminController.php:
--------------------------------------------------------------------------------
1 | adminPath}.admin")->with([
17 | 'title' => 'DashBoard',
18 | 'desc' => 'Admin DashBoard',
19 | ]);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/MenusController.php:
--------------------------------------------------------------------------------
1 | cache->tags('sm')->get('menus');
21 |
22 | return view("{$this->adminPath}.menus.index", compact('menus'));
23 | }
24 |
25 | /**
26 | * Show the form for creating new Menu.
27 | *
28 | * @return \Illuminate\Http\Response
29 | */
30 | public function create()
31 | {
32 | return view("{$this->adminPath}.menus.create");
33 | }
34 |
35 | /**
36 | * Store a newly created Menu in storage.
37 | *
38 | * @param \App\Http\Requests\StoreMenusRequest $request
39 | *
40 | * @return \Illuminate\Http\Response
41 | */
42 | public function store(Request $request)
43 | {
44 | $this->validate($request, [
45 | 'name' => 'required|unique:menus,name',
46 | ]);
47 |
48 | $menu = $this->menuModel->create($request->all());
49 |
50 | return redirect()
51 | ->route($this->crud_prefix . '.menus.index')
52 | ->with('status', trans('SimpleMenu::messages.model_created'));
53 | }
54 |
55 | /**
56 | * Show the form for editing Menu.
57 | *
58 | * @param int $id
59 | *
60 | * @return \Illuminate\Http\Response
61 | */
62 | public function edit($id)
63 | {
64 | $menu = $this->cache->tags('sm')->get('menus')->find($id) ?: abort(404);
65 |
66 | return view("{$this->adminPath}.menus.edit", compact('menu'));
67 | }
68 |
69 | /**
70 | * Update Menu in storage.
71 | *
72 | * @param \App\Http\Requests\UpdateMenusRequest $request
73 | * @param int $id
74 | *
75 | * @return \Illuminate\Http\Response
76 | */
77 | public function update($id, Request $request)
78 | {
79 | $this->validate($request, [
80 | 'name' => 'required|unique:menus,name,' . $id,
81 | ]);
82 |
83 | $menu = $this->menuModel->findOrFail($id);
84 |
85 | // clear prev records
86 | $menu->pages()->detach();
87 |
88 | foreach (json_decode($request->saveList) as $item) {
89 | if (config('simpleMenu.clearPartialyNestedParent')) {
90 | $this->clearSelfAndNests($item->id);
91 | } else {
92 | $this->clearNests($item->id);
93 | }
94 |
95 | // save page hierarchy
96 | if ($item->children) {
97 | $this->saveListToDb($item->children);
98 | }
99 |
100 | // update the menu root list
101 | $menu->pages()->attach($item->id, ['order'=>$item->order]);
102 | }
103 |
104 | // update and trigger events
105 | $menu->update($request->except('saveList'));
106 | $menu->touch();
107 |
108 | return back()->with('status', trans('SimpleMenu::messages.model_updated'));
109 | }
110 |
111 | /**
112 | * Remove Menu from storage.
113 | *
114 | * @param int $id
115 | *
116 | * @return \Illuminate\Http\Response
117 | */
118 | public function destroy($id, Request $request)
119 | {
120 | $menu = $this->menuModel->findOrFail($id);
121 | $menu->pages()->detach();
122 | $menu->delete();
123 |
124 | if ($request->expectsJson()) {
125 | return response()->json(['done'=>true]);
126 | }
127 |
128 | return redirect()
129 | ->route($this->crud_prefix . '.menus.index')
130 | ->with('status', trans('SimpleMenu::messages.model_deleted'));
131 | }
132 |
133 | public function destroyMulti(Request $request)
134 | {
135 | $ids = explode(',', $request->ids);
136 |
137 | foreach ($ids as $one) {
138 | $menu = $this->menuModel->findOrFail($one);
139 | $menu->pages()->detach();
140 | $menu->delete();
141 | }
142 |
143 | return redirect()
144 | ->route($this->crud_prefix . '.menus.index')
145 | ->with('status', trans('SimpleMenu::messages.models_deleted'));
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/PagesController.php:
--------------------------------------------------------------------------------
1 | cache->tags('sm')->get('pages');
23 |
24 | return view("{$this->adminPath}.pages.index", compact('pages'));
25 | }
26 |
27 | /**
28 | * Show the form for creating new Page.
29 | *
30 | * @return \Illuminate\Http\Response
31 | */
32 | public function create()
33 | {
34 | $locales = SimpleMenu::AppLocales();
35 | $roles = $this->roleModel->pluck('name', 'name');
36 | $permissions = $this->permissionModel->pluck('name', 'name');
37 | $menus = $this->cache->tags('sm')->get('menus')->pluck('name', 'id');
38 | $templates = array_unique($this->cache->tags('sm')->get('pages')->pluck('template')->filter()->all());
39 |
40 | return view("{$this->adminPath}.pages.create", compact('locales', 'roles', 'permissions', 'menus', 'templates'));
41 | }
42 |
43 | /**
44 | * Store a newly created Page in storage.
45 | *
46 | * @param \App\Http\Requests\StorePagesRequest $request
47 | *
48 | * @return \Illuminate\Http\Response
49 | */
50 | public function store(Request $request)
51 | {
52 | $this->sT_uP_Validaiton($request);
53 |
54 | $img = $this->getImage($request->cover);
55 | $page = $this->pageModel->create(array_merge(['cover'=>$img], $this->cleanEmptyTranslations($request)));
56 | $roles = $request->roles ?: [];
57 | $permissions = $request->permissions ?: [];
58 | $menus = $request->menus ?: [];
59 |
60 | $page->assignRole($roles);
61 | $page->givePermissionTo($permissions);
62 | $page->assignToMenus($menus);
63 |
64 | return redirect()
65 | ->route($this->crud_prefix . '.pages.index')
66 | ->with('status', trans('SimpleMenu::messages.model_created'));
67 | }
68 |
69 | /**
70 | * Show the form for editing Page.
71 | *
72 | * @param int $id
73 | *
74 | * @return \Illuminate\Http\Response
75 | */
76 | public function edit($id)
77 | {
78 | $locales = SimpleMenu::AppLocales();
79 | $roles = $this->roleModel->pluck('name', 'name');
80 | $permissions = $this->permissionModel->pluck('name', 'name');
81 | $page = $this->pageModel->findOrFail($id);
82 | $menus = $this->cache->tags('sm')->get('menus')->pluck('name', 'id');
83 | $templates = array_unique($this->cache->tags('sm')->get('pages')->pluck('template')->filter()->all());
84 |
85 | $controllerFile = $page->action ? $this->actionFileContent($page->action, 'get') : null;
86 |
87 | return view("{$this->adminPath}.pages.edit", compact('locales', 'roles', 'permissions', 'page', 'menus', 'templates', 'controllerFile'));
88 | }
89 |
90 | /**
91 | * Update Page in storage.
92 | *
93 | * @param \App\Http\Requests\UpdatePagesRequest $request
94 | * @param int $id
95 | *
96 | * @return \Illuminate\Http\Response
97 | */
98 | public function update($id, Request $request)
99 | {
100 | $this->sT_uP_Validaiton($request, $id);
101 |
102 | $img = $this->getImage($request->cover);
103 | $page = $this->getItem($id);
104 | $roles = $request->roles;
105 | $permissions = $request->permissions;
106 | $menus = $request->menus ?: [];
107 |
108 | $page->update(array_merge(['cover'=>$img], $this->cleanEmptyTranslations($request)));
109 |
110 | if (!$this->checkBeforeAssign($page->roles, $roles)) {
111 | $page->syncRoles($roles ?: []);
112 | }
113 |
114 | if (!$this->checkBeforeAssign($page->permissions, $permissions)) {
115 | $page->syncPermissions($permissions ?: []);
116 | }
117 |
118 | $page->syncMenus($menus);
119 |
120 | if (!is_null($request->controllerFile)) {
121 | $this->actionFileContent($request->action, 'update', $request->controllerFile);
122 | }
123 |
124 | $page->touch();
125 |
126 | return back()->with('status', trans('SimpleMenu::messages.model_updated'));
127 | }
128 |
129 | /**
130 | * Remove Page.
131 | *
132 | * @param int $id
133 | *
134 | * @return \Illuminate\Http\Response
135 | */
136 | public function destroy($id, Request $request)
137 | {
138 | $this->pageModel->destroy($id);
139 |
140 | if ($request->expectsJson()) {
141 | return response()->json(['done'=>true]);
142 | }
143 |
144 | return redirect()
145 | ->route($this->crud_prefix . '.pages.index')
146 | ->with('status', trans('SimpleMenu::messages.model_deleted'));
147 | }
148 |
149 | public function destroyMulti(Request $request)
150 | {
151 | $ids = explode(',', $request->ids);
152 |
153 | $this->pageModel->destroy($ids);
154 |
155 | return redirect()
156 | ->route($this->crud_prefix . '.pages.index')
157 | ->with('status', trans('SimpleMenu::messages.models_deleted'));
158 | }
159 |
160 | /**
161 | * restore model.
162 | *
163 | * @param [type] $id [description]
164 | *
165 | * @return [type] [description]
166 | */
167 | public function restore($id)
168 | {
169 | $this->getItem($id)->restore();
170 |
171 | return redirect()
172 | ->route($this->crud_prefix . '.pages.index')
173 | ->with('status', trans('SimpleMenu::messages.model_updated'));
174 | }
175 |
176 | /**
177 | * Remove Page Permanently.
178 | *
179 | * @param [type] $id [description]
180 | *
181 | * @return [type] [description]
182 | */
183 | public function forceDelete($id)
184 | {
185 | $this->getItem($id)->forceDelete();
186 |
187 | return redirect()
188 | ->route($this->crud_prefix . '.pages.index')
189 | ->with('status', trans('SimpleMenu::messages.model_deleted_perm'));
190 | }
191 |
192 | /**
193 | * helper.
194 | *
195 | * @param [type] $id [description]
196 | *
197 | * @return [type] [description]
198 | */
199 | protected function getItem($id)
200 | {
201 | return $this->pageModel->withTrashed()->findOrFail($id);
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/PermissionsController.php:
--------------------------------------------------------------------------------
1 | permissionModel->get();
21 |
22 | return view("{$this->adminPath}.permissions.index", compact('permissions'));
23 | }
24 |
25 | /**
26 | * Show the form for creating new Permission.
27 | *
28 | * @return \Illuminate\Http\Response
29 | */
30 | public function create()
31 | {
32 | return view("{$this->adminPath}.permissions.create");
33 | }
34 |
35 | /**
36 | * Store a newly created Permission in storage.
37 | *
38 | * @param \App\Http\Requests\StorePermissionsRequest $request
39 | *
40 | * @return \Illuminate\Http\Response
41 | */
42 | public function store(Request $request)
43 | {
44 | $this->validate($request, [
45 | 'name' => 'required|unique:permissions,name',
46 | ]);
47 |
48 | $this->permissionModel->create($request->all());
49 |
50 | return redirect()
51 | ->route($this->crud_prefix . '.permissions.index')
52 | ->with('status', trans('SimpleMenu::messages.model_created'));
53 | }
54 |
55 | /**
56 | * Show the form for editing Permission.
57 | *
58 | * @param int $id
59 | *
60 | * @return \Illuminate\Http\Response
61 | */
62 | public function edit($id)
63 | {
64 | $permission = $this->permissionModel->findOrFail($id);
65 |
66 | return view("{$this->adminPath}.permissions.edit", compact('permission'));
67 | }
68 |
69 | /**
70 | * Update Permission in storage.
71 | *
72 | * @param \App\Http\Requests\UpdatePermissionsRequest $request
73 | * @param int $id
74 | *
75 | * @return \Illuminate\Http\Response
76 | */
77 | public function update($id, Request $request)
78 | {
79 | $this->validate($request, [
80 | 'name' => 'required|unique:permissions,name,' . $id,
81 | ]);
82 |
83 | $this->permissionModel->findOrFail($id)->update($request->all());
84 | $this->permissionModel->touch();
85 |
86 | $this->clearCache();
87 |
88 | return back()->with('status', trans('SimpleMenu::messages.model_updated'));
89 | }
90 |
91 | /**
92 | * Remove Permission from storage.
93 | *
94 | * @param int $id
95 | *
96 | * @return \Illuminate\Http\Response
97 | */
98 | public function destroy($id, Request $request)
99 | {
100 | $this->permissionModel->destroy($id);
101 |
102 | $this->clearCache();
103 |
104 | if ($request->expectsJson()) {
105 | return response()->json(['done'=>true]);
106 | }
107 |
108 | return redirect()
109 | ->route($this->crud_prefix . '.permissions.index')
110 | ->with('status', trans('SimpleMenu::messages.model_deleted'));
111 | }
112 |
113 | public function destroyMulti(Request $request)
114 | {
115 | $ids = explode(',', $request->ids);
116 |
117 | $this->permissionModel->destroy($ids);
118 |
119 | return redirect()
120 | ->route($this->crud_prefix . '.permissions.index')
121 | ->with('status', trans('SimpleMenu::messages.models_deleted'));
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/RolesController.php:
--------------------------------------------------------------------------------
1 | roleModel->with('permissions')->get();
21 |
22 | return view("{$this->adminPath}.roles.index", compact('roles'));
23 | }
24 |
25 | /**
26 | * Show the form for creating new Role.
27 | *
28 | * @return \Illuminate\Http\Response
29 | */
30 | public function create()
31 | {
32 | $permissions = $this->permissionModel->pluck('name', 'name');
33 |
34 | return view("{$this->adminPath}.roles.create", compact('permissions'));
35 | }
36 |
37 | /**
38 | * Store a newly created Role in storage.
39 | *
40 | * @param \App\Http\Requests\StoreRolesRequest $request
41 | *
42 | * @return \Illuminate\Http\Response
43 | */
44 | public function store(Request $request)
45 | {
46 | $this->validate($request, [
47 | 'name' => 'required|unique:roles,name',
48 | ]);
49 |
50 | $role = $this->roleModel->create($request->except('permissions'));
51 | $permissions = $request->permissions ?: [];
52 |
53 | $role->givePermissionTo($permissions);
54 |
55 | return redirect()
56 | ->route($this->crud_prefix . '.roles.index')
57 | ->with('status', trans('SimpleMenu::messages.model_created'));
58 | }
59 |
60 | /**
61 | * Show the form for editing Role.
62 | *
63 | * @param int $id
64 | *
65 | * @return \Illuminate\Http\Response
66 | */
67 | public function edit($id)
68 | {
69 | $role = $this->roleModel->findOrFail($id);
70 | $permissions = $this->permissionModel->pluck('name', 'name');
71 |
72 | return view("{$this->adminPath}.roles.edit", compact('role', 'permissions'));
73 | }
74 |
75 | /**
76 | * Update Role in storage.
77 | *
78 | * @param \App\Http\Requests\UpdateRolesRequest $request
79 | * @param int $id
80 | *
81 | * @return \Illuminate\Http\Response
82 | */
83 | public function update($id, Request $request)
84 | {
85 | $this->validate($request, [
86 | 'name' => 'required|unique:roles,name,' . $id,
87 | ]);
88 |
89 | $role = $this->roleModel->findOrFail($id);
90 | $permissions = $request->permissions ?: [];
91 |
92 | $role->update($request->except('permissions'));
93 | $role->syncPermissions($permissions);
94 | $role->touch();
95 |
96 | $this->clearCache();
97 |
98 | return back()->with('status', trans('SimpleMenu::messages.model_updated'));
99 | }
100 |
101 | /**
102 | * Remove Role from storage.
103 | *
104 | * @param int $id
105 | *
106 | * @return \Illuminate\Http\Response
107 | */
108 | public function destroy($id, Request $request)
109 | {
110 | $this->roleModel->destroy($id);
111 |
112 | $this->clearCache();
113 |
114 | if ($request->expectsJson()) {
115 | return response()->json(['done'=>true]);
116 | }
117 |
118 | return redirect()
119 | ->route($this->crud_prefix . '.roles.index')
120 | ->with('status', trans('SimpleMenu::messages.model_deleted'));
121 | }
122 |
123 | public function destroyMulti(Request $request)
124 | {
125 | $ids = explode(',', $request->ids);
126 |
127 | $this->roleModel->destroy($ids);
128 |
129 | return redirect()
130 | ->route($this->crud_prefix . '.roles.index')
131 | ->with('status', trans('SimpleMenu::messages.models_deleted'));
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/Traits/MenuOps.php:
--------------------------------------------------------------------------------
1 | cache->tags('sm')->get('menus')->find($id) ?: abort(404);
19 | $pages = collect($menu->pages)
20 | ->sortBy('pivot_order')
21 | ->each(function ($item) {
22 | $item['from'] = 'pages';
23 | })->values()->all();
24 |
25 | $allPages = $this->cache->tags('sm')->get('pages')->diff($pages)->each(function ($item) {
26 | $item['from'] = 'allPages';
27 | });
28 |
29 | return response()->json(compact('pages', 'allPages'));
30 | }
31 |
32 | /**
33 | * remove page from menu with ajax.
34 | *
35 | * @param [type] $id [description]
36 | * @param Request $request [description]
37 | *
38 | * @return [type] [description]
39 | */
40 | public function removePage($id, Request $request)
41 | {
42 | // remove page from menu
43 | $menu = $this->menuModel->findOrFail($id);
44 | $menu->pages()->detach($request->page_id);
45 | $menu->touch();
46 |
47 | // clear page nesting
48 | if (config('simpleMenu.clearRootDescendants')) {
49 | $this->clearSelfAndNests($request->page_id);
50 | }
51 |
52 | return response()->json(['done'=>true]);
53 | }
54 |
55 | /**
56 | * remove nested child with ajax.
57 | *
58 | * @param Request $request [description]
59 | *
60 | * @return [type] [description]
61 | */
62 | public function removeChild(Request $request)
63 | {
64 | if (config('simpleMenu.clearNestDescendants')) {
65 | $this->clearSelfAndNests($request->child_id);
66 | } else {
67 | $page = $this->findPage($request->child_id);
68 | $page->makeRoot();
69 | $page->touch();
70 | }
71 |
72 | return response()->json(['done'=>true]);
73 | }
74 |
75 | /**
76 | * save page hierarchy to db.
77 | *
78 | * @param [type] $list [description]
79 | *
80 | * @return [type] [description]
81 | */
82 | protected function saveListToDb($list)
83 | {
84 | foreach ($list as $one) {
85 | $child = $this->findPage($one->id);
86 | $parent = $this->findPage($one->parent_id);
87 |
88 | if ($child == $parent) {
89 | return;
90 | }
91 |
92 | $child->makeChildOf($parent);
93 |
94 | $child->touch();
95 | $parent->touch();
96 |
97 | if ($one->children) {
98 | $this->saveListToDb($one->children);
99 | }
100 | }
101 | }
102 |
103 | /**
104 | * helpers.
105 | *
106 | * @param mixed $id
107 | *
108 | * @return [type] [description]
109 | */
110 | protected function clearNests($id)
111 | {
112 | return $this->findPage($id)->destroyDescendants();
113 | }
114 |
115 | protected function clearSelfAndNests($id)
116 | {
117 | $page = $this->findPage($id);
118 |
119 | return $page->clearSelfAndDescendants();
120 | }
121 |
122 | protected function findPage($id)
123 | {
124 | return $this->pageModel->findOrFail($id);
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/Traits/PageOps.php:
--------------------------------------------------------------------------------
1 | trans('SimpleMenu::messages.regex', ['attribute' => trans('SimpleMenu::messages.action')]),
22 | 'template.required_without' => trans('validation.required_without', [
23 | 'attribute' => trans('SimpleMenu::messages.template'),
24 | 'values' => trans('SimpleMenu::messages.action'),
25 | ]),
26 | 'route_name.required' => trans('validation.required', ['attribute' => trans('SimpleMenu::messages.route_name')]),
27 | 'url.required' => trans('validation.required', ['attribute' => trans('SimpleMenu::messages.url')]),
28 | 'url.unique' => trans('validation.unique', ['attribute' => trans('SimpleMenu::messages.url')]),
29 | 'title.required' => trans('validation.required', ['attribute' => trans('SimpleMenu::messages.title')]),
30 | 'title.unique' => trans('validation.unique', ['attribute' => trans('SimpleMenu::messages.title')]),
31 | ];
32 |
33 | // main
34 | $validator = Validator::make($request->all(), [
35 | 'action' => 'nullable|regex:/@/ius',
36 | 'template' => 'required_without:action',
37 | 'route_name' => 'required|unique:pages,route_name,' . $id ?: '',
38 | 'url.*' => 'unique_translation:pages,url,' . $id ?: '',
39 | 'title.*' => 'unique_translation:pages,title,' . $id ?: '',
40 | ], $customMessages);
41 |
42 | // extra
43 | $validator->after(function ($validator) use ($request, $customMessages) {
44 | // url
45 | if (!array_filter($request->url)) {
46 | $validator->errors()->add('url', $customMessages['url.required']);
47 | }
48 |
49 | // title
50 | if (!array_filter($request->title)) {
51 | $validator->errors()->add('title', $customMessages['title.required']);
52 | }
53 | });
54 |
55 | if ($validator->fails()) {
56 | throw (new ValidationException($validator))
57 | ->errorBag('default')
58 | ->redirectTo(url()->previous());
59 | }
60 | }
61 |
62 | /**
63 | * make sure we only have fields with values.
64 | *
65 | * @param [type] $request [description]
66 | *
67 | * @return [type] [description]
68 | */
69 | protected function cleanEmptyTranslations($request)
70 | {
71 | $result = $request->except(['roles', 'permissions', 'menus', 'cover', 'controllerFile']);
72 |
73 | foreach ($result as $k => $v) {
74 | if (is_array($v)) {
75 | $result[$k] = array_filter($v) ?: null;
76 | }
77 | }
78 |
79 | return $result;
80 | }
81 |
82 | /**
83 | * save or get controller content.
84 | *
85 | * @param [type] $action [description]
86 | * @param [type] $type [description]
87 | * @param [type] $data [description]
88 | *
89 | * @return [type] [description]
90 | */
91 | protected function actionFileContent($action, $type, $data = null)
92 | {
93 | $class = substr($action, 0, strpos($action, '@'));
94 | $file = (new \ReflectionClass($class))->getFileName();
95 |
96 | if ($type == 'get') {
97 | return file_get_contents($file);
98 | }
99 |
100 | return file_put_contents($file, $data);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/Traits/Paginate.php:
--------------------------------------------------------------------------------
1 | forPage($page, $perPage)->values(),
22 | $items->count(),
23 | $perPage,
24 | $page,
25 | [
26 | 'path' => Paginator::resolveCurrentPath(),
27 | 'pageName' => $pageName,
28 | ]
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/Traits/RolePermOps.php:
--------------------------------------------------------------------------------
1 | cache->tags('sm')->flush();
10 |
11 | event('sm-perms.cleared');
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/Traits/UserPageOps.php:
--------------------------------------------------------------------------------
1 | pluck('name')->sort()->values()->all();
24 | $new = collect($input)->sort()->values()->all();
25 |
26 | return $self === $new;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Controllers/Admin/UsersController.php:
--------------------------------------------------------------------------------
1 | cache->get('sm-users');
21 |
22 | return view("{$this->adminPath}.users.index", compact('users'));
23 | }
24 |
25 | /**
26 | * Show the form for creating new User.
27 | *
28 | * @return \Illuminate\Http\Response
29 | */
30 | public function create()
31 | {
32 | $roles = $this->roleModel->pluck('name', 'name');
33 | $permissions = $this->permissionModel->pluck('name', 'name');
34 |
35 | return view("{$this->adminPath}.users.create", compact('roles', 'permissions'));
36 | }
37 |
38 | /**
39 | * Store a newly created User in storage.
40 | *
41 | * @param \App\Http\Requests\StoreUsersRequest $request
42 | *
43 | * @return \Illuminate\Http\Response
44 | */
45 | public function store(Request $request)
46 | {
47 | $this->validate($request, [
48 | 'name' => 'required',
49 | 'email' => 'required|email|unique:users,email',
50 | 'password' => 'required',
51 | ]);
52 |
53 | $img = $this->getImage($request->avatar);
54 | $user = $this->userModel->create(array_merge(['avatar'=>$img], $request->except(['roles', 'permissions'])));
55 | $roles = $request->roles ?: [];
56 | $permissions = $request->permissions ?: [];
57 |
58 | $user->assignRole($roles);
59 | $user->givePermissionTo($permissions);
60 |
61 | return redirect()
62 | ->route($this->crud_prefix . '.users.index')
63 | ->with('status', trans('SimpleMenu::messages.model_created'));
64 | }
65 |
66 | /**
67 | * Show the form for editing User.
68 | *
69 | * @param int $id
70 | *
71 | * @return \Illuminate\Http\Response
72 | */
73 | public function edit($id)
74 | {
75 | $user = $this->userModel->findOrFail($id);
76 | $roles = $this->roleModel->pluck('name', 'name');
77 | $permissions = $this->permissionModel->pluck('name', 'name');
78 |
79 | return view("{$this->adminPath}.users.edit", compact('user', 'roles', 'permissions'));
80 | }
81 |
82 | /**
83 | * Update User in storage.
84 | *
85 | * @param \App\Http\Requests\UpdateUsersRequest $request
86 | * @param int $id
87 | *
88 | * @return \Illuminate\Http\Response
89 | */
90 | public function update($id, Request $request)
91 | {
92 | $this->validate($request, [
93 | 'name' => 'required',
94 | 'email' => 'required|email|unique:users,email,' . $id,
95 | ]);
96 |
97 | $user = $this->userModel->findOrFail($id);
98 | $img = $this->getImage($request->avatar);
99 | $roles = $request->roles;
100 | $permissions = $request->permissions;
101 |
102 | $user->update(array_merge(['avatar'=>$img], $request->except(['roles', 'permissions'])));
103 |
104 | if (!$this->checkBeforeAssign($user->roles, $roles)) {
105 | $user->syncRoles($roles ?: []);
106 | }
107 |
108 | if (!$this->checkBeforeAssign($user->permissions, $permissions)) {
109 | $user->syncPermissions($permissions ?: []);
110 | }
111 |
112 | $user->touch();
113 |
114 | return back()->with('status', trans('SimpleMenu::messages.model_updated'));
115 | }
116 |
117 | /**
118 | * Remove User from storage.
119 | *
120 | * @param int $id
121 | *
122 | * @return \Illuminate\Http\Response
123 | */
124 | public function destroy($id, Request $request)
125 | {
126 | // dont remove self
127 | // if (auth()->user()->id == $id) {
128 | // abort(403);
129 | // }
130 |
131 | $this->userModel->destroy($id);
132 |
133 | if ($request->expectsJson()) {
134 | return response()->json(['done'=>true]);
135 | }
136 |
137 | return redirect()
138 | ->route($this->crud_prefix . '.users.index')
139 | ->with('status', trans('SimpleMenu::messages.model_deleted'));
140 | }
141 |
142 | public function destroyMulti(Request $request)
143 | {
144 | $ids = explode(',', $request->ids);
145 |
146 | $this->userModel->destroy($ids);
147 |
148 | return redirect()
149 | ->route($this->crud_prefix . '.users.index')
150 | ->with('status', trans('SimpleMenu::messages.models_deleted'));
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/src/Controllers/BaseController.php:
--------------------------------------------------------------------------------
1 | cache = app('cache');
33 | $this->adminPath = 'SimpleMenu::admin';
34 | $this->crud_prefix = $sm_config['crud_prefix'];
35 |
36 | $this->userModel = app(Arr::get($sm_config, 'models.user'));
37 | $this->pageModel = app(Arr::get($sm_config, 'models.page'));
38 | $this->menuModel = app(Arr::get($sm_config, 'models.menu'));
39 | $this->roleModel = app(Arr::get($sp_config, 'models.role'));
40 | $this->permissionModel = app(Arr::get($sp_config, 'models.permission'));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Controllers/DummyController.php:
--------------------------------------------------------------------------------
1 | currentRouteName()));
12 |
13 | return view($template, compact('title', 'body', 'desc', 'meta', 'cover', 'breadCrumb'));
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Facade/SimpleMenu.php:
--------------------------------------------------------------------------------
1 | guest()) {
26 | throw UnauthorizedException::notLoggedIn();
27 | }
28 |
29 | if (!$request->user()->load('permissions')->hasAnyPermission($permissions)) {
30 | throw UnauthorizedException::forPermissions($permissions);
31 | }
32 |
33 | return $next($request);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Middleware/RoleMiddleware.php:
--------------------------------------------------------------------------------
1 | guest()) {
26 | throw UnauthorizedException::notLoggedIn();
27 | }
28 |
29 | if (!$request->user()->load('roles')->hasAnyRole($roles)) {
30 | throw UnauthorizedException::forRoles($roles);
31 | }
32 |
33 | return $next($request);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Models/Menu.php:
--------------------------------------------------------------------------------
1 | belongsToMany(config('simpleMenu.models.page'))->withPivot('order');
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Models/Page.php:
--------------------------------------------------------------------------------
1 | belongsToMany(config('simpleMenu.models.menu'));
32 | }
33 |
34 | protected function getCrntLocale()
35 | {
36 | return LaravelLocalization::getCurrentLocale();
37 | }
38 |
39 | /**
40 | * override HasTranslations\getAttributeValue().
41 | *
42 | * @param [type] $key [description]
43 | *
44 | * @return [type] [description]
45 | */
46 | public function getAttributeValue($key)
47 | {
48 | if (!$this->isTranslatableAttribute($key)) {
49 | return parent::getAttributeValue($key);
50 | }
51 |
52 | return $this->getTranslationWithoutFallback($key, $this->getCrntLocale());
53 | }
54 |
55 | /**
56 | * Menus.
57 | *
58 | * @param [type] $menus [description]
59 | *
60 | * @return [type] [description]
61 | */
62 | public function assignToMenus($menus)
63 | {
64 | $this->menus()->attach($menus);
65 | $this->touch();
66 | }
67 |
68 | public function syncMenus($menus)
69 | {
70 | $this->menus()->sync($menus);
71 | $this->touch();
72 | }
73 |
74 | /**
75 | * Nesting.
76 | *
77 | * @param mixed $columns
78 | *
79 | * @return [type] [description]
80 | */
81 | public function getAncestors($columns = ['*'])
82 | {
83 | return app('cache')->tags('sm')->rememberForever($this->getCrntLocale() . "-{$this->route_name}_ancestors", function () use ($columns) {
84 | return $this->ancestors()->get($columns);
85 | });
86 | }
87 |
88 | public function getNestsAttribute()
89 | {
90 | return app('cache')->tags('sm')->rememberForever($this->getCrntLocale() . "-{$this->route_name}_nests", function () {
91 | return Arr::flatten(current($this->getDescendants()->toHierarchy()));
92 | });
93 | }
94 |
95 | /**
96 | * clear Nesting.
97 | *
98 | * @return [type] [description]
99 | */
100 | public function destroyDescendants()
101 | {
102 | if (config('simpleMenu.deletePageAndNests')) {
103 | parent::destroyDescendants();
104 | } else {
105 | $this->clearNests();
106 | }
107 | }
108 |
109 | public function clearSelfAndDescendants()
110 | {
111 | $this->makeRoot();
112 | $this->clearNests();
113 | }
114 |
115 | protected function clearNests()
116 | {
117 | $lft = $this->getLeft();
118 | $rgt = $this->getRight();
119 |
120 | if (is_null($lft) || is_null($rgt)) {
121 | return;
122 | }
123 |
124 | $lftCol = $this->getLeftColumnName();
125 | $rgtCol = $this->getRightColumnName();
126 |
127 | $this->where($lftCol, '>', $lft)->where($rgtCol, '<', $rgt)->each(function ($one) {
128 | $one->makeRoot();
129 | });
130 |
131 | $this->touch();
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/Models/Traits/SMUsers.php:
--------------------------------------------------------------------------------
1 | password;
16 | }
17 |
18 | $this->attributes['password'] = app('hash')->needsRehash($value)
19 | ? app('hash')->make($value)
20 | : $value;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Observers/BaseObserver.php:
--------------------------------------------------------------------------------
1 | cache = app('cache');
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/Observers/MenuObserver.php:
--------------------------------------------------------------------------------
1 | cleanData();
13 | }
14 |
15 | /**
16 | * Listen to the Menu deleted event.
17 | */
18 | public function deleted()
19 | {
20 | return $this->cleanData();
21 | }
22 |
23 | /**
24 | * helpers.
25 | *
26 | * @return [type] [description]
27 | */
28 | protected function cleanData()
29 | {
30 | $this->cache->tags('sm')->flush();
31 |
32 | event('sm-menus.cleared');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Observers/PageObserver.php:
--------------------------------------------------------------------------------
1 | cleanData($page);
15 | }
16 |
17 | /**
18 | * Listen to the Page deleted event.
19 | */
20 | public function deleted(Page $page)
21 | {
22 | return $this->cleanData($page);
23 | }
24 |
25 | /**
26 | * helpers.
27 | *
28 | * @param [type] $page [description]
29 | *
30 | * @return [type] [description]
31 | */
32 | protected function cleanData($page)
33 | {
34 | $route_name = $page->route_name;
35 |
36 | // clear page session
37 | session()->forget($route_name);
38 |
39 | // remove the route file
40 | app('files')->delete(config('simpleMenu.routeListPath'));
41 |
42 | // clear all cache
43 | $this->cache->tags('sm')->flush();
44 |
45 | event('sm-pages.cleared');
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Observers/UserObserver.php:
--------------------------------------------------------------------------------
1 | cleanData();
13 | }
14 |
15 | /**
16 | * Listen to the User deleting event.
17 | */
18 | public function deleted()
19 | {
20 | return $this->cleanData();
21 | }
22 |
23 | /**
24 | * helpers.
25 | *
26 | * @return [type] [description]
27 | */
28 | protected function cleanData()
29 | {
30 | $this->cache->forget('sm-users');
31 |
32 | event('sm-users.cleared');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/SimpleMenu.php:
--------------------------------------------------------------------------------
1 | cache = app('cache');
27 | $this->listFileDir = config('simpleMenu.routeListPath');
28 | $this->localeCodes = array_keys(LaravelLocalization::getSupportedLocales());
29 |
30 | if ($this->listFileDir) {
31 | static::create_LFD($this->listFileDir);
32 |
33 | if (!app()->runningInConsole()) {
34 | // create caches
35 | $this->createCaches();
36 |
37 | // create routes
38 | $this->createRoutes();
39 |
40 | // create menu
41 | $this->createMenus();
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/SimpleMenuServiceProvider.php:
--------------------------------------------------------------------------------
1 | packagePublish();
24 | $this->observers();
25 | $this->macros();
26 | $this->viewComp();
27 | $this->command();
28 | $this->app['simplemenu'];
29 | }
30 |
31 | protected function packagePublish()
32 | {
33 | // config
34 | $this->publishes([
35 | __DIR__ . '/config' => config_path(),
36 | ], 'config');
37 |
38 | // migrations
39 | $this->publishes([
40 | __DIR__ . '/database/migrations' => database_path('migrations'),
41 | ], 'migrations');
42 |
43 | // seeds
44 | $this->publishes([
45 | __DIR__ . '/database/seeds' => database_path('seeds'),
46 | ], 'seeds');
47 |
48 | // resources
49 | $this->publishes([
50 | __DIR__ . '/resources/assets' => resource_path('assets/vendor/SimpleMenu'),
51 | ], 'assets');
52 |
53 | // trans
54 | $this->loadTranslationsFrom(__DIR__ . '/resources/lang', 'SimpleMenu');
55 | $this->publishes([
56 | __DIR__ . '/resources/lang' => resource_path('lang/vendor/SimpleMenu'),
57 | ], 'trans');
58 |
59 | // views
60 | $this->loadViewsFrom(__DIR__ . '/resources/views', 'SimpleMenu');
61 | $this->publishes([
62 | __DIR__ . '/resources/views' => resource_path('views/vendor/SimpleMenu'),
63 | __DIR__ . '/resources/pagination' => resource_path('views/vendor/pagination'),
64 | ], 'views');
65 | }
66 |
67 | /**
68 | * model events observers.
69 | *
70 | * @return [type] [description]
71 | */
72 | protected function observers()
73 | {
74 | $models = $this->app['config']->get('simpleMenu.models');
75 |
76 | if ($models) {
77 | $this->app->make($models['page'])->observe(PageObserver::class);
78 | $this->app->make($models['menu'])->observe(MenuObserver::class);
79 | $this->app->make($models['user'])->observe(UserObserver::class);
80 | }
81 | }
82 |
83 | /**
84 | * package macros.
85 | *
86 | * @return [type] [description]
87 | */
88 | protected function macros()
89 | {
90 | // same as "Route::is()" but better
91 | $this->app['url']->macro('is', function ($route_name, $params = null) {
92 | return $params
93 | ? request()->url() == route($route_name, $params)
94 | : request()->url() == route($route_name);
95 | });
96 |
97 | $this->app['url']->macro('has', function ($needle) {
98 | return Str::contains($this->current(), $needle);
99 | });
100 | }
101 |
102 | /**
103 | * share var across views.
104 | *
105 | * @return [type] [description]
106 | */
107 | protected function viewComp()
108 | {
109 | view()->composer('SimpleMenu::admin.*', function ($view) {
110 | $view->with([
111 | 'crud_prefix' => $this->app['config']->get('simpleMenu.crud_prefix'),
112 | ]);
113 | });
114 | }
115 |
116 | /**
117 | * package commands.
118 | *
119 | * @return [type] [description]
120 | */
121 | protected function command()
122 | {
123 | $this->commands([
124 | PackageSetup::class,
125 | ]);
126 | }
127 |
128 | /**
129 | * Register any package services.
130 | */
131 | public function register()
132 | {
133 | $this->app->singleton('simplemenu', function () {
134 | return new SimpleMenu();
135 | });
136 |
137 | $this->regPSP();
138 | $this->regPMW();
139 | }
140 |
141 | /**
142 | * packages service providers.
143 | *
144 | * @return [type] [description]
145 | */
146 | protected function regPSP()
147 | {
148 | $packagesSP = [
149 | \Baum\Providers\BaumServiceProvider::class,
150 | \ctf0\PackageChangeLog\PackageChangeLogServiceProvider::class,
151 | ];
152 |
153 | foreach ($packagesSP as $one) {
154 | $this->app->register($one);
155 | }
156 | }
157 |
158 | /**
159 | * packages middlewares.
160 | *
161 | * @return [type] [description]
162 | */
163 | protected function regPMW()
164 | {
165 | $this->app['router']->aliasMiddleware('perm', PermissionMiddleware::class);
166 | $this->app['router']->aliasMiddleware('role', RoleMiddleware::class);
167 | $this->app['router']->aliasMiddleware('localizationRedirect', LaravelLocalizationRedirectFilter::class);
168 | $this->app['router']->aliasMiddleware('localeSessionRedirect', LocaleSessionRedirect::class);
169 | }
170 | }
--------------------------------------------------------------------------------
/src/Traits/Menus.php:
--------------------------------------------------------------------------------
1 | cache->tags('sm')->get('menus')->pluck('name')->each(function ($name) {
15 | $this->viewComp($name);
16 | });
17 | }
18 |
19 | /**
20 | * [viewComp description].
21 | *
22 | * @param [type] $name [description]
23 | *
24 | * @return [type] [description]
25 | */
26 | public function viewComp($name)
27 | {
28 | $viewFile = view()->exists("SimpleMenu::menu.{$name}")
29 | ? "SimpleMenu::menu.{$name}"
30 | : 'SimpleMenu::menu.example';
31 |
32 | return view()->composer($viewFile, function ($view) use ($name) {
33 | $view->with([
34 | 'PAGES' => $this->query($name),
35 | 'menuName' => $name,
36 | ]);
37 | });
38 | }
39 |
40 | /**
41 | * menu logic.
42 | *
43 | * @param [type] $name [description]
44 | * @param null|mixed $nest
45 | *
46 | * @return [type] [description]
47 | */
48 | public function query($name)
49 | {
50 | $locale = $this->getCrntLocale();
51 |
52 | if ($this->cache->tags('sm')->get('menus')->isNotEmpty()) {
53 | return $this->cache->tags('sm')->rememberForever("{$name}Menu-{$locale}Pages", function () use ($name) {
54 | return collect($this->cache->tags('sm')->get('menus')->where('name', $name)->first()->pages)
55 | ->sortBy('pivot_order')
56 | ->filter(function ($item) {
57 | return $item->url != '';
58 | });
59 | });
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Traits/Navigation.php:
--------------------------------------------------------------------------------
1 | currentRouteName();
23 |
24 | // redir to '/' if the first item in "bc" is in diff locale
25 | $bc = $this->getRouteData($name)['breadCrumb'];
26 |
27 | if (isset($bc) && count($bc) && !$this->searchForRoute($bc->pluck('route_name')->first(), $code)) {
28 | return LaravelLocalization::getLocalizedURL($code, url('/'), [], true);
29 | }
30 |
31 | // routeName is not saved in the db (ex.php artisan make:auth)
32 | // or only url
33 | $routesListFile = include $this->listFileDir;
34 |
35 | if (is_null($name) || !isset($routesListFile[$name])) {
36 | return LaravelLocalization::getLocalizedURL($code, null, [], true);
37 | }
38 |
39 | $url = $this->routeLink($name, $code);
40 |
41 | // if we have a saved params
42 | if (session()->has($name)) {
43 | $params = session()->get($name);
44 |
45 | return LaravelLocalization::getLocalizedURL($code, url($this->getParams($url, $params)), [], true);
46 | }
47 |
48 | // no params
49 | return LaravelLocalization::getLocalizedURL($code, url($this->rmvUnUsedParams($url)), [], true);
50 | }
51 |
52 | /**
53 | * resolve route & params for links.
54 | *
55 | * @param [type] $crntRouteName [description]
56 | * @param array|null $params [description]
57 | *
58 | * @return [type] [description]
59 | */
60 | public function getRoute($crntRouteName, $params = null)
61 | {
62 | // where route is available under one locale but not the other
63 | if (!app('router')->has($crntRouteName)) {
64 | return;
65 | }
66 |
67 | $locale = $this->getCrntLocale();
68 | $url = $this->routeLink($crntRouteName, $locale);
69 | $forceDefaultLocation = LaravelLocalization::hideDefaultLocaleInURL() && $locale == LaravelLocalization::getDefaultLocale() ? false : true;
70 |
71 | // resolve route params
72 | if ($params) {
73 | foreach ($params as $key => $value) {
74 | if ($crntRouteName == $key) {
75 | session([$key => $value]);
76 |
77 | // fix link not being 'is-active'when"hideDefaultLocaleInURL => true"
78 | $finalUrl = LaravelLocalization::getLocalizedURL($locale, url($this->getParams($url, $value)), [], $forceDefaultLocation);
79 | $this->urlRoute = $finalUrl;
80 |
81 | return $finalUrl;
82 | }
83 | }
84 | }
85 |
86 | $this->urlRoute = route($crntRouteName);
87 |
88 | return $this->urlRoute;
89 | }
90 |
91 | /**
92 | * helpers.
93 | *
94 | * @return [type] [description]
95 | */
96 | public function routeUrl()
97 | {
98 | return $this->urlRoute;
99 | }
100 |
101 | public function isActiveRoute()
102 | {
103 | return request()->url() == $this->urlRoute;
104 | }
105 |
106 | public function getRouteData($name)
107 | {
108 | return $this->cache->tags('sm')->get($this->getCrntLocale() . "-$name");
109 | }
110 |
111 | public function getBC()
112 | {
113 | $name = app('router')->currentRouteName();
114 | $bc = $this->getRouteData($name)['breadCrumb'];
115 |
116 | if (isset($bc) && count($bc)) {
117 | return $bc;
118 | }
119 | }
120 |
121 | /**
122 | * resolve route url.
123 | *
124 | * @param [type] $name [description]
125 | * @param [type] $code [description]
126 | *
127 | * @return [type] [description]
128 | */
129 | protected function routeLink($name, $code)
130 | {
131 | $searchCode = $this->searchForRoute($name, $code);
132 |
133 | // if notFound, then either redir to home or show 404
134 | if (!$searchCode) {
135 | switch (config('simpleMenu.unFoundLocalizedRoute')) {
136 | case 'error':
137 | return '404';
138 | break;
139 | default:
140 | return '/';
141 | }
142 | }
143 |
144 | return $searchCode;
145 | }
146 |
147 | protected function searchForRoute($name, $code)
148 | {
149 | $routesListFile = include $this->listFileDir;
150 |
151 | // check if we have a link according to that "routeName & code"
152 | return Arr::get($routesListFile, "$name.$code", false);
153 | }
154 |
155 | /**
156 | * render menu.
157 | *
158 | * @param [type] $pages [description]
159 | * @param [type] $classes [description]
160 | * @param [type] $params [description]
161 | * @param [type] $url [description]
162 | *
163 | * @return [type] [description]
164 | */
165 | public function render($pages, $classes = null, $params = null)
166 | {
167 | $url = request()->url();
168 |
169 | switch ($classes) {
170 | case 'config':
171 | $ul = config('simpleMenu.listClasses.ul');
172 | $li = config('simpleMenu.listClasses.li');
173 | $a = config('simpleMenu.listClasses.a');
174 | break;
175 | default:
176 | $ul = $classes['ul'];
177 | $li = $classes['li'];
178 | $a = $classes['a'];
179 | break;
180 | }
181 |
182 | return $this->getHtml($pages, $ul, $li, $a, $params, $url);
183 | }
184 |
185 | /**
186 | * generate menu html.
187 | *
188 | * @param [type] $pages [description]
189 | * @param [type] $params [description]
190 | * @param [type] $url [description]
191 | * @param mixed $ul_ClassName
192 | * @param mixed $li_ClassName
193 | * @param mixed $a_ClassName
194 | *
195 | * @return [type] [description]
196 | */
197 | protected function getHtml($pages, $ul_ClassName, $li_ClassName, $a_ClassName, $params, $url)
198 | {
199 | $html = '';
200 | $html .= "";
201 |
202 | foreach ($pages as $page) {
203 | // escape empty url
204 | if (empty($page->url)) {
205 | continue;
206 | }
207 |
208 | $routeUrl = $this->getRoute($page->route_name, $params);
209 | $isActive = ($url == $routeUrl ? $a_ClassName : '');
210 |
211 | $html .= "- ";
212 | $html .= "{$page->title}";
213 |
214 | if ($childs = $page->nests) {
215 | $html .= $this->getHtml($childs, $ul_ClassName, $li_ClassName, $a_ClassName, $params, $url);
216 | }
217 | $html .= '
';
218 | }
219 |
220 | $html .= '
';
221 |
222 | return $html;
223 | }
224 |
225 | /**
226 | * resolve params.
227 | *
228 | * @param [type] $url [description]
229 | * @param [type] $params [description]
230 | *
231 | * @return [type] [description]
232 | */
233 | protected function getParams($url, $params)
234 | {
235 | foreach ($params as $key => $value) {
236 | $url = preg_replace('/\{' . preg_quote($key) . '(\?)?\}/', $value, $url);
237 | }
238 |
239 | return $this->rmvUnUsedParams($url);
240 | }
241 |
242 | /**
243 | * remove optional params. so we dont get badly formated url.
244 | *
245 | * @param [type] $url [description]
246 | *
247 | * @return [type] [description]
248 | */
249 | protected function rmvUnUsedParams($url)
250 | {
251 | return preg_replace('/\{.*\}/', '', $url);
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/src/Traits/Ops.php:
--------------------------------------------------------------------------------
1 | localeCodes;
15 | }
16 |
17 | protected function getCrntLocale()
18 | {
19 | return LaravelLocalization::getCurrentLocale();
20 | }
21 |
22 | /**
23 | * cacheing.
24 | *
25 | * @return [type] [description]
26 | */
27 | protected function createCaches()
28 | {
29 | $models = config('simpleMenu.models');
30 |
31 | $this->cache->tags('sm')->rememberForever('menus', function () use ($models) {
32 | return app($models['menu'])->with('pages')->get();
33 | });
34 |
35 | $this->cache->tags('sm')->rememberForever('pages', function () use ($models) {
36 | return app($models['page'])->withTrashed()->get();
37 | });
38 |
39 | $this->cache->rememberForever('sm-users', function () use ($models) {
40 | return app($models['user'])->with(['roles', 'permissions'])->get();
41 | });
42 | }
43 |
44 | /**
45 | * route list dir.
46 | *
47 | * @param mixed $dir
48 | */
49 | protected static function create_LFD($dir)
50 | {
51 | $files = app('files');
52 |
53 | if ($files->exists(config_path('simpleMenu.php'))) {
54 | $dir_name = dirname($dir);
55 |
56 | if (!$files->exists($dir_name)) {
57 | return $files->makeDirectory($dir_name, 0755, true);
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Traits/PackageRoutes.php:
--------------------------------------------------------------------------------
1 | group([
18 | 'prefix'=> $prefix,
19 | ], function () use ($prefix, $controllers) {
20 | /* Home */
21 | if (isset($controllers['admin'])) {
22 | app('router')->get('/', $controllers['admin'])->name($prefix);
23 | }
24 |
25 | /* Everything Else */
26 | app('router')->group([
27 | 'as'=> "$prefix.",
28 | ], function () use ($controllers) {
29 | /* Roles */
30 | app('router')->resource('roles', $controllers['roles'], ['except'=>'show']);
31 | app('router')->post('roles/remove-multi', $controllers['roles'] . '@destroyMulti')->name('roles.destroy_multi');
32 |
33 | /* Perms */
34 | app('router')->resource('permissions', $controllers['permissions'], ['except'=>'show']);
35 | app('router')->post('permissions/remove-multi', $controllers['permissions'] . '@destroyMulti')->name('permissions.destroy_multi');
36 |
37 | /* Menus */
38 | app('router')->post('menus/removechild', $controllers['menus'] . '@removeChild')->name('menus.removeChild');
39 | app('router')->post('menus/removepage/{id}', $controllers['menus'] . '@removePage')->name('menus.removePage');
40 | app('router')->get('menus/getmenupages/{id}', $controllers['menus'] . '@getMenuPages')->name('menus.getMenuPages');
41 | app('router')->resource('menus', $controllers['menus'], ['except'=>'show']);
42 | app('router')->post('menus/remove-multi', $controllers['menus'] . '@destroyMulti')->name('menus.destroy_multi');
43 |
44 | /* Users */
45 | app('router')->resource('users', $controllers['users'], ['except'=>'show']);
46 | app('router')->post('users/remove-multi', $controllers['users'] . '@destroyMulti')->name('users.destroy_multi');
47 |
48 | /* Pages */
49 | app('router')->resource('pages', $controllers['pages'], ['except'=>'show']);
50 | app('router')->post('pages/remove-multi', $controllers['pages'] . '@destroyMulti')->name('pages.destroy_multi');
51 | app('router')->put('pages/{id}/restore', $controllers['pages'] . '@restore')->name('pages.restore');
52 | app('router')->delete('pages/{id}/remove-force', $controllers['pages'] . '@forceDelete')->name('pages.destroy_force');
53 | });
54 | });
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Traits/Routes.php:
--------------------------------------------------------------------------------
1 | group([
16 | 'prefix' => LaravelLocalization::setLocale(),
17 | 'middleware' => [
18 | 'web',
19 | 'localeSessionRedirect',
20 | 'localizationRedirect',
21 | ],
22 | ], function () {
23 | $this->utilCheck();
24 | });
25 | }
26 |
27 | protected function utilCheck()
28 | {
29 | if (!app('files')->exists($this->listFileDir)) {
30 | $this->listFileFound = false;
31 |
32 | $this->utilLoop();
33 | $this->saveRoutesListToFile($this->allRoutes);
34 | } else {
35 | $this->utilLoop();
36 | }
37 | }
38 |
39 | /**
40 | * runs everytime you change the current local
41 | * so routes links gets dynamically changed without causing issues.
42 | *
43 | * @return [type] [description]
44 | */
45 | protected function utilLoop()
46 | {
47 | foreach ($this->cache->tags('sm')->get('pages') as $page) {
48 | // make route
49 | $this->routeGen($page);
50 |
51 | // create route list
52 | if (!$this->listFileFound) {
53 | $this->createRoutesList($page);
54 | }
55 | }
56 | }
57 |
58 | protected function routeGen($page)
59 | {
60 | if ($this->escapeEmptyRoute($page->url)) {
61 | return;
62 | }
63 |
64 | // route data
65 | $url = $page->url;
66 | $action = $page->action;
67 | $prefix = $page->prefix;
68 | $routeName = $page->route_name;
69 |
70 | // page data
71 | $title = $page->title;
72 | $body = $page->body;
73 | $desc = $page->desc;
74 | $meta = $page->meta;
75 | $cover = $page->cover;
76 | $template = $page->template;
77 | $breadCrumb = $page->getAncestors();
78 |
79 | // middlewares
80 | $middlewares = is_null($page->middlewares) ? null : preg_split('/[\s,]+/', $page->middlewares);
81 | $roles = empty($page->roles->pluck('name')->toArray()) ? null : 'role:' . implode(',', $page->roles->pluck('name')->toArray());
82 | $permissions = empty($page->permissions->pluck('name')->toArray()) ? null : 'perm:' . implode(',', $page->permissions->pluck('name')->toArray());
83 |
84 | // cache the page so we can pass the page params to the controller@method
85 | $compact = compact('template', 'title', 'body', 'desc', 'meta', 'cover', 'breadCrumb', 'middlewares', 'roles', 'permissions');
86 |
87 | $this->cache->tags('sm')->rememberForever($this->getCrntLocale() . "-$routeName", function () use ($compact) {
88 | return $compact;
89 | });
90 |
91 | $route = $this->getRouteUrl($url, $prefix);
92 |
93 | $uses = $action
94 | ? starts_with($action, '\\') ? $action : "\\$action"
95 | : '\ctf0\SimpleMenu\Controllers\DummyController@handle';
96 |
97 | $mds = array_filter(Arr::flatten([$middlewares, $roles, $permissions]));
98 |
99 | app('router')->get($route)
100 | ->uses($uses)
101 | ->name($routeName)
102 | ->middleware($mds);
103 | }
104 |
105 | protected function createRoutesList($page)
106 | {
107 | $routeName = $page->route_name;
108 |
109 | foreach ($this->AppLocales() as $code) {
110 | $url = $page->getTranslationWithoutFallback('url', $code);
111 | $prefix = $page->getTranslationWithoutFallback('prefix', $code);
112 |
113 | if ($this->escapeEmptyRoute($url)) {
114 | continue;
115 | }
116 |
117 | $route = $this->getRouteUrl($url, $prefix);
118 |
119 | $this->allRoutes[$routeName][$code] = $route;
120 | }
121 | }
122 |
123 | protected function escapeEmptyRoute($url)
124 | {
125 | return empty($url);
126 | }
127 |
128 | protected function getRouteUrl($url, $prefix)
129 | {
130 | if (empty($prefix)) {
131 | $clear = $url;
132 | } else {
133 | $clear = "$prefix/$url";
134 | }
135 |
136 | return $this->clearExtraSlash($clear);
137 | }
138 |
139 | protected function saveRoutesListToFile($routes)
140 | {
141 | $data = "clearExtraSlash($data);
143 |
144 | // array(...) to [...]
145 | $data = str_replace('array (', '[', $data);
146 | $data = str_replace(')', ']', $data);
147 | $data = preg_replace('/=>\s+\[/', '=> [', $data);
148 |
149 | return app('files')->put($this->listFileDir, $data);
150 | }
151 |
152 | protected function clearExtraSlash($url)
153 | {
154 | return preg_replace('/\/+/', '/', $url);
155 | }
156 | }
--------------------------------------------------------------------------------
/src/config/simpleMenu.php:
--------------------------------------------------------------------------------
1 | [
8 | 'ul' => 'menu-list',
9 | 'li' => 'list-item',
10 | 'a' => 'is-active',
11 | ],
12 |
13 | /*
14 | * the path where we will save the routes list
15 | */
16 | 'routeListPath' => storage_path('logs/simpleMenu.php'),
17 |
18 | /*
19 | * dynamic pages controller namespace
20 | */
21 | 'pagesControllerNS' => 'App\Http\Controllers',
22 |
23 | /*
24 | * where to redirect when a route is available in one locale "en" but not in another "fr" ?
25 | *
26 | * add
27 | * 'root' = '/'
28 | * 'error' = '404'
29 | */
30 | 'unFoundLocalizedRoute' => 'root',
31 |
32 | /*
33 | * package models
34 | */
35 | 'models'=> [
36 | 'user' => App\User::class,
37 | 'page' => \ctf0\SimpleMenu\Models\Page::class,
38 | 'menu' => \ctf0\SimpleMenu\Models\Menu::class,
39 | ],
40 |
41 | /*
42 | * when adding a page which is a nest of another to a menu, ex.
43 | *
44 | * root
45 | * | child 1
46 | * | child 2 "add this along with its children to another menu"
47 | * | child 3
48 | *
49 | * do you want to clear its parent and make it a root ?
50 | *
51 | * note that this will cause issues for breadcumb as to "what to show" and "what to hide"
52 | * if set to "false"
53 | */
54 | 'clearPartialyNestedParent'=> true,
55 |
56 | /*
57 | * when removing a root page from a menu, ex.
58 | *
59 | * root "remove"
60 | * | child 1
61 | * | child 2
62 | * | child 3
63 | *
64 | * do you want clear all of its 'Descendants' ?
65 | */
66 | 'clearRootDescendants' => false,
67 |
68 | /*
69 | * when removing a nest from a list, ex.
70 | *
71 | * root
72 | * | child 1
73 | * | child 2 "remove"
74 | * | child 3
75 | *
76 | * do you want to reset its hierarchy ?
77 | */
78 | 'clearNestDescendants'=> false,
79 |
80 | /*
81 | * when deleting a page "from the db", ex.
82 | *
83 | * page "delete/destroy"
84 | * | nested child 1
85 | * | nested child 2
86 | * | nested child 3
87 | *
88 | * do you also want to delete all of its children ?
89 | */
90 | 'deletePageAndNests' => false,
91 |
92 | /*
93 | * package routes url & route name prefix ex.
94 | * url = 'admin/pages'
95 | * route name = 'admin.pages.*'
96 | */
97 | 'crud_prefix' => 'admin',
98 |
99 | /*
100 | * package controllers
101 | *
102 | * all the controllers are https://laravel.com/docs/5.5/controllers#resource-controllers
103 | * except admin which is using a single method "index" to return the admin page
104 | *
105 | * if you need to change anything, just create new controller
106 | * and extend from the below original
107 | * ex. "class ExampleController extends PagesController"
108 | *
109 | * for admin, the route name will be == "crud_prefix"
110 | */
111 | 'controllers'=> [
112 | 'admin' => '\ctf0\SimpleMenu\Controllers\Admin\AdminController@index',
113 | 'users' => '\ctf0\SimpleMenu\Controllers\Admin\UsersController',
114 | 'pages' => '\ctf0\SimpleMenu\Controllers\Admin\PagesController',
115 | 'roles' => '\ctf0\SimpleMenu\Controllers\Admin\RolesController',
116 | 'permissions' => '\ctf0\SimpleMenu\Controllers\Admin\PermissionsController',
117 | 'menus' => '\ctf0\SimpleMenu\Controllers\Admin\MenusController',
118 | ],
119 | ];
120 |
--------------------------------------------------------------------------------
/src/database/migrations/2014_10_12_000000_create_users_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
16 | $table->string('name');
17 | $table->string('email')->unique();
18 | $table->string('password');
19 | $table->string('avatar')->nullable();
20 |
21 | $table->rememberToken();
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | */
29 | public function down()
30 | {
31 | Schema::dropIfExists('users');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/database/migrations/2017_02_28_202951_create_pages_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
16 | $table->integer('parent_id')->nullable();
17 | $table->integer('lft')->nullable();
18 | $table->integer('rgt')->nullable();
19 | $table->integer('depth')->nullable();
20 |
21 | $table->string('cover')->nullable();
22 | $table->string('action')->nullable();
23 | $table->string('icon')->nullable();
24 | $table->string('template')->nullable();
25 | $table->string('middlewares')->nullable();
26 | $table->string('route_name')->nullable();
27 | $table->json('prefix')->nullable();
28 | $table->json('url');
29 | $table->json('title');
30 | $table->json('body')->nullable();
31 | $table->json('desc')->nullable();
32 | $table->json('meta')->nullable();
33 |
34 | $table->softDeletes();
35 | $table->timestamps();
36 | });
37 | }
38 |
39 | /**
40 | * Reverse the migrations.
41 | */
42 | public function down()
43 | {
44 | Schema::dropIfExists('pages');
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/database/migrations/2017_03_01_232714_create_menus_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
16 | $table->string('name');
17 | $table->timestamps();
18 | });
19 | }
20 |
21 | /**
22 | * Reverse the migrations.
23 | */
24 | public function down()
25 | {
26 | Schema::dropIfExists('menus');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/database/migrations/2017_03_01_232836_create_menu_page_table.php:
--------------------------------------------------------------------------------
1 | integer('menu_id')->unsigned()->index();
16 | $table->foreign('menu_id')->references('id')->on('menus')->onDelete('cascade');
17 | $table->integer('page_id')->unsigned()->index();
18 | $table->foreign('page_id')->references('id')->on('pages')->onDelete('cascade');
19 |
20 | $table->integer('order')->nullable();
21 | });
22 | }
23 |
24 | /**
25 | * Reverse the migrations.
26 | */
27 | public function down()
28 | {
29 | Schema::dropIfExists('menu_page');
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/database/seeds/DatabaseSeeder.example:
--------------------------------------------------------------------------------
1 | flush();
13 | app('files')->delete(config('simpleMenu.routeListPath'));
14 |
15 | $this->call(PagesTableSeeder::class);
16 | $this->call(MenusTableSeeder::class);
17 | $this->call(MenuPagesTableSeeder::class);
18 | $this->call(RolePermSeeder::class);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/database/seeds/MenuPagesTableSeeder.php:
--------------------------------------------------------------------------------
1 | all() as $key => $val) {
16 | $menu = $menuModel->inRandomOrder()->first();
17 | $menu->pages()->attach($val->id);
18 | }
19 |
20 | $pageModel->findOrFail(4)->makeChildOf($pageModel->findOrFail(3));
21 | $pageModel->findOrFail(5)->makeChildOf($pageModel->findOrFail(4));
22 | $pageModel->findOrFail(6)->makeChildOf($pageModel->findOrFail(5));
23 | $pageModel->findOrFail(7)->makeChildOf($pageModel->findOrFail(6));
24 | $pageModel->findOrFail(8)->makeChildOf($pageModel->findOrFail(7));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/database/seeds/MenusTableSeeder.php:
--------------------------------------------------------------------------------
1 | create(['name'=>$one]);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/database/seeds/PagesTableSeeder.php:
--------------------------------------------------------------------------------
1 | unique()->city;
19 | $es = $faker->unique()->city;
20 |
21 | $pageModel->create([
22 | 'template' => 'SimpleMenu::template-example',
23 | 'route_name'=> Str::slug($en),
24 | 'title' => [
25 | 'en' => Str::title($en),
26 | 'es' => Str::title($es),
27 | ],
28 | 'body' => [
29 | 'en' => $faker->text(),
30 | 'es' => $faker->text(),
31 | ],
32 | 'desc' => [
33 | 'en' => $faker->text(),
34 | 'es' => $faker->text(),
35 | ],
36 | 'prefix' => [
37 | 'en' => Str::slug($faker->unique()->country),
38 | 'es' => Str::slug($faker->unique()->country),
39 | ],
40 | 'url' => [
41 | 'en' => Str::slug($en),
42 | 'es' => Str::slug($es),
43 | ],
44 | ]);
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/database/seeds/RolePermSeeder.php:
--------------------------------------------------------------------------------
1 | create(['name' => $role]);
22 | }
23 |
24 | foreach ($perms as $perm) {
25 | $permissionModel->create(['name' => $perm]);
26 | }
27 |
28 | // foreach ($pageModel->all() as $page) {
29 | // $page->givePermissionTo('guest');
30 | // $page->assignRole('guest');
31 | // }
32 |
33 | $userModel->first()->assignRole('admin');
34 | $userModel->first()->givePermissionTo('access_backend');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/resources/assets/js/index.vue:
--------------------------------------------------------------------------------
1 |
91 |
--------------------------------------------------------------------------------
/src/resources/assets/js/manager.js:
--------------------------------------------------------------------------------
1 | /* Packages */
2 | window.EventHub = require('vuemit')
3 | Vue.use(require('vue-tippy'), {
4 | arrow: true,
5 | touchHold: true,
6 | inertia: true,
7 | performance: true,
8 | flipDuration: 0,
9 | popperOptions: {
10 | modifiers: {
11 | preventOverflow: {
12 | enabled: false
13 | },
14 | hide: {
15 | enabled: false
16 | }
17 | }
18 | }
19 | })
20 | require('vue-multi-ref')
21 |
22 | // icons
23 | import 'vue-awesome/icons/search'
24 | import 'vue-awesome/icons/times'
25 | import 'vue-awesome/icons/pencil'
26 | Vue.component('icon', require('vue-awesome/components/Icon').default)
27 |
28 | // table sort
29 | window.ListJS = require('list.js')
30 |
31 | // axios
32 | window.axios = require('axios')
33 | axios.defaults.headers.common = {
34 | 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
35 | 'X-Requested-With': 'XMLHttpRequest'
36 | }
37 | axios.interceptors.response.use(
38 | (response) => response,
39 | (error) => Promise.reject(error.response)
40 | )
41 |
42 | /* Component */
43 | Vue.component('SmPage', require('./page.vue').default)
44 | Vue.component('SmMenu', require('./menu.vue').default)
45 | Vue.component('SmIndex', require('./index.vue').default)
46 | Vue.component('MyNotification', require('vue-notif').default)
47 |
--------------------------------------------------------------------------------
/src/resources/assets/js/menu.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
176 |
--------------------------------------------------------------------------------
/src/resources/assets/js/menu_child.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
34 |
35 |
36 |
44 |
45 |
46 |
47 |
48 |
67 |
68 |
121 |
--------------------------------------------------------------------------------
/src/resources/assets/js/mixins/menu.js:
--------------------------------------------------------------------------------
1 | export default {
2 | props: ['locale', 'delChild', 'editPage', 'translation'],
3 | data() {
4 | return {
5 | isDragging: false
6 | }
7 | },
8 | created() {
9 | this.eventsListeners()
10 | },
11 | methods: {
12 | getTitle(title) {
13 | let locale = this.locale
14 |
15 | return title.hasOwnProperty(locale)
16 | ? title[locale]
17 | : Object.values(title)[0].concat(` "${Object.keys(title)[0]}"`)
18 | },
19 | goTo(id) {
20 | return this.editPage.replace(0, id)
21 | },
22 | trans(key) {
23 | return this.translation[key]
24 | },
25 |
26 | // ops
27 | eventsListeners() {
28 | EventHub.listen('DragStart', () => {
29 | this.isDragging = true
30 | })
31 |
32 | EventHub.listen('DragEnd', () => {
33 | this.isDragging = false
34 | })
35 | },
36 | hasChilds(item) {
37 | return item.nests && item.nests.length > 0
38 | },
39 |
40 | // style
41 | classObj(item) {
42 | if (this.checkFrom(item)) {
43 | return 'is-warning'
44 | }
45 | if (item.created_at == null) {
46 | return 'is-danger'
47 | }
48 | },
49 |
50 | // notif
51 | showNotif(msg) {
52 | EventHub.fire('showNotif', {
53 | title: 'Success',
54 | body: msg,
55 | type: 'success',
56 | duration: 2,
57 | icon: false
58 | })
59 | },
60 |
61 | // nests
62 | dragStart() {
63 | this.isDragging = true
64 | EventHub.fire('DragStart')
65 | },
66 | dragEnd() {
67 | this.isDragging = false
68 | EventHub.fire('DragEnd')
69 | }
70 |
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/resources/assets/js/mixins/search.js:
--------------------------------------------------------------------------------
1 | export default {
2 | data() {
3 | return {
4 | searchFor: null
5 | }
6 | },
7 | methods: {
8 | resetSearch() {
9 | this.searchFor = null
10 | }
11 | },
12 | watch: {
13 | searchFor(val) {
14 | let res = this.sorter.search(val, [this.searchColName])
15 |
16 | if (typeof this.updateCounter == 'function') {
17 | this.updateCounter(res.length)
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/resources/assets/js/page.vue:
--------------------------------------------------------------------------------
1 |
136 |
--------------------------------------------------------------------------------
/src/resources/assets/sass/_checkbox.scss:
--------------------------------------------------------------------------------
1 | // https://codepen.io/andreasstorm/pen/ybPwre
2 |
3 | $grey-lighter: #dbdbdb;
4 | $primary: #ff3860;
5 |
6 | .cbx-checkbox {
7 | &[type='checkbox'],
8 | &:checked {
9 | display: none;
10 | }
11 | }
12 |
13 | .cbx {
14 | position: relative;
15 | top: 1px;
16 | display: inline-block;
17 | width: 14px;
18 | height: 14px;
19 | margin-right: 6px;
20 | cursor: pointer;
21 | vertical-align: sub;
22 | border: 1px solid $grey-lighter;
23 | border-radius: 3px;
24 |
25 | &::before {
26 | position: absolute;
27 | top: 50%;
28 | left: 50%;
29 | width: 20px;
30 | height: 20px;
31 | margin: -10px 0 0 -10px;
32 | content: '';
33 | transform: scale(0);
34 | border-radius: 100%;
35 | background: $primary;
36 | }
37 |
38 | &::after {
39 | position: absolute;
40 | top: 5px;
41 | left: 5px;
42 | width: 2px;
43 | height: 2px;
44 | content: '';
45 | transform: scale(0);
46 | border-radius: 2px;
47 | box-shadow: 0 -18px 0 $primary, 12px -12px 0 $primary, 18px 0 0 $primary, 12px 12px 0 $primary, 0 18px 0 $primary, -12px 12px 0 $primary, -18px 0 0 $primary, -12px -12px 0 $primary;
48 | }
49 |
50 | svg {
51 | position: relative;
52 | top: -1px;
53 | transform: scale(0);
54 | fill: none;
55 | stroke-linecap: round;
56 | stroke-linejoin: round;
57 |
58 | polyline {
59 | stroke: $primary;
60 | stroke-width: 2;
61 | }
62 | }
63 | }
64 |
65 | input:checked + .cbx {
66 | top: 0;
67 | border-color: transparent;
68 |
69 | &::before {
70 | transition: all 0.3s ease;
71 | transform: scale(1);
72 | opacity: 0;
73 | }
74 |
75 | &::after {
76 | transition: all 0.6s ease;
77 | transform: scale(1);
78 | opacity: 0;
79 | }
80 |
81 | svg {
82 | transition: all 0.4s ease;
83 | transition-delay: 0.1s;
84 | transform: scale(1);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/resources/assets/sass/style.scss:
--------------------------------------------------------------------------------
1 | @import './checkbox';
2 |
3 | $blue: #3273dc;
4 | $mce-brdr: #eee;
5 | $mce-btn: #a3afb7;
6 |
7 | [v-cloak] {
8 | display: none;
9 | }
10 |
11 | td {
12 | vertical-align: middle !important;
13 | }
14 |
15 | thead th {
16 | position: sticky;
17 | z-index: 1;
18 | top: 0;
19 | background-color: white;
20 | }
21 |
22 | .m-t-5 {
23 | margin-top: 5px;
24 | }
25 |
26 | .link {
27 | cursor: pointer;
28 | }
29 |
30 | .static-cell {
31 | width: 1%;
32 | white-space: nowrap;
33 | }
34 |
35 | // select
36 | .choices {
37 | font-size: 1rem;
38 | }
39 |
40 | .choices__inner {
41 | font-size: 1rem;
42 | min-height: 29px;
43 | padding: 0.5rem;
44 | border-radius: 3px;
45 | background-color: transparent;
46 | }
47 |
48 | .choices__input {
49 | width: auto !important;
50 | margin: 0;
51 | padding: 0;
52 | background-color: transparent;
53 | }
54 |
55 | .choices__list--multiple .choices__item {
56 | margin-bottom: 0;
57 | border: none;
58 | border-radius: 100vw;
59 | background-color: $blue;
60 | }
61 |
62 | .choices__button {
63 | margin: 0 !important;
64 | padding: 0 !important;
65 | padding-left: 1.5rem !important;
66 | border: none !important;
67 | }
68 |
69 | // input locales
70 | .input-box {
71 | position: relative;
72 | }
73 |
74 | .toggle-locale {
75 | position: absolute;
76 | z-index: 1;
77 | top: 0;
78 | right: 1px;
79 | opacity: 0.3;
80 |
81 | &:hover {
82 | opacity: 1;
83 | }
84 |
85 | &::after {
86 | display: none !important;
87 | }
88 |
89 | select {
90 | font-weight: bold;
91 | padding: 0.4rem 0.5rem 0.5rem !important;
92 | text-transform: capitalize;
93 | border: none;
94 | background-color: transparent;
95 | }
96 | }
97 |
98 | .toggle-pad {
99 | padding-right: 32px;
100 | }
101 |
102 | // tinymce
103 | .mce-statusbar {
104 | border: none !important;
105 | }
106 |
107 | .mce-path {
108 | visibility: hidden !important;
109 | }
110 |
111 | .mce-panel {
112 | border-color: $mce-brdr !important;
113 | border-radius: 3px !important;
114 | }
115 |
116 | .mce-tinymce,
117 | .mce-top-part::before {
118 | box-shadow: none !important;
119 | }
120 |
121 | .mce-btn {
122 | &:hover,
123 | &:active {
124 | border-color: transparent !important;
125 | }
126 |
127 | button {
128 | padding: 4px 8px !important;
129 | }
130 | }
131 |
132 | .mce-btn-group:not(:first-child) {
133 | border-left: none !important;
134 | }
135 |
136 | .mce-btn,
137 | .mce-ico {
138 | color: $mce-btn !important;
139 | }
140 |
141 | // ace
142 | #ace-editor {
143 | width: 100%;
144 | height: 500px;
145 | }
146 |
147 | // menu
148 | .menu-item {
149 | margin-bottom: 0.5em !important;
150 | padding: 0.5em;
151 | padding-left: 1em;
152 | }
153 |
154 | .dragArea {
155 | display: block;
156 | min-height: 25px;
157 | }
158 |
159 | .ghost {
160 | opacity: 1;
161 | }
162 |
163 | .is-white {
164 | color: white;
165 | }
166 |
--------------------------------------------------------------------------------
/src/resources/lang/en/messages.php:
--------------------------------------------------------------------------------
1 | 'Access',
5 | 'account' => 'Account',
6 | 'action' => 'Action',
7 | 'add_new' => 'Add new',
8 | 'avatar' => 'Avatar',
9 | 'background' => 'Background',
10 | 'bio' => 'Bio',
11 | 'body' => 'Body',
12 | 'content' => 'Content',
13 | 'control' => 'Control',
14 | 'cover' => 'Cover',
15 | 'icon' => 'Icon',
16 | 'create_new' => 'Create new',
17 | 'delete' => 'Delete',
18 | 'delete_selected' => 'Delete Selected',
19 | 'desc' => 'Description',
20 | 'edit' => 'Edit',
21 | 'email' => 'Email',
22 | 'find' => 'Find',
23 | 'go_back' => 'Go Back',
24 | 'guards' => 'Guards',
25 | 'locals' => 'Title Available In',
26 | 'menus' => 'Menus',
27 | 'meta' => 'Meta Keywords',
28 | 'middlewares' => 'MiddleWares',
29 | 'model_created' => 'Model Created !',
30 | 'model_deleted' => 'Model Deleted !',
31 | 'model_deleted_perm' => 'Model Deleted Permanently !',
32 | 'model_updated' => 'Model Updated !',
33 | 'models_deleted' => 'Models Deleted !',
34 | 'name' => 'Name',
35 | 'no_entries' => 'No Data To Display',
36 | 'ops' => 'Operations',
37 | 'pages' => 'Pages',
38 | 'password' => 'Password',
39 | 'perm_delete' => 'Permanently Delete',
40 | 'permissions' => 'Permissions',
41 | 'regex' => 'The :attribute must have an "@"',
42 | 'remove_child' => 'Remove Child',
43 | 'remove_page' => 'Remove Page',
44 | 'restore' => 'Restore',
45 | 'roles' => 'Roles',
46 | 'route' => 'Route Name',
47 | 'route_name' => 'Route Name',
48 | 'save' => 'Save',
49 | 'select_all' => 'Select All',
50 | 'select_non' => 'Select Non',
51 | 'status' => 'Status',
52 | 'template' => 'Template',
53 | 'title' => 'Title',
54 | 'undo' => 'Undo',
55 | 'update' => 'Update',
56 | 'url' => 'Url',
57 | 'url_prefix' => 'Url Prefix',
58 | 'users' => 'Users',
59 | ];
60 |
--------------------------------------------------------------------------------
/src/resources/pagination/bulma.blade.php:
--------------------------------------------------------------------------------
1 | @if ($paginator->hasPages())
2 |
39 | @endif
40 |
--------------------------------------------------------------------------------
/src/resources/views/admin/admin.blade.php:
--------------------------------------------------------------------------------
1 | @include("SimpleMenu::admin.shared")
2 |
--------------------------------------------------------------------------------
/src/resources/views/admin/editors.blade.php:
--------------------------------------------------------------------------------
1 | {{-- choices --}}
2 |
3 | {{-- tinymce --}}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | {{-- ace --}}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/resources/views/admin/menus/create.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title'){{ trans('SimpleMenu::messages.create_new') }} {{ trans('SimpleMenu::messages.menus') }}@endsection
3 |
4 | @section('sub')
5 |
8 |
9 | {{ Form::open(['method' => 'POST', 'route' => $crud_prefix.'.menus.store']) }}
10 |
11 | {{-- name --}}
12 |
13 | {{ Form::label('name', trans('SimpleMenu::messages.name'), ['class' => 'label']) }}
14 |
15 |
16 |
17 | {{ Form::text('name', null, ['class' => 'input', 'placeholder' => 'name']) }}
18 | @if($errors->has('name'))
19 |
20 | {{ $errors->first('name') }}
21 |
22 | @endif
23 |
24 |
25 | {{ Form::submit(trans('SimpleMenu::messages.save'), ['class' => 'button is-success']) }}
26 |
27 |
28 |
29 | {{ Form::close() }}
30 | @endsection
31 |
--------------------------------------------------------------------------------
/src/resources/views/admin/menus/edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title'){{ trans('SimpleMenu::messages.edit') }} "{{ $menu->name }}"@endsection
3 |
4 | @section('sub')
5 |
6 |
7 |
12 |
13 | {{-- create new --}}
14 |
20 |
21 | {{-- delete --}}
22 |
23 | {{ Form::open(['method' => 'DELETE', 'route' => [$crud_prefix.'.menus.destroy', $menu->id]]) }}
24 |
25 | {{ Form::close() }}
26 |
27 |
28 |
29 |
30 |
31 |
37 |
38 | {{ Form::model($menu, ['method' => 'PUT', 'route' => [$crud_prefix.'.menus.update', $menu->id]]) }}
39 |
40 | {{-- name --}}
41 |
42 | {{ Form::label('name', trans('SimpleMenu::messages.name'), ['class' => 'label']) }}
43 |
44 |
45 |
46 | {{ Form::text('name', $menu->name, ['class' => 'input']) }}
47 | @if($errors->has('name'))
48 |
49 | {{ $errors->first('name') }}
50 |
51 | @endif
52 |
53 |
54 | {{ Form::submit(trans('SimpleMenu::messages.update'), ['class' => 'button is-warning']) }}
55 |
56 |
57 |
58 |
59 | {{-- pages --}}
60 |
68 |
69 | {{-- main --}}
70 |
96 |
97 | {{-- childs --}}
98 |
109 |
110 |
111 |
112 |
113 | {{-- all_pages --}}
114 |
120 |
130 |
131 |
132 |
133 |
134 | {{ Form::close() }}
135 |
136 |
137 | @endsection
138 |
--------------------------------------------------------------------------------
/src/resources/views/admin/menus/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title', trans('SimpleMenu::messages.menus'))
3 |
4 | @section('sub')
5 |
6 |
7 |
8 |
9 |
10 | {{-- delete multi --}}
11 |
12 |
13 | {{ Form::open(['route' => $crud_prefix.'.menus.destroy_multi']) }}
14 |
15 |
18 | {{ Form::close() }}
19 |
20 |
21 |
22 | {{-- add new --}}
23 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{ trans('SimpleMenu::messages.menus') }} "@{{ itemsCount }}"
36 |
37 |
38 |
39 | {{-- search --}}
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
51 |
52 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | |
69 | {{ trans('SimpleMenu::messages.name') }} |
70 | {{ trans('SimpleMenu::messages.ops') }} |
71 |
72 |
73 |
74 |
75 | @foreach ($menus as $menu)
76 |
105 | @endforeach
106 |
107 |
108 | {{ trans('SimpleMenu::messages.no_entries') }} |
109 |
110 |
111 |
112 |
113 |
114 | @endsection
115 |
--------------------------------------------------------------------------------
/src/resources/views/admin/pages/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title', trans('SimpleMenu::messages.pages'))
3 |
4 | @section('sub')
5 |
6 |
7 |
8 |
9 |
10 | {{-- delete multi --}}
11 |
12 |
13 | {{ Form::open(['route' => $crud_prefix.'.pages.destroy_multi']) }}
14 |
15 |
18 | {{ Form::close() }}
19 |
20 |
21 |
22 | {{-- add new --}}
23 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{ trans('SimpleMenu::messages.pages') }} "@{{ itemsCount }}"
36 |
37 |
38 |
39 | {{-- search --}}
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
51 |
52 |
56 |
57 |
58 |
59 |
60 |
61 |
190 |
191 |
192 | @endsection
193 |
--------------------------------------------------------------------------------
/src/resources/views/admin/permissions/create.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title'){{ trans('SimpleMenu::messages.create_new') }} {{ trans('SimpleMenu::messages.permissions') }}@endsection
3 |
4 | @section('sub')
5 |
8 |
9 | {{ Form::open(['method' => 'POST', 'route' => $crud_prefix.'.permissions.store']) }}
10 |
11 | {{-- name --}}
12 |
13 | {{ Form::label('name', trans('SimpleMenu::messages.name'), ['class' => 'label']) }}
14 |
15 |
16 |
17 | {{ Form::text('name', null, ['class' => 'input']) }}
18 | @if($errors->has('name'))
19 |
20 | {{ $errors->first('name') }}
21 |
22 | @endif
23 |
24 |
25 | {{ Form::submit(trans('SimpleMenu::messages.save'), ['class' => 'button is-success']) }}
26 |
27 |
28 |
29 | {{ Form::close() }}
30 | @endsection
31 |
--------------------------------------------------------------------------------
/src/resources/views/admin/permissions/edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title'){{ trans('SimpleMenu::messages.edit') }} "{{ $permission->name }}"@endsection
3 |
4 | @section('sub')
5 |
6 |
11 |
12 | {{-- create new --}}
13 |
19 |
20 | {{-- delete --}}
21 |
22 | @php
23 | $check = in_array($permission->name, auth()->user()->permissions->pluck('name')->toArray())
24 | ? 'disabled'
25 | : '';
26 | @endphp
27 |
28 | {{ Form::open(['method' => 'DELETE', 'route' => [$crud_prefix.'.permissions.destroy', $permission->id]]) }}
29 |
32 | {{ Form::close() }}
33 |
34 |
35 |
36 |
37 | {{ Form::model($permission, ['method' => 'PUT', 'route' => [$crud_prefix.'.permissions.update', $permission->id]]) }}
38 |
39 | {{-- name --}}
40 |
41 | {{ Form::label('name', trans('SimpleMenu::messages.name'), ['class' => 'label']) }}
42 |
43 |
44 |
45 | {{ Form::text('name', $permission->name, ['class' => 'input']) }}
46 | @if($errors->has('name'))
47 |
48 | {{ $errors->first('name') }}
49 |
50 | @endif
51 |
52 |
53 | {{ Form::submit(trans('SimpleMenu::messages.update'), ['class' => 'button is-warning']) }}
54 |
55 |
56 |
57 | {{ Form::close() }}
58 | @endsection
59 |
--------------------------------------------------------------------------------
/src/resources/views/admin/permissions/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title', trans('SimpleMenu::messages.permissions'))
3 |
4 | @section('sub')
5 |
6 |
7 |
8 |
9 |
10 | {{-- delete multi --}}
11 |
12 |
13 | {{ Form::open(['route' => $crud_prefix.'.permissions.destroy_multi']) }}
14 |
15 |
18 | {{ Form::close() }}
19 |
20 |
21 |
22 | {{-- add new --}}
23 |
29 |
30 |
31 |
32 |
33 |
34 | {{ trans('SimpleMenu::messages.permissions') }} "@{{ itemsCount }}"
35 |
36 |
37 |
38 | {{-- search --}}
39 |
40 |
41 |
42 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
121 |
122 |
123 | @endsection
124 |
--------------------------------------------------------------------------------
/src/resources/views/admin/roles/create.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title'){{ trans('SimpleMenu::messages.create_new') }} {{ trans('SimpleMenu::messages.roles') }}@endsection
3 |
4 | @section('sub')
5 |
8 |
9 |
10 | {{ Form::open(['method' => 'POST', 'route' => $crud_prefix.'.roles.store']) }}
11 |
12 | {{-- name --}}
13 |
14 | {{ Form::label('name', trans('SimpleMenu::messages.name'), ['class' => 'label']) }}
15 |
16 | {{ Form::text('name', null, ['class' => 'input']) }}
17 |
18 | @if($errors->has('name'))
19 |
20 | {{ $errors->first('name') }}
21 |
22 | @endif
23 |
24 |
25 | {{-- permissions --}}
26 |
27 | {{ Form::label('permissions', trans('SimpleMenu::messages.permissions'), ['class' => 'label']) }}
28 |
29 | {{ Form::select('permissions[]', $permissions, null, ['class' => 'select2', 'multiple' => 'multiple']) }}
30 |
31 | @if($errors->has('permissions'))
32 |
33 | {{ $errors->first('permissions') }}
34 |
35 | @endif
36 |
37 |
38 | {{ Form::submit(trans('SimpleMenu::messages.save'), ['class' => 'button is-success']) }}
39 | {{ Form::close() }}
40 |
41 | @endsection
42 |
--------------------------------------------------------------------------------
/src/resources/views/admin/roles/edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title'){{ trans('SimpleMenu::messages.edit') }} "{{ $role->name }}"@endsection
3 |
4 | @section('sub')
5 |
6 |
11 |
12 | {{-- create new --}}
13 |
19 | {{-- delete --}}
20 |
21 | @php
22 | $check = in_array($role->name, auth()->user()->roles->pluck('name')->toArray())
23 | ? 'disabled'
24 | : '';
25 | @endphp
26 |
27 | {{ Form::open(['method' => 'DELETE', 'route' => [$crud_prefix.'.roles.destroy', $role->id]]) }}
28 |
31 | {{ Form::close() }}
32 |
33 |
34 |
35 |
36 |
37 | {{ Form::model($role, ['method' => 'PUT', 'route' => [$crud_prefix.'.roles.update', $role->id]]) }}
38 |
39 | {{-- name --}}
40 |
41 | {{ Form::label('name', trans('SimpleMenu::messages.name'), ['class' => 'label']) }}
42 |
43 | {{ Form::text('name', $role->name, ['class' => 'input']) }}
44 |
45 | @if($errors->has('name'))
46 |
47 | {{ $errors->first('name') }}
48 |
49 | @endif
50 |
51 |
52 | {{-- permissions --}}
53 |
54 | {{ Form::label('permissions', trans('SimpleMenu::messages.permissions'), ['class' => 'label']) }}
55 |
56 | {{ Form::select(
57 | 'permissions[]',
58 | $permissions,
59 | $role->permissions->pluck('name', 'name'),
60 | ['class' => 'select2', 'multiple' => 'multiple']
61 | ) }}
62 |
63 | @if($errors->has('permissions'))
64 |
65 | {{ $errors->first('permissions') }}
66 |
67 | @endif
68 |
69 |
70 | {{ Form::submit(trans('SimpleMenu::messages.update'), ['class' => 'button is-warning']) }}
71 | {{ Form::close() }}
72 |
73 | @endsection
74 |
--------------------------------------------------------------------------------
/src/resources/views/admin/roles/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title', trans('SimpleMenu::messages.roles'))
3 |
4 | @section('sub')
5 |
6 |
7 |
8 |
9 |
10 | {{-- delete multi --}}
11 |
12 |
13 | {{ Form::open(['route' => $crud_prefix.'.roles.destroy_multi']) }}
14 |
15 |
18 | {{ Form::close() }}
19 |
20 |
21 |
22 | {{-- add new --}}
23 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{ trans('SimpleMenu::messages.roles') }} "@{{ itemsCount }}"
36 |
37 |
38 |
39 | {{-- search --}}
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
51 |
52 |
56 |
57 |
58 |
59 |
60 |
61 |
130 |
131 |
132 | @endsection
133 |
--------------------------------------------------------------------------------
/src/resources/views/admin/shared.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | @yield('title', '')
10 |
11 | {{-- styles --}}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | {{-- notif --}}
21 |
22 | {{-- Status --}}
23 | @if (session('status'))
24 |
29 |
30 | @endif
31 |
32 |
33 |
34 |
35 | {{-- Body --}}
36 |
37 |
38 | {{-- Sidebar --}}
39 |
40 |
76 |
77 |
78 | {{-- Pages --}}
79 |
80 | @yield('sub')
81 |
82 |
83 |
84 |
85 |
86 | {{-- Footer --}}
87 | @include("SimpleMenu::admin.editors")
88 | {{-- app --}}
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/src/resources/views/admin/users/create.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title'){{ trans('SimpleMenu::messages.create_new') }} {{ trans('SimpleMenu::messages.users') }}@endsection
3 |
4 | @section('sub')
5 |
8 |
9 |
10 | {{ Form::open(['method' => 'POST', 'route' => $crud_prefix.'.users.store', 'files' => true]) }}
11 |
12 | {{-- avatar --}}
13 |
14 |
15 |
{{ trans('SimpleMenu::messages.avatar') }}
16 |
17 |
18 |
19 |
20 |
21 |
22 | {{-- Account --}}
23 |
24 | {{-- data --}}
25 |
26 |
{{ trans('SimpleMenu::messages.account') }}
27 |
28 |
29 | {{-- name --}}
30 |
31 | {{ Form::label('name', trans('SimpleMenu::messages.name'), ['class' => 'label']) }}
32 |
33 | {{ Form::text('name', null, ['class' => 'input']) }}
34 |
35 | @if($errors->has('name'))
36 |
37 | {{ $errors->first('name') }}
38 |
39 | @endif
40 |
41 |
42 | {{-- email --}}
43 |
44 | {{ Form::label('email', trans('SimpleMenu::messages.email'), ['class' => 'label']) }}
45 |
46 | {{ Form::email('email', null, ['class' => 'input']) }}
47 |
48 | @if($errors->has('email'))
49 |
50 | {{ $errors->first('email') }}
51 |
52 | @endif
53 |
54 |
55 | {{-- password --}}
56 |
57 | {{ Form::label('password', trans('SimpleMenu::messages.password'), ['class' => 'label']) }}
58 |
59 | {{ Form::password('password', ['class' => 'input', 'placeholder' => '******']) }}
60 |
61 | @if($errors->has('password'))
62 |
63 | {{ $errors->first('password') }}
64 |
65 | @endif
66 |
67 |
68 |
69 |
70 |
71 | {{-- Guards --}}
72 |
73 |
74 |
75 | {{ trans('SimpleMenu::messages.guards') }}
76 |
77 |
78 |
79 | {{-- roles --}}
80 |
81 | {{ Form::label('roles', trans('SimpleMenu::messages.roles'), ['class' => 'label']) }}
82 |
83 | {{ Form::select(
84 | 'roles[]',
85 | $roles,
86 | null,
87 | ['class' => 'select2', 'multiple' => 'multiple']
88 | ) }}
89 |
90 | @if($errors->has('roles'))
91 |
92 | {{ $errors->first('roles') }}
93 |
94 | @endif
95 |
96 |
97 | {{-- permissions --}}
98 |
99 | {{ Form::label('permissions', trans('SimpleMenu::messages.permissions'), ['class' => 'label']) }}
100 |
101 | {{ Form::select(
102 | 'permissions[]',
103 | $permissions,
104 | null,
105 | ['class' => 'select2', 'multiple' => 'multiple']
106 | ) }}
107 |
108 | @if($errors->has('permissions'))
109 |
110 | {{ $errors->first('permissions') }}
111 |
112 | @endif
113 |
114 |
115 |
116 |
117 | {{-- Submit --}}
118 |
119 |
120 |
121 | {{ Form::submit(trans('SimpleMenu::messages.save'), ['class' => 'button is-success is-fullwidth']) }}
122 |
123 |
124 | {{ Form::close() }}
125 |
126 | @endsection
127 |
--------------------------------------------------------------------------------
/src/resources/views/admin/users/edit.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title'){{ trans('SimpleMenu::messages.edit') }} "{{ $user->name }}"@endsection
3 |
4 | @section('sub')
5 |
6 |
11 |
12 | {{-- create new --}}
13 |
19 | {{-- delete --}}
20 |
21 | @php
22 | $check = $user->id == auth()->user()->id ? 'disabled' : '';
23 | @endphp
24 |
25 | {{ Form::open(['method' => 'DELETE', 'route' => [$crud_prefix.'.users.destroy', $user->id]]) }}
26 |
29 | {{ Form::close() }}
30 |
31 |
32 |
33 |
34 |
35 | {{ Form::model($user, ['method' => 'PUT', 'route' => [$crud_prefix.'.users.update', $user->id], 'files' => true]) }}
36 |
37 | {{-- avatar --}}
38 |
39 |
40 |
{{ trans('SimpleMenu::messages.avatar') }}
41 |
42 |
43 | {{-- preview --}}
44 | @if ($user->avatar)
45 |

46 | @endif
47 | {{-- upload --}}
48 |
49 |
50 |
51 |
52 |
53 |
54 | {{-- Account --}}
55 |
56 | {{-- data --}}
57 |
58 |
{{ trans('SimpleMenu::messages.account') }}
59 |
60 |
61 | {{-- name --}}
62 |
63 | {{ Form::label('name', trans('SimpleMenu::messages.name'), ['class' => 'label']) }}
64 |
65 | {{ Form::text('name', $user->name, ['class' => 'input']) }}
66 |
67 | @if($errors->has('name'))
68 |
69 | {{ $errors->first('name') }}
70 |
71 | @endif
72 |
73 |
74 | {{-- email --}}
75 |
76 | {{ Form::label('email', trans('SimpleMenu::messages.email'), ['class' => 'label']) }}
77 |
78 | {{ Form::email('email', $user->email, ['class' => 'input']) }}
79 |
80 | @if($errors->has('email'))
81 |
82 | {{ $errors->first('email') }}
83 |
84 | @endif
85 |
86 |
87 | {{-- password --}}
88 |
89 | {{ Form::label('password', trans('SimpleMenu::messages.password'), ['class' => 'label']) }}
90 |
91 | {{ Form::password('password', ['class' => 'input', 'placeholder' => '******']) }}
92 |
93 | @if($errors->has('password'))
94 |
95 | {{ $errors->first('password') }}
96 |
97 | @endif
98 |
99 |
100 |
101 |
102 |
103 | {{-- Guards --}}
104 |
105 |
106 |
{{ trans('SimpleMenu::messages.guards') }}
107 |
108 |
109 | {{-- roles --}}
110 |
111 | {{ Form::label('roles', trans('SimpleMenu::messages.roles'), ['class' => 'label']) }}
112 |
113 | {{ Form::select(
114 | 'roles[]',
115 | $roles,
116 | $user->roles->pluck('name', 'name'),
117 | ['class' => 'select2', 'multiple' => 'multiple']
118 | ) }}
119 |
120 | @if($errors->has('roles'))
121 |
122 | {{ $errors->first('roles') }}
123 |
124 | @endif
125 |
126 |
127 | {{-- permissions --}}
128 |
129 | {{ Form::label('permissions', trans('SimpleMenu::messages.permissions'), ['class' => 'label']) }}
130 |
131 | {{ Form::select(
132 | 'permissions[]',
133 | $permissions,
134 | $user->permissions->pluck('name', 'name'),
135 | ['class' => 'select2', 'multiple' => 'multiple']
136 | ) }}
137 |
138 | @if($errors->has('permissions'))
139 |
140 | {{ $errors->first('permissions') }}
141 |
142 | @endif
143 |
144 |
145 |
146 |
147 | {{-- Submit --}}
148 |
149 |
150 |
151 | {{ Form::submit(trans('SimpleMenu::messages.update'), ['class' => 'button is-warning is-fullwidth']) }}
152 |
153 |
154 |
155 | {{ Form::close() }}
156 |
157 | @endsection
158 |
--------------------------------------------------------------------------------
/src/resources/views/admin/users/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends("SimpleMenu::admin.shared")
2 | @section('title', trans('SimpleMenu::messages.users'))
3 |
4 | @section('sub')
5 |
6 |
7 |
8 |
9 |
10 | {{-- delete multi --}}
11 |
12 |
13 | {{ Form::open(['route' => $crud_prefix.'.users.destroy_multi']) }}
14 |
15 |
18 | {{ Form::close() }}
19 |
20 |
21 |
22 | {{-- add new --}}
23 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{ trans('SimpleMenu::messages.users') }} "@{{ itemsCount }}"
36 |
37 |
38 |
39 | {{-- search --}}
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
51 |
52 |
56 |
57 |
58 |
59 |
60 |
61 |
138 |
139 |
140 | @endsection
141 |
--------------------------------------------------------------------------------
/src/resources/views/breadCrumb.blade.php:
--------------------------------------------------------------------------------
1 | @if ($breadCrumb = SimpleMenu::getBC())
2 |
15 |
16 | @endif
17 |
--------------------------------------------------------------------------------
/src/resources/views/langSwitcher.blade.php:
--------------------------------------------------------------------------------
1 |
2 | @foreach(SimpleMenu::AppLocales() as $code)
3 | -
4 |
8 | {{ $code }}
9 |
10 |
11 | @if (!$loop->last)
12 | - /
13 | @endif
14 | @endforeach
15 |
--------------------------------------------------------------------------------
/src/resources/views/menu/example.blade.php:
--------------------------------------------------------------------------------
1 | @if (isset($PAGES))
2 |
3 | @foreach ($PAGES as $page)
4 |
5 | @include('SimpleMenu::menu.partials.r_params')
6 |
7 | -
8 |
9 |
10 | @if ($childs = $page->nests)
11 | @include('SimpleMenu::menu.partials.nested', ['items' => $childs])
12 | @endif
13 |
14 | @endforeach
15 |
16 | @endif
17 |
--------------------------------------------------------------------------------
/src/resources/views/menu/partials/nested.blade.php:
--------------------------------------------------------------------------------
1 |
2 | @foreach ($items as $page)
3 | @include('SimpleMenu::menu.partials.r_params')
4 |
5 | -
6 |
7 |
8 | @if ($childs = $page->nests)
9 | @include('SimpleMenu::menu.partials.nested', ['items' => $childs])
10 | @endif
11 |
12 | @endforeach
13 |
14 |
--------------------------------------------------------------------------------
/src/resources/views/menu/partials/r_params.blade.php:
--------------------------------------------------------------------------------
1 | {{-- simple --}}
2 | @php
3 | SimpleMenu::getRoute($page->route_name);
4 | @endphp
5 |
6 | {{-- advanced --}}
7 | {{-- @php
8 | SimpleMenu::getRoute($page->route_name, [
9 | 'about' => ['name'=> isset($var) ? $var : 'default'],
10 | 'contact-us' => ['name'=>'other'],
11 | ])
12 | @endphp --}}
--------------------------------------------------------------------------------
/src/resources/views/template-example.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{ $title }}
11 |
12 | {{-- styles --}}
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
{!! $title !!}
27 |
{!! $desc !!}
28 |
{!! $body !!}
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------