diff --git a/src/components/Event/EventActionSection.vue b/src/components/Event/EventActionSection.vue index ce9d1de17..f86c194fe 100644 --- a/src/components/Event/EventActionSection.vue +++ b/src/components/Event/EventActionSection.vue @@ -21,17 +21,14 @@ @cancel-anonymous-participation="cancelAnonymousParticipation" />
-

+

- - - {{ t("Participations") }} - { // @ts-ignore-end }; +const showParticipant = computed((): boolean => { + return ( + insideGroupWithAllowSee.value || + canManageEvent.value || + (event.value?.joinOptions !== EventJoinOptions.EXTERNAL && + !event.value?.options.hideNumberOfParticipants) + ); +}); + const canManageEvent = computed((): boolean => { return actorIsOrganizer.value || hasGroupPrivileges.value; }); @@ -494,6 +486,14 @@ const canManageEvent = computed((): boolean => { // ); // }); +const insideGroupWithAllowSee = computed((): boolean => { + return ( + event.value?.attributedTo?.allowSeeParticipants && + props.person?.memberships !== undefined && + props.person?.memberships?.total > 0 + ); +}); + const actorIsOrganizer = computed((): boolean => { return ( props.participations.length > 0 && diff --git a/src/graphql/event.ts b/src/graphql/event.ts index ace8c5ffe..b7891d175 100644 --- a/src/graphql/event.ts +++ b/src/graphql/event.ts @@ -8,6 +8,7 @@ import { } from "./participant"; import { TAG_FRAGMENT } from "./tags"; import { CONVERSATIONS_QUERY_FRAGMENT } from "./conversations"; +import { GROUP_MINIMAL_FIELDS_FRAGMENTS } from "./group"; const FULL_EVENT_FRAGMENT = gql` fragment FullEvent on Event { @@ -49,7 +50,7 @@ const FULL_EVENT_FRAGMENT = gql` ...ActorFragment } attributedTo { - ...ActorFragment + ...GroupMinimalFields } participantStats { going @@ -73,6 +74,7 @@ const FULL_EVENT_FRAGMENT = gql` ${TAG_FRAGMENT} ${EVENT_OPTIONS_FRAGMENT} ${ACTOR_FRAGMENT} + ${GROUP_MINIMAL_FIELDS_FRAGMENTS} `; export const FETCH_EVENT = gql` @@ -146,7 +148,7 @@ export const FETCH_EVENTS = gql` ...ActorFragment } attributedTo { - ...ActorFragment + ...GroupMinimalFields } category tags { @@ -162,6 +164,7 @@ export const FETCH_EVENTS = gql` ${TAG_FRAGMENT} ${EVENT_OPTIONS_FRAGMENT} ${ACTOR_FRAGMENT} + ${GROUP_MINIMAL_FIELDS_FRAGMENTS} `; export const CREATE_EVENT = gql` @@ -358,12 +361,13 @@ export const PARTICIPANTS = gql` ...ActorFragment } attributedTo { - ...ActorFragment + ...GroupMinimalFields } } } ${PARTICIPANTS_QUERY_FRAGMENT} ${ACTOR_FRAGMENT} + ${GROUP_MINIMAL_FIELDS_FRAGMENTS} `; export const EVENT_PERSON_PARTICIPATION = gql` @@ -445,7 +449,7 @@ export const FETCH_GROUP_EVENTS = gql` notApproved } attributedTo { - ...ActorFragment + ...GroupMinimalFields } organizerActor { ...ActorFragment @@ -466,6 +470,7 @@ export const FETCH_GROUP_EVENTS = gql` ${EVENT_OPTIONS_FRAGMENT} ${ACTOR_FRAGMENT} ${ADDRESS_FRAGMENT} + ${GROUP_MINIMAL_FIELDS_FRAGMENTS} `; export const EXPORT_EVENT_PARTICIPATIONS = gql` diff --git a/src/graphql/group.ts b/src/graphql/group.ts index 34c1755de..aced21467 100644 --- a/src/graphql/group.ts +++ b/src/graphql/group.ts @@ -53,6 +53,27 @@ export const LIST_GROUPS = gql` ${ACTOR_FRAGMENT} `; +export const GROUP_MINIMAL_FIELDS_FRAGMENTS = gql` + fragment GroupMinimalFields on Group { + ...ActorFragment + suspended + visibility + openness + manuallyApprovesFollowers + allowSeeParticipants + members { + elements { + id + role + actor { + id + } + } + } + } + ${ACTOR_FRAGMENT} +`; + export const GROUP_VERY_BASIC_FIELDS_FRAGMENTS = gql` fragment GroupVeryBasicFields on Group { ...ActorFragment diff --git a/src/views/Event/ParticipantsView.vue b/src/views/Event/ParticipantsView.vue index f75087017..6d616da41 100644 --- a/src/views/Event/ParticipantsView.vue +++ b/src/views/Event/ParticipantsView.vue @@ -82,7 +82,7 @@ detailed detail-key="id" v-model:checked-rows="checkedRows" - checkable + :checkable="canChange" :is-row-checkable=" (row: IParticipant) => row.role !== ParticipantRole.CREATOR " @@ -221,7 +221,7 @@ -

+
([]); const queueTable = ref(); +const is_enabled = computed((): boolean => { + return ( + currentActor.value?.id !== undefined && + page.value !== undefined && + role.value !== undefined + ); +}); + const { result: participantsResult, loading: participantsLoading, @@ -333,10 +342,7 @@ const { roles: role.value === "EVERYTHING" ? undefined : role.value, }), () => ({ - enabled: - currentActor.value?.id !== undefined && - page.value !== undefined && - role.value !== undefined, + enabled: is_enabled.value, }) ); @@ -354,6 +360,29 @@ const onPageChange = (p: number): void => { const event = computed(() => participantsResult.value?.event); +const getGroupMember = computed( + (): IMember | undefined => { + const group_members: IMember[] | undefined = + event.value?.attributedTo?.members.elements.filter( + (member: IMember) => + member.actor.id?.toString() === currentActor.value?.id?.toString() + ); + if (group_members?.length > 0) { + return group_members[0]; + } else { + return undefined; + } + } +); + +const canChange = computed(() => { + if (event.value?.attributedTo?.allowSeeParticipants) { + return getGroupMember.value?.role !== "MEMBER"; + } else { + return true; + } +}); + // const participantStats = computed((): IEventParticipantStats | null => { // if (!event.value) return null; // return event.value.participantStats; diff --git a/tests/unit/specs/components/Event/EventActionSection.spec.ts b/tests/unit/specs/components/Event/EventActionSection.spec.ts index 8bedef8ee..d6044cfeb 100644 --- a/tests/unit/specs/components/Event/EventActionSection.spec.ts +++ b/tests/unit/specs/components/Event/EventActionSection.spec.ts @@ -175,27 +175,24 @@ describe("EventActionSection", () => { expect(wrapper.find(".participations-link").text()).toBe( "No one is participating" ); - expect(wrapper.findAll("o-dropdown > o-dropdown-item").length).toBe(7); + expect(wrapper.findAll("o-dropdown > o-dropdown-item").length).toBe(6); expect( wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(1)").text() - ).toBe("Participations"); - expect( - wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(2)").text() ).toBe("Announcements"); expect( - wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(3)").text() + wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(2)").text() ).toBe("Edit"); expect( - wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(4)").text() + wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(3)").text() ).toBe("Duplicate"); expect( - wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(5)").text() + wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(4)").text() ).toBe("Delete"); expect( - wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(6)").text() + wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(5)").text() ).toBe("Share this event"); expect( - wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(7)").text() + wrapper.find("o-dropdown > o-dropdown-item:nth-of-type(6)").text() ).toBe("Add to my calendar"); expect( wrapper @@ -209,4 +206,54 @@ describe("EventActionSection", () => { ); expect(wrapper.html()).toMatchSnapshot(); }); + + it("event action section with event's group without permission for user/member", async () => { + const wrapper = generateWrapper( + { + attributedTo: { + id: 123, + uuid: "987654314231132", + allowSeeParticipants: false, + }, + options: { + hideNumberOfParticipants: true, + }, + }, + undefined, + [], + { + memberships: { + total: 1, + elements: [{ role: "MEMBER" }], + }, + } + ); + await wrapper.vm.$nextTick(); + expect(wrapper.html()).toMatchSnapshot(); + }); + + it("event action section with event's group with permission for user/member", async () => { + const wrapper = generateWrapper( + { + attributedTo: { + id: 123, + uuid: "987654314231132", + allowSeeParticipants: true, + }, + options: { + hideNumberOfParticipants: true, + }, + }, + undefined, + [], + { + memberships: { + total: 1, + elements: [{ role: "MEMBER" }], + }, + } + ); + await wrapper.vm.$nextTick(); + expect(wrapper.html()).toMatchSnapshot(); + }); }); diff --git a/tests/unit/specs/components/Event/__snapshots__/EventActionSection.spec.ts.snap b/tests/unit/specs/components/Event/__snapshots__/EventActionSection.spec.ts.snap index 1a5d0decb..df0482632 100644 --- a/tests/unit/specs/components/Event/__snapshots__/EventActionSection.spec.ts.snap +++ b/tests/unit/specs/components/Event/__snapshots__/EventActionSection.spec.ts.snap @@ -14,7 +14,6 @@ exports[`EventActionSection > event action section with basic informations 1`] = - Share this event Add to my calendar @@ -56,16 +55,13 @@ exports[`EventActionSection > event action section with creator as participant 1

- + No one is participating

- - Participations - Announcements @@ -113,6 +109,106 @@ exports[`EventActionSection > event action section with creator as participant 1 " `; +exports[`EventActionSection > event action section with event's group with permission for user/member 1`] = ` +"
+ +
+

+ + No one is participating + + +

+ + + + + + + Share this event + Add to my calendar + + +
+
+ + + + + + + + + + + +" +`; + +exports[`EventActionSection > event action section with event's group without permission for user/member 1`] = ` +"
+ +
+ + + + + + + + Share this event + Add to my calendar + + +
+
+ + + + + + + + + + + +" +`; + exports[`EventActionSection > event action section with participant 1`] = ` "
@@ -127,7 +223,6 @@ exports[`EventActionSection > event action section with participant 1`] = ` - Share this event Add to my calendar diff --git a/tests/unit/specs/mocks/client.ts b/tests/unit/specs/mocks/client.ts index d72ae2017..1d2f3b6f7 100644 --- a/tests/unit/specs/mocks/client.ts +++ b/tests/unit/specs/mocks/client.ts @@ -13,6 +13,7 @@ let mockClient: MockApolloClient | null; export let requestHandlers: Record; export function getMockClient(queries: Array): any { + cache.reset(); mockClient = createMockClient({ cache, resolvers: buildCurrentUserResolver(cache),