@antelopejs/dms-mailing 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (550) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +162 -0
  3. package/dist/antelope-modules.d.ts +32 -0
  4. package/dist/antelope-modules.js +36 -0
  5. package/dist/antelope-modules.js.map +1 -0
  6. package/dist/automation/email-event-trigger.d.ts +16 -0
  7. package/dist/automation/email-event-trigger.js +70 -0
  8. package/dist/automation/email-event-trigger.js.map +1 -0
  9. package/dist/automation/index.d.ts +4 -0
  10. package/dist/automation/index.js +39 -0
  11. package/dist/automation/index.js.map +1 -0
  12. package/dist/automation/send-template-action.d.ts +13 -0
  13. package/dist/automation/send-template-action.js +71 -0
  14. package/dist/automation/send-template-action.js.map +1 -0
  15. package/dist/config.d.ts +5 -0
  16. package/dist/config.js +13 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/constants.d.ts +28 -0
  19. package/dist/constants.js +32 -0
  20. package/dist/constants.js.map +1 -0
  21. package/dist/crons/index.d.ts +1 -0
  22. package/dist/crons/index.js +18 -0
  23. package/dist/crons/index.js.map +1 -0
  24. package/dist/crons/retention.d.ts +18 -0
  25. package/dist/crons/retention.js +107 -0
  26. package/dist/crons/retention.js.map +1 -0
  27. package/dist/data/body.d.ts +1 -0
  28. package/dist/data/body.js +18 -0
  29. package/dist/data/body.js.map +1 -0
  30. package/dist/data/index.d.ts +3 -0
  31. package/dist/data/index.js +20 -0
  32. package/dist/data/index.js.map +1 -0
  33. package/dist/data/sends-table.d.ts +28 -0
  34. package/dist/data/sends-table.js +161 -0
  35. package/dist/data/sends-table.js.map +1 -0
  36. package/dist/data/templates-table.d.ts +31 -0
  37. package/dist/data/templates-table.js +173 -0
  38. package/dist/data/templates-table.js.map +1 -0
  39. package/dist/data-types/categories-type.d.ts +35 -0
  40. package/dist/data-types/categories-type.js +37 -0
  41. package/dist/data-types/categories-type.js.map +1 -0
  42. package/dist/data-types/category-type.d.ts +8 -0
  43. package/dist/data-types/category-type.js +43 -0
  44. package/dist/data-types/category-type.js.map +1 -0
  45. package/dist/data-types/index.d.ts +2 -0
  46. package/dist/data-types/index.js +19 -0
  47. package/dist/data-types/index.js.map +1 -0
  48. package/dist/db/index.d.ts +2 -0
  49. package/dist/db/index.js +19 -0
  50. package/dist/db/index.js.map +1 -0
  51. package/dist/db/models/index.d.ts +4 -0
  52. package/dist/db/models/index.js +21 -0
  53. package/dist/db/models/index.js.map +1 -0
  54. package/dist/db/models/send-events.model.d.ts +27 -0
  55. package/dist/db/models/send-events.model.js +35 -0
  56. package/dist/db/models/send-events.model.js.map +1 -0
  57. package/dist/db/models/sends.model.d.ts +32 -0
  58. package/dist/db/models/sends.model.js +115 -0
  59. package/dist/db/models/sends.model.js.map +1 -0
  60. package/dist/db/models/settings.model.d.ts +23 -0
  61. package/dist/db/models/settings.model.js +13 -0
  62. package/dist/db/models/settings.model.js.map +1 -0
  63. package/dist/db/models/templates.model.d.ts +23 -0
  64. package/dist/db/models/templates.model.js +13 -0
  65. package/dist/db/models/templates.model.js.map +1 -0
  66. package/dist/db/tables/index.d.ts +4 -0
  67. package/dist/db/tables/index.js +21 -0
  68. package/dist/db/tables/index.js.map +1 -0
  69. package/dist/db/tables/send-events.table.d.ts +10 -0
  70. package/dist/db/tables/send-events.table.js +44 -0
  71. package/dist/db/tables/send-events.table.js.map +1 -0
  72. package/dist/db/tables/sends.table.d.ts +26 -0
  73. package/dist/db/tables/sends.table.js +113 -0
  74. package/dist/db/tables/sends.table.js.map +1 -0
  75. package/dist/db/tables/settings.table.d.ts +15 -0
  76. package/dist/db/tables/settings.table.js +68 -0
  77. package/dist/db/tables/settings.table.js.map +1 -0
  78. package/dist/db/tables/templates.table.d.ts +18 -0
  79. package/dist/db/tables/templates.table.js +81 -0
  80. package/dist/db/tables/templates.table.js.map +1 -0
  81. package/dist/engine/conditions.d.ts +2 -0
  82. package/dist/engine/conditions.js +20 -0
  83. package/dist/engine/conditions.js.map +1 -0
  84. package/dist/engine/coverage.d.ts +4 -0
  85. package/dist/engine/coverage.js +45 -0
  86. package/dist/engine/coverage.js.map +1 -0
  87. package/dist/engine/fallback-html.d.ts +4 -0
  88. package/dist/engine/fallback-html.js +84 -0
  89. package/dist/engine/fallback-html.js.map +1 -0
  90. package/dist/engine/index.d.ts +7 -0
  91. package/dist/engine/index.js +24 -0
  92. package/dist/engine/index.js.map +1 -0
  93. package/dist/engine/paths.d.ts +3 -0
  94. package/dist/engine/paths.js +32 -0
  95. package/dist/engine/paths.js.map +1 -0
  96. package/dist/engine/resolve.d.ts +4 -0
  97. package/dist/engine/resolve.js +139 -0
  98. package/dist/engine/resolve.js.map +1 -0
  99. package/dist/engine/tokens.d.ts +7 -0
  100. package/dist/engine/tokens.js +29 -0
  101. package/dist/engine/tokens.js.map +1 -0
  102. package/dist/engine/walk.d.ts +3 -0
  103. package/dist/engine/walk.js +14 -0
  104. package/dist/engine/walk.js.map +1 -0
  105. package/dist/hooks/index.d.ts +1 -0
  106. package/dist/hooks/index.js +18 -0
  107. package/dist/hooks/index.js.map +1 -0
  108. package/dist/hooks/tenant-export.d.ts +14 -0
  109. package/dist/hooks/tenant-export.js +84 -0
  110. package/dist/hooks/tenant-export.js.map +1 -0
  111. package/dist/implementations/dms-mailing/index.d.ts +2 -0
  112. package/dist/implementations/dms-mailing/index.js +8 -0
  113. package/dist/implementations/dms-mailing/index.js.map +1 -0
  114. package/dist/index.d.ts +13 -0
  115. package/dist/index.js +95 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/pages/editor.d.ts +9 -0
  118. package/dist/pages/editor.js +30 -0
  119. package/dist/pages/editor.js.map +1 -0
  120. package/dist/pages/index.d.ts +7 -0
  121. package/dist/pages/index.js +24 -0
  122. package/dist/pages/index.js.map +1 -0
  123. package/dist/pages/module.d.ts +1 -0
  124. package/dist/pages/module.js +12 -0
  125. package/dist/pages/module.js.map +1 -0
  126. package/dist/pages/overview.d.ts +14 -0
  127. package/dist/pages/overview.js +92 -0
  128. package/dist/pages/overview.js.map +1 -0
  129. package/dist/pages/sends.d.ts +13 -0
  130. package/dist/pages/sends.js +125 -0
  131. package/dist/pages/sends.js.map +1 -0
  132. package/dist/pages/settings/form.d.ts +1 -0
  133. package/dist/pages/settings/form.js +68 -0
  134. package/dist/pages/settings/form.js.map +1 -0
  135. package/dist/pages/settings/index.d.ts +2 -0
  136. package/dist/pages/settings/index.js +19 -0
  137. package/dist/pages/settings/index.js.map +1 -0
  138. package/dist/pages/settings/page.d.ts +10 -0
  139. package/dist/pages/settings/page.js +35 -0
  140. package/dist/pages/settings/page.js.map +1 -0
  141. package/dist/pages/templates.d.ts +10 -0
  142. package/dist/pages/templates.js +140 -0
  143. package/dist/pages/templates.js.map +1 -0
  144. package/dist/permissions.d.ts +1 -0
  145. package/dist/permissions.js +37 -0
  146. package/dist/permissions.js.map +1 -0
  147. package/dist/quick-actions.d.ts +2 -0
  148. package/dist/quick-actions.js +18 -0
  149. package/dist/quick-actions.js.map +1 -0
  150. package/dist/realtime.d.ts +4 -0
  151. package/dist/realtime.js +44 -0
  152. package/dist/realtime.js.map +1 -0
  153. package/dist/routes/events.d.ts +9 -0
  154. package/dist/routes/events.js +63 -0
  155. package/dist/routes/events.js.map +1 -0
  156. package/dist/routes/index.d.ts +7 -0
  157. package/dist/routes/index.js +24 -0
  158. package/dist/routes/index.js.map +1 -0
  159. package/dist/routes/metrics.d.ts +54 -0
  160. package/dist/routes/metrics.js +235 -0
  161. package/dist/routes/metrics.js.map +1 -0
  162. package/dist/routes/period.d.ts +5 -0
  163. package/dist/routes/period.js +36 -0
  164. package/dist/routes/period.js.map +1 -0
  165. package/dist/routes/provider.d.ts +13 -0
  166. package/dist/routes/provider.js +41 -0
  167. package/dist/routes/provider.js.map +1 -0
  168. package/dist/routes/sends.d.ts +31 -0
  169. package/dist/routes/sends.js +178 -0
  170. package/dist/routes/sends.js.map +1 -0
  171. package/dist/routes/settings.d.ts +14 -0
  172. package/dist/routes/settings.js +72 -0
  173. package/dist/routes/settings.js.map +1 -0
  174. package/dist/routes/templates.d.ts +61 -0
  175. package/dist/routes/templates.js +230 -0
  176. package/dist/routes/templates.js.map +1 -0
  177. package/dist/services/attention.d.ts +23 -0
  178. package/dist/services/attention.js +104 -0
  179. package/dist/services/attention.js.map +1 -0
  180. package/dist/services/categories.d.ts +34 -0
  181. package/dist/services/categories.js +34 -0
  182. package/dist/services/categories.js.map +1 -0
  183. package/dist/services/events.d.ts +10 -0
  184. package/dist/services/events.js +89 -0
  185. package/dist/services/events.js.map +1 -0
  186. package/dist/services/metrics.d.ts +34 -0
  187. package/dist/services/metrics.js +103 -0
  188. package/dist/services/metrics.js.map +1 -0
  189. package/dist/services/notify.d.ts +20 -0
  190. package/dist/services/notify.js +63 -0
  191. package/dist/services/notify.js.map +1 -0
  192. package/dist/services/permissions.d.ts +2 -0
  193. package/dist/services/permissions.js +15 -0
  194. package/dist/services/permissions.js.map +1 -0
  195. package/dist/services/provider.d.ts +6 -0
  196. package/dist/services/provider.js +25 -0
  197. package/dist/services/provider.js.map +1 -0
  198. package/dist/services/render.d.ts +6 -0
  199. package/dist/services/render.js +21 -0
  200. package/dist/services/render.js.map +1 -0
  201. package/dist/services/send.d.ts +49 -0
  202. package/dist/services/send.js +259 -0
  203. package/dist/services/send.js.map +1 -0
  204. package/dist/services/settings.d.ts +4 -0
  205. package/dist/services/settings.js +61 -0
  206. package/dist/services/settings.js.map +1 -0
  207. package/dist/services/status.d.ts +3 -0
  208. package/dist/services/status.js +16 -0
  209. package/dist/services/status.js.map +1 -0
  210. package/dist/services/templates.d.ts +17 -0
  211. package/dist/services/templates.js +92 -0
  212. package/dist/services/templates.js.map +1 -0
  213. package/dist/test/antelope.test.d.ts +2 -0
  214. package/dist/test/antelope.test.js +179 -0
  215. package/dist/test/antelope.test.js.map +1 -0
  216. package/dist/test/helpers/http.d.ts +4 -0
  217. package/dist/test/helpers/http.js +28 -0
  218. package/dist/test/helpers/http.js.map +1 -0
  219. package/dist/test/helpers/owner.d.ts +5 -0
  220. package/dist/test/helpers/owner.js +30 -0
  221. package/dist/test/helpers/owner.js.map +1 -0
  222. package/dist/test/integration/events.test.d.ts +1 -0
  223. package/dist/test/integration/events.test.js +132 -0
  224. package/dist/test/integration/events.test.js.map +1 -0
  225. package/dist/test/integration/retention.test.d.ts +1 -0
  226. package/dist/test/integration/retention.test.js +291 -0
  227. package/dist/test/integration/retention.test.js.map +1 -0
  228. package/dist/test/integration/sends.test.d.ts +1 -0
  229. package/dist/test/integration/sends.test.js +157 -0
  230. package/dist/test/integration/sends.test.js.map +1 -0
  231. package/dist/test/integration/settings.test.d.ts +1 -0
  232. package/dist/test/integration/settings.test.js +45 -0
  233. package/dist/test/integration/settings.test.js.map +1 -0
  234. package/dist/test/integration/setup.test.d.ts +1 -0
  235. package/dist/test/integration/setup.test.js +32 -0
  236. package/dist/test/integration/setup.test.js.map +1 -0
  237. package/dist/test/integration/templates.test.d.ts +1 -0
  238. package/dist/test/integration/templates.test.js +167 -0
  239. package/dist/test/integration/templates.test.js.map +1 -0
  240. package/dist/test/integration/tenant-export.test.d.ts +1 -0
  241. package/dist/test/integration/tenant-export.test.js +85 -0
  242. package/dist/test/integration/tenant-export.test.js.map +1 -0
  243. package/dist/test/unit/attention.test.d.ts +1 -0
  244. package/dist/test/unit/attention.test.js +109 -0
  245. package/dist/test/unit/attention.test.js.map +1 -0
  246. package/dist/test/unit/automation.test.d.ts +1 -0
  247. package/dist/test/unit/automation.test.js +104 -0
  248. package/dist/test/unit/automation.test.js.map +1 -0
  249. package/dist/test/unit/categories.test.d.ts +1 -0
  250. package/dist/test/unit/categories.test.js +38 -0
  251. package/dist/test/unit/categories.test.js.map +1 -0
  252. package/dist/test/unit/engine/conditions.test.d.ts +1 -0
  253. package/dist/test/unit/engine/conditions.test.js +23 -0
  254. package/dist/test/unit/engine/conditions.test.js.map +1 -0
  255. package/dist/test/unit/engine/coverage.test.d.ts +1 -0
  256. package/dist/test/unit/engine/coverage.test.js +106 -0
  257. package/dist/test/unit/engine/coverage.test.js.map +1 -0
  258. package/dist/test/unit/engine/fallback-html.test.d.ts +1 -0
  259. package/dist/test/unit/engine/fallback-html.test.js +78 -0
  260. package/dist/test/unit/engine/fallback-html.test.js.map +1 -0
  261. package/dist/test/unit/engine/paths.test.d.ts +1 -0
  262. package/dist/test/unit/engine/paths.test.js +33 -0
  263. package/dist/test/unit/engine/paths.test.js.map +1 -0
  264. package/dist/test/unit/engine/resolve.test.d.ts +1 -0
  265. package/dist/test/unit/engine/resolve.test.js +157 -0
  266. package/dist/test/unit/engine/resolve.test.js.map +1 -0
  267. package/dist/test/unit/engine/tokens.test.d.ts +1 -0
  268. package/dist/test/unit/engine/tokens.test.js +26 -0
  269. package/dist/test/unit/engine/tokens.test.js.map +1 -0
  270. package/dist/test/unit/events.test.d.ts +1 -0
  271. package/dist/test/unit/events.test.js +13 -0
  272. package/dist/test/unit/events.test.js.map +1 -0
  273. package/dist/test/unit/metrics.test.d.ts +1 -0
  274. package/dist/test/unit/metrics.test.js +108 -0
  275. package/dist/test/unit/metrics.test.js.map +1 -0
  276. package/dist/test/unit/notify.test.d.ts +1 -0
  277. package/dist/test/unit/notify.test.js +49 -0
  278. package/dist/test/unit/notify.test.js.map +1 -0
  279. package/dist/test/unit/period.test.d.ts +1 -0
  280. package/dist/test/unit/period.test.js +44 -0
  281. package/dist/test/unit/period.test.js.map +1 -0
  282. package/dist/test/unit/provider.test.d.ts +1 -0
  283. package/dist/test/unit/provider.test.js +47 -0
  284. package/dist/test/unit/provider.test.js.map +1 -0
  285. package/dist/test/unit/realtime.test.d.ts +1 -0
  286. package/dist/test/unit/realtime.test.js +13 -0
  287. package/dist/test/unit/realtime.test.js.map +1 -0
  288. package/dist/test/unit/render.test.d.ts +1 -0
  289. package/dist/test/unit/render.test.js +23 -0
  290. package/dist/test/unit/render.test.js.map +1 -0
  291. package/dist/test/unit/retention.test.d.ts +1 -0
  292. package/dist/test/unit/retention.test.js +66 -0
  293. package/dist/test/unit/retention.test.js.map +1 -0
  294. package/dist/test/unit/send-batch.test.d.ts +1 -0
  295. package/dist/test/unit/send-batch.test.js +46 -0
  296. package/dist/test/unit/send-batch.test.js.map +1 -0
  297. package/dist/test/unit/send.test.d.ts +1 -0
  298. package/dist/test/unit/send.test.js +120 -0
  299. package/dist/test/unit/send.test.js.map +1 -0
  300. package/dist/test/unit/smoke.test.d.ts +1 -0
  301. package/dist/test/unit/smoke.test.js +10 -0
  302. package/dist/test/unit/smoke.test.js.map +1 -0
  303. package/dist/test/unit/status.test.d.ts +1 -0
  304. package/dist/test/unit/status.test.js +16 -0
  305. package/dist/test/unit/status.test.js.map +1 -0
  306. package/dist/test/unit/templates.test.d.ts +1 -0
  307. package/dist/test/unit/templates.test.js +48 -0
  308. package/dist/test/unit/templates.test.js.map +1 -0
  309. package/dist/test/unit/tenant-export.test.d.ts +1 -0
  310. package/dist/test/unit/tenant-export.test.js +59 -0
  311. package/dist/test/unit/tenant-export.test.js.map +1 -0
  312. package/dist/test/unit/webhook-secret.test.d.ts +1 -0
  313. package/dist/test/unit/webhook-secret.test.js +42 -0
  314. package/dist/test/unit/webhook-secret.test.js.map +1 -0
  315. package/dist/types/blocks.d.ts +2 -0
  316. package/dist/types/blocks.js +3 -0
  317. package/dist/types/blocks.js.map +1 -0
  318. package/dist/types/index.d.ts +4 -0
  319. package/dist/types/index.js +21 -0
  320. package/dist/types/index.js.map +1 -0
  321. package/dist/types/resolved.d.ts +68 -0
  322. package/dist/types/resolved.js +3 -0
  323. package/dist/types/resolved.js.map +1 -0
  324. package/dist/types/sends.d.ts +14 -0
  325. package/dist/types/sends.js +19 -0
  326. package/dist/types/sends.js.map +1 -0
  327. package/dist/types/settings.d.ts +16 -0
  328. package/dist/types/settings.js +11 -0
  329. package/dist/types/settings.js.map +1 -0
  330. package/dist/validation/settings.schema.d.ts +63 -0
  331. package/dist/validation/settings.schema.js +29 -0
  332. package/dist/validation/settings.schema.js.map +1 -0
  333. package/dist/validation/templates.schema.d.ts +248 -0
  334. package/dist/validation/templates.schema.js +126 -0
  335. package/dist/validation/templates.schema.js.map +1 -0
  336. package/frontend-vue/.editorconfig +12 -0
  337. package/frontend-vue/.prettierrc +11 -0
  338. package/frontend-vue/app/components/AttentionCard.vue +78 -0
  339. package/frontend-vue/app/components/CategoriesInput.vue +126 -0
  340. package/frontend-vue/app/components/CategoryInput.vue +67 -0
  341. package/frontend-vue/app/components/Editor.vue +63 -0
  342. package/frontend-vue/app/components/FunnelCard.vue +66 -0
  343. package/frontend-vue/app/components/HtmlPreviewModal.vue +20 -0
  344. package/frontend-vue/app/components/NewTemplateModal.vue +158 -0
  345. package/frontend-vue/app/components/ProviderChip.vue +39 -0
  346. package/frontend-vue/app/components/SendDrawer.vue +298 -0
  347. package/frontend-vue/app/components/TemplateCard.vue +127 -0
  348. package/frontend-vue/app/components/TemplateDrawer.vue +394 -0
  349. package/frontend-vue/app/components/TemplateGallery.vue +112 -0
  350. package/frontend-vue/app/components/TemplatePreviewFrame.vue +103 -0
  351. package/frontend-vue/app/components/TestSendModal.vue +162 -0
  352. package/frontend-vue/app/components/TokenText.vue +26 -0
  353. package/frontend-vue/app/components/blocks/Button.vue +19 -0
  354. package/frontend-vue/app/components/blocks/Code.vue +17 -0
  355. package/frontend-vue/app/components/blocks/Divider.vue +3 -0
  356. package/frontend-vue/app/components/blocks/Footer.vue +22 -0
  357. package/frontend-vue/app/components/blocks/Heading.vue +18 -0
  358. package/frontend-vue/app/components/blocks/Hero.vue +32 -0
  359. package/frontend-vue/app/components/blocks/List.vue +33 -0
  360. package/frontend-vue/app/components/blocks/Paragraph.vue +18 -0
  361. package/frontend-vue/app/components/blocks/Total.vue +18 -0
  362. package/frontend-vue/app/components/editor/EditorBlock.vue +121 -0
  363. package/frontend-vue/app/components/editor/EditorBlockList.vue +44 -0
  364. package/frontend-vue/app/components/editor/EditorBlockSettings.vue +186 -0
  365. package/frontend-vue/app/components/editor/EditorCanvas.vue +91 -0
  366. package/frontend-vue/app/components/editor/EditorConditionFields.vue +88 -0
  367. package/frontend-vue/app/components/editor/EditorDataPanel.vue +128 -0
  368. package/frontend-vue/app/components/editor/EditorDraftBar.vue +35 -0
  369. package/frontend-vue/app/components/editor/EditorIfBlock.vue +120 -0
  370. package/frontend-vue/app/components/editor/EditorMissingLocale.vue +62 -0
  371. package/frontend-vue/app/components/editor/EditorPalette.vue +62 -0
  372. package/frontend-vue/app/components/editor/EditorRail.vue +58 -0
  373. package/frontend-vue/app/components/editor/EditorSubjectSettings.vue +37 -0
  374. package/frontend-vue/app/components/editor/EditorTemplateSettings.vue +87 -0
  375. package/frontend-vue/app/components/editor/EditorTestSendModal.vue +66 -0
  376. package/frontend-vue/app/components/editor/EditorToolbar.vue +155 -0
  377. package/frontend-vue/app/components/editor/EditorVariables.vue +163 -0
  378. package/frontend-vue/app/components/editor/EditorWorkspace.vue +189 -0
  379. package/frontend-vue/app/composables/useEditorContext.ts +44 -0
  380. package/frontend-vue/app/composables/useMailingApi.ts +197 -0
  381. package/frontend-vue/app/composables/useMailingPeriodData.ts +39 -0
  382. package/frontend-vue/app/composables/useTemplateDrawer.ts +90 -0
  383. package/frontend-vue/app/composables/useTemplateEditor.ts +228 -0
  384. package/frontend-vue/app/emails/EmailMailingTemplate.vue +24 -0
  385. package/frontend-vue/app/emails/components/MailingBlocks.vue +117 -0
  386. package/frontend-vue/app/plugins/template-gallery-display.client.ts +14 -0
  387. package/frontend-vue/app/types/component.ts +29 -0
  388. package/frontend-vue/app/types/mailing.ts +365 -0
  389. package/frontend-vue/app/utils/blocks/components.ts +14 -0
  390. package/frontend-vue/app/utils/blocks/dnd.ts +15 -0
  391. package/frontend-vue/app/utils/blocks/factory.ts +100 -0
  392. package/frontend-vue/app/utils/blocks/fields.ts +58 -0
  393. package/frontend-vue/app/utils/blocks/index.ts +5 -0
  394. package/frontend-vue/app/utils/blocks/tree.ts +74 -0
  395. package/frontend-vue/app/utils/categories.ts +54 -0
  396. package/frontend-vue/app/utils/clone.ts +3 -0
  397. package/frontend-vue/app/utils/conditions.ts +50 -0
  398. package/frontend-vue/app/utils/editor-route.ts +18 -0
  399. package/frontend-vue/app/utils/gallery.ts +41 -0
  400. package/frontend-vue/app/utils/locales.ts +41 -0
  401. package/frontend-vue/app/utils/paths.ts +84 -0
  402. package/frontend-vue/app/utils/period.ts +23 -0
  403. package/frontend-vue/app/utils/testData.ts +10 -0
  404. package/frontend-vue/app/utils/timeline.ts +68 -0
  405. package/frontend-vue/app/utils/tokens.ts +24 -0
  406. package/frontend-vue/app/utils/variables.ts +48 -0
  407. package/frontend-vue/dms.email.ts +9 -0
  408. package/frontend-vue/dms.frontend.ts +29 -0
  409. package/frontend-vue/eslint.config.mjs +13 -0
  410. package/frontend-vue/i18n/locales/mailing-en-GB.json +397 -0
  411. package/frontend-vue/i18n/locales/mailing-fr-FR.json +397 -0
  412. package/frontend-vue/package.json +32 -0
  413. package/frontend-vue/pnpm-lock.yaml +6446 -0
  414. package/frontend-vue/pnpm-workspace.yaml +2 -0
  415. package/frontend-vue/tests/block-components.test.ts +14 -0
  416. package/frontend-vue/tests/block-fields.test.ts +23 -0
  417. package/frontend-vue/tests/blocks-factory.test.ts +28 -0
  418. package/frontend-vue/tests/blocks-tree.test.ts +49 -0
  419. package/frontend-vue/tests/categories.test.ts +64 -0
  420. package/frontend-vue/tests/conditions.test.ts +36 -0
  421. package/frontend-vue/tests/dnd.test.ts +11 -0
  422. package/frontend-vue/tests/editor-block-list.test.ts +54 -0
  423. package/frontend-vue/tests/editor-route.test.ts +23 -0
  424. package/frontend-vue/tests/email-render-cases.json +77 -0
  425. package/frontend-vue/tests/gallery.test.ts +39 -0
  426. package/frontend-vue/tests/i18n-editor.test.ts +21 -0
  427. package/frontend-vue/tests/i18n.test.ts +83 -0
  428. package/frontend-vue/tests/locales.test.ts +38 -0
  429. package/frontend-vue/tests/mailing-api.test.ts +10 -0
  430. package/frontend-vue/tests/paths.test.ts +128 -0
  431. package/frontend-vue/tests/period.test.ts +13 -0
  432. package/frontend-vue/tests/smoke.test.ts +8 -0
  433. package/frontend-vue/tests/template-editor.test.ts +65 -0
  434. package/frontend-vue/tests/test-data.test.ts +15 -0
  435. package/frontend-vue/tests/timeline.test.ts +29 -0
  436. package/frontend-vue/tests/tokens.test.ts +12 -0
  437. package/frontend-vue/tests/variables.test.ts +46 -0
  438. package/frontend-vue/vitest.config.ts +10 -0
  439. package/package.json +94 -0
  440. package/src/antelope-modules.ts +48 -0
  441. package/src/automation/email-event-trigger.ts +112 -0
  442. package/src/automation/index.ts +33 -0
  443. package/src/automation/send-template-action.ts +100 -0
  444. package/src/config.ts +15 -0
  445. package/src/constants.ts +42 -0
  446. package/src/crons/index.ts +1 -0
  447. package/src/crons/retention.ts +126 -0
  448. package/src/data/body.ts +14 -0
  449. package/src/data/index.ts +3 -0
  450. package/src/data/sends-table.ts +154 -0
  451. package/src/data/templates-table.ts +202 -0
  452. package/src/data-types/categories-type.ts +29 -0
  453. package/src/data-types/category-type.ts +44 -0
  454. package/src/data-types/index.ts +2 -0
  455. package/src/db/index.ts +2 -0
  456. package/src/db/models/index.ts +4 -0
  457. package/src/db/models/send-events.model.ts +46 -0
  458. package/src/db/models/sends.model.ts +147 -0
  459. package/src/db/models/settings.model.ts +12 -0
  460. package/src/db/models/templates.model.ts +12 -0
  461. package/src/db/tables/index.ts +4 -0
  462. package/src/db/tables/send-events.table.ts +31 -0
  463. package/src/db/tables/sends.table.ts +85 -0
  464. package/src/db/tables/settings.table.ts +49 -0
  465. package/src/db/tables/templates.table.ts +70 -0
  466. package/src/engine/conditions.ts +30 -0
  467. package/src/engine/coverage.ts +67 -0
  468. package/src/engine/fallback-html.ts +116 -0
  469. package/src/engine/index.ts +7 -0
  470. package/src/engine/paths.ts +33 -0
  471. package/src/engine/resolve.ts +178 -0
  472. package/src/engine/tokens.ts +35 -0
  473. package/src/engine/walk.ts +18 -0
  474. package/src/hooks/index.ts +1 -0
  475. package/src/hooks/tenant-export.ts +127 -0
  476. package/src/implementations/dms-mailing/index.ts +2 -0
  477. package/src/index.ts +62 -0
  478. package/src/pages/editor.ts +23 -0
  479. package/src/pages/index.ts +11 -0
  480. package/src/pages/module.ts +9 -0
  481. package/src/pages/overview.ts +175 -0
  482. package/src/pages/sends.ts +174 -0
  483. package/src/pages/settings/form.ts +67 -0
  484. package/src/pages/settings/index.ts +2 -0
  485. package/src/pages/settings/page.ts +34 -0
  486. package/src/pages/templates.ts +141 -0
  487. package/src/permissions.ts +44 -0
  488. package/src/quick-actions.ts +20 -0
  489. package/src/realtime.ts +53 -0
  490. package/src/routes/events.ts +57 -0
  491. package/src/routes/index.ts +7 -0
  492. package/src/routes/metrics.ts +243 -0
  493. package/src/routes/period.ts +46 -0
  494. package/src/routes/provider.ts +31 -0
  495. package/src/routes/sends.ts +215 -0
  496. package/src/routes/settings.ts +66 -0
  497. package/src/routes/templates.ts +256 -0
  498. package/src/services/attention.ts +151 -0
  499. package/src/services/categories.ts +43 -0
  500. package/src/services/events.ts +121 -0
  501. package/src/services/metrics.ts +175 -0
  502. package/src/services/notify.ts +90 -0
  503. package/src/services/permissions.ts +42 -0
  504. package/src/services/provider.ts +46 -0
  505. package/src/services/render.ts +33 -0
  506. package/src/services/send.ts +409 -0
  507. package/src/services/settings.ts +74 -0
  508. package/src/services/status.ts +16 -0
  509. package/src/services/templates.ts +157 -0
  510. package/src/test/antelope.test.ts +188 -0
  511. package/src/test/helpers/http.ts +23 -0
  512. package/src/test/helpers/owner.ts +37 -0
  513. package/src/test/integration/events.test.ts +136 -0
  514. package/src/test/integration/retention.test.ts +363 -0
  515. package/src/test/integration/sends.test.ts +200 -0
  516. package/src/test/integration/settings.test.ts +50 -0
  517. package/src/test/integration/setup.test.ts +35 -0
  518. package/src/test/integration/templates.test.ts +229 -0
  519. package/src/test/integration/tenant-export.test.ts +125 -0
  520. package/src/test/unit/attention.test.ts +129 -0
  521. package/src/test/unit/automation.test.ts +130 -0
  522. package/src/test/unit/categories.test.ts +51 -0
  523. package/src/test/unit/engine/conditions.test.ts +35 -0
  524. package/src/test/unit/engine/coverage.test.ts +118 -0
  525. package/src/test/unit/engine/fallback-html.test.ts +86 -0
  526. package/src/test/unit/engine/paths.test.ts +39 -0
  527. package/src/test/unit/engine/resolve.test.ts +176 -0
  528. package/src/test/unit/engine/tokens.test.ts +26 -0
  529. package/src/test/unit/events.test.ts +19 -0
  530. package/src/test/unit/metrics.test.ts +170 -0
  531. package/src/test/unit/notify.test.ts +71 -0
  532. package/src/test/unit/period.test.ts +64 -0
  533. package/src/test/unit/provider.test.ts +57 -0
  534. package/src/test/unit/realtime.test.ts +11 -0
  535. package/src/test/unit/render.test.ts +23 -0
  536. package/src/test/unit/retention.test.ts +91 -0
  537. package/src/test/unit/send-batch.test.ts +72 -0
  538. package/src/test/unit/send.test.ts +161 -0
  539. package/src/test/unit/smoke.test.ts +8 -0
  540. package/src/test/unit/status.test.ts +14 -0
  541. package/src/test/unit/templates.test.ts +52 -0
  542. package/src/test/unit/tenant-export.test.ts +88 -0
  543. package/src/test/unit/webhook-secret.test.ts +50 -0
  544. package/src/types/blocks.ts +31 -0
  545. package/src/types/index.ts +4 -0
  546. package/src/types/resolved.ts +89 -0
  547. package/src/types/sends.ts +44 -0
  548. package/src/types/settings.ts +24 -0
  549. package/src/validation/settings.schema.ts +33 -0
  550. package/src/validation/templates.schema.ts +145 -0
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.duplicateSchema = exports.testSendSchema = exports.realSendSchema = exports.previewSchema = exports.testDataSchema = exports.variablesSchema = exports.variableSchema = exports.templateContentSchema = exports.localeContentSchema = exports.blockSchema = exports.conditionSchema = exports.createTemplateSchema = exports.slugSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const constants_1 = require("../constants");
6
+ const MIN_HEADING_SIZE = 12;
7
+ const MAX_HEADING_SIZE = 48;
8
+ const MAX_TEST_RECIPIENT_COUNT = 5;
9
+ exports.slugSchema = zod_1.z
10
+ .string()
11
+ .trim()
12
+ .min(1)
13
+ .max(constants_1.MAX_SLUG_LENGTH)
14
+ .regex(constants_1.SLUG_PATTERN);
15
+ exports.createTemplateSchema = zod_1.z.object({
16
+ slug: exports.slugSchema,
17
+ name: zod_1.z.string().trim().min(1).max(constants_1.MAX_NAME_LENGTH),
18
+ category: zod_1.z.string().optional(),
19
+ sourceTemplateId: zod_1.z.string().optional(),
20
+ });
21
+ exports.conditionSchema = zod_1.z.object({
22
+ path: zod_1.z.string().min(1),
23
+ operator: zod_1.z.enum(["truthy", "falsy", "eq", "ne", "gt", "lt"]),
24
+ value: zod_1.z.string(),
25
+ });
26
+ const alignSchema = zod_1.z.enum(["left", "center", "right"]);
27
+ const base = { id: zod_1.z.string().min(1), visibleIf: exports.conditionSchema.nullable() };
28
+ exports.blockSchema = zod_1.z.lazy(() => zod_1.z.discriminatedUnion("type", [
29
+ zod_1.z.object({
30
+ ...base,
31
+ type: zod_1.z.literal("hero"),
32
+ imageUrl: zod_1.z.string(),
33
+ alt: zod_1.z.string(),
34
+ }),
35
+ zod_1.z.object({
36
+ ...base,
37
+ type: zod_1.z.literal("heading"),
38
+ text: zod_1.z.string(),
39
+ align: alignSchema,
40
+ size: zod_1.z.number().int().min(MIN_HEADING_SIZE).max(MAX_HEADING_SIZE),
41
+ }),
42
+ zod_1.z.object({
43
+ ...base,
44
+ type: zod_1.z.literal("paragraph"),
45
+ text: zod_1.z.string(),
46
+ align: alignSchema,
47
+ }),
48
+ zod_1.z.object({ ...base, type: zod_1.z.literal("code"), text: zod_1.z.string() }),
49
+ zod_1.z.object({
50
+ ...base,
51
+ type: zod_1.z.literal("list"),
52
+ source: zod_1.z.string().min(1),
53
+ labelPath: zod_1.z.string().min(1),
54
+ valuePath: zod_1.z.string().min(1),
55
+ }),
56
+ zod_1.z.object({
57
+ ...base,
58
+ type: zod_1.z.literal("total"),
59
+ label: zod_1.z.string(),
60
+ value: zod_1.z.string(),
61
+ }),
62
+ zod_1.z.object({
63
+ ...base,
64
+ type: zod_1.z.literal("button"),
65
+ text: zod_1.z.string(),
66
+ href: zod_1.z.string(),
67
+ align: alignSchema,
68
+ }),
69
+ zod_1.z.object({
70
+ ...base,
71
+ type: zod_1.z.literal("if"),
72
+ condition: exports.conditionSchema,
73
+ children: zod_1.z.array(exports.blockSchema),
74
+ elseChildren: zod_1.z.array(exports.blockSchema).nullable(),
75
+ }),
76
+ zod_1.z.object({ ...base, type: zod_1.z.literal("divider") }),
77
+ zod_1.z.object({
78
+ ...base,
79
+ type: zod_1.z.literal("footer"),
80
+ text: zod_1.z.string(),
81
+ unsubscribeLabel: zod_1.z.string(),
82
+ preferencesLabel: zod_1.z.string(),
83
+ }),
84
+ ]));
85
+ exports.localeContentSchema = zod_1.z.object({
86
+ subject: zod_1.z.string(),
87
+ preheader: zod_1.z.string(),
88
+ blocks: zod_1.z.array(exports.blockSchema),
89
+ });
90
+ exports.templateContentSchema = zod_1.z.object({
91
+ locales: zod_1.z.record(exports.localeContentSchema),
92
+ });
93
+ exports.variableSchema = zod_1.z.object({
94
+ path: zod_1.z.string().min(1),
95
+ type: zod_1.z.enum([
96
+ "string",
97
+ "text",
98
+ "number",
99
+ "money",
100
+ "date",
101
+ "url",
102
+ "boolean",
103
+ "array",
104
+ ]),
105
+ required: zod_1.z.boolean(),
106
+ });
107
+ exports.variablesSchema = zod_1.z.object({ variables: zod_1.z.array(exports.variableSchema) });
108
+ exports.testDataSchema = zod_1.z.object({ data: zod_1.z.record(zod_1.z.unknown()) });
109
+ exports.previewSchema = zod_1.z.object({
110
+ locale: zod_1.z.string().min(1).optional(),
111
+ content: exports.templateContentSchema.optional(),
112
+ data: zod_1.z.record(zod_1.z.unknown()).optional(),
113
+ });
114
+ exports.realSendSchema = zod_1.z.object({
115
+ to: zod_1.z.array(zod_1.z.string().email()).min(1).max(MAX_TEST_RECIPIENT_COUNT),
116
+ locale: zod_1.z.string().min(1).optional(),
117
+ data: zod_1.z.record(zod_1.z.unknown()).optional(),
118
+ });
119
+ exports.testSendSchema = exports.previewSchema.extend({
120
+ to: zod_1.z.array(zod_1.z.string().email()).min(1).max(MAX_TEST_RECIPIENT_COUNT),
121
+ });
122
+ exports.duplicateSchema = zod_1.z.object({
123
+ slug: exports.slugSchema,
124
+ name: zod_1.z.string().trim().min(1).max(constants_1.MAX_NAME_LENGTH),
125
+ });
126
+ //# sourceMappingURL=templates.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.schema.js","sourceRoot":"","sources":["../../src/validation/templates.schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_size = 2
5
+ indent_style = space
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
10
+
11
+ [*.md]
12
+ trim_trailing_whitespace = false
@@ -0,0 +1,11 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "trailingComma": "all",
5
+ "endOfLine": "auto",
6
+ "plugins": ["prettier-plugin-tailwindcss"],
7
+ "useTabs": true,
8
+
9
+ "htmlWhitespaceSensitivity": "ignore",
10
+ "tailwindStylesheet": "~/assets/css/main.css"
11
+ }
@@ -0,0 +1,78 @@
1
+ <script setup lang="ts">
2
+ import type { MailingComponentProps } from '../types/component'
3
+ import type { AttentionResponse } from '../composables/useMailingApi'
4
+ import type { AttentionItem, AttentionTone } from '../types/mailing'
5
+
6
+ const OVERVIEW_PERIOD_SCOPE = 'mailing-overview'
7
+
8
+ const TONE_CLASSES: Record<AttentionTone, string> = {
9
+ warning: 'bg-warning/10 text-warning',
10
+ error: 'bg-error/10 text-error',
11
+ neutral: 'bg-elevated text-muted',
12
+ }
13
+
14
+ defineProps<MailingComponentProps>()
15
+
16
+ const api = useMailingApi()
17
+ const { t } = useI18n()
18
+ const { processI18n } = useTranslation()
19
+
20
+ const { data, loading } = useMailingPeriodData<AttentionResponse>(
21
+ OVERVIEW_PERIOD_SCOPE,
22
+ (query) => api.attention(query),
23
+ )
24
+
25
+ const items = computed(() => data.value?.items ?? [])
26
+
27
+ function open(item: AttentionItem): void {
28
+ if (!item.to) return
29
+ navigateDms(item.to)
30
+ }
31
+ </script>
32
+
33
+ <template>
34
+ <DmsCard :padded="false" class="p-5 sm:p-6">
35
+ <h2 class="text-highlighted mb-3 text-sm font-semibold">
36
+ {{ t('dms_mailing.overview.attention_title') }}
37
+ </h2>
38
+
39
+ <USkeleton v-if="loading && !items.length" class="h-24 w-full" />
40
+
41
+ <p v-else-if="!items.length" class="text-muted text-[13px]">
42
+ {{ t('dms_mailing.overview.attention_empty') }}
43
+ </p>
44
+
45
+ <div v-else class="flex flex-col gap-1">
46
+ <UButton
47
+ v-for="item in items"
48
+ :key="item.id"
49
+ color="neutral"
50
+ variant="ghost"
51
+ class="items-start gap-3 text-left"
52
+ :disabled="!item.to"
53
+ @click="open(item)"
54
+ >
55
+ <span
56
+ :class="TONE_CLASSES[item.tone]"
57
+ class="grid size-[30px] shrink-0 place-items-center rounded-lg"
58
+ >
59
+ <UIcon :name="item.icon" class="size-4" aria-hidden="true" />
60
+ </span>
61
+ <span class="min-w-0 flex-1">
62
+ <span class="text-toned block text-[13px] font-medium">
63
+ {{ processI18n(item.title, item.params) }}
64
+ </span>
65
+ <span class="text-dimmed mt-0.5 block text-[11.5px]">
66
+ {{ processI18n(item.description, item.params) }}
67
+ </span>
68
+ </span>
69
+ <UIcon
70
+ v-if="item.to"
71
+ name="i-ph-caret-right"
72
+ class="text-dimmed size-4 shrink-0"
73
+ aria-hidden="true"
74
+ />
75
+ </UButton>
76
+ </div>
77
+ </DmsCard>
78
+ </template>
@@ -0,0 +1,126 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ parseCategories,
4
+ serializeCategories,
5
+ slugifyId,
6
+ } from '../utils/categories'
7
+ import type { TemplateCategory } from '../types/mailing'
8
+
9
+ interface CategoriesInputProps {
10
+ modelValue?: TemplateCategory[] | string | null
11
+ initialValue?: TemplateCategory[] | string | null
12
+ disabled?: boolean
13
+ }
14
+
15
+ const DEFAULT_ICON = 'i-ph-folder'
16
+
17
+ const props = withDefaults(defineProps<CategoriesInputProps>(), {
18
+ modelValue: null,
19
+ initialValue: null,
20
+ disabled: false,
21
+ })
22
+
23
+ const emit = defineEmits<{ 'update:modelValue': [value: string] }>()
24
+
25
+ const { t } = useI18n()
26
+
27
+ const categories = ref<TemplateCategory[]>(
28
+ parseCategories(props.modelValue ?? props.initialValue).map((entry) => ({
29
+ ...entry,
30
+ })),
31
+ )
32
+
33
+ function onEdit(): void {
34
+ emit('update:modelValue', serializeCategories(categories.value))
35
+ }
36
+
37
+ // The id is stored on every template, so it is derived once at creation and
38
+ // never follows a later rename.
39
+ function addCategory(): void {
40
+ categories.value.push({ id: '', label: '', icon: DEFAULT_ICON })
41
+ onEdit()
42
+ }
43
+
44
+ function onLabelInput(index: number): void {
45
+ const entry = categories.value[index]
46
+ if (entry && !entry.id) entry.id = slugifyId(entry.label)
47
+ onEdit()
48
+ }
49
+
50
+ function removeCategory(index: number): void {
51
+ categories.value.splice(index, 1)
52
+ onEdit()
53
+ }
54
+
55
+ watch(
56
+ () => props.modelValue,
57
+ (value) => {
58
+ const parsed = parseCategories(value)
59
+ if (serializeCategories(parsed) !== serializeCategories(categories.value)) {
60
+ categories.value = parsed.map((entry) => ({ ...entry }))
61
+ }
62
+ },
63
+ )
64
+ </script>
65
+
66
+ <template>
67
+ <div class="flex flex-col gap-2">
68
+ <div
69
+ v-for="(category, index) in categories"
70
+ :key="index"
71
+ class="flex items-center gap-2"
72
+ >
73
+ <UIcon
74
+ :name="category.icon || DEFAULT_ICON"
75
+ class="text-dimmed size-4 shrink-0"
76
+ aria-hidden="true"
77
+ />
78
+ <UInput
79
+ v-model="category.label"
80
+ :placeholder="t('dms_mailing.settings.categories.label')"
81
+ :disabled="disabled"
82
+ size="sm"
83
+ class="flex-1"
84
+ @update:model-value="onLabelInput(index)"
85
+ />
86
+ <UInput
87
+ v-model="category.icon"
88
+ :placeholder="DEFAULT_ICON"
89
+ :disabled="disabled"
90
+ size="sm"
91
+ class="w-40 font-mono"
92
+ @update:model-value="onEdit"
93
+ />
94
+ <code class="text-dimmed w-28 shrink-0 truncate font-mono text-[11px]">
95
+ {{ category.id }}
96
+ </code>
97
+ <UButton
98
+ v-if="!disabled"
99
+ icon="i-ph-x"
100
+ color="neutral"
101
+ variant="ghost"
102
+ size="xs"
103
+ :title="t('dms_mailing.settings.categories.remove')"
104
+ @click="removeCategory(index)"
105
+ />
106
+ </div>
107
+
108
+ <p v-if="!categories.length" class="text-muted text-[12.5px]">
109
+ {{ t('dms_mailing.settings.categories.empty') }}
110
+ </p>
111
+
112
+ <UButton
113
+ v-if="!disabled"
114
+ icon="i-ph-plus"
115
+ variant="link"
116
+ size="sm"
117
+ class="self-start"
118
+ :label="t('dms_mailing.settings.categories.add')"
119
+ @click="addCategory"
120
+ />
121
+
122
+ <p class="text-dimmed text-[11.5px]">
123
+ {{ t('dms_mailing.settings.categories.hint') }}
124
+ </p>
125
+ </div>
126
+ </template>
@@ -0,0 +1,67 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ fromCategoryOption,
4
+ NO_CATEGORY,
5
+ toCategoryOption,
6
+ } from '../utils/categories'
7
+ import type { TemplateCategory } from '../types/mailing'
8
+
9
+ interface CategoryInputProps {
10
+ modelValue?: string | null
11
+ initialValue?: string | null
12
+ disabled?: boolean
13
+ }
14
+
15
+ const props = withDefaults(defineProps<CategoryInputProps>(), {
16
+ modelValue: null,
17
+ initialValue: null,
18
+ disabled: false,
19
+ })
20
+
21
+ const emit = defineEmits<{ 'update:modelValue': [value: string] }>()
22
+
23
+ const api = useMailingApi()
24
+ const { t } = useI18n()
25
+
26
+ const categories = ref<TemplateCategory[]>([])
27
+ const selected = ref<string>(
28
+ toCategoryOption(props.modelValue ?? props.initialValue),
29
+ )
30
+
31
+ const items = computed(() => [
32
+ { label: t('dms_mailing.templates.uncategorised'), value: NO_CATEGORY },
33
+ ...categories.value.map((entry) => ({
34
+ label: entry.label,
35
+ value: entry.id,
36
+ })),
37
+ ])
38
+
39
+ watch(
40
+ () => props.modelValue,
41
+ (value) => {
42
+ selected.value = toCategoryOption(value)
43
+ },
44
+ )
45
+
46
+ onMounted(async () => {
47
+ try {
48
+ const response = await api.listCategories()
49
+ categories.value = response.categories
50
+ } catch {
51
+ categories.value = []
52
+ }
53
+ })
54
+ </script>
55
+
56
+ <template>
57
+ <USelect
58
+ v-model="selected"
59
+ :items="items"
60
+ value-key="value"
61
+ :disabled="disabled"
62
+ class="w-full"
63
+ @update:model-value="
64
+ emit('update:modelValue', fromCategoryOption(selected))
65
+ "
66
+ />
67
+ </template>
@@ -0,0 +1,63 @@
1
+ <script setup lang="ts">
2
+ import { computed, onMounted, ref } from 'vue'
3
+ import type { TemplateContentResponse } from '../types/mailing'
4
+ import { useMailingApi } from '../composables/useMailingApi'
5
+
6
+ const { t } = useI18n()
7
+ const route = useDmsRoute()
8
+ const api = useMailingApi()
9
+
10
+ const templateId = computed(() => String(route.query.id ?? ''))
11
+ const requestedLocale = computed(() =>
12
+ route.query.locale ? String(route.query.locale) : null,
13
+ )
14
+
15
+ const loaded = ref<TemplateContentResponse | null>(null)
16
+ const loading = ref(true)
17
+ const failed = ref(false)
18
+
19
+ async function load(): Promise<void> {
20
+ loading.value = true
21
+ failed.value = false
22
+ try {
23
+ loaded.value = await api.templateContent(templateId.value)
24
+ } catch {
25
+ failed.value = true
26
+ } finally {
27
+ loading.value = false
28
+ }
29
+ }
30
+
31
+ onMounted(load)
32
+ </script>
33
+
34
+ <template>
35
+ <div class="flex h-full min-h-0 flex-col">
36
+ <div
37
+ v-if="loading"
38
+ class="text-muted flex flex-1 items-center justify-center gap-2 text-sm"
39
+ >
40
+ <UIcon name="i-ph-circle-notch" class="size-4 animate-spin" />
41
+ {{ t('dms_mailing.editor.loading') }}
42
+ </div>
43
+
44
+ <div
45
+ v-else-if="failed || !loaded"
46
+ class="flex flex-1 flex-col items-center justify-center gap-3"
47
+ >
48
+ <UIcon name="i-ph-warning-circle" class="text-error size-8" />
49
+ <p class="text-muted text-sm">{{ t('dms_mailing.editor.load_error') }}</p>
50
+ <UButton variant="outline" icon="i-ph-arrow-clockwise" @click="load()">
51
+ {{ t('dms_mailing.editor.back') }}
52
+ </UButton>
53
+ </div>
54
+
55
+ <DmsMailingEditorWorkspace
56
+ v-else
57
+ :key="templateId"
58
+ :loaded="loaded"
59
+ :template-id="templateId"
60
+ :requested-locale="requestedLocale"
61
+ />
62
+ </div>
63
+ </template>
@@ -0,0 +1,66 @@
1
+ <script setup lang="ts">
2
+ import type { MailingComponentProps } from '../types/component'
3
+ import type { FunnelResponse } from '../composables/useMailingApi'
4
+ import type { FunnelStep } from '../types/mailing'
5
+
6
+ const OVERVIEW_PERIOD_SCOPE = 'mailing-overview'
7
+ const UNSUBSCRIBED_STEP_ID = 'unsubscribed'
8
+ const RATE_DECIMALS = 1
9
+
10
+ defineProps<MailingComponentProps>()
11
+
12
+ const api = useMailingApi()
13
+ const { t, locale } = useI18n()
14
+ const { processI18n } = useTranslation()
15
+
16
+ const { data, loading } = useMailingPeriodData<FunnelResponse>(
17
+ OVERVIEW_PERIOD_SCOPE,
18
+ (query) => api.funnel(query),
19
+ )
20
+
21
+ const steps = computed(() => data.value?.steps ?? [])
22
+
23
+ const numberFormat = computed(() => new Intl.NumberFormat(locale.value))
24
+
25
+ function stepColor(step: FunnelStep): 'warning' | 'primary' {
26
+ return step.id === UNSUBSCRIBED_STEP_ID ? 'warning' : 'primary'
27
+ }
28
+
29
+ function formatRate(rate: number): string {
30
+ return `${rate.toFixed(RATE_DECIMALS)} %`
31
+ }
32
+ </script>
33
+
34
+ <template>
35
+ <DmsCard :padded="false" class="p-5 sm:p-6">
36
+ <h2 class="text-highlighted mb-4 text-sm font-semibold">
37
+ {{ t('dms_mailing.overview.funnel_title') }}
38
+ </h2>
39
+
40
+ <USkeleton v-if="loading && !steps.length" class="h-28 w-full" />
41
+
42
+ <div v-else class="flex flex-col gap-3">
43
+ <div v-for="step in steps" :key="step.id" class="flex items-center gap-3">
44
+ <span class="text-muted w-28 shrink-0 truncate text-[12.5px]">
45
+ {{ processI18n(step.label) }}
46
+ </span>
47
+ <UProgress
48
+ :model-value="step.rate"
49
+ :color="stepColor(step)"
50
+ size="sm"
51
+ class="flex-1"
52
+ />
53
+ <span
54
+ class="text-highlighted w-16 shrink-0 text-right text-[12.5px] font-medium tabular-nums"
55
+ >
56
+ {{ numberFormat.format(step.count) }}
57
+ </span>
58
+ <span
59
+ class="text-dimmed w-14 shrink-0 text-right text-[11.5px] tabular-nums"
60
+ >
61
+ {{ formatRate(step.rate) }}
62
+ </span>
63
+ </div>
64
+ </div>
65
+ </DmsCard>
66
+ </template>
@@ -0,0 +1,20 @@
1
+ <script setup lang="ts">
2
+ interface HtmlPreviewModalProps {
3
+ html: string
4
+ height?: number
5
+ }
6
+
7
+ const DEFAULT_HEIGHT = 620
8
+
9
+ withDefaults(defineProps<HtmlPreviewModalProps>(), { height: DEFAULT_HEIGHT })
10
+ </script>
11
+
12
+ <template>
13
+ <iframe
14
+ :srcdoc="html"
15
+ sandbox="allow-same-origin"
16
+ title="preview"
17
+ class="block w-full border-0 bg-white"
18
+ :style="{ height: `${height}px` }"
19
+ />
20
+ </template>