Merge pull request #3010 from jitendra-webkul/1.0

Product multiple image select feature added
This commit is contained in:
Jitendra Singh 2020-05-06 17:08:29 +05:30 committed by GitHub
commit adaeaf7087
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 175 additions and 17 deletions

View File

@ -8,7 +8,7 @@
<div class="control-group {!! $errors->has('images.*') ? 'has-error' : '' !!}">
<label>{{ __('admin::app.catalog.categories.image') }}</label>
<image-wrapper :button-label="'{{ __('admin::app.catalog.products.add-image-btn-title') }}'" input-name="images" :images='@json($product->images)'></image-wrapper>
<product-image></product-image>
<span class="control-error" v-if="{!! $errors->has('images.*') !!}">
@php $count=1 @endphp
@ -23,4 +23,171 @@
</div>
</accordian>
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.images.after', ['product' => $product]) !!}
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.images.after', ['product' => $product]) !!}
@push('scripts')
@parent
<script type="text/x-template" id="product-image-template">
<div>
<div class="image-wrapper">
<product-image-item
v-for='(image, index) in items'
:key='image.id'
:image="image"
@onRemoveImage="removeImage($event)"
@onImageSelected="imageSelected($event)"
></product-image-item>
</div>
<label class="btn btn-lg btn-primary" style="display: inline-block; width: auto" @click="createFileType">
{{ __('admin::app.catalog.products.add-image-btn-title') }}
</label>
</div>
</script>
<script type="text/x-template" id="product-image-item-template">
<label class="image-item" v-bind:class="{ 'has-image': imageData.length > 0 }">
<input type="hidden" :name="'images[' + image.id + ']'" v-if="! new_image"/>
<input type="file" v-validate="'mimes:image/*'" accept="image/*" :name="'images[]'" ref="imageInput" :id="_uid" @change="addImageView($event)" multiple="multiple"/>
<img class="preview" :src="imageData" v-if="imageData.length > 0">
<label class="remove-image" @click="removeImage()">Remove Image</label>
</label>
</script>
<script>
Vue.component('product-image', {
template: '#product-image-template',
data: function() {
return {
images: @json($product->images),
imageCount: 0,
items: []
}
},
computed: {
finalInputName: function() {
return 'images[' + this.image.id + ']';
}
},
created: function() {
var this_this = this;
this.images.forEach(function(image) {
this_this.items.push(image)
this_this.imageCount++;
});
},
methods: {
createFileType: function() {
var this_this = this;
this.imageCount++;
this.items.push({'id': 'image_' + this.imageCount});
},
removeImage (image) {
let index = this.items.indexOf(image)
Vue.delete(this.items, index);
},
imageSelected: function(event) {
var this_this = this;
Array.from(event.files).forEach(function(image, index) {
if (index) {
this_this.imageCount++;
this_this.items.push({'id': 'image_' + this_this.imageCount, file: image});
}
});
}
}
});
Vue.component('product-image-item', {
template: '#product-image-item-template',
props: {
image: {
type: Object,
required: false,
default: null
},
},
data: function() {
return {
imageData: '',
new_image: 0
}
},
mounted () {
if (this.image.id && this.image.url) {
this.imageData = this.image.url;
} else if (this.image.id && this.image.file) {
this.readFile(this.image.file);
}
},
computed: {
finalInputName: function() {
return this.inputName + '[' + this.image.id + ']';
}
},
methods: {
addImageView: function() {
var imageInput = this.$refs.imageInput;
if (imageInput.files && imageInput.files[0]) {
if (imageInput.files[0].type.includes('image/')) {
this.readFile(imageInput.files[0])
if (imageInput.files.length > 1) {
this.$emit('onImageSelected', imageInput)
}
} else {
imageInput.value = "";
alert('Only images (.jpeg, .jpg, .png, ..) are allowed.');
}
}
},
readFile: function(image) {
var reader = new FileReader();
reader.onload = (e) => {
this.imageData = e.target.result;
}
reader.readAsDataURL(image);
this.new_image = 1;
},
removeImage: function() {
this.$emit('onRemoveImage', this.image)
}
}
});
</script>
@endpush

View File

@ -67,7 +67,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.*' => 'mimes:jpeg,jpg,bmp,png',
'images.*' => 'nullable|mimes:jpeg,jpg,bmp,png',
'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'],

View File

@ -3,8 +3,9 @@
namespace Webkul\Product\Repositories;
use Illuminate\Support\Facades\Storage;
use Webkul\Core\Eloquent\Repository;
use Illuminate\Support\Str;
use Illuminate\Http\UploadedFile;
use Webkul\Core\Eloquent\Repository;
class ProductImageRepository extends Repository
{
@ -32,7 +33,7 @@ class ProductImageRepository extends Repository
$file = 'images.' . $imageId;
$dir = 'product/' . $product->id;
if (Str::contains($imageId, 'image_')) {
if ($image instanceof UploadedFile) {
if (request()->hasFile($file)) {
$this->create([
'path' => request()->file($file)->store($dir),
@ -43,16 +44,6 @@ class ProductImageRepository extends Repository
if (is_numeric($index = $previousImageIds->search($imageId))) {
$previousImageIds->forget($index);
}
if (request()->hasFile($file)) {
if ($imageModel = $this->find($imageId)) {
Storage::delete($imageModel->path);
}
$this->update([
'path' => request()->file($file)->store($dir),
], $imageId);
}
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/js/ui.js": "/js/ui.js?id=5c5ae91d95c2c0668124",
"/js/ui.js": "/js/ui.js?id=f703bc98cad12f53c89d",
"/css/ui.css": "/css/ui.css?id=b87eb840235219138c2c"
}