@capillarytech/creatives-library 8.0.125 → 8.0.127-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 (110) hide show
  1. package/config/app.js +6 -0
  2. package/containers/App/constants.js +1 -0
  3. package/index.html +3 -1
  4. package/initialReducer.js +2 -0
  5. package/package.json +1 -1
  6. package/services/api.js +94 -1
  7. package/services/tests/api.test.js +191 -0
  8. package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +8 -3
  9. package/tests/integration/TemplateCreation/api-response.js +5 -0
  10. package/tests/integration/TemplateCreation/msw-handler.js +42 -63
  11. package/utils/common.js +7 -0
  12. package/utils/commonUtils.js +2 -6
  13. package/utils/createPayload.js +272 -0
  14. package/utils/tests/createPayload.test.js +761 -0
  15. package/v2Components/CapImageUpload/index.js +59 -46
  16. package/v2Components/CapInAppCTA/index.js +1 -0
  17. package/v2Components/CapMpushCTA/constants.js +25 -0
  18. package/v2Components/CapMpushCTA/index.js +332 -0
  19. package/v2Components/CapMpushCTA/index.scss +95 -0
  20. package/v2Components/CapMpushCTA/messages.js +89 -0
  21. package/v2Components/CapTagList/index.js +177 -120
  22. package/v2Components/CapVideoUpload/constants.js +3 -0
  23. package/v2Components/CapVideoUpload/index.js +167 -110
  24. package/v2Components/CapVideoUpload/messages.js +16 -0
  25. package/v2Components/Carousel/index.js +15 -13
  26. package/v2Components/CustomerSearchSection/_customerSearch.scss +309 -0
  27. package/v2Components/CustomerSearchSection/constants.js +5 -0
  28. package/v2Components/CustomerSearchSection/index.js +367 -0
  29. package/v2Components/CustomerSearchSection/messages.js +20 -0
  30. package/v2Components/CustomerSearchSection/tests/utils.test.js +334 -0
  31. package/v2Components/CustomerSearchSection/utils.js +49 -0
  32. package/v2Components/ErrorInfoNote/style.scss +1 -0
  33. package/v2Components/MobilePushPreviewV2/index.js +37 -5
  34. package/v2Components/TemplatePreview/_templatePreview.scss +114 -72
  35. package/v2Components/TemplatePreview/assets/images/Android _ With date and time.svg +29 -0
  36. package/v2Components/TemplatePreview/assets/images/android.svg +9 -0
  37. package/v2Components/TemplatePreview/assets/images/iOS _ With date and time.svg +26 -0
  38. package/v2Components/TemplatePreview/assets/images/ios.svg +9 -0
  39. package/v2Components/TemplatePreview/index.js +178 -50
  40. package/v2Components/TemplatePreview/messages.js +4 -0
  41. package/v2Components/TestAndPreviewSlidebox/CustomValuesEditor.js +169 -0
  42. package/v2Components/TestAndPreviewSlidebox/LeftPanelContent.js +95 -0
  43. package/v2Components/TestAndPreviewSlidebox/PreviewSection.js +69 -0
  44. package/v2Components/TestAndPreviewSlidebox/SendTestMessage.js +68 -0
  45. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +543 -0
  46. package/v2Components/TestAndPreviewSlidebox/actions.js +67 -0
  47. package/v2Components/TestAndPreviewSlidebox/constants.js +67 -0
  48. package/v2Components/TestAndPreviewSlidebox/index.js +592 -0
  49. package/v2Components/TestAndPreviewSlidebox/messages.js +147 -0
  50. package/v2Components/TestAndPreviewSlidebox/reducer.js +233 -0
  51. package/v2Components/TestAndPreviewSlidebox/sagas.js +258 -0
  52. package/v2Components/TestAndPreviewSlidebox/selectors.js +142 -0
  53. package/v2Components/TestAndPreviewSlidebox/tests/CustomValuesEditor.test.js +425 -0
  54. package/v2Components/TestAndPreviewSlidebox/tests/LeftPanelContent.test.js +400 -0
  55. package/v2Components/TestAndPreviewSlidebox/tests/SendTestMessage.test.js +448 -0
  56. package/v2Components/TestAndPreviewSlidebox/tests/actions.test.js +80 -0
  57. package/v2Components/TestAndPreviewSlidebox/tests/reducer.test.js +367 -0
  58. package/v2Components/TestAndPreviewSlidebox/tests/saga.rtl.test.js +192 -0
  59. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +652 -0
  60. package/v2Components/TestAndPreviewSlidebox/tests/selector.test.js +182 -0
  61. package/v2Containers/CreativesContainer/SlideBoxContent.js +22 -10
  62. package/v2Containers/CreativesContainer/SlideBoxFooter.js +23 -2
  63. package/v2Containers/CreativesContainer/index.js +216 -136
  64. package/v2Containers/CreativesContainer/messages.js +4 -0
  65. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +21 -0
  66. package/v2Containers/Email/index.js +27 -2
  67. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +10 -0
  68. package/v2Containers/EmailWrapper/index.js +6 -0
  69. package/v2Containers/InApp/constants.js +1 -0
  70. package/v2Containers/InApp/index.js +13 -13
  71. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  72. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  73. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  74. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  75. package/v2Containers/MobilePush/Create/index.js +1 -0
  76. package/v2Containers/MobilePush/commonMethods.js +7 -14
  77. package/v2Containers/MobilePushNew/actions.js +116 -0
  78. package/v2Containers/MobilePushNew/components/CtaButtons.js +170 -0
  79. package/v2Containers/MobilePushNew/components/MediaUploaders.js +754 -0
  80. package/v2Containers/MobilePushNew/components/PlatformContentFields.js +279 -0
  81. package/v2Containers/MobilePushNew/components/index.js +5 -0
  82. package/v2Containers/MobilePushNew/components/tests/CtaButtons.test.js +779 -0
  83. package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +2114 -0
  84. package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +343 -0
  85. package/v2Containers/MobilePushNew/constants.js +115 -0
  86. package/v2Containers/MobilePushNew/hooks/tests/usePlatformSync.test.js +1299 -0
  87. package/v2Containers/MobilePushNew/hooks/tests/useUpload.test.js +1223 -0
  88. package/v2Containers/MobilePushNew/hooks/usePlatformSync.js +246 -0
  89. package/v2Containers/MobilePushNew/hooks/useUpload.js +726 -0
  90. package/v2Containers/MobilePushNew/index.js +2280 -0
  91. package/v2Containers/MobilePushNew/index.scss +308 -0
  92. package/v2Containers/MobilePushNew/messages.js +226 -0
  93. package/v2Containers/MobilePushNew/reducer.js +160 -0
  94. package/v2Containers/MobilePushNew/sagas.js +198 -0
  95. package/v2Containers/MobilePushNew/selectors.js +55 -0
  96. package/v2Containers/MobilePushNew/tests/reducer.test.js +741 -0
  97. package/v2Containers/MobilePushNew/tests/sagas.test.js +863 -0
  98. package/v2Containers/MobilePushNew/tests/selectors.test.js +425 -0
  99. package/v2Containers/MobilePushNew/tests/utils.test.js +322 -0
  100. package/v2Containers/MobilePushNew/utils.js +33 -0
  101. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +23 -5
  102. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  103. package/v2Containers/TagList/index.js +56 -10
  104. package/v2Containers/Templates/_templates.scss +101 -1
  105. package/v2Containers/Templates/index.js +147 -35
  106. package/v2Containers/Templates/messages.js +8 -0
  107. package/v2Containers/Templates/sagas.js +2 -0
  108. package/v2Containers/Whatsapp/constants.js +1 -0
  109. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -0
  110. package/v2Containers/Email/tests/index.test.js +0 -35
@@ -0,0 +1,334 @@
1
+ import {
2
+ checkForData,
3
+ removeExtraIdentifiers,
4
+ identifiersHighlight,
5
+ getNamingIcon,
6
+ } from '../utils';
7
+
8
+ describe('CustomerSearchSection Utils', () => {
9
+ describe('checkForData', () => {
10
+ it('should return filtered data based on source', () => {
11
+ const mockData = [
12
+ { source: 'INSTORE', value: 'test1' },
13
+ { source: 'ONLINE', value: 'test2' },
14
+ { source: 'INSTORE', value: 'test3' },
15
+ ];
16
+
17
+ const result = checkForData(mockData, 'INSTORE');
18
+
19
+ expect(result).toEqual([
20
+ { source: 'INSTORE', value: 'test1' },
21
+ { source: 'INSTORE', value: 'test3' },
22
+ ]);
23
+ expect(result).toHaveLength(2);
24
+ });
25
+
26
+ it('should return empty array when no matching source found', () => {
27
+ const mockData = [
28
+ { source: 'ONLINE', value: 'test1' },
29
+ { source: 'MOBILE', value: 'test2' },
30
+ ];
31
+
32
+ const result = checkForData(mockData, 'INSTORE');
33
+
34
+ expect(result).toEqual([]);
35
+ expect(result).toHaveLength(0);
36
+ });
37
+
38
+ it('should handle null/undefined data gracefully', () => {
39
+ expect(checkForData(null, 'INSTORE')).toBeUndefined();
40
+ expect(checkForData(undefined, 'INSTORE')).toBeUndefined();
41
+ expect(checkForData([], 'INSTORE')).toEqual([]);
42
+ });
43
+
44
+ it('should handle empty data array', () => {
45
+ const result = checkForData([], 'INSTORE');
46
+ expect(result).toEqual([]);
47
+ });
48
+
49
+ it('should handle case when source parameter is null/undefined', () => {
50
+ const mockData = [
51
+ { source: 'INSTORE', value: 'test1' },
52
+ { source: 'ONLINE', value: 'test2' },
53
+ ];
54
+
55
+ expect(checkForData(mockData, null)).toEqual([]);
56
+ expect(checkForData(mockData, undefined)).toEqual([]);
57
+ });
58
+ });
59
+
60
+ describe('removeExtraIdentifiers', () => {
61
+ const mockData = [
62
+ { idType: 'FIRSTNAME', idValue: 'John' },
63
+ { idType: 'LASTNAME', idValue: 'Doe' },
64
+ { idType: 'EMAIL', idValue: 'john@example.com' },
65
+ { idType: 'PHONE', idValue: '123456789' },
66
+ { idType: 'FIRSTNAME', idValue: 'Jane' },
67
+ ];
68
+
69
+ it('should remove identifiers with specified types', () => {
70
+ const result = removeExtraIdentifiers(mockData, 'FIRSTNAME', 'LASTNAME');
71
+
72
+ expect(result).toEqual([
73
+ { idType: 'EMAIL', idValue: 'john@example.com' },
74
+ { idType: 'PHONE', idValue: '123456789' },
75
+ ]);
76
+ expect(result).toHaveLength(2);
77
+ });
78
+
79
+ it('should return original data when no matching identifiers found', () => {
80
+ const result = removeExtraIdentifiers(mockData, 'NONEXISTENT', 'ALSO_NONEXISTENT');
81
+
82
+ expect(result).toEqual(mockData);
83
+ expect(result).toHaveLength(5);
84
+ });
85
+
86
+ it('should handle empty data array', () => {
87
+ const result = removeExtraIdentifiers([], 'FIRSTNAME', 'LASTNAME');
88
+ expect(result).toEqual([]);
89
+ });
90
+
91
+ it('should handle null/undefined data gracefully', () => {
92
+ expect(removeExtraIdentifiers(null, 'FIRSTNAME', 'LASTNAME')).toBeNull();
93
+ expect(removeExtraIdentifiers(undefined, 'FIRSTNAME', 'LASTNAME')).toBeUndefined();
94
+ });
95
+
96
+ it('should handle single identifier type to remove', () => {
97
+ const result = removeExtraIdentifiers(mockData, 'EMAIL', 'NONEXISTENT');
98
+
99
+ expect(result).toEqual([
100
+ { idType: 'FIRSTNAME', idValue: 'John' },
101
+ { idType: 'LASTNAME', idValue: 'Doe' },
102
+ { idType: 'PHONE', idValue: '123456789' },
103
+ { idType: 'FIRSTNAME', idValue: 'Jane' },
104
+ ]);
105
+ expect(result).toHaveLength(4);
106
+ });
107
+
108
+ it('should handle case when all identifiers match removal criteria', () => {
109
+ const onlyFirstLastData = [
110
+ { idType: 'FIRSTNAME', idValue: 'John' },
111
+ { idType: 'LASTNAME', idValue: 'Doe' },
112
+ ];
113
+
114
+ const result = removeExtraIdentifiers(onlyFirstLastData, 'FIRSTNAME', 'LASTNAME');
115
+
116
+ expect(result).toEqual([]);
117
+ expect(result).toHaveLength(0);
118
+ });
119
+ });
120
+
121
+ describe('identifiersHighlight', () => {
122
+ const mockData = [
123
+ { idValue: 'john@example.com' },
124
+ { idValue: 'jane.doe@test.com' },
125
+ { idValue: 'abcdefghijk' },
126
+ ];
127
+
128
+ it('should highlight search string in identifiers', () => {
129
+ const result = identifiersHighlight('john', mockData);
130
+
131
+ expect(result).toEqual([
132
+ {
133
+ firstString: '',
134
+ secondString: 'john',
135
+ thirdString: '@example.com',
136
+ },
137
+ {
138
+ firstString: '',
139
+ secondString: 'jan',
140
+ thirdString: 'e.doe@test.com',
141
+ },
142
+ {
143
+ firstString: '',
144
+ secondString: 'abc',
145
+ thirdString: 'defghijk',
146
+ },
147
+ ]);
148
+ });
149
+
150
+ it('should handle search string in middle of identifier', () => {
151
+ const result = identifiersHighlight('example', mockData);
152
+
153
+ expect(result).toEqual([
154
+ {
155
+ firstString: 'john@',
156
+ secondString: 'example',
157
+ thirdString: '.com',
158
+ },
159
+ {
160
+ firstString: '',
161
+ secondString: 'jane.d',
162
+ thirdString: 'oe@test.com',
163
+ },
164
+ {
165
+ firstString: '',
166
+ secondString: 'abcdef',
167
+ thirdString: 'ghijk',
168
+ },
169
+ ]);
170
+ });
171
+
172
+ it('should handle search string at end of identifier', () => {
173
+ const result = identifiersHighlight('com', mockData);
174
+
175
+ expect(result).toEqual([
176
+ {
177
+ firstString: 'john@example.',
178
+ secondString: 'com',
179
+ thirdString: '',
180
+ },
181
+ {
182
+ firstString: 'jane.doe@test.',
183
+ secondString: 'com',
184
+ thirdString: '',
185
+ },
186
+ {
187
+ firstString: '',
188
+ secondString: 'ab',
189
+ thirdString: 'cdefghijk',
190
+ },
191
+ ]);
192
+ });
193
+
194
+ it('should handle empty data array', () => {
195
+ const result = identifiersHighlight('john', []);
196
+ expect(result).toBeUndefined();
197
+ });
198
+
199
+ it('should handle null/undefined data gracefully', () => {
200
+ expect(identifiersHighlight('john', null)).toBeUndefined();
201
+ expect(identifiersHighlight('john', undefined)).toBeUndefined();
202
+ });
203
+
204
+ it('should handle empty search string', () => {
205
+ const result = identifiersHighlight('', mockData);
206
+
207
+ expect(result).toEqual([
208
+ {
209
+ firstString: '',
210
+ secondString: '',
211
+ thirdString: 'john@example.com',
212
+ },
213
+ {
214
+ firstString: '',
215
+ secondString: '',
216
+ thirdString: 'jane.doe@test.com',
217
+ },
218
+ {
219
+ firstString: '',
220
+ secondString: '',
221
+ thirdString: 'abcdefghijk',
222
+ },
223
+ ]);
224
+ });
225
+
226
+ it('should handle case when search string is not found', () => {
227
+ const result = identifiersHighlight('xyz', mockData);
228
+
229
+ expect(result).toEqual([
230
+ {
231
+ firstString: '',
232
+ secondString: 'jo',
233
+ thirdString: 'hn@example.com',
234
+ },
235
+ {
236
+ firstString: '',
237
+ secondString: 'ja',
238
+ thirdString: 'ne.doe@test.com',
239
+ },
240
+ {
241
+ firstString: '',
242
+ secondString: 'ab',
243
+ thirdString: 'cdefghijk',
244
+ },
245
+ ]);
246
+ });
247
+
248
+ it('should handle data with null/undefined idValue', () => {
249
+ const dataWithNullValues = [
250
+ { idValue: null },
251
+ { idValue: undefined },
252
+ { idValue: 'valid@email.com' },
253
+ ];
254
+
255
+ const result = identifiersHighlight('valid', dataWithNullValues);
256
+
257
+ expect(result).toEqual([
258
+ {
259
+ firstString: undefined,
260
+ secondString: undefined,
261
+ thirdString: undefined,
262
+ },
263
+ {
264
+ firstString: undefined,
265
+ secondString: undefined,
266
+ thirdString: undefined,
267
+ },
268
+ {
269
+ firstString: '',
270
+ secondString: 'valid',
271
+ thirdString: '@email.com',
272
+ },
273
+ ]);
274
+ });
275
+ });
276
+
277
+ describe('getNamingIcon', () => {
278
+ it('should return two uppercase initials for full name', () => {
279
+ expect(getNamingIcon('John Doe')).toBe('JD');
280
+ expect(getNamingIcon('Jane Smith')).toBe('JS');
281
+ expect(getNamingIcon('Mary Jane Watson')).toBe('MJ');
282
+ });
283
+
284
+ it('should return first two letters for single name', () => {
285
+ expect(getNamingIcon('John')).toBe('JO');
286
+ expect(getNamingIcon('Jane')).toBe('JA');
287
+ expect(getNamingIcon('Ab')).toBe('AB');
288
+ });
289
+
290
+ it('should handle names with extra spaces', () => {
291
+ expect(getNamingIcon('John Doe')).toBe('JD');
292
+ expect(getNamingIcon('Jane Smith')).toBe('JS');
293
+ });
294
+
295
+ it('should handle empty string', () => {
296
+ expect(getNamingIcon('')).toBe('');
297
+ });
298
+
299
+ it('should handle null/undefined gracefully', () => {
300
+ expect(() => getNamingIcon(null)).toThrow();
301
+ expect(() => getNamingIcon(undefined)).toThrow();
302
+ });
303
+
304
+ it('should handle lowercase names', () => {
305
+ expect(getNamingIcon('john doe')).toBe('JD');
306
+ expect(getNamingIcon('jane smith')).toBe('JS');
307
+ });
308
+
309
+ it('should handle mixed case names', () => {
310
+ expect(getNamingIcon('jOhN dOe')).toBe('JD');
311
+ expect(getNamingIcon('JaNe SmItH')).toBe('JS');
312
+ });
313
+
314
+ it('should handle special characters in names', () => {
315
+ expect(getNamingIcon('John-Doe')).toBe('JO');
316
+ expect(getNamingIcon("O'Connor Smith")).toBe('OS');
317
+ });
318
+
319
+ it('should handle very long names', () => {
320
+ expect(getNamingIcon('Johnathon Christopher')).toBe('JC');
321
+ expect(getNamingIcon('A B C D E F G')).toBe('AB');
322
+ });
323
+
324
+ it('should handle names with numbers', () => {
325
+ expect(getNamingIcon('John2 Doe3')).toBe('JD');
326
+ expect(getNamingIcon('User123')).toBe('US');
327
+ });
328
+
329
+ it('should handle single character names', () => {
330
+ expect(getNamingIcon('A')).toBe('A');
331
+ expect(getNamingIcon('X')).toBe('X');
332
+ });
333
+ });
334
+ });
@@ -0,0 +1,49 @@
1
+ export const checkForData = (data, source) => {
2
+ const expectedData = data?.filter((d) => d?.source === source);
3
+ return expectedData;
4
+ };
5
+
6
+ export const removeExtraIdentifiers = (
7
+ data,
8
+ identiferFirstKey,
9
+ identifiersSecondKey,
10
+ ) => {
11
+ let finalResult = data;
12
+ const extraIdentifiers = data?.filter(
13
+ (d) => d?.idType === identiferFirstKey || d?.idType === identifiersSecondKey,
14
+ );
15
+ finalResult = extraIdentifiers?.length > 0
16
+ ? data?.filter((item) => extraIdentifiers?.indexOf(item) === -1)
17
+ : data;
18
+
19
+ return finalResult;
20
+ };
21
+
22
+ export const identifiersHighlight = (searchString, data) => {
23
+ let finalResult;
24
+ if (data?.length > 0) {
25
+ finalResult = data?.map((d) => {
26
+ const searchedStringIndex = d?.idValue?.indexOf(searchString);
27
+ const searchStringLength = searchString?.length;
28
+ const sliceString = searchedStringIndex + searchStringLength;
29
+ return {
30
+ firstString: d?.idValue?.substring(0, searchedStringIndex),
31
+ secondString: d?.idValue?.substring(searchedStringIndex, sliceString),
32
+ thirdString: d?.idValue?.substring(sliceString),
33
+ };
34
+ });
35
+ }
36
+ return finalResult;
37
+ };
38
+
39
+ // Name breaking icon
40
+ export const getNamingIcon = (data) => {
41
+ let returnedString;
42
+ const splitStrings = data?.split(' ');
43
+ returnedString = splitStrings?.length > 1
44
+ ? splitStrings[0].charAt(0).toUpperCase()
45
+ + splitStrings[1].charAt(0).toUpperCase()
46
+ : splitStrings[0].charAt(0).toUpperCase()
47
+ + splitStrings[0].charAt(1).toUpperCase();
48
+ return returnedString;
49
+ };
@@ -1,6 +1,7 @@
1
1
  @import "~@capillarytech/cap-ui-library/styles/_variables.scss";
2
2
 
3
3
  .error-container {
4
+ width: max-content;
4
5
  margin-bottom: $CAP_SPACE_08;
5
6
  margin-top: $CAP_SPACE_12;
6
7
  background-color: $CAP_COLOR_05;
@@ -15,6 +15,7 @@ import { MOBILE_PUSH } from '../../v2Containers/CreativesContainer/constants';
15
15
  import { INAPP } from '../../v2Containers/App/constants';
16
16
  import { ANDROID, IOS } from '../../v2Containers/InApp/constants';
17
17
  import { getCtaObject } from '../../v2Containers/InApp/utils';
18
+ import { VIDEO } from '../../v2Containers/MobilePushNew/constants';
18
19
 
19
20
  class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react/prefer-stateless-function
20
21
  constructor(props) {
@@ -64,14 +65,40 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
64
65
  const androidContent = get(templateData, 'versions.base.ANDROID') || get(templateData, 'androidContent');
65
66
  const iosContent = get(templateData, 'versions.base.IOS') || get(templateData, 'iosContent');
66
67
 
67
- const data = device === "android" ? androidContent : iosContent;
68
- const { title = '', message = '', expandableDetails: { ctas = [], image = '' } = {}} = data || {};
68
+ const data = device?.toLowerCase() === "android" ? androidContent : iosContent;
69
+ const { title = '', message = '', expandableDetails: { ctas = [], image = '', media = [], carouselData = [] } = {}} = data || {};
70
+
71
+ // Handle video/GIF content from expandableDetails.media array (new format)
72
+ let bodyVideo = {};
73
+ let bodyGif = '';
74
+ let bodyImage = image;
75
+
76
+ if (media && Array.isArray(media) && media.length > 0) {
77
+ const mediaItem = media[0];
78
+ if (mediaItem.type === VIDEO) {
79
+ // Distinguish between actual video and GIF based on URL extension
80
+ if (mediaItem.url && mediaItem.url.toLowerCase().includes('.gif')) {
81
+ bodyGif = mediaItem.url;
82
+ } else {
83
+ bodyVideo = {
84
+ videoSrc: mediaItem.url,
85
+ videoPreview: mediaItem.url,
86
+ };
87
+ }
88
+ // Clear bodyImage when we have video/GIF content
89
+ bodyImage = '';
90
+ }
91
+ }
92
+
69
93
  content = {
70
94
  header: title,
71
95
  bodyText: message,
72
- bodyImage: image,
96
+ bodyImage,
97
+ bodyVideo,
98
+ bodyGif,
73
99
  actions: [],
74
100
  appName: templateData?.appName,
101
+ carouselData,
75
102
  };
76
103
  if (ctas && ctas?.length) {
77
104
  if (device === "android" ) {
@@ -83,6 +110,7 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
83
110
  }
84
111
  return content;
85
112
  }
113
+
86
114
  getPreview(device) {
87
115
  const deviceParam = device === ANDROID.toLowerCase() ? ANDROID : IOS;
88
116
  return (
@@ -95,17 +123,21 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
95
123
  />
96
124
  );
97
125
  }
126
+
98
127
  goToDuplicate() {
99
128
  this.props.onDuplicateClick(this.props.templateData);
100
129
  this.props.handleClose();
101
130
  }
131
+
102
132
  changeDevice(device) {
103
133
  const content = this.setContent(this.props.templateData, device, this.props.channel);
104
134
  this.setState({device, content });
105
135
  }
136
+
106
137
  goToEdit(e, path) {
107
138
  this.props.onEditClick(e, this.props.templateData._id, this.props.templateData.modeType, path);
108
139
  }
140
+
109
141
  render() {
110
142
  const {templateData} = this.props;
111
143
  let hasAndroid;
@@ -121,8 +153,8 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
121
153
  return (
122
154
  <div>
123
155
  <div className="devices">
124
- {!isEmpty(templateData) &&
125
- ( hasBothAndroidAndIos ? (
156
+ {!isEmpty(templateData)
157
+ && ( hasBothAndroidAndIos ? (
126
158
  <CapTab
127
159
  panes={[
128
160
  {