@capillarytech/creatives-library 8.0.285-alpha.1 → 8.0.286

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 (45) 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 +83 -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/ErrorInfoNote/index.js +5 -2
  10. package/v2Components/FormBuilder/index.js +158 -64
  11. package/v2Components/FormBuilder/messages.js +8 -0
  12. package/v2Components/HtmlEditor/HTMLEditor.js +5 -0
  13. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
  14. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +15 -0
  15. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +2 -1
  16. package/v2Containers/Cap/mockData.js +14 -0
  17. package/v2Containers/Cap/reducer.js +55 -3
  18. package/v2Containers/Cap/tests/reducer.test.js +102 -0
  19. package/v2Containers/CreativesContainer/index.js +1 -0
  20. package/v2Containers/Email/index.js +5 -1
  21. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +62 -10
  22. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +115 -12
  23. package/v2Containers/FTP/index.js +51 -2
  24. package/v2Containers/FTP/messages.js +4 -0
  25. package/v2Containers/InApp/index.js +96 -1
  26. package/v2Containers/InApp/tests/index.test.js +6 -17
  27. package/v2Containers/InappAdvance/index.js +103 -2
  28. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
  29. package/v2Containers/Line/Container/Text/index.js +1 -0
  30. package/v2Containers/MobilePushNew/index.js +33 -2
  31. package/v2Containers/Rcs/index.js +37 -12
  32. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +18 -4
  33. package/v2Containers/SmsTrai/Create/index.scss +1 -1
  34. package/v2Containers/SmsTrai/Edit/index.js +47 -6
  35. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
  36. package/v2Containers/Viber/index.js +1 -0
  37. package/v2Containers/Viber/index.scss +1 -1
  38. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +3 -1
  39. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +7 -0
  40. package/v2Containers/WebPush/Create/index.js +2 -2
  41. package/v2Containers/WebPush/Create/utils/validation.js +9 -18
  42. package/v2Containers/WebPush/Create/utils/validation.test.js +24 -0
  43. package/v2Containers/Whatsapp/index.js +17 -9
  44. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +624 -248
  45. package/v2Containers/Zalo/index.js +11 -3
@@ -4265,7 +4265,7 @@ FREE GIFTS-
4265
4265
  <CapCheckbox
4266
4266
  checked={false}
4267
4267
  disabled={false}
4268
- key=".3"
4268
+ key=".4"
4269
4269
  labelType="h4"
4270
4270
  onChange={[Function]}
4271
4271
  >
@@ -4327,7 +4327,7 @@ FREE GIFTS-
4327
4327
  </div>
4328
4328
  </CapCheckbox>
4329
4329
  <div
