Fixes missing Rauthy error message closes #289 #427

Merged
carla merged 7 commits from bug/289_rauthy_error_message into main 2026-02-23 15:32:00 +01:00
11 changed files with 165 additions and 198 deletions
Showing only changes of commit ac13a39e7c - Show all commits

View file

@ -1,7 +1,7 @@
defmodule Mv.Membership.Import.ImportRunner do defmodule Mv.Membership.Import.ImportRunner do
@moduledoc """ @moduledoc """
Orchestrates CSV member import: file reading, progress tracking, chunk processing, Orchestrates CSV member import: file reading, progress tracking, chunk processing,
and error formatting. Used by `MvWeb.ImportExportLive` to keep LiveView thin. and error formatting. Used by `MvWeb.ImportLive` to keep LiveView thin.
This module does not depend on Phoenix or LiveView. It provides pure functions for This module does not depend on Phoenix or LiveView. It provides pure functions for
progress/merge and side-effectful helpers (read_file_entry, process_chunk) that progress/merge and side-effectful helpers (read_file_entry, process_chunk) that

View file

@ -118,7 +118,7 @@ defmodule MvWeb.Layouts.Sidebar do
/> />
<% end %> <% end %>
<%= if can_access_page?(@current_user, PagePaths.settings()) do %> <%= if can_access_page?(@current_user, PagePaths.settings()) do %>
<.menu_subitem href={~p"/admin/import-export"} label={gettext("Import/Export")} /> <.menu_subitem href={~p"/admin/import"} label={gettext("Import")} />
<.menu_subitem href={~p"/settings"} label={gettext("Settings")} /> <.menu_subitem href={~p"/settings"} label={gettext("Settings")} />
<% end %> <% end %>
</.menu_group> </.menu_group>

View file

@ -219,6 +219,9 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
send(self(), {:editing_section_changed, nil}) send(self(), {:editing_section_changed, nil})
end end
# Get actor from assigns or fall back to socket assigns
actor = Map.get(assigns, :actor, socket.assigns[:actor])
{:ok, {:ok,
socket socket
|> assign(assigns) |> assign(assigns)
@ -228,7 +231,7 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
|> assign_new(:show_delete_modal, fn -> false end) |> assign_new(:show_delete_modal, fn -> false end)
|> assign_new(:custom_field_to_delete, fn -> nil end) |> assign_new(:custom_field_to_delete, fn -> nil end)
|> assign_new(:slug_confirmation, fn -> "" end) |> assign_new(:slug_confirmation, fn -> "" end)
|> stream(:custom_fields, stream_custom_fields(assigns[:actor], self()), reset: true)} |> stream(:custom_fields, stream_custom_fields(actor, self()), reset: true)}
end end
@impl true @impl true

View file

@ -1,6 +1,6 @@
defmodule MvWeb.ImportExportLive do defmodule MvWeb.ImportLive do
@moduledoc """ @moduledoc """
LiveView for importing and exporting members via CSV. LiveView for importing members via CSV.
## Features ## Features
- CSV member import (admin only) - CSV member import (admin only)
@ -38,7 +38,7 @@ defmodule MvWeb.ImportExportLive do
alias Mv.Membership.Import.ImportRunner alias Mv.Membership.Import.ImportRunner
alias Mv.Membership.Import.MemberCSV alias Mv.Membership.Import.MemberCSV
alias MvWeb.Authorization alias MvWeb.Authorization
alias MvWeb.ImportExportLive.Components alias MvWeb.ImportLive.Components
on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded} on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded}
@ -65,7 +65,7 @@ defmodule MvWeb.ImportExportLive do
socket = socket =
socket socket
|> assign(:page_title, gettext("Import/Export")) |> assign(:page_title, gettext("Import"))
|> assign(:club_name, club_name) |> assign(:club_name, club_name)
|> assign(:import_state, nil) |> assign(:import_state, nil)
|> assign(:import_progress, nil) |> assign(:import_progress, nil)
@ -90,13 +90,6 @@ defmodule MvWeb.ImportExportLive do
def render(assigns) do def render(assigns) do
~H""" ~H"""
<Layouts.app flash={@flash} current_user={@current_user} club_name={@club_name}> <Layouts.app flash={@flash} current_user={@current_user} club_name={@club_name}>
<.header>
{gettext("Import/Export")}
<:subtitle>
{gettext("Import members from CSV files or export member data.")}
</:subtitle>
</.header>
<%= if Authorization.can?(@current_user, :create, Mv.Membership.Member) do %> <%= if Authorization.can?(@current_user, :create, Mv.Membership.Member) do %>
<%!-- CSV Import Section --%> <%!-- CSV Import Section --%>
<.form_section title={gettext("Import Members (CSV)")}> <.form_section title={gettext("Import Members (CSV)")}>
@ -107,18 +100,6 @@ defmodule MvWeb.ImportExportLive do
<Components.import_progress {assigns} /> <Components.import_progress {assigns} />
<% end %> <% end %>
</.form_section> </.form_section>
<%!-- Export Section (Placeholder) --%>
<.form_section title={gettext("Export Members (CSV)")}>
<div role="note" class="alert alert-info">
<.icon name="hero-information-circle" class="size-5" aria-hidden="true" />
<div>
<p class="text-sm">
{gettext("Export functionality will be available in a future release.")}
</p>
</div>
</div>
</.form_section>
<% else %> <% else %>
<div role="alert" class="alert alert-error"> <div role="alert" class="alert alert-error">
<.icon name="hero-exclamation-circle" class="size-5" aria-hidden="true" /> <.icon name="hero-exclamation-circle" class="size-5" aria-hidden="true" />

View file

@ -1,6 +1,6 @@
defmodule MvWeb.ImportExportLive.Components do defmodule MvWeb.ImportLive.Components do
@moduledoc """ @moduledoc """
Function components for the Import/Export LiveView: import form, progress, results, Function components for the Import LiveView: import form, progress, results,
custom fields notice, and template links. Keeps the main LiveView focused on custom fields notice, and template links. Keeps the main LiveView focused on
mount/handle_event/handle_info and glue code. mount/handle_event/handle_info and glue code.
""" """

View file

@ -91,8 +91,8 @@ defmodule MvWeb.Router do
live "/admin/roles/:id", RoleLive.Show, :show live "/admin/roles/:id", RoleLive.Show, :show
live "/admin/roles/:id/edit", RoleLive.Form, :edit live "/admin/roles/:id/edit", RoleLive.Form, :edit
# Import/Export (Admin only) # Import (Admin only)
live "/admin/import-export", ImportExportLive live "/admin/import", ImportLive
post "/members/export.csv", MemberExportController, :export post "/members/export.csv", MemberExportController, :export
post "/members/export.pdf", MemberPdfExportController, :export post "/members/export.pdf", MemberPdfExportController, :export

View file

@ -1874,7 +1874,7 @@ msgstr "erstellt"
msgid "updated" msgid "updated"
msgstr "aktualisiert" msgstr "aktualisiert"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#: lib/mv_web/live/user_live/form.ex #: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Unknown error" msgid "Unknown error"
@ -1995,37 +1995,37 @@ msgstr "Bezahlstatus"
msgid "Reset" msgid "Reset"
msgstr "Zurücksetzen" msgstr "Zurücksetzen"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid " (Field: %{field})" msgid " (Field: %{field})"
msgstr " (Datenfeld: %{field})" msgstr " (Datenfeld: %{field})"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "CSV File" msgid "CSV File"
msgstr "CSV Datei" msgstr "CSV Datei"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Download CSV templates:" msgid "Download CSV templates:"
msgstr "CSV Vorlagen herunterladen:" msgstr "CSV Vorlagen herunterladen:"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "English Template" msgid "English Template"
msgstr "Englische Vorlage" msgstr "Englische Vorlage"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Error list truncated to %{count} entries" msgid "Error list truncated to %{count} entries"
msgstr "Liste der Fehler auf %{count} Einträge reduziert" msgstr "Liste der Fehler auf %{count} Einträge reduziert"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Errors" msgid "Errors"
msgstr "Fehler" msgstr "Fehler"
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Failed to prepare CSV import: %{reason}" msgid "Failed to prepare CSV import: %{reason}"
msgstr "Das Vorbereiten des CSV Imports ist gescheitert: %{reason}" msgstr "Das Vorbereiten des CSV Imports ist gescheitert: %{reason}"
@ -2040,27 +2040,27 @@ msgstr "Das Importieren von %{idx} ist gescheitert: %{reason}"
msgid "Failed to read file: %{reason}" msgid "Failed to read file: %{reason}"
msgstr "Fehler beim Lesen der Datei: %{reason}" msgstr "Fehler beim Lesen der Datei: %{reason}"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Failed: %{count} row(s)" msgid "Failed: %{count} row(s)"
msgstr "Fehlgeschlagen: %{count} Zeile(n)" msgstr "Fehlgeschlagen: %{count} Zeile(n)"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "German Template" msgid "German Template"
msgstr "Deutsche Vorlage" msgstr "Deutsche Vorlage"
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import Members (CSV)" msgid "Import Members (CSV)"
msgstr "Mitglieder importieren (CSV)" msgstr "Mitglieder importieren (CSV)"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import Results" msgid "Import Results"
msgstr "Import-Ergebnisse" msgstr "Import-Ergebnisse"
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import is already running. Please wait for it to complete." msgid "Import is already running. Please wait for it to complete."
msgstr "Import läuft bereits. Bitte warte, bis er abgeschlossen ist." msgstr "Import läuft bereits. Bitte warte, bis er abgeschlossen ist."
@ -2075,7 +2075,7 @@ msgstr "Import-Status fehlt. Chunk %{idx} kann nicht verarbeitet werden."
msgid "Invalid chunk index: %{idx}" msgid "Invalid chunk index: %{idx}"
msgstr "Ungültiger Chunk-Index: %{idx}" msgstr "Ungültiger Chunk-Index: %{idx}"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Line %{line}: %{message}" msgid "Line %{line}: %{message}"
msgstr "Zeile %{line}: %{message}" msgstr "Zeile %{line}: %{message}"
@ -2085,47 +2085,47 @@ msgstr "Zeile %{line}: %{message}"
msgid "No file was uploaded" msgid "No file was uploaded"
msgstr "Es wurde keine Datei hochgeladen" msgstr "Es wurde keine Datei hochgeladen"
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Only administrators can import members from CSV files." msgid "Only administrators can import members from CSV files."
msgstr "Nur Administrator*innen können Mitglieder aus CSV-Dateien importieren." msgstr "Nur Administrator*innen können Mitglieder aus CSV-Dateien importieren."
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Please select a CSV file to import." msgid "Please select a CSV file to import."
msgstr "Bitte wähle eine CSV-Datei zum Importieren." msgstr "Bitte wähle eine CSV-Datei zum Importieren."
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Please wait for the file upload to complete before starting the import." msgid "Please wait for the file upload to complete before starting the import."
msgstr "Bitte warte, bis der Datei-Upload abgeschlossen ist, bevor du den Import startest." msgstr "Bitte warte, bis der Datei-Upload abgeschlossen ist, bevor du den Import startest."
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Processing chunk %{current} of %{total}..." msgid "Processing chunk %{current} of %{total}..."
msgstr "Verarbeite Chunk %{current} von %{total}..." msgstr "Verarbeite Chunk %{current} von %{total}..."
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Start Import" msgid "Start Import"
msgstr "Import starten" msgstr "Import starten"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Starting import..." msgid "Starting import..."
msgstr "Import wird gestartet..." msgstr "Import wird gestartet..."
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Successfully inserted: %{count} member(s)" msgid "Successfully inserted: %{count} member(s)"
msgstr "Erfolgreich eingefügt: %{count} Mitglied(er)" msgstr "Erfolgreich eingefügt: %{count} Mitglied(er)"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Summary" msgid "Summary"
msgstr "Zusammenfassung" msgstr "Zusammenfassung"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Warnings" msgid "Warnings"
msgstr "Warnungen" msgstr "Warnungen"
@ -2342,7 +2342,7 @@ msgstr "%{name} entfernen"
msgid "Some members could not be added: %{errors}" msgid "Some members could not be added: %{errors}"
msgstr "Einige Mitglieder konnten nicht hinzugefügt werden: %{errors}" msgstr "Einige Mitglieder konnten nicht hinzugefügt werden: %{errors}"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "CSV files only, maximum %{size} MB" msgid "CSV files only, maximum %{size} MB"
msgstr "Nur CSV Dateien, maximal %{size} MB" msgstr "Nur CSV Dateien, maximal %{size} MB"
@ -2372,43 +2372,22 @@ msgstr "Datenfeld: %{name} erwartet %{type}, erhalten: %{value}"
msgid "Unknown column '%{header}' will be ignored. If this is a custom field, create it in Mila before importing." msgid "Unknown column '%{header}' will be ignored. If this is a custom field, create it in Mila before importing."
msgstr "Unbekannte Spalte '%{header}' wird ignoriert. Falls dies ein Datenfeld ist, erstelle es in Mila vor dem Import." msgstr "Unbekannte Spalte '%{header}' wird ignoriert. Falls dies ein Datenfeld ist, erstelle es in Mila vor dem Import."
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Export Members (CSV)"
msgstr "Mitglieder importieren (CSV)"
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format
msgid "Export functionality will be available in a future release."
msgstr "Export-Funktionalität ist im nächsten release verfügbar."
#: lib/mv/membership/import/import_runner.ex #: lib/mv/membership/import/import_runner.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Failed to read uploaded file: unexpected format" msgid "Failed to read uploaded file: unexpected format"
msgstr "Fehler beim Lesen der hochgeladenen Datei" msgstr "Fehler beim Lesen der hochgeladenen Datei"
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format
msgid "Import members from CSV files or export member data."
msgstr "Importiere Mitglieder aus CSV-Dateien oder exportiere Mitgliederdaten."
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format
msgid "Import/Export"
msgstr "Import/Export"
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "You do not have permission to access this page." msgid "You do not have permission to access this page."
msgstr "Du hast keine Berechtigung, auf diese Seite zuzugreifen." msgstr "Du hast keine Berechtigung, auf diese Seite zuzugreifen."
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Manage Member Data" msgid "Manage Member Data"
msgstr "Mitgliederdaten verwalten" msgstr "Mitgliederdaten verwalten"
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Use the data field name as the CSV column header in your file. Data fields must exist in Mila before importing, so they must be listed in the list of member data (like e-mail or first name). Unknown data field columns will be ignored with a warning." msgid "Use the data field name as the CSV column header in your file. Data fields must exist in Mila before importing, so they must be listed in the list of member data (like e-mail or first name). Unknown data field columns will be ignored with a warning."
msgstr "Verwende die Namen der Datenfelder als Spaltennamen in der CSV Datei. Datenfelder müssen in Mila bereits angelegt sein, damit sie importiert werden können. sie müssen in der Liste der Mitgliederdaten als Datenfeld enthalten sein (z.B. E-Mail). Spalten mit unbekannten Spaltenüberschriften werden mit einer Warnung ignoriert." msgstr "Verwende die Namen der Datenfelder als Spaltennamen in der CSV Datei. Datenfelder müssen in Mila bereits angelegt sein, damit sie importiert werden können. sie müssen in der Liste der Mitgliederdaten als Datenfeld enthalten sein (z.B. E-Mail). Spalten mit unbekannten Spaltenüberschriften werden mit einer Warnung ignoriert."
@ -2470,7 +2449,7 @@ msgstr "SSO / OIDC Nutzer*in"
msgid "This user is linked via SSO (Single Sign-On). A password set or changed here only affects login with email and password in this application. It does not change the password in your identity provider (e.g. Authentik). To change the SSO password, use the identity provider or your organization's IT." msgid "This user is linked via SSO (Single Sign-On). A password set or changed here only affects login with email and password in this application. It does not change the password in your identity provider (e.g. Authentik). To change the SSO password, use the identity provider or your organization's IT."
msgstr "Diese*r Nutzer*in ist über SSO (Single Sign-On) verbunden. Ein hier festgelegtes oder geändertes Passwort wirkt sich nur auf die Anmeldung mit E-Mail-Adresse und Passwort in dieser Anwendung aus. Es ändert nicht das Passwort in Eurem Identitätsanbieter (z. B. Authentik). Um das SSO-Passwort zu ändern, wende dich an den Identitätsanbieter oder die IT-Abteilung Ihrer Organisation." msgstr "Diese*r Nutzer*in ist über SSO (Single Sign-On) verbunden. Ein hier festgelegtes oder geändertes Passwort wirkt sich nur auf die Anmeldung mit E-Mail-Adresse und Passwort in dieser Anwendung aus. Es ändert nicht das Passwort in Eurem Identitätsanbieter (z. B. Authentik). Um das SSO-Passwort zu ändern, wende dich an den Identitätsanbieter oder die IT-Abteilung Ihrer Organisation."
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import aborted" msgid "Import aborted"
msgstr "Import abgebrochen" msgstr "Import abgebrochen"
@ -2631,3 +2610,24 @@ msgstr "Anzahl Mitglieder:"
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "PDF" msgid "PDF"
msgstr "PDF" msgstr "PDF"
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Import"
msgstr "Import"
#~ #: lib/mv_web/live/import_export_live.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "Export Members (CSV)"
#~ msgstr "Mitglieder exportieren (CSV)"
#~ #: lib/mv_web/live/import_export_live.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Export functionality will be available in a future release."
#~ msgstr "Export-Funktionalität ist im nächsten release verfügbar."
#~ #: lib/mv_web/live/import_export_live.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Import members from CSV files or export member data."
#~ msgstr "Importiere Mitglieder aus CSV-Dateien oder exportiere Mitgliederdaten."

View file

@ -1875,7 +1875,7 @@ msgstr ""
msgid "updated" msgid "updated"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#: lib/mv_web/live/user_live/form.ex #: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Unknown error" msgid "Unknown error"
@ -1996,37 +1996,37 @@ msgstr ""
msgid "Reset" msgid "Reset"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid " (Field: %{field})" msgid " (Field: %{field})"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "CSV File" msgid "CSV File"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Download CSV templates:" msgid "Download CSV templates:"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "English Template" msgid "English Template"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Error list truncated to %{count} entries" msgid "Error list truncated to %{count} entries"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Errors" msgid "Errors"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Failed to prepare CSV import: %{reason}" msgid "Failed to prepare CSV import: %{reason}"
msgstr "" msgstr ""
@ -2041,27 +2041,27 @@ msgstr ""
msgid "Failed to read file: %{reason}" msgid "Failed to read file: %{reason}"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Failed: %{count} row(s)" msgid "Failed: %{count} row(s)"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "German Template" msgid "German Template"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import Members (CSV)" msgid "Import Members (CSV)"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import Results" msgid "Import Results"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import is already running. Please wait for it to complete." msgid "Import is already running. Please wait for it to complete."
msgstr "" msgstr ""
@ -2076,7 +2076,7 @@ msgstr ""
msgid "Invalid chunk index: %{idx}" msgid "Invalid chunk index: %{idx}"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Line %{line}: %{message}" msgid "Line %{line}: %{message}"
msgstr "" msgstr ""
@ -2086,47 +2086,47 @@ msgstr ""
msgid "No file was uploaded" msgid "No file was uploaded"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Only administrators can import members from CSV files." msgid "Only administrators can import members from CSV files."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Please select a CSV file to import." msgid "Please select a CSV file to import."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Please wait for the file upload to complete before starting the import." msgid "Please wait for the file upload to complete before starting the import."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Processing chunk %{current} of %{total}..." msgid "Processing chunk %{current} of %{total}..."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Start Import" msgid "Start Import"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Starting import..." msgid "Starting import..."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Successfully inserted: %{count} member(s)" msgid "Successfully inserted: %{count} member(s)"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Summary" msgid "Summary"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Warnings" msgid "Warnings"
msgstr "" msgstr ""
@ -2343,7 +2343,7 @@ msgstr ""
msgid "Some members could not be added: %{errors}" msgid "Some members could not be added: %{errors}"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "CSV files only, maximum %{size} MB" msgid "CSV files only, maximum %{size} MB"
msgstr "" msgstr ""
@ -2373,43 +2373,22 @@ msgstr ""
msgid "Unknown column '%{header}' will be ignored. If this is a custom field, create it in Mila before importing." msgid "Unknown column '%{header}' will be ignored. If this is a custom field, create it in Mila before importing."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format
msgid "Export Members (CSV)"
msgstr ""
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format
msgid "Export functionality will be available in a future release."
msgstr ""
#: lib/mv/membership/import/import_runner.ex #: lib/mv/membership/import/import_runner.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Failed to read uploaded file: unexpected format" msgid "Failed to read uploaded file: unexpected format"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format
msgid "Import members from CSV files or export member data."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format
msgid "Import/Export"
msgstr ""
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "You do not have permission to access this page." msgid "You do not have permission to access this page."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Manage Member Data" msgid "Manage Member Data"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Use the data field name as the CSV column header in your file. Data fields must exist in Mila before importing, so they must be listed in the list of member data (like e-mail or first name). Unknown data field columns will be ignored with a warning." msgid "Use the data field name as the CSV column header in your file. Data fields must exist in Mila before importing, so they must be listed in the list of member data (like e-mail or first name). Unknown data field columns will be ignored with a warning."
msgstr "" msgstr ""
@ -2471,7 +2450,7 @@ msgstr ""
msgid "This user is linked via SSO (Single Sign-On). A password set or changed here only affects login with email and password in this application. It does not change the password in your identity provider (e.g. Authentik). To change the SSO password, use the identity provider or your organization's IT." msgid "This user is linked via SSO (Single Sign-On). A password set or changed here only affects login with email and password in this application. It does not change the password in your identity provider (e.g. Authentik). To change the SSO password, use the identity provider or your organization's IT."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import aborted" msgid "Import aborted"
msgstr "" msgstr ""
@ -2632,3 +2611,9 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "PDF" msgid "PDF"
msgstr "" msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format
msgid "Import"
msgstr ""

View file

@ -1875,7 +1875,7 @@ msgstr ""
msgid "updated" msgid "updated"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#: lib/mv_web/live/user_live/form.ex #: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Unknown error" msgid "Unknown error"
@ -1996,37 +1996,37 @@ msgstr ""
msgid "Reset" msgid "Reset"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid " (Field: %{field})" msgid " (Field: %{field})"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "CSV File" msgid "CSV File"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Download CSV templates:" msgid "Download CSV templates:"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "English Template" msgid "English Template"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Error list truncated to %{count} entries" msgid "Error list truncated to %{count} entries"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Errors" msgid "Errors"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Failed to prepare CSV import: %{reason}" msgid "Failed to prepare CSV import: %{reason}"
msgstr "" msgstr ""
@ -2041,27 +2041,27 @@ msgstr ""
msgid "Failed to read file: %{reason}" msgid "Failed to read file: %{reason}"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Failed: %{count} row(s)" msgid "Failed: %{count} row(s)"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "German Template" msgid "German Template"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import Members (CSV)" msgid "Import Members (CSV)"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import Results" msgid "Import Results"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import is already running. Please wait for it to complete." msgid "Import is already running. Please wait for it to complete."
msgstr "" msgstr ""
@ -2076,7 +2076,7 @@ msgstr ""
msgid "Invalid chunk index: %{idx}" msgid "Invalid chunk index: %{idx}"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Line %{line}: %{message}" msgid "Line %{line}: %{message}"
msgstr "" msgstr ""
@ -2086,47 +2086,47 @@ msgstr ""
msgid "No file was uploaded" msgid "No file was uploaded"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Only administrators can import members from CSV files." msgid "Only administrators can import members from CSV files."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Please select a CSV file to import." msgid "Please select a CSV file to import."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Please wait for the file upload to complete before starting the import." msgid "Please wait for the file upload to complete before starting the import."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Processing chunk %{current} of %{total}..." msgid "Processing chunk %{current} of %{total}..."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Start Import" msgid "Start Import"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Starting import..." msgid "Starting import..."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Successfully inserted: %{count} member(s)" msgid "Successfully inserted: %{count} member(s)"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Summary" msgid "Summary"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Warnings" msgid "Warnings"
msgstr "" msgstr ""
@ -2343,7 +2343,7 @@ msgstr ""
msgid "Some members could not be added: %{errors}" msgid "Some members could not be added: %{errors}"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "CSV files only, maximum %{size} MB" msgid "CSV files only, maximum %{size} MB"
msgstr "" msgstr ""
@ -2373,43 +2373,22 @@ msgstr ""
msgid "Unknown column '%{header}' will be ignored. If this is a custom field, create it in Mila before importing." msgid "Unknown column '%{header}' will be ignored. If this is a custom field, create it in Mila before importing."
msgstr "Unknown column '%{header}' will be ignored. If this is a custom field, create it in Mila before importing." msgstr "Unknown column '%{header}' will be ignored. If this is a custom field, create it in Mila before importing."
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Export Members (CSV)"
msgstr ""
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format
msgid "Export functionality will be available in a future release."
msgstr ""
#: lib/mv/membership/import/import_runner.ex #: lib/mv/membership/import/import_runner.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Failed to read uploaded file: unexpected format" msgid "Failed to read uploaded file: unexpected format"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live.ex #: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format
msgid "Import members from CSV files or export member data."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format
msgid "Import/Export"
msgstr ""
#: lib/mv_web/live/import_export_live.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "You do not have permission to access this page." msgid "You do not have permission to access this page."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Manage Member Data" msgid "Manage Member Data"
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Use the data field name as the CSV column header in your file. Data fields must exist in Mila before importing, so they must be listed in the list of member data (like e-mail or first name). Unknown data field columns will be ignored with a warning." msgid "Use the data field name as the CSV column header in your file. Data fields must exist in Mila before importing, so they must be listed in the list of member data (like e-mail or first name). Unknown data field columns will be ignored with a warning."
msgstr "" msgstr ""
@ -2471,7 +2450,7 @@ msgstr ""
msgid "This user is linked via SSO (Single Sign-On). A password set or changed here only affects login with email and password in this application. It does not change the password in your identity provider (e.g. Authentik). To change the SSO password, use the identity provider or your organization's IT." msgid "This user is linked via SSO (Single Sign-On). A password set or changed here only affects login with email and password in this application. It does not change the password in your identity provider (e.g. Authentik). To change the SSO password, use the identity provider or your organization's IT."
msgstr "" msgstr ""
#: lib/mv_web/live/import_export_live/components.ex #: lib/mv_web/live/import_live/components.ex
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Import aborted" msgid "Import aborted"
msgstr "" msgstr ""
@ -2632,3 +2611,24 @@ msgstr "Member count:"
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "PDF" msgid "PDF"
msgstr "" msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/import_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Import"
msgstr ""
#~ #: lib/mv_web/live/import_export_live.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "Export Members (CSV)"
#~ msgstr ""
#~ #: lib/mv_web/live/import_export_live.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Export functionality will be available in a future release."
#~ msgstr ""
#~ #: lib/mv_web/live/import_export_live.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Import members from CSV files or export member data."
#~ msgstr ""

