Merge pull request #4717 from rahulshukla-webkul/3477
Enhancement #3477, images for variant product
This commit is contained in:
commit
413eda8615
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"/js/admin.js": "/js/admin.js?id=c156943c5badc7f93027",
|
||||
"/css/admin.css": "/css/admin.css?id=f762f47b1bbc81ec1f84"
|
||||
"/js/admin.js": "/js/admin.js?id=dc1e219a5abbaf707c3b",
|
||||
"/css/admin.css": "/css/admin.css?id=ea2c51361c873676924d"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -341,6 +341,25 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
.image-wrapper {
|
||||
.image-item {
|
||||
height: 100px !important;
|
||||
width: 100px !important;
|
||||
background-size: 100px 100px !important;
|
||||
}
|
||||
|
||||
.trash-icon {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
margin-top: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
.btn.add-image {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.rtl {
|
||||
.ticket-list {
|
||||
.control-group {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,16 @@
|
|||
</style>
|
||||
@stop
|
||||
|
||||
@php
|
||||
$variantImages = [];
|
||||
|
||||
foreach ($product->variants as $variant) {
|
||||
foreach ($variant->images as $image) {
|
||||
$variantImages[$variant->id] = $image;
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.variations.before', ['product' => $product]) !!}
|
||||
|
||||
<accordian :title="'{{ __('admin::app.catalog.products.variations') }}'" :active="true">
|
||||
|
|
@ -96,6 +106,7 @@
|
|||
<tr>
|
||||
<th class="sku">{{ __('admin::app.catalog.products.sku') }}</th>
|
||||
<th>{{ __('admin::app.catalog.products.name') }}</th>
|
||||
<th>{{ __('admin::app.catalog.products.images') }}</th>
|
||||
|
||||
@foreach ($product->super_attributes as $attribute)
|
||||
<th class="{{ $attribute->code }}"
|
||||
|
|
@ -145,6 +156,26 @@
|
|||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="control-group" :class="[errors.has(variantInputName + '[images][' + index + ']') ? 'has-error' : '']">
|
||||
<div v-for='(image, index) in items' class="image-wrapper">
|
||||
<label class="image-item" v-bind:class="{ 'has-image': imageData[index] }">
|
||||
<input type="hidden" :name="[variantInputName + '[images][' + image.id + ']']" v-if="! new_image[index]"/>
|
||||
|
||||
<input type="file" v-validate="'mimes:image/*'" :name="[variantInputName + '[images][' + index + ']']" accept="image/*" :ref="'imageInput' + index" multiple="multiple" @change="addImageView($event, index)" :id="image.id"/>
|
||||
|
||||
<img class="preview" :src="imageData[index]" v-if="imageData[index]">
|
||||
</label>
|
||||
|
||||
<span class="icon trash-icon" @click="removeImage(image)"></span>
|
||||
</div>
|
||||
|
||||
<label class="btn btn-lg btn-primary add-image" @click="createFileType">
|
||||
{{ __('admin::app.catalog.products.add-image-btn-title') }}
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td v-for='(attribute, index) in superAttributes'>
|
||||
<div class="control-group">
|
||||
<input type="hidden" :name="[variantInputName + '[' + attribute.code + ']']"
|
||||
|
|
@ -388,7 +419,12 @@
|
|||
inventorySources: @json($inventorySources),
|
||||
inventories: {},
|
||||
totalQty: 0,
|
||||
superAttributes: super_attributes
|
||||
superAttributes: super_attributes,
|
||||
items: [],
|
||||
imageCount: 0,
|
||||
images: {},
|
||||
imageData: [],
|
||||
new_image: [],
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -401,6 +437,21 @@
|
|||
})
|
||||
},
|
||||
|
||||
mounted () {
|
||||
var this_this = this;
|
||||
|
||||
this_this.variant.images.forEach(function(image) {
|
||||
this_this.items.push(image)
|
||||
this_this.imageCount++;
|
||||
|
||||
if (image.id && image.url) {
|
||||
this_this.imageData.push(image.url);
|
||||
} else if (image.id && image.file) {
|
||||
this_this.readFile(image.file);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
computed: {
|
||||
variantInputName: function () {
|
||||
if (this.variant.id)
|
||||
|
|
@ -449,9 +500,54 @@
|
|||
for (var key in this.inventories) {
|
||||
this.totalQty += parseInt(this.inventories[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
createFileType: function() {
|
||||
var this_this = this;
|
||||
|
||||
this.imageCount++;
|
||||
|
||||
this.items.push({'id': 'image_' + this.imageCount});
|
||||
|
||||
this.imageData[this.imageData.length] = '';
|
||||
},
|
||||
|
||||
removeImage (image) {
|
||||
let index = this.items.indexOf(image);
|
||||
|
||||
Vue.delete(this.items, index);
|
||||
|
||||
Vue.delete(this.imageData, index);
|
||||
},
|
||||
|
||||
addImageView: function($event, index) {
|
||||
var ref = "imageInput" + index;
|
||||
var imageInput = this.$refs[ref][0];
|
||||
|
||||
if (imageInput.files && imageInput.files[0]) {
|
||||
if (imageInput.files[0].type.includes('image/')) {
|
||||
this.readFile(imageInput.files[0], index);
|
||||
|
||||
} else {
|
||||
imageInput.value = "";
|
||||
|
||||
alert('Only images (.jpeg, .jpg, .png, ..) are allowed.');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
readFile: function(image, index) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = (e) => {
|
||||
this.imageData.splice(index, 1, e.target.result);
|
||||
}
|
||||
|
||||
reader.readAsDataURL(image);
|
||||
|
||||
this.new_image[index] = 1;
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -6,9 +6,35 @@ use Illuminate\Support\Facades\Storage;
|
|||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Webkul\Core\Eloquent\Repository;
|
||||
use Illuminate\Container\Container as App;
|
||||
use Webkul\Product\Repositories\ProductRepository;
|
||||
|
||||
class ProductImageRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* ProductRepository object
|
||||
*
|
||||
* @return Object
|
||||
*/
|
||||
protected $productRepository;
|
||||
|
||||
/**
|
||||
* Create a new repository instance.
|
||||
*
|
||||
* @param \Webkul\Product\Repositories\ProductRepository $productRepository
|
||||
* @param \Illuminate\Container\Container $app
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
ProductRepository $productRepository,
|
||||
App $app
|
||||
) {
|
||||
parent::__construct($app);
|
||||
|
||||
$this->productRepository = $productRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify Model class name
|
||||
*
|
||||
|
|
@ -48,6 +74,10 @@ class ProductImageRepository extends Repository
|
|||
}
|
||||
}
|
||||
|
||||
if (isset($data['variants'])) {
|
||||
$this->uploadVariantImages($data['variants']);
|
||||
}
|
||||
|
||||
foreach ($previousImageIds as $imageId) {
|
||||
if ($imageModel = $this->find($imageId)) {
|
||||
Storage::delete($imageModel->path);
|
||||
|
|
@ -56,4 +86,44 @@ class ProductImageRepository extends Repository
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $variants
|
||||
* @return void
|
||||
*/
|
||||
public function uploadVariantImages($variants)
|
||||
{
|
||||
foreach ($variants as $variantsId => $variant) {
|
||||
$product = $this->productRepository->findOrFail($variantsId);
|
||||
$previousVariantImageIds = $product->images()->pluck('id');
|
||||
|
||||
if (isset($variant['images'])) {
|
||||
foreach ($variant['images'] as $imageId => $image) {
|
||||
$file = 'variants.' . $product->id .'.'. 'images.' . $imageId;
|
||||
$dir = 'product/' . $product->id;
|
||||
|
||||
if ($image instanceof UploadedFile) {
|
||||
if (request()->hasFile($file)) {
|
||||
$this->create([
|
||||
'path' => request()->file($file)->store($dir),
|
||||
'product_id' => $product->id,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if (is_numeric($index = $previousVariantImageIds->search($imageId))) {
|
||||
$previousVariantImageIds->forget($index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($previousVariantImageIds as $imageId) {
|
||||
if ($imageModel = $this->find($imageId)) {
|
||||
Storage::delete($imageModel->path);
|
||||
|
||||
$this->delete($imageId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue