@capillarytech/creatives-library 8.0.340-beta.0.5 → 8.0.340-beta.0.6
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.
- package/constants/unified.js +1 -0
- package/package.json +1 -1
- package/services/api.js +20 -0
- package/services/tests/api.test.js +59 -0
- package/utils/common.js +6 -0
- package/utils/test-utils.js +2 -2
- package/utils/tests/v2Common.test.js +46 -1
- package/utils/v2common.js +18 -0
- package/v2Components/CapTagList/index.js +5 -6
- package/v2Components/CommonTestAndPreview/UnifiedPreview/WhatsAppPreviewContent.js +18 -6
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +27 -0
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/WhatsAppPreviewContent.test.js +48 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +21 -0
- package/v2Components/TemplatePreview/index.js +18 -6
- package/v2Components/TemplatePreview/tests/__snapshots__/index.test.js.snap +1 -0
- package/v2Containers/Assets/images/archive_Empty_Illustration.svg +9 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +28 -20
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +24 -16
- package/v2Containers/CreativesContainer/SlideBoxContent.js +16 -5
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -1
- package/v2Containers/CreativesContainer/index.js +14 -1
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +2 -4
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +3 -0
- package/v2Containers/Email/reducer.js +12 -3
- package/v2Containers/Email/sagas.js +9 -4
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +4 -0
- package/v2Containers/Email/tests/reducer.test.js +47 -0
- package/v2Containers/Email/tests/sagas.test.js +146 -6
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +8 -1
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +7 -0
- package/v2Containers/Sms/Create/index.js +3 -0
- package/v2Containers/Templates/ChannelTypeIllustration.js +23 -6
- package/v2Containers/Templates/_templates.scss +155 -24
- package/v2Containers/Templates/actions.js +44 -0
- package/v2Containers/Templates/constants.js +31 -0
- package/v2Containers/Templates/index.js +400 -59
- package/v2Containers/Templates/messages.js +96 -0
- package/v2Containers/Templates/reducer.js +84 -1
- package/v2Containers/Templates/sagas.js +64 -0
- package/v2Containers/Templates/selectors.js +12 -0
- package/v2Containers/Templates/tests/ChannelTypeIllustration.test.js +12 -0
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1166 -1112
- package/v2Containers/Templates/tests/index.test.js +6 -0
- package/v2Containers/Templates/tests/reducer.test.js +178 -0
- package/v2Containers/Templates/tests/sagas.test.js +390 -8
- package/v2Containers/Templates/tests/selector.test.js +32 -0
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -1
- package/v2Containers/Viber/constants.js +8 -0
- package/v2Containers/Viber/index.js +5 -0
- package/v2Containers/Viber/messages.js +4 -0
- package/v2Containers/Viber/reducer.js +26 -3
- package/v2Containers/Viber/sagas.js +50 -8
- package/v2Containers/Viber/tests/index.test.js +80 -0
- package/v2Containers/Viber/tests/reducer.test.js +297 -0
- package/v2Containers/Viber/tests/saga.test.js +412 -40
- package/v2Containers/Whatsapp/constants.js +8 -0
- package/v2Containers/Whatsapp/index.js +145 -5
- package/v2Containers/Whatsapp/index.scss +12 -0
- package/v2Containers/Whatsapp/messages.js +16 -0
package/constants/unified.js
CHANGED
|
@@ -52,6 +52,7 @@ export const EXTENDED_TAG = 'ExtendedTagMessage';
|
|
|
52
52
|
export const BADGES_UI_ENABLED = 'BADGES_UI_ENABLED';
|
|
53
53
|
export const JP_LOCALE_HIDE_FEATURE = 'JP_LOCALE_HIDE_FEATURE';
|
|
54
54
|
export const ENABLE_WECHAT = 'ENABLE_WECHAT';
|
|
55
|
+
export const ENABLE_CREATIVES_ARCHIVAL = 'ENABLE_CREATIVES_ARCHIVAL';
|
|
55
56
|
export const ENABLE_WEBPUSH = 'ENABLE_WEBPUSH';
|
|
56
57
|
export const ENABLE_CUSTOMER_BARCODE_TAG = 'ENABLE_CUSTOMER_BARCODE_TAG';
|
|
57
58
|
export const EMAIL_UNSUBSCRIBE_TAG_MANDATORY = 'EMAIL_UNSUBSCRIBE_TAG_MANDATORY';
|
package/package.json
CHANGED
package/services/api.js
CHANGED
|
@@ -361,6 +361,26 @@ export const deleteTemplate = ({channel, id}) => {
|
|
|
361
361
|
//return API.deleteResource(url);
|
|
362
362
|
};
|
|
363
363
|
|
|
364
|
+
export const archiveTemplate = ({ channel, id }) => {
|
|
365
|
+
const url = `${API_ENDPOINT}/templates/archive/${id}/${channel}`;
|
|
366
|
+
return request(url, getAPICallObject('PUT'));
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
export const unarchiveTemplate = ({ channel, id }) => {
|
|
370
|
+
const url = `${API_ENDPOINT}/templates/unarchive/${id}/${channel}`;
|
|
371
|
+
return request(url, getAPICallObject('PUT'));
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
export const bulkArchiveTemplates = ({ channel, ids }) => {
|
|
375
|
+
const url = `${API_ENDPOINT}/templates/archive/bulk/${channel}`;
|
|
376
|
+
return request(url, getAPICallObject('PUT', { ids }));
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
export const bulkUnarchiveTemplates = ({ channel, ids }) => {
|
|
380
|
+
const url = `${API_ENDPOINT}/templates/unarchive/bulk/${channel}`;
|
|
381
|
+
return request(url, getAPICallObject('PUT', { ids }));
|
|
382
|
+
};
|
|
383
|
+
|
|
364
384
|
export const deleteRcsTemplate = ({ templateName }) => {
|
|
365
385
|
const url = `${API_ENDPOINT}/templates/${templateName}/RCS`;
|
|
366
386
|
return request(url, getAPICallObject('DELETE'))
|
|
@@ -1086,3 +1086,62 @@ describe('createTestCustomer', () => {
|
|
|
1086
1086
|
expect(lastCall[1].body).toBe(JSON.stringify(payload));
|
|
1087
1087
|
});
|
|
1088
1088
|
});
|
|
1089
|
+
|
|
1090
|
+
import {
|
|
1091
|
+
archiveTemplate,
|
|
1092
|
+
unarchiveTemplate,
|
|
1093
|
+
bulkArchiveTemplates,
|
|
1094
|
+
bulkUnarchiveTemplates,
|
|
1095
|
+
} from '../api';
|
|
1096
|
+
|
|
1097
|
+
describe('archiveTemplate', () => {
|
|
1098
|
+
beforeEach(() => {
|
|
1099
|
+
global.fetch = jest.fn().mockReturnValue(Promise.resolve({ json: () => Promise.resolve({}) }));
|
|
1100
|
+
});
|
|
1101
|
+
|
|
1102
|
+
it('should call PUT on archive endpoint', () => {
|
|
1103
|
+
archiveTemplate({ channel: 'EMAIL', id: 'id123' });
|
|
1104
|
+
expect(global.fetch).toHaveBeenCalled();
|
|
1105
|
+
const lastCall = global.fetch.mock.calls[global.fetch.mock.calls.length - 1];
|
|
1106
|
+
expect(lastCall[1].method).toBe('PUT');
|
|
1107
|
+
});
|
|
1108
|
+
});
|
|
1109
|
+
|
|
1110
|
+
describe('unarchiveTemplate', () => {
|
|
1111
|
+
beforeEach(() => {
|
|
1112
|
+
global.fetch = jest.fn().mockReturnValue(Promise.resolve({ json: () => Promise.resolve({}) }));
|
|
1113
|
+
});
|
|
1114
|
+
|
|
1115
|
+
it('should call PUT on unarchive endpoint', () => {
|
|
1116
|
+
unarchiveTemplate({ channel: 'EMAIL', id: 'id123' });
|
|
1117
|
+
expect(global.fetch).toHaveBeenCalled();
|
|
1118
|
+
const lastCall = global.fetch.mock.calls[global.fetch.mock.calls.length - 1];
|
|
1119
|
+
expect(lastCall[1].method).toBe('PUT');
|
|
1120
|
+
});
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
describe('bulkArchiveTemplates', () => {
|
|
1124
|
+
beforeEach(() => {
|
|
1125
|
+
global.fetch = jest.fn().mockReturnValue(Promise.resolve({ json: () => Promise.resolve({}) }));
|
|
1126
|
+
});
|
|
1127
|
+
|
|
1128
|
+
it('should call PUT on bulk archive endpoint with ids', () => {
|
|
1129
|
+
bulkArchiveTemplates({ channel: 'EMAIL', ids: ['id1', 'id2'] });
|
|
1130
|
+
expect(global.fetch).toHaveBeenCalled();
|
|
1131
|
+
const lastCall = global.fetch.mock.calls[global.fetch.mock.calls.length - 1];
|
|
1132
|
+
expect(lastCall[1].method).toBe('PUT');
|
|
1133
|
+
});
|
|
1134
|
+
});
|
|
1135
|
+
|
|
1136
|
+
describe('bulkUnarchiveTemplates', () => {
|
|
1137
|
+
beforeEach(() => {
|
|
1138
|
+
global.fetch = jest.fn().mockReturnValue(Promise.resolve({ json: () => Promise.resolve({}) }));
|
|
1139
|
+
});
|
|
1140
|
+
|
|
1141
|
+
it('should call PUT on bulk unarchive endpoint with ids', () => {
|
|
1142
|
+
bulkUnarchiveTemplates({ channel: 'EMAIL', ids: ['id1', 'id2'] });
|
|
1143
|
+
expect(global.fetch).toHaveBeenCalled();
|
|
1144
|
+
const lastCall = global.fetch.mock.calls[global.fetch.mock.calls.length - 1];
|
|
1145
|
+
expect(lastCall[1].method).toBe('PUT');
|
|
1146
|
+
});
|
|
1147
|
+
});
|
package/utils/common.js
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
ENABLE_NEW_MPUSH,
|
|
28
28
|
ENABLE_NEW_EDITOR_FLOW_INAPP,
|
|
29
29
|
SUPPORT_ENGAGEMENT_MODULE,
|
|
30
|
+
ENABLE_CREATIVES_ARCHIVAL,
|
|
30
31
|
} from '../constants/unified';
|
|
31
32
|
import { apiMessageFormatHandler } from './commonUtils';
|
|
32
33
|
|
|
@@ -122,6 +123,11 @@ export const hasWechatFeatureEnabled = Auth.hasFeatureAccess.bind(
|
|
|
122
123
|
ENABLE_WECHAT,
|
|
123
124
|
);
|
|
124
125
|
|
|
126
|
+
export const hasCreativesArchivalEnabled = Auth.hasFeatureAccess.bind(
|
|
127
|
+
null,
|
|
128
|
+
ENABLE_CREATIVES_ARCHIVAL,
|
|
129
|
+
);
|
|
130
|
+
|
|
125
131
|
export const hasWebPushFeatureEnabled = Auth.hasFeatureAccess.bind(
|
|
126
132
|
null,
|
|
127
133
|
ENABLE_WEBPUSH,
|
package/utils/test-utils.js
CHANGED
|
@@ -57,7 +57,7 @@ function getVisibleDropdown() {
|
|
|
57
57
|
return dropdowns[0];
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
async function findVisibleSelectOption(optionText) {
|
|
60
|
+
async function findVisibleSelectOption(optionText, { timeout = 1000 } = {}) {
|
|
61
61
|
return waitFor(() => {
|
|
62
62
|
const dropdowns = Array.from(document.querySelectorAll('.ant-select-dropdown'))
|
|
63
63
|
.filter((el) => !el.classList.contains('ant-select-dropdown-hidden'));
|
|
@@ -67,7 +67,7 @@ async function findVisibleSelectOption(optionText) {
|
|
|
67
67
|
if (match) return match;
|
|
68
68
|
}
|
|
69
69
|
throw new Error(`Visible select option with text "${optionText}" not found`);
|
|
70
|
-
});
|
|
70
|
+
}, { timeout });
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// re-export everything
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
import { getObjFromQueryParams, buildTemplateNameDescription } from '../v2common';
|
|
3
4
|
|
|
4
5
|
describe('Test v2common container', () => {
|
|
5
6
|
it('test getObjFromQueryParams', () => {
|
|
@@ -9,3 +10,47 @@ describe('Test v2common container', () => {
|
|
|
9
10
|
});
|
|
10
11
|
});
|
|
11
12
|
});
|
|
13
|
+
|
|
14
|
+
describe('buildTemplateNameDescription', () => {
|
|
15
|
+
it('returns undefined when templateName is empty string', () => {
|
|
16
|
+
expect(buildTemplateNameDescription('Template name', '')).toBeUndefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('returns undefined when templateName is null', () => {
|
|
20
|
+
expect(buildTemplateNameDescription('Template name', null)).toBeUndefined();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('returns undefined when templateName is undefined', () => {
|
|
24
|
+
expect(buildTemplateNameDescription('Template name', undefined)).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('renders a span wrapper when templateName is provided', () => {
|
|
28
|
+
const result = buildTemplateNameDescription('Template name', 'Welcome 01');
|
|
29
|
+
const wrapper = shallow(result);
|
|
30
|
+
expect(wrapper.type()).toBe('span');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('renders label text in the first CapLabelInline with correct class', () => {
|
|
34
|
+
const result = buildTemplateNameDescription('Template name', 'Welcome 01');
|
|
35
|
+
const wrapper = shallow(result);
|
|
36
|
+
const firstLabel = wrapper.childAt(0);
|
|
37
|
+
expect(firstLabel.prop('className')).toBe('notification-template-label');
|
|
38
|
+
expect(firstLabel.prop('children')).toBe('Template name');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('renders template name in the second CapLabelInline with correct class', () => {
|
|
42
|
+
const result = buildTemplateNameDescription('Template name', 'Welcome 01');
|
|
43
|
+
const wrapper = shallow(result);
|
|
44
|
+
const secondLabel = wrapper.childAt(1);
|
|
45
|
+
expect(secondLabel.prop('className')).toBe('notification-template-name');
|
|
46
|
+
expect(secondLabel.prop('children')).toBe('Welcome 01');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('both CapLabelInline elements have type="label1"', () => {
|
|
50
|
+
const result = buildTemplateNameDescription('Template name', 'Welcome 01');
|
|
51
|
+
const wrapper = shallow(result);
|
|
52
|
+
wrapper.children().forEach((node) => {
|
|
53
|
+
expect(node.prop('type')).toBe('label1');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
package/utils/v2common.js
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Builds a JSX description for template archive/unarchive notifications.
|
|
6
|
+
* @param {string} labelText - Localised label (e.g. "Template name ")
|
|
7
|
+
* @param {string} templateName - The template name to display
|
|
8
|
+
*/
|
|
9
|
+
export const buildTemplateNameDescription = (labelText, templateName) => (
|
|
10
|
+
templateName
|
|
11
|
+
? (
|
|
12
|
+
<span>
|
|
13
|
+
<CapLabel.CapLabelInline type="label1" className="notification-template-label">{labelText}</CapLabel.CapLabelInline>
|
|
14
|
+
<CapLabel.CapLabelInline type="label1" className="notification-template-name">{templateName}</CapLabel.CapLabelInline>
|
|
15
|
+
</span>
|
|
16
|
+
)
|
|
17
|
+
: undefined
|
|
18
|
+
);
|
|
1
19
|
|
|
2
20
|
// returns query items as obj when query string is passed
|
|
3
21
|
/**
|
|
@@ -79,7 +79,7 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
79
79
|
|
|
80
80
|
componentDidUpdate(prevProps, prevState) {
|
|
81
81
|
if (this.props.tags !== prevProps.tags || this.state.searchValue !== prevState.searchValue) {
|
|
82
|
-
const temp = this.renderTags(this.props.tags
|
|
82
|
+
const temp = this.renderTags(this.props.tags);
|
|
83
83
|
this.setState({
|
|
84
84
|
tagsList: temp,
|
|
85
85
|
});
|
|
@@ -136,14 +136,13 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
136
136
|
const tagNameWithoutUnderscore = tagName.replace(/_/g, " ");
|
|
137
137
|
const searchStringLower = _.toLower(value);
|
|
138
138
|
if (_.has(val, "subtags")) {
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
const temp = this.getSearchedExpandedKeys(val?.subtags, value, nodeKey);
|
|
140
|
+
const nodeMatches = val?.name
|
|
141
141
|
&& (tagName.includes(searchStringLower)
|
|
142
|
-
|| tagNameWithoutUnderscore.includes(searchStringLower))
|
|
143
|
-
) {
|
|
142
|
+
|| tagNameWithoutUnderscore.includes(searchStringLower));
|
|
143
|
+
if (nodeMatches || temp.length > 0) {
|
|
144
144
|
list.push(nodeKey);
|
|
145
145
|
}
|
|
146
|
-
const temp = this.getSearchedExpandedKeys(val?.subtags, value, nodeKey);
|
|
147
146
|
list = list.concat(temp);
|
|
148
147
|
} else if (
|
|
149
148
|
val?.name
|
|
@@ -18,7 +18,7 @@ import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
|
18
18
|
import { ANDROID, IOS } from '../constants';
|
|
19
19
|
import messages from '../messages';
|
|
20
20
|
import { getWhatsappQuickReply, getWhatsappCarouselButtonView } from '../../../v2Containers/Whatsapp/utils';
|
|
21
|
-
import { QUICK_REPLY, PHONE_NUMBER, WHATSAPP_CATEGORIES } from '../../../v2Containers/Whatsapp/constants';
|
|
21
|
+
import { QUICK_REPLY, PHONE_NUMBER, WHATSAPP_CATEGORIES, TEMPLATE_VARIABLE_REGEX } from '../../../v2Containers/Whatsapp/constants';
|
|
22
22
|
import videoPlay from '../../../assets/videoPlay.svg';
|
|
23
23
|
import whatsappImageEmptyPreview from '../../TemplatePreview/assets/images/empty_image_preview.svg';
|
|
24
24
|
import whatsappVideoEmptyPreview from '../../TemplatePreview/assets/images/empty_video_preview.svg';
|
|
@@ -27,6 +27,8 @@ import whatsappVideoEmptyPreview from '../../TemplatePreview/assets/images/empty
|
|
|
27
27
|
const whatsappMobileAndroid = require('../../../assets/whatsapp_android.png');
|
|
28
28
|
const whatsappMobileIos = require('../../../assets/whatsapp_ios.png');
|
|
29
29
|
|
|
30
|
+
const { CapLabelInline } = CapLabel;
|
|
31
|
+
|
|
30
32
|
const WhatsAppPreviewContent = ({
|
|
31
33
|
content,
|
|
32
34
|
device,
|
|
@@ -215,11 +217,21 @@ const WhatsAppPreviewContent = ({
|
|
|
215
217
|
|
|
216
218
|
{/* Image Preview */}
|
|
217
219
|
{content?.whatsappImageSrc && (
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
TEMPLATE_VARIABLE_REGEX.test(content.whatsappImageSrc) ? (
|
|
221
|
+
<CapRow className="whatsapp-image-url-placeholder">
|
|
222
|
+
<CapIcon type="picture" size="s" className="whatsapp-image-url-placeholder-icon" />
|
|
223
|
+
<CapLabelInline type="label2" className="whatsapp-image-url-placeholder-text">
|
|
224
|
+
{content.whatsappImageSrc}
|
|
225
|
+
</CapLabelInline>
|
|
226
|
+
</CapRow>
|
|
227
|
+
) : (
|
|
228
|
+
<CapImage
|
|
229
|
+
src={content.whatsappImageSrc}
|
|
230
|
+
className="whatsapp-image"
|
|
231
|
+
alt={formatMessage(messages.previewGenerated)}
|
|
232
|
+
onError={(e) => { e.target.src = whatsappImageEmptyPreview; }}
|
|
233
|
+
/>
|
|
234
|
+
)
|
|
223
235
|
)}
|
|
224
236
|
|
|
225
237
|
{/* Video Preview */}
|
|
@@ -941,6 +941,33 @@
|
|
|
941
941
|
}
|
|
942
942
|
}
|
|
943
943
|
|
|
944
|
+
.whatsapp-image-url-placeholder {
|
|
945
|
+
display: flex;
|
|
946
|
+
flex-direction: column;
|
|
947
|
+
align-items: center;
|
|
948
|
+
justify-content: center;
|
|
949
|
+
gap: $CAP_SPACE_08;
|
|
950
|
+
width: 100%;
|
|
951
|
+
min-height: 5rem;
|
|
952
|
+
max-height: 8.786rem;
|
|
953
|
+
margin-bottom: $CAP_SPACE_04;
|
|
954
|
+
background-color: $CAP_G09;
|
|
955
|
+
border-radius: $CAP_SPACE_04;
|
|
956
|
+
padding: $CAP_SPACE_08;
|
|
957
|
+
|
|
958
|
+
.whatsapp-image-url-placeholder-icon {
|
|
959
|
+
color: $CAP_G05;
|
|
960
|
+
font-size: 1.5rem;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
.whatsapp-image-url-placeholder-text {
|
|
964
|
+
font-size: $FONT_SIZE_S;
|
|
965
|
+
color: $CAP_G04;
|
|
966
|
+
text-align: center;
|
|
967
|
+
word-break: break-all;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
|
|
944
971
|
.whatsapp-image {
|
|
945
972
|
width: 100%;
|
|
946
973
|
max-height: 8.786rem;
|
package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/WhatsAppPreviewContent.test.js
CHANGED
|
@@ -26,6 +26,7 @@ jest.mock('../../../../v2Containers/Whatsapp/constants', () => ({
|
|
|
26
26
|
WHATSAPP_CATEGORIES: {
|
|
27
27
|
authentication: 'authentication',
|
|
28
28
|
},
|
|
29
|
+
TEMPLATE_VARIABLE_REGEX: /\{\{.*?\}\}/,
|
|
29
30
|
}));
|
|
30
31
|
|
|
31
32
|
// Convert messages object to format expected by IntlProvider
|
|
@@ -238,6 +239,53 @@ describe('WhatsAppPreviewContent', () => {
|
|
|
238
239
|
expect(image.getAttribute('src')).toBe('https://image.url');
|
|
239
240
|
});
|
|
240
241
|
|
|
242
|
+
it('should render placeholder when whatsappImageSrc is a template variable', () => {
|
|
243
|
+
const props = {
|
|
244
|
+
...defaultProps,
|
|
245
|
+
content: {
|
|
246
|
+
templateMsg: 'Message',
|
|
247
|
+
whatsappImageSrc: '{{imageUrl}}',
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const { container } = render(
|
|
252
|
+
<TestWrapper>
|
|
253
|
+
<ComponentToRender {...props} />
|
|
254
|
+
</TestWrapper>
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
expect(container.querySelector('.whatsapp-image-url-placeholder')).toBeTruthy();
|
|
258
|
+
expect(container.querySelector('.whatsapp-image-url-placeholder-icon')).toBeTruthy();
|
|
259
|
+
expect(container.querySelector('.whatsapp-image-url-placeholder-text').textContent).toBe('{{imageUrl}}');
|
|
260
|
+
expect(container.querySelector('img.whatsapp-image')).toBeFalsy();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should fall back to empty preview image when image fails to load', () => {
|
|
264
|
+
const props = {
|
|
265
|
+
...defaultProps,
|
|
266
|
+
content: {
|
|
267
|
+
templateMsg: 'Message',
|
|
268
|
+
whatsappImageSrc: 'https://broken.url/image.jpg',
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const { container } = render(
|
|
273
|
+
<TestWrapper>
|
|
274
|
+
<ComponentToRender {...props} />
|
|
275
|
+
</TestWrapper>
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
const image = container.querySelector('img.whatsapp-image');
|
|
279
|
+
expect(image).toBeTruthy();
|
|
280
|
+
expect(image.getAttribute('src')).toBe('https://broken.url/image.jpg');
|
|
281
|
+
|
|
282
|
+
// Trigger onError to swap src to fallback
|
|
283
|
+
const errorEvent = new Event('error');
|
|
284
|
+
image.dispatchEvent(errorEvent);
|
|
285
|
+
|
|
286
|
+
expect(image.getAttribute('src')).not.toBe('https://broken.url/image.jpg');
|
|
287
|
+
});
|
|
288
|
+
|
|
241
289
|
it('should render video preview when whatsappVideoPreviewImg is present', () => {
|
|
242
290
|
const props = {
|
|
243
291
|
...defaultProps,
|
|
@@ -816,6 +816,27 @@
|
|
|
816
816
|
}
|
|
817
817
|
}
|
|
818
818
|
|
|
819
|
+
.whatsapp-image-url-placeholder {
|
|
820
|
+
display: flex;
|
|
821
|
+
flex-direction: column;
|
|
822
|
+
align-items: center;
|
|
823
|
+
justify-content: center;
|
|
824
|
+
background-color: $CAP_G09;
|
|
825
|
+
border-radius: $CAP_SPACE_04;
|
|
826
|
+
width: 100%;
|
|
827
|
+
min-height: 5rem;
|
|
828
|
+
max-height: 8.786rem;
|
|
829
|
+
margin-bottom: $CAP_SPACE_04;
|
|
830
|
+
.whatsapp-image-url-placeholder-text {
|
|
831
|
+
font-size: 0.786rem;
|
|
832
|
+
color: $CAP_G04;
|
|
833
|
+
margin-top: $CAP_SPACE_04;
|
|
834
|
+
text-align: center;
|
|
835
|
+
word-break: break-all;
|
|
836
|
+
padding: 0 $CAP_SPACE_04;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
819
840
|
.msg-container-carousel {
|
|
820
841
|
display: flex;
|
|
821
842
|
.scroll-container {
|
|
@@ -48,7 +48,7 @@ import { TEMPLATE, IMAGE_CAROUSEL, IMAGE, STICKER, TEXT, IMAGE_MAP, VIDEO } from
|
|
|
48
48
|
import CapFacebookPreview from '../../v2Containers/CapFacebookPreview';
|
|
49
49
|
import WhatsappStatusContainer from '../WhatsappStatusContainer';
|
|
50
50
|
import { getWhatsappQuickReply, getWhatsappCarouselButtonView } from '../../v2Containers/Whatsapp/utils';
|
|
51
|
-
import { QUICK_REPLY, WHATSAPP_CATEGORIES, PHONE_NUMBER } from '../../v2Containers/Whatsapp/constants';
|
|
51
|
+
import { QUICK_REPLY, WHATSAPP_CATEGORIES, PHONE_NUMBER, TEMPLATE_VARIABLE_REGEX } from '../../v2Containers/Whatsapp/constants';
|
|
52
52
|
import { RCS_BUTTON_TYPES, LEFT, HORIZONTAL, VERTICAL, RIGHT} from '../../v2Containers/Rcs/constants';
|
|
53
53
|
import { ANDROID, INAPP_MESSAGE_LAYOUT_TYPES } from '../../v2Containers/InApp/constants';
|
|
54
54
|
import { CAROUSEL } from '../../v2Containers/MobilePushNew/constants';
|
|
@@ -66,6 +66,8 @@ const lineVideoPlaceholder = require('../../assets/rich-video-placeholder.svg');
|
|
|
66
66
|
const androidPushMessagePhone = require('./assets/images/Android_With_date_and_time.svg');
|
|
67
67
|
const iPhonePushMessagePhone = require('./assets/images/iOS_With_date_and_time.svg');
|
|
68
68
|
|
|
69
|
+
const { CapLabelInline } = CapLabel;
|
|
70
|
+
|
|
69
71
|
export class TemplatePreview extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
70
72
|
onPreviewContentClicked = (channel) => {
|
|
71
73
|
const IOSContent = (this.props.templateDataRaw && this.props.templateDataRaw.versions.base.IOS) ||
|
|
@@ -1195,11 +1197,21 @@ export class TemplatePreview extends React.Component { // eslint-disable-line re
|
|
|
1195
1197
|
{content?.showUrlPreview
|
|
1196
1198
|
&& renderUrlPreview(content?.metaTagsDetails)}
|
|
1197
1199
|
{content?.whatsappImageSrc && (
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1200
|
+
TEMPLATE_VARIABLE_REGEX.test(content.whatsappImageSrc) ? (
|
|
1201
|
+
<CapRow className="whatsapp-image-url-placeholder">
|
|
1202
|
+
<CapIcon type="picture" size="s" className="whatsapp-image-url-placeholder-icon" />
|
|
1203
|
+
<CapLabelInline type="label2" className="whatsapp-image-url-placeholder-text">
|
|
1204
|
+
{content.whatsappImageSrc}
|
|
1205
|
+
</CapLabelInline>
|
|
1206
|
+
</CapRow>
|
|
1207
|
+
) : (
|
|
1208
|
+
<CapImage
|
|
1209
|
+
src={content.whatsappImageSrc}
|
|
1210
|
+
className="whatsapp-image"
|
|
1211
|
+
alt={formatMessage(messages.previewGenerated)}
|
|
1212
|
+
onError={(e) => { e.target.src = whatsappImageEmptyPreview; }}
|
|
1213
|
+
/>
|
|
1214
|
+
)
|
|
1203
1215
|
)}
|
|
1204
1216
|
{content?.whatsappVideoPreviewImg && (
|
|
1205
1217
|
<CapTooltip
|
|
@@ -42,6 +42,7 @@ exports[`Test Templates container Should render correct preview component for wh
|
|
|
42
42
|
<CapImage
|
|
43
43
|
alt="Preview is being generated"
|
|
44
44
|
className="whatsapp-image"
|
|
45
|
+
onError={[Function]}
|
|
45
46
|
src="https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/c9edc114-923b-4ac7-82d0-d6682213.jpg"
|
|
46
47
|
/>
|
|
47
48
|
You have received {{1}} points
|