From c0a790bda4ae414070dd568c56df8e0d7709e328 Mon Sep 17 00:00:00 2001 From: grimsi <9295182+grimsi@users.noreply.github.com> Date: Tue, 24 Sep 2024 14:26:21 +0200 Subject: [PATCH] Implemented types for notification templates (currently only MJML is used, but it's now easily expandable) Added default templates --- assets/v2/email/gradient.png | Bin 0 -> 220 bytes assets/v2/email/logo.png | Bin 0 -> 3478 bytes build.gradle.kts | 1 + .../administration/NotificationManagement.tsx | 51 ++++++++++++--- .../de/grimsi/gameyfin/logs/LogService.kt | 8 +-- .../notifications/NotificationService.kt | 20 +++--- .../providers/AbstractNotificationProvider.kt | 2 + .../providers/EmailNotificationProvider.kt | 5 +- .../templates/MessageTemplateEndpoint.kt | 12 ++-- .../templates/MessageTemplateService.kt | 60 ++++++++++++++---- .../notifications/templates/MjmlTemplate.kt | 10 +++ .../notifications/templates/TemplateType.kt | 5 ++ .../{ => templates}/log-config-template.xml | 4 ++ .../notifications/password-reset-request.mjml | 30 +++++++++ .../notifications/user-invitation.mjml | 28 ++++++++ .../templates/notifications/welcome.mjml | 27 ++++++++ 16 files changed, 222 insertions(+), 41 deletions(-) create mode 100644 assets/v2/email/gradient.png create mode 100644 assets/v2/email/logo.png create mode 100644 src/main/kotlin/de/grimsi/gameyfin/notifications/templates/MjmlTemplate.kt create mode 100644 src/main/kotlin/de/grimsi/gameyfin/notifications/templates/TemplateType.kt rename src/main/resources/{ => templates}/log-config-template.xml (84%) create mode 100644 src/main/resources/templates/notifications/password-reset-request.mjml create mode 100644 src/main/resources/templates/notifications/user-invitation.mjml create mode 100644 src/main/resources/templates/notifications/welcome.mjml diff --git a/assets/v2/email/gradient.png b/assets/v2/email/gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..9893d899a5f05a6f36902b78e271537eea31eb1b GIT binary patch literal 220 zcmV<203-j2P)kd_jw;zgS4 z*pS;|T)GnMJ>S>iyQ$oy0M*R-l|u3uU>X0kX<=vULiu%m+uXLbnWKyE`skPC2gQcC zy~#5}eiOCl=+g76=eMgne9z}RgLD7GGtbPjcX&p9Q!(&e&wzPU`9t^9=qw{mk)L;B WttCs#LQmrW0000;mOpZh$(G+v$S2hbV*YsG9RNkBHET9{ zm9Jru6#9gGg3Sb?qX8GdcLVPLC=#uYKQ$N8k!BhsVX=xt^*aH_*#SQnfQZYw!cUp%7gh z901eRwl{r$o`7utuFI!%85f#qsP-E+RtRP*#@lxXK+ zQ{4jq?#|crIRGx9M8l5i)`sniC;R)mnznux(jVpXGrCUTdo0?iS1K3L!UyTYh7BYd zCmH+%gm32iGdlprwKrep!-T4Z(Qz0OU)tWg>c}L5UkmX`KzX0PCD#P3xp8Az zODuKmc^N@-Juo_jI;NdVdY}7;N!dNI9l-27&4OV-&j|Q48r)nGHGto^vnI6Ghv2^s zt)O&2fUjQc`vhLI%zpZQ+;1mp_l6bO0^s_*$^fAsKp-#}sSG9;AcSe3JQ$prT+Dqwa*uQAE2>* zXAL~-do)SG-XWkI(8T9dh;QxeZQC@_`yXnI{XL-7Gq=D({Q%PdQ?o0p_I$1V&f%i& z1h%y7`at&Wk!7H1gVaiB{^)XtD;i&aaU@##rxX2A@)O%W1K>;3oCSjbx(K8)vh7do z{^UzV?gBQLB}|B?!#I6t8=m^09=5jTJ)~ zqyT+%3NF_#Du89c@@(hEVC|_~rTcTqRApx1tvHPFjg$mXJM93(Vh1ZN2ja%S2bcs@ zJHeIAGwrc>nos`=p{0|&z!?C&6as?5rk>S(xlHYS{$n-DdP%~zWd;VD2$n;d-X>r{ z{hk_+Hc6;W7)!)>D_3A@ji_x4JA0mrK?+K&xQq7sCdGJL9SQK>YdTSTq4$21?1W{Rg}6dMQ_F z+JFt_g=IG`HlchHerDJUgfwJH8D}mTiXcLuBj5H}_m=0gFr| z5w8wJms+yTP(Fk@fg}s7jEm^G<|6~&#lFk8dzlPV0IC4=fk+cfrF&N8)S}(fxVgr9 z^eOnVuO$G^%0)AJNdSJaeou{OJ)e~Svw`uwXhLE2+RxD`S*_o+X>EA9Kgf)5C5`@M zC^EFGt849Gt`auB4Gb1OV3Hwh?b*HcTG% z^M0RC{e1}C^TTIbzn3pGj&1|va$Duoq6Sp(kNzW>g*rsHO-<4?^Ejn_;lc?4KRpqj|vK2z}nApF%2 z_a%CBY0;{(gG&Lm5%5E(4)3(G`QMNhIRHE`kg5KgslMu}#⁢ACk|^KtjMQafx3rer?7EOXU; zk{&D)Gn@r*lu%lwSz=6a|F2Lv4gaCRW1=eHm_^#iWR85#C0MG(DEGUpQfmGG~+;jCA z7vu9Z*59$|H!7>9q$Zq608RktCKbS9+kpeij=T7tUlW4p0+f=%NpJqh7XY#VkAgN0 zD%H1t*`aBB8D8ONbn}N4$RLE!m4 z3S<>jWUlIXY?@{!3&;f&Y1pMdhLGCYd-sp?HH{8{TpIPOEC0E(GjTef)979kSK@L2 zH~^d+08S17CkH@DXvM;gtDBm3%yXeHAsaaUqDV@~EObXCqrbo(3BU%^xFo(9J<%ULgB1j41FozW zIsjQhJ1_LXJEw*NzG!?gj8U$H7Z(7+{YU$5dv5&C1+nf09=TFf!s2uzz;ca!(W%G) zAh7piHLra6*w{O(7v8ex3xxeg6yP~J&IV3A{HIJLd++#>tPARUS_wVivbRKP01BT! zvTxb{0>HxhT{nUDdnn;|5DGj=V(09aPi0B~0DkvaU*qEd@bTF0c>uNpm|bEqw*(Fg z3J3%r8akfyw|wUd055S^Ul{M@4|8ZMp!uZ`aRMgDSV?CGGZi}ee}9lhrYh)Ki7^p8+b{Jqu>A0{^l2Ms@uI#;zmG)X7^6Q z@c-WX&#tcIYi=Ci{r&#;pYLn>&c|cB=ZPi-pep}8IV_38vEP&vgPox2SXlknZR$OpBIJ09Zkvdj8q?n>WVxZWgg5A1#`I zl%$|%{|a{`-IM}A{Ox}oY}{2F+xvis)p?Tkeh~q$@YL{97jLNBr?Y45$k7U)?|R`r z@9o)fTk*zvh~MT|!Fu=e3;fOTzt6c2-se8=`TV@=o&nHHGB9G$v;X!!7rxxr0H;N} zE-XK_jN(HxQOXI8ofq@i&ToR?f-G0*;%w=0f4|W0@eXK+wNHahXn?P3@R0M7Of}&pk9?Yo6rrT7LDDI z0>f([]); const [selectedTemplate, setSelectedTemplate] = useState(null); const [templateContent, setTemplateContent] = useState(""); + const [defaultPlaceholders, setDefaultPlaceholders] = useState([]); useEffect(() => { MessageTemplateEndpoint.getAll().then((response: any) => { @@ -53,7 +56,9 @@ function NotificationManagementLayout({getConfig, getConfigs, formik}: any) { async function openModal(template: MessageTemplateDto) { setSelectedTemplate(template); - let templateContent = await MessageTemplateEndpoint.read(template.key); + let templateContent = await MessageTemplateEndpoint.read(template.key, TemplateType.MJML); + let defaultPlaceholders = await MessageTemplateEndpoint.getDefaultPlaceholders(TemplateType.MJML); + setDefaultPlaceholders(defaultPlaceholders ? defaultPlaceholders as string[] : []); if (templateContent === undefined) { toast.error("Can't read template content"); @@ -65,7 +70,7 @@ function NotificationManagementLayout({getConfig, getConfigs, formik}: any) { } async function saveTemplate(template: MessageTemplateDto) { - await MessageTemplateEndpoint.save(template.key, templateContent); + await MessageTemplateEndpoint.save(template.key, TemplateType.MJML, templateContent); } return ( @@ -119,14 +124,40 @@ function NotificationManagementLayout({getConfig, getConfigs, formik}: any) { Edit {selectedTemplate?.name} Template -
-

Available placeholders:

- {selectedTemplate?.availablePlaceholders?.map((placeholder) => - {placeholder} - )} +
+ + + + + + + + + + + +
Required placeholders: +
+ {selectedTemplate?.availablePlaceholders?.map((placeholder) => + {placeholder} + )} +
+
Optional placeholders: +
+ {defaultPlaceholders.map((placeholder) => + {placeholder} + )} +
+
+ Powered by mjml.io +