@capillarytech/creatives-library 8.0.287-alpha.3 → 8.0.288

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 (65) hide show
  1. package/constants/unified.js +1 -0
  2. package/initialState.js +2 -0
  3. package/package.json +1 -1
  4. package/utils/common.js +8 -5
  5. package/utils/commonUtils.js +111 -2
  6. package/utils/tagValidations.js +222 -84
  7. package/utils/tests/commonUtil.test.js +118 -147
  8. package/utils/tests/tagValidations.test.js +358 -280
  9. package/v2Components/CapTagList/index.js +7 -2
  10. package/v2Components/CapTagListWithInput/index.js +4 -0
  11. package/v2Components/ErrorInfoNote/index.js +5 -2
  12. package/v2Components/FormBuilder/index.js +187 -74
  13. package/v2Components/FormBuilder/messages.js +12 -0
  14. package/v2Components/HtmlEditor/HTMLEditor.js +5 -0
  15. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
  16. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +15 -0
  17. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +2 -1
  18. package/v2Containers/Cap/mockData.js +14 -0
  19. package/v2Containers/Cap/reducer.js +55 -3
  20. package/v2Containers/Cap/tests/reducer.test.js +102 -0
  21. package/v2Containers/CreativesContainer/SlideBoxContent.js +20 -0
  22. package/v2Containers/CreativesContainer/SlideBoxFooter.js +40 -6
  23. package/v2Containers/CreativesContainer/constants.js +6 -0
  24. package/v2Containers/CreativesContainer/index.js +36 -5
  25. package/v2Containers/CreativesContainer/messages.js +12 -0
  26. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +339 -0
  27. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +18 -0
  28. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +37 -0
  29. package/v2Containers/Email/index.js +5 -1
  30. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +62 -10
  31. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +115 -12
  32. package/v2Containers/FTP/index.js +51 -2
  33. package/v2Containers/FTP/messages.js +4 -0
  34. package/v2Containers/InApp/index.js +96 -1
  35. package/v2Containers/InApp/tests/index.test.js +6 -17
  36. package/v2Containers/InappAdvance/index.js +103 -2
  37. package/v2Containers/Line/Container/Text/index.js +1 -0
  38. package/v2Containers/MobilePush/Create/index.js +37 -1
  39. package/v2Containers/MobilePush/Create/messages.js +4 -0
  40. package/v2Containers/MobilePush/Edit/index.js +37 -2
  41. package/v2Containers/MobilePush/Edit/messages.js +4 -0
  42. package/v2Containers/MobilePushNew/components/PlatformContentFields.js +36 -12
  43. package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +68 -27
  44. package/v2Containers/MobilePushNew/index.js +92 -5
  45. package/v2Containers/MobilePushNew/messages.js +8 -0
  46. package/v2Containers/MobilepushWrapper/index.js +7 -1
  47. package/v2Containers/Rcs/index.js +37 -12
  48. package/v2Containers/Sms/Create/index.js +3 -31
  49. package/v2Containers/Sms/Create/messages.js +0 -4
  50. package/v2Containers/Sms/Edit/index.js +3 -29
  51. package/v2Containers/Sms/commonMethods.js +6 -6
  52. package/v2Containers/SmsTrai/Edit/index.js +47 -6
  53. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
  54. package/v2Containers/TagList/index.js +17 -1
  55. package/v2Containers/TagList/messages.js +4 -0
  56. package/v2Containers/TemplatesV2/index.js +43 -23
  57. package/v2Containers/Viber/index.js +1 -0
  58. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +3 -1
  59. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +7 -0
  60. package/v2Containers/WebPush/Create/index.js +25 -6
  61. package/v2Containers/WebPush/Create/messages.js +8 -1
  62. package/v2Containers/WebPush/Create/utils/validation.js +20 -22
  63. package/v2Containers/WebPush/Create/utils/validation.test.js +52 -0
  64. package/v2Containers/Whatsapp/index.js +17 -9
  65. package/v2Containers/Zalo/index.js +11 -3
@@ -12,13 +12,16 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
12
12
  closeIconType="close"
