diff --git a/js/src/components/Event/GroupedMultiEventMinimalistCard.vue b/js/src/components/Event/GroupedMultiEventMinimalistCard.vue index bdb173b5f..c2b6d31da 100644 --- a/js/src/components/Event/GroupedMultiEventMinimalistCard.vue +++ b/js/src/components/Event/GroupedMultiEventMinimalistCard.vue @@ -22,8 +22,9 @@ const props = withDefaults( defineProps<{ events: IEvent[]; isCurrentActorMember?: boolean; + order: "ASC" | "DESC"; }>(), - { isCurrentActorMember: false } + { isCurrentActorMember: false, order: "ASC" } ); const monthlyGroupedEvents = computed((): Map => { @@ -48,7 +49,9 @@ const keys = computed((): string[] => { number ]; const bDate = new Date(...bParams); - return bDate.getTime() - aDate.getTime(); + return props.order === "DESC" + ? bDate.getTime() - aDate.getTime() + : aDate.getTime() - bDate.getTime(); }); }); diff --git a/js/src/graphql/event.ts b/js/src/graphql/event.ts index a7c41edcd..c0e1e9043 100644 --- a/js/src/graphql/event.ts +++ b/js/src/graphql/event.ts @@ -424,6 +424,8 @@ export const FETCH_GROUP_EVENTS = gql` $name: String! $afterDateTime: DateTime $beforeDateTime: DateTime + $order: EventOrderBy + $orderDirection: SortDirection $organisedEventsPage: Int $organisedEventsLimit: Int ) { @@ -431,6 +433,8 @@ export const FETCH_GROUP_EVENTS = gql` organizedEvents( afterDatetime: $afterDateTime beforeDatetime: $beforeDateTime + order: $order + orderDirection: $orderDirection page: $organisedEventsPage limit: $organisedEventsLimit ) { diff --git a/js/src/views/Event/GroupEvents.vue b/js/src/views/Event/GroupEvents.vue index 56f7da3ec..1ab7e90ef 100644 --- a/js/src/views/Event/GroupEvents.vue +++ b/js/src/views/Event/GroupEvents.vue @@ -48,8 +48,10 @@ t("Past events") }} EVENTS_PAGE_LIMIT" class="mt-4" :total="group.organizedEvents.total" v-model:current="page" @@ -150,6 +153,8 @@ const variables = computed(() => ({ name: route.params.preferredUsername as string, beforeDateTime: showPassedEvents.value ? new Date() : null, afterDateTime: showPassedEvents.value ? null : new Date(), + order: "BEGINS_ON", + orderDirection: showPassedEvents.value ? "DESC" : "ASC", organisedEventsPage: page.value, organisedEventsLimit: EVENTS_PAGE_LIMIT, })); diff --git a/js/src/views/Event/MyEventsView.vue b/js/src/views/Event/MyEventsView.vue index 7d44892c4..211c506ba 100644 --- a/js/src/views/Event/MyEventsView.vue +++ b/js/src/views/Event/MyEventsView.vue @@ -431,8 +431,8 @@ const eventDeleted = (eventid: string): void => { }), }); if (!upcomingEventsData) return; - let loggedUser = upcomingEventsData?.loggedUser; - let participations = loggedUser?.participations; + const loggedUser = upcomingEventsData?.loggedUser; + const participations = loggedUser?.participations; apollo.client.cache.writeQuery<{ loggedUser: IUser }>({ query: LOGGED_USER_UPCOMING_EVENTS, variables: () => ({ diff --git a/lib/graphql/resolvers/group.ex b/lib/graphql/resolvers/group.ex index d906835e8..0b556b5d8 100644 --- a/lib/graphql/resolvers/group.ex +++ b/lib/graphql/resolvers/group.ex @@ -431,13 +431,15 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do {:error, dgettext("errors", "You need to be logged-in to unfollow a group")} end - @spec find_events_for_group(Actor.t(), map(), Absinthe.Resolution.t()) :: + @spec find_events_for_group(Actor.t(), map(), Absinthe.Resolution.t() | nil) :: {:ok, Page.t(Event.t())} def find_events_for_group( %Actor{id: group_id} = group, %{ page: page, - limit: limit + limit: limit, + order: order, + order_direction: order_direction } = args, %{ context: %{ @@ -453,6 +455,8 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do :all, Map.get(args, :after_datetime), Map.get(args, :before_datetime), + order, + order_direction, page, limit )} @@ -465,7 +469,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do %Actor{} = group, %{ page: page, - limit: limit + limit: limit, + order: order, + order_direction: order_direction } = args, _resolution ) do @@ -475,6 +481,8 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do :public, Map.get(args, :after_datetime), Map.get(args, :before_datetime), + order, + order_direction, page, limit )} diff --git a/lib/graphql/schema/actors/group.ex b/lib/graphql/schema/actors/group.ex index adfe41afe..518271121 100644 --- a/lib/graphql/schema/actors/group.ex +++ b/lib/graphql/schema/actors/group.ex @@ -91,6 +91,16 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do description: "Filter events that begin before this datetime" ) + arg(:order, :event_order_by, + default_value: :begins_on, + description: "Order events by start date" + ) + + arg(:order_direction, :sort_direction, + default_value: :asc, + description: "Order events direction" + ) + arg(:page, :integer, default_value: 1, description: "The page in the paginated event list") arg(:limit, :integer, default_value: 10, description: "The limit of events per page") resolve(&Group.find_events_for_group/3) diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex index 900b56203..2bd227adc 100644 --- a/lib/mobilizon/events/events.ex +++ b/lib/mobilizon/events/events.ex @@ -415,7 +415,7 @@ defmodule Mobilizon.Events do def list_public_events_for_actor(actor, page \\ nil, limit \\ nil) def list_public_events_for_actor(%Actor{type: :Group} = group, page, limit), - do: list_organized_events_for_group(group, :public, nil, nil, page, limit) + do: list_organized_events_for_group(group, :public, nil, nil, nil, nil, page, limit) def list_public_events_for_actor(%Actor{id: actor_id}, page, limit) do actor_id @@ -431,7 +431,17 @@ defmodule Mobilizon.Events do def list_public_upcoming_events_for_actor(actor, page \\ nil, limit \\ nil) def list_public_upcoming_events_for_actor(%Actor{type: :Group} = group, page, limit), - do: list_organized_events_for_group(group, :public, DateTime.utc_now(), nil, page, limit) + do: + list_organized_events_for_group( + group, + :public, + DateTime.utc_now(), + nil, + nil, + nil, + page, + limit + ) def list_public_upcoming_events_for_actor(%Actor{id: actor_id}, page, limit) do actor_id @@ -461,14 +471,16 @@ defmodule Mobilizon.Events do @spec list_simple_organized_events_for_group(Actor.t(), integer | nil, integer | nil) :: Page.t(Event.t()) def list_simple_organized_events_for_group(%Actor{} = actor, page \\ nil, limit \\ nil) do - list_organized_events_for_group(actor, :all, nil, nil, page, limit) + list_organized_events_for_group(actor, :all, nil, nil, nil, nil, page, limit) end @spec list_organized_events_for_group( Actor.t(), - atom(), + :public | :all, DateTime.t() | nil, DateTime.t() | nil, + atom() | nil, + atom() | nil, integer | nil, integer | nil ) :: Page.t(Event.t()) @@ -477,6 +489,8 @@ defmodule Mobilizon.Events do visibility \\ :public, after_datetime \\ nil, before_datetime \\ nil, + order_by \\ nil, + order_direction \\ nil, page \\ nil, limit \\ nil ) do @@ -484,6 +498,7 @@ defmodule Mobilizon.Events do |> event_for_group_query() |> event_filter_visibility(visibility) |> event_filter_begins_on(after_datetime, before_datetime) + |> event_order_by(order_by, order_direction) |> preload_for_event() |> Page.build_page(page, limit) end @@ -1245,11 +1260,7 @@ defmodule Mobilizon.Events do @spec event_for_group_query(integer | String.t()) :: Ecto.Query.t() defp event_for_group_query(group_id) do - from( - e in Event, - where: e.attributed_to_id == ^group_id, - order_by: [asc: :begins_on] - ) + where(Event, [e], e.attributed_to_id == ^group_id) end @spec upcoming_public_event_for_actor_query(integer | String.t()) :: Ecto.Query.t() @@ -1909,19 +1920,14 @@ defmodule Mobilizon.Events do where(query, visibility: ^:public, draft: false) end - defp event_filter_begins_on(query, nil, nil), - do: event_order_begins_on_desc(query) + defp event_filter_begins_on(query, nil, nil), do: query defp event_filter_begins_on(query, %DateTime{} = after_datetime, nil) do - query - |> where([e], e.begins_on > ^after_datetime) - |> event_order_begins_on_asc() + where(query, [e], e.begins_on > ^after_datetime) end defp event_filter_begins_on(query, nil, %DateTime{} = before_datetime) do - query - |> where([e], e.begins_on < ^before_datetime) - |> event_order_begins_on_desc() + where(query, [e], e.begins_on < ^before_datetime) end defp event_filter_begins_on( @@ -1932,9 +1938,16 @@ defmodule Mobilizon.Events do query |> where([e], e.begins_on < ^before_datetime) |> where([e], e.begins_on > ^after_datetime) - |> event_order_begins_on_asc() end + defp event_order_by(query, order_by, direction) + when order_by in [:begins_on, :inserted_at, :updated_at] and direction in [:asc, :desc] do + order_by_instruction = Keyword.new([{direction, order_by}]) + order_by(query, [e], ^order_by_instruction) + end + + defp event_order_by(query, _order_by, _direction), do: event_order_by(query, :begins_on, :asc) + defp event_order(query, :match_desc), do: order_by(query, [e, f], desc: f.rank, asc: e.begins_on) @@ -1947,12 +1960,6 @@ defmodule Mobilizon.Events do defp event_order(query, _), do: query - defp event_order_begins_on_asc(query), - do: order_by(query, [e], asc: e.begins_on) - - defp event_order_begins_on_desc(query), - do: order_by(query, [e], desc: e.begins_on) - defp participation_filter_begins_on(query, nil, nil), do: participation_order_begins_on_desc(query)