View file

@ -42,7 +42,7 @@ defmodule MvWeb.GlobalSettingsLiveConfigTest do
# Arrange: Set custom row limit to 500 # Arrange: Set custom row limit to 500
Application.put_env(:mv, :csv_import, max_rows: 500) Application.put_env(:mv, :csv_import, max_rows: 500)
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
# Generate CSV with 501 rows (exceeding custom limit of 500) # Generate CSV with 501 rows (exceeding custom limit of 500)
header = "first_name;last_name;email;street;postal_code;city\n" header = "first_name;last_name;email;street;postal_code;city\n"

View file

@ -1,6 +1,6 @@
defmodule MvWeb.ImportExportLiveTest do defmodule MvWeb.ImportLiveTest do
@moduledoc """ @moduledoc """
Tests for Import/Export LiveView: authorization (business rule), CSV import integration, Tests for Import LiveView: authorization (business rule), CSV import integration,
and minimal UI smoke tests. CSV parsing/validation logic is covered by and minimal UI smoke tests. CSV parsing/validation logic is covered by
Mv.Membership.Import.MemberCSVTest; here we verify access control and end-to-end outcomes. Mv.Membership.Import.MemberCSVTest; here we verify access control and end-to-end outcomes.
""" """
@ -31,7 +31,7 @@ defmodule MvWeb.ImportExportLiveTest do
# ---------- Business logic: Authorization ---------- # ---------- Business logic: Authorization ----------
describe "Authorization" do describe "Authorization" do
test "non-admin user cannot access import/export page and sees permission error", %{ test "non-admin user cannot access import page and sees permission error", %{
conn: conn conn: conn
} do } do
member_user = Mv.Fixtures.user_with_role_fixture("own_data") member_user = Mv.Fixtures.user_with_role_fixture("own_data")
@ -42,7 +42,7 @@ defmodule MvWeb.ImportExportLiveTest do
|> put_locale_en() |> put_locale_en()
assert {:error, {:redirect, %{to: redirect_path, flash: %{"error" => msg}}}} = assert {:error, {:redirect, %{to: redirect_path, flash: %{"error" => msg}}}} =
live(conn, ~p"/admin/import-export") live(conn, ~p"/admin/import")
assert redirect_path =~ "/users/" assert redirect_path =~ "/users/"
assert msg =~ "don't have permission" assert msg =~ "don't have permission"
@ -55,7 +55,7 @@ defmodule MvWeb.ImportExportLiveTest do
Path.join([__DIR__, "..", "..", "fixtures", "valid_member_import.csv"]) Path.join([__DIR__, "..", "..", "fixtures", "valid_member_import.csv"])
|> File.read!() |> File.read!()
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
upload_csv_file(view, csv_content) upload_csv_file(view, csv_content)
submit_import(view) submit_import(view)
wait_for_import_completion() wait_for_import_completion()
@ -109,7 +109,7 @@ defmodule MvWeb.ImportExportLiveTest do
end end
test "invalid CSV shows user-friendly prepare error", %{conn: conn} do test "invalid CSV shows user-friendly prepare error", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
upload_csv_file(view, "invalid_header\nincomplete_row", "invalid.csv") upload_csv_file(view, "invalid_header\nincomplete_row", "invalid.csv")
submit_import(view) submit_import(view)
html = render(view) html = render(view)
@ -120,7 +120,7 @@ defmodule MvWeb.ImportExportLiveTest do
conn: conn, conn: conn,
invalid_csv: csv_content invalid_csv: csv_content
} do } do
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
upload_csv_file(view, csv_content, "invalid_import.csv") upload_csv_file(view, csv_content, "invalid_import.csv")
submit_import(view) submit_import(view)
wait_for_import_completion() wait_for_import_completion()
@ -135,7 +135,7 @@ defmodule MvWeb.ImportExportLiveTest do
end end
test "error list is capped and truncation message is shown", %{conn: conn} do test "error list is capped and truncation message is shown", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
header = "first_name;last_name;email;street;postal_code;city\n" header = "first_name;last_name;email;street;postal_code;city\n"
invalid_rows = invalid_rows =
@ -153,7 +153,7 @@ defmodule MvWeb.ImportExportLiveTest do
end end
test "row limit is enforced (1001 rows rejected)", %{conn: conn} do test "row limit is enforced (1001 rows rejected)", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
header = "first_name;last_name;email;street;postal_code;city\n" header = "first_name;last_name;email;street;postal_code;city\n"
rows = rows =
@ -168,7 +168,7 @@ defmodule MvWeb.ImportExportLiveTest do
end end
test "BOM and semicolon delimiter are accepted", %{conn: conn} do test "BOM and semicolon delimiter are accepted", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
csv_content = csv_content =
Path.join([__DIR__, "..", "..", "fixtures", "csv_with_bom_semicolon.csv"]) Path.join([__DIR__, "..", "..", "fixtures", "csv_with_bom_semicolon.csv"])
@ -187,7 +187,7 @@ defmodule MvWeb.ImportExportLiveTest do
test "physical line numbers in errors (empty line does not shift numbering)", %{ test "physical line numbers in errors (empty line does not shift numbering)", %{
conn: conn conn: conn
} do } do
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
csv_content = csv_content =
Path.join([__DIR__, "..", "..", "fixtures", "csv_with_empty_lines.csv"]) Path.join([__DIR__, "..", "..", "fixtures", "csv_with_empty_lines.csv"])
@ -207,7 +207,7 @@ defmodule MvWeb.ImportExportLiveTest do
conn: conn, conn: conn,
unknown_custom_field_csv: csv_content unknown_custom_field_csv: csv_content
} do } do
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
upload_csv_file(view, csv_content, "unknown_custom.csv") upload_csv_file(view, csv_content, "unknown_custom.csv")
submit_import(view) submit_import(view)
wait_for_import_completion() wait_for_import_completion()
@ -220,7 +220,7 @@ defmodule MvWeb.ImportExportLiveTest do
end end
# ---------- UI (smoke / framework): tagged for exclusion from fast CI ---------- # ---------- UI (smoke / framework): tagged for exclusion from fast CI ----------
describe "Import/Export page UI" do describe "Import page UI" do
@describetag :ui @describetag :ui
setup %{conn: conn} do setup %{conn: conn} do
admin_user = Mv.Fixtures.user_with_role_fixture("admin") admin_user = Mv.Fixtures.user_with_role_fixture("admin")
@ -233,19 +233,17 @@ defmodule MvWeb.ImportExportLiveTest do
{:ok, conn: conn} {:ok, conn: conn}
end end
test "page loads and shows import form and export placeholder", %{conn: conn} do test "page loads and shows import form", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
assert has_element?(view, "[data-testid='csv-upload-form']") assert has_element?(view, "[data-testid='csv-upload-form']")
assert has_element?(view, "[data-testid='start-import-button']") assert has_element?(view, "[data-testid='start-import-button']")
assert has_element?(view, "[data-testid='custom-fields-link']") assert has_element?(view, "[data-testid='custom-fields-link']")
html = render(view) html = render(view)
assert html =~ "Import Members (CSV)" assert html =~ "Import Members (CSV)"
assert html =~ "Export Members (CSV)"
assert html =~ "Export functionality will be available"
end end
test "template links and file input are present", %{conn: conn} do test "template links and file input are present", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
assert has_element?(view, "a[href*='/templates/member_import_en.csv']") assert has_element?(view, "a[href*='/templates/member_import_en.csv']")
assert has_element?(view, "a[href*='/templates/member_import_de.csv']") assert has_element?(view, "a[href*='/templates/member_import_de.csv']")
assert has_element?(view, "label[for='csv_file']") assert has_element?(view, "label[for='csv_file']")
@ -258,7 +256,7 @@ defmodule MvWeb.ImportExportLiveTest do
Path.join([__DIR__, "..", "..", "fixtures", "valid_member_import.csv"]) Path.join([__DIR__, "..", "..", "fixtures", "valid_member_import.csv"])
|> File.read!() |> File.read!()
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
upload_csv_file(view, csv_content) upload_csv_file(view, csv_content)
submit_import(view) submit_import(view)
wait_for_import_completion() wait_for_import_completion()
@ -273,7 +271,7 @@ defmodule MvWeb.ImportExportLiveTest do
@tag :skip @tag :skip
test "empty CSV shows error", %{conn: conn} do test "empty CSV shows error", %{conn: conn} do
conn = put_locale_en(conn) conn = put_locale_en(conn)
{:ok, view, _html} = live(conn, ~p"/admin/import-export") {:ok, view, _html} = live(conn, ~p"/admin/import")
upload_csv_file(view, " ", "empty.csv") upload_csv_file(view, " ", "empty.csv")
submit_import(view) submit_import(view)
html = render(view) html = render(view)