@capillarytech/creatives-library 8.0.291 → 8.0.292-alpha.0

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 (52) hide show
  1. package/constants/unified.js +3 -1
  2. package/initialState.js +0 -2
  3. package/package.json +1 -1
  4. package/utils/common.js +5 -8
  5. package/utils/commonUtils.js +4 -85
  6. package/utils/tagValidations.js +83 -223
  7. package/utils/tests/commonUtil.test.js +147 -124
  8. package/utils/tests/tagValidations.test.js +441 -358
  9. package/v2Components/ErrorInfoNote/index.js +2 -5
  10. package/v2Components/FormBuilder/index.js +137 -203
  11. package/v2Components/FormBuilder/messages.js +0 -8
  12. package/v2Components/HtmlEditor/HTMLEditor.js +0 -5
  13. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +0 -1
  14. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +0 -15
  15. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +1 -2
  16. package/v2Containers/Cap/mockData.js +0 -14
  17. package/v2Containers/Cap/reducer.js +3 -55
  18. package/v2Containers/Cap/tests/reducer.test.js +0 -102
  19. package/v2Containers/CreativesContainer/SlideBoxContent.js +5 -1
  20. package/v2Containers/CreativesContainer/SlideBoxFooter.js +13 -5
  21. package/v2Containers/CreativesContainer/index.js +30 -7
  22. package/v2Containers/Email/index.js +1 -5
  23. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +23 -70
  24. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +29 -137
  25. package/v2Containers/FTP/index.js +2 -51
  26. package/v2Containers/FTP/messages.js +0 -4
  27. package/v2Containers/InApp/index.js +4 -104
  28. package/v2Containers/InApp/tests/index.test.js +17 -6
  29. package/v2Containers/InappAdvance/index.js +4 -108
  30. package/v2Containers/InappAdvance/tests/index.test.js +2 -0
  31. package/v2Containers/Line/Container/Text/index.js +0 -1
  32. package/v2Containers/MobilePush/Create/index.js +42 -19
  33. package/v2Containers/MobilePush/Edit/index.js +42 -19
  34. package/v2Containers/MobilePushNew/index.js +12 -32
  35. package/v2Containers/MobilepushWrapper/index.js +3 -1
  36. package/v2Containers/Rcs/index.js +12 -37
  37. package/v2Containers/Sms/Create/index.js +39 -3
  38. package/v2Containers/Sms/Create/messages.js +4 -0
  39. package/v2Containers/Sms/Edit/index.js +35 -3
  40. package/v2Containers/Sms/commonMethods.js +3 -6
  41. package/v2Containers/Sms/tests/commonMethods.test.js +122 -0
  42. package/v2Containers/SmsTrai/Edit/index.js +11 -47
  43. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
  44. package/v2Containers/SmsWrapper/index.js +2 -0
  45. package/v2Containers/Viber/index.js +0 -1
  46. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +1 -3
  47. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -7
  48. package/v2Containers/WebPush/Create/index.js +2 -2
  49. package/v2Containers/WebPush/Create/utils/validation.js +17 -2
  50. package/v2Containers/WebPush/Create/utils/validation.test.js +59 -24
  51. package/v2Containers/Whatsapp/index.js +9 -17
  52. package/v2Containers/Zalo/index.js +3 -11
@@ -4265,7 +4265,7 @@ FREE GIFTS-
4265
4265
  <CapCheckbox
4266
4266
  checked={false}
4267
4267
  disabled={false}
