From 517b67dfd6fee65d91d7de059f6f4e8c564184a4 Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Thu, 30 Apr 2026 18:54:34 +0400 Subject: [PATCH] feat: Add rich template preview for WhatsApp & Twilio Templates (#13206) This PR introduces a comprehensive, display-only template preview system for both WhatsApp and Twilio templates rendering of all supported template types. This lays the foundation for rich template previews across: - Template selection modals - Campaign creation flows - Message composer - Message screen. template-preview --------- Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: iamsivin Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com> --- .../message/bubbles/Template/CallToAction.vue | 25 -- .../message/bubbles/Template/ListPicker.vue | 25 -- .../message/bubbles/Template/Media.vue | 20 - .../message/bubbles/Template/QuickReply.vue | 68 --- .../stories/Template/CallToAction.story.vue | 21 - .../message/stories/Template/Card.story.vue | 23 - .../stories/Template/ListPicker.story.vue | 21 - .../message/stories/Template/Media.story.vue | 23 - .../stories/Template/QuickReply.story.vue | 21 - .../message/stories/Template/Text.story.vue | 20 - .../CSATTemplate.vue} | 0 .../template-preview/CallToActionTemplate.vue | 33 ++ .../CardTemplate.vue} | 12 +- .../template-preview/MediaTemplate.vue | 67 +++ .../template-preview/QuickReplyTemplate.vue | 42 ++ .../TemplatePreview.story.vue | 105 +++++ .../template-preview/TemplatePreview.vue | 112 +++++ .../TemplatePreviewExamples.story.vue | 199 +++++++++ .../TextTemplate.vue} | 2 +- .../template-preview/WhatsAppTextTemplate.vue | 26 ++ .../components-next/template-preview/index.js | 6 + .../templates/twilio-templates.js | 209 +++++++++ .../templates/whatsapp-templates.js | 408 ++++++++++++++++++ .../settingsPage/CustomerSatisfactionPage.vue | 2 +- .../dashboard/services/TemplateConstants.js | 58 +++ .../dashboard/services/TemplateNormalizer.js | 114 +++++ .../services/TemplateNormalizer.spec.js | 143 ++++++ .../services/TemplateTypeDetector.js | 63 +++ .../services/TemplateTypeDetector.spec.js | 106 +++++ .../modules/specs/inboxes/templateFixtures.js | 4 +- theme/icons.js | 5 + 31 files changed, 1706 insertions(+), 277 deletions(-) delete mode 100644 app/javascript/dashboard/components-next/message/bubbles/Template/CallToAction.vue delete mode 100644 app/javascript/dashboard/components-next/message/bubbles/Template/ListPicker.vue delete mode 100644 app/javascript/dashboard/components-next/message/bubbles/Template/Media.vue delete mode 100644 app/javascript/dashboard/components-next/message/bubbles/Template/QuickReply.vue delete mode 100644 app/javascript/dashboard/components-next/message/stories/Template/CallToAction.story.vue delete mode 100644 app/javascript/dashboard/components-next/message/stories/Template/Card.story.vue delete mode 100644 app/javascript/dashboard/components-next/message/stories/Template/ListPicker.story.vue delete mode 100644 app/javascript/dashboard/components-next/message/stories/Template/Media.story.vue delete mode 100644 app/javascript/dashboard/components-next/message/stories/Template/QuickReply.story.vue delete mode 100644 app/javascript/dashboard/components-next/message/stories/Template/Text.story.vue rename app/javascript/dashboard/components-next/{message/bubbles/Template/CSAT.vue => template-preview/CSATTemplate.vue} (100%) create mode 100644 app/javascript/dashboard/components-next/template-preview/CallToActionTemplate.vue rename app/javascript/dashboard/components-next/{message/bubbles/Template/Card.vue => template-preview/CardTemplate.vue} (60%) create mode 100644 app/javascript/dashboard/components-next/template-preview/MediaTemplate.vue create mode 100644 app/javascript/dashboard/components-next/template-preview/QuickReplyTemplate.vue create mode 100644 app/javascript/dashboard/components-next/template-preview/TemplatePreview.story.vue create mode 100644 app/javascript/dashboard/components-next/template-preview/TemplatePreview.vue create mode 100644 app/javascript/dashboard/components-next/template-preview/TemplatePreviewExamples.story.vue rename app/javascript/dashboard/components-next/{message/bubbles/Template/Text.vue => template-preview/TextTemplate.vue} (76%) create mode 100644 app/javascript/dashboard/components-next/template-preview/WhatsAppTextTemplate.vue create mode 100644 app/javascript/dashboard/components-next/template-preview/index.js create mode 100644 app/javascript/dashboard/components-next/template-preview/templates/twilio-templates.js create mode 100644 app/javascript/dashboard/components-next/template-preview/templates/whatsapp-templates.js create mode 100644 app/javascript/dashboard/services/TemplateConstants.js create mode 100644 app/javascript/dashboard/services/TemplateNormalizer.js create mode 100644 app/javascript/dashboard/services/TemplateNormalizer.spec.js create mode 100644 app/javascript/dashboard/services/TemplateTypeDetector.js create mode 100644 app/javascript/dashboard/services/TemplateTypeDetector.spec.js diff --git a/app/javascript/dashboard/components-next/message/bubbles/Template/CallToAction.vue b/app/javascript/dashboard/components-next/message/bubbles/Template/CallToAction.vue deleted file mode 100644 index 021419065..000000000 --- a/app/javascript/dashboard/components-next/message/bubbles/Template/CallToAction.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/bubbles/Template/ListPicker.vue b/app/javascript/dashboard/components-next/message/bubbles/Template/ListPicker.vue deleted file mode 100644 index 7d9401b80..000000000 --- a/app/javascript/dashboard/components-next/message/bubbles/Template/ListPicker.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/bubbles/Template/Media.vue b/app/javascript/dashboard/components-next/message/bubbles/Template/Media.vue deleted file mode 100644 index 24340ab90..000000000 --- a/app/javascript/dashboard/components-next/message/bubbles/Template/Media.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/bubbles/Template/QuickReply.vue b/app/javascript/dashboard/components-next/message/bubbles/Template/QuickReply.vue deleted file mode 100644 index 19727578f..000000000 --- a/app/javascript/dashboard/components-next/message/bubbles/Template/QuickReply.vue +++ /dev/null @@ -1,68 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/stories/Template/CallToAction.story.vue b/app/javascript/dashboard/components-next/message/stories/Template/CallToAction.story.vue deleted file mode 100644 index 1c2b956a3..000000000 --- a/app/javascript/dashboard/components-next/message/stories/Template/CallToAction.story.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/stories/Template/Card.story.vue b/app/javascript/dashboard/components-next/message/stories/Template/Card.story.vue deleted file mode 100644 index caa594bab..000000000 --- a/app/javascript/dashboard/components-next/message/stories/Template/Card.story.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/stories/Template/ListPicker.story.vue b/app/javascript/dashboard/components-next/message/stories/Template/ListPicker.story.vue deleted file mode 100644 index f1e9dd8b8..000000000 --- a/app/javascript/dashboard/components-next/message/stories/Template/ListPicker.story.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/stories/Template/Media.story.vue b/app/javascript/dashboard/components-next/message/stories/Template/Media.story.vue deleted file mode 100644 index 67d7fc6b8..000000000 --- a/app/javascript/dashboard/components-next/message/stories/Template/Media.story.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/stories/Template/QuickReply.story.vue b/app/javascript/dashboard/components-next/message/stories/Template/QuickReply.story.vue deleted file mode 100644 index 1d670e07c..000000000 --- a/app/javascript/dashboard/components-next/message/stories/Template/QuickReply.story.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/stories/Template/Text.story.vue b/app/javascript/dashboard/components-next/message/stories/Template/Text.story.vue deleted file mode 100644 index cbb6df569..000000000 --- a/app/javascript/dashboard/components-next/message/stories/Template/Text.story.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/app/javascript/dashboard/components-next/message/bubbles/Template/CSAT.vue b/app/javascript/dashboard/components-next/template-preview/CSATTemplate.vue similarity index 100% rename from app/javascript/dashboard/components-next/message/bubbles/Template/CSAT.vue rename to app/javascript/dashboard/components-next/template-preview/CSATTemplate.vue diff --git a/app/javascript/dashboard/components-next/template-preview/CallToActionTemplate.vue b/app/javascript/dashboard/components-next/template-preview/CallToActionTemplate.vue new file mode 100644 index 000000000..b4d61d252 --- /dev/null +++ b/app/javascript/dashboard/components-next/template-preview/CallToActionTemplate.vue @@ -0,0 +1,33 @@ + + + diff --git a/app/javascript/dashboard/components-next/message/bubbles/Template/Card.vue b/app/javascript/dashboard/components-next/template-preview/CardTemplate.vue similarity index 60% rename from app/javascript/dashboard/components-next/message/bubbles/Template/Card.vue rename to app/javascript/dashboard/components-next/template-preview/CardTemplate.vue index 9a4f9f19a..e862bc008 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/Template/Card.vue +++ b/app/javascript/dashboard/components-next/template-preview/CardTemplate.vue @@ -10,22 +10,22 @@ defineProps({