From 1acf109dbac117d08b845aec6fa803acb50379e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Wed, 15 May 2019 16:48:50 +0200 Subject: [PATCH 01/20] Implemented Menus, Unit Tests and created and refactored localisations --- webapp/components/ContentMenu.vue | 20 ++++-- webapp/components/Modal/DeleteModal.spec.js | 73 +++++++++++++++++---- webapp/components/Modal/DeleteModal.vue | 42 ++++++++---- webapp/locales/de.json | 40 +++++++---- webapp/locales/en.json | 46 ++++++++----- 5 files changed, 163 insertions(+), 58 deletions(-) diff --git a/webapp/components/ContentMenu.vue b/webapp/components/ContentMenu.vue index 29473d6b2..effc801ea 100644 --- a/webapp/components/ContentMenu.vue +++ b/webapp/components/ContentMenu.vue @@ -68,7 +68,7 @@ export default { if (this.isOwner && this.resourceType === 'contribution') { routes.push({ - name: this.$t(`contribution.edit`), + name: this.$t(`post.menu.edit`), path: this.$router.resolve({ name: 'post-edit-id', params: { @@ -78,21 +78,29 @@ export default { icon: 'edit' }) routes.push({ - name: this.$t(`post.delete.title`), + name: this.$t(`post.menu.delete`), callback: () => { this.openModal('delete') }, icon: 'trash' }) } + if (this.isOwner && this.resourceType === 'comment') { + // routes.push({ + // name: this.$t(`comment.menu.edit`), + // callback: () => { + // /* eslint-disable-next-line no-console */ + // console.log('EDIT COMMENT') + // }, + // icon: 'edit' + // }) routes.push({ - name: this.$t(`comment.edit`), + name: this.$t(`comment.menu.delete`), callback: () => { - /* eslint-disable-next-line no-console */ - console.log('EDIT COMMENT') + this.openModal('delete') }, - icon: 'edit' + icon: 'trash' }) } diff --git a/webapp/components/Modal/DeleteModal.spec.js b/webapp/components/Modal/DeleteModal.spec.js index e52c252ca..6127607a9 100644 --- a/webapp/components/Modal/DeleteModal.spec.js +++ b/webapp/components/Modal/DeleteModal.spec.js @@ -22,7 +22,7 @@ describe('DeleteModal.vue', () => { beforeEach(() => { propsData = { type: 'contribution', - id: 'c300' + id: 'p23' } mocks = { $t: jest.fn(), @@ -40,7 +40,7 @@ describe('DeleteModal.vue', () => { }) describe('shallowMount', () => { - const Wrapper = () => { + Wrapper = () => { return shallowMount(DeleteModal, { propsData, mocks, localVue, router }) } @@ -57,8 +57,8 @@ describe('DeleteModal.vue', () => { describe('given a post', () => { beforeEach(() => { propsData = { + type: 'contribution', id: 'p23', - type: 'post', name: 'It is a post' } }) @@ -66,14 +66,35 @@ describe('DeleteModal.vue', () => { it('mentions post title', () => { Wrapper() const calls = mocks.$t.mock.calls - const expected = [['post.delete.message', { name: 'It is a post' }]] + const expected = [ + ['delete.contribution.message', { name: 'It is a post' }] + ] + expect(calls).toEqual(expect.arrayContaining(expected)) + }) + }) + + describe('given a comment', () => { + beforeEach(() => { + propsData = { + type: 'comment', + id: 'c3', + name: 'It is the user of the comment' + } + }) + + it('mentions comments user name', () => { + Wrapper() + const calls = mocks.$t.mock.calls + const expected = [ + ['delete.comment.message', { name: 'It is the user of the comment' }] + ] expect(calls).toEqual(expect.arrayContaining(expected)) }) }) }) describe('mount', () => { - const Wrapper = () => { + Wrapper = () => { return mount(DeleteModal, { propsData, mocks, localVue, router }) } @@ -83,16 +104,16 @@ describe('DeleteModal.vue', () => { expect(Wrapper().is('div')).toBe(true) }) - describe('given id', () => { + describe('given post id', () => { beforeEach(() => { propsData = { - type: 'user', - id: 'u3' + type: 'contribution', + id: 'p23' } wrapper = Wrapper() }) - describe('click cancel button', () => { + describe('click cancel button and do not delete the post', () => { beforeEach(() => { wrapper = Wrapper() wrapper.find('button.cancel').trigger('click') @@ -115,7 +136,7 @@ describe('DeleteModal.vue', () => { }) }) - describe('click confirm button', () => { + describe('click confirm button and delete the post', () => { beforeEach(() => { wrapper.find('button.confirm').trigger('click') }) @@ -130,7 +151,7 @@ describe('DeleteModal.vue', () => { it('displays a success message', () => { const calls = mocks.$t.mock.calls - const expected = [['post.delete.success']] + const expected = [['delete.contribution.success']] expect(calls).toEqual(expect.arrayContaining(expected)) }) @@ -151,5 +172,35 @@ describe('DeleteModal.vue', () => { }) }) }) + + describe('given comment id', () => { + beforeEach(() => { + propsData = { + type: 'comment', + id: 'c3' + } + wrapper = Wrapper() + }) + + describe('click confirm button and delete the comment', () => { + beforeEach(() => { + wrapper.find('button.confirm').trigger('click') + }) + + it('calls delete mutation', () => { + expect(mocks.$apollo.mutate).toHaveBeenCalled() + }) + + it('sets success', () => { + expect(wrapper.vm.success).toBe(true) + }) + + it('displays a success message', () => { + const calls = mocks.$t.mock.calls + const expected = [['delete.comment.success']] + expect(calls).toEqual(expect.arrayContaining(expected)) + }) + }) + }) }) }) diff --git a/webapp/components/Modal/DeleteModal.vue b/webapp/components/Modal/DeleteModal.vue index 0f9fc0d7b..8154937db 100644 --- a/webapp/components/Modal/DeleteModal.vue +++ b/webapp/components/Modal/DeleteModal.vue @@ -25,7 +25,7 @@ icon="close" @click="cancel" > - {{ $t('post.delete.cancel') }} + {{ $t(`delete.cancel`) }} - {{ $t('post.delete.submit') }} + {{ $t(`delete.submit`) }} @@ -64,11 +64,11 @@ export default { }, computed: { title() { - return this.$t(`post.delete.title`) + return this.$t(`delete.${this.type}.title`) }, message() { const name = this.$filters.truncate(this.name, 30) - return this.$t(`post.delete.message`, { name }) + return this.$t(`delete.${this.type}.message`, { name }) } }, methods: { @@ -79,22 +79,40 @@ export default { }, 1000) }, async confirm() { + var gqlMutation + this.loading = true try { - await this.$apollo.mutate({ - mutation: gql` - mutation($id: ID!) { - DeletePost(id: $id) { - id + switch (this.type) { + case 'contribution': + gqlMutation = gql` + mutation($id: ID!) { + DeletePost(id: $id) { + id + } } - } - `, + ` + break + case 'comment': + // XXX Make custom mutation and tests in the Backend !!! + gqlMutation = gql` + mutation($id: ID!) { + DeleteComment(id: $id) { + id + } + } + ` + break + } + await this.$apollo.mutate({ + mutation: gqlMutation, variables: { id: this.id } }) this.success = true - this.$toast.success(this.$t('post.delete.success')) + this.$toast.success(this.$t(`delete.${this.type}.success`)) setTimeout(() => { this.isOpen = false + // XXX For comment just reload the page !!! setTimeout(() => { this.success = false this.$emit('close') diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 96f87cd9d..8b20f763f 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -135,11 +135,24 @@ "takeAction": { "name": "Aktiv werden" }, + "menu": { + "edit": "Beitrag bearbeiten", + "delete": "Beitrag löschen" + }, "comment": { "submit": "Kommentiere", "submitted": "Kommentar Gesendet" } }, + "comment": { + "content": { + "unavailable-placeholder": "...dieser Kommentar ist nicht mehr verfügbar" + }, + "menu": { + "edit": "Kommentar bearbeiten", + "delete": "Kommentar löschen" + } + }, "quotes": { "african": { "quote": "Viele kleine Leute an vielen kleinen Orten, die viele kleine Dinge tun, werden das Antlitz dieser Welt verändern.", @@ -202,6 +215,22 @@ "message": "Bist du sicher, dass du den Kommentar \"{name}\" deaktivieren möchtest?" } }, + "delete": { + "submit": "Löschen", + "cancel": "Abbrechen", + "contribution": { + "title": "Lösche Beitrag", + "type": "Contribution", + "message": "Bist du sicher, dass du den Beitrag \"{name}\" löschen möchtest?", + "success": "Beitrag erfolgreich gelöscht!" + }, + "comment": { + "title": "Lösche Kommentar", + "type": "Comment", + "message": "Bist du sicher, dass du den Kommentar von \"{name}\" löschen möchtest?", + "success": "Kommentar erfolgreich gelöscht!" + } + }, "report": { "submit": "Melden", "cancel": "Abbrechen", @@ -222,17 +251,6 @@ "message": "Bist du sicher, dass du den Kommentar von \"{name}\" melden möchtest?" } }, - "contribution": { - "edit": "Beitrag bearbeiten", - "delete": "Beitrag löschen" - }, - "comment": { - "edit": "Kommentar bearbeiten", - "delete": "Kommentar löschen", - "content": { - "unavailable-placeholder": "...dieser Kommentar ist nicht mehr verfügbar" - } - }, "followButton": { "follow": "Folgen", "following": "Folge Ich" diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 186b31d41..c043905d0 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -135,19 +135,24 @@ "takeAction": { "name": "Take action" }, - "delete": { - "submit": "Delete", - "cancel": "Cancel", - "success": "Post deleted successfully", - "title": "Delete Post", - "type": "Contribution", - "message": "Do you really want to delete the post \"{name}\"?" + "menu": { + "edit": "Edit Post", + "delete": "Delete Post" }, "comment": { "submit": "Comment", "submitted": "Comment Submitted" } }, + "comment": { + "content": { + "unavailable-placeholder": "...this comment is not available anymore" + }, + "menu": { + "edit": "Edit Comment", + "delete": "Delete Comment" + } + }, "quotes": { "african": { "quote": "Many small people in many small places do many small things, that can alter the face of the world.", @@ -210,6 +215,22 @@ "message": "Do you really want to disable the comment from \"{name}\"?" } }, + "delete": { + "submit": "Delete", + "cancel": "Cancel", + "contribution": { + "title": "Delete Post", + "type": "Contribution", + "message": "Do you really want to delete the post \"{name}\"?", + "success": "Post successfully deleted!" + }, + "comment": { + "title": "Delete Comment", + "type": "Comment", + "message": "Do you really want to delete the comment from \"{name}\"?", + "success": "Comment successfully deleted!" + } + }, "report": { "submit": "Report", "cancel": "Cancel", @@ -230,17 +251,6 @@ "message": "Do you really want to report the comment from \"{name}\"?" } }, - "contribution": { - "edit": "Edit Contribution", - "delete": "Delete Contribution" - }, - "comment": { - "edit": "Edit Comment", - "delete": "Delete Comment", - "content": { - "unavailable-placeholder": "...this comment is not available anymore" - } - }, "followButton": { "follow": "Follow", "following": "Following" From 8033556145474aa6f1013406b5a41453113a9238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Sat, 18 May 2019 07:35:45 +0200 Subject: [PATCH 02/20] Investigation how to update the Comments List intelligent --- webapp/components/Comment.vue | 4 +++ webapp/components/Modal.vue | 5 ++++ webapp/components/Modal/DeleteModal.vue | 25 ++++++++++++++----- .../components/comments/CommentList/index.vue | 14 ++++++++++- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/webapp/components/Comment.vue b/webapp/components/Comment.vue index 13edc9c0d..5e9c4faca 100644 --- a/webapp/components/Comment.vue +++ b/webapp/components/Comment.vue @@ -19,6 +19,7 @@ @@ -37,6 +38,10 @@ export default { ReportModal, DeleteModal }, + props: { + deleteCallback: { type: Function, required: true }, + cancelCallback: { type: Function, default: null } + }, computed: { ...mapGetters({ data: 'modal/data', diff --git a/webapp/components/Modal/DeleteModal.vue b/webapp/components/Modal/DeleteModal.vue index 8154937db..5a145008d 100644 --- a/webapp/components/Modal/DeleteModal.vue +++ b/webapp/components/Modal/DeleteModal.vue @@ -53,6 +53,8 @@ export default { props: { name: { type: String, default: '' }, type: { type: String, required: true }, + deleteCallback: { type: Function, required: true }, + cancelCallback: { type: Function, default: null }, id: { type: String, required: true } }, data() { @@ -116,12 +118,23 @@ export default { setTimeout(() => { this.success = false this.$emit('close') - if (this.$router.history.current.name === 'post-id-slug') { - // redirect to index - this.$router.history.push('/') - } else { - // reload the page (when deleting from profile or index) - window.location.assign(window.location.href) + switch (this.type) { + case 'contribution': + if (this.$router.history.current.name === 'post-id-slug') { + // redirect to index + this.$router.history.push('/') + } else { + // reload the page (when deleting from profile or index) + window.location.assign(window.location.href) + } + break + case 'comment': + // reload the page + // window.location.assign(window.location.href) + console.log('Remove comment emit !!!') + // this.$parent.$parent.$emit('deleteComment') + this.deleteCallback() + break } }, 500) }, 1500) diff --git a/webapp/components/comments/CommentList/index.vue b/webapp/components/comments/CommentList/index.vue index 57b720087..b77a4cf12 100644 --- a/webapp/components/comments/CommentList/index.vue +++ b/webapp/components/comments/CommentList/index.vue @@ -19,10 +19,18 @@ class="comments" > + Date: Sat, 18 May 2019 12:58:51 +0200 Subject: [PATCH 03/20] Refactored handling of DeleteModal in Comments and Posts --- webapp/components/Comment.vue | 26 ++++++++++-- webapp/components/ContentMenu.vue | 6 ++- webapp/components/Modal.vue | 7 +--- webapp/components/Modal/DeleteModal.vue | 56 +++++++++++-------------- webapp/components/PostCard/index.vue | 3 ++ webapp/mixins/Post.js | 25 +++++++++++ webapp/pages/post/_id/_slug/index.vue | 3 ++ webapp/pages/profile/_id/_slug.vue | 3 ++ 8 files changed, 88 insertions(+), 41 deletions(-) create mode 100644 webapp/mixins/Post.js diff --git a/webapp/components/Comment.vue b/webapp/components/Comment.vue index 5e9c4faca..1d52db082 100644 --- a/webapp/components/Comment.vue +++ b/webapp/components/Comment.vue @@ -19,8 +19,8 @@ @@ -37,6 +37,7 @@ diff --git a/webapp/components/ContentMenu.vue b/webapp/components/ContentMenu.vue index bee5ca011..a8b4db02f 100644 --- a/webapp/components/ContentMenu.vue +++ b/webapp/components/ContentMenu.vue @@ -59,7 +59,7 @@ export default { required: true, validator: value => { return value.match(/(contribution|comment|organization|user)/) - } + }, }, callbacks: { type: Object, required: true }, }, @@ -101,7 +101,7 @@ export default { callback: () => { this.openModal('delete') }, - icon: 'trash' + icon: 'trash', }) } @@ -153,8 +153,8 @@ export default { data: { type: this.resourceType, resource: this.resource, - callbacks: this.callbacks - } + callbacks: this.callbacks, + }, }) }, }, diff --git a/webapp/components/Modal/DeleteModal.spec.js b/webapp/components/Modal/DeleteModal.spec.js index 0b01c3647..8fd250e19 100644 --- a/webapp/components/Modal/DeleteModal.spec.js +++ b/webapp/components/Modal/DeleteModal.spec.js @@ -24,7 +24,7 @@ describe('DeleteModal.vue', () => { id: 'p23', callbacks: { confirm: () => Post.methods.deletePostCallback('list'), - cancel: null + cancel: null, }, } mocks = { @@ -65,7 +65,7 @@ describe('DeleteModal.vue', () => { name: 'It is a post', callbacks: { confirm: () => Post.methods.deletePostCallback('list'), - cancel: null + cancel: null, }, } }) @@ -73,9 +73,7 @@ describe('DeleteModal.vue', () => { it('mentions post title', () => { Wrapper() const calls = mocks.$t.mock.calls - const expected = [ - ['delete.contribution.message', { name: 'It is a post' }] - ] + const expected = [['delete.contribution.message', { name: 'It is a post' }]] expect(calls).toEqual(expect.arrayContaining(expected)) }) }) @@ -88,17 +86,15 @@ describe('DeleteModal.vue', () => { name: 'It is the user of the comment', callbacks: { confirm: () => Post.methods.deletePostCallback('list'), - cancel: null - } + cancel: null, + }, } }) it('mentions comments user name', () => { Wrapper() const calls = mocks.$t.mock.calls - const expected = [ - ['delete.comment.message', { name: 'It is the user of the comment' }] - ] + const expected = [['delete.comment.message', { name: 'It is the user of the comment' }]] expect(calls).toEqual(expect.arrayContaining(expected)) }) }) @@ -122,7 +118,7 @@ describe('DeleteModal.vue', () => { id: 'p23', callbacks: { confirm: () => Post.methods.deletePostCallback('list'), - cancel: null + cancel: null, }, } wrapper = Wrapper() @@ -195,8 +191,8 @@ describe('DeleteModal.vue', () => { id: 'c3', callbacks: { confirm: () => Post.methods.deletePostCallback('list'), - cancel: null - } + cancel: null, + }, } wrapper = Wrapper() }) diff --git a/webapp/components/Modal/DeleteModal.vue b/webapp/components/Modal/DeleteModal.vue index 883dc28d8..ef542973b 100644 --- a/webapp/components/Modal/DeleteModal.vue +++ b/webapp/components/Modal/DeleteModal.vue @@ -74,7 +74,7 @@ export default { }, methods: { async cancel() { - if (!!this.callbacks.cancel) { + if (this.callbacks.cancel) { await this.callbacks.cancel() } this.isOpen = false @@ -85,7 +85,7 @@ export default { async confirm() { this.loading = true try { - if (!!this.callbacks.confirm) { + if (this.callbacks.confirm) { await this.callbacks.confirm() } this.success = true diff --git a/webapp/components/Modal/DisableModal.vue b/webapp/components/Modal/DisableModal.vue index c2d3d64a4..fe9921511 100644 --- a/webapp/components/Modal/DisableModal.vue +++ b/webapp/components/Modal/DisableModal.vue @@ -55,7 +55,7 @@ export default { }, methods: { async cancel() { - if (!!this.callbacks.cancel) { + if (this.callbacks.cancel) { await this.callbacks.cancel() } this.isOpen = false @@ -65,7 +65,7 @@ export default { }, async confirm() { try { - if (!!this.callbacks.confirm) { + if (this.callbacks.confirm) { await this.callbacks.confirm() } await this.$apollo.mutate({ diff --git a/webapp/components/Modal/ReportModal.vue b/webapp/components/Modal/ReportModal.vue index 2fa85967f..1d99bead1 100644 --- a/webapp/components/Modal/ReportModal.vue +++ b/webapp/components/Modal/ReportModal.vue @@ -74,7 +74,7 @@ export default { }, methods: { async cancel() { - if (!!this.callbacks.cancel) { + if (this.callbacks.cancel) { await this.callbacks.cancel() } this.isOpen = false @@ -85,7 +85,7 @@ export default { async confirm() { this.loading = true try { - if (!!this.callbacks.confirm) { + if (this.callbacks.confirm) { await this.callbacks.confirm() } await this.$apollo.mutate({ diff --git a/webapp/components/PostCard/index.vue b/webapp/components/PostCard/index.vue index b5f7e5e9b..7a6f5da89 100644 --- a/webapp/components/PostCard/index.vue +++ b/webapp/components/PostCard/index.vue @@ -1,16 +1,16 @@ - +