feat: allow to filter events by local-only
In addition to internal (self + federated) and global (global external search engine), introduce the self possibility Closes #1322 Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
d1b1979ee5
commit
9d99684402
|
@ -1,2 +1,2 @@
|
|||
elixir 1.15.5-otp-26
|
||||
erlang 26.0.2
|
||||
erlang 26.2.2
|
||||
elixir 1.16.1-otp-26
|
||||
|
|
|
@ -56,7 +56,8 @@ defmodule Mobilizon.GraphQL.API.Search do
|
|||
minimum_visibility: Map.get(args, :minimum_visibility, :public),
|
||||
current_actor_id: Map.get(args, :current_actor_id),
|
||||
exclude_my_groups: Map.get(args, :exclude_my_groups, false),
|
||||
exclude_stale_actors: true
|
||||
exclude_stale_actors: true,
|
||||
local_only: Map.get(args, :search_target, :internal) == :self
|
||||
],
|
||||
page,
|
||||
limit
|
||||
|
@ -94,7 +95,13 @@ defmodule Mobilizon.GraphQL.API.Search do
|
|||
|
||||
{:ok, service.search_events(Keyword.new(args, fn {k, v} -> {k, v} end))}
|
||||
else
|
||||
{:ok, Events.build_events_for_search(Map.put(args, :term, term), page, limit)}
|
||||
results =
|
||||
args
|
||||
|> Map.put(:term, term)
|
||||
|> Map.put(:local_only, Map.get(args, :search_target, :internal) == :self)
|
||||
|> Events.build_events_for_search(page, limit)
|
||||
|
||||
{:ok, results}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -160,6 +160,8 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
|
|||
end
|
||||
|
||||
enum :search_target do
|
||||
value(:self, description: "Search only on content from this instance")
|
||||
|
||||
value(:internal,
|
||||
description: "Search on content from this instance and from the followed instances"
|
||||
)
|
||||
|
|
|
@ -525,6 +525,7 @@ defmodule Mobilizon.Actors do
|
|||
Keyword.get(options, :radius),
|
||||
Keyword.get(options, :bbox)
|
||||
)
|
||||
|> filter_by_local_only(Keyword.get(options, :local_only, false))
|
||||
|> actors_for_location(Keyword.get(options, :location), Keyword.get(options, :radius))
|
||||
|> events_for_bounding_box(Keyword.get(options, :bbox))
|
||||
|> filter_by_type(Keyword.get(options, :actor_type, :Group))
|
||||
|
@ -1418,6 +1419,13 @@ defmodule Mobilizon.Actors do
|
|||
|
||||
defp maybe_join_address(query, _location, _radius, _bbox), do: query
|
||||
|
||||
@spec filter_by_local_only(Ecto.Queryable.t(), boolean()) :: Ecto.Query.t()
|
||||
defp filter_by_local_only(query, true) do
|
||||
where(query, [q], is_nil(q.domain))
|
||||
end
|
||||
|
||||
defp filter_by_local_only(query, false), do: query
|
||||
|
||||
@spec actors_for_location(Ecto.Queryable.t(), String.t(), integer()) :: Ecto.Query.t()
|
||||
defp actors_for_location(query, location, radius)
|
||||
when is_valid_string(location) and not is_nil(radius) do
|
||||
|
|
|
@ -581,6 +581,7 @@ defmodule Mobilizon.Events do
|
|||
|> events_for_bounding_box(args)
|
||||
|> filter_online(args)
|
||||
|> filter_draft()
|
||||
|> filter_local(if Map.get(args, :local_only, nil) == true, do: true, else: nil)
|
||||
|> filter_local_or_from_followed_instances_events()
|
||||
|> filter_public_visibility()
|
||||
|> event_order(Map.get(args, :sort_by, :match_desc), search_string)
|
||||
|
|
|
@ -293,6 +293,7 @@ export enum InstanceFollowStatus {
|
|||
}
|
||||
|
||||
export enum SearchTargets {
|
||||
SELF = "SELF",
|
||||
INTERNAL = "INTERNAL",
|
||||
GLOBAL = "GLOBAL",
|
||||
}
|
||||
|
|
|
@ -68,6 +68,22 @@
|
|||
<fieldset class="flex flex-col">
|
||||
<legend class="sr-only">{{ t("Search target") }}</legend>
|
||||
|
||||
<div>
|
||||
<input
|
||||
id="selfTarget"
|
||||
v-model="searchTarget"
|
||||
type="radio"
|
||||
name="selfTarget"
|
||||
:value="SearchTargets.SELF"
|
||||
class="w-4 h-4 border-gray-300 focus:ring-2 focus:ring-blue-300 dark:focus:ring-blue-600 dark:focus:bg-blue-600 dark:bg-gray-700 dark:border-gray-600"
|
||||
/>
|
||||
<label
|
||||
for="selfTarget"
|
||||
class="ml-3 font-medium text-gray-900 dark:text-gray-300"
|
||||
>{{ t("From this instance only") }}</label
|
||||
>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input
|
||||
id="internalTarget"
|
||||
|
|
|
@ -55,7 +55,8 @@ defmodule Mobilizon.GraphQL.API.SearchTest do
|
|||
minimum_visibility: :public,
|
||||
current_actor_id: nil,
|
||||
exclude_my_groups: false,
|
||||
exclude_stale_actors: true
|
||||
exclude_stale_actors: true,
|
||||
local_only: false
|
||||
],
|
||||
1,
|
||||
10
|
||||
|
@ -72,7 +73,7 @@ defmodule Mobilizon.GraphQL.API.SearchTest do
|
|||
assert {:ok, %{total: 1, elements: [%Event{title: "super toto event"}]}} =
|
||||
Search.search_events(%{term: "toto"}, 1, 10)
|
||||
|
||||
assert_called(Events.build_events_for_search(%{term: "toto"}, 1, 10))
|
||||
assert_called(Events.build_events_for_search(%{term: "toto", local_only: false}, 1, 10))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,6 +3,9 @@ defmodule Mobilizon.GraphQL.Resolvers.SearchTest do
|
|||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Federation.ActivityPub.Relay
|
||||
alias Mobilizon.Service.Workers
|
||||
|
||||
alias Mobilizon.GraphQL.AbsintheHelpers
|
||||
|
@ -15,8 +18,8 @@ defmodule Mobilizon.GraphQL.Resolvers.SearchTest do
|
|||
|
||||
describe "search events/3" do
|
||||
@search_events_query """
|
||||
query SearchEvents($location: String, $radius: Float, $tags: String, $term: String, $beginsOn: DateTime, $endsOn: DateTime) {
|
||||
searchEvents(location: $location, radius: $radius, tags: $tags, term: $term, beginsOn: $beginsOn, endsOn: $endsOn) {
|
||||
query SearchEvents($location: String, $radius: Float, $tags: String, $term: String, $beginsOn: DateTime, $endsOn: DateTime, $searchTarget: SearchTarget) {
|
||||
searchEvents(location: $location, radius: $radius, tags: $tags, term: $term, beginsOn: $beginsOn, endsOn: $endsOn, searchTarget: $searchTarget) {
|
||||
total,
|
||||
elements {
|
||||
id
|
||||
|
@ -218,6 +221,46 @@ defmodule Mobilizon.GraphQL.Resolvers.SearchTest do
|
|||
assert res["errors"] == nil
|
||||
assert res["data"]["searchEvents"]["total"] == 0
|
||||
end
|
||||
|
||||
test "finds events for the correct target", %{conn: conn} do
|
||||
event1 = insert(:event, title: "A local event")
|
||||
|
||||
%Actor{id: remote_instance_actor_id} = remote_instance_actor = insert(:instance_actor)
|
||||
%Actor{id: remote_actor_id} = insert(:actor, domain: "somedomain.tld", user: nil)
|
||||
|
||||
%Event{url: remote_event_url} =
|
||||
event2 = insert(:event, local: false, title: "My Remote event")
|
||||
|
||||
Mobilizon.Share.create(remote_event_url, remote_instance_actor_id, remote_actor_id)
|
||||
|
||||
%Actor{} = own_instance_actor = Relay.get_actor()
|
||||
|
||||
insert(:follower, target_actor: remote_instance_actor, actor: own_instance_actor)
|
||||
Workers.BuildSearch.insert_search_event(event1)
|
||||
Workers.BuildSearch.insert_search_event(event2)
|
||||
|
||||
res =
|
||||
AbsintheHelpers.graphql_query(conn,
|
||||
query: @search_events_query,
|
||||
variables: %{term: "event"}
|
||||
)
|
||||
|
||||
assert res["errors"] == nil
|
||||
assert res["data"]["searchEvents"]["total"] == 2
|
||||
elements = res["data"]["searchEvents"]["elements"]
|
||||
|
||||
assert MapSet.new(Enum.map(elements, & &1["id"])) ==
|
||||
MapSet.new([to_string(event1.id), to_string(event2.id)])
|
||||
|
||||
res =
|
||||
AbsintheHelpers.graphql_query(conn,
|
||||
query: @search_events_query,
|
||||
variables: %{term: "event", searchTarget: "SELF"}
|
||||
)
|
||||
|
||||
assert res["errors"] == nil
|
||||
assert res["data"]["searchEvents"]["total"] == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "search_persons/3" do
|
||||
|
|
Loading…
Reference in New Issue