Merge pull request #5 from bagisto/jitendra

Product detail page completed
This commit is contained in:
JItendra Singh 2018-09-13 16:36:09 +05:30 committed by GitHub
commit 213944e9d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 984 additions and 95 deletions

View File

@ -12,6 +12,7 @@
"dimsav/laravel-translatable": "^9.0",
"fideloper/proxy": "^4.0",
"intervention/image": "^2.4",
"intervention/imagecache": "^2.3",
"kalnoy/nestedset": "^4.3",
"laravel/framework": "5.6.*",
"laravel/tinker": "^1.0",

221
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ee788a0a8a86526cd58b0b4853a45c06",
"content-hash": "c0c2a23aa2502c590b2ccf7975329ce1",
"packages": [
{
"name": "commerceguys/intl",
@ -600,6 +600,59 @@
],
"time": "2018-05-29T14:19:03+00:00"
},
{
"name": "intervention/imagecache",
"version": "2.3.3",
"source": {
"type": "git",
"url": "https://github.com/Intervention/imagecache.git",
"reference": "7936b90e695daee1aafbd25221815352ef97bcbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/imagecache/zipball/7936b90e695daee1aafbd25221815352ef97bcbc",
"reference": "7936b90e695daee1aafbd25221815352ef97bcbc",
"shasum": ""
},
"require": {
"illuminate/cache": "~4|~5",
"illuminate/filesystem": "~4|~5",
"intervention/image": "dev-master|~2,>=2.2.0",
"jeremeamia/superclosure": "~1|~2",
"php": ">=5.3.0"
},
"require-dev": {
"mockery/mockery": "~0.9.2",
"phpunit/phpunit": "3.*"
},
"type": "library",
"autoload": {
"psr-4": {
"Intervention\\Image\\": "src/Intervention/Image"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Oliver Vogel",
"email": "oliver@olivervogel.net",
"homepage": "http://olivervogel.net/"
}
],
"description": "Caching extension for the Intervention Image Class",
"homepage": "http://image.intervention.io",
"keywords": [
"cache",
"gd",
"image",
"imagick",
"laravel"
],
"time": "2015-09-22T15:22:47+00:00"
},
{
"name": "jakub-onderka/php-console-color",
"version": "0.1",
@ -752,6 +805,64 @@
],
"time": "2018-05-16T11:53:55+00:00"
},
{
"name": "jeremeamia/SuperClosure",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/jeremeamia/super_closure.git",
"reference": "5707d5821b30b9a07acfb4d76949784aaa0e9ce9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/5707d5821b30b9a07acfb4d76949784aaa0e9ce9",
"reference": "5707d5821b30b9a07acfb4d76949784aaa0e9ce9",
"shasum": ""
},
"require": {
"nikic/php-parser": "^1.2|^2.0|^3.0|^4.0",
"php": ">=5.4",
"symfony/polyfill-php56": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4-dev"
}
},
"autoload": {
"psr-4": {
"SuperClosure\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jeremy Lindblom",
"email": "jeremeamia@gmail.com",
"homepage": "https://github.com/jeremeamia",
"role": "Developer"
}
],
"description": "Serialize Closure objects, including their context and binding",
"homepage": "https://github.com/jeremeamia/super_closure",
"keywords": [
"closure",
"function",
"lambda",
"parser",
"serializable",
"serialize",
"tokenizer"
],
"time": "2018-03-21T22:21:57+00:00"
},
{
"name": "kalnoy/nestedset",
"version": "v4.3.2",
@ -2580,6 +2691,62 @@
],
"time": "2018-04-26T10:06:28+00:00"
},
{
"name": "symfony/polyfill-php56",
"version": "v1.9.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php56.git",
"reference": "7b4fc009172cc0196535b0328bd1226284a28000"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/7b4fc009172cc0196535b0328bd1226284a28000",
"reference": "7b4fc009172cc0196535b0328bd1226284a28000",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"symfony/polyfill-util": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php56\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"time": "2018-08-06T14:22:27+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.8.0",
@ -2635,6 +2802,58 @@
],
"time": "2018-04-26T10:06:28+00:00"
},
{
"name": "symfony/polyfill-util",
"version": "v1.9.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-util.git",
"reference": "8e15d04ba3440984d23e7964b2ee1d25c8de1581"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-util/zipball/8e15d04ba3440984d23e7964b2ee1d25c8de1581",
"reference": "8e15d04ba3440984d23e7964b2ee1d25c8de1581",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Util\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony utilities for portability of PHP codes",
"homepage": "https://symfony.com",
"keywords": [
"compat",
"compatibility",
"polyfill",
"shim"
],
"time": "2018-08-06T14:22:27+00:00"
},
{
"name": "symfony/process",
"version": "v4.1.2",

View File

@ -238,7 +238,8 @@ return [
'View' => Illuminate\Support\Facades\View::class,
'Datagrid' => Webkul\Ui\DataGrid\Facades\DataGrid::class,
'ProductGrid' => Webkul\Ui\DataGrid\Facades\ProductGrid::class,
'Image' => Intervention\Image\Facades\Image::class
'Image' => Intervention\Image\Facades\Image::class,
'Core' => Webkul\Core\Facades\Core::class
],
];

