Add 2370-feature-deleting-contribution-must-be-analog-to-confirming-contribution-dialog changes.

This commit is contained in:
elweyn 2023-01-25 14:44:24 +01:00
commit 96262a2405
7 changed files with 228 additions and 209 deletions

View File

@ -39,7 +39,7 @@ module.exports = {
{ {
src: './src', src: './src',
extensions: ['.js', '.vue'], extensions: ['.js', '.vue'],
ignores: [], ignores: ['/overlay/'],
enableFix: false, enableFix: false,
}, },
], ],

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="component-overlay"> <div class="component-overlay">
<b-jumbotron class="bg-light p-4"> <b-jumbotron class="bg-light p-4">
<template #header>{{ $t('overlay.confirm.title') }}</template> <template #header><slot name="title" /></template>
<template #lead> <template #lead>
<b-row class="mt-4"> <b-row class="mt-4">
@ -31,10 +31,9 @@
</template> </template>
<hr class="my-4" /> <hr class="my-4" />
<p>{{ $t('overlay.confirm.text') }}</p> <slot name="text" />
<p> <slot name="question" />
{{ $t('overlay.confirm.question') }}
</p>
<b-container> <b-container>
<b-row> <b-row>
<b-col> <b-col>
@ -43,14 +42,7 @@
</b-button> </b-button>
</b-col> </b-col>
<b-col class="text-right"> <b-col class="text-right">
<b-button <slot name="submit-btn" />
size="md"
variant="success"
class="m-3 text-right"
@click="$emit('confirm-creation', item)"
>
{{ $t('overlay.confirm.yes') }}
</b-button>
</b-col> </b-col>
</b-row> </b-row>
</b-container> </b-container>

View File

@ -5,7 +5,7 @@
<b-button <b-button
variant="danger" variant="danger"
size="md" size="md"
@click="$emit('remove-creation', row.item)" @click="$emit('show-overlay', row.item, 'delete')"
class="mr-2" class="mr-2"
> >
<b-icon icon="trash" variant="light"></b-icon> <b-icon icon="trash" variant="light"></b-icon>
@ -37,30 +37,30 @@
</b-button> </b-button>
</div> </div>
</template> </template>
<template #cell(deny)="row">
<div v-if="$store.state.moderator.id !== row.item.userId">
<b-button
variant="warning"
size="md"
@click="$emit('show-overlay', row.item, 'deny')"
class="mr-2"
>
<b-icon icon="x" variant="light"></b-icon>
</b-button>
</div>
</template>
<template #cell(confirm)="row"> <template #cell(confirm)="row">
<div v-if="$store.state.moderator.id !== row.item.userId"> <div v-if="$store.state.moderator.id !== row.item.userId">
<b-button <b-button
variant="success" variant="success"
size="md" size="md"
@click="$emit('show-overlay', row.item)" @click="$emit('show-overlay', row.item, 'confirm')"
class="mr-2" class="mr-2"
> >
<b-icon icon="check" scale="2" variant=""></b-icon> <b-icon icon="check" scale="2" variant=""></b-icon>
</b-button> </b-button>
</div> </div>
</template> </template>
<template #cell(deny)="row">
<div v-if="$store.state.moderator.id !== row.item.userId">
<b-button
variant="danger"
size="md"
@click="$emit('deny-creation', row.item)"
class="mr-2"
>
<b-icon icon="x" variant="light"></b-icon>
</b-button>
</div>
</template>
<template #row-details="row"> <template #row-details="row">
<row-details <row-details
:row="row" :row="row"

View File

