Event components enhancements

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-06-10 10:33:16 +02:00
parent dd8096507b
commit 8e59e2f06b
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
6 changed files with 309 additions and 308 deletions

View File

@ -22,7 +22,7 @@ export default class EventBanner extends Vue {
.banner-container { .banner-container {
display: flex; display: flex;
justify-content: center; justify-content: center;
height: 400px; height: 30vh;
} }
::v-deep img { ::v-deep img {
width: 100%; width: 100%;

View File

@ -24,7 +24,7 @@
<h3 class="title">{{ participation.event.title }}</h3> <h3 class="title">{{ participation.event.title }}</h3>
</router-link> </router-link>
</div> </div>
<div class="participation-actor has-text-grey"> <div class="participation-actor">
<span> <span>
<b-icon <b-icon
icon="earth" icon="earth"
@ -50,17 +50,20 @@
" "
>{{ participation.event.physicalAddress.locality }} -</span >{{ participation.event.physicalAddress.locality }} -</span
> >
<span> <i18n
<i18n tag="span" path="Organized by {name}"> tag="span"
<popover-actor-card path="Organized by {name}"
slot="name" v-if="organizerActor.id !== currentActor.id"
:actor="organizerActor" >
:inline="true" <popover-actor-card
> slot="name"
{{ organizerActor.displayName() }} :actor="organizerActor"
</popover-actor-card> :inline="true"
</i18n> >
</span> {{ organizerActor.displayName() }}
</popover-actor-card>
</i18n>
<span v-else>{{ $t("Organized by you") }}</span>
</div> </div>
<div> <div>
<span <span
@ -116,7 +119,9 @@
$tc( $tc(
"{count} requests waiting", "{count} requests waiting",
participation.event.participantStats.notApproved, participation.event.participantStats.notApproved,
{ count: participation.event.participantStats.notApproved } {
count: participation.event.participantStats.notApproved,
}
) )
}} }}
</b-button> </b-button>
@ -347,6 +352,7 @@ article.box {
.list-card { .list-card {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 6px;
.actions { .actions {
padding-right: 7.5px; padding-right: 7.5px;

View File

@ -23,7 +23,7 @@ export default class EventMetadataBlock extends Vue {
h2 { h2 {
font-size: 1.8rem; font-size: 1.8rem;
font-weight: 500; font-weight: 500;
color: #f7ba30; color: $violet;
} }
div.eventMetadataBlock { div.eventMetadataBlock {

View File

@ -66,7 +66,9 @@ export default class OrganizerPicker extends Vue {
return this.value; return this.value;
} }
if (this.currentActor) { if (this.currentActor) {
return this.currentActor; return this.identities.find(
(identity) => identity.id === this.currentActor.id
);
} }
return undefined; return undefined;
} }

View File

@ -110,6 +110,7 @@ import { IActor, IGroup, IPerson, usernameWithDomain } from "../../types/actor";
import OrganizerPicker from "./OrganizerPicker.vue"; import OrganizerPicker from "./OrganizerPicker.vue";
import { import {
CURRENT_ACTOR_CLIENT, CURRENT_ACTOR_CLIENT,
IDENTITIES,
LOGGED_USER_MEMBERSHIPS, LOGGED_USER_MEMBERSHIPS,
} from "../../graphql/actor"; } from "../../graphql/actor";
import { Paginate } from "../../types/paginate"; import { Paginate } from "../../types/paginate";
@ -152,6 +153,7 @@ const MEMBER_ROLES = [
}, },
update: (data) => data.loggedUser.memberships, update: (data) => data.loggedUser.memberships,
}, },
identities: IDENTITIES,
}, },
}) })
export default class OrganizerPickerWrapper extends Vue { export default class OrganizerPickerWrapper extends Vue {
@ -161,6 +163,8 @@ export default class OrganizerPickerWrapper extends Vue {
currentActor!: IPerson; currentActor!: IPerson;
identities!: IPerson[];
isComponentModalActive = false; isComponentModalActive = false;
@Prop({ type: Array, required: false, default: () => [] }) @Prop({ type: Array, required: false, default: () => [] })
@ -200,7 +204,9 @@ export default class OrganizerPickerWrapper extends Vue {
return this.value; return this.value;
} }
if (this.currentActor) { if (this.currentActor) {
return this.currentActor; return this.identities.find(
(identity) => identity.id === this.currentActor.id
);
} }
return undefined; return undefined;
} }

