Products DataGrid

This commit is contained in:
prashant-webkul 2018-10-23 17:16:00 +05:30
parent 5016e03b1c
commit 96b40bf2c3
21 changed files with 398 additions and 180 deletions

View File

@ -14,7 +14,6 @@ use Webkul\Ui\DataGrid\Facades\DataGrid;
class OrderDataGrid
{
/**
* The Data Grid implementation.
*
@ -114,19 +113,17 @@ class OrderDataGrid
//don't use aliasing in case of searchables
'searchable' => [
// [
// 'column' => 'cat.id',
// 'type' => 'number',
// 'label' => 'Category ID',
// ], [
// 'column' => 'ct.name',
// 'type' => 'string',
// 'label' => 'Category Name',
// ], [
// 'column' => 'cat.status',
// 'type' => 'string',
// 'label' => 'Visible in Menu',
// ]
[
'column' => 'or.id',
'alias' => 'orderid',
'type' => 'number',
'label' => 'ID',
], [
'name' => 'or.status',
'alias' => 'orstatus',
'type' => 'string',
'label' => 'Status'
]
],
//list of viable operators that will be used

View File

@ -25,17 +25,12 @@ class ProductDataGrid
return DataGrid::make([
'name' => 'Products',
'table' => 'products_grid as prods',
'select' => 'prods.id',
'perpage' => 10,
'select' => 'prods.product_id',
'perpage' => 5,
'aliased' => true, //use this with false as default and true in case of joins
'massoperations' =>[
// [
// 'route' => route('admin.datagrid.delete'),
// 'method' => 'DELETE',
// 'label' => 'Delete',
// 'type' => 'button',
// ],
//check other grid for configuration and make of your own
],
'actions' => [
@ -61,19 +56,50 @@ class ProductDataGrid
//name, alias, type, label, sortable
[
'name' => 'prods.product_id',
'alias' => 'productID',
'type' => 'number',
'alias' => 'id',
'type' => 'string',
'label' => 'ID',
'sortable' => true,
],
[
], [
'name' => 'prods.sku',
'alias' => 'productSku',
'type' => 'string',
'label' => 'SKU',
'sortable' => true,
],
[
], [
'name' => 'prods.name',
'alias' => 'ProductName',
'type' => 'string',
'label' => 'Product Name',
'sortable' => false,
], [
'name' => 'prods.type',
'alias' => 'ProductType',
'type' => 'string',
'label' => 'Product Type',
'sortable' => false,
], [
'name' => 'prods.status',
'alias' => 'ProductStatus',
'type' => 'string',
'label' => 'Product Status',
'sortable' => false,
'wrapper' => function ($value) {
if($value == 1)
return 'Active';
else
return 'Inactive';
},
], [
'name' => 'prods.price',
'alias' => 'ProductPrice',
'type' => 'string',
'label' => 'Product Price',
'sortable' => false,
'wrapper' => function ($value) {
return core()->formatBasePrice($value);
},
], [
'name' => 'prods.quantity',
'alias' => 'ProductQuantity',
'type' => 'string',
@ -83,57 +109,50 @@ class ProductDataGrid
],
'filterable' => [
//column, type, and label
// [
// 'column' => 'prods.id',
// 'alias' => 'productID',
// 'type' => 'number',
// 'label' => 'ID',
// ],
// [
// 'column' => 'prods.sku',
// 'alias' => 'productCode',
// 'type' => 'string',
// 'label' => 'SKU',
// ],
// [
// 'column' => 'attfam.name',
// 'alias' => 'FamilyName',
// 'type' => 'string',
// 'label' => 'Family Name',
// ],
// [
// 'column' => 'pi.qty',
// 'alias' => 'ProductQuantity',
// 'type' => 'number',
// 'label' => 'Product Quatity',
// ],
//column, alias, type, and label
[
'column' => 'prods.product_id',
'alias' => 'productID',
'type' => 'number',
'label' => 'ID',
], [
'column' => 'prods.sku',
'alias' => 'productSku',
'type' => 'string',
'label' => 'SKU',
], [
'column' => 'prods.name',
'alias' => 'ProductName',
'type' => 'string',
'label' => 'Product Name',
], [
'column' => 'prods.type',
'alias' => 'ProductType',
'type' => 'string',
'label' => 'Product Type',
]
],
//don't use aliasing in case of searchables
'searchable' => [
//column, type and label
// [
// 'column' => 'prods.id',
// 'type' => 'number',
// 'label' => 'ID',
// ],
// [
// 'column' => 'prods.sku',
// 'type' => 'string',
// 'label' => 'SKU',
// ],
// [
// 'column' => 'attfam.name',
// 'type' => 'string',
// 'label' => 'Family Name',
// ],
// [
// 'column' => 'pi.qty',
// 'type' => 'string',
// 'label' => 'Product Quatity',
// ],
[
'column' => 'prods.product_id',
'type' => 'number',
'label' => 'ID',
], [
'column' => 'prods.sku',
'type' => 'string',
'label' => 'SKU',
], [
'column' => 'prods.name',
'type' => 'string',
'label' => 'Product Name',
], [
'column' => 'prods.type',
'type' => 'string',
'label' => 'Product Type',
]
],
//list of viable operators that will be used

View File

@ -68,29 +68,25 @@ class RolesDataGrid
//use aliasing on secodary columns if join is performed
'columns' => [
[
'name' => 'id',
'alias' => 'roleId',
'type' => 'number',
'label' => 'ID',
'sortable' => true,
],
[
], [
'name' => 'name',
'alias' => 'roleName',
'type' => 'string',
'label' => 'Name',
'sortable' => true,
],
[
], [
'name' => 'permission_type',
'alias' => 'rolePermissionType',
'type' => 'string',
'label' => 'Permission Type',
'sortable' => true,
],
],
//don't use aliasing in case of filters
@ -101,14 +97,12 @@ class RolesDataGrid
'alias' => 'roleId',
'type' => 'number',
'label' => 'ID',
],
[
], [
'column' => 'name',
'alias' => 'roleName',
'type' => 'string',
'label' => 'Name',
],
[
], [
'column' => 'permission_type',
'alias' => 'rolePermissionType',
'type' => 'string',
@ -123,8 +117,7 @@ class RolesDataGrid
'column' => 'name',
'type' => 'string',
'label' => 'Name',
],
[
], [
'column' => 'permission_type',
'type' => 'string',
'label' => 'Permission Type',

View File

@ -135,8 +135,7 @@ class UserDataGrid
'column' => 'u.email',
'type' => 'string',
'label' => 'E-Mail'
],
[
], [
'column' => 'u.name',
'type' => 'string',
'label' => 'Name'

View File

@ -137,6 +137,8 @@ Route::group(['middleware' => ['web']], function () {
// Catalog Routes
Route::prefix('catalog')->group(function () {
Route::get('/sync', 'Webkul\Product\Http\Controllers\ProductController@sync');
// Catalog Product Routes
Route::get('/products', 'Webkul\Product\Http\Controllers\ProductController@index')->defaults('_config', [
'view' => 'admin::catalog.products.index'

View File

@ -0,0 +1,143 @@
<?php
namespace Webkul\Admin\Listeners;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Product\Repositories\ProductGridRepository;
use Webkul\Product\Helpers\Price;
/**
* Products Event handler
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class Product {
/**
* Product Repository Object
*/
protected $product;
/**
* Price Object
*
* @var array
*/
Protected $price;
/**
* Product Grid Repository Object
*/
protected $productGrid;
public function __construct(ProductRepository $product, ProductGridRepository $productGrid, Price $price)
{
$this->product = $product;
$this->productGrid = $productGrid;
$this->price = $price;
}
/**
* Creates a new entry in the product grid whenever a new product is created.
*
* @return boolean
*/
public function afterProductCreated($product) {
$gridObject = [];
$gridObject = [
'product_id' => $product->id,
'sku' => $product->sku,
'type' => $product->type,
'attribute_family_name' => $product->toArray()['attribute_family']['name'],
];
if($this->productGrid->create($gridObject)) {
return true;
} else {
return false;
}
}
/**
* Event before the product update
*
* @return boolean
*/
public function beforeProductUpdate($productId) {
return true;
}
/**
* Event after the product update
*
* @var collection product
*
* return boolean
*/
public function afterProductUpdate($product) {
//update product grid here
$this->productGrid->updateWhere($product);
return true;
}
/**
* Event after deletion of the product
*
* @return boolean
*/
public function afterProductDelete($productId) {
return true;
}
/**
* Fill attributes for that product after the creation
*
* @return boolean
*/
public function fillAttribute() {
}
public function sync() {
$gridObject = [];
foreach($this->product->all() as $product) {
$gridObject = [
'product_id' => $product->id,
'sku' => $product->sku,
'type' => $product->type,
'name' => $product->name,
'attribute_family_name' => $product->toArray()['attribute_family']['name'],
'price' => $this->price->getMinimalPrice($product),
'status' => $product->status
];
if($product->type == 'configurable') {
$gridObject['quantity'] = 0;
} else {
$qty = 0;
foreach($product->toArray()['inventories'] as $inventorySource) {
$qty = $qty + $inventorySource['qty'];
}
$gridObject['quantity'] = $qty;
$qty = 0;
}
$this->productGrid->create($gridObject);
$gridObject = [];
}
return true;
}
}

View File

@ -51,20 +51,20 @@ class RegistrationController extends Controller
*/
public function create(Request $request)
{
// dd(request()->input());
$request->validate([
'first_name' => 'string|required',
'last_name' => 'string|required',
'email' => 'email|required',
'password' => 'confirmed|min:6|required',
'agreement' => 'confirmed'
'agreement' => 'required'
]);
$data = request()->input();
$data['password'] = bcrypt($data['password']);
$data['channel_id'] = core()->getCurrentChannel()->id;
if ($this->customer->create($data)) {
session()->flash('success', 'Account created successfully.');
@ -72,11 +72,9 @@ class RegistrationController extends Controller
return redirect()->route($this->_config['redirect']);
} else {
session()->flash('error', 'Cannot Create Your Account.');
return redirect()->back();
}
}
}

View File

@ -133,7 +133,6 @@ class WishlistController extends Controller
* @return response
*/
public function addconfigurable($urlkey) {
dd($urlkey);
session()->flash('warning', trans('Select options before adding to wishlist'));
return redirect()->route('shop.products.index', $urlkey);
}

View File

@ -18,7 +18,7 @@ class Customer extends Authenticatable
protected $table = 'customers';
protected $fillable = ['first_name', 'last_name', 'gender', 'date_of_birth','phone','email','password','customer_group_id','subscribed_to_news_letter'];
protected $fillable = ['first_name', 'channel_id', 'last_name', 'gender', 'date_of_birth','phone','email','password','customer_group_id','subscribed_to_news_letter'];
protected $hidden = ['password','remember_token'];

View File

@ -10,4 +10,7 @@ return [
'empty' => 'You Don\'t Have Any Items In Your Wishlist',
'select-options' => 'Need To Select Options Before Adding To Wishlist'
],
'reviews' => [
'empty' => 'You Haven\'t Reviewed Any Product Yet'
]
];

View File

@ -16,14 +16,15 @@ class CreateProductsGrid extends Migration
Schema::create('products_grid', function (Blueprint $table) {
$table->increments('id');
$table->integer('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products');
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->string('sku')->nullable();
$table->string('type')->nullable();
$table->string('attribute_family_name')->nullable();
$table->string('product_name')->nullable();
$table->string('name')->nullable();
$table->string('quantity')->default(0);
$table->string('cost')->default(0);
$table->string('price')->nullable();
$table->string('status')->nullable();
$table->string('attribute_family_name')->nullable();
});
}

View File

@ -10,7 +10,6 @@ use Webkul\Product\Repositories\ProductGridRepository as ProductGrid;
use Webkul\Attribute\Repositories\AttributeFamilyRepository as AttributeFamily;
use Webkul\Category\Repositories\CategoryRepository as Category;
use Webkul\Inventory\Repositories\InventorySourceRepository as InventorySource;
use Webkul\Product\Helpers\Price;
use Event;
/**
@ -63,13 +62,6 @@ class ProductController extends Controller
*/
protected $productGrid;
/**
* Price Object
*
* @var array
*/
Protected $price;
/**
* Create a new controller instance.
*
@ -84,8 +76,7 @@ class ProductController extends Controller
Category $category,
InventorySource $inventorySource,
Product $product,
ProductGrid $productGrid,
Price $price)
ProductGrid $productGrid)
{
$this->attributeFamily = $attributeFamily;
@ -97,8 +88,6 @@ class ProductController extends Controller
$this->productGrid = $productGrid;
$this->price = $price;
$this->_config = request('_config');
}
@ -190,8 +179,8 @@ class ProductController extends Controller
*/
public function update(ProductForm $request, $id)
{
//before update of product
// Event::fire('product.update.before', false);
// before update of product
// Event::fire('product.update.before', $id);
$this->product->update(request()->all(), $id);
@ -221,37 +210,7 @@ class ProductController extends Controller
return redirect()->back();
}
public function test() {
$gridObject = [];
foreach($this->product->all() as $product) {
$gridObject = [
'product_id' => $product->id,
'sku' => $product->sku,
'type' => $product->type,
'product_name' => $product->sku,
'attribute_family_name' => $product->toArray()['attribute_family']['name'],
'price' => $this->price->getMinimalPrice($product)
];
if($product->type == 'configurable') {
$gridObject['quantity'] = 0;
} else {
$qty = 0;
foreach($product->toArray()['inventories'] as $inventorySource) {
$qty = $qty + $inventorySource['qty'];
}
$gridObject['quantity'] = $qty;
$qty = 0;
}
$this->productGrid->create($gridObject);
$gridObject = [];
}
return true;
public function sync() {
Event::fire('products.datagrid.create', true);
}
}

