@capillarytech/creatives-library 7.17.97 → 7.17.99
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/package.json +1 -1
- package/v2Components/CapDeviceContent/index.js +12 -0
- package/v2Components/CapDeviceContent/index.scss +1 -1
- package/v2Components/CapDeviceContent/tests/index.test.js +3 -1
- package/v2Components/CapInAppCTA/constants.js +3 -3
- package/v2Components/CapInAppCTA/index.js +3 -3
- package/v2Components/FormBuilder/index.js +2 -1
- package/v2Components/MobilePushPreviewV2/index.js +3 -22
- package/v2Containers/Email/index.js +12 -10
- package/v2Containers/InApp/constants.js +22 -4
- package/v2Containers/InApp/index.js +55 -45
- package/v2Containers/InApp/messages.js +15 -0
- package/v2Containers/InApp/tests/index.test.js +21 -0
- package/v2Containers/InApp/tests/mockData.js +6 -6
- package/v2Containers/InApp/utils.js +12 -0
- package/v2Containers/Templates/_templates.scss +9 -0
- package/v2Containers/Templates/index.js +42 -9
package/package.json
CHANGED
|
@@ -66,6 +66,8 @@ const CapDeviceContent = (props) => {
|
|
|
66
66
|
onTagSelect,
|
|
67
67
|
handleOnTagsContextChange,
|
|
68
68
|
templateDescErrorHandler,
|
|
69
|
+
templateTitleError,
|
|
70
|
+
setTemplateTitleError,
|
|
69
71
|
} = props || {};
|
|
70
72
|
const { TextArea } = CapInput;
|
|
71
73
|
const { formatMessage } = intl;
|
|
@@ -119,7 +121,12 @@ const CapDeviceContent = (props) => {
|
|
|
119
121
|
};
|
|
120
122
|
|
|
121
123
|
const onTitleChange = ({ target: { value } }) => {
|
|
124
|
+
let error = templateDescErrorHandler(value);
|
|
125
|
+
if (value === '') {
|
|
126
|
+
error = formatMessage(messages.emptyTemplateMessageErrorMessage);
|
|
127
|
+
}
|
|
122
128
|
setTitle(value);
|
|
129
|
+
setTemplateTitleError(error);
|
|
123
130
|
};
|
|
124
131
|
|
|
125
132
|
const onTemplateMediaTypeChange = ({ target: { value } }) => {
|
|
@@ -176,6 +183,11 @@ const CapDeviceContent = (props) => {
|
|
|
176
183
|
value={title}
|
|
177
184
|
size="default"
|
|
178
185
|
isRequired
|
|
186
|
+
errorMessage={templateTitleError && (
|
|
187
|
+
<CapError className="inapp-template-message-error">
|
|
188
|
+
{templateTitleError}
|
|
189
|
+
</CapError>
|
|
190
|
+
)}
|
|
179
191
|
/>
|
|
180
192
|
</CapRow>
|
|
181
193
|
<CapRow className="creatives-inapp-media">
|
|
@@ -24,7 +24,7 @@ const renderComponent = (props) =>
|
|
|
24
24
|
|
|
25
25
|
describe('Test CapDeviceContent', () => {
|
|
26
26
|
it('test case for CapDeviceContent component Android pane', async () => {
|
|
27
|
-
renderComponent(deviceContentProps);
|
|
27
|
+
renderComponent({...deviceContentProps, templateDescErrorHandler: jest.fn()});
|
|
28
28
|
const msgBox = screen.getAllByPlaceholderText(/Please input in-app notification message content/i);
|
|
29
29
|
fireEvent.change(msgBox[0], 'val');
|
|
30
30
|
const copyLink = screen.getByRole('link', {
|
|
@@ -39,11 +39,13 @@ describe('Test CapDeviceContent', () => {
|
|
|
39
39
|
panes: "iOS",
|
|
40
40
|
buttonType: "CTA",
|
|
41
41
|
setTemplateMediaType: jest.fn(),
|
|
42
|
+
setTemplateTitleError: jest.fn(),
|
|
42
43
|
setButtonType: jest.fn(),
|
|
43
44
|
setCtaData: jest.fn(),
|
|
44
45
|
setTemplateMessage: jest.fn(),
|
|
45
46
|
setTemplateMessageError: jest.fn(),
|
|
46
47
|
setTitle: jest.fn(),
|
|
48
|
+
templateDescErrorHandler: jest.fn(),
|
|
47
49
|
templateMediType: "IMAGE",
|
|
48
50
|
addActionLink: true,
|
|
49
51
|
ctaData: [
|
|
@@ -3,7 +3,7 @@ import { FormattedMessage } from 'react-intl';
|
|
|
3
3
|
import messages from './messages';
|
|
4
4
|
|
|
5
5
|
export const DEEP_LINK = 'DEEP_LINK';
|
|
6
|
-
export const
|
|
6
|
+
export const EXTERNAL_URL = 'EXTERNAL_URL';
|
|
7
7
|
export const WEBSITE = 'WEBSITE';
|
|
8
8
|
|
|
9
9
|
export const CTA_OPTIONS = [
|
|
@@ -14,8 +14,8 @@ export const CTA_OPTIONS = [
|
|
|
14
14
|
tooltipLabel: <FormattedMessage {...messages.ctaOptionDisabledTooltipDeepLink} />,
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
|
-
key:
|
|
18
|
-
value:
|
|
17
|
+
key: EXTERNAL_URL,
|
|
18
|
+
value: EXTERNAL_URL,
|
|
19
19
|
label: <FormattedMessage {...messages.ctaLinkTypeExternal} />,
|
|
20
20
|
tooltipLabel: <FormattedMessage {...messages.ctaOptionDisabledTooltipExternalLink} />,
|
|
21
21
|
},
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
import {
|
|
26
26
|
BTN_MAX_LENGTH,
|
|
27
27
|
DEEP_LINK,
|
|
28
|
-
|
|
28
|
+
EXTERNAL_URL,
|
|
29
29
|
CTA_OPTIONS,
|
|
30
30
|
URL_MAX_LENGTH,
|
|
31
31
|
} from "./constants";
|
|
@@ -108,7 +108,7 @@ export const CapInAppCTA = (props) => {
|
|
|
108
108
|
return true;
|
|
109
109
|
} else if (urlType === DEEP_LINK && (ctaDeepLinkValue === "" || urlError)) {
|
|
110
110
|
return true;
|
|
111
|
-
} else if (urlType ===
|
|
111
|
+
} else if (urlType === EXTERNAL_URL && (url === "" || urlError)) {
|
|
112
112
|
return true;
|
|
113
113
|
}
|
|
114
114
|
};
|
|
@@ -223,7 +223,7 @@ export const CapInAppCTA = (props) => {
|
|
|
223
223
|
</>
|
|
224
224
|
|
|
225
225
|
)}
|
|
226
|
-
{urlType ===
|
|
226
|
+
{urlType === EXTERNAL_URL && (
|
|
227
227
|
<>
|
|
228
228
|
<CapHeading type="h4">
|
|
229
229
|
{formatMessage(messages.urlExternalLink)}
|
|
@@ -929,7 +929,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
929
929
|
}
|
|
930
930
|
// Check if template subject present in form data from Loyalty, DVS, Timeline
|
|
931
931
|
if (index === 'template-subject' && type.toLowerCase() === 'embedded' && (currentModule.toLowerCase() === 'loyalty' || currentModule.toLowerCase() === 'dvs' || currentModule.toLowerCase() === 'timeline' || currentModule.toLowerCase() === 'library')) {
|
|
932
|
-
|
|
932
|
+
//checking email subject name validation
|
|
933
|
+
if (!data?.trim()) {
|
|
933
934
|
errorData[index] = true;
|
|
934
935
|
isValid = false;
|
|
935
936
|
} else {
|
|
@@ -14,6 +14,7 @@ import '../PreviewSideBar/_previewsidebar.scss';
|
|
|
14
14
|
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
|
+
import { getCtaObject } from '../../v2Containers/InApp/utils';
|
|
17
18
|
|
|
18
19
|
class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
19
20
|
constructor(props) {
|
|
@@ -47,33 +48,13 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
|
|
|
47
48
|
templateTitle: androidContent?.title,
|
|
48
49
|
templateMsg: androidContent?.message,
|
|
49
50
|
mediaPreview: { inAppImageSrcAndroid: androidContent?.expandableDetails?.image },
|
|
50
|
-
ctaData: androidContent?.expandableDetails?.ctas
|
|
51
|
-
const { type = '', actionText = '', actionLink = "" } = cta;
|
|
52
|
-
const ctaObject = {
|
|
53
|
-
index,
|
|
54
|
-
text: actionText,
|
|
55
|
-
url: actionLink,
|
|
56
|
-
urlType: type,
|
|
57
|
-
isSaved: true,
|
|
58
|
-
};
|
|
59
|
-
return ctaObject;
|
|
60
|
-
}),
|
|
51
|
+
ctaData: getCtaObject(androidContent?.expandableDetails?.ctas),
|
|
61
52
|
};
|
|
62
53
|
const iosPreviewContent = {
|
|
63
54
|
templateTitle: iosContent?.title,
|
|
64
55
|
templateMsg: iosContent?.message,
|
|
65
56
|
mediaPreview: { inAppImageSrcIos: iosContent?.expandableDetails?.image },
|
|
66
|
-
ctaData: iosContent?.expandableDetails?.ctas
|
|
67
|
-
const { type = '', actionText = '', actionLink = "" } = cta;
|
|
68
|
-
const ctaObject = {
|
|
69
|
-
index,
|
|
70
|
-
text: actionText,
|
|
71
|
-
url: actionLink,
|
|
72
|
-
urlType: type,
|
|
73
|
-
isSaved: true,
|
|
74
|
-
};
|
|
75
|
-
return ctaObject;
|
|
76
|
-
}),
|
|
57
|
+
ctaData: getCtaObject(iosContent?.expandableDetails?.ctas),
|
|
77
58
|
};
|
|
78
59
|
content = {
|
|
79
60
|
inAppPreviewContent: device === ANDROID.toLowerCase() ? androidPreviewContent : iosPreviewContent,
|
|
@@ -2069,7 +2069,8 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2069
2069
|
formData[0].selectedLanguages = [];
|
|
2070
2070
|
let tabKey;
|
|
2071
2071
|
if ((this.props.location.query.isLanguageSupport === undefined || this.props.location.query.isLanguageSupport === 'false')) {
|
|
2072
|
-
formData['template-subject']
|
|
2072
|
+
// If formData['template-subject'] is empty, assign an empty string; otherwise, retain its current value or use data.base.subject.
|
|
2073
|
+
formData['template-subject'] = formData?.['template-subject'] === '' ? '' : (data?.base?.subject || '');
|
|
2073
2074
|
const baseLanguage = this.props.currentOrgDetails.basic_details.base_language;
|
|
2074
2075
|
let languageIndex = _.findIndex(this.supportedLanguages, {iso_code: baseLanguage});
|
|
2075
2076
|
|
|
@@ -2134,16 +2135,17 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2134
2135
|
this.addLanguage(false, formData, false, additionalLanguages);
|
|
2135
2136
|
}
|
|
2136
2137
|
formData.base = _.cloneDeep(formData[0]);
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2138
|
+
if (formData?.['template-subject'] !== '') {
|
|
2139
|
+
this.setState({formData, loading: false, injectedTags: data.tags, tabKey, isDragDrop: (data.base.is_drag_drop !== 0 )}, () => {
|
|
2140
|
+
// this.setState({tabKey: ''});
|
|
2141
|
+
const isBEEEnable = this.checkBeeEditorAllowedForLibrary();
|
|
2142
|
+
_.forEach(formData[0].selectedLanguages, (language) => {
|
|
2143
|
+
if (formData[0][language].is_drag_drop && isBEEEnable) {
|
|
2144
|
+
this.props.actions.getCmsSetting(BEE_PLUGIN, formData[0][language].drag_drop_id, 'open', language, isEdmSupport, isBEEEnable);
|
|
2145
|
+
}
|
|
2146
|
+
});
|
|
2145
2147
|
});
|
|
2146
|
-
}
|
|
2148
|
+
}
|
|
2147
2149
|
} else {
|
|
2148
2150
|
this.setState({injectedTags: data.tags});
|
|
2149
2151
|
}
|
|
@@ -135,8 +135,26 @@ export const BUTTON_RADIO_OPTIONS = [
|
|
|
135
135
|
];
|
|
136
136
|
|
|
137
137
|
export const INAPP_LAYOUT_DETAILS = {
|
|
138
|
-
POPUP: {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
POPUP: {
|
|
139
|
+
tagColor: CAP_ORANGE01,
|
|
140
|
+
tagTextColor: CAP_ORANGE,
|
|
141
|
+
text: <FormattedMessage {...messages.popup} />,
|
|
142
|
+
},
|
|
143
|
+
HEADER: {
|
|
144
|
+
tagColor: CAP_PURPLE03,
|
|
145
|
+
tagTextColor: CAP_PURPLE02,
|
|
146
|
+
text: <FormattedMessage {...messages.header} />,
|
|
147
|
+
},
|
|
148
|
+
FOOTER: {
|
|
149
|
+
tagColor: CAP_PALE_GREY,
|
|
150
|
+
tagTextColor: FONT_COLOR_05,
|
|
151
|
+
text: <FormattedMessage {...messages.footer} />,
|
|
152
|
+
},
|
|
153
|
+
FULLSCREEN: {
|
|
154
|
+
tagColor: CAP_GREEN02,
|
|
155
|
+
tagTextColor: CAP_GREEN01,
|
|
156
|
+
text: <FormattedMessage {...messages.layoutFullScreen} />,
|
|
157
|
+
},
|
|
142
158
|
};
|
|
159
|
+
|
|
160
|
+
export const DEVICE_SUPPORTED = '1';
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
BIG_PICTURE,
|
|
33
33
|
BIG_TEXT,
|
|
34
34
|
DEEP_LINK,
|
|
35
|
+
DEVICE_SUPPORTED,
|
|
35
36
|
INAPP_BUTTON_TYPES,
|
|
36
37
|
INAPP_MEDIA_TYPES,
|
|
37
38
|
INAPP_MESSAGE_LAYOUT_TYPES,
|
|
@@ -43,6 +44,7 @@ import { INAPP, SMS } from "../CreativesContainer/constants";
|
|
|
43
44
|
import { ALL, TAG, EMBEDDED, DEFAULT, FULL, LIBRARY } from "../Whatsapp/constants";
|
|
44
45
|
import CapDeviceContent from "../../v2Components/CapDeviceContent";
|
|
45
46
|
import { getCdnUrl } from "../../utils/cdnTransformation";
|
|
47
|
+
import { getCtaObject } from "./utils";
|
|
46
48
|
let editContent = {};
|
|
47
49
|
|
|
48
50
|
export const InApp = (props) => {
|
|
@@ -82,6 +84,8 @@ export const InApp = (props) => {
|
|
|
82
84
|
const [templateMessageIos, setTemplateMessageIos] = useState("");
|
|
83
85
|
const [templateMessageErrorAndroid, setTemplateMessageErrorAndroid] = useState(false);
|
|
84
86
|
const [templateMessageErrorIos, setTemplateMessageErrorIos] = useState(false);
|
|
87
|
+
const [templateTitleErrorAndroid, setTemplateTitleErrorAndroid] = useState(false);
|
|
88
|
+
const [templateTitleErrorIos, setTemplateTitleErrorIos] = useState(false);
|
|
85
89
|
const [accountId, setAccountId] = useState("");
|
|
86
90
|
const [accessToken, setAccessToken] = useState("");
|
|
87
91
|
const [accountName, setAccountName] = useState("");
|
|
@@ -116,7 +120,8 @@ export const InApp = (props) => {
|
|
|
116
120
|
configs = {},
|
|
117
121
|
name = "",
|
|
118
122
|
} = accountObj;
|
|
119
|
-
const isAndroidSupported = configs
|
|
123
|
+
const isAndroidSupported = configs?.android === DEVICE_SUPPORTED;
|
|
124
|
+
// DEVICE_SUPPORTED is '1', which indicates if the particular account is supported, and '0' if the devive is not supported
|
|
120
125
|
//get deep link keys in an array
|
|
121
126
|
const deepLinkKeys = Object.values(JSON.parse(deepLinkObj));
|
|
122
127
|
const keys = deepLinkKeys.map((link) => ({label: link.name, value: link.link, title: link.link }));
|
|
@@ -161,36 +166,30 @@ export const InApp = (props) => {
|
|
|
161
166
|
const {
|
|
162
167
|
title: androidTitle = '',
|
|
163
168
|
message: androidMessage = '',
|
|
164
|
-
|
|
169
|
+
ctas: androidCta = {},
|
|
165
170
|
expandableDetails: androidExpandableDetails = {},
|
|
166
171
|
} = androidContent || {};
|
|
172
|
+
const {
|
|
173
|
+
style: androidStyle,
|
|
174
|
+
image: androidImage,
|
|
175
|
+
ctas: androidCtas,
|
|
176
|
+
} = androidExpandableDetails || {};
|
|
177
|
+
const androidCtaLength = androidCtas?.length;
|
|
167
178
|
setTitleAndroid(androidTitle);
|
|
168
179
|
setTemplateMessageAndroid(androidMessage);
|
|
169
180
|
setTemplateMediaType(
|
|
170
|
-
|
|
181
|
+
androidStyle === BIG_TEXT
|
|
171
182
|
? INAPP_MEDIA_TYPES.TEXT
|
|
172
183
|
: INAPP_MEDIA_TYPES.IMAGE
|
|
173
184
|
);
|
|
174
|
-
setInAppImageSrcAndroid(
|
|
175
|
-
setDeepLinkValueAndroid(androidCta?.actionLink);
|
|
185
|
+
setInAppImageSrcAndroid(androidImage);
|
|
186
|
+
setDeepLinkValueAndroid(androidCta[0]?.actionLink);
|
|
176
187
|
setAddActionLinkAndroid(!isEmpty(androidCta) && true);
|
|
177
188
|
setButtonTypeAndroid(
|
|
178
|
-
|
|
189
|
+
androidCtaLength ? INAPP_BUTTON_TYPES.CTA : INAPP_BUTTON_TYPES.NONE
|
|
179
190
|
);
|
|
180
|
-
if (
|
|
181
|
-
setCtaDataAndroid(
|
|
182
|
-
androidExpandableDetails?.ctas?.map((cta, index) => {
|
|
183
|
-
const { type = '', actionText = '', actionLink = "" } = cta;
|
|
184
|
-
const obj = {
|
|
185
|
-
index,
|
|
186
|
-
text: actionText,
|
|
187
|
-
url: actionLink,
|
|
188
|
-
urlType: type,
|
|
189
|
-
isSaved: true,
|
|
190
|
-
};
|
|
191
|
-
return obj;
|
|
192
|
-
})
|
|
193
|
-
);
|
|
191
|
+
if (androidCtaLength > 0) {
|
|
192
|
+
setCtaDataAndroid(getCtaObject(androidCtas));
|
|
194
193
|
}
|
|
195
194
|
}
|
|
196
195
|
const iosContent = editContent?.IOS;
|
|
@@ -198,30 +197,24 @@ export const InApp = (props) => {
|
|
|
198
197
|
const {
|
|
199
198
|
title: iosTitle = '',
|
|
200
199
|
message: iosMessage = '',
|
|
201
|
-
|
|
200
|
+
ctas: iosCta = {},
|
|
202
201
|
expandableDetails: iosExpandableDetails = {},
|
|
203
202
|
} = iosContent || {};
|
|
203
|
+
const {
|
|
204
|
+
style: iosStyle,
|
|
205
|
+
image: iosImage,
|
|
206
|
+
ctas: iosCtas,
|
|
207
|
+
} = iosExpandableDetails || {};
|
|
208
|
+
const iosCtaLength = iosCtas?.length;
|
|
204
209
|
setTitleIos(iosTitle);
|
|
205
210
|
setTemplateMessageIos(iosMessage);
|
|
206
|
-
setTemplateMediaType(
|
|
207
|
-
setInAppImageSrcIos(
|
|
208
|
-
setButtonTypeIos(
|
|
211
|
+
setTemplateMediaType(iosStyle === BIG_TEXT ? INAPP_MEDIA_TYPES.TEXT : INAPP_MEDIA_TYPES.IMAGE);
|
|
212
|
+
setInAppImageSrcIos(iosImage);
|
|
213
|
+
setButtonTypeIos(iosCtaLength ? INAPP_BUTTON_TYPES.CTA : INAPP_BUTTON_TYPES.NONE);
|
|
209
214
|
setAddActionLinkIos(!isEmpty(iosCta) && true);
|
|
210
|
-
setDeepLinkValueIos(iosCta?.actionLink);
|
|
211
|
-
if (
|
|
212
|
-
setCtaDataIos(
|
|
213
|
-
iosExpandableDetails?.ctas?.map((cta, index) => {
|
|
214
|
-
const { type = '', actionText = '', actionLink = "" } = cta;
|
|
215
|
-
const obj = {
|
|
216
|
-
index,
|
|
217
|
-
text: actionText,
|
|
218
|
-
url: actionLink,
|
|
219
|
-
urlType: type,
|
|
220
|
-
isSaved: true,
|
|
221
|
-
};
|
|
222
|
-
return obj;
|
|
223
|
-
})
|
|
224
|
-
);
|
|
215
|
+
setDeepLinkValueIos(iosCta[0]?.actionLink);
|
|
216
|
+
if (iosCtaLength > 0) {
|
|
217
|
+
setCtaDataIos(getCtaObject(iosCtas));
|
|
225
218
|
}
|
|
226
219
|
}
|
|
227
220
|
}
|
|
@@ -365,6 +358,8 @@ export const InApp = (props) => {
|
|
|
365
358
|
templateMessage={templateMessageAndroid}
|
|
366
359
|
setTemplateMessage={setTemplateMessageAndroid}
|
|
367
360
|
setTemplateMessageError={setTemplateMessageErrorAndroid}
|
|
361
|
+
templateTitleError={templateTitleErrorAndroid}
|
|
362
|
+
setTemplateTitleError={setTemplateTitleErrorAndroid}
|
|
368
363
|
addActionLink={addActionLinkAndroid}
|
|
369
364
|
setAddActionLink={setAddActionLinkAndroid}
|
|
370
365
|
deepLink={deepLink}
|
|
@@ -379,7 +374,8 @@ export const InApp = (props) => {
|
|
|
379
374
|
),
|
|
380
375
|
tab: <FormattedMessage {...messages.Android} />,
|
|
381
376
|
key: ANDROID,
|
|
382
|
-
isSupported: accountData
|
|
377
|
+
isSupported: get(accountData, 'selectedWeChatAccount.configs.android') === DEVICE_SUPPORTED,
|
|
378
|
+
// DEVICE_SUPPORTED is '1', which indicates if the particular account is supported, and '0' if the devive is not supported
|
|
383
379
|
},
|
|
384
380
|
{
|
|
385
381
|
content: (
|
|
@@ -409,6 +405,8 @@ export const InApp = (props) => {
|
|
|
409
405
|
templateMessage={templateMessageIos}
|
|
410
406
|
setTemplateMessage={setTemplateMessageIos}
|
|
411
407
|
setTemplateMessageError={setTemplateMessageErrorIos}
|
|
408
|
+
templateTitleError={templateTitleErrorIos}
|
|
409
|
+
setTemplateTitleError={setTemplateTitleErrorIos}
|
|
412
410
|
addActionLink={addActionLinkIos}
|
|
413
411
|
setAddActionLink={setAddActionLinkIos}
|
|
414
412
|
deepLink={deepLink}
|
|
@@ -418,11 +416,12 @@ export const InApp = (props) => {
|
|
|
418
416
|
tags={tags}
|
|
419
417
|
onTagSelect={onTagSelect}
|
|
420
418
|
handleOnTagsContextChange={handleOnTagsContextChange}
|
|
419
|
+
templateDescErrorHandler={templateDescErrorHandler}
|
|
421
420
|
/>
|
|
422
421
|
),
|
|
423
422
|
tab: <FormattedMessage {...messages.Ios} />,
|
|
424
423
|
key: IOS,
|
|
425
|
-
isSupported: accountData
|
|
424
|
+
isSupported: get(accountData, 'selectedWeChatAccount.configs.ios') === DEVICE_SUPPORTED,
|
|
426
425
|
},
|
|
427
426
|
];
|
|
428
427
|
|
|
@@ -508,23 +507,34 @@ export const InApp = (props) => {
|
|
|
508
507
|
};
|
|
509
508
|
|
|
510
509
|
const isDisableDone = (device) => {
|
|
510
|
+
const isIosDevice = device === IOS;
|
|
511
|
+
const isAndroidDevice = device === ANDROID;
|
|
511
512
|
//if template name is not entered
|
|
512
513
|
if (isFullMode && templateName.trim() === '') {
|
|
513
514
|
return true;
|
|
514
515
|
}
|
|
515
516
|
//if template message is not entered
|
|
516
517
|
//for android
|
|
517
|
-
if (
|
|
518
|
+
if (isAndroidDevice && (templateMessageAndroid.trim() === '' || templateMessageErrorAndroid)) {
|
|
519
|
+
return true;
|
|
520
|
+
}
|
|
521
|
+
if (isIosDevice && (templateMessageIos.trim() === '' || templateMessageErrorIos)) {
|
|
522
|
+
return true;
|
|
523
|
+
}//for ios
|
|
524
|
+
|
|
525
|
+
//if template title is not entered
|
|
526
|
+
//for android
|
|
527
|
+
if (isAndroidDevice && (titleAndroid.trim() === '' || templateTitleErrorAndroid)) {
|
|
518
528
|
return true;
|
|
519
529
|
}
|
|
520
|
-
if (
|
|
530
|
+
if (isIosDevice && (titleIos.trim() === '' || templateTitleErrorIos)) {
|
|
521
531
|
return true;
|
|
522
532
|
}//for ios
|
|
523
533
|
//if media type is image and the mediaType file is not uploaded
|
|
524
|
-
if (
|
|
534
|
+
if (isAndroidDevice && !(templateMediaType === INAPP_MEDIA_TYPES.TEXT) && inAppImageSrcAndroid === '') {
|
|
525
535
|
return true;
|
|
526
536
|
}
|
|
527
|
-
if (
|
|
537
|
+
if (isIosDevice && !(templateMediaType === INAPP_MEDIA_TYPES.TEXT) && inAppImageSrcIos === '') {
|
|
528
538
|
return true;
|
|
529
539
|
}
|
|
530
540
|
//cta
|
|
@@ -96,4 +96,19 @@ export default defineMessages({
|
|
|
96
96
|
defaultMessage:
|
|
97
97
|
"Create a button that lets customers take an action",
|
|
98
98
|
},
|
|
99
|
+
popup: {
|
|
100
|
+
id: `${prefix}.popup`,
|
|
101
|
+
defaultMessage:
|
|
102
|
+
"Pop-up",
|
|
103
|
+
},
|
|
104
|
+
header: {
|
|
105
|
+
id: `${prefix}.header`,
|
|
106
|
+
defaultMessage:
|
|
107
|
+
"Header",
|
|
108
|
+
},
|
|
109
|
+
footer: {
|
|
110
|
+
id: `${prefix}.footer`,
|
|
111
|
+
defaultMessage:
|
|
112
|
+
"Footer",
|
|
113
|
+
},
|
|
99
114
|
});
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
location1,
|
|
15
15
|
} from './mockData';
|
|
16
16
|
import { metaEntities, getDefaultTags, injectedTags } from '../../Zalo/tests/mockData';
|
|
17
|
+
import { getCtaObject } from '../utils';
|
|
17
18
|
|
|
18
19
|
const mockActions = {
|
|
19
20
|
getTemplateInfoById: jest.fn(),
|
|
@@ -140,3 +141,23 @@ describe('Test activity inApp container', () => {
|
|
|
140
141
|
expect(copyLink).toBeInTheDocument();
|
|
141
142
|
});
|
|
142
143
|
});
|
|
144
|
+
describe('test for getCtaObject function', () => {
|
|
145
|
+
it('getCtaObject function', () => {
|
|
146
|
+
const response = getCtaObject([{ type: "DEEP_LINK", actionText: "btn", actionLink: "url" }]);
|
|
147
|
+
expect(response).toEqual([{
|
|
148
|
+
index: 0,
|
|
149
|
+
text: "btn",
|
|
150
|
+
url: "url",
|
|
151
|
+
urlType: "DEEP_LINK",
|
|
152
|
+
isSaved: true,
|
|
153
|
+
}]);
|
|
154
|
+
const responseDefault = getCtaObject([{}]);
|
|
155
|
+
expect(responseDefault).toEqual([{
|
|
156
|
+
index: 0,
|
|
157
|
+
text: "",
|
|
158
|
+
url: "",
|
|
159
|
+
urlType: "",
|
|
160
|
+
isSaved: true,
|
|
161
|
+
}]);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
@@ -171,7 +171,7 @@ export const accountData = {
|
|
|
171
171
|
buttons: [
|
|
172
172
|
{
|
|
173
173
|
index: 0,
|
|
174
|
-
type: "
|
|
174
|
+
type: "EXTERNAL_URL",
|
|
175
175
|
text: "test",
|
|
176
176
|
url: "https://nightly.intouch.capillarytech.com/creatives/ui/v2",
|
|
177
177
|
label: "Test_1",
|
|
@@ -196,7 +196,7 @@ export const accountData = {
|
|
|
196
196
|
buttons: [
|
|
197
197
|
{
|
|
198
198
|
index: 0,
|
|
199
|
-
type: "
|
|
199
|
+
type: "EXTERNAL_URL",
|
|
200
200
|
text: "test",
|
|
201
201
|
url: "https://nightly.intouch.capillarytech.com/creatives/ui/v2",
|
|
202
202
|
label: "Test_1",
|
|
@@ -247,7 +247,7 @@ export const accountData = {
|
|
|
247
247
|
buttons: [
|
|
248
248
|
{
|
|
249
249
|
index: 0,
|
|
250
|
-
type: "
|
|
250
|
+
type: "EXTERNAL_URL",
|
|
251
251
|
text: "test",
|
|
252
252
|
url: "https://nightly.intouch.capillarytech.com/creatives/ui/v2",
|
|
253
253
|
label: "Test_1",
|
|
@@ -276,7 +276,7 @@ export const accountData = {
|
|
|
276
276
|
buttons: [
|
|
277
277
|
{
|
|
278
278
|
index: 0,
|
|
279
|
-
type: "
|
|
279
|
+
type: "EXTERNAL_URL",
|
|
280
280
|
text: "testios",
|
|
281
281
|
url: "https://nightly.intouch.capillarytech.com/creatives/ui/v2",
|
|
282
282
|
label: "",
|
|
@@ -671,7 +671,7 @@ export const editData = {
|
|
|
671
671
|
buttons: [
|
|
672
672
|
{
|
|
673
673
|
index: 0,
|
|
674
|
-
type: "
|
|
674
|
+
type: "EXTERNAL_URL",
|
|
675
675
|
text: "test",
|
|
676
676
|
url: "https://nightly.intouch.capillarytech.com/creatives/ui/v2",
|
|
677
677
|
label: "Test_1",
|
|
@@ -697,7 +697,7 @@ export const editData = {
|
|
|
697
697
|
buttons: [
|
|
698
698
|
{
|
|
699
699
|
index: 0,
|
|
700
|
-
type: "
|
|
700
|
+
type: "EXTERNAL_URL",
|
|
701
701
|
text: "test",
|
|
702
702
|
url: "https://nightly.intouch.capillarytech.com/creatives/ui/v2",
|
|
703
703
|
label: "Test_1",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const getCtaObject = (ctaData) =>
|
|
2
|
+
ctaData?.map((cta, index) => {
|
|
3
|
+
const { type = "", actionText = "", actionLink = "" } = cta;
|
|
4
|
+
const obj = {
|
|
5
|
+
index,
|
|
6
|
+
text: actionText,
|
|
7
|
+
url: actionLink,
|
|
8
|
+
urlType: type,
|
|
9
|
+
isSaved: true,
|
|
10
|
+
};
|
|
11
|
+
return obj;
|
|
12
|
+
});
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
.creatives-templates-list.full-mode{
|
|
12
12
|
.pagination-container {
|
|
13
13
|
.cap-custom-card-list-row {
|
|
14
|
+
padding-bottom: 10rem;
|
|
14
15
|
.cap-custom-card-list-col{
|
|
15
16
|
&:nth-child(3n+3) { //every 4th child
|
|
16
17
|
margin-right: unset;
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
.creatives-templates-list.full-mode{
|
|
26
27
|
.pagination-container {
|
|
27
28
|
.cap-custom-card-list-row {
|
|
29
|
+
padding-bottom: 10rem;
|
|
28
30
|
.cap-custom-card-list-col{
|
|
29
31
|
&:nth-child(4n+4) { //every 4th child
|
|
30
32
|
margin-right: unset;
|
|
@@ -56,6 +58,9 @@
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
.pagination-container {
|
|
61
|
+
.cap-custom-card-list-row {
|
|
62
|
+
padding-bottom: 10rem;
|
|
63
|
+
}
|
|
59
64
|
.FACEBOOK {
|
|
60
65
|
.ant-card-body {
|
|
61
66
|
background-color: $CAP_G09;
|
|
@@ -524,6 +529,10 @@
|
|
|
524
529
|
border-bottom: solid 0.5px #D6D6D6;
|
|
525
530
|
}
|
|
526
531
|
|
|
532
|
+
.main-content{
|
|
533
|
+
overflow: hidden;
|
|
534
|
+
}
|
|
535
|
+
|
|
527
536
|
.wechat-filters,
|
|
528
537
|
.line-filters {
|
|
529
538
|
width: 100%;
|
|
@@ -1006,7 +1006,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1006
1006
|
);
|
|
1007
1007
|
|
|
1008
1008
|
const cardDataList = filteredTemplates && filteredTemplates.length ? map(filteredTemplates, (template) => {
|
|
1009
|
-
const
|
|
1009
|
+
const androidBodyType = get(template, 'versions.base.content.ANDROID.bodyType');
|
|
1010
|
+
const iosBodyType = get(template, 'versions.base.content.IOS.bodyType');
|
|
1011
|
+
const inappBodyType = androidBodyType || iosBodyType;
|
|
1010
1012
|
const templateData = {
|
|
1011
1013
|
key: `${currentChannel}-card-${template?.name}`,
|
|
1012
1014
|
title: (
|
|
@@ -1015,30 +1017,61 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1015
1017
|
{currentChannel === INAPP && (
|
|
1016
1018
|
<CapRow>
|
|
1017
1019
|
<CapColoredTag
|
|
1018
|
-
tagColor={INAPP_LAYOUT_DETAILS[inappBodyType]
|
|
1020
|
+
tagColor={INAPP_LAYOUT_DETAILS[inappBodyType]?.tagColor}
|
|
1019
1021
|
tagTextColor={
|
|
1020
|
-
INAPP_LAYOUT_DETAILS[inappBodyType]
|
|
1022
|
+
INAPP_LAYOUT_DETAILS[inappBodyType]?.tagTextColor
|
|
1021
1023
|
}
|
|
1022
|
-
tagHeight="
|
|
1024
|
+
tagHeight="1.25rem"
|
|
1023
1025
|
tagFontSize="12px"
|
|
1024
1026
|
>
|
|
1025
|
-
{INAPP_LAYOUT_DETAILS[inappBodyType]
|
|
1027
|
+
{INAPP_LAYOUT_DETAILS[inappBodyType]?.text}
|
|
1026
1028
|
</CapColoredTag>
|
|
1027
1029
|
</CapRow>
|
|
1028
1030
|
)}
|
|
1029
1031
|
</span>
|
|
1030
1032
|
),
|
|
1031
1033
|
extra: [
|
|
1032
|
-
<CapTooltip
|
|
1034
|
+
<CapTooltip
|
|
1035
|
+
title={
|
|
1036
|
+
this.state.channel.toLowerCase() === ZALO_LOWERCASE ? (
|
|
1037
|
+
<div className="zalo-view-tooltip">
|
|
1038
|
+
{this.props.intl.formatMessage(messages.zaloPreview)}
|
|
1039
|
+
</div>
|
|
1040
|
+
) : (
|
|
1041
|
+
""
|
|
1042
|
+
)
|
|
1043
|
+
}
|
|
1044
|
+
>
|
|
1033
1045
|
<CapIcon
|
|
1034
1046
|
className={`view-${channelLowerCase}`}
|
|
1035
|
-
style={{ marginRight:
|
|
1047
|
+
style={{ marginRight: "16px" }}
|
|
1036
1048
|
type="eye"
|
|
1037
|
-
onClick={() => {
|
|
1049
|
+
onClick={() => {
|
|
1050
|
+
if (!this.props.isFullMode || this.props.isDltFromRcs) {
|
|
1051
|
+
this.props.handlePeviewTemplate(template);
|
|
1052
|
+
} else {
|
|
1053
|
+
handlers.handlePreviewClick(template);
|
|
1054
|
+
}
|
|
1055
|
+
}}
|
|
1038
1056
|
/>
|
|
1039
1057
|
</CapTooltip>,
|
|
1040
1058
|
],
|
|
1041
|
-
hoverOption:
|
|
1059
|
+
hoverOption: (
|
|
1060
|
+
<CapButton
|
|
1061
|
+
className={
|
|
1062
|
+
this.props.isFullMode
|
|
1063
|
+
? `edit-${channelLowerCase}`
|
|
1064
|
+
: `select-${channelLowerCase}`
|
|
1065
|
+
}
|
|
1066
|
+
onClick={(e) =>
|
|
1067
|
+
handlers.handleEditClick(e, template, undefined, undefined, {
|
|
1068
|
+
account: this.state.selectedAccount,
|
|
1069
|
+
})
|
|
1070
|
+
}
|
|
1071
|
+
>
|
|
1072
|
+
{hoverButtonText}
|
|
1073
|
+
</CapButton>
|
|
1074
|
+
),
|
|
1042
1075
|
};
|
|
1043
1076
|
const {
|
|
1044
1077
|
versions: {
|