@ -34,8 +34,6 @@
"creation_form": { "creation_form": {
"creation_failed": "Ausstehende Schöpfung für {email} konnte nicht erzeugt werden.", "creation_failed": "Ausstehende Schöpfung für {email} konnte nicht erzeugt werden.",
"creation_for": "Aktives Grundeinkommen für", "creation_for": "Aktives Grundeinkommen für",
"deleteNow": "Möchtest du diesen Beitrag zur Gemeinschaft wirklich löschen?",
"denyNow": "Möchtest du diesen Beitrag zur Gemeinschaft wirklich ablehnen?",
"enter_text": "Text eintragen", "enter_text": "Text eintragen",
"form": "Schöpfungsformular", "form": "Schöpfungsformular",
"min_characters": "Mindestens 10 Zeichen eingeben", "min_characters": "Mindestens 10 Zeichen eingeben",
@ -113,12 +111,24 @@
"open": "offen", "open": "offen",
"open_creations": "Offene Schöpfungen", "open_creations": "Offene Schöpfungen",
"overlay": { "overlay": {
"cancel": "Abbrechen",
"confirm": { "confirm": {
"cancel": "Abbrechen", "question": "Willst du diesen Gemeinwohl-Beitrag wirklich bestätigen und gutschreiben?",
"question": "Willst du diese vorgespeicherte Schöpfung wirklich vollziehen und endgültig speichern?", "text": "Nach dem Speichern ist der Datensatz nicht mehr änderbar. Bitte überprüfe genau, dass alles stimmt.",
"title": "Gemeinwohl-Beitrag bestätigen!",
"yes": "Ja, Beitrag bestätigen und speichern!"
},
"delete": {
"question": "Willst du diesen Gemeinwohl-Beitrag wirklich endgültig löschen?",
"text": "Nach dem Löschen ist der Datensatz nicht mehr vorhanden.",
"title": "Gemeinwohl-Beitrag löschen!",
"yes": "Ja, Beitrag löschen!"
},
"deny": {
"question": "Willst du diesen Gemeinwohl-Beitrag wirklich ablehnen?",
"text": "Nach dem Speichern ist der Datensatz nicht mehr änderbar und kann auch nicht mehr gelöscht werden. Bitte überprüfe genau, dass alles stimmt.", "text": "Nach dem Speichern ist der Datensatz nicht mehr änderbar und kann auch nicht mehr gelöscht werden. Bitte überprüfe genau, dass alles stimmt.",
"title": "Schöpfung bestätigen!", "title": "Gemeinwohl-Beitrag ablehnen!",
"yes": "Ja, Schöpfung bestätigen und speichern!" "yes": "Ja, Beitrag ablehnen und speichern!"
} }
}, },
"redeemed": "eingelöst", "redeemed": "eingelöst",

View File

@ -34,8 +34,6 @@
"creation_form": { "creation_form": {
"creation_failed": "Could not create pending creation for {email}", "creation_failed": "Could not create pending creation for {email}",
"creation_for": "Active Basic Income for", "creation_for": "Active Basic Income for",
"deleteNow": "Do you really want to delete this contribution to the community?",
"denyNow": "Do you really want to reject this contribution to the community?",
"enter_text": "Enter text", "enter_text": "Enter text",
"form": "Creation form", "form": "Creation form",
"min_characters": "Enter at least 10 characters", "min_characters": "Enter at least 10 characters",
@ -113,12 +111,24 @@
"open": "open", "open": "open",
"open_creations": "Open creations", "open_creations": "Open creations",
"overlay": { "overlay": {
"cancel": "Cancel",
"confirm": { "confirm": {
"cancel": "Cancel",
"question": "Do you really want to carry out and finally save this pre-stored creation?", "question": "Do you really want to carry out and finally save this pre-stored creation?",
"text": "After saving, the record can no longer be changed or deleted. Please check carefully that everything is correct.", "text": "After saving, the record can no longer be changed. Please check carefully that everything is correct.",
"title": "Confirm creation!", "title": "Confirm creation!",
"yes": "Yes, confirm and save creation!" "yes": "Yes, confirm and save creation!"
},
"delete": {
"question": "Do you really want to carry out and finally save this pre-stored creation?",
"text": "After saving, the record can no longer be changed or deleted. Please check carefully that everything is correct.",
"title": "Delete creation!",
"yes": "Yes, delete and save creation!"
},
"deny": {
"question": "Do you really want to carry out and finally save this pre-stored creation?",
"text": "After saving, the record can no longer be changed or deleted. Please check carefully that everything is correct.",
"title": "Reject creation!",
"yes": "Yes, reject and save creation!"
} }
}, },
"redeemed": "redeemed", "redeemed": "redeemed",

View File

@ -139,108 +139,113 @@ describe('CreationConfirm', () => {
}) })
}) })
describe('remove creation with success', () => { describe('actions in overlay', () => {
let spy describe('delete creation', () => {
describe('admin confirms deletion', () => {
beforeEach(async () => { beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve('some value'))
await wrapper.findAll('tr').at(1).findAll('button').at(0).trigger('click') await wrapper.findAll('tr').at(1).findAll('button').at(0).trigger('click')
}) })
it('opens a modal', () => {
expect(spy).toBeCalled()
})
it('calls the adminDeleteContribution mutation', () => {
expect(adminDeleteContributionMock).toBeCalledWith({ id: 1 })
})
it('commits openCreationsMinus to store', () => {
expect(storeCommitMock).toBeCalledWith('openCreationsMinus', 1)
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_delete')
})
})
describe('admin cancels deletion', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve(false))
await wrapper.findAll('tr').at(1).findAll('button').at(0).trigger('click')
})
it('does not call the adminDeleteContribution mutation', () => {
expect(adminDeleteContributionMock).not.toBeCalled()
})
})
})
describe('remove creation with error', () => {
let spy
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve('some value'))
adminDeleteContributionMock.mockRejectedValue({ message: 'Ouchhh!' })
await wrapper.findAll('tr').at(1).findAll('button').at(0).trigger('click')
})
it('toasts an error message', () => {
expect(toastErrorSpy).toBeCalledWith('Ouchhh!')
})
})
describe('confirm creation with success', () => {
beforeEach(async () => {
await wrapper.findAll('tr').at(2).findAll('button').at(2).trigger('click')
})
describe('overlay', () => {
it('opens the overlay', () => { it('opens the overlay', () => {
expect(wrapper.find('#overlay').isVisible()).toBeTruthy() expect(wrapper.find('#overlay').isVisible()).toBeTruthy()
}) })
describe('cancel confirmation', () => { describe('with success', () => {
beforeEach(async () => { describe('cancel deletion', () => {
await wrapper.find('#overlay').findAll('button').at(0).trigger('click') beforeEach(async () => {
await wrapper.find('#overlay').findAll('button').at(0).trigger('click')
})
it('closes the overlay', async () => {
expect(wrapper.find('#overlay').exists()).toBeFalsy()
})
it('still has 2 items in the table', () => {
expect(wrapper.findAll('tbody > tr')).toHaveLength(2)
})
}) })
it('closes the overlay', async () => { describe('confirm deletion', () => {
expect(wrapper.find('#overlay').exists()).toBeFalsy() beforeEach(async () => {
await wrapper.find('#overlay').findAll('button').at(1).trigger('click')
})
it('calls the adminDeleteContribution mutation', () => {
expect(adminDeleteContributionMock).toBeCalledWith({ id: 1 })
})
it('commits openCreationsMinus to store', () => {
expect(storeCommitMock).toBeCalledWith('openCreationsMinus', 1)
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_delete')
})
it('has 1 item left in the table', () => {
expect(wrapper.findAll('tbody > tr')).toHaveLength(1)
})
}) })
it('still has 2 items in the table', () => { describe('with error', () => {
expect(wrapper.findAll('tbody > tr')).toHaveLength(2) beforeEach(async () => {
adminDeleteContributionMock.mockRejectedValue({ message: 'Ouchhh!' })
await wrapper.find('#overlay').findAll('button').at(1).trigger('click')
})
it('toasts an error message', () => {
expect(toastErrorSpy).toBeCalledWith('Ouchhh!')
})
})
})
})
describe('confirm creation', () => {
beforeEach(async () => {
await wrapper.findAll('tr').at(2).findAll('button').at(3).trigger('click')
})
it('opens the overlay', () => {
expect(wrapper.find('#overlay').isVisible()).toBeTruthy()
})
describe('with succes', () => {
describe('cancel confirmation', () => {
beforeEach(async () => {
await wrapper.find('#overlay').findAll('button').at(0).trigger('click')
})
it('closes the overlay', async () => {
expect(wrapper.find('#overlay').exists()).toBeFalsy()
})
it('still has 2 items in the table', () => {
expect(wrapper.findAll('tbody > tr')).toHaveLength(2)
})
})
describe('confirm confirmation', () => {
beforeEach(async () => {
await wrapper.find('#overlay').findAll('button').at(1).trigger('click')
})
it('calls the confirmContribution mutation', () => {
expect(confirmContributionMock).toBeCalledWith({ id: 2 })
})
it('commits openCreationsMinus to store', () => {
expect(storeCommitMock).toBeCalledWith('openCreationsMinus', 1)
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_created')
})
it('has 1 item left in the table', () => {
expect(wrapper.findAll('tbody > tr')).toHaveLength(1)
})
}) })
}) })
describe('confirm creation', () => { describe('with error', () => {
beforeEach(async () => {
await wrapper.find('#overlay').findAll('button').at(1).trigger('click')
})
it('calls the confirmContribution mutation', () => {
expect(confirmContributionMock).toBeCalledWith({ id: 2 })
})
it('commits openCreationsMinus to store', () => {
expect(storeCommitMock).toBeCalledWith('openCreationsMinus', 1)
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_created')
})
it('has 1 item left in the table', () => {
expect(wrapper.findAll('tbody > tr')).toHaveLength(1)
})
})
describe('confirm creation with error', () => {
beforeEach(async () => { beforeEach(async () => {
confirmContributionMock.mockRejectedValue({ message: 'Ouchhh!' }) confirmContributionMock.mockRejectedValue({ message: 'Ouchhh!' })
await wrapper.find('#overlay').findAll('button').at(1).trigger('click') await wrapper.find('#overlay').findAll('button').at(1).trigger('click')
@ -251,58 +256,63 @@ describe('CreationConfirm', () => {
}) })
}) })
}) })
})
describe('deny creation with error', () => { describe('deny creation', () => {
let spy
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve('some value'))
await wrapper.findAll('tr').at(1).findAll('button').at(0).trigger('click')
})
it('toasts an error message', () => {
expect(toastErrorSpy).toBeCalledWith('Ouchhh!')
})
})
describe('deny creation with success', () => {
let spy
describe('admin confirms deny', () => {
beforeEach(async () => { beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') await wrapper.findAll('tr').at(1).findAll('button').at(2).trigger('click')
spy.mockImplementation(() => Promise.resolve('some value'))
await wrapper.findAll('tr').at(1).findAll('button').at(3).trigger('click')
}) })
it('opens a modal', () => { it('opens the overlay', () => {
expect(spy).toBeCalled() expect(wrapper.find('#overlay').isVisible()).toBeTruthy()
}) })
it('calls the adminDeleteContribution mutation', () => { describe('with succes', () => {
expect(adminDenyContributionMock).toBeCalledWith({ id: 1 }) describe('cancel deny', () => {
beforeEach(async () => {
await wrapper.find('#overlay').findAll('button').at(0).trigger('click')
})
it('closes the overlay', async () => {
expect(wrapper.find('#overlay').exists()).toBeFalsy()
})
it('still has 2 items in the table', () => {
expect(wrapper.findAll('tbody > tr')).toHaveLength(2)
})
})
describe('confirm deny', () => {
beforeEach(async () => {
await wrapper.find('#overlay').findAll('button').at(1).trigger('click')
})
it('calls the denyContribution mutation', () => {
expect(adminDenyContributionMock).toBeCalledWith({ id: 1 })
})
it('commits openCreationsMinus to store', () => {
expect(storeCommitMock).toBeCalledWith('openCreationsMinus', 1)
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_denied')
})
it('has 1 item left in the table', () => {
expect(wrapper.findAll('tbody > tr')).toHaveLength(1)
})
})
}) })
it('commits openCreationsMinus to store', () => { describe('with error', () => {
expect(storeCommitMock).toBeCalledWith('openCreationsMinus', 1) beforeEach(async () => {
}) adminDenyContributionMock.mockRejectedValue({ message: 'Ouchhh!' })
await wrapper.find('#overlay').findAll('button').at(1).trigger('click')
})
it('toasts a success message', () => { it('toasts an error message', () => {
expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_denied') expect(toastErrorSpy).toBeCalledWith('Ouchhh!')
}) })
})
describe('admin cancels deny', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve(false))
await wrapper.findAll('tr').at(1).findAll('button').at(3).trigger('click')
})
it('does not call the adminDeleteContribution mutation', () => {
expect(adminDenyContributionMock).not.toBeCalled()
}) })
}) })
}) })

View File

@ -28,8 +28,6 @@
class="mt-4" class="mt-4"
:items="pendingCreations" :items="pendingCreations"
:fields="fields" :fields="fields"
@deny-creation="denyCreation"
@remove-creation="removeCreation"
@show-overlay="showOverlay" @show-overlay="showOverlay"
@update-state="updateState" @update-state="updateState"
@update-contributions="$apollo.queries.PendingContributions.refetch()" @update-contributions="$apollo.queries.PendingContributions.refetch()"
@ -55,47 +53,45 @@ export default {
pendingCreations: [], pendingCreations: [],
overlay: false, overlay: false,
item: {}, item: {},
variant: 'confirm',
} }
}, },
methods: { methods: {
denyCreation(item) { deleteCreation() {
this.$bvModal.msgBoxConfirm(this.$t('creation_form.denyNow')).then(async (value) => { this.$apollo
if (value) { .mutate({
await this.$apollo mutation: adminDeleteContribution,
.mutate({ variables: {
mutation: denyContribution, id: this.item.id,
variables: { },
id: item.id, })
}, .then((result) => {
}) this.overlay = false
.then((result) => { this.updatePendingCreations(this.item.id)
this.updatePendingCreations(item.id) this.toastSuccess(this.$t('creation_form.toasted_delete'))
this.toastSuccess(this.$t('creation_form.toasted_denied')) })
}) .catch((error) => {
.catch((error) => { this.overlay = false
this.toastError(error.message) this.toastError(error.message)
}) })
}
})
}, },
removeCreation(item) { denyCreation() {
this.$bvModal.msgBoxConfirm(this.$t('creation_form.deleteNow')).then(async (value) => { this.$apollo
if (value) .mutate({
await this.$apollo mutation: denyContribution,
.mutate({ variables: {
mutation: adminDeleteContribution, id: this.item.id,
variables: { },
id: item.id, })
}, .then((result) => {
}) this.overlay = false
.then((result) => { this.updatePendingCreations(this.item.id)
this.updatePendingCreations(item.id) this.toastSuccess(this.$t('creation_form.toasted_denied'))
this.toastSuccess(this.$t('creation_form.toasted_delete')) })
}) .catch((error) => {
.catch((error) => { this.overlay = false
this.toastError(error.message) this.toastError(error.message)
}) })
})
}, },
confirmCreation() { confirmCreation() {
this.$apollo this.$apollo
@ -119,9 +115,10 @@ export default {
this.pendingCreations = this.pendingCreations.filter((obj) => obj.id !== id) this.pendingCreations = this.pendingCreations.filter((obj) => obj.id !== id)
this.$store.commit('openCreationsMinus', 1) this.$store.commit('openCreationsMinus', 1)
}, },
showOverlay(item) { showOverlay(item, variant) {
this.overlay = true this.overlay = true
this.item = item this.item = item
this.variant = variant
}, },
updateState(id) { updateState(id) {
this.pendingCreations.find((obj) => obj.id === id).messagesCount++ this.pendingCreations.find((obj) => obj.id === id).messagesCount++
@ -152,8 +149,8 @@ export default {
}, },
{ key: 'moderator', label: this.$t('moderator') }, { key: 'moderator', label: this.$t('moderator') },
{ key: 'editCreation', label: this.$t('edit') }, { key: 'editCreation', label: this.$t('edit') },
{ key: 'confirm', label: this.$t('save') },
{ key: 'deny', label: this.$t('deny') }, { key: 'deny', label: this.$t('deny') },
{ key: 'confirm', label: this.$t('save') },
] ]
}, },
overlayTitle() { overlayTitle() {