Add boolean custom field filters to member overview closes #309 #362

Merged
simon merged 15 commits from feature/filter-boolean-custom-fields into main 2026-01-23 14:53:08 +01:00
2 changed files with 55 additions and 0 deletions
Showing only changes of commit 1011b94acf - Show all commits

View file

@ -84,6 +84,12 @@ defmodule MvWeb.MemberLive.Index do
|> Ash.Query.sort(name: :asc)
|> Ash.read!(actor: actor)
# Load boolean custom fields (filtered and sorted from all_custom_fields)
boolean_custom_fields =
all_custom_fields
|> Enum.filter(&(&1.value_type == :boolean))
|> Enum.sort_by(& &1.name, :asc)
# Load settings once to avoid N+1 queries
settings =
case Membership.get_settings() do
@ -118,6 +124,7 @@ defmodule MvWeb.MemberLive.Index do
|> assign(:settings, settings)
|> assign(:custom_fields_visible, custom_fields_visible)
|> assign(:all_custom_fields, all_custom_fields)
|> assign(:boolean_custom_fields, boolean_custom_fields)
|> assign(:all_available_fields, all_available_fields)
|> assign(:user_field_selection, initial_selection)
|> assign(

View file

@ -696,6 +696,54 @@ defmodule MvWeb.MemberLive.IndexTest do
assert state.socket.assigns.boolean_custom_field_filters == %{}
end
test "mount initializes boolean_custom_fields as empty list when no boolean fields exist", %{
conn: conn
} do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members")
state = :sys.get_state(view.pid)
assert state.socket.assigns.boolean_custom_fields == []
end
test "mount loads and filters boolean custom fields correctly", %{conn: conn} do
conn = conn_with_oidc_user(conn)
# Create boolean and non-boolean custom fields
boolean_field1 = create_boolean_custom_field(%{name: "Active Member"})
boolean_field2 = create_boolean_custom_field(%{name: "Newsletter Subscription"})
_string_field = create_string_custom_field(%{name: "Phone Number"})
{:ok, view, _html} = live(conn, "/members")
state = :sys.get_state(view.pid)
boolean_custom_fields = state.socket.assigns.boolean_custom_fields
# Should only contain boolean fields
assert length(boolean_custom_fields) == 2
assert Enum.all?(boolean_custom_fields, &(&1.value_type == :boolean))
assert Enum.any?(boolean_custom_fields, &(&1.id == boolean_field1.id))
assert Enum.any?(boolean_custom_fields, &(&1.id == boolean_field2.id))
end
test "mount sorts boolean custom fields by name ascending", %{conn: conn} do
conn = conn_with_oidc_user(conn)
# Create boolean fields with specific names to test sorting
_boolean_field_z = create_boolean_custom_field(%{name: "Zebra Field"})
_boolean_field_a = create_boolean_custom_field(%{name: "Alpha Field"})
_boolean_field_m = create_boolean_custom_field(%{name: "Middle Field"})
{:ok, view, _html} = live(conn, "/members")
state = :sys.get_state(view.pid)
boolean_custom_fields = state.socket.assigns.boolean_custom_fields
# Should be sorted by name ascending
names = Enum.map(boolean_custom_fields, & &1.name)
assert names == ["Alpha Field", "Middle Field", "Zebra Field"]
end
test "handle_params parses bf_<id> values correctly", %{conn: conn} do
conn = conn_with_oidc_user(conn)
boolean_field = create_boolean_custom_field()