View File

@ -51,7 +51,7 @@ return [
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/public/storage',
'url' => env('APP_URL') . '/public/storage',
'visibility' => 'public',
],

72
config/imagecache.php Normal file
View File

@ -0,0 +1,72 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| Name of route
|--------------------------------------------------------------------------
|
| Enter the routes name to enable dynamic imagecache manipulation.
| This handle will define the first part of the URI:
|
| {route}/{template}/{filename}
|
| Examples: "images", "img/cache"
|
*/
'route' => 'cache',
/*
|--------------------------------------------------------------------------
| Storage paths
|--------------------------------------------------------------------------
|
| The following paths will be searched for the image filename, submited
| by URI.
|
| Define as many directories as you like.
|
*/
'paths' => array(
storage_path('app/public'),
public_path('storage')
),
/*
|--------------------------------------------------------------------------
| Manipulation templates
|--------------------------------------------------------------------------
|
| Here you may specify your own manipulation filter templates.
| The keys of this array will define which templates
| are available in the URI:
|
| {route}/{template}/{filename}
|
| The values of this array will define which filter class
| will be applied, by its fully qualified name.
|
*/
'templates' => array(
'small' => 'Webkul\Product\CacheFilters\Small',
'medium' => 'Webkul\Product\CacheFilters\Medium',
'large' => 'Webkul\Product\CacheFilters\Large',
),
/*
|--------------------------------------------------------------------------
| Image Cache Lifetime
|--------------------------------------------------------------------------
|
| Lifetime in minutes of the images handled by the imagecache route.
|
*/
'lifetime' => 1,
// 'lifetime' => 43200,
);

244
config/repository.php Normal file
View File

