Add the map in search view

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2022-09-01 10:00:17 +02:00
parent b36ce27bbe
commit eecb04516e
26 changed files with 1507 additions and 329 deletions

View File

@@ -512,7 +512,13 @@ defmodule Mobilizon.Actors do
query
|> distinct([q], q.id)
|> actor_by_username_or_name_query(term)
|> maybe_join_address(
Keyword.get(options, :location),
Keyword.get(options, :radius),
Keyword.get(options, :bbox)
)
|> 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))
|> filter_by_minimum_visibility(Keyword.get(options, :minimum_visibility, :public))
|> filter_suspended(false)
@@ -1385,15 +1391,27 @@ defmodule Mobilizon.Actors do
)
end
@spec maybe_join_address(
Ecto.Queryable.t(),
String.t() | nil,
integer() | nil,
String.t() | nil
) :: Ecto.Query.t()
defp maybe_join_address(query, location, radius, bbox)
when (is_valid_string(location) and not is_nil(radius)) or is_valid_string(bbox) do
join(query, :inner, [q], a in Address, on: a.id == q.physical_address_id, as: :address)
end
defp maybe_join_address(query, _location, _radius, _bbox), 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
{lon, lat} = Geohax.decode(location)
point = Geo.WKT.decode!("SRID=4326;POINT(#{lon} #{lat})")
query
|> join(:inner, [q], a in Address, on: a.id == q.physical_address_id, as: :address)
|> where(
where(
query,
[q],
st_dwithin_in_meters(^point, as(:address).geom, ^(radius * 1000))
)
@@ -1401,6 +1419,36 @@ defmodule Mobilizon.Actors do
defp actors_for_location(query, _location, _radius), do: query
defp events_for_bounding_box(query, bbox) when is_valid_string(bbox) do
[top_left, bottom_right] = String.split(bbox, ":")
[ymax, xmin] = String.split(top_left, ",")
[ymin, xmax] = String.split(bottom_right, ",")
where(
query,
[q, ..., a],
fragment(
"? @ ST_MakeEnvelope(?,?,?,?,?)",
a.geom,
^sanitize_bounding_box_params(xmin),
^sanitize_bounding_box_params(ymin),
^sanitize_bounding_box_params(xmax),
^sanitize_bounding_box_params(ymax),
"4326"
)
)
end
defp events_for_bounding_box(query, _args), do: query
@spec sanitize_bounding_box_params(String.t()) :: float()
defp sanitize_bounding_box_params(param) do
param
|> String.trim()
|> String.to_float()
|> Float.floor(10)
end
@spec person_query :: Ecto.Query.t()
defp person_query do
from(a in Actor, where: a.type == ^:Person)

View File

@@ -534,7 +534,9 @@ defmodule Mobilizon.Events do
|> events_for_languages(args)
|> events_for_statuses(args)
|> events_for_tags(args)
|> maybe_join_address(args)
|> events_for_location(args)
|> events_for_bounding_box(args)
|> filter_online(args)
|> filter_draft()
|> filter_local_or_from_followed_instances_events()
@@ -1355,6 +1357,20 @@ defmodule Mobilizon.Events do
defp events_for_tags(query, _args), do: query
# We add the inner join on address only if we're going to use it in
# events_for_location or events_for_bounding_box
# So we're sure it's only being added once
defp maybe_join_address(query, %{location: location, radius: radius})
when is_valid_string(location) and not is_nil(radius) do
join(query, :inner, [q], a in Address, on: a.id == q.physical_address_id, as: :address)
end
defp maybe_join_address(query, %{bbox: bbox}) when is_valid_string(bbox) do
join(query, :inner, [q], a in Address, on: a.id == q.physical_address_id, as: :address)
end
defp maybe_join_address(query, _), do: query
@spec events_for_location(Ecto.Queryable.t(), map()) :: Ecto.Query.t()
defp events_for_location(query, %{radius: radius}) when is_nil(radius),
do: query
@@ -1364,9 +1380,8 @@ defmodule Mobilizon.Events do
with {lon, lat} <- Geohax.decode(location),
point <- Geo.WKT.decode!("SRID=4326;POINT(#{lon} #{lat})"),
{{x_min, y_min}, {x_max, y_max}} <- search_box({lon, lat}, radius) do
query
|> join(:inner, [q], a in Address, on: a.id == q.physical_address_id, as: :address)
|> where(
where(
query,
[q, ..., a],
st_x(a.geom) > ^x_min and st_x(a.geom) < ^x_max and
st_y(a.geom) > ^y_min and st_y(a.geom) < ^y_max and
@@ -1379,6 +1394,36 @@ defmodule Mobilizon.Events do
defp events_for_location(query, _args), do: query
defp events_for_bounding_box(query, %{bbox: bbox}) when is_valid_string(bbox) do
[top_left, bottom_right] = String.split(bbox, ":")
[ymax, xmin] = String.split(top_left, ",")
[ymin, xmax] = String.split(bottom_right, ",")
where(
query,
[q, ..., a],
fragment(
"? @ ST_MakeEnvelope(?,?,?,?,?)",
a.geom,
^sanitize_bounding_box_params(xmin),
^sanitize_bounding_box_params(ymin),
^sanitize_bounding_box_params(xmax),
^sanitize_bounding_box_params(ymax),
"4326"
)
)
end
defp events_for_bounding_box(query, _args), do: query
@spec sanitize_bounding_box_params(String.t()) :: float()
defp sanitize_bounding_box_params(param) do
param
|> String.trim()
|> String.to_float()
|> Float.floor(10)
end
@spec search_box({float(), float()}, float()) :: {{float, float}, {float, float}}
defp search_box({lon0, lat0}, radius) do
km_per_lat_deg = 111.195