Copy selected members' emails to clipboard in 'First Last <email>' format
7.2 KiB
Bulk Email Copy Feature - Detaillierter Implementierungsplan
Aktueller Stand
Die Checkbox-Funktionalität existiert bereits vollständig:
select_memberundselect_allEvents inlib/mv_web/live/member_live/index.ex(Zeilen 91-117)- Checkboxen im Template
lib/mv_web/live/member_live/index.html.heex(Zeilen 28-54) @selected_membersenthält die UUIDs der ausgewählten Mitglieder als Liste
Gewählte Implementierung: JavaScript Hook mit LiveView Event
Ablauf:
- User wählt Mitglieder über Checkboxen aus
- User klickt "E-Mail-Adressen kopieren" Button
- LiveView Event
copy_emailswird ausgelöst - Server filtert Member aus
@membersnach@selected_members - Server formatiert E-Mails im Format
Vorname Nachname <email> - Server pusht
copy_to_clipboardEvent mit formatiertem String an Client - JavaScript Hook empfängt Event und kopiert via
navigator.clipboard.writeText() - Server zeigt Flash-Nachricht mit Erfolgsbestätigung
Implementierungsschritte
Schritt 1: JavaScript Hook erstellen
Datei: assets/js/app.js
- Neuen Hook
CopyToClipboardzum bestehendenHooksObjekt hinzufügen - Hook lauscht auf
copy_to_clipboardEvent vom Server - Nutzt
navigator.clipboard.writeText()API für das Kopieren - Fallback-Behandlung für Browser ohne Clipboard API (ältere Browser)
- Fehlerbehandlung bei fehlgeschlagenem Kopieren
Schritt 2: LiveView Event Handler implementieren
Datei: lib/mv_web/live/member_live/index.ex
- Neuen
handle_event("copy_emails", ...)Callback hinzufügen - Member aus
@membersfiltern, deren ID in@selected_membersenthalten ist - Jeden Member im Format
"Vorname Nachname <email>"formatieren - Formatierte Strings mit
"; "(Semikolon + Leerzeichen) verbinden push_event/3nutzen umcopy_to_clipboardEvent zu sendenput_flash/3für Erfolgsbestätigung mit Anzahl der kopierten Adressen- Private Helper-Funktion für die E-Mail-Formatierung
Schritt 3: UI Button hinzufügen
Datei: lib/mv_web/live/member_live/index.html.heex
- Button im Header-Bereich neben "New Member" Button platzieren
- Button nur anzeigen wenn mindestens ein Mitglied ausgewählt ist (
:ifBedingung) phx-hook="CopyToClipboard"Attribut für JavaScript Hook Anbindungphx-click="copy_emails"für Event-Auslösung- Icon:
hero-clipboard-documentoderhero-envelope - Button-Text mit Anzahl der ausgewählten Mitglieder anzeigen
- Accessibility:
aria-labelfür Screen Reader
Schritt 4: Gettext Übersetzungen hinzufügen
Dateien:
priv/gettext/default.pot- Template aktualisieren viamix gettext.extractpriv/gettext/de/LC_MESSAGES/default.po- Deutsche Übersetzungenpriv/gettext/en/LC_MESSAGES/default.po- Englische Übersetzungen (falls vorhanden)
Zu übersetzende Strings:
- Button-Text: "Copy Email Addresses"
- Flash-Nachricht Erfolg: "Copied %{count} email address(es) to clipboard"
- Flash-Nachricht Fehler: "No members selected"
Schritt 5: Moduledoc aktualisieren
Datei: lib/mv_web/live/member_live/index.ex
@moduledocum neues Eventcopy_emailserweitern- Dokumentation der Funktionalität hinzufügen
Edge Cases
E1: Keine Mitglieder ausgewählt
- Button wird nicht angezeigt (UI-seitig gelöst)
- Falls Event dennoch ausgelöst wird: Error-Flash anzeigen, nichts kopieren
E2: Ausgewählte Mitglieder nicht mehr in @members Liste
- Kann passieren wenn Member zwischenzeitlich gelöscht wurde
- Nur vorhandene Member verarbeiten, keine Fehler werfen
- Flash zeigt tatsächliche Anzahl kopierter Adressen
E3: Member ohne E-Mail-Adresse
- Defensive Programmierung: Member ohne E-Mail überspringen
E4: Member mit leerem Vor- oder Nachnamen
- Defensive Programmierung: Leere Namen graceful behandeln
E5: Sonderzeichen in Namen
- Namen können Umlaute, Akzente, etc. enthalten
- Keine Escaping nötig, da Text direkt in Zwischenablage kopiert wird
- E-Mail-Clients verarbeiten Unicode korrekt
E6: Sehr lange Liste (100+ Mitglieder)
- String kann sehr lang werden
- Clipboard API hat kein praktisches Limit
- Kein spezielles Handling nötig
E7: Browser unterstützt Clipboard API nicht
navigator.clipboardist nicht in allen Browsern verfügbar- Fallback:
document.execCommand('copy')(deprecated aber breit unterstützt) - Oder: Fehler-Flash anzeigen
E8: Clipboard-Zugriff vom Browser blockiert
- Moderne Browser können Clipboard-Zugriff einschränken
- HTTPS erforderlich (in Produktion gegeben)
- User muss ggf. Berechtigung erteilen
- Fehlerbehandlung im Hook nötig
E9: Parallel laufende Suche/Filter ändert @members
- User wählt Mitglieder, dann ändert Suche die Liste
@selected_membersbleibt erhalten, aber IDs passen nicht mehr zu@members- Nur noch vorhandene (angezeigte) Members werden kopiert
- Entscheidung: Selection bei Suche beibehalten?
E10: "Select All" nach Filterung
- Wenn gefiltert und "Select All" geklickt, werden nur sichtbare Members ausgewählt
- Bestehendes Verhalten, kein neues Problem
Testplan
Unit Tests (index.ex)
T1: copy_emails Event - Erfolgsfall
- Setup: 3 Members in
@members, 2 davon in@selected_members - Assert:
push_eventwird mit korrektem String aufgerufen - Assert: Flash-Nachricht mit count=2
T2: copy_emails Event - Keine Auswahl
- Setup:
@selected_membersist leer - Assert: Kein
push_event - Assert: Error-Flash oder keine Aktion
T3: copy_emails Event - Alle ausgewählt
- Setup: Alle Members in
@selected_members - Assert: Alle E-Mails im Output-String
T4: E-Mail Formatierung
- Assert: Format ist
"Vorname Nachname <email>" - Assert: Mehrere E-Mails mit
"; "getrennt
T5: Member mit Sonderzeichen im Namen
- Setup: Member mit Name "Müller-Lüdenscheidt"
- Assert: Name wird korrekt übernommen
T6: Teilweise nicht vorhandene Member
- Setup:
@selected_membersenthält ID die nicht in@membersist - Assert: Nur vorhandene Members werden verarbeitet, kein Crash
LiveView Integration Tests
T7: Button Sichtbarkeit
- Assert: Button nicht sichtbar wenn
@selected_membersleer - Assert: Button sichtbar wenn mindestens 1 Member ausgewählt
T8: Button zeigt korrekte Anzahl
- Setup: 3 Members ausgewählt
- Assert: Button-Text enthält "(3)"
T9: Click löst Event aus
- Action: Click auf Copy-Button
- Assert:
copy_emailsEvent wird gesendet
T10: Vollständiger Flow
- Action: Member auswählen, Button klicken
- Assert: Flash-Nachricht erscheint
Zu ändernde Dateien
| Datei | Änderungstyp |
|-------|--------------|
| assets/js/app.js | Hook hinzufügen |
| lib/mv_web/live/member_live/index.ex | Event Handler + Helper |
| lib/mv_web/live/member_live/index.html.heex | Button UI |
| priv/gettext/de/LC_MESSAGES/default.po | Übersetzungen |
| test/mv_web/member_live/index_test.exs | Tests |
E-Mail Output Format
Einzelne E-Mail:
Max Mustermann <max@example.com>
Mehrere E-Mails:
Max Mustermann <max@example.com>; Erika Musterfrau <erika@example.com>; Hans Müller <hans@example.com>
Hinweis: Semikolon als Trennzeichen ist Standard für E-Mail-Clients (Outlook, Thunderbird, etc.)