Merge pull request 'create logical link between users and members closes #164' (#172) from feature/user-member-relation into main
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #172 Reviewed-by: rafael <rafael@noreply.git.local-it.org>
This commit is contained in:
commit
c116e39b56
27 changed files with 2057 additions and 245 deletions
|
|
@ -12,6 +12,12 @@ defmodule Mv.Accounts.User do
|
||||||
postgres do
|
postgres do
|
||||||
table "users"
|
table "users"
|
||||||
repo Mv.Repo
|
repo Mv.Repo
|
||||||
|
|
||||||
|
references do
|
||||||
|
# When a member is deleted, set the user's member_id to NULL
|
||||||
|
# This allows users to continue existing even if their linked member is removed
|
||||||
|
reference :member, on_delete: :nilify
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
@ -60,15 +66,77 @@ defmodule Mv.Accounts.User do
|
||||||
end
|
end
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
defaults [:read, :create, :destroy, :update]
|
# Default actions kept for framework/tooling integration:
|
||||||
|
# - :create -> Used by AshAdmin's generated "Create" UI and by generic
|
||||||
|
# AshPhoenix helpers that assume a default create action.
|
||||||
|
# It does NOT manage the :member relationship. For admin
|
||||||
|
# flows that may link an existing member, use :create_user.
|
||||||
|
# - :read -> Standard read used across the app and by admin tooling.
|
||||||
|
# - :destroy-> Standard delete used by admin tooling and maintenance tasks.
|
||||||
|
defaults [:read, :create, :destroy]
|
||||||
|
|
||||||
|
# Primary generic update action:
|
||||||
|
# - Selected by AshAdmin's generated "Edit" UI and generic AshPhoenix
|
||||||
|
# helpers that assume a default update action.
|
||||||
|
# - Intended for simple attribute updates (e.g., :email) and scenarios
|
||||||
|
# that do NOT need to manage the :member relationship.
|
||||||
|
# - For linking/unlinking a member (and the related validations), prefer
|
||||||
|
# the specialized :update_user action below.
|
||||||
|
update :update do
|
||||||
|
primary? true
|
||||||
|
|
||||||
|
# Required because custom validation functions (email validation, member relationship validation)
|
||||||
|
# cannot be executed atomically. These validations need to query the database and perform
|
||||||
|
# complex checks that are not supported in atomic operations.
|
||||||
|
require_atomic? false
|
||||||
|
end
|
||||||
|
|
||||||
create :create_user do
|
create :create_user do
|
||||||
|
description "Creates a new user with optional member relationship. The member relationship is managed through the :member argument."
|
||||||
|
# Only accept email directly - member_id is NOT in accept list
|
||||||
|
# This prevents direct foreign key manipulation, forcing use of manage_relationship
|
||||||
accept [:email]
|
accept [:email]
|
||||||
|
# Allow member to be passed as argument for relationship management
|
||||||
|
argument :member, :map, allow_nil?: true
|
||||||
upsert? true
|
upsert? true
|
||||||
|
|
||||||
|
# Manage the member relationship during user creation
|
||||||
|
change manage_relationship(:member, :member,
|
||||||
|
# Look up existing member and relate to it
|
||||||
|
on_lookup: :relate,
|
||||||
|
# Error if member doesn't exist in database
|
||||||
|
on_no_match: :error,
|
||||||
|
# If member already linked to this user, ignore (shouldn't happen in create)
|
||||||
|
on_match: :ignore,
|
||||||
|
# If no member provided, that's fine (optional relationship)
|
||||||
|
on_missing: :ignore
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
update :update_user do
|
update :update_user do
|
||||||
|
description "Updates a user and manages the optional member relationship. To change an existing member link, first remove it (set member to nil), then add the new one."
|
||||||
|
# Only accept email directly - member_id is NOT in accept list
|
||||||
|
# This prevents direct foreign key manipulation, forcing use of manage_relationship
|
||||||
accept [:email]
|
accept [:email]
|
||||||
|
# Allow member to be passed as argument for relationship management
|
||||||
|
argument :member, :map, allow_nil?: true
|
||||||
|
|
||||||
|
# Required because custom validation functions (email validation, member relationship validation)
|
||||||
|
# cannot be executed atomically. These validations need to query the database and perform
|
||||||
|
# complex checks that are not supported in atomic operations.
|
||||||
|
require_atomic? false
|
||||||
|
|
||||||
|
# Manage the member relationship during user update
|
||||||
|
change manage_relationship(:member, :member,
|
||||||
|
# Look up existing member and relate to it
|
||||||
|
on_lookup: :relate,
|
||||||
|
# Error if member doesn't exist in database
|
||||||
|
on_no_match: :error,
|
||||||
|
# If same member provided, that's fine (allows updates with same member)
|
||||||
|
on_match: :ignore,
|
||||||
|
# If no member provided, remove existing relationship (allows member removal)
|
||||||
|
on_missing: :unrelate
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Admin action for direct password changes in admin panel
|
# Admin action for direct password changes in admin panel
|
||||||
|
|
@ -76,6 +144,7 @@ defmodule Mv.Accounts.User do
|
||||||
update :admin_set_password do
|
update :admin_set_password do
|
||||||
accept [:email]
|
accept [:email]
|
||||||
argument :password, :string, allow_nil?: false, sensitive?: true
|
argument :password, :string, allow_nil?: false, sensitive?: true
|
||||||
|
require_atomic? false
|
||||||
|
|
||||||
# Set the strategy context that HashPasswordChange expects
|
# Set the strategy context that HashPasswordChange expects
|
||||||
change set_context(%{strategy_name: :password})
|
change set_context(%{strategy_name: :password})
|
||||||
|
|
@ -122,8 +191,54 @@ defmodule Mv.Accounts.User do
|
||||||
# Global validations - applied to all relevant actions
|
# Global validations - applied to all relevant actions
|
||||||
validations do
|
validations do
|
||||||
# Password strength policy: minimum 8 characters for all password-related actions
|
# Password strength policy: minimum 8 characters for all password-related actions
|
||||||
validate string_length(:password, min: 8) do
|
validate string_length(:password, min: 8),
|
||||||
where action_is([:register_with_password, :admin_set_password])
|
where: [action_is([:register_with_password, :admin_set_password])],
|
||||||
|
message: "must have length of at least 8"
|
||||||
|
|
||||||
|
# Email validation with EctoCommons.EmailValidator (same as Member)
|
||||||
|
# This ensures consistency between User and Member email validation
|
||||||
|
validate fn changeset, _ ->
|
||||||
|
# Get email from attribute (Ash.CiString) and convert to string
|
||||||
|
email = Ash.Changeset.get_attribute(changeset, :email)
|
||||||
|
email_string = if email, do: to_string(email), else: nil
|
||||||
|
|
||||||
|
# Only validate if email is present
|
||||||
|
if email_string do
|
||||||
|
changeset2 =
|
||||||
|
{%{}, %{email: :string}}
|
||||||
|
|> Ecto.Changeset.cast(%{email: email_string}, [:email])
|
||||||
|
|> EctoCommons.EmailValidator.validate_email(:email, checks: [:html_input, :pow])
|
||||||
|
|
||||||
|
if changeset2.valid? do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:error, field: :email, message: "is not a valid email"}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Prevent overwriting existing member relationship
|
||||||
|
# This validation ensures race condition safety by requiring explicit two-step process:
|
||||||
|
# 1. Remove existing member (set member to nil)
|
||||||
|
# 2. Add new member
|
||||||
|
# This prevents accidental overwrites when multiple admins work simultaneously
|
||||||
|
validate fn changeset, _context ->
|
||||||
|
member_arg = Ash.Changeset.get_argument(changeset, :member)
|
||||||
|
current_member_id = changeset.data.member_id
|
||||||
|
|
||||||
|
# Only trigger if:
|
||||||
|
# - member argument is provided AND has an ID
|
||||||
|
# - user currently has a member
|
||||||
|
# - the new member ID is different from current member ID
|
||||||
|
if member_arg && member_arg[:id] && current_member_id &&
|
||||||
|
member_arg[:id] != current_member_id do
|
||||||
|
{:error,
|
||||||
|
field: :member, message: "User already has a member. Remove existing member first."}
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -140,18 +255,28 @@ defmodule Mv.Accounts.User do
|
||||||
attributes do
|
attributes do
|
||||||
uuid_primary_key :id
|
uuid_primary_key :id
|
||||||
|
|
||||||
attribute :email, :ci_string, allow_nil?: false, public?: true
|
attribute :email, :ci_string do
|
||||||
|
allow_nil? false
|
||||||
|
public? true
|
||||||
|
# Same constraints as Member email for consistency
|
||||||
|
constraints min_length: 5, max_length: 254
|
||||||
|
end
|
||||||
|
|
||||||
attribute :hashed_password, :string, sensitive?: true, allow_nil?: true
|
attribute :hashed_password, :string, sensitive?: true, allow_nil?: true
|
||||||
attribute :oidc_id, :string, allow_nil?: true
|
attribute :oidc_id, :string, allow_nil?: true
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
|
# 1:1 relationship - User can optionally belong to one Member
|
||||||
|
# This automatically creates a `member_id` attribute in the User table
|
||||||
|
# The relationship is optional (allow_nil? true by default)
|
||||||
belongs_to :member, Mv.Membership.Member
|
belongs_to :member, Mv.Membership.Member
|
||||||
end
|
end
|
||||||
|
|
||||||
identities do
|
identities do
|
||||||
identity :unique_email, [:email]
|
identity :unique_email, [:email]
|
||||||
identity :unique_oidc_id, [:oidc_id]
|
identity :unique_oidc_id, [:oidc_id]
|
||||||
|
identity :unique_member, [:member_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
# You can customize this if you wish, but this is a safe default that
|
# You can customize this if you wish, but this is a safe default that
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,11 @@ defmodule Mv.Membership.Member do
|
||||||
|
|
||||||
create :create_member do
|
create :create_member do
|
||||||
primary? true
|
primary? true
|
||||||
|
# Properties can be created along with member
|
||||||
argument :properties, {:array, :map}
|
argument :properties, {:array, :map}
|
||||||
|
# Allow user to be passed as argument for relationship management
|
||||||
|
# user_id is NOT in accept list to prevent direct foreign key manipulation
|
||||||
|
argument :user, :map, allow_nil?: true
|
||||||
|
|
||||||
accept [
|
accept [
|
||||||
:first_name,
|
:first_name,
|
||||||
|
|
@ -32,12 +36,29 @@ defmodule Mv.Membership.Member do
|
||||||
]
|
]
|
||||||
|
|
||||||
change manage_relationship(:properties, type: :create)
|
change manage_relationship(:properties, type: :create)
|
||||||
|
|
||||||
|
# Manage the user relationship during member creation
|
||||||
|
change manage_relationship(:user, :user,
|
||||||
|
# Look up existing user and relate to it
|
||||||
|
on_lookup: :relate,
|
||||||
|
# Error if user doesn't exist in database
|
||||||
|
on_no_match: :error,
|
||||||
|
# Error if user is already linked to another member (prevents "stealing")
|
||||||
|
on_match: :error,
|
||||||
|
# If no user provided, that's fine (optional relationship)
|
||||||
|
on_missing: :ignore
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
update :update_member do
|
update :update_member do
|
||||||
primary? true
|
primary? true
|
||||||
|
# Required because custom validation function cannot be done atomically
|
||||||
require_atomic? false
|
require_atomic? false
|
||||||
|
# Properties can be updated or created along with member
|
||||||
argument :properties, {:array, :map}
|
argument :properties, {:array, :map}
|
||||||
|
# Allow user to be passed as argument for relationship management
|
||||||
|
# user_id is NOT in accept list to prevent direct foreign key manipulation
|
||||||
|
argument :user, :map, allow_nil?: true
|
||||||
|
|
||||||
accept [
|
accept [
|
||||||
:first_name,
|
:first_name,
|
||||||
|
|
@ -56,6 +77,18 @@ defmodule Mv.Membership.Member do
|
||||||
]
|
]
|
||||||
|
|
||||||
change manage_relationship(:properties, on_match: :update, on_no_match: :create)
|
change manage_relationship(:properties, on_match: :update, on_no_match: :create)
|
||||||
|
|
||||||
|
# Manage the user relationship during member update
|
||||||
|
change manage_relationship(:user, :user,
|
||||||
|
# Look up existing user and relate to it
|
||||||
|
on_lookup: :relate,
|
||||||
|
# Error if user doesn't exist in database
|
||||||
|
on_no_match: :error,
|
||||||
|
# Error if user is already linked to another member (prevents "stealing")
|
||||||
|
on_match: :error,
|
||||||
|
# If no user provided, remove existing relationship (allows user removal)
|
||||||
|
on_missing: :unrelate
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -67,6 +100,40 @@ defmodule Mv.Membership.Member do
|
||||||
validate present(:last_name)
|
validate present(:last_name)
|
||||||
validate present(:email)
|
validate present(:email)
|
||||||
|
|
||||||
|
# Prevent linking to a user that already has a member
|
||||||
|
# This validation prevents "stealing" users from other members by checking
|
||||||
|
# if the target user is already linked to a different member
|
||||||
|
# This is necessary because manage_relationship's on_match: :error only checks
|
||||||
|
# if the user is already linked to THIS specific member, not ANY member
|
||||||
|
validate fn changeset, _context ->
|
||||||
|
user_arg = Ash.Changeset.get_argument(changeset, :user)
|
||||||
|
|
||||||
|
if user_arg && user_arg[:id] do
|
||||||
|
user_id = user_arg[:id]
|
||||||
|
current_member_id = changeset.data.id
|
||||||
|
|
||||||
|
# Check the current state of the user in the database
|
||||||
|
case Ash.get(Mv.Accounts.User, user_id) do
|
||||||
|
# User is free to be linked
|
||||||
|
{:ok, %{member_id: nil}} ->
|
||||||
|
:ok
|
||||||
|
|
||||||
|
# User already linked to this member (update scenario)
|
||||||
|
{:ok, %{member_id: ^current_member_id}} ->
|
||||||
|
:ok
|
||||||
|
|
||||||
|
{:ok, %{member_id: _other_member_id}} ->
|
||||||
|
# User is linked to a different member - prevent "stealing"
|
||||||
|
{:error, field: :user, message: "User is already linked to another member"}
|
||||||
|
|
||||||
|
{:error, _} ->
|
||||||
|
{:error, field: :user, message: "User not found"}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Birth date not in the future
|
# Birth date not in the future
|
||||||
validate compare(:birth_date, less_than_or_equal_to: &Date.utc_today/0),
|
validate compare(:birth_date, less_than_or_equal_to: &Date.utc_today/0),
|
||||||
where: [present(:birth_date)],
|
where: [present(:birth_date)],
|
||||||
|
|
@ -175,5 +242,14 @@ defmodule Mv.Membership.Member do
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
has_many :properties, Mv.Membership.Property
|
has_many :properties, Mv.Membership.Property
|
||||||
|
# 1:1 relationship - Member can optionally have one User
|
||||||
|
# This references the User's member_id attribute
|
||||||
|
# The relationship is optional (allow_nil? true by default)
|
||||||
|
has_one :user, Mv.Accounts.User
|
||||||
|
end
|
||||||
|
|
||||||
|
# Define identities for upsert operations
|
||||||
|
identities do
|
||||||
|
identity :unique_email, [:email]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -42,4 +42,10 @@ defmodule Mv.Membership.Property do
|
||||||
calculations do
|
calculations do
|
||||||
calculate :value_to_string, :string, expr(value[:value] <> "")
|
calculate :value_to_string, :string, expr(value[:value] <> "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Ensure a member can only have one property per property type
|
||||||
|
# For example: A member can have only one "email" property, one "phone" property, etc.
|
||||||
|
identities do
|
||||||
|
identity :unique_property_per_member, [:member_id, :property_type_id]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -16,20 +16,27 @@ defmodule MvWeb.Layouts.Navbar do
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<a class="btn btn-ghost text-xl">Mitgliederverwaltung</a>
|
<a class="btn btn-ghost text-xl">Mitgliederverwaltung</a>
|
||||||
<ul class="menu menu-horizontal bg-base-200">
|
<ul class="menu menu-horizontal bg-base-200">
|
||||||
<li><a href="/members">{gettext("Members")}</a></li>
|
<li><.link navigate="/members">{gettext("Members")}</.link></li>
|
||||||
<li><a>Transaktionen</a></li>
|
<li><.link navigate="/users">{gettext("Users")}</.link></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<form method="post" action="/set_locale" class="mr-4">
|
<form method="post" action="/set_locale" class="mr-4">
|
||||||
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
|
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
|
||||||
<select name="locale" onchange="this.form.submit()" class="select select-sm">
|
<label class="sr-only" for="locale-select">{gettext("Select language")}</label>
|
||||||
|
<select
|
||||||
|
id="locale-select"
|
||||||
|
name="locale"
|
||||||
|
onchange="this.form.submit()"
|
||||||
|
class="select select-sm"
|
||||||
|
aria-label={gettext("Select language")}
|
||||||
|
>
|
||||||
<option value="de" selected={Gettext.get_locale() == "de"}>Deutsch</option>
|
<option value="de" selected={Gettext.get_locale() == "de"}>Deutsch</option>
|
||||||
<option value="en" selected={Gettext.get_locale() == "en"}>English</option>
|
<option value="en" selected={Gettext.get_locale() == "en"}>English</option>
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
<!-- Daisy UI Theme Toggle for dark and light mode-->
|
<!-- Daisy UI Theme Toggle for dark and light mode-->
|
||||||
<label class="flex cursor-pointer gap-2">
|
<label class="flex cursor-pointer gap-2" aria-label={gettext("Toggle dark mode")}>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="20"
|
width="20"
|
||||||
|
|
@ -40,11 +47,17 @@ defmodule MvWeb.Layouts.Navbar do
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<circle cx="12" cy="12" r="5" />
|
<circle cx="12" cy="12" r="5" />
|
||||||
<path d="M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4" />
|
<path d="M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4" />
|
||||||
</svg>
|
</svg>
|
||||||
<input type="checkbox" value="dark" class="toggle theme-controller" />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
value="dark"
|
||||||
|
class="toggle theme-controller"
|
||||||
|
aria-label={gettext("Toggle dark mode")}
|
||||||
|
/>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="20"
|
width="20"
|
||||||
|
|
@ -55,6 +68,7 @@ defmodule MvWeb.Layouts.Navbar do
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,9 @@ defmodule MvWeb.MemberLive.Show do
|
||||||
<:subtitle>{gettext("This is a member record from your database.")}</:subtitle>
|
<:subtitle>{gettext("This is a member record from your database.")}</:subtitle>
|
||||||
|
|
||||||
<:actions>
|
<:actions>
|
||||||
<.button navigate={~p"/members"}>
|
<.button navigate={~p"/members"} aria-label={gettext("Back to members list")}>
|
||||||
<.icon name="hero-arrow-left" />
|
<.icon name="hero-arrow-left" />
|
||||||
|
<span class="sr-only">{gettext("Back to members list")}</span>
|
||||||
</.button>
|
</.button>
|
||||||
<.button variant="primary" navigate={~p"/members/#{@member}/edit?return_to=show"}>
|
<.button variant="primary" navigate={~p"/members/#{@member}/edit?return_to=show"}>
|
||||||
<.icon name="hero-pencil-square" /> {gettext("Edit Member")}
|
<.icon name="hero-pencil-square" /> {gettext("Edit Member")}
|
||||||
|
|
@ -37,6 +38,19 @@ defmodule MvWeb.MemberLive.Show do
|
||||||
<:item title={gettext("Street")}>{@member.street}</:item>
|
<:item title={gettext("Street")}>{@member.street}</:item>
|
||||||
<:item title={gettext("House Number")}>{@member.house_number}</:item>
|
<:item title={gettext("House Number")}>{@member.house_number}</:item>
|
||||||
<:item title={gettext("Postal Code")}>{@member.postal_code}</:item>
|
<:item title={gettext("Postal Code")}>{@member.postal_code}</:item>
|
||||||
|
<:item title={gettext("Linked User")}>
|
||||||
|
<%= if @member.user do %>
|
||||||
|
<.link
|
||||||
|
navigate={~p"/users/#{@member.user}"}
|
||||||
|
class="text-blue-600 hover:text-blue-800 underline"
|
||||||
|
>
|
||||||
|
<.icon name="hero-user" class="h-4 w-4 inline mr-1" />
|
||||||
|
{@member.user.email}
|
||||||
|
</.link>
|
||||||
|
<% else %>
|
||||||
|
<span class="text-gray-500 italic">{gettext("No user linked")}</span>
|
||||||
|
<% end %>
|
||||||
|
</:item>
|
||||||
</.list>
|
</.list>
|
||||||
|
|
||||||
<h3 class="mt-8 mb-2 text-lg font-semibold">{gettext("Custom Properties")}</h3>
|
<h3 class="mt-8 mb-2 text-lg font-semibold">{gettext("Custom Properties")}</h3>
|
||||||
|
|
@ -67,7 +81,7 @@ defmodule MvWeb.MemberLive.Show do
|
||||||
query =
|
query =
|
||||||
Mv.Membership.Member
|
Mv.Membership.Member
|
||||||
|> filter(id == ^id)
|
|> filter(id == ^id)
|
||||||
|> load(properties: [:property_type])
|
|> load([:user, properties: [:property_type]])
|
||||||
|
|
||||||
member = Ash.read_one!(query)
|
member = Ash.read_one!(query)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ defmodule MvWeb.UserLive.Show do
|
||||||
<:subtitle>{gettext("This is a user record from your database.")}</:subtitle>
|
<:subtitle>{gettext("This is a user record from your database.")}</:subtitle>
|
||||||
|
|
||||||
<:actions>
|
<:actions>
|
||||||
<.button navigate={~p"/users"}>
|
<.button navigate={~p"/users"} aria-label={gettext("Back to users list")}>
|
||||||
<.icon name="hero-arrow-left" />
|
<.icon name="hero-arrow-left" />
|
||||||
|
<span class="sr-only">{gettext("Back to users list")}</span>
|
||||||
</.button>
|
</.button>
|
||||||
<.button variant="primary" navigate={~p"/users/#{@user}/edit?return_to=show"}>
|
<.button variant="primary" navigate={~p"/users/#{@user}/edit?return_to=show"}>
|
||||||
<.icon name="hero-pencil-square" /> {gettext("Edit User")}
|
<.icon name="hero-pencil-square" /> {gettext("Edit User")}
|
||||||
|
|
@ -26,6 +27,19 @@ defmodule MvWeb.UserLive.Show do
|
||||||
<:item title={gettext("Password Authentication")}>
|
<:item title={gettext("Password Authentication")}>
|
||||||
{if @user.hashed_password, do: gettext("Enabled"), else: gettext("Not enabled")}
|
{if @user.hashed_password, do: gettext("Enabled"), else: gettext("Not enabled")}
|
||||||
</:item>
|
</:item>
|
||||||
|
<:item title={gettext("Linked Member")}>
|
||||||
|
<%= if @user.member do %>
|
||||||
|
<.link
|
||||||
|
navigate={~p"/members/#{@user.member}"}
|
||||||
|
class="text-blue-600 hover:text-blue-800 underline"
|
||||||
|
>
|
||||||
|
<.icon name="hero-users" class="h-4 w-4 inline mr-1" />
|
||||||
|
{@user.member.first_name} {@user.member.last_name}
|
||||||
|
</.link>
|
||||||
|
<% else %>
|
||||||
|
<span class="text-gray-500 italic">{gettext("No member linked")}</span>
|
||||||
|
<% end %>
|
||||||
|
</:item>
|
||||||
</.list>
|
</.list>
|
||||||
</Layouts.app>
|
</Layouts.app>
|
||||||
"""
|
"""
|
||||||
|
|
@ -33,9 +47,11 @@ defmodule MvWeb.UserLive.Show do
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(%{"id" => id}, _session, socket) do
|
def mount(%{"id" => id}, _session, socket) do
|
||||||
|
user = Ash.get!(Mv.Accounts.User, id, domain: Mv.Accounts, load: [:member])
|
||||||
|
|
||||||
{:ok,
|
{:ok,
|
||||||
socket
|
socket
|
||||||
|> assign(:page_title, gettext("Show User"))
|
|> assign(:page_title, gettext("Show User"))
|
||||||
|> assign(:user, Ash.get!(Mv.Accounts.User, id, domain: Mv.Accounts))}
|
|> assign(:user, user)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,10 @@ msgid "Forgot your password?"
|
||||||
msgstr "Passwort vergessen?"
|
msgstr "Passwort vergessen?"
|
||||||
|
|
||||||
msgid "If this user exists in our database you will contacted with a sign-in link shortly."
|
msgid "If this user exists in our database you will contacted with a sign-in link shortly."
|
||||||
msgstr "Falls dieser Benutzer bekannt ist, wird jetzt eine Email mit Anmelde-Link versendet."
|
msgstr "Falls diese*r Benutzer*in bekannt ist, wird jetzt eine Email mit Anmelde-Link versendet."
|
||||||
|
|
||||||
msgid "If this user exists in our system, you will be contacted with reset instructions shortly."
|
msgid "If this user exists in our system, you will be contacted with reset instructions shortly."
|
||||||
msgstr "Falls dieser Benutzer bekannt ist, wird jetzt eine Email mit einer Anleitung zum Zurücksetzen versendet."
|
msgstr "Falls diese*r Benutzer*in bekannt ist, wird jetzt eine Email mit einer Anleitung zum Zurücksetzen versendet."
|
||||||
|
|
||||||
msgid "Need an account?"
|
msgid "Need an account?"
|
||||||
msgstr "Konto anlegen?"
|
msgstr "Konto anlegen?"
|
||||||
|
|
@ -61,6 +61,3 @@ 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"
|
|
||||||
msgstr "Anmelden mit der Vereinscloud"
|
|
||||||
|
|
|
||||||
|
|
@ -15,69 +15,69 @@ 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:84
|
||||||
#: 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?"
|
||||||
msgstr "Bist du sicher?"
|
msgstr "Bist du sicher?"
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts.ex:71
|
#: lib/mv_web/components/layouts.ex:80
|
||||||
#: lib/mv_web/components/layouts.ex:83
|
#: lib/mv_web/components/layouts.ex:92
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Attempting to reconnect"
|
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:69
|
||||||
#: lib/mv_web/live/member_live/show.ex:36
|
#: lib/mv_web/live/member_live/show.ex:37
|
||||||
#, 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:86
|
||||||
#: 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:78
|
||||||
#: 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
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr "Bearbeite"
|
msgstr "Bearbeite"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:18
|
#: lib/mv_web/live/member_live/show.ex:19
|
||||||
#: lib/mv_web/live/member_live/show.ex:81
|
#: lib/mv_web/live/member_live/show.ex:95
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Edit Member"
|
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:65
|
||||||
#: lib/mv_web/live/member_live/show.ex:27
|
#: lib/mv_web/live/member_live/show.ex:28
|
||||||
#: 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
|
||||||
#: lib/mv_web/live/user_live/show.ex:24
|
#: lib/mv_web/live/user_live/show.ex:25
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "E-Mail"
|
msgstr "E-Mail"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:16
|
#: lib/mv_web/live/member_live/form.ex:16
|
||||||
#: lib/mv_web/live/member_live/show.ex:25
|
#: lib/mv_web/live/member_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "First Name"
|
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:71
|
||||||
#: lib/mv_web/live/member_live/show.ex:33
|
#: lib/mv_web/live/member_live/show.ex:34
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Join Date"
|
msgid "Join Date"
|
||||||
msgstr "Beitrittsdatum"
|
msgstr "Beitrittsdatum"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:17
|
#: lib/mv_web/live/member_live/form.ex:17
|
||||||
#: lib/mv_web/live/member_live/show.ex:26
|
#: lib/mv_web/live/member_live/show.ex:27
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Last Name"
|
msgid "Last Name"
|
||||||
msgstr "Nachname"
|
msgstr "Nachname"
|
||||||
|
|
@ -87,18 +87,18 @@ 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:75
|
||||||
#: 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"
|
||||||
msgstr "Anzeigen"
|
msgstr "Anzeigen"
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts.ex:78
|
#: lib/mv_web/components/layouts.ex:87
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Something went wrong!"
|
msgid "Something went wrong!"
|
||||||
msgstr "Etwas ist schiefgelaufen!"
|
msgstr "Etwas ist schiefgelaufen!"
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts.ex:66
|
#: lib/mv_web/components/layouts.ex:75
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "We can't find the internet"
|
msgid "We can't find the internet"
|
||||||
msgstr "Keine Internetverbindung gefunden"
|
msgstr "Keine Internetverbindung gefunden"
|
||||||
|
|
@ -109,52 +109,52 @@ msgid "close"
|
||||||
msgstr "schließen"
|
msgstr "schließen"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:19
|
#: lib/mv_web/live/member_live/form.ex:19
|
||||||
#: lib/mv_web/live/member_live/show.ex:28
|
#: lib/mv_web/live/member_live/show.ex:29
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Birth Date"
|
msgid "Birth Date"
|
||||||
msgstr "Geburtsdatum"
|
msgstr "Geburtsdatum"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:30
|
#: lib/mv_web/live/member_live/form.ex:30
|
||||||
#: lib/mv_web/live/member_live/show.ex:42
|
#: lib/mv_web/live/member_live/show.ex:56
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Custom Properties"
|
msgid "Custom Properties"
|
||||||
msgstr "Eigene Eigenschaften"
|
msgstr "Eigene Eigenschaften"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:23
|
#: lib/mv_web/live/member_live/form.ex:23
|
||||||
#: lib/mv_web/live/member_live/show.ex:34
|
#: lib/mv_web/live/member_live/show.ex:35
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Exit Date"
|
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:67
|
||||||
#: lib/mv_web/live/member_live/show.ex:38
|
#: lib/mv_web/live/member_live/show.ex:39
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "House Number"
|
msgid "House Number"
|
||||||
msgstr "Hausnummer"
|
msgstr "Hausnummer"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:24
|
#: lib/mv_web/live/member_live/form.ex:24
|
||||||
#: lib/mv_web/live/member_live/show.ex:35
|
#: lib/mv_web/live/member_live/show.ex:36
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Notes"
|
msgid "Notes"
|
||||||
msgstr "Notizen"
|
msgstr "Notizen"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:20
|
#: lib/mv_web/live/member_live/form.ex:20
|
||||||
#: lib/mv_web/live/member_live/show.ex:29
|
#: lib/mv_web/live/member_live/show.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Paid"
|
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:70
|
||||||
#: lib/mv_web/live/member_live/show.ex:32
|
#: lib/mv_web/live/member_live/show.ex:33
|
||||||
#, 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:68
|
||||||
#: lib/mv_web/live/member_live/show.ex:39
|
#: lib/mv_web/live/member_live/show.ex:40
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Postal Code"
|
msgid "Postal Code"
|
||||||
msgstr "Postleitzahl"
|
msgstr "Postleitzahl"
|
||||||
|
|
@ -173,8 +173,8 @@ 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:66
|
||||||
#: lib/mv_web/live/member_live/show.ex:37
|
#: lib/mv_web/live/member_live/show.ex:38
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
msgstr "Straße"
|
msgstr "Straße"
|
||||||
|
|
@ -184,17 +184,17 @@ msgstr "Straße"
|
||||||
msgid "Use this form to manage member records and their properties."
|
msgid "Use this form to manage member records and their properties."
|
||||||
msgstr "Dieses Formular dient zur Verwaltung von Mitgliedern und deren Eigenschaften."
|
msgstr "Dieses Formular dient zur Verwaltung von Mitgliedern und deren Eigenschaften."
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:24
|
#: lib/mv_web/live/member_live/show.ex:25
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr "ID"
|
msgstr "ID"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:30
|
#: lib/mv_web/live/member_live/show.ex:31
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "Nein"
|
msgstr "Nein"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:80
|
#: lib/mv_web/live/member_live/show.ex:94
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgid "Show Member"
|
msgid "Show Member"
|
||||||
msgstr "Mitglied anzeigen"
|
msgstr "Mitglied anzeigen"
|
||||||
|
|
@ -204,7 +204,7 @@ msgstr "Mitglied anzeigen"
|
||||||
msgid "This is a member record from your database."
|
msgid "This is a member record from your database."
|
||||||
msgstr "Dies ist ein Mitglied aus deiner Datenbank."
|
msgstr "Dies ist ein Mitglied aus deiner Datenbank."
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:30
|
#: lib/mv_web/live/member_live/show.ex:31
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Ja"
|
msgstr "Ja"
|
||||||
|
|
@ -281,17 +281,17 @@ msgstr "Eigenschaftstyp auswählen"
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Beschreibung"
|
msgstr "Beschreibung"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:17
|
#: lib/mv_web/live/user_live/show.ex:18
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Edit User"
|
msgid "Edit User"
|
||||||
msgstr "Benutzer bearbeiten"
|
msgstr "Benutzer*in bearbeiten"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:27
|
#: lib/mv_web/live/user_live/show.ex:28
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Enabled"
|
msgid "Enabled"
|
||||||
msgstr "Aktiviert"
|
msgstr "Aktiviert"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:23
|
#: lib/mv_web/live/user_live/show.ex:24
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "ID"
|
msgid "ID"
|
||||||
msgstr "ID"
|
msgstr "ID"
|
||||||
|
|
@ -301,7 +301,7 @@ msgstr "ID"
|
||||||
msgid "Immutable"
|
msgid "Immutable"
|
||||||
msgstr "Unveränderlich"
|
msgstr "Unveränderlich"
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:73
|
#: lib/mv_web/components/layouts/navbar.ex:94
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr "Abmelden"
|
msgstr "Abmelden"
|
||||||
|
|
@ -310,21 +310,21 @@ msgstr "Abmelden"
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:3
|
#: lib/mv_web/live/user_live/index.html.heex:3
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Listing Users"
|
msgid "Listing Users"
|
||||||
msgstr "Benutzer auflisten"
|
msgstr "Benutzer*innen auflisten"
|
||||||
|
|
||||||
#: lib/mv_web/live/property_live/form.ex:27
|
#: lib/mv_web/live/property_live/form.ex:27
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Member"
|
msgid "Member"
|
||||||
msgstr "Mitglied"
|
msgstr "Mitglied"
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:14
|
#: lib/mv_web/components/layouts/navbar.ex:19
|
||||||
#: lib/mv_web/live/member_live/index.ex:12
|
#: lib/mv_web/live/member_live/index.ex:14
|
||||||
#: 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/member_live/index.html.heex:57
|
||||||
#: 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"
|
||||||
|
|
@ -333,14 +333,14 @@ msgstr "Name"
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:6
|
#: lib/mv_web/live/user_live/index.html.heex:6
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "New User"
|
msgid "New User"
|
||||||
msgstr "Neuer Benutzer"
|
msgstr "Neue*r Benutzer*in"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:27
|
#: lib/mv_web/live/user_live/show.ex:28
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Not enabled"
|
msgid "Not enabled"
|
||||||
msgstr "Nicht aktiviert"
|
msgstr "Nicht aktiviert"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:25
|
#: lib/mv_web/live/user_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Not set"
|
msgid "Not set"
|
||||||
msgstr "Nicht gesetzt"
|
msgstr "Nicht gesetzt"
|
||||||
|
|
@ -352,12 +352,12 @@ msgid "Note"
|
||||||
msgstr "Hinweis"
|
msgstr "Hinweis"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:52
|
#: lib/mv_web/live/user_live/index.html.heex:52
|
||||||
#: lib/mv_web/live/user_live/show.ex:25
|
#: lib/mv_web/live/user_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "OIDC ID"
|
msgid "OIDC ID"
|
||||||
msgstr "OIDC ID"
|
msgstr "OIDC ID"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:26
|
#: lib/mv_web/live/user_live/show.ex:27
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Password Authentication"
|
msgid "Password Authentication"
|
||||||
msgstr "Passwort-Authentifizierung"
|
msgstr "Passwort-Authentifizierung"
|
||||||
|
|
@ -367,15 +367,15 @@ msgstr "Passwort-Authentifizierung"
|
||||||
msgid "Please select a property type first"
|
msgid "Please select a property type first"
|
||||||
msgstr "Bitte wählen Sie zuerst einen Eigenschaftstyp"
|
msgstr "Bitte wählen Sie zuerst einen Eigenschaftstyp"
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:69
|
#: lib/mv_web/components/layouts/navbar.ex:89
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Profil"
|
msgid "Profil"
|
||||||
msgstr "Profil"
|
msgstr "Profil"
|
||||||
|
|
||||||
#: lib/mv_web/live/property_live/form.ex:207
|
#: lib/mv_web/live/property_live/form.ex:207
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Property %{action} successfully"
|
msgid "Property %{action} successfully"
|
||||||
msgstr "Mitglied %{action} erfolgreich"
|
msgstr "Eigenschaft %{action} erfolgreich"
|
||||||
|
|
||||||
#: lib/mv_web/live/property_live/form.ex:18
|
#: lib/mv_web/live/property_live/form.ex:18
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -402,17 +402,17 @@ msgstr "Eigenschaft speichern"
|
||||||
msgid "Save Property type"
|
msgid "Save Property type"
|
||||||
msgstr "Eigenschaftstyp speichern"
|
msgstr "Eigenschaftstyp speichern"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:27
|
#: lib/mv_web/live/member_live/index.html.heex:34
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Select all members"
|
msgid "Select all members"
|
||||||
msgstr "Alle Mitglieder auswählen"
|
msgstr "Alle Mitglieder auswählen"
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:41
|
#: lib/mv_web/live/member_live/index.html.heex:48
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Select member"
|
msgid "Select member"
|
||||||
msgstr "Mitglied auswählen"
|
msgstr "Mitglied auswählen"
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:72
|
#: lib/mv_web/components/layouts/navbar.ex:92
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "Einstellungen"
|
msgstr "Einstellungen"
|
||||||
|
|
@ -420,17 +420,17 @@ msgstr "Einstellungen"
|
||||||
#: lib/mv_web/live/user_live/form.ex:93
|
#: lib/mv_web/live/user_live/form.ex:93
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Save User"
|
msgid "Save User"
|
||||||
msgstr "Benutzer speichern"
|
msgstr "Benutzer*in speichern"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:38
|
#: lib/mv_web/live/user_live/show.ex:54
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Show User"
|
msgid "Show User"
|
||||||
msgstr "Benutzer anzeigen"
|
msgstr "Benutzer*in anzeigen"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:10
|
#: lib/mv_web/live/user_live/show.ex:10
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "This is a user record from your database."
|
msgid "This is a user record from your database."
|
||||||
msgstr "Dies ist ein Benutzer-Datensatz aus Ihrer Datenbank."
|
msgstr "Dies ist ein Benutzer*innen-Datensatz aus Ihrer Datenbank."
|
||||||
|
|
||||||
#: lib/mv_web/live/property_live/form.ex:95
|
#: lib/mv_web/live/property_live/form.ex:95
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -438,25 +438,25 @@ msgid "Unsupported value type: %{type}"
|
||||||
msgstr "Nicht unterstützter Wertetyp: %{type}"
|
msgstr "Nicht unterstützter Wertetyp: %{type}"
|
||||||
|
|
||||||
#: lib/mv_web/live/property_live/form.ex:10
|
#: lib/mv_web/live/property_live/form.ex:10
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Use this form to manage property records in your database."
|
msgid "Use this form to manage property records in your database."
|
||||||
msgstr "Dieses Formular dient zur Verwaltung von Mitgliedern und deren Eigenschaften."
|
msgstr "Dieses Formular dient zur Verwaltung von Eigenschaften in der Datenbank."
|
||||||
|
|
||||||
#: lib/mv_web/live/property_type_live/form.ex:11
|
#: lib/mv_web/live/property_type_live/form.ex:11
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Use this form to manage property_type records in your database."
|
msgid "Use this form to manage property_type records in your database."
|
||||||
msgstr "Dieses Formular dient zur Verwaltung von Mitgliedern und deren Eigenschaften."
|
msgstr "Dieses Formular dient zur Verwaltung von Eigenschaftstypen in der Datenbank."
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/form.ex:10
|
#: lib/mv_web/live/user_live/form.ex:10
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Use this form to manage user records in your database."
|
msgid "Use this form to manage user records in your database."
|
||||||
msgstr "Verwenden Sie dieses Formular, um Benutzer-Datensätze zu verwalten."
|
msgstr "Verwenden Sie dieses Formular, um Benutzer*innen-Datensätze zu verwalten."
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/form.ex:110
|
#: lib/mv_web/live/user_live/form.ex:110
|
||||||
#: lib/mv_web/live/user_live/show.ex:9
|
#: lib/mv_web/live/user_live/show.ex:9
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Benutzer"
|
msgstr "Benutzer*in"
|
||||||
|
|
||||||
#: lib/mv_web/live/property_live/form.ex:59
|
#: lib/mv_web/live/property_live/form.ex:59
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -481,17 +481,17 @@ msgstr "absteigend"
|
||||||
#: lib/mv_web/live/user_live/form.ex:109
|
#: lib/mv_web/live/user_live/form.ex:109
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "New"
|
msgid "New"
|
||||||
msgstr "Neuer"
|
msgstr "Neue*r"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/form.ex:64
|
#: lib/mv_web/live/user_live/form.ex:64
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Admin Note"
|
msgid "Admin Note"
|
||||||
msgstr "Administrator-Hinweis"
|
msgstr "Administrator*innen-Hinweis"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/form.ex:64
|
#: lib/mv_web/live/user_live/form.ex:64
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "As an administrator, you can directly set a new password for this user using the same secure Ash Authentication system."
|
msgid "As an administrator, you can directly set a new password for this user using the same secure Ash Authentication system."
|
||||||
msgstr "Als Administrator können Sie direkt ein neues Passwort für diesen Benutzer setzen, wobei das gleiche sichere Ash Authentication System verwendet wird."
|
msgstr "Als Administrator*in können Sie direkt ein neues Passwort für diese*n Benutzer*in setzen, wobei das gleiche sichere Ash Authentication System verwendet wird."
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/form.ex:55
|
#: lib/mv_web/live/user_live/form.ex:55
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -506,7 +506,7 @@ msgstr "Passwort ändern"
|
||||||
#: lib/mv_web/live/user_live/form.ex:75
|
#: lib/mv_web/live/user_live/form.ex:75
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Check 'Change Password' above to set a new password for this user."
|
msgid "Check 'Change Password' above to set a new password for this user."
|
||||||
msgstr "Aktivieren Sie 'Passwort ändern' oben, um ein neues Passwort für diesen Benutzer zu setzen."
|
msgstr "Aktivieren Sie 'Passwort ändern' oben, um ein neues Passwort für diese*n Benutzer*in zu setzen."
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/form.ex:45
|
#: lib/mv_web/live/user_live/form.ex:45
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -536,12 +536,12 @@ msgstr "Passwort-Anforderungen"
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:21
|
#: lib/mv_web/live/user_live/index.html.heex:21
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Select all users"
|
msgid "Select all users"
|
||||||
msgstr "Alle Benutzer auswählen"
|
msgstr "Alle Benutzer*innen auswählen"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:35
|
#: lib/mv_web/live/user_live/index.html.heex:35
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Select user"
|
msgid "Select user"
|
||||||
msgstr "Benutzer auswählen"
|
msgstr "Benutzer*in auswählen"
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/form.ex:27
|
#: lib/mv_web/live/user_live/form.ex:27
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -551,9 +551,59 @@ msgstr "Passwort setzen"
|
||||||
#: lib/mv_web/live/user_live/form.ex:83
|
#: lib/mv_web/live/user_live/form.ex:83
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
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*in wird ohne Passwort erstellt. Aktivieren Sie 'Passwort setzen', um eines hinzuzufügen."
|
||||||
|
|
||||||
#: lib/mv_web/auth_overrides.ex:30
|
#: lib/mv_web/live/user_live/show.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "or"
|
msgid "Linked Member"
|
||||||
msgstr "oder"
|
msgstr "Verknüpftes Mitglied"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:41
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Linked User"
|
||||||
|
msgstr "Verknüpfte*r Benutzer*in"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/user_live/show.ex:40
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "No member linked"
|
||||||
|
msgstr "Kein Mitglied verknüpft"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:51
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "No user linked"
|
||||||
|
msgstr "Keine*r Benutzer*in verknüpft"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:14
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:16
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Back to members list"
|
||||||
|
msgstr "Zurück zur Mitgliederliste"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/user_live/show.ex:13
|
||||||
|
#: lib/mv_web/live/user_live/show.ex:15
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Back to users list"
|
||||||
|
msgstr "Zurück zur Benutzer*innen-Liste"
|
||||||
|
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:27
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:33
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Select language"
|
||||||
|
msgstr "Sprache auswählen"
|
||||||
|
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:40
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:60
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Toggle dark mode"
|
||||||
|
msgstr "Dunklen Modus umschalten"
|
||||||
|
|
||||||
|
#: lib/mv_web/live/components/search_bar_component.ex:15
|
||||||
|
#: lib/mv_web/live/member_live/index.html.heex:15
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Search..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:20
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "Users"
|
||||||
|
msgstr "Benutzer*innen"
|
||||||
|
|
|
||||||
|
|
@ -12,101 +12,146 @@ msgstr ""
|
||||||
|
|
||||||
## From Ecto.Changeset.cast/4
|
## From Ecto.Changeset.cast/4
|
||||||
msgid "can't be blank"
|
msgid "can't be blank"
|
||||||
msgstr ""
|
msgstr "darf nicht leer sein"
|
||||||
|
|
||||||
## From Ecto.Changeset.unique_constraint/3
|
## From Ecto.Changeset.unique_constraint/3
|
||||||
msgid "has already been taken"
|
msgid "has already been taken"
|
||||||
msgstr ""
|
msgstr "ist bereits vergeben"
|
||||||
|
|
||||||
## From Ecto.Changeset.put_change/3
|
## From Ecto.Changeset.put_change/3
|
||||||
msgid "is invalid"
|
msgid "is invalid"
|
||||||
msgstr ""
|
msgstr "ist ungültig"
|
||||||
|
|
||||||
## From Ecto.Changeset.validate_acceptance/3
|
## From Ecto.Changeset.validate_acceptance/3
|
||||||
msgid "must be accepted"
|
msgid "must be accepted"
|
||||||
msgstr ""
|
msgstr "muss akzeptiert werden"
|
||||||
|
|
||||||
## From Ecto.Changeset.validate_format/3
|
## From Ecto.Changeset.validate_format/3
|
||||||
msgid "has invalid format"
|
msgid "has invalid format"
|
||||||
msgstr ""
|
msgstr "hat ein ungültiges Format"
|
||||||
|
|
||||||
## From Ecto.Changeset.validate_subset/3
|
## From Ecto.Changeset.validate_subset/3
|
||||||
msgid "has an invalid entry"
|
msgid "has an invalid entry"
|
||||||
msgstr ""
|
msgstr "hat einen ungültigen Eintrag"
|
||||||
|
|
||||||
## From Ecto.Changeset.validate_exclusion/3
|
## From Ecto.Changeset.validate_exclusion/3
|
||||||
msgid "is reserved"
|
msgid "is reserved"
|
||||||
msgstr ""
|
msgstr "ist reserviert"
|
||||||
|
|
||||||
## From Ecto.Changeset.validate_confirmation/3
|
## From Ecto.Changeset.validate_confirmation/3
|
||||||
msgid "does not match confirmation"
|
msgid "does not match confirmation"
|
||||||
msgstr ""
|
msgstr "stimmt nicht mit der Bestätigung überein"
|
||||||
|
|
||||||
## From Ecto.Changeset.no_assoc_constraint/3
|
## From Ecto.Changeset.no_assoc_constraint/3
|
||||||
msgid "is still associated with this entry"
|
msgid "is still associated with this entry"
|
||||||
msgstr ""
|
msgstr "ist noch mit diesem Eintrag verknüpft"
|
||||||
|
|
||||||
msgid "are still associated with this entry"
|
msgid "are still associated with this entry"
|
||||||
msgstr ""
|
msgstr "sind noch mit diesem Eintrag verknüpft"
|
||||||
|
|
||||||
## From Ecto.Changeset.validate_length/3
|
## From Ecto.Changeset.validate_length/3
|
||||||
msgid "should have %{count} item(s)"
|
msgid "should have %{count} item(s)"
|
||||||
msgid_plural "should have %{count} item(s)"
|
msgid_plural "should have %{count} item(s)"
|
||||||
msgstr[0] ""
|
msgstr[0] "sollte %{count} Element haben"
|
||||||
msgstr[1] ""
|
msgstr[1] "sollte %{count} Elemente haben"
|
||||||
|
|
||||||
msgid "should be %{count} character(s)"
|
msgid "should be %{count} character(s)"
|
||||||
msgid_plural "should be %{count} character(s)"
|
msgid_plural "should be %{count} character(s)"
|
||||||
msgstr[0] ""
|
msgstr[0] "sollte %{count} Zeichen haben"
|
||||||
msgstr[1] ""
|
msgstr[1] "sollte %{count} Zeichen haben"
|
||||||
|
|
||||||
msgid "should be %{count} byte(s)"
|
msgid "should be %{count} byte(s)"
|
||||||
msgid_plural "should be %{count} byte(s)"
|
msgid_plural "should be %{count} byte(s)"
|
||||||
msgstr[0] ""
|
msgstr[0] "sollte %{count} Byte haben"
|
||||||
msgstr[1] ""
|
msgstr[1] "sollte %{count} Bytes haben"
|
||||||
|
|
||||||
msgid "should have at least %{count} item(s)"
|
msgid "should have at least %{count} item(s)"
|
||||||
msgid_plural "should have at least %{count} item(s)"
|
msgid_plural "should have at least %{count} item(s)"
|
||||||
msgstr[0] ""
|
msgstr[0] "sollte mindestens %{count} Element haben"
|
||||||
msgstr[1] ""
|
msgstr[1] "sollte mindestens %{count} Elemente haben"
|
||||||
|
|
||||||
msgid "should be at least %{count} character(s)"
|
msgid "should be at least %{count} character(s)"
|
||||||
msgid_plural "should be at least %{count} character(s)"
|
msgid_plural "should be at least %{count} character(s)"
|
||||||
msgstr[0] ""
|
msgstr[0] "sollte mindestens %{count} Zeichen haben"
|
||||||
msgstr[1] ""
|
msgstr[1] "sollte mindestens %{count} Zeichen haben"
|
||||||
|
|
||||||
msgid "should be at least %{count} byte(s)"
|
msgid "should be at least %{count} byte(s)"
|
||||||
msgid_plural "should be at least %{count} byte(s)"
|
msgid_plural "should be at least %{count} byte(s)"
|
||||||
msgstr[0] ""
|
msgstr[0] "sollte mindestens %{count} Byte haben"
|
||||||
msgstr[1] ""
|
msgstr[1] "sollte mindestens %{count} Bytes haben"
|
||||||
|
|
||||||
msgid "should have at most %{count} item(s)"
|
msgid "should have at most %{count} item(s)"
|
||||||
msgid_plural "should have at most %{count} item(s)"
|
msgid_plural "should have at most %{count} item(s)"
|
||||||
msgstr[0] ""
|
msgstr[0] "sollte höchstens %{count} Element haben"
|
||||||
msgstr[1] ""
|
msgstr[1] "sollte höchstens %{count} Elemente haben"
|
||||||
|
|
||||||
msgid "should be at most %{count} character(s)"
|
msgid "should be at most %{count} character(s)"
|
||||||
msgid_plural "should be at most %{count} character(s)"
|
msgid_plural "should be at most %{count} character(s)"
|
||||||
msgstr[0] ""
|
msgstr[0] "sollte höchstens %{count} Zeichen haben"
|
||||||
msgstr[1] ""
|
msgstr[1] "sollte höchstens %{count} Zeichen haben"
|
||||||
|
|
||||||
msgid "should be at most %{count} byte(s)"
|
msgid "should be at most %{count} byte(s)"
|
||||||
msgid_plural "should be at most %{count} byte(s)"
|
msgid_plural "should be at most %{count} byte(s)"
|
||||||
msgstr[0] ""
|
msgstr[0] "sollte höchstens %{count} Byte haben"
|
||||||
msgstr[1] ""
|
msgstr[1] "sollte höchstens %{count} Bytes haben"
|
||||||
|
|
||||||
## From Ecto.Changeset.validate_number/3
|
## From Ecto.Changeset.validate_number/3
|
||||||
msgid "must be less than %{number}"
|
msgid "must be less than %{number}"
|
||||||
msgstr ""
|
msgstr "muss kleiner als %{number} sein"
|
||||||
|
|
||||||
msgid "must be greater than %{number}"
|
msgid "must be greater than %{number}"
|
||||||
msgstr ""
|
msgstr "muss größer als %{number} sein"
|
||||||
|
|
||||||
msgid "must be less than or equal to %{number}"
|
msgid "must be less than or equal to %{number}"
|
||||||
msgstr ""
|
msgstr "muss kleiner oder gleich %{number} sein"
|
||||||
|
|
||||||
msgid "must be greater than or equal to %{number}"
|
msgid "must be greater than or equal to %{number}"
|
||||||
msgstr ""
|
msgstr "muss größer oder gleich %{number} sein"
|
||||||
|
|
||||||
msgid "must be equal to %{number}"
|
msgid "must be equal to %{number}"
|
||||||
msgstr ""
|
msgstr "muss gleich %{number} sein"
|
||||||
|
|
||||||
|
## Ash Framework - Standard constraint messages
|
||||||
|
msgid "length must be greater than or equal to %{min}"
|
||||||
|
msgstr "muss mindestens %{min} Zeichen lang sein"
|
||||||
|
|
||||||
|
msgid "length must be less than or equal to %{max}"
|
||||||
|
msgstr "darf höchstens %{max} Zeichen lang sein"
|
||||||
|
|
||||||
|
msgid "must be present"
|
||||||
|
msgstr "muss vorhanden sein"
|
||||||
|
|
||||||
|
## Custom validation messages from Mv.Accounts.User
|
||||||
|
msgid "User already has a member. Remove existing member first."
|
||||||
|
msgstr "Benutzer*in hat bereits ein Mitglied. Entfernen Sie zuerst das vorhandene Mitglied."
|
||||||
|
|
||||||
|
msgid "OIDC user_info must contain a non-empty 'sub' or 'id' field"
|
||||||
|
msgstr "OIDC user_info darf kein leeres 'sub' oder 'id' Feld enthalten"
|
||||||
|
|
||||||
|
## Custom validation messages from Mv.Membership.Member
|
||||||
|
msgid "User is already linked to another member"
|
||||||
|
msgstr "Benutzer*in ist bereits mit einem anderen Mitglied verknüpft"
|
||||||
|
|
||||||
|
msgid "User not found"
|
||||||
|
msgstr "Benutzer*in nicht gefunden"
|
||||||
|
|
||||||
|
msgid "cannot be in the future"
|
||||||
|
msgstr "darf nicht in der Zukunft liegen"
|
||||||
|
|
||||||
|
msgid "cannot be before join date"
|
||||||
|
msgstr "darf nicht vor dem Beitrittsdatum liegen"
|
||||||
|
|
||||||
|
msgid "is not a valid phone number"
|
||||||
|
msgstr "ist keine gültige Telefonnummer"
|
||||||
|
|
||||||
|
msgid "must consist of 5 digits"
|
||||||
|
msgstr "muss aus 5 Ziffern bestehen"
|
||||||
|
|
||||||
|
msgid "is not a valid email"
|
||||||
|
msgstr "ist keine gültige E-Mail-Adresse"
|
||||||
|
|
||||||
|
msgid "must have length of at least 8"
|
||||||
|
msgstr "muss mindestens 8 Zeichen lang sein"
|
||||||
|
|
||||||
|
msgid "is required"
|
||||||
|
msgstr "ist erforderlich"
|
||||||
|
|
|
||||||
|
|
@ -16,69 +16,69 @@ 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:84
|
||||||
#: 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?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts.ex:71
|
#: lib/mv_web/components/layouts.ex:80
|
||||||
#: lib/mv_web/components/layouts.ex:83
|
#: lib/mv_web/components/layouts.ex:92
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Attempting to reconnect"
|
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:69
|
||||||
#: lib/mv_web/live/member_live/show.ex:36
|
#: lib/mv_web/live/member_live/show.ex:37
|
||||||
#, 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:86
|
||||||
#: 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:78
|
||||||
#: 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
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:18
|
#: lib/mv_web/live/member_live/show.ex:19
|
||||||
#: lib/mv_web/live/member_live/show.ex:81
|
#: lib/mv_web/live/member_live/show.ex:95
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Edit Member"
|
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:65
|
||||||
#: lib/mv_web/live/member_live/show.ex:27
|
#: lib/mv_web/live/member_live/show.ex:28
|
||||||
#: 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
|
||||||
#: lib/mv_web/live/user_live/show.ex:24
|
#: lib/mv_web/live/user_live/show.ex:25
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:16
|
#: lib/mv_web/live/member_live/form.ex:16
|
||||||
#: lib/mv_web/live/member_live/show.ex:25
|
#: lib/mv_web/live/member_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "First Name"
|
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:71
|
||||||
#: lib/mv_web/live/member_live/show.ex:33
|
#: lib/mv_web/live/member_live/show.ex:34
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Join Date"
|
msgid "Join Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:17
|
#: lib/mv_web/live/member_live/form.ex:17
|
||||||
#: lib/mv_web/live/member_live/show.ex:26
|
#: lib/mv_web/live/member_live/show.ex:27
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Last Name"
|
msgid "Last Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -88,18 +88,18 @@ 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:75
|
||||||
#: 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"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts.ex:78
|
#: lib/mv_web/components/layouts.ex:87
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Something went wrong!"
|
msgid "Something went wrong!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts.ex:66
|
#: lib/mv_web/components/layouts.ex:75
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "We can't find the internet"
|
msgid "We can't find the internet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -110,52 +110,52 @@ msgid "close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:19
|
#: lib/mv_web/live/member_live/form.ex:19
|
||||||
#: lib/mv_web/live/member_live/show.ex:28
|
#: lib/mv_web/live/member_live/show.ex:29
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Birth Date"
|
msgid "Birth Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:30
|
#: lib/mv_web/live/member_live/form.ex:30
|
||||||
#: lib/mv_web/live/member_live/show.ex:42
|
#: lib/mv_web/live/member_live/show.ex:56
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Custom Properties"
|
msgid "Custom Properties"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:23
|
#: lib/mv_web/live/member_live/form.ex:23
|
||||||
#: lib/mv_web/live/member_live/show.ex:34
|
#: lib/mv_web/live/member_live/show.ex:35
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Exit Date"
|
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:67
|
||||||
#: lib/mv_web/live/member_live/show.ex:38
|
#: lib/mv_web/live/member_live/show.ex:39
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "House Number"
|
msgid "House Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:24
|
#: lib/mv_web/live/member_live/form.ex:24
|
||||||
#: lib/mv_web/live/member_live/show.ex:35
|
#: lib/mv_web/live/member_live/show.ex:36
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Notes"
|
msgid "Notes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:20
|
#: lib/mv_web/live/member_live/form.ex:20
|
||||||
#: lib/mv_web/live/member_live/show.ex:29
|
#: lib/mv_web/live/member_live/show.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Paid"
|
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:70
|
||||||
#: lib/mv_web/live/member_live/show.ex:32
|
#: lib/mv_web/live/member_live/show.ex:33
|
||||||
#, 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:68
|
||||||
#: lib/mv_web/live/member_live/show.ex:39
|
#: lib/mv_web/live/member_live/show.ex:40
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Postal Code"
|
msgid "Postal Code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -174,8 +174,8 @@ 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:66
|
||||||
#: lib/mv_web/live/member_live/show.ex:37
|
#: lib/mv_web/live/member_live/show.ex:38
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -185,17 +185,17 @@ msgstr ""
|
||||||
msgid "Use this form to manage member records and their properties."
|
msgid "Use this form to manage member records and their properties."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:24
|
#: lib/mv_web/live/member_live/show.ex:25
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:30
|
#: lib/mv_web/live/member_live/show.ex:31
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:80
|
#: lib/mv_web/live/member_live/show.ex:94
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Show Member"
|
msgid "Show Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -205,7 +205,7 @@ msgstr ""
|
||||||
msgid "This is a member record from your database."
|
msgid "This is a member record from your database."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:30
|
#: lib/mv_web/live/member_live/show.ex:31
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -282,17 +282,17 @@ msgstr ""
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:17
|
#: lib/mv_web/live/user_live/show.ex:18
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Edit User"
|
msgid "Edit User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:27
|
#: lib/mv_web/live/user_live/show.ex:28
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Enabled"
|
msgid "Enabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:23
|
#: lib/mv_web/live/user_live/show.ex:24
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "ID"
|
msgid "ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -302,7 +302,7 @@ msgstr ""
|
||||||
msgid "Immutable"
|
msgid "Immutable"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:73
|
#: lib/mv_web/components/layouts/navbar.ex:94
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -318,14 +318,14 @@ msgstr ""
|
||||||
msgid "Member"
|
msgid "Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:14
|
#: lib/mv_web/components/layouts/navbar.ex:19
|
||||||
#: lib/mv_web/live/member_live/index.ex:12
|
#: lib/mv_web/live/member_live/index.ex:14
|
||||||
#: 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/member_live/index.html.heex:57
|
||||||
#: 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"
|
||||||
|
|
@ -336,12 +336,12 @@ msgstr ""
|
||||||
msgid "New User"
|
msgid "New User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:27
|
#: lib/mv_web/live/user_live/show.ex:28
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Not enabled"
|
msgid "Not enabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:25
|
#: lib/mv_web/live/user_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Not set"
|
msgid "Not set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -353,12 +353,12 @@ msgid "Note"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:52
|
#: lib/mv_web/live/user_live/index.html.heex:52
|
||||||
#: lib/mv_web/live/user_live/show.ex:25
|
#: lib/mv_web/live/user_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "OIDC ID"
|
msgid "OIDC ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:26
|
#: lib/mv_web/live/user_live/show.ex:27
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Password Authentication"
|
msgid "Password Authentication"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -368,7 +368,7 @@ msgstr ""
|
||||||
msgid "Please select a property type first"
|
msgid "Please select a property type first"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:69
|
#: lib/mv_web/components/layouts/navbar.ex:89
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Profil"
|
msgid "Profil"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -403,17 +403,17 @@ msgstr ""
|
||||||
msgid "Save Property type"
|
msgid "Save Property type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:27
|
#: lib/mv_web/live/member_live/index.html.heex:34
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Select all members"
|
msgid "Select all members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:41
|
#: lib/mv_web/live/member_live/index.html.heex:48
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Select member"
|
msgid "Select member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:72
|
#: lib/mv_web/components/layouts/navbar.ex:92
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -423,7 +423,7 @@ msgstr ""
|
||||||
msgid "Save User"
|
msgid "Save User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:38
|
#: lib/mv_web/live/user_live/show.ex:54
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Show User"
|
msgid "Show User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -554,7 +554,57 @@ 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/user_live/show.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "or"
|
msgid "Linked Member"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:41
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Linked User"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/user_live/show.ex:40
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "No member linked"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:51
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "No user linked"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:14
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:16
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Back to members list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/user_live/show.ex:13
|
||||||
|
#: lib/mv_web/live/user_live/show.ex:15
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Back to users list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:27
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:33
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Select language"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:40
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:60
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Toggle dark mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/components/search_bar_component.ex:15
|
||||||
|
#: lib/mv_web/live/member_live/index.html.heex:15
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Search..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:20
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,3 @@ msgstr ""
|
||||||
|
|
||||||
msgid "Your password has successfully been reset"
|
msgid "Your password has successfully been reset"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Sign in with Rauthy"
|
|
||||||
msgstr "Sign in with Vereinscloud"
|
|
||||||
|
|
|
||||||
|
|
@ -16,69 +16,69 @@ 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:84
|
||||||
#: 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?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts.ex:71
|
#: lib/mv_web/components/layouts.ex:80
|
||||||
#: lib/mv_web/components/layouts.ex:83
|
#: lib/mv_web/components/layouts.ex:92
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Attempting to reconnect"
|
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:69
|
||||||
#: lib/mv_web/live/member_live/show.ex:36
|
#: lib/mv_web/live/member_live/show.ex:37
|
||||||
#, 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:86
|
||||||
#: 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:78
|
||||||
#: 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
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:18
|
#: lib/mv_web/live/member_live/show.ex:19
|
||||||
#: lib/mv_web/live/member_live/show.ex:81
|
#: lib/mv_web/live/member_live/show.ex:95
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Edit Member"
|
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:65
|
||||||
#: lib/mv_web/live/member_live/show.ex:27
|
#: lib/mv_web/live/member_live/show.ex:28
|
||||||
#: 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
|
||||||
#: lib/mv_web/live/user_live/show.ex:24
|
#: lib/mv_web/live/user_live/show.ex:25
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:16
|
#: lib/mv_web/live/member_live/form.ex:16
|
||||||
#: lib/mv_web/live/member_live/show.ex:25
|
#: lib/mv_web/live/member_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "First Name"
|
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:71
|
||||||
#: lib/mv_web/live/member_live/show.ex:33
|
#: lib/mv_web/live/member_live/show.ex:34
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Join Date"
|
msgid "Join Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:17
|
#: lib/mv_web/live/member_live/form.ex:17
|
||||||
#: lib/mv_web/live/member_live/show.ex:26
|
#: lib/mv_web/live/member_live/show.ex:27
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Last Name"
|
msgid "Last Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -88,18 +88,18 @@ 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:75
|
||||||
#: 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"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts.ex:78
|
#: lib/mv_web/components/layouts.ex:87
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Something went wrong!"
|
msgid "Something went wrong!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts.ex:66
|
#: lib/mv_web/components/layouts.ex:75
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "We can't find the internet"
|
msgid "We can't find the internet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -110,52 +110,52 @@ msgid "close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:19
|
#: lib/mv_web/live/member_live/form.ex:19
|
||||||
#: lib/mv_web/live/member_live/show.ex:28
|
#: lib/mv_web/live/member_live/show.ex:29
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Birth Date"
|
msgid "Birth Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:30
|
#: lib/mv_web/live/member_live/form.ex:30
|
||||||
#: lib/mv_web/live/member_live/show.ex:42
|
#: lib/mv_web/live/member_live/show.ex:56
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Custom Properties"
|
msgid "Custom Properties"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:23
|
#: lib/mv_web/live/member_live/form.ex:23
|
||||||
#: lib/mv_web/live/member_live/show.ex:34
|
#: lib/mv_web/live/member_live/show.ex:35
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Exit Date"
|
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:67
|
||||||
#: lib/mv_web/live/member_live/show.ex:38
|
#: lib/mv_web/live/member_live/show.ex:39
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "House Number"
|
msgid "House Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:24
|
#: lib/mv_web/live/member_live/form.ex:24
|
||||||
#: lib/mv_web/live/member_live/show.ex:35
|
#: lib/mv_web/live/member_live/show.ex:36
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Notes"
|
msgid "Notes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/form.ex:20
|
#: lib/mv_web/live/member_live/form.ex:20
|
||||||
#: lib/mv_web/live/member_live/show.ex:29
|
#: lib/mv_web/live/member_live/show.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Paid"
|
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:70
|
||||||
#: lib/mv_web/live/member_live/show.ex:32
|
#: lib/mv_web/live/member_live/show.ex:33
|
||||||
#, 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:68
|
||||||
#: lib/mv_web/live/member_live/show.ex:39
|
#: lib/mv_web/live/member_live/show.ex:40
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Postal Code"
|
msgid "Postal Code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -174,8 +174,8 @@ 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:66
|
||||||
#: lib/mv_web/live/member_live/show.ex:37
|
#: lib/mv_web/live/member_live/show.ex:38
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -185,17 +185,17 @@ msgstr ""
|
||||||
msgid "Use this form to manage member records and their properties."
|
msgid "Use this form to manage member records and their properties."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:24
|
#: lib/mv_web/live/member_live/show.ex:25
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:30
|
#: lib/mv_web/live/member_live/show.ex:31
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:80
|
#: lib/mv_web/live/member_live/show.ex:94
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgid "Show Member"
|
msgid "Show Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -205,7 +205,7 @@ msgstr ""
|
||||||
msgid "This is a member record from your database."
|
msgid "This is a member record from your database."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/show.ex:30
|
#: lib/mv_web/live/member_live/show.ex:31
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -282,17 +282,17 @@ msgstr ""
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:17
|
#: lib/mv_web/live/user_live/show.ex:18
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgid "Edit User"
|
msgid "Edit User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:27
|
#: lib/mv_web/live/user_live/show.ex:28
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Enabled"
|
msgid "Enabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:23
|
#: lib/mv_web/live/user_live/show.ex:24
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "ID"
|
msgid "ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -302,7 +302,7 @@ msgstr ""
|
||||||
msgid "Immutable"
|
msgid "Immutable"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:73
|
#: lib/mv_web/components/layouts/navbar.ex:94
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -318,14 +318,14 @@ msgstr ""
|
||||||
msgid "Member"
|
msgid "Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:14
|
#: lib/mv_web/components/layouts/navbar.ex:19
|
||||||
#: lib/mv_web/live/member_live/index.ex:12
|
#: lib/mv_web/live/member_live/index.ex:14
|
||||||
#: 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/member_live/index.html.heex:57
|
||||||
#: 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"
|
||||||
|
|
@ -336,12 +336,12 @@ msgstr ""
|
||||||
msgid "New User"
|
msgid "New User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:27
|
#: lib/mv_web/live/user_live/show.ex:28
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Not enabled"
|
msgid "Not enabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:25
|
#: lib/mv_web/live/user_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgid "Not set"
|
msgid "Not set"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -353,12 +353,12 @@ msgid "Note"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/index.html.heex:52
|
#: lib/mv_web/live/user_live/index.html.heex:52
|
||||||
#: lib/mv_web/live/user_live/show.ex:25
|
#: lib/mv_web/live/user_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "OIDC ID"
|
msgid "OIDC ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:26
|
#: lib/mv_web/live/user_live/show.ex:27
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Password Authentication"
|
msgid "Password Authentication"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -368,7 +368,7 @@ msgstr ""
|
||||||
msgid "Please select a property type first"
|
msgid "Please select a property type first"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:69
|
#: lib/mv_web/components/layouts/navbar.ex:89
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Profil"
|
msgid "Profil"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -403,17 +403,17 @@ msgstr ""
|
||||||
msgid "Save Property type"
|
msgid "Save Property type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:27
|
#: lib/mv_web/live/member_live/index.html.heex:34
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Select all members"
|
msgid "Select all members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/member_live/index.html.heex:41
|
#: lib/mv_web/live/member_live/index.html.heex:48
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Select member"
|
msgid "Select member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/components/layouts/navbar.ex:72
|
#: lib/mv_web/components/layouts/navbar.ex:92
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -423,7 +423,7 @@ msgstr ""
|
||||||
msgid "Save User"
|
msgid "Save User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/live/user_live/show.ex:38
|
#: lib/mv_web/live/user_live/show.ex:54
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgid "Show User"
|
msgid "Show User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -554,7 +554,57 @@ 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/user_live/show.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgid "or"
|
msgid "Linked Member"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:41
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Linked User"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/user_live/show.ex:40
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "No member linked"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:51
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "No user linked"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:14
|
||||||
|
#: lib/mv_web/live/member_live/show.ex:16
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Back to members list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/user_live/show.ex:13
|
||||||
|
#: lib/mv_web/live/user_live/show.ex:15
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Back to users list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:27
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:33
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "Select language"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:40
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:60
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Toggle dark mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/live/components/search_bar_component.ex:15
|
||||||
|
#: lib/mv_web/live/member_live/index.html.heex:15
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Search..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/components/layouts/navbar.ex:20
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "Users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -110,3 +110,48 @@ msgstr ""
|
||||||
|
|
||||||
msgid "must be equal to %{number}"
|
msgid "must be equal to %{number}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
## Ash Framework - Standard constraint messages
|
||||||
|
msgid "length must be greater than or equal to %{min}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "length must be less than or equal to %{max}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must be present"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## Custom validation messages from Mv.Accounts.User
|
||||||
|
msgid "User already has a member. Remove existing member first."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "OIDC user_info must contain a non-empty 'sub' or 'id' field"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## Custom validation messages from Mv.Membership.Member
|
||||||
|
msgid "User is already linked to another member"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "User not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "cannot be in the future"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "cannot be before join date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "is not a valid phone number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must consist of 5 digits"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "is not a valid email"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must have length of at least 8"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "is required"
|
||||||
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -107,3 +107,48 @@ msgstr ""
|
||||||
|
|
||||||
msgid "must be equal to %{number}"
|
msgid "must be equal to %{number}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
## Ash Framework - Standard constraint messages
|
||||||
|
msgid "length must be greater than or equal to %{min}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "length must be less than or equal to %{max}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must be present"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## Custom validation messages from Mv.Accounts.User
|
||||||
|
msgid "User already has a member. Remove existing member first."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "OIDC user_info must contain a non-empty 'sub' or 'id' field"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
## Custom validation messages from Mv.Membership.Member
|
||||||
|
msgid "User is already linked to another member"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "User not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "cannot be in the future"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "cannot be before join date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "is not a valid phone number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must consist of 5 digits"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "is not a valid email"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "must have length of at least 8"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "is required"
|
||||||
|
msgstr ""
|
||||||
|
|
|
||||||
19
priv/repo/migrations/20250926164519_member_relation.exs
Normal file
19
priv/repo/migrations/20250926164519_member_relation.exs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Mv.Repo.Migrations.MemberRelation 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
|
||||||
|
# Ensure 1:1 relationship - one user can only be linked to one member
|
||||||
|
# This prevents multiple users from sharing the same member account
|
||||||
|
create unique_index(:users, [:member_id], name: "users_unique_member_index")
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
drop_if_exists unique_index(:users, [:member_id], name: "users_unique_member_index")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Mv.Repo.Migrations.AddUniqueEmailToMembers 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
|
||||||
|
# Ensure email uniqueness across all members
|
||||||
|
# This supports upsert operations and prevents duplicate member accounts
|
||||||
|
create unique_index(:members, [:email], name: "members_unique_email_index")
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
drop_if_exists unique_index(:members, [:email], name: "members_unique_email_index")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
defmodule Mv.Repo.Migrations.AddConstraintsForUserMemberAndProperty 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
|
||||||
|
drop constraint(:users, "users_member_id_fkey")
|
||||||
|
|
||||||
|
alter table(:users) do
|
||||||
|
modify :member_id,
|
||||||
|
references(:members,
|
||||||
|
column: :id,
|
||||||
|
name: "users_member_id_fkey",
|
||||||
|
type: :uuid,
|
||||||
|
prefix: "public",
|
||||||
|
on_delete: :nilify_all
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
create unique_index(:properties, [:member_id, :property_type_id],
|
||||||
|
name: "properties_unique_property_per_member_index"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
drop_if_exists unique_index(:properties, [:member_id, :property_type_id],
|
||||||
|
name: "properties_unique_property_per_member_index"
|
||||||
|
)
|
||||||
|
|
||||||
|
drop constraint(:users, "users_member_id_fkey")
|
||||||
|
|
||||||
|
alter table(:users) do
|
||||||
|
modify :member_id,
|
||||||
|
references(:members,
|
||||||
|
column: :id,
|
||||||
|
name: "users_member_id_fkey",
|
||||||
|
type: :uuid,
|
||||||
|
prefix: "public"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -48,7 +48,7 @@ Accounts.create_user!(%{email: "admin@mv.local"}, upsert?: true, upsert_identity
|
||||||
|> Ash.Changeset.for_update(:admin_set_password, %{password: "testpassword"})
|
|> Ash.Changeset.for_update(:admin_set_password, %{password: "testpassword"})
|
||||||
|> Ash.update!()
|
|> Ash.update!()
|
||||||
|
|
||||||
# Create sample members for testing
|
# Create sample members for testing - use upsert to prevent duplicates
|
||||||
for member_attrs <- [
|
for member_attrs <- [
|
||||||
%{
|
%{
|
||||||
first_name: "Hans",
|
first_name: "Hans",
|
||||||
|
|
@ -90,5 +90,96 @@ for member_attrs <- [
|
||||||
house_number: "8"
|
house_number: "8"
|
||||||
}
|
}
|
||||||
] do
|
] do
|
||||||
Membership.create_member!(member_attrs)
|
# Use upsert to prevent duplicates based on email
|
||||||
|
Membership.create_member!(member_attrs, upsert?: true, upsert_identity: :unique_email)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Create additional users for user-member linking examples
|
||||||
|
additional_users = [
|
||||||
|
%{email: "hans.mueller@example.de"},
|
||||||
|
%{email: "greta.schmidt@example.de"},
|
||||||
|
%{email: "maria.weber@example.de"},
|
||||||
|
%{email: "thomas.klein@example.de"}
|
||||||
|
]
|
||||||
|
|
||||||
|
created_users =
|
||||||
|
Enum.map(additional_users, fn user_attrs ->
|
||||||
|
Accounts.create_user!(user_attrs, upsert?: true, upsert_identity: :unique_email)
|
||||||
|
|> Ash.Changeset.for_update(:admin_set_password, %{password: "testpassword"})
|
||||||
|
|> Ash.update!()
|
||||||
|
end)
|
||||||
|
|
||||||
|
# Create members with linked users to demonstrate the 1:1 relationship
|
||||||
|
# Only create if users don't already have members
|
||||||
|
linked_members = [
|
||||||
|
%{
|
||||||
|
first_name: "Maria",
|
||||||
|
last_name: "Weber",
|
||||||
|
email: "maria.weber@example.de",
|
||||||
|
birth_date: ~D[1992-07-14],
|
||||||
|
join_date: ~D[2023-03-15],
|
||||||
|
paid: true,
|
||||||
|
phone_number: "+49301357924",
|
||||||
|
city: "Frankfurt",
|
||||||
|
street: "Goetheplatz",
|
||||||
|
house_number: "5",
|
||||||
|
postal_code: "60313",
|
||||||
|
notes: "Linked to user account",
|
||||||
|
# Link to the third user (maria.weber@example.de)
|
||||||
|
user: Enum.at(created_users, 2)
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
first_name: "Thomas",
|
||||||
|
last_name: "Klein",
|
||||||
|
email: "thomas.klein@example.de",
|
||||||
|
birth_date: ~D[1988-12-03],
|
||||||
|
join_date: ~D[2023-04-01],
|
||||||
|
paid: false,
|
||||||
|
phone_number: "+49302468135",
|
||||||
|
city: "Köln",
|
||||||
|
street: "Rheinstraße",
|
||||||
|
house_number: "23",
|
||||||
|
postal_code: "50667",
|
||||||
|
notes: "Linked to user account - needs payment follow-up",
|
||||||
|
# Link to the fourth user (thomas.klein@example.de)
|
||||||
|
user: Enum.at(created_users, 3)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create the linked members - use upsert to prevent duplicates
|
||||||
|
Enum.each(linked_members, fn member_attrs ->
|
||||||
|
user = member_attrs.user
|
||||||
|
member_attrs_without_user = Map.delete(member_attrs, :user)
|
||||||
|
|
||||||
|
# Check if user already has a member
|
||||||
|
if user.member_id == nil do
|
||||||
|
# User is free, create member and link - use upsert to prevent duplicates
|
||||||
|
Membership.create_member!(
|
||||||
|
Map.put(member_attrs_without_user, :user, %{id: user.id}),
|
||||||
|
upsert?: true,
|
||||||
|
upsert_identity: :unique_email
|
||||||
|
)
|
||||||
|
else
|
||||||
|
# User already has a member, just create the member without linking - use upsert to prevent duplicates
|
||||||
|
Membership.create_member!(member_attrs_without_user,
|
||||||
|
upsert?: true,
|
||||||
|
upsert_identity: :unique_email
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
IO.puts("✅ Seeds completed successfully!")
|
||||||
|
IO.puts("📝 Created sample data:")
|
||||||
|
IO.puts(" - Property types: String, Date, Boolean, Email")
|
||||||
|
IO.puts(" - Admin user: admin@mv.local (password: testpassword)")
|
||||||
|
IO.puts(" - Sample members: Hans, Greta, Friedrich")
|
||||||
|
|
||||||
|
IO.puts(
|
||||||
|
" - Additional users: hans.mueller@example.de, greta.schmidt@example.de, maria.weber@example.de, thomas.klein@example.de"
|
||||||
|
)
|
||||||
|
|
||||||
|
IO.puts(
|
||||||
|
" - Linked members: Maria Weber ↔ maria.weber@example.de, Thomas Klein ↔ thomas.klein@example.de"
|
||||||
|
)
|
||||||
|
|
||||||
|
IO.puts("🔗 Visit the application to see user-member relationships in action!")
|
||||||
|
|
|
||||||
202
priv/resource_snapshots/repo/members/20250926180341.json
Normal file
202
priv/resource_snapshots/repo/members/20250926180341.json
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"custom_statements": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "5F070A1E5BEE9883AE864FB5A4A5E81F487A1C57D41576C23BAC8D933005D565",
|
||||||
|
"identities": [
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "members_unique_email_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "email"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_email",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.Mv.Repo",
|
||||||
|
"schema": null,
|
||||||
|
"table": "members"
|
||||||
|
}
|
||||||
214
priv/resource_snapshots/repo/members/20251016130855.json
Normal file
214
priv/resource_snapshots/repo/members/20251016130855.json
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
{
|
||||||
|
"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_vector",
|
||||||
|
"type": "tsvector"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"custom_statements": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "6AAC71BCCA5F112087CEF6877A5BBF74EF8965D5DA4812C44CD6E672F882CC3F",
|
||||||
|
"identities": [
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "members_unique_email_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "email"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_email",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.Mv.Repo",
|
||||||
|
"schema": null,
|
||||||
|
"table": "members"
|
||||||
|
}
|
||||||
124
priv/resource_snapshots/repo/properties/20251016130855.json
Normal file
124
priv/resource_snapshots/repo/properties/20251016130855.json
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "fragment(\"gen_random_uuid()\")",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "id",
|
||||||
|
"type": "uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "value",
|
||||||
|
"type": "map"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": {
|
||||||
|
"deferrable": false,
|
||||||
|
"destination_attribute": "id",
|
||||||
|
"destination_attribute_default": null,
|
||||||
|
"destination_attribute_generated": null,
|
||||||
|
"index?": false,
|
||||||
|
"match_type": null,
|
||||||
|
"match_with": null,
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"name": "properties_member_id_fkey",
|
||||||
|
"on_delete": "delete",
|
||||||
|
"on_update": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"schema": "public",
|
||||||
|
"table": "members"
|
||||||
|
},
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "member_id",
|
||||||
|
"type": "uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": {
|
||||||
|
"deferrable": false,
|
||||||
|
"destination_attribute": "id",
|
||||||
|
"destination_attribute_default": null,
|
||||||
|
"destination_attribute_generated": null,
|
||||||
|
"index?": false,
|
||||||
|
"match_type": null,
|
||||||
|
"match_with": null,
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"name": "properties_property_type_id_fkey",
|
||||||
|
"on_delete": null,
|
||||||
|
"on_update": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"schema": "public",
|
||||||
|
"table": "property_types"
|
||||||
|
},
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "property_type_id",
|
||||||
|
"type": "uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"custom_statements": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "8F90B1AAD1063CF2BB0BDEBBDFBA86AF0B24D854689FB834BC20DFAB2143A451",
|
||||||
|
"identities": [
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "properties_unique_property_per_member_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "member_id"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "property_type_id"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_property_per_member",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.Mv.Repo",
|
||||||
|
"schema": null,
|
||||||
|
"table": "properties"
|
||||||
|
}
|
||||||
141
priv/resource_snapshots/repo/users/20250926164519.json
Normal file
141
priv/resource_snapshots/repo/users/20250926164519.json
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "fragment(\"gen_random_uuid()\")",
|
||||||
|
"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": "email",
|
||||||
|
"type": "citext"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "hashed_password",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "oidc_id",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": {
|
||||||
|
"deferrable": false,
|
||||||
|
"destination_attribute": "id",
|
||||||
|
"destination_attribute_default": null,
|
||||||
|
"destination_attribute_generated": null,
|
||||||
|
"index?": false,
|
||||||
|
"match_type": null,
|
||||||
|
"match_with": null,
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"name": "users_member_id_fkey",
|
||||||
|
"on_delete": null,
|
||||||
|
"on_update": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"schema": "public",
|
||||||
|
"table": "members"
|
||||||
|
},
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "member_id",
|
||||||
|
"type": "uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"custom_statements": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "FDEBD4840449609DDA8B50D6741C2EEDE9D81DFBC1E26D4BC77DBD9B5A8EA4DC",
|
||||||
|
"identities": [
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "users_unique_email_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "email"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_email",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "users_unique_oidc_id_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "oidc_id"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_oidc_id",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "users_unique_member_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "member_id"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_member",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.Mv.Repo",
|
||||||
|
"schema": null,
|
||||||
|
"table": "users"
|
||||||
|
}
|
||||||
141
priv/resource_snapshots/repo/users/20251016130855.json
Normal file
141
priv/resource_snapshots/repo/users/20251016130855.json
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "fragment(\"gen_random_uuid()\")",
|
||||||
|
"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": "email",
|
||||||
|
"type": "citext"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "hashed_password",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "oidc_id",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": {
|
||||||
|
"deferrable": false,
|
||||||
|
"destination_attribute": "id",
|
||||||
|
"destination_attribute_default": null,
|
||||||
|
"destination_attribute_generated": null,
|
||||||
|
"index?": false,
|
||||||
|
"match_type": null,
|
||||||
|
"match_with": null,
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"name": "users_member_id_fkey",
|
||||||
|
"on_delete": "nilify",
|
||||||
|
"on_update": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"schema": "public",
|
||||||
|
"table": "members"
|
||||||
|
},
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "member_id",
|
||||||
|
"type": "uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"custom_statements": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "1D22936DF847949B543000F3E2E4BDA7D78682AAE6EE0CB9CBD55A4F8F4A7228",
|
||||||
|
"identities": [
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "users_unique_email_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "email"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_email",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "users_unique_member_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "member_id"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_member",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "users_unique_oidc_id_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "oidc_id"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_oidc_id",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.Mv.Repo",
|
||||||
|
"schema": null,
|
||||||
|
"table": "users"
|
||||||
|
}
|
||||||
88
test/accounts/user_member_deletion_test.exs
Normal file
88
test/accounts/user_member_deletion_test.exs
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
defmodule Mv.Accounts.UserMemberDeletionTest do
|
||||||
|
@moduledoc """
|
||||||
|
Tests for ON DELETE SET NULL constraint on users.member_id.
|
||||||
|
When a member is deleted, the linked user should remain but with member_id set to NULL.
|
||||||
|
"""
|
||||||
|
use Mv.DataCase, async: true
|
||||||
|
alias Mv.Accounts
|
||||||
|
alias Mv.Membership
|
||||||
|
|
||||||
|
describe "User remains when linked Member is deleted (ON DELETE SET NULL)" do
|
||||||
|
@valid_user_attrs %{
|
||||||
|
email: "test@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
@valid_member_attrs %{
|
||||||
|
first_name: "John",
|
||||||
|
last_name: "Doe",
|
||||||
|
email: "john@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
test "deleting a member sets the user's member_id to NULL" do
|
||||||
|
# Create a member
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
# Create a user linked to the member
|
||||||
|
{:ok, user} =
|
||||||
|
Accounts.create_user(Map.put(@valid_user_attrs, :member, %{id: member.id}))
|
||||||
|
|
||||||
|
# Verify the relationship is established
|
||||||
|
{:ok, user_before_delete} = Ash.get(Mv.Accounts.User, user.id, load: [:member])
|
||||||
|
assert user_before_delete.member_id == member.id
|
||||||
|
assert user_before_delete.member.id == member.id
|
||||||
|
|
||||||
|
# Delete the member
|
||||||
|
:ok = Membership.destroy_member(member)
|
||||||
|
|
||||||
|
# Verify the user still exists but member_id is NULL
|
||||||
|
{:ok, user_after_delete} = Ash.get(Mv.Accounts.User, user.id, load: [:member])
|
||||||
|
assert user_after_delete.id == user.id
|
||||||
|
assert user_after_delete.member_id == nil
|
||||||
|
assert user_after_delete.member == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "user can be linked to a new member after old member is deleted" do
|
||||||
|
# Create first member
|
||||||
|
{:ok, member1} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
# Create user linked to first member
|
||||||
|
{:ok, user} =
|
||||||
|
Accounts.create_user(Map.put(@valid_user_attrs, :member, %{id: member1.id}))
|
||||||
|
|
||||||
|
assert user.member_id == member1.id
|
||||||
|
|
||||||
|
# Delete first member
|
||||||
|
:ok = Membership.destroy_member(member1)
|
||||||
|
|
||||||
|
# Reload user from database to get updated member_id (should be NULL)
|
||||||
|
{:ok, user_after_delete} = Ash.get(Mv.Accounts.User, user.id)
|
||||||
|
assert user_after_delete.member_id == nil
|
||||||
|
|
||||||
|
# Create second member
|
||||||
|
{:ok, member2} =
|
||||||
|
Membership.create_member(%{
|
||||||
|
first_name: "Jane",
|
||||||
|
last_name: "Smith",
|
||||||
|
email: "jane@example.com"
|
||||||
|
})
|
||||||
|
|
||||||
|
# Link user to second member (use reloaded user)
|
||||||
|
{:ok, updated_user} = Accounts.update_user(user_after_delete, %{member: %{id: member2.id}})
|
||||||
|
|
||||||
|
# Verify new relationship
|
||||||
|
{:ok, final_user} = Ash.get(Mv.Accounts.User, updated_user.id, load: [:member])
|
||||||
|
assert final_user.member_id == member2.id
|
||||||
|
assert final_user.member.id == member2.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "member without linked user can be deleted normally" do
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
# Delete member (no users linked)
|
||||||
|
assert :ok = Membership.destroy_member(member)
|
||||||
|
|
||||||
|
# Verify member is deleted
|
||||||
|
assert {:error, _} = Ash.get(Mv.Membership.Member, member.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
197
test/accounts/user_member_relationship_test.exs
Normal file
197
test/accounts/user_member_relationship_test.exs
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
defmodule Mv.Accounts.UserMemberRelationshipTest do
|
||||||
|
# Using async: true for faster test execution
|
||||||
|
# This is safe because all database operations are sandboxed per test
|
||||||
|
use Mv.DataCase, async: true
|
||||||
|
alias Mv.Accounts
|
||||||
|
alias Mv.Membership
|
||||||
|
|
||||||
|
describe "User-Member Relationship - Basic Tests" do
|
||||||
|
@valid_user_attrs %{
|
||||||
|
email: "test@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
@valid_member_attrs %{
|
||||||
|
first_name: "John",
|
||||||
|
last_name: "Doe",
|
||||||
|
email: "john@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
test "user can exist without member" do
|
||||||
|
{:ok, user} = Accounts.create_user(@valid_user_attrs)
|
||||||
|
assert user.member_id == nil
|
||||||
|
|
||||||
|
# Load the relationship to test it
|
||||||
|
{:ok, user_with_member} = Ash.get(Mv.Accounts.User, user.id, load: [:member])
|
||||||
|
assert user_with_member.member == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "member can exist without user" do
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
assert member.id != nil
|
||||||
|
assert member.first_name == "John"
|
||||||
|
|
||||||
|
# Load the relationship to test it
|
||||||
|
{:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user])
|
||||||
|
assert member_with_user.user == nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "User-Member Relationship - Linking Tests" do
|
||||||
|
@valid_user_attrs %{
|
||||||
|
email: "test1@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
@valid_member_attrs %{
|
||||||
|
first_name: "Alice",
|
||||||
|
last_name: "Johnson",
|
||||||
|
email: "alice@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
test "user can be linked to member during user creation" do
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
user_attrs = Map.put(@valid_user_attrs, :member, %{id: member.id})
|
||||||
|
{:ok, user} = Accounts.create_user(user_attrs)
|
||||||
|
|
||||||
|
# Load the relationship to test it
|
||||||
|
{:ok, user_with_member} = Ash.get(Mv.Accounts.User, user.id, load: [:member])
|
||||||
|
assert user_with_member.member.id == member.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "member can be linked to user during member creation using manage_relationship" do
|
||||||
|
{:ok, user} = Accounts.create_user(@valid_user_attrs)
|
||||||
|
|
||||||
|
member_attrs = Map.put(@valid_member_attrs, :user, %{id: user.id})
|
||||||
|
{:ok, member} = Membership.create_member(member_attrs)
|
||||||
|
|
||||||
|
# Load the relationship to test it
|
||||||
|
{:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user])
|
||||||
|
assert member_with_user.user.id == user.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "user can be linked to member during update" do
|
||||||
|
{:ok, user} = Accounts.create_user(@valid_user_attrs)
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
{:ok, updated_user} = Accounts.update_user(user, %{member: %{id: member.id}})
|
||||||
|
|
||||||
|
# Load the relationship to test it
|
||||||
|
{:ok, user_with_member} = Ash.get(Mv.Accounts.User, updated_user.id, load: [:member])
|
||||||
|
assert user_with_member.member.id == member.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "member can be linked to user during update using manage_relationship" do
|
||||||
|
{:ok, user} = Accounts.create_user(@valid_user_attrs)
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
{:ok, _updated_member} = Membership.update_member(member, %{user: %{id: user.id}})
|
||||||
|
|
||||||
|
# Load the relationship to test it
|
||||||
|
{:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user])
|
||||||
|
assert member_with_user.user.id == user.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "User-Member Relationship - Inverse Relationship Tests" do
|
||||||
|
@valid_user_attrs %{
|
||||||
|
email: "test2@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
@valid_member_attrs %{
|
||||||
|
first_name: "Bob",
|
||||||
|
last_name: "Smith",
|
||||||
|
email: "bob@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
test "ash resolves inverse relationship automatically" do
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
user_attrs = Map.put(@valid_user_attrs, :member, %{id: member.id})
|
||||||
|
{:ok, user} = Accounts.create_user(user_attrs)
|
||||||
|
|
||||||
|
# Load relationships
|
||||||
|
{:ok, user_with_member} = Ash.get(Mv.Accounts.User, user.id, load: [:member])
|
||||||
|
{:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user])
|
||||||
|
|
||||||
|
assert user_with_member.member.id == member.id
|
||||||
|
assert member_with_user.user.id == user.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "member can find associated user" do
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
{:ok, user} = Accounts.create_user(%{email: "test3@example.com", member: %{id: member.id}})
|
||||||
|
{:ok, member_with_user} = Ash.get(Mv.Membership.Member, member.id, load: [:user])
|
||||||
|
assert member_with_user.user.id == user.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "User-Member Relationship - Preventing Duplicates" do
|
||||||
|
@valid_user_attrs %{
|
||||||
|
email: "test4@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
@valid_member_attrs %{
|
||||||
|
first_name: "Charlie",
|
||||||
|
last_name: "Brown",
|
||||||
|
email: "charlie@example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
test "prevents overwriting a member of already linked user on update" do
|
||||||
|
{:ok, existing_member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
user_attrs = Map.put(@valid_user_attrs, :member, %{id: existing_member.id})
|
||||||
|
{:ok, user} = Accounts.create_user(user_attrs)
|
||||||
|
|
||||||
|
{:ok, member2} =
|
||||||
|
Membership.create_member(%{
|
||||||
|
first_name: "Dave",
|
||||||
|
last_name: "Wilson",
|
||||||
|
email: "dave@example.com"
|
||||||
|
})
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{}} =
|
||||||
|
Accounts.update_user(user, %{member: %{id: member2.id}})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "prevents linking user to already linked member on update" do
|
||||||
|
{:ok, existing_user} = Accounts.create_user(@valid_user_attrs)
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
{:ok, _updated_user} = Accounts.update_user(existing_user, %{member: %{id: member.id}})
|
||||||
|
|
||||||
|
{:ok, user2} = Accounts.create_user(%{email: "test5@example.com"})
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{}} =
|
||||||
|
Accounts.update_user(user2, %{member: %{id: member.id}})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "prevents linking member to already linked user on creation" do
|
||||||
|
{:ok, existing_member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
user_attrs = Map.put(@valid_user_attrs, :member, %{id: existing_member.id})
|
||||||
|
{:ok, user} = Accounts.create_user(user_attrs)
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{}} =
|
||||||
|
Membership.create_member(%{
|
||||||
|
first_name: "Dave",
|
||||||
|
last_name: "Wilson",
|
||||||
|
email: "dave@example.com",
|
||||||
|
user: %{id: user.id}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "prevents linking user to already linked member on creation" do
|
||||||
|
{:ok, existing_user} = Accounts.create_user(@valid_user_attrs)
|
||||||
|
{:ok, member} = Membership.create_member(@valid_member_attrs)
|
||||||
|
|
||||||
|
{:ok, _updated_user} = Accounts.update_user(existing_user, %{member: %{id: member.id}})
|
||||||
|
|
||||||
|
assert {:error, %Ash.Error.Invalid{}} =
|
||||||
|
Accounts.create_user(%{
|
||||||
|
email: "test5@example.com",
|
||||||
|
member: %{id: member.id}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -255,7 +255,7 @@ defmodule MvWeb.UserLive.FormTest do
|
||||||
conn = Plug.Test.init_test_session(conn, locale: "de")
|
conn = Plug.Test.init_test_session(conn, locale: "de")
|
||||||
{:ok, _view, html} = live(conn, "/users/new")
|
{:ok, _view, html} = live(conn, "/users/new")
|
||||||
|
|
||||||
assert html =~ "Neuer Benutzer"
|
assert html =~ "Neue*r Benutzer*in"
|
||||||
assert html =~ "E-Mail"
|
assert html =~ "E-Mail"
|
||||||
assert html =~ "Passwort setzen"
|
assert html =~ "Passwort setzen"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ defmodule MvWeb.UserLive.IndexTest do
|
||||||
conn = conn_with_oidc_user(conn)
|
conn = conn_with_oidc_user(conn)
|
||||||
conn = Plug.Test.init_test_session(conn, locale: "de")
|
conn = Plug.Test.init_test_session(conn, locale: "de")
|
||||||
{:ok, _view, html} = live(conn, "/users")
|
{:ok, _view, html} = live(conn, "/users")
|
||||||
assert html =~ "Benutzer auflisten"
|
assert html =~ "Benutzer*innen auflisten"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows translated title in English", %{conn: conn} do
|
test "shows translated title in English", %{conn: conn} do
|
||||||
|
|
@ -362,8 +362,8 @@ defmodule MvWeb.UserLive.IndexTest do
|
||||||
conn = Plug.Test.init_test_session(conn, locale: "de")
|
conn = Plug.Test.init_test_session(conn, locale: "de")
|
||||||
{:ok, _view, html} = live(conn, "/users")
|
{:ok, _view, html} = live(conn, "/users")
|
||||||
|
|
||||||
assert html =~ "Alle Benutzer auswählen"
|
assert html =~ "Alle Benutzer*innen auswählen"
|
||||||
assert html =~ "Benutzer auswählen"
|
assert html =~ "Benutzer*in auswählen"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows English translations for selection", %{conn: conn} do
|
test "shows English translations for selection", %{conn: conn} do
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue