2019-01-21 15:08:22 +01:00
< template >
2022-07-12 10:55:28 +02:00
< div class = "container mx-auto" >
< o -loading v -model :active ="eventLoading" / >
< div class = "wrapper mb-3" >
< event -banner :picture ="event?.picture" / >
2021-08-04 11:23:37 +02:00
< div class = "intro-wrapper" >
2022-07-12 10:55:28 +02:00
< div class = "date-calendar-icon-wrapper" v-if ="event?.beginsOn" >
< date -calendar -icon :date ="event.beginsOn.toString()" / >
2021-08-04 11:23:37 +02:00
< / div >
2022-07-12 10:55:28 +02:00
2021-11-07 21:02:06 +01:00
< section class = "intro" dir = "auto" >
2022-07-12 10:55:28 +02:00
< div class = "flex flex-wrap" >
< div class = "flex-1 min-w-fit" >
2021-11-13 15:58:54 +01:00
< h1
2022-07-12 10:55:28 +02:00
class = "text-4xl font-bold m-0"
2021-11-13 15:58:54 +01:00
dir = "auto"
2022-07-12 10:55:28 +02:00
: lang = "event?.language"
2021-11-13 15:58:54 +01:00
>
2022-07-12 10:55:28 +02:00
{ { event ? . title } }
2021-11-07 14:59:20 +01:00
< / h1 >
2021-08-04 11:23:37 +02:00
< div class = "organizer" >
2022-07-12 10:55:28 +02:00
< div v-if ="event?.organizerActor && !event?.attributedTo" >
2021-08-04 11:23:37 +02:00
< popover -actor -card
: actor = "event.organizerActor"
: inline = "true"
>
2022-07-12 10:55:28 +02:00
< i18n -t
keypath = "By {username}"
2022-04-22 12:00:47 +02:00
dir = "auto"
class = "block truncate max-w-xs md:max-w-sm"
>
2022-07-12 10:55:28 +02:00
< template # username >
< span dir = "ltr" > { {
displayName ( event . organizerActor )
} } < / span >
< / template >
< / i 1 8 n - t >
2021-08-04 11:23:37 +02:00
< / p o p o v e r - a c t o r - c a r d >
2021-11-07 14:59:20 +01:00
< / div >
2022-07-12 10:55:28 +02:00
< span v -else -if = " event ? .attributedTo " >
2021-08-04 11:23:37 +02:00
< popover -actor -card
: actor = "event.attributedTo"
: inline = "true"
>
2022-07-12 10:55:28 +02:00
< i18n -t
keypath = "By {group}"
2022-04-22 12:00:47 +02:00
dir = "auto"
class = "block truncate max-w-xs md:max-w-sm"
>
2022-07-12 10:55:28 +02:00
< template # group >
< router -link
: to = " {
name : RouteName . GROUP ,
params : {
preferredUsername : usernameWithDomain (
event . attributedTo
) ,
} ,
} "
dir = "ltr"
> { { displayName ( event . attributedTo ) } } < / r o u t e r - l i n k
>
< / template >
< / i 1 8 n - t >
2021-11-07 21:02:06 +01:00
< / p o p o v e r - a c t o r - c a r d >
2021-08-04 11:23:37 +02:00
< / span >
< / div >
2022-03-28 17:42:59 +02:00
< p class = "tags" dir = "auto" >
< tag v-if ="eventCategory" class="category" > {{
eventCategory
} } < / tag >
2021-08-04 11:23:37 +02:00
< router -link
2022-07-12 10:55:28 +02:00
v - for = "tag in event?.tags ?? []"
2021-08-04 11:23:37 +02:00
: key = "tag.title"
: to = "{ name: RouteName.TAG, params: { tag: tag.title } }"
>
< tag > { { tag . title } } < / tag >
< / r o u t e r - l i n k >
< / p >
2022-07-12 10:55:28 +02:00
< b -tag variant = "warning" size = "is-medium" v -if = " event ? .draft "
> { { t ( "Draft" ) } }
2021-08-04 11:23:37 +02:00
< / b - t a g >
< span
class = "event-status"
2022-07-12 10:55:28 +02:00
v - if = "event?.status !== EventStatus.CONFIRMED"
2021-08-04 11:23:37 +02:00
>
< b -tag
2022-07-12 10:55:28 +02:00
variant = "warning"
v - if = "event?.status === EventStatus.TENTATIVE"
> { { t ( "Event to be confirmed" ) } } < / b - t a g
2021-08-04 11:23:37 +02:00
>
< b -tag
2022-07-12 10:55:28 +02:00
variant = "danger"
v - if = "event?.status === EventStatus.CANCELLED"
> { { t ( "Event cancelled" ) } } < / b - t a g
2021-08-04 11:23:37 +02:00
>
< / span >
< / div >
2022-07-12 10:55:28 +02:00
< div class = "" >
2021-08-04 11:23:37 +02:00
< participation -section
2022-07-12 10:55:28 +02:00
v - if = "
event &&
currentActor &&
identities &&
anonymousParticipationConfig
"
2021-08-04 11:23:37 +02:00
: participation = "participations[0]"
: event = "event"
: anonymousParticipation = "anonymousParticipation"
2022-07-12 10:55:28 +02:00
: currentActor = "currentActor"
: identities = "identities"
: anonymousParticipationConfig = "anonymousParticipationConfig"
2021-08-04 11:23:37 +02:00
@ join - event = "joinEvent"
@ join - modal = "isJoinModalActive = true"
@ join - event - with - confirmation = "joinEventWithConfirmation"
@ confirm - leave = "confirmLeave"
@ cancel - anonymous - participation = "cancelAnonymousParticipation"
/ >
2022-07-12 10:55:28 +02:00
< div class = "flex flex-col" >
< template v-if ="!event?.draft" >
< p
v - if = "event?.visibility === EventVisibility.PUBLIC"
class = "inline-flex gap-1"
>
< Earth / >
{ { t ( "Public event" ) } }
2021-08-04 11:23:37 +02:00
< / p >
2022-07-12 10:55:28 +02:00
< p
v - if = "event?.visibility === EventVisibility.UNLISTED"
class = "inline-flex gap-1"
>
< Link / >
{ { t ( "Private event" ) } }
2021-08-04 11:23:37 +02:00
< / p >
< / template >
2022-07-12 10:55:28 +02:00
< template v-if ="!event?.local && organizer?.domain" >
< a :href ="event?.url" >
< tag > { { organizer ? . domain } } < / tag >
2021-08-04 11:23:37 +02:00
< / a >
< / template >
2022-07-12 10:55:28 +02:00
< p class = "inline-flex gap-1" >
< TicketConfirmationOutline / >
2021-08-04 11:23:37 +02:00
< router -link
class = "participations-link"
2022-07-12 10:55:28 +02:00
v - if = "canManageEvent && event?.draft === false"
2021-08-04 11:23:37 +02:00
: to = " {
name : RouteName . PARTICIPATIONS ,
params : { eventId : event . uuid } ,
} "
2019-10-23 12:36:11 +02:00
>
2022-07-12 10:55:28 +02:00
<!-- We retire one because of the event creator who is a
participant -- >
2021-10-20 11:49:55 +02:00
< span v-if ="maximumAttendeeCapacity" >
2020-02-18 08:57:00 +01:00
{ {
2022-07-12 10:55:28 +02:00
t (
2021-08-04 11:23:37 +02:00
"{available}/{capacity} available places" ,
{
available :
2021-10-20 11:49:55 +02:00
maximumAttendeeCapacity -
2021-08-04 11:23:37 +02:00
event . participantStats . participant ,
2021-10-20 11:49:55 +02:00
capacity : maximumAttendeeCapacity ,
2022-07-12 10:55:28 +02:00
} ,
maximumAttendeeCapacity -
event . participantStats . participant
2021-08-04 11:23:37 +02:00
)
2020-02-18 08:57:00 +01:00
} }
2021-08-04 11:23:37 +02:00
< / span >
< span v-else >
{ {
2022-07-12 10:55:28 +02:00
t (
2021-08-04 11:23:37 +02:00
"No one is participating|One person participating|{going} people participating" ,
{
going : event . participantStats . participant ,
2022-07-12 10:55:28 +02:00
} ,
event . participantStats . participant
2021-08-04 11:23:37 +02:00
)
} }
< / span >
< / r o u t e r - l i n k >
< span v-else >
2021-10-20 11:49:55 +02:00
< span v-if ="maximumAttendeeCapacity" >
2021-08-04 11:23:37 +02:00
{ {
2022-07-12 10:55:28 +02:00
t (
2021-08-04 11:23:37 +02:00
"{available}/{capacity} available places" ,
{
available :
2021-10-20 11:49:55 +02:00
maximumAttendeeCapacity -
2022-07-12 10:55:28 +02:00
( event ? . participantStats . participant ? ? 0 ) ,
2021-10-20 11:49:55 +02:00
capacity : maximumAttendeeCapacity ,
2022-07-12 10:55:28 +02:00
} ,
maximumAttendeeCapacity -
( event ? . participantStats . participant ? ? 0 )
2021-08-04 11:23:37 +02:00
)
} }
< / span >
< span v-else >
{ {
2022-07-12 10:55:28 +02:00
t (
2021-08-04 11:23:37 +02:00
"No one is participating|One person participating|{going} people participating" ,
{
2022-07-12 10:55:28 +02:00
going : event ? . participantStats . participant ,
} ,
event ? . participantStats . participant ? ? 0
2021-08-04 11:23:37 +02:00
)
} }
< / span >
2021-06-10 10:33:16 +02:00
< / span >
2022-07-12 10:55:28 +02:00
< VTooltip v-if ="event?.local === false" >
< HelpCircleOutline :size ="16" / >
< template # popper >
{ {
t (
"The actual number of participants may differ, as this event is hosted on another instance."
)
} }
< / template >
< / VTooltip >
2019-04-03 17:29:03 +02:00
< / p >
2022-07-12 10:55:28 +02:00
< o -dropdown >
< template # trigger >
< o -button
icon - right = "dots-horizontal"
# default = "{ active }"
>
{ { t ( "Actions" ) } }
< / o - b u t t o n >
< / template >
< o -dropdown -item
2021-08-04 11:23:37 +02:00
aria - role = "listitem"
has - link
2022-07-12 10:55:28 +02:00
v - if = "canManageEvent || event?.draft"
2020-04-23 00:27:09 +02:00
>
< router -link
2022-07-12 10:55:28 +02:00
class = "flex gap-1"
2020-11-30 10:24:11 +01:00
: to = " {
2021-08-04 11:23:37 +02:00
name : RouteName . EDIT _EVENT ,
2022-07-12 10:55:28 +02:00
params : { eventId : event ? . uuid } ,
2020-11-30 10:24:11 +01:00
} "
2020-04-23 00:27:09 +02:00
>
2022-07-12 10:55:28 +02:00
< Pencil / >
{ { t ( "Edit" ) } }
2020-04-23 00:27:09 +02:00
< / r o u t e r - l i n k >
2022-07-12 10:55:28 +02:00
< / o - d r o p d o w n - i t e m >
< o -dropdown -item
2021-08-04 11:23:37 +02:00
aria - role = "listitem"
has - link
2022-07-12 10:55:28 +02:00
v - if = "canManageEvent || event?.draft"
2021-08-04 11:23:37 +02:00
>
< router -link
2022-07-12 10:55:28 +02:00
class = "flex gap-1"
2021-08-04 11:23:37 +02:00
: to = " {
name : RouteName . DUPLICATE _EVENT ,
2022-07-12 10:55:28 +02:00
params : { eventId : event ? . uuid } ,
2021-08-04 11:23:37 +02:00
} "
2021-06-10 10:33:16 +02:00
>
2022-07-12 10:55:28 +02:00
< ContentDuplicate / >
{ { t ( "Duplicate" ) } }
2021-08-04 11:23:37 +02:00
< / r o u t e r - l i n k >
2022-07-12 10:55:28 +02:00
< / o - d r o p d o w n - i t e m >
< o -dropdown -item
2021-08-04 11:23:37 +02:00
aria - role = "listitem"
2022-07-12 10:55:28 +02:00
v - if = "canManageEvent || event?.draft"
2021-08-04 11:23:37 +02:00
@ click = "openDeleteEventModalWrapper"
2021-10-10 16:24:12 +02:00
@ keyup . enter = "openDeleteEventModalWrapper"
2022-07-12 10:55:28 +02:00
> < span class = "flex gap-1" >
< Delete / >
{ { t ( "Delete" ) } }
< / span >
< / o - d r o p d o w n - i t e m >
2021-06-10 10:33:16 +02:00
2021-08-04 11:23:37 +02:00
< hr
2021-10-10 16:24:12 +02:00
role = "presentation"
2021-08-04 11:23:37 +02:00
class = "dropdown-divider"
2022-07-12 10:55:28 +02:00
aria - role = "o-dropdown-item"
v - if = "canManageEvent || event?.draft"
2021-08-04 11:23:37 +02:00
/ >
2022-07-12 10:55:28 +02:00
< o -dropdown -item
2021-08-04 11:23:37 +02:00
aria - role = "listitem"
2022-07-12 10:55:28 +02:00
v - if = "event?.draft === false"
2021-08-04 11:23:37 +02:00
@ click = "triggerShare()"
2021-10-10 16:24:12 +02:00
@ keyup . enter = "triggerShare()"
2022-07-12 10:55:28 +02:00
class = "p-1"
2021-08-04 11:23:37 +02:00
>
2022-07-12 10:55:28 +02:00
< span class = "flex gap-1" >
< Share / >
{ { t ( "Share this event" ) } }
2021-08-04 11:23:37 +02:00
< / span >
2022-07-12 10:55:28 +02:00
< / o - d r o p d o w n - i t e m >
< o -dropdown -item
2021-08-04 11:23:37 +02:00
aria - role = "listitem"
@ click = "downloadIcsEvent()"
2021-10-10 16:24:12 +02:00
@ keyup . enter = "downloadIcsEvent()"
2022-07-12 10:55:28 +02:00
v - if = "event?.draft === false"
2021-08-04 11:23:37 +02:00
>
2022-07-12 10:55:28 +02:00
< span class = "flex gap-1" >
< CalendarPlus / >
{ { t ( "Add to my calendar" ) } }
2021-08-04 11:23:37 +02:00
< / span >
2022-07-12 10:55:28 +02:00
< / o - d r o p d o w n - i t e m >
< o -dropdown -item
2021-08-04 11:23:37 +02:00
aria - role = "listitem"
v - if = "ableToReport"
@ click = "isReportModalActive = true"
2021-10-10 16:24:12 +02:00
@ keyup . enter = "isReportModalActive = true"
2022-07-12 10:55:28 +02:00
class = "p-1"
2021-08-04 11:23:37 +02:00
>
2022-07-12 10:55:28 +02:00
< span class = "flex gap-1" >
< Flag / >
{ { t ( "Report" ) } }
2021-08-04 11:23:37 +02:00
< / span >
2022-07-12 10:55:28 +02:00
< / o - d r o p d o w n - i t e m >
< / o - d r o p d o w n >
2020-02-18 08:57:00 +01:00
< / div >
< / div >
2021-08-04 11:23:37 +02:00
< / div >
< / section >
< / div >
2022-07-12 10:55:28 +02:00
< div
class = "event-description-wrapper rounded-lg dark:border-violet-title flex flex-wrap flex-col md:flex-row-reverse"
>
< aside class = "event-metadata rounded dark:bg-gray-600 shadow-md" >
2021-08-04 11:23:37 +02:00
< div class = "sticky" >
2021-08-09 14:26:11 +02:00
< event -metadata -sidebar
2022-07-12 10:55:28 +02:00
v - if = "event && loggedUser"
2021-08-09 14:26:11 +02:00
: event = "event"
2021-10-10 16:25:50 +02:00
: user = "loggedUser"
@ showMapModal = "showMap = true"
2021-08-09 14:26:11 +02:00
/ >
2021-08-04 11:23:37 +02:00
< / div >
< / aside >
< div class = "event-description-comments" >
< section class = "event-description" >
2022-07-12 10:55:28 +02:00
< h2 class = "text-xl" > { { t ( "About this event" ) } } < / h2 >
< p v-if ="!event?.description" >
{ { t ( "The event organizer didn't add any description." ) } }
2021-08-04 11:23:37 +02:00
< / p >
< div v-else >
< div
2022-07-12 10:55:28 +02:00
: lang = "event?.language"
2021-11-07 14:59:20 +01:00
dir = "auto"
2021-08-04 11:23:37 +02:00
class = "description-content"
ref = "eventDescriptionElement"
v - html = "event.description"
/ >
2019-04-03 17:29:03 +02:00
< / div >
2021-08-04 11:23:37 +02:00
< / section >
2021-08-09 14:26:11 +02:00
< section class = "integration-wrappers" >
< component
v - for = "(metadata, integration) in integrations"
: is = "integration"
: key = "integration"
: metadata = "metadata"
/ >
< / section >
2021-08-04 11:23:37 +02:00
< section class = "comments" ref = "commentsObserver" >
< a href = "#comments" >
2022-07-12 10:55:28 +02:00
< h2 class = "text-xl" id = "comments" > { { t ( "Comments" ) } } < / h2 >
2021-08-04 11:23:37 +02:00
< / a >
2022-07-12 10:55:28 +02:00
< comment -tree v -if = " event & & loadComments " :event ="event" / >
2021-08-04 11:23:37 +02:00
< / section >
< / div >
< / div >
2022-07-12 10:55:28 +02:00
2021-08-04 11:23:37 +02:00
< section
class = "more-events section"
2022-07-12 10:55:28 +02:00
v - if = "(event?.relatedEvents ?? []).length > 0"
2021-08-04 11:23:37 +02:00
>
< h3 class = "title has-text-centered" >
2022-07-12 10:55:28 +02:00
{ { t ( "These events may interest you" ) } }
2021-08-04 11:23:37 +02:00
< / h3 >
2022-07-12 10:55:28 +02:00
< multi -card : events = "event?.relatedEvents ?? []" / >
2021-08-04 11:23:37 +02:00
< / section >
2022-07-12 10:55:28 +02:00
< o -modal
v - model : active = "isReportModalActive"
2021-08-04 11:23:37 +02:00
has - modal - card
ref = "reportModal"
2022-07-12 10:55:28 +02:00
: close - button - aria - label = "t('Close')"
2021-08-04 11:23:37 +02:00
>
< report -modal
: on - confirm = "reportEvent"
2022-07-12 10:55:28 +02:00
: title = "t('Report this event')"
2021-08-04 11:23:37 +02:00
: outside - domain = "organizerDomain"
/ >
2022-07-12 10:55:28 +02:00
< / o - m o d a l >
< o -modal
: close - button - aria - label = "t('Close')"
v - model : active = "isShareModalActive"
2021-08-04 11:23:37 +02:00
has - modal - card
ref = "shareModal"
>
< share -event -modal :event ="event" :eventCapacityOK ="eventCapacityOK" / >
2022-07-12 10:55:28 +02:00
< / o - m o d a l >
< o -modal
v - model : active = "isJoinModalActive"
2021-08-04 11:23:37 +02:00
has - modal - card
ref = "participationModal"
2022-07-12 10:55:28 +02:00
: close - button - aria - label = "t('Close')"
2021-08-04 11:23:37 +02:00
>
< identity -picker v-model ="identity" >
< template v -slot : footer >
< footer class = "modal-card-foot" >
< button
class = "button"
ref = "cancelButton"
@ click = "isJoinModalActive = false"
2021-10-10 16:24:12 +02:00
@ keyup . enter = "isJoinModalActive = false"
2021-08-04 11:23:37 +02:00
>
2022-07-12 10:55:28 +02:00
{ { t ( "Cancel" ) } }
2021-08-04 11:23:37 +02:00
< / button >
< button
2022-07-12 10:55:28 +02:00
v - if = "identity"
2021-08-04 11:23:37 +02:00
class = "button is-primary"
ref = "confirmButton"
@ click = "
2022-07-12 10:55:28 +02:00
event ? . joinOptions === EventJoinOptions . RESTRICTED
2021-08-04 11:23:37 +02:00
? joinEventWithConfirmation ( identity )
: joinEvent ( identity )
"
2021-10-10 16:24:12 +02:00
@ keyup . enter = "
2022-07-12 10:55:28 +02:00
event ? . joinOptions === EventJoinOptions . RESTRICTED
2021-10-10 16:24:12 +02:00
? joinEventWithConfirmation ( identity )
: joinEvent ( identity )
"
2021-08-04 11:23:37 +02:00
>
2022-07-12 10:55:28 +02:00
{ { t ( "Confirm my particpation" ) } }
2021-08-04 11:23:37 +02:00
< / button >
< / footer >
< / template >
< / i d e n t i t y - p i c k e r >
2022-07-12 10:55:28 +02:00
< / o - m o d a l >
< o -modal
v - model : active = "isJoinConfirmationModalActive"
2021-08-04 11:23:37 +02:00
has - modal - card
ref = "joinConfirmationModal"
2022-07-12 10:55:28 +02:00
: close - button - aria - label = "t('Close')"
2021-08-04 11:23:37 +02:00
>
< div class = "modal-card" >
< header class = "modal-card-head" >
< p class = "modal-card-title" >
2022-07-12 10:55:28 +02:00
{ { t ( "Participation confirmation" ) } }
2021-08-04 11:23:37 +02:00
< / p >
< / header >
< section class = "modal-card-body" >
< p >
{ {
2022-07-12 10:55:28 +02:00
t (
2021-08-04 11:23:37 +02:00
"The event organiser has chosen to validate manually participations. Do you want to add a little note to explain why you want to participate to this event?"
)
} }
< / p >
< form
@ submit . prevent = "
joinEvent ( actorForConfirmation , messageForConfirmation )
"
2020-02-18 08:57:00 +01:00
>
2022-07-12 10:55:28 +02:00
< o -field :label ="t('Message')" >
< o -input
2021-08-04 11:23:37 +02:00
type = "textarea"
size = "is-medium"
v - model = "messageForConfirmation"
minlength = "10"
2022-07-12 10:55:28 +02:00
> < / o - i n p u t >
< / o - f i e l d >
2021-08-04 11:23:37 +02:00
< div class = "buttons" >
2022-07-12 10:55:28 +02:00
< o -button
2021-08-04 11:23:37 +02:00
native - type = "button"
2020-11-30 10:24:11 +01:00
class = "button"
ref = "cancelButton"
2021-08-04 11:23:37 +02:00
@ click = "isJoinConfirmationModalActive = false"
2021-10-10 16:24:12 +02:00
@ keyup . enter = "isJoinConfirmationModalActive = false"
2022-07-12 10:55:28 +02:00
> { { t ( "Cancel" ) } }
< / o - b u t t o n >
< o -button variant = "primary" native -type = " submit " >
{ { t ( "Confirm my participation" ) } }
< / o - b u t t o n >
2021-08-04 11:23:37 +02:00
< / div >
< / form >
< / section >
< / div >
2022-07-12 10:55:28 +02:00
< / o - m o d a l >
< o -modal
v - model : active = "showMap"
: close - button - aria - label = "t('Close')"
2021-10-10 16:25:50 +02:00
class = "map-modal"
2022-07-12 10:55:28 +02:00
v - if = "event?.physicalAddress?.geom"
2021-10-10 16:25:50 +02:00
has - modal - card
full - screen
: can - cancel = "['escape', 'outside']"
>
< template # default = "props" >
2022-07-12 10:55:28 +02:00
<!-- < event -map
2021-10-10 16:25:50 +02:00
: routingType = "routingType"
: address = "event.physicalAddress"
@ close = "props.close"
2022-07-12 10:55:28 +02:00
/ > - - >
2021-10-10 16:25:50 +02:00
< / template >
2022-07-12 10:55:28 +02:00
< / o - m o d a l >
< dialog
variant = "danger"
: title = "t('Delete event')"
: message = "deleteEventMessage"
: confirmText = "t('Delete {eventTitle}', { eventTitle: event?.title })"
: onConfirm = "
( ) => ( event ? . id ? deleteEvent ( { eventId : event ? . id } ) : null )
"
> < / dialog >
2021-08-04 11:23:37 +02:00
< / div >
2019-10-08 22:27:14 +02:00
< / div >
2019-01-21 15:08:22 +01:00
< / template >
2022-07-12 10:55:28 +02:00
< script lang = "ts" setup >
2020-11-30 10:24:11 +01:00
import {
EventJoinOptions ,
EventStatus ,
EventVisibility ,
2021-07-26 17:15:40 +02:00
MemberRole ,
2020-11-30 10:24:11 +01:00
ParticipantRole ,
} from "@/types/enums" ;
2020-02-18 08:57:00 +01:00
import {
EVENT _PERSON _PARTICIPATION ,
EVENT _PERSON _PARTICIPATION _SUBSCRIPTION _CHANGED ,
FETCH _EVENT ,
JOIN _EVENT ,
} from "../../graphql/event" ;
2021-10-25 13:18:13 +02:00
import { CURRENT _ACTOR _CLIENT , PERSON _STATUS _GROUP } from "../../graphql/actor" ;
2020-11-27 19:27:44 +01:00
import { EventModel , IEvent } from "../../types/event.model" ;
2022-04-22 12:00:47 +02:00
import {
displayName ,
IActor ,
IPerson ,
Person ,
usernameWithDomain ,
} from "../../types/actor" ;
2020-02-18 08:57:00 +01:00
import { GRAPHQL _API _ENDPOINT } from "../../api/_entrypoint" ;
import DateCalendarIcon from "../../components/Event/DateCalendarIcon.vue" ;
2021-10-29 10:54:35 +02:00
import MultiCard from "../../components/Event/MultiCard.vue" ;
2020-02-18 08:57:00 +01:00
import ReportModal from "../../components/Report/ReportModal.vue" ;
import { IReport } from "../../types/report.model" ;
import { CREATE _REPORT } from "../../graphql/report" ;
import EventMixin from "../../mixins/event" ;
import IdentityPicker from "../Account/IdentityPicker.vue" ;
2020-12-04 15:12:00 +01:00
import ParticipationSection from "../../components/Participation/ParticipationSection.vue" ;
2020-02-18 08:57:00 +01:00
import RouteName from "../../router/name" ;
import CommentTree from "../../components/Comment/CommentTree.vue" ;
import "intersection-observer" ;
import { CONFIG } from "../../graphql/config" ;
2019-12-20 13:04:34 +01:00
import {
AnonymousParticipationNotFoundError ,
getLeaveTokenForParticipation ,
isParticipatingInThisEvent ,
2020-02-18 08:57:00 +01:00
removeAnonymousParticipation ,
} from "../../services/AnonymousParticipationStorage" ;
import { IConfig } from "../../types/config.model" ;
import Tag from "../../components/Tag.vue" ;
2021-08-09 14:26:11 +02:00
import EventMetadataSidebar from "../../components/Event/EventMetadataSidebar.vue" ;
2021-06-10 10:33:16 +02:00
import EventBanner from "../../components/Event/EventBanner.vue" ;
2021-10-10 16:25:50 +02:00
import EventMap from "../../components/Event/EventMap.vue" ;
2020-02-18 08:57:00 +01:00
import PopoverActorCard from "../../components/Account/PopoverActorCard.vue" ;
2020-11-27 19:27:44 +01:00
import { IParticipant } from "../../types/participant.model" ;
2021-06-11 14:21:27 +02:00
import { ApolloCache , FetchResult } from "@apollo/client/core" ;
2021-08-09 14:26:11 +02:00
import { IEventMetadataDescription } from "@/types/event-metadata" ;
import { eventMetaDataList } from "../../services/EventMetadata" ;
2021-10-10 16:25:50 +02:00
import { USER _SETTINGS } from "@/graphql/user" ;
import { IUser } from "@/types/current-user.model" ;
2022-07-12 10:55:28 +02:00
import { useDeleteEvent , useFetchEvent } from "@/composition/apollo/event" ;
import {
computed ,
handleError ,
onMounted ,
ref ,
watch ,
defineAsyncComponent ,
inject ,
} from "vue" ;
import { useRoute , useRouter } from "vue-router" ;
import Earth from "vue-material-design-icons/Earth.vue" ;
import Link from "vue-material-design-icons/Link.vue" ;
import Flag from "vue-material-design-icons/Flag.vue" ;
import CalendarPlus from "vue-material-design-icons/CalendarPlus.vue" ;
import ContentDuplicate from "vue-material-design-icons/ContentDuplicate.vue" ;
import Delete from "vue-material-design-icons/Delete.vue" ;
import Pencil from "vue-material-design-icons/Pencil.vue" ;
import HelpCircleOutline from "vue-material-design-icons/HelpCircleOutline.vue" ;
import TicketConfirmationOutline from "vue-material-design-icons/TicketConfirmationOutline.vue" ;
import {
useCurrentActorClient ,
useCurrentUserIdentities ,
usePersonStatusGroup ,
} from "@/composition/apollo/actor" ;
import { useLoggedUser } from "@/composition/apollo/user" ;
import { useMutation , useQuery } from "@vue/apollo-composable" ;
import {
useAnonymousActorId ,
useAnonymousParticipationConfig ,
useAnonymousReportsConfig ,
useEventCategories ,
} from "@/composition/apollo/config" ;
import { useCreateReport } from "@/composition/apollo/report" ;
import Share from "vue-material-design-icons/Share.vue" ;
import { useI18n } from "vue-i18n" ;
import { useProgrammatic } from "@oruga-ui/oruga-next" ;
import { Dialog } from "@/plugins/dialog" ;
import { Notifier } from "@/plugins/notifier" ;
const ShareEventModal = defineAsyncComponent (
( ) => import ( "../../components/Event/ShareEventModal.vue" )
) ;
const IntegrationTwitch = defineAsyncComponent (
( ) => import ( "../../components/Event/Integrations/Twitch.vue" )
) ;
const IntegrationPeertube = defineAsyncComponent (
( ) => import ( "../../components/Event/Integrations/PeerTube.vue" )
) ;
const IntegrationYoutube = defineAsyncComponent (
( ) => import ( "../../components/Event/Integrations/YouTube.vue" )
) ;
const IntegrationJitsiMeet = defineAsyncComponent (
( ) => import ( "../../components/Event/Integrations/JitsiMeet.vue" )
) ;
const IntegrationEtherpad = defineAsyncComponent (
( ) => import ( "../../components/Event/Integrations/Etherpad.vue" )
) ;
const props = defineProps < {
uuid : string ;
} > ( ) ;
const { t } = useI18n ( { useScope : "global" } ) ;
const {
event ,
onError : onFetchEventError ,
loading : eventLoading ,
} = useFetchEvent ( props . uuid ) ;
const eventId = computed ( ( ) => event . value ? . id ) ;
const { currentActor } = useCurrentActorClient ( ) ;
const currentActorId = computed ( ( ) => currentActor . value ? . id ) ;
const { loggedUser } = useLoggedUser ( ) ;
const {
result : participationsResult ,
subscribeToMore : subscribeToMoreParticipation ,
} = useQuery < { person : IPerson } > (
EVENT _PERSON _PARTICIPATION ,
( ) => ( {
eventId : event . value ? . id ,
actorId : currentActorId . value ,
} ) ,
( ) => ( {
enabled :
currentActorId . value !== undefined &&
currentActorId . value !== null &&
eventId . value !== undefined ,
} )
) ;
// subscribeToMoreParticipation(() => ({
// document: EVENT_PERSON_PARTICIPATION_SUBSCRIPTION_CHANGED,
// variables: {
// eventId: eventId,
// actorId: currentActorId,
// },
// }));
const participations = computed (
( ) => participationsResult . value ? . person . participations . elements ? ? [ ]
) ;
const { person } = usePersonStatusGroup (
usernameWithDomain ( event . value ? . attributedTo )
) ;
const { anonymousReportsConfig } = useAnonymousReportsConfig ( ) ;
const { anonymousActorId } = useAnonymousActorId ( ) ;
const { eventCategories } = useEventCategories ( ) ;
const { anonymousParticipationConfig } = useAnonymousParticipationConfig ( ) ;
const { identities } = useCurrentUserIdentities ( ) ;
// metaInfo() {
// return {
// // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// // @ts-ignore
// title: this.eventTitle,
// meta: [
// // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// // @ts-ignore
// { name: "description", content: this.eventDescription },
// ],
// };
// },
const identity = ref < IPerson | null > ( null ) ;
const reportModal = ref ( ) ;
const oldParticipationRole = ref < string | undefined > ( undefined ) ;
const isReportModalActive = ref ( false ) ;
const isShareModalActive = ref ( false ) ;
const isJoinModalActive = ref ( false ) ;
const isJoinConfirmationModalActive = ref ( false ) ;
const observer = ref < IntersectionObserver | null > ( null ) ;
const commentsObserver = ref < Element | null > ( null ) ;
const loadComments = ref ( false ) ;
const anonymousParticipation = ref < boolean | null > ( null ) ;
const actorForConfirmation = ref < IPerson | null > ( null ) ;
const messageForConfirmation = ref ( "" ) ;
const eventTitle = computed ( ( ) : undefined | string => {
return event . value ? . title ;
} ) ;
const eventDescription = computed ( ( ) : undefined | string => {
return event . value ? . description ;
} ) ;
const route = useRoute ( ) ;
const router = useRouter ( ) ;
const eventDescriptionElement = ref < HTMLElement | null > ( null ) ;
onMounted ( async ( ) => {
identity . value = currentActor . value ;
if ( route . hash . includes ( "#comment-" ) ) {
loadComments . value = true ;
2019-10-14 12:56:37 +02:00
}
2022-07-12 10:55:28 +02:00
try {
if ( window . isSecureContext ) {
anonymousParticipation . value = await anonymousParticipationConfirmed ( ) ;
}
} catch ( e ) {
if ( e instanceof AnonymousParticipationNotFoundError ) {
anonymousParticipation . value = null ;
} else {
console . error ( e ) ;
2019-11-15 18:36:47 +01:00
}
2022-07-12 10:55:28 +02:00
}
2019-11-15 18:36:47 +01:00
2022-07-12 10:55:28 +02:00
observer . value = new IntersectionObserver (
( entries ) => {
// eslint-disable-next-line no-restricted-syntax
for ( const entry of entries ) {
if ( entry ) {
loadComments . value = entry . isIntersecting || loadComments . value ;
}
2019-12-20 13:04:34 +01:00
}
2022-07-12 10:55:28 +02:00
} ,
{
rootMargin : "-50px 0px -50px" ,
2019-12-20 13:04:34 +01:00
}
2022-07-12 10:55:28 +02:00
) ;
if ( commentsObserver . value ) {
observer . value . observe ( commentsObserver . value ) ;
}
2019-12-20 13:04:34 +01:00
2022-07-12 10:55:28 +02:00
watch ( eventDescription , ( ) => {
if ( ! eventDescription . value ) return ;
if ( ! eventDescriptionElement . value ) return ;
eventDescriptionElement . value . addEventListener ( "click" , ( $event ) => {
// TODO: Find the right type for target
let { target } : { target : any } = $event ;
while ( target && target . tagName !== "A" ) target = target . parentNode ;
// handle only links that occur inside the component and do not reference external resources
if ( target && target . matches ( ".hashtag" ) && target . href ) {
// some sanity checks taken from vue-router:
// https://github.com/vuejs/vue-router/blob/dev/src/components/link.js#L106
const { altKey , ctrlKey , metaKey , shiftKey , button , defaultPrevented } =
$event ;
// don't handle with control keys
if ( metaKey || altKey || ctrlKey || shiftKey ) return ;
// don't handle when preventDefault called
if ( defaultPrevented ) return ;
// don't handle right clicks
if ( button !== undefined && button !== 0 ) return ;
// don't handle if `target="_blank"`
if ( target && target . getAttribute ) {
const linkTarget = target . getAttribute ( "target" ) ;
if ( /\b_blank\b/i . test ( linkTarget ) ) return ;
2019-11-15 18:36:47 +01:00
}
2022-07-12 10:55:28 +02:00
// don't handle same page links/anchors
const url = new URL ( target . href ) ;
const to = url . pathname ;
if ( window . location . pathname !== to && $event . preventDefault ) {
$event . preventDefault ( ) ;
router . push ( to ) ;
2019-10-23 12:36:11 +02:00
}
2022-07-12 10:55:28 +02:00
}
2020-06-25 11:38:12 +02:00
} ) ;
2022-07-12 10:55:28 +02:00
} ) ;
// this.$on("event-deleted", () => {
// return router.push({ name: RouteName.HOME });
// });
} ) ;
/ * *
* Delete the event , then redirect to home .
* /
const openDeleteEventModalWrapper = async ( ) : Promise < void > => {
await openDeleteEventModal ( event . value ) ;
} ;
const deleteEventMessage = computed ( ( ) => {
const participantsLength = event . value ? . participantStats . participant ;
const prefix = participantsLength
? t (
"There are {participants} participants." ,
{
participants : event . value . participantStats . participant ,
} ,
event . value . participantStats . participant
)
: "" ;
return ` ${ prefix }
$ { t (
"Are you sure you want to delete this event? This action cannot be reverted."
) }
< br > < br >
$ { t ( 'To confirm, type your event title "{eventTitle}"' , {
eventTitle : event . value ? . title ,
} ) } ` ;
} ) ;
const { mutate : deleteEvent } = useDeleteEvent ( ) ;
const openDeleteEventModal = async (
event : IEvent | undefined
) : Promise < void > => {
function escapeRegExp ( string : string ) {
return string . replace ( /[.*+?^${}()|[\]\\]/g , "\\$&" ) ; // $& means the whole matched string
2019-09-26 16:38:58 +02:00
}
2022-07-12 10:55:28 +02:00
} ;
const notifier = inject < Notifier > ( "notifier" ) ;
const reportEvent = async (
content : string ,
forward : boolean
) : Promise < void > => {
isReportModalActive . value = false ;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
reportModal . value . close ( ) ;
if ( ! organizer . value ) return ;
const { mutate , onDone , onError } = useCreateReport ( ) ;
mutate ( {
eventId : event . value ? . id ? ? "" ,
reportedId : organizer . value ? . id ? ? "" ,
content ,
forward ,
} ) ;
onDone ( ( ) => {
notifier ? . success ( t ( "Event {eventTitle} reported" , { eventTitle } ) ) ;
} ) ;
onError ( ( error ) => {
console . error ( error ) ;
} ) ;
} ;
const joinEventWithConfirmation = ( actor : IPerson ) : void => {
isJoinConfirmationModalActive . value = true ;
actorForConfirmation . value = actor ;
} ;
const {
mutate : joinEventMutation ,
onDone : onJoinEventMutationDone ,
onError : onJoinEventMutationError ,
} = useMutation < {
joinEvent : IParticipant ;
} > ( JOIN _EVENT , ( ) => ( {
update : (
store : ApolloCache < {
joinEvent : IParticipant ;
} > ,
{ data } : FetchResult
) => {
if ( data == null ) return ;
const participationCachedData = store . readQuery < { person : IPerson } > ( {
query : EVENT _PERSON _PARTICIPATION ,
variables : { eventId : event . value ? . id , actorId : identity . value . id } ,
} ) ;
2019-01-21 15:08:22 +01:00
2022-07-12 10:55:28 +02:00
if ( participationCachedData ? . person == undefined ) {
console . error (
"Cannot update participation cache, because of null value."
2020-11-30 10:24:11 +01:00
) ;
2022-07-12 10:55:28 +02:00
return ;
2019-09-09 09:31:08 +02:00
}
2022-07-12 10:55:28 +02:00
store . writeQuery ( {
query : EVENT _PERSON _PARTICIPATION ,
variables : { eventId : event . value ? . id , actorId : identity . value . id } ,
data : {
person : {
... participationCachedData ? . person ,
participations : {
elements : [ data . joinEvent ] ,
total : 1 ,
} ,
2019-03-22 10:57:14 +01:00
} ,
2019-12-20 13:04:34 +01:00
} ,
2019-09-11 09:59:01 +02:00
} ) ;
2022-07-12 10:55:28 +02:00
const cachedData = store . readQuery < { event : IEvent } > ( {
query : FETCH _EVENT ,
variables : { uuid : event . value ? . uuid } ,
} ) ;
if ( cachedData == null ) return ;
const { event : cachedEvent } = cachedData ;
if ( cachedEvent === null ) {
console . error (
"Cannot update event participant cache, because of null value."
) ;
return ;
2019-12-03 11:29:51 +01:00
}
2022-07-12 10:55:28 +02:00
const participantStats = { ... cachedEvent . participantStats } ;
2019-12-03 11:29:51 +01:00
2022-07-12 10:55:28 +02:00
if ( data . joinEvent . role === ParticipantRole . NOT _APPROVED ) {
participantStats . notApproved += 1 ;
2020-06-05 15:20:53 +02:00
} else {
2022-07-12 10:55:28 +02:00
participantStats . going += 1 ;
participantStats . participant += 1 ;
2020-06-05 15:20:53 +02:00
}
2022-07-12 10:55:28 +02:00
store . writeQuery ( {
query : FETCH _EVENT ,
variables : { uuid : props . uuid } ,
data : {
event : {
... cachedEvent ,
participantStats ,
} ,
} ,
} ) ;
} ,
} ) ) ;
const joinEvent = async (
identity : IPerson ,
message : string | null = null
) : Promise < void > => {
isJoinConfirmationModalActive . value = false ;
isJoinModalActive . value = false ;
joinEventMutation ( {
eventId : event . value ? . id ,
actorId : identity ? . id ,
message ,
} ) ;
} ;
onJoinEventMutationDone ( ( { data } ) => {
if ( data ) {
if ( data . joinEvent . role === ParticipantRole . NOT _APPROVED ) {
participationRequestedMessage ( ) ;
} else {
participationConfirmedMessage ( ) ;
2019-10-02 19:14:39 +02:00
}
}
2022-07-12 10:55:28 +02:00
} ) ;
2019-10-02 19:14:39 +02:00
2022-07-12 10:55:28 +02:00
onJoinEventMutationError ( ( error ) => {
console . error ( error ) ;
} ) ;
2021-07-26 17:15:40 +02:00
2022-07-12 10:55:28 +02:00
const dialog = inject < Dialog > ( "dialog" ) ;
2019-10-02 17:59:07 +02:00
2022-07-12 10:55:28 +02:00
const confirmLeave = ( ) : void => {
dialog ? . confirm ( {
title : t ( 'Leaving event "{title}"' , {
title : event . value ? . title ,
} ) ,
message : t (
'Are you sure you want to cancel your participation at event "{title}"?' ,
{
title : event . value ? . title ,
}
) ,
confirmText : t ( "Leave event" ) ,
cancelText : t ( "Cancel" ) ,
type : "danger" ,
hasIcon : true ,
onConfirm : ( ) => {
if ( currentActor . value ? . id ) {
leaveEvent ( event . value , currentActor . value . id ) ;
}
} ,
} ) ;
} ;
2019-10-11 15:06:58 +02:00
2022-07-12 10:55:28 +02:00
watch ( participations , ( ) => {
if ( participations . value . length > 0 ) {
if (
oldParticipationRole . value &&
participations . value [ 0 ] . role !== ParticipantRole . NOT _APPROVED &&
oldParticipationRole . value !== participations . value [ 0 ] . role
) {
switch ( participations . value [ 0 ] . role ) {
case ParticipantRole . PARTICIPANT :
participationConfirmedMessage ( ) ;
break ;
case ParticipantRole . REJECTED :
participationRejectedMessage ( ) ;
break ;
default :
participationChangedMessage ( ) ;
break ;
}
}
oldParticipationRole . value = participations . value [ 0 ] . role ;
2019-10-11 15:06:58 +02:00
}
2022-07-12 10:55:28 +02:00
} ) ;
const participationConfirmedMessage = ( ) => {
notifier ? . success ( t ( "Your participation has been confirmed" ) ) ;
} ;
const participationRequestedMessage = ( ) => {
notifier ? . success ( t ( "Your participation has been requested" ) ) ;
} ;
const participationRejectedMessage = ( ) => {
notifier ? . error ( t ( "Your participation has been rejected" ) ) ;
} ;
const participationChangedMessage = ( ) => {
notifier ? . info ( t ( "Your participation status has been changed" ) ) ;
} ;
const downloadIcsEvent = async ( ) : Promise < void > => {
const data = await (
await fetch ( ` ${ GRAPHQL _API _ENDPOINT } /events/ ${ props . uuid } /export/ics ` )
) . text ( ) ;
const blob = new Blob ( [ data ] , { type : "text/calendar" } ) ;
const link = document . createElement ( "a" ) ;
link . href = window . URL . createObjectURL ( blob ) ;
link . download = ` ${ event . value ? . title } .ics ` ;
document . body . appendChild ( link ) ;
link . click ( ) ;
document . body . removeChild ( link ) ;
} ;
const triggerShare = ( ) : void => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore-start
if ( navigator . share ) {
navigator
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
. share ( {
title : event . value ? . title ,
url : event . value ? . url ,
} )
. then ( ( ) => console . log ( "Successful share" ) )
. catch ( ( error : any ) => console . log ( "Error sharing" , error ) ) ;
} else {
isShareModalActive . value = true ;
// send popup
2019-12-20 13:04:34 +01:00
}
2022-07-12 10:55:28 +02:00
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore-end
} ;
const handleErrors = ( errors : any [ ] ) : void => {
if (
errors . some ( ( error ) => error . status _code === 404 ) ||
errors . some ( ( { message } ) => message . includes ( "has invalid value $uuid" ) )
) {
router . replace ( { name : RouteName . PAGE _NOT _FOUND } ) ;
2019-12-20 13:04:34 +01:00
}
2022-07-12 10:55:28 +02:00
} ;
onFetchEventError ( ( { graphQlErrors } ) => handleErrors ( graphQLErrors ) ) ;
const actorIsParticipant = computed ( ( ) : boolean => {
if ( actorIsOrganizer . value ) return true ;
return (
participations . value . length > 0 &&
participations . value [ 0 ] . role === ParticipantRole . PARTICIPANT
) ;
} ) ;
const actorIsOrganizer = computed ( ( ) : boolean => {
return (
participations . value . length > 0 &&
participations . value [ 0 ] . role === ParticipantRole . CREATOR
) ;
} ) ;
const hasGroupPrivileges = computed ( ( ) : boolean => {
return (
person . value ? . memberships !== undefined &&
person . value ? . memberships ? . total > 0 &&
[ MemberRole . MODERATOR , MemberRole . ADMINISTRATOR ] . includes (
person . value ? . memberships ? . elements [ 0 ] . role
)
) ;
} ) ;
const canManageEvent = computed ( ( ) : boolean => {
return actorIsOrganizer . value || hasGroupPrivileges . value ;
} ) ;
const endDate = computed ( ( ) : Date | undefined => {
return event . value ? . endsOn && event . value . endsOn > event . value . beginsOn
? event . value . endsOn
: event . value ? . beginsOn ;
} ) ;
const maximumAttendeeCapacity = computed ( ( ) : number | undefined => {
return event . value ? . options ? . maximumAttendeeCapacity ;
} ) ;
const eventCapacityOK = computed ( ( ) : boolean => {
if ( event . value ? . draft ) return true ;
if ( ! maximumAttendeeCapacity . value ) return true ;
return (
event . value ? . options ? . maximumAttendeeCapacity !== undefined &&
event . value . participantStats . participant !== undefined &&
event . value ? . options ? . maximumAttendeeCapacity >
event . value . participantStats . participant
) ;
} ) ;
const numberOfPlacesStillAvailable = computed ( ( ) : number | undefined => {
if ( event . value ? . draft ) return maximumAttendeeCapacity . value ;
return (
( maximumAttendeeCapacity . value ? ? 0 ) -
( event . value ? . participantStats . participant ? ? 0 )
) ;
} ) ;
const anonymousParticipationConfirmed = async ( ) : Promise < boolean > => {
return isParticipatingInThisEvent ( props . uuid ) ;
} ;
const cancelAnonymousParticipation = async ( ) : Promise < void > => {
const token = ( await getLeaveTokenForParticipation ( props . uuid ) ) as string ;
await leaveEvent ( event . value , anonymousActorId . value , token ) ;
await removeAnonymousParticipation ( props . uuid ) ;
anonymousParticipation . value = null ;
} ;
const ableToReport = computed ( ( ) : boolean => {
return (
currentActor . value ? . id != null ||
anonymousReportsConfig . value ? . allowed === true
) ;
} ) ;
const organizer = computed ( ( ) : IActor | null => {
if ( event . value ? . attributedTo ? . id ) {
return event . value . attributedTo ;
2020-06-09 14:07:49 +02:00
}
2022-07-12 10:55:28 +02:00
if ( event . value ? . organizerActor ) {
return event . value . organizerActor ;
2021-08-09 14:26:11 +02:00
}
2022-07-12 10:55:28 +02:00
return null ;
} ) ;
const organizerDomain = computed ( ( ) : string | undefined => {
return organizer . value ? . domain ? ? undefined ;
} ) ;
const metadataToComponent : Record < string , string > = {
"mz:live:twitch:url" : "IntegrationTwitch" ,
"mz:live:peertube:url" : "IntegrationPeertube" ,
"mz:live:youtube:url" : "IntegrationYoutube" ,
"mz:visio:jitsi_meet" : "IntegrationJitsiMeet" ,
"mz:notes:etherpad:url" : "IntegrationEtherpad" ,
} ;
const integrations = computed ( ( ) : Record < string , IEventMetadataDescription > => {
return ( event . value ? . metadata ? ? [ ] )
. map ( ( val ) => {
const def = eventMetaDataList . find ( ( dat ) => dat . key === val . key ) ;
return {
... def ,
... val ,
} ;
} )
. reduce ( ( acc : Record < string , IEventMetadataDescription > , metadata ) => {
const component = metadataToComponent [ metadata . key ] ;
if ( component !== undefined ) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
acc [ component ] = metadata ;
}
return acc ;
} , { } ) ;
} ) ;
2021-10-10 16:25:50 +02:00
2022-07-12 10:55:28 +02:00
const showMap = ref ( false ) ;
2021-10-10 16:25:50 +02:00
2022-07-12 10:55:28 +02:00
const routingType = computed ( ( ) : string | undefined => {
return config . value ? . maps ? . routing ? . type ;
} ) ;
2022-03-28 17:42:59 +02:00
2022-07-12 10:55:28 +02:00
const eventCategory = computed ( ( ) : string | undefined => {
if ( event . value ? . category === "MEETING" ) {
return undefined ;
2022-03-28 17:42:59 +02:00
}
2022-07-12 10:55:28 +02:00
return ( eventCategories . value ? ? [ ] ) . find ( ( eventCategory ) => {
return eventCategory . id === event . value ? . category ;
} ) ? . label as string ;
} ) ;
2019-01-21 15:08:22 +01:00
< / script >
2019-04-03 17:29:03 +02:00
< style lang = "scss" scoped >
2021-11-04 18:14:36 +01:00
@ use "@/styles/_mixins" as * ;
2020-02-18 08:57:00 +01:00
. section {
2020-06-17 15:54:24 +02:00
padding : 1 rem 2 rem 4 rem ;
2020-02-18 08:57:00 +01:00
}
. fade - enter - active ,
. fade - leave - active {
transition : opacity 0.5 s ;
}
. fade - enter ,
. fade - leave - to {
opacity : 0 ;
}
div . sidebar {
display : flex ;
flex - wrap : wrap ;
flex - direction : column ;
position : relative ;
& : : before {
content : "" ;
background : # b3b3b2 ;
position : absolute ;
bottom : 30 px ;
top : 30 px ;
left : 0 ;
height : calc ( 100 % - 60 px ) ;
width : 1 px ;
2019-12-20 13:04:34 +01:00
}
2020-02-18 08:57:00 +01:00
div . organizer {
display : inline - flex ;
padding - top : 10 px ;
a {
color : # 4 a4a4a ;
span {
line - height : 2.7 rem ;
2021-11-04 18:14:36 +01:00
@ include padding - right ( 6 px ) ;
2020-02-18 08:57:00 +01:00
}
}
2019-10-08 22:27:14 +02:00
}
2020-02-18 08:57:00 +01:00
}
2021-06-10 10:33:16 +02:00
. intro {
2022-07-12 10:55:28 +02:00
// background: white;
2020-02-18 08:57:00 +01:00
2021-04-13 16:58:41 +02:00
. is - 3 - tablet {
width : initial ;
}
2020-02-18 08:57:00 +01:00
p . tags {
2020-06-17 15:54:24 +02:00
a {
text - decoration : none ;
}
2020-12-17 11:26:25 +01:00
2020-02-18 08:57:00 +01:00
span {
& . tag {
margin : 0 2 px ;
}
}
2019-10-08 22:27:14 +02:00
}
2020-02-18 08:57:00 +01:00
}
. event - description - wrapper {
padding : 0 ;
2019-10-08 22:27:14 +02:00
2020-02-18 08:57:00 +01:00
aside . event - metadata {
min - width : 20 rem ;
flex : 1 ;
. sticky {
2022-07-12 10:55:28 +02:00
// position: sticky;
// background: white;
2020-02-18 08:57:00 +01:00
top : 50 px ;
2021-06-14 16:14:17 +02:00
padding : 1 rem ;
2019-04-03 17:29:03 +02:00
}
2021-04-26 17:27:27 +02:00
}
2020-02-18 08:57:00 +01:00
div . event - description - comments {
min - width : 20 rem ;
padding : 1 rem ;
flex : 2 ;
2022-07-12 10:55:28 +02:00
// background: white;
2020-02-18 08:57:00 +01:00
}
2019-04-03 17:29:03 +02:00
2020-02-18 08:57:00 +01:00
. description - content {
2022-07-12 10:55:28 +02:00
: deep ( h1 ) {
2020-02-18 08:57:00 +01:00
font - size : 2 rem ;
2019-10-11 15:06:58 +02:00
}
2019-04-03 17:29:03 +02:00
2022-07-12 10:55:28 +02:00
: deep ( h2 ) {
2020-02-18 08:57:00 +01:00
font - size : 1.5 rem ;
2019-04-03 17:29:03 +02:00
}
2022-07-12 10:55:28 +02:00
: deep ( h3 ) {
2020-02-18 08:57:00 +01:00
font - size : 1.25 rem ;
}
2019-04-03 17:29:03 +02:00
2022-07-12 10:55:28 +02:00
: deep ( ul ) {
2020-02-18 08:57:00 +01:00
list - style - type : disc ;
2019-04-03 17:29:03 +02:00
}
2022-07-12 10:55:28 +02:00
: deep ( li ) {
2020-02-18 08:57:00 +01:00
margin : 10 px auto 10 px 2 rem ;
}
2019-04-03 17:29:03 +02:00
2022-07-12 10:55:28 +02:00
: deep ( blockquote ) {
2020-02-18 08:57:00 +01:00
border - left : 0.2 em solid # 333 ;
display : block ;
2021-11-04 18:14:36 +01:00
@ include padding - left ( 1 rem ) ;
2020-02-18 08:57:00 +01:00
}
2019-04-03 17:29:03 +02:00
2022-07-12 10:55:28 +02:00
: deep ( p ) {
2020-02-18 08:57:00 +01:00
margin : 10 px auto ;
2019-04-03 17:29:03 +02:00
2020-02-18 08:57:00 +01:00
a {
display : inline - block ;
2019-04-03 17:29:03 +02:00
padding : 0.3 rem ;
2020-02-18 08:57:00 +01:00
color : # 111 ;
2019-04-03 17:29:03 +02:00
2020-02-18 08:57:00 +01:00
& : empty {
display : none ;
2019-04-03 17:29:03 +02:00
}
}
}
}
2020-02-18 08:57:00 +01:00
}
2019-04-03 17:29:03 +02:00
2020-02-18 08:57:00 +01:00
. comments {
padding - top : 3 rem ;
2019-04-03 17:29:03 +02:00
2020-02-18 08:57:00 +01:00
a h3 # comments {
margin - bottom : 10 px ;
2019-04-03 17:29:03 +02:00
}
2020-02-18 08:57:00 +01:00
}
2019-04-03 17:29:03 +02:00
2020-02-18 08:57:00 +01:00
. more - events {
2022-07-12 10:55:28 +02:00
// background: white;
2021-06-14 16:14:17 +02:00
padding : 1 rem 1 rem 4 rem ;
& > . title {
font - size : 1.5 rem ;
}
2020-02-18 08:57:00 +01:00
}
2022-07-12 10:55:28 +02:00
// .dropdown .dropdown-trigger span {
// cursor: pointer;
// }
2020-02-18 08:57:00 +01:00
2022-07-12 10:55:28 +02:00
// a.dropdown-item,
// .dropdown .dropdown-menu .has-link a,
// button.dropdown-item {
// white-space: nowrap;
// width: 100%;
// @include padding-right(1rem);
// text-align: right;
// }
2020-06-17 15:54:24 +02:00
a . participations - link {
text - decoration : none ;
}
. event - status . tag {
font - size : 1 rem ;
}
2020-07-07 10:54:10 +02:00
2020-12-17 11:26:25 +01:00
. no - border {
border : 0 ;
cursor : auto ;
2020-07-07 10:54:10 +02:00
}
2021-06-10 10:05:47 +02:00
. wrapper ,
. intro - wrapper {
display : flex ;
flex - direction : column ;
}
. intro - wrapper {
position : relative ;
padding : 0 16 px 16 px ;
2022-07-12 10:55:28 +02:00
// background: #fff;
2021-06-10 10:05:47 +02:00
. date - calendar - icon - wrapper {
margin - top : 16 px ;
height : 0 ;
display : flex ;
align - items : flex - end ;
align - self : flex - start ;
margin - bottom : 7 px ;
2021-11-04 18:14:36 +01:00
@ include margin - left ( 0 ) ;
2021-06-10 10:05:47 +02:00
}
}
. title {
margin : 0 ;
font - size : 2 rem ;
}
2019-03-22 17:35:07 +01:00
< / style >