Improve group dashboard for members without moderator rights

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2020-10-22 10:48:49 +02:00
parent e754e1172a
commit 2ce5f8e66c
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
7 changed files with 148 additions and 95 deletions

View File

@ -37,6 +37,7 @@ section {
flex-direction: column; flex-direction: column;
margin-bottom: 2rem; margin-bottom: 2rem;
border: 2px solid $violet; border: 2px solid $violet;
min-height: 30vh;
.create-slot { .create-slot {
display: flex; display: flex;
@ -48,6 +49,7 @@ section {
.main-slot { .main-slot {
min-height: 5rem; min-height: 5rem;
padding: 5px; padding: 5px;
flex: 1;
} }
} }

View File

@ -731,7 +731,6 @@
"Create to-do lists for all the tasks you need to do, assign them and set due dates.": "Create to-do lists for all the tasks you need to do, assign them and set due dates.", "Create to-do lists for all the tasks you need to do, assign them and set due dates.": "Create to-do lists for all the tasks you need to do, assign them and set due dates.",
"A place to store links to documents or resources of any type.": "A place to store links to documents or resources of any type.", "A place to store links to documents or resources of any type.": "A place to store links to documents or resources of any type.",
"{group}'s events": "{group}'s events", "{group}'s events": "{group}'s events",
"When someone from the group creates an event and attributes it to the group, it will show up here.": "When someone from the group creates an event and attributes it to the group, it will show up here.",
"View all": "View all", "View all": "View all",
"+ Start a discussion": "+ Start a discussion", "+ Start a discussion": "+ Start a discussion",
"+ Add a resource": "+ Add a resource", "+ Add a resource": "+ Add a resource",
@ -815,5 +814,7 @@
"An ethical alternative": "An ethical alternative", "An ethical alternative": "An ethical alternative",
"Ethical alternative to Facebook events, groups and pages, Mobilizon is a <b>tool designed to serve you</b>. Period.": "Ethical alternative to Facebook events, groups and pages, Mobilizon is a <b>tool designed to serve you</b>. Period.", "Ethical alternative to Facebook events, groups and pages, Mobilizon is a <b>tool designed to serve you</b>. Period.": "Ethical alternative to Facebook events, groups and pages, Mobilizon is a <b>tool designed to serve you</b>. Period.",
"A federated software": "A federated software", "A federated software": "A federated software",
"Mobilizon is not a giant platform, but a <b>multitude of interconnected Mobilizon websites</b>.": "Mobilizon is not a giant platform, but a <b>multitude of interconnected Mobilizon websites</b>." "Mobilizon is not a giant platform, but a <b>multitude of interconnected Mobilizon websites</b>.": "Mobilizon is not a giant platform, but a <b>multitude of interconnected Mobilizon websites</b>.",
"When a moderator from the group creates an event and attributes it to the group, it will show up here.": "When a moderator from the group creates an event and attributes it to the group, it will show up here.",
"Only group moderators can create, edit and delete posts.": "Only group moderators can create, edit and delete posts."
} }

View File

@ -867,5 +867,7 @@
"An ethical alternative": "Une alternative éthique", "An ethical alternative": "Une alternative éthique",
"Ethical alternative to Facebook events, groups and pages, Mobilizon is a <b>tool designed to serve you</b>. Period.": "Alternative éthique aux événements, groupes et pages Facebook, Mobilizon est <b>un outil conçu pour vous servir</b>. Point.", "Ethical alternative to Facebook events, groups and pages, Mobilizon is a <b>tool designed to serve you</b>. Period.": "Alternative éthique aux événements, groupes et pages Facebook, Mobilizon est <b>un outil conçu pour vous servir</b>. Point.",
"A federated software": "Un logiciel fédéré", "A federated software": "Un logiciel fédéré",
"Mobilizon is not a giant platform, but a <b>multitude of interconnected Mobilizon websites</b>.": "Mobilizon nest pas une plateforme géante, mais une <b>multitude de sites web Mobilizon interconnectés</b>." "Mobilizon is not a giant platform, but a <b>multitude of interconnected Mobilizon websites</b>.": "Mobilizon nest pas une plateforme géante, mais une <b>multitude de sites web Mobilizon interconnectés</b>.",
"When a moderator from the group creates an event and attributes it to the group, it will show up here.": "Lorsqu'un·e modérateur·ice du groupe crée un événement et l'attribue au groupe, il s'affichera ici.",
"Only group moderators can create, edit and delete posts.": "Seul·es les modérateur·ices du groupe peuvent créer, éditer et supprimer des billets."
} }

