Introduce group basic federation, event new page and notifications
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -1,80 +1,104 @@
|
||||
<template>
|
||||
<section class="section container">
|
||||
<h1 class="title">
|
||||
{{ $t('My events') }}
|
||||
</h1>
|
||||
<b-loading :active.sync="$apollo.loading"></b-loading>
|
||||
<section v-if="futureParticipations.length > 0">
|
||||
<subtitle>
|
||||
{{ $t('Upcoming') }}
|
||||
</subtitle>
|
||||
<transition-group name="list" tag="p">
|
||||
<div v-for="month in monthlyFutureParticipations" :key="month[0]">
|
||||
<h3 class="upcoming-month">{{ month[0] }}</h3>
|
||||
<EventListCard
|
||||
v-for="participation in month[1]"
|
||||
:key="participation.id"
|
||||
:participation="participation"
|
||||
:options="{ hideDate: false }"
|
||||
@eventDeleted="eventDeleted"
|
||||
class="participation"
|
||||
/>
|
||||
</div>
|
||||
</transition-group>
|
||||
<div class="columns is-centered">
|
||||
<b-button class="column is-narrow"
|
||||
v-if="hasMoreFutureParticipations && (futureParticipations.length === limit)" @click="loadMoreFutureParticipations" size="is-large" type="is-primary">{{ $t('Load more') }}</b-button>
|
||||
</div>
|
||||
</section>
|
||||
<section v-if="drafts.length > 0">
|
||||
<subtitle>
|
||||
{{ $t('Drafts') }}
|
||||
</subtitle>
|
||||
<div class="columns is-multiline">
|
||||
<EventCard
|
||||
v-for="draft in drafts"
|
||||
:key="draft.uuid"
|
||||
:event="draft"
|
||||
class="is-one-quarter-desktop column"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
<section v-if="pastParticipations.length > 0">
|
||||
<subtitle>
|
||||
{{ $t('Past events') }}
|
||||
</subtitle>
|
||||
<transition-group name="list" tag="p">
|
||||
<div v-for="month in monthlyPastParticipations" :key="month[0]">
|
||||
<h3>{{ month[0] }}</h3>
|
||||
<EventListCard
|
||||
v-for="participation in month[1]"
|
||||
:key="participation.id"
|
||||
:participation="participation"
|
||||
:options="{ hideDate: false }"
|
||||
@eventDeleted="eventDeleted"
|
||||
class="participation"
|
||||
/>
|
||||
</div>
|
||||
</transition-group>
|
||||
<div class="columns is-centered">
|
||||
<b-button class="column is-narrow"
|
||||
v-if="hasMorePastParticipations && (pastParticipations.length === limit)" @click="loadMorePastParticipations" size="is-large" type="is-primary">{{ $t('Load more') }}</b-button>
|
||||
</div>
|
||||
</section>
|
||||
<b-message v-if="futureParticipations.length === 0 && pastParticipations.length === 0 && $apollo.loading === false" type="is-danger">
|
||||
{{ $t('No events found') }}
|
||||
</b-message>
|
||||
<section class="section container">
|
||||
<h1 class="title">
|
||||
{{ $t("My events") }}
|
||||
</h1>
|
||||
<b-loading :active.sync="$apollo.loading"></b-loading>
|
||||
<section v-if="futureParticipations.length > 0">
|
||||
<subtitle>
|
||||
{{ $t("Upcoming") }}
|
||||
</subtitle>
|
||||
<transition-group name="list" tag="p">
|
||||
<div v-for="month in monthlyFutureParticipations" :key="month[0]">
|
||||
<span class="upcoming-month">{{ month[0] }}</span>
|
||||
<EventListCard
|
||||
v-for="participation in month[1]"
|
||||
:key="participation.id"
|
||||
:participation="participation"
|
||||
:options="{ hideDate: false }"
|
||||
@eventDeleted="eventDeleted"
|
||||
class="participation"
|
||||
/>
|
||||
</div>
|
||||
</transition-group>
|
||||
<div class="columns is-centered">
|
||||
<b-button
|
||||
class="column is-narrow"
|
||||
v-if="hasMoreFutureParticipations && futureParticipations.length === limit"
|
||||
@click="loadMoreFutureParticipations"
|
||||
size="is-large"
|
||||
type="is-primary"
|
||||
>{{ $t("Load more") }}</b-button
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
<section v-if="drafts.length > 0">
|
||||
<subtitle>
|
||||
{{ $t("Drafts") }}
|
||||
</subtitle>
|
||||
<div class="columns is-multiline">
|
||||
<EventCard
|
||||
v-for="draft in drafts"
|
||||
:key="draft.uuid"
|
||||
:event="draft"
|
||||
class="is-one-quarter-desktop column"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
<section v-if="pastParticipations.length > 0">
|
||||
<subtitle>
|
||||
{{ $t("Past events") }}
|
||||
</subtitle>
|
||||
<transition-group name="list" tag="p">
|
||||
<div v-for="month in monthlyPastParticipations" :key="month[0]">
|
||||
<span>{{ month[0] }}</span>
|
||||
<EventListCard
|
||||
v-for="participation in month[1]"
|
||||
:key="participation.id"
|
||||
:participation="participation"
|
||||
:options="{ hideDate: false }"
|
||||
@eventDeleted="eventDeleted"
|
||||
class="participation"
|
||||
/>
|
||||
</div>
|
||||
</transition-group>
|
||||
<div class="columns is-centered">
|
||||
<b-button
|
||||
class="column is-narrow"
|
||||
v-if="hasMorePastParticipations && pastParticipations.length === limit"
|
||||
@click="loadMorePastParticipations"
|
||||
size="is-large"
|
||||
type="is-primary"
|
||||
>{{ $t("Load more") }}</b-button
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
<b-message
|
||||
v-if="
|
||||
futureParticipations.length === 0 &&
|
||||
pastParticipations.length === 0 &&
|
||||
$apollo.loading === false
|
||||
"
|
||||
type="is-danger"
|
||||
>
|
||||
{{ $t("No events found") }}
|
||||
</b-message>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import { LOGGED_USER_PARTICIPATIONS, LOGGED_USER_DRAFTS } from '@/graphql/actor';
|
||||
import { EventModel, IEvent, IParticipant, Participant, ParticipantRole } from '@/types/event.model';
|
||||
import EventListCard from '@/components/Event/EventListCard.vue';
|
||||
import EventCard from '@/components/Event/EventCard.vue';
|
||||
import Subtitle from '@/components/Utils/Subtitle.vue';
|
||||
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import { LOGGED_USER_PARTICIPATIONS, LOGGED_USER_DRAFTS } from "../../graphql/actor";
|
||||
import {
|
||||
EventModel,
|
||||
IEvent,
|
||||
IParticipant,
|
||||
Participant,
|
||||
ParticipantRole,
|
||||
} from "../../types/event.model";
|
||||
import EventListCard from "../../components/Event/EventListCard.vue";
|
||||
import EventCard from "../../components/Event/EventCard.vue";
|
||||
import Subtitle from "../../components/Utils/Subtitle.vue";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
@@ -85,76 +109,91 @@ import Subtitle from '@/components/Utils/Subtitle.vue';
|
||||
apollo: {
|
||||
futureParticipations: {
|
||||
query: LOGGED_USER_PARTICIPATIONS,
|
||||
fetchPolicy: 'network-only',
|
||||
fetchPolicy: "network-only",
|
||||
variables: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
afterDateTime: (new Date()).toISOString(),
|
||||
afterDateTime: new Date().toISOString(),
|
||||
},
|
||||
update: data => data.loggedUser.participations.map(participation => new Participant(participation)),
|
||||
update: (data) =>
|
||||
data.loggedUser.participations.elements.map(
|
||||
(participation: IParticipant) => new Participant(participation)
|
||||
),
|
||||
},
|
||||
drafts: {
|
||||
query: LOGGED_USER_DRAFTS,
|
||||
fetchPolicy: 'network-only',
|
||||
fetchPolicy: "network-only",
|
||||
variables: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
},
|
||||
update: data => data.loggedUser.drafts.map(event => new EventModel(event)),
|
||||
update: (data) => data.loggedUser.drafts.map((event: IEvent) => new EventModel(event)),
|
||||
},
|
||||
pastParticipations: {
|
||||
query: LOGGED_USER_PARTICIPATIONS,
|
||||
fetchPolicy: 'network-only',
|
||||
fetchPolicy: "network-only",
|
||||
variables: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
beforeDateTime: (new Date()).toISOString(),
|
||||
beforeDateTime: new Date().toISOString(),
|
||||
},
|
||||
update: data => data.loggedUser.participations.map(participation => new Participant(participation)),
|
||||
update: (data) =>
|
||||
data.loggedUser.participations.elements.map(
|
||||
(participation: IParticipant) => new Participant(participation)
|
||||
),
|
||||
},
|
||||
},
|
||||
metaInfo() {
|
||||
return {
|
||||
// if no subcomponents specify a metaInfo.title, this title will be used
|
||||
title: this.$t('My events') as string,
|
||||
// all titles will be injected into this template
|
||||
titleTemplate: '%s | Mobilizon',
|
||||
// if no subcomponents specify a metaInfo.title, this title will be used
|
||||
title: this.$t("My events") as string,
|
||||
// all titles will be injected into this template
|
||||
titleTemplate: "%s | Mobilizon",
|
||||
};
|
||||
},
|
||||
})
|
||||
export default class MyEvents extends Vue {
|
||||
futurePage: number = 1;
|
||||
pastPage: number = 1;
|
||||
limit: number = 10;
|
||||
futurePage = 1;
|
||||
|
||||
pastPage = 1;
|
||||
|
||||
limit = 10;
|
||||
|
||||
futureParticipations: IParticipant[] = [];
|
||||
hasMoreFutureParticipations: boolean = true;
|
||||
|
||||
hasMoreFutureParticipations = true;
|
||||
|
||||
pastParticipations: IParticipant[] = [];
|
||||
hasMorePastParticipations: boolean = true;
|
||||
|
||||
hasMorePastParticipations = true;
|
||||
|
||||
drafts: IEvent[] = [];
|
||||
|
||||
private monthlyParticipations(participations: IParticipant[]): Map<string, Participant[]> {
|
||||
const res = participations.filter(({ event, role }) => event.beginsOn != null && role !== ParticipantRole.REJECTED);
|
||||
static monthlyParticipations(participations: IParticipant[]): Map<string, Participant[]> {
|
||||
const res = participations.filter(
|
||||
({ event, role }) => event.beginsOn != null && role !== ParticipantRole.REJECTED
|
||||
);
|
||||
res.sort(
|
||||
(a: IParticipant, b: IParticipant) => a.event.beginsOn.getTime() - b.event.beginsOn.getTime(),
|
||||
);
|
||||
(a: IParticipant, b: IParticipant) => a.event.beginsOn.getTime() - b.event.beginsOn.getTime()
|
||||
);
|
||||
return res.reduce((acc: Map<string, IParticipant[]>, participation: IParticipant) => {
|
||||
const month = (new Date(participation.event.beginsOn)).toLocaleDateString(undefined, { year: 'numeric', month: 'long' });
|
||||
const participations: IParticipant[] = acc.get(month) || [];
|
||||
participations.push(participation);
|
||||
acc.set(month, participations);
|
||||
const month = new Date(participation.event.beginsOn).toLocaleDateString(undefined, {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
});
|
||||
const filteredParticipations: IParticipant[] = acc.get(month) || [];
|
||||
filteredParticipations.push(participation);
|
||||
acc.set(month, filteredParticipations);
|
||||
return acc;
|
||||
}, new Map());
|
||||
}, new Map());
|
||||
}
|
||||
|
||||
get monthlyFutureParticipations(): Map<string, Participant[]> {
|
||||
return this.monthlyParticipations(this.futureParticipations);
|
||||
return MyEvents.monthlyParticipations(this.futureParticipations);
|
||||
}
|
||||
|
||||
get monthlyPastParticipations(): Map<string, Participant[]> {
|
||||
return this.monthlyParticipations(this.pastParticipations);
|
||||
return MyEvents.monthlyParticipations(this.pastParticipations);
|
||||
}
|
||||
|
||||
loadMoreFutureParticipations() {
|
||||
@@ -183,12 +222,12 @@ export default class MyEvents extends Vue {
|
||||
loadMorePastParticipations() {
|
||||
this.pastPage += 1;
|
||||
this.$apollo.queries.pastParticipations.fetchMore({
|
||||
// New variables
|
||||
// New variables
|
||||
variables: {
|
||||
page: this.pastPage,
|
||||
limit: this.limit,
|
||||
},
|
||||
// Transform the previous result with new data
|
||||
// Transform the previous result with new data
|
||||
updateQuery: (previousResult, { fetchMoreResult }) => {
|
||||
const newParticipations = fetchMoreResult.loggedUser.participations;
|
||||
this.hasMorePastParticipations = newParticipations.length === this.limit;
|
||||
@@ -203,28 +242,32 @@ export default class MyEvents extends Vue {
|
||||
});
|
||||
}
|
||||
|
||||
eventDeleted(eventid) {
|
||||
this.futureParticipations = this.futureParticipations.filter(participation => participation.event.id !== eventid);
|
||||
this.pastParticipations = this.pastParticipations.filter(participation => participation.event.id !== eventid);
|
||||
eventDeleted(eventid: string) {
|
||||
this.futureParticipations = this.futureParticipations.filter(
|
||||
(participation) => participation.event.id !== eventid
|
||||
);
|
||||
this.pastParticipations = this.pastParticipations.filter(
|
||||
(participation) => participation.event.id !== eventid
|
||||
);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style lang="scss" scoped>
|
||||
@import "../../variables";
|
||||
@import "../../variables";
|
||||
|
||||
main > .container {
|
||||
background: $white;
|
||||
}
|
||||
main > .container {
|
||||
background: $white;
|
||||
}
|
||||
|
||||
.participation {
|
||||
margin: 1rem auto;
|
||||
}
|
||||
.participation {
|
||||
margin: 1rem auto;
|
||||
}
|
||||
|
||||
section {
|
||||
.upcoming-month {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
section {
|
||||
.upcoming-month {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user