@capillarytech/creatives-library 8.0.11 → 8.0.12
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
CHANGED
package/services/api.js
CHANGED
|
@@ -351,10 +351,11 @@ export const getUserList = () => {
|
|
|
351
351
|
return API.get(url);// request(url, getAPICallObject('GET'));
|
|
352
352
|
};
|
|
353
353
|
|
|
354
|
-
export const fetchSchemaForEntity = ({queryParams}) => {
|
|
354
|
+
export const fetchSchemaForEntity = async ({queryParams}) => {
|
|
355
355
|
if (queryParams.version === "v2" && queryParams.type === "LAYOUT") {
|
|
356
356
|
const schema = getSchema(queryParams.layout);
|
|
357
|
-
|
|
357
|
+
// Added async/await to ensure the schema object is resolved before returning it
|
|
358
|
+
return await schema.then((layout) => layout).catch((err) => {
|
|
358
359
|
console.error(err);
|
|
359
360
|
});
|
|
360
361
|
}
|
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
getTemplateInfoById,
|
|
12
12
|
askAiraForLiquid,
|
|
13
13
|
getLiquidTags,
|
|
14
|
+
fetchSchemaForEntity,
|
|
14
15
|
} from '../api';
|
|
15
16
|
import { mockData } from './mockData';
|
|
17
|
+
import getSchema from '../getSchema';
|
|
16
18
|
const sampleFile = require('../../assets/line.png');
|
|
17
19
|
|
|
18
20
|
let mockDecompressJsonObject;
|
|
@@ -24,6 +26,8 @@ jest.mock('@capillarytech/cap-ui-utils', () => {
|
|
|
24
26
|
};
|
|
25
27
|
});
|
|
26
28
|
|
|
29
|
+
jest.mock('../getSchema', () => jest.fn());
|
|
30
|
+
|
|
27
31
|
describe('getSenderDetails -- Test with valid responses', () => {
|
|
28
32
|
it('Should return correct response', () =>
|
|
29
33
|
expect(getSenderDetails('WHATSAPP', -1)).toEqual(Promise.resolve()));
|
|
@@ -438,4 +442,33 @@ describe('getLiquidTags -- Test with various responses', () => {
|
|
|
438
442
|
error: 'Internal Server Error',
|
|
439
443
|
});
|
|
440
444
|
});
|
|
441
|
-
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
describe('fetchSchemaForEntity', () => {
|
|
448
|
+
it('should fetch schema for version v2 and type LAYOUT', async () => {
|
|
449
|
+
const queryParams = { version: 'v2', type: 'LAYOUT', layout: 'testLayout' };
|
|
450
|
+
const mockLayout = { id: 'layout1', name: 'Test Layout' };
|
|
451
|
+
|
|
452
|
+
getSchema.mockReturnValue(Promise.resolve(mockLayout));
|
|
453
|
+
|
|
454
|
+
const result = await fetchSchemaForEntity({ queryParams });
|
|
455
|
+
|
|
456
|
+
expect(getSchema).toHaveBeenCalledWith(queryParams.layout);
|
|
457
|
+
expect(result).toEqual(mockLayout);
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it('should handle errors when fetching schema', async () => {
|
|
461
|
+
const queryParams = { version: 'v2', type: 'LAYOUT', layout: 'testLayout' };
|
|
462
|
+
const mockError = new Error('Failed to fetch schema');
|
|
463
|
+
|
|
464
|
+
getSchema.mockReturnValue(Promise.reject(mockError));
|
|
465
|
+
|
|
466
|
+
console.error = jest.fn();
|
|
467
|
+
|
|
468
|
+
const result = await fetchSchemaForEntity({ queryParams });
|
|
469
|
+
|
|
470
|
+
expect(getSchema).toHaveBeenCalledWith(queryParams.layout);
|
|
471
|
+
expect(result).toBeUndefined();
|
|
472
|
+
expect(console.error).toHaveBeenCalledWith(mockError);
|
|
473
|
+
});
|
|
474
|
+
});
|
|
@@ -98,7 +98,6 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
98
98
|
customPopoverVisible: false,
|
|
99
99
|
isDrawerVisible: false,
|
|
100
100
|
translationLang: 'en',
|
|
101
|
-
showLiquidValidation: false,
|
|
102
101
|
liquidErrorMessage: {
|
|
103
102
|
STANDARD_ERROR_MSG: [],
|
|
104
103
|
LIQUID_ERROR_MSG: [],
|
|
@@ -494,7 +493,6 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
494
493
|
const type = (this.props.location && this.props.location.query.type) ? this.props.location.query.type : 'full';
|
|
495
494
|
const currentModule = (this.props.location && this.props.location.query.module) ? this.props.location.query.module : 'default';
|
|
496
495
|
let errorData = _.cloneDeep(this.state.errorData);
|
|
497
|
-
const stateFormData = _.cloneDeep(this.state.formData);
|
|
498
496
|
if (channel && channel.toUpperCase() === SMS) {
|
|
499
497
|
for (let count = 0; count < this.state.tabCount; count += 1) {
|
|
500
498
|
if (_.isEmpty(errorData[count])) {
|
|
@@ -961,7 +959,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
961
959
|
} else if(index === 'template-version' && data !== '') {
|
|
962
960
|
errorData[index] = false;
|
|
963
961
|
}
|
|
964
|
-
|
|
962
|
+
isLiquidValid = isValid; // Existing validations support for liquid enabled orgs
|
|
965
963
|
// Check error for the versions
|
|
966
964
|
if (!isNaN(index) || index === 'base') {
|
|
967
965
|
if (errorData[index] === undefined) {
|
|
@@ -1002,7 +1000,6 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1002
1000
|
// Adds a bypass for cases where content is initially empty in the creation flow.
|
|
1003
1001
|
if(this.liquidFlow && !this.props.isEdit){
|
|
1004
1002
|
errorString = "";
|
|
1005
|
-
isValid = true;
|
|
1006
1003
|
isLiquidValid = true;
|
|
1007
1004
|
}
|
|
1008
1005
|
}
|
|
@@ -1013,7 +1010,6 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1013
1010
|
if (this.liquidFlow) {
|
|
1014
1011
|
this.setState(
|
|
1015
1012
|
(prevState) => ({
|
|
1016
|
-
showLiquidValidation: true,
|
|
1017
1013
|
liquidErrorMessage: {
|
|
1018
1014
|
...prevState.liquidErrorMessage,
|
|
1019
1015
|
STANDARD_ERROR_MSG: [errorString],
|
|
@@ -1036,15 +1032,16 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1036
1032
|
}
|
|
1037
1033
|
});
|
|
1038
1034
|
}
|
|
1035
|
+
|
|
1036
|
+
const isTemplateValid = this.liquidFlow ? isLiquidValid : isValid;
|
|
1039
1037
|
//Updating the state with the error data
|
|
1040
1038
|
this.setState((prevState) => ({
|
|
1041
|
-
isFormValid:
|
|
1042
|
-
showLiquidValidation: prevState.liquidErrorMessage?.LIQUID_ERROR_MSG?.length > 0 ? true : !isLiquidValid,
|
|
1039
|
+
isFormValid: isTemplateValid,
|
|
1043
1040
|
liquidErrorMessage: {
|
|
1044
1041
|
//Do not update the LIQUID_ERROR_MSG validation error message
|
|
1045
1042
|
...prevState.liquidErrorMessage,
|
|
1046
1043
|
//update Standard error message based on the updated content
|
|
1047
|
-
STANDARD_ERROR_MSG:
|
|
1044
|
+
STANDARD_ERROR_MSG: isTemplateValid ? [] : prevState.liquidErrorMessage?.STANDARD_ERROR_MSG,
|
|
1048
1045
|
},
|
|
1049
1046
|
errorData,
|
|
1050
1047
|
}), () => {
|
|
@@ -1054,8 +1051,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1054
1051
|
}
|
|
1055
1052
|
});
|
|
1056
1053
|
|
|
1057
|
-
this.props.onFormValidityChange(
|
|
1058
|
-
return
|
|
1054
|
+
this.props.onFormValidityChange(isTemplateValid, errorData);
|
|
1055
|
+
return isTemplateValid;
|
|
1059
1056
|
}
|
|
1060
1057
|
|
|
1061
1058
|
indexOfEnd(targetString, string) {
|
|
@@ -1083,9 +1080,9 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1083
1080
|
*/
|
|
1084
1081
|
const handleResult = (result) => {
|
|
1085
1082
|
const {formatMessage} = this.props.intl;
|
|
1083
|
+
// Checks for errors in the result and displays them if any are found.
|
|
1086
1084
|
if (result?.errors?.length > 0) {
|
|
1087
1085
|
this.setState((prevState) => ({
|
|
1088
|
-
showLiquidValidation: true,
|
|
1089
1086
|
liquidErrorMessage: {
|
|
1090
1087
|
...prevState.liquidErrorMessage,
|
|
1091
1088
|
LIQUID_ERROR_MSG: result?.errors?.map(error => error?.message) ?? [formatMessage(messages.somethingWentWrong)],
|
|
@@ -1096,22 +1093,22 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1096
1093
|
this.props.stopValidation();
|
|
1097
1094
|
return;
|
|
1098
1095
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1096
|
+
// Extracts the supported liquid tags from the given content and do the necessary checks.
|
|
1097
|
+
else {
|
|
1098
|
+
const extractedLiquidTags = extractNames(result?.data || []);
|
|
1101
1099
|
// Extracts the supported liquid tags from the given content.
|
|
1102
1100
|
const supportedLiquidTags = checkSupport(
|
|
1103
1101
|
result,
|
|
1104
1102
|
this.props?.metaEntities?.tagLookupMap
|
|
1105
1103
|
);
|
|
1106
1104
|
const unsupportedLiquidTags = extractedLiquidTags?.filter(
|
|
1107
|
-
(tag) => !supportedLiquidTags?.includes(tag)
|
|
1105
|
+
(tag) => !supportedLiquidTags?.includes(tag) && !this.skipTags(tag)
|
|
1108
1106
|
);
|
|
1109
1107
|
if (
|
|
1110
1108
|
unsupportedLiquidTags?.length > 0
|
|
1111
1109
|
) {
|
|
1112
1110
|
this.setState(
|
|
1113
1111
|
(prevState) => ({
|
|
1114
|
-
showLiquidValidation: true,
|
|
1115
1112
|
liquidErrorMessage: {
|
|
1116
1113
|
...prevState.liquidErrorMessage,
|
|
1117
1114
|
LIQUID_ERROR_MSG: [formatMessage(messages.unsupportedTagsValidationError, {
|
|
@@ -3425,7 +3422,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3425
3422
|
<CapColumn
|
|
3426
3423
|
style={val.colStyle ? val.colStyle : {border : ""}}
|
|
3427
3424
|
span={val.width}
|
|
3428
|
-
className={`${this.state.
|
|
3425
|
+
className={`${(this.state.liquidErrorMessage?.LIQUID_ERROR_MSG?.length || this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.length) && this.liquidFlow && "error-boundary"} `}
|
|
3429
3426
|
>
|
|
3430
3427
|
<CKEditor
|
|
3431
3428
|
id={val.id}
|
|
@@ -3469,7 +3466,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3469
3466
|
isModuleFilterEnabled = this.props.isFullMode;
|
|
3470
3467
|
}
|
|
3471
3468
|
columns.push(
|
|
3472
|
-
<CapColumn style={val.colStyle ? val.colStyle : {}} span={val.width} className={`${this.state.
|
|
3469
|
+
<CapColumn style={val.colStyle ? val.colStyle : {}} span={val.width} className={`${(this.state.liquidErrorMessage?.LIQUID_ERROR_MSG?.length || this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.length) && this.liquidFlow && "error-boundary"}`}>
|
|
3473
3470
|
<BeeEditor
|
|
3474
3471
|
uid={uuid}
|
|
3475
3472
|
tokenData={beeToken}
|
|
@@ -41,6 +41,8 @@ import v2MobilePushEditReducer from './reducer';
|
|
|
41
41
|
import * as globalActions from '../../Cap/actions';
|
|
42
42
|
import { MAPP_SDK } from './constants';
|
|
43
43
|
import { isEmbeddedEditOrPreview } from '../../../utils/commonUtils';
|
|
44
|
+
import { EMBEDDED } from '../../Whatsapp/constants';
|
|
45
|
+
import { OUTBOUND } from '../../../v2Components/FormBuilder/constants';
|
|
44
46
|
|
|
45
47
|
const PrefixWrapper = styled.div`
|
|
46
48
|
margin-right: 16px;
|
|
@@ -115,27 +117,53 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
115
117
|
let selectedWeChatAccount = {};
|
|
116
118
|
const queryType = String(get(this.props, 'location.query.type', ''))?.toLowerCase();
|
|
117
119
|
const creativesMode = String(get(this.props, 'creativesMode', ''))?.toLowerCase();
|
|
120
|
+
const { Edit: EditProps, templateData, Templates, type } = this.props || {};
|
|
121
|
+
const { selectedWeChatAccount: editSelectedWeChatAccount, templateDetails } = EditProps || {};
|
|
122
|
+
const { id: selectedWeChatAccountId } = editSelectedWeChatAccount || {};
|
|
123
|
+
const { definition } = templateDetails || {};
|
|
124
|
+
const { accountId: templateAccountId } = definition || {};
|
|
125
|
+
const { Edit: nextEdit } = nextProps || {};
|
|
118
126
|
if (isEmbeddedEditOrPreview(queryType, creativesMode)) {
|
|
119
|
-
selectedWeChatAccount = !_.isEmpty(
|
|
120
|
-
?
|
|
121
|
-
:
|
|
122
|
-
} else if (!_.isEmpty(
|
|
123
|
-
selectedWeChatAccount =
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
this.setMobilePushAccountOptions(
|
|
128
|
-
}
|
|
129
|
-
// Check if the query type is 'embedded' and the creatives mode is either 'edit' or 'preview'.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
127
|
+
selectedWeChatAccount = !_.isEmpty(editSelectedWeChatAccount)
|
|
128
|
+
? editSelectedWeChatAccount
|
|
129
|
+
: nextEdit?.selectedWeChatAccount;
|
|
130
|
+
} else if (!_.isEmpty(Templates?.selectedWeChatAccount)) {
|
|
131
|
+
selectedWeChatAccount = Templates?.selectedWeChatAccount;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (queryType === EMBEDDED && !nextEdit?.fetchingWeCrmAccounts && !_.isEqual(EditProps?.weCrmAccounts, nextEdit?.weCrmAccounts) && (!selectedWeChatAccount || _.isEmpty(selectedWeChatAccount))) {
|
|
135
|
+
this.setMobilePushAccountOptions(nextEdit?.weCrmAccounts, templateData?.definition?.accountId);
|
|
136
|
+
}
|
|
137
|
+
// Check if the query type is 'embedded' and the creatives mode is either 'edit' or 'preview'.
|
|
138
|
+
// If the type is not 'outbound', ensure that the selected WeChat account ID is not equal to the account ID in the template details.
|
|
139
|
+
// If all conditions are met, set the mobile push account options using the provided weCrmAccounts and the account ID from templateData.
|
|
140
|
+
if (
|
|
141
|
+
isEmbeddedEditOrPreview(queryType, creativesMode) &&
|
|
142
|
+
type !== OUTBOUND.toLowerCase() &&
|
|
143
|
+
nextEdit?.weCrmAccounts &&
|
|
144
|
+
!EditProps?.fetchingWeCrmAccounts &&
|
|
145
|
+
templateData?.definition?.accountId &&
|
|
146
|
+
!_.isEqual(templateAccountId, templateData?.definition?.accountId)
|
|
147
|
+
) {
|
|
148
|
+
this.setMobilePushAccountOptions(nextEdit?.weCrmAccounts, templateData?.definition?.accountId);
|
|
149
|
+
}
|
|
150
|
+
// If the type is 'outbound', ensure that the selected WeChat account ID is not equal to the account ID in the template details.
|
|
151
|
+
// If all conditions are met, set the mobile push account options using the provided weCrmAccounts and the template account ID.
|
|
152
|
+
if (
|
|
153
|
+
isEmbeddedEditOrPreview(queryType, creativesMode) &&
|
|
154
|
+
type === OUTBOUND.toLowerCase() &&
|
|
155
|
+
nextEdit?.weCrmAccounts &&
|
|
156
|
+
selectedWeChatAccountId &&
|
|
157
|
+
templateAccountId &&
|
|
158
|
+
!_.isEqual(selectedWeChatAccountId, templateAccountId)
|
|
159
|
+
) {
|
|
160
|
+
this.setMobilePushAccountOptions(nextEdit?.weCrmAccounts, templateAccountId);
|
|
161
|
+
}
|
|
162
|
+
if (!_.isEmpty(nextEdit?.selectedWeChatAccount) && !_.isEqual(editSelectedWeChatAccount, nextEdit?.selectedWeChatAccount) && (queryType === EMBEDDED) && this.props.location.query.module === "loyalty") {
|
|
135
163
|
const params = {
|
|
136
164
|
name: '',
|
|
137
165
|
sortBy: 'Most Recent',
|
|
138
|
-
accountId:
|
|
166
|
+
accountId: nextEdit?.selectedWeChatAccount?.id,
|
|
139
167
|
};
|
|
140
168
|
this.props.actions.getMobilepushTemplatesList('mobilepush', params);
|
|
141
169
|
}
|
|
@@ -164,7 +192,6 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
164
192
|
this.setTemplateOptions(nextProps.Edit.mobilepushTemplates);
|
|
165
193
|
}
|
|
166
194
|
}
|
|
167
|
-
|
|
168
195
|
this.handleEditSchemaOnPropsChange(nextProps, selectedWeChatAccount);
|
|
169
196
|
if (nextProps.Edit.uploadedAssetData) {
|
|
170
197
|
const formData = _.cloneDeep(this.state.formData);
|