View File

@ -9,7 +9,7 @@ class ProductGrid extends Model
{
protected $table = 'products_grid';
protected $fillable = ['product_id', 'sku', 'type', 'attribute_family_name', 'product_name', 'quantity', 'cost', 'price'];
protected $fillable = ['product_id', 'sku', 'type', 'attribute_family_name', 'name', 'quantity', 'cost', 'price', 'status'];
public $timestamps = false;

View File

@ -19,15 +19,17 @@ class ProductServiceProvider extends ServiceProvider
{
$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
// Event::listen('product.save.before', 'Webkul\Product\Listeners\ProductListener@beforeProductUpdate');
Event::listen('products.datagrid.create', 'Webkul\Admin\Listeners\Product@sync');
Event::listen('product.save.after', 'Webkul\Product\Listeners\ProductListener@afterProductSave');
Event::listen('product.save.after', 'Webkul\Admin\Listeners\Product@afterProductCreated');
// Event::listen('product.update.before', 'Webkul\Product\Listeners\ProductListener@beforeProductUpdate');
Event::listen('product.update.before',
'Webkul\Admin\Listeners\Product@beforeProductUpdate');
Event::listen('product.update.after', 'Webkul\Product\Listeners\ProductListener@beforeProductUpdate');
Event::listen('product.update.after',
'Webkul\Admin\Listeners\Product@afterProductUpdate');
Event::listen('product.delete.after', 'Webkul\Product\Listeners\ProductListener@afterProductDelete');
Event::listen('product.delete.after', 'Webkul\Admin\Listeners\Product@afterProductDelete');
Product::observe(ProductObserver::class);
}

View File

@ -4,17 +4,111 @@ namespace Webkul\Product\Repositories;
use Illuminate\Container\Container as App;
use Webkul\Core\Eloquent\Repository;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Product\Repositories\ProductRepository as Product;
use Webkul\Product\Helpers\Price;
/**
* Product Repository
*
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @author Prashant Singh <prashant.singh852@webkul.com> @prashant-webkul
* @copyright 2018 Webkul Software Pvt Ltd (http://www.webkul.com)
*/
class ProductGridRepository extends Repository
{
protected $product;
/**
* Price Object
*
* @var array
*/
Protected $price;
public function __construct(
Product $product,
Price $price,
App $app
)
{
$this->product = $product;
$this->price = $price;
parent::__construct($app);
}
public function model() {
return 'Webkul\Product\Models\ProductGrid';
}
public function updateWhere($product) {
if($product->type == "simple") {
$gridObject = [
'sku' => $product->sku,
'name' => $product->name,
'attribute_family_name' => $product->toArray()['attribute_family']['name'],
'price' => $this->price->getMinimalPrice($product),
'status' => $product->status
];
$qty = 0;
if($product->parent_id == 'null') {
$gridObject['type'] = $product->type;
}
foreach($product->toArray()['inventories'] as $inventorySource) {
$qty = $qty + $inventorySource['qty'];
}
$gridObject['quantity'] = $qty;
return $this->getModel()->where('product_id', $product->id)->update($gridObject);
} else if($product->type == "configurable") {
$gridObject = [
'sku' => $product->sku,
'type' => $product->type,
'name' => $product->name,
'attribute_family_name' => $product->toArray()['attribute_family']['name'],
'price' => $this->price->getMinimalPrice($product),
'status' => $product->status
];
$qty = 0;
$gridObject['quantity'] = $qty;
$this->getModel()->where('product_id', $product->id)->update($gridObject);
$variants = $product->variants;
foreach($variants as $variant) {
$gridObject = [];
$gridObject = [
'sku' => $variant->sku,
'name' => $variant->name,
'attribute_family_name' => $variant->toArray()['attribute_family']['name'],
'price' => $this->price->getMinimalPrice($variant),
'status' => $variant->status
];
if($variant->type == 'configurable') {
$gridObject['quantity'] = 0;
} else {
$qty = 0;
foreach($variant->toArray()['inventories'] as $inventorySource) {
$qty = $qty + $inventorySource['qty'];
}
$gridObject['quantity'] = $qty;
}
return $this->getModel()->where('product_id', $product->id)->update($gridObject);
}
}
return false;
}
}

View File

@ -7,7 +7,7 @@
background-image:URL('../images/icon-dropdown-left.svg');
width: 8px;
height: 8px;
margin-left:auto;
margin-left: auto;
margin-bottom: 2px;
}
@ -15,7 +15,14 @@
background-image:URL('../images/icon-menu-close.svg');
width: 24px;
height: 24px;
margin-left:auto;
margin-left: auto;
}
.icon-menu-close-adj {
background-image:URL('../images/cross-icon-adj.svg');
width: 32px;
height: 32px;
margin-left: auto;
}
.grid-view-icon {

View File

@ -17,7 +17,6 @@ return [
'add-review-page-title' => 'Add Review',
'write-review' => 'Write a review',
'review-title' => 'Give Your Review a Title',
'empty' => 'You Haven\'t Reviewed Any Product Yet'
],
'customer' => [

View File

@ -16,39 +16,37 @@
</div>
<div class="account-items-list">
@if(!is_null($reviews))
@if(!$reviews->isEmpty())
@foreach($reviews as $review)
<div class="account-item-card mt-15 mb-15">
<div class="media-info">
<?php $image = $productImageHelper->getGalleryImages($review->product); ?>
<img class="media" src="{{ $image[0]['small_image_url'] }}" />
<div class="account-item-card mt-15 mb-15">
<div class="media-info">
<?php $image = $productImageHelper->getGalleryImages($review->product); ?>
<img class="media" src="{{ $image[0]['small_image_url'] }}" />
<div class="info mt-20">
<div class="product-name">{{$review->product->name}}</div>
<div class="info mt-20">
<div class="product-name">{{$review->product->name}}</div>
<div>
@for($i=0 ; $i < $review->rating ; $i++)
<span class="icon star-icon"></span>
@endfor
</div>
<div>
@for($i=0 ; $i < $review->rating ; $i++)
<span class="icon star-icon"></span>
@endfor
</div>
<div>
{{ $review->comment }}
<div>
{{ $review->comment }}
</div>
</div>
</div>
<div class="operations">
</div>
</div>
<div class="operations">
</div>
</div>
<div class="horizontal-rule mb-10 mt-10"></div>
<div class="horizontal-rule mb-10 mt-10"></div>
@endforeach
@else
<div class="empty">
{{-- {{ __('customer::app.wishlist.empty') }} --}}
{{ __('customer::app.reviews.empty') }}
</div>
@endif

View File

@ -546,7 +546,6 @@ class DataGrid
{
foreach ($this->columns as $column) {
if ($column->filter) { // if the filter bag in array exists then these will be applied.
dd($column);
if (count($column->filter['condition']) == count($column->filter['condition'], COUNT_RECURSIVE)) {
$this->query->{$column->filter['function']}(...$column->filter['condition']);
} else {

View File

@ -685,7 +685,6 @@ class ProductGrid
{
foreach ($this->columns as $column) {
if ($column->filter) { // if the filter bag in array exists then these will be applied.
dd($column);
if (count($column->filter['condition']) == count($column->filter['condition'], COUNT_RECURSIVE)) {
$this->query->{$column->filter['function']}(...$column->filter['condition']);
} else {

View File

@ -18,6 +18,13 @@
margin-left: auto;
}
.icon-menu-close-adj {
background-image: URL("../images/cross-icon-adj.svg");
width: 32px;
height: 32px;
margin-left: auto;
}
.grid-view-icon {
background-image: URL("../images/icon-grid-view.svg");
width: 24px;