@ -0,0 +1,244 @@
<?php
/*
|--------------------------------------------------------------------------
| Prettus Repository Config
|--------------------------------------------------------------------------
|
|
*/
return [
/*
|--------------------------------------------------------------------------
| Repository Pagination Limit Default
|--------------------------------------------------------------------------
|
*/
'pagination' => [
'limit' => 15
],
/*
|--------------------------------------------------------------------------
| Fractal Presenter Config
|--------------------------------------------------------------------------
|
Available serializers:
ArraySerializer
DataArraySerializer
JsonApiSerializer
*/
'fractal' => [
'params' => [
'include' => 'include'
],
'serializer' => League\Fractal\Serializer\DataArraySerializer::class
],
/*
|--------------------------------------------------------------------------
| Cache Config
|--------------------------------------------------------------------------
|
*/
'cache' => [
/*
|--------------------------------------------------------------------------
| Cache Status
|--------------------------------------------------------------------------
|
| Enable or disable cache
|
*/
'enabled' => false,
/*
|--------------------------------------------------------------------------
| Cache Minutes
|--------------------------------------------------------------------------
|
| Time of expiration cache
|
*/
'minutes' => 30,
/*
|--------------------------------------------------------------------------
| Cache Repository
|--------------------------------------------------------------------------
|
| Instance of Illuminate\Contracts\Cache\Repository
|
*/
'repository' => 'cache',
/*
|--------------------------------------------------------------------------
| Cache Clean Listener
|--------------------------------------------------------------------------
|
|
|
*/
'clean' => [
/*
|--------------------------------------------------------------------------
| Enable clear cache on repository changes
|--------------------------------------------------------------------------
|
*/
'enabled' => true,
/*
|--------------------------------------------------------------------------
| Actions in Repository
|--------------------------------------------------------------------------
|
| create : Clear Cache on create Entry in repository
| update : Clear Cache on update Entry in repository
| delete : Clear Cache on delete Entry in repository
|
*/
'on' => [
'create' => true,
'update' => true,
'delete' => true,
]
],
'params' => [
/*
|--------------------------------------------------------------------------
| Skip Cache Params
|--------------------------------------------------------------------------
|
|
| Ex: http://prettus.local/?search=lorem&skipCache=true
|
*/
'skipCache' => 'skipCache'
],
/*
|--------------------------------------------------------------------------
| Methods Allowed
|--------------------------------------------------------------------------
|
| methods cacheable : all, paginate, find, findByField, findWhere, getByCriteria
|
| Ex:
|
| 'only' =>['all','paginate'],
|
| or
|
| 'except' =>['find'],
*/
'allowed' => [
'only' => null,
'except' => null
]
],
/*
|--------------------------------------------------------------------------
| Criteria Config
|--------------------------------------------------------------------------
|
| Settings of request parameters names that will be used by Criteria
|
*/
'criteria' => [
/*
|--------------------------------------------------------------------------
| Accepted Conditions
|--------------------------------------------------------------------------
|
| Conditions accepted in consultations where the Criteria
|
| Ex:
|
| 'acceptedConditions'=>['=','like']
|
| $query->where('foo','=','bar')
| $query->where('foo','like','bar')
|
*/
'acceptedConditions' => [
'=',
'like'
],
/*
|--------------------------------------------------------------------------
| Request Params
|--------------------------------------------------------------------------
|
| Request parameters that will be used to filter the query in the repository
|
| Params :
|
| - search : Searched value
| Ex: http://prettus.local/?search=lorem
|
| - searchFields : Fields in which research should be carried out
| Ex:
| http://prettus.local/?search=lorem&searchFields=name;email
| http://prettus.local/?search=lorem&searchFields=name:like;email
| http://prettus.local/?search=lorem&searchFields=name:like
|
| - filter : Fields that must be returned to the response object
| Ex:
| http://prettus.local/?search=lorem&filter=id,name
|
| - orderBy : Order By
| Ex:
| http://prettus.local/?search=lorem&orderBy=id
|
| - sortedBy : Sort
| Ex:
| http://prettus.local/?search=lorem&orderBy=id&sortedBy=asc
| http://prettus.local/?search=lorem&orderBy=id&sortedBy=desc
|
| - searchJoin: Specifies the search method (AND / OR), by default the
| application searches each parameter with OR
| EX:
| http://prettus.local/?search=lorem&searchJoin=and
| http://prettus.local/?search=lorem&searchJoin=or
|
*/
'params' => [
'search' => 'search',
'searchFields' => 'searchFields',
'filter' => 'filter',
'orderBy' => 'orderBy',
'sortedBy' => 'sortedBy',
'with' => 'with',
'searchJoin' => 'searchJoin'
]
],
/*
|--------------------------------------------------------------------------
| Generator Config
|--------------------------------------------------------------------------
|
*/
'generator' => [
'basePath' => app()->path(),
'rootNamespace' => 'App\\',
'stubsOverridePath' => app()->path(),
'paths' => [
'models' => 'Entities',
'repositories' => 'Repositories',
'interfaces' => 'Repositories',
'transformers' => 'Transformers',
'presenters' => 'Presenters',
'validators' => 'Validators',
'controllers' => 'Http/Controllers',
'provider' => 'RepositoryServiceProvider',
'criteria' => 'Criteria'
]
]
];

View File

@ -27,9 +27,9 @@ class CoreServiceProvider extends ServiceProvider
$router->aliasMiddleware('locale', Locale::class);
$this->publishes([
__DIR__ . '/../../publishable/lang' => public_path('vendor/webkul/core/lang'),
], 'public');
// $this->publishes([
// __DIR__ . '/../../publishable/lang' => public_path('vendor/webkul/core/lang'),
// ], 'public');
Validator::extend('slug', 'Webkul\Core\Contracts\Validations\Slug@passes');

View File

