From a4e7ee37bedc63b2193a401c801b3b1298f566d2 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Wed, 26 Apr 2023 16:33:11 +0200 Subject: [PATCH] fix(search): Fix event search order Signed-off-by: Thomas Citharel --- js/src/components/Home/SearchFields.vue | 4 +- js/src/views/SearchView.vue | 7 +- lib/graphql/schema/search.ex | 3 +- lib/mobilizon/events/events.ex | 78 +++++++++++++------ lib/service/global_search/search_mobilizon.ex | 1 + 5 files changed, 65 insertions(+), 28 deletions(-) diff --git a/js/src/components/Home/SearchFields.vue b/js/src/components/Home/SearchFields.vue index 1b3a80454..f4fdc5517 100644 --- a/js/src/components/Home/SearchFields.vue +++ b/js/src/components/Home/SearchFields.vue @@ -39,7 +39,7 @@ import { IAddress } from "@/types/address.model"; import { AddressSearchType } from "@/types/enums"; import { computed, defineAsyncComponent } from "vue"; import { useI18n } from "vue-i18n"; -import { useRouter } from "vue-router"; +import { useRouter, useRoute } from "vue-router"; import RouteName from "@/router/name"; const FullAddressAutoComplete = defineAsyncComponent( @@ -53,6 +53,7 @@ const props = defineProps<{ }>(); const router = useRouter(); +const route = useRoute(); const emit = defineEmits<{ (event: "update:location", location: IAddress | null): void; @@ -89,6 +90,7 @@ const submit = () => { router.push({ name: RouteName.SEARCH, query: { + ...route.query, locationName: location.value?.locality ?? location.value?.region, lat, lon, diff --git a/js/src/views/SearchView.vue b/js/src/views/SearchView.vue index 61354e8df..ad09e1d23 100644 --- a/js/src/views/SearchView.vue +++ b/js/src/views/SearchView.vue @@ -818,6 +818,7 @@ enum ViewMode { enum EventSortValues { MATCH_DESC = "MATCH_DESC", + START_TIME_ASC = "START_TIME_ASC", START_TIME_DESC = "START_TIME_DESC", CREATED_AT_DESC = "CREATED_AT_DESC", CREATED_AT_ASC = "CREATED_AT_ASC", @@ -831,6 +832,7 @@ enum GroupSortValues { enum SortValues { MATCH_DESC = "MATCH_DESC", + START_TIME_ASC = "START_TIME_ASC", START_TIME_DESC = "START_TIME_DESC", CREATED_AT_DESC = "CREATED_AT_DESC", CREATED_AT_ASC = "CREATED_AT_ASC", @@ -1157,7 +1159,7 @@ const sortOptions = computed(() => { if (contentType.value == ContentType.EVENTS) { options.push( { - key: SortValues.START_TIME_DESC, + key: SortValues.START_TIME_ASC, label: t("Event date"), }, { @@ -1239,6 +1241,9 @@ const sortByForType = ( value: SortValues, allowed: typeof EventSortValues | typeof GroupSortValues ): SortValues | undefined => { + if (value === SortValues.START_TIME_ASC && when.value === "past") { + value = SortValues.START_TIME_DESC; + } return Object.values(allowed).includes(value) ? value : undefined; }; diff --git a/lib/graphql/schema/search.ex b/lib/graphql/schema/search.ex index 57d355ac4..8f75c5e91 100644 --- a/lib/graphql/schema/search.ex +++ b/lib/graphql/schema/search.ex @@ -174,7 +174,8 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do enum :search_event_sort_options do value(:match_desc, description: "The pertinence of the result") - value(:start_time_desc, description: "The start date of the result") + value(:start_time_asc, description: "The start date of the result, ordered ascending") + value(:start_time_desc, description: "The start date of the result, ordered descending") value(:created_at_desc, description: "When the event was published") value(:created_at_asc, description: "When the event was published") value(:participant_count_desc, description: "With the most participants") diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex index 2bd227adc..b10a673fa 100644 --- a/lib/mobilizon/events/events.ex +++ b/lib/mobilizon/events/events.ex @@ -562,11 +562,12 @@ defmodule Mobilizon.Events do """ @spec build_events_for_search(map(), integer | nil, integer | nil) :: Page.t(Event.t()) def build_events_for_search(%{term: term} = args, page \\ nil, limit \\ nil) do - term - |> normalize_search_string() + search_string = normalize_search_string(term) + + search_string |> events_for_search_query() - |> events_for_begins_on(args) - |> events_for_ends_on(args) + |> events_for_begins_on(Map.get(args, :begins_on, DateTime.utc_now())) + |> events_for_ends_on(Map.get(args, :ends_on)) |> events_for_category(args) |> events_for_categories(args) |> events_for_languages(args) @@ -579,7 +580,7 @@ defmodule Mobilizon.Events do |> filter_draft() |> filter_local_or_from_followed_instances_events() |> filter_public_visibility() - |> event_order(Map.get(args, :sort_by, :match_desc)) + |> event_order(Map.get(args, :sort_by, :match_desc), search_string) |> Page.build_page(page, limit, :begins_on) end @@ -1321,18 +1322,16 @@ defmodule Mobilizon.Events do end end + defp events_for_search_query(""), do: Event + defp events_for_search_query(search_string) do - Event - |> distinct(:id) - |> join(:inner, [e], id_and_rank in matching_event_ids_and_ranks(search_string), + join(Event, :inner, [e], id_and_rank in matching_event_ids_and_ranks(search_string), on: id_and_rank.id == e.id ) end - @spec events_for_begins_on(Ecto.Queryable.t(), map()) :: Ecto.Query.t() - defp events_for_begins_on(query, args) do - begins_on = Map.get(args, :begins_on, DateTime.utc_now()) - + @spec events_for_begins_on(Ecto.Queryable.t(), DateTime.t() | nil) :: Ecto.Query.t() + defp events_for_begins_on(query, begins_on) do if is_nil(begins_on) do query else @@ -1345,10 +1344,8 @@ defmodule Mobilizon.Events do end end - @spec events_for_ends_on(Ecto.Queryable.t(), map()) :: Ecto.Query.t() - defp events_for_ends_on(query, args) do - ends_on = Map.get(args, :ends_on) - + @spec events_for_ends_on(Ecto.Queryable.t(), DateTime.t() | nil) :: Ecto.Query.t() + defp events_for_ends_on(query, ends_on) do if is_nil(ends_on) do query else @@ -1759,7 +1756,6 @@ defmodule Mobilizon.Events do |> distinct([e], e.id) |> join(:left, [e], et in "events_tags", on: e.id == et.event_id) |> join(:left, [e], a in Address, on: e.physical_address_id == a.id) - |> events_for_begins_on(%{}) |> filter_draft() |> filter_local_or_from_followed_instances_events() |> filter_public_visibility() @@ -1948,17 +1944,49 @@ defmodule Mobilizon.Events do 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) + defp event_order(query, :match_desc, "") do + query + |> distinct([e], desc: e.begins_on, asc: e.id) + |> order_by([e], desc: e.begins_on) + end - defp event_order(query, :start_time_desc), do: order_by(query, [e], asc: e.begins_on) - defp event_order(query, :created_at_desc), do: order_by(query, [e], desc: e.publish_at) - defp event_order(query, :created_at_asc), do: order_by(query, [e], asc: e.publish_at) + defp event_order(query, :match_desc, _) do + query + |> distinct([e, f], desc: f.rank, asc: e.begins_on, asc: e.id) + |> order_by([e, f], desc: f.rank, asc: e.begins_on) + end - defp event_order(query, :participant_count_desc), - do: order_by(query, [e], fragment("participant_stats->>'participant' DESC")) + defp event_order(query, :start_time_desc, _) do + query + |> distinct([e], desc: e.begins_on, asc: e.id) + |> order_by([e], desc: e.begins_on) + end - defp event_order(query, _), do: query + defp event_order(query, :start_time_asc, _) do + query + |> distinct([e], asc: e.begins_on, asc: e.id) + |> order_by([e], asc: e.begins_on) + end + + defp event_order(query, :created_at_desc, _) do + query + |> distinct([e], desc: e.publish_at, asc: e.id) + |> order_by([e], desc: e.publish_at) + end + + defp event_order(query, :created_at_asc, _) do + query + |> distinct([e], asc: e.publish_at, asc: e.id) + |> order_by([e], asc: e.publish_at) + end + + defp event_order(query, :participant_count_desc, _) do + query + |> distinct(:id) + |> order_by([e], fragment("participant_stats->>'participant' DESC")) + end + + defp event_order(query, _, _), do: query defp participation_filter_begins_on(query, nil, nil), do: participation_order_begins_on_desc(query) diff --git a/lib/service/global_search/search_mobilizon.ex b/lib/service/global_search/search_mobilizon.ex index 8cd8fe00c..157bb8afc 100644 --- a/lib/service/global_search/search_mobilizon.ex +++ b/lib/service/global_search/search_mobilizon.ex @@ -17,6 +17,7 @@ defmodule Mobilizon.Service.GlobalSearch.SearchMobilizon do @sort_by_options %{ match_desc: "-match", + start_time_asc: "startTime", start_time_desc: "-startTime", created_at_desc: "-createdAt", created_at_asc: "createdAt",