counting events

This commit is contained in:
tykayn 2020-12-03 16:10:50 +01:00 committed by Baptiste Lemoine
parent 482e2cf124
commit 26f62f7174
5 changed files with 336 additions and 285 deletions

View File

@ -43,8 +43,9 @@ export default class DateCalendarIcon extends Vue {
<style lang="scss" scoped>
time.datetime-container {
background: $backgrounds;
background: $primary-dark;
border: 1px solid $borders;
color: $white;
border-radius: 8px;
display: flex;
flex-direction: column;
@ -59,7 +60,7 @@ time.datetime-container {
font-weight: 600;
&.month {
color: $danger;
color: $white;
padding: 2px 0;
font-size: 12px;
line-height: 12px;

View File

@ -20,13 +20,15 @@
<b-tag type="is-danger" v-if="event.status === EventStatus.CANCELLED">
{{ $t("Cancelled") }}
</b-tag>
<router-link
:to="{ name: RouteName.TAG, params: { tag: tag.title } }"
v-for="tag in event.tags.slice(0, 3)"
:key="tag.slug"
>
<b-tag type="is-light">{{ tag.title }}</b-tag>
</router-link>
<span v-if="event.tags">
<router-link
:to="{ name: RouteName.TAG, params: { tag: tag.title } }"
v-for="tag in event.tags.slice(0, 3)"
:key="tag.slug"
>
<b-tag type="is-light">{{ tag.title }}</b-tag>
</router-link>
</span>
</div>
</figure>
</div>

View File

@ -21,104 +21,115 @@
<h3 class="title">{{ participation.event.title }}</h3>
</router-link>
</div>
<div class="participation-actor has-text-grey">
<span>
<b-icon
icon="earth"
v-if="participation.event.visibility === EventVisibility.PUBLIC"
/>
<b-icon
icon="link"
v-else-if="
participation.event.visibility === EventVisibility.UNLISTED
"
/>
<b-icon
icon="lock"
v-else-if="
participation.event.visibility === EventVisibility.PRIVATE
"
/>
</span>
<span
v-if="
participation.event.physicalAddress &&
participation.event.physicalAddress.locality
"
>{{ participation.event.physicalAddress.locality }} -</span
>
<span>
<i18n tag="span" path="Organized by {name}">
<popover-actor-card
slot="name"
:actor="organizerActor"
:inline="true"
>
{{ organizerActor.displayName() }}
</popover-actor-card>
</i18n>
</span>
</div>
<div>
<span
class="participant-stats"
v-if="
![
ParticipantRole.PARTICIPANT,
ParticipantRole.NOT_APPROVED,
].includes(participation.role)
"
>
<span
v-if="participation.event.options.maximumAttendeeCapacity !== 0"
>
{{
$tc(
"{available}/{capacity} available places",
participation.event.options.maximumAttendeeCapacity -
participation.event.participantStats.participant,
{
available:
participation.event.options.maximumAttendeeCapacity -
participation.event.participantStats.participant,
capacity:
participation.event.options.maximumAttendeeCapacity,
}
)
}}
</span>
<span v-else>
{{
$tc(
"{count} participants",
participation.event.participantStats.participant,
{
count: participation.event.participantStats.participant,
}
)
}}
</span>
<span v-if="participation.event.participantStats.notApproved > 0">
<b-button
type="is-text"
@click="
gotToWithCheck(participation, {
name: RouteName.PARTICIPATIONS,
query: { role: ParticipantRole.NOT_APPROVED },
params: { eventId: participation.event.uuid },
})
<div class="marged-left details">
<div class="figure">
<div
class="card-image"
v-if="participation.event.picture"
:style="`background-image: url('${participation.event.picture.url}')`"
></div>
</div>
<div class="participation-actor has-text-grey">
<span>
<b-icon
icon="earth"
v-if="participation.event.visibility === EventVisibility.PUBLIC"
/>
<b-icon
icon="link"
v-else-if="
participation.event.visibility === EventVisibility.UNLISTED
"
/>
<b-icon
icon="lock"
v-else-if="
participation.event.visibility === EventVisibility.PRIVATE
"
/>
</span>
<span
v-if="
participation.event.physicalAddress &&
participation.event.physicalAddress.locality
"
>{{ participation.event.physicalAddress.locality }} -</span
>
<span>
<i18n tag="span" path="Organized by {name}">
<popover-actor-card
slot="name"
:actor="organizerActor"
:inline="true"
>
{{ organizerActor.displayName() }}
</popover-actor-card>
</i18n>
</span>
</div>
<div>
<span
class="participant-stats"
v-if="
![
ParticipantRole.PARTICIPANT,
ParticipantRole.NOT_APPROVED,
].includes(participation.role)
"
>
<span
v-if="participation.event.options.maximumAttendeeCapacity !== 0"
>
{{
$tc(
"{count} requests waiting",
participation.event.participantStats.notApproved,
{ count: participation.event.participantStats.notApproved }
"{available}/{capacity} available places",
participation.event.options.maximumAttendeeCapacity -
participation.event.participantStats.participant,
{
available:
participation.event.options.maximumAttendeeCapacity -
participation.event.participantStats.participant,
capacity:
participation.event.options.maximumAttendeeCapacity,
}
)
}}
</b-button>
</span>
<span v-else>
{{
$tc(
"{count} participants",
participation.event.participantStats.participant,
{
count: participation.event.participantStats.participant,
}
)
}}
</span>
<span v-if="participation.event.participantStats.notApproved > 0">
<b-button
type="is-text"
@click="
gotToWithCheck(participation, {
name: RouteName.PARTICIPATIONS,
query: { role: ParticipantRole.NOT_APPROVED },
params: { eventId: participation.event.uuid },
})
"
>
{{
$tc(
"{count} requests waiting",
participation.event.participantStats.notApproved,
{
count: participation.event.participantStats.notApproved,
}
)
}}
</b-button>
</span>
</span>
</span>
</div>
</div>
</div>
<div class="actions">
@ -405,6 +416,18 @@ article.box {
& > .columns {
padding: 1.25rem;
}
padding: 0;
}
.marged-left {
padding-left: 4em;
}
.details {
.figure, .card-image {
width: 4em;
height: 4em;
}
}
</style>

View File

@ -6,11 +6,11 @@
<b-loading :active.sync="$apollo.loading"></b-loading>
<section v-if="futureParticipations.length > 0">
<subtitle>
{{ $t("Upcoming") }}
{{ futureParticipations.length }} {{ $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>
<div class="upcoming-month has-text-centered">{{ month[0] }}</div>
<EventListCard
v-for="participation in month[1]"
:key="participation.id"
@ -49,11 +49,11 @@
</section>
<section v-if="pastParticipations.length > 0">
<subtitle>
{{ $t("Past events") }}
{{ pastParticipations.length }} {{ $t("Past events") }}
</subtitle>
<transition-group name="list" tag="p">
<div v-for="month in monthlyPastParticipations" :key="month[0]">
<span>{{ month[0] }}</span>
<span class="past-months has-text-centered">{{ month[0] }}</span>
<EventListCard
v-for="participation in month[1]"
:key="participation.id"

View File

@ -1,14 +1,14 @@
<template>
<div id="homepage">
<template >
<div id='homepage' >
<section
class="hero"
v-if="config && (!currentUser.id || !currentActor.id)"
class='hero'
v-if='config && (!currentUser.id || !currentActor.id)'
>
<div class="hero-body">
<div class="container">
<h1 class="title">
{{ config.slogan || $t("Gather ⋅ Organize ⋅ Mobilize") }}
</h1>
<div class='hero-body' >
<div class='container' >
<h1 class='title' >
{{ config.slogan || $t('Gather ⋅ Organize ⋅ Mobilize') }}
</h1 >
<p
v-html="
$t('Join <b>{instance}</b>, a Mobilizon instance', {
@ -16,71 +16,80 @@
})
"
/>
<p class="instance-description">{{ config.description }}</p>
<p class='instance-description' >{{ config.description }}</p >
<!-- We don't invite to find other instances yet -->
<!-- <p v-if="!config.registrationsOpen">
{{ $t("This instance isn't opened to registrations, but you can register on other instances.") }}
</p>-->
<b-message type="is-danger" v-if="!config.registrationsOpen">{{
$t("Unfortunately, this instance isn't opened to registrations")
}}</b-message>
<div class="buttons">
<b-message
type='is-danger'
v-if='!config.registrationsOpen' >{{
$t('Unfortunately, this instance isn\'t opened to registrations')
}}
</b-message >
<div class='buttons' >
<b-button
type="is-primary"
tag="router-link"
:to="{ name: RouteName.REGISTER }"
v-if="config.registrationsOpen"
>{{ $t("Create an account") }}</b-button
type='is-primary'
tag='router-link'
:to='{ name: RouteName.REGISTER }'
v-if='config.registrationsOpen'
>{{ $t('Create an account') }}
</b-button
>
<!-- We don't invite to find other instances yet -->
<!-- <b-button v-else type="is-link" tag="a" href="https://joinmastodon.org">{{ $t('Find an instance') }}</b-button> -->
<b-button
type="is-text"
tag="router-link"
:to="{ name: RouteName.ABOUT }"
type='is-text'
tag='router-link'
:to='{ name: RouteName.ABOUT }'
>
{{ $t("Learn more about {instance}", { instance: config.name }) }}
</b-button>
</div>
</div>
</div>
</section>
{{ $t('Learn more about {instance}', { instance: config.name }) }}
</b-button >
</div >
</div >
</div >
</section >
<div
id="featured_events"
class="container section"
v-if="config && (!currentUser.id || !currentActor.id)"
id='featured_events'
class='container section'
v-if='config && (!currentUser.id || !currentActor.id)'
>
<section class="events-featured">
<h2 class="title">{{ $t("Featured events") }}</h2>
<b-loading :active.sync="$apollo.loading" />
<section class='events-featured' >
<h2 class='title' >{{ $t('Featured events') }}</h2 >
<b-loading :active.sync='$apollo.loading' />
<div
v-if="filteredFeaturedEvents.length > 0"
class="columns is-multiline"
v-if='filteredFeaturedEvents.length > 0'
class='columns is-multiline'
>
<div
class="column is-one-third-desktop"
v-for="event in filteredFeaturedEvents.slice(0, 6)"
:key="event.uuid"
class='column is-one-third-desktop'
v-for='event in filteredFeaturedEvents.slice(0, 6)'
:key='event.uuid'
>
<EventCard :event="event" />
</div>
</div>
<b-message v-else type="is-danger">{{
$t("No events found")
}}</b-message>
</section>
</div>
<div id="picture" v-if="config && (!currentUser.id || !currentActor.id)">
<div class="picture-container">
<EventCard :event='event' />
</div >
</div >
<b-message
v-else
type='is-danger' >{{
$t('No events found')
}}
</b-message >
</section >
</div >
<div
id='picture'
v-if='config && (!currentUser.id || !currentActor.id)' >
<div class='picture-container' >
<img
src="/img/pics/2020-10-06-mobilizon-illustration-A_homepage.jpg"
alt=""
src='/img/pics/2020-10-06-mobilizon-illustration-A_homepage.jpg'
alt=''
/>
</div>
<div class="container section">
<div class="columns">
<div class="column">
<h3 class="title">{{ $t("A practical tool") }}</h3>
</div >
<div class='container section' >
<div class='columns' >
<div class='column' >
<h3 class='title' >{{ $t('A practical tool') }}</h3 >
<p
v-html="
$t(
@ -88,9 +97,9 @@
)
"
/>
</div>
<div class="column">
<h3 class="title">{{ $t("An ethical alternative") }}</h3>
</div >
<div class='column' >
<h3 class='title' >{{ $t('An ethical alternative') }}</h3 >
<p
v-html="
$t(
@ -98,9 +107,9 @@
)
"
/>
</div>
<div class="column">
<h3 class="title">{{ $t("A federated software") }}</h3>
</div >
<div class='column' >
<h3 class='title' >{{ $t('A federated software') }}</h3 >
<p
v-html="
$t(
@ -108,134 +117,144 @@
)
"
/>
</div>
</div>
<div class="buttons">
</div >
</div >
<div class='buttons' >
<a
class="button is-primary is-large"
href="https://joinmobilizon.org"
>{{ $t("Learn more about Mobilizon") }}</a
class='button is-primary is-large'
href='https://joinmobilizon.org'
>{{ $t('Learn more about Mobilizon') }}</a
>
</div>
</div>
</div>
</div >
</div >
</div >
<div
class="container section"
v-if="config && loggedUser && loggedUser.settings"
class='container section'
v-if='config && loggedUser && loggedUser.settings'
>
<section v-if="currentActor.id">
<b-message type="is-info" v-if="welcomeBack">{{
$t("Welcome back {username}!", {
username: currentActor.displayName(),
})
}}</b-message>
<b-message type="is-info" v-if="newRegisteredUser">{{
$t("Welcome to Mobilizon, {username}!", {
username: currentActor.displayName(),
})
}}</b-message>
</section>
<section v-if='currentActor.id' >
<b-message
type='is-info'
v-if='welcomeBack' >{{
$t('Welcome back {username}!', {
username: currentActor.displayName(),
})
}}
</b-message >
<b-message
type='is-info'
v-if='newRegisteredUser' >{{
$t('Welcome to Mobilizon, {username}!', {
username: currentActor.displayName(),
})
}}
</b-message >
</section >
<section
v-if="currentActor.id && goingToEvents.size > 0"
class="container"
v-if='currentActor.id && goingToEvents.size > 0'
class='container'
>
<h3 class="title">{{ $t("Upcoming") }}</h3>
<b-loading :active.sync="$apollo.loading" />
<div v-for="row of goingToEvents" class="upcoming-events" :key="row[0]">
<h3 class='title' >{{ $t('Upcoming') }}</h3 >
<b-loading :active.sync='$apollo.loading' />
<div
v-for='row of goingToEvents'
class='upcoming-events'
:key='row[0]' >
<span
class="date-component-container"
v-if="isInLessThanSevenDays(row[0])"
class='date-component-container'
v-if='isInLessThanSevenDays(row[0])'
>
<date-component :date="row[0]" />
<subtitle v-if="isToday(row[0])">{{
$tc("You have one event today.", row[1].length, {
count: row[1].length,
})
}}</subtitle>
<subtitle v-else-if="isTomorrow(row[0])">{{
$tc("You have one event tomorrow.", row[1].length, {
count: row[1].length,
})
}}</subtitle>
<subtitle v-else-if="isInLessThanSevenDays(row[0])">
{{
$tc("You have one event in {days} days.", row[1].length, {
<date-component :date='row[0]' />
<subtitle v-if='isToday(row[0])' >{{
$tc('You have one event today.', row[1].length, {
count: row[1].length,
days: calculateDiffDays(row[0]),
})
}}</subtitle >
<subtitle v-else-if='isTomorrow(row[0])' >{{
$tc('You have one event tomorrow.', row[1].length, {
count: row[1].length,
})
}}</subtitle >
<subtitle v-else-if='isInLessThanSevenDays(row[0])' >
{{
$tc('You have one event in {days} days.', row[1].length, {
count: row[1].length,
days : calculateDiffDays(row[0]),
})
}}
</subtitle>
</span>
<div>
</subtitle >
</span >
<div >
<EventListCard
v-for="participation in thisWeek(row)"
@event-deleted="eventDeleted"
:key="participation[1].id"
:participation="participation[1]"
v-for='participation in thisWeek(row)'
@event-deleted='eventDeleted'
:key='participation[1].id'
:participation='participation[1]'
/>
</div>
</div>
<span class="view-all">
<router-link :to="{ name: RouteName.MY_EVENTS }"
>{{ $t("View everything") }} >></router-link
</div >
</div >
<span class='view-all' >
<router-link
:to='{ name: RouteName.MY_EVENTS }'
>{{ $t('View everything') }} >></router-link
>
</span>
</section>
<section v-if="currentActor && lastWeekEvents.length > 0">
<h3 class="title">{{ $t("Last week") }}</h3>
<b-loading :active.sync="$apollo.loading" />
<div>
</span >
</section >
<section v-if='currentActor && lastWeekEvents.length > 0' >
<h3 class='title' >{{ $t('Last week') }}</h3 >
<b-loading :active.sync='$apollo.loading' />
<div >
<EventListCard
v-for="participation in lastWeekEvents"
:key="participation.id"
:participation="participation"
@event-deleted="eventDeleted"
:options="{ hideDate: false }"
v-for='participation in lastWeekEvents'
:key='participation.id'
:participation='participation'
@event-deleted='eventDeleted'
:options='{ hideDate: false }'
/>
</div>
</section>
<section class="events-featured">
<h2 class="title">{{ $t("Featured events") }}</h2>
<b-loading :active.sync="$apollo.loading" />
</div >
</section >
<section class='events-featured' >
<h2 class='title' >{{ $t('Featured events') }}</h2 >
<b-loading :active.sync='$apollo.loading' />
<div
v-if="filteredFeaturedEvents.length > 0"
class="columns is-multiline"
v-if='filteredFeaturedEvents.length > 0'
class='columns is-multiline'
>
<div
class="column is-one-third-desktop"
v-for="event in filteredFeaturedEvents.slice(0, 6)"
:key="event.uuid"
class='column is-one-third-desktop'
v-for='event in filteredFeaturedEvents.slice(0, 6)'
:key='event.uuid'
>
<EventCard :event="event" />
</div>
</div>
<b-message v-else type="is-danger">{{
$t("No events found")
}}</b-message>
</section>
</div>
</div>
</template>
<EventCard :event='event' />
</div >
</div >
<b-message
v-else
type='is-danger' >{{
$t('No events found')
}}
</b-message >
</section >
</div >
</div >
</template >
<script lang="ts">
import { Component, Vue, Watch } from "vue-property-decorator";
import { ParticipantRole } from "@/types/enums";
import { IParticipant, Participant } from "../types/participant.model";
import { FETCH_EVENTS } from "../graphql/event";
<script lang='ts' >
import {Component, Vue, Watch} from "vue-property-decorator";
import {ParticipantRole} from "@/types/enums";
import {IParticipant, Participant} from "../types/participant.model";
import {FETCH_EVENTS} from "../graphql/event";
import EventListCard from "../components/Event/EventListCard.vue";
import EventCard from "../components/Event/EventCard.vue";
import {
CURRENT_ACTOR_CLIENT,
LOGGED_USER_PARTICIPATIONS,
} from "../graphql/actor";
import { IPerson, Person } from "../types/actor";
import { ICurrentUser, IUser } from "../types/current-user.model";
import { CURRENT_USER_CLIENT, USER_SETTINGS } from "../graphql/user";
import {CURRENT_ACTOR_CLIENT, LOGGED_USER_PARTICIPATIONS,} from "../graphql/actor";
import {IPerson, Person} from "../types/actor";
import {ICurrentUser, IUser} from "../types/current-user.model";
import {CURRENT_USER_CLIENT, USER_SETTINGS} from "../graphql/user";
import RouteName from "../router/name";
import { IEvent } from "../types/event.model";
import {IEvent} from "../types/event.model";
import DateComponent from "../components/Event/DateCalendarIcon.vue";
import { CONFIG } from "../graphql/config";
import { IConfig } from "../types/config.model";
import {CONFIG} from "../graphql/config";
import {IConfig} from "../types/config.model";
import Subtitle from "../components/Utils/Subtitle.vue";
@Component({
@ -299,9 +318,9 @@ export default class Home extends Vue {
locations = [];
city = { name: null };
city = {name: null};
country = { name: null };
country = {name: null};
currentUser!: ICurrentUser;
@ -389,7 +408,7 @@ export default class Home extends Vue {
get goingToEvents(): Map<string, Map<string, IParticipant>> {
const res = this.currentUserParticipations.filter(
({ event, role }) =>
({event, role}) =>
event.beginsOn != null &&
this.isAfter(event.beginsOn.toDateString(), 0) &&
this.isBefore(event.beginsOn.toDateString(), 7) &&
@ -421,7 +440,7 @@ export default class Home extends Vue {
get lastWeekEvents(): IParticipant[] {
const res = this.currentUserParticipations.filter(
({ event, role }) =>
({event, role}) =>
event.beginsOn != null &&
this.isBefore(event.beginsOn.toDateString(), 0) &&
role !== ParticipantRole.REJECTED
@ -430,6 +449,7 @@ export default class Home extends Vue {
(a: IParticipant, b: IParticipant) =>
a.event.beginsOn.getTime() - b.event.beginsOn.getTime()
);
console.log('lastWeekEvents', res)
return res;
}
@ -437,13 +457,15 @@ export default class Home extends Vue {
* Return all events from server excluding the ones shown as participating
*/
get filteredFeaturedEvents(): IEvent[] {
console.log('filteredFeaturedEvents this.events', this.events)
return this.events.filter(
({ id }) =>
({id}) =>
!this.currentUserParticipations
.filter(
(participation) => participation.role === ParticipantRole.CREATOR
)
.map(({ event: { id: eventId } }) => eventId)
.map(({event: {id: eventId}}) => eventId)
.includes(id)
);
}
@ -455,7 +477,7 @@ export default class Home extends Vue {
}
viewEvent(event: IEvent): void {
this.$router.push({ name: RouteName.EVENT, params: { uuid: event.uuid } });
this.$router.push({name: RouteName.EVENT, params: {uuid: event.uuid}});
}
@Watch("loggedUser")
@ -463,14 +485,16 @@ export default class Home extends Vue {
if (loggedUser && loggedUser.id && loggedUser.settings === null) {
this.$router.push({
name: RouteName.WELCOME_SCREEN,
params: { step: "1" },
params: {step: "1"},
});
}
}
}
</script>
</script >
<style lang="scss" scoped>
<style
lang='scss'
scoped >
@import "~bulma/sass/utilities/mixins.sass";
main > div > .container {
@ -567,6 +591,7 @@ section.hero {
#picture {
.picture-container {
position: relative;
&::before {
content: "";
position: absolute;
@ -575,11 +600,11 @@ section.hero {
width: 100%;
height: 100%;
background: linear-gradient(
0deg,
$white 0,
rgba(0, 0, 0, 0) 5%,
rgba(0, 0, 0, 0) 90%,
$white 100%
0deg,
$white 0,
rgba(0, 0, 0, 0) 5%,
rgba(0, 0, 0, 0) 90%,
$white 100%
);
z-index: 1;
}
@ -616,4 +641,4 @@ section.hero {
#homepage {
background: $white;
}
</style>
</style >