first upload all files
This commit is contained in:
69
Modules/Menu/Admin/MenuItemTabs.php
Normal file
69
Modules/Menu/Admin/MenuItemTabs.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Admin;
|
||||
|
||||
use Modules\Admin\Ui\Tab;
|
||||
use Modules\Admin\Ui\Tabs;
|
||||
use Modules\Page\Entities\Page;
|
||||
use Modules\Menu\Entities\MenuItem;
|
||||
use Modules\Category\Entities\Category;
|
||||
|
||||
class MenuItemTabs extends Tabs
|
||||
{
|
||||
/**
|
||||
* Make new tabs with groups.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function make()
|
||||
{
|
||||
$this->group('menu_item_information', trans('menu::menu_items.tabs.group.menu_item_information'))
|
||||
->active()
|
||||
->add($this->general())
|
||||
->add($this->image());
|
||||
}
|
||||
|
||||
private function general()
|
||||
{
|
||||
return tap(new Tab('general', trans('menu::menu_items.tabs.general')), function (Tab $tab) {
|
||||
$tab->active();
|
||||
$tab->weight(5);
|
||||
$tab->view('menu::admin.menu_items.tabs.general', [
|
||||
'categories' => $this->categories(),
|
||||
'pages' => $this->pages(),
|
||||
'parentMenuItems' => $this->parentMenuItems(),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
private function categories()
|
||||
{
|
||||
return Category::where('parent_id', null)->get()->sortBy('name')->pluck('name', 'id')
|
||||
->prepend(trans('menu::menu_items.form.select_category'), '');
|
||||
}
|
||||
|
||||
private function pages()
|
||||
{
|
||||
return Page::all()->sortBy('name')->pluck('name', 'id')
|
||||
->prepend(trans('menu::menu_items.form.select_page'), '');
|
||||
}
|
||||
|
||||
private function parentMenuItems()
|
||||
{
|
||||
$parentMenuItems = ['' => trans('menu::menu_items.form.select_parent')];
|
||||
|
||||
return $parentMenuItems += MenuItem::parents(request('menuId'), request('id'));
|
||||
}
|
||||
|
||||
private function image()
|
||||
{
|
||||
return tap(new Tab('image', trans('menu::menu_items.tabs.image')), function (Tab $tab) {
|
||||
if (! auth()->user()->hasAccess('admin.media.index')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tab->weight(10);
|
||||
$tab->view('menu::admin.menu_items.tabs.image');
|
||||
});
|
||||
}
|
||||
}
|
||||
22
Modules/Menu/Config/assets.php
Normal file
22
Modules/Menu/Config/assets.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Define which assets will be available through the asset manager
|
||||
|--------------------------------------------------------------------------
|
||||
| These assets are registered on the asset manager
|
||||
*/
|
||||
'all_assets' => [
|
||||
'admin.menu.css' => ['module' => 'menu:admin/css/menu.css'],
|
||||
'admin.menu.js' => ['module' => 'menu:admin/js/menu.js'],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Define which default assets will always be included in your pages
|
||||
| through the asset pipeline
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'required_assets' => [],
|
||||
];
|
||||
16
Modules/Menu/Config/permissions.php
Normal file
16
Modules/Menu/Config/permissions.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'admin.menus' => [
|
||||
'index' => 'menu::permissions.menus.index',
|
||||
'create' => 'menu::permissions.menus.create',
|
||||
'edit' => 'menu::permissions.menus.edit',
|
||||
'destroy' => 'menu::permissions.menus.destroy',
|
||||
],
|
||||
'admin.menu_items' => [
|
||||
'index' => 'menu::permissions.menu_items.index',
|
||||
'create' => 'menu::permissions.menu_items.create',
|
||||
'edit' => 'menu::permissions.menu_items.edit',
|
||||
'destroy' => 'menu::permissions.menu_items.destroy',
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMenusTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('menus', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->boolean('is_active');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('menus');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMenuTranslationsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('menu_translations', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('menu_id')->unsigned();
|
||||
$table->string('locale');
|
||||
$table->string('name');
|
||||
|
||||
$table->unique(['menu_id', 'locale']);
|
||||
$table->foreign('menu_id')->references('id')->on('menus')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('menu_translations');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMenuitemsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('menu_items', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('menu_id')->unsigned()->index();
|
||||
$table->integer('parent_id')->unsigned()->nullable();
|
||||
$table->integer('category_id')->unsigned()->nullable();
|
||||
$table->integer('page_id')->unsigned()->nullable();
|
||||
$table->string('type');
|
||||
$table->string('url')->nullable();
|
||||
$table->string('target');
|
||||
$table->integer('position')->unsigned()->nullable();
|
||||
$table->boolean('is_root')->default(false);
|
||||
$table->boolean('is_fluid');
|
||||
$table->boolean('is_active');
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('menu_id')->references('id')->on('menus')->onDelete('cascade');
|
||||
$table->foreign('parent_id')->references('id')->on('menu_items')->onDelete('cascade');
|
||||
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
|
||||
$table->foreign('page_id')->references('id')->on('pages')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('menu_items');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMenuitemTranslationTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('menu_item_translations', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('menu_item_id')->unsigned();
|
||||
$table->string('locale');
|
||||
$table->string('name');
|
||||
|
||||
$table->unique(['menu_item_id', 'locale']);
|
||||
$table->foreign('menu_item_id')->references('id')->on('menu_items')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('menu_item_translations');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddIconColumnToMenuItemsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('menu_items', function (Blueprint $table) {
|
||||
$table->string('icon')->nullable()->after('url');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('menu_items', function (Blueprint $table) {
|
||||
$table->dropColumn('icon');
|
||||
});
|
||||
}
|
||||
}
|
||||
19
Modules/Menu/Database/Seeders/MenuDatabaseSeeder.php
Normal file
19
Modules/Menu/Database/Seeders/MenuDatabaseSeeder.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class MenuDatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Model::unguard();
|
||||
}
|
||||
}
|
||||
77
Modules/Menu/Entities/Menu.php
Normal file
77
Modules/Menu/Entities/Menu.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Entities;
|
||||
|
||||
use Modules\Admin\Ui\AdminTable;
|
||||
use Modules\Support\Eloquent\Model;
|
||||
use Modules\Support\Eloquent\Translatable;
|
||||
|
||||
class Menu extends Model
|
||||
{
|
||||
use Translatable;
|
||||
|
||||
/**
|
||||
* The relations to eager load on every query.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $with = ['translations'];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = ['is_active'];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that are translatable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $translatedAttributes = ['name'];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::addActiveGlobalScope();
|
||||
}
|
||||
|
||||
public static function for($menuId)
|
||||
{
|
||||
return static::findOrNew($menuId)
|
||||
->menuItems()
|
||||
->with(['category', 'page', 'files'])
|
||||
->get()
|
||||
->noCleaning()
|
||||
->nest();
|
||||
}
|
||||
|
||||
public function menuItems()
|
||||
{
|
||||
return $this->hasMany(MenuItem::class)->orderByRaw('-position DESC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table data for the resource
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function table()
|
||||
{
|
||||
return new AdminTable($this->newQuery()->withoutGlobalScope('active'));
|
||||
}
|
||||
}
|
||||
232
Modules/Menu/Entities/MenuItem.php
Normal file
232
Modules/Menu/Entities/MenuItem.php
Normal file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Entities;
|
||||
|
||||
use TypiCMS\NestableTrait;
|
||||
use Modules\Page\Entities\Page;
|
||||
use Modules\Media\Entities\File;
|
||||
use Modules\Support\Eloquent\Model;
|
||||
use Modules\Media\Eloquent\HasMedia;
|
||||
use Modules\Category\Entities\Category;
|
||||
use Modules\Support\Eloquent\Translatable;
|
||||
|
||||
class MenuItem extends Model
|
||||
{
|
||||
use Translatable, NestableTrait, HasMedia;
|
||||
|
||||
/**
|
||||
* The relations to eager load on every query.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $with = ['translations'];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'menu_id',
|
||||
'category_id',
|
||||
'page_id',
|
||||
'parent_id',
|
||||
'type',
|
||||
'url',
|
||||
'icon',
|
||||
'target',
|
||||
'position',
|
||||
'is_root',
|
||||
'is_fluid',
|
||||
'is_active',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'is_root' => 'boolean',
|
||||
'is_fluid' => 'boolean',
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* The accessors to append to the model's array form.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $appends = ['background_image'];
|
||||
|
||||
/**
|
||||
* The attributes that are translatable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $translatedAttributes = ['name'];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::addGlobalScope('not_root', function ($query) {
|
||||
$query->where('is_root', false);
|
||||
});
|
||||
|
||||
static::addActiveGlobalScope();
|
||||
}
|
||||
|
||||
public function menu()
|
||||
{
|
||||
return $this->belongsTo(Menu::class);
|
||||
}
|
||||
|
||||
public function children()
|
||||
{
|
||||
return $this->hasMany(MenuItem::class, 'parent_id');
|
||||
}
|
||||
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(Category::class);
|
||||
}
|
||||
|
||||
public function page()
|
||||
{
|
||||
return $this->belongsTo(Page::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the menu item's page id.
|
||||
*
|
||||
* @param int $pageId
|
||||
* @return void
|
||||
*/
|
||||
public function setPageIdAttribute($pageId)
|
||||
{
|
||||
$this->attributes['page_id'] = $pageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the menu item's parent id.
|
||||
*
|
||||
* @param int $parentId
|
||||
* @return void
|
||||
*/
|
||||
public function setParentIdAttribute($parentId)
|
||||
{
|
||||
$this->attributes['parent_id'] = $parentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the menu item's background image.
|
||||
*
|
||||
* @return \Modules\Media\Entities\File
|
||||
*/
|
||||
public function getBackgroundImageAttribute()
|
||||
{
|
||||
return $this->files->where('pivot.zone', 'background_image')->first() ?: new File;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the menu item has any children.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasChildren()
|
||||
{
|
||||
return $this->items->isNotEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the menu item type is category.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCategoryType()
|
||||
{
|
||||
return $this->type === 'category';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the menu item type is page.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPageType()
|
||||
{
|
||||
return $this->type === 'page';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the menu item type is url.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isUrlType()
|
||||
{
|
||||
return $this->type === 'url';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public url for the menu item.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
if ($this->isCategoryType()) {
|
||||
return optional($this->category)->url();
|
||||
}
|
||||
|
||||
if ($this->isPageType()) {
|
||||
return optional($this->page)->url();
|
||||
}
|
||||
|
||||
if ($this->getAttributeFromArray('url') === '#') {
|
||||
return '#';
|
||||
}
|
||||
|
||||
if (filter_var($this->getAttributeFromArray('url'), FILTER_VALIDATE_URL)) {
|
||||
return $this->getAttributeFromArray('url');
|
||||
}
|
||||
|
||||
return localized_url(locale(), $this->getAttributeFromArray('url'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root menu item for the given menu id.
|
||||
*
|
||||
* @param int $menuId
|
||||
* @return $this
|
||||
*/
|
||||
public static function root($menuId)
|
||||
{
|
||||
return static::withoutGlobalScope('not_root')
|
||||
->where('menu_id', $menuId)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parents of the given menuId.
|
||||
*
|
||||
* @param int $menuId
|
||||
* @param int $menuItemId
|
||||
* @return array
|
||||
*/
|
||||
public static function parents($menuId, $menuItemId)
|
||||
{
|
||||
return static::withoutGlobalScope('active')
|
||||
->where('id', '!=', $menuItemId)
|
||||
->where('menu_id', $menuId)
|
||||
->get()
|
||||
->noCleaning()
|
||||
->nest()
|
||||
->setIndent('¦–– ')
|
||||
->listsFlattened('name');
|
||||
}
|
||||
}
|
||||
15
Modules/Menu/Entities/MenuItemTranslation.php
Normal file
15
Modules/Menu/Entities/MenuItemTranslation.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Entities;
|
||||
|
||||
use Modules\Support\Eloquent\TranslationModel;
|
||||
|
||||
class MenuItemTranslation extends TranslationModel
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = ['name'];
|
||||
}
|
||||
15
Modules/Menu/Entities/MenuTranslation.php
Normal file
15
Modules/Menu/Entities/MenuTranslation.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Entities;
|
||||
|
||||
use Modules\Support\Eloquent\TranslationModel;
|
||||
|
||||
class MenuTranslation extends TranslationModel
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = ['name'];
|
||||
}
|
||||
34
Modules/Menu/Events/Listeners/CreateRootMenuItem.php
Normal file
34
Modules/Menu/Events/Listeners/CreateRootMenuItem.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Events\Listeners;
|
||||
|
||||
use Modules\Menu\Entities\Menu;
|
||||
use Modules\Menu\Entities\MenuItem;
|
||||
|
||||
class CreateRootMenuItem
|
||||
{
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \Modules\Menu\Entities\Menu $menu
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Menu $menu)
|
||||
{
|
||||
$data = [
|
||||
'menu_id' => $menu->id,
|
||||
'type' => 'URL',
|
||||
'target' => '_self',
|
||||
'position' => 0,
|
||||
'is_root' => true,
|
||||
'is_fluid' => false,
|
||||
'is_active' => true,
|
||||
];
|
||||
|
||||
foreach (supported_locales() as $locale => $language) {
|
||||
$data[$locale]['name'] = 'root';
|
||||
}
|
||||
|
||||
MenuItem::create($data);
|
||||
}
|
||||
}
|
||||
70
Modules/Menu/Http/Controllers/Admin/MenuController.php
Normal file
70
Modules/Menu/Http/Controllers/Admin/MenuController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Http\Controllers\Admin;
|
||||
|
||||
use Modules\Menu\Entities\Menu;
|
||||
use Modules\Admin\Traits\HasCrudActions;
|
||||
use Modules\Menu\Http\Requests\SaveMenuRequest;
|
||||
|
||||
class MenuController
|
||||
{
|
||||
use HasCrudActions;
|
||||
|
||||
/**
|
||||
* Model for the resource.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $model = Menu::class;
|
||||
|
||||
/**
|
||||
* Label of the resource.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label = 'menu::menus.menu';
|
||||
|
||||
/**
|
||||
* View path of the resource.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $viewPath = 'menu::admin.menus';
|
||||
|
||||
/**
|
||||
* Form requests for the resource.
|
||||
*
|
||||
* @var array|string
|
||||
*/
|
||||
protected $validation = SaveMenuRequest::class;
|
||||
|
||||
/**
|
||||
* Redirect to url after saving a resource.
|
||||
*
|
||||
* @param \Modules\Menu\Entities\Menu $menu
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function redirectTo($menu)
|
||||
{
|
||||
return redirect()->route('admin.menus.edit', $menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$menu = Menu::withoutGlobalScope('active')->findOrFail($id);
|
||||
|
||||
$menuItems = $menu->menuItems()
|
||||
->withoutGlobalScope('active')
|
||||
->withoutGlobalScope('not_root')
|
||||
->get()
|
||||
->nest();
|
||||
|
||||
return view('menu::admin.menus.edit', compact('menu', 'menuItems'));
|
||||
}
|
||||
}
|
||||
117
Modules/Menu/Http/Controllers/Admin/MenuItemController.php
Normal file
117
Modules/Menu/Http/Controllers/Admin/MenuItemController.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Http\Controllers\Admin;
|
||||
|
||||
use Modules\Menu\Entities\Menu;
|
||||
use Modules\Menu\Entities\MenuItem;
|
||||
use Modules\Admin\Ui\Facades\TabManager;
|
||||
use Modules\Menu\Http\Requests\SaveMenuItemRequest;
|
||||
|
||||
class MenuItemController
|
||||
{
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param int $menuId
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create($menuId)
|
||||
{
|
||||
$menuItem = new MenuItem;
|
||||
$tabs = TabManager::get('menu_items');
|
||||
|
||||
return view('menu::admin.menu_items.create', compact('menuId', 'menuItem', 'tabs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param int $menuId
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store($menuId, SaveMenuItemRequest $request)
|
||||
{
|
||||
$menuItem = MenuItem::create(
|
||||
$this->prepare($menuId, $request->all())
|
||||
);
|
||||
|
||||
return redirect()->route('admin.menus.edit', $menuId)
|
||||
->withSuccess(trans('admin::messages.resource_saved', ['resource' => trans('menu::menu_items.menu_item')]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $menuId
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit($menuId, $id)
|
||||
{
|
||||
$menuItem = MenuItem::withoutGlobalScope('active')->findOrFail($id);
|
||||
$tabs = TabManager::get('menu_items');
|
||||
|
||||
return view('menu::admin.menu_items.edit', compact('menuId', 'menuItem', 'tabs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param int $menuId
|
||||
* @param int $id
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update($menuId, $id, SaveMenuItemRequest $request)
|
||||
{
|
||||
MenuItem::withoutGlobalScope('active')
|
||||
->findOrFail($id)
|
||||
->update(
|
||||
$this->prepare($menuId, $request->all())
|
||||
);
|
||||
|
||||
return redirect()->route('admin.menus.edit', $menuId)
|
||||
->withSuccess(trans('admin::messages.resource_saved', ['resource' => trans('menu::menu_items.menu_item')]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
MenuItem::withoutGlobalScope('active')->findOrFail($id)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare menu item attributes for saving.
|
||||
*
|
||||
* @param int $menuId
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
private function prepare($menuId, array $attributes)
|
||||
{
|
||||
if (is_null($attributes['parent_id'])) {
|
||||
$attributes['parent_id'] = $this->parentId($menuId);
|
||||
}
|
||||
|
||||
return array_merge($attributes, ['menu_id' => $menuId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent id for the given menu id.
|
||||
*
|
||||
* @param string string
|
||||
* @return int
|
||||
*/
|
||||
private function parentId($menuId)
|
||||
{
|
||||
return MenuItem::withoutGlobalScope('not_root')
|
||||
->where('menu_id', $menuId)
|
||||
->value('id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Http\Controllers\Admin;
|
||||
|
||||
use Modules\Menu\Services\MenuItemOrdener;
|
||||
|
||||
class MenuItemOrderController
|
||||
{
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Modules\Menu\Services\MenuItemOrdener $ordener
|
||||
* @return void
|
||||
*/
|
||||
public function update(MenuItemOrdener $ordener)
|
||||
{
|
||||
$ordener->order(request()->json()->all());
|
||||
}
|
||||
}
|
||||
35
Modules/Menu/Http/Requests/SaveMenuItemRequest.php
Normal file
35
Modules/Menu/Http/Requests/SaveMenuItemRequest.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Http\Requests;
|
||||
|
||||
use Illuminate\Validation\Rule;
|
||||
use Modules\Core\Http\Requests\Request;
|
||||
|
||||
class SaveMenuItemRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Available attributes.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $availableAttributes = 'menu::attributes';
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => 'required',
|
||||
'type' => ['required', Rule::in('category', 'page', 'url')],
|
||||
'category_id' => 'required_if:type,category',
|
||||
'page_id' => 'required_if:type,page',
|
||||
'url' => 'required_if:type,url',
|
||||
'target' => ['required', Rule::in('_self', '_blank')],
|
||||
'is_fluid' => 'required|boolean',
|
||||
'is_active' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
}
|
||||
27
Modules/Menu/Http/Requests/SaveMenuRequest.php
Normal file
27
Modules/Menu/Http/Requests/SaveMenuRequest.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Http\Requests;
|
||||
|
||||
use Modules\Core\Http\Requests\Request;
|
||||
|
||||
class SaveMenuRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Available attributes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $availableAttributes = 'menu::attributes';
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => 'required',
|
||||
];
|
||||
}
|
||||
}
|
||||
31
Modules/Menu/MegaMenu/MegaMenu.php
Normal file
31
Modules/Menu/MegaMenu/MegaMenu.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\MegaMenu;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Modules\Menu\Entities\Menu as MenuModel;
|
||||
|
||||
class MegaMenu
|
||||
{
|
||||
private $menuId;
|
||||
|
||||
public function __construct($menuId)
|
||||
{
|
||||
$this->menuId = $menuId;
|
||||
}
|
||||
|
||||
public function menus()
|
||||
{
|
||||
return Cache::tags(['mega_menu', 'menu_items', 'pages', 'categories'])
|
||||
->rememberForever(md5("mega_menu.{$this->menuId}:" . locale()), function () {
|
||||
return $this->getMenus()->map(function ($menu) {
|
||||
return new Menu($menu);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private function getMenus()
|
||||
{
|
||||
return MenuModel::for($this->menuId)->where('menu_id', $this->menuId);
|
||||
}
|
||||
}
|
||||
89
Modules/Menu/MegaMenu/Menu.php
Normal file
89
Modules/Menu/MegaMenu/Menu.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\MegaMenu;
|
||||
|
||||
use Modules\Category\Entities\Category;
|
||||
|
||||
class Menu
|
||||
{
|
||||
private $menu;
|
||||
private $subMenus;
|
||||
|
||||
public function __construct($menu)
|
||||
{
|
||||
$this->menu = $menu;
|
||||
}
|
||||
|
||||
public function isFluid()
|
||||
{
|
||||
return $this->menu->is_fluid;
|
||||
}
|
||||
|
||||
public function url()
|
||||
{
|
||||
return $this->menu->url();
|
||||
}
|
||||
|
||||
public function hasIcon()
|
||||
{
|
||||
return ! is_null($this->icon());
|
||||
}
|
||||
|
||||
public function icon()
|
||||
{
|
||||
return $this->menu->icon;
|
||||
}
|
||||
|
||||
public function hasBackgroundImage()
|
||||
{
|
||||
return ! is_null($this->backgroundImage());
|
||||
}
|
||||
|
||||
public function backgroundImage()
|
||||
{
|
||||
return $this->menu->background_image->path;
|
||||
}
|
||||
|
||||
public function target()
|
||||
{
|
||||
return $this->menu->target;
|
||||
}
|
||||
|
||||
public function name()
|
||||
{
|
||||
return $this->menu->name;
|
||||
}
|
||||
|
||||
public function hasSubMenus()
|
||||
{
|
||||
return $this->subMenus()->isNotEmpty();
|
||||
}
|
||||
|
||||
public function subMenus()
|
||||
{
|
||||
if (! is_null($this->subMenus)) {
|
||||
return $this->subMenus;
|
||||
}
|
||||
|
||||
return $this->subMenus = $this->getSubMenus()->map(function ($subMenu) {
|
||||
return new SubMenu($subMenu);
|
||||
});
|
||||
}
|
||||
|
||||
private function getSubMenus()
|
||||
{
|
||||
if ($this->menu->isCategoryType()) {
|
||||
return $this->getCategorySubMenus();
|
||||
}
|
||||
|
||||
return $this->menu->items ?? collect();
|
||||
}
|
||||
|
||||
private function getCategorySubMenus()
|
||||
{
|
||||
return Category::tree()
|
||||
->where('id', $this->menu->category_id)
|
||||
->first()
|
||||
->items ?? collect();
|
||||
}
|
||||
}
|
||||
51
Modules/Menu/MegaMenu/SubMenu.php
Normal file
51
Modules/Menu/MegaMenu/SubMenu.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\MegaMenu;
|
||||
|
||||
use Modules\Category\Entities\Category;
|
||||
|
||||
class SubMenu
|
||||
{
|
||||
private $subMenu;
|
||||
private $subMenuItems;
|
||||
|
||||
public function __construct($subMenu)
|
||||
{
|
||||
$this->subMenu = $subMenu;
|
||||
}
|
||||
|
||||
public function url()
|
||||
{
|
||||
return $this->subMenu->url();
|
||||
}
|
||||
|
||||
public function target()
|
||||
{
|
||||
if ($this->subMenu instanceof Category) {
|
||||
return '_self';
|
||||
}
|
||||
|
||||
return $this->subMenu->target;
|
||||
}
|
||||
|
||||
public function name()
|
||||
{
|
||||
return $this->subMenu->name;
|
||||
}
|
||||
|
||||
public function hasItems()
|
||||
{
|
||||
return $this->items()->isNotEmpty();
|
||||
}
|
||||
|
||||
public function items()
|
||||
{
|
||||
if (! is_null($this->subMenuItems)) {
|
||||
return $this->subMenuItems;
|
||||
}
|
||||
|
||||
return $this->subMenuItems = $this->subMenu->items->map(function ($item) {
|
||||
return new SubMenu($item);
|
||||
});
|
||||
}
|
||||
}
|
||||
22
Modules/Menu/Providers/EventServiceProvider.php
Normal file
22
Modules/Menu/Providers/EventServiceProvider.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Providers;
|
||||
|
||||
use Modules\Menu\Entities\Menu;
|
||||
use Modules\Menu\Events\Listeners\CreateRootMenuItem;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
Menu::created(CreateRootMenuItem::class);
|
||||
}
|
||||
}
|
||||
26
Modules/Menu/Providers/MenuServiceProvider.php
Normal file
26
Modules/Menu/Providers/MenuServiceProvider.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Providers;
|
||||
|
||||
use Modules\Menu\Admin\MenuItemTabs;
|
||||
use Modules\Support\Traits\AddsAsset;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Modules\Admin\Ui\Facades\TabManager;
|
||||
|
||||
class MenuServiceProvider extends ServiceProvider
|
||||
{
|
||||
use AddsAsset;
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
TabManager::register('menu_items', MenuItemTabs::class);
|
||||
|
||||
$this->addAdminAssets('admin.menus.(create|edit)', ['admin.menu.css', 'admin.menu.js']);
|
||||
$this->addAdminAssets('admin.menus.items.(create|edit)', ['admin.media.css', 'admin.media.js', 'admin.menu.js']);
|
||||
}
|
||||
}
|
||||
53
Modules/Menu/Resources/assets/admin/js/main.js
Normal file
53
Modules/Menu/Resources/assets/admin/js/main.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import 'nestable2';
|
||||
|
||||
window.admin.removeSubmitButtonOffsetOn('#image');
|
||||
|
||||
$('#type').on('change', (e) => {
|
||||
$('.link-field').addClass('hide');
|
||||
$(`.${e.currentTarget.value}-field`).removeClass('hide');
|
||||
});
|
||||
|
||||
$('.dd').nestable({ maxDepth: 15 });
|
||||
|
||||
$('.dd').on('change', () => {
|
||||
$.ajax({
|
||||
type: 'PUT',
|
||||
url: route('admin.menus.items.order.update'),
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
data: JSON.stringify($('.dd').nestable('serialize')[0]),
|
||||
success() {
|
||||
success(trans('menu::messages.menu_items_order_updated'));
|
||||
},
|
||||
error(xhr) {
|
||||
error(xhr.responseJSON.message);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
let id;
|
||||
let confirmationModal = $('#confirmation-modal');
|
||||
|
||||
$('.delete-menu-item').on('click', (e) => {
|
||||
id = $(e.currentTarget).closest('.dd-item').data('id');
|
||||
|
||||
confirmationModal.modal('show');
|
||||
});
|
||||
|
||||
confirmationModal.find('form').on('submit', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
confirmationModal.modal('hide');
|
||||
|
||||
$.ajax({
|
||||
type: 'DELETE',
|
||||
url: route('admin.menus.items.destroy', id),
|
||||
success() {
|
||||
success(trans('menu::messages.menu_item_deleted'));
|
||||
|
||||
$(`.dd-item[data-id="${id}"]`).fadeOut();
|
||||
},
|
||||
error(xhr) {
|
||||
error(xhr.responseJSON.message);
|
||||
},
|
||||
});
|
||||
});
|
||||
205
Modules/Menu/Resources/assets/admin/sass/main.scss
Normal file
205
Modules/Menu/Resources/assets/admin/sass/main.scss
Normal file
@@ -0,0 +1,205 @@
|
||||
#menu-create-form .box-body,
|
||||
#menu-edit-form .box-body {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#menu-edit-form .box-body {
|
||||
.dd {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-item-actions {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
margin-top: 3px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.menu-item-actions .btn:last-child {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.delete-menu-item {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.edit-menu-item {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dd {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
font-size: 13px;
|
||||
line-height: 29px;
|
||||
}
|
||||
|
||||
.dd-list {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
.dd-list {
|
||||
padding-left: 25px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background: transparent;
|
||||
color: #555555;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.dd-expand,
|
||||
.dd-collapse {
|
||||
margin-top: 10px;
|
||||
color: #555555;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dd-collapsed .dd-list {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dd-item,
|
||||
.dd-item-root,
|
||||
.dd-empty,
|
||||
.dd-placeholder {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 20px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.dd-handle-root,
|
||||
.dd-handle {
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 15px;
|
||||
display: block;
|
||||
margin: 5px 0;
|
||||
padding: 8px 10px;
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
border: 1px solid #d9d9d9;
|
||||
background: #fafafa;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.dd-handle:hover {
|
||||
color: #333;
|
||||
background: #fff;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.dd-item-root > .btn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dd-item-root > button,
|
||||
.dd-item > button {
|
||||
display: block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
width: 25px;
|
||||
height: 20px;
|
||||
margin: 5px 0;
|
||||
padding: 0;
|
||||
text-indent: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dd-item-root > button:before,
|
||||
.dd-item > button:before {
|
||||
content: '+';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
text-indent: 0;
|
||||
font-size: 20px;
|
||||
line-height: 9px;
|
||||
}
|
||||
|
||||
.dd-item-root > button[data-action="collapse"]:before,
|
||||
.dd-item > button[data-action="collapse"]:before {
|
||||
content: '-';
|
||||
font-size: 20px;
|
||||
line-height: 9px;
|
||||
}
|
||||
|
||||
.dd-placeholder,
|
||||
.dd-empty {
|
||||
margin: 5px 0;
|
||||
padding: 0;
|
||||
min-height: 30px !important;
|
||||
background: #f2fbff !important;
|
||||
border: 1px dashed #b6bcbf;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.dd-empty {
|
||||
border: 1px dashed #bbb;
|
||||
min-height: 100px;
|
||||
background-color: #e5e5e5;
|
||||
background-image: -webkit-linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%, #ffffff 75%, #ffffff), -webkit-linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%, #ffffff 75%, #ffffff);
|
||||
background-image: -moz-linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%, #ffffff 75%, #ffffff), -moz-linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%, #ffffff 75%, #ffffff);
|
||||
background-image: linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%, #ffffff 75%, #ffffff), linear-gradient(45deg, #ffffff 25%, transparent 25%, transparent 75%, #ffffff 75%, #ffffff);
|
||||
background-size: 60px 60px;
|
||||
background-position: 0 0, 30px 30px;
|
||||
}
|
||||
|
||||
.dd-dragel {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.dd-dragel > .dd-item .dd-handle {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.dd-dragel .dd-handle {
|
||||
-webkit-box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dd-hover > .dd-handle {
|
||||
background: #2196f3 !important;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 700px) {
|
||||
.dd {
|
||||
float: left;
|
||||
width: 100%;
|
||||
|
||||
+ .dd {
|
||||
margin-left: 2%;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Modules/Menu/Resources/lang/en/attributes.php
Normal file
14
Modules/Menu/Resources/lang/en/attributes.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'name' => 'Name',
|
||||
'type' => 'Type',
|
||||
'url' => 'URL',
|
||||
'icon' => 'Icon',
|
||||
'category_id' => 'Category',
|
||||
'page_id' => 'Page',
|
||||
'parent_id' => 'Parent Menu Item',
|
||||
'target' => 'Target',
|
||||
'is_fluid' => 'Fluid Menu',
|
||||
'is_active' => 'Status',
|
||||
];
|
||||
30
Modules/Menu/Resources/lang/en/menu_items.php
Normal file
30
Modules/Menu/Resources/lang/en/menu_items.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'menu_item' => 'Menu Item',
|
||||
'back_to_menu_edit_page' => 'Back to Menu Edit Page',
|
||||
'tabs' => [
|
||||
'group' => [
|
||||
'menu_item_information' => 'Menu Item Information',
|
||||
],
|
||||
'general' => 'General',
|
||||
'image' => 'Image',
|
||||
],
|
||||
'form' => [
|
||||
'types' => [
|
||||
'category' => 'Category',
|
||||
'page' => 'Page',
|
||||
'url' => 'URL',
|
||||
],
|
||||
'targets' => [
|
||||
'_self' => 'Same Tab',
|
||||
'_blank' => 'New Tab',
|
||||
],
|
||||
'select_category' => 'Select Category',
|
||||
'select_page' => 'Select Page',
|
||||
'select_parent' => 'Select Parent',
|
||||
'background_image' => 'Background Image',
|
||||
'full_width_menu' => 'This is a full width menu',
|
||||
'enable_the_menu_item' => 'Enable the menu item',
|
||||
],
|
||||
];
|
||||
13
Modules/Menu/Resources/lang/en/menus.php
Normal file
13
Modules/Menu/Resources/lang/en/menus.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'menu' => 'Menu',
|
||||
'menus' => 'Menus',
|
||||
'table' => [
|
||||
'name' => 'Name',
|
||||
],
|
||||
'form' => [
|
||||
'please_save_the_menu_first' => 'Please save the menu first to add menu items.',
|
||||
'enable_the_menu' => 'Enable the menu',
|
||||
],
|
||||
];
|
||||
6
Modules/Menu/Resources/lang/en/messages.php
Normal file
6
Modules/Menu/Resources/lang/en/messages.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'menu_item_deleted' => 'Menu item has been deleted.',
|
||||
'menu_items_order_updated' => 'Menu items order has been updated.',
|
||||
];
|
||||
16
Modules/Menu/Resources/lang/en/permissions.php
Normal file
16
Modules/Menu/Resources/lang/en/permissions.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'menus' => [
|
||||
'index' => 'Index Menus',
|
||||
'create' => 'Create Menus',
|
||||
'edit' => 'Edit Menus',
|
||||
'destroy' => 'Delete Menus',
|
||||
],
|
||||
'menu_items' => [
|
||||
'index' => 'Index Menu Items',
|
||||
'create' => 'Create Menu Items',
|
||||
'edit' => 'Edit Menu Items',
|
||||
'destroy' => 'Delete Menu Items',
|
||||
],
|
||||
];
|
||||
5
Modules/Menu/Resources/lang/en/sidebar.php
Normal file
5
Modules/Menu/Resources/lang/en/sidebar.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'menus' => 'Menus',
|
||||
];
|
||||
@@ -0,0 +1,19 @@
|
||||
@extends('admin::layout')
|
||||
|
||||
@component('admin::components.page.header')
|
||||
@slot('title', trans('admin::resource.create', ['resource' => trans('menu::menu_items.menu_item')]))
|
||||
|
||||
<li><a href="{{ route('admin.menus.index') }}">{{ trans('menu::menus.menus') }}</a></li>
|
||||
<li><a href="{{ route('admin.menus.edit', $menuId) }}">{{ trans('admin::resource.edit', ['resource' => trans('menu::menus.menu')]) }}</a></li>
|
||||
<li class="active">{{ trans('admin::resource.create', ['resource' => trans('menu::menu_items.menu_item')]) }}</li>
|
||||
@endcomponent
|
||||
|
||||
@section('content')
|
||||
<form method="POST" action="{{ route('admin.menus.items.store', $menuId) }}" class="form-horizontal" id="menu-item-create-form" novalidate>
|
||||
{{ csrf_field() }}
|
||||
|
||||
{!! $tabs->render(compact('menuId', 'menuItem')) !!}
|
||||
</form>
|
||||
@endsection
|
||||
|
||||
@include('menu::admin.menu_items.partials.shortcuts')
|
||||
20
Modules/Menu/Resources/views/admin/menu_items/edit.blade.php
Normal file
20
Modules/Menu/Resources/views/admin/menu_items/edit.blade.php
Normal file
@@ -0,0 +1,20 @@
|
||||
@extends('admin::layout')
|
||||
|
||||
@component('admin::components.page.header')
|
||||
@slot('title', trans('admin::resource.edit', ['resource' => trans('menu::menu_items.menu_item')]))
|
||||
@slot('subtitle', $menuItem->title)
|
||||
|
||||
<li><a href="{{ route('admin.menus.edit', $menuId) }}">{{ trans('admin::resource.edit', ['resource' => trans('menu::menus.menu')]) }}</a></li>
|
||||
<li class="active">{{ trans('admin::resource.edit', ['resource' => trans('menu::menu_items.menu_item')]) }}</li>
|
||||
@endcomponent
|
||||
|
||||
@section('content')
|
||||
<form method="POST" action="{{ route('admin.menus.items.update', [$menuId, $menuItem]) }}" class="form-horizontal" id="menu-item-edit-form" novalidate>
|
||||
{{ csrf_field() }}
|
||||
{{ method_field('put') }}
|
||||
|
||||
{!! $tabs->render(compact('menuId', 'menuItem')) !!}
|
||||
</form>
|
||||
@endsection
|
||||
|
||||
@include('menu::admin.menu_items.partials.shortcuts')
|
||||
@@ -0,0 +1,14 @@
|
||||
@push('shortcuts')
|
||||
<dl class="dl-horizontal">
|
||||
<dt><code>b</code></dt>
|
||||
<dd>{{ trans('menu::menu_items.back_to_menu_edit_page') }}</dd>
|
||||
</dl>
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
keypressAction([
|
||||
{ key: 'b', route: "{{ route('admin.menus.edit', $menuId) }}" },
|
||||
]);
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,24 @@
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
{{ Form::text('name', trans('menu::attributes.name'), $errors, $menuItem, ['required' => true]) }}
|
||||
{{ Form::select('type', trans('menu::attributes.type'), $errors, trans('menu::menu_items.form.types'), $menuItem, ['required' => true]) }}
|
||||
|
||||
<div class="link-field category-field {{ old('type', $menuItem->type ?? 'category') !== 'category' ? 'hide' :'' }}">
|
||||
{{ Form::select('category_id', trans('menu::attributes.category_id'), $errors, $categories, $menuItem, ['required' => true]) }}
|
||||
</div>
|
||||
|
||||
<div class="link-field page-field {{ old('type', $menuItem->type) !== 'page' ? 'hide' :'' }}">
|
||||
{{ Form::select('page_id', trans('menu::attributes.page_id'), $errors, $pages, $menuItem, ['required' => true]) }}
|
||||
</div>
|
||||
|
||||
<div class="link-field url-field {{ old('type', $menuItem->type) !== 'url' ? 'hide' :'' }}">
|
||||
{{ Form::text('url', trans('menu::attributes.url'), $errors, $menuItem, ['required' => true]) }}
|
||||
</div>
|
||||
|
||||
{{ Form::text('icon', trans('menu::attributes.icon'), $errors, $menuItem) }}
|
||||
{{ Form::checkbox('is_fluid', trans('menu::attributes.is_fluid'), trans('menu::menu_items.form.full_width_menu'), $errors, $menuItem) }}
|
||||
{{ Form::select('target', trans('menu::attributes.target'), $errors, trans('menu::menu_items.form.targets'), $menuItem) }}
|
||||
{{ Form::select('parent_id', trans('menu::attributes.parent_id'), $errors, $parentMenuItems, $menuItem) }}
|
||||
{{ Form::checkbox('is_active', trans('menu::attributes.is_active'), trans('menu::menu_items.form.enable_the_menu_item'), $errors, $menuItem) }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,5 @@
|
||||
@include('media::admin.image_picker.single', [
|
||||
'title' => trans('menu::menu_items.form.background_image'),
|
||||
'inputName' => 'files[background_image]',
|
||||
'file' => $menuItem->backgroundImage,
|
||||
])
|
||||
18
Modules/Menu/Resources/views/admin/menus/create.blade.php
Normal file
18
Modules/Menu/Resources/views/admin/menus/create.blade.php
Normal file
@@ -0,0 +1,18 @@
|
||||
@extends('admin::layout')
|
||||
|
||||
@component('admin::components.page.header')
|
||||
@slot('title', trans('admin::resource.create', ['resource' => trans('menu::menus.menu')]))
|
||||
|
||||
<li><a href="{{ route('admin.menus.index') }}">{{ trans('menu::menus.menus') }}</a></li>
|
||||
<li class="active">{{ trans('admin::resource.create', ['resource' => trans('menu::menus.menu')]) }}</li>
|
||||
@endcomponent
|
||||
|
||||
@section('content')
|
||||
<form method="POST" action="{{ route('admin.menus.store') }}" class="form-horizontal" id="menu-create-form" novalidate>
|
||||
{{ csrf_field() }}
|
||||
|
||||
@include('menu::admin.menus.form.fields')
|
||||
</form>
|
||||
@endsection
|
||||
|
||||
@include('menu::admin.menus.partials.shortcuts')
|
||||
27
Modules/Menu/Resources/views/admin/menus/edit.blade.php
Normal file
27
Modules/Menu/Resources/views/admin/menus/edit.blade.php
Normal file
@@ -0,0 +1,27 @@
|
||||
@extends('admin::layout')
|
||||
|
||||
@component('admin::components.page.header')
|
||||
@slot('title', trans('admin::resource.edit', ['resource' => trans('menu::menus.menu')]))
|
||||
@slot('subtitle', $menu->title)
|
||||
|
||||
<li><a href="{{ route('admin.menus.index') }}">{{ trans('menu::menus.menus') }}</a></li>
|
||||
<li class="active">{{ trans('admin::resource.edit', ['resource' => trans('menu::menus.menu')]) }}</li>
|
||||
@endcomponent
|
||||
|
||||
@section('content')
|
||||
<form method="POST" action="{{ route('admin.menus.update', $menu) }}" class="form-horizontal" id="menu-edit-form" novalidate>
|
||||
{{ csrf_field() }}
|
||||
{{ method_field('put') }}
|
||||
|
||||
@include('menu::admin.menus.form.fields')
|
||||
</form>
|
||||
@endsection
|
||||
|
||||
@push('globals')
|
||||
<script>
|
||||
FleetCart.langs['menu::messages.menu_item_deleted'] = '{{ trans('menu::messages.menu_item_deleted') }}';
|
||||
FleetCart.langs['menu::messages.menu_items_order_updated'] = '{{ trans('menu::messages.menu_items_order_updated') }}';
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@include('menu::admin.menus.partials.shortcuts')
|
||||
@@ -0,0 +1,46 @@
|
||||
<div class="row">
|
||||
@hasAccess('admin.menu_items.index')
|
||||
<div class="col-md-6">
|
||||
@if ($menu->exists)
|
||||
@hasAccess('admin.menu_items.create')
|
||||
<div class="btn-group pull-right m-b-15">
|
||||
<a href="{{ route('admin.menus.items.create', $menu) }}" class="btn btn-primary">
|
||||
{{ trans('admin::resource.create', ['resource' => trans('menu::menu_items.menu_item')]) }}
|
||||
</a>
|
||||
</div>
|
||||
@endHasAccess
|
||||
|
||||
@hasAccess('admin.menu_items.edit')
|
||||
<div class="box box-primary overflow-hidden">
|
||||
<div class="box-body">
|
||||
<div class="dd">
|
||||
@include('menu::admin.menus.form.menu_items_list')
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endHasAccess
|
||||
@else
|
||||
<div class="alert alert-info">
|
||||
{{ trans('menu::menus.form.please_save_the_menu_first') }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endHasAccess
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="box box-primary">
|
||||
<div class="box-body">
|
||||
{{ Form::text('name', trans('menu::attributes.name'), $errors, $menu, ['required' => true]) }}
|
||||
{{ Form::checkbox('is_active', trans('menu::attributes.is_active'), trans('menu::menus.form.enable_the_menu'), $errors, $menu) }}
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-3 col-md-9">
|
||||
<button type="submit" class="btn btn-primary" data-loading>
|
||||
{{ trans('admin::admin.buttons.save') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
<ol class="dd-list">
|
||||
@foreach ($menuItems as $menuItem)
|
||||
<li class="dd-item" data-id="{{ $menuItem->id }}">
|
||||
@if (! $menuItem->is_root)
|
||||
<div class="menu-item-actions btn-group" role="group">
|
||||
<a href="{{ route('admin.menus.items.edit', [$menu->id, $menuItem->id]) }}" class="btn edit-menu-item ">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
|
||||
<button type="button" class="btn delete-menu-item" data-action="{{ route('admin.menus.items.destroy', [$menu->id, $menuItem->id]) }}">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="{{ $menuItem->is_root ? 'dd-handle-root' : 'dd-handle' }}">{{ $menuItem->name }}</div>
|
||||
|
||||
@if (count($menuItem->items) !== 0)
|
||||
@include('menu::admin.menus.form.menu_items_list', ['menuItems' => $menuItem->items])
|
||||
@endif
|
||||
</li>
|
||||
@endforeach
|
||||
</ol>
|
||||
49
Modules/Menu/Resources/views/admin/menus/index.blade.php
Normal file
49
Modules/Menu/Resources/views/admin/menus/index.blade.php
Normal file
@@ -0,0 +1,49 @@
|
||||
@extends('admin::layout')
|
||||
|
||||
@component('admin::components.page.header')
|
||||
@slot('title', trans('menu::menus.menus'))
|
||||
|
||||
<li class="active">{{ trans('menu::menus.menu') }}</li>
|
||||
@endcomponent
|
||||
|
||||
@component('admin::components.page.index_table')
|
||||
@slot('buttons', ['create'])
|
||||
@slot('resource', 'menus')
|
||||
@slot('name', trans('menu::menus.menu'))
|
||||
|
||||
@slot('thead')
|
||||
<tr>
|
||||
@include('admin::partials.table.select_all')
|
||||
|
||||
<th>{{ trans('admin::admin.table.id') }}</th>
|
||||
<th>{{ trans('menu::menus.table.name') }}</th>
|
||||
<th>{{ trans('admin::admin.table.status') }}</th>
|
||||
<th data-sort>{{ trans('admin::admin.table.created') }}</th>
|
||||
</tr>
|
||||
@endslot
|
||||
@endcomponent
|
||||
|
||||
@push('shortcuts')
|
||||
<dl class="dl-horizontal">
|
||||
<dt><code>c</code></dt>
|
||||
<dd>{{ trans('admin::resource.create', ['resource' => trans('menu::menus.menu')]) }}</dd>
|
||||
</dl>
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
keypressAction([
|
||||
{ key: 'c', route: "{{ route('admin.menus.create') }}" },
|
||||
]);
|
||||
|
||||
new DataTable('#menus-table .table', {
|
||||
columns: [
|
||||
{ data: 'checkbox', orderable: false, searchable: false, width: '3%' },
|
||||
{ data: 'id', width: '5%' },
|
||||
{ data: 'name', name: 'translations.name', orderable: false, defaultContent: '' },
|
||||
{ data: 'status', name: 'is_active', searchable: false },
|
||||
{ data: 'created', name: 'created_at' },
|
||||
]
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -0,0 +1,25 @@
|
||||
@push('shortcuts')
|
||||
@isset($menu)
|
||||
<dl class="dl-horizontal">
|
||||
<dt><code>c</code></dt>
|
||||
<dd>{{ trans('admin::resource.create', ['resource' => trans('menu::menu_items.menu_item')]) }}</dd>
|
||||
</dl>
|
||||
@endisset
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt><code>b</code></dt>
|
||||
<dd>{{ trans('admin::admin.shortcuts.back_to_index', ['name' => trans('menu::menus.menu')]) }}</dd>
|
||||
</dl>
|
||||
@endpush
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
keypressAction([
|
||||
@isset($menu)
|
||||
{ key: 'c', route: "{{ route('admin.menus.items.create', $menu) }}" },
|
||||
@endisset
|
||||
|
||||
{ key: 'b', route: "{{ route('admin.menus.index') }}" },
|
||||
]);
|
||||
</script>
|
||||
@endpush
|
||||
75
Modules/Menu/Routes/admin.php
Normal file
75
Modules/Menu/Routes/admin.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::get('menus', [
|
||||
'as' => 'admin.menus.index',
|
||||
'uses' => 'MenuController@index',
|
||||
'middleware' => 'can:admin.menus.index',
|
||||
]);
|
||||
|
||||
Route::get('menus/create', [
|
||||
'as' => 'admin.menus.create',
|
||||
'uses' => 'MenuController@create',
|
||||
'middleware' => 'can:admin.menus.create',
|
||||
]);
|
||||
|
||||
Route::post('menus', [
|
||||
'as' => 'admin.menus.store',
|
||||
'uses' => 'MenuController@store',
|
||||
'middleware' => 'can:admin.menus.create',
|
||||
]);
|
||||
|
||||
Route::get('menus/{id}/edit', [
|
||||
'as' => 'admin.menus.edit',
|
||||
'uses' => 'MenuController@edit',
|
||||
'middleware' => 'can:admin.menus.edit',
|
||||
]);
|
||||
|
||||
Route::put('menus/{id}', [
|
||||
'as' => 'admin.menus.update',
|
||||
'uses' => 'MenuController@update',
|
||||
'middleware' => 'can:admin.menus.edit',
|
||||
]);
|
||||
|
||||
Route::delete('menus/{ids?}', [
|
||||
'as' => 'admin.menus.destroy',
|
||||
'uses' => 'MenuController@destroy',
|
||||
'middleware' => 'can:admin.menus.destroy',
|
||||
]);
|
||||
|
||||
Route::get('menus/{menuId?}/items/create', [
|
||||
'as' => 'admin.menus.items.create',
|
||||
'uses' => 'MenuItemController@create',
|
||||
'middleware' => 'can:admin.menu_items.create',
|
||||
]);
|
||||
|
||||
Route::post('menus/{menuId}/items', [
|
||||
'as' => 'admin.menus.items.store',
|
||||
'uses' => 'MenuItemController@store',
|
||||
'middleware' => 'can:admin.menu_items.create',
|
||||
]);
|
||||
|
||||
Route::get('menus/{menuId}/items/{id}/edit', [
|
||||
'as' => 'admin.menus.items.edit',
|
||||
'uses' => 'MenuItemController@edit',
|
||||
'middleware' => 'can:admin.menu_items.edit',
|
||||
]);
|
||||
|
||||
Route::put('menus/{menuId}/items/{id}', [
|
||||
'as' => 'admin.menus.items.update',
|
||||
'uses' => 'MenuItemController@update',
|
||||
'middleware' => 'can:admin.menu_items.edit',
|
||||
]);
|
||||
|
||||
Route::delete('menus/items/{id}', [
|
||||
'as' => 'admin.menus.items.destroy',
|
||||
'uses' => 'MenuItemController@destroy',
|
||||
'middleware' => 'can:admin.menu_items.destroy',
|
||||
]);
|
||||
|
||||
Route::put('menus/items/order', [
|
||||
'as' => 'admin.menus.items.order.update',
|
||||
'uses' => 'MenuItemOrderController@update',
|
||||
'middleware' => 'can:admin.menu_items.edit',
|
||||
]);
|
||||
43
Modules/Menu/Services/MenuItemOrdener.php
Normal file
43
Modules/Menu/Services/MenuItemOrdener.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Services;
|
||||
|
||||
use Modules\Menu\Entities\MenuItem;
|
||||
|
||||
class MenuItemOrdener
|
||||
{
|
||||
/**
|
||||
* Order the menu items.
|
||||
*
|
||||
* @param array $rootItem
|
||||
* @return void
|
||||
*/
|
||||
public function order(array $rootItem)
|
||||
{
|
||||
$this->orderChildren($rootItem['id'], $rootItem['children']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order child menu items recursively.
|
||||
*
|
||||
* @param int $parentId
|
||||
* @param array $childItems
|
||||
* @return void
|
||||
*/
|
||||
private function orderChildren($parentId, array $childItems)
|
||||
{
|
||||
foreach ($childItems as $position => $childItem) {
|
||||
$menuItem = MenuItem::find($childItem['id']);
|
||||
|
||||
if (is_null($menuItem)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$menuItem->update(['parent_id' => $parentId, 'position' => $position]);
|
||||
|
||||
if (isset($childItem['children'])) {
|
||||
$this->orderChildren($childItem['id'], $childItem['children']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Modules/Menu/Sidebar/SidebarExtender.php
Normal file
25
Modules/Menu/Sidebar/SidebarExtender.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Menu\Sidebar;
|
||||
|
||||
use Maatwebsite\Sidebar\Item;
|
||||
use Maatwebsite\Sidebar\Menu;
|
||||
use Maatwebsite\Sidebar\Group;
|
||||
use Modules\Admin\Sidebar\BaseSidebarExtender;
|
||||
|
||||
class SidebarExtender extends BaseSidebarExtender
|
||||
{
|
||||
public function extend(Menu $menu)
|
||||
{
|
||||
$menu->group(trans('admin::sidebar.content'), function (Group $group) {
|
||||
$group->item(trans('menu::sidebar.menus'), function (Item $item) {
|
||||
$item->weight(35);
|
||||
$item->icon('fa fa-bars');
|
||||
$item->route('admin.menus.index');
|
||||
$item->authorize(
|
||||
$this->auth->hasAccess('admin.menus.index')
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
28
Modules/Menu/composer.json
Normal file
28
Modules/Menu/composer.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "fleetcart/menu",
|
||||
"description": "The FleetCart Menu Module.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Envay Soft",
|
||||
"email": "envaysoft@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.0.2",
|
||||
"typicms/nestablecollection": "^1.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\Menu\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
10
Modules/Menu/module.json
Normal file
10
Modules/Menu/module.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Menu",
|
||||
"alias": "menu",
|
||||
"description": "Managing menus.",
|
||||
"priority": 90,
|
||||
"providers": [
|
||||
"Modules\\Menu\\Providers\\MenuServiceProvider",
|
||||
"Modules\\Menu\\Providers\\EventServiceProvider"
|
||||
]
|
||||
}
|
||||
7
Modules/Menu/package.json
Normal file
7
Modules/Menu/package.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "menu-module",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"nestable2": "^1.6.0"
|
||||
}
|
||||
}
|
||||
8
Modules/Menu/webpack.mix.js
Normal file
8
Modules/Menu/webpack.mix.js
Normal file
@@ -0,0 +1,8 @@
|
||||
let mix = require('laravel-mix');
|
||||
let execSync = require('child_process').execSync;
|
||||
|
||||
mix.js(`${__dirname}/Resources/assets/admin/js/main.js`, `${__dirname}/Assets/admin/js/menu.js`)
|
||||
.sass(`${__dirname}/Resources/assets/admin/sass/main.scss`, `${__dirname}/Assets/admin/css/menu.css`)
|
||||
.then(() => {
|
||||
execSync(`npm run rtlcss ${__dirname}/Assets/admin/css/menu.css ${__dirname}/Assets/admin/css/menu.rtl.css`);
|
||||
});
|
||||
13
Modules/Menu/yarn.lock
Normal file
13
Modules/Menu/yarn.lock
Normal file
@@ -0,0 +1,13 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
jquery@>=1.7.2:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787"
|
||||
|
||||
nestable2@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/nestable2/-/nestable2-1.6.0.tgz#83ffe2483cca1c63771ec0012693b5155bfdd115"
|
||||
dependencies:
|
||||
jquery ">=1.7.2"
|
||||
Reference in New Issue
Block a user