Compare commits
11 commits
9b64e35cce
...
3b3ef796a4
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b3ef796a4 | |||
| 5009bbf84b | |||
| 39d2de4644 | |||
| f737e1b9f2 | |||
| 80b79d80cd | |||
| 2095d9b0da | |||
| e68e1604a4 | |||
| 02b3084789 | |||
| 53f6b62289 | |||
| 78588cbad9 | |||
| dd03000428 |
15 changed files with 849 additions and 102 deletions
|
|
@ -166,6 +166,11 @@ defmodule Mv.Membership.Member do
|
||||||
attribute :postal_code, :string do
|
attribute :postal_code, :string do
|
||||||
allow_nil? true
|
allow_nil? true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
attribute :search_vector, AshPostgres.Tsvector,
|
||||||
|
writable?: false,
|
||||||
|
public?: false,
|
||||||
|
select_by_default?: false
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
|
|
|
||||||
61
lib/mv_web/live/components/search_bar_component.ex
Normal file
61
lib/mv_web/live/components/search_bar_component.ex
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
defmodule MvWeb.Components.SearchBarComponent do
|
||||||
|
@moduledoc """
|
||||||
|
Provides the SearchBar Live-Component.
|
||||||
|
|
||||||
|
- uses the DaisyUI search input field
|
||||||
|
- sends search_changed event to parent live view with a query
|
||||||
|
"""
|
||||||
|
use MvWeb, :live_component
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def update(_assigns, socket) do
|
||||||
|
socket =
|
||||||
|
socket
|
||||||
|
|> assign_new(:query, fn -> "" end)
|
||||||
|
|> assign_new(:placeholder, fn -> gettext("Search...") end)
|
||||||
|
|
||||||
|
{:ok, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def render(assigns) do
|
||||||
|
~H"""
|
||||||
|
<form phx-change="search" phx-target={@myself} class="flex" role="search" aria-label="Search">
|
||||||
|
<label class="input">
|
||||||
|
<svg
|
||||||
|
class="h-[1em] opacity-50"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-width="2.5"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
|
<path d="m21 21-4.3-4.3"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
placeholder={@placeholder}
|
||||||
|
value={@query}
|
||||||
|
name="query"
|
||||||
|
phx-debounce="300"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
# Function to handle the search
|
||||||
|
def handle_event("search", %{"query" => q}, socket) do
|
||||||
|
# Forward a high level message to the parent
|
||||||
|
send(self(), {:search_changed, q})
|
||||||
|
{:noreply, assign(socket, :query, q)}
|
||||||
|
end
|
||||||
|
end
|
||||||
61
lib/mv_web/live/components/sort_header_component.ex
Normal file
61
lib/mv_web/live/components/sort_header_component.ex
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
defmodule MvWeb.Components.SortHeaderComponent do
|
||||||
|
@moduledoc """
|
||||||
|
Sort Header that can be used as column header and sorts a table:
|
||||||
|
Props:
|
||||||
|
- field: atom() # Ash‑Field for sorting
|
||||||
|
- label: string() # Column Heading (can be aan heex templyte)
|
||||||
|
- sort_field: atom() | nil # current sort-field from parent liveview
|
||||||
|
- sort_order: :asc | :desc | nil # current sorting order
|
||||||
|
"""
|
||||||
|
use MvWeb, :live_component
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def update(assigns, socket) do
|
||||||
|
{:ok, assign(socket, assigns)}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check if we can add the aria-sort label directly to the daisyUI header
|
||||||
|
# aria-sort={aria_sort(@field, @sort_field, @sort_order)}
|
||||||
|
@impl true
|
||||||
|
def render(assigns) do
|
||||||
|
~H"""
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-label={aria_sort(@field, @sort_field, @sort_order)}
|
||||||
|
class="btn btn-ghost select-none"
|
||||||
|
phx-click="sort"
|
||||||
|
phx-value-field={@field}
|
||||||
|
phx-target={@myself}
|
||||||
|
data-testid={@field}
|
||||||
|
>
|
||||||
|
{@label}
|
||||||
|
<%= if @sort_field == @field do %>
|
||||||
|
<.icon name={if @sort_order == :asc, do: "hero-chevron-up", else: "hero-chevron-down"} />
|
||||||
|
<% else %>
|
||||||
|
<.icon
|
||||||
|
name="hero-chevron-up-down"
|
||||||
|
class="opacity-40"
|
||||||
|
/>
|
||||||
|
<% end %>
|
||||||
|
</button>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_event("sort", %{"field" => field_str}, socket) do
|
||||||
|
send(self(), {:sort, field_str})
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
# -------------------------------------------------
|
||||||
|
# Hilfsfunktionen für ARIA‑Attribute & Icon‑SVG
|
||||||
|
# -------------------------------------------------
|
||||||
|
defp aria_sort(field, sort_field, dir) when field == sort_field do
|
||||||
|
case dir do
|
||||||
|
:asc -> gettext("ascending")
|
||||||
|
:desc -> gettext("descending")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp aria_sort(_, _, _), do: gettext("Click to sort")
|
||||||
|
end
|
||||||
|
|
@ -1,21 +1,55 @@
|
||||||
defmodule MvWeb.MemberLive.Index do
|
defmodule MvWeb.MemberLive.Index do
|
||||||
use MvWeb, :live_view
|
use MvWeb, :live_view
|
||||||
|
import Ash.Expr
|
||||||
|
import Ash.Query
|
||||||
import MvWeb.TableComponents
|
import MvWeb.TableComponents
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(_params, _session, socket) do
|
def mount(params, _session, socket) do
|
||||||
members = Ash.read!(Mv.Membership.Member)
|
socket =
|
||||||
sorted = Enum.sort_by(members, & &1.first_name)
|
|
||||||
|
|
||||||
{:ok,
|
|
||||||
socket
|
socket
|
||||||
|> assign(:page_title, gettext("Members"))
|
|> assign(:page_title, gettext("Members"))
|
||||||
|> assign(:sort_field, :first_name)
|
|> assign(:query, "")
|
||||||
|> assign(:sort_order, :asc)
|
|> assign_new(:sort_field, fn -> :first_name end)
|
||||||
|> assign(:members, sorted)
|
|> assign_new(:sort_order, fn -> :asc end)
|
||||||
|> assign(:selected_members, [])}
|
|> assign(:selected_members, [])
|
||||||
|
|
||||||
|
# We call handle params to use the query from the URL
|
||||||
|
{:noreply, socket} = handle_params(params, nil, socket)
|
||||||
|
{:ok, socket}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Receive messages from any toolbar component
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
# Function to handle search
|
||||||
|
@impl true
|
||||||
|
def handle_info({:search_changed, q}, socket) do
|
||||||
|
members =
|
||||||
|
if String.trim(q) == "" do
|
||||||
|
Ash.read!(Mv.Membership.Member)
|
||||||
|
else
|
||||||
|
Mv.Membership.Member
|
||||||
|
|> filter(expr(fragment("search_vector @@ plainto_tsquery('simple', ?)", ^q)))
|
||||||
|
|> Ash.read!()
|
||||||
|
end
|
||||||
|
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> assign(:query, q)
|
||||||
|
|> assign(:members, members)}
|
||||||
|
end
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Handle Events
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Handle Events
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
# Delete a member
|
||||||
@impl true
|
@impl true
|
||||||
def handle_event("delete", %{"id" => id}, socket) do
|
def handle_event("delete", %{"id" => id}, socket) do
|
||||||
member = Ash.get!(Mv.Membership.Member, id)
|
member = Ash.get!(Mv.Membership.Member, id)
|
||||||
|
|
@ -37,32 +71,7 @@ defmodule MvWeb.MemberLive.Index do
|
||||||
{:noreply, assign(socket, :selected_members, selected)}
|
{:noreply, assign(socket, :selected_members, selected)}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sorts the list of members according to a field, when you click on the column header
|
|
||||||
@impl true
|
|
||||||
def handle_event("sort", %{"field" => field_str}, socket) do
|
|
||||||
members = socket.assigns.members
|
|
||||||
field = String.to_existing_atom(field_str)
|
|
||||||
|
|
||||||
new_order =
|
|
||||||
if socket.assigns.sort_field == field do
|
|
||||||
toggle_order(socket.assigns.sort_order)
|
|
||||||
else
|
|
||||||
:asc
|
|
||||||
end
|
|
||||||
|
|
||||||
sorted_members =
|
|
||||||
members
|
|
||||||
|> Enum.sort_by(&Map.get(&1, field), sort_fun(new_order))
|
|
||||||
|
|
||||||
{:noreply,
|
|
||||||
socket
|
|
||||||
|> assign(:sort_field, field)
|
|
||||||
|> assign(:sort_order, new_order)
|
|
||||||
|> assign(:members, sorted_members)}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Selects all members in the list of members
|
# Selects all members in the list of members
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_event("select_all", _params, socket) do
|
def handle_event("select_all", _params, socket) do
|
||||||
members = socket.assigns.members
|
members = socket.assigns.members
|
||||||
|
|
@ -79,8 +88,117 @@ defmodule MvWeb.MemberLive.Index do
|
||||||
{:noreply, assign(socket, :selected_members, selected)}
|
{:noreply, assign(socket, :selected_members, selected)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Handle Infos from Child Components
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
# Sorts the list of members according to a field, when you click on the column header
|
||||||
|
@impl true
|
||||||
|
def handle_info({:sort, field_str}, socket) do
|
||||||
|
field = String.to_existing_atom(field_str)
|
||||||
|
|
||||||
|
{new_order, new_field} =
|
||||||
|
if socket.assigns.sort_field == field do
|
||||||
|
{toggle_order(socket.assigns.sort_order), field}
|
||||||
|
else
|
||||||
|
{:asc, field}
|
||||||
|
end
|
||||||
|
|
||||||
|
active_id = :"sort_#{new_field}"
|
||||||
|
|
||||||
|
# Update the SortHeader to
|
||||||
|
send_update(MvWeb.Components.SortHeaderComponent,
|
||||||
|
id: active_id,
|
||||||
|
sort_field: new_field,
|
||||||
|
sort_order: new_order
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build the URL with queries
|
||||||
|
query_params = %{
|
||||||
|
"sort_field" => Atom.to_string(new_field),
|
||||||
|
"sort_order" => Atom.to_string(new_order)
|
||||||
|
}
|
||||||
|
|
||||||
|
# "/members" is the path you defined in router.ex
|
||||||
|
new_path = "/members?" <> URI.encode_query(query_params)
|
||||||
|
|
||||||
|
# Push the new URL
|
||||||
|
{:noreply,
|
||||||
|
push_patch(socket,
|
||||||
|
to: new_path,
|
||||||
|
# replace true
|
||||||
|
replace: true
|
||||||
|
)}
|
||||||
|
end
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# Handle Params from the URL
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
@impl true
|
||||||
|
def handle_params(params, _url, socket) do
|
||||||
|
socket =
|
||||||
|
socket
|
||||||
|
|> maybe_update_sort(params)
|
||||||
|
|> load_members()
|
||||||
|
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# FUNCTIONS
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# Load members eg based on a query for sorting
|
||||||
|
defp load_members(socket) do
|
||||||
|
query =
|
||||||
|
Mv.Membership.Member
|
||||||
|
|> Ash.Query.new()
|
||||||
|
|> Ash.Query.select([
|
||||||
|
:id,
|
||||||
|
:first_name,
|
||||||
|
:last_name,
|
||||||
|
:email,
|
||||||
|
:street,
|
||||||
|
:house_number,
|
||||||
|
:postal_code,
|
||||||
|
:city,
|
||||||
|
:phone_number,
|
||||||
|
:join_date
|
||||||
|
])
|
||||||
|
|> maybe_sort(socket.assigns.sort_field, socket.assigns.sort_order)
|
||||||
|
|
||||||
|
members = Ash.read!(query)
|
||||||
|
assign(socket, :members, members)
|
||||||
|
end
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# Helper Functions
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
|
||||||
|
# Functions to toggle sorting order
|
||||||
defp toggle_order(:asc), do: :desc
|
defp toggle_order(:asc), do: :desc
|
||||||
defp toggle_order(:desc), do: :asc
|
defp toggle_order(:desc), do: :asc
|
||||||
defp sort_fun(:asc), do: &<=/2
|
defp toggle_order(nil), do: :asc
|
||||||
defp sort_fun(:desc), do: &>=/2
|
|
||||||
|
# Function to sort the column if needed
|
||||||
|
defp maybe_sort(query, nil, _), do: query
|
||||||
|
defp maybe_sort(query, field, :asc), do: Ash.Query.sort(query, [{field, :asc}])
|
||||||
|
defp maybe_sort(query, field, :desc), do: Ash.Query.sort(query, [{field, :desc}])
|
||||||
|
|
||||||
|
# Function to maybe update the sort
|
||||||
|
defp maybe_update_sort(socket, %{"sort_field" => sf, "sort_order" => so}) do
|
||||||
|
field =
|
||||||
|
try do
|
||||||
|
String.to_existing_atom(sf)
|
||||||
|
rescue
|
||||||
|
ArgumentError -> socket.assigns.sort_field
|
||||||
|
end
|
||||||
|
|
||||||
|
order = if so in ["asc", "desc"], do: String.to_atom(so), else: socket.assigns.sort_order
|
||||||
|
|
||||||
|
socket
|
||||||
|
|> assign(:sort_field, field)
|
||||||
|
|> assign(:sort_order, order)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_update_sort(socket, _), do: socket
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,13 @@
|
||||||
</:actions>
|
</:actions>
|
||||||
</.header>
|
</.header>
|
||||||
|
|
||||||
|
<.live_component
|
||||||
|
module={MvWeb.Components.SearchBarComponent}
|
||||||
|
id="search-bar"
|
||||||
|
query={@query}
|
||||||
|
placeholder={gettext("Search...")}
|
||||||
|
/>
|
||||||
|
|
||||||
<.table
|
<.table
|
||||||
id="members"
|
id="members"
|
||||||
rows={@members}
|
rows={@members}
|
||||||
|
|
@ -45,23 +52,139 @@
|
||||||
<:col
|
<:col
|
||||||
:let={member}
|
:let={member}
|
||||||
label={
|
label={
|
||||||
sort_button(%{
|
~H"""
|
||||||
field: :first_name,
|
<.live_component
|
||||||
label: gettext("Name"),
|
module={MvWeb.Components.SortHeaderComponent}
|
||||||
sort_field: @sort_field,
|
id={:sort_first_name}
|
||||||
sort_order: @sort_order
|
field={:first_name}
|
||||||
})
|
label={gettext("First name")}
|
||||||
|
sort_field={@sort_field}
|
||||||
|
sort_order={@sort_order}
|
||||||
|
/>
|
||||||
|
"""
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{member.first_name} {member.last_name}
|
{member.first_name} {member.last_name}
|
||||||
</:col>
|
</:col>
|
||||||
<:col :let={member} label={gettext("Email")}>{member.email}</:col>
|
<:col
|
||||||
<:col :let={member} label={gettext("Street")}>{member.street}</:col>
|
:let={member}
|
||||||
<:col :let={member} label={gettext("House Number")}>{member.house_number}</:col>
|
label={
|
||||||
<:col :let={member} label={gettext("Postal Code")}>{member.postal_code}</:col>
|
~H"""
|
||||||
<:col :let={member} label={gettext("City")}>{member.city}</:col>
|
<.live_component
|
||||||
<:col :let={member} label={gettext("Phone Number")}>{member.phone_number}</:col>
|
module={MvWeb.Components.SortHeaderComponent}
|
||||||
<:col :let={member} label={gettext("Join Date")}>{member.join_date}</:col>
|
id={:sort_email}
|
||||||
|
field={:email}
|
||||||
|
label={gettext("Email")}
|
||||||
|
sort_field={@sort_field}
|
||||||
|
sort_order={@sort_order}
|
||||||
|
/>
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{member.email}
|
||||||
|
</:col>
|
||||||
|
<:col
|
||||||
|
:let={member}
|
||||||
|
label={
|
||||||
|
~H"""
|
||||||
|
<.live_component
|
||||||
|
module={MvWeb.Components.SortHeaderComponent}
|
||||||
|
id={:sort_street}
|
||||||
|
field={:street}
|
||||||
|
label={gettext("Street")}
|
||||||
|
sort_field={@sort_field}
|
||||||
|
sort_order={@sort_order}
|
||||||
|
/>
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{member.street}
|
||||||
|
</:col>
|
||||||
|
<:col
|
||||||
|
:let={member}
|
||||||
|
label={
|
||||||
|
~H"""
|
||||||
|
<.live_component
|
||||||
|
module={MvWeb.Components.SortHeaderComponent}
|
||||||
|
id={:sort_house_number}
|
||||||
|
field={:house_number}
|
||||||
|
label={gettext("House Number")}
|
||||||
|
sort_field={@sort_field}
|
||||||
|
sort_order={@sort_order}
|
||||||
|
/>
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{member.house_number}
|
||||||
|
</:col>
|
||||||
|
<:col
|
||||||
|
:let={member}
|
||||||
|
label={
|
||||||
|
~H"""
|
||||||
|
<.live_component
|
||||||
|
module={MvWeb.Components.SortHeaderComponent}
|
||||||
|
id={:sort_postal_code}
|
||||||
|
field={:postal_code}
|
||||||
|
label={gettext("Postal Code")}
|
||||||
|
sort_field={@sort_field}
|
||||||
|
sort_order={@sort_order}
|
||||||
|
/>
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{member.postal_code}
|
||||||
|
</:col>
|
||||||
|
<:col
|
||||||
|
:let={member}
|
||||||
|
label={
|
||||||
|
~H"""
|
||||||
|
<.live_component
|
||||||
|
module={MvWeb.Components.SortHeaderComponent}
|
||||||
|
id={:sort_city}
|
||||||
|
field={:city}
|
||||||
|
label={gettext("City")}
|
||||||
|
sort_field={@sort_field}
|
||||||
|
sort_order={@sort_order}
|
||||||
|
/>
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{member.city}
|
||||||
|
</:col>
|
||||||
|
<:col
|
||||||
|
:let={member}
|
||||||
|
label={
|
||||||
|
~H"""
|
||||||
|
<.live_component
|
||||||
|
module={MvWeb.Components.SortHeaderComponent}
|
||||||
|
id={:sort_phone_number}
|
||||||
|
field={:phone_number}
|
||||||
|
label={gettext("Phone Number")}
|
||||||
|
sort_field={@sort_field}
|
||||||
|
sort_order={@sort_order}
|
||||||
|
/>
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{member.phone_number}
|
||||||
|
</:col>
|
||||||
|
<:col
|
||||||
|
:let={member}
|
||||||
|
label={
|
||||||
|
~H"""
|
||||||
|
<.live_component
|
||||||
|
module={MvWeb.Components.SortHeaderComponent}
|
||||||
|
id={:sort_join_date}
|
||||||
|
field={:join_date}
|
||||||
|
label={gettext("Join Date")}
|
||||||
|
sort_field={@sort_field}
|
||||||
|
sort_order={@sort_order}
|
||||||
|
/>
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{member.join_date}
|
||||||
|
</:col>
|
||||||
|
|
||||||
<:action :let={member}>
|
<:action :let={member}>
|
||||||
<div class="sr-only">
|
<div class="sr-only">
|
||||||
|
|
|
||||||
|
|
@ -62,5 +62,5 @@ msgstr "Anmelden..."
|
||||||
msgid "Your password has successfully been reset"
|
msgid "Your password has successfully been reset"
|
||||||
msgstr "Das Passwort wurde erfolgreich zurückgesetzt"
|
msgstr "Das Passwort wurde erfolgreich zurückgesetzt"
|
||||||
|
|
||||||
msgid "Sign in with Rauthy"
|
#~ msgid "Sign in with Rauthy"
|
||||||
msgstr "Anmelden mit der Vereinscloud"
|
#~ msgstr "Anmelden mit der Vereinscloud"
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ msgstr ""
|
||||||
msgid "Actions"
|
msgid "Actions"
|
||||||
msgstr "Aktionen"
|
msgstr "Aktionen"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:77
|
#: lib/mv_web/live/member_live/index.html.heex:193
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:65
|
#: lib/mv_web/live/user_live/index.html.heex:65
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
|
|
@ -28,19 +28,19 @@ msgid "Attempting to reconnect"
|
||||||
msgstr "Verbindung wird wiederhergestellt"
|
msgstr "Verbindung wird wiederhergestellt"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:25
|
#: lib/mv_web/live/member_live/form.ex:25
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:62
|
#: lib/mv_web/live/member_live/index.html.heex:138
|
||||||
#: lib/mv_web/live/member_live/show.ex:36
|
#: lib/mv_web/live/member_live/show.ex:36
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "City"
|
msgid "City"
|
||||||
msgstr "Stadt"
|
msgstr "Stadt"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:79
|
#: lib/mv_web/live/member_live/index.html.heex:195
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:67
|
#: lib/mv_web/live/user_live/index.html.heex:67
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr "Löschen"
|
msgstr "Löschen"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:71
|
#: lib/mv_web/live/member_live/index.html.heex:187
|
||||||
#: lib/mv_web/live/user_live/form.ex:109
|
#: lib/mv_web/live/user_live/form.ex:109
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:59
|
#: lib/mv_web/live/user_live/index.html.heex:59
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -54,7 +54,7 @@ msgid "Edit Member"
|
||||||
msgstr "Mitglied bearbeiten"
|
msgstr "Mitglied bearbeiten"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:18
|
#: lib/mv_web/live/member_live/form.ex:18
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:58
|
#: lib/mv_web/live/member_live/index.html.heex:70
|
||||||
#: lib/mv_web/live/member_live/show.ex:27
|
#: lib/mv_web/live/member_live/show.ex:27
|
||||||
#: lib/mv_web/live/user_live/form.ex:14
|
#: lib/mv_web/live/user_live/form.ex:14
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:44
|
#: lib/mv_web/live/user_live/index.html.heex:44
|
||||||
|
|
@ -70,7 +70,7 @@ msgid "First Name"
|
||||||
msgstr "Vorname"
|
msgstr "Vorname"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:22
|
#: lib/mv_web/live/member_live/form.ex:22
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:64
|
#: lib/mv_web/live/member_live/index.html.heex:172
|
||||||
#: lib/mv_web/live/member_live/show.ex:33
|
#: lib/mv_web/live/member_live/show.ex:33
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Join Date"
|
msgid "Join Date"
|
||||||
|
|
@ -87,7 +87,7 @@ msgstr "Nachname"
|
||||||
msgid "New Member"
|
msgid "New Member"
|
||||||
msgstr "Neues Mitglied"
|
msgstr "Neues Mitglied"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:68
|
#: lib/mv_web/live/member_live/index.html.heex:184
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:56
|
#: lib/mv_web/live/user_live/index.html.heex:56
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Show"
|
msgid "Show"
|
||||||
|
|
@ -127,7 +127,7 @@ msgid "Exit Date"
|
||||||
msgstr "Austrittsdatum"
|
msgstr "Austrittsdatum"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:27
|
#: lib/mv_web/live/member_live/form.ex:27
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:60
|
#: lib/mv_web/live/member_live/index.html.heex:104
|
||||||
#: lib/mv_web/live/member_live/show.ex:38
|
#: lib/mv_web/live/member_live/show.ex:38
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "House Number"
|
msgid "House Number"
|
||||||
|
|
@ -146,14 +146,14 @@ msgid "Paid"
|
||||||
msgstr "Bezahlt"
|
msgstr "Bezahlt"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:21
|
#: lib/mv_web/live/member_live/form.ex:21
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:63
|
#: lib/mv_web/live/member_live/index.html.heex:155
|
||||||
#: lib/mv_web/live/member_live/show.ex:32
|
#: lib/mv_web/live/member_live/show.ex:32
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Phone Number"
|
msgid "Phone Number"
|
||||||
msgstr "Telefonnummer"
|
msgstr "Telefonnummer"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:28
|
#: lib/mv_web/live/member_live/form.ex:28
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:61
|
#: lib/mv_web/live/member_live/index.html.heex:121
|
||||||
#: lib/mv_web/live/member_live/show.ex:39
|
#: lib/mv_web/live/member_live/show.ex:39
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Postal Code"
|
msgid "Postal Code"
|
||||||
|
|
@ -173,7 +173,7 @@ msgid "Saving..."
|
||||||
msgstr "Speichern..."
|
msgstr "Speichern..."
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:26
|
#: lib/mv_web/live/member_live/form.ex:26
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:59
|
#: lib/mv_web/live/member_live/index.html.heex:87
|
||||||
#: lib/mv_web/live/member_live/show.ex:37
|
#: lib/mv_web/live/member_live/show.ex:37
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
|
|
@ -318,13 +318,12 @@ msgid "Member"
|
||||||
msgstr "Mitglied"
|
msgstr "Mitglied"
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:14
|
#: lib/mv_web/components/layouts/navbar.ex:14
|
||||||
#: lib/mv_web/live/member_live/index.ex:12
|
#: lib/mv_web/live/member_live/index.ex:8
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:3
|
#: lib/mv_web/live/member_live/index.html.heex:3
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Members"
|
msgid "Members"
|
||||||
msgstr "Mitglieder"
|
msgstr "Mitglieder"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:50
|
|
||||||
#: lib/mv_web/live/property_type_live/form.ex:16
|
#: lib/mv_web/live/property_type_live/form.ex:16
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
|
|
@ -469,11 +468,13 @@ msgid "Value type"
|
||||||
msgstr "Wertetyp"
|
msgstr "Wertetyp"
|
||||||
|
|
||||||
#: lib/mv_web/components/table_components.ex:30
|
#: lib/mv_web/components/table_components.ex:30
|
||||||
|
#: lib/mv_web/live/components/sort_header_component.ex:55
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "ascending"
|
msgid "ascending"
|
||||||
msgstr "aufsteigend"
|
msgstr "aufsteigend"
|
||||||
|
|
||||||
#: lib/mv_web/components/table_components.ex:30
|
#: lib/mv_web/components/table_components.ex:30
|
||||||
|
#: lib/mv_web/live/components/sort_header_component.ex:56
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "descending"
|
msgid "descending"
|
||||||
msgstr "absteigend"
|
msgstr "absteigend"
|
||||||
|
|
@ -553,7 +554,17 @@ msgstr "Passwort setzen"
|
||||||
msgid "User will be created without a password. Check 'Set Password' to add one."
|
msgid "User will be created without a password. Check 'Set Password' to add one."
|
||||||
msgstr "Benutzer wird ohne Passwort erstellt. Aktivieren Sie 'Passwort setzen', um eines hinzuzufügen."
|
msgstr "Benutzer wird ohne Passwort erstellt. Aktivieren Sie 'Passwort setzen', um eines hinzuzufügen."
|
||||||
|
|
||||||
#: lib/mv_web/auth_overrides.ex:30
|
#: lib/mv_web/live/components/sort_header_component.ex:60
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "or"
|
msgid "Click to sort"
|
||||||
msgstr "oder"
|
msgstr "Klicke um zu sortieren"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/index.html.heex:53
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "First name"
|
||||||
|
msgstr "Vorname"
|
||||||
|
|
||||||
|
#~ #: lib/mv_web/auth_overrides.ex:30
|
||||||
|
#~ #, elixir-autogen, elixir-format
|
||||||
|
#~ msgid "or"
|
||||||
|
#~ msgstr "oder"
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ msgstr ""
|
||||||
msgid "Actions"
|
msgid "Actions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:77
|
#: lib/mv_web/live/member_live/index.html.heex:193
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:65
|
#: lib/mv_web/live/user_live/index.html.heex:65
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
|
|
@ -29,19 +29,19 @@ msgid "Attempting to reconnect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:25
|
#: lib/mv_web/live/member_live/form.ex:25
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:62
|
#: lib/mv_web/live/member_live/index.html.heex:138
|
||||||
#: lib/mv_web/live/member_live/show.ex:36
|
#: lib/mv_web/live/member_live/show.ex:36
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "City"
|
msgid "City"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:79
|
#: lib/mv_web/live/member_live/index.html.heex:195
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:67
|
#: lib/mv_web/live/user_live/index.html.heex:67
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:71
|
#: lib/mv_web/live/member_live/index.html.heex:187
|
||||||
#: lib/mv_web/live/user_live/form.ex:109
|
#: lib/mv_web/live/user_live/form.ex:109
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:59
|
#: lib/mv_web/live/user_live/index.html.heex:59
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -55,7 +55,7 @@ msgid "Edit Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:18
|
#: lib/mv_web/live/member_live/form.ex:18
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:58
|
#: lib/mv_web/live/member_live/index.html.heex:70
|
||||||
#: lib/mv_web/live/member_live/show.ex:27
|
#: lib/mv_web/live/member_live/show.ex:27
|
||||||
#: lib/mv_web/live/user_live/form.ex:14
|
#: lib/mv_web/live/user_live/form.ex:14
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:44
|
#: lib/mv_web/live/user_live/index.html.heex:44
|
||||||
|
|
@ -71,7 +71,7 @@ msgid "First Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:22
|
#: lib/mv_web/live/member_live/form.ex:22
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:64
|
#: lib/mv_web/live/member_live/index.html.heex:172
|
||||||
#: lib/mv_web/live/member_live/show.ex:33
|
#: lib/mv_web/live/member_live/show.ex:33
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Join Date"
|
msgid "Join Date"
|
||||||
|
|
@ -88,7 +88,7 @@ msgstr ""
|
||||||
msgid "New Member"
|
msgid "New Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:68
|
#: lib/mv_web/live/member_live/index.html.heex:184
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:56
|
#: lib/mv_web/live/user_live/index.html.heex:56
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Show"
|
msgid "Show"
|
||||||
|
|
@ -128,7 +128,7 @@ msgid "Exit Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:27
|
#: lib/mv_web/live/member_live/form.ex:27
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:60
|
#: lib/mv_web/live/member_live/index.html.heex:104
|
||||||
#: lib/mv_web/live/member_live/show.ex:38
|
#: lib/mv_web/live/member_live/show.ex:38
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "House Number"
|
msgid "House Number"
|
||||||
|
|
@ -147,14 +147,14 @@ msgid "Paid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:21
|
#: lib/mv_web/live/member_live/form.ex:21
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:63
|
#: lib/mv_web/live/member_live/index.html.heex:155
|
||||||
#: lib/mv_web/live/member_live/show.ex:32
|
#: lib/mv_web/live/member_live/show.ex:32
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Phone Number"
|
msgid "Phone Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:28
|
#: lib/mv_web/live/member_live/form.ex:28
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:61
|
#: lib/mv_web/live/member_live/index.html.heex:121
|
||||||
#: lib/mv_web/live/member_live/show.ex:39
|
#: lib/mv_web/live/member_live/show.ex:39
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Postal Code"
|
msgid "Postal Code"
|
||||||
|
|
@ -174,7 +174,7 @@ msgid "Saving..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:26
|
#: lib/mv_web/live/member_live/form.ex:26
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:59
|
#: lib/mv_web/live/member_live/index.html.heex:87
|
||||||
#: lib/mv_web/live/member_live/show.ex:37
|
#: lib/mv_web/live/member_live/show.ex:37
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
|
|
@ -319,13 +319,12 @@ msgid "Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:14
|
#: lib/mv_web/components/layouts/navbar.ex:14
|
||||||
#: lib/mv_web/live/member_live/index.ex:12
|
#: lib/mv_web/live/member_live/index.ex:8
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:3
|
#: lib/mv_web/live/member_live/index.html.heex:3
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Members"
|
msgid "Members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:50
|
|
||||||
#: lib/mv_web/live/property_type_live/form.ex:16
|
#: lib/mv_web/live/property_type_live/form.ex:16
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
|
|
@ -470,11 +469,13 @@ msgid "Value type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/table_components.ex:30
|
#: lib/mv_web/components/table_components.ex:30
|
||||||
|
#: lib/mv_web/live/components/sort_header_component.ex:55
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "ascending"
|
msgid "ascending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/table_components.ex:30
|
#: lib/mv_web/components/table_components.ex:30
|
||||||
|
#: lib/mv_web/live/components/sort_header_component.ex:56
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "descending"
|
msgid "descending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -554,7 +555,12 @@ msgstr ""
|
||||||
msgid "User will be created without a password. Check 'Set Password' to add one."
|
msgid "User will be created without a password. Check 'Set Password' to add one."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/auth_overrides.ex:30
|
#: lib/mv_web/live/components/sort_header_component.ex:60
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "or"
|
msgid "Click to sort"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/index.html.heex:53
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "First name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -59,5 +59,5 @@ msgstr ""
|
||||||
msgid "Your password has successfully been reset"
|
msgid "Your password has successfully been reset"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Sign in with Rauthy"
|
#~ msgid "Sign in with Rauthy"
|
||||||
msgstr "Sign in with Vereinscloud"
|
#~ msgstr "Sign in with Vereinscloud"
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ msgstr ""
|
||||||
msgid "Actions"
|
msgid "Actions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:77
|
#: lib/mv_web/live/member_live/index.html.heex:193
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:65
|
#: lib/mv_web/live/user_live/index.html.heex:65
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
|
|
@ -29,19 +29,19 @@ msgid "Attempting to reconnect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:25
|
#: lib/mv_web/live/member_live/form.ex:25
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:62
|
#: lib/mv_web/live/member_live/index.html.heex:138
|
||||||
#: lib/mv_web/live/member_live/show.ex:36
|
#: lib/mv_web/live/member_live/show.ex:36
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "City"
|
msgid "City"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:79
|
#: lib/mv_web/live/member_live/index.html.heex:195
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:67
|
#: lib/mv_web/live/user_live/index.html.heex:67
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:71
|
#: lib/mv_web/live/member_live/index.html.heex:187
|
||||||
#: lib/mv_web/live/user_live/form.ex:109
|
#: lib/mv_web/live/user_live/form.ex:109
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:59
|
#: lib/mv_web/live/user_live/index.html.heex:59
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -55,7 +55,7 @@ msgid "Edit Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:18
|
#: lib/mv_web/live/member_live/form.ex:18
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:58
|
#: lib/mv_web/live/member_live/index.html.heex:70
|
||||||
#: lib/mv_web/live/member_live/show.ex:27
|
#: lib/mv_web/live/member_live/show.ex:27
|
||||||
#: lib/mv_web/live/user_live/form.ex:14
|
#: lib/mv_web/live/user_live/form.ex:14
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:44
|
#: lib/mv_web/live/user_live/index.html.heex:44
|
||||||
|
|
@ -71,7 +71,7 @@ msgid "First Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:22
|
#: lib/mv_web/live/member_live/form.ex:22
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:64
|
#: lib/mv_web/live/member_live/index.html.heex:172
|
||||||
#: lib/mv_web/live/member_live/show.ex:33
|
#: lib/mv_web/live/member_live/show.ex:33
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Join Date"
|
msgid "Join Date"
|
||||||
|
|
@ -88,7 +88,7 @@ msgstr ""
|
||||||
msgid "New Member"
|
msgid "New Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:68
|
#: lib/mv_web/live/member_live/index.html.heex:184
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:56
|
#: lib/mv_web/live/user_live/index.html.heex:56
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Show"
|
msgid "Show"
|
||||||
|
|
@ -128,7 +128,7 @@ msgid "Exit Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:27
|
#: lib/mv_web/live/member_live/form.ex:27
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:60
|
#: lib/mv_web/live/member_live/index.html.heex:104
|
||||||
#: lib/mv_web/live/member_live/show.ex:38
|
#: lib/mv_web/live/member_live/show.ex:38
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "House Number"
|
msgid "House Number"
|
||||||
|
|
@ -147,14 +147,14 @@ msgid "Paid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:21
|
#: lib/mv_web/live/member_live/form.ex:21
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:63
|
#: lib/mv_web/live/member_live/index.html.heex:155
|
||||||
#: lib/mv_web/live/member_live/show.ex:32
|
#: lib/mv_web/live/member_live/show.ex:32
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Phone Number"
|
msgid "Phone Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:28
|
#: lib/mv_web/live/member_live/form.ex:28
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:61
|
#: lib/mv_web/live/member_live/index.html.heex:121
|
||||||
#: lib/mv_web/live/member_live/show.ex:39
|
#: lib/mv_web/live/member_live/show.ex:39
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Postal Code"
|
msgid "Postal Code"
|
||||||
|
|
@ -174,7 +174,7 @@ msgid "Saving..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:26
|
#: lib/mv_web/live/member_live/form.ex:26
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:59
|
#: lib/mv_web/live/member_live/index.html.heex:87
|
||||||
#: lib/mv_web/live/member_live/show.ex:37
|
#: lib/mv_web/live/member_live/show.ex:37
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
|
|
@ -319,13 +319,12 @@ msgid "Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:14
|
#: lib/mv_web/components/layouts/navbar.ex:14
|
||||||
#: lib/mv_web/live/member_live/index.ex:12
|
#: lib/mv_web/live/member_live/index.ex:8
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:3
|
#: lib/mv_web/live/member_live/index.html.heex:3
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Members"
|
msgid "Members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:50
|
|
||||||
#: lib/mv_web/live/property_type_live/form.ex:16
|
#: lib/mv_web/live/property_type_live/form.ex:16
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
|
|
@ -470,11 +469,13 @@ msgid "Value type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/table_components.ex:30
|
#: lib/mv_web/components/table_components.ex:30
|
||||||
|
#: lib/mv_web/live/components/sort_header_component.ex:55
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "ascending"
|
msgid "ascending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/table_components.ex:30
|
#: lib/mv_web/components/table_components.ex:30
|
||||||
|
#: lib/mv_web/live/components/sort_header_component.ex:56
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "descending"
|
msgid "descending"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -554,7 +555,17 @@ msgstr "Set Password"
|
||||||
msgid "User will be created without a password. Check 'Set Password' to add one."
|
msgid "User will be created without a password. Check 'Set Password' to add one."
|
||||||
msgstr "User will be created without a password. Check 'Set Password' to add one."
|
msgstr "User will be created without a password. Check 'Set Password' to add one."
|
||||||
|
|
||||||
#: lib/mv_web/auth_overrides.ex:30
|
#: lib/mv_web/live/components/sort_header_component.ex:60
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "or"
|
msgid "Click to sort"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/index.html.heex:53
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "First name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#~ #: lib/mv_web/auth_overrides.ex:30
|
||||||
|
#~ #, elixir-autogen, elixir-format
|
||||||
|
#~ msgid "or"
|
||||||
|
#~ msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
defmodule Mv.Repo.Migrations.AddSearchVectorToMembers do
|
||||||
|
@moduledoc """
|
||||||
|
Updates resources based on their most recent snapshots.
|
||||||
|
|
||||||
|
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||||
|
"""
|
||||||
|
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
alter table(:members) do
|
||||||
|
add :search_vector, :tsvector
|
||||||
|
end
|
||||||
|
|
||||||
|
execute("""
|
||||||
|
CREATE INDEX members_search_vector_idx
|
||||||
|
ON members
|
||||||
|
USING GIN (search_vector)
|
||||||
|
""")
|
||||||
|
|
||||||
|
# Eigene Trigger-Funktion mit Gewichtung
|
||||||
|
execute("""
|
||||||
|
CREATE FUNCTION members_search_vector_trigger() RETURNS trigger AS $$
|
||||||
|
BEGIN
|
||||||
|
NEW.search_vector :=
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.first_name, '')), 'A') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.last_name, '')), 'A') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.email, '')), 'B') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.birth_date::text, '')), 'C') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.phone_number, '')), 'C') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.join_date::text, '')), 'D') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.exit_date::text, '')), 'D') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.notes, '')), 'B') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.city, '')), 'C') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.street, '')), 'C') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.house_number::text, '')), 'C') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(NEW.postal_code::text, '')), 'C');
|
||||||
|
RETURN NEW;
|
||||||
|
END
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
""")
|
||||||
|
|
||||||
|
execute("""
|
||||||
|
CREATE TRIGGER update_search_vector
|
||||||
|
BEFORE INSERT OR UPDATE ON members
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION members_search_vector_trigger()
|
||||||
|
""")
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
execute("DROP TRIGGER IF EXISTS update_search_vector ON members")
|
||||||
|
execute("DROP FUNCTION IF EXISTS members_search_vector_trigger()")
|
||||||
|
execute("DROP INDEX IF EXISTS members_search_vector_idx")
|
||||||
|
|
||||||
|
alter table(:members) do
|
||||||
|
remove :search_vector
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
199
priv/resource_snapshots/repo/members/20250912085235.json
Normal file
199
priv/resource_snapshots/repo/members/20250912085235.json
Normal file
|
|
@ -0,0 +1,199 @@
|
||||||
|
{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "fragment(\"uuid_generate_v7()\")",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "id",
|
||||||
|
"type": "uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "first_name",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "last_name",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "email",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "birth_date",
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "paid",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "phone_number",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "join_date",
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "exit_date",
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "notes",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "city",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "street",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "house_number",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "postal_code",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "search_vectors",
|
||||||
|
"type": "tsvector"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"custom_statements": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "3B162FD69B92BF8258DB56BA0CBB6108FBE996B1F7231C5F2D9EC53D956EFC75",
|
||||||
|
"identities": [],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.Mv.Repo",
|
||||||
|
"schema": null,
|
||||||
|
"table": "members"
|
||||||
|
}
|
||||||
33
test/mv_web/components/search_bar_component_test.exs
Normal file
33
test/mv_web/components/search_bar_component_test.exs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
defmodule MvWeb.Components.SearchBarComponentTest do
|
||||||
|
use MvWeb.ConnCase, async: true
|
||||||
|
import Phoenix.LiveViewTest
|
||||||
|
|
||||||
|
describe "SearchBarComponent" do
|
||||||
|
test "renders with placeholder", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
|
assert has_element?(view, "input[placeholder='Search...']")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "updates query when user types", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
|
# simulate search input and check that other members are not listed
|
||||||
|
html =
|
||||||
|
view
|
||||||
|
|> element("form[role=search]")
|
||||||
|
|> render_change(%{"query" => "Friedrich"})
|
||||||
|
|
||||||
|
refute html =~ "Greta"
|
||||||
|
|
||||||
|
html =
|
||||||
|
view
|
||||||
|
|> element("form[role=search]")
|
||||||
|
|> render_change(%{"query" => "Greta"})
|
||||||
|
|
||||||
|
refute html =~ "Friedrich"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
12
test/mv_web/components/sort_header_component_test.exs
Normal file
12
test/mv_web/components/sort_header_component_test.exs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
defmodule MvWeb.Components.SortHeaderComponentTest do
|
||||||
|
use MvWeb.ConnCase, async: true
|
||||||
|
use Phoenix.Component
|
||||||
|
import Phoenix.LiveViewTest
|
||||||
|
|
||||||
|
test "renders sort header with correct attributes", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
|
assert view |> element("[data-testid='first_name']")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -55,7 +55,6 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
|
|
||||||
test "shows translated flash message after creating a member in English", %{conn: conn} do
|
test "shows translated flash message after creating a member in English", %{conn: conn} do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn_with_oidc_user(conn)
|
||||||
conn = Plug.Test.init_test_session(conn, locale: "en")
|
|
||||||
{:ok, form_view, _html} = live(conn, "/members/new")
|
{:ok, form_view, _html} = live(conn, "/members/new")
|
||||||
|
|
||||||
form_data = %{
|
form_data = %{
|
||||||
|
|
@ -73,4 +72,52 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
|
|
||||||
assert has_element?(index_view, "#flash-group", "Member create successfully")
|
assert has_element?(index_view, "#flash-group", "Member create successfully")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "sorting interaction" do
|
||||||
|
test "clicking a column header toggles sort order and updates the URL", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
|
# The component data test ids are built as "<field>"
|
||||||
|
# First click – should sort ASC
|
||||||
|
view
|
||||||
|
|> element("[data-testid='email']")
|
||||||
|
|> render_click()
|
||||||
|
|
||||||
|
# The LiveView pushes a patch with the new query params
|
||||||
|
assert_patch(view, "/members?sort_field=email&sort_order=asc")
|
||||||
|
|
||||||
|
# Second click – toggles to DESC
|
||||||
|
view
|
||||||
|
|> element("[data-testid='email']")
|
||||||
|
|> render_click()
|
||||||
|
|
||||||
|
assert_patch(view, "/members?sort_field=email&sort_order=desc")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "URL param handling" do
|
||||||
|
test "handle_params reads sort query and applies it", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
url = "/members?sort_field=email&sort_order=desc"
|
||||||
|
|
||||||
|
conn = get(conn, url)
|
||||||
|
|
||||||
|
# The LiveView must have parsed the params and stored them as atoms.
|
||||||
|
assert conn.assigns.sort_field == :email
|
||||||
|
assert conn.assigns.sort_order == :desc
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "handle_info(:search_changed) updates assigns with search results", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
|
|
||||||
|
send(view.pid, {:search_changed, "Friedrich"})
|
||||||
|
|
||||||
|
state = :sys.get_state(view.pid)
|
||||||
|
|
||||||
|
assert state.socket.assigns.query == "Friedrich"
|
||||||
|
assert is_list(state.socket.assigns.members)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue