Merge pull request #2585 from Human-Connection/1188-Delete_teaser_image

🍰feat: Delete teaser image
This commit is contained in:
Robert Schäfer 2020-02-18 22:50:33 +01:00 committed by GitHub
commit 523f6915de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 86 additions and 26 deletions

11
.vscode/settings.json vendored
View File

@ -1,11 +0,0 @@
{
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "vue",
"autoFix": true
}
],
"editor.formatOnSave": false,
}

View File

@ -5,7 +5,7 @@ import orderBy from 'lodash/orderBy'
const languages = orderBy(locales, 'name')
const narratorAvatar =
"https://s3.amazonaws.com/uifaces/faces/twitter/nerrsoft/128.jpg";
let expectedValue = { title: 'new post', content: 'new post content', src: 'onourjourney' }
When("I type in a comment with {int} characters", size => {
var c="";
for (var i = 0; i < size; i++) {
@ -89,8 +89,7 @@ Then("I see a toaster with {string}", (title) => {
Then("I should be able to {string} a teaser image", condition => {
cy.reload()
let teaserImageUpload = "onourjourney.png";
if (condition === 'change') teaserImageUpload = "humanconnection.png";
const teaserImageUpload = (condition === 'change') ? "humanconnection.png" : "onourjourney.png";
cy.fixture(teaserImageUpload).as('postTeaserImage').then(function() {
cy.get("#postdropzone").upload(
{ fileContent: this.postTeaserImage, fileName: teaserImageUpload, mimeType: "image/png" },
@ -120,15 +119,13 @@ Then("I add all required fields", () => {
})
Then("the post was saved successfully with the {string} teaser image", condition => {
if (condition === 'updated')
expectedValue = { title: 'to be updated', content: 'successfully updated', src: 'humanconnection' }
cy.get(".ds-card-content > .ds-heading")
.should("contain", expectedValue.title)
.should("contain", condition === 'updated' ? 'to be updated' : 'new post')
.get(".content")
.should("contain", expectedValue.content)
.should("contain", condition === 'updated' ? 'successfully updated' : 'new post content')
.get('.post-page img')
.should("have.attr", "src")
.and("contains", expectedValue.src)
.and("contains", condition === 'updated' ? 'humanconnection' : 'onourjourney')
})
Then("the first image should be removed from the preview", () => {
@ -142,11 +139,11 @@ Then("the first image should be removed from the preview", () => {
})
})
Then('the post was saved successfully without a teaser image', () => {
Then('the {string} post was saved successfully without a teaser image', condition => {
cy.get(".ds-card-content > .ds-heading")
.should("contain", 'new post')
.should("contain", condition === 'updated' ? 'to be updated' : 'new post')
.get(".content")
.should("contain", 'new post content')
.should("contain", condition === 'updated' ? 'successfully updated' : 'new post content')
.get('.post-page')
.should('exist')
.get('.post-page img.ds-card-image')
@ -156,4 +153,15 @@ Then('the post was saved successfully without a teaser image', () => {
Then('I should be able to remove it', () => {
cy.get('.crop-cancel')
.click()
})
When('my post has a teaser image', () => {
cy.get('.contribution-image')
.should('exist')
.and('have.attr', 'src')
})
Then('I should be able to remove the image', () => {
cy.get('.delete-image')
.click()
})

View File

@ -0,0 +1,19 @@
Feature: Delete Teaser Image
As a user
I would like to be able to remove an image I have previously added to my Post
So that I have control over the content of my Post
Background:
Given I have a user account
Given I am logged in
Given we have the following posts in our database:
| authorId | id | title | content |
| id-of-peter-pan | p1 | Post to be updated | successfully updated |
Scenario: Delete existing image
Given I am on the 'post/edit/p1' page
And my post has a teaser image
Then I should be able to remove the image
And I click on "Save"
Then I get redirected to ".../post-to-be-updated"
And the "updated" post was saved successfully without a teaser image

View File

@ -44,4 +44,4 @@ Feature: Upload Teaser Image
And I add all required fields
And I click on "Save"
Then I get redirected to ".../new-post"
And the post was saved successfully without a teaser image
And the "new" post was saved successfully without a teaser image

View File

@ -384,6 +384,15 @@ describe('ContributionForm.vue', () => {
await wrapper.find('form').trigger('submit')
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
})
it('supports deleting a teaser image', async () => {
expectedParams.variables.image = null
propsData.contribution.image = '/uploads/someimage.png'
wrapper = Wrapper()
wrapper.find('.contribution-form .delete-image').trigger('click')
await wrapper.find('form').trigger('submit')
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
})
})
})
})

View File

@ -7,11 +7,22 @@
@submit="submit"
>
<template slot-scope="{ errors }">
<base-button
v-if="showDeleteImageButton"
class="delete-image"
icon="close"
size="small"
circle
danger
filled
@click.prevent="deleteImage"
/>
<hc-teaser-image
:contribution="contribution"
@addTeaserImage="addTeaserImage"
:class="{ '--blur-image': form.blurImage }"
@addTeaserImage="addTeaserImage"
@addImageAspectRatio="addImageAspectRatio"
@cropInProgress="cropInProgress"
>
<img
v-if="contribution"
@ -195,6 +206,7 @@ export default {
contentMin: 3,
hashtags: [],
elem: null,
isCropInProgress: null,
}
},
computed: {
@ -204,6 +216,9 @@ export default {
...mapGetters({
currentUser: 'auth/user',
}),
showDeleteImageButton() {
return this.contribution && this.contribution.image && !this.isCropInProgress
},
},
methods: {
submit() {
@ -260,6 +275,14 @@ export default {
categoryIds(categories) {
return categories.map(c => c.id)
},
deleteImage() {
this.contribution.image = null
this.form.image = null
this.form.teaserImage = null
},
cropInProgress(boolean) {
this.isCropInProgress = boolean
},
},
apollo: {
User: {
@ -326,4 +349,11 @@ export default {
}
}
}
.delete-image {
right: 10px;
position: relative;
z-index: 1;
float: right;
top: $space-large;
}
</style>

View File

@ -89,6 +89,7 @@ export default {
},
transformImage(file) {
this.file = file
this.$emit('cropInProgress', true)
this.showCropper = true
this.initEditor()
this.initCropper()
@ -106,6 +107,9 @@ export default {
this.oldImage = contributionImage
if (contributionImage) contributionImage.remove()
},
deleteImage() {
this.clearImages()
},
initCropper() {
this.image = new Image()
this.image.src = URL.createObjectURL(this.file)
@ -145,10 +149,12 @@ export default {
cancelCrop() {
if (this.oldImage) this.thumbnailElement.appendChild(this.oldImage)
this.showCropper = false
this.$emit('cropInProgress', false)
},
emitImageData(imageFile) {
this.$emit('addTeaserImage', imageFile)
this.$emit('addImageAspectRatio', this.imageAspectRatio)
this.$emit('cropInProgress', false)
},
},
}
@ -222,7 +228,7 @@ export default {
}
.hc-drag-marker-update-post {
opacity: 0;
opacity: 0.1;
}
.contribution-form-footer {

View File

@ -157,7 +157,6 @@ export default {
border-radius: 100%;
border: 1px dashed hsl(0, 0%, 25%);
}
.hc-attachments-upload-area:hover & {
opacity: 1;
}