4330
- key=".5"
4330
+ key=".6"
4331
4331
  style={
4332
4332
  Object {
4333
4333
  "marginBottom": "100px",
@@ -15176,7 +15176,7 @@ FREE GIFTS-
15176
15176
  <CapCheckbox
15177
15177
  checked={false}
15178
15178
  disabled={false}
15179
- key=".3"
15179
+ key=".4"
15180
15180
  labelType="h4"
15181
15181
  onChange={[Function]}
15182
15182
  >
@@ -15238,7 +15238,7 @@ FREE GIFTS-
15238
15238
  </div>
15239
15239
  </CapCheckbox>
15240
15240
  <div
15241
- key=".5"
15241
+ key=".6"
15242
15242
  style={
15243
15243
  Object {
15244
15244
  "marginBottom": "100px",
@@ -26117,7 +26117,7 @@ FREE GIFTS-
26117
26117
  <CapCheckbox
26118
26118
  checked={false}
26119
26119
  disabled={false}
26120
- key=".3"
26120
+ key=".4"
26121
26121
  labelType="h4"
26122
26122
  onChange={[Function]}
26123
26123
  >
@@ -26179,7 +26179,7 @@ FREE GIFTS-
26179
26179
  </div>
26180
26180
  </CapCheckbox>
26181
26181
  <div
26182
- key=".5"
26182
+ key=".6"
26183
26183
  style={
26184
26184
  Object {
26185
26185
  "marginBottom": "100px",
@@ -234,6 +234,7 @@ export const Viber = (props) => {
234
234
  const { valid, isBraceError } = validateTags({
235
235
  content: value,
236
236
  tagsParam: tags,
237
+ injectedTagsParams: injectedTags,
237
238
  location,
238
239
  tagModule: 'outbound',
239
240
  isFullMode,
@@ -121,5 +121,5 @@
121
121
  margin-top: $CAP_SPACE_08;
122
122
  }
123
123
  .test-and-preview-button {
124
- margin-left: 120px;
124
+ margin-left: 100px;
125
125
  }
@@ -105,10 +105,12 @@ export const useTagManagement = ({
105
105
  const validationConfig = useMemo(
106
106
  () => ({
107
107
  tagsParam: tags,
108
+ injectedTagsParams: injectedTags,
108
109
  location,
109
110
  tagModule: getDefaultTags,
111
+ eventContextTags,
110
112
  }),
111
- [tags, location, getDefaultTags],
113
+ [tags, injectedTags, location, getDefaultTags, eventContextTags],
112
114
  );
113
115
 
114
116
  return {
@@ -528,19 +528,26 @@ describe('useTagManagement', () => {
528
528
 
529
529
  describe('validationConfig', () => {
530
530
  it('should return validation config with tags', () => {
531
+ const injectedTags = [{ id: 5, name: 'Injected Tag' }];
532
+ const eventContextTags = [{ id: 6, name: 'Event Tag' }];
533
+
531
534
  const { result } = renderHook(() =>
532
535
  useTagManagement({
533
536
  location: defaultLocation,
534
537
  globalActions: mockGlobalActions,
535
538
  metaEntities: defaultMetaEntities,
539
+ injectedTags,
540
+ eventContextTags,
536
541
  getDefaultTags: 'custom',
537
542
  })
538
543
  );
539
544
 
540
545
  expect(result.current.validationConfig).toEqual({
541
546
  tagsParam: defaultMetaEntities.tags.standard,
547
+ injectedTagsParams: injectedTags,
542
548
  location: defaultLocation,
543
549
  tagModule: 'custom',
550
+ eventContextTags,
544
551
  });
545
552
  });
546
553
 
@@ -285,8 +285,8 @@ const WebPushCreate = ({
285
285
  const validateTemplateName = useCallback((value) => validateTemplateNameUtil(value), []);
286
286
 
287
287
  const validateTitle = useCallback(
288
- (value) => validateTitleUtil(value, formatMessage, messages, validationConfig, isFullMode),
289
- [formatMessage, validationConfig, isFullMode],
288
+ (value) => validateTitleUtil(value, formatMessage, messages),
289
+ [formatMessage],
290
290
  );
291
291
 
292
292
  const validateUrl = useCallback(
@@ -10,31 +10,16 @@ import globalMessages from '../../../Cap/messages';
10
10
  export const validateTemplateName = (value) => !value || value.trim() === '';
11
11
 
12
12
  /**
13
- * Validates notification title (required and optional tag validation)
13
+ * Validates notification title
14
14
  * @param {string} value - The title value
15
15
  * @param {Function} formatMessage - i18n format message function
16
16
  * @param {Object} messages - Message definitions
17
- * @param {Object} [validationConfig] - Optional config for tag validation
18
- * @param {boolean} [isFullMode] - Optional; when set with validationConfig, runs tag validation
19
17
  * @returns {string} Error message if invalid, empty string if valid
20
18
  */
21
- export const validateTitle = (value, formatMessage, messages, validationConfig, isFullMode) => {
19
+ export const validateTitle = (value, formatMessage, messages) => {
22
20
  if (!value || value.trim() === '') {
23
21
  return formatMessage(messages.titleRequired);
24
22
  }
25
-
26
- if (validationConfig != null) {
27
- const validationResponse = validateTags({
28
- content: value,
29
- ...validationConfig,
30
- isFullMode,
31
- }) || {};
32
-
33
- if (validationResponse?.isBraceError) {
34
- return formatMessage(globalMessages.unbalanacedCurlyBraces);
35
- }
36
- }
37
-
38
23
  return '';
39
24
  };
40
25
 
@@ -75,7 +60,13 @@ export const validateMessageContent = (value, formatMessage, messages, validatio
75
60
  ...validationConfig,
76
61
  isFullMode,
77
62
  }) || {};
78
-
63
+
64
+ if (validationResponse?.unsupportedTags?.length) {
65
+ return formatMessage(globalMessages.unsupportedTagsValidationError, {
66
+ unsupportedTags: validationResponse.unsupportedTags.join(', '),
67
+ });
68
+ }
69
+
79
70
  if (validationResponse?.isBraceError) {
80
71
  return formatMessage(globalMessages.unbalanacedCurlyBraces);
81
72
  }
@@ -169,8 +169,10 @@ describe('validation', () => {
169
169
  describe('validateMessageContent', () => {
170
170
  const mockValidationConfig = {
171
171
  tagsParam: [],
172
+ injectedTagsParams: [],
172
173
  location: {},
173
174
  tagModule: '',
175
+ eventContextTags: [],
174
176
  };
175
177
 
176
178
  beforeEach(() => {
@@ -209,6 +211,17 @@ describe('validation', () => {
209
211
  });
210
212
  });
211
213
 
214
+ it('should return error message for unsupported tags', () => {
215
+ validateTags.mockReturnValue({
216
+ unsupportedTags: ['tag1', 'tag2'],
217
+ });
218
+ const result = validateMessageContent('Message with {tag1} and {tag2}', mockFormatMessage, mockMessages, mockValidationConfig);
219
+ expect(result).toBe('Unsupported tags: tag1, tag2');
220
+ expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unsupportedTagsValidationError, {
221
+ unsupportedTags: 'tag1, tag2',
222
+ });
223
+ });
224
+
212
225
  it('should return error message for unbalanced curly braces', () => {
213
226
  validateTags.mockReturnValue({
214
227
  isBraceError: true,
@@ -218,11 +231,22 @@ describe('validation', () => {
218
231
  expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unbalanacedCurlyBraces);
219
232
  });
220
233
 
234
+ it('should return error message for both unsupported tags and brace error (unsupported tags takes precedence)', () => {
235
+ validateTags.mockReturnValue({
236
+ unsupportedTags: ['tag1'],
237
+ isBraceError: true,
238
+ });
239
+ const result = validateMessageContent('Message with {tag1}', mockFormatMessage, mockMessages, mockValidationConfig);
240
+ expect(result).toBe('Unsupported tags: tag1');
241
+ });
242
+
221
243
  it('should pass validation config to validateTags', () => {
222
244
  const customConfig = {
223
245
  tagsParam: [{ id: 1, name: 'Tag1' }],
246
+ injectedTagsParams: [{ id: 2, name: 'Tag2' }],
224
247
  location: { query: { type: 'test' } },
225
248
  tagModule: 'custom',
249
+ eventContextTags: [{ id: 3, name: 'Tag3' }],
226
250
  };
227
251
  validateTags.mockReturnValue({});
228
252
  validateMessageContent('Valid message', mockFormatMessage, mockMessages, customConfig);
@@ -637,21 +637,22 @@ export const Whatsapp = (props) => {
637
637
  validateTags({
638
638
  content: contentData.join(""),
639
639
  tagsParam: tags,
640
+ injectedTagsParams: injectedTags,
640
641
  location,
641
642
  tagModule: getDefaultTags,
643
+ eventContextTags,
642
644
  isFullMode,
643
645
  }) || {};
646
+ const unsupportedTagsLengthCheck =
647
+ validationResponse?.unsupportedTags?.length > 0;
644
648
  if (type === HEADER_TEXT) {
645
649
  headerTagValidationResponse = validationResponse;
646
- updateIsHeaderTagValidationError(validationResponse.isBraceError);
650
+ updateIsHeaderTagValidationError(unsupportedTagsLengthCheck);
647
651
  } else if (type === CAROUSEL_TEXT) {
648
- return [
649
- { fieldName: "carouselTagValidationErrMessage", value: validationResponse.isBraceError ? validationResponse : {} },
650
- { fieldName: "carouselTagValidationErr", value: validationResponse.isBraceError },
651
- ];
652
+ return [{fieldName: "carouselTagValidationErrMessage", value: validationResponse}, {fieldName: "carouselTagValidationErr", value: unsupportedTagsLengthCheck}];
652
653
  } else {
653
654
  tagValidationResponse = validationResponse;
654
- updateIsTagValidationError(validationResponse.isBraceError);
655
+ updateIsTagValidationError(unsupportedTagsLengthCheck);
655
656
  }
656
657
  }
657
658
  };
@@ -2681,11 +2682,18 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
2681
2682
  } else {
2682
2683
  validationResponse = tagValidationResponse;
2683
2684
  }
2684
- const { isBraceError } = validationResponse || {};
2685
+ const { unsupportedTags = [], isBraceError } = validationResponse;
2686
+
2687
+ let tagError = "";
2688
+ if (unsupportedTags.length > 0) {
2689
+ tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
2690
+ unsupportedTags,
2691
+ });
2692
+ }
2685
2693
  if (isBraceError) {
2686
- return <CapError>{formatMessage(globalMessages.unbalanacedCurlyBraces)}</CapError>;
2694
+ tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
2687
2695
  }
2688
- return null;
2696
+ return <CapError>{tagError}</CapError>;
2689
2697
  };
2690
2698
 
2691
2699
  const editModeContent = () => (