Files
orderPRO/.paul/phases/51-email-html-layout/51-01-PLAN.md
2026-03-28 21:16:21 +01:00

9.1 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
51-email-html-layout 01 execute 1
database/migrations/20260328_000001_add_html_layout_to_email_mailboxes.sql
src/Modules/Settings/EmailMailboxController.php
src/Modules/Settings/EmailMailboxRepository.php
resources/views/settings/email-mailboxes.php
src/Modules/Email/EmailSendingService.php
true
## Goal Rozbudowa modulu e-mail o HTML layout: header i footer konfigurowane na poziomie skrzynki pocztowej, content z szablonu. Finalna wiadomosc = header + content + footer. Edytor ograniczony do email-safe HTML.

Purpose

Umozliwienie uzytkownikowi stworzenia spojnego brandingu e-mail (naglowek z logo/nazwa firmy, stopka z danymi kontaktowymi) bez powielania tresci w kazdym szablonie.

Output

  • Migracja DB: kolumny header_html, footer_html w email_mailboxes
  • UI skrzynek: dwa edytory Quill (header/footer) z toolbar email-safe
  • Kompozycja e-mail: header + body + footer w EmailSendingService i preview
## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md

Source Files

@src/Modules/Settings/EmailMailboxController.php @src/Modules/Settings/EmailMailboxRepository.php @resources/views/settings/email-mailboxes.php @src/Modules/Email/EmailSendingService.php @resources/views/settings/email-templates.php (reference — Quill config)

## Required Skills (from SPECIAL-FLOWS.md)

No specialized flows configured as required for this work type.

<acceptance_criteria>

Given tabela email_mailboxes istnieje
When migracja zostanie wykonana
Then tabela zawiera kolumny header_html TEXT NULL i footer_html TEXT NULL
And istniejace rekordy maja NULL w obu kolumnach (brak breaking change)

AC-2: Edycja header/footer w formularzu skrzynki

Given uzytkownik otwiera formularz edycji skrzynki pocztowej
When widzi sekcje "Szablon wiadomosci" pod ustawieniami SMTP
Then sa dwa edytory Quill: "Naglowek (header)" i "Stopka (footer)"
And toolbar kazdego edytora ogranicza sie do: bold, italic, underline, link, kolor tekstu, kolor tla, wyrownanie, listy, naglowki (h1-h3), obraz (inline base64)
And tresc edytorow jest zapisywana do DB przy submit formularza
Given skrzynka ma ustawiony header_html i footer_html
And szablon ma body_html
When e-mail jest wysylany lub podgladany (preview)
Then tresc wiadomosci = header_html + body_html (resolved) + footer_html
And header i footer rowniez przechodza przez variable resolver

AC-4: E-mail bez header/footer

Given skrzynka ma puste (NULL) header_html i/lub footer_html
When e-mail jest wysylany
Then tresc wiadomosci zawiera tylko body_html (bez pustych sekcji)

</acceptance_criteria>

Task 1: Migracja DB + Repository + Controller database/migrations/20260328_000001_add_html_layout_to_email_mailboxes.sql, src/Modules/Settings/EmailMailboxRepository.php, src/Modules/Settings/EmailMailboxController.php 1. Utworzyc migracje SQL: ```sql ALTER TABLE email_mailboxes ADD COLUMN header_html TEXT NULL AFTER sender_name, ADD COLUMN footer_html TEXT NULL AFTER header_html; ```
2. EmailMailboxRepository:
   - `save()`: dodac `header_html` i `footer_html` do INSERT/UPDATE
   - `findById()`: upewnic sie ze zwraca te kolumny (juz zwraca SELECT * wiec OK)
   - `listAll()`: bez zmian (nie potrzebuje HTML w liscie)

3. EmailMailboxController:
   - `save()`: pobrac `header_html` i `footer_html` z POST body
   - Nie escapowac HTML (to jest tresc edytora WYSIWYG, jak body_html w szablonach)
   - Przekazac do repozytorium w tablicy save data
- Migracja wykonuje sie bez bledow - DESCRIBE email_mailboxes pokazuje header_html i footer_html jako TEXT NULL - Zapis i odczyt skrzynki z header/footer dziala poprawnie AC-1 satisfied: kolumny istnieja i sa zapisywane/odczytywane Task 2: UI edytorow header/footer w formularzu skrzynki resources/views/settings/email-mailboxes.php 1. Po sekcji "Ustawienia SMTP" dodac nowa sekcje "Szablon wiadomosci" z dwoma edytorami Quill
2. Kazdy edytor (header, footer):
   - Label: "Naglowek (header)" / "Stopka (footer)"
   - Div z id `js-header-editor` / `js-footer-editor` (kontener Quill)
   - Hidden input `header_html` / `footer_html` (sync przy submit)
   - Podpowiedz: "Opcjonalnie. Bedzie dolaczany do kazdego e-maila wysylanego z tej skrzynki."

3. Toolbar edytora — TYLKO email-safe opcje:
   ```javascript
   [
     [{ header: [1, 2, 3, false] }],
     ['bold', 'italic', 'underline'],
     [{ color: [] }, { background: [] }],
     [{ align: [] }],
     [{ list: 'ordered' }, { list: 'bullet' }],
     ['link', 'image'],
     ['clean']
   ]
   ```
   - Image: Quill domyslnie wstawia jako base64 inline — to jest email-safe
   - Brak: strike, blockquote, code-block, video, indent (slabo obslugiwane w klientach pocztowych)

4. Zaladowac Quill CSS/JS z CDN (ten sam co w email-templates: 2.0.3)

5. Na submit formularza: sync innerHTML z edytorow do hidden inputs

6. Przy edycji istniejacego rekordu: zaladowac HTML do edytorow przez `quill.root.innerHTML = ...`

7. Edytory powinny miec mniejsza domyslna wysokosc niz edytor szablonu (np. min-height: 80px)
- Otworz /settings/email-mailboxes — formularz pokazuje dwa edytory - Wpisz tresc w header/footer, zapisz — dane sa w DB - Edytuj skrzynke — header/footer sa zaladowane do edytorow - Toolbar nie zawiera opcji niebezpiecznych dla e-mail (video, code-block) AC-2 satisfied: edytory sa dostepne, ograniczone do email-safe, i zapisuja dane Task 3: Kompozycja e-mail w EmailSendingService src/Modules/Email/EmailSendingService.php 1. W metodzie `send()` po rozwiazaniu zmiennych w body: - Pobrac header_html i footer_html z resolved mailbox - Przepuscic je przez variableResolver.resolve() (aby zmienne dzialaly tez w header/footer) - Zlozyc finalBody: header_html + resolvedBody + footer_html - Jezeli header_html lub footer_html sa NULL/puste — pominac (bez pustych divow) - Uzyc finalBody zamiast resolvedBody w sendViaSMTP i logEmail
2. W metodzie `preview()`:
   - Analogicznie: pobrac mailbox dla szablonu, zlozyc header + body + footer
   - Aby preview dzialal, potrzebujemy mailbox — uzyc resolveMailbox() (juz istnieje)
   - Jezeli mailbox nie znaleziony — pokazac sam body (bez header/footer)

3. Metoda `resolveMailbox()` jest private — juz zwraca pelne dane z findById() wlacznie z header_html/footer_html

4. Nowa prywatna metoda `composeBody(string $resolvedBody, ?array $mailbox, array $variableMap): string`:
   - Wydzielic logike kompozycji do reusable metody
   - Uzyc w send() i preview()
- Wyslij e-mail ze skrzynka z ustawionym header/footer — e-mail zawiera header + body + footer - Wyslij e-mail ze skrzynka BEZ header/footer — e-mail zawiera tylko body - Preview pokazuje zlozony wynik header + body + footer - Zmienne w header/footer sa rozwiazywane (np. {{firma.nazwa}}) AC-3 i AC-4 satisfied: kompozycja dziala z i bez header/footer

DO NOT CHANGE

  • resources/views/settings/email-templates.php (edytor szablonow — bez zmian)
  • src/Modules/Email/VariableResolver.php (resolver zmiennych — bez zmian)
  • src/Modules/Email/AttachmentGenerator.php
  • database/migrations/ (istniejace migracje)
  • Struktura tabeli email_templates (body_html pozostaje jak jest)

SCOPE LIMITS

  • Brak edytora MJML / dedykowanego email buildera — Quill z ograniczonym toolbar wystarcza
  • Brak podgladu header/footer w formularzu skrzynki (preview jest w szablonach)
  • Brak importu gotowych szablonow HTML
  • Zmienne w header/footer dzialaja, ale panel zmiennych NIE jest dodawany do formularza skrzynki (header/footer to zwykle statyczny branding)
Before declaring plan complete: - [ ] Migracja wykonana, kolumny widoczne w DESCRIBE - [ ] Formularz skrzynki: dwa edytory Quill z email-safe toolbar - [ ] Zapis i odczyt header/footer dziala - [ ] E-mail wysylany ze skrzynka z header/footer zawiera zlozony layout - [ ] E-mail wysylany ze skrzynka BEZ header/footer zawiera tylko body - [ ] Preview pokazuje zlozony wynik - [ ] Zmienne w header/footer sa rozwiazywane - [ ] Brak bledow PHP/JS w konsoli

<success_criteria>

  • Wszystkie 3 taski zakonczone
  • Wszystkie 4 acceptance criteria spelnione
  • Wszystkie verification checks przeszly
  • Brak regresji w istniejacym wysylaniu e-mail </success_criteria>
After completion, create `.paul/phases/51-email-html-layout/51-01-SUMMARY.md`