Merge branch 'discussion-list-if-not-member' into 'master'

Discussion list if not member

See merge request framasoft/mobilizon!792
This commit is contained in:
Thomas Citharel 2021-01-15 08:45:52 +01:00
commit d2d6842504
5 changed files with 149 additions and 17 deletions

View File

@ -163,14 +163,14 @@ pages:
- mkdir public
- mix docs
- mv doc public/backend
# #- yarn run --cwd "js" styleguide:build
# #- mv js/styleguide public/frontend
# rules:
# - if: '$CI_COMMIT_BRANCH == "master"'
# artifacts:
# expire_in: 1 hour
# paths:
# - public
# #- yarn run --cwd "js" styleguide:build
# #- mv js/styleguide public/frontend
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
artifacts:
expire_in: 1 hour
paths:
- public
.docker: &docker
stage: docker

View File

@ -0,0 +1,37 @@
<template>
<div class="empty-content" :class="{ inline }" role="note">
<b-icon :icon="icon" size="is-large" />
<h2 class="empty-content__title">
<!-- @slot Mandatory title -->
<slot />
</h2>
<p v-show="$slots.desc">
<!-- @slot Optional description -->
<slot name="desc" />
</p>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
@Component
export default class EmptyContent extends Vue {
@Prop({ type: String, required: true }) icon!: string;
@Prop({ type: Boolean, required: false, default: false }) inline!: boolean;
}
</script>
<style lang="scss">
.empty-content {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 20vh;
&__title {
margin-bottom: 10px;
}
&.inline {
margin-top: 5vh;
}
}
</style>

View File

@ -27,7 +27,7 @@
</li>
</ul>
</nav>
<section>
<section v-if="isCurrentActorAGroupMember">
<p>
{{
$t(
@ -39,7 +39,7 @@
tag="router-link"
:to="{
name: RouteName.CREATE_DISCUSSION,
params: { preferredUsername: this.preferredUsername },
params: { preferredUsername },
}"
>{{ $t("New discussion") }}</b-button
>
@ -50,18 +50,38 @@
:key="discussion.id"
/>
</div>
<empty-content v-else icon="chat">
{{ $t("There's no discussions yet") }}
</empty-content>
</section>
<section class="section" v-else>
<empty-content icon="chat">
{{ $t("Only group members can access discussions") }}
<template #desc>
<router-link
:to="{ name: RouteName.GROUP, params: { preferredUsername } }"
>
{{ $t("Return to the group page") }}
</router-link>
</template>
</empty-content>
</section>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import { FETCH_GROUP } from "@/graphql/group";
import { IGroup, usernameWithDomain } from "@/types/actor";
import { IActor, IGroup, IPerson, usernameWithDomain } from "@/types/actor";
import DiscussionListItem from "@/components/Discussion/DiscussionListItem.vue";
import RouteName from "../../router/name";
import { MemberRole } from "@/types/enums";
import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor";
import { GROUP_MEMBERSHIP_SUBSCRIPTION_CHANGED } from "@/graphql/event";
import { IMember } from "@/types/actor/member.model";
import EmptyContent from "@/components/Utils/EmptyContent.vue";
@Component({
components: { DiscussionListItem },
components: { DiscussionListItem, EmptyContent },
apollo: {
group: {
query: FETCH_GROUP,
@ -75,6 +95,30 @@ import RouteName from "../../router/name";
return !this.preferredUsername;
},
},
person: {
query: PERSON_MEMBERSHIPS,
fetchPolicy: "cache-and-network",
variables() {
return {
id: this.currentActor.id,
};
},
subscribeToMore: {
document: GROUP_MEMBERSHIP_SUBSCRIPTION_CHANGED,
variables() {
return {
actorId: this.currentActor.id,
};
},
skip() {
return !this.currentActor || !this.currentActor.id;
},
},
skip() {
return !this.currentActor || !this.currentActor.id;
},
},
currentActor: CURRENT_ACTOR_CLIENT,
},
metaInfo() {
return {
@ -89,11 +133,36 @@ import RouteName from "../../router/name";
export default class DiscussionsList extends Vue {
@Prop({ type: String, required: true }) preferredUsername!: string;
person!: IPerson;
group!: IGroup;
currentActor!: IActor;
RouteName = RouteName;
usernameWithDomain = usernameWithDomain;
get groupMemberships(): (string | undefined)[] {
if (!this.person || !this.person.id) return [];
return this.person.memberships.elements
.filter(
(membership: IMember) =>
![
MemberRole.REJECTED,
MemberRole.NOT_APPROVED,
MemberRole.INVITED,
].includes(membership.role)
)
.map(({ parent: { id } }) => id);
}
get isCurrentActorAGroupMember(): boolean {
return (
this.groupMemberships !== undefined &&
this.groupMemberships.includes(this.group.id)
);
}
}
</script>
<style lang="scss">

View File

@ -218,11 +218,9 @@
</div>
</b-table-column>
<template slot="empty">
<section class="section">
<div class="content has-text-grey has-text-centered">
<p>{{ $t("No member matches the filters") }}</p>
</div>
</section>
<empty-content icon="account" inline>
{{ $t("No member matches the filters") }}
</empty-content>
</template>
</b-table>
</section>
@ -247,6 +245,7 @@ import {
UPDATE_MEMBER,
} from "../../graphql/member";
import { usernameWithDomain } from "../../types/actor";
import EmptyContent from "@/components/Utils/EmptyContent.vue";
@Component({
apollo: {
@ -263,6 +262,9 @@ import { usernameWithDomain } from "../../types/actor";
update: (data) => data.group.members,
},
},
components: {
EmptyContent,
},
})
export default class GroupMembers extends mixins(GroupMixin) {
loading = true;

View File

@ -136,10 +136,13 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do
"""
test "find_group/3 returns a group by its username", %{conn: conn, actor: actor, user: user} do
user2 = insert(:user)
insert(:actor, user: user2)
group = insert(:group)
insert(:member, parent: group, actor: actor, role: :administrator)
insert(:member, parent: group, role: :member)
# Unlogged
res =
conn
|> AbsintheHelpers.graphql_query(
@ -157,6 +160,26 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do
assert res["data"]["group"]["members"]["total"] == 2
assert res["data"]["group"]["members"]["elements"] == []
# Login with non-member
res =
conn
|> auth_conn(user2)
|> AbsintheHelpers.graphql_query(
query: @group_query,
variables: %{
preferredUsername: group.preferred_username
}
)
assert res["errors"] == nil
assert res["data"]["group"]["preferredUsername"] ==
group.preferred_username
assert res["data"]["group"]["members"]["total"] == 2
assert res["data"]["group"]["members"]["elements"] == []
# Login with member
res =
conn
|> auth_conn(user)
@ -179,6 +202,7 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do
assert admin["actor"]["preferredUsername"] ==
actor.preferred_username
# Non existent username
res =
conn
|> AbsintheHelpers.graphql_query(