View File

@ -29,10 +29,18 @@
<p v-if="isCurrentActorMember"> <p v-if="isCurrentActorMember">
{{ {{
$t( $t(
"When someone from the group creates an event and attributes it to the group, it will show up here." "When a moderator from the group creates an event and attributes it to the group, it will show up here."
) )
}} }}
</p> </p>
<router-link
v-if="isCurrentActorAGroupModerator"
:to="{
name: RouteName.CREATE_EVENT,
}"
class="button is-primary"
>{{ $t("+ Create an event") }}</router-link
>
<b-loading :active.sync="$apollo.loading"></b-loading> <b-loading :active.sync="$apollo.loading"></b-loading>
<section v-if="group"> <section v-if="group">
<subtitle> <subtitle>
@ -58,12 +66,14 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-property-decorator"; import { Component } from "vue-property-decorator";
import { mixins } from "vue-class-component";
import { FETCH_GROUP } from "@/graphql/group"; import { FETCH_GROUP } from "@/graphql/group";
import RouteName from "@/router/name"; import RouteName from "@/router/name";
import Subtitle from "@/components/Utils/Subtitle.vue"; import Subtitle from "@/components/Utils/Subtitle.vue";
import EventListViewCard from "@/components/Event/EventListViewCard.vue"; import EventListViewCard from "@/components/Event/EventListViewCard.vue";
import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor"; import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor";
import GroupMixin from "@/mixins/group";
import { IGroup, IMember, IPerson, usernameWithDomain } from "../../types/actor"; import { IGroup, IMember, IPerson, usernameWithDomain } from "../../types/actor";
@Component({ @Component({
@ -98,7 +108,7 @@ import { IGroup, IMember, IPerson, usernameWithDomain } from "../../types/actor"
EventListViewCard, EventListViewCard,
}, },
}) })
export default class GroupEvents extends Vue { export default class GroupEvents extends mixins(GroupMixin) {
group!: IGroup; group!: IGroup;
memberships!: IMember[]; memberships!: IMember[];
@ -117,3 +127,8 @@ export default class GroupEvents extends Vue {
} }
} }
</script> </script>
<style lang="scss" scoped>
.container.section {
background: $white;
}
</style>

View File

