feat(assets): Ajoute l'éditeur de template d'email et la sauvegarde des configurations.

 feat(mails): Crée un template twig pour la prévisualisation des emails.
 feat(TemplateController): Ajoute la prévisualisation du template newsletter.
This commit is contained in:
Serreau Jovann
2025-08-04 16:02:50 +02:00
parent dbcd5c0dd2
commit 5e56340224
3 changed files with 107 additions and 3 deletions

View File

@@ -4,6 +4,11 @@ import sortable from "sortablejs/src/Sortable.js";
export class MainframeEmailEditor extends HTMLElement {
connectedCallback() {
let template = document.body.querySelector('#template_content')
let configTemplate = template.getAttribute('value');
let element = this;
let button = document.createElement('button');
button.innerText = "Modifier le template";
@@ -26,6 +31,9 @@ export class MainframeEmailEditor extends HTMLElement {
<div class="email-builder-toolbar">
<h2>EsyMail - Editor</h2>
<div class="email-builder-actions">
<a class="save px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white transition font-semibold">
Sauvegarder
</a>
<a class="closed px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white transition font-semibold">
Fermer
</a>
@@ -60,6 +68,29 @@ export class MainframeEmailEditor extends HTMLElement {
</ul>
</div>
`;
let content = modal.querySelector('.content');
let save = modal.querySelector('.save');
save.addEventListener('click', (event) => {
event.preventDefault();
modal.remove();
let configs = {};
content.querySelectorAll('.area-block').forEach((block,posBlock) => {
configs[posBlock] = {
type: block.getAttribute('type'),
config: JSON.parse(block.getAttribute('config')),
modules: {}
}
})
console.log(configs);
template.setAttribute('value',JSON.stringify(configs));
template.value = JSON.stringify(configs);
})
let closed = modal.querySelector('.closed');
closed.addEventListener('click', (event) => {
@@ -71,8 +102,6 @@ export class MainframeEmailEditor extends HTMLElement {
let area = modal.querySelector('.area');
let module = modal.querySelector('.module');
let content = modal.querySelector('.content');
new sortable(area, {
sort: false,
group: {
@@ -545,6 +574,19 @@ export class MainframeEmailEditor extends HTMLElement {
ulCol.style.background = config.backgroundColor;
element.querySelector('.area-block-body').appendChild(ulCol);
new sortable(ulCol,{
group: {
name: 'module',
revertClone: true,
},
onSort:(event)=>{
event.to.querySelectorAll('li').forEach((eleModule, posModule) => {
});
}
})
let edit = element.querySelector('.edit');
edit.addEventListener('click', (event) => {
event.preventDefault();

View File

@@ -7,9 +7,12 @@ use App\Form\Artemis\Newsletter\TemplateType;
use App\Repository\Newsletter\TemplateRepository;
use App\Service\Mailer\AmazonSesClient;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
use Symfony\Component\Routing\Attribute\Route;
class TemplateController extends AbstractController
@@ -69,8 +72,38 @@ class TemplateController extends AbstractController
}
#[Route(path: '/artemis/newsletter/template/{id}/preview',name: 'artemis_newsletter_template_preview',methods: ['GET', 'POST'])]
public function templatePreview(TemplateRepository $templateRepository): Response
public function templatePreview(?Template $template): Response
{
$configs = json_decode($template->getContent(),true);
$mjml= $this->render('mails/preview.twig', [
'cg' => $configs,
]);
$html = $this->convertMjmlToHtml($mjml);
return new Response($html);
}
private function convertMjmlToHtml(string $mjmlContent): string
{
$command = ['mjml', '--stdin'];
$process = new Process($command);
try {
$process->setInput($mjmlContent);
$process->run();
// Exécute la commande et vérifie la réussite
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
return $process->getOutput();
} catch (ProcessFailedException $exception) {
return ''; // Retourne une chaîne vide en cas d'échec
} catch (Exception $e) {
return '';
}
}
}

View File

@@ -0,0 +1,29 @@
<mjml>
<mj-body>
{% for item in cg %}
<mj-section background-color="{{item.config.backgroundColor}}">
{% if item.type == "1col" %}
<mj-column>
<mj-text font-size="20px" color="#F45E43" font-family="helvetica">Hello World</mj-text>
</mj-column>
{% endif%}
{% if item.type == "5050col" or item.type == "505050col" %}
<mj-column background-color="{{item.config.backgroundColor_1}}">
<mj-text font-size="20px" color="#F45E43" font-family="helvetica">Hello World</mj-text>
</mj-column>
<mj-column background-color="{{item.config.backgroundColor_2}}">
COL TWO
</mj-column>
{% endif%}
{% if item.type == "505050col" %}
<mj-column background-color="{{item.config.backgroundColor_3}}">
<mj-text font-size="20px" color="#F45E43" font-family="helvetica">Hello World</mj-text>
</mj-column>
{% endif%}
</mj-section>
{% endfor %}
</mj-body>
</mjml>