View File

@ -1,299 +1,296 @@
<template> <template>
<div class="container"> <div class="container">
<transition appear name="fade" mode="out-in"> <transition appear name="fade" mode="out-in">
<div> <div class="wrapper">
<div <event-banner :picture="event.picture" />
class="header-picture" <div class="intro-wrapper">
v-if="event.picture" <div class="date-calendar-icon-wrapper">
:style="`background-image: url('${event.picture.url}')`" <date-calendar-icon :date="event.beginsOn" />
/> </div>
<div class="header-picture-default" v-else /> <section class="intro">
<section class="section intro"> <div class="columns">
<div class="columns"> <div class="column">
<div class="column is-1-tablet"> <h1 class="title" style="margin: 0">{{ event.title }}</h1>
<date-calendar-icon :date="event.beginsOn" /> <div class="organizer">
</div> <span v-if="event.organizerActor && !event.attributedTo">
<div class="column"> <popover-actor-card
<h1 class="title" style="margin: 0">{{ event.title }}</h1> :actor="event.organizerActor"
<div class="organizer"> :inline="true"
<span v-if="event.organizerActor && !event.attributedTo"> >
<popover-actor-card <span>
:actor="event.organizerActor" {{
:inline="true" $t("By @{username}", {
username: usernameWithDomain(event.organizerActor),
})
}}
</span>
</popover-actor-card>
</span>
<span
v-else-if="
event.attributedTo &&
event.options.hideOrganizerWhenGroupEvent
"
> >
<span>
{{
$t("By @{username}", {
username: usernameWithDomain(event.organizerActor),
})
}}
</span>
</popover-actor-card>
</span>
<span
v-else-if="
event.attributedTo &&
event.options.hideOrganizerWhenGroupEvent
"
>
<popover-actor-card
:actor="event.attributedTo"
:inline="true"
>
{{
$t("By @{group}", {
group: usernameWithDomain(event.attributedTo),
})
}}
</popover-actor-card>
</span>
<span v-else-if="event.organizerActor && event.attributedTo">
<i18n path="By {group}">
<popover-actor-card <popover-actor-card
:actor="event.attributedTo" :actor="event.attributedTo"
slot="group"
:inline="true" :inline="true"
>
{{
$t("By @{group}", {
group: usernameWithDomain(event.attributedTo),
})
}}
</popover-actor-card>
</span>
<span v-else-if="event.organizerActor && event.attributedTo">
<i18n path="By {group}">
<popover-actor-card
:actor="event.attributedTo"
slot="group"
:inline="true"
>
<router-link
:to="{
name: RouteName.GROUP,
params: {
preferredUsername: usernameWithDomain(
event.attributedTo
),
},
}"
>
{{
$t("@{group}", {
group: usernameWithDomain(event.attributedTo),
})
}}
</router-link>
</popover-actor-card>
</i18n>
</span>
</div>
<p class="tags" v-if="event.tags && event.tags.length > 0">
<router-link
v-for="tag in event.tags"
:key="tag.title"
:to="{ name: RouteName.TAG, params: { tag: tag.title } }"
>
<tag>{{ tag.title }}</tag>
</router-link>
</p>
<b-tag type="is-warning" size="is-medium" v-if="event.draft"
>{{ $t("Draft") }}
</b-tag>
<span
class="event-status"
v-if="event.status !== EventStatus.CONFIRMED"
>
<b-tag
type="is-warning"
v-if="event.status === EventStatus.TENTATIVE"
>{{ $t("Event to be confirmed") }}</b-tag
>
<b-tag
type="is-danger"
v-if="event.status === EventStatus.CANCELLED"
>{{ $t("Event cancelled") }}</b-tag
>
</span>
</div>
<div class="column is-3-tablet">
<participation-section
:participation="participations[0]"
:event="event"
:anonymousParticipation="anonymousParticipation"
@join-event="joinEvent"
@join-modal="isJoinModalActive = true"
@join-event-with-confirmation="joinEventWithConfirmation"
@confirm-leave="confirmLeave"
@cancel-anonymous-participation="cancelAnonymousParticipation"
/>
<div class="has-text-right">
<template class="visibility" v-if="!event.draft">
<p v-if="event.visibility === EventVisibility.PUBLIC">
{{ $t("Public event") }}
<b-icon icon="earth" />
</p>
<p v-if="event.visibility === EventVisibility.UNLISTED">
{{ $t("Private event") }}
<b-icon icon="link" />
</p>
</template>
<template v-if="!event.local && organizer">
<a :href="event.url">
<tag>{{ organizer.domain }}</tag>
</a>
</template>
<p>
<router-link
class="participations-link"
v-if="actorIsOrganizer && event.draft === false"
:to="{
name: RouteName.PARTICIPATIONS,
params: { eventId: event.uuid },
}"
>
<!-- We retire one because of the event creator who is a participant -->
<span v-if="event.options.maximumAttendeeCapacity">
{{
$tc(
"{available}/{capacity} available places",
event.options.maximumAttendeeCapacity -
event.participantStats.participant,
{
available:
event.options.maximumAttendeeCapacity -
event.participantStats.participant,
capacity: event.options.maximumAttendeeCapacity,
}
)
}}
</span>
<span v-else>
{{
$tc(
"No one is participating|One person participating|{going} people participating",
event.participantStats.participant,
{
going: event.participantStats.participant,
}
)
}}
</span>
</router-link>
<span v-else>
<span v-if="event.options.maximumAttendeeCapacity">
{{
$tc(
"{available}/{capacity} available places",
event.options.maximumAttendeeCapacity -
event.participantStats.participant,
{
available:
event.options.maximumAttendeeCapacity -
event.participantStats.participant,
capacity: event.options.maximumAttendeeCapacity,
}
)
}}
</span>
<span v-else>
{{
$tc(
"No one is participating|One person participating|{going} people participating",
event.participantStats.participant,
{
going: event.participantStats.participant,
}
)
}}
</span>
</span>
<b-tooltip
type="is-dark"
v-if="!event.local"
:label="
$t(
'The actual number of participants may differ, as this event is hosted on another instance.'
)
"
>
<b-icon size="is-small" icon="help-circle-outline" />
</b-tooltip>
<b-icon icon="ticket-confirmation-outline" />
</p>
<b-dropdown position="is-bottom-left" aria-role="list">
<b-button
slot="trigger"
role="button"
icon-right="dots-horizontal"
>
{{ $t("Actions") }}
</b-button>
<b-dropdown-item
aria-role="listitem"
has-link
v-if="actorIsOrganizer || event.draft"
> >
<router-link <router-link
:to="{ :to="{
name: RouteName.GROUP, name: RouteName.EDIT_EVENT,
params: { params: { eventId: event.uuid },
preferredUsername: usernameWithDomain(
event.attributedTo
),
},
}" }"
> >
{{ {{ $t("Edit") }}
$t("@{group}", { <b-icon icon="pencil" />
group: usernameWithDomain(event.attributedTo),
})
}}
</router-link> </router-link>
</popover-actor-card> </b-dropdown-item>
</i18n> <b-dropdown-item
</span> aria-role="listitem"
</div> has-link
<p class="tags" v-if="event.tags && event.tags.length > 0"> v-if="actorIsOrganizer || event.draft"
<router-link
v-for="tag in event.tags"
:key="tag.title"
:to="{ name: RouteName.TAG, params: { tag: tag.title } }"
>
<tag>{{ tag.title }}</tag>
</router-link>
</p>
<b-tag type="is-warning" size="is-medium" v-if="event.draft"
>{{ $t("Draft") }}
</b-tag>
<span
class="event-status"
v-if="event.status !== EventStatus.CONFIRMED"
>
<b-tag
type="is-warning"
v-if="event.status === EventStatus.TENTATIVE"
>{{ $t("Event to be confirmed") }}</b-tag
>
<b-tag
type="is-danger"
v-if="event.status === EventStatus.CANCELLED"
>{{ $t("Event cancelled") }}</b-tag
>
</span>
</div>
<div class="column is-3-tablet">
<participation-section
:participation="participations[0]"
:event="event"
:anonymousParticipation="anonymousParticipation"
@join-event="joinEvent"
@join-modal="isJoinModalActive = true"
@join-event-with-confirmation="joinEventWithConfirmation"
@confirm-leave="confirmLeave"
@cancel-anonymous-participation="cancelAnonymousParticipation"
/>
<div class="has-text-right">
<template class="visibility" v-if="!event.draft">
<p v-if="event.visibility === EventVisibility.PUBLIC">
{{ $t("Public event") }}
<b-icon icon="earth" />
</p>
<p v-if="event.visibility === EventVisibility.UNLISTED">
{{ $t("Private event") }}
<b-icon icon="link" />
</p>
</template>
<template v-if="!event.local && organizer">
<a :href="event.url">
<tag>{{ organizer.domain }}</tag>
</a>
</template>
<p>
<router-link
class="participations-link"
v-if="actorIsOrganizer && event.draft === false"
:to="{
name: RouteName.PARTICIPATIONS,
params: { eventId: event.uuid },
}"
>
<!-- We retire one because of the event creator who is a participant -->
<span v-if="event.options.maximumAttendeeCapacity">
{{
$tc(
"{available}/{capacity} available places",
event.options.maximumAttendeeCapacity -
event.participantStats.participant,
{
available:
event.options.maximumAttendeeCapacity -
event.participantStats.participant,
capacity: event.options.maximumAttendeeCapacity,
}
)
}}
</span>
<span v-else>
{{
$tc(
"No one is participating|One person participating|{going} people participating",
event.participantStats.participant,
{
going: event.participantStats.participant,
}
)
}}
</span>
</router-link>
<span v-else>
<span v-if="event.options.maximumAttendeeCapacity">
{{
$tc(
"{available}/{capacity} available places",
event.options.maximumAttendeeCapacity -
event.participantStats.participant,
{
available:
event.options.maximumAttendeeCapacity -
event.participantStats.participant,
capacity: event.options.maximumAttendeeCapacity,
}
)
}}
</span>
<span v-else>
{{
$tc(
"No one is participating|One person participating|{going} people participating",
event.participantStats.participant,
{
going: event.participantStats.participant,
}
)
}}
</span>
</span>
<b-tooltip
type="is-dark"
v-if="!event.local"
:label="
$t(
'The actual number of participants may differ, as this event is hosted on another instance.'
)
"
>
<b-icon size="is-small" icon="help-circle-outline" />
</b-tooltip>
<b-icon icon="ticket-confirmation-outline" />
</p>
<b-dropdown position="is-bottom-left" aria-role="list">
<b-button
slot="trigger"
role="button"
icon-right="dots-horizontal"
>
{{ $t("Actions") }}
</b-button>
<b-dropdown-item
aria-role="listitem"
has-link
v-if="actorIsOrganizer || event.draft"
>
<router-link
:to="{
name: RouteName.EDIT_EVENT,
params: { eventId: event.uuid },
}"
> >
{{ $t("Edit") }} <router-link
<b-icon icon="pencil" /> :to="{
</router-link> name: RouteName.DUPLICATE_EVENT,
</b-dropdown-item> params: { eventId: event.uuid },
<b-dropdown-item }"
aria-role="listitem" >
has-link {{ $t("Duplicate") }}
v-if="actorIsOrganizer || event.draft" <b-icon icon="content-duplicate" />
> </router-link>
<router-link </b-dropdown-item>
:to="{ <b-dropdown-item
name: RouteName.DUPLICATE_EVENT, aria-role="listitem"
params: { eventId: event.uuid }, v-if="actorIsOrganizer || event.draft"
}" @click="openDeleteEventModalWrapper"
> >
{{ $t("Duplicate") }} {{ $t("Delete") }}
<b-icon icon="content-duplicate" /> <b-icon icon="delete" />
</router-link> </b-dropdown-item>
</b-dropdown-item>
<b-dropdown-item
aria-role="listitem"
v-if="actorIsOrganizer || event.draft"
@click="openDeleteEventModalWrapper"
>
{{ $t("Delete") }}
<b-icon icon="delete" />
</b-dropdown-item>
<hr <hr
class="dropdown-divider" class="dropdown-divider"
aria-role="menuitem" aria-role="menuitem"
v-if="actorIsOrganizer || event.draft" v-if="actorIsOrganizer || event.draft"
/> />
<b-dropdown-item <b-dropdown-item
aria-role="listitem" aria-role="listitem"
v-if="!event.draft" v-if="!event.draft"
@click="triggerShare()" @click="triggerShare()"
> >
<span> <span>
{{ $t("Share this event") }} {{ $t("Share this event") }}
<b-icon icon="share" /> <b-icon icon="share" />
</span> </span>
</b-dropdown-item> </b-dropdown-item>
<b-dropdown-item <b-dropdown-item
aria-role="listitem" aria-role="listitem"
@click="downloadIcsEvent()" @click="downloadIcsEvent()"
v-if="!event.draft" v-if="!event.draft"
> >
<span> <span>
{{ $t("Add to my calendar") }} {{ $t("Add to my calendar") }}
<b-icon icon="calendar-plus" /> <b-icon icon="calendar-plus" />
</span> </span>
</b-dropdown-item> </b-dropdown-item>
<b-dropdown-item <b-dropdown-item
aria-role="listitem" aria-role="listitem"
v-if="ableToReport" v-if="ableToReport"
@click="isReportModalActive = true" @click="isReportModalActive = true"
> >
<span> <span>
{{ $t("Report") }} {{ $t("Report") }}
<b-icon icon="flag" /> <b-icon icon="flag" />
</span> </span>
</b-dropdown-item> </b-dropdown-item>
</b-dropdown> </b-dropdown>
</div>
</div> </div>
</div> </div>
</div> </section>
</section> </div>
<div class="event-description-wrapper"> <div class="event-description-wrapper">
<aside class="event-metadata"> <aside class="event-metadata">
<div class="sticky"> <div class="sticky">
@ -662,6 +659,7 @@ import { IConfig } from "../../types/config.model";
import Subtitle from "../../components/Utils/Subtitle.vue"; import Subtitle from "../../components/Utils/Subtitle.vue";
import Tag from "../../components/Tag.vue"; import Tag from "../../components/Tag.vue";
import EventMetadataBlock from "../../components/Event/EventMetadataBlock.vue"; import EventMetadataBlock from "../../components/Event/EventMetadataBlock.vue";
import EventBanner from "../../components/Event/EventBanner.vue";
import ActorCard from "../../components/Account/ActorCard.vue"; import ActorCard from "../../components/Account/ActorCard.vue";
import PopoverActorCard from "../../components/Account/PopoverActorCard.vue"; import PopoverActorCard from "../../components/Account/PopoverActorCard.vue";
import { IParticipant } from "../../types/participant.model"; import { IParticipant } from "../../types/participant.model";
@ -683,6 +681,7 @@ import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core";
Tag, Tag,
ActorCard, ActorCard,
PopoverActorCard, PopoverActorCard,
EventBanner,
"map-leaflet": () => "map-leaflet": () =>
import(/* webpackChunkName: "map" */ "../../components/Map.vue"), import(/* webpackChunkName: "map" */ "../../components/Map.vue"),
ShareEventModal: () => ShareEventModal: () =>
@ -1308,18 +1307,6 @@ export default class Event extends EventMixin {
opacity: 0; opacity: 0;
} }
.header-picture,
.header-picture-default {
height: 400px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.header-picture-default {
background-image: url("../../../public/img/mobilizon_default_card.png");
}
div.sidebar { div.sidebar {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@ -1353,7 +1340,7 @@ div.sidebar {
} }
} }
.intro.section { .intro {
background: white; background: white;
.is-3-tablet { .is-3-tablet {