4268
- key=".4"
4268
+ key=".3"
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=".6"
4330
+ key=".5"
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=".4"
15179
+ key=".3"
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=".6"
15241
+ key=".5"
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=".4"
26120
+ key=".3"
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=".6"
26182
+ key=".5"
26183
26183
  style={
26184
26184
  Object {
26185
26185
  "marginBottom": "100px",
@@ -36,6 +36,7 @@ const SmsWrapper = (props) => {
36
36
  handleTestAndPreview,
37
37
  handleCloseTestAndPreview,
38
38
  isTestAndPreviewMode,
39
+ onValidationFail,
39
40
  } = props;
40
41
 
41
42
  const smsProps = {
@@ -58,6 +59,7 @@ const SmsWrapper = (props) => {
58
59
  handleTestAndPreview,
59
60
  handleCloseTestAndPreview,
60
61
  isTestAndPreviewMode,
62
+ onValidationFail,
61
63
  };
62
64
  const isTraiDlt = isTraiDLTEnable(isFullMode, smsRegister);
63
65
  return <>
@@ -234,7 +234,6 @@ export const Viber = (props) => {
234
234
  const { valid, isBraceError } = validateTags({
235
235
  content: value,
236
236
  tagsParam: tags,
237
- injectedTagsParams: injectedTags,
238
237
  location,
239
238
  tagModule: 'outbound',
240
239
  isFullMode,
@@ -105,12 +105,10 @@ export const useTagManagement = ({
105
105
  const validationConfig = useMemo(
106
106
  () => ({
107
107
  tagsParam: tags,
108
- injectedTagsParams: injectedTags,
109
108
  location,
110
109
  tagModule: getDefaultTags,
111
- eventContextTags,
112
110
  }),
113
- [tags, injectedTags, location, getDefaultTags, eventContextTags],
111
+ [tags, location, getDefaultTags],
114
112
  );
115
113
 
116
114
  return {
@@ -528,26 +528,19 @@ 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
-
534
531
  const { result } = renderHook(() =>
535
532
  useTagManagement({
536
533
  location: defaultLocation,
537
534
  globalActions: mockGlobalActions,
538
535
  metaEntities: defaultMetaEntities,
539
- injectedTags,
540
- eventContextTags,
541
536
  getDefaultTags: 'custom',
542
537
  })
543
538
  );
544
539
 
545
540
  expect(result.current.validationConfig).toEqual({
546
541
  tagsParam: defaultMetaEntities.tags.standard,
547
- injectedTagsParams: injectedTags,
548
542
  location: defaultLocation,
549
543
  tagModule: 'custom',
550
- eventContextTags,
551
544
  });
552
545
  });
553
546
 
@@ -295,8 +295,8 @@ const WebPushCreate = ({
295
295
  const validateTemplateName = useCallback((value) => validateTemplateNameUtil(value), []);
296
296
 
297
297
  const validateTitle = useCallback(
298
- (value) => validateTitleUtil(value, formatMessage, messages, restrictPersonalization),
299
- [formatMessage, restrictPersonalization],
298
+ (value) => validateTitleUtil(value, formatMessage, messages, restrictPersonalization, validationConfig, isFullMode),
299
+ [formatMessage, restrictPersonalization, validationConfig, isFullMode],
300
300
  );
301
301
 
302
302
  const validateUrl = useCallback(
@@ -11,19 +11,34 @@ import { hasPersonalizationTags } from '../../../../utils/commonUtils';
11
11
  export const validateTemplateName = (value) => !value || value.trim() === '';
12
12
 
13
13
  /**
14
- * Validates notification title
14
+ * Validates notification title (required and optional tag validation)
15
15
  * @param {string} value - The title value
16
16
  * @param {Function} formatMessage - i18n format message function
17
17
  * @param {Object} messages - Message definitions
18
+ * @param {Object} [validationConfig] - Optional config for tag validation
19
+ * @param {boolean} [isFullMode] - Optional; when set with validationConfig, runs tag validation
18
20
  * @returns {string} Error message if invalid, empty string if valid
19
21
  */
20
- export const validateTitle = (value, formatMessage, messages, restrictPersonalization) => {
22
+ export const validateTitle = (value, formatMessage, messages, restrictPersonalization, validationConfig, isFullMode) => {
21
23
  if (!value || value.trim() === '') {
22
24
  return formatMessage(messages.titleRequired);
23
25
  }
24
26
  if (restrictPersonalization && hasPersonalizationTags(value)) {
25
27
  return formatMessage(messages.personalizationTokensErrorMessage);
26
28
  }
29
+
30
+ if (validationConfig != null) {
31
+ const validationResponse = validateTags({
32
+ content: value,
33
+ ...validationConfig,
34
+ isFullMode,
35
+ }) || {};
36
+
37
+ if (validationResponse?.isBraceError) {
38
+ return formatMessage(globalMessages.unbalanacedCurlyBraces);
39
+ }
40
+ }
41
+
27
42
  return '';
28
43
  };
29
44
 
@@ -127,6 +127,40 @@ describe('validation', () => {
127
127
  expect(result).toBe('Personalization tags are not supported for anonymous customers');
128
128
  expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.personalizationTokensErrorMessage);
129
129
  });
130
+
131
+ it('should return brace error when validationConfig is provided and validateTags returns isBraceError', () => {
132
+ const validationConfig = { tagsParam: [], location: {}, tagModule: '' };
133
+ validateTags.mockReturnValue({ isBraceError: true });
134
+ const result = validateTitle(
135
+ 'Valid Title',
136
+ mockFormatMessage,
137
+ mockMessages,
138
+ false,
139
+ validationConfig,
140
+ false
141
+ );
142
+ expect(result).toBe('Unbalanced curly braces');
143
+ expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unbalanacedCurlyBraces);
144
+ expect(validateTags).toHaveBeenCalledWith({
145
+ content: 'Valid Title',
146
+ ...validationConfig,
147
+ isFullMode: false,
148
+ });
149
+ });
150
+
151
+ it('should not run tag validation when validationConfig is null', () => {
152
+ validateTags.mockClear();
153
+ const result = validateTitle('Valid Title', mockFormatMessage, mockMessages, false, null);
154
+ expect(result).toBe('');
155
+ expect(validateTags).not.toHaveBeenCalled();
156
+ });
157
+
158
+ it('should not run tag validation when validationConfig is undefined', () => {
159
+ validateTags.mockClear();
160
+ const result = validateTitle('Valid Title', mockFormatMessage, mockMessages, false, undefined);
161
+ expect(result).toBe('');
162
+ expect(validateTags).not.toHaveBeenCalled();
163
+ });
130
164
  });
131
165
 
132
166
  describe('validateUrl', () => {
@@ -183,10 +217,8 @@ describe('validation', () => {
183
217
  describe('validateMessageContent', () => {
184
218
  const mockValidationConfig = {
185
219
  tagsParam: [],
186
- injectedTagsParams: [],
187
220
  location: {},
188
221
  tagModule: '',
189
- eventContextTags: [],
190
222
  };
191
223
 
192
224
  beforeEach(() => {
@@ -225,17 +257,6 @@ describe('validation', () => {
225
257
  });
226
258
  });
227
259
 
228
- it('should return error message for unsupported tags', () => {
229
- validateTags.mockReturnValue({
230
- unsupportedTags: ['tag1', 'tag2'],
231
- });
232
- const result = validateMessageContent('Message with {tag1} and {tag2}', mockFormatMessage, mockMessages, mockValidationConfig);
233
- expect(result).toBe('Unsupported tags: tag1, tag2');
234
- expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unsupportedTagsValidationError, {
235
- unsupportedTags: 'tag1, tag2',
236
- });
237
- });
238
-
239
260
  it('should return error message for unbalanced curly braces', () => {
240
261
  validateTags.mockReturnValue({
241
262
  isBraceError: true,
@@ -245,22 +266,11 @@ describe('validation', () => {
245
266
  expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unbalanacedCurlyBraces);
246
267
  });
247
268
 
248
- it('should return error message for both unsupported tags and brace error (unsupported tags takes precedence)', () => {
249
- validateTags.mockReturnValue({
250
- unsupportedTags: ['tag1'],
251
- isBraceError: true,
252
- });
253
- const result = validateMessageContent('Message with {tag1}', mockFormatMessage, mockMessages, mockValidationConfig);
254
- expect(result).toBe('Unsupported tags: tag1');
255
- });
256
-
257
269
  it('should pass validation config to validateTags', () => {
258
270
  const customConfig = {
259
271
  tagsParam: [{ id: 1, name: 'Tag1' }],
260
- injectedTagsParams: [{ id: 2, name: 'Tag2' }],
261
272
  location: { query: { type: 'test' } },
262
273
  tagModule: 'custom',
263
- eventContextTags: [{ id: 3, name: 'Tag3' }],
264
274
  };
265
275
  validateTags.mockReturnValue({});
266
276
  validateMessageContent('Valid message', mockFormatMessage, mockMessages, customConfig);
@@ -306,6 +316,31 @@ describe('validation', () => {
306
316
  expect(result).toBe('Personalization tags are not supported for anonymous customers');
307
317
  expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.personalizationTokensErrorMessage);
308
318
  });
319
+
320
+ it('should return unsupported tags error when validateTags returns unsupportedTags', () => {
321
+ validateTags.mockReturnValue({ unsupportedTags: ['invalidTag', 'otherTag'] });
322
+ const result = validateMessageContent(
323
+ 'Hello {{invalidTag}}',
324
+ mockFormatMessage,
325
+ mockMessages,
326
+ mockValidationConfig
327
+ );
328
+ expect(result).toBe('Unsupported tags: invalidTag, otherTag');
329
+ expect(mockFormatMessage).toHaveBeenCalledWith(
330
+ globalMessages.unsupportedTagsValidationError,
331
+ { unsupportedTags: 'invalidTag, otherTag' }
332
+ );
333
+ });
334
+
335
+ it('should pass isFullMode to validateTags when provided', () => {
336
+ validateTags.mockReturnValue({});
337
+ validateMessageContent('Valid message', mockFormatMessage, mockMessages, mockValidationConfig, true);
338
+ expect(validateTags).toHaveBeenCalledWith({
339
+ content: 'Valid message',
340
+ ...mockValidationConfig,
341
+ isFullMode: true,
342
+ });
343
+ });
309
344
  });
310
345
  });
311
346
 
@@ -637,22 +637,21 @@ export const Whatsapp = (props) => {
637
637
  validateTags({
638
638
  content: contentData.join(""),
639
639
  tagsParam: tags,
640
- injectedTagsParams: injectedTags,
641
640
  location,
642
641
  tagModule: getDefaultTags,
643
- eventContextTags,
644
642
  isFullMode,
645
643
  }) || {};
646
- const unsupportedTagsLengthCheck =
647
- validationResponse?.unsupportedTags?.length > 0;
648
644
  if (type === HEADER_TEXT) {
649
645
  headerTagValidationResponse = validationResponse;
650
- updateIsHeaderTagValidationError(unsupportedTagsLengthCheck);
646
+ updateIsHeaderTagValidationError(validationResponse.isBraceError);
651
647
  } else if (type === CAROUSEL_TEXT) {
652
- return [{fieldName: "carouselTagValidationErrMessage", value: validationResponse}, {fieldName: "carouselTagValidationErr", value: unsupportedTagsLengthCheck}];
648
+ return [
649
+ { fieldName: "carouselTagValidationErrMessage", value: validationResponse.isBraceError ? validationResponse : {} },
650
+ { fieldName: "carouselTagValidationErr", value: validationResponse.isBraceError },
651
+ ];
653
652
  } else {
654
653
  tagValidationResponse = validationResponse;
655
- updateIsTagValidationError(unsupportedTagsLengthCheck);
654
+ updateIsTagValidationError(validationResponse.isBraceError);
656
655
  }
657
656
  }
658
657
  };
@@ -2682,18 +2681,11 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
2682
2681
  } else {
2683
2682
  validationResponse = tagValidationResponse;
2684
2683
  }
2685
- const { unsupportedTags = [], isBraceError } = validationResponse;
2686
-
2687
- let tagError = "";
2688
- if (unsupportedTags.length > 0) {
2689
- tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
2690
- unsupportedTags,
2691
- });
2692
- }
2684
+ const { isBraceError } = validationResponse || {};
2693
2685
  if (isBraceError) {
2694
- tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
2686
+ return <CapError>{formatMessage(globalMessages.unbalanacedCurlyBraces)}</CapError>;
2695
2687
  }
2696
- return <CapError>{tagError}</CapError>;
2688
+ return null;
2697
2689
  };
2698
2690
 
2699
2691
  const editModeContent = () => (
@@ -270,23 +270,15 @@ export const Zalo = (props) => {
270
270
  validateTags({
271
271
  content: message,
272
272
  tagsParam: tags,
273
- injectedTagsParams: injectedTags,
274
273
  location,
275
274
  tagModule: getDefaultTags,
276
- eventContextTags,
277
275
  isFullMode,
278
276
  }) || {};
279
- const { unsupportedTags = [], isBraceError } = tagValidationResponse;
280
- let tagError = '';
281
- if (unsupportedTags.length > 0) {
282
- tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
283
- unsupportedTags,
284
- });
285
- }
277
+ const { isBraceError } = tagValidationResponse;
286
278
  if (isBraceError) {
287
- tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
279
+ return formatMessage(globalMessages.unbalanacedCurlyBraces);
288
280
  }
289
- return tagError;
281
+ return '';
290
282
  };
291
283
 
292
284
  //this function is used for checking errror validation in this it validate tags error and length error