Improvements to group page
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -34,20 +34,25 @@
|
||||
}}
|
||||
</p>
|
||||
<b-loading :active.sync="$apollo.loading"></b-loading>
|
||||
<section v-if="group && group.organizedEvents.total > 0">
|
||||
<section v-if="group">
|
||||
<subtitle>
|
||||
{{ $t("Past events") }}
|
||||
{{ showPassedEvents ? $t("Past events") : $t("Upcoming events") }}
|
||||
</subtitle>
|
||||
<b-switch v-model="showPassedEvents">{{ $t("Past events") }}</b-switch>
|
||||
<transition-group name="list" tag="p">
|
||||
<EventListViewCard v-for="event in group.organizedEvents.elements" :key="event.id" />
|
||||
<EventListViewCard
|
||||
v-for="event in group.organizedEvents.elements"
|
||||
:key="event.id"
|
||||
:event="event"
|
||||
/>
|
||||
</transition-group>
|
||||
<b-message
|
||||
v-if="group.organizedEvents.elements.length === 0 && $apollo.loading === false"
|
||||
type="is-danger"
|
||||
>
|
||||
{{ $t("No events found") }}
|
||||
</b-message>
|
||||
</section>
|
||||
<b-message
|
||||
v-if="group.organizedEvents.elements.length === 0 && $apollo.loading === false"
|
||||
type="is-danger"
|
||||
>
|
||||
{{ $t("No events found") }}
|
||||
</b-message>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
@@ -55,6 +60,8 @@
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import { FETCH_GROUP } from "@/graphql/group";
|
||||
import RouteName from "@/router/name";
|
||||
import Subtitle from "@/components/Utils/Subtitle.vue";
|
||||
import EventListViewCard from "@/components/Event/EventListViewCard.vue";
|
||||
import { IGroup, usernameWithDomain } from "../../types/actor";
|
||||
|
||||
@Component({
|
||||
@@ -64,10 +71,16 @@ import { IGroup, usernameWithDomain } from "../../types/actor";
|
||||
variables() {
|
||||
return {
|
||||
name: this.$route.params.preferredUsername,
|
||||
beforeDateTime: this.showPassedEvents ? new Date() : null,
|
||||
afterDateTime: this.showPassedEvents ? null : new Date(),
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Subtitle,
|
||||
EventListViewCard,
|
||||
},
|
||||
})
|
||||
export default class GroupEvents extends Vue {
|
||||
group!: IGroup;
|
||||
@@ -75,5 +88,7 @@ export default class GroupEvents extends Vue {
|
||||
usernameWithDomain = usernameWithDomain;
|
||||
|
||||
RouteName = RouteName;
|
||||
|
||||
showPassedEvents = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -302,6 +302,10 @@
|
||||
{{ $t("No group found") }}
|
||||
</b-message>
|
||||
<div v-else class="public-container">
|
||||
<section>
|
||||
<subtitle>{{ $t("About") }}</subtitle>
|
||||
<div v-html="group.summary" />
|
||||
</section>
|
||||
<section>
|
||||
<subtitle>{{ $t("Upcoming events") }}</subtitle>
|
||||
<div class="organized-events-wrapper" v-if="group && group.organizedEvents.total > 0">
|
||||
@@ -318,16 +322,12 @@
|
||||
</section>
|
||||
<section>
|
||||
<subtitle>{{ $t("Latest posts") }}</subtitle>
|
||||
<div v-if="group && group.posts.total > 0">
|
||||
<router-link
|
||||
v-for="post in group.posts.elements"
|
||||
:key="post.id"
|
||||
:to="{ name: RouteName.POST, params: { slug: post.slug } }"
|
||||
>
|
||||
{{ post.title }}
|
||||
</router-link>
|
||||
<div v-if="group.posts.total > 0" class="posts-wrapper">
|
||||
<post-list-item v-for="post in group.posts.elements" :key="post.id" :post="post" />
|
||||
</div>
|
||||
<div v-else-if="group" class="content has-text-grey has-text-centered">
|
||||
<p>{{ $t("No posts yet") }}</p>
|
||||
</div>
|
||||
<span v-else-if="group">{{ $t("No public posts") }}</span>
|
||||
<b-skeleton animated v-else></b-skeleton>
|
||||
</section>
|
||||
<b-modal v-if="physicalAddress && physicalAddress.geom" :active.sync="showMap">
|
||||
@@ -369,6 +369,7 @@ import FolderItem from "@/components/Resource/FolderItem.vue";
|
||||
import { Address } from "@/types/address.model";
|
||||
import Invitations from "@/components/Group/Invitations.vue";
|
||||
import addMinutes from "date-fns/addMinutes";
|
||||
import { Route } from "vue-router";
|
||||
import GroupSection from "../../components/Group/GroupSection.vue";
|
||||
import RouteName from "../../router/name";
|
||||
|
||||
@@ -413,11 +414,13 @@ import RouteName from "../../router/name";
|
||||
metaInfo() {
|
||||
return {
|
||||
// if no subcomponents specify a metaInfo.title, this title will be used
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
title: this.groupTitle,
|
||||
// all titles will be injected into this template
|
||||
titleTemplate: "%s | Mobilizon",
|
||||
meta: [
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
{ name: "description", content: this.groupSummary },
|
||||
],
|
||||
@@ -442,14 +445,14 @@ export default class Group extends Vue {
|
||||
showMap = false;
|
||||
|
||||
@Watch("currentActor")
|
||||
watchCurrentActor(currentActor: IActor, oldActor: IActor) {
|
||||
watchCurrentActor(currentActor: IActor, oldActor: IActor): void {
|
||||
if (currentActor.id && oldActor && currentActor.id !== oldActor.id) {
|
||||
this.$apollo.queries.group.refetch();
|
||||
}
|
||||
}
|
||||
|
||||
async leaveGroup() {
|
||||
const { data } = await this.$apollo.mutate({
|
||||
async leaveGroup(): Promise<Route> {
|
||||
await this.$apollo.mutate({
|
||||
mutation: LEAVE_GROUP,
|
||||
variables: {
|
||||
groupId: this.group.id,
|
||||
@@ -458,9 +461,10 @@ export default class Group extends Vue {
|
||||
return this.$router.push({ name: RouteName.MY_GROUPS });
|
||||
}
|
||||
|
||||
acceptInvitation() {
|
||||
acceptInvitation(): void {
|
||||
if (this.groupMember) {
|
||||
const index = this.person.memberships.elements.findIndex(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
({ id }: IMember) => id === this.groupMember.id
|
||||
);
|
||||
@@ -471,12 +475,12 @@ export default class Group extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
get groupTitle() {
|
||||
get groupTitle(): undefined | string {
|
||||
if (!this.group) return undefined;
|
||||
return this.group.preferredUsername;
|
||||
}
|
||||
|
||||
get groupSummary() {
|
||||
get groupSummary(): undefined | string {
|
||||
if (!this.group) return undefined;
|
||||
return this.group.summary;
|
||||
}
|
||||
@@ -486,8 +490,8 @@ export default class Group extends Vue {
|
||||
return this.person.memberships.elements.find(({ parent: { id } }) => id === this.group.id);
|
||||
}
|
||||
|
||||
get groupMemberships() {
|
||||
if (!this.person || !this.person.id) return undefined;
|
||||
get groupMemberships(): (string | undefined)[] {
|
||||
if (!this.person || !this.person.id) return [];
|
||||
return this.person.memberships.elements
|
||||
.filter(
|
||||
(membership: IMember) =>
|
||||
@@ -499,7 +503,7 @@ export default class Group extends Vue {
|
||||
}
|
||||
|
||||
get isCurrentActorAGroupMember(): boolean {
|
||||
return this.groupMemberships != undefined && this.groupMemberships.includes(this.group.id);
|
||||
return this.groupMemberships !== undefined && this.groupMemberships.includes(this.group.id);
|
||||
}
|
||||
|
||||
get isCurrentActorARejectedGroupMember(): boolean {
|
||||
@@ -532,7 +536,8 @@ export default class Group extends Vue {
|
||||
}
|
||||
|
||||
/**
|
||||
* New members, if on a different server, can take a while to refresh the group and fetch all private data
|
||||
* New members, if on a different server,
|
||||
* can take a while to refresh the group and fetch all private data
|
||||
*/
|
||||
get isCurrentActorARecentMember(): boolean {
|
||||
return (
|
||||
@@ -673,5 +678,11 @@ div.container {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.public-container {
|
||||
section {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<b-input v-model="group.name" />
|
||||
</b-field>
|
||||
<b-field :label="$t('Group short description')">
|
||||
<b-input type="textarea" v-model="group.summary"
|
||||
<editor mode="basic" v-model="group.summary"
|
||||
/></b-field>
|
||||
<p class="label">{{ $t("Group visibility") }}</p>
|
||||
<div class="field">
|
||||
@@ -105,12 +105,12 @@
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import FullAddressAutoComplete from "@/components/Event/FullAddressAutoComplete.vue";
|
||||
import { Route } from "vue-router";
|
||||
import RouteName from "../../router/name";
|
||||
import { FETCH_GROUP, UPDATE_GROUP, DELETE_GROUP } from "../../graphql/group";
|
||||
import { IGroup, usernameWithDomain } from "../../types/actor";
|
||||
import { Address, IAddress } from "../../types/address.model";
|
||||
import { IMember, Group } from "../../types/actor/group.model";
|
||||
import { Paginate } from "../../types/paginate";
|
||||
import { Group } from "../../types/actor/group.model";
|
||||
|
||||
@Component({
|
||||
apollo: {
|
||||
@@ -129,6 +129,7 @@ import { Paginate } from "../../types/paginate";
|
||||
},
|
||||
components: {
|
||||
FullAddressAutoComplete,
|
||||
editor: () => import("../../components/Editor.vue"),
|
||||
},
|
||||
})
|
||||
export default class GroupSettings extends Vue {
|
||||
@@ -149,7 +150,7 @@ export default class GroupSettings extends Vue {
|
||||
|
||||
showCopiedTooltip = false;
|
||||
|
||||
async updateGroup() {
|
||||
async updateGroup(): Promise<void> {
|
||||
const variables = { ...this.group };
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
@@ -165,7 +166,7 @@ export default class GroupSettings extends Vue {
|
||||
});
|
||||
}
|
||||
|
||||
confirmDeleteGroup() {
|
||||
confirmDeleteGroup(): void {
|
||||
this.$buefy.dialog.confirm({
|
||||
title: this.$t("Delete group") as string,
|
||||
message: this.$t(
|
||||
@@ -179,7 +180,7 @@ export default class GroupSettings extends Vue {
|
||||
});
|
||||
}
|
||||
|
||||
async deleteGroup() {
|
||||
async deleteGroup(): Promise<Route> {
|
||||
await this.$apollo.mutate<{ deleteGroup: IGroup }>({
|
||||
mutation: DELETE_GROUP,
|
||||
variables: {
|
||||
@@ -189,7 +190,7 @@ export default class GroupSettings extends Vue {
|
||||
return this.$router.push({ name: RouteName.MY_GROUPS });
|
||||
}
|
||||
|
||||
async copyURL() {
|
||||
async copyURL(): Promise<void> {
|
||||
await window.navigator.clipboard.writeText(this.group.url);
|
||||
this.showCopiedTooltip = true;
|
||||
setTimeout(() => {
|
||||
@@ -197,6 +198,7 @@ export default class GroupSettings extends Vue {
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
get canShowCopyButton(): boolean {
|
||||
return window.isSecureContext;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user