Date: Tue, 4 Feb 2025 17:35:09 +0100
Subject: [PATCH 049/121] add unsubscribe and view mail on the web buttons
---
assets/css/src/header.css | 6 +-
site/blueprints/pages/email.yml | 1 +
site/collections/categories.php | 18 +--
site/config/config.php | 41 +++---
site/config/menu.php | 48 +++----
site/config/routes/subscribe.php | 31 ++--
site/plugins/helpers/index.php | 1 +
site/plugins/send-button/index.css | 2 +-
site/plugins/send-button/index.js | 2 +-
site/plugins/send-button/index.php | 14 +-
.../send-button}/routes/send-newsletter.php | 52 +++----
.../routes/unsubscribe-newsletter.php | 39 +++++
.../src/components/SendButtonField.vue | 17 +--
site/snippets/cover.php | 39 +++--
site/snippets/footer.php | 6 +-
site/snippets/header.php | 134 ++++++++++--------
site/templates/email.php | 2 +-
site/templates/emails/newsletter.html.php | 5 +-
site/templates/error.php | 12 +-
site/templates/linear.php | 43 +++---
20 files changed, 289 insertions(+), 224 deletions(-)
rename site/{config => plugins/send-button}/routes/send-newsletter.php (51%)
create mode 100644 site/plugins/send-button/routes/unsubscribe-newsletter.php
diff --git a/assets/css/src/header.css b/assets/css/src/header.css
index bf5a8d9..c39ab8f 100644
--- a/assets/css/src/header.css
+++ b/assets/css/src/header.css
@@ -123,8 +123,10 @@ button.toggle.right::before {
[data-template="author"] .page-cover,
[data-template="category"] .page-cover,
- [data-template="year"] .page-cover {
- height: initial;
+ [data-template="year"] .page-cover,
+ [data-template="email"] .page-cover,
+ [data-template="error"] .page-cover {
+ height: initial !important;
}
.page-cover .links {
diff --git a/site/blueprints/pages/email.yml b/site/blueprints/pages/email.yml
index 0f15dfe..78b650d 100644
--- a/site/blueprints/pages/email.yml
+++ b/site/blueprints/pages/email.yml
@@ -1,6 +1,7 @@
title: Email
status:
draft: Brouillon
+ unlisted: Testé
listed: Envoyé
image:
back: black
diff --git a/site/collections/categories.php b/site/collections/categories.php
index b6e6c5e..81ec8f6 100644
--- a/site/collections/categories.php
+++ b/site/collections/categories.php
@@ -1,26 +1,28 @@
categories()->split() as $categoryName) {
$category = new Page([
- 'slug' => Str::slug($categoryName),
+ 'slug' => Str::slug($categoryName),
'template' => 'category',
- 'status' => 'listed',
- 'content' => [
+ 'status' => 'listed',
+ 'content' => [
'title' => $categoryName,
],
- 'children' => []
+ 'children' => [],
]);
$categories->add($category);
- }
+ }
return $categories;
}
-function createCategories() {
+function createCategories()
+{
$emptyCategories = createEmptyCategories();
foreach (page('textes')->grandChildren() as $text) {
try {
diff --git a/site/config/config.php b/site/config/config.php
index 7d2c051..5fcfb1a 100644
--- a/site/config/config.php
+++ b/site/config/config.php
@@ -1,24 +1,23 @@
true,
- "panel" => array(
- "menu" => require __DIR__ . "/menu.php",
- "css" => "assets/css/panel.css"
- ),
- "email" => [
- "transport" => [
- "type" => "smtp",
- "host" => "mail.infomaniak.com",
- "port" => 465,
- "auth" => true,
- "username" => "info@actuel-inactuel.fr",
- "password" => "v!Vr$#JH7quJ35"
- ]
+return [
+ 'debug' => true,
+ 'panel' => [
+ 'menu' => require __DIR__ . '/menu.php',
+ 'css' => 'assets/css/panel.css',
+ ],
+ 'email' => [
+ 'transport' => [
+ 'type' => 'smtp',
+ 'host' => 'smtp.mailersend.net',
+ 'port' => 587,
+ 'auth' => true,
+ 'username' => 'MS_K9grTE@actuel-inactuel.fr',
+ 'password' => 'mssp.GJGywUh.z3m5jgrq71xldpyo.owybzs9',
],
- "routes" => array(
- require __DIR__ . "/routes/virtual-category.php",
- require __DIR__ . "/routes/send-newsletter.php",
- require __DIR__ . "/routes/subscribe.php",
- )
-);
+ ],
+ 'routes' => [
+ require __DIR__ . '/routes/virtual-category.php',
+ require __DIR__ . '/routes/subscribe.php',
+ ],
+];
diff --git a/site/config/menu.php b/site/config/menu.php
index 6831988..5b57f01 100644
--- a/site/config/menu.php
+++ b/site/config/menu.php
@@ -2,62 +2,62 @@
return [
'site' => [
- 'label' => 'Accueil',
+ 'label' => 'Accueil',
'current' => function ($current) {
$path = Kirby::instance()->request()->path()->toString();
return Str::contains($path, 'site');
- }
+ },
],
'texts' => [
- 'icon' => 'pen',
- 'label' => 'Textes',
- 'link' => 'pages/textes',
+ 'icon' => 'pen',
+ 'label' => 'Textes',
+ 'link' => 'pages/textes',
'current' => function ($current) {
$path = Kirby::instance()->request()->path()->toString();
return Str::contains($path, 'pages/textes');
- }
+ },
],
'authors' => [
- 'icon' => 'users',
- 'label' => 'Auteurs',
- 'link' => 'pages/auteurs',
+ 'icon' => 'users',
+ 'label' => 'Auteurs',
+ 'link' => 'pages/auteurs',
'current' => function ($current) {
- $path = Kirby::instance()->request()->path()->toString();
- return Str::contains($path, 'pages/auteurs');
- }
+ $path = Kirby::instance()->request()->path()->toString();
+ return Str::contains($path, 'pages/auteurs');
+ },
],
'-',
'-',
'infos' => [
- 'icon' => 'question',
- 'label' => 'À propos',
- 'link' => 'pages/a-propos',
+ 'icon' => 'question',
+ 'label' => 'À propos',
+ 'link' => 'pages/a-propos',
'current' => function ($current) {
$path = Kirby::instance()->request()->path()->toString();
return Str::contains($path, 'pages/a-propos');
- }
+ },
],
'subscription' => [
- 'icon' => 'email',
- 'label' => 'Liste de diffusion',
- 'link' => 'pages/inscription',
+ 'icon' => 'email',
+ 'label' => 'Liste de diffusion',
+ 'link' => 'pages/lettre',
'current' => function ($current) {
$path = Kirby::instance()->request()->path()->toString();
return Str::contains($path, 'pages/liste-de-diffusion');
- }
+ },
],
'-',
'-',
'users',
'comments',
'admin' => [
- 'icon' => 'folder',
- 'label' => 'Administration',
- 'link' => 'pages/admin',
+ 'icon' => 'folder',
+ 'label' => 'Administration',
+ 'link' => 'pages/admin',
'current' => function ($current) {
$path = Kirby::instance()->request()->path()->toString();
return Str::contains($path, 'pages/admin');
- }
+ },
],
'-',
'-',
diff --git a/site/config/routes/subscribe.php b/site/config/routes/subscribe.php
index d54eab2..7d183d1 100644
--- a/site/config/routes/subscribe.php
+++ b/site/config/routes/subscribe.php
@@ -2,43 +2,42 @@
return [
'pattern' => '/subscribe.json',
- 'method' => 'POST',
+ 'method' => 'POST',
'action' => function () {
- $jsonRequest = file_get_contents("php://input");
+ $jsonRequest = file_get_contents('php://input');
$email = Str::lower(json_decode($jsonRequest));
if (V::email($email)) {
kirby()->impersonate('kirby');
-
- $page = page("inscription");
+
+ $page = page('lettre');
$subscribers = $page->subscribers()->yaml();
- $emailExists = in_array(["email" => $email], $subscribers);
+ $emailExists = in_array(['email' => $email], $subscribers);
if ($emailExists) {
return [
- "status" => "error",
- "message" => "Cet email est déjà inscris."
+ 'status' => 'error',
+ 'message' => 'Cet email est déjà inscris.',
];
}
- $newSubscriber = ["email" => $email];
+ $newSubscriber = ['email' => $email];
$subscribers[] = $newSubscriber;
-
+
$page->update([
- 'subscribers' => $subscribers
+ 'subscribers' => $subscribers,
]);
return [
- "status" => "success",
- "message" => "Inscription réussie."
+ 'status' => 'success',
+ 'message' => 'lettre réussie.',
];
} else {
return [
- "status" => "error",
- "message" => "Email invalide."
+ 'status' => 'error',
+ 'message' => 'Email invalide.',
];
}
- }
+ },
];
-
diff --git a/site/plugins/helpers/index.php b/site/plugins/helpers/index.php
index c52d137..69357d7 100644
--- a/site/plugins/helpers/index.php
+++ b/site/plugins/helpers/index.php
@@ -29,3 +29,4 @@ function getAuthorBySlug($slug)
return $author;
}
+
\ No newline at end of file
diff --git a/site/plugins/send-button/index.css b/site/plugins/send-button/index.css
index b5dbbb2..1331a1c 100644
--- a/site/plugins/send-button/index.css
+++ b/site/plugins/send-button/index.css
@@ -1 +1 @@
-.wrapper[data-v-76f92a36]{display:flex;gap:10vw}.k-field-footer[data-v-76f92a36]{width:15rem}@media screen and (max-width: 800px){.k-field-footer[data-v-76f92a36]{width:9rem}}@media screen and (min-width: 533px){button[data-v-76f92a36]{margin-top:2.15rem}}
+.wrapper[data-v-0e6a95b9]{display:flex;gap:10vw}.k-field-footer[data-v-0e6a95b9]{width:15rem}@media screen and (max-width: 800px){.k-field-footer[data-v-0e6a95b9]{width:9rem}}@media screen and (min-width: 533px){button[data-v-0e6a95b9]{margin-top:2.15rem}}
diff --git a/site/plugins/send-button/index.js b/site/plugins/send-button/index.js
index d6cd167..293859c 100644
--- a/site/plugins/send-button/index.js
+++ b/site/plugins/send-button/index.js
@@ -1 +1 @@
-(function(){"use strict";function d(t,e,r,n,o,l,a,i){var s=typeof t=="function"?t.options:t;return s.render=e,s.staticRenderFns=r,s._compiled=!0,s._scopeId="data-v-"+l,{exports:t,options:s}}const _={__name:"SendButtonField",props:{pageUri:String,pageStatus:String},setup(t){const{pageUri:e}=t,r=Vue.ref({icon:"plane",text:"Tester",theme:null,error:null}),n=Vue.ref({icon:"plane",text:"Envoyer",theme:"orange",error:null});async function o(l,a=!1){l.preventDefault();const i=a?r:n;i.value={theme:"blue",text:"En cours…",icon:"loader",error:null};const s={method:"POST",body:JSON.stringify({pageUri:e,isTest:a})};try{const u=await(await fetch("/send-newsletter.json",s)).json();if(u.status==="success")i.value={theme:"green",icon:"check",text:a?"Test envoyé":"Envoi réussi",error:null},a?i.value={icon:"plane",text:"Re-tester",theme:null,error:null}:setTimeout(()=>{location.href=location.href},2e3);else throw new Error(u.message||"Erreur inconnue")}catch(c){i.value={theme:"red",icon:"alert",text:a?"Échec du test":"Erreur",error:c.message}}}return{__sfc:!0,testBtnState:r,sendBtnState:n,send:o}}};var f=function(){var e=this,r=e._self._c,n=e._self._setupProxy;return e.pageStatus==="draft"?r("div",{staticClass:"wrapper"},[r("div",{staticClass:"test-wrapper"},[r("k-button",{staticStyle:{width:"max-content"},attrs:{variant:"filled",help:"test",theme:n.testBtnState.theme,icon:n.testBtnState.icon},on:{click:function(o){return n.send(o,!0)}}},[e._v(e._s(n.testBtnState.text))]),e._m(0),n.testBtnState.error?r("k-box",{staticStyle:{"margin-top":"var(--spacing-1)"},attrs:{theme:"error"}},[e._v(e._s(n.testBtnState.error))]):e._e()],1),r("div",{staticClass:"send-wrapper"},[r("k-button",{attrs:{variant:"filled",theme:n.sendBtnState.theme,icon:n.sendBtnState.icon},on:{click:function(o){return n.send(o)}}},[e._v(e._s(n.sendBtnState.text))]),n.sendBtnState.error?r("k-box",{staticStyle:{"margin-top":"var(--spacing-1)"},attrs:{theme:"error"}},[e._v(e._s(n.sendBtnState.error))]):e._e(),e._m(1)],1)]):e._e()},p=[function(){var t=this,e=t._self._c;return t._self._setupProxy,e("footer",{staticClass:"k-field-footer"},[e("div",{staticClass:"k-help k-field-help k-text"},[e("p",[t._v(" Envoie seulement aux "),e("a",{attrs:{href:"/panel/users",title:"voir la liste"}},[t._v("éditeurs")]),t._v(". ")])])])},function(){var t=this,e=t._self._c;return t._self._setupProxy,e("footer",{staticClass:"k-field-footer"},[e("div",{staticClass:"k-help k-field-help k-text"},[e("strong",[t._v("⚠ Envoie à tous les abonnés.")])])])}],v=d(_,f,p,!1,null,"76f92a36");const m=v.exports;window.panel.plugin("adrienpayet/send-button",{fields:{"send-button":m}})})();
+(function(){"use strict";function d(t,e,r,n,o,l,a,i){var s=typeof t=="function"?t.options:t;return s.render=e,s.staticRenderFns=r,s._compiled=!0,s._scopeId="data-v-"+l,{exports:t,options:s}}const _={__name:"SendButtonField",props:{pageUri:String,pageStatus:String},setup(t){const{pageUri:e}=t,r=Vue.ref({icon:"plane",text:"Tester",theme:null,error:null}),n=Vue.ref({icon:"plane",text:"Envoyer",theme:"orange",error:null});async function o(l,a=!1){l.preventDefault();const i=a?r:n;i.value={theme:"blue",text:"En cours…",icon:"loader",error:null};const s={method:"POST",body:JSON.stringify({pageUri:e,isTest:a})};try{const u=await(await fetch("/send-newsletter.json",s)).json();if(u.status==="success")i.value={theme:"green",icon:"check",text:a?"Test envoyé":"Envoi réussi",error:null},setTimeout(()=>{location.href=location.href},2e3);else throw new Error(u.message||"Erreur inconnue")}catch(c){i.value={theme:"red",icon:"alert",text:a?"Échec du test":"Erreur",error:c.message}}}return{__sfc:!0,testBtnState:r,sendBtnState:n,send:o}}};var f=function(){var e=this,r=e._self._c,n=e._self._setupProxy;return e.pageStatus!=="listed"?r("div",{staticClass:"wrapper"},[r("div",{staticClass:"test-wrapper"},[r("k-button",{staticStyle:{width:"max-content"},attrs:{variant:"filled",help:"test",theme:n.testBtnState.theme,icon:n.testBtnState.icon},on:{click:function(o){return n.send(o,!0)}}},[e._v(e._s(n.testBtnState.text))]),e._m(0),n.testBtnState.error?r("k-box",{staticStyle:{"margin-top":"var(--spacing-1)"},attrs:{theme:"error"}},[e._v(e._s(n.testBtnState.error))]):e._e()],1),r("div",{staticClass:"send-wrapper"},[r("k-button",{attrs:{variant:"filled",theme:n.sendBtnState.theme,icon:n.sendBtnState.icon},on:{click:function(o){return n.send(o)}}},[e._v(e._s(n.sendBtnState.text))]),n.sendBtnState.error?r("k-box",{staticStyle:{"margin-top":"var(--spacing-1)"},attrs:{theme:"error"}},[e._v(e._s(n.sendBtnState.error))]):e._e(),e._m(1)],1)]):e._e()},p=[function(){var t=this,e=t._self._c;return t._self._setupProxy,e("footer",{staticClass:"k-field-footer"},[e("div",{staticClass:"k-help k-field-help k-text"},[e("p",[t._v(" Envoie seulement aux "),e("a",{attrs:{href:"/panel/users",title:"voir la liste"}},[t._v("éditeurs")]),t._v(". ")])])])},function(){var t=this,e=t._self._c;return t._self._setupProxy,e("footer",{staticClass:"k-field-footer"},[e("div",{staticClass:"k-help k-field-help k-text"},[e("strong",[t._v("⚠ Envoie à tous les abonnés.")])])])}],v=d(_,f,p,!1,null,"0e6a95b9");const m=v.exports;window.panel.plugin("adrienpayet/send-button",{fields:{"send-button":m}})})();
diff --git a/site/plugins/send-button/index.php b/site/plugins/send-button/index.php
index b63feb1..5b596b4 100755
--- a/site/plugins/send-button/index.php
+++ b/site/plugins/send-button/index.php
@@ -5,12 +5,16 @@ Kirby::plugin('adrienpayet/send-button', [
'send-button' => [
'computed' => [
'pageUri' => function () {
- return $this->model()->uri();
+ return $this->model()->uri();
},
'pageStatus' => function () {
- return $this->model()->status();
+ return $this->model()->status();
},
- ]
- ]
- ]
+ ],
+ ],
+ ],
+ 'routes' => [
+ require __DIR__ . '/routes/send-newsletter.php',
+ require __DIR__ . '/routes/unsubscribe-newsletter.php',
+ ],
]);
diff --git a/site/config/routes/send-newsletter.php b/site/plugins/send-button/routes/send-newsletter.php
similarity index 51%
rename from site/config/routes/send-newsletter.php
rename to site/plugins/send-button/routes/send-newsletter.php
index 1329e30..17a2a76 100644
--- a/site/config/routes/send-newsletter.php
+++ b/site/plugins/send-button/routes/send-newsletter.php
@@ -2,74 +2,78 @@
return [
'pattern' => '/send-newsletter.json',
- 'method' => 'POST',
- 'action' => function () {
- $jsonRequest = file_get_contents("php://input");
+ 'method' => 'POST',
+ 'action' => function () {
+ $jsonRequest = file_get_contents('php://input');
$data = json_decode($jsonRequest);
if (!$data || !isset($data->pageUri) || !isset($data->isTest)) {
return json_encode([
- 'status' => 'error',
- 'message' => 'Invalid request data. Required fields: pageUri, isTest.'
+ 'status' => 'error',
+ 'message' => 'Invalid request data. Required fields: pageUri, isTest.',
]);
}
$kirby = kirby();
- $emailPage = page('inscription')->childrenAndDrafts()->find($data->pageUri);
+ $emailPage = page('lettre')->childrenAndDrafts()->find($data->pageUri);
if (!$emailPage) {
return json_encode([
- 'status' => 'error',
- 'message' => 'The specified page does not exist.'
+ 'status' => 'error',
+ 'message' => 'The specified page does not exist.',
]);
}
$recipients = $data->isTest
? $kirby->users()->pluck('email', null, true)
- : page('inscription')->subscribers()->toStructure()->pluck('email', true, true);
+ : page('lettre')->subscribers()->toStructure()->pluck('email', true, true);
if (empty($recipients)) {
return json_encode([
- 'status' => 'error',
- 'message' => 'No recipients found.'
+ 'status' => 'error',
+ 'message' => 'No recipients found.',
]);
}
$subject = $data->isTest
- ? "[TEST] - " . $emailPage->title()->value()
+ ? '[TEST] - ' . $emailPage->title()->value()
: $emailPage->title()->value();
$from = new \Kirby\Cms\User([
'email' => 'info@actuel-inactuel.fr',
'name' => 'actuel-inactuel',
]);
-
+
try {
foreach ($recipients as $recipient) {
$kirby->email([
- 'from' => $from,
- 'to' => $recipient,
- 'subject' => $subject,
+ 'from' => $from,
+ 'to' => $recipient,
+ 'subject' => $subject,
'template' => 'newsletter',
- 'data' => [
- 'body' => $emailPage->body()
- ]
+ 'data' => [
+ 'body' => $emailPage->body(),
+ 'url' => (string) $emailPage->url(),
+ 'recipient' => $recipient,
+ ],
]);
}
if (!$data->isTest) {
$emailPage->changeStatus('listed');
+ } else {
+ $emailPage->changeStatus('unlisted');
}
return json_encode([
- 'status' => 'success',
- 'message' => 'Email(s) sent successfully.'
+ 'status' => 'success',
+ 'message' => 'Email(s) sent successfully.',
]);
} catch (Exception $error) {
return json_encode([
- 'status' => 'error',
- 'message' => $error->getMessage() . " file " . $error->getFile() . " line " . $error->getLine()
+ 'status' => 'error',
+ 'message' => $error->getMessage() . ' file ' . $error->getFile() . ' line ' . $error->getLine(),
]);
}
- }
+ },
];
diff --git a/site/plugins/send-button/routes/unsubscribe-newsletter.php b/site/plugins/send-button/routes/unsubscribe-newsletter.php
new file mode 100644
index 0000000..36cf263
--- /dev/null
+++ b/site/plugins/send-button/routes/unsubscribe-newsletter.php
@@ -0,0 +1,39 @@
+ '/deslettre',
+ 'action' => function () {
+ $email = get('email');
+ $page = page('lettre');
+
+ $emailExists = in_array(['email' => $email], $page->subscribers()->yaml());
+
+ if (!$emailExists) {
+ $title = 'Erreur';
+ $body = '' . $email . ' est introuvable dans la base de données. Vous pouvez demander une déslettre manuelle en écrivant à info@actuel-inactuel.fr.
';
+ } else {
+ $subscribers = array_filter(
+ $page->subscribers()->yaml(),
+ fn($subscriber) => $subscriber !== ['email' => $email]
+ );
+
+ $page->update([
+ 'subscribers' => $subscribers,
+ ]);
+
+ $title = $email . ' désinscrit';
+ $body = 'Si la déslettre automatique n\'a pas fonctionné et que vous continuez à recevoir des mails, vous pouvez demander la déslettre manuelle à info@actuel-inactuel.fr.
';
+
+ }
+
+ return new Page([
+ 'slug' => Str::slug('test'),
+ 'template' => 'error',
+ 'status' => 'unlisted',
+ 'content' => [
+ 'title' => $title,
+ 'body' => $body,
+ ],
+ ]);
+ },
+];
diff --git a/site/plugins/send-button/src/components/SendButtonField.vue b/site/plugins/send-button/src/components/SendButtonField.vue
index 40499d7..2aaf7d1 100755
--- a/site/plugins/send-button/src/components/SendButtonField.vue
+++ b/site/plugins/send-button/src/components/SendButtonField.vue
@@ -1,5 +1,5 @@
-
+
{
- location.href = location.href;
- }, 2000);
- } else {
- currentBtnState.value = {
- icon: "plane",
- text: "Re-tester",
- theme: null,
- error: null,
- };
- }
+ setTimeout(() => {
+ location.href = location.href;
+ }, 2000);
} else {
throw new Error(data.message || "Erreur inconnue");
}
diff --git a/site/snippets/cover.php b/site/snippets/cover.php
index 7b0f53e..4e8dab6 100644
--- a/site/snippets/cover.php
+++ b/site/snippets/cover.php
@@ -1,36 +1,35 @@
-
+
- text()): ?>
-
- = $slots->text() ?>
-
+ text()): ?>
+
+ = $slots->text() ?>
+
- is(page('inscription'))): ?>
- -
-
- accueil
-
-
+ is(page('lettre'))): ?>
+ -
+
+ accueil
+
+
- -
-
- s'inscrire
-
-
+ -
+
+ s'inscrire
+
+
-
-
+
à propos
diff --git a/site/snippets/footer.php b/site/snippets/footer.php
index ee5a818..948be72 100644
--- a/site/snippets/footer.php
+++ b/site/snippets/footer.php
@@ -1,11 +1,11 @@