Merge pull request #3 from bagisto/master

This commit is contained in:
Glenn Hermans 2020-12-31 16:16:48 +01:00 committed by GitHub
commit 475d5cccf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
296 changed files with 7849 additions and 4535 deletions

View File

@ -40,7 +40,6 @@ jobs:
- name: Composer install
run: |
set -e
composer global require hirak/prestissimo
composer install --no-interaction --ansi --no-progress --no-suggest --optimize-autoloader
- name: Migrate database

View File

@ -66,7 +66,7 @@ Take advantage of two of the hottest frameworks used in this project -- Laravel
* **OS**: Ubuntu 16.04 LTS or higher / Windows 7 or Higher (WampServer / XAMPP).
* **SERVER**: Apache 2 or NGINX.
* **RAM**: 3 GB or higher.
* **PHP**: 7.2.0 or higher.
* **PHP**: 7.3 or higher.
* **Processor**: Clock Cycle 1 Ghz or higher.
* **For MySQL users**: 5.7.23 or higher.
* **For MariaDB users**: 10.2.7 or Higher.

View File

@ -14,7 +14,7 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Webkul\Core\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,

View File

@ -13,7 +13,7 @@ class AuthServiceProvider extends ServiceProvider
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
// 'App\Model' => 'App\Policies\ModelPolicy',
];
/**

View File

@ -5,9 +5,9 @@
"framework",
"laravel"
],
"license": "MIT",
"type": "project",
"require": {
"php": "^7.2.5",
"ext-curl": "*",
@ -21,10 +21,12 @@
"astrotomic/laravel-translatable": "^11.0.0",
"babenkoivan/elastic-scout-driver": "^1.1",
"bagistobrasil/bagisto-product-social-share": "^0.1.2",
"barryvdh/laravel-debugbar": "^3.1",
"barryvdh/laravel-dompdf": "0.8.6",
"doctrine/dbal": "2.9.2",
"fideloper/proxy": "^4.2",
"flynsarmy/db-blade-compiler": "^5.5",
"fzaninotto/faker": "^1.4",
"guzzlehttp/guzzle": "~6.3",
"intervention/image": "^2.4",
"intervention/imagecache": "^2.3",
@ -36,19 +38,18 @@
"laravel/tinker": "^2.0",
"laravel/ui": "^2.0",
"maatwebsite/excel": "3.1.19",
"paypal/paypal-checkout-sdk": "1.0.1",
"prettus/l5-repository": "^2.6",
"tymon/jwt-auth": "^1.0.0"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.1",
"codeception/codeception": "4.1.1",
"codeception/module-asserts": "^1.1",
"codeception/module-filesystem": "^1.0",
"codeception/module-laravel5": "^1.0",
"codeception/module-webdriver": "^1.0",
"filp/whoops": "^2.0",
"fzaninotto/faker": "^1.4",
"mockery/mockery": "^1.3.1",
"nunomaduro/collision": "^4.1",
"phpunit/phpunit": "^8.5"
@ -107,7 +108,8 @@
"Webkul\\CMS\\": "packages/Webkul/CMS/src",
"Webkul\\Velocity\\": "packages/Webkul/Velocity/src",
"Webkul\\BookingProduct\\": "packages/Webkul/BookingProduct/src",
"Webkul\\SocialLogin\\": "packages/Webkul/SocialLogin/src"
"Webkul\\SocialLogin\\": "packages/Webkul/SocialLogin/src",
"Webkul\\DebugBar\\": "packages/Webkul/DebugBar/src"
}
},
@ -123,7 +125,6 @@
"extra": {
"laravel": {
"dont-discover": [
"barryvdh/laravel-debugbar",
"laravel/dusk"
]
}
@ -143,12 +144,20 @@
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover"
],
"test": [
"set -e",
"@php artisan migrate:fresh --env=testing",
"vendor/bin/codecept run unit",
"vendor/bin/codecept run functional",
"vendor/bin/codecept run trigger"
],
"test-win": [
"@set -e",
"@php artisan migrate:fresh --env=testing",
"vendor\\bin\\codecept.bat run unit",
"vendor\\bin\\codecept.bat run functional",
"vendor\\bin\\codecept.bat run trigger"
]
},
"config": {

3594
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -246,8 +246,6 @@ return [
//Laravel Maatwebsite
Maatwebsite\Excel\ExcelServiceProvider::class,
Barryvdh\Debugbar\ServiceProvider::class,
//Repository
Prettus\Repository\Providers\RepositoryServiceProvider::class,
Konekt\Concord\ConcordServiceProvider::class,
@ -282,6 +280,7 @@ return [
Webkul\Velocity\Providers\VelocityServiceProvider::class,
Webkul\BookingProduct\Providers\BookingProductServiceProvider::class,
Webkul\SocialLogin\Providers\SocialLoginServiceProvider::class,
Webkul\DebugBar\Providers\DebugBarServiceProvider::class,
],
/*
@ -339,6 +338,7 @@ return [
'PDF' => Barryvdh\DomPDF\Facade::class,
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
'Concord' => Konekt\Concord\Facades\Concord::class,
'Helper' => Konekt\Concord\Facades\Helper::class
'Helper' => Konekt\Concord\Facades\Helper::class,
'Debugbar' => Barryvdh\Debugbar\Facade::class,
],
];

View File

@ -12,21 +12,30 @@ return [
*
*/
\Webkul\Admin\Providers\ModuleServiceProvider::class,
\Webkul\API\Providers\ModuleServiceProvider::class,
\Webkul\Attribute\Providers\ModuleServiceProvider::class,
\Webkul\BookingProduct\Providers\ModuleServiceProvider::class,
\Webkul\CartRule\Providers\ModuleServiceProvider::class,
\Webkul\CatalogRule\Providers\ModuleServiceProvider::class,
\Webkul\Category\Providers\ModuleServiceProvider::class,
\Webkul\Checkout\Providers\ModuleServiceProvider::class,
\Webkul\Core\Providers\ModuleServiceProvider::class,
\Webkul\CMS\Providers\ModuleServiceProvider::class,
\Webkul\Customer\Providers\ModuleServiceProvider::class,
\Webkul\Inventory\Providers\ModuleServiceProvider::class,
\Webkul\Payment\Providers\ModuleServiceProvider::class,
\Webkul\Paypal\Providers\ModuleServiceProvider::class,
\Webkul\Product\Providers\ModuleServiceProvider::class,
\Webkul\Rule\Providers\ModuleServiceProvider::class,
\Webkul\Sales\Providers\ModuleServiceProvider::class,
\Webkul\Tax\Providers\ModuleServiceProvider::class,
\Webkul\User\Providers\ModuleServiceProvider::class,
\Webkul\CatalogRule\Providers\ModuleServiceProvider::class,
\Webkul\CartRule\Providers\ModuleServiceProvider::class,
\Webkul\CMS\Providers\ModuleServiceProvider::class,
\Webkul\Velocity\Providers\ModuleServiceProvider::class,
\Webkul\Shipping\Providers\ModuleServiceProvider::class,
\Webkul\Shop\Providers\ModuleServiceProvider::class,
\Webkul\SocialLogin\Providers\ModuleServiceProvider::class,
\Webkul\Tax\Providers\ModuleServiceProvider::class,
\Webkul\Theme\Providers\ModuleServiceProvider::class,
\Webkul\Ui\Providers\ModuleServiceProvider::class,
\Webkul\User\Providers\ModuleServiceProvider::class,
\Webkul\Velocity\Providers\ModuleServiceProvider::class,
]
];

View File

@ -16,7 +16,8 @@ return [
'enabled' => env('DEBUGBAR_ENABLED', null),
'except' => [
'telescope*'
'telescope*',
'horizon*',
],
/*
@ -36,7 +37,7 @@ return [
'driver' => 'file', // redis, file, pdo, custom
'path' => storage_path('debugbar'), // For file driver
'connection' => null, // Leave null for default connection (Redis/PDO)
'provider' => '' // Instance of StorageInterface for custom driver
'provider' => '', // Instance of StorageInterface for custom driver
],
/*
@ -123,6 +124,7 @@ return [
'config' => false, // Display config settings
'cache' => false, // Display cache events
'models' => true, // Display models
'livewire' => true, // Display Livewire (when available)
],
/*
@ -141,27 +143,29 @@ return [
'db' => [
'with_params' => true, // Render SQL with the parameters substituted
'backtrace' => true, // Use a backtrace to find the origin of the query in your files.
'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults)
'timeline' => false, // Add the queries to the timeline
'explain' => [ // Show EXPLAIN output on queries
'enabled' => false,
'types' => ['SELECT'], // // workaround ['SELECT'] only. https://github.com/barryvdh/laravel-debugbar/issues/888 ['SELECT', 'INSERT', 'UPDATE', 'DELETE']; for MySQL 5.6.3+
'types' => ['SELECT'], // Deprecated setting, is always only SELECT
],
'hints' => true, // Show hints for common mistakes
'hints' => false, // Show hints for common mistakes
'show_copy' => false, // Show copy button next to the query
],
'mail' => [
'full_log' => false
'full_log' => false,
],
'views' => [
'data' => false, //Note: Can slow down the application, because the data can be quite large..
],
'route' => [
'label' => true // show complete route on bar
'label' => true, // show complete route on bar
],
'logs' => [
'file' => null
'file' => null,
],
'cache' => [
'values' => true // collect cache values
'values' => true, // collect cache values
],
],
@ -199,4 +203,14 @@ return [
| To override default domain, specify it as a non-empty value.
*/
'route_domain' => null,
/*
|--------------------------------------------------------------------------
| DebugBar theme
|--------------------------------------------------------------------------
|
| Switches between light and dark theme. If set to auto it will respect system preferences
| Possible values: auto, light, dark
*/
'theme' => 'auto',
];

View File

@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
return [
'hosts' => [

View File

@ -1,5 +1,5 @@
<?php
<?php declare(strict_types=1);
return [
'refresh_documents' => env('ELASTIC_SCOUT_DRIVER_REFRESH_DOCUMENTS', false)
'refresh_documents' => env('ELASTIC_SCOUT_DRIVER_REFRESH_DOCUMENTS', false),
];

View File

@ -19,7 +19,7 @@ return [
/*
|--------------------------------------------------------------------------
| Alias Whitelist
| Auto Aliased Classes
|--------------------------------------------------------------------------
|
| Tinker will not automatically alias classes in your vendor namespaces
@ -34,7 +34,7 @@ return [
/*
|--------------------------------------------------------------------------
| Alias Blacklist
| Classes That Should Not Be Aliased
|--------------------------------------------------------------------------
|
| Typically, Tinker automatically aliases classes as you require them in

View File

@ -2,20 +2,19 @@
namespace Webkul\API\Http\Controllers\Shop;
use Illuminate\Support\Facades\Event;
use Webkul\Checkout\Repositories\CartRepository;
use Webkul\Checkout\Repositories\CartItemRepository;
use Webkul\Shipping\Facades\Shipping;
use Webkul\Payment\Facades\Payment;
use Webkul\API\Http\Resources\Checkout\Cart as CartResource;
use Webkul\API\Http\Resources\Checkout\CartShippingRate as CartShippingRateResource;
use Webkul\API\Http\Resources\Sales\Order as OrderResource;
use Webkul\Checkout\Http\Requests\CustomerAddressForm;
use Webkul\Sales\Repositories\OrderRepository;
use Illuminate\Support\Str;
use Cart;
use Exception;
use Illuminate\Support\Str;
use Webkul\Payment\Facades\Payment;
use Webkul\Shipping\Facades\Shipping;
use Webkul\Sales\Repositories\OrderRepository;
use Webkul\Checkout\Repositories\CartRepository;
use Webkul\Shop\Http\Controllers\OnepageController;
use Webkul\Checkout\Repositories\CartItemRepository;
use Webkul\Checkout\Http\Requests\CustomerAddressForm;
use Webkul\API\Http\Resources\Sales\Order as OrderResource;
use Webkul\API\Http\Resources\Checkout\Cart as CartResource;
use Webkul\API\Http\Resources\Checkout\CartShippingRate as CartShippingRateResource;
class CheckoutController extends Controller
{
@ -162,6 +161,26 @@ class CheckoutController extends Controller
]);
}
/**
* Check for minimum order.
*
* @return \Illuminate\Http\Response
*/
public function checkMinimumOrder()
{
$minimumOrderAmount = (float) core()->getConfigData('sales.orderSettings.minimum-order.minimum_order_amount') ?? 0;
$status = Cart::checkMinimumOrder();
return response()->json([
'status' => ! $status ? false : true,
'message' => ! $status ? trans('shop::app.checkout.cart.minimum-order-message', ['amount' => core()->currency($minimumOrderAmount)]) : 'Success',
'data' => [
'cart' => new CartResource($cart),
]
]);
}
/**
* Saves order.
*

View File

@ -43,7 +43,9 @@ class InvoiceController extends Controller
$this->middleware('auth:' . $this->guard);
}
$this->repository = app($this->_config['repository']);
if ($this->_config) {
$this->repository = app($this->_config['repository']);
}
}
/**

View File

@ -12,7 +12,7 @@ class ResourceController extends Controller
* @var array
*/
protected $guard;
/**
* Contains route related configuration
*
@ -45,7 +45,9 @@ class ResourceController extends Controller
$this->middleware('auth:' . $this->guard);
}
$this->repository = app($this->_config['repository']);
if ($this->_config) {
$this->repository = app($this->_config['repository']);
}
}
/**
@ -58,8 +60,8 @@ class ResourceController extends Controller
$query = $this->repository->scopeQuery(function($query) {
if (isset($this->_config['authorization_required']) && $this->_config['authorization_required']) {
$query = $query->where('customer_id', auth()->user()->id );
}
}
foreach (request()->except(['page', 'limit', 'pagination', 'sort', 'order', 'token']) as $input => $value) {
$query = $query->whereIn($input, array_map('trim', explode(',', $value)));
}
@ -89,11 +91,11 @@ class ResourceController extends Controller
* @return \Illuminate\Http\Response
*/
public function get($id)
{
$query = isset($this->_config['authorization_required']) && $this->_config['authorization_required'] ?
$this->repository->where('customer_id', auth()->user()->id)->findOrFail($id) :
{
$query = isset($this->_config['authorization_required']) && $this->_config['authorization_required'] ?
$this->repository->where('customer_id', auth()->user()->id)->findOrFail($id) :
$this->repository->findOrFail($id);
return new $this->_config['resource']($query);
}
@ -108,7 +110,7 @@ class ResourceController extends Controller
$wishlistProduct = $this->repository->findOrFail($id);
$this->repository->delete($id);
return response()->json([
'message' => 'Item removed successfully.',
]);

View File

@ -31,6 +31,8 @@ class Product extends JsonResource
{
$product = $this->product ? $this->product : $this;
$prices = $product->getTypeInstance()->getProductPrices();
return [
'id' => $product->id,
'type' => $product->type,
@ -49,13 +51,21 @@ class Product extends JsonResource
'super_attributes' => Attribute::collection($product->super_attributes),
]),
'special_price' => $this->when(
$product->getTypeInstance()->haveSpecialPrice(),
$product->getTypeInstance()->getSpecialPrice()
),
$product->getTypeInstance()->haveSpecialPrice(),
$product->getTypeInstance()->getSpecialPrice()
),
'formated_special_price' => $this->when(
$product->getTypeInstance()->haveSpecialPrice(),
core()->currency($product->getTypeInstance()->getSpecialPrice())
),
$product->getTypeInstance()->haveSpecialPrice(),
core()->currency($product->getTypeInstance()->getSpecialPrice())
),
'regular_price' => $this->when(
$product->getTypeInstance()->haveSpecialPrice(),
data_get($prices, 'regular_price.price')
),
'formated_regular_price' => $this->when(
$product->getTypeInstance()->haveSpecialPrice(),
data_get($prices, 'regular_price.formated_price')
),
'reviews' => [
'total' => $total = $this->productReviewHelper->getTotalReviews($product),
'total_rating' => $total ? $this->productReviewHelper->getTotalRating($product) : 0,
@ -67,4 +77,4 @@ class Product extends JsonResource
'updated_at' => $this->updated_at,
];
}
}
}

View File

@ -270,6 +270,8 @@ Route::group(['prefix' => 'api'], function ($router) {
Route::post('save-payment', 'CheckoutController@savePayment');
Route::post('check-minimum-order', 'CheckoutController@checkMinimumOrder');
Route::post('save-order', 'CheckoutController@saveOrder');
});
});

View File

@ -0,0 +1,11 @@
<?php
namespace Webkul\API\Providers;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
];
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/js/admin.js": "/js/admin.js?id=b022291aa1cad7dfcc84",
"/css/admin.css": "/css/admin.css?id=8f4fcca5914f5370ddda"
"/js/admin.js": "/js/admin.js?id=e4c3d46b82083613b407",
"/css/admin.css": "/css/admin.css?id=f2b20e4283a639808ef6"
}

View File

@ -218,6 +218,10 @@ return [
],
],
'channel_based' => true,
], [
'name' => 'buy_now_button_display',
'title' => 'admin::app.admin.system.buy-now-button-display',
'type' => 'boolean',
]
],
], [

View File

@ -12,11 +12,15 @@ class CartRuleCouponDataGrid extends DataGrid
protected $sortOrder = 'desc';
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('cart_rule_coupons')
->addSelect('id', 'code', 'created_at', 'expired_at', 'times_used')
->where('cart_rule_coupons.cart_rule_id', collect(request()->segments())->last());
{
$route = request()->route() ? request()->route()->getName() : "" ;
$cartRuleId = $route == 'admin.cart-rules.edit' ? collect(request()->segments())->last() : last(explode("/", url()->previous()));
$queryBuilder = DB::table('cart_rule_coupons')
->addSelect('id', 'code', 'created_at', 'expired_at', 'times_used')
->where('cart_rule_coupons.cart_rule_id', $cartRuleId);
$this->setQueryBuilder($queryBuilder);
}

View File

@ -99,6 +99,14 @@ class CategoryDataGrid extends DataGrid
'route' => 'admin.catalog.categories.delete',
'confirm_text' => trans('ui::app.datagrid.massaction.delete', ['resource' => 'product']),
'icon' => 'icon trash-icon',
'function' => 'deleteFunction($event, "delete")'
]);
$this->addMassAction([
'type' => 'delete',
'label' => trans('admin::app.datagrid.delete'),
'action' => route('admin.catalog.categories.massdelete'),
'method' => 'DELETE',
]);
}
}

View File

@ -2,18 +2,61 @@
namespace Webkul\Admin\DataGrids;
use Illuminate\Support\Facades\DB;
use Webkul\Ui\DataGrid\DataGrid;
use Webkul\Core\Repositories\ChannelRepository;
class ChannelDataGrid extends DataGrid
{
/**
* Assign primary key.
*/
protected $index = 'id';
/**
* Sort order.
*/
protected $sortOrder = 'desc';
/**
* Filter Locale.
*/
protected $locale;
/**
* ChannelRepository $channelRepository
*
* @var \Webkul\Core\Repositories\ChannelRepository
*/
protected $channelRepository;
/**
* Create a new datagrid instance.
*
* @param \Webkul\Core\Repositories\ChannelRepository $channelRepository
* @return void
*/
public function __construct(
ChannelRepository $channelRepository
)
{
parent::__construct();
$this->locale = request()->get('locale') ?? app()->getLocale();
$this->channelRepository = $channelRepository;
}
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('channels')->addSelect('id', 'code', 'name', 'hostname');
$queryBuilder = $this->channelRepository->query()
->leftJoin('channel_translations', 'channel_translations.channel_id', '=', 'channels.id')
->addSelect('channels.id', 'channels.code', 'channel_translations.locale', 'channel_translations.name as translated_name', 'channels.hostname')
->where('channel_translations.locale', '=', $this->locale);
$this->addFilter('id', 'channels.id');
$this->addFilter('code', 'channels.code');
$this->addFilter('hostname', 'channels.hostname');
$this->addFilter('translated_name', 'channel_translations.name');
$this->setQueryBuilder($queryBuilder);
}
@ -39,7 +82,7 @@ class ChannelDataGrid extends DataGrid
]);
$this->addColumn([
'index' => 'name',
'index' => 'translated_name',
'label' => trans('admin::app.datagrid.name'),
'type' => 'string',
'searchable' => true,

View File

@ -66,6 +66,7 @@ class ProductDataGrid extends DataGrid
'product_flat.channel',
'product_flat.product_id',
'products.sku as product_sku',
'product_flat.product_number',
'product_flat.name as product_name',
'products.type as product_type',
'product_flat.status',
@ -82,6 +83,7 @@ class ProductDataGrid extends DataGrid
$this->addFilter('product_id', 'product_flat.product_id');
$this->addFilter('product_name', 'product_flat.name');
$this->addFilter('product_sku', 'products.sku');
$this->addFilter('product_number', 'product_flat.product_number');
$this->addFilter('status', 'product_flat.status');
$this->addFilter('product_type', 'products.type');
$this->addFilter('attribute_family', 'attribute_families.name');
@ -109,6 +111,15 @@ class ProductDataGrid extends DataGrid
'filterable' => true,
]);
$this->addColumn([
'index' => 'product_number',
'label' => trans('admin::app.datagrid.product-number'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true,
]);
$this->addColumn([
'index' => 'product_name',
'label' => trans('admin::app.datagrid.name'),

View File

@ -2,12 +2,13 @@
namespace Webkul\Admin\DataGrids;
use Illuminate\Support\Facades\DB;
use Webkul\Core\Models\Channel;
use Webkul\Ui\DataGrid\DataGrid;
use Illuminate\Support\Facades\DB;
class SliderDataGrid extends DataGrid
{
protected $index = 'slider_id';
protected $index = 'id';
protected $sortOrder = 'desc';
@ -15,7 +16,11 @@ class SliderDataGrid extends DataGrid
protected $channel = 'all';
/** @var string[] contains the keys for which extra filters to render */
/**
* Contains the keys for which extra filters to render.
*
* @var string[]
**/
protected $extraFilters = [
'channels',
'locales',
@ -26,25 +31,32 @@ class SliderDataGrid extends DataGrid
parent::__construct();
$this->locale = request()->get('locale') ?? 'all';
$this->channel = request()->get('channel') ?? 'all';
$this->channel = request()->get('channel')
? Channel::find(request()->get('channel'))->code
: 'all';
}
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('sliders as sl')
->addSelect('sl.id as slider_id', 'sl.title', 'sl.locale', 'ch.name', 'ch.code')
->leftJoin('channels as ch', 'sl.channel_id', '=', 'ch.id');
->select('sl.id', 'sl.title', 'sl.locale', 'ct.channel_id', 'ct.name', 'ch.code')
->leftJoin('channels as ch', 'sl.channel_id', '=', 'ch.id')
->leftJoin('channel_translations as ct', 'ch.id', '=', 'ct.channel_id')
->where('ct.locale', app()->getLocale());
if ($this->locale !== 'all') {
$queryBuilder->where('locale', $this->locale);
$queryBuilder->where('sl.locale', $this->locale);
}
if ($this->channel !== 'all') {
$queryBuilder->where('ch.code', $this->channel);
}
$this->addFilter('slider_id', 'sl.id');
$this->addFilter('channel_name', 'ch.name');
$this->addFilter('id', 'sl.id');
$this->addFilter('title', 'sl.title');
$this->addFilter('locale', 'sl.locale');
$this->addFilter('channel_name', 'ct.name');
$this->addFilter('code', 'ch.code');
$this->setQueryBuilder($queryBuilder);
}
@ -52,7 +64,7 @@ class SliderDataGrid extends DataGrid
public function addColumns()
{
$this->addColumn([
'index' => 'slider_id',
'index' => 'id',
'label' => trans('admin::app.datagrid.id'),
'type' => 'number',
'searchable' => false,

View File

@ -7,17 +7,6 @@ use Excel;
class ExportController extends Controller
{
protected $exportableGrids = [
'OrderDataGrid',
'OrderInvoicesDataGrid',
'OrderShipmentsDataGrid',
'OrderRefundDataGrid',
'CustomerDataGrid',
'TaxRateDataGrid',
'ProductDataGrid',
'CMSPageDataGrid',
];
/**
* Create a new controller instance.
*
@ -43,18 +32,6 @@ class ExportController extends Controller
$path = '\Webkul\Admin\DataGrids'.'\\'.last($gridName);
$proceed = false;
foreach ($this->exportableGrids as $exportableGrid) {
if (last($gridName) == $exportableGrid) {
$proceed = true;
}
}
if (! $proceed) {
return redirect()->back();
}
$gridInstance = new $path;
$records = $gridInstance->export();

View File

@ -0,0 +1,52 @@
<?php
namespace Webkul\Admin\Http\Middleware;
use Webkul\Core\Repositories\LocaleRepository;
use Closure;
class Locale
{
/**
* @var LocaleRepository
*/
protected $locale;
/**
* @param \Webkul\Core\Repositories\LocaleRepository $locale
*/
public function __construct(LocaleRepository $locale)
{
$this->locale = $locale;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$locale = request()->get('admin_locale');
if ($locale) {
if ($this->locale->findOneByField('code', $locale)) {
app()->setLocale($locale);
session()->put('admin_locale', $locale);
}
} else {
if ($locale = session()->get('admin_locale')) {
app()->setLocale($locale);
} else {
app()->setLocale(app()->getLocale());
}
}
unset($request['admin_locale']);
return $next($request);
}
}

View File

@ -1,6 +1,6 @@
<?php
Route::group(['middleware' => ['web']], function () {
Route::group(['middleware' => ['web', 'admin_locale']], function () {
Route::prefix(config('app.admin_url'))->group(function () {
Route::get('/', 'Webkul\Admin\Http\Controllers\Controller@redirectToLogin');
@ -335,6 +335,13 @@ Route::group(['middleware' => ['web']], function () {
Route::post('/categories/delete/{id}', 'Webkul\Category\Http\Controllers\CategoryController@destroy')->name('admin.catalog.categories.delete');
//category massdelete
Route::post('categories/massdelete', 'Webkul\Category\Http\Controllers\CategoryController@massDestroy')->defaults('_config', [
'redirect' => 'admin.catalog.categories.index',
])->name('admin.catalog.categories.massdelete');
Route::post('/categories/product/count', 'Webkul\Category\Http\Controllers\CategoryController@categoryProductCount')->name('admin.catalog.categories.product.count');
// Catalog Attribute Routes
Route::get('/attributes', 'Webkul\Attribute\Http\Controllers\AttributeController@index')->defaults('_config', [

View File

@ -0,0 +1,23 @@
<?php
namespace Webkul\Admin\Listeners;
use Illuminate\Support\Facades\Artisan;
class ChannelSettingsChange
{
/**
* Check for maintenance mode and set according to settings.
*
* @param \Webkul\Core\Models\Channel $channel
* @return void
*/
public function checkForMaintenaceMode($channel)
{
if ((bool) $channel->is_maintenance_on) {
Artisan::call('down');
} else {
Artisan::call('up');
}
}
}

View File

@ -3,6 +3,8 @@
namespace Webkul\Admin\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Routing\Router;
use Webkul\Admin\Http\Middleware\Locale;
use Webkul\Core\Tree;
class AdminServiceProvider extends ServiceProvider
@ -12,7 +14,7 @@ class AdminServiceProvider extends ServiceProvider
*
* @return void
*/
public function boot()
public function boot(Router $router)
{
$this->loadRoutesFrom(__DIR__ . '/../Http/routes.php');
@ -29,6 +31,8 @@ class AdminServiceProvider extends ServiceProvider
$this->registerACL();
$router->aliasMiddleware('admin_locale', Locale::class);
$this->app->register(EventServiceProvider::class);
}

View File

@ -27,5 +27,7 @@ class EventServiceProvider extends ServiceProvider
Event::listen('sales.refund.save.after','Webkul\Admin\Listeners\Order@sendNewRefundMail');
Event::listen('sales.order.comment.create.after','Webkul\Admin\Listeners\Order@sendOrderCommentMail');
Event::listen('core.channel.update.after','Webkul\Admin\Listeners\ChannelSettingsChange@checkForMaintenaceMode');
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Webkul\Admin\Providers;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
];
}

View File

@ -17,6 +17,8 @@ Vue.use(VeeValidate, {
});
Vue.prototype.$http = axios
Vue.component('required-if', require('./components/validators/required-if').default);
window.eventBus = new Vue();
$(document).ready(function () {

View File

@ -0,0 +1,86 @@
<template>
<div class="control-group" :class="[errors.has(name) ? 'has-error' : '']">
<label :for="name" :class="checkValidations">
{{ label }}
<span class="locale"> {{ channel_locale ? `[${channel_locale}]` : '' }} </span>
</label>
<select v-if="this.options.length" v-validate="checkValidations" class="control" :id = "name" :name = "name" v-model="savedValue"
:data-vv-as="label">
<option v-for='(option, index) in this.options' :value="option.value"> {{ option.title }} </option>
</select>
<input v-else
type="text"
class="control"
:id="name"
:name="name"
:placeholder="info"
v-validate="checkValidations"
v-model="savedValue"
:data-vv-as="label">
<span class="control-error" v-if="errors.has(name)">
{{ errors.first(name) }}
</span>
</div>
</template>
<script>
export default {
props: [
'name',
'label',
'info',
'options',
'result',
'validations',
'depend',
'dependResult',
'channel_locale',
],
inject: ['$validator'],
data: function() {
return {
isRequire: false,
checkValidations: [],
savedValue: this.result,
dependSavedValue: parseInt(this.dependResult)
}
},
mounted: function () {
this.isRequire = this.dependSavedValue ? true : false;
this.updateValidations();
$(document.getElementById(this.depend)).on('change', (e) => {
this.dependSavedValue = !this.dependSavedValue;
this.dependSavedValue = this.dependSavedValue ? 1 : 0;
this.isRequire = this.dependSavedValue ? true : false;
this.updateValidations();
});
},
methods: {
updateValidations: function () {
this.checkValidations = this.validations.split('|').filter(validation => !this.validations.includes('required_if'));
if (this.isRequire) {
this.checkValidations.push('required');
} else {
this.checkValidations = this.checkValidations.filter((value) => {
return value !== 'required';
});
}
this.checkValidations = this.checkValidations.join('|');
}
}
}
</script>

View File

@ -174,6 +174,10 @@
float: left;
}
.multiselect {
text-align: unset;
}
.pagination .page-item .icon {
transform: rotate(180deg);
}

View File

@ -2,7 +2,7 @@
return [
'save' => 'حفظ',
'create' => 'خلق',
'create' => 'إنشاء',
'update' => 'تحديث',
'delete' => 'حذف',
'copy-of' => 'نسخة من ',
@ -47,20 +47,20 @@ return [
'my-account' => 'حسابي',
'logout' => 'خروج',
'visit-shop' => 'قم بزيارة المتجر',
'dashboard' => 'لوحة العدادات',
'dashboard' => 'لوحة التحكم',
'sales' => 'المبيعات',
'orders' => 'الأوامر',
'orders' => 'الطلبات',
'shipments' => 'الشحنات',
'invoices' => 'الفواتير',
'catalog' => 'فهرس',
'products' => 'المنتجات',
'categories' => 'الفئات',
'attributes' => 'الصفات',
'attributes' => 'الخصائص',
'attribute-families' => 'وصف الأسر',
'customers' => 'زبائن',
'groups' => 'المجموعات',
'reviews' => 'باء-الاستعراضات',
'newsletter-subscriptions' => 'الاشتراك في الرسالة الإخبارية',
'reviews' => 'التقييمات',
'newsletter-subscriptions' => 'الاشتراك في النشرة البريدية',
'configure' => 'اضبط',
'settings' => 'إعدادات',
'locales' => 'لغات',
@ -81,9 +81,9 @@ return [
],
'acl' => [
'dashboard' => 'لوحة العدادات',
'dashboard' => 'لوحة التحكم',
'sales' => 'المبيعات',
'orders' => 'الأوامر',
'orders' => 'الطلبات',
'shipments' => 'الشحنات',
'invoices' => 'الفواتير',
'catalog' => 'فهرس',
@ -117,7 +117,7 @@ return [
],
'dashboard' => [
'title' => 'لوحة العدادات',
'title' => 'لوحة التحكم',
'from' => 'من',
'to' => 'إلى',
'total-customers' => 'مجموع الزبائن',
@ -140,10 +140,10 @@ return [
'datagrid' => [
'mass-ops' => [
'method-error' => 'خطأ! تم اكتشاف طريقة خاطئة ، الرجاء التحقق من تشكيل حركة الكتلة',
'delete-success' => "تم حذف المورد بنجاح :Selected",
'method-error' => 'خطأ! تم اكتشاف طريقة خاطئة، الرجاء التحقق من تشكيل حركة الكتلة',
'delete-success' => "تم الحذف بنجاح :Selected",
'partial-action' => 'ولم تنفذ بعض الإجراءات بسبب القيود المفروضة على النظام :resource',
'update-success' => "تم تحديث المورد بنجاح :Selected",
'update-success' => "تم التحديث بنجاح :Selected",
'no-resource' => 'المورد المقدم غير كاف للعمل',
],
@ -154,7 +154,7 @@ return [
'copy' => 'نسخ',
'name' => 'اسم',
'direction' => 'اتجاه',
'fullname' => 'الاسم الكامل',
'fullname' => 'الاسم بالكامل',
'type' => 'النوع',
'required' => 'مطلوب',
'unique' => 'فريد',
@ -171,10 +171,10 @@ return [
'layout' => 'نسق',
'url-key' => 'مفتاح URL',
'comment' => 'تعليق',
'product-name' => 'المنتج',
'product-name' => 'إسم المنتج',
'currency-name' => 'اسم العملة',
'exch-rate' => 'باء-سعر الصرف',
'priority' => 'Priority',
'priority' => 'الأولوية',
'subscribed' => 'مشترك',
'base-total' => 'المجموع الأساسي',
'grand-total' => 'المجموع الكلي',
@ -189,6 +189,7 @@ return [
'shipment-date' => 'تاريخ الشحن',
'shipment-to' => 'الشحن إلى',
'sku' => 'SKU',
'product-number' => 'رقم المنتج',
'price' => 'السعر',
'qty' => 'كمية',
'permission-type' => 'نوع الإذن',
@ -232,10 +233,10 @@ return [
'account' => [
'title' => 'حسابي',
'save-btn-title' => 'احفظ',
'general' => 'ألف-لمحة عامة',
'general' => 'عام',
'name' => 'اسم',
'email' => 'البريد الإلكتروني',
'password' => 'كلمه السر',
'password' => 'كلمه المرور',
'confirm-password' => 'تأكيد كلمة المرور',
'change-password' => 'غير كلمة سر الحساب',
'current-password' => 'كلمة المرور الحالية'
@ -243,22 +244,22 @@ return [
'users' => [
'forget-password' => [
'title' => 'انس كلمة السر',
'header-title' => 'استرجع كلمة السر',
'title' => 'نسيت كلمة المرور',
'header-title' => 'استرجع كلمة المرور',
'email' => 'البريد الإلكتروني المسجل',
'password' => 'كلمه السر',
'password' => 'كلمه المرور',
'confirm-password' => 'تأكيد كلمة المرور',
'back-link-title' => 'العودة للتوقيع',
'submit-btn-title' => 'بريد إلكتروني كلمة مرور إعادة تعيين وصلة'
],
'reset-password' => [
'title' => 'أعد ضبط كلمة السر',
'title' => 'أعد ضبط كلمة المرور',
'email' => 'البريد الإلكتروني المسجل',
'password' => 'كلمه السر',
'password' => 'كلمه المرور',
'confirm-password' => 'تأكيد كلمة المرور',
'back-link-title' => 'العودة للتوقيع',
'submit-btn-title' => 'أعد ضبط كلمة السر'
'submit-btn-title' => 'أعد ضبط كلمة المرور'
],
'roles' => [
@ -266,10 +267,10 @@ return [
'add-role-title' => 'أضف الدور',
'edit-role-title' => 'حرر الدور',
'save-btn-title' => 'احفظ الدور',
'general' => 'ألف-لمحة عامة',
'general' => 'عام',
'name' => 'اسم',
'description' => 'الوصف',
'access-control' => 'مراقبة الدخول',
'access-control' => 'صلاحيات الوصول',
'permissions' => 'الأذون',
'custom' => 'مخصص',
'all' => 'الكل'
@ -280,33 +281,33 @@ return [
'add-user-title' => 'إضافة مستخدم',
'edit-user-title' => 'حرر المستخدم',
'save-btn-title' => 'احفظ المستخدم',
'general' => 'ألف-لمحة عامة',
'general' => 'عام',
'email' => 'البريد الإلكتروني',
'name' => 'اسم',
'password' => 'كلمه الس',
'password' => 'كلمه المرور',
'confirm-password' => 'تأكيد كلمة المرور',
'status-and-role' => 'المركز والدور',
'role' => 'الدور',
'status' => 'الحالة',
'account-is-active' => 'الحساب نشط',
'current-password' => 'أدخل كلمة السر الحالية',
'current-password' => 'أدخل كلمة المرور الحالية',
'confirm-delete' => 'تأكيد حذف هذا الحساب',
'confirm-delete-title' => 'تأكيد كلمة السر قبل حذف',
'confirm-delete-title' => 'تأكيد كلمة المرور قبل حذف',
'delete-last' => 'على الأقل مدير واحد مطلوب.',
'delete-success' => 'نجاح! حذف المستخدم',
'incorrect-password' => 'كلمة السر التي أدخلتها غير صحيحة',
'password-match' => 'كلمة السر الحالية لا تطابق.',
'incorrect-password' => 'كلمة المرور التي أدخلتها غير صحيحة',
'password-match' => 'كلمة المرور الحالية لا تطابق.',
'account-save' => 'الحساب التغييرات و الموفرة بنجاح.',
'login-error' => 'الرجاء التحقق من أوراق اعتمادك ومحاولة مرة أخرى.',
'activate-warning' => 'حسابك لم يتم تفعيله بعد ، الرجاء الاتصال بالمدير.'
'activate-warning' => 'حسابك لم يتم تفعيله بعد، الرجاء الاتصال بالمدير.'
],
'sessions' => [
'title' => 'وقع هنا',
'email' => 'البريد الإلكتروني',
'password' => 'كلمه السر',
'forget-password-link-title' => 'نسيت كلمة السر ؟',
'remember-me' => 'تذكريني',
'password' => 'كلمه المرور',
'forget-password-link-title' => 'نسيت كلمة المرور؟',
'remember-me' => 'تذكرني',
'submit-btn-title' => 'وقع هنا'
]
],
@ -528,7 +529,13 @@ return [
'checkbox' => 'خانة اختيار',
'multiselect' => 'تحديد متعدد',
'new-option' => 'خيار جديد',
'is-default' => 'افتراضي'
'is-default' => 'افتراضي',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' => [
@ -804,7 +811,9 @@ return [
'seo-title' => 'عنوان Meta',
'seo-description' => 'وصف Meta',
'seo-keywords' => 'الكلمات الدالة Meta',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' => [
@ -1235,7 +1244,7 @@ return [
'admin' => [
'emails' => [
'email' => 'Email',
'email' => 'البريد الإلكتروني',
'notification_label' => 'إشعارات',
'notifications' => [
'verification' => 'ارسل ايميل التفعيل',
@ -1281,6 +1290,7 @@ return [
'description' => 'وصف',
'rate' => 'معدل',
'status' => 'الحالة',
'calculate-tax' => 'احسب الضريبة',
'type' => 'اكتب',
'payment-methods' => 'طرق الدفع',
'cash-on-delivery' => 'الدفع عند الاستلام',
@ -1301,6 +1311,11 @@ return [
'weight-unit' => 'وحدة الوزن',
'admin-page-limit' => 'العناصر الافتراضية لكل صفحة (المشرف)',
'design' => 'التصميم',
'email-settings' => 'إعدادات البريد الإلكتروني',
'email-sender-name' => 'اسم مرسل البريد الإلكتروني',
'shop-email-from' => 'متجر عنوان البريد الإلكتروني [لإرسال رسائل البريد الإلكتروني]',
'admin-name' => 'اسم المسؤول',
'admin-email' => 'البريد الإلكتروني للمسؤول',
'admin-logo' => 'شعار المسؤول',
'logo-image' => 'صورة الشعار',
'credit-max' => 'الحد الأقصى لائتمان العميل',
@ -1312,52 +1327,63 @@ return [
'order-number-length' => 'طول رقم الطلب',
'order-number-suffix' => 'لاحقة رقم الطلب',
'order-number-generator-class' => 'مولد رقم الطلب',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'إفتراضي',
'sandbox' => 'صندوق الرمل',
'all-channels' => 'الكل',
'all-locales' => 'الكل',
'invoice-slip-design' => 'Invoice Slip Design',
'logo' => 'Logo',
'storefront' => 'Storefront',
'default-list-mode' => 'Default List Mode',
'grid' => 'Grid',
'list' => 'List',
'products-per-page' => 'Products Per Page',
'sort-by' => 'Sort By',
'invoice-slip-design' => 'تصميم قسيمة الفاتورة',
'logo' => 'شعار',
'storefront' => 'واجهة المحل',
'default-list-mode' => 'وضع القائمة الافتراضي',
'grid' => 'جريد',
'list' => 'قائمة',
'products-per-page' => 'المنتجات في الصفحة',
'sort-by' => 'صنف حسب',
'from-z-a' => 'From Z-A',
'from-a-z' => 'From A-Z',
'newest-first' => 'Newest First',
'oldest-first' => 'Oldest First',
'cheapest-first' => 'Cheapest First',
'expensive-first' => 'Expensive First',
'comma-seperated' => 'Comma Seperated',
'favicon' => 'Favicon',
'comma-seperated' => 'مفصولة بفواصل',
'favicon' => 'فافيكون',
'seo' => 'SEO',
'rich-snippets' => 'Rich Snippets',
'products' => 'Products',
'enable' => 'Enable',
'show-weight' => 'Show Weight',
'show-categories' => 'Show Categories',
'show-images' => 'Show Images',
'show-reviews' => 'Show Reviews',
'show-ratings' => 'Show Ratings',
'show-offers' => 'Show Offers',
'show-sku' => 'Show SKU',
'categories' => 'Categories',
'show-sku' => 'Show SKU',
'show-search-input-field' => 'Show Search Input Field',
'rich-snippets' => 'قصاصات غنية',
'products' => 'منتجات',
'enable' => 'ممكن',
'show-weight' => 'عرض الوزن',
'show-categories' => 'إظهار الفئات',
'show-images' => 'عرض الصور',
'show-reviews' => 'عرض التعليقات',
'show-ratings' => 'إظهار التقييمات',
'show-offers' => 'عرض العروض',
'show-sku' => 'عرض SKU',
'categories' => 'التصنيفات',
'show-sku' => 'عرض SKU',
'show-search-input-field' => 'إظهار حقل إدخال البحث',
'store-name' => 'اسم المتجر',
'vat-number' => 'ظريبه الشراء',
'contact-number' => 'رقم الاتصال',
'bank-details' => 'التفاصيل المصرفية',
'mailing-address' => 'Send Check to',
'instructions' => 'Instructions',
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'mailing-address' => 'أرسل الشيك إلى',
'instructions' => 'تعليمات',
'custom-scripts' => 'البرامج النصية المخصصة',
'custom-css' => 'لغة تنسيق ويب حسب الطلب',
'custom-javascript' => 'جافا سكريبت مخصص',
'paypal-smart-button' => 'زر PayPal الذكي',
'client-id' => 'معرف العميل',
'client-id-info' => 'استخدم "sb" للاختبار.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
]
]
];

View File

@ -188,6 +188,7 @@ return [
'shipment-date' => 'Versand Datum',
'shipment-to' => 'Versand',
'sku' => 'SKU',
'product-number' => 'Produktnummer',
'price' => 'Preis',
'qty' => 'Menge',
'permission-type' => 'Berechtigungsart',
@ -520,6 +521,12 @@ return [
'multiselect' => 'Multiselect',
'new-option' => 'Neue Option',
'is-default' => 'Ist Standard',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' =>
[
@ -803,6 +810,9 @@ return [
'seo-title' => 'Meta Titel',
'seo-description' => 'Meta-Beschreibung',
'seo-keywords' => 'Meta-keywords',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' =>
[
@ -1287,6 +1297,7 @@ return [
'description' => 'Beschreibung',
'rate' => 'Rate',
'status' => 'Status',
'calculate-tax' => 'Steuern berechnen',
'type' => 'Typ',
'payment-methods' => 'Zahlungsmethoden',
'cash-on-delivery' => 'Nachnahme',
@ -1323,6 +1334,8 @@ return [
'order-number-length' => 'Auftragsnummer Länge',
'order-number-suffix' => 'Auftragsnummer Suffix',
'order-number-generator-class' => 'Bestell nummern generator',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'Standard',
'sandbox' => 'Sandbox',
'all-channels' => 'Alle',
@ -1338,9 +1351,14 @@ return [
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'paypal-smart-button' => 'PayPal',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'client-id-info' => 'Use "sb" for testing.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
],
],
];

View File

@ -189,6 +189,7 @@ return [
'shipment-date' => 'Shipment Date',
'shipment-to' => 'Shipping To',
'sku' => 'SKU',
'product-number' => 'Product Number',
'price' => 'Price',
'qty' => 'Quantity',
'permission-type' => 'Permission Type',
@ -532,6 +533,12 @@ return [
'all-group' => 'All Groups',
'fixed' => 'Fixed',
'discount' => 'Discount',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' => [
@ -804,7 +811,9 @@ return [
'seo-title' => 'Meta title',
'seo-description' => 'Meta description',
'seo-keywords' => 'Meta keywords',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' => [
@ -1286,11 +1295,12 @@ return [
'description' => 'Description',
'rate' => 'Rate',
'status' => 'Status',
'calculate-tax' => 'Calculate Tax',
'type' => 'Type',
'payment-methods' => 'Payment Methods',
'cash-on-delivery' => 'Cash On Delivery',
'money-transfer' => 'Money Transfer',
'paypal-standard' => 'Paypal Standard',
'paypal-standard' => 'PayPal Standard',
'business-account' => 'Business Account',
'newsletter' => 'NewsLetter Subscription',
'newsletter-subscription' => 'Allow NewsLetter Subscription',
@ -1322,6 +1332,8 @@ return [
'order-number-length' => 'Order Number Length',
'order-number-suffix' => 'Order Number Suffix',
'order-number-generator-class' => 'Order Number Generator',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'Default',
'sandbox' => 'Sandbox',
'all-channels' => 'All Channels',
@ -1364,9 +1376,14 @@ return [
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'paypal-smart-button' => 'PayPal',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'client-id-info' => 'Use "sb" for testing.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
]
]
];

View File

@ -186,6 +186,7 @@ return [
'shipment-date' => 'Fecha de envío',
'shipment-to' => 'Enviar hacia',
'sku' => 'SKU',
'product-number' => 'Número de producto',
'price' => 'Precio',
'qty' => 'Cantidad',
'permission-type' => 'Tipo de permiso',
@ -521,7 +522,13 @@ return [
'checkbox' => 'Opción múltiple',
'multiselect' => 'Lista de selección múltiple',
'new-option' => 'Nueva opción',
'is-default' => 'Es predeterminada'
'is-default' => 'Es predeterminada',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' => [
@ -797,7 +804,9 @@ return [
'seo-title' => 'Meta title',
'seo-description' => 'Meta description',
'seo-keywords' => 'Meta keywords',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' => [
@ -1270,11 +1279,12 @@ return [
'description' => 'Descripción',
'rate' => 'Tasa',
'status' => 'Estado',
'calculate-tax' => 'Calcular impuestos',
'type' => 'Tipo',
'payment-methods' => 'Métodos de pago',
'cash-on-delivery' => 'Pago contraentrega',
'money-transfer' => 'Transferencia',
'paypal-standard' => 'Paypal',
'paypal-standard' => 'PayPal',
'business-account' => 'Cuenta de negocio',
'newsletter' => 'Suscripción a newsletter',
'newsletter-subscription' => 'Permitir suscripciones a newsletter',
@ -1305,6 +1315,8 @@ return [
'order-number-prefix' => 'Prefijo para Pedido #',
'order-number-length' => 'Largo para Pedido #',
'order-number-suffix' => 'Sufijo para Pedido #',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'Predeterminado',
'sandbox' => 'Sandbox',
'all-channels' => 'Todos',
@ -1320,9 +1332,14 @@ return [
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'paypal-smart-button' => 'PayPal',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'client-id-info' => 'Use "sb" for testing.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
]
]
];

View File

@ -187,6 +187,7 @@ return [
'shipment-date' => 'تاریخ ارسال',
'shipment-to' => 'حمل و نقل به',
'sku' => 'واحد نگهداری موجودی',
'product-number' => 'شماره محصول',
'price' => 'قیمت',
'qty' => 'مقدار',
'permission-type' => 'نوع مجوز',
@ -526,7 +527,13 @@ return [
'checkbox' => 'Checkbox',
'multiselect' => 'Multiselect',
'new-option' => 'New Option',
'is-default' => 'Is Default'
'is-default' => 'Is Default',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' => [
@ -802,7 +809,9 @@ return [
'seo-title' => 'عنوان Meta',
'seo-description' => 'شرح Meta',
'seo-keywords' => 'کلید واژه ها Meta',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' => [
@ -1276,6 +1285,7 @@ return [
'description' => 'توضیحات',
'rate' => 'نرخ',
'status' => 'وضعیت',
'calculate-tax' => 'محاسبه مالیات',
'type' => 'نوع',
'payment-methods' => 'روش های پرداخت',
'cash-on-delivery' => 'پرداخت در محل',
@ -1312,6 +1322,8 @@ return [
'order-number-length' => 'طول شماره سفارش',
'order-number-suffix' => 'تعداد کافی شماره سفارش',
'order-number-generator-class' => 'تولید کننده شماره سفارش',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'پیش فرض',
'sandbox' => 'Sandbox',
'all-channels' => 'همه',
@ -1356,9 +1368,14 @@ return [
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'paypal-smart-button' => 'PayPal',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'client-id-info' => 'Use "sb" for testing.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
]
]
];

View File

@ -188,6 +188,7 @@ return [
'shipment-date' => 'Data Spedizione',
'shipment-to' => 'Spedizione A',
'sku' => 'SKU',
'product-number' => 'Numero del prodotto',
'price' => 'Prezzo',
'qty' => 'Quantità',
'permission-type' => 'Tipo Permessi',
@ -529,7 +530,13 @@ return [
'multiselect' => 'Multiselect',
'new-option' => 'Nuova Opzione',
'is-default' => 'È Predefinita',
'actions' => 'Azioni'
'actions' => 'Azioni',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' => [
@ -806,7 +813,9 @@ return [
'seo-title' => 'Meta title',
'seo-description' => 'Meta description',
'seo-keywords' => 'Meta keywords',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' => [
@ -1281,11 +1290,12 @@ return [
'description' => 'Descrizione',
'rate' => 'Tasso',
'status' => 'Stato',
'calculate-tax' => 'Calcola le tasse',
'type' => 'Tipo',
'payment-methods' => 'Metodi di Pagamento',
'cash-on-delivery' => 'Contrassegno',
'money-transfer' => 'Bonifico',
'paypal-standard' => 'Paypal Standard',
'paypal-standard' => 'PayPal Standard',
'business-account' => 'Account Business',
'newsletter' => 'Iscrizione a NewsLetter',
'newsletter-subscription' => 'Consenti Iscrizione a NewsLetter',
@ -1317,6 +1327,8 @@ return [
'order-number-length' => 'Lunghezza Numero Ordine',
'order-number-suffix' => 'Suffisso Numero Ordine',
'order-number-generator-class' => 'Generatore di numeri dordine',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'Default',
'sandbox' => 'Sandbox',
'all-channels' => 'Tutti',
@ -1361,9 +1373,14 @@ return [
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'paypal-smart-button' => 'PayPal',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'client-id-info' => 'Use "sb" for testing.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
]
]
];

View File

@ -188,6 +188,7 @@ return [
'shipment-date' => 'Verzenddatum',
'shipment-to' => 'Shipping To',
'sku' => 'SKU',
'product-number' => 'Productnummer',
'price' => 'Prijs',
'qty' => 'Aantal',
'permission-type' => 'Permission Type',
@ -528,6 +529,12 @@ return [
'multiselect' => 'Multiselect',
'new-option' => 'Nieuwe optie',
'is-default' => 'is standaard',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' => [
@ -803,7 +810,9 @@ return [
'seo-title' => 'Meta titel',
'seo-description' => 'Meta omschrijving',
'seo-keywords' => 'Meta trefwoorden',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' => [
@ -1277,11 +1286,12 @@ return [
'description' => 'Omschrijving',
'rate' => 'Tarief',
'status' => 'Toestand',
'calculate-tax' => 'Beregn skat',
'type' => 'Type',
'payment-methods' => 'Betaalmethodes',
'cash-on-delivery' => 'Rembours',
'money-transfer' => 'Overschrijving',
'paypal-standard' => 'Paypal Standard',
'paypal-standard' => 'PayPal Standard',
'business-account' => 'Zakelijk account',
'newsletter' => 'Nieuwsbrief',
'newsletter-subscription' => 'Abonnement op Nieuwsbrief toestaan',
@ -1313,6 +1323,8 @@ return [
'order-number-length' => 'Bestelnummer Lengte',
'order-number-suffix' => 'Achtervoegsel bestelnummer',
'order-number-generator-class' => 'Ordernummer Generator',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'Standaard',
'sandbox' => 'Sandbox',
'all-channels' => 'Alles',
@ -1356,9 +1368,14 @@ return [
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'paypal-smart-button' => 'PayPal',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'client-id-info' => 'Use "sb" for testing.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
]
]
];

View File

@ -186,6 +186,7 @@ return [
'shipment-date' => 'Data wysyłki',
'shipment-to' => 'Wysyłka do',
'sku' => 'SKU',
'product-number' => 'Numer produktu',
'price' => 'Cena',
'qty' => 'Ilość',
'permission-type' => 'Rodzaj zezwolenia',
@ -527,7 +528,13 @@ return [
'checkbox' => 'Pole wyboru',
'multiselect' => 'Wielokrotny wybór',
'new-option' => 'Nowa opcja',
'is-default' => 'Jest domyślny'
'is-default' => 'Jest domyślny',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' => [
@ -804,7 +811,9 @@ return [
'seo-title' => 'Meta tytuł',
'seo-description' => 'Meta opis',
'seo-keywords' => 'Meta słowa kluczowe',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' => [
@ -1278,11 +1287,12 @@ return [
'description' => 'Opis',
'rate' => 'Stawka',
'status' => 'Status',
'calculate-tax' => 'Oblicz podatek',
'type' => 'Rodzaj',
'payment-methods' => 'Metody płatności',
'cash-on-delivery' => 'Za pobraniem',
'money-transfer' => 'Przekaz pieniężny',
'paypal-standard' => 'Paypal Standard',
'paypal-standard' => 'PayPal Standard',
'business-account' => 'Konto biznesowe',
'newsletter' => 'Subskrypcja newslettera',
'newsletter-subscription' => 'Zezwól na subskrypcję newslettera',
@ -1314,6 +1324,8 @@ return [
'order-number-length' => 'Długość numeru zamówienia',
'order-number-suffix' => 'Sufiks numeru zamówienia”',
'order-number-generator-class' => 'Generator numeru zamówienia',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'Domyślna',
'sandbox' => 'Piaskownica',
'all-channels' => 'Wszystkie kanały',
@ -1345,9 +1357,14 @@ return [
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'paypal-smart-button' => 'PayPal',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'client-id-info' => 'Use "sb" for testing.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
]
]
];

View File

@ -187,6 +187,7 @@ return [
'shipment-date' => 'Data de Envio',
'shipment-to' => 'Enviado para',
'sku' => 'SKU',
'product-number' => 'Número de produto',
'price' => 'Preço',
'qty' => 'Quantidade',
'permission-type' => 'Tipo de Permissão',
@ -526,7 +527,13 @@ return [
'checkbox' => 'Checkbox',
'multiselect' => 'Multiselect',
'new-option' => 'New Option',
'is-default' => 'Is Default'
'is-default' => 'Is Default',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' => [
@ -803,7 +810,9 @@ return [
'seo-title' => 'Meta título',
'seo-description' => 'Meta Descrição',
'seo-keywords' => 'Meta palavras-chave',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' => [
@ -1277,11 +1286,12 @@ return [
'description' => 'Descrição',
'rate' => 'Taxa',
'status' => 'Status',
'calculate-tax' => 'Calcular o imposto',
'type' => 'Tipo',
'payment-methods' => 'Métodos de Pagamento',
'cash-on-delivery' => 'Dinheiro na entrega',
'money-transfer' => 'Transferência de dinheiro',
'paypal-standard' => 'Padrão Paypal',
'paypal-standard' => 'Padrão PayPal',
'business-account' => 'Conta de negócios',
'newsletter' => 'Assinatura de Newsletter',
'newsletter-subscription' => 'Permitir assinatura do NewsLetter',
@ -1315,6 +1325,8 @@ return [
'order-number-length' => 'Tamanho do Número do Pedido',
'order-number-suffix' => 'Sufixo do Número de Pedido',
'order-number-generator-class' => 'Gerador de número de pedido',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'Padrão',
'sandbox' => 'Sandbox',
'all-channels' => 'Todos',
@ -1359,9 +1371,14 @@ return [
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'paypal-smart-button' => 'PayPal',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'client-id-info' => 'Use "sb" for testing.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
]
]
];

View File

@ -185,6 +185,7 @@ return [
'shipment-date' => 'Kargo Tarihi',
'shipment-to' => 'Kargo Bilgileri',
'sku' => 'Barkod',
'product-number' => 'Ürün numarası',
'price' => 'Fiyat',
'qty' => 'Miktar',
'permission-type' => 'İzin Tipi',
@ -522,7 +523,13 @@ return [
'checkbox' => 'Onay Kutusu',
'multiselect' => 'Çoklu Seçim',
'new-option' => 'Yeni Seçenek',
'is-default' => 'Varsayılan'
'is-default' => 'Varsayılan',
'remove-image-btn-title' => 'Remove Image',
'videos' => 'Videos',
'video' => 'Video',
'add-video-btn-title' => 'Add Video',
'remove-video-btn-title' => 'Remove Video',
'not-support-video' => 'Your browser does not support the video tag.',
],
'attributes' => [
@ -795,7 +802,9 @@ return [
'seo-title' => 'Meta Başlık',
'seo-description' => 'Meta Açıklama',
'seo-keywords' => 'Meta Anahtar Kelimeler',
'maintenance-mode' => 'Maintenance Mode',
'maintenance-mode-text' => 'Message',
'allowed-ips' => 'Allowed IPs'
],
'sliders' => [
@ -1265,11 +1274,12 @@ return [
'description' => 'Açıklama',
'rate' => 'Oran',
'status' => 'Durum',
'calculate-tax' => 'Vergiyi Hesapla',
'type' => 'Tipi',
'payment-methods' => 'Ödeme Türleri',
'cash-on-delivery' => 'Kapıda Ödeme',
'money-transfer' => 'Havale/EFT',
'paypal-standard' => 'Paypal',
'paypal-standard' => 'PayPal',
'business-account' => 'İş Hesabı',
'newsletter' => 'Bülten Aboneliği',
'newsletter-subscription' => 'Bülten Aboneliğine İzin Ver',
@ -1301,6 +1311,8 @@ return [
'order-number-length' => 'Numara Uzunluğu',
'order-number-suffix' => 'Numara Son Eki',
'order-number-generator-class' => 'Sipariş Numarası Üreticisi',
'minimum-order' => 'Minimum Order Settings',
'minimum-order-amount' => 'Minimum Order Amount',
'default' => 'Varsayılan',
'sandbox' => 'Havuz',
'all-channels' => 'Tümü',
@ -1342,9 +1354,14 @@ return [
'custom-scripts' => 'Custom Scripts',
'custom-css' => 'Custom CSS',
'custom-javascript' => 'Custom Javascript',
'paypal-smart-button' => 'Paypal Smart Button',
'paypal-smart-button' => 'PayPal',
'client-id' => 'Client Id',
'client-id-info' => 'Use "sb" for testing.'
'client-id-info' => 'Use "sb" for testing.',
'client-secret' => 'Client Secret',
'client-secret-info' => 'Add your secret key here',
'accepted-currencies' => 'Accepted currencies',
'accepted-currencies-info' => 'Add currency code comma seperated e.g. USD,INR,...',
'buy-now-button-display' => 'Allow customers to directly buy products'
]
]
];

View File

@ -26,4 +26,58 @@
{!! view_render_event('bagisto.admin.catalog.categories.list.after') !!}
</div>
@stop
@stop
@push('scripts')
<script>
$(document).ready(function(){
$("input[type='checkbox']").change(deleteFunction);
});
var deleteFunction = function(e,type) {
if (type == 'delete') {
var indexes = $(e.target).parent().attr('id');
} else {
$("input[type='checkbox']").attr('disabled', true);
var formData = {};
$.each($('form').serializeArray(), function(i, field) {
formData[field.name] = field.value;
});
var indexes = formData.indexes;
}
if (indexes) {
$.ajax({
type : 'POST',
url : '{{route("admin.catalog.categories.product.count")}}',
data : {
_token: '{{csrf_token()}}',
indexes: indexes
},
success:function(data) {
$("input[type='checkbox']").attr('disabled', false);
if (data.product_count > 0) {
var message = "{{trans('ui::app.datagrid.massaction.delete-category-product')}}";
if (type == 'delete') {
doAction(e, message);
} else {
$('form').attr('onsubmit', 'return confirm("'+message+'")');
}
} else {
var message = "{{ __('ui::app.datagrid.click_on_action') }}";
if (type == 'delete') {
doAction(e, message);
} else {
$('form').attr('onsubmit', 'return confirm("'+message+'")');
}
}
}
});
} else {
$("input[type='checkbox']").attr('disabled', false);
}
}
</script>
@endpush

View File

@ -85,7 +85,7 @@
<div class="control-group">
<div class="control-group" :class="[errors.has(inputName + '[value]') ? 'has-error' : '']">
<input type="number" v-validate="'required|min_value:0'" :name="[inputName + '[value]']" v-model="customerGroupPrice.value" class="control" data-vv-as="&quot;{{ __('admin::app.datagrid.price') }}&quot;"/>
<input type="number" v-validate="{required: true, min_value: 0, ...(customerGroupPrice.value_type === 'discount' ? {max_value: 100} : {})}" :name="[inputName + '[value]']" v-model="customerGroupPrice.value" class="control" data-vv-as="&quot;{{ __('admin::app.datagrid.price') }}&quot;"/>
<span class="control-error" v-if="errors.has(inputName + '[value]')">@{{ errors.first(inputName + '[value]') }}</span>
</div>
</div>
@ -159,4 +159,4 @@
}
});
</script>
@endpush
@endpush

View File

@ -54,7 +54,9 @@
<img class="preview" :src="imageData" v-if="imageData.length > 0">
<label class="remove-image" @click="removeImage()">Remove Image</label>
<label class="remove-image" @click="removeImage()">
{{ __('admin::app.catalog.products.remove-image-btn-title') }}
</label>
</label>
</script>

View File

@ -0,0 +1,198 @@
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.videos.before', ['product' => $product]) !!}
<accordian :title="'{{ __('admin::app.catalog.products.videos') }}'" :active="false">
<div slot="body">
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.videos.controls.before', ['product' => $product]) !!}
<div class="control-group {!! $errors->has('videos.*') ? 'has-error' : '' !!}">
<label>{{ __('admin::app.catalog.products.video') }}</label>
<product-video></product-video>
<span class="control-error" v-if="{!! $errors->has('videos.*') !!}">
@php $count=1 @endphp
@foreach ($errors->get('videos.*') as $key => $message)
@php echo str_replace($key, 'Video'.$count, $message[0]); $count++ @endphp
@endforeach
</span>
</div>
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.videos.controls.after', ['product' => $product]) !!}
</div>
</accordian>
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.videos.after', ['product' => $product]) !!}
@push('scripts')
@parent
<script type="text/x-template" id="product-video-template">
<div>
<div class="image-wrapper">
<product-video-item
v-for='(video, index) in items'
:key='video.id'
:video="video"
@onRemoveVideo="removeVideo($event)"
@onVideoSelected="videoSelected($event)"
></product-video-item>
</div>
<label class="btn btn-lg btn-primary" style="display: inline-block; width: auto" @click="createFileType">
{{ __('admin::app.catalog.products.add-video-btn-title') }}
</label>
</div>
</script>
<script type="text/x-template" id="product-video-item-template">
<label class="image-item" v-bind:class="{ 'has-image': videoData.length > 0 }">
<input type="hidden" :name="'videos[' + video.id + ']'" v-if="! new_video"/>
<input type="file" v-validate="'mimes:video/*'" accept="video/*" :name="'videos[]'" ref="videoInput" :id="_uid" @change="addVideoView($event)" multiple="multiple"/>
<video class="preview" v-if="videoData.length > 0" width="200" height="160" controls>
<source :src="videoData" type="video/mp4">
{{ __('admin::app.catalog.products.not-support-video') }}
</video>
<label class="remove-image" @click="removeVideo()">
{{ __('admin::app.catalog.products.remove-video-btn-title') }}
</label>
</label>
</script>
<script>
Vue.component('product-video', {
template: '#product-video-template',
data: function() {
return {
videos: @json($product->videos),
videoCount: 0,
items: []
}
},
computed: {
finalInputName: function() {
return 'videos[' + this.video.id + ']';
}
},
created: function() {
var this_this = this;
this.videos.forEach(function(video) {
this_this.items.push(video)
this_this.videoCount++;
});
},
methods: {
createFileType: function() {
var this_this = this;
this.videoCount++;
this.items.push({'id': 'video_' + this.videoCount});
},
removeVideo (video) {
let index = this.items.indexOf(video)
Vue.delete(this.items, index);
},
videoSelected: function(event) {
var this_this = this;
Array.from(event.files).forEach(function(video, index) {
if (index) {
this_this.videoCount++;
this_this.items.push({'id': 'video_' + this_this.videoCount, file: video});
}
});
}
}
});
Vue.component('product-video-item', {
template: '#product-video-item-template',
props: {
video: {
type: Object,
required: false,
default: null
},
},
data: function() {
return {
videoData: '',
new_video: 0
}
},
mounted () {
if (this.video.id && this.video.url) {
this.videoData = this.video.url;
} else if (this.video.id && this.video.file) {
this.readFile(this.video.file);
}
},
computed: {
finalInputName: function() {
return this.inputName + '[' + this.video.id + ']';
}
},
methods: {
addVideoView: function() {
var videoInput = this.$refs.videoInput;
if (videoInput.files && videoInput.files[0]) {
if (videoInput.files[0].type.includes('video/')) {
this.readFile(videoInput.files[0])
if (videoInput.files.length > 1) {
this.$emit('onVideoSelected', videoInput)
}
} else {
videoInput.value = "";
alert('Only videos (.mp4, .mov, .ogg ..) are allowed.');
}
}
},
readFile: function(video) {
var reader = new FileReader();
reader.onload = (e) => {
this.videoData = e.target.result;
}
reader.readAsDataURL(video);
this.new_video = 1;
},
removeVideo: function() {
this.$emit('onRemoveVideo', this.video)
}
}
});
</script>
@endpush

View File

@ -65,18 +65,34 @@
}
$selectedOption = core()->getConfigData($name) ?? '';
$dependSelectedOption = core()->getConfigData(implode('.', [$firstField, $secondField, $thirdField, $dependField])) ?? '';
?>
<depends
:options = '@json($field['options'])'
:name = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]'"
:validations = "'{{ $validations }}'"
:depend = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $dependField }}]'"
:value = "'{{ $dependValue }}'"
:field_name = "'{{ trans($field['title']) }}'"
:channel_locale = "'{{ $channel_locale }}'"
:result = "'{{ $selectedOption }}'"
></depends>
@if (strpos($field['validation'], 'required_if') !== false)
<required-if
:name = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]'"
:label = "'{{ trans($field['title']) }}'"
:info = "'{{ trans(isset($field['info']) ? $field['info'] : '') }}'"
:options = '@json($field['options'])'
:result = "'{{ $selectedOption }}'"
:validations = "'{{ $validations }}'"
:depend = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $dependField }}]'"
:depend-result= "'{{ $dependSelectedOption }}'"
:channel_locale = "'{{ $channel_locale }}'"
></required-if>
@else
<depends
:options = '@json($field['options'])'
:name = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]'"
:validations = "'{{ $validations }}'"
:depend = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $dependField }}]'"
:value = "'{{ $dependValue }}'"
:field_name = "'{{ trans($field['title']) }}'"
:channel_locale = "'{{ $channel_locale }}'"
:result = "'{{ $selectedOption }}'"
:depend-saved-value= "'{{ $dependSelectedOption }}'"
></depends>
@endif
@else
@ -99,7 +115,7 @@
@elseif ($field['type'] == 'password')
<input type="password" v-validate="'{{ $validations }}'" class="control" id="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" name="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" value="{{ old($name) ?: core()->getConfigData($name) }}" data-vv-as="&quot;{{ trans($field['title']) }}&quot;">
@elseif ($field['type'] == 'number')
<input type="number" min="0" v-validate="'{{ $validations }}'" class="control" id="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" name="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" value="{{ old($name) ?: core()->getConfigData($name) }}" data-vv-as="&quot;{{ trans($field['title']) }}&quot;">
@ -111,7 +127,7 @@
@elseif ($field['type'] == 'textarea')
<textarea v-validate="'{{ $validations }}'" class="control" id="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" name="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" data-vv-as="&quot;{{ trans($field['title']) }}&quot;">{{ old($name) ?: core()->getConfigData($name) }}</textarea>
<textarea v-validate="'{{ $validations }}'" class="control" id="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" name="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" data-vv-as="&quot;{{ trans($field['title']) }}&quot;">{{ old($name) ?: core()->getConfigData($name) ?: (isset($field['default_value']) ? $field['default_value'] : '') }}</textarea>
@elseif ($field['type'] == 'select')
@ -215,7 +231,7 @@
@elseif ($field['type'] == 'boolean')
<?php $selectedOption = core()->getConfigData($name) ?? ''; ?>
<?php $selectedOption = core()->getConfigData($name) ?? (isset($field['default_value']) ? $field['default_value'] : ''); ?>
<label class="switch">
<input type="hidden" name="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" value="0" />

View File

@ -20,7 +20,7 @@
</div>
<div class="error-messgae" style="font-size: 24px;color: #5E5E5E">
{{ __('admin::app.error.right-back') }}
{{ core()->getCurrentChannel()->maintenance_mode_text ?: __('admin::app.error.right-back') }}
</div>
</div>

View File

@ -71,7 +71,7 @@
{!! view_render_event('bagisto.admin.layout.head') !!}
</head>
<body @if (core()->getCurrentLocale()->direction == 'rtl') class="rtl" @endif style="scroll-behavior: smooth;">
<body @if (core()->getCurrentLocale() && core()->getCurrentLocale()->direction == 'rtl') class="rtl" @endif style="scroll-behavior: smooth;">
<div id="app" class="container">
<flash-wrapper ref='flashes'></flash-wrapper>

View File

@ -7,7 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
@if ($favicon = core()->getConfigData('general.design.admin_logo.favicon'))
@if ($favicon = core()->getConfigData('general.design.admin_logo.favicon', core()->getCurrentChannelCode()))
<link rel="icon" sizes="16x16" href="{{ \Illuminate\Support\Facades\Storage::url($favicon) }}" />
@else
<link rel="icon" sizes="16x16" href="{{ asset('vendor/webkul/ui/assets/images/favicon.ico') }}" />

View File

@ -16,6 +16,42 @@
<span class="avatar">
</span>
<?php $locale = request()->get('admin_locale') ?: app()->getLocale();?>
<div class="profile-info">
<div class="dropdown-toggle">
<div style="display: inline-block; vertical-align: middle;">
<span class="name">
{{ __('admin::app.datagrid.locale') }}
</span>
@foreach (core()->getAllLocales() as $localeModel)
@if ($localeModel->code == $locale)
<span class="role">
{{ $localeModel->name }}
</span>
@endif
@endforeach
</div>
<i class="icon arrow-down-icon active"></i>
</div>
<div class="dropdown-list bottom-right">
<div class="control-group">
<select class="control" onChange="window.location.href = this.value" style="margin-left: 30px;">
@foreach (core()->getAllLocales() as $localeModel)
<option value="{{ '?admin_locale=' . $localeModel->code }}" {{ ($localeModel->code) == $locale ? 'selected' : '' }}>
{{ $localeModel->name }}
</option>
@endforeach
</select>
</div>
</div>
</div>
<div class="profile-info">
<div class="dropdown-toggle">
<div style="display: inline-block; vertical-align: middle;">

View File

@ -457,12 +457,38 @@
</form>
<div class="content">
<div class="page-header">
<div class="page-action">
<div class="export-import" @click="showModal('downloadDataGrid')">
<i class="export-icon"></i>
<span >
{{ __('admin::app.export.export') }}
</span>
</div>
</div>
</div>
</div>
<modal id="downloadDataGrid" :is-open="this.$root.modalIds.downloadDataGrid">
<h3 slot="header">{{ __('admin::app.export.download') }}</h3>
<div slot="body">
<export-form></export-form>
</div>
</modal>
@inject('cartRuleCouponGrid','Webkul\Admin\DataGrids\CartRuleCouponDataGrid')
{!! $cartRuleCouponGrid->render() !!}
</div>
</script>
@push('scripts')
@include('admin::export.export', ['gridName' => $cartRuleCouponGrid])
@endpush
<script>
Vue.component('cart-rule', {
@ -754,7 +780,11 @@
})
}
});
}
},
showModal(id) {
this.$root.$set(this.$root.modalIds, id, true);
},
}
});
</script>

View File

@ -454,8 +454,14 @@
<tr class="bold">
<td>{{ __('admin::app.sales.orders.total-due') }}</td>
<td>-</td>
<td>{{ core()->formatBasePrice($order->base_total_due) }}</td>
@if($order->status !== 'canceled')
<td>{{ core()->formatBasePrice($order->base_total_due) }}</td>
@else
<td id="due-amount-on-cancelled">{{ core()->formatBasePrice(0.00) }}</td>
@endif
</tr>
</table>
</div>

View File

@ -30,6 +30,7 @@
{!! view_render_event('bagisto.admin.settings.channel.create.before') !!}
{{-- general --}}
<accordian :title="'{{ __('admin::app.settings.channels.general') }}'" :active="true">
<div slot="body">
@ -84,6 +85,7 @@
</div>
</accordian>
{{-- currencies and locales --}}
<accordian :title="'{{ __('admin::app.settings.channels.currencies-and-locales') }}'" :active="true">
<div slot="body">
@ -138,6 +140,7 @@
</div>
</accordian>
{{-- design --}}
<accordian :title="'{{ __('admin::app.settings.channels.design') }}'" :active="true">
<div slot="body">
<div class="control-group">
@ -176,6 +179,7 @@
</div>
</accordian>
{{-- home page seo --}}
<accordian :title="'{{ __('admin::app.settings.channels.seo') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('seo_title') ? 'has-error' : '']">
@ -202,6 +206,30 @@
</div>
</accordian>
{{-- maintenance mode --}}
<accordian title="{{ __('admin::app.settings.channels.maintenance-mode') }}" :active="true">
<div slot="body">
<div class="control-group">
<label for="maintenance-mode-status">{{ __('admin::app.status') }}</label>
<label class="switch">
<input type="hidden" name="is_maintenance_on" value="0" />
<input type="checkbox" id="maintenance-mode-status" name="is_maintenance_on" value="1">
<span class="slider round"></span>
</label>
</div>
<div class="control-group">
<label for="maintenance-mode-text">{{ __('admin::app.settings.channels.maintenance-mode-text') }}</label>
<input class="control" id="maintenance-mode-text" name="maintenance_mode_text" value=""/>
</div>
<div class="control-group">
<label for="allowed-ips">{{ __('admin::app.settings.channels.allowed-ips') }}</label>
<input class="control" id="allowed-ips" name="allowed_ips" value=""/>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.admin.settings.channel.create.after') !!}
</div>
</div>

View File

@ -6,8 +6,9 @@
@section('content')
<div class="content">
@php $locale = request()->get('locale') ?: app()->getLocale(); @endphp
<form method="POST" action="{{ route('admin.channels.update', $channel->id) }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<form method="POST" action="{{ route('admin.channels.update', ['id' => $channel->id, 'locale' => $locale]) }}" @submit.prevent="onSubmit" enctype="multipart/form-data">
<div class="page-header">
<div class="page-title">
<h1>
@ -15,6 +16,18 @@
{{ __('admin::app.settings.channels.edit-title') }}
</h1>
<div class="control-group">
<select class="control" id="locale-switcher" onChange="window.location.href = this.value">
@foreach (core()->getAllLocales() as $localeModel)
<option value="{{ route('admin.channels.edit', $channel->id) . '?locale=' . $localeModel->code }}" {{ ($localeModel->code) == $locale ? 'selected' : '' }}>
{{ $localeModel->name }}
</option>
@endforeach
</select>
</div>
</div>
<div class="page-action">
@ -25,12 +38,14 @@
</div>
<div class="page-content">
<div class="form-container">
@csrf()
<input name="_method" type="hidden" value="PUT">
{!! view_render_event('bagisto.admin.settings.channel.edit.before') !!}
{{-- general --}}
<accordian :title="'{{ __('admin::app.settings.channels.general') }}'" :active="true">
<div slot="body">
@ -41,15 +56,21 @@
<span class="control-error" v-if="errors.has('code')">@{{ errors.first('code') }}</span>
</div>
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.settings.channels.name') }}</label>
<input v-validate="'required'" class="control" id="name" name="name" data-vv-as="&quot;{{ __('admin::app.settings.channels.name') }}&quot;" value="{{ old('name') ?: $channel->name }}"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
<div class="control-group" :class="[errors.has('{{$locale}}[name]') ? 'has-error' : '']">
<label for="name" class="required">
{{ __('admin::app.settings.channels.name') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<input v-validate="'required'" class="control" id="name" name="{{$locale}}[name]" data-vv-as="&quot;{{ __('admin::app.settings.channels.name') }}&quot;" value="{{ old($locale)['name'] ?? ($channel->translate($locale)['name'] ?? '') }}"/>
<span class="control-error" v-if="errors.has('{{$locale}}[name]')">@{{ errors.first('{!!$locale!!}[page_title]') }}</span>
</div>
<div class="control-group">
<label for="description">{{ __('admin::app.settings.channels.description') }}</label>
<textarea class="control" id="description" name="description">{{ old('description') ?: $channel->description }}</textarea>
<label for="description">
{{ __('admin::app.settings.channels.description') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<textarea class="control" id="description" name="{{$locale}}[description]">{{ old($locale)['description'] ?? ($channel->translate($locale)['description'] ?? '') }}</textarea>
</div>
<div class="control-group" :class="[errors.has('inventory_sources[]') ? 'has-error' : '']">
@ -88,6 +109,7 @@
</div>
</accordian>
{{-- currencies and locales --}}
<accordian :title="'{{ __('admin::app.settings.channels.currencies-and-locales') }}'" :active="true">
<div slot="body">
@ -95,9 +117,9 @@
<label for="locales" class="required">{{ __('admin::app.settings.channels.locales') }}</label>
<?php $selectedOptionIds = old('locales') ?: $channel->locales->pluck('id')->toArray() ?>
<select v-validate="'required'" class="control" id="locales" name="locales[]" data-vv-as="&quot;{{ __('admin::app.settings.channels.locales') }}&quot;" multiple>
@foreach (core()->getAllLocales() as $locale)
<option value="{{ $locale->id }}" {{ in_array($locale->id, $selectedOptionIds) ? 'selected' : '' }}>
{{ $locale->name }}
@foreach (core()->getAllLocales() as $localeModel)
<option value="{{ $localeModel->id }}" {{ in_array($localeModel->id, $selectedOptionIds) ? 'selected' : '' }}>
{{ $localeModel->name }}
</option>
@endforeach
</select>
@ -108,9 +130,9 @@
<label for="default_locale_id" class="required">{{ __('admin::app.settings.channels.default-locale') }}</label>
<?php $selectedOption = old('default_locale_id') ?: $channel->default_locale_id ?>
<select v-validate="'required'" class="control" id="default_locale_id" name="default_locale_id" data-vv-as="&quot;{{ __('admin::app.settings.channels.default-locale') }}&quot;">
@foreach (core()->getAllLocales() as $locale)
<option value="{{ $locale->id }}" {{ $selectedOption == $locale->id ? 'selected' : '' }}>
{{ $locale->name }}
@foreach (core()->getAllLocales() as $localeModel)
<option value="{{ $localeModel->id }}" {{ $selectedOption == $localeModel->id ? 'selected' : '' }}>
{{ $localeModel->name }}
</option>
@endforeach
</select>
@ -146,6 +168,7 @@
</div>
</accordian>
{{-- design --}}
<accordian :title="'{{ __('admin::app.settings.channels.design') }}'" :active="true">
<div slot="body">
<div class="control-group">
@ -163,13 +186,19 @@
</div>
<div class="control-group">
<label for="home_page_content">{{ __('admin::app.settings.channels.home_page_content') }}</label>
<textarea class="control" id="home_page_content" name="home_page_content">{{ old('home_page_content') ?: $channel->home_page_content }}</textarea>
<label for="home_page_content">
{{ __('admin::app.settings.channels.home_page_content') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<textarea class="control" id="home_page_content" name="{{$locale}}[home_page_content]">{{ old($locale)['home_page_content'] ?? ($channel->translate($locale)['home_page_content'] ?? '') }}</textarea>
</div>
<div class="control-group">
<label for="footer_content">{{ __('admin::app.settings.channels.footer_content') }}</label>
<textarea class="control" id="footer_content" name="footer_content">{{ old('footer_content') ?: $channel->footer_content }}</textarea>
<label for="footer_content">
{{ __('admin::app.settings.channels.footer_content') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<textarea class="control" id="footer_content" name="{{$locale}}[footer_content]">{{ old($locale)['footer_content'] ?? ($channel->translate($locale)['footer_content'] ?? '') }}</textarea>
</div>
<div class="control-group">
@ -188,31 +217,71 @@
</accordian>
@php
$seo = json_decode($channel->home_seo);
$home_seo = $channel->translate($locale)['home_seo'] ?? '{}';
$seo = json_decode($home_seo);
@endphp
{{-- home page seo --}}
<accordian :title="'{{ __('admin::app.settings.channels.seo') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('seo_title') ? 'has-error' : '']">
<label for="seo_title" class="required">{{ __('admin::app.settings.channels.seo-title') }}</label>
<input v-validate="'required'" class="control" id="seo_title" name="seo_title" data-vv-as="&quot;{{ __('admin::app.settings.channels.seo-title') }}&quot;" value="{{ $seo->meta_title ?? old('seo_title') }}"/>
<span class="control-error" v-if="errors.has('seo_title')">@{{ errors.first('seo_title') }}</span>
<div class="control-group" :class="[errors.has('{{$locale}}[seo_title]') ? 'has-error' : '']">
<label for="seo_title" class="required">
{{ __('admin::app.settings.channels.seo-title') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<input v-validate="'required'" class="control" id="seo_title" name="{{$locale}}[seo_title]" data-vv-as="&quot;{{ __('admin::app.settings.channels.seo-title') }}&quot;" value="{{ $seo->meta_title ?? (old($locale)['seo_title'] ?? '') }}"/>
<span class="control-error" v-if="errors.has('{{$locale}}[seo_title]')">@{{ errors.first('{!!$locale!!}[page_title]') }}</span>
</div>
<div class="control-group" :class="[errors.has('seo_description') ? 'has-error' : '']">
<label for="seo_description" class="required">{{ __('admin::app.settings.channels.seo-description') }}</label>
<div class="control-group" :class="[errors.has('{{$locale}}[seo_description]') ? 'has-error' : '']">
<label for="seo_description" class="required">
{{ __('admin::app.settings.channels.seo-description') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<textarea v-validate="'required'" class="control" id="seo_description" name="seo_description" data-vv-as="&quot;{{ __('admin::app.settings.channels.seo-description') }}&quot;">{{ $seo->meta_description ?? old('seo_description') }}</textarea>
<textarea v-validate="'required'" class="control" id="seo_description" name="{{$locale}}[seo_description]" data-vv-as="&quot;{{ __('admin::app.settings.channels.seo-description') }}&quot;">{{ $seo->meta_description ?? (old($locale)['seo_description'] ?? '') }}</textarea>
<span class="control-error" v-if="errors.has('seo_description')">@{{ errors.first('seo_description') }}</span>
<span class="control-error" v-if="errors.has('{{$locale}}[seo_description]')">@{{ errors.first('{!!$locale!!}[page_title]') }}</span>
</div>
<div class="control-group" :class="[errors.has('seo_keywords') ? 'has-error' : '']">
<label for="seo_keywords" class="required">{{ __('admin::app.settings.channels.seo-keywords') }}</label>
<div class="control-group" :class="[errors.has('{{$locale}}[seo_keywords]') ? 'has-error' : '']">
<label for="seo_keywords" class="required">
{{ __('admin::app.settings.channels.seo-keywords') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<textarea v-validate="'required'" class="control" id="seo_keywords" name="seo_keywords" data-vv-as="&quot;{{ __('admin::app.settings.channels.seo-keywords') }}&quot;">{{ $seo->meta_keywords ?? old('seo_keywords') }}</textarea>
<textarea v-validate="'required'" class="control" id="seo_keywords" name="{{$locale}}[seo_keywords]" data-vv-as="&quot;{{ __('admin::app.settings.channels.seo-keywords') }}&quot;">{{ $seo->meta_keywords ?? (old($locale)['seo_keywords'] ?? '') }}</textarea>
<span class="control-error" v-if="errors.has('seo_keywords')">@{{ errors.first('seo_keywords') }}</span>
<span class="control-error" v-if="errors.has('{{$locale}}[seo_keywords]')">@{{ errors.first('{!!$locale!!}[page_title]') }}</span>
</div>
</div>
</accordian>
{{-- maintenance mode --}}
<accordian title="{{ __('admin::app.settings.channels.maintenance-mode') }}" :active="true">
<div slot="body">
<div class="control-group">
<label for="maintenance-mode-status">{{ __('admin::app.status') }}</label>
<label class="switch">
<input type="hidden" name="is_maintenance_on" value="0" />
<input type="checkbox" id="maintenance-mode-status" name="is_maintenance_on" value="1" {{ $channel->is_maintenance_on ? 'checked' : '' }}>
<span class="slider round"></span>
</label>
</div>
<div class="control-group">
<label for="maintenance-mode-text">
{{ __('admin::app.settings.channels.maintenance-mode-text') }}
<span class="locale">[{{ $locale }}]</span>
</label>
<input class="control" id="maintenance-mode-text" name="{{$locale}}[maintenance_mode_text]" value="{{ old('maintenance_mode_text') ?? ($channel->translate($locale)['maintenance_mode_text'] ?? '') }}"/>
</div>
<div class="control-group">
<label for="allowed-ips">{{ __('admin::app.settings.channels.allowed-ips') }}</label>
<input class="control" id="allowed-ips" name="allowed_ips" value="{{ old('allowed_ips') ?: $channel->allowed_ips }}"/>
</div>
</div>
</accordian>

View File

@ -25,26 +25,26 @@ class AttributeGroupTableSeeder extends Seeder
'is_user_defined' => '0',
'attribute_family_id' => '1',
], [
'id' => '2',
'name' => 'Description',
'id' => '2',
'name' => 'Description',
'position' => '2',
'is_user_defined' => '0',
'attribute_family_id' => '1',
], [
'id' => '3',
'id' => '3',
'name' => 'Meta Description',
'position' => '3',
'is_user_defined' => '0',
'attribute_family_id' => '1',
], [
'id' => '4',
'name' => 'Price',
'id' => '4',
'name' => 'Price',
'position' => '4',
'is_user_defined' => '0',
'attribute_family_id' => '1',
], [
'id' => '5',
'name' => 'Shipping',
'id' => '5',
'name' => 'Shipping',
'position' => '5',
'is_user_defined' => '0',
'attribute_family_id' => '1'
@ -59,31 +59,31 @@ class AttributeGroupTableSeeder extends Seeder
], [
'attribute_id' => '2',
'attribute_group_id' => '1',
'position' => '2',
'position' => '3',
], [
'attribute_id' => '3',
'attribute_group_id' => '1',
'position' => '3',
'position' => '4',
], [
'attribute_id' => '4',
'attribute_group_id' => '1',
'position' => '4',
'position' => '5',
], [
'attribute_id' => '5',
'attribute_group_id' => '1',
'position' => '5',
'position' => '6',
], [
'attribute_id' => '6',
'attribute_group_id' => '1',
'position' => '6',
'position' => '7',
], [
'attribute_id' => '7',
'attribute_group_id' => '1',
'position' => '7',
'position' => '8',
], [
'attribute_id' => '8',
'attribute_group_id' => '1',
'position' => '8',
'position' => '10',
], [
'attribute_id' => '9',
'attribute_group_id' => '2',
@ -143,19 +143,23 @@ class AttributeGroupTableSeeder extends Seeder
], [
'attribute_id' => '23',
'attribute_group_id' => '1',
'position' => '10',
'position' => '11',
], [
'attribute_id' => '24',
'attribute_group_id' => '1',
'position' => '11',
'position' => '12',
], [
'attribute_id' => '25',
'attribute_group_id' => '1',
'position' => '12',
'position' => '13',
], [
'attribute_id' => '26',
'attribute_group_id' => '1',
'position' => '9',
], [
'attribute_id' => '27',
'attribute_group_id' => '1',
'position' => '2',
]
]);

View File

@ -12,7 +12,7 @@ class AttributeTableSeeder extends Seeder
public function run()
{
DB::table('attributes')->delete();
DB::table('attribute_translations')->delete();
$now = Carbon::now();
@ -43,7 +43,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Name',
'type' => 'text',
'validation' => NULL,
'position' => '2',
'position' => '3',
'is_required' => '1',
'is_unique' => '0',
'value_per_locale' => '1',
@ -62,7 +62,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'URL Key',
'type' => 'text',
'validation' => NULL,
'position' => '3',
'position' => '4',
'is_required' => '1',
'is_unique' => '1',
'value_per_locale' => '0',
@ -81,7 +81,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Tax Category',
'type' => 'select',
'validation' => NULL,
'position' => '4',
'position' => '5',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -100,7 +100,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'New',
'type' => 'boolean',
'validation' => NULL,
'position' => '5',
'position' => '6',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -119,7 +119,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Featured',
'type' => 'boolean',
'validation' => NULL,
'position' => '6',
'position' => '7',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -138,7 +138,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Visible Individually',
'type' => 'boolean',
'validation' => NULL,
'position' => '7',
'position' => '9',
'is_required' => '1',
'is_unique' => '0',
'value_per_locale' => '0',
@ -157,7 +157,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Status',
'type' => 'boolean',
'validation' => NULL,
'position' => '8',
'position' => '10',
'is_required' => '1',
'is_unique' => '0',
'value_per_locale' => '0',
@ -176,7 +176,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Short Description',
'type' => 'textarea',
'validation' => NULL,
'position' => '9',
'position' => '11',
'is_required' => '1',
'is_unique' => '0',
'value_per_locale' => '1',
@ -195,7 +195,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Description',
'type' => 'textarea',
'validation' => NULL,
'position' => '10',
'position' => '12',
'is_required' => '1',
'is_unique' => '0',
'value_per_locale' => '1',
@ -214,7 +214,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Price',
'type' => 'price',
'validation' => 'decimal',
'position' => '11',
'position' => '13',
'is_required' => '1',
'is_unique' => '0',
'value_per_locale' => '0',
@ -233,7 +233,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Cost',
'type' => 'price',
'validation' => 'decimal',
'position' => '12',
'position' => '14',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -252,7 +252,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Special Price',
'type' => 'price',
'validation' => 'decimal',
'position' => '13',
'position' => '15',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -271,7 +271,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Special Price From',
'type' => 'date',
'validation' => NULL,
'position' => '14',
'position' => '16',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -290,7 +290,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Special Price To',
'type' => 'date',
'validation' => NULL,
'position' => '15',
'position' => '17',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -309,7 +309,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Meta Title',
'type' => 'textarea',
'validation' => NULL,
'position' => '16',
'position' => '18',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '1',
@ -328,7 +328,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Meta Keywords',
'type' => 'textarea',
'validation' => NULL,
'position' => '17',
'position' => '20',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '1',
@ -347,7 +347,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Meta Description',
'type' => 'textarea',
'validation' => NULL,
'position' => '18',
'position' => '21',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '1',
@ -366,7 +366,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Width',
'type' => 'text',
'validation' => 'decimal',
'position' => '19',
'position' => '22',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -385,7 +385,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Height',
'type' => 'text',
'validation' => 'decimal',
'position' => '20',
'position' => '23',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -404,7 +404,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Depth',
'type' => 'text',
'validation' => 'decimal',
'position' => '21',
'position' => '24',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -423,7 +423,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Weight',
'type' => 'text',
'validation' => 'decimal',
'position' => '22',
'position' => '25',
'is_required' => '1',
'is_unique' => '0',
'value_per_locale' => '0',
@ -442,7 +442,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Color',
'type' => 'select',
'validation' => NULL,
'position' => '23',
'position' => '26',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -461,7 +461,7 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Size',
'type' => 'select',
'validation' => NULL,
'position' => '24',
'position' => '27',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
@ -480,14 +480,14 @@ class AttributeTableSeeder extends Seeder
'admin_name' => 'Brand',
'type' => 'select',
'validation' => NULL,
'position' => '25',
'position' => '28',
'is_required' => '0',
'is_unique' => '0',
'value_per_locale' => '0',
'value_per_channel' => '0',
'is_filterable' => '1',
'is_configurable' => '0',
'is_user_defined' => '0',
'is_user_defined' => '1',
'is_visible_on_front' => '1',
'use_in_flat' => '1',
'created_at' => $now,
@ -512,6 +512,25 @@ class AttributeTableSeeder extends Seeder
'created_at' => $now,
'updated_at' => $now,
'is_comparable' => '0',
], [
'id' => '27',
'code' => 'product_number',
'admin_name' => 'Product Number',
'type' => 'text',
'validation' => NULL,
'position' => '2',
'is_required' => '0',
'is_unique' => '1',
'value_per_locale' => '0',
'value_per_channel' => '0',
'is_filterable' => '0',
'is_configurable' => '0',
'is_user_defined' => '0',
'is_visible_on_front' => '0',
'use_in_flat' => '1',
'created_at' => $now,
'updated_at' => $now,
'is_comparable' => '0',
]
]);
@ -646,6 +665,11 @@ class AttributeTableSeeder extends Seeder
'locale' => 'en',
'name' => 'Allow Guest Checkout',
'attribute_id' => '26',
], [
'id' => '27',
'locale' => 'en',
'name' => 'Product Number',
'attribute_id' => '27',
]
]);
}

View File

@ -2,9 +2,9 @@
namespace Webkul\Attribute\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\Attribute\Models\Attribute::class,

View File

@ -0,0 +1,19 @@
<?php
namespace Webkul\Attribute\Repositories;
use Webkul\Core\Eloquent\Repository;
class AttributeOptionTranslationRepository extends Repository
{
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\Attribute\Contracts\AttributeOptionTranslation';
}
}

View File

@ -2,9 +2,9 @@
namespace Webkul\BookingProduct\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\BookingProduct\Models\BookingProduct::class,

View File

@ -55,16 +55,20 @@
</span>
</div>
<div class="control-group">
<div class="control-group" :class="[errors.has(controlName + '[special_price]') ? 'has-error' : '']">
<label class="ticket-label">{{ __('bookingproduct::app.admin.catalog.products.special-price') }}</label>
<input type="text" :name="controlName + '[special_price]'" v-model="ticketItem.special_price" class="control">
<input type="text" v-validate="{decimal: true, min_value:0, ...(ticketItem.price ? {max_value: ticketItem.price} : {})}" :name="controlName + '[special_price]'" v-model="ticketItem.special_price" class="control" data-vv-as="&quot;{{ __('bookingproduct::app.admin.catalog.products.price') }}&quot;">
<span class="control-error" v-if="errors.has(controlName + '[special_price]')">
@{{ errors.first(controlName + '[special_price]') }}
</span>
</div>
</td>
<td>
<div class="control-group" :class="[errors.has(controlName + '[price]') ? 'has-error' : '']">
<label class="ticket-label">{{ __('bookingproduct::app.admin.catalog.products.price') }}</label>
<input type="text" v-validate="'required'" :name="controlName + '[price]'" v-model="ticketItem.price" class="control" data-vv-as="&quot;{{ __('bookingproduct::app.admin.catalog.products.price') }}&quot;">
<input type="text" v-validate="'required|decimal|min_value:0'" :name="controlName + '[price]'" v-model="ticketItem.price" class="control" data-vv-as="&quot;{{ __('bookingproduct::app.admin.catalog.products.price') }}&quot;">
<span class="control-error" v-if="errors.has(controlName + '[price]')">
@{{ errors.first(controlName + '[price]') }}

View File

@ -8,7 +8,7 @@
<div class="control-group-container">
<div class="form-group date" :class="[errors.has('booking[date]') ? 'has-error' : '']">
<date @onChange="dateSelected($event)">
<date @onChange="dateSelected($event)" :minDate="'{{$bookingProduct->available_from}}'" :maxDate="'{{$bookingProduct->available_to}}'">
<input type="text" v-validate="'required'" name="booking[date]" class="form-style" data-vv-as="&quot;{{ __('bookingproduct::app.shop.products.date') }}&quot;"/>
</date>
@ -24,7 +24,7 @@
</div>
</div>
</div>
</script>
<script>
@ -54,6 +54,6 @@
}
}
});
</script>
@endpush
@endpush

View File

@ -12,6 +12,7 @@ use Webkul\Product\Datatypes\CartItemValidationResult;
use Webkul\Product\Helpers\ProductImage;
use Webkul\Product\Repositories\ProductAttributeValueRepository;
use Webkul\Product\Repositories\ProductImageRepository;
use Webkul\Product\Repositories\ProductVideoRepository;
use Webkul\Product\Repositories\ProductInventoryRepository;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Product\Type\Virtual;
@ -44,6 +45,7 @@ class Booking extends Virtual
'admin::catalog.products.accordians.channels',
'bookingproduct::admin.catalog.products.accordians.booking',
'admin::catalog.products.accordians.product-links',
'admin::catalog.products.accordians.videos',
];
/**
@ -54,9 +56,10 @@ class Booking extends Virtual
* @param \Webkul\Product\Repositories\ProductAttributeValueRepository $attributeValueRepository
* @param \Webkul\Product\Repositories\ProductInventoryRepository $productInventoryRepository
* @param \Webkul\Product\Repositories\ProductImageRepository $productImageRepository
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
* @param \Webkul\BookingProduct\Repositories\BookingProductRepository $bookingProductRepository
* @param \Webkul\BookingProduct\Helpers\BookingHelper $bookingHelper
* @param \Webkul\BookingProduct\Helpers\BookingHelper $bookingHelper
* @param \Webkul\Product\Repositories\ProductVideoRepository $productVideoRepository
* @return void
*/
public function __construct(
@ -67,7 +70,8 @@ class Booking extends Virtual
ProductImageRepository $productImageRepository,
ProductImage $productImageHelper,
BookingProductRepository $bookingProductRepository,
BookingHelper $bookingHelper
BookingHelper $bookingHelper,
ProductVideoRepository $productVideoRepository
)
{
parent::__construct(
@ -76,7 +80,8 @@ class Booking extends Virtual
$attributeValueRepository,
$productInventoryRepository,
$productImageRepository,
$productImageHelper
$productImageHelper,
$productVideoRepository
);
$this->bookingProductRepository = $bookingProductRepository;
@ -238,6 +243,7 @@ class Booking extends Virtual
}
if (isset($options1['booking'], $options2['booking'])
&& isset($options1['booking']['ticket_id'], $options2['booking']['ticket_id'])
&& $options1['booking']['ticket_id'] === $options2['booking']['ticket_id']) {
return true;
}

View File

@ -2,9 +2,9 @@
namespace Webkul\CMS\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\CMS\Models\CmsPage::class,

View File

@ -179,7 +179,7 @@ class CartRule
/** @var \Webkul\CartRule\Models\CartRule $rule */
// Laravel relation is used instead of repository for performance
// reasons (cart_rule_coupon-relation is pre-loaded by self::getCartRuleQuery())
$coupon = $rule->cart_rule_coupon->where('code', $cart->coupon_code)->first();
$coupon = $rule->cart_rule_coupon()->where('code', $cart->coupon_code)->first();
if ($coupon && $coupon->code === $cart->coupon_code) {
if ($coupon->usage_limit && $coupon->times_used >= $coupon->usage_limit) {
@ -275,25 +275,19 @@ class CartRule
break;
case 'cart_fixed':
// if ($this->itemTotals[$rule->id]['total_items'] <= 1) {
// $discountAmount = core()->convertPrice($rule->discount_amount);
if ($this->itemTotals[$rule->id]['total_items'] <= 1) {
$discountAmount = core()->convertPrice($rule->discount_amount);
// $baseDiscountAmount = min($item->base_price * $quantity, $rule->discount_amount);
// } else {
// $discountRate = $item->base_price * $quantity / $this->itemTotals[$rule->id]['base_total_price'];
$baseDiscountAmount = min($item->base_price * $quantity, $rule->discount_amount);
} else {
$discountRate = $item->base_price * $quantity / $this->itemTotals[$rule->id]['base_total_price'];
// $maxDiscount = $rule->discount_amount * $discountRate;
$maxDiscount = $rule->discount_amount * $discountRate;
// $discountAmount = core()->convertPrice($maxDiscount);
$discountAmount = core()->convertPrice($maxDiscount);
// $baseDiscountAmount = min($item->base_price * $quantity, $maxDiscount);
// }
$discountAmount = core()->convertPrice($rule->discount_amount);
$baseDiscountAmount = min($item->base_price * $quantity, $rule->discount_amount);
$discountAmount = min($item->price * $quantity, $discountAmount);
$baseDiscountAmount = min($item->base_price * $quantity, $maxDiscount);
}
break;
@ -537,7 +531,7 @@ class CartRule
}
$coupons = $this->cartRuleCouponRepository->where(['code' => $cart->coupon_code])->get();
foreach ($coupons as $coupon) {
if (in_array($coupon->cart_rule_id, explode(',', $cart->applied_cart_rule_ids))) {
return true;

View File

@ -6,6 +6,7 @@ use Exception;
use Illuminate\View\View;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Event;
use Illuminate\Validation\ValidationException;
use Webkul\CartRule\Repositories\CartRuleRepository;
use Webkul\CartRule\Repositories\CartRuleCouponRepository;
@ -113,30 +114,39 @@ class CartRuleController extends Controller
*/
public function store()
{
$this->validate(request(), [
'name' => 'required',
'channels' => 'required|array|min:1',
'customer_groups' => 'required|array|min:1',
'coupon_type' => 'required',
'use_auto_generation' => 'required_if:coupon_type,==,1',
'coupon_code' => 'required_if:use_auto_generation,==,0',
'starts_from' => 'nullable|date',
'ends_till' => 'nullable|date|after_or_equal:starts_from',
'action_type' => 'required',
'discount_amount' => 'required|numeric',
]);
try {
$this->validate(request(), [
'name' => 'required',
'channels' => 'required|array|min:1',
'customer_groups' => 'required|array|min:1',
'coupon_type' => 'required',
'use_auto_generation' => 'required_if:coupon_type,==,1',
'coupon_code' => 'required_if:use_auto_generation,==,0|unique:cart_rule_coupons,code',
'starts_from' => 'nullable|date',
'ends_till' => 'nullable|date|after_or_equal:starts_from',
'action_type' => 'required',
'discount_amount' => 'required|numeric',
]);
$data = request()->all();
$data = request()->all();
Event::dispatch('promotions.cart_rule.create.before');
Event::dispatch('promotions.cart_rule.create.before');
$cartRule = $this->cartRuleRepository->create($data);
$cartRule = $this->cartRuleRepository->create($data);
Event::dispatch('promotions.cart_rule.create.after', $cartRule);
Event::dispatch('promotions.cart_rule.create.after', $cartRule);
session()->flash('success', trans('admin::app.response.create-success', ['name' => 'Cart Rule']));
session()->flash('success', trans('admin::app.response.create-success', ['name' => 'Cart Rule']));
return redirect()->route($this->_config['redirect']);
return redirect()->route($this->_config['redirect']);
} catch (ValidationException $e) {
if ($firstError = collect($e->errors())->first()) {
session()->flash('error', $firstError[0]);
}
}
return redirect()->back();
}
/**
@ -163,30 +173,39 @@ class CartRuleController extends Controller
*/
public function update(Request $request, $id)
{
$this->validate(request(), [
'name' => 'required',
'channels' => 'required|array|min:1',
'customer_groups' => 'required|array|min:1',
'coupon_type' => 'required',
'use_auto_generation' => 'required_if:coupon_type,==,1',
'coupon_code' => 'required_if:use_auto_generation,==,0',
'starts_from' => 'nullable|date',
'ends_till' => 'nullable|date|after_or_equal:starts_from',
'action_type' => 'required',
'discount_amount' => 'required|numeric',
]);
try {
$this->validate(request(), [
'name' => 'required',
'channels' => 'required|array|min:1',
'customer_groups' => 'required|array|min:1',
'coupon_type' => 'required',
'use_auto_generation' => 'required_if:coupon_type,==,1',
'coupon_code' => 'required_if:use_auto_generation,==,0|unique:cart_rule_coupons,code,' . $id,
'starts_from' => 'nullable|date',
'ends_till' => 'nullable|date|after_or_equal:starts_from',
'action_type' => 'required',
'discount_amount' => 'required|numeric',
]);
$cartRule = $this->cartRuleRepository->findOrFail($id);
$cartRule = $this->cartRuleRepository->findOrFail($id);
Event::dispatch('promotions.cart_rule.update.before', $cartRule);
Event::dispatch('promotions.cart_rule.update.before', $cartRule);
$cartRule = $this->cartRuleRepository->update(request()->all(), $id);
$cartRule = $this->cartRuleRepository->update(request()->all(), $id);
Event::dispatch('promotions.cart_rule.update.after', $cartRule);
Event::dispatch('promotions.cart_rule.update.after', $cartRule);
session()->flash('success', trans('admin::app.response.update-success', ['name' => 'Cart Rule']));
session()->flash('success', trans('admin::app.response.update-success', ['name' => 'Cart Rule']));
return redirect()->route($this->_config['redirect']);
return redirect()->route($this->_config['redirect']);
} catch (ValidationException $e) {
if ($firstError = collect($e->errors())->first()) {
session()->flash('error', $firstError[0]);
}
}
return redirect()->back();
}
/**

View File

@ -2,9 +2,9 @@
namespace Webkul\CartRule\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\CartRule\Models\CartRule::class,

View File

@ -2,9 +2,9 @@
namespace Webkul\CatalogRule\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\CatalogRule\Models\CatalogRule::class,

View File

@ -153,7 +153,10 @@ class CategoryController extends Controller
try {
Event::dispatch('catalog.category.delete.before', $id);
$this->categoryRepository->delete($id);
if($category->products->count() > 0) {
$category->products()->delete();
}
$category->delete();
Event::dispatch('catalog.category.delete.after', $id);
@ -175,36 +178,52 @@ class CategoryController extends Controller
*/
public function massDestroy()
{
$suppressFlash = false;
$suppressFlash = true;
$categoryIds = explode(',', request()->input('indexes'));
if (request()->isMethod('delete') || request()->isMethod('post')) {
$indexes = explode(',', request()->input('indexes'));
foreach ($categoryIds as $categoryId) {
$category = $this->categoryRepository->find($categoryId);
foreach ($indexes as $key => $value) {
try {
Event::dispatch('catalog.category.delete.before', $value);
if (isset($category)) {
if(strtolower($category->name) == "root") {
$suppressFlash = false;
session()->flash('warning', trans('admin::app.response.delete-category-root', ['name' => 'Category']));
} else {
try {
$suppressFlash = true;
Event::dispatch('catalog.category.delete.before', $categoryId);
$this->categoryRepository->delete($value);
if($category->products->count() > 0) {
$category->products()->delete();
}
$category->delete();
Event::dispatch('catalog.category.delete.after', $value);
} catch(\Exception $e) {
$suppressFlash = true;
continue;
Event::dispatch('catalog.category.delete.after', $categoryId);
} catch(\Exception $e) {
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Category']));
}
}
}
if (! $suppressFlash) {
session()->flash('success', trans('admin::app.datagrid.mass-ops.delete-success'));
} else {
session()->flash('info', trans('admin::app.datagrid.mass-ops.partial-action', ['resource' => 'Attribute Family']));
}
return redirect()->back();
} else {
session()->flash('error', trans('admin::app.datagrid.mass-ops.method-error'));
return redirect()->back();
}
if (count($categoryIds) != 1 || $suppressFlash == true) {
session()->flash('success', trans('admin::app.datagrid.mass-ops.delete-success', ['resource' => 'Category']));
}
return redirect()->route($this->_config['redirect']);
}
public function categoryProductCount() {
$indexes = explode(",", request()->input('indexes'));
$product_count = 0;
foreach($indexes as $index) {
$category = $this->categoryRepository->find($index);
$product_count += $category->products->count();
}
return response()->json(['product_count' => $product_count], 200);
}
}

View File

@ -9,6 +9,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Webkul\Category\Contracts\Category as CategoryContract;
use Webkul\Attribute\Models\AttributeProxy;
use Webkul\Category\Repositories\CategoryRepository;
use Webkul\Product\Models\ProductProxy;
/**
* Class Category
@ -129,4 +130,12 @@ class Category extends TranslatableModel implements CategoryContract
return $this->findInTree($category->children);
}
/**
* The products that belong to the category.
*/
public function products()
{
return $this->belongsToMany(ProductProxy::modelClass(), 'product_categories');
}
}

View File

@ -2,9 +2,9 @@
namespace Webkul\Category\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\Category\Models\Category::class,

View File

@ -293,7 +293,7 @@ class Cart
public function getItemByProduct($data)
{
$items = $this->getCart()->all_items;
foreach ($items as $item) {
if ($item->product->getTypeInstance()->compareOptions($item->additional, $data['additional'])) {
if (isset($data['additional']['parent_id'])) {
@ -558,14 +558,6 @@ class Cart
$cart->grand_total = $cart->sub_total + $cart->tax_total - $cart->discount_amount;
$cart->base_grand_total = $cart->base_sub_total + $cart->base_tax_total - $cart->base_discount_amount;
if ($shipping = $cart->selected_shipping_rate) {
$cart->grand_total = (float)$cart->grand_total + $shipping->price - $shipping->discount_amount;
$cart->base_grand_total = (float)$cart->base_grand_total + $shipping->base_price - $shipping->base_discount_amount;
$cart->discount_amount += $shipping->discount_amount;
$cart->base_discount_amount += $shipping->base_discount_amount;
}
$cart = $this->finalizeCartTotals($cart);
$quantities = 0;
@ -578,6 +570,8 @@ class Cart
$cart->items_qty = $quantities;
$cart->cart_currency_code = core()->getCurrentCurrencyCode();
$cart->save();
Event::dispatch('checkout.cart.collect.totals.after', $cart);
@ -607,7 +601,7 @@ class Cart
if ($validationResult->isItemInactive()) {
$this->removeItem($item->id);
$isInvalid = true;
session()->flash('info', __('shop::app.checkout.cart.item.inactive'));
@ -698,8 +692,20 @@ class Cart
if ($haveTaxRate) {
$item->tax_percent = $rate->tax_rate;
$item->tax_amount = round(($item->total * $rate->tax_rate) / 100, 4);
$item->base_tax_amount = round(($item->base_total * $rate->tax_rate) / 100, 4);
/* getting shipping rate for tax calculation */
$shippingPrice = $shippingBasePrice = 0;
if ($shipping = $cart->selected_shipping_rate) {
if ($shipping->is_calculate_tax) {
$shippingPrice = $shipping->price - $shipping->discount_amount;
$shippingBasePrice = $shipping->base_price - $shipping->base_discount_amount;
}
}
/* now assigning shipping prices for tax calculation */
$item->tax_amount = round((($item->total + $shippingPrice) * $rate->tax_rate) / 100, 4);
$item->base_tax_amount = round((($item->base_total + $shippingBasePrice) * $rate->tax_rate) / 100, 4);
break;
}
@ -708,7 +714,7 @@ class Cart
$item->save();
}
Event::dispatch('checkout.cart.calculate.items.tax.after', $cart);
}
@ -1275,4 +1281,20 @@ class Cart
}
}
}
/**
* Check minimum order.
*
* @return boolean
*/
public function checkMinimumOrder(): bool
{
$cart = $this->getCart();
if (! $cart) {
return false;
}
return $cart->checkMinimumOrder();
}
}

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddIsTaxCalculationColumnToCartShippingRatesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('cart_shipping_rates', function (Blueprint $table) {
$table->boolean('is_calculate_tax')->default(true);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('cart_shipping_rates', function (Blueprint $table) {
$table->dropColumn('is_calculate_tax');
});
}
}

View File

@ -3,18 +3,20 @@
namespace Webkul\Checkout\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class CustomerAddressForm extends FormRequest
{
protected $rules;
/**
* Rules.
*/
protected $rules = [];
/**
* Determine if the product is authorized to make this request.
*
* @return bool
*/
public function authorize()
public function authorize(): bool
{
return true;
}
@ -24,14 +26,22 @@ class CustomerAddressForm extends FormRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
$customerAddressIds = $this->getCustomerAddressIds();
if (isset($this->get('billing')['address_id'])) {
$this->rules = [
$billingAddressRules = [
'billing.address_id' => ['required'],
];
if (! empty($customerAddressIds)) {
$billingAddressRules['billing.address_id'][] = "in:{$customerAddressIds}";
}
$this->mergeWithRules($billingAddressRules);
} else {
$this->rules = [
$this->mergeWithRules([
'billing.first_name' => ['required'],
'billing.last_name' => ['required'],
'billing.email' => ['required'],
@ -41,16 +51,22 @@ class CustomerAddressForm extends FormRequest
'billing.postcode' => ['required'],
'billing.phone' => ['required'],
'billing.country' => ['required'],
];
]);
}
if (isset($this->get('billing')['use_for_shipping']) && !$this->get('billing')['use_for_shipping']) {
if (isset($this->get('billing')['use_for_shipping']) && ! $this->get('billing')['use_for_shipping']) {
if (isset($this->get('shipping')['address_id'])) {
$this->rules = array_merge($this->rules, [
$shippingAddressRules = [
'shipping.address_id' => ['required'],
]);
];
if (! empty($customerAddressIds)) {
$shippingAddressRules['shipping.address_id'][] = "in:{$customerAddressIds}";
}
$this->mergeWithRules($shippingAddressRules);
} else {
$this->rules = array_merge($this->rules, [
$this->mergeWithRules([
'shipping.first_name' => ['required'],
'shipping.last_name' => ['required'],
'shipping.email' => ['required'],
@ -66,4 +82,28 @@ class CustomerAddressForm extends FormRequest
return $this->rules;
}
/**
* Merge additional rules.
*
* @return string
*/
private function mergeWithRules($additionalRules): void
{
$this->rules = array_merge($this->rules, $additionalRules);
}
/**
* If customer is placing order then fetching all address ids to check with the request ids.
*
* @return string
*/
private function getCustomerAddressIds(): string
{
if ($customer = auth('customer')->user()) {
return $customer->addresses->pluck('id')->join(',');
}
return '';
}
}

View File

@ -3,7 +3,6 @@
namespace Webkul\Checkout\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Product\Models\ProductProxy;
use Webkul\Checkout\Contracts\Cart as CartContract;
class Cart extends Model implements CartContract
@ -169,4 +168,18 @@ class Cart extends Model implements CartContract
return true;
}
/**
* Check minimum order.
*
* @return boolean
*/
public function checkMinimumOrder(): bool
{
$minimumOrderAmount = (float) core()->getConfigData('sales.orderSettings.minimum-order.minimum_order_amount') ?? 0;
$cartBaseSubTotal = (float) $this->base_sub_total;
return $cartBaseSubTotal >= $minimumOrderAmount;
}
}

View File

@ -2,9 +2,9 @@
namespace Webkul\Checkout\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
use Webkul\Core\Providers\CoreModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\Checkout\Models\Cart::class,

View File

@ -12,21 +12,30 @@ return [
*
*/
\Webkul\Admin\Providers\ModuleServiceProvider::class,
\Webkul\API\Providers\ModuleServiceProvider::class,
\Webkul\Attribute\Providers\ModuleServiceProvider::class,
\Webkul\BookingProduct\Providers\ModuleServiceProvider::class,
\Webkul\CartRule\Providers\ModuleServiceProvider::class,
\Webkul\CatalogRule\Providers\ModuleServiceProvider::class,
\Webkul\Category\Providers\ModuleServiceProvider::class,
\Webkul\Checkout\Providers\ModuleServiceProvider::class,
\Webkul\Core\Providers\ModuleServiceProvider::class,
\Webkul\CMS\Providers\ModuleServiceProvider::class,
\Webkul\Customer\Providers\ModuleServiceProvider::class,
\Webkul\Inventory\Providers\ModuleServiceProvider::class,
\Webkul\Payment\Providers\ModuleServiceProvider::class,
\Webkul\Paypal\Providers\ModuleServiceProvider::class,
\Webkul\Product\Providers\ModuleServiceProvider::class,
\Webkul\Rule\Providers\ModuleServiceProvider::class,
\Webkul\Sales\Providers\ModuleServiceProvider::class,
\Webkul\Tax\Providers\ModuleServiceProvider::class,
\Webkul\User\Providers\ModuleServiceProvider::class,
\Webkul\CatalogRule\Providers\ModuleServiceProvider::class,
\Webkul\CartRule\Providers\ModuleServiceProvider::class,
\Webkul\CMS\Providers\ModuleServiceProvider::class,
\Webkul\Velocity\Providers\ModuleServiceProvider::class,
\Webkul\Shipping\Providers\ModuleServiceProvider::class,
\Webkul\Shop\Providers\ModuleServiceProvider::class,
\Webkul\SocialLogin\Providers\ModuleServiceProvider::class,
\Webkul\Tax\Providers\ModuleServiceProvider::class,
\Webkul\Theme\Providers\ModuleServiceProvider::class,
\Webkul\Ui\Providers\ModuleServiceProvider::class,
\Webkul\User\Providers\ModuleServiceProvider::class,
\Webkul\Velocity\Providers\ModuleServiceProvider::class,
]
];

View File

@ -0,0 +1,22 @@
<?php
namespace Webkul\Core\Console\Commands;
use Illuminate\Foundation\Console\DownCommand as OriginalCommand;
use Webkul\Core\Models\Channel;
class DownCommand extends OriginalCommand
{
public function handle()
{
$this->downAllChannel();
parent::handle();
}
protected function downAllChannel()
{
$this->comment('All channels are down.');
return Channel::query()->update(['is_maintenance_on' => 1]);
}
}

View File

@ -38,7 +38,16 @@ class Install extends Command
public function handle()
{
$this->checkForEnvFile();
// cached new changes
$this->warn('Step: Caching new changes...');
$cached = $this->call('config:cache');
$this->info($cached);
// waiting for 2 seconds
$this->warn('Please wait...');
sleep(2);
// running `php artisan migrate`
$this->warn('Step: Migrating all tables into database...');
$migrate = $this->call('migrate:fresh');
@ -64,15 +73,10 @@ class Install extends Command
$result = shell_exec('composer dump-autoload');
$this->info($result);
// cached new changes
$this->warn('Step: Caching new changes...');
$cached = $this->call('config:cache');
$this->info($cached);
$this->info('-----------------------------');
$this->info('Congratulations!');
$this->info('The installation has been finished and you can now use Bagisto.');
$this->info('Go to https://your-site/admin and authenticate with:');
$this->info('Go to '. url(config('app.admin_url')) .' and authenticate with:');
$this->info('Email: admin@example.com');
$this->info('Password: admin123');
$this->info('Cheers!');
@ -107,6 +111,10 @@ class Install extends Command
$input_app_url = $this->ask('Please Enter the APP URL : ');
$this->envUpdate('APP_URL=', $input_app_url ? $input_app_url : $default_app_url );
$default_admin_url = 'admin';
$input_admin_url = $this->ask('Please Enter the Admin URL : ');
$this->envUpdate('APP_ADMIN_URL=', $input_admin_url ?: $default_admin_url);
$locale = $this->choice('Please select the default locale or press enter to continue', ['ar', 'en', 'fa', 'nl', 'pt_BR'], 1);
$this->envUpdate('APP_LOCALE=', $locale);

View File

@ -0,0 +1,22 @@
<?php
namespace Webkul\Core\Console\Commands;
use Illuminate\Foundation\Console\UpCommand as OriginalCommand;
use Webkul\Core\Models\Channel;
class UpCommand extends OriginalCommand
{
public function handle()
{
$this->upAllChannel();
parent::handle();
}
protected function upAllChannel()
{
$this->comment('Activating all channels.');
return Channel::query()->update(['is_maintenance_on' => 0]);
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace Webkul\Core\Contracts;
interface ChannelTranslation
{
}

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddColumnsInChannelsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('channels', function (Blueprint $table) {
$table->boolean('is_maintenance_on')->after('footer_content')->default(0);
$table->text('maintenance_mode_text')->after('is_maintenance_on')->nullable();
$table->text('allowed_ips')->after('maintenance_mode_text')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('channels', function (Blueprint $table) {
$table->dropColumn('is_maintenance_on');
$table->dropColumn('maintenance_mode_text');
$table->dropColumn('allowed_ips');
});
}
}

View File

@ -0,0 +1,42 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateChannelTranslationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('channel_translations', function (Blueprint $table) {
$table->id();
$table->integer('channel_id')->unsigned();
$table->string('locale')->index();
$table->string('name');
$table->text('description')->nullable();
$table->text('home_page_content')->nullable();
$table->text('footer_content')->nullable();
$table->text('maintenance_mode_text')->nullable();
$table->json('home_seo')->nullable();
$table->timestamps();
$table->unique(['channel_id', 'locale']);
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('channel_translations');
}
}

View File

@ -0,0 +1,37 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class RemoveColumnsFromChannelsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('channels', function (Blueprint $table) {
$table->dropColumn('name');
$table->dropColumn('description');
$table->dropColumn('home_page_content');
$table->dropColumn('footer_content');
$table->dropColumn('maintenance_mode_text');
$table->dropColumn('home_seo');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('channels', function (Blueprint $table) {
//
});
}
}

View File

@ -2,8 +2,8 @@
namespace Webkul\Core\Database\Seeders;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class ChannelTableSeeder extends Seeder
{
@ -14,19 +14,175 @@ class ChannelTableSeeder extends Seeder
DB::table('channels')->insert([
'id' => 1,
'code' => 'default',
'name' => 'Default',
'theme' => 'velocity',
'hostname' => config('app.url'),
'root_category_id' => 1,
'home_page_content' => '<p>@include("shop::home.slider") @include("shop::home.featured-products") @include("shop::home.new-products")</p>
<div class="banner-container">
<div class="left-banner"><img data-src="themes/default/assets/images/1.webp" class="lazyload" alt="test" width="720" height="720" /></div>
<div class="right-banner"><img data-src="themes/default/assets/images/2.webp" class="lazyload" alt="test" width="460" height="330" /> <img data-src="themes/default/assets/images/3.webp" class="lazyload" alt="test" width="460" height="330" /></div>
</div>',
'footer_content' => '<div class="list-container"><span class="list-heading">Quick Links</span><ul class="list-group"><li><a href="@php echo route(\'shop.cms.page\', \'about-us\') @endphp">About Us</a></li><li><a href="@php echo route(\'shop.cms.page\', \'return-policy\') @endphp">Return Policy</a></li><li><a href="@php echo route(\'shop.cms.page\', \'refund-policy\') @endphp">Refund Policy</a></li><li><a href="@php echo route(\'shop.cms.page\', \'terms-conditions\') @endphp">Terms and conditions</a></li><li><a href="@php echo route(\'shop.cms.page\', \'terms-of-use\') @endphp">Terms of Use</a></li><li><a href="@php echo route(\'shop.cms.page\', \'contact-us\') @endphp">Contact Us</a></li></ul></div><div class="list-container"><span class="list-heading">Connect With Us</span><ul class="list-group"><li><a href="#"><span class="icon icon-facebook"></span>Facebook </a></li><li><a href="#"><span class="icon icon-twitter"></span> Twitter </a></li><li><a href="#"><span class="icon icon-instagram"></span> Instagram </a></li><li><a href="#"> <span class="icon icon-google-plus"></span>Google+ </a></li><li><a href="#"> <span class="icon icon-linkedin"></span>LinkedIn </a></li></ul></div>',
'name' => 'Default',
'default_locale_id' => 1,
'base_currency_id' => 1,
'home_seo' => '{"meta_title": "Demo store", "meta_keywords": "Demo store meta keyword", "meta_description": "Demo store meta description"}',
]);
DB::table('channel_translations')->insert([
[
'id' => 1,
'channel_id' => 1,
'locale' => 'en',
'name' => 'Default',
'home_page_content' => '
<p>@include("shop::home.slider") @include("shop::home.featured-products") @include("shop::home.new-products")</p>
<div class="banner-container">
<div class="left-banner">
<img src='.asset("/themes/default/assets/images/1.webp").' data-src='.asset("/themes/default/assets/images/1.webp").' class="lazyload" alt="test" width="720" height="720" />
</div>
<div class="right-banner">
<img src='. asset("/themes/default/assets/images/2.webp").' data-src='. asset("/themes/default/assets/images/2.webp").' class="lazyload" alt="test" width="460" height="330" />
<img src='.asset("/themes/default/assets/images/3.webp").' data-src='.asset("/themes/default/assets/images/3.webp").' class="lazyload" alt="test" width="460" height="330" />
</div>
</div>
',
'footer_content' => '
<div class="list-container">
<span class="list-heading">Quick Links</span>
<ul class="list-group">
<li><a href="@php echo route(\'shop.cms.page\', \'about-us\') @endphp">About Us</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'return-policy\') @endphp">Return Policy</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'refund-policy\') @endphp">Refund Policy</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'terms-conditions\') @endphp">Terms and conditions</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'terms-of-use\') @endphp">Terms of Use</a></li><li><a href="@php echo route(\'shop.cms.page\', \'contact-us\') @endphp">Contact Us</a></li>
</ul>
</div>
<div class="list-container">
<span class="list-heading">Connect With Us</span>
<ul class="list-group">
<li><a href="#"><span class="icon icon-facebook"></span>Facebook </a></li>
<li><a href="#"><span class="icon icon-twitter"></span> Twitter </a></li>
<li><a href="#"><span class="icon icon-instagram"></span> Instagram </a></li>
<li><a href="#"> <span class="icon icon-google-plus"></span>Google+ </a></li>
<li><a href="#"> <span class="icon icon-linkedin"></span>LinkedIn </a></li>
</ul>
</div>
',
'home_seo' => '{"meta_title": "Demo store", "meta_keywords": "Demo store meta keyword", "meta_description": "Demo store meta description"}',
], [
'id' => 2,
'channel_id' => 1,
'locale' => 'fr',
'name' => 'Default',
'home_page_content' => '
<p>@include("shop::home.slider") @include("shop::home.featured-products") @include("shop::home.new-products")</p>
<div class="banner-container">
<div class="left-banner">
<img src='.asset("/themes/default/assets/images/1.webp").' data-src='.asset("/themes/default/assets/images/1.webp").' class="lazyload" alt="test" width="720" height="720" />
</div>
<div class="right-banner">
<img src='. asset("/themes/default/assets/images/2.webp").' data-src='. asset("/themes/default/assets/images/2.webp").' class="lazyload" alt="test" width="460" height="330" />
<img src='.asset("/themes/default/assets/images/3.webp").' data-src='.asset("/themes/default/assets/images/3.webp").' class="lazyload" alt="test" width="460" height="330" />
</div>
</div>
',
'footer_content' => '
<div class="list-container">
<span class="list-heading">Quick Links</span>
<ul class="list-group">
<li><a href="@php echo route(\'shop.cms.page\', \'about-us\') @endphp">About Us</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'return-policy\') @endphp">Return Policy</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'refund-policy\') @endphp">Refund Policy</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'terms-conditions\') @endphp">Terms and conditions</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'terms-of-use\') @endphp">Terms of Use</a></li><li><a href="@php echo route(\'shop.cms.page\', \'contact-us\') @endphp">Contact Us</a></li>
</ul>
</div>
<div class="list-container">
<span class="list-heading">Connect With Us</span>
<ul class="list-group">
<li><a href="#"><span class="icon icon-facebook"></span>Facebook </a></li>
<li><a href="#"><span class="icon icon-twitter"></span> Twitter </a></li>
<li><a href="#"><span class="icon icon-instagram"></span> Instagram </a></li>
<li><a href="#"> <span class="icon icon-google-plus"></span>Google+ </a></li>
<li><a href="#"> <span class="icon icon-linkedin"></span>LinkedIn </a></li>
</ul>
</div>
',
'home_seo' => '{"meta_title": "Demo store", "meta_keywords": "Demo store meta keyword", "meta_description": "Demo store meta description"}',
], [
'id' => 3,
'channel_id' => 1,
'locale' => 'nl',
'name' => 'Default',
'home_page_content' => '
<p>@include("shop::home.slider") @include("shop::home.featured-products") @include("shop::home.new-products")</p>
<div class="banner-container">
<div class="left-banner">
<img src='.asset("/themes/default/assets/images/1.webp").' data-src='.asset("/themes/default/assets/images/1.webp").' class="lazyload" alt="test" width="720" height="720" />
</div>
<div class="right-banner">
<img src='. asset("/themes/default/assets/images/2.webp").' data-src='. asset("/themes/default/assets/images/2.webp").' class="lazyload" alt="test" width="460" height="330" />
<img src='.asset("/themes/default/assets/images/3.webp").' data-src='.asset("/themes/default/assets/images/3.webp").' class="lazyload" alt="test" width="460" height="330" />
</div>
</div>
',
'footer_content' => '
<div class="list-container">
<span class="list-heading">Quick Links</span>
<ul class="list-group">
<li><a href="@php echo route(\'shop.cms.page\', \'about-us\') @endphp">About Us</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'return-policy\') @endphp">Return Policy</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'refund-policy\') @endphp">Refund Policy</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'terms-conditions\') @endphp">Terms and conditions</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'terms-of-use\') @endphp">Terms of Use</a></li><li><a href="@php echo route(\'shop.cms.page\', \'contact-us\') @endphp">Contact Us</a></li>
</ul>
</div>
<div class="list-container">
<span class="list-heading">Connect With Us</span>
<ul class="list-group">
<li><a href="#"><span class="icon icon-facebook"></span>Facebook </a></li>
<li><a href="#"><span class="icon icon-twitter"></span> Twitter </a></li>
<li><a href="#"><span class="icon icon-instagram"></span> Instagram </a></li>
<li><a href="#"> <span class="icon icon-google-plus"></span>Google+ </a></li>
<li><a href="#"> <span class="icon icon-linkedin"></span>LinkedIn </a></li>
</ul>
</div>
',
'home_seo' => '{"meta_title": "Demo store", "meta_keywords": "Demo store meta keyword", "meta_description": "Demo store meta description"}',
], [
'id' => 4,
'channel_id' => 1,
'locale' => 'tr',
'name' => 'Default',
'home_page_content' => '
<p>@include("shop::home.slider") @include("shop::home.featured-products") @include("shop::home.new-products")</p>
<div class="banner-container">
<div class="left-banner">
<img src='.asset("/themes/default/assets/images/1.webp").' data-src='.asset("/themes/default/assets/images/1.webp").' class="lazyload" alt="test" width="720" height="720" />
</div>
<div class="right-banner">
<img src='. asset("/themes/default/assets/images/2.webp").' data-src='. asset("/themes/default/assets/images/2.webp").' class="lazyload" alt="test" width="460" height="330" />
<img src='.asset("/themes/default/assets/images/3.webp").' data-src='.asset("/themes/default/assets/images/3.webp").' class="lazyload" alt="test" width="460" height="330" />
</div>
</div>
',
'footer_content' => '
<div class="list-container">
<span class="list-heading">Quick Links</span>
<ul class="list-group">
<li><a href="@php echo route(\'shop.cms.page\', \'about-us\') @endphp">About Us</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'return-policy\') @endphp">Return Policy</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'refund-policy\') @endphp">Refund Policy</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'terms-conditions\') @endphp">Terms and conditions</a></li>
<li><a href="@php echo route(\'shop.cms.page\', \'terms-of-use\') @endphp">Terms of Use</a></li><li><a href="@php echo route(\'shop.cms.page\', \'contact-us\') @endphp">Contact Us</a></li>
</ul>
</div>
<div class="list-container">
<span class="list-heading">Connect With Us</span>
<ul class="list-group">
<li><a href="#"><span class="icon icon-facebook"></span>Facebook </a></li>
<li><a href="#"><span class="icon icon-twitter"></span> Twitter </a></li>
<li><a href="#"><span class="icon icon-instagram"></span> Instagram </a></li>
<li><a href="#"> <span class="icon icon-google-plus"></span>Google+ </a></li>
<li><a href="#"> <span class="icon icon-linkedin"></span>LinkedIn </a></li>
</ul>
</div>
',
'home_seo' => '{"meta_title": "Demo store", "meta_keywords": "Demo store meta keyword", "meta_description": "Demo store meta description"}',
]
]);
DB::table('channel_currencies')->insert([
@ -44,4 +200,4 @@ class ChannelTableSeeder extends Seeder
'inventory_source_id' => 1,
]);
}
}
}

View File

@ -8,7 +8,7 @@ use Webkul\Core\Repositories\ChannelRepository;
class ChannelController extends Controller
{
/**
* Contains route related configuration
* Contains route related configuration.
*
* @var array
*/
@ -61,35 +61,40 @@ class ChannelController extends Controller
*/
public function store()
{
$this->validate(request(), [
'code' => ['required', 'unique:channels,code', new \Webkul\Core\Contracts\Validations\Code],
'name' => 'required',
'locales' => 'required|array|min:1',
'default_locale_id' => 'required|in_array:locales.*',
'currencies' => 'required|array|min:1',
'base_currency_id' => 'required|in_array:currencies.*',
'root_category_id' => 'required',
'logo.*' => 'mimes:bmp,jpeg,jpg,png,webp',
'favicon.*' => 'mimes:bmp,jpeg,jpg,png,webp',
'seo_title' => 'required|string',
'seo_description' => 'required|string',
'seo_keywords' => 'required|string',
'hostname' => 'unique:channels,hostname',
$data = $this->validate(request(), [
/* general */
'code' => ['required', 'unique:channels,code', new \Webkul\Core\Contracts\Validations\Code],
'name' => 'required',
'description' => 'nullable',
'inventory_sources' => 'required|array|min:1',
'root_category_id' => 'required',
'hostname' => 'unique:channels,hostname',
/* currencies and locales */
'locales' => 'required|array|min:1',
'default_locale_id' => 'required|in_array:locales.*',
'currencies' => 'required|array|min:1',
'base_currency_id' => 'required|in_array:currencies.*',
/* design */
'theme' => 'nullable',
'home_page_content' => 'nullable',
'footer_content' => 'nullable',
'logo.*' => 'nullable|mimes:bmp,jpeg,jpg,png,webp',
'favicon.*' => 'nullable|mimes:bmp,jpeg,jpg,png,webp',
/* seo */
'seo_title' => 'required|string',
'seo_description' => 'required|string',
'seo_keywords' => 'required|string',
/* maintenance mode */
'is_maintenance_on' => 'boolean',
'maintenance_mode_text' => 'nullable',
'allowed_ips' => 'nullable'
]);
$data = request()->all();
$data['seo']['meta_title'] = $data['seo_title'];
$data['seo']['meta_description'] = $data['seo_description'];
$data['seo']['meta_keywords'] = $data['seo_keywords'];
unset($data['seo_title']);
unset($data['seo_description']);
unset($data['seo_keywords']);
$data['home_seo'] = json_encode($data['seo']);
unset($data['seo']);
$data = $this->setSEOContent($data);
Event::dispatch('core.channel.create.before');
@ -123,31 +128,42 @@ class ChannelController extends Controller
*/
public function update($id)
{
$this->validate(request(), [
'code' => ['required', 'unique:channels,code,' . $id, new \Webkul\Core\Contracts\Validations\Code],
'name' => 'required',
'locales' => 'required|array|min:1',
'inventory_sources' => 'required|array|min:1',
'default_locale_id' => 'required|in_array:locales.*',
'currencies' => 'required|array|min:1',
'base_currency_id' => 'required|in_array:currencies.*',
'root_category_id' => 'required',
'logo.*' => 'mimes:bmp,jpeg,jpg,png,webp',
'favicon.*' => 'mimes:bmp,jpeg,jpg,png,webp',
'hostname' => 'unique:channels,hostname,' . $id,
$locale = request()->get('locale') ?: app()->getLocale();
$data = $this->validate(request(), [
/* general */
'code' => ['required', 'unique:channels,code,' . $id, new \Webkul\Core\Contracts\Validations\Code],
$locale . '.name' => 'required',
$locale . '.description' => 'nullable',
'inventory_sources' => 'required|array|min:1',
'root_category_id' => 'required',
'hostname' => 'unique:channels,hostname,' . $id,
/* currencies and locales */
'locales' => 'required|array|min:1',
'default_locale_id' => 'required|in_array:locales.*',
'currencies' => 'required|array|min:1',
'base_currency_id' => 'required|in_array:currencies.*',
/* design */
'theme' => 'nullable',
$locale . '.home_page_content' => 'nullable',
$locale . '.footer_content' => 'nullable',
'logo.*' => 'nullable|mimes:bmp,jpeg,jpg,png,webp',
'favicon.*' => 'nullable|mimes:bmp,jpeg,jpg,png,webp',
/* seo */
$locale . '.seo_title' => 'nullable',
$locale . '.seo_description' => 'nullable',
$locale . '.seo_keywords' => 'nullable',
/* maintenance mode */
'is_maintenance_on' => 'boolean',
$locale . '.maintenance_mode_text' => 'nullable',
'allowed_ips' => 'nullable'
]);
$data = request()->all();
$data['seo']['meta_title'] = $data['seo_title'];
$data['seo']['meta_description'] = $data['seo_description'];
$data['seo']['meta_keywords'] = $data['seo_keywords'];
unset($data['seo_title']);
unset($data['seo_description']);
unset($data['seo_keywords']);
$data['home_seo'] = json_encode($data['seo']);
$data = $this->setSEOContent($data, $locale);
Event::dispatch('core.channel.update.before', $id);
@ -188,11 +204,55 @@ class ChannelController extends Controller
return response()->json(['message' => true], 200);
} catch(\Exception $e) {
// session()->flash('warning', trans($e->getMessage()));
session()->flash('error', trans('admin::app.response.delete-failed', ['name' => 'Channel']));
}
}
return response()->json(['message' => false], 400);
}
/**
* Set the seo content and return back the updated array.
*
* @param array $data
* @param string $locale
* @return array
*/
private function setSEOContent(array $data, $locale = null)
{
$editedData = $data;
if ($locale) {
$editedData = $data[$locale];
}
$editedData['home_seo']['meta_title'] = $editedData['seo_title'];
$editedData['home_seo']['meta_description'] = $editedData['seo_description'];
$editedData['home_seo']['meta_keywords'] = $editedData['seo_keywords'];
$editedData['home_seo'] = json_encode($editedData['home_seo']);
$editedData = $this->unsetKeys($editedData, ['seo_title', 'seo_description', 'seo_keywords']);
if ($locale) {
$data[$locale] = $editedData;
$editedData = $data;
}
return $editedData;
}
/**
* Unset keys.
*
* @param array $keys
* @return array
*/
private function unsetKeys($data, $keys)
{
foreach ($keys as $key) {
unset($data[$key]);
}
return $data;
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace Webkul\Core\Http\Middleware;
use Closure;
use Illuminate\Routing\Route;
use Illuminate\Contracts\Foundation\Application;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Original;
class CheckForMaintenanceMode extends Original
{
/**
* The application implementation.
*
* @var \Illuminate\Contracts\Foundation\Application
*/
protected $app;
/**
* Current channel.
*
* @var \Webkul\Core\Models\Channel
*/
protected $channel;
/**
* Exclude route names.
*/
protected $excludedNames = [];
/**
* Exclude route uris.
*/
protected $except = [];
/**
* Exclude ips.
*/
protected $excludedIPs = [];
/**
* Constructor.
*
* @param \Illuminate\Contracts\Foundation\Application $app
*/
public function __construct(Application $app)
{
/* application */
$this->app = $app;
/* current channel */
$this->channel = core()->getCurrentChannel();
/* adding exception for admin routes */
$this->except[] = env('APP_ADMIN_URL', 'admin') . '*';
/* adding exception for ips */
$this->excludedIPs = array_map('trim', explode(',', $this->channel->allowed_ips));
}
/**
* Check for the except routes.
*
* @param \Illuminate\Http\Request $request
* @return boolean
*/
protected function shouldPassThrough($request)
{
foreach ($this->except as $except) {
if ($except !== '/') {
$except = trim($except, '/');
}
if ($request->is($except)) {
return true;
}
}
return false;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
*/
public function handle($request, Closure $next)
{
if ($this->app->isDownForMaintenance()) {
$response = $next($request);
if (in_array($request->ip(), $this->excludedIPs)) {
return $response;
}
$route = $request->route();
if ($route instanceof Route) {
if (in_array($route->getName(), $this->excludedNames)) {
return $response;
}
}
if ($this->shouldPassThrough($request))
{
return $response;
}
throw new HttpException(503);
}
return $next($request);
}
}

View File

@ -2,13 +2,13 @@
namespace Webkul\Core\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Webkul\Category\Models\CategoryProxy;
use Webkul\Core\Eloquent\TranslatableModel;
use Webkul\Inventory\Models\InventorySourceProxy;
use Webkul\Core\Contracts\Channel as ChannelContract;
class Channel extends Model implements ChannelContract
class Channel extends TranslatableModel implements ChannelContract
{
protected $fillable = [
'code',
@ -22,6 +22,18 @@ class Channel extends Model implements ChannelContract
'base_currency_id',
'root_category_id',
'home_seo',
'is_maintenance_on',
'maintenance_mode_text',
'allowed_ips'
];
public $translatedAttributes = [
'name',
'description',
'home_page_content',
'footer_content',
'maintenance_mode_text',
'home_seo',
];
/**

View File

@ -0,0 +1,11 @@
<?php
namespace Webkul\Core\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Core\Contracts\ChannelTranslation as ChannelTranslationContract;
class ChannelTranslation extends Model implements ChannelTranslationContract
{
protected $guarded = [];
}

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\Core\Models;
use Konekt\Concord\Proxies\ModelProxy;
class ChannelTranslationProxy extends ModelProxy
{
}

View File

@ -0,0 +1,29 @@
<?php
namespace Webkul\Core\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
class CoreModuleServiceProvider extends BaseModuleServiceProvider
{
public function boot()
{
if ($this->areMigrationsEnabled()) {
$this->registerMigrations();
}
if ($this->areModelsEnabled()) {
$this->registerModels();
$this->registerEnums();
$this->registerRequestTypes();
}
if ($this->areViewsEnabled()) {
$this->registerViews();
}
if ($routes = $this->config('routes', true)) {
$this->registerRoutes($routes);
}
}
}

View File

@ -2,23 +2,25 @@
namespace Webkul\Core\Providers;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\Facades\Event;
use Webkul\Theme\ViewRenderEventManager;
use Webkul\Core\View\Compilers\BladeCompiler;
use Webkul\Core\Console\Commands\BookingCron;
use Webkul\Core\Core;
use Webkul\Core\Exceptions\Handler;
use Webkul\Core\Facades\Core as CoreFacade;
use Webkul\Core\Models\SliderProxy;
use Webkul\Core\Observers\SliderObserver;
use Webkul\Core\Console\Commands\BagistoVersion;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\ServiceProvider;
use Webkul\Theme\ViewRenderEventManager;
use Illuminate\Support\Facades\Validator;
use Webkul\Core\Console\Commands\Install;
use Webkul\Core\Observers\SliderObserver;
use Webkul\Core\Console\Commands\UpCommand;
use Webkul\Core\Facades\Core as CoreFacade;
use Webkul\Core\Console\Commands\BookingCron;
use Webkul\Core\Console\Commands\DownCommand;
use Webkul\Core\View\Compilers\BladeCompiler;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Webkul\Core\Console\Commands\BagistoVersion;
use Webkul\Core\Console\Commands\ExchangeRateUpdate;
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
class CoreServiceProvider extends ServiceProvider
{
@ -65,6 +67,14 @@ class CoreServiceProvider extends ServiceProvider
Event::listen('bagisto.admin.layout.head', static function(ViewRenderEventManager $viewRenderEventManager) {
$viewRenderEventManager->addTemplate('core::blade.tracer.style');
});
$this->app->extend('command.down', function () {
return new DownCommand;
});
$this->app->extend('command.up', function () {
return new UpCommand;
});
}
/**

View File

@ -2,9 +2,7 @@
namespace Webkul\Core\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\Core\Models\Channel::class,

View File

@ -26,7 +26,17 @@ class ChannelRepository extends Repository
*/
public function create(array $data)
{
$channel = $this->model->create($data);
$model = $this->getModel();
foreach (core()->getAllLocales() as $locale) {
foreach ($model->translatedAttributes as $attribute) {
if (isset($data[$attribute])) {
$data[$locale->code][$attribute] = $data[$attribute];
}
}
}
$channel = parent::create($data);
$channel->locales()->sync($data['locales']);
@ -51,7 +61,7 @@ class ChannelRepository extends Repository
{
$channel = $this->find($id);
$channel->update($data);
$channel = parent::update($data, $id, $attribute);
$channel->locales()->sync($data['locales']);

View File

@ -29,7 +29,6 @@
}
.main-container-wrapper .product-card .product-image img {
height: auto;
max-width: 100%;
}
</style>
@ -102,7 +101,7 @@
}
$('.path-hint-tooltip').css('left', left - minus)
$('.path-hint-tooltip').css('top', currentElement.offset().top + 20)
})

Some files were not shown because too many files have changed in this diff Show More