From 62b37b9aa224bd982e5f0c35520f21b3899b0a51 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 24 Feb 2026 13:55:33 +0100 Subject: [PATCH] feat: Datafields page, merge fee types into membership_fee_settings, sidebar - Add /admin/datafields (DatafieldsLive) for member and custom field config - Remove Memberdata block from GlobalSettingsLive - Router: drop /membership_fee_types, add new_fee_type and edit_fee_type under membership_fee_settings - MembershipFeeSettingsLive: fee types table, collapsible examples; Index links updated - PagePaths: admin_datafields, admin_import; remove membership_fee_types - Sidebar: order and labels (Basic settings, Datafields, Membership fee settings, Import, Users, Roles) - Gettext: German translations for sidebar and OIDC - Tests: datafields and fee routes, permission and form tests updated --- lib/mv_web/components/layouts/sidebar.ex | 30 +- lib/mv_web/live/datafields_live.ex | 132 ++++++++ .../live/membership_fee_settings_live.ex | 286 +++++++++++++++--- .../live/membership_fee_type_live/form.ex | 3 +- .../live/membership_fee_type_live/index.ex | 4 +- lib/mv_web/page_paths.ex | 10 +- lib/mv_web/router.ex | 12 +- priv/gettext/de/LC_MESSAGES/default.po | 162 ++++++++-- priv/gettext/default.pot | 162 ++++++++-- priv/gettext/en/LC_MESSAGES/default.po | 162 ++++++++-- test/mv/oidc_role_sync_test.exs | 33 +- .../components/sidebar_authorization_test.exs | 10 +- .../live/custom_field_live/deletion_test.exs | 18 +- .../mv_web/live/global_settings_live_test.exs | 16 - .../index_component_test.exs | 16 +- .../membership_fee_type_live/form_test.exs | 24 +- .../membership_fee_type_live/index_test.exs | 25 +- .../plugs/check_page_permission_test.exs | 32 +- 18 files changed, 886 insertions(+), 251 deletions(-) create mode 100644 lib/mv_web/live/datafields_live.ex diff --git a/lib/mv_web/components/layouts/sidebar.ex b/lib/mv_web/components/layouts/sidebar.ex index 7d4cce6..cb94fb3 100644 --- a/lib/mv_web/components/layouts/sidebar.ex +++ b/lib/mv_web/components/layouts/sidebar.ex @@ -80,11 +80,11 @@ defmodule MvWeb.Layouts.Sidebar do /> <% end %> - <%= if can_access_page?(@current_user, PagePaths.membership_fee_types()) do %> + <%= if can_access_page?(@current_user, PagePaths.groups()) do %> <.menu_item - href={~p"/membership_fee_types"} - icon="hero-currency-euro" - label={gettext("Fee Types")} + href={~p"/groups"} + icon="hero-user-group" + label={gettext("Groups")} /> <% end %> @@ -102,24 +102,26 @@ defmodule MvWeb.Layouts.Sidebar do label={gettext("Administration")} testid="sidebar-administration" > - <%= if can_access_page?(@current_user, PagePaths.users()) do %> - <.menu_subitem href={~p"/users"} label={gettext("Users")} /> + <%= if can_access_page?(@current_user, PagePaths.settings()) do %> + <.menu_subitem href={~p"/settings"} label={gettext("Basic settings")} /> <% end %> - <%= if can_access_page?(@current_user, PagePaths.groups()) do %> - <.menu_subitem href={~p"/groups"} label={gettext("Groups")} /> - <% end %> - <%= if can_access_page?(@current_user, PagePaths.admin_roles()) do %> - <.menu_subitem href={~p"/admin/roles"} label={gettext("Roles")} /> + <%= if can_access_page?(@current_user, PagePaths.admin_datafields()) do %> + <.menu_subitem href={~p"/admin/datafields"} label={gettext("Datafields")} /> <% end %> <%= if can_access_page?(@current_user, PagePaths.membership_fee_settings()) do %> <.menu_subitem href={~p"/membership_fee_settings"} - label={gettext("Fee Settings")} + label={gettext("Membership fee settings")} /> <% end %> - <%= if can_access_page?(@current_user, PagePaths.settings()) do %> + <%= if can_access_page?(@current_user, PagePaths.admin_import()) do %> <.menu_subitem href={~p"/admin/import"} label={gettext("Import")} /> - <.menu_subitem href={~p"/settings"} label={gettext("Settings")} /> + <% end %> + <%= if can_access_page?(@current_user, PagePaths.users()) do %> + <.menu_subitem href={~p"/users"} label={gettext("Users")} /> + <% end %> + <%= if can_access_page?(@current_user, PagePaths.admin_roles()) do %> + <.menu_subitem href={~p"/admin/roles"} label={gettext("Roles")} /> <% end %> <% end %> diff --git a/lib/mv_web/live/datafields_live.ex b/lib/mv_web/live/datafields_live.ex new file mode 100644 index 0000000..f7436ab --- /dev/null +++ b/lib/mv_web/live/datafields_live.ex @@ -0,0 +1,132 @@ +defmodule MvWeb.DatafieldsLive do + @moduledoc """ + LiveView for managing member field visibility/required and custom fields (datafields). + + Renders MemberFieldLive.IndexComponent and CustomFieldLive.IndexComponent. + Moved from GlobalSettingsLive (Memberdata section) to a dedicated page. + """ + use MvWeb, :live_view + + alias Mv.Membership + + on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded} + + @impl true + def mount(_params, _session, socket) do + {:ok, settings} = Membership.get_settings() + + {:ok, + socket + |> assign(:page_title, gettext("Datafields")) + |> assign(:settings, settings) + |> assign(:active_editing_section, nil)} + end + + @impl true + def render(assigns) do + ~H""" + + <.header> + {gettext("Datafields")} + <:subtitle> + {gettext("Configure member fields and custom data fields.")} + + + + <.form_section title={gettext("Member fields")}> + <.live_component + :if={@active_editing_section != :custom_fields} + module={MvWeb.MemberFieldLive.IndexComponent} + id="member-fields-component" + settings={@settings} + /> + + + <.form_section title={gettext("Custom fields")}> + <.live_component + :if={@active_editing_section != :member_fields} + module={MvWeb.CustomFieldLive.IndexComponent} + id="custom-fields-component" + actor={@current_user} + /> + + + """ + end + + @impl true + def handle_info({:custom_field_saved, _custom_field, action}, socket) do + send_update(MvWeb.CustomFieldLive.IndexComponent, + id: "custom-fields-component", + show_form: false + ) + + {:noreply, + socket + |> assign(:active_editing_section, nil) + |> put_flash(:info, gettext("Data field %{action} successfully", action: action))} + end + + @impl true + def handle_info({:custom_field_deleted, _custom_field}, socket) do + {:noreply, put_flash(socket, :info, gettext("Data field deleted successfully"))} + end + + @impl true + def handle_info({:custom_field_delete_error, error}, socket) do + {:noreply, + put_flash( + socket, + :error, + gettext("Failed to delete data field: %{error}", error: inspect(error)) + )} + end + + @impl true + def handle_info(:custom_field_slug_mismatch, socket) do + {:noreply, put_flash(socket, :error, gettext("Slug does not match. Deletion cancelled."))} + end + + def handle_info({:custom_fields_load_error, _error}, socket) do + {:noreply, + put_flash( + socket, + :error, + gettext("Could not load data fields. Please check your permissions.") + )} + end + + @impl true + def handle_info({:editing_section_changed, section}, socket) do + {:noreply, assign(socket, :active_editing_section, section)} + end + + @impl true + def handle_info({:member_field_saved, _member_field, action}, socket) do + {:ok, updated_settings} = Membership.get_settings() + + send_update(MvWeb.MemberFieldLive.IndexComponent, + id: "member-fields-component", + show_form: false, + settings: updated_settings + ) + + {:noreply, + socket + |> assign(:settings, updated_settings) + |> assign(:active_editing_section, nil) + |> put_flash(:info, gettext("Member field %{action} successfully", action: action))} + end + + @impl true + def handle_info({:member_field_visibility_updated}, socket) do + {:ok, updated_settings} = Membership.get_settings() + + send_update(MvWeb.MemberFieldLive.IndexComponent, + id: "member-fields-component", + settings: updated_settings + ) + + {:noreply, assign(socket, :settings, updated_settings)} + end +end diff --git a/lib/mv_web/live/membership_fee_settings_live.ex b/lib/mv_web/live/membership_fee_settings_live.ex index 2b79c4e..bfa20f8 100644 --- a/lib/mv_web/live/membership_fee_settings_live.ex +++ b/lib/mv_web/live/membership_fee_settings_live.ex @@ -1,17 +1,23 @@ defmodule MvWeb.MembershipFeeSettingsLive do @moduledoc """ - LiveView for managing membership fee settings (Admin). + LiveView for membership fee settings and fee types (Admin). - Allows administrators to configure: - - Default membership fee type for new members - - Whether to include the joining cycle in membership fee generation + Combines: + - Global settings (default fee type, include joining cycle) + - Membership fee types table (CRUD links to new/edit routes; delete inline) + Examples and info are collapsible to save space. """ use MvWeb, :live_view + require Ash.Query + import MvWeb.LiveHelpers, only: [current_actor: 1] alias Mv.Membership + alias Mv.Membership.Member + alias Mv.MembershipFees alias Mv.MembershipFees.MembershipFeeType + alias MvWeb.Helpers.MembershipFeeHelpers @impl true def mount(_params, _session, socket) do @@ -23,11 +29,14 @@ defmodule MvWeb.MembershipFeeSettingsLive do |> Ash.Query.sort(name: :asc) |> Ash.read!(domain: Mv.MembershipFees, actor: actor) + member_counts = load_member_counts(membership_fee_types, actor) + {:ok, socket |> assign(:page_title, gettext("Membership Fee Settings")) |> assign(:settings, settings) |> assign(:membership_fee_types, membership_fee_types) + |> assign(:member_counts, member_counts) |> assign_form()} end @@ -81,6 +90,51 @@ defmodule MvWeb.MembershipFeeSettingsLive do end end + @impl true + def handle_event("delete", %{"id" => id}, socket) do + actor = current_actor(socket) + + case Ash.get(MembershipFeeType, id, domain: MembershipFees, actor: actor) do + {:ok, fee_type} -> + case Ash.destroy(fee_type, domain: MembershipFees, actor: actor) do + :ok -> + updated_types = Enum.reject(socket.assigns.membership_fee_types, &(&1.id == id)) + updated_counts = Map.delete(socket.assigns.member_counts, id) + + {:noreply, + socket + |> assign(:membership_fee_types, updated_types) + |> assign(:member_counts, updated_counts) + |> put_flash(:info, gettext("Membership fee type deleted"))} + + {:error, %Ash.Error.Forbidden{}} -> + {:noreply, + put_flash( + socket, + :error, + gettext("You do not have permission to delete this membership fee type") + )} + + {:error, error} -> + {:noreply, put_flash(socket, :error, format_error(error))} + end + + {:error, %Ash.Error.Query.NotFound{}} -> + {:noreply, put_flash(socket, :error, gettext("Membership fee type not found"))} + + {:error, %Ash.Error.Forbidden{}} -> + {:noreply, + put_flash( + socket, + :error, + gettext("You do not have permission to access this membership fee type") + )} + + {:error, error} -> + {:noreply, put_flash(socket, :error, format_error(error))} + end + end + @impl true def render(assigns) do ~H""" @@ -88,8 +142,13 @@ defmodule MvWeb.MembershipFeeSettingsLive do <.header> {gettext("Membership Fee Settings")} <:subtitle> - {gettext("Configure global settings for membership fees.")} + {gettext("Configure global settings and fee types for membership fees.")} + <:actions> + <.button variant="primary" navigate={~p"/membership_fee_settings/new_fee_type"}> + <.icon name="hero-plus" /> {gettext("New Membership Fee Type")} + +
@@ -188,58 +247,169 @@ defmodule MvWeb.MembershipFeeSettingsLive do
- <%!-- Examples Card --%> + <%!-- Examples Card (collapsible) --%>
-

- <.icon name="hero-light-bulb" class="size-5" /> - {gettext("Examples")} -

+
+ + <.icon name="hero-chevron-right" class="size-5 transition group-open:rotate-90" /> + <.icon name="hero-light-bulb" class="size-5" /> + {gettext("Examples")} + - <.example_section - title={gettext("Yearly Interval - Joining Cycle Included")} - joining_date="15.03.2023" - include_joining={true} - start_date="01.01.2023" - periods={["2023", "2024", "2025"]} - note={gettext("Member pays for the year they joined")} - /> +
+ <.example_section + title={gettext("Yearly Interval - Joining Cycle Included")} + joining_date="15.03.2023" + include_joining={true} + start_date="01.01.2023" + periods={["2023", "2024", "2025"]} + note={gettext("Member pays for the year they joined")} + /> -
+
- <.example_section - title={gettext("Yearly Interval - Joining Cycle Excluded")} - joining_date="15.03.2023" - include_joining={false} - start_date="01.01.2024" - periods={["2024", "2025"]} - note={gettext("Member pays from the next full year")} - /> + <.example_section + title={gettext("Yearly Interval - Joining Cycle Excluded")} + joining_date="15.03.2023" + include_joining={false} + start_date="01.01.2024" + periods={["2024", "2025"]} + note={gettext("Member pays from the next full year")} + /> -
+
- <.example_section - title={gettext("Quarterly Interval - Joining Cycle Excluded")} - joining_date="15.05.2024" - include_joining={false} - start_date="01.07.2024" - periods={["Q3/2024", "Q4/2024", "Q1/2025"]} - note={gettext("Member pays from the next full quarter")} - /> + <.example_section + title={gettext("Quarterly Interval - Joining Cycle Excluded")} + joining_date="15.05.2024" + include_joining={false} + start_date="01.07.2024" + periods={["Q3/2024", "Q4/2024", "Q1/2025"]} + note={gettext("Member pays from the next full quarter")} + /> -
+
- <.example_section - title={gettext("Monthly Interval - Joining Cycle Included")} - joining_date="15.03.2024" - include_joining={true} - start_date="01.03.2024" - periods={["03/2024", "04/2024", "05/2024", "..."]} - note={gettext("Member pays from the joining month")} - /> + <.example_section + title={gettext("Monthly Interval - Joining Cycle Included")} + joining_date="15.03.2024" + include_joining={true} + start_date="01.03.2024" + periods={["03/2024", "04/2024", "05/2024", "..."]} + note={gettext("Member pays from the joining month")} + /> +
+
+ + <%!-- Fee Types Table --%> +
+

{gettext("Membership Fee Types")}

+ <.table + id="membership_fee_types" + rows={@membership_fee_types} + row_id={fn mft -> "mft-#{mft.id}" end} + > + <:col :let={mft} label={gettext("Name")}> + {mft.name} +

{mft.description}

+ + + <:col :let={mft} label={gettext("Amount")}> + {MembershipFeeHelpers.format_currency(mft.amount)} + + + <:col :let={mft} label={gettext("Interval")}> + + {MembershipFeeHelpers.format_interval(mft.interval)} + + + + <:col :let={mft} label={gettext("Members")}> + {get_member_count(mft, @member_counts)} + + + <:action :let={mft}> + <.link + navigate={~p"/membership_fee_settings/#{mft.id}/edit_fee_type"} + class="btn btn-ghost btn-xs" + aria-label={gettext("Edit membership fee type")} + > + <.icon name="hero-pencil" class="size-4" /> + + + + <:action :let={mft}> +
0} + class="tooltip tooltip-left" + data-tip={ + gettext("Cannot delete - %{count} member(s) assigned", + count: get_member_count(mft, @member_counts) + ) + } + > + +
+ + + + +
+ + <.icon name="hero-information-circle" class="size-5" /> + {gettext("About Membership Fee Types")} + +
+

+ {gettext( + "Membership fee types define different membership fee structures. Each type has a fixed interval (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation." + )} +

+
    +
  • + {gettext("Name & Amount")} + - {gettext("Can be changed at any time. Amount changes affect future periods only.")} +
  • +
  • + {gettext("Interval")} + - {gettext( + "Fixed after creation. Members can only switch between types with the same interval." + )} +
  • +
  • + {gettext("Deletion")} + - {gettext("Only possible if no members are assigned to this type.")} +
  • +
+
+
+
""" end @@ -286,6 +456,32 @@ defmodule MvWeb.MembershipFeeSettingsLive do defp format_interval(:half_yearly), do: gettext("Half-yearly") defp format_interval(:yearly), do: gettext("Yearly") + defp load_member_counts(fee_types, actor) do + fee_type_ids = Enum.map(fee_types, & &1.id) + + members = + Member + |> Ash.Query.filter(membership_fee_type_id in ^fee_type_ids) + |> Ash.Query.select([:membership_fee_type_id]) + |> Ash.read!(domain: Membership, actor: actor) + + members + |> Enum.group_by(& &1.membership_fee_type_id) + |> Enum.map(fn {fee_type_id, members_list} -> {fee_type_id, length(members_list)} end) + |> Map.new() + end + + defp get_member_count(fee_type, member_counts) do + Map.get(member_counts, fee_type.id, 0) + end + + defp format_error(%Ash.Error.Invalid{} = error) do + Enum.map_join(error.errors, ", ", fn e -> e.message end) + end + + defp format_error(error) when is_binary(error), do: error + defp format_error(_error), do: gettext("An error occurred") + defp assign_form(%{assigns: %{settings: settings}} = socket) do form = AshPhoenix.Form.for_update( diff --git a/lib/mv_web/live/membership_fee_type_live/form.ex b/lib/mv_web/live/membership_fee_type_live/form.ex index 6fe80a8..d8569e2 100644 --- a/lib/mv_web/live/membership_fee_type_live/form.ex +++ b/lib/mv_web/live/membership_fee_type_live/form.ex @@ -384,7 +384,8 @@ defmodule MvWeb.MembershipFeeTypeLive.Form do defp format_interval_value(value), do: to_string(value) @spec return_path(String.t(), MembershipFeeType.t() | nil) :: String.t() - defp return_path("index", _membership_fee_type), do: ~p"/membership_fee_types" + defp return_path("index", _membership_fee_type), do: ~p"/membership_fee_settings" + defp return_path(_, _), do: ~p"/membership_fee_settings" @spec get_affected_member_count(String.t(), Mv.Accounts.User.t() | nil) :: non_neg_integer() # Checks if amount changed and updates socket assigns accordingly diff --git a/lib/mv_web/live/membership_fee_type_live/index.ex b/lib/mv_web/live/membership_fee_type_live/index.ex index 84cd26d..f5f760f 100644 --- a/lib/mv_web/live/membership_fee_type_live/index.ex +++ b/lib/mv_web/live/membership_fee_type_live/index.ex @@ -47,7 +47,7 @@ defmodule MvWeb.MembershipFeeTypeLive.Index do {gettext("Manage membership fee types for membership fees.")} <:actions> - <.button variant="primary" navigate={~p"/membership_fee_types/new"}> + <.button variant="primary" navigate={~p"/membership_fee_settings/new_fee_type"}> <.icon name="hero-plus" /> {gettext("New Membership Fee Type")} @@ -79,7 +79,7 @@ defmodule MvWeb.MembershipFeeTypeLive.Index do <:action :let={mft}> <.link - navigate={~p"/membership_fee_types/#{mft.id}/edit"} + navigate={~p"/membership_fee_settings/#{mft.id}/edit_fee_type"} class="btn btn-ghost btn-xs" aria-label={gettext("Edit membership fee type")} > diff --git a/lib/mv_web/page_paths.ex b/lib/mv_web/page_paths.ex index 2720c0f..551cada 100644 --- a/lib/mv_web/page_paths.ex +++ b/lib/mv_web/page_paths.ex @@ -8,30 +8,30 @@ defmodule MvWeb.PagePaths do # Sidebar top-level menu paths @members "/members" - @membership_fee_types "/membership_fee_types" @statistics "/statistics" # Administration submenu paths (all must match router) @users "/users" @groups "/groups" @admin_roles "/admin/roles" + @admin_datafields "/admin/datafields" @membership_fee_settings "/membership_fee_settings" + @admin_import "/admin/import" @settings "/settings" @admin_page_paths [ @users, @groups, @admin_roles, + @admin_datafields, @membership_fee_settings, + @admin_import, @settings ] @doc "Path for Members index (sidebar and page permission check)." def members, do: @members - @doc "Path for Membership Fee Types index (sidebar and page permission check)." - def membership_fee_types, do: @membership_fee_types - @doc "Path for Statistics page (sidebar and page permission check)." def statistics, do: @statistics @@ -41,6 +41,8 @@ defmodule MvWeb.PagePaths do def users, do: @users def groups, do: @groups def admin_roles, do: @admin_roles + def admin_datafields, do: @admin_datafields def membership_fee_settings, do: @membership_fee_settings + def admin_import, do: @admin_import def settings, do: @settings end diff --git a/lib/mv_web/router.ex b/lib/mv_web/router.ex index ec90f1b..9e39937 100644 --- a/lib/mv_web/router.ex +++ b/lib/mv_web/router.ex @@ -68,16 +68,13 @@ defmodule MvWeb.Router do live "/settings", GlobalSettingsLive - # Membership Fee Settings + # Membership Fee Settings (includes fee types list; new/edit under sub-routes) live "/membership_fee_settings", MembershipFeeSettingsLive - - # Membership Fee Types Management - live "/membership_fee_types", MembershipFeeTypeLive.Index, :index + live "/membership_fee_settings/new_fee_type", MembershipFeeTypeLive.Form, :new + live "/membership_fee_settings/:id/edit_fee_type", MembershipFeeTypeLive.Form, :edit # Statistics live "/statistics", StatisticsLive, :index - live "/membership_fee_types/new", MembershipFeeTypeLive.Form, :new - live "/membership_fee_types/:id/edit", MembershipFeeTypeLive.Form, :edit # Groups Management live "/groups", GroupLive.Index, :index @@ -91,6 +88,9 @@ defmodule MvWeb.Router do live "/admin/roles/:id", RoleLive.Show, :show live "/admin/roles/:id/edit", RoleLive.Form, :edit + # Datafields (member fields + custom fields) + live "/admin/datafields", DatafieldsLive + # Import (Admin only) live "/admin/import", ImportLive diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index c0672c5..f70d343 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -18,6 +18,7 @@ msgid "Actions" msgstr "Aktionen" #: lib/mv_web/live/member_live/index.html.heex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/role_live/index.html.heex #: lib/mv_web/live/role_live/show.ex @@ -322,6 +323,7 @@ msgstr "Benutzer*innen auflisten" #: lib/mv_web/live/group_live/show.ex #: lib/mv_web/live/member_live/index.ex #: lib/mv_web/live/member_live/index.html.heex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/statistics_live.ex #, elixir-autogen, elixir-format @@ -335,6 +337,7 @@ msgstr "Mitglieder" #: lib/mv_web/live/group_live/show.ex #: lib/mv_web/live/member_field_live/form_component.ex #: lib/mv_web/live/member_field_live/index_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/role_live/form.ex @@ -382,7 +385,6 @@ msgstr "Alle Mitglieder auswählen" msgid "Select member" msgstr "Mitglied auswählen" -#: lib/mv_web/components/layouts/sidebar.ex #: lib/mv_web/live/global_settings_live.ex #, elixir-autogen, elixir-format msgid "Settings" @@ -842,6 +844,7 @@ msgid "Create Member" msgstr "Mitglied erstellen" #: lib/mv_web/live/member_live/show/membership_fees_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format @@ -853,11 +856,13 @@ msgstr "Betrag" msgid "Back to Settings" msgstr "Zurück zu den Einstellungen" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Can be changed at any time. Amount changes affect future periods only." msgstr "Kann jederzeit geändert werden. Änderungen des Betrags betreffen nur zukünftige Zyklen." +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Deletion" @@ -868,6 +873,7 @@ msgstr "Löschen" msgid "Examples" msgstr "Beispiele" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Fixed after creation. Members can only switch between types with the same interval." @@ -886,6 +892,7 @@ msgid "Half-yearly" msgstr "Halbjährlich" #: lib/mv_web/live/member_live/show/membership_fees_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format @@ -924,11 +931,13 @@ msgstr "Mitglied zahlt ab dem nächsten vollständigen Jahr" msgid "Monthly" msgstr "Monatlich" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Name & Amount" msgstr "Name & Betrag" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Only possible if no members are assigned to this type." @@ -1002,7 +1011,7 @@ msgstr "Alle auswählen" msgid "Select none" msgstr "Keine auswählen" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Slug does not match. Deletion cancelled." msgstr "Eingegebener Text war nicht korrekt. Vorgang abgebrochen." @@ -1044,11 +1053,6 @@ msgstr "Textfeld" msgid "Yes/No-Selection" msgstr "Ja/Nein-Auswahl" -#: lib/mv_web/live/global_settings_live.ex -#, elixir-autogen, elixir-format, fuzzy -msgid "Memberdata" -msgstr "Mitgliederdaten" - #: lib/mv_web/live/custom_field_live/index_component.ex #: lib/mv_web/live/member_field_live/index_component.ex #, elixir-autogen, elixir-format @@ -1060,7 +1064,7 @@ msgstr "Optional" msgid "These fields are neccessary for MILA to handle member identification and payment calculations in the future. Thus you cannot delete these fields but hide them in the member overview." msgstr "Diese Datenfelder sind für MILA notwendig um Mitglieder zu identifizieren und zukünftig Beitragszahlungen zu berechnen. Aus diesem Grund können sie nicht gelöscht, aber in der Übersicht ausgeblendet werden." -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Member field %{action} successfully" msgstr "Mitgliedsfeld wurde erfolgreich %{action}" @@ -1070,6 +1074,7 @@ msgstr "Mitgliedsfeld wurde erfolgreich %{action}" msgid "A cycle for this period already exists" msgstr "Ein Zyklus für diesen Zeitraum existiert bereits" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "About Membership Fee Types" @@ -1086,6 +1091,7 @@ msgid "Already paid cycles will remain with the old amount." msgstr "Bereits bezahlte Zyklen bleiben mit dem alten Betrag." #: lib/mv_web/live/member_live/show/membership_fees_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/role_live/helpers.ex #, elixir-autogen, elixir-format @@ -1097,6 +1103,7 @@ msgstr "Ein Fehler ist aufgetreten" msgid "Are you sure you want to delete this cycle?" msgstr "Möchtest du diesen Zyklus wirklich löschen?" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Cannot delete - %{count} member(s) assigned" @@ -1117,11 +1124,6 @@ msgstr "Die Änderung des Betrags betrifft %{count} Mitglied(er)." msgid "Click to edit amount" msgstr "Klicke, um den Betrag zu bearbeiten" -#: lib/mv_web/live/membership_fee_settings_live.ex -#, elixir-autogen, elixir-format, fuzzy -msgid "Configure global settings for membership fees." -msgstr "Globale Einstellungen für Mitgliedsbeiträge konfigurieren." - #: lib/mv_web/live/membership_fee_type_live/form.ex #, elixir-autogen, elixir-format msgid "Confirm Change" @@ -1232,6 +1234,7 @@ msgstr "Feld bearbeiten: %{field}" msgid "Edit Membership Fee Type" msgstr "Mitgliedsbeitragsart bearbeiten" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Edit membership fee type" @@ -1330,6 +1333,7 @@ msgstr "Mitgliedsbeitragsstatus" msgid "Membership Fee Type" msgstr "Mitgliedsbeitragsart" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Membership Fee Types" @@ -1346,6 +1350,7 @@ msgstr "Mitgliedsbeiträge" msgid "Membership fee start" msgstr "Beitragsbeginn" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Membership fee type deleted" @@ -1366,6 +1371,7 @@ msgstr "Mitgliedsbeitragsart erfolgreich gespeichert" msgid "Membership fee type updated. Cycles regenerated." msgstr "Mitgliedsbeitragsart aktualisiert. Zyklen regeneriert." +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Membership fee types define different membership fee structures. Each type has a fixed interval (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation." @@ -1376,6 +1382,7 @@ msgstr "Mitgliedsbeitragsarten definieren verschiedene Mitgliedsbeitragsstruktur msgid "Monthly Interval - Joining Cycle Included" msgstr "Monatliches Intervall – Beitrittszeitraum einbezogen" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format @@ -1550,6 +1557,7 @@ msgstr "Jährliches Intervall – Beitrittszeitraum einbezogen" msgid "You are about to delete all %{count} cycles for this member." msgstr "Du bist dabei alle %{count} Zyklen für dieses Mitglied zu löschen." +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Delete Membership Fee Type" @@ -1571,12 +1579,12 @@ msgstr "Spalten ein-/ausblenden" msgid "Back to settings" msgstr "Zurück zu den Einstellungen" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Data field %{action} successfully" msgstr "Datenfeld erfolgreich %{action}" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Data field deleted successfully" msgstr "Datenfeld erfolgreich gelöscht" @@ -1591,7 +1599,7 @@ msgstr "Datenfeld löschen" msgid "Edit Data Field" msgstr "Datenfeld bearbeiten" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Failed to delete data field: %{error}" msgstr "Konnte Datenfeld nicht löschen: %{error}" @@ -1823,6 +1831,7 @@ msgstr "Zyklus löschen" msgid "The cycle period will be calculated based on this date and the interval." msgstr "Der Zyklus wird basierend auf diesem Datum und dem Intervall berechnet." +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Membership fee type not found" @@ -1843,6 +1852,7 @@ msgstr "Benutzer*in erfolgreich gelöscht" msgid "User not found" msgstr "Benutzer*in nicht gefunden" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "You do not have permission to access this membership fee type" @@ -1853,6 +1863,7 @@ msgstr "Du hast keine Berechtigung, auf diese Mitgliedsbeitragsart zuzugreifen" msgid "You do not have permission to access this user" msgstr "Du hast keine Berechtigung, auf diese*n Benutzer*in zuzugreifen" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "You do not have permission to delete this membership fee type" @@ -1924,16 +1935,6 @@ msgstr "E-Mail ist erforderlich." msgid "Roles" msgstr "Rollen" -#: lib/mv_web/components/layouts/sidebar.ex -#, elixir-autogen, elixir-format, fuzzy -msgid "Fee Settings" -msgstr "Beitragseinstellungen" - -#: lib/mv_web/components/layouts/sidebar.ex -#, elixir-autogen, elixir-format -msgid "Fee Types" -msgstr "Beitragstypen" - #: lib/mv_web/components/layouts/sidebar.ex #, elixir-autogen, elixir-format msgid "Administration" @@ -2272,7 +2273,7 @@ msgstr "Dieser Benutzer kann nicht angezeigt werden." msgid "Not authorized." msgstr "Nicht berechtigt." -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Could not load data fields. Please check your permissions." msgstr "Datenfelder konnten nicht geladen werden. Bitte überprüfe deine Berechtigungen." @@ -2423,6 +2424,7 @@ msgstr "Beitragsart auswählen" msgid "Linked" msgstr "Verknüpft" +#: lib/mv_web/live/global_settings_live.ex #: lib/mv_web/live/user_live/index.html.heex #: lib/mv_web/live/user_live/show.ex #, elixir-autogen, elixir-format @@ -2975,3 +2977,109 @@ msgstr "Für die Vereinfacht-Integration erforderlich und kann nicht deaktiviert #, elixir-autogen, elixir-format msgid "Fee Type" msgstr "Beitragsart" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Admin group name" +msgstr "Admin-Gruppenname" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Base URL" +msgstr "Basis-URL" + +#: lib/mv_web/components/layouts/sidebar.ex +#, elixir-autogen, elixir-format +msgid "Basic settings" +msgstr "Grundeinstellungen" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Client ID" +msgstr "Client-ID" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Client Secret" +msgstr "Client-Geheimnis" + +#: lib/mv_web/live/membership_fee_settings_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Configure global settings and fee types for membership fees." +msgstr "Globale Einstellungen für Mitgliedsbeiträge konfigurieren." + +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format +msgid "Configure member fields and custom data fields." +msgstr "Mitgliedsfelder und benutzerdefinierte Datenfelder konfigurieren." + +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Custom fields" +msgstr "Benutzerdefinierte Felder" + +#: lib/mv_web/components/layouts/sidebar.ex +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format +msgid "Datafields" +msgstr "Datenfelder" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_ADMIN_GROUP_NAME" +msgstr "Aus OIDC_ADMIN_GROUP_NAME" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_BASE_URL" +msgstr "Aus OIDC_BASE_URL" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_CLIENT_ID" +msgstr "Aus OIDC_CLIENT_ID" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_CLIENT_SECRET" +msgstr "Aus OIDC_CLIENT_SECRET" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_GROUPS_CLAIM" +msgstr "Aus OIDC_GROUPS_CLAIM" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_REDIRECT_URI" +msgstr "Aus OIDC_REDIRECT_URI" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Groups claim" +msgstr "Gruppen" + +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Member fields" +msgstr "Mitgliedsfilter" + +#: lib/mv_web/components/layouts/sidebar.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Membership fee settings" +msgstr "Beitragseinstellungen" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Redirect URI" +msgstr "Weiterleitungs-URI" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Save OIDC Settings" +msgstr "Einstellungen speichern" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "e.g. admin" +msgstr "z. B. admin" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index e26b874..5347731 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -19,6 +19,7 @@ msgid "Actions" msgstr "" #: lib/mv_web/live/member_live/index.html.heex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/role_live/index.html.heex #: lib/mv_web/live/role_live/show.ex @@ -323,6 +324,7 @@ msgstr "" #: lib/mv_web/live/group_live/show.ex #: lib/mv_web/live/member_live/index.ex #: lib/mv_web/live/member_live/index.html.heex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/statistics_live.ex #, elixir-autogen, elixir-format @@ -336,6 +338,7 @@ msgstr "" #: lib/mv_web/live/group_live/show.ex #: lib/mv_web/live/member_field_live/form_component.ex #: lib/mv_web/live/member_field_live/index_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/role_live/form.ex @@ -383,7 +386,6 @@ msgstr "" msgid "Select member" msgstr "" -#: lib/mv_web/components/layouts/sidebar.ex #: lib/mv_web/live/global_settings_live.ex #, elixir-autogen, elixir-format msgid "Settings" @@ -843,6 +845,7 @@ msgid "Create Member" msgstr "" #: lib/mv_web/live/member_live/show/membership_fees_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format @@ -854,11 +857,13 @@ msgstr "" msgid "Back to Settings" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Can be changed at any time. Amount changes affect future periods only." msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Deletion" @@ -869,6 +874,7 @@ msgstr "" msgid "Examples" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Fixed after creation. Members can only switch between types with the same interval." @@ -887,6 +893,7 @@ msgid "Half-yearly" msgstr "" #: lib/mv_web/live/member_live/show/membership_fees_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format @@ -925,11 +932,13 @@ msgstr "" msgid "Monthly" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Name & Amount" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Only possible if no members are assigned to this type." @@ -1003,7 +1012,7 @@ msgstr "" msgid "Select none" msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Slug does not match. Deletion cancelled." msgstr "" @@ -1045,11 +1054,6 @@ msgstr "" msgid "Yes/No-Selection" msgstr "" -#: lib/mv_web/live/global_settings_live.ex -#, elixir-autogen, elixir-format -msgid "Memberdata" -msgstr "" - #: lib/mv_web/live/custom_field_live/index_component.ex #: lib/mv_web/live/member_field_live/index_component.ex #, elixir-autogen, elixir-format @@ -1061,7 +1065,7 @@ msgstr "" msgid "These fields are neccessary for MILA to handle member identification and payment calculations in the future. Thus you cannot delete these fields but hide them in the member overview." msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Member field %{action} successfully" msgstr "" @@ -1071,6 +1075,7 @@ msgstr "" msgid "A cycle for this period already exists" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "About Membership Fee Types" @@ -1087,6 +1092,7 @@ msgid "Already paid cycles will remain with the old amount." msgstr "" #: lib/mv_web/live/member_live/show/membership_fees_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/role_live/helpers.ex #, elixir-autogen, elixir-format @@ -1098,6 +1104,7 @@ msgstr "" msgid "Are you sure you want to delete this cycle?" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Cannot delete - %{count} member(s) assigned" @@ -1118,11 +1125,6 @@ msgstr "" msgid "Click to edit amount" msgstr "" -#: lib/mv_web/live/membership_fee_settings_live.ex -#, elixir-autogen, elixir-format -msgid "Configure global settings for membership fees." -msgstr "" - #: lib/mv_web/live/membership_fee_type_live/form.ex #, elixir-autogen, elixir-format msgid "Confirm Change" @@ -1233,6 +1235,7 @@ msgstr "" msgid "Edit Membership Fee Type" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Edit membership fee type" @@ -1331,6 +1334,7 @@ msgstr "" msgid "Membership Fee Type" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Membership Fee Types" @@ -1347,6 +1351,7 @@ msgstr "" msgid "Membership fee start" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Membership fee type deleted" @@ -1367,6 +1372,7 @@ msgstr "" msgid "Membership fee type updated. Cycles regenerated." msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Membership fee types define different membership fee structures. Each type has a fixed interval (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation." @@ -1377,6 +1383,7 @@ msgstr "" msgid "Monthly Interval - Joining Cycle Included" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format @@ -1551,6 +1558,7 @@ msgstr "" msgid "You are about to delete all %{count} cycles for this member." msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Delete Membership Fee Type" @@ -1572,12 +1580,12 @@ msgstr "" msgid "Back to settings" msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Data field %{action} successfully" msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Data field deleted successfully" msgstr "" @@ -1592,7 +1600,7 @@ msgstr "" msgid "Edit Data Field" msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Failed to delete data field: %{error}" msgstr "" @@ -1824,6 +1832,7 @@ msgstr "" msgid "The cycle period will be calculated based on this date and the interval." msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Membership fee type not found" @@ -1844,6 +1853,7 @@ msgstr "" msgid "User not found" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "You do not have permission to access this membership fee type" @@ -1854,6 +1864,7 @@ msgstr "" msgid "You do not have permission to access this user" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "You do not have permission to delete this membership fee type" @@ -1925,16 +1936,6 @@ msgstr "" msgid "Roles" msgstr "" -#: lib/mv_web/components/layouts/sidebar.ex -#, elixir-autogen, elixir-format -msgid "Fee Settings" -msgstr "" - -#: lib/mv_web/components/layouts/sidebar.ex -#, elixir-autogen, elixir-format -msgid "Fee Types" -msgstr "" - #: lib/mv_web/components/layouts/sidebar.ex #, elixir-autogen, elixir-format msgid "Administration" @@ -2273,7 +2274,7 @@ msgstr "" msgid "Not authorized." msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Could not load data fields. Please check your permissions." msgstr "" @@ -2424,6 +2425,7 @@ msgstr "" msgid "Linked" msgstr "" +#: lib/mv_web/live/global_settings_live.ex #: lib/mv_web/live/user_live/index.html.heex #: lib/mv_web/live/user_live/show.ex #, elixir-autogen, elixir-format @@ -2975,3 +2977,109 @@ msgstr "" #, elixir-autogen, elixir-format msgid "Fee Type" msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Admin group name" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Base URL" +msgstr "" + +#: lib/mv_web/components/layouts/sidebar.ex +#, elixir-autogen, elixir-format +msgid "Basic settings" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Client ID" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Client Secret" +msgstr "" + +#: lib/mv_web/live/membership_fee_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Configure global settings and fee types for membership fees." +msgstr "" + +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format +msgid "Configure member fields and custom data fields." +msgstr "" + +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format +msgid "Custom fields" +msgstr "" + +#: lib/mv_web/components/layouts/sidebar.ex +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format +msgid "Datafields" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_ADMIN_GROUP_NAME" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_BASE_URL" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_CLIENT_ID" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_CLIENT_SECRET" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_GROUPS_CLAIM" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_REDIRECT_URI" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Groups claim" +msgstr "" + +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format +msgid "Member fields" +msgstr "" + +#: lib/mv_web/components/layouts/sidebar.ex +#, elixir-autogen, elixir-format +msgid "Membership fee settings" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Redirect URI" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Save OIDC Settings" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "e.g. admin" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index 839a43b..c9e30ca 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -19,6 +19,7 @@ msgid "Actions" msgstr "" #: lib/mv_web/live/member_live/index.html.heex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/role_live/index.html.heex #: lib/mv_web/live/role_live/show.ex @@ -323,6 +324,7 @@ msgstr "" #: lib/mv_web/live/group_live/show.ex #: lib/mv_web/live/member_live/index.ex #: lib/mv_web/live/member_live/index.html.heex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/statistics_live.ex #, elixir-autogen, elixir-format @@ -336,6 +338,7 @@ msgstr "" #: lib/mv_web/live/group_live/show.ex #: lib/mv_web/live/member_field_live/form_component.ex #: lib/mv_web/live/member_field_live/index_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/role_live/form.ex @@ -383,7 +386,6 @@ msgstr "" msgid "Select member" msgstr "" -#: lib/mv_web/components/layouts/sidebar.ex #: lib/mv_web/live/global_settings_live.ex #, elixir-autogen, elixir-format msgid "Settings" @@ -843,6 +845,7 @@ msgid "Create Member" msgstr "" #: lib/mv_web/live/member_live/show/membership_fees_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format @@ -854,11 +857,13 @@ msgstr "" msgid "Back to Settings" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Can be changed at any time. Amount changes affect future periods only." msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Deletion" @@ -869,6 +874,7 @@ msgstr "" msgid "Examples" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Fixed after creation. Members can only switch between types with the same interval." @@ -887,6 +893,7 @@ msgid "Half-yearly" msgstr "" #: lib/mv_web/live/member_live/show/membership_fees_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format @@ -925,11 +932,13 @@ msgstr "" msgid "Monthly" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Name & Amount" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "Only possible if no members are assigned to this type." @@ -1003,7 +1012,7 @@ msgstr "" msgid "Select none" msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Slug does not match. Deletion cancelled." msgstr "" @@ -1045,11 +1054,6 @@ msgstr "" msgid "Yes/No-Selection" msgstr "" -#: lib/mv_web/live/global_settings_live.ex -#, elixir-autogen, elixir-format, fuzzy -msgid "Memberdata" -msgstr "" - #: lib/mv_web/live/custom_field_live/index_component.ex #: lib/mv_web/live/member_field_live/index_component.ex #, elixir-autogen, elixir-format, fuzzy @@ -1061,7 +1065,7 @@ msgstr "" msgid "These fields are neccessary for MILA to handle member identification and payment calculations in the future. Thus you cannot delete these fields but hide them in the member overview." msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Member field %{action} successfully" msgstr "" @@ -1071,6 +1075,7 @@ msgstr "" msgid "A cycle for this period already exists" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format msgid "About Membership Fee Types" @@ -1087,6 +1092,7 @@ msgid "Already paid cycles will remain with the old amount." msgstr "" #: lib/mv_web/live/member_live/show/membership_fees_component.ex +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #: lib/mv_web/live/role_live/helpers.ex #, elixir-autogen, elixir-format @@ -1098,6 +1104,7 @@ msgstr "" msgid "Are you sure you want to delete this cycle?" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Cannot delete - %{count} member(s) assigned" @@ -1118,11 +1125,6 @@ msgstr "" msgid "Click to edit amount" msgstr "" -#: lib/mv_web/live/membership_fee_settings_live.ex -#, elixir-autogen, elixir-format, fuzzy -msgid "Configure global settings for membership fees." -msgstr "" - #: lib/mv_web/live/membership_fee_type_live/form.ex #, elixir-autogen, elixir-format msgid "Confirm Change" @@ -1233,6 +1235,7 @@ msgstr "" msgid "Edit Membership Fee Type" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Edit membership fee type" @@ -1331,6 +1334,7 @@ msgstr "" msgid "Membership Fee Type" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Membership Fee Types" @@ -1347,6 +1351,7 @@ msgstr "" msgid "Membership fee start" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Membership fee type deleted" @@ -1367,6 +1372,7 @@ msgstr "" msgid "Membership fee type updated. Cycles regenerated." msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Membership fee types define different membership fee structures. Each type has a fixed interval (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation." @@ -1377,6 +1383,7 @@ msgstr "" msgid "Monthly Interval - Joining Cycle Included" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/form.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy @@ -1551,6 +1558,7 @@ msgstr "" msgid "You are about to delete all %{count} cycles for this member." msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Delete Membership Fee Type" @@ -1572,12 +1580,12 @@ msgstr "" msgid "Back to settings" msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Data field %{action} successfully" msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Data field deleted successfully" msgstr "" @@ -1592,7 +1600,7 @@ msgstr "" msgid "Edit Data Field" msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Failed to delete data field: %{error}" msgstr "" @@ -1824,6 +1832,7 @@ msgstr "" msgid "The cycle period will be calculated based on this date and the interval." msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Membership fee type not found" @@ -1844,6 +1853,7 @@ msgstr "" msgid "User not found" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "You do not have permission to access this membership fee type" @@ -1854,6 +1864,7 @@ msgstr "" msgid "You do not have permission to access this user" msgstr "" +#: lib/mv_web/live/membership_fee_settings_live.ex #: lib/mv_web/live/membership_fee_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "You do not have permission to delete this membership fee type" @@ -1925,16 +1936,6 @@ msgstr "" msgid "Roles" msgstr "" -#: lib/mv_web/components/layouts/sidebar.ex -#, elixir-autogen, elixir-format, fuzzy -msgid "Fee Settings" -msgstr "" - -#: lib/mv_web/components/layouts/sidebar.ex -#, elixir-autogen, elixir-format -msgid "Fee Types" -msgstr "" - #: lib/mv_web/components/layouts/sidebar.ex #, elixir-autogen, elixir-format msgid "Administration" @@ -2273,7 +2274,7 @@ msgstr "" msgid "Not authorized." msgstr "" -#: lib/mv_web/live/global_settings_live.ex +#: lib/mv_web/live/datafields_live.ex #, elixir-autogen, elixir-format msgid "Could not load data fields. Please check your permissions." msgstr "" @@ -2424,6 +2425,7 @@ msgstr "" msgid "Linked" msgstr "" +#: lib/mv_web/live/global_settings_live.ex #: lib/mv_web/live/user_live/index.html.heex #: lib/mv_web/live/user_live/show.ex #, elixir-autogen, elixir-format @@ -2975,3 +2977,109 @@ msgstr "Required for Vereinfacht integration and cannot be disabled." #, elixir-autogen, elixir-format msgid "Fee Type" msgstr "Fee Type" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Admin group name" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Base URL" +msgstr "" + +#: lib/mv_web/components/layouts/sidebar.ex +#, elixir-autogen, elixir-format +msgid "Basic settings" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Client ID" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Client Secret" +msgstr "" + +#: lib/mv_web/live/membership_fee_settings_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Configure global settings and fee types for membership fees." +msgstr "" + +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format +msgid "Configure member fields and custom data fields." +msgstr "" + +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Custom fields" +msgstr "" + +#: lib/mv_web/components/layouts/sidebar.ex +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format +msgid "Datafields" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_ADMIN_GROUP_NAME" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_BASE_URL" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_CLIENT_ID" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_CLIENT_SECRET" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_GROUPS_CLAIM" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "From OIDC_REDIRECT_URI" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Groups claim" +msgstr "" + +#: lib/mv_web/live/datafields_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Member fields" +msgstr "" + +#: lib/mv_web/components/layouts/sidebar.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Membership fee settings" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "Redirect URI" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "Save OIDC Settings" +msgstr "" + +#: lib/mv_web/live/global_settings_live.ex +#, elixir-autogen, elixir-format +msgid "e.g. admin" +msgstr "" diff --git a/test/mv/oidc_role_sync_test.exs b/test/mv/oidc_role_sync_test.exs index 229f56a..a4729ec 100644 --- a/test/mv/oidc_role_sync_test.exs +++ b/test/mv/oidc_role_sync_test.exs @@ -12,14 +12,14 @@ defmodule Mv.OidcRoleSyncTest do setup do ensure_roles_exist() - restore_config = put_oidc_config(admin_group_name: "mila-admin", groups_claim: "groups") + restore_config = put_oidc_env(admin_group_name: "mila-admin", groups_claim: "groups") on_exit(restore_config) :ok end describe "apply_admin_role_from_user_info/2" do test "when OIDC_ADMIN_GROUP_NAME not configured: does not change user (Mitglied stays)" do - restore = put_oidc_config(admin_group_name: nil, groups_claim: "groups") + restore = put_oidc_env(admin_group_name: nil, groups_claim: "groups") on_exit(restore) email = "sync-no-config-#{System.unique_integer([:positive])}@test.example.com" @@ -58,7 +58,7 @@ defmodule Mv.OidcRoleSyncTest do end test "when OIDC_GROUPS_CLAIM is different: reads groups from that claim" do - restore = put_oidc_config(admin_group_name: "mila-admin", groups_claim: "ak_groups") + restore = put_oidc_env(admin_group_name: "mila-admin", groups_claim: "ak_groups") on_exit(restore) email = "sync-claim-#{System.unique_integer([:positive])}@test.example.com" @@ -131,13 +131,30 @@ defmodule Mv.OidcRoleSyncTest do end end - defp put_oidc_config(opts) do - current = Application.get_env(:mv, :oidc_role_sync, []) - merged = Keyword.merge(current, opts) - Application.put_env(:mv, :oidc_role_sync, merged) + defp put_oidc_env(opts) do + prev_admin = System.get_env("OIDC_ADMIN_GROUP_NAME") + prev_claim = System.get_env("OIDC_GROUPS_CLAIM") + + if opts[:admin_group_name] != nil do + System.put_env("OIDC_ADMIN_GROUP_NAME", to_string(opts[:admin_group_name])) + else + System.delete_env("OIDC_ADMIN_GROUP_NAME") + end + + if opts[:groups_claim] != nil do + System.put_env("OIDC_GROUPS_CLAIM", to_string(opts[:groups_claim])) + else + System.delete_env("OIDC_GROUPS_CLAIM") + end fn -> - Application.put_env(:mv, :oidc_role_sync, current) + if prev_admin, + do: System.put_env("OIDC_ADMIN_GROUP_NAME", prev_admin), + else: System.delete_env("OIDC_ADMIN_GROUP_NAME") + + if prev_claim, + do: System.put_env("OIDC_GROUPS_CLAIM", prev_claim), + else: System.delete_env("OIDC_GROUPS_CLAIM") end end diff --git a/test/mv_web/components/sidebar_authorization_test.exs b/test/mv_web/components/sidebar_authorization_test.exs index 110d9e5..5d4277b 100644 --- a/test/mv_web/components/sidebar_authorization_test.exs +++ b/test/mv_web/components/sidebar_authorization_test.exs @@ -30,7 +30,7 @@ defmodule MvWeb.SidebarAuthorizationTest do html = render_sidebar(sidebar_assigns(user)) assert html =~ ~s(href="/members") - assert html =~ ~s(href="/membership_fee_types") + assert html =~ ~s(href="/membership_fee_settings") assert html =~ ~s(href="/statistics") assert html =~ ~s(data-testid="sidebar-administration") assert html =~ ~s(href="/users") @@ -55,7 +55,7 @@ defmodule MvWeb.SidebarAuthorizationTest do user = Fixtures.user_with_role_fixture("read_only") html = render_sidebar(sidebar_assigns(user)) - refute html =~ ~s(href="/membership_fee_types") + refute html =~ ~s(href="/membership_fee_settings") refute html =~ ~s(href="/users") refute html =~ ~s(href="/admin/roles") refute html =~ ~s(href="/settings") @@ -76,7 +76,7 @@ defmodule MvWeb.SidebarAuthorizationTest do user = Fixtures.user_with_role_fixture("normal_user") html = render_sidebar(sidebar_assigns(user)) - refute html =~ ~s(href="/membership_fee_types") + refute html =~ ~s(href="/membership_fee_settings") refute html =~ ~s(href="/users") refute html =~ ~s(href="/admin/roles") refute html =~ ~s(href="/settings") @@ -96,7 +96,7 @@ defmodule MvWeb.SidebarAuthorizationTest do html = render_sidebar(sidebar_assigns(user)) refute html =~ ~s(href="/statistics") - refute html =~ ~s(href="/membership_fee_types") + refute html =~ ~s(href="/membership_fee_settings") refute html =~ ~s(href="/users") refute html =~ ~s(data-testid="sidebar-administration") end @@ -117,7 +117,7 @@ defmodule MvWeb.SidebarAuthorizationTest do html = render_sidebar(sidebar_assigns(user)) refute html =~ ~s(href="/members") - refute html =~ ~s(href="/membership_fee_types") + refute html =~ ~s(href="/membership_fee_settings") refute html =~ ~s(href="/users") end end diff --git a/test/mv_web/live/custom_field_live/deletion_test.exs b/test/mv_web/live/custom_field_live/deletion_test.exs index 36e46e2..28f98a2 100644 --- a/test/mv_web/live/custom_field_live/deletion_test.exs +++ b/test/mv_web/live/custom_field_live/deletion_test.exs @@ -54,7 +54,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do # Create custom field value create_custom_field_value(member, custom_field, "test") - {:ok, view, _html} = live(conn, ~p"/settings") + {:ok, view, _html} = live(conn, ~p"/admin/datafields") # Click delete button - find the delete link within the component view @@ -80,7 +80,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do create_custom_field_value(member1, custom_field, "test1") create_custom_field_value(member2, custom_field, "test2") - {:ok, view, _html} = live(conn, ~p"/settings") + {:ok, view, _html} = live(conn, ~p"/admin/datafields") view |> element("#custom-fields-component a", "Delete") @@ -93,7 +93,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do test "shows 0 members for custom field without values", %{conn: conn} do {:ok, _custom_field} = create_custom_field("test_field", :string) - {:ok, view, _html} = live(conn, ~p"/settings") + {:ok, view, _html} = live(conn, ~p"/admin/datafields") view |> element("#custom-fields-component a", "Delete") @@ -108,7 +108,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do test "updates confirmation state when typing", %{conn: conn} do {:ok, custom_field} = create_custom_field("test_field", :string) - {:ok, view, _html} = live(conn, ~p"/settings") + {:ok, view, _html} = live(conn, ~p"/admin/datafields") view |> element("#custom-fields-component a", "Delete") @@ -126,7 +126,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do test "delete button is disabled when slug doesn't match", %{conn: conn} do {:ok, _custom_field} = create_custom_field("test_field", :string) - {:ok, view, _html} = live(conn, ~p"/settings") + {:ok, view, _html} = live(conn, ~p"/admin/datafields") view |> element("#custom-fields-component a", "Delete") @@ -148,7 +148,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do {:ok, custom_field} = create_custom_field("test_field", :string) {:ok, custom_field_value} = create_custom_field_value(member, custom_field, "test") - {:ok, view, _html} = live(conn, ~p"/settings") + {:ok, view, _html} = live(conn, ~p"/admin/datafields") # Open modal view @@ -185,7 +185,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do } do {:ok, custom_field} = create_custom_field("test_field", :string) - {:ok, view, _html} = live(conn, ~p"/settings") + {:ok, view, _html} = live(conn, ~p"/admin/datafields") view |> element("#custom-fields-component a", "Delete") @@ -209,7 +209,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do test "closes modal without deleting", %{conn: conn} do {:ok, custom_field} = create_custom_field("test_field", :string) - {:ok, view, _html} = live(conn, ~p"/settings") + {:ok, view, _html} = live(conn, ~p"/admin/datafields") view |> element("#custom-fields-component a", "Delete") @@ -234,7 +234,7 @@ defmodule MvWeb.CustomFieldLive.DeletionTest do describe "create custom field" do test "submitting new data field form creates custom field and shows success", %{conn: conn} do - {:ok, view, _html} = live(conn, ~p"/settings") + {:ok, view, _html} = live(conn, ~p"/admin/datafields") # Open "New Data Field" form view diff --git a/test/mv_web/live/global_settings_live_test.exs b/test/mv_web/live/global_settings_live_test.exs index 86680f3..6a739b5 100644 --- a/test/mv_web/live/global_settings_live_test.exs +++ b/test/mv_web/live/global_settings_live_test.exs @@ -64,21 +64,5 @@ defmodule MvWeb.GlobalSettingsLiveTest do assert html =~ "must be present" end - - test "displays Memberdata section", %{conn: conn} do - {:ok, _view, html} = live(conn, ~p"/settings") - - assert html =~ "Memberdata" or html =~ "Member Data" - end - - test "displays flash message after member field visibility update", %{conn: conn} do - {:ok, view, _html} = live(conn, ~p"/settings") - - # Simulate member field visibility update - send(view.pid, {:member_field_visibility_updated}) - - # Check for flash message - assert render(view) =~ "updated" or render(view) =~ "success" - end end end diff --git a/test/mv_web/live/member_field_live/index_component_test.exs b/test/mv_web/live/member_field_live/index_component_test.exs index 6ad1627..d3c1612 100644 --- a/test/mv_web/live/member_field_live/index_component_test.exs +++ b/test/mv_web/live/member_field_live/index_component_test.exs @@ -23,7 +23,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponentTest do describe "rendering" do test "renders all member fields from Constants", %{conn: conn} do - {:ok, _view, html} = live(conn, ~p"/settings") + {:ok, _view, html} = live(conn, ~p"/admin/datafields") # Check that all member fields are displayed member_fields = Mv.Constants.member_fields() @@ -36,7 +36,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponentTest do end test "displays show_in_overview status as badge", %{conn: conn} do - {:ok, _view, html} = live(conn, ~p"/settings") + {:ok, _view, html} = live(conn, ~p"/admin/datafields") # Should have "Show in overview" column header assert html =~ "Show in overview" or html =~ "Show in Overview" @@ -46,7 +46,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponentTest do end test "displays required status column", %{conn: conn} do - {:ok, _view, html} = live(conn, ~p"/settings") + {:ok, _view, html} = live(conn, ~p"/admin/datafields") # Should have "Required" column; email is always required assert html =~ "Required" or html =~ "required" @@ -59,7 +59,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponentTest do {:ok, _updated} = Membership.update_settings(settings, %{member_field_visibility: %{}}) - {:ok, _view, html} = live(conn, ~p"/settings") + {:ok, _view, html} = live(conn, ~p"/admin/datafields") # All fields should show as visible (Yes) by default # Check for "Yes" badge or similar indicator @@ -74,7 +74,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponentTest do {:ok, _updated} = Membership.update_member_field_visibility(settings, visibility_config) - {:ok, _view, html} = live(conn, ~p"/settings") + {:ok, _view, html} = live(conn, ~p"/admin/datafields") # Street and house_number should show as hidden (No) # Other fields should show as visible (Yes) @@ -102,7 +102,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponentTest do end test "marks email as required (always from settings)", %{conn: conn} do - {:ok, _view, html} = live(conn, ~p"/settings") + {:ok, _view, html} = live(conn, ~p"/admin/datafields") # Email is always required assert html =~ "email" or html =~ "Email" @@ -119,7 +119,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponentTest do required: true ) - {:ok, _view, html} = live(conn, ~p"/settings") + {:ok, _view, html} = live(conn, ~p"/admin/datafields") # First name row should show Required (and Optional for others) assert html =~ "First name" or html =~ "first_name" @@ -127,7 +127,7 @@ defmodule MvWeb.MemberFieldLive.IndexComponentTest do end test "optional fields show Optional when not required in settings", %{conn: conn} do - {:ok, _view, html} = live(conn, ~p"/settings") + {:ok, _view, html} = live(conn, ~p"/admin/datafields") # Email is required; other fields default to optional assert html =~ "Optional" diff --git a/test/mv_web/live/membership_fee_type_live/form_test.exs b/test/mv_web/live/membership_fee_type_live/form_test.exs index 71edbba..a836c4d 100644 --- a/test/mv_web/live/membership_fee_type_live/form_test.exs +++ b/test/mv_web/live/membership_fee_type_live/form_test.exs @@ -11,7 +11,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do require Ash.Query setup %{conn: conn} do - # User must have admin role (or normal_user) to access /membership_fee_types pages + # User must have admin role (or normal_user) to access /membership_fee_settings pages user = Mv.Fixtures.user_with_role_fixture("admin") authenticated_conn = conn_with_password_user(conn, user) %{conn: authenticated_conn, user: user} @@ -51,7 +51,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do describe "create form" do test "creates new membership fee type", %{conn: conn, user: user} do - {:ok, view, _html} = live(conn, "/membership_fee_types/new") + {:ok, view, _html} = live(conn, "/membership_fee_settings/new_fee_type") form_data = %{ "membership_fee_type[name]" => "New Type", @@ -65,7 +65,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do |> form("#membership-fee-type-form", form_data) |> render_submit() - assert to == "/membership_fee_types" + assert to == "/membership_fee_settings" # Verify type was created (use actor so read is authorized) type = @@ -79,7 +79,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do end test "interval field is editable on create", %{conn: conn} do - {:ok, _view, html} = live(conn, "/membership_fee_types/new") + {:ok, _view, html} = live(conn, "/membership_fee_settings/new_fee_type") # Interval field should be editable (not disabled) refute html =~ "disabled" || html =~ "readonly" @@ -90,7 +90,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do test "loads existing type data", %{conn: conn} do fee_type = create_fee_type(%{name: "Existing Type", amount: Decimal.new("60.00")}) - {:ok, _view, html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit") + {:ok, _view, html} = live(conn, "/membership_fee_settings/#{fee_type.id}/edit_fee_type") assert html =~ "Existing Type" assert html =~ "60" || html =~ "60,00" @@ -99,7 +99,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do test "interval field is grayed out on edit", %{conn: conn} do fee_type = create_fee_type(%{interval: :yearly}) - {:ok, _view, html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit") + {:ok, _view, html} = live(conn, "/membership_fee_settings/#{fee_type.id}/edit_fee_type") # Interval field should be disabled assert html =~ "disabled" || html =~ "readonly" @@ -109,7 +109,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do fee_type = create_fee_type(%{amount: Decimal.new("50.00")}) create_member(%{membership_fee_type_id: fee_type.id}) - {:ok, view, _html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit") + {:ok, view, _html} = live(conn, "/membership_fee_settings/#{fee_type.id}/edit_fee_type") # Change amount view @@ -129,7 +129,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do create_member(%{membership_fee_type_id: fee_type.id}) end) - {:ok, view, _html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit") + {:ok, view, _html} = live(conn, "/membership_fee_settings/#{fee_type.id}/edit_fee_type") # Change amount html = @@ -144,7 +144,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do test "amount change can be confirmed", %{conn: conn, user: user} do fee_type = create_fee_type(%{amount: Decimal.new("50.00")}) - {:ok, view, _html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit") + {:ok, view, _html} = live(conn, "/membership_fee_settings/#{fee_type.id}/edit_fee_type") # Change amount and confirm view @@ -173,7 +173,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do test "amount change can be cancelled", %{conn: conn, user: user} do fee_type = create_fee_type(%{amount: Decimal.new("50.00")}) - {:ok, view, _html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit") + {:ok, view, _html} = live(conn, "/membership_fee_settings/#{fee_type.id}/edit_fee_type") # Change amount and cancel view @@ -195,7 +195,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do end test "validation errors display correctly", %{conn: conn} do - {:ok, view, _html} = live(conn, "/membership_fee_types/new") + {:ok, view, _html} = live(conn, "/membership_fee_settings/new_fee_type") # Submit with invalid data html = @@ -214,7 +214,7 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do describe "permissions" do test "only admin can access", %{conn: conn} do # This test assumes non-admin users cannot access - {:ok, _view, html} = live(conn, "/membership_fee_types/new") + {:ok, _view, html} = live(conn, "/membership_fee_settings/new_fee_type") # Should show the form (admin user in setup) assert html =~ "Membership Fee Type" || html =~ "Beitragsart" diff --git a/test/mv_web/live/membership_fee_type_live/index_test.exs b/test/mv_web/live/membership_fee_type_live/index_test.exs index 7d2d4be..c9bb7ca 100644 --- a/test/mv_web/live/membership_fee_type_live/index_test.exs +++ b/test/mv_web/live/membership_fee_type_live/index_test.exs @@ -60,7 +60,7 @@ defmodule MvWeb.MembershipFeeTypeLive.IndexTest do admin_user ) - {:ok, _view, html} = live(conn, "/membership_fee_types") + {:ok, _view, html} = live(conn, "/membership_fee_settings") assert html =~ "Regular" assert html =~ "Reduced" @@ -77,33 +77,33 @@ defmodule MvWeb.MembershipFeeTypeLive.IndexTest do create_member(%{membership_fee_type_id: fee_type.id}, admin_user) end) - {:ok, _view, html} = live(conn, "/membership_fee_types") + {:ok, _view, html} = live(conn, "/membership_fee_settings") assert html =~ "3" || html =~ "Members" || html =~ "Mitglieder" end test "create button navigates to form", %{conn: conn} do - {:ok, view, _html} = live(conn, "/membership_fee_types") + {:ok, view, _html} = live(conn, "/membership_fee_settings") {:error, {:live_redirect, %{to: to}}} = view - |> element("a[href='/membership_fee_types/new']") + |> element("a[href='/membership_fee_settings/new_fee_type']") |> render_click() - assert to == "/membership_fee_types/new" + assert to == "/membership_fee_settings/new_fee_type" end test "edit button per row navigates to edit form", %{conn: conn, current_user: admin_user} do fee_type = create_fee_type(%{interval: :yearly}, admin_user) - {:ok, view, _html} = live(conn, "/membership_fee_types") + {:ok, view, _html} = live(conn, "/membership_fee_settings") {:error, {:live_redirect, %{to: to}}} = view - |> element("a[href='/membership_fee_types/#{fee_type.id}/edit']") + |> element("a[href='/membership_fee_settings/#{fee_type.id}/edit_fee_type']") |> render_click() - assert to == "/membership_fee_types/#{fee_type.id}/edit" + assert to == "/membership_fee_settings/#{fee_type.id}/edit_fee_type" end end @@ -112,7 +112,7 @@ defmodule MvWeb.MembershipFeeTypeLive.IndexTest do fee_type = create_fee_type(%{interval: :yearly}, admin_user) create_member(%{membership_fee_type_id: fee_type.id}, admin_user) - {:ok, _view, html} = live(conn, "/membership_fee_types") + {:ok, _view, html} = live(conn, "/membership_fee_settings") # Delete button should be disabled assert html =~ "disabled" || html =~ "cursor-not-allowed" @@ -122,7 +122,7 @@ defmodule MvWeb.MembershipFeeTypeLive.IndexTest do fee_type = create_fee_type(%{interval: :yearly}, admin_user) # No members assigned - {:ok, view, _html} = live(conn, "/membership_fee_types") + {:ok, view, _html} = live(conn, "/membership_fee_settings") # Delete button should be enabled view @@ -142,10 +142,11 @@ defmodule MvWeb.MembershipFeeTypeLive.IndexTest do test "only admin can access", %{conn: conn} do # This test assumes non-admin users cannot access # Adjust based on actual permission implementation - {:ok, _view, html} = live(conn, "/membership_fee_types") + {:ok, _view, html} = live(conn, "/membership_fee_settings") # Should show the page (admin user in setup) - assert html =~ "Membership Fee Types" || html =~ "Beitragsarten" + assert html =~ "Membership Fee Settings" || html =~ "Beitragseinstellungen" || + html =~ "Membership Fee Types" end end end diff --git a/test/mv_web/plugs/check_page_permission_test.exs b/test/mv_web/plugs/check_page_permission_test.exs index e342744..6dd8022 100644 --- a/test/mv_web/plugs/check_page_permission_test.exs +++ b/test/mv_web/plugs/check_page_permission_test.exs @@ -279,17 +279,11 @@ defmodule MvWeb.Plugs.CheckPagePermissionTest do end @tag role: :member - test "GET /membership_fee_types redirects to user profile", %{conn: conn, current_user: user} do - conn = get(conn, "/membership_fee_types") - assert redirected_to(conn) == "/users/#{user.id}" - end - - @tag role: :member - test "GET /membership_fee_types/new redirects to user profile", %{ + test "GET /membership_fee_settings/new_fee_type redirects to user profile", %{ conn: conn, current_user: user } do - conn = get(conn, "/membership_fee_types/new") + conn = get(conn, "/membership_fee_settings/new_fee_type") assert redirected_to(conn) == "/users/#{user.id}" end @@ -385,7 +379,7 @@ defmodule MvWeb.Plugs.CheckPagePermissionTest do end @tag role: :member - test "GET /membership_fee_types/:id/edit redirects to user profile", %{ + test "GET /membership_fee_settings/:id/edit_fee_type redirects to user profile", %{ conn: conn, current_user: user } do @@ -396,7 +390,7 @@ defmodule MvWeb.Plugs.CheckPagePermissionTest do |> List.first() if type do - conn = get(conn, "/membership_fee_types/#{type.id}/edit") + conn = get(conn, "/membership_fee_settings/#{type.id}/edit_fee_type") assert redirected_to(conn) == "/users/#{user.id}" end end @@ -680,15 +674,6 @@ defmodule MvWeb.Plugs.CheckPagePermissionTest do assert redirected_to(conn) == "/users/#{user.id}" end - @tag role: :read_only - test "GET /membership_fee_types redirects to user profile", %{ - conn: conn, - current_user: user - } do - conn = get(conn, "/membership_fee_types") - assert redirected_to(conn) == "/users/#{user.id}" - end - @tag role: :read_only test "GET /groups/new redirects to user profile", %{conn: conn, current_user: user} do conn = get(conn, "/groups/new") @@ -864,15 +849,6 @@ defmodule MvWeb.Plugs.CheckPagePermissionTest do assert redirected_to(conn) == "/users/#{user.id}" end - @tag role: :normal_user - test "GET /membership_fee_types redirects to user profile", %{ - conn: conn, - current_user: user - } do - conn = get(conn, "/membership_fee_types") - assert redirected_to(conn) == "/users/#{user.id}" - end - @tag role: :normal_user test "GET /admin/roles redirects to user profile", %{conn: conn, current_user: user} do conn = get(conn, "/admin/roles")