Show related events

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2019-04-12 17:00:55 +02:00
parent 5ee97dfa43
commit f241251b24
8 changed files with 89 additions and 42 deletions

View File

@ -43,6 +43,7 @@ export const FETCH_EVENT = gql`
organizerActor { organizerActor {
avatarUrl, avatarUrl,
preferredUsername, preferredUsername,
domain,
name, name,
}, },
# attributedTo { # attributedTo {
@ -56,6 +57,20 @@ export const FETCH_EVENT = gql`
tags { tags {
slug, slug,
title title
},
relatedEvents {
uuid,
title,
beginsOn,
physicalAddress {
description
},
organizerActor {
avatarUrl,
preferredUsername,
domain,
name,
}
} }
} }
} }

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: mobilizon 0.1.0\n" "Project-Id-Version: mobilizon 0.1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-04-10 16:31+0200\n" "POT-Creation-Date: 2019-04-12 16:47+0200\n"
"PO-Revision-Date: 2019-04-08 20:58+0200\n" "PO-Revision-Date: 2019-04-08 20:58+0200\n"
"Last-Translator: Automatically generated\n" "Last-Translator: Automatically generated\n"
"Language-Team: none\n" "Language-Team: none\n"
@ -29,7 +29,7 @@ msgstr "A validation email was sent to %{email}"
msgid "About" msgid "About"
msgstr "About" msgstr "About"
#: src/views/Event/Event.vue:138 #: src/views/Event/Event.vue:137
msgid "About this event" msgid "About this event"
msgstr "About this event" msgstr "About this event"
@ -41,7 +41,7 @@ msgstr "About this instance"
msgid "Add a new profile" msgid "Add a new profile"
msgstr "Add a new profile" msgstr "Add a new profile"
#: src/views/Event/Event.vue:44 src/views/Event/Event.vue:217 #: src/views/Event/Event.vue:44 src/views/Event/Event.vue:216
msgid "Add to my calendar" msgid "Add to my calendar"
msgstr "Add to my calendar" msgstr "Add to my calendar"
@ -53,7 +53,7 @@ msgstr "Are you going to this event?"
msgid "Before you can login, you need to click on the link inside it to validate your account" msgid "Before you can login, you need to click on the link inside it to validate your account"
msgstr "Before you can login, you need to click on the link inside it to validate your account" msgstr "Before you can login, you need to click on the link inside it to validate your account"
#: src/views/Event/Event.vue:101 #: src/views/Event/Event.vue:100
msgid "By %{ name }" msgid "By %{ name }"
msgstr "By %{ name }" msgstr "By %{ name }"
@ -93,7 +93,7 @@ msgstr "Create your communities and your events"
msgid "Current" msgid "Current"
msgstr "Current" msgstr "Current"
#: src/views/Account/Profile.vue:93 src/views/Event/Event.vue:64 #: src/views/Account/Profile.vue:93 src/views/Event/Event.vue:63
msgid "Delete" msgid "Delete"
msgstr "Delete" msgstr "Delete"
@ -101,7 +101,7 @@ msgstr "Delete"
msgid "Didn't receive the instructions ?" msgid "Didn't receive the instructions ?"
msgstr "Didn't receive the instructions ?" msgstr "Didn't receive the instructions ?"
#: src/views/Event/Event.vue:59 #: src/views/Event/Event.vue:58
msgid "Edit" msgid "Edit"
msgstr "Edit" msgstr "Edit"
@ -205,7 +205,7 @@ msgstr "Members"
msgid "My account" msgid "My account"
msgstr "My account" msgstr "My account"
#: src/views/Event/Event.vue:70 #: src/views/Event/Event.vue:69
msgid "No address defined" msgid "No address defined"
msgstr "No address defined" msgstr "No address defined"
@ -304,7 +304,7 @@ msgstr "Reset my password"
msgid "RSS/Atom Feed" msgid "RSS/Atom Feed"
msgstr "RSS/Atom Feed" msgstr "RSS/Atom Feed"
#: src/views/PageNotFound.vue:18 src/components/SearchField.vue:19 #: src/views/PageNotFound.vue:19 src/components/SearchField.vue:19
msgid "Search" msgid "Search"
msgstr "Search" msgstr "Search"
@ -320,11 +320,11 @@ msgstr "Send confirmation email again"
msgid "Send email to reset my password" msgid "Send email to reset my password"
msgstr "Send email to reset my password" msgstr "Send email to reset my password"
#: src/views/Event/Event.vue:206 #: src/views/Event/Event.vue:205
msgid "Share this event" msgid "Share this event"
msgstr "Share this event" msgstr "Share this event"
#: src/views/Event/Event.vue:79 #: src/views/Event/Event.vue:78
msgid "Show map" msgid "Show map"
msgstr "Show map" msgstr "Show map"
@ -340,7 +340,7 @@ msgstr "The %{ date } at %{ time }"
msgid "The %{ date } from %{ startTime } to %{ endTime }" msgid "The %{ date } from %{ startTime } to %{ endTime }"
msgstr "The %{ date } from %{ startTime } to %{ endTime }" msgstr "The %{ date } from %{ startTime } to %{ endTime }"
#: src/views/Event/Event.vue:141 #: src/views/Event/Event.vue:140
msgid "The event organizer didn't add any description." msgid "The event organizer didn't add any description."
msgstr "The event organizer didn't add any description." msgstr "The event organizer didn't add any description."
@ -348,7 +348,7 @@ msgstr "The event organizer didn't add any description."
msgid "The page you're looking for doesn't exist." msgid "The page you're looking for doesn't exist."
msgstr "" msgstr ""
#: src/views/Event/Event.vue:224 #: src/views/Event/Event.vue:223
msgid "These events may interest you" msgid "These events may interest you"
msgstr "These events may interest you" msgstr "These events may interest you"
@ -434,6 +434,6 @@ msgstr "Your local administrator resumed it's policy:"
msgid "World map" msgid "World map"
msgstr "World map" msgstr "World map"
#: src/views/PageNotFound.vue:40 #: src/views/PageNotFound.vue:42
msgid "Search events, groups, etc." msgid "Search events, groups, etc."
msgstr "" msgstr ""

View File

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: mobilizon 0.1.0\n" "Project-Id-Version: mobilizon 0.1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-04-10 16:31+0200\n" "POT-Creation-Date: 2019-04-12 16:47+0200\n"
"PO-Revision-Date: 2019-04-10 16:33+0200\n" "PO-Revision-Date: 2019-04-12 16:45+0200\n"
"Last-Translator: Automatically generated\n" "Last-Translator: Automatically generated\n"
"Language-Team: none\n" "Language-Team: none\n"
"Language: fr_FR\n" "Language: fr_FR\n"
@ -30,7 +30,7 @@ msgstr "Un email de validation a été envoyé à %{email}"
msgid "About" msgid "About"
msgstr "À propos" msgstr "À propos"
#: src/views/Event/Event.vue:138 #: src/views/Event/Event.vue:137
msgid "About this event" msgid "About this event"
msgstr "À propos de cet événement" msgstr "À propos de cet événement"
@ -42,7 +42,7 @@ msgstr "À propos de cette instance"
msgid "Add a new profile" msgid "Add a new profile"
msgstr "Ajouter un nouveau profil" msgstr "Ajouter un nouveau profil"
#: src/views/Event/Event.vue:44 src/views/Event/Event.vue:217 #: src/views/Event/Event.vue:44 src/views/Event/Event.vue:216
msgid "Add to my calendar" msgid "Add to my calendar"
msgstr "Ajouter à mon agenda" msgstr "Ajouter à mon agenda"
@ -54,7 +54,7 @@ msgstr "Allez-vous à cet événement ?"
msgid "Before you can login, you need to click on the link inside it to validate your account" msgid "Before you can login, you need to click on the link inside it to validate your account"
msgstr "Avant que vous puissiez vous enregistrer, vous devez cliquer sur le lien à l'intérieur pour valider votre compte" msgstr "Avant que vous puissiez vous enregistrer, vous devez cliquer sur le lien à l'intérieur pour valider votre compte"
#: src/views/Event/Event.vue:101 #: src/views/Event/Event.vue:100
msgid "By %{ name }" msgid "By %{ name }"
msgstr "Par %{name}" msgstr "Par %{name}"
@ -94,7 +94,7 @@ msgstr "Créer vos communautés et vos événements"
msgid "Current" msgid "Current"
msgstr "Actuel" msgstr "Actuel"
#: src/views/Account/Profile.vue:93 src/views/Event/Event.vue:64 #: src/views/Account/Profile.vue:93 src/views/Event/Event.vue:63
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
@ -102,7 +102,7 @@ msgstr "Supprimer"
msgid "Didn't receive the instructions ?" msgid "Didn't receive the instructions ?"
msgstr "Vous n'avez pas reçu les instructions ?" msgstr "Vous n'avez pas reçu les instructions ?"
#: src/views/Event/Event.vue:59 #: src/views/Event/Event.vue:58
msgid "Edit" msgid "Edit"
msgstr "Éditer" msgstr "Éditer"
@ -206,7 +206,7 @@ msgstr "Membres"
msgid "My account" msgid "My account"
msgstr "Mon compte" msgstr "Mon compte"
#: src/views/Event/Event.vue:70 #: src/views/Event/Event.vue:69
msgid "No address defined" msgid "No address defined"
msgstr "Aucune adresse définie" msgstr "Aucune adresse définie"
@ -305,7 +305,7 @@ msgstr "Réinitialiser mon mot de passe"
msgid "RSS/Atom Feed" msgid "RSS/Atom Feed"
msgstr "Flux RSS/Atom" msgstr "Flux RSS/Atom"
#: src/views/PageNotFound.vue:18 src/components/SearchField.vue:19 #: src/views/PageNotFound.vue:19 src/components/SearchField.vue:19
msgid "Search" msgid "Search"
msgstr "Rechercher" msgstr "Rechercher"
@ -321,11 +321,11 @@ msgstr "Envoyer l'email de confirmation à nouveau"
msgid "Send email to reset my password" msgid "Send email to reset my password"
msgstr "Envoyer un email pour réinitialiser mon mot de passe" msgstr "Envoyer un email pour réinitialiser mon mot de passe"
#: src/views/Event/Event.vue:206 #: src/views/Event/Event.vue:205
msgid "Share this event" msgid "Share this event"
msgstr "Partager cet événement" msgstr "Partager l'événement"
#: src/views/Event/Event.vue:79 #: src/views/Event/Event.vue:78
msgid "Show map" msgid "Show map"
msgstr "Afficher la carte" msgstr "Afficher la carte"
@ -341,7 +341,7 @@ msgstr "Le %{ date } à %{ time }"
msgid "The %{ date } from %{ startTime } to %{ endTime }" msgid "The %{ date } from %{ startTime } to %{ endTime }"
msgstr "Le %{ date } de %{ startTime } à %{ endTime }" msgstr "Le %{ date } de %{ startTime } à %{ endTime }"
#: src/views/Event/Event.vue:141 #: src/views/Event/Event.vue:140
msgid "The event organizer didn't add any description." msgid "The event organizer didn't add any description."
msgstr "L'organisateur de l'événement n'a pas ajouté de description." msgstr "L'organisateur de l'événement n'a pas ajouté de description."
@ -349,7 +349,7 @@ msgstr "L'organisateur de l'événement n'a pas ajouté de description."
msgid "The page you're looking for doesn't exist." msgid "The page you're looking for doesn't exist."
msgstr "La page que vous recherchez n'existe pas." msgstr "La page que vous recherchez n'existe pas."
#: src/views/Event/Event.vue:224 #: src/views/Event/Event.vue:223
msgid "These events may interest you" msgid "These events may interest you"
msgstr "Ces événements peuvent vous intéresser" msgstr "Ces événements peuvent vous intéresser"
@ -435,6 +435,6 @@ msgstr "Votre administrateur local a résumé sa politique ainsi :"
msgid "World map" msgid "World map"
msgstr "Carte mondiale" msgstr "Carte mondiale"
#: src/views/PageNotFound.vue:40 #: src/views/PageNotFound.vue:42
msgid "Search events, groups, etc." msgid "Search events, groups, etc."
msgstr "Rechercher des événements, des groupes, etc." msgstr "Rechercher des événements, des groupes, etc."

File diff suppressed because one or more lines are too long

View File

@ -69,6 +69,8 @@ export interface IEvent {
attributedTo: IActor; attributedTo: IActor;
participants: IParticipant[]; participants: IParticipant[];
relatedEvents: IEvent[];
onlineAddress?: string; onlineAddress?: string;
phoneAddress?: string; phoneAddress?: string;
physicalAddress?: IAddress; physicalAddress?: IAddress;
@ -94,6 +96,7 @@ export class EventModel implements IEvent {
visibility: EventVisibility = EventVisibility.PUBLIC; visibility: EventVisibility = EventVisibility.PUBLIC;
attributedTo: IActor = new Actor(); attributedTo: IActor = new Actor();
organizerActor: IActor = new Actor(); organizerActor: IActor = new Actor();
relatedEvents: IEvent[] = [];
onlineAddress: string = ''; onlineAddress: string = '';
phoneAddress: string = ''; phoneAddress: string = '';
} }

View File

@ -204,12 +204,14 @@
<div class="columns"> <div class="columns">
<div class="column is-half has-text-centered"> <div class="column is-half has-text-centered">
<h3 class="title"><translate>Share this event</translate></h3> <h3 class="title"><translate>Share this event</translate></h3>
<b-icon icon="mastodon" size="is-large" type="is-primary" /> <div>
<a :href="facebookShareUrl" target="_blank" rel="nofollow noopener"><b-icon icon="facebook" size="is-large" type="is-primary" /></a> <b-icon icon="mastodon" size="is-large" type="is-primary" />
<a :href="twitterShareUrl" target="_blank" rel="nofollow noopener"><b-icon icon="twitter" size="is-large" type="is-primary" /></a> <a :href="facebookShareUrl" target="_blank" rel="nofollow noopener"><b-icon icon="facebook" size="is-large" type="is-primary" /></a>
<a :href="emailShareUrl" target="_blank" rel="nofollow noopener"><b-icon icon="email" size="is-large" type="is-primary" /></a> <a :href="twitterShareUrl" target="_blank" rel="nofollow noopener"><b-icon icon="twitter" size="is-large" type="is-primary" /></a>
<!-- TODO: mailto: links are not used anymore, we should provide a popup to redact a message instead --> <a :href="emailShareUrl" target="_blank" rel="nofollow noopener"><b-icon icon="email" size="is-large" type="is-primary" /></a>
<a :href="linkedInShareUrl" target="_blank" rel="nofollow noopener"><b-icon icon="linkedin" size="is-large" type="is-primary" /></a> <!-- TODO: mailto: links are not used anymore, we should provide a popup to redact a message instead -->
<a :href="linkedInShareUrl" target="_blank" rel="nofollow noopener"><b-icon icon="linkedin" size="is-large" type="is-primary" /></a>
</div>
</div> </div>
<hr /> <hr />
<div class="column is-half has-text-right add-to-calendar"> <div class="column is-half has-text-right add-to-calendar">
@ -223,8 +225,8 @@
<section class="more-events container"> <section class="more-events container">
<h3 class="title has-text-centered"><translate>These events may interest you</translate></h3> <h3 class="title has-text-centered"><translate>These events may interest you</translate></h3>
<div class="columns"> <div class="columns">
<div class="column" v-for="index in 3" :key="index"> <div class="column" v-for="relatedEvent in event.relatedEvents" :key="relatedEvent.uuid">
<EventCard :event="event" /> <EventCard :event="relatedEvent" />
</div> </div>
</div> </div>
</section> </section>

