mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
move deleteImage logic to ImageUploader
This commit is contained in:
parent
888051a6ae
commit
4a17cf0e07
@ -380,9 +380,10 @@ describe('ContributionForm.vue', () => {
|
||||
|
||||
it('supports deleting a teaser image', async () => {
|
||||
expectedParams.variables.image = null
|
||||
expectedParams.variables.imageAspectRatio = null
|
||||
propsData.contribution.image = '/uploads/someimage.png'
|
||||
wrapper = Wrapper()
|
||||
wrapper.find('.contribution-form .delete-image').trigger('click')
|
||||
wrapper.find('[data-test="delete-button"]').trigger('click')
|
||||
await wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||
})
|
||||
|
||||
@ -11,11 +11,11 @@
|
||||
<template #heroImage>
|
||||
<img
|
||||
v-if="formData.image"
|
||||
:src="contribution.image | proxyApiUrl"
|
||||
:src="formData.image | proxyApiUrl"
|
||||
:class="['image', formData.imageBlurred && '--blur-image']"
|
||||
/>
|
||||
<image-uploader
|
||||
:contribution="contribution"
|
||||
:hasImage="!!formData.image"
|
||||
:class="[formData.imageBlurred && '--blur-image']"
|
||||
@addHeroImage="addHeroImage"
|
||||
@addImageAspectRatio="addImageAspectRatio"
|
||||
@ -150,6 +150,7 @@ export default {
|
||||
loading: false,
|
||||
users: [],
|
||||
hashtags: [],
|
||||
imageUpload: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -162,11 +163,6 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
const newImage =
|
||||
!this.contribution || this.contribution.image !== this.formData.image
|
||||
? this.formData.image
|
||||
: null
|
||||
|
||||
this.loading = true
|
||||
this.$apollo
|
||||
.mutate({
|
||||
@ -175,8 +171,8 @@ export default {
|
||||
...this.formData,
|
||||
id: this.contribution.id || null,
|
||||
language: this.formData.language.value,
|
||||
image: newImage ? null : this.formData.image,
|
||||
imageUpload: newImage,
|
||||
image: this.imageUpload ? null : this.formData.image,
|
||||
imageUpload: this.imageUpload,
|
||||
},
|
||||
})
|
||||
.then(({ data }) => {
|
||||
@ -198,7 +194,8 @@ export default {
|
||||
this.$refs.contributionForm.update('content', value)
|
||||
},
|
||||
addHeroImage(file) {
|
||||
this.formData.image = file
|
||||
this.imageUpload = file
|
||||
this.formData.image = file ? URL.createObjectURL(file) : null
|
||||
},
|
||||
addImageAspectRatio(aspectRatio) {
|
||||
this.formData.imageAspectRatio = aspectRatio
|
||||
@ -245,6 +242,10 @@ export default {
|
||||
|
||||
> .hero-image {
|
||||
position: relative;
|
||||
|
||||
> .image {
|
||||
max-height: $size-image-max-height;
|
||||
}
|
||||
}
|
||||
|
||||
.image.--blur-image {
|
||||
|
||||
@ -6,17 +6,18 @@
|
||||
:options="dropzoneOptions"
|
||||
:use-custom-slot="true"
|
||||
@vdropzone-error="onDropzoneError"
|
||||
@vdropzone-thumbnail="initCropper"
|
||||
@vdropzone-file-added="initCropper"
|
||||
>
|
||||
<loading-spinner v-if="isLoadingImage" />
|
||||
<base-icon v-else name="image" />
|
||||
<base-button
|
||||
class="delete-image"
|
||||
icon="close"
|
||||
size="small"
|
||||
v-if="hasImage"
|
||||
icon="trash"
|
||||
circle
|
||||
danger
|
||||
filled
|
||||
data-test="delete-button"
|
||||
:title="$t('actions.delete')"
|
||||
@click.stop="deleteImage"
|
||||
/>
|
||||
</vue-dropzone>
|
||||
@ -50,14 +51,17 @@ export default {
|
||||
VueDropzone,
|
||||
},
|
||||
props: {
|
||||
contribution: { type: Object, default: () => {} },
|
||||
hasImage: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dropzoneOptions: {
|
||||
url: () => '',
|
||||
maxFilesize: 5.0,
|
||||
previewTemplate: '<img class="preview-image" />',
|
||||
previewTemplate: '<span class="no-preview" />',
|
||||
},
|
||||
cropper: null,
|
||||
file: null,
|
||||
@ -69,62 +73,44 @@ export default {
|
||||
onDropzoneError(file, message) {
|
||||
this.$toast.error(file.status, message)
|
||||
},
|
||||
clearImages() {
|
||||
const images = document.querySelectorAll('.preview-image')
|
||||
images.forEach((image, index) => {
|
||||
if (index === images.length - 1) image.src = ''
|
||||
else image.remove()
|
||||
})
|
||||
},
|
||||
initCropper(file) {
|
||||
this.showCropper = true
|
||||
this.file = file
|
||||
console.log(file)
|
||||
this.clearImages()
|
||||
|
||||
const imageElement = document.querySelector('#cropping-image')
|
||||
imageElement.src = URL.createObjectURL(file)
|
||||
this.cropper = new Cropper(imageElement, { zoomable: false, autoCropArea: 0.9 })
|
||||
},
|
||||
deleteImage() {
|
||||
this.clearImages()
|
||||
this.$emit('addHeroImage', null) // maybe?
|
||||
},
|
||||
cropImage() {
|
||||
this.isLoadingImage = true
|
||||
|
||||
const onCropComplete = (aspectRatio, imageFile) => {
|
||||
this.$emit('addImageAspectRatio', aspectRatio)
|
||||
this.$emit('addHeroImage', imageFile)
|
||||
this.$nextTick((this.isLoadingImage = false))
|
||||
this.closeCropper()
|
||||
}
|
||||
|
||||
if (this.file.type === 'image/jpeg') {
|
||||
const canvas = this.cropper.getCroppedCanvas()
|
||||
canvas.toBlob(blob => {
|
||||
const imageAspectRatio = canvas.width / canvas.height
|
||||
const croppedImageFile = new File([blob], this.file.name, { type: this.file.type })
|
||||
this.$emit('addHeroImage', croppedImageFile)
|
||||
this.$emit('addImageAspectRatio', imageAspectRatio)
|
||||
this.$emit('cropInProgress', false)
|
||||
this.setupPreview(canvas.toDataURL())
|
||||
onCropComplete(imageAspectRatio, croppedImageFile)
|
||||
}, 'image/jpeg')
|
||||
} else {
|
||||
// TODO: use cropped file instead of original file
|
||||
const imageAspectRatio = this.file.width / this.file.height || 1.0
|
||||
const croppedImageFile = this.file
|
||||
this.setupPreview(this.file.dataURL)
|
||||
this.$emit('addHeroImage', croppedImageFile)
|
||||
this.$emit('addImageAspectRatio', imageAspectRatio)
|
||||
this.$emit('cropInProgress', false)
|
||||
onCropComplete(imageAspectRatio, this.file)
|
||||
}
|
||||
this.closeCropper()
|
||||
},
|
||||
setupPreview(url) {
|
||||
const previewElement = document.querySelector('.image-uploader .preview-image')
|
||||
previewElement.src = url
|
||||
this.$nextTick((this.isLoadingImage = false))
|
||||
},
|
||||
closeCropper() {
|
||||
this.showCropper = false
|
||||
this.cropper.destroy()
|
||||
},
|
||||
cancelCrop() {
|
||||
if (this.oldImage) this.thumbnailElement.appendChild(this.oldImage)
|
||||
this.showCropper = false
|
||||
this.$emit('cropInProgress', false)
|
||||
deleteImage() {
|
||||
this.$emit('addHeroImage', null)
|
||||
this.$emit('addImageAspectRatio', null)
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -151,16 +137,6 @@ export default {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.--blur-image .preview-image {
|
||||
filter: blur($blur-radius);
|
||||
}
|
||||
|
||||
.preview-image {
|
||||
width: 100%;
|
||||
max-height: $size-image-max-height;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
> .crop-overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -212,12 +188,13 @@ export default {
|
||||
font-size: $size-icon-large;
|
||||
opacity: $opacity-soft;
|
||||
}
|
||||
|
||||
> .base-button {
|
||||
position: absolute;
|
||||
top: $space-small;
|
||||
right: $space-small;
|
||||
z-index: $z-index-surface;
|
||||
}
|
||||
}
|
||||
}
|
||||
.delete-image {
|
||||
position: absolute;
|
||||
top: $space-small;
|
||||
right: $space-small;
|
||||
z-index: $z-index-surface;
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user