13
13
  content={
14
14
  <SlideBoxContent
15
+ channelsToHide={Array []}
15
16
  currentChannel="RCS"
17
+ customerType=""
16
18
  getFormData={[Function]}
17
19
  handleClose={[Function]}
18
20
  handleCloseTestAndPreview={[Function]}
19
21
  handleTestAndPreview={[Function]}
20
22
  hostName=""
21
23
  inAppEditorType={null}
24
+ isAnonymousType={false}
22
25
  isTestAndPreviewMode={false}
23
26
  loyaltyMetaData={
24
27
  Object {
@@ -38,6 +41,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
38
41
  onInAppEditorTypeChange={[Function]}
39
42
  onInAppModeChange={[Function]}
40
43
  onMobilepushModeChange={[Function]}
44
+ onPersonalizationTokensChange={[Function]}
41
45
  onPreviewTemplate={[Function]}
42
46
  onRemoveTemplateName={[Function]}
43
47
  onResetStep={[Function]}
@@ -46,6 +50,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
46
50
  onValidationFail={[Function]}
47
51
  onWeChatMaptemplateStepChange={[Function]}
48
52
  onWechatTemplateChange={[Function]}
53
+ restrictPersonalization={false}
49
54
  saveMessage={[Function]}
50
55
  setIsLoadingContent={[Function]}
51
56
  showLiquidErrorInFooter={[Function]}
@@ -103,13 +108,16 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
103
108
  closeIconType="close"
104
109
  content={
105
110
  <SlideBoxContent
111
+ channelsToHide={Array []}
106
112
  currentChannel="WHATSAPP"
113
+ customerType=""
107
114
  getFormData={[Function]}
108
115
  handleClose={[Function]}
109
116
  handleCloseTestAndPreview={[Function]}
110
117
  handleTestAndPreview={[Function]}
111
118
  hostName=""
112
119
  inAppEditorType={null}
120
+ isAnonymousType={false}
113
121
  isTestAndPreviewMode={false}
114
122
  loyaltyMetaData={
115
123
  Object {
@@ -129,6 +137,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
129
137
  onInAppEditorTypeChange={[Function]}
130
138
  onInAppModeChange={[Function]}
131
139
  onMobilepushModeChange={[Function]}
140
+ onPersonalizationTokensChange={[Function]}
132
141
  onPreviewTemplate={[Function]}
133
142
  onRemoveTemplateName={[Function]}
134
143
  onResetStep={[Function]}
@@ -137,6 +146,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
137
146
  onValidationFail={[Function]}
138
147
  onWeChatMaptemplateStepChange={[Function]}
139
148
  onWechatTemplateChange={[Function]}
149
+ restrictPersonalization={false}
140
150
  saveMessage={[Function]}
141
151
  setIsLoadingContent={[Function]}
142
152
  showLiquidErrorInFooter={[Function]}
@@ -194,13 +204,16 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
194
204
  closeIconType="close"
195
205
  content={
196
206
  <SlideBoxContent
207
+ channelsToHide={Array []}
197
208
  currentChannel="WHATSAPP"
209
+ customerType=""
198
210
  getFormData={[Function]}
199
211
  handleClose={[Function]}
200
212
  handleCloseTestAndPreview={[Function]}
201
213
  handleTestAndPreview={[Function]}
202
214
  hostName=""
203
215
  inAppEditorType={null}
216
+ isAnonymousType={false}
204
217
  isTestAndPreviewMode={false}
205
218
  loyaltyMetaData={
206
219
  Object {
@@ -220,6 +233,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
220
233
  onInAppEditorTypeChange={[Function]}
221
234
  onInAppModeChange={[Function]}
222
235
  onMobilepushModeChange={[Function]}
236
+ onPersonalizationTokensChange={[Function]}
223
237
  onPreviewTemplate={[Function]}
224
238
  onRemoveTemplateName={[Function]}
225
239
  onResetStep={[Function]}
@@ -228,6 +242,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
228
242
  onValidationFail={[Function]}
229
243
  onWeChatMaptemplateStepChange={[Function]}
230
244
  onWechatTemplateChange={[Function]}
245
+ restrictPersonalization={false}
231
246
  saveMessage={[Function]}
232
247
  setIsLoadingContent={[Function]}
233
248
  showLiquidErrorInFooter={[Function]}
@@ -257,6 +272,8 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
257
272
  }
258
273
  }
259
274
  fetchingCmsData={false}
275
+ formData={Array []}
276
+ hasPersonalizationTokenError={false}
260
277
  htmlEditorValidationState={
261
278
  Object {
262
279
  "errorsAcknowledged": false,
@@ -269,6 +286,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
269
286
  "validationComplete": false,
270
287
  }
271
288
  }
289
+ isAnonymousType={false}
272
290
  isContinueButtonDisabled={false}
273
291
  isCreatingTemplate={false}
274
292
  isEmptyContent={false}
@@ -280,6 +298,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
280
298
  onEditTemplate={[Function]}
281
299
  onSave={[Function]}
282
300
  onTestAndPreview={[Function]}
301
+ restrictPersonalization={false}
283
302
  selectedEmailCreateMode={null}
284
303
  shouldShowContinueFooter={[Function]}
285
304
  shouldShowDoneFooter={[Function]}
@@ -323,13 +342,16 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
323
342
  closeIconType="close"
324
343
  content={
325
344
  <SlideBoxContent
345
+ channelsToHide={Array []}
326
346
  currentChannel="WHATSAPP"
347
+ customerType=""
327
348
  getFormData={[Function]}
328
349
  handleClose={[Function]}
329
350
  handleCloseTestAndPreview={[Function]}
330
351
  handleTestAndPreview={[Function]}
331
352
  hostName=""
332
353
  inAppEditorType={null}
354
+ isAnonymousType={false}
333
355
  isTestAndPreviewMode={false}
334
356
  loyaltyMetaData={
335
357
  Object {
@@ -349,6 +371,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
349
371
  onInAppEditorTypeChange={[Function]}
350
372
  onInAppModeChange={[Function]}
351
373
  onMobilepushModeChange={[Function]}
374
+ onPersonalizationTokensChange={[Function]}
352
375
  onPreviewTemplate={[Function]}
353
376
  onRemoveTemplateName={[Function]}
354
377
  onResetStep={[Function]}
@@ -357,6 +380,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
357
380
  onValidationFail={[Function]}
358
381
  onWeChatMaptemplateStepChange={[Function]}
359
382
  onWechatTemplateChange={[Function]}
383
+ restrictPersonalization={false}
360
384
  saveMessage={[Function]}
361
385
  setIsLoadingContent={[Function]}
362
386
  showLiquidErrorInFooter={[Function]}
@@ -386,6 +410,8 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
386
410
  }
387
411
  }
388
412
  fetchingCmsData={false}
413
+ formData={Array []}
414
+ hasPersonalizationTokenError={false}
389
415
  htmlEditorValidationState={
390
416
  Object {
391
417
  "errorsAcknowledged": false,
@@ -398,6 +424,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
398
424
  "validationComplete": false,
399
425
  }
400
426
  }
427
+ isAnonymousType={false}
401
428
  isContinueButtonDisabled={false}
402
429
  isCreatingTemplate={false}
403
430
  isEmptyContent={false}
@@ -409,6 +436,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
409
436
  onEditTemplate={[Function]}
410
437
  onSave={[Function]}
411
438
  onTestAndPreview={[Function]}
439
+ restrictPersonalization={false}
412
440
  selectedEmailCreateMode={null}
413
441
  shouldShowContinueFooter={[Function]}
414
442
  shouldShowDoneFooter={[Function]}
@@ -452,13 +480,16 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
452
480
  closeIconType="close"
453
481
  content={
454
482
  <SlideBoxContent
483
+ channelsToHide={Array []}
455
484
  currentChannel="WHATSAPP"
485
+ customerType=""
456
486
  getFormData={[Function]}
457
487
  handleClose={[Function]}
458
488
  handleCloseTestAndPreview={[Function]}
459
489
  handleTestAndPreview={[Function]}
460
490
  hostName=""
461
491
  inAppEditorType={null}
492
+ isAnonymousType={false}
462
493
  isTestAndPreviewMode={false}
463
494
  loyaltyMetaData={
464
495
  Object {
@@ -478,6 +509,7 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
478
509
  onInAppEditorTypeChange={[Function]}
479
510
  onInAppModeChange={[Function]}
480
511
  onMobilepushModeChange={[Function]}
512
+ onPersonalizationTokensChange={[Function]}
481
513
  onPreviewTemplate={[Function]}
482
514
  onRemoveTemplateName={[Function]}
483
515
  onResetStep={[Function]}
@@ -486,6 +518,7 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
486
518
  onValidationFail={[Function]}
487
519
  onWeChatMaptemplateStepChange={[Function]}
488
520
  onWechatTemplateChange={[Function]}
521
+ restrictPersonalization={false}
489
522
  saveMessage={[Function]}
490
523
  setIsLoadingContent={[Function]}
491
524
  showLiquidErrorInFooter={[Function]}
@@ -515,6 +548,8 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
515
548
  }
516
549
  }
517
550
  fetchingCmsData={false}
551
+ formData={Array []}
552
+ hasPersonalizationTokenError={false}
518
553
  htmlEditorValidationState={
519
554
  Object {
520
555
  "errorsAcknowledged": false,
@@ -527,6 +562,7 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
527
562
  "validationComplete": false,
528
563
  }
529
564
  }
565
+ isAnonymousType={false}
530
566
  isContinueButtonDisabled={false}
531
567
  isCreatingTemplate={false}
532
568
  isEmptyContent={false}
@@ -538,6 +574,7 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
538
574
  onEditTemplate={[Function]}
539
575
  onSave={[Function]}
540
576
  onTestAndPreview={[Function]}
577
+ restrictPersonalization={false}
541
578
  selectedEmailCreateMode={null}
542
579
  shouldShowContinueFooter={[Function]}
543
580
  shouldShowDoneFooter={[Function]}
@@ -26,7 +26,7 @@ import * as globalActions from '../Cap/actions';
26
26
  import './_email.scss';
27
27
  import {getMessageObject} from '../../utils/messageUtils';
28
28
  import EmailPreview from '../../v2Components/EmailPreview';
29
- import { getDecodedFileName, hasSupportCKEditor } from '../../utils/common';
29
+ import { getDecodedFileName, hasLiquidSupportFeature, hasSupportCKEditor } from '../../utils/common';
30
30
  import Pagination from '../../v2Components/Pagination';
31
31
  import * as creativesContainerActions from '../CreativesContainer/actions';
32
32
  import withCreatives from '../../hoc/withCreatives';
@@ -170,6 +170,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
170
170
  deleteLanguage: this.deleteLanguage,
171
171
  },
172
172
  };
173
+ this.liquidFlow = hasLiquidSupportFeature();
173
174
  }
174
175
  componentWillMount() {
175
176
  const formData = this.initFormData(this.props, true); //_.cloneDeep(this.state.formData);
@@ -254,6 +255,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
254
255
  layout: 'EMAIL',
255
256
  type: 'LAYOUT',
256
257
  version: 'v2',
258
+ liquidFlow:this.liquidFlow,
257
259
  };
258
260
  this.props.globalActions.fetchSchemaForEntity(query);
259
261
  window.addEventListener("message", this.handleFrameTasks);
@@ -345,6 +347,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
345
347
  type: 'TAG',
346
348
  context: this.props.location.query.type === 'embedded' ? this.props.location.query.module : 'default',
347
349
  embedded: this.props.location.query.type === 'embedded' ? this.props.location.query.type : 'full',
350
+ liquidFlow:this.liquidFlow
348
351
  };
349
352
  if (this.props.getDefaultTags) {
350
353
  query.context = this.props.getDefaultTags;
@@ -2370,6 +2373,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2370
2373
  type: 'TAG',
2371
2374
  context: (data || '').toLowerCase() === 'all' ? 'default' : (data || '').toLowerCase(),
2372
2375
  embedded: 'full',
2376
+ liquidFlow:this.liquidFlow
2373
2377
  };
2374
2378
  this.props.globalActions.fetchSchemaForEntity(query);
2375
2379
  }
@@ -15,7 +15,7 @@ import HTMLEditor from '../../../v2Components/HtmlEditor';
15
15
  import CapTagListWithInput from '../../../v2Components/CapTagListWithInput';
16
16
  import formBuilderMessages from '../../../v2Components/FormBuilder/messages';
17
17
  import { validateLiquidTemplateContent } from '../../../utils/commonUtils';
18
- import { isEmailUnsubscribeTagOptional } from '../../../utils/common';
18
+ import { hasLiquidSupportFeature, isEmailUnsubscribeTagMandatory } from '../../../utils/common';
19
19
  import history from '../../../utils/history';
20
20
  import messages from '../messages';
21
21
  import emailMessages from '../../Email/messages';
@@ -108,10 +108,13 @@ const EmailHTMLEditor = (props) => {
108
108
  standardErrors: [],
109
109
  });
110
110
 
111
- // Merge tag validation errors (missing) into apiValidationErrors so they show in ValidationErrorDisplay
111
+ // Merge tag validation errors (unsupported/missing) into apiValidationErrors so they show in ValidationErrorDisplay
112
112
  const mergedApiValidationErrors = useMemo(() => {
113
113
  const tagMessages = [];
114
- if (tagValidationError?.missingTags?.length && !isEmailUnsubscribeTagOptional()) {
114
+ if (tagValidationError?.unsupportedTags?.length) {
115
+ tagMessages.push(`Unsupported tags are: ${tagValidationError.unsupportedTags.join(', ')}`);
116
+ }
117
+ if (tagValidationError?.missingTags?.length && !isEmailUnsubscribeTagMandatory()) {
115
118
  tagMessages.push(`Missing tags are: ${tagValidationError.missingTags.join(', ')}`);
116
119
  }
117
120
  if (tagMessages.length === 0) {
@@ -187,6 +190,9 @@ const EmailHTMLEditor = (props) => {
187
190
  },
188
191
  }), [htmlContent, subject, currentOrgDetails]);
189
192
 
193
+ // Check if liquid support is enabled
194
+ const isLiquidEnabled = hasLiquidSupportFeature();
195
+
190
196
  // Detect edit mode: when isEditEmail is false (create flow), never treat as edit or fetch template details
191
197
  const hasParamsId = params?.id || location?.query?.id || location?.params?.id || location?.pathname?.includes('/edit/');
192
198
  const currentTemplateId = isEditEmail
@@ -487,8 +493,10 @@ const EmailHTMLEditor = (props) => {
487
493
  const validationResult = validateTags({
488
494
  content,
489
495
  tagsParam: tags,
496
+ injectedTagsParams: injectedTags,
490
497
  location,
491
498
  tagModule: getDefaultTags,
499
+ eventContextTags,
492
500
  isFullMode,
493
501
  });
494
502
 
@@ -642,7 +650,7 @@ const EmailHTMLEditor = (props) => {
642
650
  // IMPORTANT: Clear API validation errors FIRST before checking for validation errors
643
651
  // This ensures that old API errors don't block the save when user fixes content and clicks Update again
644
652
  // We'll re-validate with fresh API call anyway
645
- if (getLiquidTags) {
653
+ if (isLiquidEnabled && getLiquidTags) {
646
654
  setApiValidationErrors({
647
655
  liquidErrors: [],
648
656
  standardErrors: [],
@@ -704,7 +712,7 @@ const EmailHTMLEditor = (props) => {
704
712
  // When EMAIL_UNSUBSCRIBE_TAG_MANDATORY is false: validate and require unsubscribe tag.
705
713
  // Run for both library and full mode so liquid-enabled orgs also get the error (notification + ValidationErrorDisplay).
706
714
  const isModuleTypeOutbound = (moduleType || '').toUpperCase() === OUTBOUND;
707
- if (!isEmailUnsubscribeTagOptional() && isModuleTypeOutbound) {
715
+ if (!isEmailUnsubscribeTagMandatory() && isModuleTypeOutbound) {
708
716
  const unsubscribeRegex = /{{unsubscribe(\(#[a-zA-Z\d]{6}\))?}}/g; // eslint-disable-line no-useless-escape
709
717
  const hasUnsubscribeTag = unsubscribeRegex.test(htmlContent);
710
718
 
@@ -736,17 +744,52 @@ const EmailHTMLEditor = (props) => {
736
744
  const validationResult = validateTags({
737
745
  content: htmlContent,
738
746
  tagsParam: tags,
747
+ injectedTagsParams: injectedTags,
739
748
  location,
740
749
  tagModule: getDefaultTags,
750
+ eventContextTags,
741
751
  isFullMode,
742
752
  });
743
753
 
744
- if (!validationResult?.valid) {
754
+ const hasUnsupportedTags = validationResult?.unsupportedTags?.length > 0;
755
+ if (!validationResult?.valid || (hasUnsupportedTags && !isFullMode)) {
745
756
  setTagValidationError(validationResult);
746
- // For liquid orgs, show warning and continue (extractTags API will validate)
757
+ // IMPORTANT: For non-liquid orgs, block save (like CK/BEE editor)
758
+ // For liquid orgs, continue (extractTags API will validate)
759
+ if (!isLiquidEnabled) {
760
+ // Show notification popup like CK/BEE editor
761
+ const baseLanguage = get(currentOrgDetails, 'basic_details.base_language', 'en');
762
+
763
+ const contentNotValidMsg = intl.formatMessage(formBuilderMessages.contentNotValidLanguage);
764
+ let errorMessage = `${contentNotValidMsg} ${baseLanguage}`;
765
+
766
+ if (hasUnsupportedTags) {
767
+ const unsupportedTagsMsg = intl.formatMessage(formBuilderMessages.unsupportedTags);
768
+ errorMessage += `\n${unsupportedTagsMsg} ${validationResult?.unsupportedTags?.join(', ')}`;
769
+ }
770
+ if (validationResult?.missingTags?.length > 0) {
771
+ const missingTagsMsg = intl.formatMessage(formBuilderMessages.missingTags);
772
+ errorMessage += `\n${missingTagsMsg} ${validationResult?.missingTags?.join(', ')}`;
773
+ }
774
+
775
+ const type = 'error';
776
+ CapNotification[type]({
777
+ message: `${type.toUpperCase()} ! ! ! `,
778
+ description: errorMessage,
779
+ duration: 5,
780
+ });
781
+
782
+ // Reset parent state so next click is detected as a change
783
+ if (onValidationFail) {
784
+ onValidationFail();
785
+ }
786
+ // Block save for non-liquid orgs
787
+ return;
788
+ }
789
+ // For liquid orgs, just show warning and continue
747
790
  }
748
791
  // Clear tag errors if valid
749
- if (tagValidationError && validationResult?.valid) {
792
+ if (tagValidationError && validationResult?.valid && !hasUnsupportedTags) {
750
793
  setTagValidationError(null);
751
794
  }
752
795
  }
@@ -913,8 +956,8 @@ const EmailHTMLEditor = (props) => {
913
956
  }
914
957
  };
915
958
 
916
- // Validate first using extractTags API
917
- if (getLiquidTags) {
959
+ // If liquid enabled, validate first using extractTags API
960
+ if (isLiquidEnabled && getLiquidTags) {
918
961
  // Note: API validation errors are already cleared at the start of handleSave
919
962
  // This ensures fresh validation on every save attempt
920
963
 
@@ -955,6 +998,10 @@ const EmailHTMLEditor = (props) => {
955
998
  messages: formBuilderMessages,
956
999
  onError,
957
1000
  onSuccess,
1001
+ tagLookupMap: metaEntities?.tagLookupMap,
1002
+ eventContextTags,
1003
+ isLiquidFlow: true,
1004
+ forwardedTags: forwardedTags || {},
958
1005
  });
959
1006
  } else {
960
1007
  performSave();
@@ -966,6 +1013,7 @@ const EmailHTMLEditor = (props) => {
966
1013
  injectedTags,
967
1014
  location,
968
1015
  getDefaultTags,
1016
+ eventContextTags,
969
1017
  formatMessage,
970
1018
  subjectError,
971
1019
  isFullMode,
@@ -977,8 +1025,11 @@ const EmailHTMLEditor = (props) => {
977
1025
  emailActions,
978
1026
  getFormdata,
979
1027
  isGetFormData,
1028
+ isLiquidEnabled,
980
1029
  getLiquidTags,
981
1030
  showLiquidErrorInFooter,
1031
+ metaEntities,
1032
+ forwardedTags,
982
1033
  globalActions,
983
1034
  intl,
984
1035
  extractedTemplateName,
@@ -1124,6 +1175,7 @@ const EmailHTMLEditor = (props) => {
1124
1175
  userLocale={intl.locale || 'en'}
1125
1176
  moduleFilterEnabled={location?.query?.type !== EMBEDDED}
1126
1177
  onTagContextChange={handleOnTagsContextChange}
1178
+ isLiquidEnabled={isLiquidEnabled}
1127
1179
  isFullMode={isFullMode}
1128
1180
  onErrorAcknowledged={handleErrorAcknowledged}
1129
1181
  onValidationChange={handleValidationChange}