Browse Source

Add advanced search filtering by software

master
Sean King 9 months ago
parent
commit
602950b502
Signed by: seanking GPG Key ID: 778810DE76B9460F
  1. 13
      assets/css/tabs.scss
  2. 12
      lib/fuck_gab/instance.ex
  3. 32
      lib/fuck_gab_web/live/directory_live.ex
  4. 8
      lib/fuck_gab_web/live/directory_live.html.leex
  5. 23
      test/fuck_gab/instance_test.exs
  6. 24
      test/fuck_gab_web/live/directory_live_test.exs

13
assets/css/tabs.scss

@ -48,6 +48,19 @@
.advanced-search {
padding: 2.0rem;
ul {
list-style: none;
margin-bottom: 0;
}
li {
margin-bottom: 0.25rem;
}
input[type="checkbox"] {
margin: 0.2rem;
}
.row {
width: 100%;
margin-left: 0;

12
lib/fuck_gab/instance.ex

@ -11,8 +11,11 @@ defmodule FuckGab.Instance do
@primary_key {:id, FlakeId.Ecto.Type, autogenerate: true}
# Source of @domain_regex: https://www.regextester.com/93928
@domain_regex ~r/^(?!:\/\/)([a-zA-Z0-9-_]+\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+\.[a-zA-Z]{2,11}?$/
@software_tags ["mastodon", "misskey", "pleroma"]
@derive {Jason.Encoder, only: [:domain, :data]}
schema "instances" do
field :domain, :string, null: false
@ -97,9 +100,12 @@ defmodule FuckGab.Instance do
|> Repo.one()
end
def filter("", per_page, page_number) do
def filter("", per_page, software, page_number) do
software = if software == [], do: @software_tags, else: software
Instance
|> where(is_approved: true)
|> where([q], q.software in ^software)
|> order_by(
[_q],
fragment("""
@ -112,8 +118,9 @@ defmodule FuckGab.Instance do
|> Repo.paginate(page: page_number, page_size: per_page)
end
def filter(search, per_page, page_number) when is_binary(search) do
def filter(search, per_page, software, page_number) when is_binary(search) do
search = "%#{search}%"
software = if software == [], do: @software_tags, else: software
Instance
|> where(
@ -132,6 +139,7 @@ defmodule FuckGab.Instance do
^search
)
)
|> where([q], q.software in ^software)
|> order_by(
[_q],
fragment("""

32
lib/fuck_gab_web/live/directory_live.ex

@ -6,7 +6,7 @@ defmodule FuckGabWeb.DirectoryLive do
alias FuckGab.Instance
def mount(_session, _, socket) do
assigns = get_search_and_assign_page("", 5, 1)
assigns = get_search_and_assign_page("", 5, [], 1)
socket =
socket
@ -17,18 +17,33 @@ defmodule FuckGabWeb.DirectoryLive do
{:ok, socket}
end
def handle_event("search", %{"search" => search, "per_page" => per_page} = _value, socket) do
assigns = get_search_and_assign_page(search, per_page, 1)
def handle_event(
"search",
%{"search" => search, "per_page" => per_page, "software" => software} = _value,
socket
) do
assigns = get_search_and_assign_page(search, per_page, software, 1)
{:noreply, assign(socket, assigns)}
end
def handle_event(
"search",
%{"search" => search, "per_page" => per_page} = _value,
socket
) do
assigns = get_search_and_assign_page(search, per_page, [], 1)
{:noreply, assign(socket, assigns)}
end
def handle_event("search", %{"search" => search} = _value, socket) do
assigns = get_search_and_assign_page(search, socket.assigns.per_page, 1)
assigns =
get_search_and_assign_page(search, socket.assigns.per_page, socket.assigns.software, 1)
{:noreply, assign(socket, assigns)}
end
def handle_event("search", _, socket) do
assigns = get_search_and_assign_page("", socket.assigns.per_page, 1)
assigns = get_search_and_assign_page("", socket.assigns.per_page, socket.assigns.software, 1)
{:noreply, assign(socket, assigns)}
end
@ -37,6 +52,7 @@ defmodule FuckGabWeb.DirectoryLive do
get_search_and_assign_page(
socket.assigns.search,
socket.assigns.per_page,
socket.assigns.software,
socket.assigns.page_number - 1
)
@ -48,6 +64,7 @@ defmodule FuckGabWeb.DirectoryLive do
get_search_and_assign_page(
socket.assigns.search,
socket.assigns.per_page,
socket.assigns.software,
socket.assigns.page_number + 1
)
@ -58,16 +75,17 @@ defmodule FuckGabWeb.DirectoryLive do
{:noreply, update(socket, :show_advanced, &(!&1))}
end
defp get_search_and_assign_page(search, per_page, page_number) do
defp get_search_and_assign_page(search, per_page, software, page_number) do
%{
entries: entries,
page_number: page_number,
total_pages: total_pages
} = Instance.filter(search, per_page, page_number)
} = Instance.filter(search, per_page, software, page_number)
[
instances: entries,
per_page: per_page,
software: software,
page_number: page_number,
search: search,
total_pages: total_pages

8
lib/fuck_gab_web/live/directory_live.html.leex

@ -15,6 +15,14 @@
<label for="per_page">Instances per page:</label>
<input type="number" name="per_page" min="1" value="<%= @per_page %>" />
</article>
<article class="column">
<label for="software">Filter by software:</label>
<ul>
<li><input type="checkbox" name="software[]" value="mastodon" <%= if "mastodon" in @software do %>checked<% end %>> Mastodon</li>
<li><input type="checkbox" name="software[]" value="misskey" <%= if "misskey" in @software do %>checked<% end %>> Misskey</li>
<li><input type="checkbox" name="software[]" value="pleroma" <%= if "pleroma" in @software do %>checked<% end %>> Pleroma</li>
</ul>
</article>
</div>
</div>
<% end %>

23
test/fuck_gab/instance_test.exs

@ -23,11 +23,11 @@ defmodule FuckGab.InstanceTest do
data: json_file("test/fixtures/traboone-instance.json")
}
with %Instance{} = instance <- Repo.reload(instance) do
{:ok, %Instance{} = instance} =
Instance.changeset(instance, new_attrs)
|> Instance.update()
{:ok, %Instance{} = instance} =
Instance.changeset(instance, new_attrs)
|> Instance.update()
with %Instance{} = instance <- Repo.reload(instance) do
assert instance.data == json_file("test/fixtures/traboone-instance.json")
end
end
@ -49,8 +49,19 @@ defmodule FuckGab.InstanceTest do
test "search an instance" do
instance = insert(:instance, domain: "traboone.com")
search = Instance.filter(instance.domain, 1, 5)
[^instance] = search.entries
new_attrs = %{
data: json_file("test/fixtures/traboone-instance.json"),
software: "pleroma"
}
{:ok, %Instance{} = instance} =
Instance.changeset(instance, new_attrs)
|> Instance.update()
with %Instance{} = instance <- Repo.reload(instance) do
search = Instance.filter(instance.domain, 5, [], 1)
assert search.entries == [instance]
end
end
# Function to read a JSON file

24
test/fuck_gab_web/live/directory_live_test.exs

@ -104,7 +104,29 @@ defmodule FuckGabWeb.DirectoryLiveTest do
render_click(view, :toggle_advanced, %{})
disconnected_html = render_change(view, :search, %{search: "", per_page: 1})
disconnected_html = render_change(view, :search, %{search: "", software: [], per_page: 1})
assert disconnected_html =~ "<h4 class=\"tab-title\">#{instance.data["title"]}</h4>"
assert disconnected_html != "<h4 class=\"tab-title\">#{instance2.data["title"]}</h4>"
end
test "filter instances by software", %{conn: conn} do
instance = insert(:instance, domain: "gameliberty.club")
instance2 = insert(:instance, domain: "traboone.com")
Scraper.scrape_instance(instance)
Scraper.scrape_instance(instance2)
instance = Repo.reload(instance)
instance2 = Repo.reload(instance2)
{:ok, view, _disconnected_html} =
live_isolated(conn, FuckGabWeb.DirectoryLive, session: %{})
render_click(view, :toggle_advanced, %{})
disconnected_html =
render_change(view, :search, %{search: "", software: ["mastodon"], per_page: 2})
assert disconnected_html =~ "<h4 class=\"tab-title\">#{instance.data["title"]}</h4>"
assert disconnected_html != "<h4 class=\"tab-title\">#{instance2.data["title"]}</h4>"

Loading…
Cancel
Save