View File

@ -57,6 +57,7 @@ defmodule Mobilizon.Events do
e.organizer_actor_id == ^actor_id and e.visibility in [^:public, ^:unlisted] and e.organizer_actor_id == ^actor_id and e.visibility in [^:public, ^:unlisted] and
e.begins_on > ^DateTime.utc_now(), e.begins_on > ^DateTime.utc_now(),
order_by: [asc: :begins_on], order_by: [asc: :begins_on],
limit: 1,
preload: [ preload: [
:organizer_actor, :organizer_actor,
:tags, :tags,
@ -259,18 +260,42 @@ defmodule Mobilizon.Events do
[%Event{}, ...] [%Event{}, ...]
""" """
def list_events(page \\ nil, limit \\ nil) do @spec list_events(integer(), integer(), atom(), atom()) :: list(Event.t())
def list_events(
page \\ nil,
limit \\ nil,
sort \\ :begins_on,
direction \\ :asc,
unlisted \\ false,
future \\ true
) do
query = query =
from( from(
e in Event, e in Event,
where: e.visibility == ^:public,
preload: [:organizer_actor, :participants] preload: [:organizer_actor, :participants]
) )
|> paginate(page, limit) |> paginate(page, limit)
|> sort(sort, direction)
|> restrict_future_events(future)
|> allow_unlisted(unlisted)
Repo.all(query) Repo.all(query)
end end
# Make sure we only show future events
@spec restrict_future_events(Ecto.Query.t(), boolean()) :: Ecto.Query.t()
defp restrict_future_events(query, true),
do: from(q in query, where: q.begins_on > ^DateTime.utc_now())
defp restrict_future_events(query, false), do: query
# Make sure unlisted events don't show up where they're not allowed
@spec allow_unlisted(Ecto.Query.t(), boolean()) :: Ecto.Query.t()
defp allow_unlisted(query, true),
do: from(q in query, where: q.visibility in [^:public, ^:unlisted])
defp allow_unlisted(query, false), do: from(q in query, where: q.visibility == ^:public)
@doc """ @doc """
Find events by name Find events by name
""" """

View File

@ -49,7 +49,7 @@ defmodule MobilizonWeb.Resolvers.Event do
List related events List related events
""" """
def list_related_events( def list_related_events(
%Event{tags: tags, organizer_actor: organizer_actor}, %Event{tags: tags, organizer_actor: organizer_actor, uuid: uuid},
_args, _args,
_resolution _resolution
) do ) do
@ -57,12 +57,13 @@ defmodule MobilizonWeb.Resolvers.Event do
events = events =
[Events.get_actor_upcoming_public_event(organizer_actor, uuid)] |> Enum.filter(&is_map/1) [Events.get_actor_upcoming_public_event(organizer_actor, uuid)] |> Enum.filter(&is_map/1)
# We find similar events with the same tags
# uniq_by : It's possible event_from_same_actor is inside events_from_tags # uniq_by : It's possible event_from_same_actor is inside events_from_tags
events = events =
(events ++ (events ++
Events.find_similar_events_by_common_tags( Events.find_similar_events_by_common_tags(
tags, tags,
@number_of_related_events - length(events) @number_of_related_events
)) ))
|> uniq_events() |> uniq_events()
@ -85,10 +86,11 @@ defmodule MobilizonWeb.Resolvers.Event do
# We return only @number_of_related_events right now # We return only @number_of_related_events right now
|> Enum.take(@number_of_related_events) |> Enum.take(@number_of_related_events)
# TODO: We should use tag_relations to find more events
{:ok, events} {:ok, events}
end end
defp uniq_events(events), do: Enum.uniq_by(events, fn event -> event.uuid end)
@doc """ @doc """
Join an event for an actor Join an event for an actor
""" """