Implements exporting groups closes #428 #435
3 changed files with 111 additions and 57 deletions
|
|
@ -244,9 +244,15 @@ defmodule Mv.Membership.MemberExport.Build do
|
||||||
defp maybe_sort(query, _field, nil), do: {query, false}
|
defp maybe_sort(query, _field, nil), do: {query, false}
|
||||||
|
|
||||||
defp maybe_sort(query, field, order) when is_binary(field) do
|
defp maybe_sort(query, field, order) when is_binary(field) do
|
||||||
if custom_field_sort?(field) do
|
cond do
|
||||||
|
field == "groups" ->
|
||||||
|
# Groups sort → in-memory nach dem Read (wie Tabelle)
|
||||||
{query, true}
|
{query, true}
|
||||||
else
|
|
||||||
|
custom_field_sort?(field) ->
|
||||||
|
{query, true}
|
||||||
|
|
||||||
|
true ->
|
||||||
field_atom = String.to_existing_atom(field)
|
field_atom = String.to_existing_atom(field)
|
||||||
|
|
||||||
if field_atom in (Mv.Constants.member_fields() -- [:notes]) do
|
if field_atom in (Mv.Constants.member_fields() -- [:notes]) do
|
||||||
|
|
@ -263,6 +269,9 @@ defmodule Mv.Membership.MemberExport.Build do
|
||||||
do: []
|
do: []
|
||||||
|
|
||||||
defp sort_members_by_custom_field(members, field, order, custom_fields) when is_binary(field) do
|
defp sort_members_by_custom_field(members, field, order, custom_fields) when is_binary(field) do
|
||||||
|
if field == "groups" do
|
||||||
|
sort_members_by_groups_export(members, order)
|
||||||
|
else
|
||||||
id_str = String.trim_leading(field, @custom_field_prefix)
|
id_str = String.trim_leading(field, @custom_field_prefix)
|
||||||
custom_field = Enum.find(custom_fields, fn cf -> to_string(cf.id) == id_str end)
|
custom_field = Enum.find(custom_fields, fn cf -> to_string(cf.id) == id_str end)
|
||||||
|
|
||||||
|
|
@ -279,6 +288,27 @@ defmodule Mv.Membership.MemberExport.Build do
|
||||||
|> Enum.sort(fn {_, ka}, {_, kb} -> MemberExportSort.key_lt(ka, kb, order) end)
|
|> Enum.sort(fn {_, ka}, {_, kb} -> MemberExportSort.key_lt(ka, kb, order) end)
|
||||||
|> Enum.map(fn {m, _} -> m end)
|
|> Enum.map(fn {m, _} -> m end)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp sort_members_by_groups_export(members, order) do
|
||||||
|
# Members with groups first, then by first group name alphabetically (min = first by sort order)
|
||||||
|
# Match table behavior from MvWeb.MemberLive.Index.sort_members_by_groups/2
|
||||||
|
first_group_name = fn member ->
|
||||||
|
(member.groups || [])
|
||||||
|
|> Enum.map(& &1.name)
|
||||||
|
|> Enum.min(fn -> nil end)
|
||||||
|
end
|
||||||
|
|
||||||
|
members
|
||||||
|
|> Enum.sort_by(fn member ->
|
||||||
|
name = first_group_name.(member)
|
||||||
|
# Nil (no groups) sorts last in asc, first in desc
|
||||||
|
{name == nil, name || ""}
|
||||||
|
end)
|
||||||
|
|> then(fn list ->
|
||||||
|
if order == "desc", do: Enum.reverse(list), else: list
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
defp find_cfv(member, custom_field) do
|
defp find_cfv(member, custom_field) do
|
||||||
(member.custom_field_values || [])
|
(member.custom_field_values || [])
|
||||||
|
|
|
||||||
|
|
@ -341,10 +341,16 @@ defmodule MvWeb.MemberExportController do
|
||||||
defp maybe_sort_export(query, _field, nil), do: {query, false}
|
defp maybe_sort_export(query, _field, nil), do: {query, false}
|
||||||
|
|
||||||
defp maybe_sort_export(query, field, order) when is_binary(field) do
|
defp maybe_sort_export(query, field, order) when is_binary(field) do
|
||||||
if custom_field_sort?(field) do
|
cond do
|
||||||
|
field == "groups" ->
|
||||||
|
# Groups sort → in-memory nach dem Read (wie Tabelle)
|
||||||
|
{query, true}
|
||||||
|
|
||||||
|
custom_field_sort?(field) ->
|
||||||
# Custom field sort → in-memory nach dem Read (wie Tabelle)
|
# Custom field sort → in-memory nach dem Read (wie Tabelle)
|
||||||
{query, true}
|
{query, true}
|
||||||
else
|
|
||||||
|
true ->
|
||||||
field_atom = String.to_existing_atom(field)
|
field_atom = String.to_existing_atom(field)
|
||||||
|
|
||||||
if field_atom in (Mv.Constants.member_fields() -- [:notes]) do
|
if field_atom in (Mv.Constants.member_fields() -- [:notes]) do
|
||||||
|
|
@ -370,6 +376,10 @@ defmodule MvWeb.MemberExportController do
|
||||||
defp sort_members_by_custom_field_export(members, field, order, custom_fields)
|
defp sort_members_by_custom_field_export(members, field, order, custom_fields)
|
||||||
when is_binary(field) do
|
when is_binary(field) do
|
||||||
order = order || "asc"
|
order = order || "asc"
|
||||||
|
|
||||||
|
if field == "groups" do
|
||||||
|
sort_members_by_groups_export(members, order)
|
||||||
|
else
|
||||||
id_str = String.trim_leading(field, @custom_field_prefix)
|
id_str = String.trim_leading(field, @custom_field_prefix)
|
||||||
|
|
||||||
custom_field =
|
custom_field =
|
||||||
|
|
@ -398,6 +408,27 @@ defmodule MvWeb.MemberExportController do
|
||||||
sorted_with_values ++ without_values
|
sorted_with_values ++ without_values
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp sort_members_by_groups_export(members, order) do
|
||||||
|
# Members with groups first, then by first group name alphabetically (min = first by sort order)
|
||||||
|
# Match table behavior from MvWeb.MemberLive.Index.sort_members_by_groups/2
|
||||||
|
first_group_name = fn member ->
|
||||||
|
(member.groups || [])
|
||||||
|
|> Enum.map(& &1.name)
|
||||||
|
|> Enum.min(fn -> nil end)
|
||||||
|
end
|
||||||
|
|
||||||
|
members
|
||||||
|
|> Enum.sort_by(fn member ->
|
||||||
|
name = first_group_name.(member)
|
||||||
|
# Nil (no groups) sorts last in asc, first in desc
|
||||||
|
{name == nil, name || ""}
|
||||||
|
end)
|
||||||
|
|> then(fn list ->
|
||||||
|
if order == "desc", do: Enum.reverse(list), else: list
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
defp has_non_empty_custom_field_value?(member, custom_field) do
|
defp has_non_empty_custom_field_value?(member, custom_field) do
|
||||||
case find_cfv(member, custom_field) do
|
case find_cfv(member, custom_field) do
|
||||||
|
|
|
||||||
|
|
@ -1066,13 +1066,6 @@ defmodule MvWeb.MemberLive.Index do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp computed_field?(field) do
|
|
||||||
computed_atoms = FieldVisibility.computed_member_fields()
|
|
||||||
computed_strings = Enum.map(computed_atoms, &Atom.to_string/1)
|
|
||||||
|
|
||||||
(is_atom(field) and field in computed_atoms) or
|
|
||||||
(is_binary(field) and field in computed_strings)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp apply_sort_to_query(query, field, order) do
|
defp apply_sort_to_query(query, field, order) do
|
||||||
cond do
|
cond do
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue