Base sync

This commit is contained in:
Prashant Singh 2019-08-19 16:11:09 +05:30
commit a29409b1a4
195 changed files with 6954 additions and 2177 deletions

View File

@ -41,6 +41,8 @@ STRIPE_LIVE_PUBLISHABLE_KEY=
STRIPE_LIVE_SECRET_KEY=
STRIPE_STATEMENT_DESCRIPTOR=
fixer_api_key=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=

View File

@ -21,7 +21,7 @@
"doctrine/dbal": "^2.9@dev",
"fideloper/proxy": "^4.0",
"flynsarmy/db-blade-compiler": "*",
"guzzlehttp/guzzle": "^6.3@dev",
"guzzlehttp/guzzle": "~6.0",
"intervention/image": "^2.4",
"intervention/imagecache": "^2.3",
"kalnoy/nestedset": "^4.3",
@ -90,6 +90,7 @@
"Webkul\\Tax\\": "packages/Webkul/Tax/src",
"Webkul\\API\\": "packages/Webkul/API",
"Webkul\\Discount\\": "packages/Webkul/Discount/src",
"Webkul\\CMS\\": "packages/Webkul/CMS/src",
"Webkul\\CustomerDocument\\": "packages/Webkul/CustomerDocument",
"Webkul\\BulkAddToCart\\": "packages/Webkul/BulkAddToCart",
"Webkul\\SAASCustomizer\\": "packages/Webkul/SAASCustomizer/src",
@ -108,7 +109,9 @@
},
"extra": {
"laravel": {
"dont-discover": []
"dont-discover": [
"barryvdh/laravel-debugbar"
]
}
},
"scripts": {

View File

@ -245,6 +245,7 @@ return [
Webkul\Tax\Providers\TaxServiceProvider::class,
Webkul\API\Providers\APIServiceProvider::class,
Webkul\Discount\Providers\DiscountServiceProvider::class,
Webkul\CMS\Providers\CMSServiceProvider::class,
Webkul\CustomerDocument\Providers\CustomerDocumentServiceProvider::class,
Webkul\BulkAddToCart\Providers\BulkAddToCartServiceProvider::class,
Webkul\AdminAuthCheck\Providers\AdminAuthCheckServiceProvider::class,

View File

@ -20,6 +20,7 @@ return [
\Webkul\Tax\Providers\ModuleServiceProvider::class,
\Webkul\User\Providers\ModuleServiceProvider::class,
\Webkul\Discount\Providers\ModuleServiceProvider::class,
\Webkul\CMS\Providers\ModuleServiceProvider::class,
\Webkul\StripeConnect\Providers\ModuleServiceProvider::class,
\Webkul\PreOrder\Providers\ModuleServiceProvider::class
]

View File

@ -56,8 +56,8 @@ return [
*/
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
'address' => env('SHOP_MAIL_FROM'),
'name' => env('MAIL_FROM_NAME')
],
/*

View File

@ -29,10 +29,18 @@ return [
'secret' => env('SPARKPOST_SECRET'),
],
'exchange-api' => [
'default' => 'fixer',
'fixer' => [
'paid_account' => false,
'key' => env('fixer_api_key'),
'class' => 'Webkul\Core\Helpers\Exchange\FixerExchange'
]
],
'stripe' => [
'model' => App\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
]
];

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=2bab17ad3ee2b7f905ac",
"/css/admin.css": "/css/admin.css?id=195e1b16939f9c233f32"
"/js/admin.js": "/js/admin.js?id=7f0b8f49bcf11cef838f",
"/css/admin.css": "/css/admin.css?id=96d341f257529071e8e7"
}

View File

@ -42,25 +42,25 @@ return [
'key' => 'catalog.products',
'name' => 'admin::app.layouts.products',
'route' => 'admin.catalog.products.index',
'sort' => 1,
'sort' => 4,
'icon-class' => '',
], [
'key' => 'catalog.categories',
'name' => 'admin::app.layouts.categories',
'route' => 'admin.catalog.categories.index',
'sort' => 2,
'sort' => 3,
'icon-class' => '',
], [
'key' => 'catalog.attributes',
'name' => 'admin::app.layouts.attributes',
'route' => 'admin.catalog.attributes.index',
'sort' => 3,
'sort' => 1,
'icon-class' => '',
], [
'key' => 'catalog.families',
'name' => 'admin::app.layouts.attribute-families',
'route' => 'admin.catalog.families.index',
'sort' => 4,
'sort' => 2,
'icon-class' => '',
], [
'key' => 'customers',
@ -188,5 +188,25 @@ return [
'route' => 'admin.cart-rule.index',
'sort' => 1,
'icon-class' => '',
],
// [
// 'key' => 'promotions.catalog-rule',
// 'name' => 'admin::app.promotion.catalog-rule',
// 'route' => 'admin.catalog-rule.index',
// 'sort' => 1,
// 'icon-class' => '',
// ],
[
'key' => 'cms',
'name' => 'admin::app.layouts.cms',
'route' => 'admin.cms.index',
'sort' => 6,
'icon-class' => 'cms-icon',
], [
'key' => 'cms.pages',
'name' => 'admin::app.cms.pages.pages',
'route' => 'admin.cms.index',
'sort' => 1,
'icon-class' => '',
]
];

View File

@ -8,7 +8,7 @@ return [
], [
'key' => 'catalog.products',
'name' => 'admin::app.admin.system.products',
'sort' => 1,
'sort' => 2
], [
'key' => 'catalog.products.review',
'name' => 'admin::app.admin.system.review',

View File

@ -13,9 +13,9 @@ use DB;
*/
class AttributeDataGrid extends DataGrid
{
protected $index = 'id'; //the column that needs to be treated as index column
protected $index = 'id'; // column that needs to be treated as index column
protected $sortOrder = 'desc'; //asc or desc
protected $sortOrder = 'desc'; // asc or desc
public function prepareQueryBuilder()
{
@ -147,6 +147,7 @@ class AttributeDataGrid extends DataGrid
'type' => 'delete',
'action' => route('admin.catalog.attributes.massdelete'),
'label' => 'Delete',
'index' => 'admin_name',
'method' => 'DELETE'
]);
}

View File

@ -0,0 +1,72 @@
<?php
namespace Webkul\Admin\DataGrids;
use Webkul\Ui\DataGrid\DataGrid;
use DB;
/**
* CMSPagesDataGrid class
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CMSPageDataGrid extends DataGrid
{
protected $index = 'id'; //the column that needs to be treated as index column
protected $sortOrder = 'desc'; //asc or desc
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('cms_pages')->select('id', 'url_key', 'page_title');
$this->setQueryBuilder($queryBuilder);
}
public function addColumns()
{
$this->addColumn([
'index' => 'id',
'label' => trans('admin::app.datagrid.id'),
'type' => 'number',
'searchable' => false,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'url_key',
'label' => trans('admin::app.datagrid.url-key'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'page_title',
'label' => trans('admin::app.cms.pages.page-title'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true
]);
}
public function prepareActions() {
$this->addAction([
'type' => 'Edit',
'method' => 'GET', // use GET request only for redirect purposes
'route' => 'admin.cms.edit',
'icon' => 'icon pencil-lg-icon'
]);
$this->addAction([
'type' => 'Delete',
'method' => 'POST', // use GET request only for redirect purposes
'route' => 'admin.cms.delete',
'icon' => 'icon trash-icon'
]);
}
}

View File

@ -21,7 +21,7 @@ class CatalogRuleDataGrid extends DataGrid
{
$queryBuilder = DB::table('catalog_rules')
->select('id')
->addSelect('id', 'name', 'starts_from', 'ends_till', 'priority', 'status', 'end_other_rules', 'action_type');
->addSelect('id', 'name', 'starts_from', 'ends_till', 'status', 'end_other_rules', 'action_code');
$this->setQueryBuilder($queryBuilder);
}
@ -64,15 +64,6 @@ class CatalogRuleDataGrid extends DataGrid
'filterable' => true
]);
$this->addColumn([
'index' => 'priority',
'label' => trans('admin::app.datagrid.priority'),
'type' => 'number',
'searchable' => false,
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'status',
'label' => trans('admin::app.datagrid.status'),
@ -104,19 +95,12 @@ class CatalogRuleDataGrid extends DataGrid
]);
$this->addColumn([
'index' => 'action_type',
'index' => 'action_code',
'label' => 'Action Type',
'type' => 'string',
'searchable' => false,
'sortable' => true,
'filterable' => true,
'wrapper' => function ($value) {
foreach(config('pricerules.catalog.actions') as $key => $action) {
if ($value->action_type == $key) {
return trans($action);
}
}
}
'filterable' => true
]);
}

View File

@ -28,7 +28,7 @@ class Handler extends ExceptionHandler
*/
public function render($request, Exception $exception)
{
$path = $this->isAdminUri() ? 'admin' : 'shop';
$path = 'admin';
if ($exception instanceof HttpException) {
$statusCode = in_array($exception->getStatusCode(), [401, 403, 404, 503]) ? $exception->getStatusCode() : 500;

View File

@ -17,7 +17,7 @@ use Excel;
class ExportController extends Controller
{
protected $exportableGrids = [
'OrderDataGrid', 'OrderInvoicesDataGrid', 'OrderShipmentsDataGrid', 'CustomerDataGrid', 'TaxRateDataGrid', 'ProductDataGrid'
'OrderDataGrid', 'OrderInvoicesDataGrid', 'OrderShipmentsDataGrid', 'CustomerDataGrid', 'TaxRateDataGrid', 'ProductDataGrid', 'CMSPageDataGrid'
];
/**
@ -37,6 +37,7 @@ class ExportController extends Controller
public function export()
{
$criteria = request()->all();
$format = $criteria['format'];
$gridName = explode('\\', $criteria['gridName']);

View File

@ -445,6 +445,8 @@ Route::group(['middleware' => ['web']], function () {
'view' => 'admin::settings.exchange_rates.edit'
])->name('admin.exchange_rates.edit');
Route::get('/exchange_rates/update-rates/{service}', 'Webkul\Core\Http\Controllers\ExchangeRateController@updateRates')->name('admin.exchange_rates.update-rates');
Route::put('/exchange_rates/edit/{id}', 'Webkul\Core\Http\Controllers\ExchangeRateController@update')->defaults('_config', [
'redirect' => 'admin.exchange_rates.index'
])->name('admin.exchange_rates.update');
@ -625,33 +627,33 @@ Route::group(['middleware' => ['web']], function () {
Route::post('admin/export', 'Webkul\Admin\Http\Controllers\ExportController@export')->name('admin.datagrid.export');
Route::prefix('promotion')->group(function () {
// Route::get('/catalog-rule', 'Webkul\Discount\Http\Controllers\CatalogRuleController@index')->defaults('_config', [
// 'view' => 'admin::promotions.catalog-rule.index'
// ])->name('admin.catalog-rule.index');
Route::get('/catalog-rules', 'Webkul\Discount\Http\Controllers\CatalogRuleController@index')->defaults('_config', [
'view' => 'admin::promotions.catalog-rule.index'
])->name('admin.catalog-rule.index');
// Route::get('/catalog-rule/create', 'Webkul\Discount\Http\Controllers\CatalogRuleController@create')->defaults('_config', [
// 'view' => 'admin::promotions.catalog-rule.create'
// ])->name('admin.catalog-rule.create');
Route::get('/catalog-rules/create', 'Webkul\Discount\Http\Controllers\CatalogRuleController@create')->defaults('_config', [
'view' => 'admin::promotions.catalog-rule.create'
])->name('admin.catalog-rule.create');
// Route::post('/catalog-rule/create', 'Webkul\Discount\Http\Controllers\CatalogRuleController@store')->defaults('_config', [
// 'redirect' => 'admin.catalog-rule.index'
// ])->name('admin.catalog-rule.store');
Route::post('/catalog-rules/create', 'Webkul\Discount\Http\Controllers\CatalogRuleController@store')->defaults('_config', [
'redirect' => 'admin.catalog-rule.index'
])->name('admin.catalog-rule.store');
// Route::get('/catalog-rule/edit/{id}', 'Webkul\Discount\Http\Controllers\CatalogRuleController@edit')->defaults('_config', [
// 'view' => 'admin::promotions.catalog-rule.edit'
// ])->name('admin.catalog-rule.edit');
Route::get('/catalog-rules/edit/{id}', 'Webkul\Discount\Http\Controllers\CatalogRuleController@edit')->defaults('_config', [
'view' => 'admin::promotions.catalog-rule.edit'
])->name('admin.catalog-rule.edit');
// Route::post('/catalog-rule/edit/{id}', 'Webkul\Discount\Http\Controllers\CatalogRuleController@update')->defaults('_config', [
// 'redirect' => 'admin.catalog-rule.index'
// ])->name('admin.catalog-rule.update');
Route::post('/catalog-rules/edit/{id}', 'Webkul\Discount\Http\Controllers\CatalogRuleController@update')->defaults('_config', [
'redirect' => 'admin.catalog-rule.index'
])->name('admin.catalog-rule.update');
// Route::get('/catalog-rule/apply', 'Webkul\Discount\Http\Controllers\CatalogRuleController@applyRules')->defaults('_config', [
// 'view' => 'admin::promotions.catalog-rule.index'
// ])->name('admin.catalog-rule.apply');
Route::get('/catalog-rules/apply', 'Webkul\Discount\Http\Controllers\CatalogRuleController@applyRules')->defaults('_config', [
'view' => 'admin::promotions.catalog-rule.index'
])->name('admin.catalog-rule.apply');
// Route::post('/catalog-rule/delete/{id}', 'Webkul\Discount\Http\Controllers\CatalogRuleController@destroy')->name('admin.catalog-rule.delete');
Route::post('/catalog-rules/delete/{id}', 'Webkul\Discount\Http\Controllers\CatalogRuleController@destroy')->name('admin.catalog-rule.delete');
// Route::post('fetch/options', 'Webkul\Discount\Http\Controllers\CatalogRuleController@fetchAttributeOptions')->name('admin.catalog-rule.options');
Route::post('fetch/options', 'Webkul\Discount\Http\Controllers\CatalogRuleController@fetchAttributeOptions')->name('admin.catalog-rule.options');
Route::get('cart-rules', 'Webkul\Discount\Http\Controllers\CartRuleController@index')->defaults('_config', [
'view' => 'admin::promotions.cart-rule.index'
@ -675,6 +677,34 @@ Route::group(['middleware' => ['web']], function () {
Route::post('cart-rules/delete/{id}', 'Webkul\Discount\Http\Controllers\CartRuleController@destroy')->name('admin.cart-rule.delete');
});
Route::prefix('cms')->group(function () {
Route::get('/', 'Webkul\CMS\Http\Controllers\Admin\PageController@index')->defaults('_config', [
'view' => 'admin::cms.index'
])->name('admin.cms.index');
Route::get('preview/{url_key}', 'Webkul\CMS\Http\Controllers\Admin\PageController@preview')->name('admin.cms.preview');
Route::get('create', 'Webkul\CMS\Http\Controllers\Admin\PageController@create')->defaults('_config', [
'view' => 'admin::cms.create'
])->name('admin.cms.create');
Route::post('create', 'Webkul\CMS\Http\Controllers\Admin\PageController@store')->defaults('_config', [
'redirect' => 'admin.cms.index'
])->name('admin.cms.store');
Route::get('update/{id}', 'Webkul\CMS\Http\Controllers\Admin\PageController@edit')->defaults('_config', [
'view' => 'admin::cms.edit'
])->name('admin.cms.edit');
Route::post('update/{id}', 'Webkul\CMS\Http\Controllers\Admin\PageController@update')->defaults('_config', [
'redirect' => 'admin.cms.index'
])->name('admin.cms.update');
Route::post('/delete/{id}', 'Webkul\CMS\Http\Controllers\Admin\PageController@delete')->defaults('_config', [
'redirect' => 'admin.cms.index'
])->name('admin.cms.delete');
});
});
});
});

View File

@ -16,7 +16,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
class NewInvoiceNotification extends Mailable
{
use Queueable, SerializesModels;
/**
* The invoice instance.
*
@ -45,6 +45,7 @@ class NewInvoiceNotification extends Mailable
$order = $this->invoice->order;
return $this->to($order->customer_email, $order->customer_full_name)
->from(env('SHOP_MAIL_FROM'))
->subject(trans('shop::app.mail.invoice.subject', ['order_id' => $order->id]))
->view('shop::emails.sales.new-invoice');
}

View File

@ -42,6 +42,7 @@ class NewOrderNotification extends Mailable
public function build()
{
return $this->to($this->order->customer_email, $this->order->customer_full_name)
->from(env('SHOP_MAIL_FROM'))
->subject(trans('shop::app.mail.order.subject'))
->view('shop::emails.sales.new-order');
}

View File

@ -45,6 +45,7 @@ class NewShipmentNotification extends Mailable
$order = $this->shipment->order;
return $this->to($order->customer_email, $order->customer_full_name)
->from(env('SHOP_MAIL_FROM'))
->subject(trans('shop::app.mail.shipment.subject', ['order_id' => $order->id]))
->view('shop::emails.sales.new-shipment');
}

View File

@ -21,7 +21,5 @@ class EventServiceProvider extends ServiceProvider
Event::listen('sales.shipment.save.after', 'Webkul\Admin\Listeners\Order@sendNewShipmentMail');
Event::listen('checkout.order.save.after', 'Webkul\Admin\Listeners\Order@updateProductInventory');
Event::listen('products.datagrid.sync', 'Webkul\Admin\Listeners\Product@sync');
}
}

View File

@ -8,76 +8,6 @@ Vue.prototype.$http = axios
window.eventBus = new Vue();
window.addEventListener('DOMContentLoaded', function() {
moveDown = 60;
moveUp = -60;
count = 0;
countKeyUp = 0;
pageDown = 60;
pageUp = -60;
scroll = 0;
listLastElement = $('.menubar li:last-child').offset();
if (listLastElement) {
lastElementOfNavBar = listLastElement.top;
}
navbarTop = $('.navbar-left').css("top");
menuTopValue = $('.navbar-left').css('top');
menubarTopValue = menuTopValue;
documentHeight = $(document).height();
menubarHeight = $('ul.menubar').height();
navbarHeight = $('.navbar-left').height();
windowHeight = $(window).height();
contentHeight = $('.content').height();
innerSectionHeight = $('.inner-section').height();
gridHeight = $('.grid-container').height();
pageContentHeight = $('.page-content').height();
if (menubarHeight <= windowHeight) {
differenceInHeight = windowHeight - menubarHeight;
} else {
differenceInHeight = menubarHeight - windowHeight;
}
if (menubarHeight > windowHeight) {
document.addEventListener("keydown", function(event) {
if ((event.keyCode == 38) && count <= 0) {
count = count + moveDown;
$('.navbar-left').css("top", count + "px");
} else if ((event.keyCode == 40) && count >= -differenceInHeight) {
count = count + moveUp;
$('.navbar-left').css("top", count + "px");
} else if ((event.keyCode == 33) && countKeyUp <= 0) {
countKeyUp = countKeyUp + pageDown;
$('.navbar-left').css("top", countKeyUp + "px");
} else if ((event.keyCode == 34) && countKeyUp >= -differenceInHeight) {
countKeyUp = countKeyUp + pageUp;
$('.navbar-left').css("top", countKeyUp + "px");
} else {
$('.navbar-left').css("position", "fixed");
}
});
$("body").css({minHeight: $(".menubar").outerHeight() + 100 + "px"});
window.addEventListener('scroll', function() {
documentScrollWhenScrolled = $(document).scrollTop();
if (documentScrollWhenScrolled <= differenceInHeight + 200) {
$('.navbar-left').css('top', -documentScrollWhenScrolled + 60 + 'px');
scrollTopValueWhenNavBarFixed = $(document).scrollTop();
}
});
}
});
$(document).ready(function () {
Vue.config.ignoredElements = [
'option-wrapper',

View File

@ -269,7 +269,7 @@ body {
.control-container {
display: flex;
flex-direction: row;
align-items: center;
align-items: flex-start;
width: 750px;
.control {
@ -881,6 +881,19 @@ body {
}
// css for rtl end here
// For fixed and and save button
.fixed-action {
position: fixed;
top: 108px;
right: 32px;
}
.fixed-action-slight {
position: fixed;
top: 94px;
right: 32px;
}
.pagination {
margin-top: 30px;
}

View File

@ -41,7 +41,8 @@ return [
'tax-categories' => 'Tax Categories',
'tax-rates' => 'Tax Rates',
'promotion' => 'Promotions',
'discount' => 'Discount'
'discount' => 'Discount',
'cms' => 'CMS'
],
'acl' => [
@ -127,6 +128,8 @@ return [
'email' => 'Email',
'group' => 'Group',
'title' => 'Title',
'layout' => 'Layout',
'url-key' => 'URL Key',
'comment' => 'Comment',
'product-name' => 'Product',
'currency-name' => 'Currency Name',
@ -603,6 +606,8 @@ return [
'source_currency' => 'Source Currency',
'target_currency' => 'Target Currency',
'rate' => 'Rate',
'exchange-class-not-found' => ':service exchange rate class not found',
'update-rates' => 'Update rates using :service',
'create-success' => 'Exchange Rate created successfully.',
'update-success' => 'Exchange Rate updated successfully.',
'delete-success' => 'Exchange Rate deleted successfully.',
@ -810,6 +815,11 @@ return [
],
'promotion' => [
'information' => 'Information',
'conditions' => 'Conditions',
'actions' => 'Actions',
'coupons' => 'Coupons',
'zero-unlimited' => 'Zero denotes unlimited usage here',
'catalog-rule' => 'Catalog Rules',
'cart-rule' => 'Cart Rules',
'add-catalog-rule' => 'Add Catalog Rule',
@ -821,10 +831,31 @@ return [
'save-btn-title' => 'Create',
'edit-btn-title' => 'Edit',
'save' => 'Save',
'select-attr' => 'Select Attribute',
'select-attr-fam' => 'Select Attribute Family',
'select-cart-attr' => 'Select Cart Attribute',
'select-products' => 'How to choose products ?',
'select-category' => 'Select by Categories',
'select-attribute' => 'Select by Attributes',
'cannot-activate-catalog-rule' => 'Cannot activate catalog rule',
'catalog-rule-already-activated' => 'Catalog rule is already activated',
'catalog-rule-activated' => 'Catalog rule is activated',
'select-attribute' => 'Select :attribute',
'enter-attribute' => 'Enter :attribute',
'add-condition' => 'Add Condition',
'cart-properties' => 'Cart Properties',
'yes' => 'Yes',
'no' => 'No',
'note' => 'Note',
'rule-name' => 'Enter Rule Name',
'rule-desc' => 'Enter Rule Description',
'convert-x-note' => 'If this section is left empty, then rule will get applied to all the products in the cart.',
'add-attr-condition' => 'Add Attribute Condition',
'general-info' => [
'sku-like' => 'SKU Like',
'on-shipping' => 'If applied on shipping',
'discount' => 'Discount',
'shipping-apply-info' => 'It signifies how rule behaves when it is used for shipping',
'general-info' => 'General Info',
'options' => 'Options',
'name' => 'Rule Name',
'description' => 'Description',
'starts-from' => 'Start',
@ -859,7 +890,12 @@ return [
'is-guest' => 'For Guests',
'disc_qty' => 'Max. Quantity Allowed To Be Discounted',
'test-mode' => 'Choose how to test conditions',
'labels' => 'Labels'
'labels' => 'Labels',
'prefix' => 'Prefix',
'suffix' => 'Suffix',
'code' => 'Code',
'global-label' => 'Global Label',
'label' => 'Label'
],
'status' => [
@ -944,6 +980,35 @@ return [
'illegal-format' => 'Error! This type of format is either not supported or its illegal format'
],
'cms' => [
'pages' => [
'pages' => 'Page',
'title' => 'pages',
'add-title' => 'Add Page',
'content' => 'Content',
'url-key' => 'URL Key',
'create-btn-title' => 'Add Page',
'edit-title' => 'Edit Page',
'edit-btn-title' => 'Save Page',
'create-success' => 'Page created successfully',
'create-failure' => 'Page cannot be created',
'update-success' => 'Page updated successfully',
'update-failure' => 'Page cannot be updated',
'page-title' => 'Page Title',
'layout' => 'Layout',
'meta_keywords' => 'Meta Keywords',
'meta_description' => 'Meta Description',
'meta_title' => 'Meta Title',
'delete-success' => 'CMS page deleted successfully',
'delete-failure' => 'CMS page cannot be deleted',
'preview' => 'Preview',
'one-col' => '<div class="mt-10">Use class: <b>"static-container one-column"</b> for one column layout.</div>',
'two-col' => '<div class="mt-10">Use class: <b>"static-container two-column"</b> for two column layout.</div>',
'three-col' => '<div class="mt-10">Use class: <b>"static-container three-column"</b> for three column layout.</div>',
'helper-classes' => 'Helper Classes'
]
],
'response' => [
'being-used' => 'This resource :name is getting used in :source',
'cannot-delete-default' => 'Cannot delete the default channel',

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,8 @@
</h1>
</div>
<div class="page-action">
<button type="submit" class="btn btn-lg btn-primary">
<div class="page-action fixed-action">
<button type="submi t" class="btn btn-lg btn-primary">
{{ __('admin::app.account.save-btn-title') }}
</button>
</div>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.attributes.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.attributes.save-btn-title') }}
</button>

View File

@ -18,7 +18,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.categories.save-btn-title') }}
</button>

View File

@ -18,7 +18,7 @@
{{ __('admin::app.catalog.categories.edit-title') }}
</h1>
<div class="control-group">
<div class="control-group fixed-action">
<select class="control" id="locale-switcher" onChange="window.location.href = this.value">
@foreach (core()->getAllLocales() as $localeModel)

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.families.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.families.save-btn-title') }}
</button>

View File

@ -32,7 +32,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.products.save-btn-title') }}
</button>

View File

@ -47,7 +47,7 @@
</div>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.catalog.products.save-btn-title') }}
</button>

View File

@ -0,0 +1,149 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.cms.pages.add-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" action="{{ route('admin.cms.store') }}" @submit.prevent="onSubmit">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
{{ __('admin::app.cms.pages.pages') }}
</h1>
<div class="control-group">
<select class="control" id="channel-switcher" name="channel">
@php
$locale = request()->get('locale') ?: app()->getLocale();
$channel = request()->get('channel') ?: core()->getDefaultChannelCode();
@endphp
@foreach (core()->getAllChannels() as $channelModel)
<option value="{{ $channelModel->code }}" {{ ($channelModel->code) == $channel ? 'selected' : '' }}>
{{ $channelModel->name }}
</option>
@endforeach
</select>
</div>
<div class="control-group">
<select class="control" id="locale-switcher" name="locale">
@foreach (core()->getAllLocales() as $localeModel)
<option value="{{ $localeModel->code }}" {{ ($localeModel->code) == $locale ? 'selected' : '' }}>
{{ $localeModel->name }}
</option>
@endforeach
</select>
</div>
</div>
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.cms.pages.create-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
<div class="control-group" :class="[errors.has('url_key') ? 'has-error' : '']">
<label for="url-key" class="required">{{ __('admin::app.cms.pages.url-key') }}</label>
<input type="text" class="control" name="url_key" v-validate="'required'" value="{{ old('url-key') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.url-key') }}&quot;" v-slugify>
<span class="control-error" v-if="errors.has('url_key')">@{{ errors.first('url_key') }}</span>
</div>
<div class="control-group" :class="[errors.has('html_content') ? 'has-error' : '']">
<label for="html_content" class="required">{{ __('admin::app.cms.pages.content') }}</label>
<textarea type="text" class="control" id="content" name="html_content" v-validate="'required'" value="{{ old('html_content') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.content') }}&quot;"></textarea>
{!! __('admin::app.cms.pages.one-col') !!}
{!! __('admin::app.cms.pages.two-col') !!}
{!! __('admin::app.cms.pages.three-col') !!}
<div class="mt-10 mb-10">
<a target="_blank" href="{{ route('ui.helper.classes') }}" class="btn btn-sm btn-primary">
{{ __('admin::app.cms.pages.helper-classes') }}
</a>
</div>
<span class="control-error" v-if="errors.has('html_content')">@{{ errors.first('html_content') }}</span>
</div>
<div class="control-group" :class="[errors.has('page_title') ? 'has-error' : '']">
<label for="page_title" class="required">{{ __('admin::app.cms.pages.page-title') }}</label>
<input type="text" class="control" name="page_title" v-validate="'required'" value="{{ old('page_title') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.page-title') }}&quot;">
<span class="control-error" v-if="errors.has('page_title')">@{{ errors.first('page_title') }}</span>
</div>
<div class="control-group" :class="[errors.has('meta_title') ? 'has-error' : '']">
<label for="meta_title" class="required">{{ __('admin::app.cms.pages.meta_title') }}</label>
<input type="text" class="control" name="meta_title" v-validate="'required'" value="{{ old('meta_title') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.meta_title') }}&quot;">
<span class="control-error" v-if="errors.has('meta_title')">@{{ errors.first('meta_title') }}</span>
</div>
<div class="control-group" :class="[errors.has('meta_keywords') ? 'has-error' : '']">
<label for="meta_keywords" class="required">{{ __('admin::app.cms.pages.meta_keywords') }}</label>
<textarea type="text" class="control" name="meta_keywords" v-validate="'required'" value="{{ old('meta_keywords') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.meta_keywords') }}&quot;"></textarea>
<span class="control-error" v-if="errors.has('meta_keywords')">@{{ errors.first('meta_keywords') }}</span>
</div>
<div class="control-group" :class="[errors.has('meta_description') ? 'has-error' : '']">
<label for="meta_description">{{ __('admin::app.cms.pages.meta_description') }}</label>
<textarea type="text" class="control" name="meta_description" value="{{ old('meta_description') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.meta_description') }}&quot;"></textarea>
<span class="control-error" v-if="errors.has('meta_description')">@{{ errors.first('meta_description') }}</span>
</div>
</div>
</div>
</form>
</div>
{{-- <modal id="showHelpers" :is-open="modalIds.showHelpers">
<h3 slot="header">{{ __('admin::app.cms.pages.helper-classes') }}</h3>
<div slot="body">
@include('ui::partials.helper-classes')
</div>
</modal> --}}
@stop
@push('scripts')
<script src="{{ asset('vendor/webkul/admin/assets/js/tinyMCE/tinymce.min.js') }}"></script>
<script>
$(document).ready(function () {
tinymce.init({
selector: 'textarea#content',
height: 200,
width: "70%",
plugins: 'image imagetools media wordcount save fullscreen code',
toolbar1: 'formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat | code',
image_advtab: true,
valid_elements : '*[*]'
});
});
</script>
@endpush

View File

@ -0,0 +1,162 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.cms.pages.edit-title') }}
@stop
@section('content')
<div class="content">
<form method="POST" id="page-form" action="{{ route('admin.cms.edit', $page->id) }}" @submit.prevent="onSubmit">
<div class="page-header">
<div class="page-title">
<h1>
<i class="icon angle-left-icon back-link" onclick="history.length > 1 ? history.go(-1) : window.location = '{{ url('/admin/dashboard') }}';"></i>
{{ __('admin::app.cms.pages.pages') }}
</h1>
<div class="control-group">
<select class="control" id="channel-switcher" name="channel">
@php
$locale = request()->get('locale') ?: app()->getLocale();
$channel = request()->get('channel') ?: core()->getDefaultChannelCode();
@endphp
@foreach (core()->getAllChannels() as $channelModel)
<option value="{{ $channelModel->code }}" {{ ($channelModel->code) == $channel ? 'selected' : '' }}>
{{ $channelModel->name }}
</option>
@endforeach
</select>
</div>
<div class="control-group">
<select class="control" id="locale-switcher" name="locale">
@foreach (core()->getAllLocales() as $localeModel)
<option value="{{ $localeModel->code }}" {{ ($localeModel->code) == $locale ? 'selected' : '' }}>
{{ $localeModel->name }}
</option>
@endforeach
</select>
</div>
</div>
<div class="page-action fixed-action">
<button id="preview" class="btn btn-lg btn-primary">
{{ __('admin::app.cms.pages.preview') }}
</button>
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.cms.pages.edit-btn-title') }}
</button>
</div>
</div>
<div class="page-content">
<div class="form-container">
@csrf()
<div class="control-group" :class="[errors.has('url_key') ? 'has-error' : '']">
<label for="url-key" class="required">{{ __('admin::app.cms.pages.url-key') }}</label>
<input type="text" class="control" name="url_key" v-validate="'required'" value="{{ $page->url_key ?? old('url_key') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.url-key') }}&quot;" v-slugify>
<span class="control-error" v-if="errors.has('url_key')">@{{ errors.first('url_key') }}</span>
</div>
<div class="control-group" :class="[errors.has('html_content') ? 'has-error' : '']">
<label for="html_content" class="required">{{ __('admin::app.cms.pages.content') }}</label>
<textarea type="text" class="control" id="content" name="html_content" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.cms.pages.content') }}&quot;">{{ $page->html_content ?? old('html_content') }}</textarea>
{!! __('admin::app.cms.pages.one-col') !!}
{!! __('admin::app.cms.pages.two-col') !!}
{!! __('admin::app.cms.pages.three-col') !!}
<div class="mt-10 mb-10">
<a target="_blank" href="{{ route('ui.helper.classes') }}" class="btn btn-sm btn-primary">
{{ __('admin::app.cms.pages.helper-classes') }}
</a>
</div>
<span class="control-error" v-if="errors.has('html_content')">@{{ errors.first('html_content') }}</span>
</div>
<div class="control-group" :class="[errors.has('page_title') ? 'has-error' : '']">
<label for="page_title" class="required">{{ __('admin::app.cms.pages.page-title') }}</label>
<input type="text" class="control" name="page_title" v-validate="'required'" value="{{ $page->page_title ?? old('page_title') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.page-title') }}&quot;">
<span class="control-error" v-if="errors.has('page_title')">@{{ errors.first('page_title') }}</span>
</div>
<div class="control-group" :class="[errors.has('meta_title') ? 'has-error' : '']">
<label for="meta_title" class="required">{{ __('admin::app.cms.pages.meta_title') }}</label>
<input type="text" class="control" name="meta_title" v-validate="'required'" value="{{ $page->meta_title ?? old('meta_title') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.meta_title') }}&quot;">
<span class="control-error" v-if="errors.has('meta_title')">@{{ errors.first('meta_title') }}</span>
</div>
<div class="control-group" :class="[errors.has('meta_keywords') ? 'has-error' : '']">
<label for="meta_keywords" class="required">{{ __('admin::app.cms.pages.meta_keywords') }}</label>
<textarea type="text" class="control" name="meta_keywords" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.cms.pages.meta_keywords') }}&quot;">{{ $page->meta_keywords ?? old('meta_keywords') }}</textarea>
<span class="control-error" v-if="errors.has('meta_keywords')">@{{ errors.first('meta_keywords') }}</span>
</div>
<div class="control-group" :class="[errors.has('meta_description') ? 'has-error' : '']">
<label for="meta_description">{{ __('admin::app.cms.pages.meta_description') }}</label>
<textarea type="text" class="control" name="meta_description" data-vv-as="&quot;{{ __('admin::app.cms.pages.meta_description') }}&quot;">{{ $page->meta_description ?? old('meta_description') }}</textarea>
<span class="control-error" v-if="errors.has('meta_description')">@{{ errors.first('meta_description') }}</span>
</div>
</div>
</div>
</form>
</div>
@stop
@push('scripts')
<script src="{{ asset('vendor/webkul/admin/assets/js/tinyMCE/tinymce.min.js') }}"></script>
<script>
$(document).ready(function () {
$('#preview').on('click', function(e) {
var form = $('#page-form').serialize();
// var url = '{{ route('admin.cms.preview', $page->id) }}' + '?' + form;
var url = '{{ route('admin.cms.preview', $page->url_key) }}';
window.open(url, '_blank').focus();
return false;
});
$('#channel-switcher, #locale-switcher').on('change', function (e) {
$('#channel-switcher').val()
var query = '?channel=' + $('#channel-switcher').val() + '&locale=' + $('#locale-switcher').val();
window.location.href = "{{ route('admin.cms.edit', $page->id) }}" + query;
});
tinymce.init({
selector: 'textarea#content',
height: 200,
width: "70%",
plugins: 'image imagetools media wordcount save fullscreen code',
toolbar1: 'formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat | code',
image_advtab: true,
valid_elements : '*[*]'
});
});
</script>
@endpush

View File

@ -0,0 +1,46 @@
@extends('admin::layouts.content')
@section('page_title')
{{ __('admin::app.cms.pages.title') }}
@stop
@section('content')
<div class="content">
<div class="page-header">
<div class="page-title">
<h1>{{ __('admin::app.cms.pages.pages') }}</h1>
</div>
<div class="page-action">
<div class="export-import" @click="showModal('downloadDataGrid')">
<i class="export-icon"></i>
<span >
{{ __('admin::app.export.export') }}
</span>
</div>
<a href="{{ route('admin.cms.create') }}" class="btn btn-lg btn-primary">
{{ __('admin::app.cms.pages.add-title') }}
</a>
</div>
</div>
<div class="page-content">
@inject('cmsGrid', 'Webkul\Admin\DataGrids\CMSPageDataGrid')
{!! $cmsGrid->render() !!}
</div>
</div>
<modal id="downloadDataGrid" :is-open="modalIds.downloadDataGrid">
<h3 slot="header">{{ __('admin::app.export.download') }}</h3>
<div slot="body">
<export-form></export-form>
</div>
</modal>
@stop
@push('scripts')
@include('admin::export.export', ['gridName' => $cmsGrid])
@endpush

View File

@ -35,13 +35,13 @@
}
?>
@if ($field['type'] == 'depands')
@if ($field['type'] == 'depends')
<?php
$depands = explode(":", $field['depand']);
$depandField = current($depands);
$depandValue = end($depands);
$depends = explode(":", $field['depend']);
$dependField = current($depends);
$dependValue = end($depends);
if (count($channel_locale)) {
$channel_locale = implode(' - ', $channel_locale);
@ -67,16 +67,16 @@
$selectedOption = core()->getConfigData($name) ?? '';
?>
<depands
<depends
:options = '@json($field['options'])'
:name = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]'"
:validations = "'{{ $validations }}'"
:depand = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $depandField }}]'"
:value = "'{{ $depandValue }}'"
:field_name = "'{{ trans($field['title']) }}'"
:channel_loacle = "'{{ $channel_locale }}'"
:depend = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $dependField }}]'"
:value = "'{{ $dependValue }}'"
:field_name = "'{{ $field['title'] }}'"
:channel_locale = "'{{ $channel_locale }}'"
:result = "'{{ $selectedOption }}'"
></depands>
></depends>
@else
@ -94,20 +94,20 @@
@if ($field['type'] == 'text')
<input type="text" 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;{{ $field['name'] }}&quot;">
<input type="text" 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'] == '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;{{ $field['name'] }}&quot;">
<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'] == 'textarea')
<textarea v-validate="'{{ $validations }}'" class="control" id="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" name="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" data-vv-as="&quot;{{ $field['name'] }}&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) }}</textarea>
@elseif ($field['type'] == 'select')
<select v-validate="'{{ $validations }}'" class="control" id="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" name="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" data-vv-as="&quot;{{ $field['name'] }}&quot;" >
<select 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;" >
<?php
$selectedOption = core()->getConfigData($name) ?? '';
@ -124,8 +124,8 @@
@else
@foreach ($field['options'] as $option)
<?php
if ($option['value'] == false) {
$value = 0;
if (! isset($option['value'])) {
$value = null;
} else {
$value = $option['value'];
}
@ -141,7 +141,7 @@
@elseif ($field['type'] == 'multiselect')
<select v-validate="'{{ $validations }}'" class="control" id="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" name="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}][]" data-vv-as="&quot;{{ $field['name'] }}&quot;" multiple>
<select 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;" multiple>
<?php
$selectedOption = core()->getConfigData($name) ?? '';
@ -158,8 +158,8 @@
@else
@foreach ($field['options'] as $option)
<?php
if ($option['value'] == false) {
$value = 0;
if (! isset($option['value'])) {
$value = null;
} else {
$value = $option['value'];
}
@ -199,7 +199,7 @@
@elseif ($field['type'] == 'boolean')
<select v-validate="'{{ $validations }}'" class="control" id="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" name="{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]" data-vv-as="&quot;{{ $field['name'] }}&quot;">
<select 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;">
<?php
$selectedOption = core()->getConfigData($name) ?? '';
@ -228,7 +228,7 @@
</a>
@endif
<input type="file" 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;{{ $field['name'] }}&quot;" style="padding-top: 5px;">
<input type="file" 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;" style="padding-top: 5px;">
@if ($result)
<div class="control-group" style="margin-top: 5px;">
@ -255,7 +255,7 @@
</a>
@endif
<input type="file" 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;{{ $field['name'] }}&quot;" style="padding-top: 5px;">
<input type="file" 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;" style="padding-top: 5px;">
@if ($result)
<div class="control-group" style="margin-top: 5px;">
@ -271,7 +271,7 @@
@endif
@if (isset($field['info']))
<span class="control-info">{{ trans($field['info']) }}</span>
<span class="control-info mt-10">{{ trans($field['info']) }}</span>
@endif
<span class="control-error" @if ($field['type'] == 'multiselect') v-if="errors.has('{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}][]')" @else v-if="errors.has('{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]')" @endif
@ -392,12 +392,12 @@
});
</script>
<script type="text/x-template" id="depands-template">
<script type="text/x-template" id="depends-template">
<div class="control-group" :class="[errors.has(name) ? 'has-error' : '']" v-if="this.isVisible">
<label :for="name" :class="[ isRequire ? 'required' : '']">
@{{ field_name }}
<span class="locale"> [@{{ channel_loacle }}] </span>
<span class="locale"> [@{{ channel_locale }}] </span>
</label>
<select v-if="this.options.length" v-validate= "validations" class="control" :id = "name" :name = "name" v-model="this.result"
@ -416,13 +416,13 @@
</script>
<script>
Vue.component('depands', {
Vue.component('depends', {
template: '#depands-template',
template: '#depends-template',
inject: ['$validator'],
props: ['options', 'name', 'validations', 'depand', 'value', 'field_name', 'channel_loacle', 'repository', 'result'],
props: ['options', 'name', 'validations', 'depend', 'value', 'field_name', 'channel_locale', 'repository', 'result'],
data: function() {
return {
@ -439,17 +439,17 @@
}
$(document).ready(function(){
var dependentElement = document.getElementById(this_this.depand);
var depandValue = this_this.value;
var dependentElement = document.getElementById(this_this.depend);
var dependValue = this_this.value;
if (depandValue == 'true') {
depandValue = 1;
} else if (depandValue == 'false') {
depandValue = 0;
if (dependValue == 'true') {
dependValue = 1;
} else if (dependValue == 'false') {
dependValue = 0;
}
$(document).on("change", "select.control", function() {
if (this_this.depand == this.name) {
if (this_this.depend == this.name) {
if (this_this.value == this.value) {
this_this.isVisible = true;
} else {
@ -458,7 +458,7 @@
}
})
if (dependentElement && dependentElement.value == depandValue) {
if (dependentElement && dependentElement.value == dependValue) {
this_this.isVisible = true;
} else {
this_this.isVisible = false;

View File

@ -19,7 +19,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.customers.customers.save-btn-title') }}
</button>

View File

@ -19,7 +19,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.customers.customers.save-btn-title') }}
</button>

View File

@ -75,7 +75,77 @@
<script type="text/javascript" src="{{ asset('vendor/webkul/admin/assets/js/admin.js') }}"></script>
<script type="text/javascript" src="{{ asset('vendor/webkul/ui/assets/js/ui.js') }}"></script>
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function() {
moveDown = 60;
moveUp = -60;
count = 0;
countKeyUp = 0;
pageDown = 60;
pageUp = -60;
scroll = 0;
listLastElement = $('.menubar li:last-child').offset();
if (listLastElement) {
lastElementOfNavBar = listLastElement.top;
}
navbarTop = $('.navbar-left').css("top");
menuTopValue = $('.navbar-left').css('top');
menubarTopValue = menuTopValue;
documentHeight = $(document).height();
menubarHeight = $('ul.menubar').height();
navbarHeight = $('.navbar-left').height();
windowHeight = $(window).height();
contentHeight = $('.content').height();
innerSectionHeight = $('.inner-section').height();
gridHeight = $('.grid-container').height();
pageContentHeight = $('.page-content').height();
if (menubarHeight <= windowHeight) {
differenceInHeight = windowHeight - menubarHeight;
} else {
differenceInHeight = menubarHeight - windowHeight;
}
if (menubarHeight > windowHeight) {
document.addEventListener("keydown", function(event) {
if ((event.keyCode == 38) && count <= 0) {
count = count + moveDown;
$('.navbar-left').css("top", count + "px");
} else if ((event.keyCode == 40) && count >= -differenceInHeight) {
count = count + moveUp;
$('.navbar-left').css("top", count + "px");
} else if ((event.keyCode == 33) && countKeyUp <= 0) {
countKeyUp = countKeyUp + pageDown;
$('.navbar-left').css("top", countKeyUp + "px");
} else if ((event.keyCode == 34) && countKeyUp >= -differenceInHeight) {
countKeyUp = countKeyUp + pageUp;
$('.navbar-left').css("top", countKeyUp + "px");
} else {
$('.navbar-left').css("position", "fixed");
}
});
$("body").css({minHeight: $(".menubar").outerHeight() + 100 + "px"});
window.addEventListener('scroll', function() {
documentScrollWhenScrolled = $(document).scrollTop();
if (documentScrollWhenScrolled <= differenceInHeight + 200) {
$('.navbar-left').css('top', -documentScrollWhenScrolled + 60 + 'px');
scrollTopValueWhenNavBarFixed = $(document).scrollTop();
}
});
}
});
</script>
@stack('scripts')
{!! view_render_event('bagisto.admin.layout.body.after') !!}

View File

@ -24,7 +24,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.promotion.save-btn-title') }}
</button>
@ -36,7 +36,7 @@
<div>
@csrf()
<accordian :active="true" title="Information">
<accordian :active="true" title="{{ __('admin::app.promotion.information') }}">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.promotion.general-info.name') }}</label>
@ -78,7 +78,7 @@
<label for="customer_groups" class="required">{{ __('admin::app.promotion.general-info.cust-groups') }}</label>
<select type="text" class="control" name="customer_groups[]" v-model="customer_groups" v-validate="'required'" value="{{ old('customer_groups[]') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.cust-groups') }}&quot;" multiple="multiple">
<option disabled="disabled">Select Customer Groups</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Customer Group']) }}</option>
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $channel)
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
@endforeach
@ -91,7 +91,7 @@
<label for="channels" class="required">{{ __('admin::app.promotion.general-info.channels') }}</label>
<select type="text" class="control" name="channels[]" v-model="channels" v-validate="'required'" value="{{ old('channels') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.channels-req') }}&quot;" multiple="multiple">
<option disabled="disabled">Select Channels</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Channels']) }}</option>
@foreach(app('Webkul\Core\Repositories\ChannelRepository')->all() as $channel)
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
@endforeach
@ -104,7 +104,7 @@
<label for="status" class="required">{{ __('admin::app.promotion.general-info.status') }}</label>
<select type="text" class="control" name="status" v-model="status" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.status') }}&quot;">
<option disabled="disabled">Select status</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribtue', ['attribute' => 'Status']) }}</option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
@ -140,9 +140,9 @@
<input type="number" step="1" class="control" name="per_customer" v-model="per_customer" v-validate="'required|numeric|min_value:0'" value="{{ old('per_customer') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.uses-per-cust') }}&quot;">
<span class="control-error" v-if="errors.has('per_customer')">@{{ errors.first('per_customer') }}</span>
</div> --}}
</div>
{{-- <div class="control-group" :class="[errors.has('usage_limit') ? 'has-error' : '']">
<div class="control-group" :class="[errors.has('usage_limit') ? 'has-error' : '']">
<label for="usage_limit" class="required">{{ __('admin::app.promotion.general-info.limit') }}</label>
<input type="number" step="1" class="control" name="usage_limit" v-model="usage_limit" v-validate="'required|numeric|min_value:0'" value="{{ old('usage_limit') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.uses-per-cust') }}&quot;">
@ -160,7 +160,7 @@
</div>
</accordian>
<accordian :active="false" title="Conditions">
<accordian :active="false" title="{{ __('admin::app.promotion.conditions') }}">
<div slot="body">
<input type="hidden" name="all_conditions" v-model="all_conditions">
@ -169,7 +169,7 @@
<label for="criteria" class="required">{{ __('admin::app.promotion.general-info.add-condition') }}</label>
<select type="text" class="control" v-model="criteria">
<option value="cart">Cart Properties</option>
<option value="cart">{{ __('admin::app.promotion.cart-properties') }}</option>
</select>
</div>
</div> --}}
@ -189,7 +189,7 @@
<!-- Cart Attributes -->
<div class="control-container mt-20" v-for="(condition, index) in conditions_list" :key="index">
<select class="control" name="cart_attributes[]" v-model="conditions_list[index].attribute" title="You Can Make Multiple Selections Here" style="margin-right: 15px; width: 30%;" v-on:change="enableCondition($event, index)">
<option disabled="disabled">Select Option</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribtue', ['attrbibute' => 'Option']) }}</option>
<option v-for="(cart_ip, index1) in cart_input" :value="cart_ip.code" :key="index1">@{{ cart_ip.name }}</option>
</select>
@ -200,7 +200,7 @@
<div v-if='conditions_list[index].attribute == "shipping_state"'>
<select class="control" v-model="conditions_list[index].value">
<option disabled="disabled">Select State</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribtue', ['attrbibute' => 'State']) }}</option>
<optgroup v-for='(state, code) in country_and_states.states' :label="code">
<option v-for="(stateObj, index) in state" :value="stateObj.code">@{{ stateObj.default_name }}</option>
</optgroup>
@ -209,7 +209,7 @@
<div v-if='conditions_list[index].attribute == "shipping_country"'>
<select class="control" v-model="conditions_list[index].value">
<option disabled="disabled">Select Country</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribtue', ['attrbibute' => 'Country']) }}</option>
<option v-for="(country, index) in country_and_states.countries" :value="country.code">@{{ country.name }}</option>
</select>
</div>
@ -229,11 +229,11 @@
</div>
</div>
<span class="btn btn-primary btn-lg mt-20" v-on:click="addCondition">Add Condition</span>
<span class="btn btn-primary btn-lg mt-20" v-on:click="addCondition">{{ __('admin::app.promotion.add-condition') }}</span>
</div>
</accordian>
<accordian :active="false" title="Actions">
<accordian :active="false" title="{{ __('admin::app.promotion.actions') }}">
<div slot="body">
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
<label for="action_type" class="required">{{ __('admin::app.promotion.general-info.apply') }}</label>
@ -253,13 +253,13 @@
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
</div>
<div class="control-group" :class="[errors.has('disc_threshold') ? 'has-error' : '']">
{{-- <div class="control-group" :class="[errors.has('disc_threshold') ? 'has-error' : '']">
<label for="disc_threshold" class="required">{{ __('admin::app.promotion.cart.buy-atleast') }}</label>
<input type="number" step="1" class="control" name="disc_threshold" v-model="disc_threshold" v-validate="'required|numeric|min_value:1'" value="{{ old('disc_threshold') }}" data-vv-as="&quot;{{ __('admin::app.promotion.cart.buy-atleast') }}&quot;">
<span class="control-error" v-if="errors.has('disc_threshold')">@{{ errors.first('disc_threshold') }}</span>
</div>
</div> --}}
<div class="control-group" :class="[errors.has('disc_quantity') ? 'has-error' : '']">
<label for="disc_quantity" class="required">{{ __('admin::app.promotion.general-info.disc_qty') }}</label>
@ -308,22 +308,22 @@
</div>
</accordian>
<accordian :active="false" title="Coupons" v-if="use_coupon == 1">
<accordian :active="false" title="{{ __('admin::app.promotion.coupons') }}" v-if="use_coupon == 1">
<div slot="body">
{{-- <div v-if="!auto_generation">
<div class="control-group" :class="[errors.has('prefix') ? 'has-error' : '']">
<label for="prefix" class="required">Prefix</label>
<label for="prefix" class="required">{{ __('admin::app.promotion.general-info.prefix') }}</label>
<input type="text" class="control" name="prefix" v-model="prefix" v-validate="'alpha'" value="{{ old('prefix') }}" data-vv-as="&quot;Prefix&quot;">
<input type="text" class="control" name="prefix" v-model="prefix" v-validate="'alpha'" value="{{ old('prefix') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.prefix') }}&quot;">
<span class="control-error" v-if="errors.has('prefix')">@{{ errors.first('prefix') }}</span>
</div>
<div class="control-group" :class="[errors.has('suffix') ? 'has-error' : '']"">
<label for="suffix" class="required">Suffix</label>
<label for="suffix" class="required">{{ __('admin::app.promotion.general-info.suffix') }}</label>
<input type="text" class="control" name="suffix" v-model="suffix" v-validate="'alpha'" value="{{ old('suffix') }}" data-vv-as="&quot;suffix&quot;">
<input type="text" class="control" name="suffix" v-model="suffix" v-validate="'alpha'" value="{{ old('suffix') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.suffix') }}&quot;">
<span class="control-error" v-if="errors.has('suffix')">@{{ errors.first('suffix') }}</span>
</div>
@ -331,9 +331,9 @@
<div>
<div class="control-group" :class="[errors.has('code') ? 'has-error' : '']">
<label for="code" class="required">Code</label>
<label for="code" class="required">{{ __('admin::app.promotion.general-info.code') }}</label>
<input type="text" class="control" name="code" v-model="code" v-validate="'required'" value="{{ old('code') }}" data-vv-as="&quot;Code&quot;">
<input type="text" class="control" name="code" v-model="code" v-validate="'required'" value="{{ old('code') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.code') }}&quot;">
<span class="control-error" v-if="errors.has('code')">@{{ errors.first('code') }}</span>
</div>
@ -341,12 +341,60 @@
</div>
</accordian>
<accordian :active="true" title="{{ __('admin::app.promotion.select-products') }}">
<div slot="body">
<input type="hidden" name="all_attributes" v-model="all_attributes">
<div class="control-group" :class="[errors.has('category_values') ? 'has-error' : '']">
<label class="mb-10" for="categories">{{ __('admin::app.promotion.select-category') }}</label>
<multiselect v-model="category_values" :close-on-select="false" :options="category_options" :searchable="false" :custom-label="categoryLabel" :show-labels="true" placeholder="Select Categories" track-by="slug" :multiple="true"></multiselect>
</div>
<label class="mb-10" for="attributes">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Attribute']) }}</label>
<br/>
<div class="control-container mt-20" v-for="(condition, index) in attribute_values" :key="index">
<select class="control" v-model="attribute_values[index].attribute" title="You Can Make Multiple Selections Here" style="margin-right: 15px; width: 30%;" v-on:change="enableAttributeCondition($event, index)">
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
<option v-for="(attr_ip, index1) in attribute_input" :value="attr_ip.code" :key="index1">@{{ attr_ip.name }}</option>
</select>
<select class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
</select>
<div v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' style="display: flex;">
<select class="control" v-model="attribute_values[index].value" style="margin-right: 15px; height: 100px" :multiple="true">
<option :disabled="true">
{{ __('ui::form.select-attribute', ['attribute' => 'Values']) }}
</option>
<option v-for="(label, index2) in attribute_values[index].options" :value="label.id" :key="index2">@{{ label.admin_name }}</option>
</select>
{{-- <multiselect v-model="attribute_values[index].value" :close-on-select="false" :options="attribute_values[index].options" :searchable="false" :track-by="admin_name" :custom-label="attributeListLabel" :multiple="true" ></multiselect> --}}
</div>
<div v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price" || attribute_values[index].type == "textarea"' style="display: flex">
<input class="control" v-model="attribute_values[index].value" type="text" placeholder="{{ __('ui::form.enter-attribute', ['attribute' => 'Text']) }}">
</div>
<span class="icon trash-icon" v-on:click="removeAttr(index)"></span>
</div>
<span class="btn btn-primary btn-lg mt-20" v-on:click="addAttributeCondition">{{ __('admin::app.promotion.add-attr-condition') }}</span>
</div>
</accordian>
<accordian :active="false" :title="'{{ __('admin::app.promotion.general-info.labels') }}'">
<div slot="body">
<div class="control-group" :class="[errors.has('label') ? 'has-error' : '']" v-if="dedicated_label">
<label for="label">Global Label</label>
<label for="label">{{ __('admin::app.promotion.general-info.global-label') }}</label>
<input type="text" class="control" name="label[global]" v-model="label.global" data-vv-as="&quot;label&quot;">
<input type="text" class="control" name="label[global]" v-model="label.global" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.label') }}&quot;">
<span class="control-error" v-if="errors.has('label')">@{{ errors.first('label') }}</span>
</div>
@ -357,7 +405,7 @@
<div class="control-group" :class="[errors.has('label') ? 'has-error' : '']">
<label for="code"><span class="locale">[{{ $channel->code }} - {{ $locale->code }}]</span></label>
<input type="text" class="control" name="label[{{ $channel->code }}][{{ $locale->code }}]" v-model="label.{{ $channel->code }}.{{ $locale->code }}" data-vv-as="&quot;Label&quot;">
<input type="text" class="control" name="label[{{ $channel->code }}][{{ $locale->code }}]" v-model="label.{{ $channel->code }}.{{ $locale->code }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.label') }}&quot;">
<span class="control-error" v-if="errors.has('label')">@{{ errors.first('label') }}</span>
</div>
@ -400,7 +448,7 @@
apply_prct: false,
apply_to_shipping: 0,
disc_amount: null,
disc_threshold: null,
// disc_threshold: null,
disc_quantity: null,
end_other_rules: 0,
coupon_type: null,
@ -409,6 +457,11 @@
all_conditions: [],
match_criteria: 'all_are_true',
all_attributes: {
'categories' : null,
'attributes' : null
},
code: null,
suffix: null,
prefix: null,
@ -431,16 +484,35 @@
actions: @json($cart_rule[0]).actions,
conditions_list:[],
cart_object: {
attribute: null,
condition: null,
attribute: [],
condition: [],
value: []
},
country_and_states: @json($cart_rule[2])
country_and_states: @json($cart_rule[2]),
category_options: @json($cart_rule[1]),
category_values: [],
attribute_values: [],
attr_object: {
attribute: null,
condition: null,
value: [],
options: []
},
attribute_input: @json($cart_rule[3]),
}
},
methods: {
categoryLabel (option) {
return option.name + ' [ ' + option.slug + ' ]';
},
attributeListLabel(option) {
return option.label;
},
addCondition () {
if (this.criteria == 'product_subselection' || this.criteria == 'cart') {
this.condition_on = this.criteria;
@ -461,6 +533,17 @@
}
},
addAttributeCondition() {
this.attribute_values.push(this.attr_object);
this.attr_object = {
attribute: null,
condition: null,
value: [],
options: []
};
},
checkAutogen() {
},
@ -484,6 +567,20 @@
}
},
enableAttributeCondition (event, index) {
selectedIndex = event.target.selectedIndex - 1;
for(i in this.attribute_input) {
if (i == selectedIndex) {
if (this.attribute_input[i].has_options == true) {
this.attribute_values[index].options = this.attribute_input[i].options;
}
this.attribute_values[index].type = this.attribute_input[i].type;
}
}
},
// useCoupon() {
// if (this.use_coupon == 0) {
// this.auto_generation = null;
@ -496,11 +593,27 @@
this.conditions_list.splice(index, 1);
},
removeCat(index) {
this.cats.splice(index, 1);
removeAttr(index) {
this.attribute_values.splice(index, 1);
},
onSubmit: function (e) {
if (this.attribute_values.length > 0 || this.category_values.length > 0) {
for (i in this.attribute_values) {
delete this.attribute_values[i].options;
}
if (this.category_values.length > 0) {
this.all_attributes.categories = this.category_values;
}
this.all_attributes.attributes = this.attribute_values;
this.all_attributes = JSON.stringify(this.all_attributes);
} else {
this.all_attributes = null;
}
if (this.conditions_list.length != 0) {
this.conditions_list.push({'criteria': this.match_criteria});

View File

@ -24,7 +24,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.promotion.save') }}
</button>
@ -36,7 +36,7 @@
<div>
@csrf()
<accordian :active="true" title="Information">
<accordian :active="true" title="{{ __('admin::app.promotion.information') }}">
<div slot="body">
<input type="hidden" name="all_conditions" v-model="all_conditions">
@ -80,7 +80,7 @@
<label for="customer_groups" class="required">{{ __('admin::app.promotion.general-info.cust-groups') }}</label>
<select type="text" class="control" name="customer_groups[]" v-model="customer_groups" v-validate="'required'" value="{{ old('customer_groups[]') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.cust-groups') }}&quot;" multiple="multiple">
<option disabled="disabled">Select Customer Groups</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Customer Group']) }}</option>
@foreach(app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $customerGroup)
<option value="{{ $customerGroup->id }}">{{ $customerGroup->name }}</option>
@endforeach
@ -93,7 +93,7 @@
<label for="channels" class="required">{{ __('admin::app.promotion.general-info.channels') }}</label>
<select type="text" class="control" name="channels[]" v-model="channels" v-validate="'required'" value="{{ old('channels[]') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.channels-req') }}&quot;" multiple="multiple">
<option disabled="disabled">Select Channels</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Channels']) }}</option>
@foreach(app('Webkul\Core\Repositories\ChannelRepository')->all() as $channel)
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
@endforeach
@ -106,9 +106,9 @@
<label for="status" class="required">{{ __('admin::app.promotion.general-info.status') }}</label>
<select type="text" class="control" name="status" v-model="status" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.status') }}&quot;">
<option disabled="disabled">Select status</option>
<option value="1">Yes</option>
<option value="0">No</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Status']) }}</option>
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
<option value="0">{{ __('admin::app.promotion.no') }}</option>
</select>
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
@ -141,25 +141,18 @@
<input type="number" step="1" class="control" name="per_customer" v-model="per_customer" v-validate="'required|numeric|min_value:0'" value="{{ old('per_customer') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.uses-per-cust') }}&quot;">
<figcaption class="required">* {{ __('admin::app.promotion.zero-unlimited') }}</figcaption>
<span class="control-error" v-if="errors.has('per_customer')">@{{ errors.first('per_customer') }}</span>
</div> --}}
</div>
{{-- <div class="control-group" :class="[errors.has('is_guest') ? 'has-error' : '']">
<label for="is_guest" class="required">{{ __('admin::app.promotion.general-info.is-guest') }}</label>
<select type="text" class="control" name="is_guest" v-model="is_guest" v-validate="'required'" value="{{ old('is_guest')}}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.is-guest') }}&quot;">
<option value="1" :selected="is_guest == 1">{{ __('admin::app.promotion.general-info.is-coupon-yes') }}</option>
<option value="0" :selected="is_guest == 0">{{ __('admin::app.promotion.general-info.is-coupon-no') }}</option>
</select>
<span class="control-error" v-if="errors.has('is_guest')">@{{ errors.first('is_guest') }}</span>
</div> --}}
{{-- <div class="control-group" :class="[errors.has('usage_limit') ? 'has-error' : '']">
<div class="control-group" :class="[errors.has('usage_limit') ? 'has-error' : '']">
<label for="usage_limit" class="required">{{ __('admin::app.promotion.general-info.limit') }}</label>
<input type="number" step="1" class="control" name="usage_limit" v-model="usage_limit" v-validate="'required|numeric|min_value:0'" value="{{ old('usage_limit') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.uses-per-cust') }}&quot;">
<figcaption class="required">* {{ __('admin::app.promotion.zero-unlimited') }}</figcaption>
<span class="control-error" v-if="errors.has('usage_limit')">@{{ errors.first('usage_limit') }}</span>
</div> --}}
@ -173,7 +166,7 @@
</div>
</accordian>
<accordian :active="false" title="Conditions">
<accordian :active="false" title="{{ __('admin::app.promotion.conditions') }}">
<div slot="body">
<input type="hidden" name="all_conditions" v-model="all_conditions">
@ -202,7 +195,7 @@
<!-- Cart Attributes -->
<div class="control-container mt-20" v-for="(condition, index) in conditions_list" :key="index">
<select class="control" name="cart_attributes[]" v-model="conditions_list[index].attribute" title="You Can Make Multiple Selections Here" style="margin-right: 15px; width: 30%;" v-on:change="enableCondition($event, index)">
<option disabled="disabled">Select Option</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
<option v-for="(cart_ip, index1) in cart_input" :value="cart_ip.code" :key="index1">@{{ cart_ip.name }}</option>
</select>
@ -213,7 +206,7 @@
<div v-if='conditions_list[index].attribute == "shipping_state"'>
<select class="control" v-model="conditions_list[index].value">
<option disabled="disabled">Select State</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'State']) }}</option>
<optgroup v-for='(state, code) in country_and_states.states' :label="code">
<option v-for="(stateObj, index) in state" :value="stateObj.code">@{{ stateObj.default_name }}</option>
</optgroup>
@ -222,12 +215,12 @@
<div v-if='conditions_list[index].attribute == "shipping_country"'>
<select class="control" v-model="conditions_list[index].value">
<option disabled="disabled">Select Country</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Country']) }}</option>
<option v-for="(country, index) in country_and_states.countries" :value="country.code">@{{ country.name }}</option>
</select>
</div>
<input class="control" type="text" name="cart_attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value" v-if='conditions_list[index].attribute != "shipping_state" && conditions_list[index].attribute != "shipping_country"'>
<input class="control" type="text" name="cart_attributes[]" v-model="conditions_list[index].value" placeholder="{{ __('admin::app.promotion.enter-attribtue', ['attrbibute' => 'Value']) }}" v-if='conditions_list[index].attribute != "shipping_state" && conditions_list[index].attribute != "shipping_country"'>
</div>
<div v-if='conditions_list[index].type == "numeric"' style="display: flex">
@ -235,21 +228,21 @@
<option v-for="(condition, index) in conditions.numeric" :value="index" :key="index">@{{ condition }}</option>
</select>
<input class="control" type="number" step="0.1000" name="cart_attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value">
<input class="control" type="number" step="0.1000" name="cart_attributes[]" v-model="conditions_list[index].value" placeholder="{{ __('admin::app.promotion.enter-attribtue', ['attrbibute' => 'Value']) }}">
</div>
<span class="icon trash-icon" v-on:click="removeCartAttr(index)"></span>
</div>
</div>
<span class="btn btn-primary btn-lg mt-20" v-on:click="addCondition">Add Condition</span>
<span class="btn btn-primary btn-lg mt-20" v-on:click="addCondition">{{ __('admin::app.promotion.add-condition') }}</span>
</div>
</accordian>
<accordian :active="false" title="Actions">
<accordian :active="false" title="{{ __('admin::app.promotion.actions') }}">
<div slot="body">
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
<label for="action_type" class="required">Apply</label>
<label for="action_type" class="required">{{ __('admin::app.promotion.general-info.apply') }}</label>
<select class="control" name="action_type" v-model="action_type" v-validate="'required'" value="{{ old('action_type') }}" data-vv-as="&quot;Apply As&quot;" v-on:change="detectApply">
<option v-for="(action, index) in actions" :value="index">@{{ action }}</option>
@ -266,13 +259,13 @@
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
</div>
<div class="control-group" :class="[errors.has('disc_threshold') ? 'has-error' : '']">
{{-- <div class="control-group" :class="[errors.has('disc_threshold') ? 'has-error' : '']">
<label for="disc_threshold" class="required">{{ __('admin::app.promotion.cart.buy-atleast') }}</label>
<input type="number" step="1" class="control" name="disc_threshold" v-model="disc_threshold" v-validate="'required|numeric|min_value:1'" value="{{ old('disc_threshold') }}" data-vv-as="&quot;{{ __('admin::app.promotion.cart.buy-atleast') }}&quot;">
<span class="control-error" v-if="errors.has('disc_threshold')">@{{ errors.first('disc_threshold') }}</span>
</div>
</div> --}}
<div class="control-group" :class="[errors.has('disc_quantity') ? 'has-error' : '']">
<label for="disc_amount" class="required">{{ __('admin::app.promotion.general-info.disc_qty') }}</label>
@ -321,19 +314,19 @@
</div>
</accordian>
<accordian :active="false" title="Coupons" v-if="use_coupon == 1">
<accordian :active="false" title="{{ __('admin::app.promotion.coupons') }}" v-if="use_coupon == 1">
<div slot="body">
{{-- <div v-if="!auto_generation">
<div class="control-group" :class="[errors.has('prefix') ? 'has-error' : '']">
<label for="prefix" class="required">Prefix</label>
<label for="prefix" class="required">{{ __('admin::app.promotion.general-info.prefix') }}</label>
<input type="text" class="control" name="prefix" v-model="prefix" value="{{ old('prefix') }}" data-vv-as="&quot;Prefix&quot;">
<input type="text" class="control" name="prefix" v-model="prefix" value="{{ old('prefix') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.prefix') }}&quot;">
<span class="control-error" v-if="errors.has('prefix')">@{{ errors.first('prefix') }}</span>
</div>
<div class="control-group" :class="[errors.has('suffix') ? 'has-error' : '']"">
<label for="suffix" class="required">Suffix</label>
<label for="suffix" class="required">{{ __('admin::app.promotion.general-info.suffix') }}</label>
<input type="text" class="control" name="suffix" v-model="suffix" value="{{ old('suffix') }}" data-vv-as="&quot;suffix&quot;">
@ -343,9 +336,9 @@
{{-- <div v-if="auto_generation != 0"> --}}
<div class="control-group" :class="[errors.has('code') ? 'has-error' : '']">
<label for="code" class="required">Code</label>
<label for="code" class="required">{{ __('admin::app.promotion.general-info.code') }}</label>
<input type="text" class="control" name="code" v-model="code" v-validate="'required'" value="{{ old('code') }}" data-vv-as="&quot;Code&quot;">
<input type="text" class="control" name="code" v-model="code" v-validate="'required'" value="{{ old('code') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.code') }}&quot;">
<span class="control-error" v-if="errors.has('code')">@{{ errors.first('code') }}</span>
</div>
@ -353,6 +346,60 @@
</div>
</accordian>
<accordian :active="true" title="{{ __('admin::app.promotion.select-products') }}">
<div slot="body">
<input type="hidden" name="all_attributes" v-model="all_attributes">
<span class="info mb-20" style="display: block;">
<b>{{ __('admin::app.promotion.note') }}:</b>
{{ __('admin::app.promotion.convert-x-note') }}
</span>
<div class="control-group" :class="[errors.has('category_values') ? 'has-error' : '']">
<label class="mb-10" for="categories">{{ __('admin::app.promotion.select-category') }}</label>
<multiselect v-model="category_values" :close-on-select="false" :options="category_options" :searchable="false" :custom-label="categoryLabel" :show-labels="true" placeholder="{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Categories']) }}" track-by="slug" :multiple="true"></multiselect>
</div>
<label class="mb-10" for="attributes">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</label>
<br/>
<div class="control-container mt-20" v-for="(condition, index) in attribute_values" :key="index">
<select class="control" v-model="attribute_values[index].attribute" title="You Can Make Multiple Selections Here" style="margin-right: 15px; width: 30%;" v-on:change="enableAttributeCondition($event, index)">
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
<option v-for="(attr_ip, index1) in attribute_input" :value="attr_ip.code" :key="index1">@{{ attr_ip.name }}</option>
</select>
<select class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
</select>
<div v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' style="display: flex;">
<select class="control" v-model="attribute_values[index].value" style="margin-right: 15px; height: 100px" :multiple="true">
<option :disabled="true">
{{ __('ui::form.select-attribute', ['attribute' => 'Values']) }}
</option>
<option v-for="(label, index2) in attribute_values[index].options" :value="label.id" :key="index2">@{{ label.admin_name }}</option>
</select>
{{-- <multiselect v-model="attribute_values[index].value" :close-on-select="false" :options="attribute_values[index].options" :searchable="false" :track-by="admin_name" :custom-label="attributeListLabel" :multiple="true" ></multiselect> --}}
</div>
<div v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price" || attribute_values[index].type == "textarea"' style="display: flex">
<input class="control" v-model="attribute_values[index].value" type="text" placeholder="{{ __('ui::form.enter-attribute', ['attribute' => 'Text']) }}">
</div>
<span class="icon trash-icon" v-on:click="removeAttr(index)"></span>
</div>
<span class="btn btn-primary btn-lg mt-20" v-on:click="addAttributeCondition">{{ __('admin::app.promotion.add-attr-condition') }}</span>
</div>
</accordian>
<accordian :active="false" :title="'{{ __('admin::app.promotion.general-info.labels') }}'">
<div slot="body">
@foreach($cart_rule[3]->labels as $label)
@ -381,8 +428,8 @@
data () {
return {
name: 'Name of rule',
description: 'Enter Some Description',
name: '{{ __('admin::app.promotion.rule-name') }}',
description: '{{ __('admin::app.promotion.rule-desc') }}',
channels: [],
customer_groups: [],
ends_till: null,
@ -399,9 +446,8 @@
apply_amt: false,
apply_prct: false,
apply_to_shipping: null,
buy_atleast: null,
disc_amount: null,
disc_threshold: null,
// disc_threshold: null,
disc_quantity: null,
end_other_rules: null,
coupon_type: null,
@ -410,6 +456,11 @@
all_conditions: null,
match_criteria: 'all_are_true',
all_attributes: {
'categories' : null,
'attributes' : null
},
code: null,
suffix: null,
prefix: null,
@ -435,7 +486,19 @@
condition: null,
value: []
},
country_and_states: @json($cart_rule[2])
country_and_states: @json($cart_rule[2]),
category_options: @json($cart_rule[1]),
category_values: [],
attribute_values: [],
attr_object: {
attribute: null,
condition: null,
value: [],
options: []
},
attribute_input: @json($cart_rule[4]),
}
},
@ -483,9 +546,8 @@
this.apply_amt = false;
this.apply_prct = false;
this.apply_to_shipping = data.apply_to_shipping;
this.buy_atleast = data.disc_threshold;
this.disc_amount = data.disc_amount;
this.disc_threshold = data.disc_threshold;
// this.disc_threshold = data.disc_threshold;
this.disc_quantity = data.disc_quantity;
this.end_other_rules = data.end_other_rules;
this.coupon_type = data.coupon_type;
@ -498,10 +560,41 @@
this.match_criteria = this.conditions_list.pop().criteria;
}
if (JSON.parse(JSON.parse(data.actions).attribute_conditions)) {
this.category_values = JSON.parse(JSON.parse(data.actions).attribute_conditions).categories;
this.attribute_values = JSON.parse(JSON.parse(data.actions).attribute_conditions).attributes;
// creating options and has option param on the frontend
for (i in this.attribute_values) {
for (j in this.attribute_input) {
if (this.attribute_input[j].code == this.attribute_values[i].attribute) {
if (this.attribute_input[j].has_options == true) {
this.attribute_values[i].has_options = true;
this.attribute_values[i].options = this.attribute_input[j].options;
} else {
this.attribute_values[i].has_options = false;
this.attribute_values[i].options = null;
}
}
}
}
}
criteria = null;
},
methods: {
categoryLabel (option) {
return option.name + ' [ ' + option.slug + ' ]';
},
attributeListLabel(option) {
return option.label;
},
addCondition () {
if (this.criteria == 'product_subselection' || this.criteria == 'cart') {
this.condition_on = this.criteria;
@ -522,6 +615,17 @@
}
},
addAttributeCondition() {
this.attribute_values.push(this.attr_object);
this.attr_object = {
attribute: null,
condition: null,
value: [],
options: []
};
},
checkAutogen() {
},
@ -545,6 +649,20 @@
}
},
enableAttributeCondition (event, index) {
selectedIndex = event.target.selectedIndex - 1;
for(i in this.attribute_input) {
if (i == selectedIndex) {
if (this.attribute_input[i].has_options == true) {
this.attribute_values[index].options = this.attribute_input[i].options;
}
this.attribute_values[index].type = this.attribute_input[i].type;
}
}
},
useCoupon() {
if (this.use_coupon == 0) {
this.auto_generation = null;
@ -561,7 +679,27 @@
this.cats.splice(index, 1);
},
removeAttr(index) {
this.attribute_values.splice(index, 1);
},
onSubmit: function (e) {
if (this.attribute_values.length != 0 || this.category_values.length != 0) {
for (i in this.attribute_values) {
delete this.attribute_values[i].options;
}
if (this.category_values != null && this.category_values.length > 0) {
this.all_attributes.categories = this.category_values;
}
this.all_attributes.attributes = this.attribute_values;
this.all_attributes = JSON.stringify(this.all_attributes);
} else {
this.all_attributes = null;
}
if (this.conditions_list.length != 0) {
this.conditions_list.push({'criteria': this.match_criteria});

View File

@ -24,7 +24,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.promotion.save-btn-title') }}
</button>
@ -35,7 +35,7 @@
<div class="form-container">
@csrf()
<accordian :active="true" title="Information">
<accordian :active="true" title="{{ __('admin::app.promotion.information') }}">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.promotion.general-info.name') }}</label>
@ -83,31 +83,19 @@
<label for="status" class="required">{{ __('admin::app.promotion.general-info.status') }}</label>
<select type="text" class="control" name="status" v-model="status" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.status') }}&quot;">
<option disabled="disabled">Select status</option>
<option value="1">Yes</option>
<option value="0">No</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
<option value="0">{{ __('admin::app.promotion.no') }}</option>
</select>
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
</div>
<div class="control-group" :class="[errors.has('end_other_rules') ? 'has-error' : '']">
<label for="end_other_rules" class="required">{{ __('admin::app.promotion.general-info.end_other_rules') }}</label>
<select type="text" class="control" name="end_other_rules" v-model="end_other_rules" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.end_other_rules') }}&quot;">
<option disabled="disabled">Select option</option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
<span class="control-error" v-if="errors.has('end_other_rules')">@{{ errors.first('end_other_rules') }}</span>
</div>
<datetime :name="starts_from">
<div class="control-group" :class="[errors.has('starts_from') ? 'has-error' : '']">
<label for="starts_from" class="required">{{ __('admin::app.promotion.general-info.starts-from') }}</label>
<input type="text" class="control" v-model="starts_from" name="starts_from" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.starts-from') }}&quot;">
<input type="text" class="control" v-model="starts_from" name="starts_from" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.starts-from') }}&quot;">
<span class="control-error" v-if="errors.has('starts_from')">@{{ errors.first('starts_from') }}</span>
</div>
@ -117,233 +105,98 @@
<div class="control-group" :class="[errors.has('ends_till') ? 'has-error' : '']">
<label for="ends_till" class="required">{{ __('admin::app.promotion.general-info.ends-till') }}</label>
<input type="text" class="control" v-model="ends_till" name="ends_till" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.ends-till') }}&quot;">
<input type="text" class="control" v-model="ends_till" name="ends_till" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.ends-till') }}&quot;">
<span class="control-error" v-if="errors.has('ends_till')">@{{ errors.first('ends_till') }}</span>
</div>
</datetime>
<div class="control-group" :class="[errors.has('priority') ? 'has-error' : '']">
<label for="priority" class="required">{{ __('admin::app.promotion.general-info.priority') }}</label>
<input type="number" class="control" step="1" name="priority" v-model="priority" v-validate="'required|numeric|min_value:1'" value="{{ old('priority') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.priority') }}&quot;">
<span class="control-error" v-if="errors.has('priority')">@{{ errors.first('priority') }}</span>
</div>
</div>
</accordian>
<accordian :active="false" title="Conditions">
<accordian :active="false" title="{{ __('admin::app.promotion.conditions') }}">
<div slot="body">
<div class="add-condition">
<input type="hidden" v-model="global_condition.allorany">
<input type="hidden" v-model="global_condition.alltrueorfalse">
<div class="control-group" :class="[errors.has('criteria') ? 'has-error' : '']">
<label for="criteria" class="required">{{ __('admin::app.promotion.general-info.add-condition') }}</label>
<input type="hidden" name="all_conditions" v-model="all_conditions">
<select type="text" class="control" name="criteria" v-model="criteria" v-validate="'required'" value="" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.cust-groups') }}&quot;">
<option value="attribute">Attribute</option>
<option value="category">Category</option>
<option value="attribute_family">Attribute Family</option>
</select>
<!-- Categories selection input block -->
<div class="control-group" :class="[errors.has('category_values') ? 'has-error' : '']">
<label class="mb-10" for="categories">{{ __('admin::app.promotion.select-category') }}</label>
<span class="control-error" v-if="errors.has('criteria')">@{{ errors.first('criteria') }}</span>
</div>
<span class="btn btn-primary btn-lg" v-on:click="addCondition">Add Condition</span>
<multiselect v-model="category_values" :close-on-select="false" :options="category_options" :searchable="false" :custom-label="categoryLabel" :show-labels="true" placeholder="Select Categories" track-by="slug" :multiple="true"></multiselect>
</div>
<label class="mb-10" for="attributes">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Attribute']) }}</label>
<br/>
<div class="condition-set" v-if="conditions_list.length">
{{-- <span class="control-group" v-on:click="genericGroupCondition" v-if="generic_condition">
{{ __('admin::app.promotion.general-info.all-conditions-true') }}
</span>
<!-- Product attributes conditions block -->
<div class="control-container mt-20" v-for="(condition, index) in attribute_values" :key="index">
<select class="control" v-model="attribute_values[index].attribute" style="margin-right: 15px; width: 30%;" v-on:change="enableAttributeCondition($event, index)">
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
<span class="control-group" v-on:click="genericGroupCondition" v-if="! generic_condition">
{{ __('admin::app.promotion.general-info.assuming') }}
<select>
<option selected="selected">All</option>
<option>Any</option>
</select>
{{ __('admin::app.promotion.general-info.are') }}
<select>
<option selected="selected">True</option>
<option>False</option>
</select>
</span> --}}
<!-- Conditions -->
<div v-for="(condition, index) in conditions_list" :key="index">
<div class="control-container mt-20" v-if='conditions_list[index].criteria == "attribute"'>
<div class="title-bar">
{{-- <span>Group </span>
<input type="checkbox" v-model="condition_groups" v-on:click="groupSelected(index)" /> --}}
<span>Attribute is </span>
<span class="icon cross-icon" v-on:click="removeAttr(index)"></span>
</div>
<div class="control-group mt-10" :key="index">
<select class="control" name="attributes[]" v-model="conditions_list[index].attribute" v-validate="'required'" title="You Can Make Multiple Selections Here" style="margin-right: 15px;" v-on:change="enableCondition($event, index)">
<option disabled="disabled">Select attribute</option>
<option v-for="(attr_ip, i) in attrs_input" :value="attr_ip.code">@{{ attr_ip.name }}</option>
</select>
<div v-if='conditions_list[index].type == "text" || conditions_list[index].type == "textarea"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['text'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<input type="text" class="control" name="attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value">
</div>
<div v-if='conditions_list[index].type == "price"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['numeric'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<input type="number" step="0.1000" class="control" name="attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value">
</div>
<div v-else-if='conditions_list[index].type == "boolean"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
<option selected="selected">is</option>
</select>
<select class="control" name="attributes[]" v-model="conditions_list[index].value">
@foreach($catalog_rule[4]['boolean'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
</div>
<div v-else-if='conditions_list[index].type == "date"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['numeric'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<date>
<input type="text" class="control" v-model="conditions_list[index].value" name="attributes[]" v-validate="'required'" value="Enter Value">
</date>
</div>
<div v-else-if='conditions_list[index].type == "datetime"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['numeric'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<datetime>
<input type="text" class="control" v-model="conditions_list[index].value" name="attributes[]" v-validate="'required'" value="Enter Value">
</datetime>
</div>
<div v-else-if='conditions_list[index].type == "select" || conditions_list[index].type == "multiselect"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['text'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<select class="control" v-model="conditions_list[index].value" name="attributes[]" v-validate="'required'" multiple>
<option v-for="option in conditions_list[index].options" :value="option.id">@{{ option.admin_name }}</option>
</select>
</div>
</div>
</div>
<div class="control-container mt-20" v-if='conditions_list[index].criteria == "category"'>
<div class="title-bar">
<span>Category </span>
{{-- <span>Group </span>
<input type="checkbox" v-model="condition_groups" v-on:click="groupSelected(index)" /> --}}
<span class="icon cross-icon" v-on:click="removeAttr(index)"></span>
</div>
<div class="control-group mt-10" :key="index">
<input type="hidden" class="control" name="attributes[]" v-model="conditions_list[index].category" v-validate="'required'" style="margin-right: 15px;" v-on:change="enableCondition($event, index)">
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['text'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<select class="control" name="attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value" multiple>
<option v-for="(category, index) in categories" :value="category.id">@{{ category.name }}</option>
</select>
</div>
</div>
<div class="control-container mt-20" v-if='conditions_list[index].criteria == "attribute_family"'>
<div class="title-bar">
<span>Attribute Family </span>
{{-- <span>Group </span>
<input type="checkbox" v-model="condition_groups" v-on:click="groupSelected(index)" /> --}}
<span class="icon cross-icon" v-on:click="removeAttr(index)"></span>
</div>
<div class="control-group mt-10" :key="index">
<input type="hidden" class="control" name="attributes[]" v-model="conditions_list[index].family" v-validate="'required'" style="margin-right: 15px;" v-on:change="enableCondition($event, index)">
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['boolean'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<select class="control" name="attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value">
<option v-for="(attr_family, index) in attr_families" :value="attr_family.id">@{{ attr_family.name }}</option>
</select>
</div>
</div>
</div>
<input type="hidden" name="all_conditions[]" v-model="all_conditions">
</div>
</div>
</accordian>
<accordian :active="false" title="Actions">
<div slot="body">
<div class="control-group" :class="[errors.has('apply') ? 'has-error' : '']">
<label for="apply" class="required">Apply</label>
<select class="control" name="apply" v-model="apply" v-validate="'required'" value="{{ old('apply') }}" data-vv-as="&quot;Apply As&quot;" v-on:change="detectApply">
@foreach($catalog_rule[3]['actions'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
<option v-for="(attr_ip, index1) in attribute_input" :value="attr_ip.code" :key="index1">@{{ attr_ip.name }}</option>
</select>
<span class="control-error" v-if="errors.has('apply')">@{{ errors.first('apply') }}</span>
<select v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
<option v-for="(condition, index) in conditions.select" :value="index" :key="index">@{{ condition }}</option>
</select>
<select v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price"' class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
</select>
<div v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' style="display: flex;">
<select class="control" v-model="attribute_values[index].value" style="margin-right: 15px; height: 100px" :multiple="true">
<option :disabled="true">
{{ __('ui::form.select-attribute', ['attribute' => 'Values']) }}
</option>
<option v-for="(label, index2) in attribute_values[index].options" :value="index2" :key="index2">@{{ label.admin_name }}</option>
</select>
{{-- <multiselect v-model="attribute_values[index].value" :close-on-select="false" :options="attribute_values[index].options" :searchable="false" :track-by="admin_name" :custom-label="attributeListLabel" :multiple="true" ></multiselect> --}}
</div>
<div v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price" || attribute_values[index].type == "textarea"' style="display: flex">
<input class="control" v-model="attribute_values[index].value" type="text" placeholder="{{ __('ui::form.enter-attribute', ['attribute' => 'Text']) }}">
</div>
<span class="icon trash-icon" v-on:click="removeAttr(index)"></span>
</div>
<div class="control-group" :class="[errors.has('disc_amount') ? 'has-error' : '']" v-if="apply_amt">
<span class="btn btn-primary btn-lg mt-20" v-on:click="addAttributeCondition">{{ __('admin::app.promotion.add-attr-condition') }}</span>
</div>
</accordian>
<accordian :active="false" title="{{ __('admin::app.promotion.actions') }}">
<div slot="body">
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
<label for="action_type" class="required">{{ __('admin::app.promotion.general-info.apply') }}</label>
<select class="control" name="action_type" v-model="action_type" v-validate="'required'" value="{{ old('action_type') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.apply') }}&quot;" v-on:change="detectApply">
<option v-for="(action, index) in actions" :value="index">@{{ action }}</option>
</select>
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
</div>
<div class="control-group" :class="[errors.has('disc_amount') ? 'has-error' : '']">
<label for="disc_amount" class="required">{{ __('admin::app.promotion.general-info.disc_amt') }}</label>
<input type="number" step="1.0000" class="control" name="disc_amount" v-model="disc_amount" v-validate="'required|decimal|min_value:0.0001'" value="{{ old('disc_amount') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.disc_amt') }}&quot;">
<input type="number" step="0.5000" class="control" name="disc_amount" v-model="disc_amount" v-validate="'required|min_value:0.0001'" value="{{ old('disc_amount') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.disc_amt') }}&quot;">
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
</div>
<div class="control-group" :class="[errors.has('disc_percent') ? 'has-error' : '']" v-if="apply_prct">
<label for="disc_percent" class="required">{{ __('admin::app.promotion.general-info.disc_percent') }}</label>
<div class="control-group" :class="[errors.has('end_other_rules') ? 'has-error' : '']">
<label for="end_other_rules" class="required">{{ __('admin::app.promotion.general-info.end-other-rules') }}</label>
<input type="number" step="0.5000" class="control" name="disc_percent" v-model="disc_percent" v-validate="'required|decimal|min_value:0.0001'" value="{{ old('disc_percent') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.disc_percent') }}&quot;">
<select type="text" class="control" name="end_other_rules" v-model="end_other_rules" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.end-other-rules') }}&quot;">
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
<option value="0">{{ __('admin::app.promotion.no') }}</option>
</select>
<span class="control-error" v-if="errors.has('disc_percent')">@{{ errors.first('disc_percent') }}</span>
<span class="control-error" v-if="errors.has('end_other_rules')">@{{ errors.first('end_other_rules') }}</span>
</div>
</div>
</accordian>
@ -361,62 +214,64 @@
data () {
return {
all_conditions: [],
name: null,
description: null,
conditions_list: [],
channels: [],
customer_groups: [],
ends_till: null,
starts_from: null,
per_customer: 0,
status: 1,
use_coupon: null,
auto_generation: false,
usage_limit: 0,
action_type: null,
apply: null,
apply_amt: false,
apply_prct: false,
applied_config: @json($catalog_rule[3]),
conditions_list: [],
attr_families: @json($catalog_rule[5]),
attrs_input: @json($catalog_rule[0]),
attrs_options: @json($catalog_rule[2]),
global_condition: {
allorany: false,
alltrueorfalse: true
apply_to_shipping: 0,
disc_amount: null,
end_other_rules: 0,
all_conditions: [],
all_attributes: {
'categories' : null,
'attributes' : null
},
criteria: 'cart',
actions: @json($catalog_rule[0]).actions,
category_options: @json($catalog_rule[1]),
category_values: [],
conditions: @json($catalog_rule[0]).conditions,
attribute_values: [],
attr_object: {
criteria: 'attribute',
attribute: null,
condition: null,
type: null,
value: null
value: [],
options: []
},
cat_object: {
criteria: 'category',
category: 'category',
condition: null,
value: []
},
fam_object: {
criteria: 'attribute_family',
family: 'attribute_family',
condition: null,
value: null
},
categories: @json($catalog_rule[1]),
cats_count: 0,
channels: [],
conditions: [],
condition_groups: [],
criteria: null,
customer_groups: [],
description: null,
disc_amount: 0.0,
disc_percent: 0.0,
ends_till: null,
end_other_rules: null,
generic_condition: true,
name: null,
priority: 0,
starts_from: null,
status: null
attribute_input: @json($catalog_rule[3])
}
},
mounted () {
console.log(this.attribute_input);
},
methods: {
categoryLabel (option) {
return option.name + ' [ ' + option.slug + ' ]';
},
attributeListLabel(option) {
return option.label;
},
addCondition () {
if (this.criteria == 'attribute' || this.criteria == 'attribute_family' || this.criteria == 'category') {
this.condition_on = this.criteria;
@ -458,6 +313,17 @@
}
},
addAttributeCondition() {
this.attribute_values.push(this.attr_object);
this.attr_object = {
attribute: null,
condition: null,
value: [],
options: []
};
},
enableCondition(event, index) {
this.conditions_list[index].type = this.attrs_input[event.target.selectedIndex - 1].type;
var this_this = this;
@ -469,6 +335,21 @@
}
},
enableAttributeCondition (event, index) {
selectedIndex = event.target.selectedIndex - 1;
for(i in this.attribute_input) {
if (i == selectedIndex) {
if (this.attribute_input[i].has_options == true) {
this.selectedIndex
this.attribute_values[index].options = this.attribute_input[i].options;
}
this.attribute_values[index].type = this.attribute_input[i].type;
}
}
},
detectApply() {
if (this.apply == 0 || this.apply == 2) {
this.apply_prct = true;
@ -480,7 +361,7 @@
},
removeAttr(index) {
this.conditions_list.splice(index, 1);
this.attribute_values.splice(index, 1);
},
removeCat(index) {
@ -488,37 +369,37 @@
},
onSubmit: function (e) {
if (this.attribute_values.length > 0 || this.category_values.length > 0) {
for (i in this.attribute_values) {
delete this.attribute_values[i].options;
}
if (this.category_values.length > 0) {
this.all_attributes.categories = this.category_values;
}
this.all_attributes.attributes = this.attribute_values;
this.all_conditions = JSON.stringify(this.all_attributes);
} else {
this.all_conditions = null;
}
// this.all_conditions = JSON.stringify(this.conditions_list);
// if (this.conditions_list.length != 0) {
// this.conditions_list.push({'criteria': this.match_criteria});
// this.all_conditions = JSON.stringify(this.conditions_list);
// }
// return false;
this.$validator.validateAll().then(result => {
if (result) {
e.target.submit();
}
});
for (index in this.conditions_list) {
if (this.conditions_list[index].condition == null || this.conditions_list[index].condition == "" || this.conditions_list[index].condition == undefined) {
window.flashMessages = [{'type': 'alert-error', 'message': "{{ __('admin::app.promotion.catalog.condition-missing') }}" }];
this.$root.addFlashMessages();
return false;
} else if (this.conditions_list[index].value == null || this.conditions_list[index].value == "" || this.conditions_list[index].value == undefined) {
window.flashMessages = [{'type': 'alert-error', 'message': "{{ __('admin::app.promotion.catalog.condition-missing') }}" }];
this.$root.addFlashMessages();
return false;
}
}
if (this.conditions_list.length == 0) {
window.flashMessages = [{'type': 'alert-error', 'message': "{{ __('admin::app.promotion.catalog.condition-missing') }}" }];
this.$root.addFlashMessages();
return false;
}
this.all_conditions = JSON.stringify(this.conditions_list);
},
genericGroupCondition() {

View File

@ -24,7 +24,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.promotion.edit-btn-title') }}
</button>
@ -35,7 +35,7 @@
<div class="form-container">
@csrf()
<accordian :active="true" title="Information">
<accordian :active="true" title="{{ __('admin::app.promotion.information') }}">
<div slot="body">
<div class="control-group" :class="[errors.has('name') ? 'has-error' : '']">
<label for="name" class="required">{{ __('admin::app.promotion.general-info.name') }}</label>
@ -76,253 +76,131 @@
@endforeach
</select>
<span class="control-error" v-if="errors.has('channels[]')">@{{ errors.first('channels[]') }}</span>
<span class="control-error" v-if="errors.has('channels[]')">@{{ errors.first('status') }}</span>
</div>
<div class="control-group" :class="[errors.has('status') ? 'has-error' : '']">
<label for="status" class="required">{{ __('admin::app.promotion.general-info.status') }}</label>
<select type="text" class="control" name="status" v-model="status" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.status') }}&quot;">
<option disabled="disabled">Select status</option>
<option value="1">Yes</option>
<option value="0">No</option>
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
<option value="0">{{ __('admin::app.promotion.no') }}</option>
</select>
<span class="control-error" v-if="errors.has('status')">@{{ errors.first('status') }}</span>
</div>
<div class="control-group" :class="[errors.has('end_other_rules') ? 'has-error' : '']">
<label for="end_other_rules" class="required">{{ __('admin::app.promotion.general-info.end_other_rules') }}</label>
@php
$now = new \Carbon\Carbon();
@endphp
<select type="text" class="control" name="end_other_rules" v-model="end_other_rules" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.end_other_rules') }}&quot;">
<option disabled="disabled">Select option</option>
<option value="1">Yes</option>
<option value="0">No</option>
</select>
<span class="control-error" v-if="errors.has('end_other_rules')">@{{ errors.first('end_other_rules') }}</span>
</div>
<datetime :name="starts_from">
<date :name="starts_from">
<div class="control-group" :class="[errors.has('starts_from') ? 'has-error' : '']">
<label for="starts_from" class="required">{{ __('admin::app.promotion.general-info.starts-from') }}</label>
<input type="text" class="control" v-model="starts_from" name="starts_from" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.starts-from') }}&quot;">
<input type="text" class="control" v-model="starts_from" name="starts_from" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.starts-from') }}&quot;">
<span class="control-error" v-if="errors.has('starts_from')">@{{ errors.first('starts_from') }}</span>
</div>
</datetime>
</date>
<datetime :name="starts_from">
<date :name="starts_from">
<div class="control-group" :class="[errors.has('ends_till') ? 'has-error' : '']">
<label for="ends_till" class="required">{{ __('admin::app.promotion.general-info.ends-till') }}</label>
<input type="text" class="control" v-model="ends_till" name="ends_till" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.ends-till') }}&quot;">
<input type="text" class="control" v-model="ends_till" name="ends_till" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.ends-till') }}&quot;">
<span class="control-error" v-if="errors.has('ends_till')">@{{ errors.first('ends_till') }}</span>
</div>
</datetime>
<div class="control-group" :class="[errors.has('priority') ? 'has-error' : '']">
<label for="priority" class="required">{{ __('admin::app.promotion.general-info.priority') }}</label>
<input type="number" class="control" step="1" name="priority" v-model="priority" v-validate="'required|numeric|min_value:1'" value="{{ old('priority') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.priority') }}&quot;">
<span class="control-error" v-if="errors.has('priority')">@{{ errors.first('priority') }}</span>
</div>
</date>
</div>
</accordian>
<accordian :active="true" title="Conditions">
<accordian :active="false" title="{{ __('admin::app.promotion.conditions') }}">
<div slot="body">
<div class="add-condition">
<div class="control-group" :class="[errors.has('criteria') ? 'has-error' : '']">
<label for="criteria" class="required">{{ __('admin::app.promotion.general-info.add-condition') }}</label>
<input type="hidden" name="all_conditions" v-model="all_conditions">
<select type="text" class="control" name="criteria" v-model="criteria" v-validate="'required'" value="" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.cust-groups') }}&quot;">
<option value="attribute">Attribute</option>
<option value="category">Category</option>
<option value="attribute_family">Attribute Family</option>
</select>
<!-- Categories selection input block -->
<div class="control-group" :class="[errors.has('category_values') ? 'has-error' : '']">
<label class="mb-10" for="categories">{{ __('admin::app.promotion.select-category') }}</label>
<span class="control-error" v-if="errors.has('criteria')">@{{ errors.first('criteria') }}</span>
</div>
<span class="btn btn-primary btn-lg" v-on:click="addCondition">Add Condition</span>
<multiselect v-model="category_values" :close-on-select="false" :options="category_options" :searchable="false" :custom-label="categoryLabel" :show-labels="true" placeholder="Select Categories" track-by="slug" :multiple="true"></multiselect>
</div>
<div class="condition-set" v-if="conditions_list.length">
<!-- Attribute -->
<div v-for="(condition, index) in conditions_list" :key="index">
<div class="control-container mt-20" v-if='conditions_list[index].criteria == "attribute"'>
<div class="title-bar">
{{-- <span>Group </span>
<input type="checkbox" v-model="condition_groups" v-on:click="groupSelected(index)" /> --}}
<label class="mb-10" for="attributes">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Attribute']) }}</label>
<span>Attribute is </span>
<span class="icon cross-icon" v-on:click="removeAttr(index)"></span>
</div>
<br/>
<div class="control-group mt-10" :key="index">
<select class="control" name="attributes[]" v-model="conditions_list[index].attribute" v-validate="'required'" title="You Can Make Multiple Selections Here" style="margin-right: 15px;" v-on:change="enableCondition($event, index)">
<option disabled="disabled">Select attribute</option>
<option v-for="(attr_ip, i) in attrs_input" :value="attr_ip.code">@{{ attr_ip.name }}</option>
</select>
<!-- Product attributes conditions block -->
<div class="control-container mt-20" v-for="(condition, index) in attribute_values" :key="index">
<select class="control" v-model="attribute_values[index].attribute" style="margin-right: 15px; width: 30%;" v-on:change="enableAttributeCondition($event, index)">
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
<div v-if='conditions_list[index].type == "text" || conditions_list[index].type == "textarea"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['text'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<input type="text" class="control" name="attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value">
</div>
<div v-if='conditions_list[index].type == "price"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['numeric'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<input type="number" step="0.1000" class="control" name="attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value">
</div>
<div v-else-if='conditions_list[index].type == "boolean"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
<option selected="selected">is</option>
</select>
<select class="control" name="attributes[]" v-model="conditions_list[index].value">
@foreach($catalog_rule[4]['boolean'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
</div>
<div v-else-if='conditions_list[index].type == "date"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['numeric'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<date>
<input type="text" class="control" v-model="conditions_list[index].value" name="attributes[]" v-validate="'required'" value="Enter Value">
</date>
</div>
<div v-else-if='conditions_list[index].type == "datetime"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['numeric'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<datetime>
<input type="text" class="control" v-model="conditions_list[index].value" name="attributes[]" v-validate="'required'" value="Enter Value">
</datetime>
</div>
<div v-else-if='conditions_list[index].type == "select" || conditions_list[index].type == "multiselect"'>
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['text'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<select class="control" v-model="conditions_list[index].value" name="attributes[]" v-validate="'required'" multiple>
<option v-for="option in conditions_list[index].options" :value="option.id">@{{ option.admin_name }}</option>
</select>
</div>
</div>
</div>
<div class="control-container mt-20" v-if='conditions_list[index].criteria == "category"'>
<div class="title-bar">
<span>Category </span>
{{-- <span>Group </span>
<input type="checkbox" v-model="condition_groups" v-on:click="groupSelected(index)" /> --}}
<span class="icon cross-icon" v-on:click="removeAttr(index)"></span>
</div>
<div class="control-group mt-10" :key="index">
<input type="hidden" class="control" name="attributes[]" v-model="conditions_list[index].category" v-validate="'required'" style="margin-right: 15px;" v-on:change="enableCondition($event, index)">
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['text'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<select class="control" name="attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value" multiple>
<option v-for="(category, index) in categories" :value="category.id">@{{ category.name }}</option>
</select>
</div>
</div>
<div class="control-container mt-20" v-if='conditions_list[index].criteria == "attribute_family"'>
<div class="title-bar">
<span>Attribute Family </span>
{{-- <span>Group </span>
<input type="checkbox" v-model="condition_groups" v-on:click="groupSelected(index)" /> --}}
<span class="icon cross-icon" v-on:click="removeAttr(index)"></span>
</div>
<div class="control-group mt-10" :key="index">
<input type="hidden" class="control" name="attributes[]" v-model="conditions_list[index].family" v-validate="'required'" style="margin-right: 15px;" v-on:change="enableCondition($event, index)">
<select class="control" name="attributes[]" v-model="conditions_list[index].condition" v-validate="'required'" style="margin-right: 15px;">
@foreach($catalog_rule[4]['boolean'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
</select>
<select class="control" name="attributes[]" v-model="conditions_list[index].value" placeholder="Enter Value">
<option v-for="(attr_family, index) in attr_families" :value="attr_family.id">@{{ attr_family.name }}</option>
</select>
</div>
</div>
</div>
<input type="hidden" name="all_conditions[]" v-model="all_conditions">
</div>
</div>
</accordian>
<accordian :active="true" title="Actions">
<div slot="body">
<div class="control-group" :class="[errors.has('apply') ? 'has-error' : '']">
<label for="apply" class="required">Apply</label>
<select class="control" name="apply" v-model="apply" v-validate="'required'" value="{{ old('apply') }}" data-vv-as="&quot;Apply As&quot;" v-on:change="detectApply">
@foreach($catalog_rule[3]['actions'] as $key => $value)
<option value="{{ $key }}">{{ __($value) }}</option>
@endforeach
<option v-for="(attr_ip, index1) in attribute_input" :value="attr_ip.code" :key="index1">@{{ attr_ip.name }}</option>
</select>
<span class="control-error" v-if="errors.has('apply')">@{{ errors.first('apply') }}</span>
<select v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
<option v-for="(condition, index) in conditions.select" :value="index" :key="index">@{{ condition }}</option>
</select>
<select v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price"' class="control" v-model="attribute_values[index].condition" style="margin-right: 15px;">
<option v-for="(condition, index) in conditions.string" :value="index" :key="index">@{{ condition }}</option>
</select>
<div v-show='attribute_values[index].type == "select" || attribute_values[index].type == "multiselect"' style="display: flex;">
<select class="control" v-model="attribute_values[index].value" style="margin-right: 15px; height: 100px" :multiple="true">
<option :disabled="true">
{{ __('ui::form.select-attribute', ['attribute' => 'Values']) }}
</option>
<option v-for="(label, index2) in attribute_values[index].options" :value="index2" :key="index2">@{{ label.admin_name }}</option>
</select>
{{-- <multiselect v-model="attribute_values[index].value" :close-on-select="false" :options="attribute_values[index].options" :searchable="false" :track-by="admin_name" :custom-label="attributeListLabel" :multiple="true" ></multiselect> --}}
</div>
<div v-show='attribute_values[index].type == "text" || attribute_values[index].type == "textarea" || attribute_values[index].type == "price" || attribute_values[index].type == "textarea"' style="display: flex">
<input class="control" v-model="attribute_values[index].value" type="text" placeholder="{{ __('ui::form.enter-attribute', ['attribute' => 'Text']) }}">
</div>
<span class="icon trash-icon" v-on:click="removeAttr(index)"></span>
</div>
<div class="control-group" :class="[errors.has('disc_amount') ? 'has-error' : '']" v-if="apply_amt">
<span class="btn btn-primary btn-lg mt-20" v-on:click="addAttributeCondition">{{ __('admin::app.promotion.add-attr-condition') }}</span>
</div>
</accordian>
<accordian :active="false" title="{{ __('admin::app.promotion.actions') }}">
<div slot="body">
<div class="control-group" :class="[errors.has('action_type') ? 'has-error' : '']">
<label for="action_type" class="required">{{ __('admin::app.promotion.general-info.apply') }}</label>
<select class="control" name="action_type" v-model="action_type" v-validate="'required'" value="{{ old('action_type') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.apply') }}&quot;" v-on:change="detectApply">
<option v-for="(action, index) in actions" :value="index">@{{ action }}</option>
</select>
<span class="control-error" v-if="errors.has('action_type')">@{{ errors.first('action_type') }}</span>
</div>
<div class="control-group" :class="[errors.has('disc_amount') ? 'has-error' : '']">
<label for="disc_amount" class="required">{{ __('admin::app.promotion.general-info.disc_amt') }}</label>
<input type="number" step="1.0000" class="control" name="disc_amount" v-model="disc_amount" v-validate="'required|decimal|min_value:0.0001'" value="{{ old('disc_amount') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.disc_amt') }}&quot;">
<input type="number" step="0.5000" class="control" name="disc_amount" v-model="disc_amount" v-validate="'required|min_value:0.0001'" value="{{ old('disc_amount') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.disc_amt') }}&quot;">
<span class="control-error" v-if="errors.has('disc_amount')">@{{ errors.first('disc_amount') }}</span>
</div>
<div class="control-group" :class="[errors.has('disc_percent') ? 'has-error' : '']" v-if="apply_prct">
<label for="disc_percent" class="required">{{ __('admin::app.promotion.general-info.disc_percent') }}</label>
<div class="control-group" :class="[errors.has('end_other_rules') ? 'has-error' : '']">
<label for="end_other_rules" class="required">{{ __('admin::app.promotion.general-info.end-other-rules') }}</label>
<input type="number" step="0.5000" class="control" name="disc_percent" v-model="disc_percent" v-validate="'required|decimal|min_value:0.0001'" value="{{ old('disc_percent') }}" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.disc_percent') }}&quot;">
<select type="text" class="control" name="end_other_rules" v-model="end_other_rules" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.promotion.general-info.end-other-rules') }}&quot;">
<option disabled="disabled">{{ __('admin::app.promotion.select-attribute', ['attribute' => 'Option']) }}</option>
<option value="1">{{ __('admin::app.promotion.yes') }}</option>
<option value="0">{{ __('admin::app.promotion.no') }}</option>
</select>
<span class="control-error" v-if="errors.has('disc_percent')">@{{ errors.first('disc_percent') }}</span>
<span class="control-error" v-if="errors.has('end_other_rules')">@{{ errors.first('end_other_rules') }}</span>
</div>
</div>
</accordian>
@ -340,143 +218,133 @@
data () {
return {
all_conditions: [],
apply: null,
apply_amt: false,
apply_prct: false,
applied_config: @json($catalog_rule[3]),
name: '{{ $catalog_rule[5]->name }}',
description: '{{ $catalog_rule[5]->description }}',
conditions_list: [],
attr_families: @json($catalog_rule[8]),
attrs_input: @json($catalog_rule[0]),
attrs_options: @json($catalog_rule[2]),
global_condition: {
all_conditions: false,
all_condition: true
channels: [],
customer_groups: [],
ends_till: '{{ $catalog_rule[5]->ends_till }}',
starts_from: '{{ $catalog_rule[5]->starts_from }}',
status: '{{ $catalog_rule[5]->status }}',
actions: @json($catalog_rule[3]).actions,
action_type: '{{ $catalog_rule[5]->action_code }}',
disc_amount: '{{ $catalog_rule[5]->disc_amount }}',
end_other_rules: '{{ $catalog_rule[5]->end_other_rules }}',
all_conditions: [],
all_attributes: {
'categories' : null,
'attributes' : null
},
criteria: 'cart',
category_options: @json($catalog_rule[1]),
category_values: [],
conditions: @json($catalog_rule[3]).conditions,
attribute_values: [],
attr_object: {
criteria: 'attribute',
attribute: null,
condition: null,
type: null,
value: null
value: [],
options: []
},
cat_object: {
criteria: 'category',
category: 'category',
condition: null,
value: []
},
fam_object: {
criteria: 'attribute_family',
family: 'attribute_family',
condition: null,
value: null
},
categories: @json($catalog_rule[1]),
cats: [],
cats_count: 0,
channels: [],
conditions: [],
criteria: null,
customer_groups: [],
description: null,
disc_amount: 0.0,
disc_percent: 0.0,
ends_till: null,
end_other_rules: null,
name: null,
priority: 0,
starts_from: null,
status: null,
attribute_input: @json($catalog_rule[0])
}
},
mounted () {
all = @json($catalog_rule[5]);
this.name = all.name;
this.description = all.description;
this.apply = all.action_type;
this.end_other_rules = all.end_other_rules;
this.criteria = 'attribute';
console.log(this.conditions)
channels = @json($catalog_rule[5]->channels);
channels = @json($catalog_rule[6]);
this.channels = [];
for (i in channels) {
this.channels.push(channels[i].channel_id);
}
customer_groups = @json($catalog_rule[7]);
customer_groups = @json($catalog_rule[5]->customer_groups);
for (i in customer_groups) {
this.customer_groups.push(customer_groups[i].customer_group_id);
}
this.conditions_list = JSON.parse(JSON.parse(all.conditions)[0]);
this.status = @json($catalog_rule[5]).status;
this.starts_from = @json($catalog_rule[5]).starts_from;
this.ends_till = @json($catalog_rule[5]).ends_till;
this.priority = @json($catalog_rule[5]).priority;
data = @json($catalog_rule[5]->conditions);
if (this.apply == 0 || this.apply == 2) {
this.apply_prct = true;
if (JSON.parse(JSON.parse(data))) {
this.category_values = JSON.parse(JSON.parse(data)).categories;
this.disc_percent = @json($catalog_rule[5]).disc_percent;
} else if (this.apply == 1 || this.apply == 3) {
this.apply_amt = true;
this.attribute_values = JSON.parse(JSON.parse(data)).attributes;
this.disc_amount = @json($catalog_rule[5]).disc_amount;
// creating options and has option param on the frontend
for (i in this.attribute_values) {
for (j in this.attribute_input) {
if (this.attribute_input[j].code == this.attribute_values[i].attribute) {
if (this.attribute_input[j].has_options == true) {
this.attribute_values[i].has_options = true;
this.attribute_values[i].options = this.attribute_input[j].options;
} else {
this.attribute_values[i].has_options = false;
this.attribute_values[i].options = null;
}
}
}
}
}
this.action_type = '{{ $catalog_rule[5]->action_code }}',
this.disc_amount = '{{ $catalog_rule[5]->discount_amount }}',
this.end_other_rules = '{{ $catalog_rule[5]->end_other_rules }}'
},
methods: {
addCondition () {
if (this.criteria == 'attribute' || this.criteria == 'attribute_family' || this.criteria == 'category') {
this.condition_on = this.criteria;
} else {
alert('please try again');
return false;
}
if (this.condition_on == 'attribute') {
this.conditions_list.push(this.attr_object);
this.attr_object = {
criteria: this.condition_on,
attribute: null,
condition: null,
value: null,
type: null,
options: null
};
} else if (this.condition_on == 'category') {
this.conditions_list.push(this.cat_object);
this.cat_object = {
criteria: this.condition_on,
category: 'category',
condition: null,
value: []
};
} else if (this.condition_on == 'attribute_family') {
this.conditions_list.push(this.fam_object);
this.fam_object = {
criteria: this.condition_on,
family: 'attribute_family',
condition: null,
value: null
};
}
created() {
VeeValidate.Validator.extend('is_time', {
getMessage: field => `The format must be HH:MM:SS`,
validate: (value) => new Promise(resolve => {
let regex = new RegExp("([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])");
resolve({
valid: value && regex.test(value)
});
})
});
},
enableCondition(event, index) {
this.conditions_list[index].type = this.attrs_input[event.target.selectedIndex - 1].type;
categoryLabel (option) {
return option.name + ' [ ' + option.slug + ' ]';
},
var this_this = this;
attributeListLabel(option) {
return option.label;
},
if (this.attrs_input[event.target.selectedIndex - 1].type == 'select' || this.attrs_input[event.target.selectedIndex - 1].type == 'multiselect') {
this.conditions_list[index].options = this.attrs_options[this.attrs_input[event.target.selectedIndex - 1].name];
addAttributeCondition() {
this.attribute_values.push(this.attr_object);
this.conditions_list[index].value = [];
this.attr_object = {
attribute: null,
condition: null,
value: [],
options: []
};
},
enableAttributeCondition (event, index) {
selectedIndex = event.target.selectedIndex - 1;
for(i in this.attribute_input) {
if (i == selectedIndex) {
if (this.attribute_input[i].has_options == true) {
this.attribute_values[index].options = this.attribute_input[i].options;
}
this.attribute_values[index].type = this.attribute_input[i].type;
debugger
}
}
},
@ -491,41 +359,49 @@
},
removeAttr(index) {
this.conditions_list.splice(index, 1);
this.attribute_values.splice(index, 1);
},
removeCat(index) {
this.cats.splice(index, 1);
},
onSubmit: function (e) {
if (this.attribute_values.length > 0 || this.category_values.length > 0) {
for (i in this.attribute_values) {
delete this.attribute_values[i].options;
}
if (this.category_values.length > 0) {
this.all_attributes.categories = this.category_values;
}
this.all_attributes.attributes = this.attribute_values;
this.all_conditions = JSON.stringify(this.all_attributes);
} else {
this.all_conditions = null;
}
// this.all_conditions = JSON.stringify(this.conditions_list);
// if (this.conditions_list.length != 0) {
// this.conditions_list.push({'criteria': this.match_criteria});
// this.all_conditions = JSON.stringify(this.conditions_list);
// }
// return false;
this.$validator.validateAll().then(result => {
if (result) {
e.target.submit();
}
});
},
for (index in this.conditions_list) {
if (this.conditions_list[index].condition == null || this.conditions_list[index].condition == "" || this.conditions_list[index].condition == undefined) {
window.flashMessages = [{'type': 'alert-error', 'message': "{{ __('admin::app.promotion.catalog.condition-missing') }}" }];
this.$root.addFlashMessages();
return false;
} else if (this.conditions_list[index].value == null || this.conditions_list[index].value == "" || this.conditions_list[index].value == undefined) {
window.flashMessages = [{'type': 'alert-error', 'message': "{{ __('admin::app.promotion.catalog.condition-missing') }}" }];
this.$root.addFlashMessages();
return false;
}
}
if (this.conditions_list.length == 0) {
window.flashMessages = [{'type': 'alert-error', 'message': "{{ __('admin::app.promotion.catalog.condition-missing') }}" }];
this.$root.addFlashMessages();
return false;
}
this.all_conditions = JSON.stringify(this.conditions_list);
genericGroupCondition() {
this.generic_condition = false;
},
addFlashMessages() {

View File

@ -8,7 +8,7 @@
<div class="content full-page">
<form method="POST" action="{{ route('admin.sales.invoices.store', $order->id) }}" @submit.prevent="onSubmit">
@csrf()
<div class="page-header">
<div class="page-title">
<h1>
@ -18,7 +18,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.sales.invoices.save-btn-title') }}
</button>
@ -38,7 +38,7 @@
<div class="section-content">
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.invoices.order-id') }}
</span>
@ -48,11 +48,11 @@
</div>
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.orders.order-date') }}
</span>
<span class="value">
<span class="value">
{{ $order->created_at }}
</span>
</div>
@ -61,7 +61,7 @@
<span class="title">
{{ __('admin::app.sales.orders.order-status') }}
</span>
<span class="value">
{{ $order->status_label }}
</span>
@ -71,7 +71,7 @@
<span class="title">
{{ __('admin::app.sales.orders.channel') }}
</span>
<span class="value">
{{ $order->channel_name }}
</span>
@ -86,21 +86,21 @@
<div class="section-content">
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.orders.customer-name') }}
</span>
<span class="value">
<span class="value">
{{ $order->customer_full_name }}
</span>
</div>
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.orders.email') }}
</span>
<span class="value">
<span class="value">
{{ $order->customer_email }}
</span>
</div>
@ -119,9 +119,9 @@
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->billing_address])
</div>
</div>
@ -132,13 +132,13 @@
</div>
<div class="section-content">
@include ('admin::sales.address', ['address' => $order->shipping_address])
</div>
</div>
@endif
</div>
</accordian>
@ -152,21 +152,21 @@
<div class="section-content">
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.orders.payment-method') }}
</span>
<span class="value">
<span class="value">
{{ core()->getConfigData('sales.paymentmethods.' . $order->payment->method . '.title') }}
</span>
</div>
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.orders.currency') }}
</span>
<span class="value">
<span class="value">
{{ $order->order_currency_code }}
</span>
</div>
@ -180,21 +180,21 @@
<div class="section-content">
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.orders.shipping-method') }}
</span>
<span class="value">
<span class="value">
{{ $order->shipping_title }}
</span>
</div>
<div class="row">
<span class="title">
<span class="title">
{{ __('admin::app.sales.orders.shipping-price') }}
</span>
<span class="value">
<span class="value">
{{ core()->formatBasePrice($order->base_shipping_amount) }}
</span>
</div>

View File

@ -18,7 +18,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.sales.shipments.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.channels.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.channels.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.currencies.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.currencies.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.exchange_rates.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.exchange_rates.save-btn-title') }}
</button>

View File

@ -15,6 +15,16 @@
<a href="{{ route('admin.exchange_rates.create') }}" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.exchange_rates.add-title') }}
</a>
@php
$defaultService = config('services.exchange-api.default');
@endphp
{{-- <a href="{{ route('admin.exchange_rates.update-rates', $defaultService) }}" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.exchange_rates.update-rates', [
'service' => $defaultService
]) }}
</a> --}}
</div>
</div>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.inventory_sources.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.inventory_sources.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.locales.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.locales.save-btn-title') }}
</button>

View File

@ -16,7 +16,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.sliders.save-btn-title') }}
</button>

View File

@ -16,7 +16,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.sliders.save-btn-title') }}
</button>

View File

@ -16,7 +16,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action-slight">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.tax-categories.save-btn-title') }}
</button>

View File

@ -16,7 +16,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action-slight">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.tax-categories.save-btn-title') }}
</button>

View File

@ -16,7 +16,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action-slight">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.tax-rates.save-btn-title') }}
</button>

View File

@ -16,7 +16,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action-slight">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.settings.tax-rates.edit-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action-slight">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.users.roles.save-btn-title') }}
</button>

View File

@ -17,7 +17,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action-slight">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.users.roles.save-btn-title') }}
</button>
@ -54,7 +54,7 @@
<option value="all" {{ $role->permission_type == 'all' ? 'selected' : '' }}>{{ __('admin::app.users.roles.all') }}</option>
</select>
</div>
<div class="control-group tree-wrapper {{ $role->permission_type == 'all' ? 'hide' : '' }}">
<tree-view value-field="key" id-field="key" items='@json($acl->items)' value='@json($role->permissions)'></tree-view>
</div>
@ -75,7 +75,7 @@
} else {
$('.tree-wrapper').addClass('hide')
}
})
});
</script>

View File

@ -16,7 +16,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action-slight">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.users.users.save-btn-title') }}
</button>

View File

@ -16,7 +16,7 @@
</h1>
</div>
<div class="page-action">
<div class="page-action fixed-action-slight">
<button type="submit" class="btn btn-lg btn-primary">
{{ __('admin::app.users.users.save-btn-title') }}
</button>

View File

@ -43,7 +43,8 @@ class AttributeGroupTableSeeder extends Seeder
['attribute_id' => '21','attribute_group_id' => '5','position' => '3'],
['attribute_id' => '22','attribute_group_id' => '5','position' => '4'],
['attribute_id' => '23','attribute_group_id' => '1','position' => '9'],
['attribute_id' => '24','attribute_group_id' => '1','position' => '10']
['attribute_id' => '24','attribute_group_id' => '1','position' => '10'],
['attribute_id' => '25','attribute_group_id' => '1','position' => '11']
]);
}
}

View File

@ -59,6 +59,8 @@ class AttributeTableSeeder extends Seeder
['id' => '23','code' => 'color','admin_name' => 'Color','type' => 'select','validation' => NULL,'position' => '23','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '1','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '24','code' => 'size','admin_name' => 'Size','type' => 'select','validation' => NULL,'position' => '24','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '1','is_configurable' => '1','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '25','code' => 'brand','admin_name' => 'Brand','type' => 'text','validation' => NULL,'position' => '25','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_visible_on_front' => '1',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now]
]);
@ -87,7 +89,8 @@ class AttributeTableSeeder extends Seeder
['id' => '21','locale' => 'en','name' => 'Depth','attribute_id' => '21'],
['id' => '22','locale' => 'en','name' => 'Weight','attribute_id' => '22'],
['id' => '23','locale' => 'en','name' => 'Color','attribute_id' => '23'],
['id' => '24','locale' => 'en','name' => 'Size','attribute_id' => '24']
['id' => '24','locale' => 'en','name' => 'Size','attribute_id' => '24'],
['id' => '25','locale' => 'en','name' => 'Brand','attribute_id' => '25']
]);
}
}

View File

@ -221,12 +221,26 @@ class AttributeRepository extends Repository
foreach($attributes as $key => $attribute) {
if ($attribute->code != 'tax_category_id' && ($attribute->type == 'select' || $attribute->type == 'multiselect' || $attribute->code == 'sku')) {
array_push($trimmed, [
'id' => $attribute->id,
'name' => $attribute->name,
'type' => $attribute->type,
'code' => $attribute->code
]);
if ($attribute->options()->exists()) {
array_push($trimmed, [
'id' => $attribute->id,
'name' => $attribute->admin_name,
'type' => $attribute->type,
'code' => $attribute->code,
'has_options' => true,
'options' => $attribute->options
]);
} else {
array_push($trimmed, [
'id' => $attribute->id,
'name' => $attribute->admin_name,
'type' => $attribute->type,
'code' => $attribute->code,
'has_options' => false,
'options' => null
]);
}
}
}

View File

@ -0,0 +1,27 @@
{
"name": "bagisto/laravel-cms",
"license": "MIT",
"authors": [
{
"name": "Prashant Singh",
"email": "prashant.singh852@webkul.com"
}
],
"require": {
"konekt/concord": "^1.2"
},
"autoload": {
"psr-4": {
"Webkul\\CMS\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Webkul\\CMS\\Providers\\CMSServiceProvider"
],
"aliases": {}
}
},
"minimum-stability": "dev"
}

View File

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

View File

@ -0,0 +1,43 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCmsPagesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('cms_pages', function (Blueprint $table) {
$table->increments('id');
$table->string('url_key')->unique();
$table->longtext('html_content');
$table->string('page_title');
$table->string('meta_title');
$table->text('meta_description')->nullable();
$table->text('meta_keywords')->nullable();
$table->json('content')->nullable();
$table->string('layout')->nullable();
$table->integer('channel_id')->unsigned();
$table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
$table->integer('locale_id')->unsigned();
$table->foreign('locale_id')->references('id')->on('locales')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('cms_pages');
}
}

View File

@ -0,0 +1,222 @@
<?php
namespace Webkul\CMS\Http\Controllers\Admin;
use Webkul\CMS\Http\Controllers\Controller;
use Webkul\CMS\Repositories\CMSRepository as CMS;
use Webkul\Core\Repositories\ChannelRepository as Channel;
use Webkul\Core\Repositories\LocaleRepository as Locale;
/**
* CMS controller
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class PageController extends Controller
{
/**
* To hold the request variables from route file
*/
protected $_config;
/**
* To hold the channel reposotry instance
*/
protected $channel;
/**
* To hold the locale reposotry instance
*/
protected $locale;
/**
* To hold the CMSRepository instance
*/
protected $cms;
public function __construct(Channel $channel, Locale $locale, CMS $cms)
{
/**
* Pass the class instance through admin middleware
*/
$this->middleware('auth:admin');
/**
* Channel repository instance
*/
$this->channel = $channel;
/**
* Locale repository instance
*/
$this->locale = $locale;
/**
* CMS repository instance
*/
$this->cms = $cms;
$this->_config = request('_config');
}
/**
* Loads the index page showing the static pages resources
*/
public function index()
{
return view($this->_config['view']);
}
/**
* To create a new CMS page
*
* @return view
*/
public function create()
{
return view($this->_config['view']);
}
/**
* To store a new CMS page in storage
*
* @return view
*/
public function store()
{
$this->validate(request(), [
'channel' => 'required|string',
'locale' => 'required|string',
'url_key' => 'required|unique:cms_pages,url_key',
'html_content' => 'required|string',
'page_title' => 'required|string',
'meta_title' => 'required|string',
'meta_description' => 'string',
'meta_keywords' => 'required|string'
]);
$data = request()->all();
$data['content']['html'] = $data['html_content'];
$data['content']['page_title'] = $data['page_title'];
$data['content']['meta_keywords'] = $data['meta_keywords'];
$data['content']['meta_title'] = $data['meta_title'];
$data['content']['meta_description'] = $data['meta_description'];
$data['content'] = json_encode($data['content']);
$result = $this->cms->create($data);
if ($result) {
session()->flash('success', trans('admin::app.cms.pages.create-success'));
} else {
session()->flash('success', trans('admin::app.cms.pages.create-failure'));
}
return redirect()->route($this->_config['redirect']);
}
/**
* To edit a previously created CMS page
*
* @return view
*/
public function edit($id)
{
$page = $this->cms->findOrFail($id);
return view($this->_config['view'])->with('page', $page);
}
/**
* To update the previously created CMS page in storage
*
* @return view
*/
public function update($id)
{
$page = $this->cms->findOrFail($id);
$this->validate(request(), [
'channel' => 'required|string',
'locale' => 'required|string',
'url_key' => 'required|unique:cms_pages,url_key,'.$id,
'html_content' => 'required|string',
'page_title' => 'required|string',
'meta_title' => 'required|string',
'meta_description' => 'string',
'meta_keywords' => 'required|string'
]);
$data = request()->all();
$data['content']['html'] = $data['html_content'];
$data['content']['page_title'] = $data['page_title'];
$data['content']['meta_keywords'] = $data['meta_keywords'];
$data['content']['meta_title'] = $data['meta_title'];
$data['content']['meta_description'] = $data['meta_description'];
$data['content'] = json_encode($data['content']);
$result = $this->cms->update($data, $id);
if ($result) {
session()->flash('success', trans('admin::app.cms.pages.update-success'));
} else {
session()->flash('success', trans('admin::app.cms.pages.update-failure'));
}
return redirect()->route($this->_config['redirect']);
}
/**
* To preview the content of the currently creating page or previously creating page
*
* @return mixed
*/
public function preview($urlKey)
{
$page = $this->cms->findOneWhere([
'url_key' => $urlKey
]);
return view('shop::cms.page')->with('page', $page);
}
/**
* To delete the previously create CMS page
*
* @return json
*/
public function delete($id)
{
$page = $this->cms->findOrFail($id);
if ($page->delete()) {
session()->flash('success', trans('admin::app.cms.pages.delete-success'));
return response()->json(['message' => true], 200);
} else {
session()->flash('success', trans('admin::app.cms.pages.delete-failure'));
return response()->json(['message' => false], 200);
}
}
/**
* To extract the page content and load it in the respective view file\
*
* @return view
*/
public function presenter($slug)
{
$page = $this->cms->findOneWhere([
'url_key' => $slug
]);
$layout = $page->layout;
return view('shop::cms.page')->with('data', $page);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Webkul\CMS\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
class Controller extends BaseController
{
use DispatchesJobs, ValidatesRequests;
}

View File

@ -0,0 +1,85 @@
<?php
namespace Webkul\CMS\Http\Controllers\Shop;
use Webkul\CMS\Http\Controllers\Controller;
use Webkul\CMS\Repositories\CMSRepository as CMS;
use Webkul\Core\Repositories\ChannelRepository as Channel;
use Webkul\Core\Repositories\LocaleRepository as Locale;
/**
* PagePresenter controller
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class PagePresenterController extends Controller
{
/**
* To hold the request variables from route file
*/
protected $_config;
/**
* To hold the channel reposotry instance
*/
protected $channel;
/**
* To hold the locale reposotry instance
*/
protected $locale;
/**
* To hold the CMSRepository instance
*/
protected $cms;
public function __construct(Channel $channel, Locale $locale, CMS $cms)
{
/**
* Channel repository instance
*/
$this->channel = $channel;
/**
* Locale repository instance
*/
$this->locale = $locale;
/**
* CMS repository instance
*/
$this->cms = $cms;
$this->_config = request('_config');
}
/**
* To extract the page content and load it in the respective view file\
*
* @return view
*/
public function presenter($slug)
{
$currentChannel = core()->getCurrentChannel();
$currentLocale = app()->getLocale();
$currentLocale = $this->locale->findOneWhere([
'code' => $currentLocale
]);
$page = $this->cms->findOneWhere([
'url_key' => $slug,
'locale_id' => $currentLocale->id,
'channel_id' => $currentChannel->id
]);
if ($page) {
return view('shop::cms.page')->with('page', $page);
} else {
abort(404);
}
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Webkul\CMS\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\CMS\Contracts\CMS as CMSContract;
class CMS extends Model implements CMSContract
{
protected $table = 'cms_pages';
protected $fillable = ['content', 'meta_description', 'meta_title', 'page_title', 'meta_keywords', 'html_content', 'url_key', 'layout', 'channel_id', 'locale_id'];
}

View File

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

View File

@ -0,0 +1,17 @@
<?php
namespace Webkul\CMS\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Routing\Router;
use Webkul\CMS\Providers\ModuleServiceProvider;
class CMSServiceProvider extends ServiceProvider
{
public function boot(Router $router)
{
$this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'cms');
$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Webkul\CMS\Providers;
use Konekt\Concord\BaseModuleServiceProvider;
class ModuleServiceProvider extends BaseModuleServiceProvider
{
protected $models = [
\Webkul\CMS\Models\CMS::class
];
}

View File

@ -0,0 +1,64 @@
<?php
namespace Webkul\CMS\Repositories;
use Webkul\Core\Eloquent\Repository;
use Illuminate\Container\Container as App;
use Webkul\Core\Repositories\ChannelRepository as Channel;
use Webkul\Core\Repositories\LocaleRepository as Locale;
/**
* CMS Reposotory
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CMSRepository extends Repository
{
/**
* To hold the channel reposotry instance
*/
protected $channel;
/**
* To hold the locale reposotry instance
*/
protected $locale;
public function __construct(Channel $channel, Locale $locale, App $app)
{
$this->channel = $channel;
$this->locale = $locale;
parent::__construct($app);
}
/**
* Specify Model class name
*
* @return mixed
*/
function model()
{
return 'Webkul\CMS\Contracts\CMS';
}
public function create(array $data)
{
$channel = $this->channel->findOneByField('code', $data['channel']);
$locale = $this->locale->findOneByField('code', $data['locale']);
$data['channel_id'] = $channel->id;
$data['locale_id'] = $locale->id;
$result = $this->model->create($data);
if ($result) {
return true;
} else {
return false;
}
}
}

View File

@ -222,7 +222,7 @@ class CategoryRepository extends Repository
}
}
public function getPartial()
public function getPartial($columns = null)
{
$categories = $this->model->all();
$trimmed = array();
@ -231,7 +231,8 @@ class CategoryRepository extends Repository
if ($category->name != null || $category->name != "") {
$trimmed[$key] = [
'id' => $category->id,
'name' => $category->name
'name' => $category->name,
'slug' => $category->slug
];
}
}

View File

@ -15,8 +15,10 @@ return [
\Webkul\Core\Providers\ModuleServiceProvider::class,
\Webkul\Customer\Providers\ModuleServiceProvider::class,
\Webkul\Inventory\Providers\ModuleServiceProvider::class,
\Webkul\Product\Providers\ModuleServiceProvider::class,\Webkul\Sales\Providers\ModuleServiceProvider::class,
\Webkul\Product\Providers\ModuleServiceProvider::class,
\Webkul\Sales\Providers\ModuleServiceProvider::class,
\Webkul\Tax\Providers\ModuleServiceProvider::class,
\Webkul\User\Providers\ModuleServiceProvider::class,\Webkul\Discount\Providers\ModuleServiceProvider::class,
\Webkul\User\Providers\ModuleServiceProvider::class,
\Webkul\Discount\Providers\ModuleServiceProvider::class,
]
];

View File

@ -394,9 +394,9 @@ class Core
if (is_null($amount))
$amount = 0;
$formater = new \NumberFormatter( app()->getLocale(), \NumberFormatter::CURRENCY );
$formatter = new \NumberFormatter( app()->getLocale(), \NumberFormatter::CURRENCY );
return $formater->formatCurrency($this->convertPrice($amount), $this->getCurrentCurrency()->code);
return $formatter->formatCurrency($this->convertPrice($amount), $this->getCurrentCurrency()->code);
}
/**
@ -424,9 +424,9 @@ class Core
if (is_null($price))
$price = 0;
$formater = new \NumberFormatter( app()->getLocale(), \NumberFormatter::CURRENCY );
$formatter = new \NumberFormatter( app()->getLocale(), \NumberFormatter::CURRENCY );
return $formater->formatCurrency($price, $currencyCode);
return $formatter->formatCurrency($price, $currencyCode);
}
/**
@ -439,10 +439,10 @@ class Core
{
if (is_null($price))
$price = 0;
$formater = new \NumberFormatter( app()->getLocale(), \NumberFormatter::CURRENCY );
return $formater->formatCurrency($price, $this->getBaseCurrencyCode());
$formatter = new \NumberFormatter( app()->getLocale(), \NumberFormatter::CURRENCY );
return $formatter->formatCurrency($price, $this->getBaseCurrencyCode());
}
/**

View File

@ -0,0 +1,10 @@
<?php
namespace Webkul\Core\Helpers\Exchange;
abstract class ExchangeRate
{
abstract public function fetchRates();
abstract public function UpdateRates();
}

View File

@ -0,0 +1,56 @@
<?php
namespace Webkul\Core\Helpers\Exchange;
use Webkul\Core\Helpers\Exchange\ExchangeRate;
use Webkul\Core\Repositories\ExchangeRateRepository;
class FixerExchange extends ExchangeRate
{
/**
* API key
*/
protected $apiKey;
/**
* API endpoint
*/
protected $apiEndPoint;
/**
* Holds ExchangeRateRepository instance
*/
protected $exchangeRate;
public function __construct()
{
$this->apiKey = config('services.exchange-api')['fixer']['key'];
$this->apiEndPoint = 'http://data.fixer.io/api/latest?access_key='.$this->apiKey;
}
public function fetchRates()
{
$rates = array();
$this->exchangeRate = app('Webkul\Core\Repositories\ExchangeRateRepository');
// dummy api call
$client = new \GuzzleHttp\Client();
if (config('services.exchange-api')['fixer']['paid_account']) {
$result = $client->request('GET', 'http://data.fixer.io/api/'.date('Y-m-d').'?access_key='.$this->apiKey.'&base='.core()->getBaseCurrency()->code.'&symbols=INR');
} else {
$result = $client->request('GET', 'http://data.fixer.io/api/'.date('Y-m-d').'?access_key='.$this->apiKey.'&symbols=USD');
}
$result = json_decode($result->getBody()->getContents());
return $result;
}
public function updateRates()
{
}
}

View File

@ -5,7 +5,6 @@ namespace Webkul\Core\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Event;
use Webkul\Core\Repositories\ExchangeRateRepository as ExchangeRate;
use Webkul\Core\Repositories\CurrencyRepository as Currency;
/**
@ -23,13 +22,6 @@ class ExchangeRateController extends Controller
*/
protected $_config;
/**
* ExchangeRateRepository object
*
* @var array
*/
protected $exchangeRate;
/**
* CurrencyRepository object
*
@ -44,10 +36,8 @@ class ExchangeRateController extends Controller
* @param \Webkul\Core\Repositories\CurrencyRepository $currency
* @return void
*/
public function __construct(ExchangeRate $exchangeRate, Currency $currency)
public function __construct(Currency $currency)
{
$this->exchangeRate = $exchangeRate;
$this->currency = $currency;
$this->_config = request('_config');
@ -139,6 +129,42 @@ class ExchangeRateController extends Controller
return redirect()->route($this->_config['redirect']);
}
/**
* Update Rates Using Exchange Rates API
*
* @return void
*/
public function updateRates($service)
{
$exchangeService = config('services.exchange-api')[$service];
if (is_array($exchangeService)) {
if (! array_key_exists('class', $exchangeService)) {
return response()->json([
'success' => false,
'rates' => null,
'error' => trans('admin::app.exchange-rate.exchange-class-not-found', [
'service' => $service
])
], 400);
}
$exchangeServiceInstance = new $exchangeService['class'];
$updatedRates = $exchangeServiceInstance->fetchRates();
return response()->json([
'success' => true,
'rates' => 'rates'
], 200);
} else {
return response()->json([
'success' => false,
'rates' => null,
'error' => trans('admin::app.exchange-rate.invalid-config')
], 400);
}
}
/**
* Remove the specified resource from storage.
*

View File

@ -0,0 +1,7 @@
<?php
return [
'slug' => ':attribute باید نامک معتبر داشته باشد.',
'code' => ':attribute باید معتبر باشد.',
'decimal' => ':attribute باید معتبر باشد.'
];

View File

@ -14,7 +14,7 @@ class AddCodeColumnInCustomerGroupsTable extends Migration
public function up()
{
Schema::table('customer_groups', function (Blueprint $table) {
$table->string('code');
$table->string('code')->unique();
});
}

View File

@ -11,9 +11,10 @@ use Auth;
use Hash;
/**
* Customer controlller for the customer basically for the tasks of customers which will be done after customer authentication.
* Customer controlller for the customer basically for the tasks of customers which will be
* done after customer authentication.
*
* @author Prashant Singh <prashant.singh852@webkul.com>
* @author Prashant Singh <prashant.singh852@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class CustomerController extends Controller

View File

@ -31,6 +31,7 @@ class VerificationEmail extends Mailable
public function build()
{
return $this->to($this->verificationData['email'])
->from(env('SHOP_MAIL_FROM'))
->subject('Verification email')
->view('shop::emails.customer.verification-email')->with('data', ['email' => $this->verificationData['email'], 'token' => $this->verificationData['token']]);
}

View File

@ -28,6 +28,19 @@ class Customer extends Authenticatable implements CustomerContract, JWTSubject
return ucfirst($this->first_name) . ' ' . ucfirst($this->last_name);
}
/**
* Email exists or not
*/
public function emailExists($email) {
$results = $this->where('email', $email);
if ($results->count() == 0) {
return false;
} else {
return true;
}
}
/**
* Get the customer group that owns the customer.
*/

View File

@ -21,6 +21,7 @@ class CustomerResetPassword extends ResetPassword
}
return (new MailMessage)
->from(env('SHOP_MAIL_FROM'))
->subject(__('shop::app.mail.forget-password.subject') )
->view('shop::emails.customer.forget-password', [
'user_name' => $notifiable->name,

View File

@ -1,8 +0,0 @@
Discount Condition:
Attribute Family is all the attributes
Cart Attribute such as
base_total,
grand_total,
shipping_free,
shipping_not_free,

View File

@ -4,7 +4,5 @@ namespace Webkul\Discount\Actions;
abstract class Action
{
abstract public function calculate($rule, $item, $cart);
abstract public function calculateOnShipping($cart);
abstract public function calculate($rule);
}

View File

@ -1,52 +0,0 @@
<?php
namespace Webkul\Discount\Actions;
use Webkul\Discount\Actions\Action;
class BuyAGetB extends Action
{
public function calculate($rule, $item, $cart)
{
//calculate discount amount
$action_type = $rule->action_type; // action type used
$disc_threshold = $rule->disc_threshold; // atleast quantity by default 1
$disc_amount = $rule->disc_amount; // value of discount
$disc_quantity = $rule->disc_quantity; //max quantity allowed to be discounted
$amountDiscounted = 0;
$realQty = $item['quantity'];
if ($cart->items_qty >= $disc_threshold) {
$amountDiscounted = $disc_amount;
if ($realQty > $disc_quantity) {
$amountDiscounted = $amountDiscounted * $disc_quantity;
} else {
$amountDiscounted = $amountDiscounted * $realQty;
}
if ($amountDiscounted > $item['base_price'] && $realQty == 1) {
$amountDiscounted = $item['base_price'];
}
}
$report['discount'] = $amountDiscounted;
$report['formatted_discount'] = core()->currency($amountDiscounted);
return $report;
}
/**
* Calculates the impact on the shipping amount if the rule is apply_to_shipping enabled
*/
public function calculateOnShipping($cart)
{
$percentOfDiscount = ($cart->base_discount_amount * 100) / $cart->base_grand_total;
$discountOnShipping = ($percentOfDiscount / 100) * $cart->selected_shipping_rate->base_price;
return $discountOnShipping;
}
}

View File

@ -0,0 +1,73 @@
<?php
namespace Webkul\Discount\Actions\Cart;
use Webkul\Discount\Actions\Action;
class FixedAmount extends Action
{
public function calculate($rule)
{
$cart = \Cart::getCart();
$items = $cart->items;
$impact = collect();
$impact->discount = $rule->disc_amount;
$impact->formatted_discount = core()->currency($impact->discount);
if ($rule->uses_attribute_conditions) {
$productIDs = $rule->product_ids;
$productIDs = explode(',', $productIDs);
$matchCount = 0;
foreach ($productIDs as $productID) {
foreach ($items as $item) {
if ($item->product_id == $productID) {
$matchCount++;
}
}
}
if ($matchCount > 0) {
$discountPerItem = $impact->discount / $matchCount;
}
foreach ($productIDs as $productID) {
foreach ($items as $item) {
if ($item->product_id == $productID) {
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = round($discountPerItem, 4);
$report['formatted_discount'] = core()->currency(round($discountPerItem, 4));
$impact->push($report);
unset($report);
}
}
}
} else {
$discountPerItem = $impact->discount / $cart->items_qty;
foreach ($items as $item) {
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = round($discountPerItem, 4);
$report['formatted_discount'] = core()->currency(round($discountPerItem, 4));
$impact->push($report);
unset($report);
}
}
return $impact;
}
}

View File

@ -0,0 +1,99 @@
<?php
namespace Webkul\Discount\Actions\Cart;
use Webkul\Discount\Actions\Action;
class PercentOfProduct extends Action
{
public function calculate($rule)
{
$cart = \Cart::getCart();
$items = $cart->items;
$impact = collect();
$totalDiscount = 0;
if ($rule->discount_amount >= 100) {
$impact->discount = $cart->base_sub_total;
$impact->formatted_discount = core()->currency($impact->discount);
} else {
if ($rule->uses_attribute_conditions) {
$productIDs = $rule->product_ids;
$productIDs = explode(',', $productIDs);
$matchCount = 0;
foreach ($productIDs as $productID) {
foreach ($items as $item) {
if ($item->product_id == $productID) {
$matchCount++;
}
}
}
foreach ($productIDs as $productID) {
foreach ($items as $item) {
$itemPrice = $item->base_price;
if ($item->product->type == 'configurable') {
$itemProductId = $item->child->product_id;
} else {
$itemProductId = $item->product_id;
}
$discount = round(($itemPrice * $rule->disc_amount) / 100, 4);
if ($itemProductId == $productID) {
$totalDiscount = $totalDiscount + $discount;
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->child ? $item->child->product_id : $item->product_id;
$report['discount'] = $discount;
$report['formatted_discount'] = core()->currency($discount);
$impact->push($report);
unset($report);
}
}
}
} else {
foreach ($items as $item) {
$itemPrice = $item->base_price;
if ($item->product->type == 'configurable') {
$itemProductId = $item->child->product_id;
} else {
$itemProductId = $item->product_id;
}
$discount = round(($itemPrice * $rule->disc_amount) / 100, 4);
$totalDiscount = $totalDiscount + $discount;
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->child ? $item->child->product_id : $item->product_id;
$report['discount'] = $discount;
$report['formatted_discount'] = core()->currency($discount);
$impact->push($report);
unset($report);
}
}
}
$impact->discount = $totalDiscount;
$impact->formatted_discount = core()->currency($impact->discount);
return $impact;
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace Webkul\Discount\Actions\Cart;
use Webkul\Discount\Actions\Action;
class WholeCartToFixed extends Action
{
public function calculate($rule)
{
$cart = \Cart::getCart();
$items = $cart->items;
$impact = collect();
$impact->discount = $rule->disc_amount;
$impact->formatted_discount = core()->currency($impact->discount);
if ($rule->uses_attribute_conditions) {
$productIDs = $rule->product_ids;
$productIDs = explode(',', $productIDs);
$matchCount = 0;
foreach ($productIDs as $productID) {
foreach ($items as $item) {
if ($item->product_id == $productID) {
$matchCount++;
}
}
}
foreach ($productIDs as $productID) {
foreach ($items as $item) {
$itemPrice = $item->base_price;
if ($item->product->type == 'configurable') {
$itemProductId = $item->child->product_id;
} else {
$itemProductId = $item->product_id;
}
$discount = round(($itemPrice * $impact->discount) / 100, 4);
if ($itemProductId == $productID) {
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = $discount;
$report['formatted_discount'] = core()->currency($discount);
$impact->push($report);
unset($report);
}
}
}
} else {
foreach ($items as $item) {
$itemPrice = $item->base_price;
if ($item->product->type == 'configurable') {
$itemProductId = $item->child->product_id;
} else {
$itemProductId = $item->product_id;
}
$discount = round(($itemPrice * $impact->discount) / 100, 4);
$report = array();
$report['item_id'] = $item->id;
$report['product_id'] = $item->product_id;
$report['discount'] = $discount;
$report['formatted_discount'] = core()->currency($discount);
$impact->push($report);
unset($report);
}
}
return $impact;
}
}

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