Merge pull request #4276 from rahulcs0082/development
option to add video in advertisement and product gallery for default theme
This commit is contained in:
commit
f1af54dc5e
|
|
@ -529,7 +529,13 @@ return [
|
|||
'checkbox' => 'خانة اختيار',
|
||||
'multiselect' => 'تحديد متعدد',
|
||||
'new-option' => 'خيار جديد',
|
||||
'is-default' => 'افتراضي'
|
||||
'is-default' => 'افتراضي',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -521,6 +521,12 @@ return [
|
|||
'multiselect' => 'Multiselect',
|
||||
'new-option' => 'Neue Option',
|
||||
'is-default' => 'Ist Standard',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
'attributes' =>
|
||||
[
|
||||
|
|
|
|||
|
|
@ -533,6 +533,12 @@ return [
|
|||
'all-group' => 'All Groups',
|
||||
'fixed' => 'Fixed',
|
||||
'discount' => 'Discount',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -522,7 +522,13 @@ return [
|
|||
'checkbox' => 'Opción múltiple',
|
||||
'multiselect' => 'Lista de selección múltiple',
|
||||
'new-option' => 'Nueva opción',
|
||||
'is-default' => 'Es predeterminada'
|
||||
'is-default' => 'Es predeterminada',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -527,7 +527,13 @@ return [
|
|||
'checkbox' => 'Checkbox',
|
||||
'multiselect' => 'Multiselect',
|
||||
'new-option' => 'New Option',
|
||||
'is-default' => 'Is Default'
|
||||
'is-default' => 'Is Default',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -530,7 +530,13 @@ return [
|
|||
'multiselect' => 'Multiselect',
|
||||
'new-option' => 'Nuova Opzione',
|
||||
'is-default' => 'È Predefinita',
|
||||
'actions' => 'Azioni'
|
||||
'actions' => 'Azioni',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -529,6 +529,12 @@ return [
|
|||
'multiselect' => 'Multiselect',
|
||||
'new-option' => 'Nieuwe optie',
|
||||
'is-default' => 'is standaard',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -528,7 +528,13 @@ return [
|
|||
'checkbox' => 'Pole wyboru',
|
||||
'multiselect' => 'Wielokrotny wybór',
|
||||
'new-option' => 'Nowa opcja',
|
||||
'is-default' => 'Jest domyślny'
|
||||
'is-default' => 'Jest domyślny',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -527,7 +527,13 @@ return [
|
|||
'checkbox' => 'Checkbox',
|
||||
'multiselect' => 'Multiselect',
|
||||
'new-option' => 'New Option',
|
||||
'is-default' => 'Is Default'
|
||||
'is-default' => 'Is Default',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -523,7 +523,13 @@ return [
|
|||
'checkbox' => 'Onay Kutusu',
|
||||
'multiselect' => 'Çoklu Seçim',
|
||||
'new-option' => 'Yeni Seçenek',
|
||||
'is-default' => 'Varsayılan'
|
||||
'is-default' => 'Varsayılan',
|
||||
'remove-image-btn-title' => 'Remove Image',
|
||||
'videos' => 'Videos',
|
||||
'video' => 'Video',
|
||||
'add-video-btn-title' => 'Add Video',
|
||||
'remove-video-btn-title' => 'Remove Video',
|
||||
'not-support-video' => 'Your browser does not support the video tag.',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@
|
|||
|
||||
<img class="preview" :src="imageData" v-if="imageData.length > 0">
|
||||
|
||||
<label class="remove-image" @click="removeImage()">Remove Image</label>
|
||||
<label class="remove-image" @click="removeImage()">
|
||||
{{ __('admin::app.catalog.products.remove-image-btn-title') }}
|
||||
</label>
|
||||
</label>
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,198 @@
|
|||
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.videos.before', ['product' => $product]) !!}
|
||||
|
||||
<accordian :title="'{{ __('admin::app.catalog.products.videos') }}'" :active="false">
|
||||
<div slot="body">
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.videos.controls.before', ['product' => $product]) !!}
|
||||
|
||||
<div class="control-group {!! $errors->has('videos.*') ? 'has-error' : '' !!}">
|
||||
<label>{{ __('admin::app.catalog.products.video') }}</label>
|
||||
|
||||
<product-video></product-video>
|
||||
|
||||
<span class="control-error" v-if="{!! $errors->has('videos.*') !!}">
|
||||
@php $count=1 @endphp
|
||||
@foreach ($errors->get('videos.*') as $key => $message)
|
||||
@php echo str_replace($key, 'Video'.$count, $message[0]); $count++ @endphp
|
||||
@endforeach
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.videos.controls.after', ['product' => $product]) !!}
|
||||
|
||||
</div>
|
||||
</accordian>
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.videos.after', ['product' => $product]) !!}
|
||||
|
||||
@push('scripts')
|
||||
@parent
|
||||
|
||||
<script type="text/x-template" id="product-video-template">
|
||||
<div>
|
||||
<div class="image-wrapper">
|
||||
<product-video-item
|
||||
v-for='(video, index) in items'
|
||||
:key='video.id'
|
||||
:video="video"
|
||||
@onRemoveVideo="removeVideo($event)"
|
||||
@onVideoSelected="videoSelected($event)"
|
||||
></product-video-item>
|
||||
</div>
|
||||
|
||||
<label class="btn btn-lg btn-primary" style="display: inline-block; width: auto" @click="createFileType">
|
||||
{{ __('admin::app.catalog.products.add-video-btn-title') }}
|
||||
</label>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="product-video-item-template">
|
||||
<label class="image-item" v-bind:class="{ 'has-image': videoData.length > 0 }">
|
||||
<input type="hidden" :name="'videos[' + video.id + ']'" v-if="! new_video"/>
|
||||
|
||||
<input type="file" v-validate="'mimes:video/*'" accept="video/*" :name="'videos[]'" ref="videoInput" :id="_uid" @change="addVideoView($event)" multiple="multiple"/>
|
||||
|
||||
<video class="preview" v-if="videoData.length > 0" width="200" height="160" controls>
|
||||
<source :src="videoData" type="video/mp4">
|
||||
{{ __('admin::app.catalog.products.not-support-video') }}
|
||||
</video>
|
||||
|
||||
<label class="remove-image" @click="removeVideo()">
|
||||
{{ __('admin::app.catalog.products.remove-video-btn-title') }}
|
||||
</label>
|
||||
</label>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('product-video', {
|
||||
|
||||
template: '#product-video-template',
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
videos: @json($product->videos),
|
||||
|
||||
videoCount: 0,
|
||||
|
||||
items: []
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
finalInputName: function() {
|
||||
return 'videos[' + this.video.id + ']';
|
||||
}
|
||||
},
|
||||
|
||||
created: function() {
|
||||
var this_this = this;
|
||||
|
||||
this.videos.forEach(function(video) {
|
||||
this_this.items.push(video)
|
||||
|
||||
this_this.videoCount++;
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
createFileType: function() {
|
||||
var this_this = this;
|
||||
|
||||
this.videoCount++;
|
||||
|
||||
this.items.push({'id': 'video_' + this.videoCount});
|
||||
},
|
||||
|
||||
removeVideo (video) {
|
||||
let index = this.items.indexOf(video)
|
||||
|
||||
Vue.delete(this.items, index);
|
||||
},
|
||||
|
||||
videoSelected: function(event) {
|
||||
var this_this = this;
|
||||
|
||||
Array.from(event.files).forEach(function(video, index) {
|
||||
if (index) {
|
||||
this_this.videoCount++;
|
||||
|
||||
this_this.items.push({'id': 'video_' + this_this.videoCount, file: video});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('product-video-item', {
|
||||
|
||||
template: '#product-video-item-template',
|
||||
|
||||
props: {
|
||||
video: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
},
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
videoData: '',
|
||||
|
||||
new_video: 0
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
if (this.video.id && this.video.url) {
|
||||
this.videoData = this.video.url;
|
||||
} else if (this.video.id && this.video.file) {
|
||||
this.readFile(this.video.file);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
finalInputName: function() {
|
||||
return this.inputName + '[' + this.video.id + ']';
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addVideoView: function() {
|
||||
var videoInput = this.$refs.videoInput;
|
||||
|
||||
if (videoInput.files && videoInput.files[0]) {
|
||||
if (videoInput.files[0].type.includes('video/')) {
|
||||
this.readFile(videoInput.files[0])
|
||||
|
||||
if (videoInput.files.length > 1) {
|
||||
this.$emit('onVideoSelected', videoInput)
|
||||
}
|
||||
} else {
|
||||
videoInput.value = "";
|
||||
|
||||
alert('Only videos (.mp4, .mov, .ogg ..) are allowed.');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
readFile: function(video) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = (e) => {
|
||||
this.videoData = e.target.result;
|
||||
}
|
||||
|
||||
reader.readAsDataURL(video);
|
||||
|
||||
this.new_video = 1;
|
||||
},
|
||||
|
||||
removeVideo: function() {
|
||||
this.$emit('onRemoveVideo', this.video)
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@endpush
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
<div class="dropdown-list bottom-right">
|
||||
<div class="control-group">
|
||||
<select class="control" id="locale-switcher" onChange="window.location.href = this.value" style="margin-left: 30px;">
|
||||
<select class="control" onChange="window.location.href = this.value" style="margin-left: 30px;">
|
||||
@foreach (core()->getAllLocales() as $localeModel)
|
||||
|
||||
<option value="{{ '?admin_locale=' . $localeModel->code }}" {{ ($localeModel->code) == $locale ? 'selected' : '' }}>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use Webkul\Product\Datatypes\CartItemValidationResult;
|
|||
use Webkul\Product\Helpers\ProductImage;
|
||||
use Webkul\Product\Repositories\ProductAttributeValueRepository;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
use Webkul\Product\Type\Virtual;
|
||||
|
|
@ -44,6 +45,7 @@ class Booking extends Virtual
|
|||
'admin::catalog.products.accordians.channels',
|
||||
'bookingproduct::admin.catalog.products.accordians.booking',
|
||||
'admin::catalog.products.accordians.product-links',
|
||||
'admin::catalog.products.accordians.videos',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -54,9 +56,10 @@ class Booking extends Virtual
|
|||
* @param \Webkul\Product\Repositories\ProductAttributeValueRepository $attributeValueRepository
|
||||
* @param \Webkul\Product\Repositories\ProductInventoryRepository $productInventoryRepository
|
||||
* @param \Webkul\Product\Repositories\ProductImageRepository $productImageRepository
|
||||
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
|
||||
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
|
||||
* @param \Webkul\BookingProduct\Repositories\BookingProductRepository $bookingProductRepository
|
||||
* @param \Webkul\BookingProduct\Helpers\BookingHelper $bookingHelper
|
||||
* @param \Webkul\BookingProduct\Helpers\BookingHelper $bookingHelper
|
||||
* @param \Webkul\Product\Repositories\ProductVideoRepository $productVideoRepository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
|
|
@ -67,7 +70,8 @@ class Booking extends Virtual
|
|||
ProductImageRepository $productImageRepository,
|
||||
ProductImage $productImageHelper,
|
||||
BookingProductRepository $bookingProductRepository,
|
||||
BookingHelper $bookingHelper
|
||||
BookingHelper $bookingHelper,
|
||||
ProductVideoRepository $productVideoRepository
|
||||
)
|
||||
{
|
||||
parent::__construct(
|
||||
|
|
@ -76,7 +80,8 @@ class Booking extends Virtual
|
|||
$attributeValueRepository,
|
||||
$productInventoryRepository,
|
||||
$productImageRepository,
|
||||
$productImageHelper
|
||||
$productImageHelper,
|
||||
$productVideoRepository
|
||||
);
|
||||
|
||||
$this->bookingProductRepository = $bookingProductRepository;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Contracts;
|
||||
|
||||
interface ProductVideo
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateProductVideosTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('product_videos', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('type')->nullable();
|
||||
$table->string('path');
|
||||
$table->integer('product_id')->unsigned();
|
||||
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('product_videos');
|
||||
}
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ class ProductImage extends AbstractProduct
|
|||
];
|
||||
}
|
||||
|
||||
if (! $product->parent_id && ! count($images)) {
|
||||
if (! $product->parent_id && ! count($images) && ! count($product->videos)) {
|
||||
$images[] = [
|
||||
'small_image_url' => asset('vendor/webkul/ui/assets/images/product/small-product-placeholder.webp'),
|
||||
'medium_image_url' => asset('vendor/webkul/ui/assets/images/product/meduim-product-placeholder.webp'),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Helpers;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ProductVideo extends AbstractProduct
|
||||
{
|
||||
/**
|
||||
* Retrieve collection of videos
|
||||
*
|
||||
* @param \Webkul\Product\Contracts\Product|\Webkul\Product\Contracts\ProductFlat $product
|
||||
* @return array
|
||||
*/
|
||||
public function getVideos($product)
|
||||
{
|
||||
if (! $product) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$videos = [];
|
||||
|
||||
foreach ($product->videos as $video) {
|
||||
if (! Storage::has($video->path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$videos[] = [
|
||||
'type' => $video->type,
|
||||
'video_url' => Storage::url($video->path),
|
||||
];
|
||||
}
|
||||
|
||||
return $videos;
|
||||
}
|
||||
}
|
||||
|
|
@ -68,6 +68,7 @@ class ProductForm extends FormRequest
|
|||
$this->rules = array_merge($product->getTypeInstance()->getTypeValidationRules(), [
|
||||
'sku' => ['required', 'unique:products,sku,' . $this->id, new \Webkul\Core\Contracts\Validations\Slug],
|
||||
'images.*' => 'nullable|mimes:bmp,jpeg,jpg,png,webp',
|
||||
'videos.*' => 'nullable|mimes:mov,mp4|max:2048',
|
||||
'special_price_from' => 'nullable|date',
|
||||
'special_price_to' => 'nullable|date|after_or_equal:special_price_from',
|
||||
'special_price' => ['nullable', new \Webkul\Core\Contracts\Validations\Decimal, 'lt:price'],
|
||||
|
|
|
|||
|
|
@ -143,6 +143,14 @@ class Product extends Model implements ProductContract
|
|||
return $this->hasMany(ProductImageProxy::modelClass(), 'product_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* The videos that belong to the product.
|
||||
*/
|
||||
public function videos()
|
||||
{
|
||||
return $this->hasMany(ProductVideoProxy::modelClass(), 'product_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* The images that belong to the product.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -126,6 +126,14 @@ class ProductFlat extends Model implements ProductFlatContract
|
|||
->select('product_images.*');
|
||||
}
|
||||
|
||||
/**
|
||||
* The videos that belong to the product.
|
||||
*/
|
||||
public function videos()
|
||||
{
|
||||
return $this->product->videos();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the attributes for the attribute groups.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Webkul\Product\Contracts\ProductVideo as ProductVideoContract;
|
||||
|
||||
class ProductVideo extends Model implements ProductVideoContract
|
||||
{
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = [
|
||||
'path',
|
||||
'product_id',
|
||||
'type',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the product that owns the image.
|
||||
*/
|
||||
public function product()
|
||||
{
|
||||
return $this->belongsTo(ProductProxy::modelClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image url for the product image.
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return Storage::url($this->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image url for the product image.
|
||||
*/
|
||||
public function getUrlAttribute()
|
||||
{
|
||||
return $this->url();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCustomAttribute($attribute)
|
||||
{
|
||||
return $this->attribute_family->custom_attributes->pluck('code')->contains($attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$array = parent::toArray();
|
||||
|
||||
$array['url'] = $this->url;
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Models;
|
||||
|
||||
use Konekt\Concord\Proxies\ModelProxy;
|
||||
|
||||
class ProductVideoProxy extends ModelProxy
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -22,5 +22,6 @@ class ModuleServiceProvider extends CoreModuleServiceProvider
|
|||
\Webkul\Product\Models\ProductBundleOptionTranslation::class,
|
||||
\Webkul\Product\Models\ProductBundleOptionProduct::class,
|
||||
\Webkul\Product\Models\ProductCustomerGroupPrice::class,
|
||||
\Webkul\Product\Models\ProductVideo::class,
|
||||
];
|
||||
}
|
||||
|
|
@ -735,6 +735,12 @@ class ProductRepository extends Repository
|
|||
}
|
||||
}
|
||||
|
||||
if (! in_array('videos', $attributesToSkip)) {
|
||||
foreach ($originalProduct->videos as $video) {
|
||||
$copiedProduct->videos()->save($video->replicate());
|
||||
}
|
||||
}
|
||||
|
||||
if (! in_array('super_attributes', $attributesToSkip)) {
|
||||
foreach ($originalProduct->super_attributes as $super_attribute) {
|
||||
$copiedProduct->super_attributes()->save($super_attribute);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Repositories;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Webkul\Core\Eloquent\Repository;
|
||||
|
||||
class ProductVideoRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* Specify Model class name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function model()
|
||||
{
|
||||
return 'Webkul\Product\Contracts\ProductVideo';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param \Webkul\Product\Contracts\Product $product
|
||||
* @return void
|
||||
*/
|
||||
public function uploadVideos($data, $product)
|
||||
{
|
||||
$previousVideoIds = $product->videos()->pluck('id');
|
||||
|
||||
if (isset($data['videos'])) {
|
||||
foreach ($data['videos'] as $videoId => $video) {
|
||||
$file = 'videos.' . $videoId;
|
||||
$dir = 'product/' . $product->id;
|
||||
|
||||
if ($video instanceof UploadedFile) {
|
||||
if (request()->hasFile($file)) {
|
||||
$this->create([
|
||||
'path' => request()->file($file)->store($dir),
|
||||
'product_id' => $product->id,
|
||||
'type' => 'video'
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if (is_numeric($index = $previousVideoIds->search($videoId))) {
|
||||
$previousVideoIds->forget($index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($previousVideoIds as $videoId) {
|
||||
if ($videoModel = $this->find($videoId)) {
|
||||
Storage::delete($videoModel->path);
|
||||
|
||||
$this->delete($videoId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ use Webkul\Product\Repositories\ProductRepository;
|
|||
use Webkul\Attribute\Repositories\AttributeRepository;
|
||||
use Webkul\Product\Datatypes\CartItemValidationResult;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductAttributeValueRepository;
|
||||
|
||||
|
|
@ -47,10 +48,17 @@ abstract class AbstractType
|
|||
/**
|
||||
* ProductImageRepository instance
|
||||
*
|
||||
* @var \Webkul\Product\Repositories\ProductInventoryRepository
|
||||
* @var \Webkul\Product\Repositories\productImageRepository
|
||||
*/
|
||||
protected $productImageRepository;
|
||||
|
||||
/**
|
||||
* ProductVideoRepository instance
|
||||
*
|
||||
* @var \Webkul\Product\Repositories\productVideoRepository
|
||||
*/
|
||||
protected $productVideoRepository;
|
||||
|
||||
/**
|
||||
* Product Image helper instance
|
||||
*
|
||||
|
|
@ -141,6 +149,7 @@ abstract class AbstractType
|
|||
* @param \Webkul\Product\Repositories\ProductInventoryRepository $productInventoryRepository
|
||||
* @param \Webkul\Product\Repositories\ProductImageRepository $productImageRepository
|
||||
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
|
||||
* @param \Webkul\Product\Repositories\ProductVideoRepository $productVideoRepository
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
|
@ -150,7 +159,8 @@ abstract class AbstractType
|
|||
ProductAttributeValueRepository $attributeValueRepository,
|
||||
ProductInventoryRepository $productInventoryRepository,
|
||||
ProductImageRepository $productImageRepository,
|
||||
ProductImage $productImageHelper
|
||||
ProductImage $productImageHelper,
|
||||
ProductVideoRepository $productVideoRepository
|
||||
) {
|
||||
$this->attributeRepository = $attributeRepository;
|
||||
|
||||
|
|
@ -163,6 +173,8 @@ abstract class AbstractType
|
|||
$this->productImageRepository = $productImageRepository;
|
||||
|
||||
$this->productImageHelper = $productImageHelper;
|
||||
|
||||
$this->productVideoRepository = $productVideoRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -271,6 +283,8 @@ abstract class AbstractType
|
|||
|
||||
$this->productImageRepository->uploadImages($data, $product);
|
||||
|
||||
$this->productVideoRepository->uploadVideos($data, $product);
|
||||
|
||||
app('Webkul\Product\Repositories\ProductCustomerGroupPriceRepository')->saveCustomerGroupPrices($data,
|
||||
$product);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use Webkul\Product\Repositories\ProductRepository;
|
|||
use Webkul\Product\Repositories\ProductAttributeValueRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
use Webkul\Product\Repositories\ProductBundleOptionRepository;
|
||||
use Webkul\Product\Repositories\ProductBundleOptionProductRepository;
|
||||
use Webkul\Product\Helpers\ProductImage;
|
||||
|
|
@ -54,7 +55,8 @@ class Bundle extends AbstractType
|
|||
'admin::catalog.products.accordians.categories',
|
||||
'admin::catalog.products.accordians.bundle-items',
|
||||
'admin::catalog.products.accordians.channels',
|
||||
'admin::catalog.products.accordians.product-links'
|
||||
'admin::catalog.products.accordians.product-links',
|
||||
'admin::catalog.products.accordians.videos',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -88,6 +90,7 @@ class Bundle extends AbstractType
|
|||
* @param \Webkul\Product\Repositories\ProductBundleOptionProductRepository $productBundleOptionProductRepository
|
||||
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
|
||||
* @param \Webkul\Product\Helpers\BundleOption $bundleOptionHelper
|
||||
* @param \Webkul\Product\Repositories\ProductVideoRepository $productVideoRepository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
|
|
@ -99,7 +102,8 @@ class Bundle extends AbstractType
|
|||
ProductBundleOptionRepository $productBundleOptionRepository,
|
||||
ProductBundleOptionProductRepository $productBundleOptionProductRepository,
|
||||
ProductImage $productImageHelper,
|
||||
BundleOption $bundleOptionHelper
|
||||
BundleOption $bundleOptionHelper,
|
||||
ProductVideoRepository $productVideoRepository
|
||||
)
|
||||
{
|
||||
parent::__construct(
|
||||
|
|
@ -108,7 +112,8 @@ class Bundle extends AbstractType
|
|||
$attributeValueRepository,
|
||||
$productInventoryRepository,
|
||||
$productImageRepository,
|
||||
$productImageHelper
|
||||
$productImageHelper,
|
||||
$productVideoRepository
|
||||
);
|
||||
|
||||
$this->productBundleOptionRepository = $productBundleOptionRepository;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ class Configurable extends AbstractType
|
|||
'admin::catalog.products.accordians.categories',
|
||||
'admin::catalog.products.accordians.variations',
|
||||
'admin::catalog.products.accordians.channels',
|
||||
'admin::catalog.products.accordians.product-links'
|
||||
'admin::catalog.products.accordians.product-links',
|
||||
'admin::catalog.products.accordians.videos',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use Webkul\Product\Repositories\ProductRepository;
|
|||
use Webkul\Attribute\Repositories\AttributeRepository;
|
||||
use Webkul\Product\Datatypes\CartItemValidationResult;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductAttributeValueRepository;
|
||||
use Webkul\Product\Repositories\ProductDownloadableLinkRepository;
|
||||
|
|
@ -47,6 +48,7 @@ class Downloadable extends AbstractType
|
|||
'admin::catalog.products.accordians.downloadable',
|
||||
'admin::catalog.products.accordians.channels',
|
||||
'admin::catalog.products.accordians.product-links',
|
||||
'admin::catalog.products.accordians.videos',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -79,6 +81,7 @@ class Downloadable extends AbstractType
|
|||
* @param \Webkul\Product\Repositories\ProductDownloadableLinkRepository $productDownloadableLinkRepository
|
||||
* @param \Webkul\Product\Repositories\ProductDownloadableSampleRepository $productDownloadableSampleRepository
|
||||
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
|
||||
* @param \Webkul\Product\Repositories\ProductVideoRepository $productVideoRepository
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
|
@ -90,7 +93,8 @@ class Downloadable extends AbstractType
|
|||
productImageRepository $productImageRepository,
|
||||
ProductDownloadableLinkRepository $productDownloadableLinkRepository,
|
||||
ProductDownloadableSampleRepository $productDownloadableSampleRepository,
|
||||
ProductImage $productImageHelper
|
||||
ProductImage $productImageHelper,
|
||||
ProductVideoRepository $productVideoRepository
|
||||
)
|
||||
{
|
||||
parent::__construct(
|
||||
|
|
@ -99,7 +103,8 @@ class Downloadable extends AbstractType
|
|||
$attributeValueRepository,
|
||||
$productInventoryRepository,
|
||||
$productImageRepository,
|
||||
$productImageHelper
|
||||
$productImageHelper,
|
||||
$productVideoRepository
|
||||
);
|
||||
|
||||
$this->productDownloadableLinkRepository = $productDownloadableLinkRepository;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use Webkul\Product\Repositories\ProductRepository;
|
|||
use Webkul\Product\Repositories\ProductAttributeValueRepository;
|
||||
use Webkul\Product\Repositories\ProductInventoryRepository;
|
||||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Repositories\ProductVideoRepository;
|
||||
use Webkul\Product\Repositories\ProductGroupedProductRepository;
|
||||
use Webkul\Product\Helpers\ProductImage;
|
||||
use Webkul\Product\Models\ProductAttributeValue;
|
||||
|
|
@ -38,7 +39,8 @@ class Grouped extends AbstractType
|
|||
'admin::catalog.products.accordians.categories',
|
||||
'admin::catalog.products.accordians.grouped-products',
|
||||
'admin::catalog.products.accordians.channels',
|
||||
'admin::catalog.products.accordians.product-links'
|
||||
'admin::catalog.products.accordians.product-links',
|
||||
'admin::catalog.products.accordians.videos',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -51,13 +53,14 @@ class Grouped extends AbstractType
|
|||
/**
|
||||
* Create a new product type instance.
|
||||
*
|
||||
* @param \Webkul\Attribute\Repositories\AttributeRepository $attributeRepository
|
||||
* @param \Webkul\Product\Repositories\ProductRepository $productRepository
|
||||
* @param \Webkul\Attribute\Repositories\AttributeRepository $attributeRepository
|
||||
* @param \Webkul\Product\Repositories\ProductRepository $productRepository
|
||||
* @param \Webkul\Product\Repositories\ProductAttributeValueRepository $attributeValueRepository
|
||||
* @param \Webkul\Product\Repositories\ProductInventoryRepository $productInventoryRepository
|
||||
* @param \Webkul\Product\Repositories\ProductImageRepository $productImageRepository
|
||||
* @param \Webkul\Product\Repositories\ProductInventoryRepository $productInventoryRepository
|
||||
* @param \Webkul\Product\Repositories\ProductImageRepository $productImageRepository
|
||||
* @param \Webkul\Product\Repositories\ProductGroupedProductRepository $productGroupedProductRepository
|
||||
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
|
||||
* @param \Webkul\Product\Helpers\ProductImage $productImageHelper
|
||||
* @param \Webkul\Product\Repositories\ProductVideoRepository $productVideoRepository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
|
|
@ -67,7 +70,8 @@ class Grouped extends AbstractType
|
|||
ProductInventoryRepository $productInventoryRepository,
|
||||
ProductImageRepository $productImageRepository,
|
||||
ProductGroupedProductRepository $productGroupedProductRepository,
|
||||
ProductImage $productImageHelper
|
||||
ProductImage $productImageHelper,
|
||||
ProductVideoRepository $productVideoRepository
|
||||
)
|
||||
{
|
||||
parent::__construct(
|
||||
|
|
@ -76,7 +80,8 @@ class Grouped extends AbstractType
|
|||
$attributeValueRepository,
|
||||
$productInventoryRepository,
|
||||
$productImageRepository,
|
||||
$productImageHelper
|
||||
$productImageHelper,
|
||||
$productVideoRepository
|
||||
);
|
||||
|
||||
$this->productGroupedProductRepository = $productGroupedProductRepository;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class Simple extends AbstractType
|
|||
'admin::catalog.products.accordians.categories',
|
||||
'admin::catalog.products.accordians.channels',
|
||||
'admin::catalog.products.accordians.product-links',
|
||||
'admin::catalog.products.accordians.videos',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class Virtual extends AbstractType
|
|||
'admin::catalog.products.accordians.categories',
|
||||
'admin::catalog.products.accordians.channels',
|
||||
'admin::catalog.products.accordians.product-links',
|
||||
'admin::catalog.products.accordians.videos',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,7 +1,15 @@
|
|||
@inject ('productImageHelper', 'Webkul\Product\Helpers\ProductImage')
|
||||
@inject ('productVideoHelper', 'Webkul\Product\Helpers\ProductVideo')
|
||||
@inject ('wishListHelper', 'Webkul\Customer\Helpers\Wishlist')
|
||||
|
||||
<?php $images = $productImageHelper->getGalleryImages($product); ?>
|
||||
<?php
|
||||
$images = $productImageHelper->getGalleryImages($product);
|
||||
|
||||
$videos = $productVideoHelper->getVideos($product);
|
||||
|
||||
$images = array_merge($images, $videos);
|
||||
?>
|
||||
|
||||
|
||||
{!! view_render_event('bagisto.shop.products.view.gallery.before', ['product' => $product]) !!}
|
||||
|
||||
|
|
@ -30,7 +38,12 @@
|
|||
</li>
|
||||
|
||||
<li class="thumb-frame" v-for='(thumb, index) in thumbs' @mouseover="changeImage(thumb)" :class="[thumb.large_image_url == currentLargeImageUrl ? 'active' : '']" id="thumb-frame">
|
||||
<img :src="thumb.small_image_url" alt=""/>
|
||||
<video v-if="thumb.type == 'video'" width="100%" height="100%" onclick="this.paused ? this.play() : this.pause();">
|
||||
<source :src="thumb.video_url" type="video/mp4">
|
||||
{{ __('admin::app.catalog.products.not-support-video') }}
|
||||
</video>
|
||||
|
||||
<img v-else :src="thumb.small_image_url" alt=""/>
|
||||
</li>
|
||||
|
||||
<li class="gallery-control bottom" @click="moveThumbs('bottom')" v-if="(thumbs.length > 4) && this.is_move.down">
|
||||
|
|
@ -39,10 +52,13 @@
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<div class="product-hero-image" id="product-hero-image">
|
||||
<img :src="currentLargeImageUrl" id="pro-img" :data-image="currentOriginalImageUrl" alt=""/>
|
||||
<video :key="currentVideoUrl" v-if="currentType == 'video'" width="100%" height="100%" controls>
|
||||
<source :src="currentVideoUrl" :data-image="currentOriginalImageUrl" type="video/mp4">
|
||||
{{ __('admin::app.catalog.products.not-support-video') }}
|
||||
</video>
|
||||
|
||||
<img v-else :src="currentLargeImageUrl" id="pro-img" :data-image="currentOriginalImageUrl" alt=""/>
|
||||
|
||||
@auth('customer')
|
||||
@php
|
||||
|
|
@ -76,6 +92,10 @@
|
|||
|
||||
currentOriginalImageUrl: '',
|
||||
|
||||
currentVideoUrl: '',
|
||||
|
||||
currentType: '',
|
||||
|
||||
counter: {
|
||||
up: 0,
|
||||
down: 0,
|
||||
|
|
@ -114,11 +134,19 @@
|
|||
},
|
||||
|
||||
changeImage: function(image) {
|
||||
this.currentLargeImageUrl = image.large_image_url;
|
||||
this.currentType = image.type;
|
||||
|
||||
this.currentOriginalImageUrl = image.original_image_url;
|
||||
if (image.type == 'video') {
|
||||
this.currentVideoUrl = image.video_url;
|
||||
|
||||
if ($(window).width() > 580) {
|
||||
this.currentLargeImageUrl = image.large_image_url = image.video_url;
|
||||
} else {
|
||||
this.currentLargeImageUrl = image.large_image_url;
|
||||
|
||||
this.currentOriginalImageUrl = image.original_image_url;
|
||||
}
|
||||
|
||||
if ($(window).width() > 580 && image.original_image_url) {
|
||||
$('img#pro-img').data('zoom-image', image.original_image_url).ezPlus();
|
||||
}
|
||||
},
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"/js/velocity.js": "/js/velocity.js?id=9969a6f54dbcc0665da0",
|
||||
"/js/velocity.js": "/js/velocity.js?id=a2c7aca94b55b22e8f8e",
|
||||
"/css/velocity-admin.css": "/css/velocity-admin.css?id=4322502d80a0e4a0affd",
|
||||
"/css/velocity.css": "/css/velocity.css?id=e41e400c39a3cb5bc551"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
<template>
|
||||
<div class="magnifier">
|
||||
<img
|
||||
:src="src"
|
||||
:data-zoom-image="src"
|
||||
class="main-product-image"
|
||||
/>
|
||||
<div :class="[!isMobile() ? 'magnifier' : '']">
|
||||
<video :key=this.activeImageVideoURL v-if="currentType == 'video'" width="100%" height="100%" controls>
|
||||
<source :src=this.activeImageVideoURL ref="activeProductImage"
|
||||
id="active-product-image"
|
||||
class="main-product-image" type="video/mp4">
|
||||
</video>
|
||||
|
||||
<img v-else
|
||||
:src=this.activeImageVideoURL
|
||||
:data-zoom-image="[!isMobile() ? 'src' : '']"
|
||||
:class="[!isMobile() ? 'main-product-image' : 'vc-small-product-image']"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -20,26 +25,39 @@
|
|||
|
||||
<script type="text/javascript">
|
||||
export default {
|
||||
props: ['src'],
|
||||
props: ['src', 'type'],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
'activeImage': null
|
||||
'activeImage': null,
|
||||
'activeImageElement': null,
|
||||
activeImageVideoURL: '',
|
||||
currentType: '',
|
||||
}
|
||||
},
|
||||
|
||||
mounted: function () {
|
||||
/* jQuery object */
|
||||
this.activeImage = $('.main-product-image');
|
||||
/* store image related info in global variables */
|
||||
this.activeImageElement = this.$refs.activeProductImage;
|
||||
|
||||
this.currentType = this.type;
|
||||
this.activeImageVideoURL = this.src;
|
||||
|
||||
/* convert into jQuery object */
|
||||
this.activeImage = new jQuery.fn.init(this.activeImageElement);
|
||||
|
||||
/* initialise zoom */
|
||||
this.elevateZoom();
|
||||
|
||||
this.$root.$on('changeMagnifiedImage', ({smallImageUrl, largeImageUrl}) => {
|
||||
this.$root.$on('changeMagnifiedImage', ({smallImageUrl, largeImageUrl, currentType}) => {
|
||||
/* removed old instance */
|
||||
$('.zoomContainer').remove();
|
||||
this.activeImage.removeData('elevateZoom');
|
||||
|
||||
this.currentType = currentType;
|
||||
|
||||
this.activeImageVideoURL = largeImageUrl;
|
||||
|
||||
/* update source for images */
|
||||
this.activeImage.attr('src', smallImageUrl);
|
||||
this.activeImage.data('zoom-image', largeImageUrl);
|
||||
|
|
@ -47,6 +65,8 @@
|
|||
/* reinitialize zoom */
|
||||
this.elevateZoom();
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -1,75 +1,89 @@
|
|||
@inject ('productImageHelper', 'Webkul\Product\Helpers\ProductImage')
|
||||
@inject ('productVideoHelper', 'Webkul\Product\Helpers\ProductVideo')
|
||||
@inject ('wishListHelper', 'Webkul\Customer\Helpers\Wishlist')
|
||||
|
||||
@php
|
||||
$images = $productImageHelper->getGalleryImages($product);
|
||||
$videos = $productVideoHelper->getVideos($product);
|
||||
|
||||
if (! count($images)) {
|
||||
$images[0] = $productImageHelper->getProductBaseImage($product);
|
||||
$videoData = $imageData = [];
|
||||
|
||||
foreach ($videos as $key => $video) {
|
||||
$videoData[$key]['type'] = $video['type'];
|
||||
$videoData[$key]['large_image_url'] = $videoData[$key]['small_image_url']= $videoData[$key]['medium_image_url']= $videoData[$key]['original_image_url'] = $video['video_url'];
|
||||
}
|
||||
|
||||
foreach ($images as $key => $image) {
|
||||
$imageData[$key]['type'] = '';
|
||||
$imageData[$key]['large_image_url'] = $image['large_image_url'];
|
||||
$imageData[$key]['small_image_url'] = $image['small_image_url'];
|
||||
$imageData[$key]['medium_image_url'] = $image['medium_image_url'];
|
||||
$imageData[$key]['original_image_url'] = $image['original_image_url'];
|
||||
}
|
||||
|
||||
$images = array_merge($imageData, $videoData);
|
||||
@endphp
|
||||
|
||||
{!! view_render_event('bagisto.shop.products.view.gallery.before', ['product' => $product]) !!}
|
||||
|
||||
<div class="product-image-group">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<magnify-image src="{{ $images[0]['large_image_url'] }}" v-if="!isMobile()">
|
||||
</magnify-image>
|
||||
<div class="row col-12">
|
||||
<magnify-image src="{{ $images[0]['large_image_url'] }}" type="{{ $images[0]['type'] }}">
|
||||
</magnify-image>
|
||||
</div>
|
||||
|
||||
<img
|
||||
v-else
|
||||
class="vc-small-product-image"
|
||||
src="{{ $images[0]['large_image_url'] }}" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<product-gallery></product-gallery>
|
||||
</div>
|
||||
<div class="row col-12">
|
||||
<product-gallery></product-gallery>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{!! view_render_event('bagisto.shop.products.view.gallery.after', ['product' => $product]) !!}
|
||||
|
||||
<script type="text/x-template" id="product-gallery-template">
|
||||
<ul class="thumb-list col-12 row ltr" type="none">
|
||||
<li class="arrow left" @click="scroll('prev')" v-if="thumbs.length > 4">
|
||||
<i class="rango-arrow-left fs24"></i>
|
||||
</li>
|
||||
|
||||
<carousel-component
|
||||
slides-per-page="4"
|
||||
:id="galleryCarouselId"
|
||||
pagination-enabled="hide"
|
||||
navigation-enabled="hide"
|
||||
add-class="product-gallery"
|
||||
:slides-count="thumbs.length">
|
||||
|
||||
<slide :slot="`slide-${index}`" v-for="(thumb, index) in thumbs">
|
||||
<li
|
||||
@mouseover="changeImage({
|
||||
largeImageUrl: thumb.large_image_url,
|
||||
originalImageUrl: thumb.original_image_url,
|
||||
currentType: thumb.type
|
||||
})"
|
||||
:class="`thumb-frame ${index + 1 == 4 ? '' : 'mr5'} ${thumb.large_image_url == currentLargeImageUrl ? 'active' : ''}`"
|
||||
>
|
||||
|
||||
<video v-if="thumb.type == 'video'" width="110" height="110" controls>
|
||||
<source :src="thumb.small_image_url" type="video/mp4">
|
||||
{{ __('admin::app.catalog.products.not-support-video') }}
|
||||
</video>
|
||||
|
||||
<div v-else
|
||||
class="bg-image"
|
||||
:style="`background-image: url(${thumb.small_image_url})`">
|
||||
</div>
|
||||
</li>
|
||||
</slide>
|
||||
</carousel-component>
|
||||
|
||||
<li class="arrow right" @click="scroll('next')" v-if="thumbs.length > 4">
|
||||
<i class="rango-arrow-right fs24"></i>
|
||||
</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/x-template" id="product-gallery-template">
|
||||
<ul class="thumb-list col-12 row ltr" type="none">
|
||||
<li class="arrow left" @click="scroll('prev')" v-if="thumbs.length > 4">
|
||||
<i class="rango-arrow-left fs24"></i>
|
||||
</li>
|
||||
|
||||
<carousel-component
|
||||
slides-per-page="4"
|
||||
:id="galleryCarouselId"
|
||||
pagination-enabled="hide"
|
||||
navigation-enabled="hide"
|
||||
add-class="product-gallery"
|
||||
:slides-count="thumbs.length">
|
||||
|
||||
<slide :slot="`slide-${index}`" v-for="(thumb, index) in thumbs" :key="index">
|
||||
<li
|
||||
@mouseover="changeImage({
|
||||
largeImageUrl: thumb.large_image_url,
|
||||
originalImageUrl: thumb.original_image_url,
|
||||
})"
|
||||
:class="`thumb-frame ${index + 1 == 4 ? '' : 'mr5'} ${thumb.large_image_url == currentLargeImageUrl ? 'active' : ''}`"
|
||||
>
|
||||
|
||||
<div
|
||||
class="bg-image"
|
||||
:style="`background-image: url(${thumb.small_image_url})`">
|
||||
</div>
|
||||
</li>
|
||||
</slide>
|
||||
</carousel-component>
|
||||
|
||||
<li class="arrow right" @click="scroll('next')" v-if="thumbs.length > 4">
|
||||
<i class="rango-arrow-right fs24"></i>
|
||||
</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
(() => {
|
||||
var galleryImages = @json($images);
|
||||
|
|
@ -83,6 +97,7 @@
|
|||
galleryCarouselId: 'product-gallery-carousel',
|
||||
currentLargeImageUrl: '',
|
||||
currentOriginalImageUrl: '',
|
||||
currentType: '',
|
||||
counter: {
|
||||
up: 0,
|
||||
down: 0,
|
||||
|
|
@ -96,6 +111,7 @@
|
|||
this.changeImage({
|
||||
largeImageUrl: this.images[0]['large_image_url'],
|
||||
originalImageUrl: this.images[0]['original_image_url'],
|
||||
currentType: this.images[0]['type']
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -107,11 +123,12 @@
|
|||
this.changeImage({
|
||||
largeImageUrl: this.images[0]['large_image_url'],
|
||||
originalImageUrl: this.images[0]['original_image_url'],
|
||||
currentType: this.images[0]['type']
|
||||
});
|
||||
|
||||
eventBus.$on('configurable-variant-update-images-event', this.updateImages);
|
||||
|
||||
this.prepareThumbs()
|
||||
this.prepareThumbs();
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
@ -127,14 +144,17 @@
|
|||
});
|
||||
},
|
||||
|
||||
changeImage: function({largeImageUrl, originalImageUrl}) {
|
||||
changeImage: function({largeImageUrl, originalImageUrl, currentType}) {
|
||||
this.currentLargeImageUrl = largeImageUrl;
|
||||
|
||||
this.currentOriginalImageUrl = originalImageUrl;
|
||||
|
||||
this.currentType = currentType;
|
||||
|
||||
this.$root.$emit('changeMagnifiedImage', {
|
||||
smallImageUrl: this.currentOriginalImageUrl,
|
||||
largeImageUrl: this.currentLargeImageUrl
|
||||
largeImageUrl: this.currentLargeImageUrl,
|
||||
currentType : this.currentType
|
||||
});
|
||||
|
||||
let productImage = $('.vc-small-product-image');
|
||||
|
|
|
|||
Loading…
Reference in New Issue