@ -13,12 +13,6 @@ class CustomerServiceProvider extends ServiceProvider
{
public function boot(Router $router)
{
// include __DIR__ . '/../Http/routes.php';
$this->publishes([
__DIR__ . '/../../publishable/assets' => public_path('vendor/webkul/customer/assets'),
], 'public');
$router->aliasMiddleware('customer', RedirectIfNotCustomer::class);
$this->loadMigrationsFrom(__DIR__ . '/../Database/migrations');

View File

@ -0,0 +1,14 @@
<?php
namespace Webkul\Product\CacheFilters;
use Intervention\Image\Image;
use Intervention\Image\Filters\FilterInterface;
class Large implements FilterInterface
{
public function applyFilter(Image $image)
{
return $image->resize(480, 480);
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Webkul\Product\CacheFilters;
use Intervention\Image\Image;
use Intervention\Image\Filters\FilterInterface;
class Medium implements FilterInterface
{
public function applyFilter(Image $image)
{
return $image->resize(280, 350);
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Webkul\Product\CacheFilters;
use Intervention\Image\Image;
use Intervention\Image\Filters\FilterInterface;
class Small implements FilterInterface
{
public function applyFilter(Image $image)
{
return $image->resize(120, 120);
}
}

View File

@ -3,7 +3,7 @@
namespace Webkul\Product\Product;
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
use Webkul\Product\Product\Gallery;
use Webkul\Product\Product\ProductImage;
use Webkul\Product\Product\Price;
class ConfigurableOption extends AbstractProduct
@ -16,11 +16,11 @@ class ConfigurableOption extends AbstractProduct
protected $attributeOption;
/**
* Gallery object
* ProductImage object
*
* @var array
*/
protected $gallery;
protected $productImage;
/**
* Price object
@ -33,19 +33,19 @@ class ConfigurableOption extends AbstractProduct
* Create a new controller instance.
*
* @param Webkul\Attribute\Repositories\AttributeOptionRepository $attributeOption
* @param Webkul\Product\Product\Gallery $gallery
* @param Webkul\Product\Product\ProductImage $productImage
* @param Webkul\Product\Product\Price $price
* @return void
*/
public function __construct(
AttributeOption $attributeOption,
Gallery $gallery,
ProductImage $productImage,
Price $price
)
{
$this->attributeOption = $attributeOption;
$this->gallery = $gallery;
$this->productImage = $productImage;
$this->price = $price;
}
@ -230,7 +230,7 @@ class ConfigurableOption extends AbstractProduct
$images = [];
foreach ($this->getAllowProducts($product) as $variant) {
$images[$variant->id] = $this->gallery->getImages($variant);
$images[$variant->id] = $this->productImage->getGalleryImages($variant);
}
return $images;

View File

@ -1,25 +0,0 @@
<?php
namespace Webkul\Product\Product;
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
class Gallery extends AbstractProduct
{
/**
* Retrieve collection of gallery images
*
* @param Product $product
* @return array
*/
public function getImages($product)
{
$images[] = [
'small_image_url' => '',
'medium_image_url' => '',
'large_image_url' => '',
];
return $images;
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace Webkul\Product\Product;
use Webkul\Attribute\Repositories\AttributeOptionRepository as AttributeOption;
use Illuminate\Support\Facades\Storage;
class ProductImage extends AbstractProduct
{
/**
* Retrieve collection of gallery images
*
* @param Product $product
* @return array
*/
public function getGalleryImages($product)
{
$images = [];
foreach($product->images as $image) {
if(!Storage::has($image->path))
continue;
$images[] = [
'small_image_url' => url('cache/small/' . $image->path),
'medium_image_url' => url('cache/medium/' . $image->path),
'large_image_url' => url('cache/large/' . $image->path),
'original_image_url' => url('cache/original/' . $image->path),
];
}
if(!$product->parent_id && !count($images)) {
$images[] = [
'small_image_url' => bagisto_asset('images/product/small-product-placeholder.png'),
'medium_image_url' => bagisto_asset('images/product/meduim-product-placeholder.png'),
'large_image_url' => bagisto_asset('images/product/large-product-placeholder.png'),
'original_image_url' => bagisto_asset('images/product/large-product-placeholder.png'),
];
}
return $images;
}
/**
* Get product's base image
*
* @param Product $product
* @return array
*/
public function getProductBaseImage($product)
{
$images = $product->images;
if($images->count()) {
$image = [
'small_image_url' => url('cache/small/' . $images[0]->path),
'medium_image_url' => url('cache/medium/' . $images[0]->path),
'large_image_url' => url('cache/large/' . $images[0]->path),
'original_image_url' => url('cache/original/' . $images[0]->path),
];
} else {
$image = [
'small_image_url' => bagisto_asset('images/product/small-product-placeholder.png'),
'medium_image_url' => bagisto_asset('images/product/meduim-product-placeholder.png'),
'large_image_url' => bagisto_asset('images/product/large-product-placeholder.png'),
'original_image_url' => bagisto_asset('images/product/large-product-placeholder.png'),
];
}
return $image;
}
}

View File

@ -24,7 +24,7 @@ Route::group(['middleware' => ['web']], function () {
'view' => 'shop::products.reviews.create'
])->name('shop.reviews.create');
Route::post('/reviews/create/{slug}', 'Webkul\Core\Http\Controllers\ReviewController@store')->defaults('_config', [
Route::post('/reviews/create/{slug}', 'Webkul\Shop\Http\Controllers\ReviewController@store')->defaults('_config', [
'redirect' => 'admin.reviews.index'
])->name('admin.reviews.store');

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -483,10 +483,18 @@ section.slider-block {
.product-card {
.product-image img {
align-self: center;
width: 100%;
margin-bottom: 14px;
.product-image {
background: #F2F2F2;
margin-bottom: 10px;
// width: 380px;
// max-width: 100%;
// text-align: center;
img {
align-self: center;
width: 100%;
margin-bottom: 14px;
}
}
.product-name {
@ -995,25 +1003,80 @@ section.product-detail {
}
div.layouter {
display:flex;
flex-flow: row;
margin-top: 21px;
margin-top: 20px;
margin-bottom: 20px;
display: inline-block;
width: 100%;
div.product-image-group {
display:flex;
flex-direction: row;
justify-content: flex-start;
margin-right: 2.5%;
width: 43%;
float: left;
min-height: 1px;
position: relative;
.side-group {
.thumb-list {
display: flex;
flex-direction: column;
margin-right: 4px;
height: 480px;
overflow: hidden;
position: relative;
float: left;
.thumb-frame {
border: 2px solid transparent;
background: #F2F2F2;
width: 120px;
height: 120px;
&.active {
border-color: #979797;
}
img {
width: 100%;
height: 100%;
}
}
.gallery-control {
width: 100%;
position: absolute;
text-align: center;
cursor: pointer;
z-index: 1;
.overlay {
opacity: 0.3;
background: #000000;
width: 100%;
height: 18px;
position: absolute;
left: 0;
z-index: -1;
}
.icon {
z-index: 2;
}
&.top {
top: 0;
}
&.bottom {
bottom: 0;
}
}
}
.product-hero-image {
display: block;
position: relative;
background: #F2F2F2;
width: 480px;
max-height: 480px;
float: left;
.wishlist {
position: absolute;
@ -1030,6 +1093,9 @@ section.product-detail {
}
.details {
width: 57%;
float: left;
.product-price {
margin-bottom: 14px;
}

View File

@ -1,7 +1,12 @@
<div class="product-card">
@inject ('productImageHelper', 'Webkul\Product\Product\ProductImage')
<?php $productBaseImage = $productImageHelper->getProductBaseImage($product); ?>
<div class="product-image">
<a href="{{ route('shop.products.index', $product->url_key) }}" title="{{ $product->name }}">
<img src="{{ bagisto_asset('images/gogs.png') }}" />
<img src="{{ $productBaseImage['medium_image_url'] }}" />
</a>
</div>

View File

@ -10,7 +10,7 @@
<div class="layouter">
<form action="" style="display: inherit;">
<form action="">
@csrf()

View File

@ -16,7 +16,7 @@
<select v-validate="'required'" class="control" :name="['super_attribute[' + attribute.id + ']']" :disabled="attribute.disabled" @change="configure(attribute, $event.target.value)" :id="['attribute_' + attribute.id]">
<option v-for='(option, index) in attribute.options' :value="option.id">@{{ option.label }}</option>
<option v-for='(option, index) in attribute.options' :value="option.id">@{{ option.label }}</option>
</select>
@ -43,10 +43,14 @@
selectedProductId: '',
simpleProduct: null
simpleProduct: null,
galleryImages: []
}),
created () {
this.galleryImages = galleryImages.slice(0)
var config = @json($config);
var childAttributes = this.childAttributes,
@ -228,7 +232,17 @@
},
changeProductImages () {
console.log(this.config.variant_images[this.simpleProduct])
galleryImages.splice(0, galleryImages.length)
this.galleryImages.forEach(function(image) {
galleryImages.push(image)
});
if(this.simpleProduct) {
this.config.variant_images[this.simpleProduct].forEach(function(image) {
galleryImages.unshift(image)
});
}
},
}

View File

@ -1,25 +1,104 @@
@inject ('productImageHelper', 'Webkul\Product\Product\ProductImage')
<?php $images = $productImageHelper->getGalleryImages($product); ?>
<div class="product-image-group">
<div class="side-group">
<img src="{{ bagisto_asset('images/jeans.jpg') }}" />
<img src="{{ bagisto_asset('images/jeans.jpg') }}" />
<img src="{{ bagisto_asset('images/jeans.jpg') }}" />
<img src="{{ bagisto_asset('images/jeans.jpg') }}" />
</div>
<product-gallery></product-gallery>
@include ('shop::products.add-to')
<div class="product-hero-image" id="product-hero-image">
<img src="{{ bagisto_asset('images/jeans_big.jpg') }}" />
<img class="wishlist" src="{{ bagisto_asset('images/wish.svg') }}" />
<img class="share" src="{{ bagisto_asset('images/icon-share.svg') }}" />
</div>
</div>
@push('scripts')
<script type="text/x-template" id="product-gallery-template">
<div>
<ul class="thumb-list">
<li class="gallery-control top" @click="moveThumbs('top')" v-if="thumbs.length > 4">
<span class="overlay"></span>
<i class="icon arrow-up-white-icon"></i>
</li>
<li class="thumb-frame" v-for='(thumb, index) in thumbs' @click="changeImage(thumb)" :class="[thumb.large_image_url == currentLargeImageUrl ? 'active' : '']">
<img :src="thumb.small_image_url" />
</li>
<li class="gallery-control bottom" @click="moveThumbs('bottom')" v-if="thumbs.length > 4">
<span class="overlay"></span>
<i class="icon arrow-down-white-icon"></i>
</li>
</ul>
<div class="product-hero-image" id="product-hero-image">
<img :src="currentLargeImageUrl" />
</div>
</div>
</script>
<script>
var galleryImages = @json($images);
Vue.component('product-gallery', {
props: ['images']
template: '#product-gallery-template',
data: () => ({
images: galleryImages,
thumbs: [],
currentLargeImageUrl: ''
}),
watch: {
'images': function(newVal, oldVal) {
this.changeImage(this.images[0])
this.prepareThumbs()
}
},
created () {
console.log(this.images[0])
this.changeImage(this.images[0])
this.prepareThumbs()
},
methods: {
prepareThumbs () {
var this_this = this;
this_this.thumbs = [];
this.images.forEach(function(image) {
this_this.thumbs.push(image);
});
},
changeImage (image) {
this.currentLargeImageUrl = image.large_image_url;
},
moveThumbs(direction) {
let len = this.thumbs.length;
if (direction === "top") {
const moveThumb = this.thumbs.splice(len - 1, 1);
this.thumbs = [moveThumb[0], ...this.thumbs];
} else {
const moveThumb = this.thumbs.splice(0, 1);
this.thumbs = [...this.thumbs, moveThumb[0]];
}
},
}
});
</script>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="8px" viewBox="0 0 12 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 50 (54983) - http://www.bohemiancoding.com/sketch -->
<title>down-arrow</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="down-arrow" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<polygon id="" fill="#FFFFFF" transform="translate(6.000000, 4.519196) rotate(-270.000000) translate(-6.000000, -4.519196) " points="3.48080444 8.51919556 6.54690552 4.51919556 3.48080444 0.519195557 5.48550415 0.519195557 8.51919556 4.51919556 5.48550415 8.51919556"></polygon>
</g>
</svg>

After

Width:  |  Height:  |  Size: 741 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="8px" viewBox="0 0 12 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 50 (54983) - http://www.bohemiancoding.com/sketch -->
<title>up-arrow</title>
<desc>Created with Sketch.</desc>
<defs>
<polygon id="path-1" points="3.48080444 7.51919556 6.54690552 3.51919556 3.48080444 -0.480804443 5.48550415 -0.480804443 8.51919556 3.51919556 5.48550415 7.51919556"></polygon>
</defs>
<g id="up-arrow" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="" fill="#FFFFFF" transform="translate(6.000000, 3.519196) scale(1, -1) rotate(-270.000000) translate(-6.000000, -3.519196) " xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 911 B

View File

@ -988,6 +988,7 @@ h2 {
background-image: url("../images/placeholder-icon.svg");
background-repeat: no-repeat;
background-position: center;
margin-bottom: 20px;
img.preview {
width: 100%;

View File

@ -164,6 +164,18 @@
height: 24px;
}
.arrow-down-white-icon {
background-image: url("../images/down-arrow-white.svg");
width: 17px;
height: 13px;
}
.arrow-up-white-icon {
background-image: url("../images/up-arrow-white.svg");
width: 17px;
height: 13px;
}
.active {
.dashboard-icon {
background-image: url("../images/Icon-Dashboard-Active.svg");

View File

@ -4,6 +4,20 @@ namespace Webkul\User;
class Bouncer
{
/**
* Checks if user has permission for certain action
*
* @param String $permission
* @return Void
*/
public static function hasPermission($permission)
{
if(!auth()->check() || !auth()->user()->hasPermission($permission))
return false;
return true;
}
/**
* Checks if user allowed or not for certain action
*

View File

@ -570,6 +570,11 @@ section.slider-block div.slider-content div.slider-control .light-right-icon {
justify-content: center;
}
.main-container-wrapper .product-card .product-image {
background: #F2F2F2;
margin-bottom: 10px;
}
.main-container-wrapper .product-card .product-image img {
-ms-flex-item-align: center;
align-self: center;
@ -1105,31 +1110,20 @@ section.product-detail div.category-breadcrumbs {
}
section.product-detail div.layouter {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-flow: row;
flex-flow: row;
margin-top: 21px;
margin-top: 20px;
margin-bottom: 20px;
display: inline-block;
width: 100%;
}
section.product-detail div.layouter div.product-image-group {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
margin-right: 2.5%;
width: 43%;
float: left;
min-height: 1px;
position: relative;
}
section.product-detail div.layouter div.product-image-group .side-group {
section.product-detail div.layouter div.product-image-group .thumb-list {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
@ -1138,11 +1132,65 @@ section.product-detail div.layouter div.product-image-group .side-group {
-ms-flex-direction: column;
flex-direction: column;
margin-right: 4px;
height: 480px;
overflow: hidden;
position: relative;
float: left;
}
section.product-detail div.layouter div.product-image-group .thumb-list .thumb-frame {
border: 2px solid transparent;
background: #F2F2F2;
width: 120px;
height: 120px;
}
section.product-detail div.layouter div.product-image-group .thumb-list .thumb-frame.active {
border-color: #979797;
}
section.product-detail div.layouter div.product-image-group .thumb-list .thumb-frame img {
width: 100%;
height: 100%;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control {
width: 100%;
position: absolute;
text-align: center;
cursor: pointer;
z-index: 1;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control .overlay {
opacity: 0.3;
background: #000000;
width: 100%;
height: 18px;
position: absolute;
left: 0;
z-index: -1;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control .icon {
z-index: 2;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control.top {
top: 0;
}
section.product-detail div.layouter div.product-image-group .thumb-list .gallery-control.bottom {
bottom: 0;
}
section.product-detail div.layouter div.product-image-group .product-hero-image {
display: block;
position: relative;
background: #F2F2F2;
width: 480px;
max-height: 480px;
float: left;
}
section.product-detail div.layouter div.product-image-group .product-hero-image .wishlist {
@ -1157,6 +1205,11 @@ section.product-detail div.layouter div.product-image-group .product-hero-image
right: 45px;
}
section.product-detail div.layouter .details {
width: 57%;
float: left;
}
section.product-detail div.layouter .details .product-price {
margin-bottom: 14px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB