feat: markdown in email body for mailing and transactional
This commit is contained in:
@@ -3,9 +3,11 @@
|
||||
namespace App\Controller\Admin\Teamer;
|
||||
|
||||
use App\Controller\Traits\ReturnUrlTrait;
|
||||
use App\Email\MailBodyRenderer;
|
||||
use App\Form\TeamerMailingType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use App\Message\SendTeamerMailing;
|
||||
use App\Model\TeamerMailingDto;
|
||||
use App\Service\Common\TeamerFilterHandler;
|
||||
use App\Service\Teamer\TeamerMailingDraftHandler;
|
||||
use App\Service\Teamer\TeamerMailingService;
|
||||
@@ -25,6 +27,7 @@ class MailingController extends AbstractController
|
||||
private readonly TeamerFilterHandler $filterHandler,
|
||||
private readonly TeamerMailingService $mailingService,
|
||||
private readonly TeamerMailingDraftHandler $draftHandler,
|
||||
private readonly MailBodyRenderer $mailBodyRenderer,
|
||||
private readonly MessageBusInterface $messageBus,
|
||||
) {
|
||||
}
|
||||
@@ -54,9 +57,12 @@ class MailingController extends AbstractController
|
||||
|
||||
$filterDto = $this->filterHandler->getFilterSettings();
|
||||
|
||||
// no redirect after the preview, the composed mail has to survive it
|
||||
// No redirect after the preview mail, the composed mail has to survive it. The
|
||||
// preview pane is rendered here so the page arrives complete; from then on the
|
||||
// draft route above keeps it up to date.
|
||||
return $this->render('admin/teamer/mailing.html.twig', [
|
||||
'form' => $form->createView(),
|
||||
'preview' => $this->renderPreview($form->getData()),
|
||||
'filterDto' => $filterDto,
|
||||
'recipients' => $this->mailingService->resolveRecipients($filterDto),
|
||||
'placeholders' => TeamerMailingService::PLACEHOLDERS,
|
||||
@@ -66,16 +72,22 @@ class MailingController extends AbstractController
|
||||
}
|
||||
|
||||
/**
|
||||
* Park what has been typed so far, so that a trip to the filter and back does not
|
||||
* throw the composed mail away. Answers nothing, the page stays as it is.
|
||||
* Park what has been typed so far, so that a trip to the filter and back does not throw
|
||||
* the composed mail away, and answer with the preview of that very draft.
|
||||
*
|
||||
* Both hang off the same form content, so they are deliberately one request rather than
|
||||
* two routes on the same keystroke: the preview can never show wording other than the
|
||||
* one that was parked.
|
||||
*/
|
||||
#[Route('/admin/teamer/mailing/draft', name: 'app_admin_teamer_mailing_draft', methods: ['POST'])]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function draft(Request $request): Response
|
||||
{
|
||||
$this->draftHandler->saveDraft($this->createMailingForm($request)->getData());
|
||||
$mailingDto = $this->createMailingForm($request)->getData();
|
||||
|
||||
return new Response(null, Response::HTTP_NO_CONTENT);
|
||||
$this->draftHandler->saveDraft($mailingDto);
|
||||
|
||||
return $this->render('admin/teamer/_mailing_preview.html.twig', $this->renderPreview($mailingDto));
|
||||
}
|
||||
|
||||
#[Route('/admin/teamer/mailing/discard', name: 'app_admin_teamer_mailing_discard')]
|
||||
@@ -140,6 +152,26 @@ class MailingController extends AbstractController
|
||||
return new HxRedirectResponse($this->generateUrl('app_administrative_teamer_index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* What the composing admin would receive. The placeholders are filled from their own
|
||||
* record, the same way sendPreview() fills the test mail, so the pane and the mail that
|
||||
* lands in their inbox show the same name.
|
||||
*
|
||||
* Deliberately rendered whether or not the form validates: a mail that is still missing
|
||||
* its subject is exactly the one an admin is looking at while writing it.
|
||||
*
|
||||
* @return array{subject: string, bodyHtml: string}
|
||||
*/
|
||||
private function renderPreview(TeamerMailingDto $mailingDto): array
|
||||
{
|
||||
$values = $this->mailingService->placeholderValuesForUser($this->getUser());
|
||||
|
||||
return [
|
||||
'subject' => $this->mailingService->render($mailingDto->getSubject(), $values),
|
||||
'bodyHtml' => $this->mailBodyRenderer->render($mailingDto->getMessage(), $values),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* A GET starts from the parked draft, a POST always carries the current one itself.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user