Fix discussion list page showing empty content when not a member

Introduce the EmptyContent component to display an empty content message

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-01-14 19:17:12 +01:00
parent 7b051346a4
commit 4100fd8705
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
3 changed files with 117 additions and 9 deletions

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> </li>
</ul> </ul>
</nav> </nav>
<section> <section v-if="isCurrentActorAGroupMember">
<p> <p>
{{ {{
$t( $t(
@ -39,7 +39,7 @@
tag="router-link" tag="router-link"
:to="{ :to="{
name: RouteName.CREATE_DISCUSSION, name: RouteName.CREATE_DISCUSSION,
params: { preferredUsername: this.preferredUsername }, params: { preferredUsername },
}" }"
>{{ $t("New discussion") }}</b-button >{{ $t("New discussion") }}</b-button
> >
@ -50,18 +50,38 @@
:key="discussion.id" :key="discussion.id"
/> />
</div> </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> </section>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import { FETCH_GROUP } from "@/graphql/group"; 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 DiscussionListItem from "@/components/Discussion/DiscussionListItem.vue";
import RouteName from "../../router/name"; 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({ @Component({
components: { DiscussionListItem }, components: { DiscussionListItem, EmptyContent },
apollo: { apollo: {
group: { group: {
query: FETCH_GROUP, query: FETCH_GROUP,
@ -75,6 +95,30 @@ import RouteName from "../../router/name";
return !this.preferredUsername; 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() { metaInfo() {
return { return {
@ -89,11 +133,36 @@ import RouteName from "../../router/name";
export default class DiscussionsList extends Vue { export default class DiscussionsList extends Vue {
@Prop({ type: String, required: true }) preferredUsername!: string; @Prop({ type: String, required: true }) preferredUsername!: string;
person!: IPerson;
group!: IGroup; group!: IGroup;
currentActor!: IActor;
RouteName = RouteName; RouteName = RouteName;
usernameWithDomain = usernameWithDomain; 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> </script>
<style lang="scss"> <style lang="scss">

View File

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