¨4.0.1¨
This commit is contained in:
25
.env.example
25
.env.example
@@ -1,3 +1,4 @@
|
|||||||
|
#Application
|
||||||
APP_ENV=local
|
APP_ENV=local
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
APP_CACHE=false
|
APP_CACHE=false
|
||||||
@@ -5,10 +6,13 @@ APP_INSTALLED=false
|
|||||||
APP_KEY=
|
APP_KEY=
|
||||||
APP_URL=http://localhost
|
APP_URL=http://localhost
|
||||||
|
|
||||||
|
#Ignition
|
||||||
IGNITION_EDITOR=vscode
|
IGNITION_EDITOR=vscode
|
||||||
|
|
||||||
|
#Logging
|
||||||
LOG_CHANNEL=stack
|
LOG_CHANNEL=stack
|
||||||
|
|
||||||
|
#Database
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=127.0.0.1
|
DB_HOST=127.0.0.1
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
@@ -16,15 +20,24 @@ DB_DATABASE=homestead
|
|||||||
DB_USERNAME=homestead
|
DB_USERNAME=homestead
|
||||||
DB_PASSWORD=secret
|
DB_PASSWORD=secret
|
||||||
|
|
||||||
|
#Queue
|
||||||
QUEUE_DRIVER=sync
|
QUEUE_DRIVER=sync
|
||||||
|
|
||||||
|
#Cache
|
||||||
CACHE_DRIVER=file
|
CACHE_DRIVER=file
|
||||||
|
|
||||||
|
#Session
|
||||||
SESSION_DRIVER=file
|
SESSION_DRIVER=file
|
||||||
|
|
||||||
|
#File System
|
||||||
FILESYSTEM_DRIVER=public_storage
|
FILESYSTEM_DRIVER=public_storage
|
||||||
|
|
||||||
|
#Redis
|
||||||
REDIS_HOST=127.0.0.1
|
REDIS_HOST=127.0.0.1
|
||||||
REDIS_PASSWORD=null
|
REDIS_PASSWORD=null
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
#Mail
|
||||||
MAIL_DRIVER=smtp
|
MAIL_DRIVER=smtp
|
||||||
MAIL_HOST=smtp.mailtrap.io
|
MAIL_HOST=smtp.mailtrap.io
|
||||||
MAIL_PORT=2525
|
MAIL_PORT=2525
|
||||||
@@ -34,15 +47,23 @@ MAIL_FROM_ADDRESS=null
|
|||||||
MAIL_FROM_NAME=null
|
MAIL_FROM_NAME=null
|
||||||
MAIL_ENCRYPTION=null
|
MAIL_ENCRYPTION=null
|
||||||
|
|
||||||
|
#Mailchimp
|
||||||
|
MAILCHIMP_APIKEY=
|
||||||
|
|
||||||
|
#AWS
|
||||||
AWS_ACCESS_KEY_ID=
|
AWS_ACCESS_KEY_ID=
|
||||||
AWS_SECRET_ACCESS_KEY=
|
AWS_SECRET_ACCESS_KEY=
|
||||||
AWS_DEFAULT_REGION=us-east-1
|
AWS_DEFAULT_REGION=us-east-1
|
||||||
AWS_BUCKET=
|
AWS_BUCKET=
|
||||||
|
|
||||||
|
#Scout
|
||||||
SCOUT_QUEUE=false
|
SCOUT_QUEUE=false
|
||||||
|
|
||||||
MAILCHIMP_APIKEY=
|
#Laravel DataTables (yajra/laravel-datatables)
|
||||||
|
|
||||||
DATATABLES_ERROR=null
|
DATATABLES_ERROR=null
|
||||||
|
|
||||||
|
#Debugbar for Laravel (barryvdh/laravel-debugbar)
|
||||||
DEBUGBAR_ENABLED=false
|
DEBUGBAR_ENABLED=false
|
||||||
|
|
||||||
|
#Laravel Query Detector (beyondcode/laravel-query-detector)
|
||||||
QUERY_DETECTOR_ENABLED=false
|
QUERY_DETECTOR_ENABLED=false
|
||||||
|
|||||||
48
.gitignore
vendored
48
.gitignore
vendored
@@ -1,21 +1,47 @@
|
|||||||
|
#Meta
|
||||||
|
.meta/
|
||||||
.idea/
|
.idea/
|
||||||
.phpintel/
|
.phpintel/
|
||||||
*.sublime-project
|
*.sublime-project
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
#Env
|
||||||
|
.env
|
||||||
|
|
||||||
|
#Dependencies
|
||||||
node_modules/
|
node_modules/
|
||||||
/vendor/
|
vendor/
|
||||||
/public/storage/
|
|
||||||
/public/modules/
|
#Assets
|
||||||
/public/themes/
|
public/images/
|
||||||
/storage/logs/*
|
public/modules/
|
||||||
|
public/themes/
|
||||||
|
public/build/
|
||||||
|
public/pwa/
|
||||||
|
Modules/*/Assets/
|
||||||
|
Themes/*/assets/
|
||||||
|
|
||||||
|
#Fonts
|
||||||
|
Themes/Storefront/resources/assets/public/fonts/
|
||||||
|
|
||||||
|
#Storage
|
||||||
|
public/storage/
|
||||||
|
|
||||||
|
#Logs
|
||||||
public/phplog
|
public/phplog
|
||||||
/Modules/*/Assets/
|
storage/logs/*
|
||||||
/Themes/*/assets/
|
Modules/*/yarn-error.log
|
||||||
/tags
|
|
||||||
/.meta
|
|
||||||
mix-manifest.json
|
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
*.log
|
||||||
|
|
||||||
|
#Others
|
||||||
|
tools/
|
||||||
*.map
|
*.map
|
||||||
.env
|
tags/
|
||||||
|
public/hot
|
||||||
|
mix-manifest.json
|
||||||
|
public/sitemaps/*
|
||||||
|
public/sitemap.xml
|
||||||
|
.php-cs-fixer.cache
|
||||||
|
|||||||
@@ -18,16 +18,18 @@ class AccountAddressController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function store(SaveAddressRequest $request)
|
public function store(SaveAddressRequest $request)
|
||||||
{
|
{
|
||||||
$address = auth()->user()->addresses()->create($request->all());
|
$address = auth()->user()->addresses()->create($request->all());
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'address' => $address,
|
'address' => $address,
|
||||||
'message' => trans('account::messages.address_saved'),
|
'message' => trans('account::messages.address_created'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function update(SaveAddressRequest $request, $id)
|
public function update(SaveAddressRequest $request, $id)
|
||||||
{
|
{
|
||||||
$address = Address::find($id);
|
$address = Address::find($id);
|
||||||
@@ -35,10 +37,11 @@ class AccountAddressController extends Controller
|
|||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'address' => $address,
|
'address' => $address,
|
||||||
'message' => trans('account::messages.address_saved'),
|
'message' => trans('account::messages.address_updated'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
auth()->user()->addresses()->find($id)->delete();
|
auth()->user()->addresses()->find($id)->delete();
|
||||||
|
|||||||
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
namespace Modules\Account\Http\Controllers;
|
namespace Modules\Account\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
|
||||||
class AccountDashboardController
|
class AccountDashboardController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace Modules\Account\Http\Controllers;
|
namespace Modules\Account\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Routing\Controller;
|
use Illuminate\Routing\Controller;
|
||||||
|
use Illuminate\Contracts\Support\Renderable;
|
||||||
use Modules\Address\Entities\DefaultAddress;
|
use Modules\Address\Entities\DefaultAddress;
|
||||||
|
|
||||||
class AccountDefaultAddressController extends Controller
|
class AccountDefaultAddressController extends Controller
|
||||||
@@ -10,7 +11,7 @@ class AccountDefaultAddressController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Contracts\Support\Renderable
|
* @return Renderable
|
||||||
*/
|
*/
|
||||||
public function update()
|
public function update()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Modules\Account\Http\Controllers;
|
namespace Modules\Account\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Response;
|
||||||
use Modules\Order\Entities\Order;
|
use Modules\Order\Entities\Order;
|
||||||
|
|
||||||
class AccountDownloadsController
|
class AccountDownloadsController
|
||||||
@@ -9,7 +10,7 @@ class AccountDownloadsController
|
|||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
@@ -18,23 +19,26 @@ class AccountDownloadsController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Http\Response
|
*
|
||||||
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$file = $this->getDownloads()->firstWhere('id', decrypt($id));
|
$file = $this->getDownloads()->firstWhere('id', decrypt($id));
|
||||||
|
|
||||||
if (is_null($file) || ! file_exists($file->realPath())) {
|
if (is_null($file) || !file_exists($file->realPath())) {
|
||||||
return back()->with('error', trans('storefront::account.downloads.no_file_found'));
|
return back()->with('error', trans('storefront::account.downloads.no_file_found'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->download($file->realPath(), $file->filename);
|
return response()->download($file->realPath(), $file->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getDownloads()
|
private function getDownloads()
|
||||||
{
|
{
|
||||||
return auth()->user()
|
return auth()->user()
|
||||||
|
|||||||
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
namespace Modules\Account\Http\Controllers;
|
namespace Modules\Account\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
|
||||||
class AccountOrdersController
|
class AccountOrdersController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
@@ -19,11 +21,13 @@ class AccountOrdersController
|
|||||||
return view('public.account.orders.index', compact('orders'));
|
return view('public.account.orders.index', compact('orders'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Http\Response
|
*
|
||||||
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Modules\Account\Http\Controllers;
|
namespace Modules\Account\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Response;
|
||||||
use Modules\User\Http\Requests\UpdateProfileRequest;
|
use Modules\User\Http\Requests\UpdateProfileRequest;
|
||||||
|
|
||||||
class AccountProfileController
|
class AccountProfileController
|
||||||
@@ -9,7 +10,7 @@ class AccountProfileController
|
|||||||
/**
|
/**
|
||||||
* Show the form for editing the specified resource.
|
* Show the form for editing the specified resource.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function edit()
|
public function edit()
|
||||||
{
|
{
|
||||||
@@ -18,15 +19,17 @@ class AccountProfileController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*
|
*
|
||||||
* @param \Modules\User\Http\Requests\UpdateProfileRequest $request
|
* @param UpdateProfileRequest $request
|
||||||
* @return \Illuminate\Http\Response
|
*
|
||||||
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function update(UpdateProfileRequest $request)
|
public function update(UpdateProfileRequest $request)
|
||||||
{
|
{
|
||||||
$request->bcryptPassword($request);
|
$request->bcryptPassword();
|
||||||
|
|
||||||
auth()->user()->update($request->all());
|
auth()->user()->update($request->all());
|
||||||
|
|
||||||
|
|||||||
@@ -2,22 +2,19 @@
|
|||||||
|
|
||||||
namespace Modules\Account\Http\Controllers;
|
namespace Modules\Account\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Illuminate\Contracts\View\Factory;
|
||||||
|
use Illuminate\Contracts\Foundation\Application;
|
||||||
|
|
||||||
class AccountReviewController
|
class AccountReviewController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return Application|Factory|View
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index(): View|Factory|Application
|
||||||
{
|
{
|
||||||
$reviews = auth()->user()
|
return view('public.account.reviews.index');
|
||||||
->reviews()
|
|
||||||
->withoutGlobalScope('approved')
|
|
||||||
->with('product.files')
|
|
||||||
->whereHas('product')
|
|
||||||
->paginate(20);
|
|
||||||
|
|
||||||
return view('public.account.reviews.index', compact('reviews'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
namespace Modules\Account\Http\Controllers;
|
namespace Modules\Account\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
|
||||||
class AccountWishlistController
|
class AccountWishlistController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ class SaveAddressRequest extends Request
|
|||||||
*/
|
*/
|
||||||
protected $availableAttributes = 'account::attributes.addresses';
|
protected $availableAttributes = 'account::attributes.addresses';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the validation rules that apply to the request.
|
* Get the validation rules that apply to the request.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'profile_updated' => 'Your profile has been updated.',
|
'profile_updated' => 'Your profile has been updated',
|
||||||
'default_address_updated' => 'The default address has been updated.',
|
'default_address_updated' => 'The default address has been updated',
|
||||||
'address_saved' => 'The address has been saved.',
|
'address_created' => 'The address has been created',
|
||||||
'address_deleted' => 'The address has been deleted.',
|
'address_updated' => 'The address has been updated',
|
||||||
|
'address_deleted' => 'The address has been deleted',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class CreateAddressesTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class CreateDefaultAddressesTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,21 +13,25 @@ class Address extends Model
|
|||||||
|
|
||||||
protected $appends = ['full_name', 'state_name', 'country_name'];
|
protected $appends = ['full_name', 'state_name', 'country_name'];
|
||||||
|
|
||||||
|
|
||||||
public function customer()
|
public function customer()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getFullNameAttribute()
|
public function getFullNameAttribute()
|
||||||
{
|
{
|
||||||
return $this->first_name . ' ' . $this->last_name;
|
return $this->first_name . ' ' . $this->last_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getStateNameAttribute()
|
public function getStateNameAttribute()
|
||||||
{
|
{
|
||||||
return State::name($this->country, $this->state);
|
return State::name($this->country, $this->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getCountryNameAttribute()
|
public function getCountryNameAttribute()
|
||||||
{
|
{
|
||||||
return Country::name($this->country);
|
return Country::name($this->country);
|
||||||
|
|||||||
@@ -6,42 +6,47 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
|
|
||||||
class DefaultAddress extends Model
|
class DefaultAddress extends Model
|
||||||
{
|
{
|
||||||
|
public $timestamps = false;
|
||||||
protected $with = ['address'];
|
protected $with = ['address'];
|
||||||
|
|
||||||
protected $fillable = ['customer_id', 'address_id'];
|
protected $fillable = ['customer_id', 'address_id'];
|
||||||
|
|
||||||
public $timestamps = false;
|
|
||||||
|
|
||||||
public function address()
|
public function address()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Address::class);
|
return $this->belongsTo(Address::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getAddress1Attribute()
|
public function getAddress1Attribute()
|
||||||
{
|
{
|
||||||
return $this->address->address_1;
|
return $this->address->address_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getAddress2Attribute()
|
public function getAddress2Attribute()
|
||||||
{
|
{
|
||||||
return $this->address->address_1;
|
return $this->address->address_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getCityAttribute()
|
public function getCityAttribute()
|
||||||
{
|
{
|
||||||
return $this->address->city;
|
return $this->address->city;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getStateAttribute()
|
public function getStateAttribute()
|
||||||
{
|
{
|
||||||
return $this->address->state;
|
return $this->address->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getZipAttribute()
|
public function getZipAttribute()
|
||||||
{
|
{
|
||||||
return $this->address->zip;
|
return $this->address->zip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getCountryAttribute()
|
public function getCountryAttribute()
|
||||||
{
|
{
|
||||||
return $this->address->country;
|
return $this->address->country;
|
||||||
|
|||||||
@@ -2,18 +2,20 @@
|
|||||||
|
|
||||||
namespace Modules\Admin\Http\Controllers\Admin;
|
namespace Modules\Admin\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use Illuminate\Http\Response;
|
||||||
use Modules\User\Entities\User;
|
use Modules\User\Entities\User;
|
||||||
use Modules\Order\Entities\Order;
|
use Modules\Order\Entities\Order;
|
||||||
use Modules\Review\Entities\Review;
|
use Modules\Review\Entities\Review;
|
||||||
use Modules\Product\Entities\Product;
|
use Modules\Product\Entities\Product;
|
||||||
use Modules\Product\Entities\SearchTerm;
|
use Modules\Product\Entities\SearchTerm;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
class DashboardController
|
class DashboardController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display the dashboard with its widgets.
|
* Display the dashboard with its widgets.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
@@ -28,15 +30,17 @@ class DashboardController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getLatestSearchTerms()
|
private function getLatestSearchTerms()
|
||||||
{
|
{
|
||||||
return SearchTerm::latest('updated_at')->take(5)->get();
|
return SearchTerm::latest('updated_at')->take(5)->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get latest five orders.
|
* Get latest five orders.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
private function getLatestOrders()
|
private function getLatestOrders()
|
||||||
{
|
{
|
||||||
@@ -50,10 +54,11 @@ class DashboardController
|
|||||||
])->latest()->take(5)->get();
|
])->latest()->take(5)->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get latest five reviews.
|
* Get latest five reviews.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
private function getLatestReviews()
|
private function getLatestReviews()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Modules\Admin\Http\Controllers\Admin;
|
namespace Modules\Admin\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use Illuminate\Http\Response;
|
||||||
use Modules\Order\Entities\Order;
|
use Modules\Order\Entities\Order;
|
||||||
|
|
||||||
class SalesAnalyticsController
|
class SalesAnalyticsController
|
||||||
@@ -9,8 +10,9 @@ class SalesAnalyticsController
|
|||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @param \Modules\Order\Entities\Order $order
|
* @param Order $order
|
||||||
* @return \Illuminate\Http\Response
|
*
|
||||||
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function index(Order $order)
|
public function index(Order $order)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,18 +9,19 @@ use Maatwebsite\Sidebar\Presentation\SidebarRenderer;
|
|||||||
class AdminSidebarCreator
|
class AdminSidebarCreator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var \Modules\Admin\Sidebar\AdminSidebar
|
* @var AdminSidebar
|
||||||
*/
|
*/
|
||||||
protected $sidebar;
|
protected $sidebar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Maatwebsite\Sidebar\Presentation\SidebarRenderer
|
* @var SidebarRenderer
|
||||||
*/
|
*/
|
||||||
protected $renderer;
|
protected $renderer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Modules\Admin\Sidebar\AdminSidebar $sidebar
|
* @param AdminSidebar $sidebar
|
||||||
* @param \Maatwebsite\Sidebar\Presentation\SidebarRenderer $renderer
|
* @param SidebarRenderer $renderer
|
||||||
*/
|
*/
|
||||||
public function __construct(AdminSidebar $sidebar, SidebarRenderer $renderer)
|
public function __construct(AdminSidebar $sidebar, SidebarRenderer $renderer)
|
||||||
{
|
{
|
||||||
@@ -28,6 +29,7 @@ class AdminSidebarCreator
|
|||||||
$this->renderer = $renderer;
|
$this->renderer = $renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function create(View $view)
|
public function create(View $view)
|
||||||
{
|
{
|
||||||
$view->sidebar = $this->renderer->render($this->sidebar);
|
$view->sidebar = $this->renderer->render($this->sidebar);
|
||||||
|
|||||||
@@ -4,16 +4,11 @@ namespace Modules\Admin\Providers;
|
|||||||
|
|
||||||
use Modules\Admin\Ui\Facades\Form;
|
use Modules\Admin\Ui\Facades\Form;
|
||||||
use Illuminate\Pagination\Paginator;
|
use Illuminate\Pagination\Paginator;
|
||||||
use Illuminate\Support\Facades\View;
|
|
||||||
use Modules\Support\Traits\AddsAsset;
|
|
||||||
use Illuminate\Foundation\AliasLoader;
|
use Illuminate\Foundation\AliasLoader;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Modules\Admin\Http\ViewComposers\AssetsComposer;
|
|
||||||
|
|
||||||
class AdminServiceProvider extends ServiceProvider
|
class AdminServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
use AddsAsset;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrap any application services.
|
* Bootstrap any application services.
|
||||||
*
|
*
|
||||||
@@ -21,12 +16,10 @@ class AdminServiceProvider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
View::composer('admin::layout', AssetsComposer::class);
|
|
||||||
Paginator::defaultSimpleView('admin::pagination.simple');
|
Paginator::defaultSimpleView('admin::pagination.simple');
|
||||||
|
|
||||||
$this->addAdminAssets('admin.dashboard.index', ['admin.dashboard.css', 'admin.dashboard.js']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the service provider.
|
* Register the service provider.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class SidebarServiceProvider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function boot(SidebarManager $manager)
|
public function boot(SidebarManager $manager)
|
||||||
{
|
{
|
||||||
if (! config('app.installed')) {
|
if (!config('app.installed')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
Modules/Admin/Resources/assets/images/placeholder_image.png
Normal file
BIN
Modules/Admin/Resources/assets/images/placeholder_image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
@@ -1,4 +1,4 @@
|
|||||||
import NProgress from 'nprogress';
|
import NProgress from "nprogress";
|
||||||
|
|
||||||
export default class {
|
export default class {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -14,43 +14,52 @@ export default class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectize() {
|
selectize() {
|
||||||
let selects = $('select.selectize').removeClass('form-control custom-select-black');
|
let selects = $("select.selectize").removeClass(
|
||||||
|
"form-control custom-select-black"
|
||||||
|
);
|
||||||
|
|
||||||
let options = _.merge({
|
let options = _.merge(
|
||||||
valueField: 'id',
|
{
|
||||||
labelField: 'name',
|
valueField: "id",
|
||||||
searchField: 'name',
|
labelField: "name",
|
||||||
delimiter: ',',
|
searchField: "name",
|
||||||
persist: true,
|
delimiter: ",",
|
||||||
selectOnTab: true,
|
persist: true,
|
||||||
hideSelected: false,
|
selectOnTab: true,
|
||||||
allowEmptyOption: true,
|
hideSelected: true,
|
||||||
onItemAdd(value) {
|
allowEmptyOption: true,
|
||||||
this.getItem(value)[0].innerHTML = this.getItem(value)[0].innerHTML.replace(/¦––\s/g, '');
|
onItemAdd(value) {
|
||||||
},
|
this.getItem(value)[0].innerHTML = this.getItem(
|
||||||
onInitialize() {
|
value
|
||||||
for (let index in this.options) {
|
)[0].innerHTML.replace(/¦––\s/g, "");
|
||||||
let label = this.options[index].name;
|
},
|
||||||
let value = this.options[index].id;
|
onInitialize() {
|
||||||
|
for (let index in this.options) {
|
||||||
|
let label = this.options[index].name;
|
||||||
|
let value = this.options[index].id;
|
||||||
|
|
||||||
this.$control.find(`.item[data-value="${value}"]`).html(
|
this.$control
|
||||||
label.replace(/¦––\s/g, '') +
|
.find(`.item[data-value="${value}"]`)
|
||||||
'<a href="javascript:void(0)" class="remove" tabindex="-1">×</a>'
|
.html(
|
||||||
);
|
label.replace(/¦––\s/g, "") +
|
||||||
}
|
'<a href="javascript:void(0)" class="remove" tabindex="-1">×</a>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}, ...FleetCart.selectize);
|
...FleetCart.selectize
|
||||||
|
);
|
||||||
|
|
||||||
for (let select of selects) {
|
for (let select of selects) {
|
||||||
select = $(select);
|
select = $(select);
|
||||||
|
|
||||||
let create = true;
|
let create = true;
|
||||||
let plugins = ['remove_button', 'restore_on_backspace'];
|
let plugins = ["remove_button", "restore_on_backspace"];
|
||||||
|
|
||||||
if (select.hasClass('prevent-creation')) {
|
if (select.hasClass("prevent-creation")) {
|
||||||
create = false;
|
create = false;
|
||||||
|
|
||||||
plugins.remove('restore_on_backspace');
|
plugins.remove("restore_on_backspace");
|
||||||
}
|
}
|
||||||
|
|
||||||
select.selectize(_.merge(options, { create, plugins }));
|
select.selectize(_.merge(options, { create, plugins }));
|
||||||
@@ -58,33 +67,33 @@ export default class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dateTimePicker(elements) {
|
dateTimePicker(elements) {
|
||||||
elements = elements || $('.datetime-picker');
|
elements = elements || $(".datetime-picker");
|
||||||
|
|
||||||
elements = elements instanceof jQuery ? elements : $(elements);
|
elements = elements instanceof jQuery ? elements : $(elements);
|
||||||
|
|
||||||
for (let el of elements) {
|
for (let el of elements) {
|
||||||
$(el).flatpickr({
|
$(el).flatpickr({
|
||||||
mode: el.hasAttribute('data-range') ? 'range' : 'single',
|
mode: el.hasAttribute("data-range") ? "range" : "single",
|
||||||
enableTime: el.hasAttribute('data-time'),
|
enableTime: el.hasAttribute("data-time"),
|
||||||
noCalender: el.hasAttribute('data-no-calender'),
|
noCalender: el.hasAttribute("data-no-calender"),
|
||||||
altInput: true,
|
altInput: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changeAccordionTabState() {
|
changeAccordionTabState() {
|
||||||
$('.accordion-box [data-toggle="tab"]').on('click', (e) => {
|
$('.accordion-box [data-toggle="tab"]').on("click", (e) => {
|
||||||
if (! $(e.currentTarget).parent().hasClass('active')) {
|
if (!$(e.currentTarget).parent().hasClass("active")) {
|
||||||
$('.accordion-tab li.active').removeClass('active');
|
$(".accordion-tab li.active").removeClass("active");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
preventChangingCurrentTab() {
|
preventChangingCurrentTab() {
|
||||||
$('[data-toggle="tab"]').on('click', (e) => {
|
$('[data-toggle="tab"]').on("click", (e) => {
|
||||||
let targetElement = $(e.currentTarget);
|
let targetElement = $(e.currentTarget);
|
||||||
|
|
||||||
if (targetElement.parent().hasClass('active')) {
|
if (targetElement.parent().hasClass("active")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -93,76 +102,85 @@ export default class {
|
|||||||
removeSubmitButtonOffsetOn(tabs, tabsSelector = null) {
|
removeSubmitButtonOffsetOn(tabs, tabsSelector = null) {
|
||||||
tabs = Array.isArray(tabs) ? tabs : [tabs];
|
tabs = Array.isArray(tabs) ? tabs : [tabs];
|
||||||
|
|
||||||
$(tabsSelector || '.accordion-tab li > a').on('click', (e) => {
|
$(tabsSelector || ".accordion-tab li > a").on("click", (e) => {
|
||||||
if (tabs.includes(e.currentTarget.getAttribute('href'))) {
|
if (tabs.includes(e.currentTarget.getAttribute("href"))) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
$('button[type=submit]').parent().removeClass('col-md-offset-2');
|
$("button[type=submit]")
|
||||||
|
.parent()
|
||||||
|
.removeClass("col-md-offset-2");
|
||||||
}, 150);
|
}, 150);
|
||||||
} else {
|
} else {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
$('button[type=submit]').parent().addClass('col-md-offset-2');
|
$("button[type=submit]")
|
||||||
|
.parent()
|
||||||
|
.addClass("col-md-offset-2");
|
||||||
}, 150);
|
}, 150);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonLoading() {
|
buttonLoading() {
|
||||||
$(document).on('click', '[data-loading]', (e) => {
|
$(document).on("click", "[data-loading]", (e) => {
|
||||||
let button = $(e.currentTarget);
|
let button = $(e.currentTarget);
|
||||||
|
|
||||||
button.data('loading-text', button.html())
|
button
|
||||||
.addClass('btn-loading')
|
.data("loading-text", button.html())
|
||||||
.button('loading');
|
.addClass("btn-loading")
|
||||||
|
.button("loading");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
stopButtonLoading(button) {
|
stopButtonLoading(button) {
|
||||||
button = button instanceof jQuery ? button : $(button);
|
button = button instanceof jQuery ? button : $(button);
|
||||||
|
|
||||||
button.data('loading-text', button.html())
|
button
|
||||||
.removeClass('btn-loading')
|
.data("loading-text", button.html())
|
||||||
.button('reset');
|
.removeClass("btn-loading")
|
||||||
|
.button("reset");
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmationModal() {
|
confirmationModal() {
|
||||||
let confirmationModal = $('#confirmation-modal');
|
let confirmationModal = $("#confirmation-modal");
|
||||||
|
|
||||||
$('[data-confirm]').on('click', () => {
|
$("[data-confirm]").on("click", () => {
|
||||||
confirmationModal.modal('show');
|
confirmationModal.modal("show");
|
||||||
});
|
});
|
||||||
|
|
||||||
confirmationModal.find('form').on('submit', () => {
|
confirmationModal.find("form").on("submit", () => {
|
||||||
confirmationModal.find('button.delete').prop('disabled', true);
|
confirmationModal.find("button.delete").prop("disabled", true);
|
||||||
});
|
});
|
||||||
|
|
||||||
confirmationModal.on('hidden.bs.modal', () => {
|
confirmationModal.on("hidden.bs.modal", () => {
|
||||||
confirmationModal.find('button.delete').prop('disabled', false);
|
confirmationModal.find("button.delete").prop("disabled", false);
|
||||||
});
|
});
|
||||||
|
|
||||||
confirmationModal.on('shown.bs.modal', () => {
|
confirmationModal.on("shown.bs.modal", () => {
|
||||||
confirmationModal.find('button.delete').focus();
|
confirmationModal.find("button.delete").focus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tooltip() {
|
tooltip() {
|
||||||
$('[data-toggle="tooltip"]').tooltip({ trigger : 'hover' })
|
$('[data-toggle="tooltip"]')
|
||||||
.on('click', (e) => {
|
.tooltip({ trigger: "hover" })
|
||||||
$(e.currentTarget).tooltip('hide');
|
.on("click", (e) => {
|
||||||
|
$(e.currentTarget).tooltip("hide");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
shortcuts() {
|
shortcuts() {
|
||||||
Mousetrap.bind('f1', () => {
|
Mousetrap.bind("f1", () => {
|
||||||
window.open(`http://envaysoft.com/fleetcart/docs/${FleetCart.version}`, '_blank');
|
window.open("https://docs.envaysoft.com/", "_blank");
|
||||||
});
|
});
|
||||||
|
|
||||||
Mousetrap.bind('?', () => {
|
Mousetrap.bind("?", () => {
|
||||||
$('#keyboard-shortcuts-modal').modal();
|
$("#keyboard-shortcuts-modal").modal();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
nprogress() {
|
nprogress() {
|
||||||
let inMobile = /iphone|ipod|android|ie|blackberry|fennec/i.test(window.navigator.userAgent);
|
let inMobile = /iphone|ipod|android|ie|blackberry|fennec/i.test(
|
||||||
|
window.navigator.userAgent
|
||||||
|
);
|
||||||
|
|
||||||
if (inMobile) {
|
if (inMobile) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import "datatables.net";
|
||||||
|
import "datatables.net-bs";
|
||||||
|
|
||||||
// Initialize state holders.
|
// Initialize state holders.
|
||||||
FleetCart.dataTable = { routes: {}, selected: {} };
|
FleetCart.dataTable = { routes: {}, selected: {} };
|
||||||
|
|
||||||
@@ -24,7 +27,7 @@ export default class {
|
|||||||
{
|
{
|
||||||
serverSide: true,
|
serverSide: true,
|
||||||
processing: true,
|
processing: true,
|
||||||
ajax: this.route("index", { table: true }),
|
ajax: this.route("table", { table: true }),
|
||||||
stateSave: true,
|
stateSave: true,
|
||||||
sort: true,
|
sort: true,
|
||||||
info: true,
|
info: true,
|
||||||
@@ -34,9 +37,6 @@ export default class {
|
|||||||
autoWidth: false,
|
autoWidth: false,
|
||||||
pageLength: 20,
|
pageLength: 20,
|
||||||
lengthMenu: [10, 20, 50, 100, 200],
|
lengthMenu: [10, 20, 50, 100, 200],
|
||||||
language: {
|
|
||||||
processing: '<i class="fa fa-refresh fa-spin"></i>',
|
|
||||||
},
|
|
||||||
order: [
|
order: [
|
||||||
sortColumn.index() !== -1 ? sortColumn.index() : 1,
|
sortColumn.index() !== -1 ? sortColumn.index() : 1,
|
||||||
sortColumn.data("sort") || "desc",
|
sortColumn.data("sort") || "desc",
|
||||||
@@ -74,7 +74,6 @@ export default class {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
stateSaveParams(settings, data) {
|
stateSaveParams(settings, data) {
|
||||||
delete data.start;
|
|
||||||
delete data.search;
|
delete data.search;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -136,7 +135,6 @@ export default class {
|
|||||||
deleted = _.flatten(deleted.concat(ids));
|
deleted = _.flatten(deleted.concat(ids));
|
||||||
|
|
||||||
this.constructor.setSelectedIds(this.selector, []);
|
this.constructor.setSelectedIds(this.selector, []);
|
||||||
|
|
||||||
this.constructor.reload(this.element);
|
this.constructor.reload(this.element);
|
||||||
},
|
},
|
||||||
error: (xhr) => {
|
error: (xhr) => {
|
||||||
@@ -145,7 +143,6 @@ export default class {
|
|||||||
deleted = _.flatten(deleted.concat(ids));
|
deleted = _.flatten(deleted.concat(ids));
|
||||||
|
|
||||||
this.constructor.setSelectedIds(this.selector, []);
|
this.constructor.setSelectedIds(this.selector, []);
|
||||||
|
|
||||||
this.constructor.reload(this.element);
|
this.constructor.reload(this.element);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -157,10 +154,6 @@ export default class {
|
|||||||
let url = this.route(key, { id });
|
let url = this.route(key, { id });
|
||||||
|
|
||||||
$(row).addClass("clickable-row").data("href", url);
|
$(row).addClass("clickable-row").data("href", url);
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
$(".clickable-row td:not(:first-child)").css("cursor", "pointer");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onRowClick(handler) {
|
onRowClick(handler) {
|
||||||
|
|||||||
56
Modules/Admin/Resources/assets/js/Errors.js
Normal file
56
Modules/Admin/Resources/assets/js/Errors.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import Vue from "vue";
|
||||||
|
|
||||||
|
export default class {
|
||||||
|
constructor() {
|
||||||
|
this.errors = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
record(errors) {
|
||||||
|
this.errors = Object.assign({}, this.errors, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
any() {
|
||||||
|
return Object.keys(this.errors).length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
has(key) {
|
||||||
|
return this.errors.hasOwnProperty(this.normalizeKey(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key) {
|
||||||
|
if (this.errors[this.normalizeKey(key)]) {
|
||||||
|
return this.errors[this.normalizeKey(key)][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set(errors = {}) {
|
||||||
|
this.errors = Object.assign({}, this.errors, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear(keys) {
|
||||||
|
if (keys === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys = Array.isArray(keys) ? keys : [keys];
|
||||||
|
|
||||||
|
keys.forEach((key) => {
|
||||||
|
Vue.delete(this.errors, this.normalizeKey(key));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.errors = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeKey(key) {
|
||||||
|
let keyParts = key.split("[");
|
||||||
|
|
||||||
|
// No need to normalize the key.
|
||||||
|
if (keyParts.length === 1) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyParts.join(".").slice(0, -1).replace(/]/g, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
245
Modules/Admin/Resources/assets/js/FleetCart.js
Normal file
245
Modules/Admin/Resources/assets/js/FleetCart.js
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
$.FleetCart = {};
|
||||||
|
|
||||||
|
/* ----------------------------------
|
||||||
|
- FleetCart Options -
|
||||||
|
---------------------------------- */
|
||||||
|
$.FleetCart.options = {
|
||||||
|
animationSpeed: 300,
|
||||||
|
// Sidebar push menu toggle button selector
|
||||||
|
sidebarToggleSelector: "[data-toggle='offcanvas']",
|
||||||
|
// Activate sidebar push menu
|
||||||
|
sidebarPushMenu: true,
|
||||||
|
// BoxRefresh Plugin
|
||||||
|
enableBoxRefresh: true,
|
||||||
|
// Bootstrap.js tooltip
|
||||||
|
enableBSToppltip: true,
|
||||||
|
BSTooltipSelector: "[data-toggle='tooltip']",
|
||||||
|
// Control Sidebar Tree views
|
||||||
|
enableControlTreeView: true,
|
||||||
|
// The standard screen sizes that bootstrap uses.
|
||||||
|
screenSizes: {
|
||||||
|
xs: 480,
|
||||||
|
sm: 768,
|
||||||
|
md: 992,
|
||||||
|
lg: 1200,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------------------------
|
||||||
|
- Implementation -
|
||||||
|
---------------------------------- */
|
||||||
|
$(function () {
|
||||||
|
// Easy access to options
|
||||||
|
var o = $.FleetCart.options;
|
||||||
|
|
||||||
|
// Set up the object
|
||||||
|
_init();
|
||||||
|
|
||||||
|
// Activate layout
|
||||||
|
$.FleetCart.layout.activate();
|
||||||
|
|
||||||
|
// Enable sidebar tree view controls
|
||||||
|
if (o.enableControlTreeView) {
|
||||||
|
$.FleetCart.tree(".sidebar");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate sidebar push menu
|
||||||
|
if (o.sidebarPushMenu) {
|
||||||
|
$.FleetCart.pushMenu.activate(o.sidebarToggleSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate Bootstrap tooltip
|
||||||
|
if (o.enableBSToppltip) {
|
||||||
|
$("body").tooltip({
|
||||||
|
selector: o.BSTooltipSelector,
|
||||||
|
container: "body",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ----------------------------------
|
||||||
|
- Initialize the FleetCart Object -
|
||||||
|
---------------------------------- */
|
||||||
|
function _init() {
|
||||||
|
// Layout
|
||||||
|
$.FleetCart.layout = {
|
||||||
|
activate: function () {
|
||||||
|
var _this = this;
|
||||||
|
_this.fix();
|
||||||
|
|
||||||
|
$(window, ".wrapper").resize(function () {
|
||||||
|
_this.fix();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fix: function () {
|
||||||
|
var window_height = $(window).height();
|
||||||
|
|
||||||
|
$(".wrapper").css("min-height", window_height + "px");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// PushMenu
|
||||||
|
$.FleetCart.pushMenu = {
|
||||||
|
activate: function (toggleBtn) {
|
||||||
|
var screenSizes = $.FleetCart.options.screenSizes;
|
||||||
|
|
||||||
|
$(document).on("click", toggleBtn, function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if ($(window).outerWidth() > screenSizes.md - 1) {
|
||||||
|
if ($("body").hasClass("sidebar-collapse")) {
|
||||||
|
$("body")
|
||||||
|
.removeClass("sidebar-collapse")
|
||||||
|
.trigger("expanded.pushMenu");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("body")
|
||||||
|
.addClass("sidebar-collapse")
|
||||||
|
.trigger("collapsed.pushMenu");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($("body").hasClass("sidebar-open")) {
|
||||||
|
$("body")
|
||||||
|
.removeClass("sidebar-open")
|
||||||
|
.removeClass("sidebar-collapse")
|
||||||
|
.trigger("collapsed.pushMenu");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("body").addClass("sidebar-open").trigger("expanded.pushMenu");
|
||||||
|
});
|
||||||
|
|
||||||
|
$(window).on("resize", function () {
|
||||||
|
if ($(window).outerWidth() > screenSizes.md - 1) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
$("body").removeClass("sidebar-collapse");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".content-wrapper").click(function () {
|
||||||
|
if (
|
||||||
|
$(window).width() <= screenSizes.md - 1 &&
|
||||||
|
$("body").hasClass("sidebar-open")
|
||||||
|
) {
|
||||||
|
$("body").removeClass("sidebar-open");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tree
|
||||||
|
$.FleetCart.tree = function (menu) {
|
||||||
|
var animationSpeed = $.FleetCart.options.animationSpeed;
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.off("click", menu + " li a")
|
||||||
|
.on("click", menu + " li a", function (e) {
|
||||||
|
var self = $(this);
|
||||||
|
var checkElement = self.next();
|
||||||
|
var activeElement = self
|
||||||
|
.closest(".sidebar-menu")
|
||||||
|
.find(".active");
|
||||||
|
|
||||||
|
if (checkElement.is(".treeview-menu")) {
|
||||||
|
self.closest(".sidebar-menu")
|
||||||
|
.find(".selected")
|
||||||
|
.removeClass("selected");
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.parent().is(".active")) {
|
||||||
|
activeElement.toggleClass("closed");
|
||||||
|
} else {
|
||||||
|
activeElement.addClass("closed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
checkElement.is(".treeview-menu") &&
|
||||||
|
checkElement.is(":visible") &&
|
||||||
|
!$("body").hasClass("sidebar-collapse")
|
||||||
|
) {
|
||||||
|
self.parent().removeClass("selected");
|
||||||
|
|
||||||
|
checkElement.slideUp(animationSpeed);
|
||||||
|
} else if (
|
||||||
|
checkElement.is(".treeview-menu") &&
|
||||||
|
!checkElement.is(":visible")
|
||||||
|
) {
|
||||||
|
var ul = self
|
||||||
|
.parents("ul")
|
||||||
|
.first()
|
||||||
|
.find("ul:visible")
|
||||||
|
.slideUp(animationSpeed);
|
||||||
|
|
||||||
|
self.parent().addClass("selected");
|
||||||
|
checkElement.slideDown(animationSpeed);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------
|
||||||
|
- Box Refresh Button -
|
||||||
|
---------------------------------- */
|
||||||
|
(function ($) {
|
||||||
|
$.fn.boxRefresh = function (options) {
|
||||||
|
var settings = $.extend(
|
||||||
|
{
|
||||||
|
trigger: ".refresh-btn",
|
||||||
|
source: "",
|
||||||
|
onLoadStart: function (box) {
|
||||||
|
return box;
|
||||||
|
},
|
||||||
|
onLoadDone: function (box) {
|
||||||
|
return box;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
var overlay = $(
|
||||||
|
'<div class="overlay"><div class="fa fa-refresh fa-spin"></div></div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.each(function () {
|
||||||
|
if (settings.source === "") {
|
||||||
|
if (window.console) {
|
||||||
|
window.console.log(
|
||||||
|
"Please specify a source first - boxRefresh()"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var box = $(this);
|
||||||
|
var rBtn = box.find(settings.trigger).first();
|
||||||
|
|
||||||
|
rBtn.on("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
start(box);
|
||||||
|
|
||||||
|
box.find(".box-body").load(settings.source, function () {
|
||||||
|
done(box);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function start(box) {
|
||||||
|
box.append(overlay);
|
||||||
|
settings.onLoadStart.call(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
function done(box) {
|
||||||
|
box.find(overlay).remove();
|
||||||
|
settings.onLoadDone.call(box);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(jQuery);
|
||||||
16
Modules/Admin/Resources/assets/js/Toaster.js
Normal file
16
Modules/Admin/Resources/assets/js/Toaster.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import Vue from "vue";
|
||||||
|
import VueToast from "vue-toast-notification";
|
||||||
|
|
||||||
|
Vue.use(VueToast);
|
||||||
|
|
||||||
|
export function toaster(message, options = {}) {
|
||||||
|
Vue.$toast.open({
|
||||||
|
message,
|
||||||
|
type: options.type || "default",
|
||||||
|
duration: 5000,
|
||||||
|
dismissible: true,
|
||||||
|
position: "bottom-right",
|
||||||
|
pauseOnHover: true,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,215 +1,48 @@
|
|||||||
$.FleetCart = {};
|
import "bootstrap";
|
||||||
|
import "selectize";
|
||||||
|
import "flatpickr";
|
||||||
|
import "mousetrap";
|
||||||
|
import "./FleetCart";
|
||||||
|
import "./jquery.keypressAction";
|
||||||
|
|
||||||
/* ----------------------------------
|
import Admin from "./Admin";
|
||||||
- FleetCart Options -
|
import Form from "./Form";
|
||||||
---------------------------------- */
|
import DataTable from "./DataTable";
|
||||||
$.FleetCart.options = {
|
import {
|
||||||
animationSpeed: 300,
|
trans,
|
||||||
// Sidebar push menu toggle button selector
|
keypressAction,
|
||||||
sidebarToggleSelector: '[data-toggle=\'offcanvas\']',
|
notify,
|
||||||
// Activate sidebar push menu
|
info,
|
||||||
sidebarPushMenu: true,
|
success,
|
||||||
// BoxRefresh Plugin
|
warning,
|
||||||
enableBoxRefresh: true,
|
error,
|
||||||
// Bootstrap.js tooltip
|
} from "./functions";
|
||||||
enableBSToppltip: true,
|
|
||||||
BSTooltipSelector: '[data-toggle=\'tooltip\']',
|
|
||||||
// Control Sidebar Tree views
|
|
||||||
enableControlTreeView: true,
|
|
||||||
// The standard screen sizes that bootstrap uses.
|
|
||||||
screenSizes: {
|
|
||||||
xs: 480,
|
|
||||||
sm: 768,
|
|
||||||
md: 992,
|
|
||||||
lg: 1200,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ----------------------------------
|
if (
|
||||||
- Implementation -
|
!route().current("admin.products.create") &&
|
||||||
---------------------------------- */
|
!route().current("admin.products.edit")
|
||||||
$(function () {
|
) {
|
||||||
// Easy access to options
|
window.admin = new Admin();
|
||||||
var o = $.FleetCart.options;
|
|
||||||
|
|
||||||
// Set up the object
|
|
||||||
_init();
|
|
||||||
|
|
||||||
// Activate layout
|
|
||||||
$.FleetCart.layout.activate();
|
|
||||||
|
|
||||||
// Enable sidebar tree view controls
|
|
||||||
if (o.enableControlTreeView) {
|
|
||||||
$.FleetCart.tree('.sidebar');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Activate sidebar push menu
|
|
||||||
if (o.sidebarPushMenu) {
|
|
||||||
$.FleetCart.pushMenu.activate(o.sidebarToggleSelector);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Activate Bootstrap tooltip
|
|
||||||
if (o.enableBSToppltip) {
|
|
||||||
$('body').tooltip({
|
|
||||||
selector: o.BSTooltipSelector,
|
|
||||||
container: 'body',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* ----------------------------------
|
|
||||||
- Initialize the FleetCart Object -
|
|
||||||
---------------------------------- */
|
|
||||||
function _init() {
|
|
||||||
|
|
||||||
// Layout
|
|
||||||
$.FleetCart.layout = {
|
|
||||||
activate: function () {
|
|
||||||
var _this = this;
|
|
||||||
_this.fix();
|
|
||||||
|
|
||||||
$(window, '.wrapper').resize(function () {
|
|
||||||
_this.fix();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
fix: function () {
|
|
||||||
var window_height = $(window).height();
|
|
||||||
|
|
||||||
$('.wrapper').css('min-height', window_height + 'px');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// PushMenu
|
|
||||||
$.FleetCart.pushMenu = {
|
|
||||||
activate: function (toggleBtn) {
|
|
||||||
var screenSizes = $.FleetCart.options.screenSizes;
|
|
||||||
|
|
||||||
$(document).on('click', toggleBtn, function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if ($(window).outerWidth() > (screenSizes.md - 1)) {
|
|
||||||
if ($('body').hasClass('sidebar-collapse')) {
|
|
||||||
$('body').removeClass('sidebar-collapse').trigger('expanded.pushMenu');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('body').addClass('sidebar-collapse').trigger('collapsed.pushMenu');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($('body').hasClass('sidebar-open')) {
|
|
||||||
$('body').removeClass('sidebar-open').removeClass('sidebar-collapse').trigger('collapsed.pushMenu');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('body').addClass('sidebar-open').trigger('expanded.pushMenu');
|
|
||||||
});
|
|
||||||
|
|
||||||
$(window).on('resize', function () {
|
|
||||||
if ($(window).outerWidth() > (screenSizes.md - 1)) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
$('body').removeClass('sidebar-collapse');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.content-wrapper').click(function () {
|
|
||||||
if ($(window).width() <= (screenSizes.md - 1) && $('body').hasClass('sidebar-open')) {
|
|
||||||
$('body').removeClass('sidebar-open');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Tree
|
|
||||||
$.FleetCart.tree = function (menu) {
|
|
||||||
var animationSpeed = $.FleetCart.options.animationSpeed;
|
|
||||||
|
|
||||||
$(document).off('click', menu + ' li a')
|
|
||||||
.on('click', menu + ' li a', function (e) {
|
|
||||||
var self = $(this);
|
|
||||||
var checkElement = self.next();
|
|
||||||
var activeElement = self.closest('.sidebar-menu').find('.active');
|
|
||||||
|
|
||||||
if (checkElement.is('.treeview-menu')) {
|
|
||||||
self.closest('.sidebar-menu').find('.selected').removeClass('selected');
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.parent().is('.active')) {
|
|
||||||
activeElement.toggleClass('closed');
|
|
||||||
} else {
|
|
||||||
activeElement.addClass('closed');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible')) && (!$('body').hasClass('sidebar-collapse'))) {
|
|
||||||
self.parent().removeClass('selected');
|
|
||||||
|
|
||||||
checkElement.slideUp(animationSpeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) {
|
|
||||||
var ul = self.parents('ul').first().find('ul:visible').slideUp(animationSpeed);
|
|
||||||
|
|
||||||
self.parent().addClass('selected');
|
|
||||||
checkElement.slideDown(animationSpeed);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------
|
window.form = new Form();
|
||||||
- Box Refresh Button -
|
window.DataTable = DataTable;
|
||||||
---------------------------------- */
|
|
||||||
(function ($) {
|
|
||||||
$.fn.boxRefresh = function (options) {
|
|
||||||
var settings = $.extend({
|
|
||||||
trigger: '.refresh-btn',
|
|
||||||
source: '',
|
|
||||||
onLoadStart: function (box) {
|
|
||||||
return box;
|
|
||||||
},
|
|
||||||
onLoadDone: function (box) {
|
|
||||||
return box;
|
|
||||||
},
|
|
||||||
}, options);
|
|
||||||
|
|
||||||
var overlay = $('<div class="overlay"><div class="fa fa-refresh fa-spin"></div></div>');
|
window.trans = trans;
|
||||||
|
window.keypressAction = keypressAction;
|
||||||
|
window.notify = notify;
|
||||||
|
window.info = info;
|
||||||
|
window.success = success;
|
||||||
|
window.warning = warning;
|
||||||
|
window.error = error;
|
||||||
|
|
||||||
return this.each(function () {
|
$.ajaxSetup({
|
||||||
if (settings.source === '') {
|
headers: {
|
||||||
if (window.console) {
|
Authorization: FleetCart.apiToken,
|
||||||
window.console.log('Please specify a source first - boxRefresh()');
|
"X-CSRF-TOKEN": FleetCart.csrfToken,
|
||||||
}
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return;
|
$(document).on("preInit.dt", () => {
|
||||||
}
|
$(".dataTables_length select").addClass("custom-select-black");
|
||||||
|
});
|
||||||
var box = $(this);
|
|
||||||
var rBtn = box.find(settings.trigger).first();
|
|
||||||
|
|
||||||
rBtn.on('click', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
start(box);
|
|
||||||
|
|
||||||
box.find('.box-body').load(settings.source, function () {
|
|
||||||
done(box);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function start(box) {
|
|
||||||
box.append(overlay);
|
|
||||||
settings.onLoadStart.call(box);
|
|
||||||
}
|
|
||||||
|
|
||||||
function done(box) {
|
|
||||||
box.find(overlay).remove();
|
|
||||||
settings.onLoadDone.call(box);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})(jQuery);
|
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import Chart from 'chart.js';
|
import Chart from "chart.js/auto";
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: "GET",
|
||||||
url: route('admin.sales_analytics.index'),
|
url: route("admin.sales_analytics.index"),
|
||||||
success(response) {
|
success(response) {
|
||||||
let data = { labels: response.labels, sales: [], formatted: [], totalOrders: [] };
|
let data = {
|
||||||
|
labels: response.labels,
|
||||||
|
sales: [],
|
||||||
|
formatted: [],
|
||||||
|
totalOrders: [],
|
||||||
|
};
|
||||||
|
|
||||||
for (let item of response.data) {
|
for (let item of response.data) {
|
||||||
data.sales.push(item.total.amount);
|
data.sales.push(item.total.amount);
|
||||||
@@ -19,45 +24,56 @@ $(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function initSalesAnalyticsChart(data) {
|
function initSalesAnalyticsChart(data) {
|
||||||
new Chart($('.sales-analytics .chart'), {
|
new Chart($(".sales-analytics .chart"), {
|
||||||
type: 'bar',
|
type: "bar",
|
||||||
data: {
|
data: {
|
||||||
labels: data.labels,
|
labels: data.labels,
|
||||||
datasets: [{
|
datasets: [
|
||||||
data: data.sales,
|
{
|
||||||
backgroundColor: [
|
data: data.sales,
|
||||||
'rgba(255, 99, 132, 0.5)',
|
backgroundColor: [
|
||||||
'rgba(54, 162, 235, 0.5)',
|
"rgba(255, 99, 132, 0.5)",
|
||||||
'rgba(255, 206, 86, 0.5)',
|
"rgba(54, 162, 235, 0.5)",
|
||||||
'rgba(75, 192, 192, 0.5)',
|
"rgba(255, 206, 86, 0.5)",
|
||||||
'rgba(153, 102, 255, 0.5)',
|
"rgba(75, 192, 192, 0.5)",
|
||||||
'rgba(255, 159, 64, 0.5)',
|
"rgba(153, 102, 255, 0.5)",
|
||||||
],
|
"rgba(255, 159, 64, 0.5)",
|
||||||
}],
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
barThickness: 1,
|
|
||||||
options: {
|
options: {
|
||||||
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
legend: {
|
plugins: {
|
||||||
display: false,
|
legend: false,
|
||||||
},
|
tooltip: {
|
||||||
tooltips: {
|
displayColors: false,
|
||||||
displayColors: false,
|
callbacks: {
|
||||||
callbacks: {
|
label(item) {
|
||||||
label(item) {
|
let orders = `${trans(
|
||||||
let orders = `${trans('admin::dashboard.sales_analytics.orders')}: ${data.totalOrders[item.index]}`;
|
"admin::dashboard.sales_analytics.orders"
|
||||||
let sales = `${trans('admin::dashboard.sales_analytics.sales')}: ${data.formatted[item.index]}`;
|
)}: ${data.totalOrders[item.dataIndex]}`;
|
||||||
|
|
||||||
return [orders, sales];
|
let sales = `${trans(
|
||||||
|
"admin::dashboard.sales_analytics.sales"
|
||||||
|
)}: ${data.formatted[item.dataIndex]}`;
|
||||||
|
|
||||||
|
return [orders, sales];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
scales: {
|
scales: {
|
||||||
yAxes: [{
|
y: {
|
||||||
|
beginAtZero: true,
|
||||||
ticks: {
|
ticks: {
|
||||||
beginAtZero: true,
|
// Include the currency symbol in the ticks
|
||||||
|
callback: function (value) {
|
||||||
|
return data.formatted[0].charAt(0) + value;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}],
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ohSnap } from './ohsnap';
|
import { ohSnap } from "./ohsnap";
|
||||||
|
|
||||||
export function trans(langKey, replace = {}) {
|
export function trans(langKey, replace = {}) {
|
||||||
let line = window.FleetCart.langs[langKey];
|
let line = window.FleetCart.langs[langKey];
|
||||||
@@ -16,14 +16,14 @@ export function keypressAction(actions) {
|
|||||||
|
|
||||||
export function notify(type, message, { duration = 5000, context = document }) {
|
export function notify(type, message, { duration = 5000, context = document }) {
|
||||||
let types = {
|
let types = {
|
||||||
'info': 'blue',
|
info: "blue",
|
||||||
'success': 'green',
|
success: "green",
|
||||||
'warning': 'yellow',
|
warning: "yellow",
|
||||||
'error': 'red',
|
error: "red",
|
||||||
};
|
};
|
||||||
|
|
||||||
ohSnap(message, {
|
ohSnap(message, {
|
||||||
'container-id': 'notification-toast',
|
"container-id": "notification-toast",
|
||||||
context,
|
context,
|
||||||
color: types[type],
|
color: types[type],
|
||||||
duration,
|
duration,
|
||||||
@@ -31,27 +31,60 @@ export function notify(type, message, { duration = 5000, context = document }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function info(message, duration) {
|
export function info(message, duration) {
|
||||||
notify('info', message, { duration });
|
notify("info", message, { duration });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function success(message, duration) {
|
export function success(message, duration) {
|
||||||
notify('success', message, { duration });
|
notify("success", message, { duration });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function warning(message, duration) {
|
export function warning(message, duration) {
|
||||||
notify('warning', message, { duration });
|
notify("warning", message, { duration });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function error(message, duration) {
|
export function error(message, duration) {
|
||||||
notify('error', message, { duration });
|
notify("error", message, { duration });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateSlug(name) {
|
||||||
|
let slug = "";
|
||||||
|
|
||||||
|
// Change to lower case
|
||||||
|
const nameLower = name.toLowerCase();
|
||||||
|
|
||||||
|
// Letter "e"
|
||||||
|
slug = nameLower.replace(/e|é|è|ẽ|ẻ|ẹ|ê|ế|ề|ễ|ể|ệ/gi, "e");
|
||||||
|
// Letter "a"
|
||||||
|
slug = slug.replace(/a|á|à|ã|ả|ạ|ă|ắ|ằ|ẵ|ẳ|ặ|â|ấ|ầ|ẫ|ẩ|ậ/gi, "a");
|
||||||
|
// Letter "o"
|
||||||
|
slug = slug.replace(/o|ó|ò|õ|ỏ|ọ|ô|ố|ồ|ỗ|ổ|ộ|ơ|ớ|ờ|ỡ|ở|ợ/gi, "o");
|
||||||
|
// Letter "u"
|
||||||
|
slug = slug.replace(/u|ú|ù|ũ|ủ|ụ|ư|ứ|ừ|ữ|ử|ự/gi, "u");
|
||||||
|
// Letter "c"
|
||||||
|
slug = slug.replace(/ć|ĉ|č|ċ|ç/gi, "c");
|
||||||
|
// Letter "i"
|
||||||
|
slug = slug.replace(/î|ï|í|ī|į|ì/gi, "i");
|
||||||
|
// Letter (/, ', ")
|
||||||
|
slug = slug.replace(/\/|'|"|′|’|,|\?|\.|;|]|\[|\+|=|\$|%|&|<|>|:/g, " ");
|
||||||
|
// Letter "d"
|
||||||
|
slug = slug.replace(/đ/gi, "d");
|
||||||
|
// Trim the last whitespace
|
||||||
|
slug = slug.replace(/\s*$/g, "");
|
||||||
|
// Change whitespace to "-"
|
||||||
|
slug = slug.replace(/\s+/g, "-");
|
||||||
|
|
||||||
|
return slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://stackoverflow.com/a/3955096
|
* @see https://stackoverflow.com/a/3955096
|
||||||
*/
|
*/
|
||||||
if (! Array.prototype.remove) {
|
if (!Array.prototype.remove) {
|
||||||
Array.prototype.remove = function () {
|
Array.prototype.remove = function () {
|
||||||
let what, a = arguments, L = a.length, ax;
|
let what,
|
||||||
|
a = arguments,
|
||||||
|
L = a.length,
|
||||||
|
ax;
|
||||||
|
|
||||||
while (L && this.length) {
|
while (L && this.length) {
|
||||||
what = a[--L];
|
what = a[--L];
|
||||||
@@ -68,10 +101,12 @@ if (! Array.prototype.remove) {
|
|||||||
/**
|
/**
|
||||||
* @see https://stackoverflow.com/a/4673436
|
* @see https://stackoverflow.com/a/4673436
|
||||||
*/
|
*/
|
||||||
if (! String.prototype.format) {
|
if (!String.prototype.format) {
|
||||||
String.prototype.format = function () {
|
String.prototype.format = function () {
|
||||||
return this.replace(/%(\d+)%/g, (match, number) => {
|
return this.replace(/%(\d+)%/g, (match, number) => {
|
||||||
return typeof arguments[number] !== 'undefined' ? arguments[number] : match;
|
return typeof arguments[number] !== "undefined"
|
||||||
|
? arguments[number]
|
||||||
|
: match;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,7 @@
|
|||||||
window._ = require('lodash');
|
import jQuery from "jquery";
|
||||||
window.Sortable = require('sortablejs');
|
import _ from "lodash";
|
||||||
window.$ = window.jQuery = require('jquery');
|
import Sortable from "sortablejs";
|
||||||
|
|
||||||
require('bootstrap');
|
window.$ = window.jQuery = jQuery;
|
||||||
require('selectize');
|
window._ = _;
|
||||||
require('flatpickr');
|
window.Sortable = Sortable;
|
||||||
require('jquery-slimscroll');
|
|
||||||
require('mousetrap');
|
|
||||||
require('datatables.net');
|
|
||||||
require('datatables.net-bs');
|
|
||||||
|
|
||||||
require('./app');
|
|
||||||
require('./wysiwyg');
|
|
||||||
require('./jquery.keypressAction');
|
|
||||||
|
|
||||||
import Admin from './Admin';
|
|
||||||
import Form from './Form';
|
|
||||||
import DataTable from './DataTable';
|
|
||||||
import { trans, keypressAction, notify, info, success, warning, error } from './functions';
|
|
||||||
|
|
||||||
window.admin = new Admin();
|
|
||||||
window.form = new Form();
|
|
||||||
window.DataTable = DataTable;
|
|
||||||
|
|
||||||
window.trans = trans;
|
|
||||||
window.keypressAction = keypressAction;
|
|
||||||
window.notify = notify;
|
|
||||||
window.info = info;
|
|
||||||
window.success = success;
|
|
||||||
window.warning = warning;
|
|
||||||
window.error = error;
|
|
||||||
|
|
||||||
$.ajaxSetup({
|
|
||||||
headers: {
|
|
||||||
'Authorization': FleetCart.apiToken,
|
|
||||||
'X-CSRF-TOKEN': FleetCart.csrfToken,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('preInit.dt', () => {
|
|
||||||
$('.dataTables_length select').addClass('custom-select-black');
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,38 +1,46 @@
|
|||||||
import tinyMCE from 'tinymce';
|
import tinyMCE from "tinymce";
|
||||||
|
|
||||||
tinyMCE.baseURL = `${FleetCart.baseUrl}/modules/admin/js/wysiwyg`;
|
export default function () {
|
||||||
|
tinyMCE.baseURL = `${FleetCart.baseUrl}/build/assets/tinymce`;
|
||||||
|
|
||||||
tinyMCE.init({
|
tinyMCE.init({
|
||||||
selector: '.wysiwyg',
|
selector: ".wysiwyg",
|
||||||
theme: 'silver',
|
theme: "silver",
|
||||||
mobile: { theme: 'mobile' },
|
height: 350,
|
||||||
height: 350,
|
menubar: false,
|
||||||
menubar: false,
|
branding: false,
|
||||||
branding: false,
|
image_advtab: true,
|
||||||
image_advtab: true,
|
automatic_uploads: true,
|
||||||
automatic_uploads: true,
|
media_alt_source: false,
|
||||||
media_alt_source: false,
|
media_poster: false,
|
||||||
media_poster: false,
|
relative_urls: false,
|
||||||
relative_urls: false,
|
toolbar_mode: "sliding", // Possible values: floating, sliding, scrolling, wrap
|
||||||
directionality: FleetCart.rtl ? 'rtl' : 'ltr',
|
directionality: FleetCart.rtl ? "rtl" : "ltr",
|
||||||
cache_suffix: `?v=${FleetCart.version}`,
|
cache_suffix: `?v=${FleetCart.version}`,
|
||||||
plugins: 'lists, link, table, image, media, paste, autosave, autolink, wordcount, code, fullscreen',
|
plugins:
|
||||||
toolbar: 'styleselect bold italic underline | bullist numlist | alignleft aligncenter alignright | outdent indent | image media link table | code fullscreen',
|
"lists, link, table, image, media, paste, autosave, autolink,quickbars, wordcount, code, fullscreen",
|
||||||
|
toolbar:
|
||||||
|
"styleselect | bold italic underline strikethrough blockquote | bullist numlist | alignleft aligncenter alignright alignjustify | outdent indent | forecolor removeformat | table | image media link | code fullscreen",
|
||||||
|
quickbars_selection_toolbar:
|
||||||
|
"bold italic | quicklink h2 h3 blockquote quickimage quicktable",
|
||||||
|
images_upload_handler(blobInfo, success, failure) {
|
||||||
|
let formData = new FormData();
|
||||||
|
|
||||||
images_upload_handler(blobInfo, success, failure) {
|
formData.append("file", blobInfo.blob(), blobInfo.filename());
|
||||||
let formData = new FormData();
|
|
||||||
formData.append('file', blobInfo.blob(), blobInfo.filename());
|
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
url: route('admin.media.store'),
|
url: route("admin.media.store"),
|
||||||
data: formData,
|
data: formData,
|
||||||
processData: false,
|
processData: false,
|
||||||
contentType: false,
|
contentType: false,
|
||||||
}).then((file) => {
|
})
|
||||||
success(file.path);
|
.then((file) => {
|
||||||
}).catch((xhr) => {
|
success(file.path);
|
||||||
failure(xhr.responseJSON.message);
|
})
|
||||||
});
|
.catch((xhr) => {
|
||||||
},
|
failure(xhr.responseJSON.message);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.accordion-content {
|
.accordion-content {
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
padding: 20px 0px;
|
padding: 20px 5px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
top: 12px;
|
top: 12px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
color: #000000;
|
color: #333333;
|
||||||
transform: rotateX(180deg);
|
transform: rotateX(180deg);
|
||||||
transition: all 200ms ease-in-out;
|
transition: all 200ms ease-in-out;
|
||||||
}
|
}
|
||||||
@@ -68,14 +68,13 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
font-family: FontAwesome;
|
font-family: FontAwesome;
|
||||||
content: "\f107";
|
content: "\f107";
|
||||||
right: 10px;
|
top: 15px;
|
||||||
top: 12px;
|
right: 15px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
color: #000000;
|
color: #333333;
|
||||||
transform: rotateX(180deg);
|
transform: rotateX(180deg);
|
||||||
transition: all 200ms ease-in-out;
|
transition: all 200ms ease-in-out;
|
||||||
top: 15px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-box .panel-heading [data-toggle="collapse"].collapsed:after,
|
.accordion-box .panel-heading [data-toggle="collapse"].collapsed:after,
|
||||||
@@ -85,12 +84,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.accordion-box .panel-heading [data-toggle="collapse"].collapsed:hover:after {
|
.accordion-box .panel-heading [data-toggle="collapse"].collapsed:hover:after {
|
||||||
color: #000000;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-box-content {
|
.accordion-box-content {
|
||||||
.panel-heading [data-toggle="collapse"].collapsed:hover:after {
|
.panel-heading [data-toggle="collapse"].collapsed:hover:after {
|
||||||
color: #000000;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-group .panel + .panel {
|
.panel-group .panel + .panel {
|
||||||
@@ -102,19 +101,20 @@
|
|||||||
.accordion-box {
|
.accordion-box {
|
||||||
.panel-title a {
|
.panel-title a {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 12px 15px;
|
padding: 10px 15px;
|
||||||
display: block;
|
display: block;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
&.has-error.collapsed {
|
&.has-error {
|
||||||
border-left: 3px solid #ff3366;
|
border-left: 2px solid #ff3366;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-body a {
|
.panel-body a {
|
||||||
color: #333333;
|
color: #333333;
|
||||||
display: block;
|
display: block;
|
||||||
padding: 14px 15px;
|
padding: 12px 15px;
|
||||||
transition: 200ms ease-in-out;
|
transition: 200ms ease-in-out;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
float: none;
|
float: none !important;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
|
||||||
> a {
|
> a {
|
||||||
@@ -193,7 +193,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.has-error > a {
|
&.has-error > a {
|
||||||
border-left: 3px solid #ff3366;
|
border-left: 2px solid #ff3366;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active > a {
|
&.active > a {
|
||||||
@@ -206,9 +206,12 @@
|
|||||||
&:focus {
|
&:focus {
|
||||||
border-left: 3px solid #0068e1;
|
border-left: 3px solid #0068e1;
|
||||||
border-bottom-color: #e9e9e9;
|
border-bottom-color: #e9e9e9;
|
||||||
border-right: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.active.has-error > a {
|
||||||
|
border-left: 2px solid #ff3366;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.nav-tabs > li.active > a {
|
&.nav-tabs > li.active > a {
|
||||||
@@ -223,19 +226,22 @@
|
|||||||
|
|
||||||
.content-accordion {
|
.content-accordion {
|
||||||
&.panel-group {
|
&.panel-group {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel {
|
.panel {
|
||||||
|
border: 1px solid #ebebed;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border: none;
|
box-shadow: none;
|
||||||
border: 1px solid #e9e9e9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-heading {
|
.panel-heading {
|
||||||
background: #f6f6f7;
|
background: #f6f6f7;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
.panel-title a {
|
|
||||||
|
.panel-title [data-toggle="collapse"] {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
|
||||||
@@ -244,9 +250,19 @@
|
|||||||
&:focus {
|
&:focus {
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.has-error {
|
||||||
|
border-left: 2px solid #ff3366;
|
||||||
|
border-radius: 2px 0 0 0;
|
||||||
|
|
||||||
|
&.collapsed {
|
||||||
|
border-radius: 2px 0 0 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-default > .panel-heading + .panel-collapse > .panel-body {
|
.panel-default > .panel-heading + .panel-collapse > .panel-body {
|
||||||
border-top-color: #e9e9e9;
|
border-top-color: #ebebed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,68 +1,69 @@
|
|||||||
.alert {
|
.alert {
|
||||||
border: none;
|
border: none;
|
||||||
color: #555555;
|
color: #555555;
|
||||||
font-size: 15px;
|
font-size: 14px;
|
||||||
padding: 12px 15px;
|
border-radius: 3px;
|
||||||
border-radius: 3px;
|
|
||||||
|
|
||||||
.close {
|
.close {
|
||||||
top: 4px;
|
right: 0;
|
||||||
right: 0;
|
outline: 0;
|
||||||
outline: 0;
|
opacity: 0.5;
|
||||||
opacity: 0.5;
|
color: #626060;
|
||||||
color: #626060;
|
text-shadow: none;
|
||||||
text-shadow: none;
|
font-weight: normal;
|
||||||
font-weight: normal;
|
transition: 150ms ease-in-out;
|
||||||
transition: 200ms ease-in-out;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-text {
|
.alert-text {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 6px 20px 0 45px;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-icon {
|
.alert-icon {
|
||||||
float: left;
|
float: left;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
display: table;
|
display: table;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
> i {
|
> i {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-success {
|
.alert-success {
|
||||||
background: #deedee;
|
background: #deedee;
|
||||||
border-left: 3px solid #37bc9b;
|
border-left: 3px solid #37bc9b;
|
||||||
|
|
||||||
.alert-icon {
|
.alert-icon {
|
||||||
background: #c5e6e2;
|
background: #c5e6e2;
|
||||||
|
|
||||||
> i {
|
> i {
|
||||||
color: #37bc9b;
|
color: #37bc9b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-danger {
|
.alert-danger {
|
||||||
background: #f2e8ee;
|
background: #f2e8ee;
|
||||||
border-left: 3px solid #ff3366;
|
border-left: 3px solid #ff3366;
|
||||||
|
|
||||||
.alert-icon {
|
.alert-icon {
|
||||||
background: #f4ced5;
|
background: #f4ced5;
|
||||||
|
|
||||||
> i {
|
> i {
|
||||||
color: #ff3366;
|
color: #ff3366;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-dismissible {
|
||||||
|
padding-right: 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
/* buttons */
|
/* buttons */
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
font-size: 15px;
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 10px 20px;
|
padding: 8px 16px;
|
||||||
transition: 200ms ease-in-out;
|
transition: 150ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-default {
|
.btn-default {
|
||||||
background: #f1f1f1;
|
background: #f1f1f1;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
border-color: #dddddd;
|
border-color: #dddddd;
|
||||||
|
|
||||||
&.focus,
|
&.focus,
|
||||||
&:focus,
|
&:focus,
|
||||||
&.active {
|
&.active {
|
||||||
@@ -65,6 +67,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-delete {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
fieldset[disabled] .btn-default {
|
fieldset[disabled] .btn-default {
|
||||||
&:focus,
|
&:focus,
|
||||||
&.focus,
|
&.focus,
|
||||||
@@ -310,9 +316,9 @@ fieldset[disabled] .btn-info {
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
height: 16px;
|
height: 14px;
|
||||||
width: 16px;
|
width: 14px;
|
||||||
border: 2px solid #ffffff;
|
border: 1px solid #ffffff;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
border-right-color: transparent;
|
border-right-color: transparent;
|
||||||
border-top-color: transparent;
|
border-top-color: transparent;
|
||||||
@@ -320,7 +326,7 @@ fieldset[disabled] .btn-info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.btn-default:after {
|
&.btn-default:after {
|
||||||
border: 2px solid #0068e1;
|
border: 1px solid #0068e1;
|
||||||
border-right-color: transparent;
|
border-right-color: transparent;
|
||||||
border-top-color: transparent;
|
border-top-color: transparent;
|
||||||
}
|
}
|
||||||
@@ -380,26 +386,35 @@ fieldset[disabled] .btn-info {
|
|||||||
/* label */
|
/* label */
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
font-weight: normal;
|
font-weight: 500;
|
||||||
|
display: inline-block;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label-default {
|
.label-default {
|
||||||
background: #d2d6de;
|
color: #4b5563;
|
||||||
|
background: #e5e7eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label-primary {
|
.label-primary {
|
||||||
background: #0068e1;
|
color: #3b82f6;
|
||||||
|
background: #dbeafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label-success {
|
.label-success {
|
||||||
background: #37bc9b;
|
color: #16a34a;
|
||||||
|
background: #bbf7d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label-danger {
|
.label-danger {
|
||||||
background: #fc4b4b;
|
color: #ef4444;
|
||||||
|
background: #fee2e2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.label-warning {
|
||||||
|
color: #c08304;
|
||||||
|
background: #fdeba3;
|
||||||
|
}
|
||||||
|
|
||||||
/* form error */
|
/* form error */
|
||||||
|
|
||||||
@@ -429,8 +444,8 @@ fieldset[disabled] .btn-info {
|
|||||||
|
|
||||||
.input-group-addon {
|
.input-group-addon {
|
||||||
color: #ff3366;
|
color: #ff3366;
|
||||||
background-color: #f2dede;
|
background: #f6f6f7;
|
||||||
border-color: #ff3366;
|
border-color: #d9d9d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control-feedback {
|
.form-control-feedback {
|
||||||
@@ -438,13 +453,15 @@ fieldset[disabled] .btn-info {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.help-block {
|
.input-group-addon {
|
||||||
margin-bottom: 0;
|
background: #f6f6f7;
|
||||||
|
border-color: #d9d9d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox {
|
.checkbox {
|
||||||
label {
|
label {
|
||||||
font-size: 15px;
|
font-size: 14px;
|
||||||
|
font-weight: 400 !important;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
@@ -458,7 +475,7 @@ fieldset[disabled] .btn-info {
|
|||||||
|
|
||||||
&:checked + label,
|
&:checked + label,
|
||||||
&:not(:checked) + label {
|
&:not(:checked) + label {
|
||||||
font-family: "Roboto", sans-serif;
|
font-family: "Inter", sans-serif;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: 28px;
|
padding-left: 28px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -476,7 +493,7 @@ fieldset[disabled] .btn-info {
|
|||||||
height: 17px;
|
height: 17px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background: #e9e9e9;
|
background: #e9e9e9;
|
||||||
transition: 200ms ease-in-out;
|
transition: 150ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:checked + label:after,
|
&:checked + label:after,
|
||||||
@@ -489,7 +506,7 @@ fieldset[disabled] .btn-info {
|
|||||||
left: 2px;
|
left: 2px;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
-webkit-text-stroke: 1px #0068e1;
|
-webkit-text-stroke: 1px #0068e1;
|
||||||
transition: 200ms ease-in-out;
|
transition: 150ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:checked + label:before {
|
&:checked + label:before {
|
||||||
@@ -509,8 +526,6 @@ fieldset[disabled] .btn-info {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* radio button */
|
|
||||||
|
|
||||||
.radio {
|
.radio {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
@@ -527,7 +542,7 @@ fieldset[disabled] .btn-info {
|
|||||||
|
|
||||||
&:checked + label,
|
&:checked + label,
|
||||||
&:not(:checked) + label {
|
&:not(:checked) + label {
|
||||||
font-family: "Roboto", sans-serif;
|
font-family: "Inter", sans-serif;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: 28px;
|
padding-left: 28px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -557,7 +572,7 @@ fieldset[disabled] .btn-info {
|
|||||||
top: 4px;
|
top: 4px;
|
||||||
left: 3px;
|
left: 3px;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
transition: 200ms ease-in-out;
|
transition: 150ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(:checked) + label:after {
|
&:not(:checked) + label:after {
|
||||||
@@ -569,7 +584,7 @@ fieldset[disabled] .btn-info {
|
|||||||
top: 3px;
|
top: 3px;
|
||||||
left: 3px;
|
left: 3px;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
transition: 200ms ease-in-out;
|
transition: 150ms ease-in-out;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(0);
|
transform: scale(0);
|
||||||
}
|
}
|
||||||
@@ -589,11 +604,60 @@ fieldset[disabled] .btn-info {
|
|||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.switch {
|
||||||
|
[type="checkbox"] {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&:checked + label::before {
|
||||||
|
background: #0068e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked + label::after {
|
||||||
|
left: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: 400 !important;
|
||||||
|
position: relative;
|
||||||
|
min-height: 20px;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
padding-left: 46px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 4px;
|
||||||
|
height: 12px;
|
||||||
|
width: 30px;
|
||||||
|
background: #e9e9e9;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: 150ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: -4px;
|
||||||
|
top: 1px;
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3);
|
||||||
|
transition: 150ms ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* select option */
|
/* select option */
|
||||||
|
|
||||||
.custom-select-white {
|
.custom-select-white {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
background: #f9f9f9 url('../images/arrow-white.png') no-repeat right 8px center;
|
background: #f9f9f9 url("../images/arrow-white.png") no-repeat right 8px
|
||||||
|
center;
|
||||||
background-size: 10px;
|
background-size: 10px;
|
||||||
line-height: normal !important;
|
line-height: normal !important;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
@@ -604,9 +668,9 @@ fieldset[disabled] .btn-info {
|
|||||||
|
|
||||||
.custom-select-black {
|
.custom-select-black {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
background: #ffffff url('../images/arrow-black.png') no-repeat right 8px center;
|
background: #ffffff url("../images/arrow-black.png") no-repeat right 8px
|
||||||
|
center;
|
||||||
background-size: 10px;
|
background-size: 10px;
|
||||||
line-height: normal !important;
|
|
||||||
height: 40px;
|
height: 40px;
|
||||||
padding: 0 30px 0 10px;
|
padding: 0 30px 0 10px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|||||||
@@ -1,99 +1,125 @@
|
|||||||
.grid {
|
.content {
|
||||||
.single-grid {
|
> .row {
|
||||||
position: relative;
|
> div {
|
||||||
overflow: hidden;
|
padding-right: 10px;
|
||||||
height: 130px;
|
padding-left: 10px;
|
||||||
padding: 0 15px;
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 3px;
|
|
||||||
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
h4 {
|
&:first-child {
|
||||||
margin: 22px 0;
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
> .row {
|
||||||
|
> div {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-grid {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 130px;
|
||||||
|
padding: 25px;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: 600;
|
||||||
|
display: block;
|
||||||
|
color: #ffffff;
|
||||||
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
.count {
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
margin-top: 3px;
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
font-size: 36px;
|
font-size: 96px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 15px;
|
top: 10px;
|
||||||
bottom: 22px;
|
right: -10px;
|
||||||
margin: 0;
|
color: rgba(255, 255, 255, 0.25);
|
||||||
}
|
|
||||||
|
|
||||||
&.total-orders {
|
|
||||||
i {
|
|
||||||
color: rgba(0, 104, 225, 0.7);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.total-sales {
|
&.total-sales {
|
||||||
i {
|
background: #f24a78;
|
||||||
color: rgba(112, 124, 210, 0.7);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.total-customers {
|
&.total-orders {
|
||||||
i {
|
background: #2faedf;
|
||||||
color: rgba(255, 51, 102, 0.7);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.total-products {
|
&.total-products {
|
||||||
i {
|
background: #3e8ce8;
|
||||||
color: rgba(55, 188, 155, 0.7);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-panel {
|
&.total-customers {
|
||||||
margin-top: 30px;
|
background: #3abcbf;
|
||||||
padding: 0 15px;
|
}
|
||||||
background: #ffffff;
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 3px;
|
|
||||||
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
.table-responsive {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-header {
|
.grid-header {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
h4 {
|
h5 {
|
||||||
margin: 15px 0;
|
margin: 12px 0;
|
||||||
float: left;
|
float: left;
|
||||||
|
}
|
||||||
i {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sales-analytics {
|
.dashboard-panel {
|
||||||
background: #ffffff;
|
margin-bottom: 20px;
|
||||||
margin-top: 30px;
|
padding: 0 15px;
|
||||||
padding: 0 15px 15px;
|
background: #ffffff;
|
||||||
border-radius: 3px;
|
overflow: hidden;
|
||||||
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.1);
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
.chart {
|
&:last-child {
|
||||||
height: 282px !important;
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.sales-analytics {
|
||||||
|
padding: 0 15px 15px;
|
||||||
|
|
||||||
|
.chart {
|
||||||
|
height: 282px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-responsive {
|
||||||
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.anchor-table {
|
.anchor-table {
|
||||||
.table {
|
.table {
|
||||||
> tbody {
|
> tbody {
|
||||||
> tr {
|
> tr {
|
||||||
> td {
|
> td {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@@ -114,7 +140,7 @@
|
|||||||
color: #0059bd;
|
color: #0059bd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,21 +158,42 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1199px) {
|
@media screen and (max-width: 1199px) {
|
||||||
.single-grid {
|
.content {
|
||||||
&.total-customers {
|
> .row {
|
||||||
margin-top: 15px;
|
> div {
|
||||||
}
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
|
||||||
&.total-products {
|
&:first-child {
|
||||||
margin-top: 15px;
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
> .row {
|
||||||
|
> div {
|
||||||
|
&:nth-child(2) {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 767px) {
|
@media screen and (max-width: 767px) {
|
||||||
.single-grid {
|
.grid {
|
||||||
&.total-orders {
|
> .row {
|
||||||
margin-top: 15px;
|
> div {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,4 @@
|
|||||||
.index-table {
|
@import "datatables.net-bs/css/dataTables.bootstrap";
|
||||||
.label {
|
|
||||||
padding: 6px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .loading-spinner {
|
|
||||||
display: table;
|
|
||||||
margin: 0 auto;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dataTable.table {
|
.dataTable.table {
|
||||||
border-bottom: 1px solid #e9e9e9;
|
border-bottom: 1px solid #e9e9e9;
|
||||||
@@ -16,24 +6,20 @@
|
|||||||
> {
|
> {
|
||||||
thead > tr > th,
|
thead > tr > th,
|
||||||
tfoot > tr > th {
|
tfoot > tr > th {
|
||||||
font-family: 'Open Sans', sans-serif;
|
font-family: "Inter", sans-serif;
|
||||||
color: #4a4a4a;
|
color: #4a4a4a;
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
border-color: #e9e9e9;
|
border-color: #e9e9e9;
|
||||||
|
|
||||||
&:after {
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody > tr {
|
tbody > tr {
|
||||||
transition: 200ms ease-in-out;
|
transition: 150ms ease-in-out;
|
||||||
|
|
||||||
&:first-child > td {
|
&:first-child > td {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-of-type(2n+1) {
|
&:nth-of-type(2n + 1) {
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -41,6 +27,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.clickable-row {
|
||||||
|
> td:not(:first-child) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
> td {
|
> td {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
@@ -87,6 +79,32 @@
|
|||||||
table.dataTable {
|
table.dataTable {
|
||||||
margin: 5px 0 !important;
|
margin: 5px 0 !important;
|
||||||
|
|
||||||
|
&.table-hover {
|
||||||
|
> tbody {
|
||||||
|
> tr:hover {
|
||||||
|
> * {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.table-striped {
|
||||||
|
> tbody {
|
||||||
|
> tr {
|
||||||
|
&.odd > * {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
> * {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
thead {
|
thead {
|
||||||
.sorting,
|
.sorting,
|
||||||
.sorting_asc,
|
.sorting_asc,
|
||||||
@@ -121,23 +139,24 @@ div.dataTables_wrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.dataTables_processing {
|
div.dataTables_processing {
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border: 0;
|
margin: 0 !important;
|
||||||
text-align: center;
|
|
||||||
background: rgba(255, 255, 255, 0.7);
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
border: 0;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
.fa-spin {
|
> div {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
left: 50%;
|
||||||
color: #000;
|
top: 50%;
|
||||||
font-size: 30px;
|
margin: 0;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
> div {
|
||||||
|
background: #0068e1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,8 +169,10 @@ div.dataTables_wrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-delete {
|
div.dataTables_processing {
|
||||||
margin-left: 10px;
|
&.panel {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dataTables_empty {
|
.dataTables_empty {
|
||||||
@@ -191,30 +212,9 @@ div.dataTables_wrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.dataTables_wrapper {
|
div.dataTables_wrapper {
|
||||||
> .row > .col-sm-6 {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.dataTables_filter {
|
div.dataTables_filter {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 340px) {
|
|
||||||
div.dataTables_length {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
.btn-delete {
|
|
||||||
display: table;
|
|
||||||
margin: 15px 0 0 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
div.dataTables_wrapper {
|
|
||||||
div.dataTables_length {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,43 +1,33 @@
|
|||||||
@import '~flatpickr/dist/flatpickr';
|
@import "flatpickr/dist/flatpickr";
|
||||||
|
|
||||||
.flatpickr-calendar {
|
.flatpickr-calendar {
|
||||||
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.flatpickr-months {
|
||||||
|
.flatpickr-month {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flatpickr-prev-month,
|
||||||
|
.flatpickr-next-month {
|
||||||
|
top: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.rtl {
|
.rtl {
|
||||||
.flatpickr-calendar {
|
.flatpickr-prev-month,
|
||||||
&:before,
|
.flatpickr-next-month {
|
||||||
&:after {
|
transform: rotateY(180deg);
|
||||||
right: 22px;
|
}
|
||||||
left: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.flatpickr-month {
|
.flatpickr-current-month {
|
||||||
height: 50px;
|
height: auto;
|
||||||
}
|
|
||||||
|
|
||||||
.flatpickr-prev-month,
|
|
||||||
.flatpickr-next-month {
|
|
||||||
top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rtl {
|
|
||||||
.flatpickr-prev-month,
|
|
||||||
.flatpickr-next-month {
|
|
||||||
transform: rotateY(180deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
span.flatpickr-current-month {
|
|
||||||
.cur-month {
|
|
||||||
font-family: "Open Sans", sans-serif !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.flatpickr-weekdays {
|
.flatpickr-weekdays {
|
||||||
span {
|
span {
|
||||||
font-family: "Open Sans", sans-serif;
|
font-family: "Inter", sans-serif;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,20 @@
|
|||||||
@import '~bootstrap/dist/css/bootstrap';
|
@import "bootstrap/dist/css/bootstrap";
|
||||||
@import '~font-awesome/css/font-awesome';
|
@import "font-awesome/css/font-awesome";
|
||||||
@import '~nprogress/nprogress';
|
@import "nprogress/nprogress";
|
||||||
@import '~datatables.net-bs/css/dataTables.bootstrap';
|
@import "flatpickr/dist/ie";
|
||||||
@import '~flatpickr/dist/ie';
|
@import "./datatables";
|
||||||
@import './datatables';
|
@import "./selectize";
|
||||||
@import './selectize';
|
@import "./toaster.scss";
|
||||||
@import './wysiwyg';
|
@import "./ohsnap";
|
||||||
@import './ohsnap';
|
@import "./flatpickr";
|
||||||
@import './flatpickr';
|
@import "./classes";
|
||||||
@import './classes';
|
@import "./tab";
|
||||||
@import './tab';
|
@import "./alert";
|
||||||
@import './alert';
|
@import "./modal";
|
||||||
@import './modal';
|
@import "./utilities";
|
||||||
@import './utilities';
|
@import "./accordion";
|
||||||
@import './accordion';
|
@import "./fleetcart";
|
||||||
@import './fleetcart';
|
@import "./panel";
|
||||||
@import './panel';
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
@@ -26,11 +25,11 @@ html {
|
|||||||
|
|
||||||
> i {
|
> i {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.overflow-hidden {
|
.overflow-hidden {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nprogress {
|
#nprogress {
|
||||||
@@ -49,13 +48,13 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sortable-ghost {
|
.sortable-ghost {
|
||||||
opacity: .2;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group.open .dropdown-toggle,
|
.btn-group.open .dropdown-toggle,
|
||||||
.btn-group .dropdown-toggle:active {
|
.btn-group .dropdown-toggle:active {
|
||||||
-webkit-box-shadow: none;
|
-webkit-box-shadow: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dot {
|
.dot {
|
||||||
@@ -74,23 +73,33 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.options {
|
.options {
|
||||||
|
&.table > {
|
||||||
|
thead > {
|
||||||
|
tr > {
|
||||||
|
th {
|
||||||
|
padding: 6px 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tr td:first-child {
|
tr td:first-child {
|
||||||
width: 34px;
|
width: 35px;
|
||||||
min-width: 34px;
|
min-width: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr td:last-child {
|
tr td:last-child {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drag-icon {
|
.drag-handle {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #737881;
|
color: #737881;
|
||||||
cursor: move;
|
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
margin-top: 12px;
|
margin-top: 11px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
cursor: move;
|
||||||
|
|
||||||
i {
|
i {
|
||||||
float: left;
|
float: left;
|
||||||
@@ -103,7 +112,11 @@ html {
|
|||||||
|
|
||||||
.choose-file,
|
.choose-file,
|
||||||
.delete-row {
|
.delete-row {
|
||||||
padding: 10px 15px;
|
padding: 8px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-row {
|
||||||
|
color: #4d4d4d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +128,7 @@ html {
|
|||||||
margin-left: -1px;
|
margin-left: -1px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 1px solid #e9e9e9;
|
border: 1px solid #e9e9e9;
|
||||||
transition: 200ms ease-in-out;
|
transition: 150ms ease-in-out;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -159,7 +172,8 @@ html {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover, &:focus {
|
&:hover,
|
||||||
|
&:focus {
|
||||||
color: #0068e1;
|
color: #0068e1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,3 +207,7 @@ html {
|
|||||||
.empty {
|
.empty {
|
||||||
color: #626060;
|
color: #626060;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[v-cloak] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
outline: 0;
|
outline: 0;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
-webkit-text-stroke: 1px #ffffff;
|
-webkit-text-stroke: 1px #ffffff;
|
||||||
transition: 200ms ease-in-out;
|
transition: 150ms ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
.panel-wrap {
|
.panel-wrap {
|
||||||
.panel {
|
.panel {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border: 1px solid #e9e9e9;
|
border: 1px solid #e9e9e9;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
||||||
.panel-header {
|
.panel-header {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
background: #f6f6f7;
|
background: #f6f6f7;
|
||||||
border-bottom: 1px solid #e9e9e9;
|
border-bottom: 1px solid #e9e9e9;
|
||||||
|
|
||||||
.drag-icon {
|
.drag-handle {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 2px 10px 0 0;
|
margin: 3px 10px 0 0;
|
||||||
color: #737881;
|
color: #737881;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -21,19 +23,24 @@
|
|||||||
> i {
|
> i {
|
||||||
float: left;
|
float: left;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-left: 1px;
|
margin-left: 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
|
color: #737881;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|
||||||
i {
|
i {
|
||||||
-webkit-text-stroke: 1px #f6f6f7;
|
-webkit-text-stroke: 1px #f6f6f7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +48,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-image {
|
.panel-image {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 15px;
|
left: 15px;
|
||||||
@@ -101,4 +108,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import '~selectize/dist/css/selectize';
|
@import "selectize/dist/css/selectize";
|
||||||
|
|
||||||
.selectize-control:not(.multi) {
|
.selectize-control:not(.multi) {
|
||||||
.selectize-input .item,
|
.selectize-input .item,
|
||||||
@@ -10,21 +10,34 @@
|
|||||||
padding-right: 0 !important;
|
padding-right: 0 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectize-control {
|
.selectize-control {
|
||||||
&.multi .selectize-input > div {
|
&.multi {
|
||||||
padding: 4px 8px;
|
.selectize-input {
|
||||||
|
&.has-items {
|
||||||
|
padding: 4px 4px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
padding: 3px 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.single .selectize-input {
|
&.single .selectize-input {
|
||||||
cursor: text;
|
cursor: text;
|
||||||
|
|
||||||
|
&.full {
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
content: none;
|
content: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> span {
|
> span {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 2px 0
|
padding: 2px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@@ -39,6 +52,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
border-left-color: #e9e9e9;
|
border-left-color: #e9e9e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,22 +65,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.selectize-input {
|
.selectize-input {
|
||||||
|
padding: 4px 12px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border-color: #d9d9d9;
|
border-color: #d9d9d9;
|
||||||
min-height: 40px;
|
min-height: 36px;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
transition: border-color ease-in-out .15s;
|
transition: border-color ease-in-out 0.15s;
|
||||||
|
|
||||||
.dropdown-active {
|
.dropdown-active {
|
||||||
-webkit-border-radius: 0;
|
-webkit-border-radius: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
> input {
|
|
||||||
margin-top: 2px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
input {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
transition: 0ms !important;
|
transition: 0ms !important;
|
||||||
@@ -87,7 +98,7 @@
|
|||||||
|
|
||||||
&.focus {
|
&.focus {
|
||||||
border-color: #6f8dfd;
|
border-color: #6f8dfd;
|
||||||
box-shadow: 0 0 2px rgba(30, 140, 190, .8);
|
box-shadow: 0 0 2px rgba(30, 140, 190, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
@@ -98,6 +109,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ltr {
|
||||||
|
.selectize-input {
|
||||||
|
> input {
|
||||||
|
margin-top: 4px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.selectize-dropdown {
|
.selectize-dropdown {
|
||||||
[data-selectable] {
|
[data-selectable] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -108,7 +127,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.selectize-dropdown-content .create strong {
|
.selectize-dropdown-content .create strong {
|
||||||
font-family: "Open Sans", sans-serif;
|
font-family: "Inter", sans-serif;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
width: 0;
|
width: 0;
|
||||||
background: #0068e1;
|
background: #0068e1;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
transition: 200ms ease-in-out;
|
transition: 150ms ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
Modules/Admin/Resources/assets/sass/toaster.scss
Normal file
23
Modules/Admin/Resources/assets/sass/toaster.scss
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
@import "vue-toast-notification/dist/theme-sugar";
|
||||||
|
|
||||||
|
.v-toast {
|
||||||
|
padding: 20px 20px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-toast__item {
|
||||||
|
min-height: 3em;
|
||||||
|
|
||||||
|
.v-toast__icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-toast__text {
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 991px) {
|
||||||
|
.v-toast {
|
||||||
|
padding: 15px 15px 10px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,191 +1,219 @@
|
|||||||
.p-tb-0 {
|
.p-tb-0 {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-tb-5 {
|
.p-tb-5 {
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-tb-10 {
|
.p-tb-10 {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-tb-15 {
|
.p-tb-15 {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-t-0 {
|
.p-t-0 {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-t-5 {
|
.p-t-5 {
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-t-10 {
|
.p-t-10 {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-t-15 {
|
.p-t-15 {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-b-0 {
|
.p-b-0 {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-b-5 {
|
.p-b-5 {
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-b-10 {
|
.p-b-10 {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-b-15 {
|
.p-b-15 {
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-l-0 {
|
.p-l-0 {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-l-5 {
|
.p-l-5 {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-l-10 {
|
.p-l-10 {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-l-15 {
|
.p-l-15 {
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-r-0 {
|
.p-r-0 {
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-r-5 {
|
.p-r-5 {
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-r-10 {
|
.p-r-10 {
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-r-15 {
|
.p-r-15 {
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-tb-0 {
|
.m-tb-0 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-tb-5 {
|
.m-tb-5 {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-tb-10 {
|
.m-tb-10 {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-tb-15 {
|
.m-tb-15 {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-t-0 {
|
.m-t-0 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-t-5 {
|
.m-t-5 {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-t-10 {
|
.m-t-10 {
|
||||||
margin-top: 10px;
|
margin-top: 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-t-15 {
|
.m-t-15 {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-b-0 {
|
.m-b-0 {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-b-5 {
|
.m-b-5 {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-b-10 {
|
.m-b-10 {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-b-15 {
|
.m-b-15 {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-b-20 {
|
||||||
|
margin-bottom: 20px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-l-0 {
|
.m-l-0 {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-l-5 {
|
.m-l-5 {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-l-10 {
|
.m-l-10 {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-l-15 {
|
.m-l-15 {
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-r-0 {
|
.m-r-0 {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-r-5 {
|
.m-r-5 {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-r-10 {
|
.m-r-10 {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-r-15 {
|
.m-r-15 {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-border {
|
.no-border {
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-padding {
|
.no-padding {
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-margin {
|
.no-margin {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-shadow {
|
.no-shadow {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cursor-auto {
|
.cursor-auto {
|
||||||
cursor: auto !important;
|
cursor: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cursor-move {
|
||||||
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-left {
|
.text-left {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.d-block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.d-flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-content-between {
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,3 +13,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tox-tinymce {
|
||||||
|
border-radius: 3px !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,40 +1,49 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'admin' => 'Admin',
|
||||||
'visit_store' => 'Visit Store',
|
'visit_store' => 'Visit Store',
|
||||||
|
|
||||||
'form' => [
|
'form' => [
|
||||||
'please_select' => 'Please Select',
|
'please_select' => 'Please Select',
|
||||||
],
|
],
|
||||||
|
|
||||||
'buttons' => [
|
'buttons' => [
|
||||||
'save' => 'Save',
|
'save' => 'Save',
|
||||||
'delete' => 'Delete',
|
'delete' => 'Delete',
|
||||||
'cancel' => 'Cancel',
|
'cancel' => 'Cancel',
|
||||||
],
|
],
|
||||||
|
|
||||||
'table' => [
|
'table' => [
|
||||||
'id' => 'ID',
|
'id' => 'ID',
|
||||||
'status' => 'Status',
|
'status' => 'Status',
|
||||||
'created' => 'Created',
|
'created' => 'Created',
|
||||||
|
'updated' => 'Updated',
|
||||||
'date' => 'Date',
|
'date' => 'Date',
|
||||||
],
|
],
|
||||||
|
|
||||||
'pagination' => [
|
'pagination' => [
|
||||||
'previous' => 'Previous',
|
'previous' => 'Previous',
|
||||||
'next' => 'Next',
|
'next' => 'Next',
|
||||||
],
|
],
|
||||||
|
|
||||||
'delete' => [
|
'delete' => [
|
||||||
'confirmation' => 'Confirmation',
|
'confirmation' => 'Confirmation',
|
||||||
'confirmation_message' => 'Are you sure you want to delete?',
|
'confirmation_message' => 'Are you sure you want to delete?',
|
||||||
],
|
],
|
||||||
|
|
||||||
'shortcuts' => [
|
'shortcuts' => [
|
||||||
'available_shortcuts' => 'Available keyboard shortcuts on this page',
|
'available_shortcuts' => 'Available keyboard shortcuts on this page',
|
||||||
'this_menu' => 'This Menu',
|
'this_menu' => 'This Menu',
|
||||||
'back_to_index' => 'Back to :name Index',
|
'back_to_index' => 'Back to :name Index',
|
||||||
],
|
],
|
||||||
|
|
||||||
'errors' => [
|
'errors' => [
|
||||||
'404' => '404',
|
'404' => '404',
|
||||||
'404_title' => 'Oops! This page was not found',
|
'404_title' => 'Oops! This page was not found',
|
||||||
'404_description' => 'The page you are looking for was not found.',
|
'404_description' => 'The page you are looking for was not found',
|
||||||
'500' => '500',
|
'500' => '500',
|
||||||
'500_title' => 'Oops! Something went wrong',
|
'500_title' => 'Oops! Something went wrong',
|
||||||
'500_description' => 'An administrator was notified.',
|
'500_description' => 'An administrator was notified',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'resource_saved' => ':resource has been saved.',
|
'resource_created' => ':resource created',
|
||||||
'resource_deleted' => ':resource has been deleted.',
|
'resource_updated' => ':resource updated',
|
||||||
'permission_denied' => 'Permission Denied (required permission: ":permission").',
|
'resource_deleted' => ':resource deleted',
|
||||||
|
'permission_denied' => 'Permission Denied (required permission: ":permission")',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
@endpush
|
@endpush
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script>
|
<script type="module">
|
||||||
@if (isset($buttons) && in_array('create', $buttons))
|
@if (isset($buttons) && in_array('create', $buttons))
|
||||||
keypressAction([
|
keypressAction([
|
||||||
{ key: 'c', route: '{{ route("admin.{$resource}.create") }}'}
|
{ key: 'c', route: '{{ route("admin.{$resource}.create") }}'}
|
||||||
@@ -54,10 +54,10 @@
|
|||||||
Mousetrap.bind('backspace', function () {
|
Mousetrap.bind('backspace', function () {
|
||||||
$('.btn-delete').trigger('click');
|
$('.btn-delete').trigger('click');
|
||||||
});
|
});
|
||||||
|
|
||||||
@isset($resource)
|
@isset($resource)
|
||||||
DataTable.setRoutes('#{{ $resource }}-table .table', {
|
DataTable.setRoutes('#{{ $resource }}-table .table', {
|
||||||
index: '{{ "admin.{$resource}.index" }}',
|
table: '{{ "admin.{$resource}.table" }}',
|
||||||
edit: '{{ "admin.{$resource}.edit" }}',
|
edit: '{{ "admin.{$resource}.edit" }}',
|
||||||
destroy: '{{ "admin.{$resource}.destroy" }}',
|
destroy: '{{ "admin.{$resource}.destroy" }}',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<div class="col-lg-3 col-md-6 col-sm-6">
|
<div class="col-lg-3 col-md-6 col-sm-6">
|
||||||
<div class="single-grid total-customers">
|
<div class="single-grid total-customers">
|
||||||
<h4>{{ trans('admin::dashboard.total_customers') }}</h4>
|
<i class="fa fa-users" aria-hidden="true"></i>
|
||||||
|
|
||||||
<i class="fa fa-users pull-left" aria-hidden="true"></i>
|
<span class="title">{{ trans('admin::dashboard.total_customers') }}</span>
|
||||||
<span class="pull-right">{{ $totalCustomers }}</span>
|
|
||||||
|
<span class="count">{{ $totalCustomers }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<div class="col-lg-3 col-md-6 col-sm-6">
|
<div class="col-lg-3 col-md-6 col-sm-6">
|
||||||
<div class="single-grid total-orders">
|
<div class="single-grid total-orders">
|
||||||
<h4>{{ trans('admin::dashboard.total_orders') }}</h4>
|
<i class="fa fa-shopping-cart" aria-hidden="true"></i>
|
||||||
|
|
||||||
<i class="fa fa-shopping-cart pull-left" aria-hidden="true"></i>
|
<span class="title">{{ trans('admin::dashboard.total_orders') }}</span>
|
||||||
<span class="pull-right">{{ $totalOrders }}</span>
|
|
||||||
|
<span class="count">{{ $totalOrders }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<div class="col-lg-3 col-md-6 col-sm-6">
|
<div class="col-lg-3 col-md-6 col-sm-6">
|
||||||
<div class="single-grid total-products">
|
<div class="single-grid total-products">
|
||||||
<h4>{{ trans('admin::dashboard.total_products') }}</h4>
|
|
||||||
|
|
||||||
<i class="fa fa-cubes" aria-hidden="true"></i>
|
<i class="fa fa-cubes" aria-hidden="true"></i>
|
||||||
<span class="pull-right">{{ $totalProducts }}</span>
|
|
||||||
|
<span class="title">{{ trans('admin::dashboard.total_products') }}</span>
|
||||||
|
|
||||||
|
<span class="count">{{ $totalProducts }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<div class="col-lg-3 col-md-6 col-sm-6">
|
<div class="col-lg-3 col-md-6 col-sm-6">
|
||||||
<div class="single-grid total-sales">
|
<div class="single-grid total-sales">
|
||||||
<h4>{{ trans('admin::dashboard.total_sales') }}</h4>
|
<i class="fa fa-money" aria-hidden="true"></i>
|
||||||
|
|
||||||
<i class="fa fa-money pull-left" aria-hidden="true"></i>
|
<span class="title">{{ trans('admin::dashboard.total_sales') }}</span>
|
||||||
<span class="pull-right">{{ $totalSales->format() }}</span>
|
|
||||||
|
<span class="count">{{ $totalSales->format() }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
@section('title', trans('admin::dashboard.dashboard'))
|
@section('title', trans('admin::dashboard.dashboard'))
|
||||||
|
|
||||||
@section('content_header')
|
@section('content_header')
|
||||||
<h2 class="pull-left">{{ trans('admin::dashboard.dashboard') }}</h2>
|
<h3 class="pull-left">{{ trans('admin::dashboard.dashboard') }}</h3>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
@@ -44,3 +44,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@push('globals')
|
||||||
|
@vite([
|
||||||
|
"Modules/Admin/Resources/assets/sass/dashboard.scss",
|
||||||
|
"Modules/Admin/Resources/assets/js/dashboard.js",
|
||||||
|
])
|
||||||
|
@endpush
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<div class="dashboard-panel">
|
<div class="dashboard-panel">
|
||||||
<div class="grid-header">
|
<div class="grid-header">
|
||||||
<h4><i class="fa fa-shopping-cart" aria-hidden="true"></i>{{ trans('admin::dashboard.latest_orders') }}</h4>
|
<h5>{{ trans('admin::dashboard.latest_orders') }}</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<div class="dashboard-panel">
|
<div class="dashboard-panel">
|
||||||
<div class="grid-header">
|
<div class="grid-header">
|
||||||
<h4><i class="fa fa-comments-o" aria-hidden="true"></i>{{ trans('admin::dashboard.latest_reviews') }}</h4>
|
<h5>{{ trans('admin::dashboard.latest_reviews') }}</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<div class="dashboard-panel">
|
<div class="dashboard-panel">
|
||||||
<div class="grid-header">
|
<div class="grid-header">
|
||||||
<h4><i class="fa fa-search" aria-hidden="true"></i>{{ trans('admin::dashboard.latest_search_terms') }}</h4>
|
<h5>{{ trans('admin::dashboard.latest_search_terms') }}</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
<div class="sales-analytics">
|
<div class="dashboard-panel sales-analytics">
|
||||||
<div class="grid-header clearfix">
|
<div class="grid-header clearfix">
|
||||||
<h4>
|
<h5>{{ trans('admin::dashboard.sales_analytics_title') }}</h5>
|
||||||
<i class="fa fa-bar-chart" aria-hidden="true"></i>{{ trans('admin::dashboard.sales_analytics_title') }}
|
|
||||||
</h4>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="canvas">
|
<div class="canvas">
|
||||||
|
|||||||
@@ -1,60 +1,57 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{ locale() }}">
|
<html lang="{{ locale() }}">
|
||||||
|
<head>
|
||||||
|
<base href="{{ url('/') }}">
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
|
|
||||||
<head>
|
<title>
|
||||||
<base href="{{ url('/') }}">
|
@yield('title') - {{ setting('store_name') }} {{trans('admin::admin.admin')}}
|
||||||
<meta charset="UTF-8">
|
</title>
|
||||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
|
||||||
|
|
||||||
<title>
|
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
||||||
@yield('title') - {{ setting('store_name') }} Admin
|
|
||||||
</title>
|
|
||||||
|
|
||||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:600|Roboto:400,500" rel="stylesheet">
|
@vite([
|
||||||
|
'Modules/Admin/Resources/assets/sass/main.scss',
|
||||||
|
'Modules/Admin/Resources/assets/js/main.js',
|
||||||
|
'Modules/Admin/Resources/assets/js/app.js'
|
||||||
|
])
|
||||||
|
|
||||||
@foreach ($assets->allCss() as $css)
|
@stack('styles')
|
||||||
<link media="all" type="text/css" rel="stylesheet" href="{{ v($css) }}">
|
|
||||||
@endforeach
|
|
||||||
|
|
||||||
@stack('styles')
|
@include('admin::partials.globals')
|
||||||
|
</head>
|
||||||
|
|
||||||
@include('admin::partials.globals')
|
<body class="skin-blue sidebar-mini offcanvas clearfix {{ is_rtl() ? 'rtl' : 'ltr' }}" dir>
|
||||||
</head>
|
<div class="left-side"></div>
|
||||||
|
|
||||||
<body class="skin-blue sidebar-mini offcanvas clearfix {{ is_rtl() ? 'rtl' : 'ltr' }}">
|
@include('admin::partials.sidebar')
|
||||||
<div class="left-side"></div>
|
|
||||||
|
|
||||||
@include('admin::partials.sidebar')
|
<div class="wrapper">
|
||||||
|
<div class="content-wrapper">
|
||||||
|
@include('admin::partials.top_nav')
|
||||||
|
|
||||||
<div class="wrapper">
|
<section class="content-header clearfix">
|
||||||
<div class="content-wrapper">
|
@yield('content_header')
|
||||||
@include('admin::partials.top_nav')
|
</section>
|
||||||
|
|
||||||
<section class="content-header clearfix">
|
<section class="content">
|
||||||
@yield('content_header')
|
@include('admin::partials.notification')
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="content">
|
@yield('content')
|
||||||
@include('admin::partials.notification')
|
</section>
|
||||||
|
|
||||||
@yield('content')
|
<div id="notification-toast"></div>
|
||||||
</section>
|
</div>
|
||||||
|
|
||||||
<div id="notification-toast"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
@include('admin::partials.footer')
|
@include('admin::partials.footer')
|
||||||
|
@include('admin::partials.confirmation_modal')
|
||||||
@include('admin::partials.confirmation_modal')
|
|
||||||
|
|
||||||
@foreach ($assets->allJs() as $js)
|
|
||||||
<script src="{{ v($js) }}"></script>
|
|
||||||
@endforeach
|
|
||||||
|
|
||||||
@stack('scripts')
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
@stack('scripts')
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<i class="fa fa-times" aria-hidden="true"></i>
|
<i class="fa fa-times" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<h3 class="modal-title">{{ trans('admin::admin.delete.confirmation') }}</h3>
|
<h4 class="modal-title">{{ trans('admin::admin.delete.confirmation') }}</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<a type="button" class="close" data-dismiss="modal" aria-label="Close">×</a>
|
<a type="button" class="close" data-dismiss="modal" aria-label="Close">×</a>
|
||||||
<h4 class="modal-title">{{ trans('admin::admin.shortcuts.available_shortcuts') }}</h4>
|
<h5 class="modal-title">{{ trans('admin::admin.shortcuts.available_shortcuts') }}</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -21,7 +21,11 @@
|
|||||||
|
|
||||||
<footer class="main-footer">
|
<footer class="main-footer">
|
||||||
<div class="pull-right hidden-xs">
|
<div class="pull-right hidden-xs">
|
||||||
<span>v{{ fleetcart_version() }}</span>
|
<span>
|
||||||
|
<strong>
|
||||||
|
v{{ fleetcart_version() }}
|
||||||
|
</strong>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="#" data-toggle="modal" data-target="#keyboard-shortcuts-modal">
|
<a href="#" data-toggle="modal" data-target="#keyboard-shortcuts-modal">
|
||||||
@@ -30,6 +34,6 @@
|
|||||||
|
|
||||||
<span>
|
<span>
|
||||||
Copyright © {{ date('Y') }} <a href="{{ route('home') }}"
|
Copyright © {{ date('Y') }} <a href="{{ route('home') }}"
|
||||||
target="_blank">{{ setting('store_name') }}</a>
|
target="_blank"><strong>{{ setting('store_name') }}</strong></a>
|
||||||
</span>
|
</span>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
FleetCart.langs['admin::admin.buttons.delete'] = '{{ trans('admin::admin.buttons.delete') }}';
|
FleetCart.langs['admin::admin.buttons.delete'] = '{{ trans('admin::admin.buttons.delete') }}';
|
||||||
FleetCart.langs['media::media.file_manager.title'] = '{{ trans('media::media.file_manager.title') }}';
|
FleetCart.langs['media::media.file_manager.title'] = '{{ trans('media::media.file_manager.title') }}';
|
||||||
FleetCart.langs['media::messages.image_has_been_added'] = '{{ trans('media::messages.image_has_been_added') }}';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@stack('globals')
|
@stack('globals')
|
||||||
|
|||||||
@@ -1,23 +1,18 @@
|
|||||||
@if (session()->has('success'))
|
@if (session()->has('success'))
|
||||||
<div class="alert alert-success fade in alert-dismissable clearfix">
|
<div class="alert alert-success fade in alert-dismissible clearfix">
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||||
|
|
||||||
<div class="alert-icon">
|
|
||||||
<i class="fa fa-check" aria-hidden="true"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span class="alert-text">{{ session('success') }}</span>
|
<span class="alert-text">{{ session('success') }}</span>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (session()->has('error'))
|
@if (session()->has('error'))
|
||||||
<div class="alert alert-danger fade in alert-dismissable clearfix">
|
<div class="alert alert-danger fade in alert-dismissible clearfix">
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||||
|
|
||||||
<div class="alert-icon">
|
|
||||||
<i class="fa fa-exclamation" aria-hidden="true"></i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span class="alert-text">{{ session('error') }}</span>
|
<span class="alert-text">{{ session('error') }}</span>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
|
@stack('notifications')
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
<nav class="navbar navbar-static-top clearfix">
|
<nav class="navbar navbar-static-top clearfix">
|
||||||
<ul class="nav navbar-nav clearfix">
|
<ul class="nav navbar-nav clearfix">
|
||||||
<li class="visit-store hidden-sm hidden-xs">
|
<li class="visit-store hidden-sm hidden-xs">
|
||||||
<a href="{{ route('home') }}">
|
<a href="{{ route('home') }}" target="_blank">
|
||||||
<i class="fa fa-desktop"></i>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<title>storefront-outline</title>
|
||||||
|
<path d="M5.06 3C4.63 3 4.22 3.14 3.84 3.42S3.24 4.06 3.14 4.5L2.11 8.91C1.86 10 2.06 10.95 2.72 11.77L3 12.05V19C3 19.5 3.2 20 3.61 20.39S4.5 21 5 21H19C19.5 21 20 20.8 20.39 20.39S21 19.5 21 19V12.05L21.28 11.77C21.94 10.95 22.14 10 21.89 8.91L20.86 4.5C20.73 4.06 20.5 3.7 20.13 3.42C19.77 3.14 19.38 3 18.94 3H5.06M18.89 4.97L19.97 9.38C20.06 9.81 19.97 10.2 19.69 10.55C19.44 10.86 19.13 11 18.75 11C18.44 11 18.17 10.9 17.95 10.66C17.73 10.43 17.61 10.16 17.58 9.84L16.97 5L18.89 4.97M5.06 5H7.03L6.42 9.84C6.3 10.63 5.91 11 5.25 11C4.84 11 4.53 10.86 4.31 10.55C4.03 10.2 3.94 9.81 4.03 9.38L5.06 5M9.05 5H11V9.7C11 10.05 10.89 10.35 10.64 10.62C10.39 10.88 10.08 11 9.7 11C9.36 11 9.07 10.88 8.84 10.59S8.5 10 8.5 9.66V9.5L9.05 5M13 5H14.95L15.5 9.5C15.58 9.92 15.5 10.27 15.21 10.57C14.95 10.87 14.61 11 14.2 11C13.89 11 13.61 10.88 13.36 10.62C13.11 10.35 13 10.05 13 9.7V5M7.45 12.05C8.08 12.67 8.86 13 9.8 13C10.64 13 11.38 12.67 12 12.05C12.69 12.67 13.45 13 14.3 13C15.17 13 15.92 12.67 16.55 12.05C17.11 12.67 17.86 13 18.8 13H19.03V19H5V13H5.25C6.16 13 6.89 12.67 7.45 12.05Z" />
|
||||||
|
</svg>
|
||||||
|
|
||||||
{{ trans('admin::admin.visit_store') }}
|
{{ trans('admin::admin.visit_store') }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dropdown top-nav-menu pull-right">
|
<li class="user dropdown top-nav-menu pull-right">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
<i class="fa fa-user-circle-o"></i><span>{{ $currentUser->first_name }}</span>
|
<i class="fa fa-user-circle-o"></i><span>{{ $currentUser->first_name }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
8
Modules/Admin/Services/CRUDService.php
Normal file
8
Modules/Admin/Services/CRUDService.php
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\Services;
|
||||||
|
|
||||||
|
class CRUDService implements CRUDAactions
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,21 +5,22 @@ namespace Modules\Admin\Sidebar;
|
|||||||
use Maatwebsite\Sidebar\Menu;
|
use Maatwebsite\Sidebar\Menu;
|
||||||
use Maatwebsite\Sidebar\Sidebar;
|
use Maatwebsite\Sidebar\Sidebar;
|
||||||
use Nwidart\Modules\Facades\Module;
|
use Nwidart\Modules\Facades\Module;
|
||||||
use Nwidart\Modules\Contracts\RepositoryInterface as Modules;
|
|
||||||
|
|
||||||
class AdminSidebar implements Sidebar
|
class AdminSidebar implements Sidebar
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The menu instance.
|
* The menu instance.
|
||||||
*
|
*
|
||||||
* @var \Maatwebsite\Sidebar\Menu
|
* @var Menu
|
||||||
*/
|
*/
|
||||||
protected $menu;
|
protected $menu;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new sidebar instance.
|
* Create a new sidebar instance.
|
||||||
*
|
*
|
||||||
* @param \Maatwebsite\Sidebar\Menu $menu
|
* @param Menu $menu
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(Menu $menu)
|
public function __construct(Menu $menu)
|
||||||
@@ -27,10 +28,11 @@ class AdminSidebar implements Sidebar
|
|||||||
$this->menu = $menu;
|
$this->menu = $menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the built menu.
|
* Get the built menu.
|
||||||
*
|
*
|
||||||
* @return \Maatwebsite\Sidebar\Menu
|
* @return Menu
|
||||||
*/
|
*/
|
||||||
public function getMenu()
|
public function getMenu()
|
||||||
{
|
{
|
||||||
@@ -39,6 +41,7 @@ class AdminSidebar implements Sidebar
|
|||||||
return $this->menu;
|
return $this->menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the sidebar menu.
|
* Build the sidebar menu.
|
||||||
*
|
*
|
||||||
@@ -50,6 +53,7 @@ class AdminSidebar implements Sidebar
|
|||||||
$this->addModuleExtenders();
|
$this->addModuleExtenders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add active theme's sidebar extender.
|
* Add active theme's sidebar extender.
|
||||||
*
|
*
|
||||||
@@ -62,6 +66,24 @@ class AdminSidebar implements Sidebar
|
|||||||
$this->add("Themes\\{$theme}\\Sidebar\\SidebarExtender");
|
$this->add("Themes\\{$theme}\\Sidebar\\SidebarExtender");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add sidebar extender to the menu.
|
||||||
|
*
|
||||||
|
* @param string $extender
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function add($extender)
|
||||||
|
{
|
||||||
|
if (class_exists($extender)) {
|
||||||
|
resolve($extender)->extend($this->menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->menu->add($this->menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add all enabled modules sidebar extender.
|
* Add all enabled modules sidebar extender.
|
||||||
*
|
*
|
||||||
@@ -73,19 +95,4 @@ class AdminSidebar implements Sidebar
|
|||||||
$this->add("Modules\\{$module->getName()}\\Sidebar\\SidebarExtender");
|
$this->add("Modules\\{$module->getName()}\\Sidebar\\SidebarExtender");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add sidebar extender to the menu.
|
|
||||||
*
|
|
||||||
* @param string $extender
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function add($extender)
|
|
||||||
{
|
|
||||||
if (class_exists($extender)) {
|
|
||||||
resolve($extender)->extend($this->menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->menu->add($this->menu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class BaseSidebarExtender
|
|||||||
{
|
{
|
||||||
protected $auth;
|
protected $auth;
|
||||||
|
|
||||||
|
|
||||||
public function __construct(Authentication $auth)
|
public function __construct(Authentication $auth)
|
||||||
{
|
{
|
||||||
$this->auth = $auth;
|
$this->auth = $auth;
|
||||||
|
|||||||
@@ -3,16 +3,21 @@
|
|||||||
namespace Modules\Admin\Traits;
|
namespace Modules\Admin\Traits;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Modules\Admin\Ui\AdminTable;
|
||||||
|
use Modules\Support\Eloquent\Model;
|
||||||
use Modules\Support\Search\Searchable;
|
use Modules\Support\Search\Searchable;
|
||||||
use Modules\Admin\Ui\Facades\TabManager;
|
use Modules\Admin\Ui\Facades\TabManager;
|
||||||
|
use Illuminate\Database\Eloquent\Model as EloquentModel;
|
||||||
|
|
||||||
trait HasCrudActions
|
trait HasCrudActions
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param Request $request
|
||||||
* @return \Illuminate\Http\Response
|
*
|
||||||
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
@@ -24,32 +29,14 @@ trait HasCrudActions
|
|||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->has('table')) {
|
|
||||||
return $this->getModel()->table($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
return view("{$this->viewPath}.index");
|
return view("{$this->viewPath}.index");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$data = array_merge([
|
|
||||||
'tabs' => TabManager::get($this->getModel()->getTable()),
|
|
||||||
$this->getResourceName() => $this->getModel(),
|
|
||||||
], $this->getFormData('create'));
|
|
||||||
|
|
||||||
return view("{$this->viewPath}.create", $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store a newly created resource in storage.
|
* Store a newly created resource in storage.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
@@ -65,15 +52,42 @@ trait HasCrudActions
|
|||||||
return $this->redirectTo($entity);
|
return $this->redirectTo($entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request()->wantsJson()) {
|
||||||
|
return response()->json(
|
||||||
|
[
|
||||||
|
'success' => true,
|
||||||
|
'message' => trans('admin::messages.resource_created', ['resource' => $this->getLabel()]),
|
||||||
|
], 200
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return redirect()->route("{$this->getRoutePrefix()}.index")
|
return redirect()->route("{$this->getRoutePrefix()}.index")
|
||||||
->withSuccess(trans('admin::messages.resource_saved', ['resource' => $this->getLabel()]));
|
->withSuccess(trans('admin::messages.resource_created', ['resource' => $this->getLabel()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$data = array_merge([
|
||||||
|
'tabs' => TabManager::get($this->getModel()->getTable()),
|
||||||
|
$this->getResourceName() => $this->getModel(),
|
||||||
|
], $this->getFormData('create'));
|
||||||
|
|
||||||
|
return view("{$this->viewPath}.create", $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Http\Response
|
*
|
||||||
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
@@ -86,11 +100,13 @@ trait HasCrudActions
|
|||||||
return view("{$this->viewPath}.show")->with($this->getResourceName(), $entity);
|
return view("{$this->viewPath}.show")->with($this->getResourceName(), $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the form for editing the specified resource.
|
* Show the form for editing the specified resource.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Http\Response
|
*
|
||||||
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
@@ -99,14 +115,17 @@ trait HasCrudActions
|
|||||||
$this->getResourceName() => $this->getEntity($id),
|
$this->getResourceName() => $this->getEntity($id),
|
||||||
], $this->getFormData('edit', $id));
|
], $this->getFormData('edit', $id));
|
||||||
|
|
||||||
|
|
||||||
return view("{$this->viewPath}.edit", $data);
|
return view("{$this->viewPath}.edit", $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Http\Response
|
*
|
||||||
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function update($id)
|
public function update($id)
|
||||||
{
|
{
|
||||||
@@ -118,24 +137,39 @@ trait HasCrudActions
|
|||||||
$this->getRequest('update')->all()
|
$this->getRequest('update')->all()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$entity->withoutEvents(function () use ($entity) {
|
||||||
|
$entity->touch();
|
||||||
|
});
|
||||||
|
|
||||||
$this->searchable($entity);
|
$this->searchable($entity);
|
||||||
|
|
||||||
if (method_exists($this, 'redirectTo')) {
|
if (method_exists($this, 'redirectTo')) {
|
||||||
return $this->redirectTo($entity)
|
return $this->redirectTo($entity)
|
||||||
->withSuccess(trans('admin::messages.resource_saved', ['resource' => $this->getLabel()]));
|
->withSuccess(trans('admin::messages.resource_updated', ['resource' => $this->getLabel()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request()->wantsJson()) {
|
||||||
|
return response()->json(
|
||||||
|
[
|
||||||
|
'success' => true,
|
||||||
|
'message' => trans('admin::messages.resource_updated', ['resource' => $this->getLabel()]),
|
||||||
|
], 200
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->route("{$this->getRoutePrefix()}.index")
|
return redirect()->route("{$this->getRoutePrefix()}.index")
|
||||||
->withSuccess(trans('admin::messages.resource_saved', ['resource' => $this->getLabel()]));
|
->withSuccess(trans('admin::messages.resource_updated', ['resource' => $this->getLabel()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy resources by given ids.
|
* Destroy resources by given ids.
|
||||||
*
|
*
|
||||||
* @param string $ids
|
* @param string $ids
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function destroy($ids)
|
public function destroy(string $ids): void
|
||||||
{
|
{
|
||||||
$this->getModel()
|
$this->getModel()
|
||||||
->withoutGlobalScope('active')
|
->withoutGlobalScope('active')
|
||||||
@@ -143,13 +177,153 @@ trait HasCrudActions
|
|||||||
->delete();
|
->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the table response for the resource.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return AdminTable
|
||||||
|
*/
|
||||||
|
public function table(Request $request): AdminTable
|
||||||
|
{
|
||||||
|
return $this->getModel()->table($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new instance of the model.
|
||||||
|
*
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
protected function getModel()
|
||||||
|
{
|
||||||
|
return new $this->model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable search syncing for the entity.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function disableSearchSyncing(): void
|
||||||
|
{
|
||||||
|
if ($this->isSearchable()) {
|
||||||
|
$this->getModel()->disableSearchSyncing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the entity is searchable.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isSearchable(): bool
|
||||||
|
{
|
||||||
|
return in_array(Searchable::class, class_uses_recursive($this->getModel()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get name of the resource.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getResourceName(): string
|
||||||
|
{
|
||||||
|
return match (true) {
|
||||||
|
isset($this->resourceName) => $this->resourceName,
|
||||||
|
default => lcfirst(class_basename($this->model))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get form data for the given action.
|
||||||
|
*
|
||||||
|
* @param string $action
|
||||||
|
* @param mixed ...$args
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getFormData(string $action, ...$args): array
|
||||||
|
{
|
||||||
|
return match (true) {
|
||||||
|
method_exists($this, 'formData') => $this->formData(...$args),
|
||||||
|
($action === 'create' && method_exists($this, 'createFormData')) => $this->createFormData(),
|
||||||
|
($action === 'edit' && method_exists($this, 'editFormData')) => $this->editFormData(...$args),
|
||||||
|
default => []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get request object
|
||||||
|
*
|
||||||
|
* @param string $action
|
||||||
|
*
|
||||||
|
* @return Request
|
||||||
|
*/
|
||||||
|
protected function getRequest(string $action): Request
|
||||||
|
{
|
||||||
|
return match (true) {
|
||||||
|
!isset($this->validation) => request(),
|
||||||
|
isset($this->validation[$action]) => resolve($this->validation[$action]),
|
||||||
|
default => resolve($this->validation),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the given model instance searchable.
|
||||||
|
*
|
||||||
|
* @param $entity
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function searchable($entity): void
|
||||||
|
{
|
||||||
|
if ($this->isSearchable()) {
|
||||||
|
$entity->searchable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get label of the resource.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function getLabel(): string
|
||||||
|
{
|
||||||
|
return trans($this->label);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get route prefix of the resource.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getRoutePrefix(): string
|
||||||
|
{
|
||||||
|
return match (true) {
|
||||||
|
isset($this->routePrefix) => $this->routePrefix,
|
||||||
|
default => "admin.{$this->getModel()->getTable()}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an entity by the given id.
|
* Get an entity by the given id.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Database\Eloquent\Model
|
*
|
||||||
|
* @return EloquentModel
|
||||||
*/
|
*/
|
||||||
protected function getEntity($id)
|
protected function getEntity(int|string $id): EloquentModel
|
||||||
{
|
{
|
||||||
return $this->getModel()
|
return $this->getModel()
|
||||||
->with($this->relations())
|
->with($this->relations())
|
||||||
@@ -157,142 +331,20 @@ trait HasCrudActions
|
|||||||
->findOrFail($id);
|
->findOrFail($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the relations that should be eager loaded.
|
* Get the relations that should be eager loaded.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function relations()
|
private function relations(): array
|
||||||
{
|
{
|
||||||
return collect($this->with ?? [])->mapWithKeys(function ($relation) {
|
return collect($this->with ?? [])->mapWithKeys(
|
||||||
return [$relation => function ($query) {
|
function ($relation) {
|
||||||
return $query->withoutGlobalScope('active');
|
return [$relation => function ($query) {
|
||||||
}];
|
return $query->withoutGlobalScope('active');
|
||||||
})->all();
|
}];
|
||||||
}
|
}
|
||||||
|
)->all();
|
||||||
/**
|
|
||||||
* Get form data for the given action.
|
|
||||||
*
|
|
||||||
* @param string $action
|
|
||||||
* @param mixed ...$args
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getFormData($action, ...$args)
|
|
||||||
{
|
|
||||||
if (method_exists($this, 'formData')) {
|
|
||||||
return $this->formData(...$args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($action === 'create' && method_exists($this, 'createFormData')) {
|
|
||||||
return $this->createFormData();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($action === 'edit' && method_exists($this, 'editFormData')) {
|
|
||||||
return $this->editFormData(...$args);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get name of the resource.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function getResourceName()
|
|
||||||
{
|
|
||||||
if (isset($this->resourceName)) {
|
|
||||||
return $this->resourceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lcfirst(class_basename($this->model));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get label of the resource.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function getLabel()
|
|
||||||
{
|
|
||||||
return trans($this->label);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get route prefix of the resource.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function getRoutePrefix()
|
|
||||||
{
|
|
||||||
if (isset($this->routePrefix)) {
|
|
||||||
return $this->routePrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "admin.{$this->getModel()->getTable()}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a new instance of the model.
|
|
||||||
*
|
|
||||||
* @return \Modules\Support\Eloquent\Model
|
|
||||||
*/
|
|
||||||
protected function getModel()
|
|
||||||
{
|
|
||||||
return new $this->model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get request object
|
|
||||||
*
|
|
||||||
* @param string $action
|
|
||||||
* @return \Illuminate\Http\Request
|
|
||||||
*/
|
|
||||||
protected function getRequest($action)
|
|
||||||
{
|
|
||||||
if (! isset($this->validation)) {
|
|
||||||
return request();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($this->validation[$action])) {
|
|
||||||
return resolve($this->validation[$action]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolve($this->validation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable search syncing for the entity.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function disableSearchSyncing()
|
|
||||||
{
|
|
||||||
if ($this->isSearchable()) {
|
|
||||||
$this->getModel()->disableSearchSyncing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the entity is searchable.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function isSearchable()
|
|
||||||
{
|
|
||||||
return in_array(Searchable::class, class_uses_recursive($this->getModel()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make the given model instance searchable.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function searchable($entity)
|
|
||||||
{
|
|
||||||
if ($this->isSearchable($entity)) {
|
|
||||||
$entity->searchable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
namespace Modules\Admin\Ui;
|
namespace Modules\Admin\Ui;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Yajra\DataTables\DataTables;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Yajra\DataTables\Exceptions\Exception;
|
||||||
use Illuminate\Contracts\Support\Responsable;
|
use Illuminate\Contracts\Support\Responsable;
|
||||||
|
|
||||||
class AdminTable implements Responsable
|
class AdminTable implements Responsable
|
||||||
@@ -11,28 +17,30 @@ class AdminTable implements Responsable
|
|||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $rawColumns = [];
|
protected array $rawColumns = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raw columns that will not be escaped.
|
* Raw columns that will not be escaped.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $defaultRawColumns = [
|
protected array $defaultRawColumns = [
|
||||||
'checkbox', 'thumbnail', 'status', 'created',
|
'checkbox', 'thumbnail', 'status', 'created', 'updated',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Source of the table.
|
* Source of the table.
|
||||||
*
|
*
|
||||||
* @var \Illuminate\Database\Eloquent\Builder
|
* @var Builder
|
||||||
*/
|
*/
|
||||||
protected $source;
|
protected $source;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new table instance.
|
* Create a new table instance.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Database\Eloquent\Builder $source
|
* @param Builder $source
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct($source = null)
|
public function __construct($source = null)
|
||||||
@@ -40,22 +48,38 @@ class AdminTable implements Responsable
|
|||||||
$this->source = $source;
|
$this->source = $source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an HTTP response that represents the object.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function toResponse($request)
|
||||||
|
{
|
||||||
|
return $this->make()->toJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make table response for the resource.
|
* Make table response for the resource.
|
||||||
*
|
*
|
||||||
* @param mixed $source
|
* @param mixed $source
|
||||||
* @return \Illuminate\Http\JsonResponse
|
*
|
||||||
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function make()
|
public function make()
|
||||||
{
|
{
|
||||||
return $this->newTable();
|
return $this->newTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new datatable instance;
|
* Create a new datatable instance;
|
||||||
*
|
*
|
||||||
* @param mixed $source
|
* @return DataTables
|
||||||
* @return \Yajra\DataTables\DataTables
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function newTable()
|
public function newTable()
|
||||||
{
|
{
|
||||||
@@ -71,18 +95,10 @@ class AdminTable implements Responsable
|
|||||||
->editColumn('created', function ($entity) {
|
->editColumn('created', function ($entity) {
|
||||||
return view('admin::partials.table.date')->with('date', $entity->created_at);
|
return view('admin::partials.table.date')->with('date', $entity->created_at);
|
||||||
})
|
})
|
||||||
|
->editColumn('updated', function ($entity) {
|
||||||
|
return view('admin::partials.table.date')->with('date', $entity->updated_at);
|
||||||
|
})
|
||||||
->rawColumns(array_merge($this->defaultRawColumns, $this->rawColumns))
|
->rawColumns(array_merge($this->defaultRawColumns, $this->rawColumns))
|
||||||
->removeColumn('translations');
|
->removeColumn('translations');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an HTTP response that represents the object.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
|
||||||
public function toResponse($request)
|
|
||||||
{
|
|
||||||
return $this->make()->toJson();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ trait InputFields
|
|||||||
{$attributes}"
|
{$attributes}"
|
||||||
. ($disabled ? 'disabled' : '')
|
. ($disabled ? 'disabled' : '')
|
||||||
. ($readonly ? 'readonly ' : '') .
|
. ($readonly ? 'readonly ' : '') .
|
||||||
'>';
|
'>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function textareaField($name, $value, $class, $attributes, $options)
|
protected function textareaField($name, $value, $class, $attributes, $options)
|
||||||
{
|
{
|
||||||
$readonly = array_pull($options, 'readonly', false);
|
$readonly = array_pull($options, 'readonly', false);
|
||||||
@@ -38,21 +39,22 @@ trait InputFields
|
|||||||
{$attributes}"
|
{$attributes}"
|
||||||
. ($disabled ? 'disabled' : '')
|
. ($disabled ? 'disabled' : '')
|
||||||
. ($readonly ? 'readonly ' : '') .
|
. ($readonly ? 'readonly ' : '') .
|
||||||
">{$value}</textarea>";
|
">{$value}</textarea>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function checkboxField($name, $value, $class, $attributes, $options, $label)
|
protected function checkboxField($name, $value, $class, $attributes, $options, $label)
|
||||||
{
|
{
|
||||||
$checked = array_pull($options, 'checked', false);
|
$checked = array_pull($options, 'checked', false);
|
||||||
$disabled = array_get($options, 'disabled', false);
|
$disabled = array_get($options, 'disabled', false);
|
||||||
|
|
||||||
if (! is_null($value)) {
|
if (!is_null($value)) {
|
||||||
$checked = $value;
|
$checked = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
$html = '<div class="checkbox">';
|
$html = '<div class="checkbox">';
|
||||||
|
|
||||||
if (! $disabled) {
|
if (!$disabled) {
|
||||||
$html .= "<input type='hidden' value='0' name='{$name}'>";
|
$html .= "<input type='hidden' value='0' name='{$name}'>";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,9 +65,9 @@ trait InputFields
|
|||||||
id='{$name}'
|
id='{$name}'
|
||||||
{$attributes}
|
{$attributes}
|
||||||
value='1'"
|
value='1'"
|
||||||
. ($checked ? 'checked ' : '')
|
. ($checked ? 'checked ' : '')
|
||||||
. ($disabled ? 'disabled' : '') .
|
. ($disabled ? 'disabled' : '') .
|
||||||
'>';
|
'>';
|
||||||
|
|
||||||
$html .= "<label for='{$name}'>{$label}</label>";
|
$html .= "<label for='{$name}'>{$label}</label>";
|
||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
@@ -73,6 +75,7 @@ trait InputFields
|
|||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function selectField($name, $value, $class, $attributes, $options, $list)
|
protected function selectField($name, $value, $class, $attributes, $options, $list)
|
||||||
{
|
{
|
||||||
$multiple = array_get($options, 'multiple', false);
|
$multiple = array_get($options, 'multiple', false);
|
||||||
@@ -86,7 +89,7 @@ trait InputFields
|
|||||||
{$attributes}"
|
{$attributes}"
|
||||||
. ($disabled ? 'disabled' : '')
|
. ($disabled ? 'disabled' : '')
|
||||||
. ($readonly ? 'readonly ' : '') .
|
. ($readonly ? 'readonly ' : '') .
|
||||||
'>';
|
'>';
|
||||||
|
|
||||||
foreach ($list as $listValue => $listName) {
|
foreach ($list as $listValue => $listName) {
|
||||||
$listValue = e($listValue);
|
$listValue = e($listValue);
|
||||||
@@ -94,10 +97,10 @@ trait InputFields
|
|||||||
|
|
||||||
if ($multiple && $value instanceof Collection) {
|
if ($multiple && $value instanceof Collection) {
|
||||||
$selected = $value->where('id', $listValue)->isNotEmpty() ? 'selected' : '';
|
$selected = $value->where('id', $listValue)->isNotEmpty() ? 'selected' : '';
|
||||||
} elseif ($multiple && is_array($value)) {
|
} else if ($multiple && is_array($value)) {
|
||||||
$selected = in_array($listValue, $value) ? 'selected' : '';
|
$selected = in_array($listValue, $value) ? 'selected' : '';
|
||||||
} else {
|
} else {
|
||||||
$selected = (! is_null($value) && $value == $listValue) ? 'selected' : '';
|
$selected = (!is_null($value) && $value == $listValue) ? 'selected' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$html .= "<option value='{$listValue}' {$selected}>{$listName}</option>";
|
$html .= "<option value='{$listValue}' {$selected}>{$listName}</option>";
|
||||||
@@ -108,6 +111,7 @@ trait InputFields
|
|||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function field($name, $title, $errors, $entity, $options, callable $fieldCallback, ...$args)
|
protected function field($name, $title, $errors, $entity, $options, callable $fieldCallback, ...$args)
|
||||||
{
|
{
|
||||||
$value = $this->getValue($entity, $name);
|
$value = $this->getValue($entity, $name);
|
||||||
@@ -139,7 +143,7 @@ trait InputFields
|
|||||||
$html .= "<div class='col-md-{$fieldCol}'>";
|
$html .= "<div class='col-md-{$fieldCol}'>";
|
||||||
$html .= call_user_func_array($fieldCallback, $params);
|
$html .= call_user_func_array($fieldCallback, $params);
|
||||||
|
|
||||||
if ($help && ! $errors->has($normalizedName)) {
|
if ($help && !$errors->has($normalizedName)) {
|
||||||
$html .= "<span class='help-block'>{$help}</span>";
|
$html .= "<span class='help-block'>{$help}</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,15 +155,31 @@ trait InputFields
|
|||||||
return new HtmlString($html);
|
return new HtmlString($html);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function normalizeTranslatableFieldName($name)
|
|
||||||
|
protected function generateHtmlAttributes($options = [])
|
||||||
{
|
{
|
||||||
if (starts_with($name, 'translatable[')) {
|
$this->unsetUnnecessaryAttributes($options);
|
||||||
return 'translatable.' . str_between($name, 'translatable[', ']');
|
|
||||||
|
$attributes = '';
|
||||||
|
|
||||||
|
foreach ($options as $attr => $value) {
|
||||||
|
$attributes .= "{$attr}='{$value}' ";
|
||||||
}
|
}
|
||||||
|
|
||||||
return $name;
|
return $attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function unsetUnnecessaryAttributes(&$options = [])
|
||||||
|
{
|
||||||
|
foreach ($this->unnecessaryAttributes as $attribute) {
|
||||||
|
if (array_key_exists($attribute, $options)) {
|
||||||
|
unset($options[$attribute]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function label($name, $title, $labelCol = 3, $required = false)
|
protected function label($name, $title, $labelCol = 3, $required = false)
|
||||||
{
|
{
|
||||||
$html = "<label for='{$name}' class='col-md-{$labelCol} control-label text-left'>{$title}";
|
$html = "<label for='{$name}' class='col-md-{$labelCol} control-label text-left'>{$title}";
|
||||||
@@ -171,6 +191,7 @@ trait InputFields
|
|||||||
return $html .= '</label>';
|
return $html .= '</label>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getValue($entity, $name)
|
private function getValue($entity, $name)
|
||||||
{
|
{
|
||||||
if (is_object($entity) && method_exists($entity, 'translate') && $entity->isTranslationAttribute($name)) {
|
if (is_object($entity) && method_exists($entity, 'translate') && $entity->isTranslationAttribute($name)) {
|
||||||
@@ -201,25 +222,13 @@ trait InputFields
|
|||||||
return old($normalizedName, $value);
|
return old($normalizedName, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generateHtmlAttributes($options = [])
|
|
||||||
|
private function normalizeTranslatableFieldName($name)
|
||||||
{
|
{
|
||||||
$this->unsetUnnecessaryAttributes($options);
|
if (starts_with($name, 'translatable[')) {
|
||||||
|
return 'translatable.' . str_between($name, 'translatable[', ']');
|
||||||
$attributes = '';
|
|
||||||
|
|
||||||
foreach ($options as $attr => $value) {
|
|
||||||
$attributes .= "{$attr}='{$value}' ";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $attributes;
|
return $name;
|
||||||
}
|
|
||||||
|
|
||||||
protected function unsetUnnecessaryAttributes(&$options = [])
|
|
||||||
{
|
|
||||||
foreach ($this->unnecessaryAttributes as $attribute) {
|
|
||||||
if (array_key_exists($attribute, $options)) {
|
|
||||||
unset($options[$attribute]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,48 +10,49 @@ class Form
|
|||||||
|
|
||||||
protected $unnecessaryAttributes = ['disabled', 'readonly', 'checked'];
|
protected $unnecessaryAttributes = ['disabled', 'readonly', 'checked'];
|
||||||
|
|
||||||
|
|
||||||
public function text($name, $title, $errors, $entity = null, $options = [])
|
public function text($name, $title, $errors, $entity = null, $options = [])
|
||||||
{
|
{
|
||||||
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'text']));
|
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'text']));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function password($name, $title, $errors, $entity = null, $options = [])
|
|
||||||
{
|
|
||||||
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'password']));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function number($name, $title, $errors, $entity = null, $options = [])
|
|
||||||
{
|
|
||||||
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'number']));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function email($name, $title, $errors, $entity = null, $options = [])
|
|
||||||
{
|
|
||||||
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'email']));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function file($name, $title, $errors, $entity = null, $options = [])
|
|
||||||
{
|
|
||||||
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'file']));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function color($name, $title, $errors, $entity = null, $options = [])
|
|
||||||
{
|
|
||||||
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'color']));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function input($name, $title, $errors, $entity = null, $options = [])
|
public function input($name, $title, $errors, $entity = null, $options = [])
|
||||||
{
|
{
|
||||||
return $this->field($name, $title, $errors, $entity, $options, [$this, 'inputField']);
|
return $this->field($name, $title, $errors, $entity, $options, [$this, 'inputField']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function textarea($name, $title, $errors, $entity = null, $options = [])
|
|
||||||
{
|
|
||||||
$options = array_merge(['rows' => 10, 'cols' => 10], $options);
|
|
||||||
|
|
||||||
return $this->field($name, $title, $errors, $entity, $options, [$this, 'textareaField']);
|
public function password($name, $title, $errors, $entity = null, $options = [])
|
||||||
|
{
|
||||||
|
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'password']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function number($name, $title, $errors, $entity = null, $options = [])
|
||||||
|
{
|
||||||
|
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'number']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function email($name, $title, $errors, $entity = null, $options = [])
|
||||||
|
{
|
||||||
|
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'email']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function file($name, $title, $errors, $entity = null, $options = [])
|
||||||
|
{
|
||||||
|
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'file']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function color($name, $title, $errors, $entity = null, $options = [])
|
||||||
|
{
|
||||||
|
return $this->input($name, $title, $errors, $entity, array_merge($options, ['type' => 'color']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function wysiwyg($name, $title, $errors, $entity = null, $options = [])
|
public function wysiwyg($name, $title, $errors, $entity = null, $options = [])
|
||||||
{
|
{
|
||||||
$options['class'] = array_get($options, 'class', '') . ' wysiwyg';
|
$options['class'] = array_get($options, 'class', '') . ' wysiwyg';
|
||||||
@@ -59,11 +60,21 @@ class Form
|
|||||||
return $this->textarea($name, $title, $errors, $entity, $options);
|
return $this->textarea($name, $title, $errors, $entity, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function textarea($name, $title, $errors, $entity = null, $options = [])
|
||||||
|
{
|
||||||
|
$options = array_merge(['rows' => 10, 'cols' => 10], $options);
|
||||||
|
|
||||||
|
return $this->field($name, $title, $errors, $entity, $options, [$this, 'textareaField']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function checkbox($name, $title, $label, $errors, $entity = null, $options = [])
|
public function checkbox($name, $title, $label, $errors, $entity = null, $options = [])
|
||||||
{
|
{
|
||||||
return $this->field($name, $title, $errors, $entity, $options, [$this, 'checkboxField'], $label);
|
return $this->field($name, $title, $errors, $entity, $options, [$this, 'checkboxField'], $label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function select($name, $title, $errors, $list = [], $entity = null, $options = [])
|
public function select($name, $title, $errors, $list = [], $entity = null, $options = [])
|
||||||
{
|
{
|
||||||
return $this->field($name, $title, $errors, $entity, $options, [$this, 'selectField'], $list);
|
return $this->field($name, $title, $errors, $entity, $options, [$this, 'selectField'], $list);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Modules\Admin\Ui;
|
namespace Modules\Admin\Ui;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
use Illuminate\Support\ViewErrorBag;
|
use Illuminate\Support\ViewErrorBag;
|
||||||
|
|
||||||
class Tab
|
class Tab
|
||||||
@@ -11,21 +12,21 @@ class Tab
|
|||||||
*
|
*
|
||||||
* @var bool
|
* @var bool
|
||||||
*/
|
*/
|
||||||
private $active = false;
|
public $active = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the tab.
|
* Name of the tab.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $name;
|
public $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Label of the tab.
|
* Label of the tab.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $label;
|
public $label;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Weight of the tab.
|
* Weight of the tab.
|
||||||
@@ -44,10 +45,25 @@ class Tab
|
|||||||
/**
|
/**
|
||||||
* View of the tab.
|
* View of the tab.
|
||||||
*
|
*
|
||||||
* @var string|\Closure
|
* @var string|Closure
|
||||||
*/
|
*/
|
||||||
private $view;
|
private $view;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepend to the View of the tab.
|
||||||
|
*
|
||||||
|
* @var string|Closure
|
||||||
|
*/
|
||||||
|
private $prependView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append to the view of the tab.
|
||||||
|
*
|
||||||
|
* @var string|Closure
|
||||||
|
*/
|
||||||
|
private $appendView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data for the tab view.
|
* Data for the tab view.
|
||||||
*
|
*
|
||||||
@@ -58,15 +74,17 @@ class Tab
|
|||||||
/**
|
/**
|
||||||
* Error message bag.
|
* Error message bag.
|
||||||
*
|
*
|
||||||
* @var \Illuminate\Support\ViewErrorBag
|
* @var ViewErrorBag
|
||||||
*/
|
*/
|
||||||
private $errors;
|
private $errors;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Tab instance.
|
* Create a new Tab instance.
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param string $label
|
* @param string $label
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct($name, $label)
|
public function __construct($name, $label)
|
||||||
@@ -76,6 +94,7 @@ class Tab
|
|||||||
$this->errors = request()->session()->get('errors') ?: new ViewErrorBag;
|
$this->errors = request()->session()->get('errors') ?: new ViewErrorBag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set tab as active.
|
* Set tab as active.
|
||||||
*
|
*
|
||||||
@@ -88,10 +107,12 @@ class Tab
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set weight of tab.
|
* Set weight of tab.
|
||||||
*
|
*
|
||||||
* @param int $weight
|
* @param int $weight
|
||||||
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function weight($weight)
|
public function weight($weight)
|
||||||
@@ -101,6 +122,7 @@ class Tab
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get weight of the tab.
|
* Get weight of the tab.
|
||||||
*
|
*
|
||||||
@@ -111,10 +133,12 @@ class Tab
|
|||||||
return $this->weight;
|
return $this->weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get nav of the tab.
|
* Get nav of the tab.
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getNav()
|
public function getNav()
|
||||||
@@ -124,30 +148,12 @@ class Tab
|
|||||||
</li>";
|
</li>";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return active class if tab is active.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function activeClass()
|
|
||||||
{
|
|
||||||
return $this->active ? 'active' : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return error class if tab fields has any error.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function errorClass()
|
|
||||||
{
|
|
||||||
return $this->errors->hasAny($this->fields) ? 'has-error' : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set fields of the tab.
|
* Set fields of the tab.
|
||||||
*
|
*
|
||||||
* @param array|string $fields
|
* @param array|string $fields
|
||||||
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function fields($fields)
|
public function fields($fields)
|
||||||
@@ -157,6 +163,7 @@ class Tab
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get fields of the tab.
|
* Get fields of the tab.
|
||||||
*
|
*
|
||||||
@@ -167,31 +174,61 @@ class Tab
|
|||||||
return $this->fields;
|
return $this->fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set view of the tab.
|
* Set view of the tab.
|
||||||
*
|
*
|
||||||
* @param \Closure|string $view
|
* @param Closure|string $view
|
||||||
* @param array $data
|
* @param array $data
|
||||||
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function view($view, $data = [])
|
public function view($view, $data = [], $prependView = null, $appendView = null)
|
||||||
{
|
{
|
||||||
$this->view = $view;
|
$this->view = $view;
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
|
$this->prependView = $prependView;
|
||||||
|
$this->appendView = $appendView;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get view of the tab.
|
* Get view of the tab.
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getView($data = [])
|
public function getView($data = [])
|
||||||
{
|
{
|
||||||
$html = "<div class='tab-pane fade in {$this->activeClass()}' id='{$this->name}'>";
|
return $this->getPrependView($data) . $this->getMainView($data) . $this->getAppendView($data);
|
||||||
$html .= "<h3 class='tab-content-title'>{$this->label}</h3>";
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getPrependView($data = [])
|
||||||
|
{
|
||||||
|
$html = '';
|
||||||
|
|
||||||
|
if (!is_null($this->prependView)) {
|
||||||
|
if (is_callable($this->prependView)) {
|
||||||
|
$html .= call_user_func($this->prependView, $this->name, $this->label, $this->activeClass());
|
||||||
|
} else {
|
||||||
|
$html .= $this->prependView;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$html .= "<div class='tab-pane fade in {$this->activeClass()}' id='{$this->name}'>";
|
||||||
|
$html .= "<h4 class='tab-content-title'>{$this->label}</h4>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getMainView($data = [])
|
||||||
|
{
|
||||||
|
$html = '';
|
||||||
|
|
||||||
if (is_callable($this->view)) {
|
if (is_callable($this->view)) {
|
||||||
$html .= call_user_func($this->view, array_merge($this->data, $data));
|
$html .= call_user_func($this->view, array_merge($this->data, $data));
|
||||||
@@ -199,6 +236,46 @@ class Tab
|
|||||||
$html .= view($this->view)->with(array_merge($this->data, $data))->render();
|
$html .= view($this->view)->with(array_merge($this->data, $data))->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $html .= '</div>';
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getAppendView($data = [])
|
||||||
|
{
|
||||||
|
$html = '';
|
||||||
|
|
||||||
|
if (!is_null($this->appendView)) {
|
||||||
|
if (is_callable($this->appendView)) {
|
||||||
|
$html .= call_user_func($this->appendView, $this->name, $this->label, $this->activeClass());
|
||||||
|
} else {
|
||||||
|
$html .= $this->appendView;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$html .= '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return active class if tab is active.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function activeClass()
|
||||||
|
{
|
||||||
|
return $this->active ? 'active' : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return error class if tab fields has any error.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function errorClass()
|
||||||
|
{
|
||||||
|
return $this->errors->hasAny($this->fields) ? 'has-error' : '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,13 @@ class TabManager
|
|||||||
*/
|
*/
|
||||||
private $extends = [];
|
private $extends = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new Tabs.
|
* Register a new Tabs.
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param string $tabs
|
* @param string $tabs
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register($name, $tabs)
|
public function register($name, $tabs)
|
||||||
@@ -30,28 +32,18 @@ class TabManager
|
|||||||
$this->tabs[$name] = $tabs;
|
$this->tabs[$name] = $tabs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new Tabs extender.
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param string $extender
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function extend($name, $extender)
|
|
||||||
{
|
|
||||||
$this->extends[$name][] = $extender;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get tabs for the given name.
|
* Get tabs for the given name.
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @return \Modules\Admin\Ui\Tabs
|
*
|
||||||
|
* @return Tabs
|
||||||
*/
|
*/
|
||||||
public function get($name)
|
public function get($name)
|
||||||
{
|
{
|
||||||
if (! array_key_exists($name, $this->tabs)) {
|
if (!array_key_exists($name, $this->tabs)) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tap(resolve($this->tabs[$name]), function (Tabs $tabs) use ($name) {
|
return tap(resolve($this->tabs[$name]), function (Tabs $tabs) use ($name) {
|
||||||
@@ -61,11 +53,27 @@ class TabManager
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new Tabs extender.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $extender
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function extend($name, $extender)
|
||||||
|
{
|
||||||
|
$this->extends[$name][] = $extender;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the given tabs using the given extenders.
|
* Extend the given tabs using the given extenders.
|
||||||
*
|
*
|
||||||
* @param \Modules\Admin\Ui\Tabs $tabs
|
* @param Tabs $tabs
|
||||||
* @param array $extenders
|
* @param array $extenders
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function extendTabs(Tabs $tabs, array $extenders)
|
private function extendTabs(Tabs $tabs, array $extenders)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ abstract class Tabs
|
|||||||
*/
|
*/
|
||||||
protected $buttonOffset = true;
|
protected $buttonOffset = true;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make new tabs with groups.
|
* Make new tabs with groups.
|
||||||
*
|
*
|
||||||
@@ -43,23 +44,6 @@ abstract class Tabs
|
|||||||
*/
|
*/
|
||||||
abstract public function make();
|
abstract public function make();
|
||||||
|
|
||||||
/**
|
|
||||||
* Set group name.
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param string $title
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public function group($name, $title = null)
|
|
||||||
{
|
|
||||||
$this->group = $name;
|
|
||||||
|
|
||||||
if (! is_null($title)) {
|
|
||||||
$this->groups[$name]['title'] = $title;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set current group as active group.
|
* Set current group as active group.
|
||||||
@@ -73,21 +57,24 @@ abstract class Tabs
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add new tab.
|
* Add new tab.
|
||||||
*
|
*
|
||||||
* @param \Modules\Admin\Ui\Tab|null $tab
|
* @param Tab|null $tab
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function add($tab)
|
public function add($tab)
|
||||||
{
|
{
|
||||||
if (! is_null($tab)) {
|
if (!is_null($tab)) {
|
||||||
$this->tabs[$this->group][] = $tab;
|
$this->tabs[$this->group][] = $tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if tabs fields has any error.
|
* Determine if tabs fields has any error.
|
||||||
*
|
*
|
||||||
@@ -98,16 +85,70 @@ abstract class Tabs
|
|||||||
return $this->getErrors()->hasAny($this->getTabFields());
|
return $this->getErrors()->hasAny($this->getTabFields());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate navs for the tabs.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return HtmlString
|
||||||
|
*/
|
||||||
|
public function navs($data = [])
|
||||||
|
{
|
||||||
|
return new HtmlString($this->getTabsData('nav', $data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the tabs,
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function render($data = [])
|
||||||
|
{
|
||||||
|
return view('admin::components.accordion', [
|
||||||
|
'tabs' => $this,
|
||||||
|
'name' => class_basename($this),
|
||||||
|
'groups' => $this->groups(),
|
||||||
|
'contents' => $this->contents($data),
|
||||||
|
'buttonOffset' => $this->buttonOffset,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set group name.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $title
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function group($name, $title = null)
|
||||||
|
{
|
||||||
|
$this->group = $name;
|
||||||
|
|
||||||
|
if (!is_null($title)) {
|
||||||
|
$this->groups[$name]['title'] = $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get error message bag.
|
* Get error message bag.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Support\ViewErrorBag
|
* @return ViewErrorBag
|
||||||
*/
|
*/
|
||||||
protected function getErrors()
|
protected function getErrors()
|
||||||
{
|
{
|
||||||
return request()->session()->get('errors') ?: new ViewErrorBag;
|
return request()->session()->get('errors') ?: new ViewErrorBag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all tabs fields.
|
* Get all tabs fields.
|
||||||
*
|
*
|
||||||
@@ -120,34 +161,50 @@ abstract class Tabs
|
|||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate navs for the tabs.
|
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
* @return \Illuminate\Support\HtmlString
|
|
||||||
*/
|
|
||||||
public function navs($data = [])
|
|
||||||
{
|
|
||||||
return new HtmlString($this->getTabsData('nav', $data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the tabs,
|
* Get sorted tabs.
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @return array
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function render($data = [])
|
protected function getSortedTabs()
|
||||||
{
|
{
|
||||||
return view('admin::components.accordion', [
|
return collect($this->tabs[$this->group])->sortBy(function (Tab $tab) {
|
||||||
'tabs' => $this,
|
return $tab->getWeight();
|
||||||
'name' => class_basename($this),
|
})->all();
|
||||||
'groups' => $this->groups(),
|
|
||||||
'contents' => $this->contents($data),
|
|
||||||
'buttonOffset' => $this->buttonOffset,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tabs data for the given type.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
protected function getTabsData($type, $data = [])
|
||||||
|
{
|
||||||
|
if (!array_key_exists($this->group, $this->tabs)) {
|
||||||
|
throw new InvalidArgumentException("Group [$this->group] is not registered.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = '';
|
||||||
|
|
||||||
|
foreach ($this->getSortedTabs() as $tab) {
|
||||||
|
$method = 'get' . ucfirst($type);
|
||||||
|
|
||||||
|
if (method_exists($tab, $method)) {
|
||||||
|
$html .= call_user_func_array([$tab, $method], [$data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all groups with it's options.
|
* Get all groups with it's options.
|
||||||
*
|
*
|
||||||
@@ -164,11 +221,13 @@ abstract class Tabs
|
|||||||
return $groups;
|
return $groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate contents for the tabs.
|
* Generate contents for the tabs.
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return \Illuminate\Support\HtmlString
|
*
|
||||||
|
* @return HtmlString
|
||||||
*/
|
*/
|
||||||
protected function contents($data = [])
|
protected function contents($data = [])
|
||||||
{
|
{
|
||||||
@@ -180,44 +239,4 @@ abstract class Tabs
|
|||||||
|
|
||||||
return new HtmlString($contents);
|
return new HtmlString($contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get tabs data for the given type.
|
|
||||||
*
|
|
||||||
* @param string $type
|
|
||||||
* @param array $data
|
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
*/
|
|
||||||
protected function getTabsData($type, $data = [])
|
|
||||||
{
|
|
||||||
if (! array_key_exists($this->group, $this->tabs)) {
|
|
||||||
throw new InvalidArgumentException("Group [$this->group] is not registered.");
|
|
||||||
}
|
|
||||||
|
|
||||||
$html = '';
|
|
||||||
|
|
||||||
foreach ($this->getSortedTabs() as $tab) {
|
|
||||||
$method = 'get' . ucfirst($type);
|
|
||||||
|
|
||||||
if (method_exists($tab, $method)) {
|
|
||||||
$html .= call_user_func_array([$tab, $method], [$data]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get sorted tabs.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getSortedTabs()
|
|
||||||
{
|
|
||||||
return collect($this->tabs[$this->group])->sortBy(function (Tab $tab) {
|
|
||||||
return $tab->getWeight();
|
|
||||||
})->all();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "admin-module",
|
"name": "admin-module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "^3.3.7",
|
"bootstrap": "^3.3.7",
|
||||||
"chart.js": "^2.7.3",
|
"chart.js": "^4.4.0",
|
||||||
"datatables.net": "^1.10.15",
|
"datatables.net": "^1.13.8",
|
||||||
"datatables.net-bs": "^1.10.15",
|
"datatables.net-bs": "^1.13.8",
|
||||||
"flatpickr": "^3.0.6",
|
"flatpickr": "^4.6.13",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"jquery": "^3.2.1",
|
|
||||||
"jquery-slimscroll": "^1.3.8",
|
"jquery-slimscroll": "^1.3.8",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.21",
|
||||||
"mousetrap": "^1.6.1",
|
"mousetrap": "^1.6.5",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"selectize": "^0.12.6",
|
"selectize": "^0.12.6",
|
||||||
"sortablejs": "https://github.com/RubaXa/Sortable",
|
"sortablejs": "^1.15.0",
|
||||||
"tinymce": "^5.2.2"
|
"tinymce": "5.10.7",
|
||||||
|
"vue-toast-notification": "0.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class AttributeSetTabs extends Tabs
|
|||||||
->add($this->general());
|
->add($this->general());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function general()
|
private function general()
|
||||||
{
|
{
|
||||||
return tap(new Tab('general', trans('attribute::attribute_sets.tabs.general')), function (Tab $tab) {
|
return tap(new Tab('general', trans('attribute::attribute_sets.tabs.general')), function (Tab $tab) {
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
namespace Modules\Attribute\Admin;
|
namespace Modules\Attribute\Admin;
|
||||||
|
|
||||||
use Modules\Admin\Ui\AdminTable;
|
use Modules\Admin\Ui\AdminTable;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
class AttributeTable extends AdminTable
|
class AttributeTable extends AdminTable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Make table response for the resource.
|
* Make table response for the resource.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function make()
|
public function make()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class AttributeTabs extends Tabs
|
|||||||
->add($this->values());
|
->add($this->values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function general()
|
private function general()
|
||||||
{
|
{
|
||||||
return tap(new Tab('general', trans('attribute::admin.tabs.general')), function (Tab $tab) {
|
return tap(new Tab('general', trans('attribute::admin.tabs.general')), function (Tab $tab) {
|
||||||
@@ -30,12 +31,14 @@ class AttributeTabs extends Tabs
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getAttributeSets()
|
private function getAttributeSets()
|
||||||
{
|
{
|
||||||
return AttributeSet::all()->sortBy('name')->pluck('name', 'id')
|
return AttributeSet::all()->sortBy('name')->pluck('name', 'id')
|
||||||
->prepend(trans('admin::admin.form.please_select'), '');
|
->prepend(trans('admin::admin.form.please_select'), '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function values()
|
private function values()
|
||||||
{
|
{
|
||||||
return tap(new Tab('values', trans('attribute::admin.tabs.values')), function (Tab $tab) {
|
return tap(new Tab('values', trans('attribute::admin.tabs.values')), function (Tab $tab) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class CreateAttributeSetsTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class CreateAttributeSetTranslationsTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class CreateAttributesTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class CreateAttributeTranslationsTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class CreateProductAttributesTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class CreateAttributeValuesTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class CreateAttributeValueTranslationsTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class CreateProductAttributeValuesTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class CreateAttributeCategoriesTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class AddSlugColumnToAttributesTable extends Migration
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the migrations.
|
* Reverse the migrations.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -12,20 +12,24 @@ class Attribute extends Model
|
|||||||
{
|
{
|
||||||
use Translatable, Sluggable;
|
use Translatable, Sluggable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are translatable.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $translatedAttributes = ['name'];
|
||||||
/**
|
/**
|
||||||
* The relations to eager load on every query.
|
* The relations to eager load on every query.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $with = ['translations'];
|
protected $with = ['translations'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = ['attribute_set_id', 'slug', 'is_filterable'];
|
protected $fillable = ['attribute_set_id', 'slug', 'is_filterable'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be cast to native types.
|
* The attributes that should be cast to native types.
|
||||||
*
|
*
|
||||||
@@ -34,14 +38,6 @@ class Attribute extends Model
|
|||||||
protected $casts = [
|
protected $casts = [
|
||||||
'is_filterable' => 'boolean',
|
'is_filterable' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
|
||||||
* The attributes that are translatable.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public $translatedAttributes = ['name'];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attribute that will be slugged.
|
* The attribute that will be slugged.
|
||||||
*
|
*
|
||||||
@@ -49,6 +45,7 @@ class Attribute extends Model
|
|||||||
*/
|
*/
|
||||||
protected $slugAttribute = 'name';
|
protected $slugAttribute = 'name';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform any actions required after the model boots.
|
* Perform any actions required after the model boots.
|
||||||
*
|
*
|
||||||
@@ -61,25 +58,6 @@ class Attribute extends Model
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attributeSet()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(AttributeSet::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function categories()
|
|
||||||
{
|
|
||||||
return $this->belongsToMany(Category::class, 'attribute_categories');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function values()
|
|
||||||
{
|
|
||||||
return $this->hasMany(AttributeValue::class)->orderBy('position');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function table()
|
|
||||||
{
|
|
||||||
return new AttributeTable($this->with('attributeSet'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function saveRelations(array $attributes)
|
public function saveRelations(array $attributes)
|
||||||
{
|
{
|
||||||
@@ -87,6 +65,13 @@ class Attribute extends Model
|
|||||||
$this->saveValues(array_get($attributes, 'values', []));
|
$this->saveValues(array_get($attributes, 'values', []));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function categories()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Category::class, 'attribute_categories');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function saveValues($values = [])
|
public function saveValues($values = [])
|
||||||
{
|
{
|
||||||
$ids = $this->getDeleteCandidates($values);
|
$ids = $this->getDeleteCandidates($values);
|
||||||
@@ -103,6 +88,25 @@ class Attribute extends Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function values()
|
||||||
|
{
|
||||||
|
return $this->hasMany(AttributeValue::class)->orderBy('position');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function attributeSet()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(AttributeSet::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function table()
|
||||||
|
{
|
||||||
|
return new AttributeTable($this->with('attributeSet'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getDeleteCandidates($values = [])
|
private function getDeleteCandidates($values = [])
|
||||||
{
|
{
|
||||||
return $this->values()
|
return $this->values()
|
||||||
|
|||||||
@@ -10,13 +10,18 @@ class AttributeSet extends Model
|
|||||||
{
|
{
|
||||||
use Translatable;
|
use Translatable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are translatable.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $translatedAttributes = ['name'];
|
||||||
/**
|
/**
|
||||||
* The relations to eager load on every query.
|
* The relations to eager load on every query.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $with = ['translations'];
|
protected $with = ['translations'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that aren't mass assignable.
|
* The attributes that aren't mass assignable.
|
||||||
*
|
*
|
||||||
@@ -24,18 +29,13 @@ class AttributeSet extends Model
|
|||||||
*/
|
*/
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* The attributes that are translatable.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public $translatedAttributes = ['name'];
|
|
||||||
|
|
||||||
public function attributes()
|
public function attributes()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Attribute::class);
|
return $this->hasMany(Attribute::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function table()
|
public function table()
|
||||||
{
|
{
|
||||||
return new AdminTable($this->newQuery());
|
return new AdminTable($this->newQuery());
|
||||||
|
|||||||
@@ -9,24 +9,22 @@ class AttributeValue extends Model
|
|||||||
{
|
{
|
||||||
use Translatable;
|
use Translatable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are translatable.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $translatedAttributes = ['value'];
|
||||||
/**
|
/**
|
||||||
* The relations to eager load on every query.
|
* The relations to eager load on every query.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $with = ['translations'];
|
protected $with = ['translations'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = ['position'];
|
protected $fillable = ['position'];
|
||||||
|
|
||||||
/**
|
|
||||||
* The attributes that are translatable.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public $translatedAttributes = ['value'];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,20 +6,24 @@ use Modules\Support\Eloquent\Model;
|
|||||||
|
|
||||||
class ProductAttribute extends Model
|
class ProductAttribute extends Model
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Indicates if the model should be timestamped.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $timestamps = false;
|
||||||
/**
|
/**
|
||||||
* The relations to eager load on every query.
|
* The relations to eager load on every query.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $with = ['attribute', 'values'];
|
protected $with = ['attribute', 'values'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = ['attribute_id'];
|
protected $fillable = ['attribute_id'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The accessors to append to the model's array form.
|
* The accessors to append to the model's array form.
|
||||||
*
|
*
|
||||||
@@ -27,28 +31,25 @@ class ProductAttribute extends Model
|
|||||||
*/
|
*/
|
||||||
protected $appends = ['name'];
|
protected $appends = ['name'];
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates if the model should be timestamped.
|
|
||||||
*
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
public $timestamps = false;
|
|
||||||
|
|
||||||
public function attribute()
|
public function attribute()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Attribute::class);
|
return $this->belongsTo(Attribute::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function values()
|
public function values()
|
||||||
{
|
{
|
||||||
return $this->hasMany(ProductAttributeValue::class, 'product_attribute_id');
|
return $this->hasMany(ProductAttributeValue::class, 'product_attribute_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getNameAttribute()
|
public function getNameAttribute()
|
||||||
{
|
{
|
||||||
return $this->attribute->name;
|
return $this->attribute->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getAttributeSetAttribute()
|
public function getAttributeSetAttribute()
|
||||||
{
|
{
|
||||||
return $this->attribute->attributeSet->name;
|
return $this->attribute->attributeSet->name;
|
||||||
|
|||||||
@@ -27,21 +27,25 @@ class ProductAttributeValue extends Model
|
|||||||
*/
|
*/
|
||||||
protected $appends = ['value'];
|
protected $appends = ['value'];
|
||||||
|
|
||||||
|
|
||||||
public function exists()
|
public function exists()
|
||||||
{
|
{
|
||||||
return ! is_null($this->attributeValue);
|
return !is_null($this->attributeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function attributeValue()
|
public function attributeValue()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(AttributeValue::class, 'attribute_value_id');
|
return $this->belongsTo(AttributeValue::class, 'attribute_value_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getIdAttribute()
|
public function getIdAttribute()
|
||||||
{
|
{
|
||||||
return $this->attributeValue->id;
|
return $this->attributeValue->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getValueAttribute()
|
public function getValueAttribute()
|
||||||
{
|
{
|
||||||
return $this->attributeValue->value;
|
return $this->attributeValue->value;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class SaveAttributeRequest extends Request
|
|||||||
*/
|
*/
|
||||||
protected $availableAttributes = 'attribute::attributes.attributes';
|
protected $availableAttributes = 'attribute::attributes.attributes';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the validation rules that apply to the request.
|
* Get the validation rules that apply to the request.
|
||||||
*
|
*
|
||||||
@@ -30,18 +31,6 @@ class SaveAttributeRequest extends Request
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getSlugRules()
|
|
||||||
{
|
|
||||||
$rules = $this->route()->getName() === 'admin.attributes.update'
|
|
||||||
? ['required']
|
|
||||||
: ['sometimes'];
|
|
||||||
|
|
||||||
$slug = Attribute::where('id', $this->id)->value('slug');
|
|
||||||
|
|
||||||
$rules[] = Rule::unique('attributes', 'slug')->ignore($slug, 'slug');
|
|
||||||
|
|
||||||
return $rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get data to be validated from the request.
|
* Get data to be validated from the request.
|
||||||
@@ -55,16 +44,32 @@ class SaveAttributeRequest extends Request
|
|||||||
])->all();
|
])->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getSlugRules()
|
||||||
|
{
|
||||||
|
$rules = $this->route()->getName() === 'admin.attributes.update'
|
||||||
|
? ['required']
|
||||||
|
: ['sometimes'];
|
||||||
|
|
||||||
|
$slug = Attribute::where('id', $this->id)->value('slug');
|
||||||
|
|
||||||
|
$rules[] = Rule::unique('attributes', 'slug')->ignore($slug, 'slug');
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter attribute values.
|
* Filter attribute values.
|
||||||
*
|
*
|
||||||
* @param array $values
|
* @param array $values
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function filter($values = [])
|
private function filter($values = [])
|
||||||
{
|
{
|
||||||
return array_filter($values, function ($value) {
|
return array_filter($values, function ($value) {
|
||||||
return ! is_null($value['value']);
|
return !is_null($value['value']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ class SaveAttributeSetRequest extends Request
|
|||||||
*/
|
*/
|
||||||
protected $availableAttributes = 'attribute::attributes.attribute_sets';
|
protected $availableAttributes = 'attribute::attributes.attribute_sets';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the validation rules that apply to the request.
|
* Get the validation rules that apply to the request.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class SaveProductAttributesRequest extends Request
|
|||||||
*/
|
*/
|
||||||
protected $availableAttributes = 'attribute::attributes.product_attributes';
|
protected $availableAttributes = 'attribute::attributes.product_attributes';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the validation rules that apply to the request.
|
* Get the validation rules that apply to the request.
|
||||||
*
|
*
|
||||||
@@ -27,6 +28,7 @@ class SaveProductAttributesRequest extends Request
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get data to be validated from the request.
|
* Get data to be validated from the request.
|
||||||
*
|
*
|
||||||
@@ -43,16 +45,18 @@ class SaveProductAttributesRequest extends Request
|
|||||||
])->all();
|
])->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter product attributes.
|
* Filter product attributes.
|
||||||
*
|
*
|
||||||
* @param array $attributes
|
* @param array $attributes
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function filter($attributes = [])
|
private function filter($attributes = [])
|
||||||
{
|
{
|
||||||
return array_filter($attributes, function ($attribute) {
|
return array_filter($attributes, function ($attribute) {
|
||||||
return ! is_null($attribute['attribute_id']);
|
return !is_null($attribute['attribute_id']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ class SaveProductAttributes
|
|||||||
/**
|
/**
|
||||||
* Handle the event.
|
* Handle the event.
|
||||||
*
|
*
|
||||||
* @param \Modules\Product\Entities\Product $product
|
* @param Product $product
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle(Product $product)
|
public function handle(Product $product)
|
||||||
@@ -19,10 +20,12 @@ class SaveProductAttributes
|
|||||||
$this->createProductAttributes($product);
|
$this->createProductAttributes($product);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all product attributes associated with the given product.
|
* Delete all product attributes associated with the given product.
|
||||||
*
|
*
|
||||||
* @param \Modules\Product\Entities\Product $product
|
* @param Product $product
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function deleteProductAttributes(Product $product)
|
private function deleteProductAttributes(Product $product)
|
||||||
@@ -30,10 +33,12 @@ class SaveProductAttributes
|
|||||||
$product->attributes()->delete();
|
$product->attributes()->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create product attributes for the given product.
|
* Create product attributes for the given product.
|
||||||
*
|
*
|
||||||
* @param \Modules\Product\Entities\Product $product
|
* @param Product $product
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function createProductAttributes(Product $product)
|
private function createProductAttributes(Product $product)
|
||||||
@@ -56,10 +61,12 @@ class SaveProductAttributes
|
|||||||
$this->createProductAttributeValues($productAttributeValues);
|
$this->createProductAttributeValues($productAttributeValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the given product attribute values.
|
* Create the given product attribute values.
|
||||||
*
|
*
|
||||||
* @param array $productAttributeValues
|
* @param array $productAttributeValues
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function createProductAttributeValues(array $productAttributeValues)
|
private function createProductAttributeValues(array $productAttributeValues)
|
||||||
|
|||||||
@@ -2,17 +2,14 @@
|
|||||||
|
|
||||||
namespace Modules\Attribute\Providers;
|
namespace Modules\Attribute\Providers;
|
||||||
|
|
||||||
use Modules\Support\Traits\AddsAsset;
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Modules\Admin\Ui\Facades\TabManager;
|
use Modules\Admin\Ui\Facades\TabManager;
|
||||||
use Modules\Attribute\Admin\AttributeTabs;
|
use Modules\Attribute\Admin\AttributeTabs;
|
||||||
use Modules\Attribute\Admin\AttributeSetTabs;
|
use Modules\Attribute\Admin\AttributeSetTabs;
|
||||||
use Modules\Attribute\Admin\ProductTabsExtender;
|
|
||||||
|
|
||||||
class AttributeServiceProvider extends ServiceProvider
|
class AttributeServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
use AddsAsset;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrap the application services.
|
* Bootstrap the application services.
|
||||||
*
|
*
|
||||||
@@ -22,8 +19,5 @@ class AttributeServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
TabManager::register('attributes', AttributeTabs::class);
|
TabManager::register('attributes', AttributeTabs::class);
|
||||||
TabManager::register('attribute_sets', AttributeSetTabs::class);
|
TabManager::register('attribute_sets', AttributeSetTabs::class);
|
||||||
TabManager::extend('products', ProductTabsExtender::class);
|
|
||||||
|
|
||||||
$this->addAdminAssets('admin.(attributes|products).(create|edit)', ['admin.attribute.css', 'admin.attribute.js']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ namespace Modules\Attribute\Providers;
|
|||||||
|
|
||||||
use Modules\Product\Entities\Product;
|
use Modules\Product\Entities\Product;
|
||||||
use Modules\Attribute\Listeners\SaveProductAttributes;
|
use Modules\Attribute\Listeners\SaveProductAttributes;
|
||||||
use Modules\Attribute\Http\Requests\SaveProductAttributesRequest;
|
|
||||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
class EventServiceProvider extends ServiceProvider
|
class EventServiceProvider extends ServiceProvider
|
||||||
@@ -18,10 +17,6 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
parent::boot();
|
parent::boot();
|
||||||
|
|
||||||
Product::saving(function () {
|
|
||||||
resolve(SaveProductAttributesRequest::class);
|
|
||||||
});
|
|
||||||
|
|
||||||
Product::saved(SaveProductAttributes::class);
|
Product::saved(SaveProductAttributes::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user