From bfaa77482ce130f11061856c15d1edb1371e6986 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:07:35 +0100 Subject: [PATCH 01/15] refactor: Bootstrap Vue Toast in Admin Interface --- .../ConfirmRegisterMailFormular.spec.js | 12 +++----- .../ConfirmRegisterMailFormular.vue | 4 +-- admin/src/locales/de.json | 4 ++- admin/src/locales/en.json | 4 ++- admin/src/main.js | 14 ++------- admin/src/mixins/toaster.js | 29 +++++++++++++++++++ admin/test/testSetup.js | 7 +++++ 7 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 admin/src/mixins/toaster.js diff --git a/admin/src/components/ConfirmRegisterMailFormular.spec.js b/admin/src/components/ConfirmRegisterMailFormular.spec.js index 78f5791dc..e9e21b31e 100644 --- a/admin/src/components/ConfirmRegisterMailFormular.spec.js +++ b/admin/src/components/ConfirmRegisterMailFormular.spec.js @@ -1,21 +1,17 @@ import { mount } from '@vue/test-utils' import ConfirmRegisterMailFormular from './ConfirmRegisterMailFormular.vue' +import { toastErrorSpy, toastSuccessSpy } from '../../test/testSetup' + const localVue = global.localVue const apolloMutateMock = jest.fn().mockResolvedValue() -const toastSuccessMock = jest.fn() -const toastErrorMock = jest.fn() const mocks = { $t: jest.fn((t) => t), $apollo: { mutate: apolloMutateMock, }, - $toasted: { - success: toastSuccessMock, - error: toastErrorMock, - }, } const propsData = { @@ -54,7 +50,7 @@ describe('ConfirmRegisterMailFormular', () => { }) it('toasts a success message', () => { - expect(toastSuccessMock).toBeCalledWith('unregister_mail.success') + expect(toastSuccessSpy).toBeCalledWith('unregister_mail.success') }) }) @@ -66,7 +62,7 @@ describe('ConfirmRegisterMailFormular', () => { }) it('toasts an error message', () => { - expect(toastErrorMock).toBeCalledWith('unregister_mail.error') + expect(toastErrorSpy).toBeCalledWith('unregister_mail.error') }) }) }) diff --git a/admin/src/components/ConfirmRegisterMailFormular.vue b/admin/src/components/ConfirmRegisterMailFormular.vue index 067e95c67..1b72f55d0 100644 --- a/admin/src/components/ConfirmRegisterMailFormular.vue +++ b/admin/src/components/ConfirmRegisterMailFormular.vue @@ -48,10 +48,10 @@ export default { }, }) .then(() => { - this.$toasted.success(this.$t('unregister_mail.success', { email: this.email })) + this.toastSuccess(this.$t('unregister_mail.success', { email: this.email })) }) .catch((error) => { - this.$toasted.error(this.$t('unregister_mail.error', { message: error.message })) + this.toastError(this.$t('unregister_mail.error', { message: error.message })) }) }, }, diff --git a/admin/src/locales/de.json b/admin/src/locales/de.json index e5f4bf4ca..e9bc6ec51 100644 --- a/admin/src/locales/de.json +++ b/admin/src/locales/de.json @@ -92,5 +92,7 @@ "userIsDeleted": "Der Nutzer ist gelöscht. Es können keine GDD mehr geschöpft werden.", "user_deleted": "Nutzer ist gelöscht.", "user_recovered": "Nutzer ist wiederhergestellt.", - "user_search": "Nutzer-Suche" + "user_search": "Nutzer-Suche", + "error": "Fehler", + "success": "Erfolg" } diff --git a/admin/src/locales/en.json b/admin/src/locales/en.json index d772d638f..36b37e609 100644 --- a/admin/src/locales/en.json +++ b/admin/src/locales/en.json @@ -92,5 +92,7 @@ "userIsDeleted": "The user is deleted. No more GDD can be created.", "user_deleted": "User is deleted.", "user_recovered": "User is recovered.", - "user_search": "User search" + "user_search": "User search", + "error": "Error", + "success": "Success" } diff --git a/admin/src/main.js b/admin/src/main.js index f4a8dfb3c..fb6de5f17 100644 --- a/admin/src/main.js +++ b/admin/src/main.js @@ -17,7 +17,7 @@ import { BootstrapVue, IconsPlugin } from 'bootstrap-vue' import 'bootstrap/dist/css/bootstrap.css' import 'bootstrap-vue/dist/bootstrap-vue.css' -import Toasted from 'vue-toasted' +import { toasters } from './mixins/toaster' import { apolloProvider } from './plugins/apolloProvider' @@ -27,17 +27,7 @@ Vue.use(IconsPlugin) Vue.use(VueApollo) -Vue.use(Toasted, { - position: 'top-center', - duration: 5000, - fullWidth: true, - action: { - text: 'x', - onClick: (e, toastObject) => { - toastObject.goAway(0) - }, - }, -}) +Vue.mixin(toasters) addNavigationGuards(router, store, apolloProvider.defaultClient, i18n) diff --git a/admin/src/mixins/toaster.js b/admin/src/mixins/toaster.js new file mode 100644 index 000000000..b9ce02db2 --- /dev/null +++ b/admin/src/mixins/toaster.js @@ -0,0 +1,29 @@ +export const toasters = { + methods: { + toastSuccess(message) { + this.toast(message, { + title: this.$t('success'), + variant: 'success', + }) + }, + toastError(message) { + this.toast(message, { + title: this.$t('error'), + variant: 'danger', + }) + }, + toast(message, options) { + message = message.replace(/^GraphQL error: /, '') + this.$bvToast.toast(message, { + autoHideDelay: 5000, + appendToast: true, + solid: true, + toaster: 'b-toaster-top-right', + headerClass: 'gdd-toaster-title', + bodyClass: 'gdd-toaster-body', + toastClass: 'gdd-toaster', + ...options, + }) + }, + }, +} diff --git a/admin/test/testSetup.js b/admin/test/testSetup.js index caaa3c19c..df3a025da 100644 --- a/admin/test/testSetup.js +++ b/admin/test/testSetup.js @@ -5,11 +5,18 @@ import { BootstrapVue, IconsPlugin } from 'bootstrap-vue' // without this async calls are not working import 'regenerator-runtime' +import { toasters } from '../src/mixins/toaster' + +export const toastErrorSpy = jest.spyOn(toasters.methods, 'toastError') +export const toastSuccessSpy = jest.spyOn(toasters.methods, 'toastSuccess') + global.localVue = createLocalVue() global.localVue.use(BootstrapVue) global.localVue.use(IconsPlugin) +global.localVue.mixin(toasters) + // throw errors for vue warnings to force the programmers to take care about warnings Vue.config.warnHandler = (w) => { throw new Error(w) From f2af15991470a31bbb73715450d17f4e9008dc79 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:23:20 +0100 Subject: [PATCH 02/15] bv toast in creation formular --- admin/src/components/CreationFormular.spec.js | 19 +++++++------------ admin/src/components/CreationFormular.vue | 10 +++++----- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/admin/src/components/CreationFormular.spec.js b/admin/src/components/CreationFormular.spec.js index cfc23fa26..f2ce36908 100644 --- a/admin/src/components/CreationFormular.spec.js +++ b/admin/src/components/CreationFormular.spec.js @@ -2,6 +2,7 @@ import { mount } from '@vue/test-utils' import CreationFormular from './CreationFormular.vue' import { createPendingCreation } from '../graphql/createPendingCreation' import { createPendingCreations } from '../graphql/createPendingCreations' +import { toastErrorSpy, toastSuccessSpy } from '../../test/testSetup' const localVue = global.localVue @@ -11,8 +12,6 @@ const apolloMutateMock = jest.fn().mockResolvedValue({ }, }) const stateCommitMock = jest.fn() -const toastedErrorMock = jest.fn() -const toastedSuccessMock = jest.fn() const mocks = { $t: jest.fn((t, options) => (options ? [t, options] : t)), @@ -32,10 +31,6 @@ const mocks = { }, }, }, - $toasted: { - error: toastedErrorMock, - success: toastedSuccessMock, - }, } const propsData = { @@ -140,7 +135,7 @@ describe('CreationFormular', () => { }) it('toasts a success message', () => { - expect(toastedSuccessMock).toBeCalledWith([ + expect(toastSuccessSpy).toBeCalledWith([ 'creation_form.toasted', { email: 'benjamin@bluemchen.de', value: '90' }, ]) @@ -162,7 +157,7 @@ describe('CreationFormular', () => { }) it('toasts an error message', () => { - expect(toastedErrorMock).toBeCalledWith('Ouch!') + expect(toastErrorSpy).toBeCalledWith('Ouch!') }) }) @@ -292,7 +287,7 @@ describe('CreationFormular', () => { }) it('toast success message', () => { - expect(toastedSuccessMock).toBeCalled() + expect(toastSuccessSpy).toBeCalled() }) it('store commit openCreationPlus', () => { @@ -427,10 +422,10 @@ describe('CreationFormular', () => { }) it('toasts two errors', () => { - expect(toastedErrorMock).toBeCalledWith( + expect(toastErrorSpy).toBeCalledWith( 'Could not created PendingCreation for bob@baumeister.de', ) - expect(toastedErrorMock).toBeCalledWith( + expect(toastErrorSpy).toBeCalledWith( 'Could not created PendingCreation for bibi@bloxberg.de', ) }) @@ -454,7 +449,7 @@ describe('CreationFormular', () => { }) it('toasts an error message', () => { - expect(toastedErrorMock).toBeCalledWith('Oh no!') + expect(toastErrorSpy).toBeCalledWith('Oh no!') }) }) }) diff --git a/admin/src/components/CreationFormular.vue b/admin/src/components/CreationFormular.vue index 34df13e11..a705bbba8 100644 --- a/admin/src/components/CreationFormular.vue +++ b/admin/src/components/CreationFormular.vue @@ -173,13 +173,13 @@ export default { if (result.data.createPendingCreations.failedCreation.length > 0) { result.data.createPendingCreations.failedCreation.forEach((failed) => { // TODO: Please localize this error message - this.$toasted.error('Could not created PendingCreation for ' + failed) + this.toastError('Could not created PendingCreation for ' + failed) }) } this.$emit('remove-all-bookmark') }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) }) } else if (this.type === 'singleCreation') { submitObj = { @@ -196,19 +196,19 @@ export default { }) .then((result) => { this.$emit('update-user-data', this.item, result.data.createPendingCreation) - this.$toasted.success( + this.$store.commit('openCreationsPlus', 1) + this.toastSuccess( this.$t('creation_form.toasted', { value: this.value, email: this.item.email, }), ) - this.$store.commit('openCreationsPlus', 1) // what is this? Tests says that this.text is not reseted this.$refs.creationForm.reset() this.value = 0 }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) this.$refs.creationForm.reset() this.value = 0 }) From 11808f1e228f27c39fd3286fcbfe4784f27db030 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:26:10 +0100 Subject: [PATCH 03/15] bv toast in creation transaction formular --- .../components/CreationTransactionListFormular.spec.js | 8 ++------ admin/src/components/CreationTransactionListFormular.vue | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/admin/src/components/CreationTransactionListFormular.spec.js b/admin/src/components/CreationTransactionListFormular.spec.js index 88cda89ee..7331184b7 100644 --- a/admin/src/components/CreationTransactionListFormular.spec.js +++ b/admin/src/components/CreationTransactionListFormular.spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils' import CreationTransactionListFormular from './CreationTransactionListFormular.vue' +import { toastErrorSpy } from '../../test/testSetup' const localVue = global.localVue @@ -50,17 +51,12 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ }, }) -const toastedErrorMock = jest.fn() - const mocks = { $d: jest.fn((t) => t), $t: jest.fn((t) => t), $apollo: { query: apolloQueryMock, }, - $toasted: { - error: toastedErrorMock, - }, } const propsData = { @@ -109,7 +105,7 @@ describe('CreationTransactionListFormular', () => { }) it('toast error', () => { - expect(toastedErrorMock).toBeCalledWith('OUCH!') + expect(toastErrorSpy).toBeCalledWith('OUCH!') }) }) }) diff --git a/admin/src/components/CreationTransactionListFormular.vue b/admin/src/components/CreationTransactionListFormular.vue index 627647534..f4fbe7c8b 100644 --- a/admin/src/components/CreationTransactionListFormular.vue +++ b/admin/src/components/CreationTransactionListFormular.vue @@ -62,7 +62,7 @@ export default { this.items = result.data.transactionList.transactions.filter((t) => t.type === 'creation') }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) }) }, }, From bb4a237f18c4b47448676d1d292e7da44eb0af32 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:29:01 +0100 Subject: [PATCH 04/15] bv toast in deleted user formular --- admin/src/components/DeletedUserFormular.spec.js | 16 +++++----------- admin/src/components/DeletedUserFormular.vue | 8 ++++---- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/admin/src/components/DeletedUserFormular.spec.js b/admin/src/components/DeletedUserFormular.spec.js index bad97c1d7..78ed5e43f 100644 --- a/admin/src/components/DeletedUserFormular.spec.js +++ b/admin/src/components/DeletedUserFormular.spec.js @@ -2,6 +2,7 @@ import { mount } from '@vue/test-utils' import DeletedUserFormular from './DeletedUserFormular.vue' import { deleteUser } from '../graphql/deleteUser' import { unDeleteUser } from '../graphql/unDeleteUser' +import { toastErrorSpy, toastSuccessSpy } from '../../test/testSetup' const localVue = global.localVue @@ -13,9 +14,6 @@ const apolloMutateMock = jest.fn().mockResolvedValue({ }, }) -const toastedErrorMock = jest.fn() -const toastedSuccessMock = jest.fn() - const mocks = { $t: jest.fn((t) => t), $apollo: { @@ -29,10 +27,6 @@ const mocks = { }, }, }, - $toasted: { - error: toastedErrorMock, - success: toastedSuccessMock, - }, } const propsData = { @@ -119,7 +113,7 @@ describe('DeletedUserFormular', () => { }) it('toasts a success message', () => { - expect(toastedSuccessMock).toBeCalledWith('user_deleted') + expect(toastSuccessSpy).toBeCalledWith('user_deleted') }) it('emits update deleted At', () => { @@ -147,7 +141,7 @@ describe('DeletedUserFormular', () => { }) it('toasts an error message', () => { - expect(toastedErrorMock).toBeCalledWith('Oh no!') + expect(toastErrorSpy).toBeCalledWith('Oh no!') }) }) @@ -216,7 +210,7 @@ describe('DeletedUserFormular', () => { }) it('toasts a success message', () => { - expect(toastedSuccessMock).toBeCalledWith('user_recovered') + expect(toastSuccessSpy).toBeCalledWith('user_recovered') }) it('emits update deleted At', () => { @@ -244,7 +238,7 @@ describe('DeletedUserFormular', () => { }) it('toasts an error message', () => { - expect(toastedErrorMock).toBeCalledWith('Oh no!') + expect(toastErrorSpy).toBeCalledWith('Oh no!') }) }) diff --git a/admin/src/components/DeletedUserFormular.vue b/admin/src/components/DeletedUserFormular.vue index b840fdb23..be9f280d9 100644 --- a/admin/src/components/DeletedUserFormular.vue +++ b/admin/src/components/DeletedUserFormular.vue @@ -45,7 +45,7 @@ export default { }, }) .then((result) => { - this.$toasted.success(this.$t('user_deleted')) + this.toastSuccess(this.$t('user_deleted')) this.$emit('updateDeletedAt', { userId: this.item.userId, deletedAt: result.data.deleteUser, @@ -53,7 +53,7 @@ export default { this.checked = false }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) }) }, unDeleteUser() { @@ -65,7 +65,7 @@ export default { }, }) .then((result) => { - this.$toasted.success(this.$t('user_recovered')) + this.toastSuccess(this.$t('user_recovered')) this.$emit('updateDeletedAt', { userId: this.item.userId, deletedAt: result.data.unDeleteUser, @@ -73,7 +73,7 @@ export default { this.checked = false }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) }) }, }, From 371bfba0eef49223c115252cca5c30c2437e7b83 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:31:08 +0100 Subject: [PATCH 05/15] bv toast in edit creation formular --- admin/src/components/EditCreationFormular.spec.js | 11 +++-------- admin/src/components/EditCreationFormular.vue | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/admin/src/components/EditCreationFormular.spec.js b/admin/src/components/EditCreationFormular.spec.js index 84d3e26d3..f5c7fb0fe 100644 --- a/admin/src/components/EditCreationFormular.spec.js +++ b/admin/src/components/EditCreationFormular.spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils' import EditCreationFormular from './EditCreationFormular.vue' +import { toastErrorSpy, toastSuccessSpy } from '../../test/testSetup' const localVue = global.localVue @@ -16,8 +17,6 @@ const apolloMutateMock = jest.fn().mockResolvedValue({ }) const stateCommitMock = jest.fn() -const toastedErrorMock = jest.fn() -const toastedSuccessMock = jest.fn() const mocks = { $t: jest.fn((t) => t), @@ -37,10 +36,6 @@ const mocks = { }, commit: stateCommitMock, }, - $toasted: { - error: toastedErrorMock, - success: toastedSuccessMock, - }, } const now = new Date(Date.now()) @@ -142,7 +137,7 @@ describe('EditCreationFormular', () => { }) it('toasts a success message', () => { - expect(toastedSuccessMock).toBeCalledWith('creation_form.toasted_update') + expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_update') }) }) @@ -155,7 +150,7 @@ describe('EditCreationFormular', () => { }) it('toasts an error message', () => { - expect(toastedErrorMock).toBeCalledWith('Oh no!') + expect(toastErrorSpy).toBeCalledWith('Oh no!') }) }) }) diff --git a/admin/src/components/EditCreationFormular.vue b/admin/src/components/EditCreationFormular.vue index 650b00410..82b444154 100644 --- a/admin/src/components/EditCreationFormular.vue +++ b/admin/src/components/EditCreationFormular.vue @@ -132,7 +132,7 @@ export default { moderator: Number(result.data.updatePendingCreation.moderator), row: this.row, }) - this.$toasted.success( + this.toastSuccess( this.$t('creation_form.toasted_update', { value: this.value, email: this.item.email, @@ -144,7 +144,7 @@ export default { this.value = 0 }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) // das creation Formular reseten this.$refs.updateCreationForm.reset() // Den geschöpften Wert auf o setzen From b8f4980bdad053b33c5310410e8eb40a0531433e Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:33:40 +0100 Subject: [PATCH 06/15] bv toast in creation page --- admin/src/pages/Creation.spec.js | 7 ++----- admin/src/pages/Creation.vue | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/admin/src/pages/Creation.spec.js b/admin/src/pages/Creation.spec.js index 81d556e9b..4bbd25e5b 100644 --- a/admin/src/pages/Creation.spec.js +++ b/admin/src/pages/Creation.spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils' import Creation from './Creation.vue' +import { toastErrorSpy } from '../../test/testSetup' const localVue = global.localVue @@ -29,7 +30,6 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ }, }) -const toastErrorMock = jest.fn() const storeCommitMock = jest.fn() const mocks = { @@ -38,9 +38,6 @@ const mocks = { $apollo: { query: apolloQueryMock, }, - $toasted: { - error: toastErrorMock, - }, $store: { commit: storeCommitMock, state: { @@ -298,7 +295,7 @@ describe('Creation', () => { }) it('toasts an error message', () => { - expect(toastErrorMock).toBeCalledWith('Ouch') + expect(toastErrorSpy).toBeCalledWith('Ouch') }) }) }) diff --git a/admin/src/pages/Creation.vue b/admin/src/pages/Creation.vue index 16678cad8..10217fae6 100644 --- a/admin/src/pages/Creation.vue +++ b/admin/src/pages/Creation.vue @@ -118,7 +118,7 @@ export default { } }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) }) }, pushItem(selectedItem) { From 16501a7488ae7ffe66baf240b93b7cf0cf839b33 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:36:57 +0100 Subject: [PATCH 07/15] bv toast in creation confirm page --- admin/src/pages/CreationConfirm.spec.js | 17 ++++++----------- admin/src/pages/CreationConfirm.vue | 10 +++++----- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/admin/src/pages/CreationConfirm.spec.js b/admin/src/pages/CreationConfirm.spec.js index f0412678b..6df60378c 100644 --- a/admin/src/pages/CreationConfirm.spec.js +++ b/admin/src/pages/CreationConfirm.spec.js @@ -2,12 +2,11 @@ import { mount } from '@vue/test-utils' import CreationConfirm from './CreationConfirm.vue' import { deletePendingCreation } from '../graphql/deletePendingCreation' import { confirmPendingCreation } from '../graphql/confirmPendingCreation' +import { toastErrorSpy, toastSuccessSpy } from '../../test/testSetup' const localVue = global.localVue const storeCommitMock = jest.fn() -const toastedErrorMock = jest.fn() -const toastedSuccessMock = jest.fn() const apolloQueryMock = jest.fn().mockResolvedValue({ data: { getPendingCreations: [ @@ -47,10 +46,6 @@ const mocks = { query: apolloQueryMock, mutate: apolloMutateMock, }, - $toasted: { - error: toastedErrorMock, - success: toastedSuccessMock, - }, } describe('CreationConfirm', () => { @@ -101,7 +96,7 @@ describe('CreationConfirm', () => { }) it('toasts a success message', () => { - expect(toastedSuccessMock).toBeCalledWith('creation_form.toasted_delete') + expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_delete') }) }) @@ -112,7 +107,7 @@ describe('CreationConfirm', () => { }) it('toasts an error message', () => { - expect(toastedErrorMock).toBeCalledWith('Ouchhh!') + expect(toastErrorSpy).toBeCalledWith('Ouchhh!') }) }) @@ -158,7 +153,7 @@ describe('CreationConfirm', () => { }) it('toasts a success message', () => { - expect(toastedSuccessMock).toBeCalledWith('creation_form.toasted_created') + expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_created') }) it('has 1 item left in the table', () => { @@ -173,7 +168,7 @@ describe('CreationConfirm', () => { }) it('toasts an error message', () => { - expect(toastedErrorMock).toBeCalledWith('Ouchhh!') + expect(toastErrorSpy).toBeCalledWith('Ouchhh!') }) }) }) @@ -189,7 +184,7 @@ describe('CreationConfirm', () => { }) it('toast an error message', () => { - expect(toastedErrorMock).toBeCalledWith('Ouch!') + expect(toastErrorSpy).toBeCalledWith('Ouch!') }) }) }) diff --git a/admin/src/pages/CreationConfirm.vue b/admin/src/pages/CreationConfirm.vue index 54580c366..26928fb67 100644 --- a/admin/src/pages/CreationConfirm.vue +++ b/admin/src/pages/CreationConfirm.vue @@ -43,10 +43,10 @@ export default { }) .then((result) => { this.updatePendingCreations(item.id) - this.$toasted.success(this.$t('creation_form.toasted_delete')) + this.toastSuccess(this.$t('creation_form.toasted_delete')) }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) }) }, confirmCreation() { @@ -60,11 +60,11 @@ export default { .then((result) => { this.overlay = false this.updatePendingCreations(this.item.id) - this.$toasted.success(this.$t('creation_form.toasted_created')) + this.toastSuccess(this.$t('creation_form.toasted_created')) }) .catch((error) => { this.overlay = false - this.$toasted.error(error.message) + this.toastError(error.message) }) }, getPendingCreations() { @@ -79,7 +79,7 @@ export default { this.$store.commit('setOpenCreations', result.data.getPendingCreations.length) }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) }) }, updatePendingCreations(id) { From 1d31b00622b615962f49f4a56de7696982aab922 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:40:46 +0100 Subject: [PATCH 08/15] bv toast in user search page --- admin/src/components/Tables/SearchUserTable.spec.js | 4 ---- admin/src/pages/UserSearch.spec.js | 8 ++------ admin/src/pages/UserSearch.vue | 2 +- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/admin/src/components/Tables/SearchUserTable.spec.js b/admin/src/components/Tables/SearchUserTable.spec.js index 9e1ce5e52..eb87357cc 100644 --- a/admin/src/components/Tables/SearchUserTable.spec.js +++ b/admin/src/components/Tables/SearchUserTable.spec.js @@ -73,10 +73,6 @@ const mocks = { }, }, }, - $toasted: { - error: jest.fn(), - success: jest.fn(), - }, } describe('SearchUserTable', () => { diff --git a/admin/src/pages/UserSearch.spec.js b/admin/src/pages/UserSearch.spec.js index ab2bd722f..5f91f679a 100644 --- a/admin/src/pages/UserSearch.spec.js +++ b/admin/src/pages/UserSearch.spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils' import UserSearch from './UserSearch.vue' +import { toastErrorSpy } from '../../test/testSetup' const localVue = global.localVue @@ -45,17 +46,12 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ }, }) -const toastErrorMock = jest.fn() - const mocks = { $t: jest.fn((t) => t), $d: jest.fn((d) => String(d)), $apollo: { query: apolloQueryMock, }, - $toasted: { - error: toastErrorMock, - }, } describe('UserSearch', () => { @@ -196,7 +192,7 @@ describe('UserSearch', () => { }) it('toasts an error message', () => { - expect(toastErrorMock).toBeCalledWith('Ouch') + expect(toastErrorSpy).toBeCalledWith('Ouch') }) }) }) diff --git a/admin/src/pages/UserSearch.vue b/admin/src/pages/UserSearch.vue index edd64445c..a24a47c26 100644 --- a/admin/src/pages/UserSearch.vue +++ b/admin/src/pages/UserSearch.vue @@ -94,7 +94,7 @@ export default { this.searchResult = result.data.searchUsers.userList }) .catch((error) => { - this.$toasted.error(error.message) + this.toastError(error.message) }) }, updateDeletedAt(userId, deletedAt) { From f887781c54b9a4b0a0ea8e7adb04683384268c0d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:43:45 +0100 Subject: [PATCH 09/15] remove vue-toasted package --- admin/package.json | 1 - admin/yarn.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/admin/package.json b/admin/package.json index 0cbf57f5a..8f72d996f 100644 --- a/admin/package.json +++ b/admin/package.json @@ -43,7 +43,6 @@ "vue-i18n": "^8.26.5", "vue-jest": "^3.0.7", "vue-router": "^3.5.3", - "vue-toasted": "^1.1.28", "vuex": "^3.6.2", "vuex-persistedstate": "^4.1.0" }, diff --git a/admin/yarn.lock b/admin/yarn.lock index aff8f0d0b..4e5d587e5 100644 --- a/admin/yarn.lock +++ b/admin/yarn.lock @@ -12512,11 +12512,6 @@ vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0: resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== -vue-toasted@^1.1.28: - version "1.1.28" - resolved "https://registry.yarnpkg.com/vue-toasted/-/vue-toasted-1.1.28.tgz#dbabb83acc89f7a9e8765815e491d79f0dc65c26" - integrity sha512-UUzr5LX51UbbiROSGZ49GOgSzFxaMHK6L00JV8fir/CYNJCpIIvNZ5YmS4Qc8Y2+Z/4VVYRpeQL2UO0G800Raw== - vue@^2.6.11: version "2.6.14" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235" From 950d0181a0fd77cff241918d2c02a57d9758ec54 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 12:50:53 +0100 Subject: [PATCH 10/15] fix locales --- admin/src/locales/de.json | 6 +++--- admin/src/locales/en.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/admin/src/locales/de.json b/admin/src/locales/de.json index e9bc6ec51..feae344c4 100644 --- a/admin/src/locales/de.json +++ b/admin/src/locales/de.json @@ -28,6 +28,7 @@ "delete_user": "Nutzer löschen", "details": "Details", "edit": "Bearbeiten", + "error": "Fehler", "e_mail": "E-Mail", "firstname": "Vorname", "gradido_admin_footer": "Gradido Akademie Adminkonsole", @@ -68,6 +69,7 @@ "remove_all": "alle Nutzer entfernen", "save": "Speichern", "status": "Status", + "success": "Erfolg", "text": "Text", "transaction": "Transaktion", "transactionlist": { @@ -92,7 +94,5 @@ "userIsDeleted": "Der Nutzer ist gelöscht. Es können keine GDD mehr geschöpft werden.", "user_deleted": "Nutzer ist gelöscht.", "user_recovered": "Nutzer ist wiederhergestellt.", - "user_search": "Nutzer-Suche", - "error": "Fehler", - "success": "Erfolg" + "user_search": "Nutzer-Suche" } diff --git a/admin/src/locales/en.json b/admin/src/locales/en.json index 36b37e609..e9ccec7f8 100644 --- a/admin/src/locales/en.json +++ b/admin/src/locales/en.json @@ -28,6 +28,7 @@ "delete_user": "Delete user", "details": "Details", "edit": "Edit", + "error": "Error", "e_mail": "E-mail", "firstname": "Firstname", "gradido_admin_footer": "Gradido Academy Admin Console", @@ -68,6 +69,7 @@ "remove_all": "Remove all users", "save": "Speichern", "status": "Status", + "success": "Success", "text": "Text", "transaction": "Transaction", "transactionlist": { @@ -92,7 +94,5 @@ "userIsDeleted": "The user is deleted. No more GDD can be created.", "user_deleted": "User is deleted.", "user_recovered": "User is recovered.", - "user_search": "User search", - "error": "Error", - "success": "Success" + "user_search": "User search" } From 5be959a58404249ffe83dde362f1d766ad1cb011 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 13:04:02 +0100 Subject: [PATCH 11/15] localize error for fail on create pending creation --- admin/src/components/CreationFormular.spec.js | 14 ++++++++------ admin/src/components/CreationFormular.vue | 5 ++--- admin/src/locales/de.json | 1 + admin/src/locales/en.json | 1 + admin/src/mixins/toaster.js | 3 ++- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/admin/src/components/CreationFormular.spec.js b/admin/src/components/CreationFormular.spec.js index f2ce36908..1d3338d93 100644 --- a/admin/src/components/CreationFormular.spec.js +++ b/admin/src/components/CreationFormular.spec.js @@ -422,12 +422,14 @@ describe('CreationFormular', () => { }) it('toasts two errors', () => { - expect(toastErrorSpy).toBeCalledWith( - 'Could not created PendingCreation for bob@baumeister.de', - ) - expect(toastErrorSpy).toBeCalledWith( - 'Could not created PendingCreation for bibi@bloxberg.de', - ) + expect(toastErrorSpy).toBeCalledWith([ + 'creation_form.creation_failed', + { email: 'bob@baumeister.de' }, + ]) + expect(toastErrorSpy).toBeCalledWith([ + 'creation_form.creation_failed', + { email: 'bibi@bloxberg.de' }, + ]) }) }) diff --git a/admin/src/components/CreationFormular.vue b/admin/src/components/CreationFormular.vue index a705bbba8..57361348d 100644 --- a/admin/src/components/CreationFormular.vue +++ b/admin/src/components/CreationFormular.vue @@ -171,9 +171,8 @@ export default { result.data.createPendingCreations.successfulCreation.length, ) if (result.data.createPendingCreations.failedCreation.length > 0) { - result.data.createPendingCreations.failedCreation.forEach((failed) => { - // TODO: Please localize this error message - this.toastError('Could not created PendingCreation for ' + failed) + result.data.createPendingCreations.failedCreation.forEach((email) => { + this.toastError(this.$t('creation_form.creation_failed', { email })) }) } this.$emit('remove-all-bookmark') diff --git a/admin/src/locales/de.json b/admin/src/locales/de.json index feae344c4..4c85db8db 100644 --- a/admin/src/locales/de.json +++ b/admin/src/locales/de.json @@ -5,6 +5,7 @@ "confirmed": "bestätigt", "creation": "Schöpfung", "creation_form": { + "creation_failed": "Ausstehende Schöpfung für {email} konnte nicht erzeugt werden.", "creation_for": "Aktives Grundeinkommen für", "enter_text": "Text eintragen", "form": "Schöpfungsformular", diff --git a/admin/src/locales/en.json b/admin/src/locales/en.json index e9ccec7f8..b7a7b5013 100644 --- a/admin/src/locales/en.json +++ b/admin/src/locales/en.json @@ -5,6 +5,7 @@ "confirmed": "confirmed", "creation": "Creation", "creation_form": { + "creation_failed": "Could not create pending creation for {email}", "creation_for": "Active Basic Income for", "enter_text": "Enter text", "form": "Creation form", diff --git a/admin/src/mixins/toaster.js b/admin/src/mixins/toaster.js index b9ce02db2..9f79b91e8 100644 --- a/admin/src/mixins/toaster.js +++ b/admin/src/mixins/toaster.js @@ -13,7 +13,8 @@ export const toasters = { }) }, toast(message, options) { - message = message.replace(/^GraphQL error: /, '') + // for unit tests, check that replace is present + if (message.replace) message = message.replace(/^GraphQL error: /, '') this.$bvToast.toast(message, { autoHideDelay: 5000, appendToast: true, From f41354f12304feb8dcd4a9c69971d5d311a55922 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 19:44:50 +0100 Subject: [PATCH 12/15] use portal vue --- admin/package.json | 1 + admin/src/main.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/admin/package.json b/admin/package.json index 8f72d996f..d499117af 100644 --- a/admin/package.json +++ b/admin/package.json @@ -36,6 +36,7 @@ "graphql": "^15.6.1", "identity-obj-proxy": "^3.0.0", "jest": "26.6.3", + "portal-vue": "^2.1.7", "regenerator-runtime": "^0.13.9", "stats-webpack-plugin": "^0.7.0", "vue": "^2.6.11", diff --git a/admin/src/main.js b/admin/src/main.js index fb6de5f17..f6c021a53 100644 --- a/admin/src/main.js +++ b/admin/src/main.js @@ -13,6 +13,8 @@ import i18n from './i18n' import VueApollo from 'vue-apollo' +import PortalVue from 'portal-vue' + import { BootstrapVue, IconsPlugin } from 'bootstrap-vue' import 'bootstrap/dist/css/bootstrap.css' import 'bootstrap-vue/dist/bootstrap-vue.css' @@ -21,6 +23,7 @@ import { toasters } from './mixins/toaster' import { apolloProvider } from './plugins/apolloProvider' +Vue.use(PortalVue) Vue.use(BootstrapVue) Vue.use(IconsPlugin) From f7015ea11ff812e6da26c9400b36ba7da0b6e326 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 20:01:57 +0100 Subject: [PATCH 13/15] move success toast after user delete/recover in UserSearch page --- .../components/DeletedUserFormular.spec.js | 10 +-------- admin/src/components/DeletedUserFormular.vue | 1 - admin/src/pages/UserSearch.spec.js | 21 ++++++++++++++++++- admin/src/pages/UserSearch.vue | 1 + 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/admin/src/components/DeletedUserFormular.spec.js b/admin/src/components/DeletedUserFormular.spec.js index 78ed5e43f..5c41831e5 100644 --- a/admin/src/components/DeletedUserFormular.spec.js +++ b/admin/src/components/DeletedUserFormular.spec.js @@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils' import DeletedUserFormular from './DeletedUserFormular.vue' import { deleteUser } from '../graphql/deleteUser' import { unDeleteUser } from '../graphql/unDeleteUser' -import { toastErrorSpy, toastSuccessSpy } from '../../test/testSetup' +import { toastErrorSpy } from '../../test/testSetup' const localVue = global.localVue @@ -112,10 +112,6 @@ describe('DeletedUserFormular', () => { ) }) - it('toasts a success message', () => { - expect(toastSuccessSpy).toBeCalledWith('user_deleted') - }) - it('emits update deleted At', () => { expect(wrapper.emitted('updateDeletedAt')).toEqual( expect.arrayContaining([ @@ -209,10 +205,6 @@ describe('DeletedUserFormular', () => { ) }) - it('toasts a success message', () => { - expect(toastSuccessSpy).toBeCalledWith('user_recovered') - }) - it('emits update deleted At', () => { expect(wrapper.emitted('updateDeletedAt')).toEqual( expect.arrayContaining([ diff --git a/admin/src/components/DeletedUserFormular.vue b/admin/src/components/DeletedUserFormular.vue index be9f280d9..03359d9f9 100644 --- a/admin/src/components/DeletedUserFormular.vue +++ b/admin/src/components/DeletedUserFormular.vue @@ -45,7 +45,6 @@ export default { }, }) .then((result) => { - this.toastSuccess(this.$t('user_deleted')) this.$emit('updateDeletedAt', { userId: this.item.userId, deletedAt: result.data.deleteUser, diff --git a/admin/src/pages/UserSearch.spec.js b/admin/src/pages/UserSearch.spec.js index 5f91f679a..bd18965ac 100644 --- a/admin/src/pages/UserSearch.spec.js +++ b/admin/src/pages/UserSearch.spec.js @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils' import UserSearch from './UserSearch.vue' -import { toastErrorSpy } from '../../test/testSetup' +import { toastErrorSpy, toastSuccessSpy } from '../../test/testSetup' const localVue = global.localVue @@ -16,6 +16,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ email: 'bibi@bloxberg.de', creation: [200, 400, 600], emailChecked: true, + deletedAt: null, }, { userId: 2, @@ -24,6 +25,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ email: 'benjamin@bluemchen.de', creation: [1000, 1000, 1000], emailChecked: true, + deletedAt: null, }, { userId: 3, @@ -32,6 +34,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ email: 'peter@lustig.de', creation: [0, 0, 0], emailChecked: true, + deletedAt: null, }, { userId: 4, @@ -40,6 +43,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ email: 'new@user.ch', creation: [1000, 1000, 1000], emailChecked: false, + deletedAt: null, }, ], }, @@ -183,6 +187,21 @@ describe('UserSearch', () => { }) }) + describe('delete user', () => { + const now = new Date() + beforeEach(async () => { + wrapper.findComponent({ name: 'SearchUserTable' }).vm.$emit('updateDeletedAt', 4, now) + }) + + it('marks the user as deleted', () => { + expect(wrapper.vm.searchResult.find((obj) => obj.userId === 4).deletedAt).toEqual(now) + }) + + it('toasts a success message', () => { + expect(toastSuccessSpy).toBeCalledWith('user_deleted') + }) + }) + describe('apollo returns error', () => { beforeEach(() => { apolloQueryMock.mockRejectedValue({ diff --git a/admin/src/pages/UserSearch.vue b/admin/src/pages/UserSearch.vue index a24a47c26..ea49bf805 100644 --- a/admin/src/pages/UserSearch.vue +++ b/admin/src/pages/UserSearch.vue @@ -99,6 +99,7 @@ export default { }, updateDeletedAt(userId, deletedAt) { this.searchResult.find((obj) => obj.userId === userId).deletedAt = deletedAt + this.toastSuccess(this.$t('user_deleted')) }, }, watch: { From 2e53cfea0db12f398e884cb9f41d0638b2b5050a Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 20:24:01 +0100 Subject: [PATCH 14/15] add event to toast failed creation emails after model update --- admin/src/components/CreationFormular.spec.js | 15 +++++++------ admin/src/components/CreationFormular.vue | 4 +++- admin/src/pages/Creation.spec.js | 21 ++++++++++++++++++- admin/src/pages/Creation.vue | 6 ++++++ 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/admin/src/components/CreationFormular.spec.js b/admin/src/components/CreationFormular.spec.js index 1d3338d93..9e11048e8 100644 --- a/admin/src/components/CreationFormular.spec.js +++ b/admin/src/components/CreationFormular.spec.js @@ -421,14 +421,13 @@ describe('CreationFormular', () => { expect(stateCommitMock).toBeCalledWith('openCreationsPlus', 0) }) - it('toasts two errors', () => { - expect(toastErrorSpy).toBeCalledWith([ - 'creation_form.creation_failed', - { email: 'bob@baumeister.de' }, - ]) - expect(toastErrorSpy).toBeCalledWith([ - 'creation_form.creation_failed', - { email: 'bibi@bloxberg.de' }, + it('emits remove all bookmarks', () => { + expect(wrapper.emitted('remove-all-bookmark')).toBeTruthy() + }) + + it('emits toast dailed creations with two emails', () => { + expect(wrapper.emitted('toast-failed-creations')).toEqual([ + [['bob@baumeister.de', 'bibi@bloxberg.de']], ]) }) }) diff --git a/admin/src/components/CreationFormular.vue b/admin/src/components/CreationFormular.vue index 57361348d..cd4de5fd6 100644 --- a/admin/src/components/CreationFormular.vue +++ b/admin/src/components/CreationFormular.vue @@ -166,16 +166,18 @@ export default { fetchPolicy: 'no-cache', }) .then((result) => { + const failedCreations = [] this.$store.commit( 'openCreationsPlus', result.data.createPendingCreations.successfulCreation.length, ) if (result.data.createPendingCreations.failedCreation.length > 0) { result.data.createPendingCreations.failedCreation.forEach((email) => { - this.toastError(this.$t('creation_form.creation_failed', { email })) + failedCreations.push(email) }) } this.$emit('remove-all-bookmark') + this.$emit('toast-failed-creations', failedCreations) }) .catch((error) => { this.toastError(error.message) diff --git a/admin/src/pages/Creation.spec.js b/admin/src/pages/Creation.spec.js index 4bbd25e5b..f9a4ed506 100644 --- a/admin/src/pages/Creation.spec.js +++ b/admin/src/pages/Creation.spec.js @@ -33,7 +33,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({ const storeCommitMock = jest.fn() const mocks = { - $t: jest.fn((t) => t), + $t: jest.fn((t, options) => (options ? [t, options] : t)), $d: jest.fn((d) => d), $apollo: { query: apolloQueryMock, @@ -233,6 +233,25 @@ describe('Creation', () => { }) }) + describe('failed creations', () => { + beforeEach(async () => { + await wrapper + .findComponent({ name: 'CreationFormular' }) + .vm.$emit('toast-failed-creations', ['bibi@bloxberg.de', 'benjamin@bluemchen.de']) + }) + + it('toasts two error messages', () => { + expect(toastErrorSpy).toBeCalledWith([ + 'creation_form.creation_failed', + { email: 'bibi@bloxberg.de' }, + ]) + expect(toastErrorSpy).toBeCalledWith([ + 'creation_form.creation_failed', + { email: 'benjamin@bluemchen.de' }, + ]) + }) + }) + describe('watchers', () => { beforeEach(() => { jest.clearAllMocks() diff --git a/admin/src/pages/Creation.vue b/admin/src/pages/Creation.vue index 10217fae6..a5966ee68 100644 --- a/admin/src/pages/Creation.vue +++ b/admin/src/pages/Creation.vue @@ -56,6 +56,7 @@ :creation="creation" :items="itemsMassCreation" @remove-all-bookmark="removeAllBookmarks" + @toast-failed-creations="toastFailedCreations" /> @@ -144,6 +145,11 @@ export default { this.$store.commit('setUserSelectedInMassCreation', []) this.getUsers() }, + toastFailedCreations(failedCreations) { + failedCreations.forEach((email) => + this.toastError(this.$t('creation_form.creation_failed', { email })), + ) + }, }, computed: { Searchfields() { From 5ec86bb05336fa6328e22d93756fb6aabd33a39d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 3 Mar 2022 20:28:00 +0100 Subject: [PATCH 15/15] fix typo in describe --- admin/src/components/CreationFormular.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/src/components/CreationFormular.spec.js b/admin/src/components/CreationFormular.spec.js index 9e11048e8..083b7ca67 100644 --- a/admin/src/components/CreationFormular.spec.js +++ b/admin/src/components/CreationFormular.spec.js @@ -425,7 +425,7 @@ describe('CreationFormular', () => { expect(wrapper.emitted('remove-all-bookmark')).toBeTruthy() }) - it('emits toast dailed creations with two emails', () => { + it('emits toast failed creations with two emails', () => { expect(wrapper.emitted('toast-failed-creations')).toEqual([ [['bob@baumeister.de', 'bibi@bloxberg.de']], ])