@ -231,6 +231,7 @@
</template> </template>
<template v-slot:create> <template v-slot:create>
<router-link <router-link
v-if="isCurrentActorAGroupModerator"
:to="{ :to="{
name: RouteName.CREATE_EVENT, name: RouteName.CREATE_EVENT,
}" }"
@ -259,6 +260,7 @@
</template> </template>
<template v-slot:create> <template v-slot:create>
<router-link <router-link
v-if="isCurrentActorAGroupModerator"
:to="{ :to="{
name: RouteName.POST_CREATE, name: RouteName.POST_CREATE,
params: { preferredUsername: usernameWithDomain(group) }, params: { preferredUsername: usernameWithDomain(group) },

View File

@ -1,5 +1,6 @@
<template> <template>
<form @submit.prevent="publish(false)"> <div>
<form @submit.prevent="publish(false)" v-if="isCurrentActorAGroupModerator">
<div class="container section"> <div class="container section">
<h1 class="title" v-if="isUpdate === true"> <h1 class="title" v-if="isUpdate === true">
{{ $t("Edit post") }} {{ $t("Edit post") }}
@ -85,12 +86,25 @@
</div> </div>
</nav> </nav>
</form> </form>
<b-loading
v-else-if="$apollo.loading"
:is-full-page="false"
:active.sync="$apollo.loading"
:can-cancel="false"
></b-loading>
<div class="container section" v-else>
<b-message type="is-danger">
{{ $t("Only group moderators can create, edit and delete posts.") }}
</b-message>
</div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"; import { Component, Prop } from "vue-property-decorator";
import { mixins } from "vue-class-component";
import { FETCH_GROUP } from "@/graphql/group"; import { FETCH_GROUP } from "@/graphql/group";
import { buildFileFromIPicture, readFileAsync } from "@/utils/image"; import { buildFileFromIPicture, readFileAsync } from "@/utils/image";
import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; import GroupMixin from "@/mixins/group";
import { TAGS } from "../../graphql/tags"; import { TAGS } from "../../graphql/tags";
import { CONFIG } from "../../graphql/config"; import { CONFIG } from "../../graphql/config";
import { FETCH_POST, CREATE_POST, UPDATE_POST, DELETE_POST } from "../../graphql/post"; import { FETCH_POST, CREATE_POST, UPDATE_POST, DELETE_POST } from "../../graphql/post";
@ -105,7 +119,6 @@ import PictureUpload from "../../components/PictureUpload.vue";
@Component({ @Component({
apollo: { apollo: {
currentActor: CURRENT_ACTOR_CLIENT,
tags: TAGS, tags: TAGS,
config: CONFIG, config: CONFIG,
post: { post: {
@ -150,7 +163,7 @@ import PictureUpload from "../../components/PictureUpload.vue";
}; };
}, },
}) })
export default class EditPost extends Vue { export default class EditPost extends mixins(GroupMixin) {
@Prop({ required: false, type: String }) slug: undefined | string; @Prop({ required: false, type: String }) slug: undefined | string;
@Prop({ required: false, type: String }) preferredUsername!: string; @Prop({ required: false, type: String }) preferredUsername!: string;
@ -278,14 +291,27 @@ export default class EditPost extends Vue {
} }
get actualGroup(): IActor { get actualGroup(): IActor {
if (!this.group) { if (!this.group.id) {
return this.post.attributedTo as IActor; return this.post.attributedTo as IActor;
} }
return this.group; return this.group;
} }
hasCurrentActorThisRole(givenRole: string | string[]): boolean {
const roles = Array.isArray(givenRole) ? givenRole : [givenRole];
return (
this.person &&
this.person.memberships.elements.some(
({ parent: { id }, role }) => id === this.actualGroup.id && roles.includes(role)
)
);
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.container.section {
background: $white;
}
form { form {
nav.navbar { nav.navbar {
position: sticky; position: sticky;

View File

@ -35,8 +35,11 @@
) )
}} }}
</p> </p>
<p v-if="isCurrentActorMember">
{{ $t("Only group moderators can create, edit and delete posts.") }}
</p>
<router-link <router-link
v-if="isCurrentActorMember" v-if="isCurrentActorAGroupModerator"
:to="{ :to="{
name: RouteName.POST_CREATE, name: RouteName.POST_CREATE,
params: { preferredUsername: usernameWithDomain(group) }, params: { preferredUsername: usernameWithDomain(group) },
@ -75,8 +78,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"; import { Component, Prop } from "vue-property-decorator";
import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor"; import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor";
import { mixins } from "vue-class-component";
import GroupMixin from "@/mixins/group";
import { FETCH_GROUP_POSTS } from "../../graphql/post"; import { FETCH_GROUP_POSTS } from "../../graphql/post";
import { Paginate } from "../../types/paginate"; import { Paginate } from "../../types/paginate";
import { IPost } from "../../types/post.model"; import { IPost } from "../../types/post.model";
@ -131,7 +136,7 @@ const POSTS_PAGE_LIMIT = 10;
}; };
}, },
}) })
export default class PostList extends Vue { export default class PostList extends mixins(GroupMixin) {
@Prop({ required: true, type: String }) preferredUsername!: string; @Prop({ required: true, type: String }) preferredUsername!: string;
group!: IGroup; group!: IGroup;