From 558e964c8314e03e06de411d8d3651480d3a8796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Fri, 10 Oct 2025 19:21:07 +0200 Subject: [PATCH] feat(webapp): add reason and call to action on post view page if commenting is disabled (#8958) Co-authored-by: Ulf Gebhardt --- .../components/Button/JoinLeaveButton.spec.js | 38 ++ webapp/components/Button/JoinLeaveButton.vue | 3 +- .../JoinLeaveButton.spec.js.snap | 7 + .../CallToAction/CtaJoinLeaveGroup.spec.js | 79 +++ .../Empty/CallToAction/CtaJoinLeaveGroup.vue | 64 +++ .../CallToAction/CtaUnblockAuthor.spec.js | 36 ++ .../Empty/CallToAction/CtaUnblockAuthor.vue | 38 ++ .../CtaJoinLeaveGroup.spec.js.snap | 19 + .../CtaUnblockAuthor.spec.js.snap | 18 + webapp/components/Empty/Empty.vue | 31 +- webapp/locales/de.json | 15 +- webapp/locales/en.json | 17 +- webapp/locales/es.json | 18 +- webapp/locales/fr.json | 18 +- webapp/locales/it.json | 18 +- webapp/locales/nl.json | 18 +- webapp/locales/pl.json | 18 +- webapp/locales/pt.json | 18 +- webapp/locales/ru.json | 18 +- .../_id/__snapshots__/_slug.spec.js.snap | 460 ++++++++++-------- webapp/pages/groups/_id/_slug.spec.js | 120 ++--- webapp/pages/groups/_id/_slug.vue | 11 +- webapp/pages/post/_id/_slug/index.vue | 68 ++- .../_id/__snapshots__/_slug.spec.js.snap | 196 ++++---- 24 files changed, 897 insertions(+), 449 deletions(-) create mode 100755 webapp/components/Button/JoinLeaveButton.spec.js create mode 100755 webapp/components/Button/__snapshots__/JoinLeaveButton.spec.js.snap create mode 100755 webapp/components/Empty/CallToAction/CtaJoinLeaveGroup.spec.js create mode 100644 webapp/components/Empty/CallToAction/CtaJoinLeaveGroup.vue create mode 100755 webapp/components/Empty/CallToAction/CtaUnblockAuthor.spec.js create mode 100644 webapp/components/Empty/CallToAction/CtaUnblockAuthor.vue create mode 100644 webapp/components/Empty/CallToAction/__snapshots__/CtaJoinLeaveGroup.spec.js.snap create mode 100755 webapp/components/Empty/CallToAction/__snapshots__/CtaUnblockAuthor.spec.js.snap diff --git a/webapp/components/Button/JoinLeaveButton.spec.js b/webapp/components/Button/JoinLeaveButton.spec.js new file mode 100755 index 000000000..d0d7968fc --- /dev/null +++ b/webapp/components/Button/JoinLeaveButton.spec.js @@ -0,0 +1,38 @@ +import { shallowMount } from '@vue/test-utils' + +import Component from './JoinLeaveButton.vue' + +const localVue = global.localVue + +describe('JoinLeaveButton.vue', () => { + let propsData, wrapper, mocks + + beforeEach(() => { + propsData = { + group: { + id: 'g-1', + name: 'Group 1', + }, + userId: 'u1', + isMember: false, + isNonePendingMember: false, + } + mocks = { + $t: jest.fn((t) => t), + } + }) + + const Wrapper = () => { + return shallowMount(Component, { propsData, localVue, mocks }) + } + + describe('shallowMount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('renders', () => { + expect(wrapper).toMatchSnapshot() + }) + }) +}) diff --git a/webapp/components/Button/JoinLeaveButton.vue b/webapp/components/Button/JoinLeaveButton.vue index f4cc2c009..1035ee3c6 100644 --- a/webapp/components/Button/JoinLeaveButton.vue +++ b/webapp/components/Button/JoinLeaveButton.vue @@ -4,7 +4,7 @@ :disabled="disabled" :loading="localLoading" :icon="icon" - :filled="isMember && !hovered" + :filled="filled || (isMember && !hovered)" :danger="isMember && hovered" v-tooltip="tooltip" @mouseenter.native="onHover" @@ -26,6 +26,7 @@ export default { userId: { type: String, required: true }, isMember: { type: Boolean, required: true }, isNonePendingMember: { type: Boolean, required: true }, + filled: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, loading: { type: Boolean, default: false }, }, diff --git a/webapp/components/Button/__snapshots__/JoinLeaveButton.spec.js.snap b/webapp/components/Button/__snapshots__/JoinLeaveButton.spec.js.snap new file mode 100755 index 000000000..1cd5db0a4 --- /dev/null +++ b/webapp/components/Button/__snapshots__/JoinLeaveButton.spec.js.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`JoinLeaveButton.vue shallowMount renders 1`] = ` + + group.joinLeaveButton.join + +`; diff --git a/webapp/components/Empty/CallToAction/CtaJoinLeaveGroup.spec.js b/webapp/components/Empty/CallToAction/CtaJoinLeaveGroup.spec.js new file mode 100755 index 000000000..f0a1026a5 --- /dev/null +++ b/webapp/components/Empty/CallToAction/CtaJoinLeaveGroup.spec.js @@ -0,0 +1,79 @@ +import { mount, RouterLinkStub } from '@vue/test-utils' + +import Component from './CtaJoinLeaveGroup.vue' + +const localVue = global.localVue + +describe('CtaJoinLeaveGroup.vue', () => { + let propsData, wrapper, mocks, stubs + + beforeEach(() => { + propsData = { + group: { + id: 'g-123', + slug: 'group-123', + name: 'Group 123', + myRole: null, + }, + } + mocks = { + $t: jest.fn((t) => t), + $store: { + getters: { + 'auth/user': { + id: 'u-1', + }, + }, + }, + $apollo: { + mutate: jest.fn(), + }, + } + stubs = { + NuxtLink: RouterLinkStub, + } + }) + + const Wrapper = () => { + return mount(Component, { propsData, localVue, mocks, stubs }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('renders', () => { + expect(wrapper).toMatchSnapshot() + }) + + describe('clicking on button', () => { + beforeEach(async () => { + mocks.$apollo.mutate = jest.fn().mockResolvedValue({ + data: { + JoinGroup: { + id: 'g-123', + slug: 'group-123', + name: 'Group 123', + myRoleInGroup: 'usual', + }, + }, + }) + wrapper.find('.base-button').trigger('click') + await wrapper.vm.$nextTick() + }) + it('emits update event', async () => { + expect(wrapper.emitted().update).toEqual([ + [ + { + id: 'g-123', + slug: 'group-123', + name: 'Group 123', + myRoleInGroup: 'usual', + }, + ], + ]) + }) + }) + }) +}) diff --git a/webapp/components/Empty/CallToAction/CtaJoinLeaveGroup.vue b/webapp/components/Empty/CallToAction/CtaJoinLeaveGroup.vue new file mode 100644 index 000000000..e0ec24dfe --- /dev/null +++ b/webapp/components/Empty/CallToAction/CtaJoinLeaveGroup.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/webapp/components/Empty/CallToAction/CtaUnblockAuthor.spec.js b/webapp/components/Empty/CallToAction/CtaUnblockAuthor.spec.js new file mode 100755 index 000000000..66e46b4b5 --- /dev/null +++ b/webapp/components/Empty/CallToAction/CtaUnblockAuthor.spec.js @@ -0,0 +1,36 @@ +import { shallowMount } from '@vue/test-utils' + +import Component from './CtaUnblockAuthor.vue' + +const localVue = global.localVue + +describe('CtaUnblockAuthor.vue', () => { + let propsData, wrapper, mocks + + beforeEach(() => { + propsData = { + author: { + id: 'u-123', + slug: 'user-123', + name: 'User 123', + }, + } + mocks = { + $t: jest.fn((t) => t), + } + }) + + const Wrapper = () => { + return shallowMount(Component, { propsData, localVue, mocks }) + } + + describe('shallowMount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('renders', () => { + expect(wrapper).toMatchSnapshot() + }) + }) +}) diff --git a/webapp/components/Empty/CallToAction/CtaUnblockAuthor.vue b/webapp/components/Empty/CallToAction/CtaUnblockAuthor.vue new file mode 100644 index 000000000..aa6d39335 --- /dev/null +++ b/webapp/components/Empty/CallToAction/CtaUnblockAuthor.vue @@ -0,0 +1,38 @@ + + + diff --git a/webapp/components/Empty/CallToAction/__snapshots__/CtaJoinLeaveGroup.spec.js.snap b/webapp/components/Empty/CallToAction/__snapshots__/CtaJoinLeaveGroup.spec.js.snap new file mode 100644 index 000000000..671f16eb4 --- /dev/null +++ b/webapp/components/Empty/CallToAction/__snapshots__/CtaJoinLeaveGroup.spec.js.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CtaJoinLeaveGroup.vue mount renders 1`] = ` +
+
+

+ contribution.comment.commenting-disabled.no-group-member.reason + + Group 123 + +

+

+ contribution.comment.commenting-disabled.no-group-member.call-to-action +

+
+`; diff --git a/webapp/components/Empty/CallToAction/__snapshots__/CtaUnblockAuthor.spec.js.snap b/webapp/components/Empty/CallToAction/__snapshots__/CtaUnblockAuthor.spec.js.snap new file mode 100755 index 000000000..d3b8ad797 --- /dev/null +++ b/webapp/components/Empty/CallToAction/__snapshots__/CtaUnblockAuthor.spec.js.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CtaUnblockAuthor.vue shallowMount renders 1`] = ` + + + + contribution.comment.commenting-disabled.blocked-author.reason + + + contribution.comment.commenting-disabled.blocked-author.call-to-action + + + + contribution.comment.commenting-disabled.blocked-author.button-label + + + +`; diff --git a/webapp/components/Empty/Empty.vue b/webapp/components/Empty/Empty.vue index 9d5e075fe..1f4c6a441 100644 --- a/webapp/components/Empty/Empty.vue +++ b/webapp/components/Empty/Empty.vue @@ -1,19 +1,22 @@