Resolved conflicts

This commit is contained in:
jitendra 2019-08-19 16:01:38 +05:30
commit e2bd18e916
244 changed files with 8649 additions and 2565 deletions

View File

@ -30,9 +30,12 @@ MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
SHOP_MAIL_FROM=shop@bagsaas.com
ADMIN_MAIL_TO=admin@bagsaas.com
fixer_api_key=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=

1
.gitignore vendored
View File

@ -19,3 +19,4 @@ yarn-error.log
composer.lock
yarn.lock
package-lock.json
yarn.lock

View File

@ -10,15 +10,15 @@
<a href="#sponsors"><img src="https://opencollective.com/bagisto/sponsors/badge.svg" alt="Sponsors on Open Collective"></a>
</p>
# Topics
1. ### [Introduction](#1-introduction-)
2. ### [Documentation](#2-documentation-)
3. ### [Requirements](#2-requirements-)
4. ### [Installation & Configuration](#3-installation--configuration-)
5. ### [License](#4-license-)
6. ### [Miscellaneous](#5-miscellaneous-)
## Topics
1. [Introduction](#introduction)
2. [Documentation](#documentation)
3. [Requirements](#requirements)
4. [Installation & Configuration](#installation-and-configuration)
5. [License](#license)
6. [Miscellaneous](#miscellaneous)
### 1. Introduction <a name="#1-introduction-"></a>:
### Introduction
[Bagisto](https://www.bagisto.com) is a hand tailored E-Commerce framework designed on some of the hottest opensource technologies
such as [Laravel](https://laravel.com) a [PHP](https://secure.php.net/) framework, [Vue.js](https://vuejs.org)
@ -54,14 +54,14 @@ It packs in lots of demanding features that allows your business to scale in no
Dev guys can take advantage of two of the hottest frameworks used in this project Laravel and Vue.js, both of these frameworks have been used in Bagisto.
Bagisto is using power of both of these frameworks and making best out of it out of the box.
### 2. Documentation <a name="#-documentation-"></a>:
### Documentation
#### Bagisto Documentation [https://devdocs.bagisto.com](https://devdocs.bagisto.com)
### 3. Requirements <a name="#requirements"></a>:
### Requirements
* **OS**: Ubuntu 16.04 LTS or higher.
* **SERVER**: Apache 2 or NGINX
* **OS**: Ubuntu 16.04 LTS or higher / Windows 7 or Higher (WAMP / XAMP).
* **SERVER**: Apache 2 or NGINX.
* **RAM**: 3 GB or higher.
* **PHP**: 7.1.17 or higher.
* **Processor**: Clock Cycle 1 Ghz or higher.
@ -70,13 +70,13 @@ Bagisto is using power of both of these frameworks and making best out of it out
* **Node**: 8.11.3 LTS or higher.
* **Composer**: 1.6.5 or higher.
### 4. Installation & Configuration <a name="#configuration"></a>:
### Installation and Configuration
**1. Try our new GUI installer to install Bagisto:**
##### a. Download zip from the link below:
[Download](https://github.com/bagisto/bagisto/archive/v0.1.5.zip)
[Download](https://github.com/bagisto/bagisto/archive/v0.1.6.zip)
##### b. Extract the contents of zip and execute the project in browser:
@ -172,36 +172,26 @@ password:admin123
> *http(s)://example.com/customer/register*
### 5. License <a name="#license"></a>:
### License
Bagisto is a truly opensource E-Commerce framework which will always be free under the [MIT License](https://github.com/bagisto/bagisto/blob/master/LICENSE).
### 6. Miscellaneous <a name="#miscellaneous"></a>:
### Miscellaneous
#### Contributors
This project exists thanks to all the people who contribute.
<a href="https://github.com/bagisto/bagisto/graphs/contributors"><img src="https://opencollective.com/bagisto/contributors.svg?width=890&button=false" /></a>
This project is on [Open Collective](https://opencollective.com/bagisto) and it exists thanks to this people who contribute.
<a href="https://github.com/bagisto/bagisto/graphs/contributors"><img src="https://opencollective.com/bagisto/contributors.svg?width=890&button=false"/></a>
#### Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/bagisto#backer)]
<a href="https://opencollective.com/bagisto#backers" target="_blank"><img src="https://opencollective.com/bagisto/backers.svg?width=890"></a>
Thank you to all our backers! 🙏
<a href="https://opencollective.com/bagisto#contributors" target="_blank"><img src="https://opencollective.com/bagisto/backers.svg?width=890"></a>
#### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/bagisto#sponsor)]
Support this project by becoming a sponsor. Your logo will show up here with a link to your website.
<a href="https://opencollective.com/bagisto/sponsor/0/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/sponsor/1/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/sponsor/2/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/sponsor/3/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/sponsor/4/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/sponsor/5/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/sponsor/6/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/sponsor/7/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/sponsor/8/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/sponsor/9/website" target="_blank"><img src="https://opencollective.com/bagisto/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/bagisto/contribute/sponsor-7372/checkout" target="_blank"><img src="https://images.opencollective.com/static/images/become_sponsor.svg"></a>

View File

@ -10,6 +10,7 @@
"require": {
"php": "^7.1.3",
"ext-curl": "*",
"ext-intl": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-pdo": "*",
@ -20,6 +21,7 @@
"doctrine/dbal": "^2.9@dev",
"fideloper/proxy": "^4.0",
"flynsarmy/db-blade-compiler": "*",
"guzzlehttp/guzzle": "~6.0",
"intervention/image": "^2.4",
"intervention/imagecache": "^2.3",
"kalnoy/nestedset": "^4.3",
@ -87,7 +89,8 @@
"Webkul\\Sales\\": "packages/Webkul/Sales/src",
"Webkul\\Tax\\": "packages/Webkul/Tax/src",
"Webkul\\API\\": "packages/Webkul/API",
"Webkul\\Discount\\": "packages/Webkul/Discount/src"
"Webkul\\Discount\\": "packages/Webkul/Discount/src",
"Webkul\\CMS\\": "packages/Webkul/CMS/src"
}
},
"autoload-dev": {
@ -97,7 +100,9 @@
},
"extra": {
"laravel": {
"dont-discover": []
"dont-discover": [
"barryvdh/laravel-debugbar"
]
}
},
"scripts": {

View File

@ -245,7 +245,8 @@ return [
Webkul\Sales\Providers\SalesServiceProvider::class,
Webkul\Tax\Providers\TaxServiceProvider::class,
Webkul\API\Providers\APIServiceProvider::class,
Webkul\Discount\Providers\DiscountServiceProvider::class
Webkul\Discount\Providers\DiscountServiceProvider::class,
Webkul\CMS\Providers\CMSServiceProvider::class
],
/*

View File

@ -19,6 +19,7 @@ return [
\Webkul\Sales\Providers\ModuleServiceProvider::class,
\Webkul\Tax\Providers\ModuleServiceProvider::class,
\Webkul\User\Providers\ModuleServiceProvider::class,
\Webkul\Discount\Providers\ModuleServiceProvider::class
\Webkul\Discount\Providers\ModuleServiceProvider::class,
\Webkul\CMS\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

@ -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

@ -8,14 +8,14 @@ use DB;
/**
* AttributeDataGrid class
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
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

@ -8,8 +8,8 @@ use DB;
/**
* AttributeFamilyDataGrid Class
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class AttributeFamilyDataGrid extends DataGrid
{

View File

@ -0,0 +1,114 @@
<?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', 'channel_id', 'locale_id');
$this->setQueryBuilder($queryBuilder);
}
public function addColumns()
{
$channels = app('Webkul\Core\Repositories\ChannelRepository');
$locales = app('Webkul\Core\Repositories\LocaleRepository');
$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
]);
$this->addColumn([
'index' => 'locale_id',
'label' => trans('admin::app.cms.pages.locale'),
'type' => 'string',
'searchable' => false,
'sortable' => true,
'filterable' => true,
'wrapper' => function($row) use($locales) {
$localeCode = $locales->find($row->locale_id)->code;
return $row->locale_id.' ('. $localeCode. ')';
}
]);
$this->addColumn([
'index' => 'channel_id',
'label' => trans('admin::app.cms.pages.channel'),
'type' => 'number',
'searchable' => false,
'sortable' => true,
'filterable' => true,
'wrapper' => function($row) use($channels) {
$channelCode = $channels->find($row->channel_id)->name;
return $row->channel_id.' ('. $channelCode. ')';
}
]);
}
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'
]);
}
public function prepareMassActions()
{
$this->addMassAction([
'type' => 'delete',
'label' => 'Delete',
'action' => route('admin.cms.mass-delete'),
'method' => 'DELETE'
]);
}
}

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

@ -58,7 +58,7 @@ class CategoryDataGrid extends DataGrid
$this->addColumn([
'index' => 'position',
'label' => trans('admin::app.datagrid.position'),
'type' => 'string',
'type' => 'number',
'searchable' => false,
'sortable' => true,
'filterable' => true

View File

@ -38,7 +38,7 @@ class CustomerGroupDataGrid extends DataGrid
$this->addColumn([
'index' => 'code',
'label' => 'Code',
'type' => 'number',
'type' => 'string',
'searchable' => false,
'sortable' => true,
'filterable' => true

View File

@ -19,7 +19,7 @@ class LocalesDataGrid extends DataGrid
public function prepareQueryBuilder()
{
$queryBuilder = DB::table('locales')->addSelect('id', 'code', 'name');
$queryBuilder = DB::table('locales')->addSelect('id', 'code', 'name', 'direction');
$this->setQueryBuilder($queryBuilder);
}
@ -52,6 +52,15 @@ class LocalesDataGrid extends DataGrid
'sortable' => true,
'filterable' => true
]);
$this->addColumn([
'index' => 'direction',
'label' => trans('admin::app.datagrid.direction'),
'type' => 'string',
'searchable' => true,
'sortable' => true,
'filterable' => true
]);
}
public function prepareActions() {

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

@ -6,6 +6,8 @@ use Webkul\Admin\Http\Controllers\Controller;
use Webkul\Customer\Repositories\CustomerRepository;
use Webkul\Customer\Repositories\CustomerGroupRepository;
use Webkul\Core\Repositories\ChannelRepository;
use Webkul\Admin\Mail\NewCustomerNotification;
use Mail;
/**
* Customer controlller
@ -110,13 +112,15 @@ class CustomerController extends Controller
$data = request()->all();
$password = bcrypt(rand(100000,10000000));
$password = rand(100000,10000000);
$data['password'] = $password;
$data['password'] = bcrypt($password);
$data['is_verified'] = 1;
$this->customerRepository->create($data);
$customer = $this->customerRepository->create($data);
Mail::queue(new NewCustomerNotification($customer, $password));
session()->flash('success', trans('admin::app.response.create-success', ['name' => 'Customer']));

View File

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

View File

@ -452,6 +452,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');
@ -513,21 +515,6 @@ Route::group(['middleware' => ['web']], function () {
Route::put('/account', 'Webkul\User\Http\Controllers\AccountController@update')->name('admin.account.update');
//API Authorizations
// Route::get('/api/clients', 'Webkul\Admin\Http\Controllers\AuthorizationController@show')->defaults('_config', [
// 'view' => 'admin::apiauth.client'
// ])->name('admin.index.oauth.client');
// //view an OAuth API Client
// Route::get('/api/clients/view/{id}', 'Webkul\Admin\Http\Controllers\AuthorizationController@view')->defaults('_config', [
// 'view' => 'admin::apiauth.view'
// ])->name('admin.view.oauth.client');
// //edit an OAuth API Client
// Route::get('/api/clients/delete/{id}', 'Webkul\Admin\Http\Controllers\AuthorizationController@delete')->defaults('_config', [
// 'view' => 'admin::apiauth.edit'
// ])->name('admin.delete.oauth.client');
// Admin Store Front Settings Route
Route::get('/subscribers','Webkul\Core\Http\Controllers\SubscriptionController@index')->defaults('_config',[
@ -632,33 +619,37 @@ 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::get('/catalog-rules/declutter', 'Webkul\Discount\Http\Controllers\CatalogRuleController@deClutter')->defaults('_config', [
'redirect' => 'admin.catalog-rule.index'
])->name('admin.catalog-rule.declut');
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'
@ -682,6 +673,42 @@ 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');
Route::post('/massdelete', 'Webkul\CMS\Http\Controllers\Admin\PageController@massDelete')->defaults('_config', [
'redirect' => 'admin.cms.index'
])->name('admin.cms.mass-delete');
// Route::post('/delete/{id}', 'Webkul\CMS\Http\Controllers\Admin\PageController@delete')->defaults('_config', [
// 'redirect' => 'admin.cms.index'
// ])->name('admin.cms.delete');
});
});
});
});

View File

@ -0,0 +1,57 @@
<?php
namespace Webkul\Admin\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
/**
* New Admin Mail class
*
* @author Rahul Shukla <rahulshukla.symfony517@webkul.com>
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class NewCustomerNotification extends Mailable
{
use Queueable, SerializesModels;
/**
* The customer instance.
*
* @var customer
*/
public $customer;
/**
* The password instance.
*
* @var password
*/
public $password;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($customer, $password)
{
$this->customer = $customer;
$this->password = $password;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->to($this->customer->email)
->subject(trans('shop::app.mail.customer.subject'))
->view('shop::emails.customer.new-customer')->with(['customer' => $this->customer, 'password' => $this->password]);
}
}

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' => [
@ -107,6 +108,7 @@ return [
'delete-success' => 'Selected index of :resource were successfully deleted',
'partial-action' => 'Some actions were not performed due restricted system constraints on :resource',
'update-success' => 'Selected index of :resource were successfully updated',
'no-resource' => 'The resource provided for insufficient for the action'
],
'id' => 'ID',
@ -114,6 +116,7 @@ return [
'code' => 'Code',
'admin-name' => 'Name',
'name' => 'Name',
'direction' => 'Direction',
'fullname' => 'Full Name',
'type' => 'Type',
'required' => 'Required',
@ -126,6 +129,8 @@ return [
'email' => 'Email',
'group' => 'Group',
'title' => 'Title',
'layout' => 'Layout',
'url-key' => 'URL Key',
'comment' => 'Comment',
'product-name' => 'Product',
'currency-name' => 'Currency Name',
@ -187,7 +192,6 @@ return [
],
'reset-password' => [
'title' => 'Reset Password',
'title' => 'Reset Password',
'email' => 'Registered Email',
'password' => 'Password',
@ -411,7 +415,8 @@ return [
'searching' => 'Searching ...',
'grouped-products' => 'Grouped Products',
'search-products' => 'Search Products',
'no-result-found' => 'Products not found with same name.'
'no-result-found' => 'Products not found with same name.',
'channel' => 'Channels'
],
'attributes' => [
@ -461,7 +466,9 @@ return [
'text-swatch' => 'Text Swatch',
'swatch' => 'Swatch',
'image' => 'Image',
'file' => 'File'
'file' => 'File',
'checkbox' => 'Checkbox',
'use_in_flat' => "Create in Product Flat Table",
],
'families' => [
'title' => 'Families',
@ -505,6 +512,8 @@ return [
'meta_description' => 'Meta Description',
'meta_keywords' => 'Meta Keywords',
'image' => 'Image',
'filterable-attributes' => 'Filterable Attributes',
'attributes' => 'Attributes',
]
],
@ -576,6 +585,7 @@ return [
'general' => 'General',
'code' => 'Code',
'name' => 'Name',
'direction' => 'Direction',
'create-success' => 'Locale created successfully.',
'update-success' => 'Locale updated successfully.',
'delete-success' => 'Locale deleted successfully.',
@ -612,6 +622,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.',
@ -819,6 +831,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',
@ -830,10 +847,34 @@ 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.',
'declut' => 'Declutter Rules',
'declut-success' => 'Catalog rules decluttering successful',
'declut-failure' => 'Catalog rules decluttering failed',
'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',
@ -868,7 +909,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' => [
@ -953,6 +999,37 @@ 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',
'channel' => 'Channel',
'locale' => 'Locale',
'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',
@ -990,7 +1067,6 @@ return [
'customer' => 'Customer',
'settings' => 'Settings',
'address' => 'Address',
'address' => 'Address',
'street-lines' => 'Lines in a Street Address',
'sales' => 'Sales',
'shipping-methods' => 'Shipping Methods',

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
<?php
return [
'common' => [
'no-result-found' => 'Não conseguimos encontrar nenhum registro.',
@ -8,7 +7,6 @@ return [
'true' => 'Verdadeiro',
'false' => 'Falso'
],
'layouts' => [
'my-account' => 'Minha Conta',
'logout' => 'Sair',
@ -39,9 +37,10 @@ return [
'sliders' => 'Sliders',
'taxes' => 'Impostos',
'tax-categories' => 'Categorias de Impostos',
'tax-rates' => 'Impostos de Impostos'
'tax-rates' => 'Impostos de Impostos',
'promotion' => 'Promoções',
'discount' => 'Desconto'
],
'acl' => [
'dashboard' => 'Dashboard',
'sales' => 'Vendas',
@ -73,8 +72,9 @@ return [
'edit' => 'Edit',
'create' => 'Add',
'delete' => 'Delete',
'promotions' => 'Promoções',
'cart-rules' => 'Regras do Carrinho'
],
'dashboard' => [
'title' => 'Dashboard',
'from' => 'De',
@ -96,7 +96,6 @@ return [
'stock-threshold' => 'Limite de Estoque',
'qty-left' => ':qty Restante',
],
'datagrid' => [
'mass-ops' => [
'method-error' => 'Erro! Método errado detectado, por favor, verifique a configuração de ação em massa',
@ -104,7 +103,6 @@ return [
'partial-action' => 'Algumas ações não foram executadas devido a restrições restritas do sistema em :resource',
'update-success' => 'O índice selecionado :resource foram atualizados com sucesso',
],
'id' => 'ID',
'status' => 'Status',
'code' => 'Código',
@ -151,8 +149,13 @@ return [
'role' => 'Função',
'sub-total' => 'Sub Total',
'no-of-products' => 'Número de Produtos',
'attribute-family' => 'Família de Atributos',
'starts-from' => 'Começa de',
'ends-till' => 'Termina Até',
'per-cust' => 'Por cliente',
'usage-throttle' => 'Tempos de uso',
'for-guest' => 'Para convidados'
],
'account' => [
'title' => 'Minha Conta',
'save-btn-title' => 'Salvar',
@ -164,7 +167,6 @@ return [
'change-password' => 'Mudar Senha da Conta',
'current-password' => 'Senha Atual'
],
'users' => [
'forget-password' => [
'title' => 'Esqueci Minha Senha',
@ -175,7 +177,6 @@ return [
'back-link-title' => 'Voltar para Login',
'submit-btn-title' => 'Link do E-mail para Recuperar Senha'
],
'reset-password' => [
'title' => 'Resetar Senha',
'email' => 'E-mail Registrado',
@ -184,7 +185,6 @@ return [
'back-link-title' => 'Voltar para Login',
'submit-btn-title' => 'Resetar Senha'
],
'roles' => [
'title' => 'Funções',
'add-role-title' => 'Add Função',
@ -198,7 +198,6 @@ return [
'custom' => 'Personalizado',
'all' => 'Tudo'
],
'users' => [
'title' => 'Usuário',
'add-user-title' => 'Add Usuário',
@ -219,8 +218,11 @@ return [
'delete-last' => 'Ao menos um admin é obrigatório.',
'delete-success' => 'Sucesso! Usuário Deletado',
'incorrect-password' => 'A Senha informada é incorreta!',
'password-match' => 'A senha atual não corresponde.',
'account-save' => 'Alterações na conta salvas com sucesso.',
'login-error' => 'Por favor, verifique suas credenciais e tente novamente.',
'activate-warning' => 'Sua conta ainda está para ser ativada, entre em contato com o administrador.'
],
'sessions' => [
'title' => 'Entrar',
'email' => 'Email',
@ -230,7 +232,6 @@ return [
'submit-btn-title' => 'Entrar'
]
],
'sales' => [
'orders' => [
'title' => 'Pedidos',
@ -285,7 +286,6 @@ return [
'total-due' => 'Total Devido',
'cancel-confirm-msg' => 'Tem certeza que deseja cancelar esse pedido ?'
],
'invoices' => [
'title' => 'Faturas',
'id' => 'Id',
@ -305,9 +305,10 @@ return [
'bill-to' => 'Cobrar de',
'ship-to' => 'Enviar para',
'print' => 'Imprimir',
'order-date' => 'Data do Pedido'
'order-date' => 'Data do Pedido',
'creation-error' => 'A criação de fatura de pedido não é permitida.',
'product-error' => 'A fatura não pode ser criada sem produtos.'
],
'shipments' => [
'title' => 'Entregas',
'id' => 'Id',
@ -328,10 +329,12 @@ return [
'inventory-source' => 'Fonte do Estoque',
'carrier-title' => 'Título da Transportadora',
'tracking-number' => 'Código de Rastreio',
'view-title' => 'Entrega #:shipment_id'
'view-title' => 'Entrega #:shipment_id',
'creation-error' => 'A expedição não pode ser criada para este pedido.',
'order-error' => 'A criação de remessa de pedidos não é permitida.',
'quantity-invalid' => 'A quantidade solicitada é inválida ou não está disponível.'
]
],
'catalog' => [
'products' => [
'title' => 'Produtos',
@ -363,11 +366,6 @@ return [
'add-image-btn-title' => 'Add Imagem',
'mass-delete-success' => 'Todos os índices de produtos selecionados foram excluídos com sucesso',
'mass-update-success' => 'Todo o índice selecionado de produtos foi atualizado com sucesso',
'configurable-error' => 'Please select atleast one configurable attribute.',
'categories' => 'Categories',
'images' => 'Images',
'inventories' => 'Inventories',
'variations' => 'Variations',
'downloadable' => 'Downloadable Information',
'links' => 'Links',
'add-link-btn-title' => 'Add Link',
@ -380,18 +378,22 @@ return [
'url' => 'Url',
'sort-order' => 'Sort Order',
'browse-file' => 'Browse File',
'product-link' => 'Linked Products',
'cross-selling' => 'Cross Selling',
'up-selling' => 'Up Selling',
'related-products' => 'Related Products',
'product-search-hint' => 'Start typing product name',
'no-result-found' => 'Products not found with same name.',
'searching' => 'Searching ...',
'configurable-error' => 'Por favor, selecione pelo menos um atributo configurável.',
'categories' => 'Categorias',
'images' => 'Imagens',
'inventories' => 'Os inventários',
'variations' => 'Variações',
'product-link' => 'Produtos Vinculados',
'cross-selling' => 'Venda cruzada',
'up-selling' => 'Acima de vender',
'related-products' => 'Produtos relacionados',
'product-search-hint' => 'Comece a digitar o nome do produto',
'no-result-found' => 'Produtos não encontrados com o mesmo nome.',
'searching' => 'Procurando ...',
'grouped-products' => 'Grouped Products',
'search-products' => 'Search Products',
'no-result-found' => 'Products not found with same name.'
],
'attributes' => [
'title' => 'Atributos',
'add-title' => 'Add Atributo',
@ -430,7 +432,15 @@ return [
'is_filterable' => 'Usar na navegação em camadas',
'is_configurable' => 'Usar para Criar Produtos Configuráveis',
'admin_name' => 'Admin Nome',
'is_visible_on_front' => 'Visível na página de exibição do produto no front-end'
'is_visible_on_front' => 'Visível na página de exibição do produto no front-end',
'swatch_type' => 'Tipo de amostra',
'dropdown' => 'Suspenso (a)',
'color-swatch' => 'Amostra de cor',
'image-swatch' => 'Amostra de imagem',
'text-swatch' => 'Amostra de texto',
'swatch' => 'Swatch',
'image' => 'Imagem',
'file' => 'Arquivo'
],
'families' => [
'title' => 'Famílias',
@ -476,7 +486,6 @@ return [
'image' => 'Imagem',
]
],
'configuration' => [
'title' => 'Configuração',
'save-btn-title' => 'Salvar',
@ -484,7 +493,6 @@ return [
'yes' => 'Sim',
'no' => 'Não',
'delete' => 'Deletar',
'tax-categories' => [
'title' => 'Categorias de Imposto',
'add-title' => 'Add Categorias de Imposto',
@ -501,7 +509,6 @@ return [
'edit-button-title' => 'Editar Categorias de Imposto'
]
],
'tax-rates' => [
'title' => 'Taxas de Impostos',
'add-title' => 'Add Taxas de Imposto',
@ -521,8 +528,8 @@ return [
'edit-button-title' => 'Editar Taxa'
],
'zip_code' => 'CEP',
'is_zip' => 'Ativar intervalo de CEP'
],
'sales' => [
'shipping-method' => [
'title' => 'Método de Entregas',
@ -533,7 +540,6 @@ return [
]
]
],
'settings' => [
'locales' => [
'title' => 'Idiomas',
@ -543,7 +549,11 @@ return [
'save-btn-title' => 'Salvar Idioma',
'general' => 'Geral',
'code' => 'Código',
'name' => 'Nome'
'name' => 'Nome',
'create-success' => 'Local criado com sucesso.',
'update-success' => 'Localidade atualizada com sucesso.',
'delete-success' => 'Locale excluído com sucesso.',
'last-delete-error' => 'Pelo menos um local é obrigatório.'
],
'countries' => [
'title' => 'Países',
@ -561,7 +571,11 @@ return [
'general' => 'Geral',
'code' => 'Código',
'name' => 'Nome',
'symbol' => 'Símbolo'
'symbol' => 'Símbolo',
'create-success' => 'Moeda criada com sucesso.',
'update-success' => 'Moeda atualizada com sucesso.',
'delete-success' => 'Moeda excluída com sucesso.',
'last-delete-error' => 'Pelo menos uma moeda é necessária.'
],
'exchange_rates' => [
'title' => 'Taxas de Câmbio',
@ -571,7 +585,11 @@ return [
'general' => 'Geral',
'source_currency' => 'Moeda de Origem',
'target_currency' => 'Moeda Alvo',
'rate' => 'Taxa'
'rate' => 'Taxa',
'create-success' => 'Taxa de Câmbio criada com sucesso.',
'update-success' => 'Taxa de Câmbio atualizada com sucesso.',
'delete-success' => 'Taxa de Câmbio excluída com sucesso.',
'last-delete-error' => 'Pelo menos uma taxa de câmbio é necessária.'
],
'inventory_sources' => [
'title' => 'Origens do Estoque',
@ -597,7 +615,11 @@ return [
'priority' => 'Prioridade',
'latitude' => 'Latitude',
'longitude' => 'Longitude',
'status' => 'Status'
'status' => 'Status',
'create-success' => 'Fonte de inventário criada com sucesso.',
'update-success' => 'Fonte de inventário atualizada com sucesso.',
'delete-success' => 'Fonte de inventário excluída com sucesso.',
'last-delete-error' => 'Pelo menos uma fonte de inventário é necessária.'
],
'channels' => [
'title' => 'Canais (Lojas)',
@ -621,9 +643,12 @@ return [
'home_page_content' => 'Conteúdo da Página Inicial',
'footer_content' => 'Conteúdo do Rodapé',
'logo' => 'Logo',
'favicon' => 'Favicon'
'favicon' => 'Favicon',
'create-success' => 'Canal criado com sucesso.',
'update-success' => 'Canal atualizado com sucesso.',
'delete-success' => 'Canal excluído com sucesso.',
'last-delete-error' => 'Pelo menos um canal é necessário.'
],
'sliders' => [
'title' => 'Sliders',
'add-title' => 'Criar Slider',
@ -640,7 +665,6 @@ return [
'delete-success' => 'Não foi possível excluir o slider',
'delete-fail' => 'Slider excluído com sucesso'
],
'tax-categories' => [
'title' => 'Categorias de Imposto',
'add-title' => 'Criar Categoria de Imposto',
@ -663,7 +687,6 @@ return [
'atleast-one' => 'Não é possível excluir a última Categoria de Imposto',
'delete' => 'Categoria de Imposto excluída com sucesso'
],
'tax-rates' => [
'title' => 'Taxas de Impostos',
'add-title' => 'Criar Taxas de Impostos',
@ -692,7 +715,6 @@ return [
'atleast-one' => 'Não é Possível Excluir a Última Taxa de Impostos'
]
],
'customers' => [
'groups' =>[
'add-title' => 'Add Grupo',
@ -705,14 +727,12 @@ return [
'is_user_defined' => 'Usuário Definido',
'yes' => 'Sim'
],
'note' => [
'title' => 'Add Note',
'save-note' => 'Save Note',
'enter-note' => 'Enter Note',
'help-title' => 'Add Note On This Customer'
],
'customers' => [
'add-title' => 'Add Cliente',
'edit-title' => 'Editar Cliente',
@ -733,6 +753,13 @@ return [
'female' => 'Feminino',
'phone' => 'Telefone',
'group-default' => 'Não possível excluir o grupo de cliente.',
'edit-help-title' => 'Editar cliente',
'delete-help-title' => 'Excluir cliente',
'mass-destroy-success' => 'Clientes excluídos com sucesso',
'mass-update-success' => 'Clientes atualizados com sucesso',
'status' => 'Status',
'active' => 'Ativo (a)',
'in-active' => 'Inativo (a)'
],
'reviews' => [
'title' => 'Avaliações',
@ -741,9 +768,9 @@ return [
'status' => 'Status',
'comment' => 'Comentar',
'pending' => 'Pendente',
'approved' => 'Aprovado'
'approved' => 'Aprovado',
'disapproved' => 'Desaprovar'
],
'subscribers' => [
'title' => 'Assinantes de Newletter',
'title-edit' => 'Editar Assinante',
@ -756,12 +783,93 @@ return [
'delete-failed' => 'Erro! Você não pode excluir a inscrição desse usuário',
]
],
'promotion' => [
'catalog-rule' => 'Regras de Catálogo',
'cart-rule' => 'Regras do Carrinho',
'add-catalog-rule' => 'Adicionar regra de catálogo',
'add-cart-rule' => 'Adicionar Regra do Carrinho',
'edit-cart-rule' => 'Editar regra do carrinho',
'edit-catalog-rule' => 'Editar regra do catálogo',
'create-catalog-rule' => 'Criar regra de catálogo',
'create-cart-rule' => 'Criar regra de carrinho',
'save-btn-title' => 'Criar',
'edit-btn-title' => 'Editar',
'save' => 'Salve',
'select-attr' => 'Selecione o atributo',
'select-attr-fam' => 'Selecione a Família de Atributos',
'select-cart-attr' => 'Selecione o atributo Carrinho',
'general-info' => [
'name' => 'Nome da regra',
'description' => 'Descrição',
'starts-from' => 'Começar',
'ends-till' => 'Fim',
'channels' => 'Canais',
'channels-req' => 'Canais',
'cust-groups' => 'Grupos de clientes',
'priority' => 'Prioridade',
'add-condition' => 'Adicionar condições',
'disc_amt' => 'Valor de desconto',
'disc_percent' => 'Porcentagem de desconto',
'is-coupon' => 'Use cupom',
'is-coupon-yes' => 'Sim',
'is-coupon-no' => 'Não',
'uses-per-cust' => 'Usos por cliente',
'all' => 'Todos (a)',
'any' => 'Qualquer',
'end-other-rules' => 'Acabar com outras regras',
'status' => 'Está ativo',
'all-conditions-true' => 'Assumindo que todas as condições sejam verdadeiras',
'assuming' => 'Assumindo',
'any' => 'Qualquer',
'all' => 'Todos (a)',
'conditions' => 'Condições',
'apply' => 'Aplique',
'are' => 'está',
'true' => 'verdade',
'false' => 'falso (a)',
'limit' => 'Limite de uso',
'specific-coupon' => 'Cupom Específico (Cheque) / Gerado Automaticamente (Desmarque)',
'free-shipping' => 'Frete grátis',
'is-guest' => 'Para os hóspedes',
'disc_qty' => 'Max. Quantidade permitida para ser descontado',
'test-mode' => 'Escolha como testar as condições',
'labels' => 'Rótulos'
],
'status' => [
'success' => 'Sucesso! regra criada',
'success-coupon' => 'Sucesso! regra criada junto com o cupom',
'failed' => 'Erro! não conseguiu criar regra',
'update-success' => 'Sucesso! regra atualizada',
'update-coupon-success' => 'Sucesso! regra atualizada junto com cupom',
'update-failed' => 'Erro! não pode atualizar',
'delete-success' => 'Sucesso! regra excluída',
'delete-failed' => 'Erro! não pode apagar',
'coupon-applied' => 'Cupom Usado',
'coupon-failed' => 'O cupom não foi aplicado',
'no-coupon' => '* Cupom não aplicável',
'coupon-removed' => 'Cupom removido com sucesso',
'coupon-remove-failed' => 'Remoção de cupons falhou',
'duplicate-coupon' => 'O cupom já existe, por favor tente novamente com um cupom diferente'
],
'catalog' => [
'name' => 'Nome',
'description' => 'Descrição',
'apply-percent' => 'Aplique como porcentagem',
'apply-fixed' => 'Aplicar como quantia fixa',
'adjust-to-percent' => 'Ajuste para porcentagem',
'adjust-to-value' => 'Ajustar ao valor de desconto',
'condition-missing' => 'Por favor, verifique condições, alguns valores podem estar faltando'
],
'cart' => [
'buy-atleast' => 'Compre Atleast',
'apply-to-shipping' => 'Aplicar ao envio'
]
],
'error' => [
'go-to-home' => 'IR PARA PÁGINA INICIAL',
'in-maitainace' => 'In Maintenance',
'right-back' => 'Be Right Back',
'404' => [
'page-title' => '404 Página não Encontrada',
'name' => '404',
@ -790,14 +898,24 @@ return [
'export' => [
'export' => 'Exportar',
'import' => 'Importar',
'format' => 'Selecione o Formato',
'download' => 'Download',
'upload' => 'Upload',
'csv' => 'CSV',
'xls' => 'XLS'
'xls' => 'XLS',
'file' => 'Arquivo',
'upload-error' => 'O arquivo deve ser um arquivo do tipo: xls, xlsx, csv.',
'duplicate-error' => 'Identificador deve ser único, identificador duplicado :identifier na linha :position.',
'enough-row-error' => 'arquivo não tem linhas suficientes',
'allowed-type' => 'Tipo permitido :',
'file-type' => 'csv, xls, xlsx.',
'no-records' => 'Nada para exportar',
'illegal-format' => 'Erro! Este tipo de formato não é suportado ou seu formato ilegal'
],
'response' => [
'cannot-delete-default' => 'Cannot delete the default channel',
'being-used' => 'Este recurso :name está sendo usado em :source',
'cannot-delete-default' => 'Não é possível excluir o canal padrão',
'create-success' => ':name criado com sucesso.',
'update-success' => ':name atualizaco com sucesso.',
'delete-success' => ':name excluído com sucesso.',
@ -806,6 +924,70 @@ return [
'attribute-error' => ':name é usado em produtos configuráveis.',
'attribute-product-error' => ':name é usado em produtos.',
'customer-associate' => ':name não pode ser excluído porque o cliente está associado a esse grupo.',
'currency-delete-error' => 'Esta moeda é definida como moeda base do canal, então não pode ser excluída.'
'currency-delete-error' => 'Esta moeda é definida como moeda base do canal, então não pode ser excluída.',
'upload-success' => ':name carregado com sucesso.',
'delete-category-root' => 'Não é possível excluir a categoria raiz',
'create-root-failure' => 'A categoria com nome root já existe',
'cancel-success' => ':name cancelado com sucesso.',
'cancel-error' => ':name não pode ser cancelado.',
'already-taken' => 'O :name já foi tomada.'
],
'footer' => [
'copy-right' => '© Copyright '.date('Y').' Webkul Software, Todos os direitos reservados.'
],
'admin' => [
'system' => [
'catalog' => 'Catálogo',
'products' => 'Produtos',
'review' => 'Reveja',
'allow-guest-review' => 'Permitir comentário de convidado',
'inventory' => 'Inventário',
'stock-options' => 'Opções de ações',
'allow-backorders' => 'Permitir atrasos',
'customer' => 'Cliente',
'settings' => 'Definições',
'address' => 'Endereço',
'street-lines' => 'Linhas em um endereço de rua',
'sales' => 'Vendas',
'shipping-methods' => 'Métodos de Envio',
'free-shipping' => 'Frete grátis',
'flate-rate-shipping' => 'Envio de taxa fixa',
'shipping' => 'Remessa',
'origin' => 'Origem',
'country' => 'País',
'state' => 'Estado',
'zip' => 'CEP',
'city' => 'Cidade',
'street-address' => 'Endereço',
'title' => 'Titulo',
'description' => 'Descrição',
'rate' => 'Taxa',
'status' => 'Status',
'type' => 'Tipo',
'payment-methods' => 'Métodos de Pagamento',
'cash-on-delivery' => 'Dinheiro na entrega',
'money-transfer' => 'Transferência de dinheiro',
'paypal-standard' => 'Padrão Paypal',
'business-account' => 'Conta de negócios',
'newsletter' => 'Assinatura de Newsletter',
'newsletter-subscription' => 'Permitir assinatura do NewsLetter',
'email' => 'Verificação de e-mail',
'email-verification' => 'Permitir verificação de e-mail',
'sort_order' => 'Ordem de classificação',
'general' => 'Geral',
'footer' => 'Rodapé',
'content' => 'Conteúdo',
'footer-content' => 'Texto de rodapé',
'locale-options' => 'Opções de unidade',
'weight-unit' => 'Unidade de peso',
'design' => 'Design',
'admin-logo' => 'Admin Logo',
'logo-image' => 'Logo Imagem',
'credit-max' => 'Máximo de crédito do cliente',
'credit-max-value' => 'Valor Máximo de Crédito',
'use-credit-max' => 'Use o máximo de crédito'
]
]
];

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>
@ -36,7 +36,7 @@
{!! view_render_event('bagisto.admin.catalog.attribute.create_form_accordian.general.controls.before') !!}
<div class="control-group" :class="[errors.has('code') ? 'has-error' : '']">
<label for="code">{{ __('admin::app.catalog.attributes.code') }}</label>
<label for="code" class="required">{{ __('admin::app.catalog.attributes.code') }}</label>
<input type="text" v-validate="'required'" class="control" id="code" name="code" value="{{ old('code') }}" data-vv-as="&quot;{{ __('admin::app.catalog.attributes.code') }}&quot;" v-code/>
<span class="control-error" v-if="errors.has('code')">@{{ errors.first('code') }}</span>
</div>
@ -54,6 +54,7 @@
<option value="date">{{ __('admin::app.catalog.attributes.date') }}</option>
<option value="image">{{ __('admin::app.catalog.attributes.image') }}</option>
<option value="file">{{ __('admin::app.catalog.attributes.file') }}</option>
<option value="checkbox">{{ __('admin::app.catalog.attributes.checkbox') }}</option>
</select>
</div>
@ -204,6 +205,14 @@
</select>
</div>
<div class="control-group">
<label for="use_in_flat">{{ __('admin::app.catalog.attributes.use_in_flat') }}</label>
<select class="control" id="use_in_flat" name="use_in_flat">
<option value="0">{{ __('admin::app.catalog.attributes.no') }}</option>
<option value="1">{{ __('admin::app.catalog.attributes.yes') }}</option>
</select>
</div>
{!! view_render_event('bagisto.admin.catalog.attribute.create_form_accordian.configuration.controls.after') !!}
</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>
@ -77,6 +77,9 @@
<option value="file" {{ $selectedOption == 'file' ? 'selected' : '' }}>
{{ __('admin::app.catalog.attributes.file') }}
</option>
<option value="file" {{ $selectedOption == 'checkbox' ? 'selected' : '' }}>
{{ __('admin::app.catalog.attributes.checkbox') }}
</option>
</select>
<input type="hidden" name="type" value="{{ $attribute->type }}"/>
</div>
@ -263,6 +266,18 @@
</select>
</div>
<div class="control-group">
<label for="use_in_flat">{{ __('admin::app.catalog.attributes.use_in_flat') }}</label>
<select class="control" id="use_in_flat" name="use_in_flat">
<option value="0" {{ $attribute->use_in_flat ? '' : 'selected' }}>
{{ __('admin::app.catalog.attributes.no') }}
</option>
<option value="1" {{ $attribute->use_in_flat ? 'selected' : '' }}>
{{ __('admin::app.catalog.attributes.yes') }}
</option>
</select>
</div>
{!! view_render_event('bagisto.admin.catalog.attribute.edit_form_accordian.configuration.controls.after', ['attribute' => $attribute]) !!}
</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.catalog.categories.save-btn-title') }}
</button>
@ -136,6 +136,23 @@
@endif
<accordian :title="'{{ __('admin::app.catalog.categories.filterable-attributes') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('attributes[]') ? 'has-error' : '']">
<label for="attributes" class="required">{{ __('admin::app.catalog.categories.attributes') }}</label>
<select class="control" name="attributes[]" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.catalog.categories.attributes') }}&quot;" multiple>
@foreach ($attributes as $attribute)
<option value="{{ $attribute->id }}">
{{ $attribute->name ? $attribute->name : $attribute->admin_name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('attributes[]')">
@{{ errors.first('attributes[]') }}
</span>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.admin.catalog.category.create_form_accordian.seo.before') !!}

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)
@ -148,6 +148,23 @@
@endif
<accordian :title="'{{ __('admin::app.catalog.categories.filterable-attributes') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('attributes[]') ? 'has-error' : '']">
<label for="attributes" class="required">{{ __('admin::app.catalog.categories.attributes') }}</label>
<select class="control" name="attributes[]" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.catalog.categories.attributes') }}&quot;" multiple>
@foreach ($attributes as $attribute)
<option value="{{ $attribute->id }}" {{ in_array($attribute->id, $category->filterableAttributes->pluck('id')->toArray()) ? 'selected' : ''}}>
{{ $attribute->name ? $attribute->name : $attribute->admin_name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('attributes[]')">
@{{ errors.first('attributes[]') }}
</span>
</div>
</div>
</accordian>
{!! view_render_event('bagisto.admin.catalog.category.edit_form_accordian.seo.before', ['category' => $category]) !!}

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

@ -0,0 +1,27 @@
@inject ('productFlatRepository', 'Webkul\Product\Repositories\ProductFlatRepository')
<?php
$productChannels = $productFlatRepository->findWhere([
'product_id' => $product->id
])->pluck('channel')->unique()->toArray();
?>
<accordian :title="'{{ __('admin::app.catalog.products.channel') }}'" :active="true">
<div slot="body">
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
<label for="channels" class="required">{{ __('admin::app.catalog.products.channel') }}</label>
<select class="control" name="channels[]" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.catalog.products.channel') }}&quot;" multiple>
@foreach (app('Webkul\Core\Repositories\ChannelRepository')->all() as $channel)
<option value="{{ $channel->id }}" {{ in_array($channel->code, $productChannels) ? 'selected' : ''}}>
{{ $channel->name }}
</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('channels[]')">
@{{ errors.first('channels[]') }}
</span>
</div>
</div>
</accordian>

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,13 @@
<div class="control-group" style="margin-top: 5px;">
@foreach ($attribute->options as $option)
<span class="checkbox" style="margin-top: 5px;">
<input type="checkbox" name="{{ $attribute->code }}[]" value="{{ $option->id }}" {{ in_array($option->id, explode(',', $product[$attribute->code])) ? 'checked' : ''}}>
</input>
<label class="checkbox-view"></label>
{{ $option->admin_name }}
</span>
@endforeach
</div>

View File

@ -0,0 +1,146 @@
@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>
<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('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('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>
@inject('channels', 'Webkul\Core\Repositories\ChannelRepository')
@inject('locales', 'Webkul\Core\Repositories\LocaleRepository')
<div class="control-group" :class="[errors.has('channels[]') ? 'has-error' : '']">
<label for="url-key" class="required">{{ __('admin::app.cms.pages.channel') }}</label>
<select type="text" class="control" name="channels[]" v-validate="'required'" value="{{ old('channel[]') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.channel') }}&quot;" multiple="multiple">
@foreach($channels->all() as $channel)
<option value="{{ $channel->id }}">{{ $channel->name }}</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('channels[]')">@{{ errors.first('channels[]') }}</span>
</div>
<div class="control-group" :class="[errors.has('locales[]') ? 'has-error' : '']">
<label for="url-key" class="required">{{ __('admin::app.cms.pages.locale') }}</label>
<select type="text" class="control" name="locales[]" v-validate="'required'" value="{{ old('locale[]') }}" data-vv-as="&quot;{{ __('admin::app.cms.pages.locale') }}&quot;" multiple="multiple">
@foreach($locales->all() as $locale)
<option value="{{ $locale->id }}">{{ $locale->name }}</option>
@endforeach
</select>
<span class="control-error" v-if="errors.has('locales[]')">@{{ errors.first('locales[]') }}</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('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,132 @@
@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>
<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('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('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;" disabled>
<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('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->id) }}';
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);
@ -61,28 +61,28 @@
}
if (! isset($field['options'])) {
$field['options'] = [['title' => 'No', 'value' => 0],['title' => 'Yes', 'value' => 1]];
$field['options'] = '';
}
$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 }}'"
:depend = "'{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $dependField }}]'"
:value = "'{{ $dependValue }}'"
:field_name = "'{{ $field['title'] }}'"
:channel_loacle = "'{{ $channel_locale }}'"
:channel_locale = "'{{ $channel_locale }}'"
:result = "'{{ $selectedOption }}'"
></depands>
></depends>
@else
<div class="control-group {{ $field['type'] }}" @if ($field['type'] == 'multiselect') :class="[errors.has('{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}][]') ? 'has-error' : '']" @else :class="[errors.has('{{ $firstField }}[{{ $secondField }}][{{ $thirdField }}][{{ $field['name'] }}]') ? 'has-error' : '']" @endif>
<label for="{{ $name }}" {{ !isset($field['validation']) || strpos('required', $field['validation']) === false ? '' : 'class=required' }}>
<label for="{{ $name }}" {{ !isset($field['validation']) || preg_match('/\brequired\b/', $field['validation']) == false ? '' : 'class=required' }}>
{{ trans($field['title']) }}
@ -94,19 +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) ?? '';
@ -123,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'];
}
@ -140,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) ?? '';
@ -157,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'];
}
@ -198,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) ?? '';
@ -227,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;">
@ -254,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;">
@ -270,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
@ -391,19 +392,22 @@
});
</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-validate= "validations" class="control" :id = "name" :name = "name" v-model="this.result"
<select v-if="this.options.length" v-validate= "validations" class="control" :id = "name" :name = "name" v-model="this.result"
:data-vv-as="field_name">
<option v-for='(option, index) in this.options' :value="option.value"> @{{ option.title }} </option>
</select>
<input v-else type="text" class="control" v-validate= "validations" :id = "name" :name = "name" v-model="this.result"
:data-vv-as="field_name">
<span class="control-error" v-if="errors.has(name)">
@{{ errors.first(name) }}
</span>
@ -412,51 +416,61 @@
</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 {
isVisible: false,
isRequire: false,
isVisible: false,
}
},
created: function () {
mounted: function () {
var this_this = this;
if (this_this.validations || (this_this.validations.indexOf("required") != -1)) {
this_this.isRequire = true;
}
$(document).ready(function () {
var dependentElement = document.getElementById(this_this.depand);
var depandValue = this_this.value;
$(document).ready(function(){
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;
}
dependentElement.onchange = function() {
if (dependentElement.value == depandValue) {
$(document).on("change", "select.control", function() {
if (this_this.depend == this.name) {
if (this_this.value == this.value) {
this_this.isVisible = true;
} else {
this_this.isVisible = false;
}
}
})
if (dependentElement && dependentElement.value == dependValue) {
this_this.isVisible = true;
} else {
this_this.isVisible = false;
}
if (this_this.result) {
if (dependentElement.value == this_this.value) {
this_this.isVisible = true;
} else {
this_this.isVisible = false;
}
}
if (dependentElement.value == depandValue) {
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

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

View File

@ -19,7 +19,7 @@
</head>
<body @if (app()->getLocale() == 'ar') class="rtl" @endif style="scroll-behavior: smooth;">
<body @if (core()->getCurrentLocale()->direction == 'rtl') class="rtl" @endif style="scroll-behavior: smooth;">
{!! view_render_event('bagisto.admin.layout.body.before') !!}
<div id="app">
@ -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

@ -2,7 +2,11 @@
<div class="navbar-top-left">
<div class="brand-logo">
<a href="{{ route('admin.dashboard.index') }}">
<img src="{{ asset('vendor/webkul/ui/assets/images/logo.png') }}" alt="Bagisto"/>
@if (core()->getConfigData('general.design.admin_logo.logo_image'))
<img src="{{ \Illuminate\Support\Facades\Storage::url(core()->getConfigData('general.design.admin_logo.logo_image')) }}" alt="Bagisto" style="height: 40px; width: 110px;"/>
@else
<img src="{{ asset('vendor/webkul/ui/assets/images/logo.png') }}" alt="Bagisto"/>
@endif
</a>
</div>
</div>

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

@ -13,12 +13,16 @@
</div>
<div class="page-action">
<a href="{{ route('admin.catalog-rule.create') }}" class="btn btn-lg btn-primary">
{{ __('admin::app.promotion.add-catalog-rule') }}
</a>
<a href="{{ route('admin.catalog-rule.apply') }}" class="btn btn-lg btn-primary">
{{ __('Apply Rules') }}
</a>
<a href="{{ route('admin.catalog-rule.create') }}" class="btn btn-lg btn-primary">
{{ __('admin::app.promotion.add-catalog-rule') }}
<a href="{{ route('admin.catalog-rule.declut') }}" class="btn btn-lg btn-primary">
{{ __('admin::app.promotion.declut') }}
</a>
</div>
</div>

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>

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>
@ -41,6 +41,15 @@
<input v-validate="'required'" class="control" id="name" name="name" data-vv-as="&quot;{{ __('admin::app.settings.locales.name') }}&quot;"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
<div class="control-group" :class="[errors.has('direction') ? 'has-error' : '']">
<label for="direction" class="required">{{ __('admin::app.settings.locales.direction') }}</label>
<select v-validate="'required'" class="control" id="direction" name="direction" data-vv-as="&quot;{{ __('admin::app.settings.locales.direction') }}&quot;">
<option value="ltr" selected title="Text direction left to right">ltr</option>
<option value="rtl" title="Text direction right to left">rtl</option>
</select>
<span class="control-error" v-if="errors.has('direction')">@{{ errors.first('direction') }}</span>
</div>
</div>
</accordian>

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>
@ -44,6 +44,15 @@
<input v-validate="'required'" class="control" id="name" name="name" data-vv-as="&quot;{{ __('admin::app.settings.locales.name') }}&quot;" value="{{ old('name') ?: $locale->name }}"/>
<span class="control-error" v-if="errors.has('name')">@{{ errors.first('name') }}</span>
</div>
<div class="control-group" :class="[errors.has('direction') ? 'has-error' : '']">
<label for="direction" class="required">{{ __('admin::app.settings.locales.direction') }}</label>
<select v-validate="'required'" class="control" id="direction" name="direction" data-vv-as="&quot;{{ __('admin::app.settings.locales.direction') }}&quot;">
<option value="ltr" {{ old('direction') == 'ltr' ? 'selected' : '' }} title="Text direction left to right">ltr</option>
<option value="rtl" {{ old('direction') == 'rtl' ? 'selected' : '' }} title="Text direction right to left">rtl</option>
</select>
<span class="control-error" v-if="errors.has('direction')">@{{ errors.first('direction') }}</span>
</div>
</div>
</accordian>

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>
@ -27,7 +27,7 @@
<div class="form-container">
@csrf()
<div class="control-group" :class="[errors.has('title') ? 'has-error' : '']">
<label for="title">{{ __('admin::app.settings.sliders.title') }}</label>
<label for="title" class="required">{{ __('admin::app.settings.sliders.title') }}</label>
<input type="text" class="control" name="title" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.settings.sliders.title') }}&quot;">
<span class="control-error" v-if="errors.has('title')">@{{ errors.first('title') }}</span>
</div>
@ -45,9 +45,16 @@
<span class="control-error" v-if="errors.has('channel_id')">@{{ errors.first('channel_id') }}</span>
</div>
<div class="control-group" :class="[errors.has('image') ? 'has-error' : '']">
<label for="new_image">{{ __('admin::app.settings.sliders.image') }}</label>
<image-wrapper :button-label="'{{ __('admin::app.settings.sliders.image') }}'" input-name="image" :multiple="false" :required="true"></image-wrapper>
<div class="control-group {!! $errors->has('image.*') ? 'has-error' : '' !!}">
<label>{{ __('admin::app.catalog.categories.image') }}
<image-wrapper :button-label="'{{ __('admin::app.settings.sliders.image') }}'" input-name="image" :multiple="false"></image-wrapper>
<span class="control-error" v-if="{!! $errors->has('image.*') !!}">
@foreach ($errors->get('image.*') as $key => $message)
@php echo str_replace($key, 'Image', $message[0]); @endphp
@endforeach
</span>
</div>
<div class="control-group" :class="[errors.has('content') ? 'has-error' : '']">

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>
@ -29,7 +29,7 @@
@csrf()
<div class="control-group" :class="[errors.has('title') ? 'has-error' : '']">
<label for="title">{{ __('admin::app.settings.sliders.title') }}</label>
<label for="title" class="required">{{ __('admin::app.settings.sliders.title') }}</label>
<input type="text" class="control" name="title" v-validate="'required'" data-vv-as="&quot;{{ __('admin::app.settings.sliders.title') }}&quot;" value="{{ $slider->title ?: old('title') }}">
<span class="control-error" v-if="errors.has('title')">@{{ errors.first('title') }}</span>
</div>
@ -47,8 +47,16 @@
<span class="control-error" v-if="errors.has('channel_id')">@{{ errors.first('channel_id') }}</span>
</div>
<div class="control-group">
<image-wrapper :button-label="'{{ __('admin::app.settings.sliders.image') }}'" input-name="image" :multiple="false" :images='"{{ url('storage/'.$slider->path) }}"' :required="true"></image-wrapper>
<div class="control-group {!! $errors->has('image.*') ? 'has-error' : '' !!}">
<label>{{ __('admin::app.catalog.categories.image') }}
<image-wrapper :button-label="'{{ __('admin::app.settings.sliders.image') }}'" input-name="image" :multiple="false" :images='"{{ url('storage/'.$slider->path) }}"' ></image-wrapper>
<span class="control-error" v-if="{!! $errors->has('image.*') !!}">
@foreach ($errors->get('image.*') as $key => $message)
@php echo str_replace($key, 'Image', $message[0]); @endphp
@endforeach
</span>
</div>
<div class="control-group">

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

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

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

@ -16,30 +16,52 @@ class AttributeTableSeeder extends Seeder
$now = Carbon::now();
DB::table('attributes')->insert([
['id' => '1','code' => 'sku','admin_name' => 'SKU','type' => 'text','validation' => NULL,'position' => '1','is_required' => '1','is_unique' => '1','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '2','code' => 'name','admin_name' => 'Name','type' => 'text','validation' => NULL,'position' => '2','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '3','code' => 'url_key','admin_name' => 'URL Key','type' => 'text','validation' => NULL,'position' => '3','is_required' => '1','is_unique' => '1','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '4','code' => 'tax_category_id','admin_name' => 'Tax Category','type' => 'select','validation' => NULL,'position' => '4','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '5','code' => 'new','admin_name' => 'New','type' => 'boolean','validation' => NULL,'position' => '5','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '6','code' => 'featured','admin_name' => 'Featured','type' => 'boolean','validation' => NULL,'position' => '6','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '7','code' => 'visible_individually','admin_name' => 'Visible Individually','type' => 'boolean','validation' => NULL,'position' => '7','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '8','code' => 'status','admin_name' => 'Status','type' => 'boolean','validation' => NULL,'position' => '8','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '9','code' => 'short_description','admin_name' => 'Short Description','type' => 'textarea','validation' => NULL,'position' => '9','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '10','code' => 'description','admin_name' => 'Description','type' => 'textarea','validation' => NULL,'position' => '10','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '11','code' => 'price','admin_name' => 'Price','type' => 'price','validation' => 'decimal','position' => '11','is_required' => '1','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' => '0','created_at' => $now,'updated_at' => $now],
['id' => '12','code' => 'cost','admin_name' => 'Cost','type' => 'price','validation' => 'decimal','position' => '12','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '13','code' => 'special_price','admin_name' => 'Special Price','type' => 'price','validation' => 'decimal','position' => '13','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '14','code' => 'special_price_from','admin_name' => 'Special Price From','type' => 'date','validation' => NULL,'position' => '14','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '15','code' => 'special_price_to','admin_name' => 'Special Price To','type' => 'date','validation' => NULL,'position' => '15','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '16','code' => 'meta_title','admin_name' => 'Meta Title','type' => 'textarea','validation' => NULL,'position' => '16','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '17','code' => 'meta_keywords','admin_name' => 'Meta Keywords','type' => 'textarea','validation' => NULL,'position' => '17','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '18','code' => 'meta_description','admin_name' => 'Meta Description','type' => 'textarea','validation' => NULL,'position' => '18','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '19','code' => 'width','admin_name' => 'Width','type' => 'text','validation' => 'decimal','position' => '19','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '20','code' => 'height','admin_name' => 'Height','type' => 'text','validation' => 'decimal','position' => '20','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '21','code' => 'depth','admin_name' => 'Depth','type' => 'text','validation' => 'decimal','position' => '21','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '22','code' => 'weight','admin_name' => 'Weight','type' => 'text','validation' => 'decimal','position' => '22','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['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','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','created_at' => $now,'updated_at' => $now]
['id' => '1','code' => 'sku','admin_name' => 'SKU','type' => 'text','validation' => NULL,'position' => '1','is_required' => '1','is_unique' => '1','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '2','code' => 'name','admin_name' => 'Name','type' => 'text','validation' => NULL,'position' => '2','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '3','code' => 'url_key','admin_name' => 'URL Key','type' => 'text','validation' => NULL,'position' => '3','is_required' => '1','is_unique' => '1','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '4','code' => 'tax_category_id','admin_name' => 'Tax Category','type' => 'select','validation' => NULL,'position' => '4','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '5','code' => 'new','admin_name' => 'New','type' => 'boolean','validation' => NULL,'position' => '5','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '6','code' => 'featured','admin_name' => 'Featured','type' => 'boolean','validation' => NULL,'position' => '6','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '7','code' => 'visible_individually','admin_name' => 'Visible Individually','type' => 'boolean','validation' => NULL,'position' => '7','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','created_at' => $now,
'use_in_flat' => '1','updated_at' => $now],
['id' => '8','code' => 'status','admin_name' => 'Status','type' => 'boolean','validation' => NULL,'position' => '8','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '9','code' => 'short_description','admin_name' => 'Short Description','type' => 'textarea','validation' => NULL,'position' => '9','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0',
'is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '10','code' => 'description','admin_name' => 'Description','type' => 'textarea','validation' => NULL,'position' => '10','is_required' => '1','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '11','code' => 'price','admin_name' => 'Price','type' => 'price','validation' => 'decimal','position' => '11','is_required' => '1','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' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '12','code' => 'cost','admin_name' => 'Cost','type' => 'price','validation' => 'decimal','position' => '12','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '13','code' => 'special_price','admin_name' => 'Special Price','type' => 'price','validation' => 'decimal','position' => '13','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '14','code' => 'special_price_from','admin_name' => 'Special Price From','type' => 'date','validation' => NULL,'position' => '14','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '15','code' => 'special_price_to','admin_name' => 'Special Price To','type' => 'date','validation' => NULL,'position' => '15','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0',
'use_in_flat' => '1','is_visible_on_front' => '0','created_at' => $now,'updated_at' => $now],
['id' => '16','code' => 'meta_title','admin_name' => 'Meta Title','type' => 'textarea','validation' => NULL,'position' => '16','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '17','code' => 'meta_keywords','admin_name' => 'Meta Keywords','type' => 'textarea','validation' => NULL,'position' => '17','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '18','code' => 'meta_description','admin_name' => 'Meta Description','type' => 'textarea','validation' => NULL,'position' => '18','is_required' => '0','is_unique' => '0','value_per_locale' => '1','value_per_channel' => '1','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0','use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '19','code' => 'width','admin_name' => 'Width','type' => 'text','validation' => 'decimal','position' => '19','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '20','code' => 'height','admin_name' => 'Height','type' => 'text','validation' => 'decimal','position' => '20','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '21','code' => 'depth','admin_name' => 'Depth','type' => 'text','validation' => 'decimal','position' => '21','is_required' => '0','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '1','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['id' => '22','code' => 'weight','admin_name' => 'Weight','type' => 'text','validation' => 'decimal','position' => '22','is_required' => '1','is_unique' => '0','value_per_locale' => '0','value_per_channel' => '0','is_filterable' => '0','is_configurable' => '0','is_user_defined' => '0','is_visible_on_front' => '0',
'use_in_flat' => '1','created_at' => $now,'updated_at' => $now],
['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]
]);
@ -67,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

@ -9,7 +9,7 @@ class Attribute extends TranslatableModel implements AttributeContract
{
public $translatedAttributes = ['name'];
protected $fillable = ['code', 'admin_name', 'type', 'position', 'is_required', 'is_unique', 'validation', 'value_per_locale', 'value_per_channel', 'is_filterable', 'is_configurable', 'is_visible_on_front', 'is_user_defined', 'swatch_type'];
protected $fillable = ['code', 'admin_name', 'type', 'position', 'is_required', 'is_unique', 'validation', 'value_per_locale', 'value_per_channel', 'is_filterable', 'is_configurable', 'is_visible_on_front', 'is_user_defined', 'swatch_type', 'use_in_flat'];
// protected $with = ['options'];

View File

@ -229,12 +229,26 @@ class AttributeRepository extends Repository
|| $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')->nullable();
$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,286 @@
<?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(), [
'channels' => 'required',
'locales' => 'required',
'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();
foreach ($data['channels'] as $channel) {
foreach ($data['locales'] as $locale) {
$data['channel_id'] = $channel;
$data['locale_id'] = $locale;
$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);
unset($data['content']);
}
}
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);
if (request()->has('channel') && request()->has('locale')) {
$channel = $this->channel->findOneWhere([
'code' => request()->input('channel')
]);
$locale = $this->locale->findOneWhere([
'code' => request()->input('locale')
]);
$page = $this->cms->findOneWhere([
'channel_id' => $channel->id,
'locale_id' => $locale->id,
'url_key' => $page->url_key
]);
if (! $page) {
$page = $this->cms->create([
'url_key' => str_random(8),
'channel' => $channel->code,
'locale' => $locale->code
]);
return redirect()->route('admin.cms.edit', $page->id);
}
} else {
$page = $this->cms->findOrFail($id);
}
return view($this->_config['view'])->with('page', $page);
}
/**
* To update the previously created CMS page in storage
*
* @param Integer $id
*
* @return View
*/
public function update($id)
{
$page = $this->cms->findOrFail($id);
$data = request()->all();
$this->validate(request(), [
'page_title' => 'required|string',
'html_content' => 'required|string',
'meta_title' => 'required|string',
'meta_description' => 'string',
'meta_keywords' => 'required|string'
]);
$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
*
* @param Integer $id
*
* @return mixed
*/
public function preview($id)
{
$page = $this->cms->findOrFail($id);
return view('shop::cms.page')->with('page', $page);
}
/**
* To delete the previously create CMS page
*
* @param Integer $id
*
* @return Response 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 mass delete the CMS resource from storage
*
* @return Response redirect
*/
public function massDelete()
{
$data = request()->all();
if ($data['indexes']) {
$pageIDs = explode(',', $data['indexes']);
$actualCount = count($pageIDs);
$count = 0;
foreach ($pageIDs as $pageId) {
$page = $this->cms->find($pageId);
if ($page) {
$page->delete();
$count++;
}
}
if ($actualCount == $count) {
session()->flash('success', trans('admin::app.datagrid.mass-ops.delete-success', [
'resource' => 'CMS Pages'
]));
} else {
session()->flash('success', trans('admin::app.datagrid.mass-ops.partial-action', [
'resource' => 'CMS Pages'
]));
}
} else {
session()->flash('warning', trans('admin::app.datagrid.mass-ops.no-resource'));
}
return redirect()->route('admin.cms.index');
}
}

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,57 @@
<?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)
{
$result = $this->model->create($data);
if ($result) {
return $result;
} else {
return $result;
}
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddLocaleIdInCategoryTranslations extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('category_translations', function (Blueprint $table) {
$table->integer('locale_id')->nullable()->unsigned();
});
Schema::table('category_translations', function (Blueprint $table) {
$table->foreign('locale_id')->references('id')->on('locales')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCategoryFilterableAttributesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('category_filterable_attributes', function (Blueprint $table) {
$table->integer('category_id')->unsigned();
$table->integer('attribute_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->foreign('attribute_id')->references('id')->on('attributes')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('category_filterable_attributes');
}
}

View File

@ -24,20 +24,33 @@ class CategoryController extends Controller
/**
* CategoryRepository object
*
* @var array
* @var Object
*/
protected $categoryRepository;
/**
* AttributeRepository object
*
* @var Object
*/
protected $attributeRepository;
/**
* Create a new controller instance.
*
* @param \Webkul\Category\Repositories\CategoryRepository $categoryRepository
* @param \Webkul\Category\Repositories\CategoryRepository $categoryRepository
* @param \Webkul\Attribute\Repositories\AttributeRepository $attributeRepository
* @return void
*/
public function __construct(CategoryRepository $categoryRepository)
public function __construct(
CategoryRepository $categoryRepository,
AttributeRepository $attributeRepository
)
{
$this->categoryRepository = $categoryRepository;
$this->attributeRepository = $attributeRepository;
$this->_config = request('_config');
}
@ -60,7 +73,9 @@ class CategoryController extends Controller
{
$categories = $this->categoryRepository->getCategoryTree(null, ['id']);
return view($this->_config['view'], compact('categories'));
$attributes = $this->attributeRepository->findWhere(['is_filterable' => 1]);
return view($this->_config['view'], compact('categories', 'attributes'));
}
/**
@ -108,7 +123,9 @@ class CategoryController extends Controller
$category = $this->categoryRepository->findOrFail($id);
return view($this->_config['view'], compact('category', 'categories'));
$attributes = $this->attributeRepository->findWhere(['is_filterable' => 1]);
return view($this->_config['view'], compact('category', 'categories', 'attributes'));
}
/**

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