@capillarytech/creatives-library 8.0.10 → 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.
Files changed (45) hide show
  1. package/config/app.js +2 -0
  2. package/containers/App/constants.js +1 -0
  3. package/initialState.js +3 -0
  4. package/package.json +1 -1
  5. package/services/api.js +23 -2
  6. package/services/tests/api.test.js +181 -0
  7. package/utils/common.js +7 -0
  8. package/utils/commonUtils.js +7 -1
  9. package/utils/tagValidations.js +99 -1
  10. package/utils/tests/commonUtil.test.js +37 -1
  11. package/utils/tests/tagValidations.test.js +392 -2
  12. package/v2Components/Ckeditor/index.js +12 -10
  13. package/v2Components/ErrorInfoNote/index.js +89 -0
  14. package/v2Components/ErrorInfoNote/messages.js +29 -0
  15. package/v2Components/ErrorInfoNote/style.scss +72 -0
  16. package/v2Components/FormBuilder/_formBuilder.scss +4 -1
  17. package/v2Components/FormBuilder/index.js +172 -74
  18. package/v2Components/FormBuilder/messages.js +8 -0
  19. package/v2Containers/Cap/actions.js +8 -0
  20. package/v2Containers/Cap/constants.js +4 -0
  21. package/v2Containers/Cap/mockData.js +74 -0
  22. package/v2Containers/Cap/reducer.js +12 -0
  23. package/v2Containers/Cap/sagas.js +28 -1
  24. package/v2Containers/Cap/selectors.js +5 -0
  25. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +1 -0
  26. package/v2Containers/Cap/tests/reducer.test.js +50 -0
  27. package/v2Containers/Cap/tests/saga.test.js +81 -1
  28. package/v2Containers/CreativesContainer/SlideBoxContent.js +7 -0
  29. package/v2Containers/CreativesContainer/SlideBoxFooter.js +40 -17
  30. package/v2Containers/CreativesContainer/constants.js +1 -0
  31. package/v2Containers/CreativesContainer/index.js +45 -4
  32. package/v2Containers/CreativesContainer/index.scss +13 -1
  33. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +16 -0
  34. package/v2Containers/Email/_email.scss +3 -0
  35. package/v2Containers/Email/index.js +2 -0
  36. package/v2Containers/EmailWrapper/index.js +3 -0
  37. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +3 -0
  38. package/v2Containers/MobilePush/Edit/constants.js +2 -0
  39. package/v2Containers/MobilePush/Edit/index.js +124 -30
  40. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +93 -0
  41. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +12 -0
  42. package/v2Containers/Viber/constants.js +1 -1
  43. package/v2Containers/Viber/index.js +19 -19
  44. package/v2Containers/Viber/messages.js +0 -4
  45. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +12 -0
@@ -39,6 +39,11 @@ import injectReducer from '../../../utils/injectReducer';
39
39
  import { v2MobilePushEditSagas } from './sagas';
40
40
  import v2MobilePushEditReducer from './reducer';
41
41
  import * as globalActions from '../../Cap/actions';
42
+ import { MAPP_SDK } from './constants';
43
+ import { isEmbeddedEditOrPreview } from '../../../utils/commonUtils';
44
+ import { EMBEDDED } from '../../Whatsapp/constants';
45
+ import { OUTBOUND } from '../../../v2Components/FormBuilder/constants';
46
+
42
47
  const PrefixWrapper = styled.div`
43
48
  margin-right: 16px;
44
49
  `;
@@ -109,16 +114,56 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
109
114
  } else if (nextProps.isGetFormData && this.props.isGetFormData !== nextProps.isGetFormData && this.props.isFullMode && !this.props.Create.createTemplateInProgress) {
110
115
  this.startValidation();
111
116
  }
112
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount :
113
- (!_.isEmpty(this.props.Edit.selectedWeChatAccount) ? this.props.Edit.selectedWeChatAccount : nextProps.Edit.selectedWeChatAccount));
114
- if (this.props.location.query.type === 'embedded' && !nextProps.Edit.fetchingWeCrmAccounts && !_.isEqual(this.props.Edit.weCrmAccounts, nextProps.Edit.weCrmAccounts) && (!selectedWeChatAccount || _.isEmpty(selectedWeChatAccount))) {
115
- this.setMobilePushAccountOptions(nextProps.Edit.weCrmAccounts, get(this.props, "templateData.definition.accountId"));
116
- }
117
- if (!_.isEmpty(nextProps.Edit.selectedWeChatAccount) && !_.isEqual(this.props.Edit.selectedWeChatAccount, nextProps.Edit.selectedWeChatAccount) && (this.props.location.query.type === 'embedded') && this.props.location.query.module === "loyalty") {
117
+ let selectedWeChatAccount = {};
118
+ const queryType = String(get(this.props, 'location.query.type', ''))?.toLowerCase();
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 || {};
126
+ if (isEmbeddedEditOrPreview(queryType, creativesMode)) {
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") {
118
163
  const params = {
119
164
  name: '',
120
165
  sortBy: 'Most Recent',
121
- accountId: nextProps.Edit.selectedWeChatAccount.id,
166
+ accountId: nextEdit?.selectedWeChatAccount?.id,
122
167
  };
123
168
  this.props.actions.getMobilepushTemplatesList('mobilepush', params);
124
169
  }
@@ -147,7 +192,6 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
147
192
  this.setTemplateOptions(nextProps.Edit.mobilepushTemplates);
148
193
  }
149
194
  }
150
-
151
195
  this.handleEditSchemaOnPropsChange(nextProps, selectedWeChatAccount);
152
196
  if (nextProps.Edit.uploadedAssetData) {
153
197
  const formData = _.cloneDeep(this.state.formData);
@@ -217,8 +261,26 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
217
261
  }
218
262
  };
219
263
 
264
+ getWeChatAccount = () => {
265
+ const { location, creativesMode, Edit: EditProps, Templates } = this.props || {};
266
+ const { query } = location || {};
267
+ const { selectedWeChatAccount: editSelectedWeChatAccount } = EditProps || {};
268
+ const { selectedWeChatAccount: templateSelectedWeChatAccount } = Templates || {};
269
+ const queryType = String(get(query, 'type', '')).toLowerCase();
270
+ const mode = String(creativesMode).toLowerCase();
271
+ let selectedWeChatAccount = {};
272
+ if (isEmbeddedEditOrPreview(queryType, mode)) {
273
+ selectedWeChatAccount = !_.isEmpty(editSelectedWeChatAccount)
274
+ ? editSelectedWeChatAccount
275
+ : templateSelectedWeChatAccount;
276
+ } else if (!_.isEmpty(templateSelectedWeChatAccount)) {
277
+ selectedWeChatAccount = templateSelectedWeChatAccount;
278
+ }
279
+ return selectedWeChatAccount;
280
+ };
281
+
220
282
  onLinkTypeChange = (eventTriggered, formData, field, currentTab, inputSchema) => {
221
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount : this.props.Edit.selectedWeChatAccount);
283
+ const selectedWeChatAccount = this.getWeChatAccount();
222
284
  const schema = inputSchema ? _.cloneDeep(inputSchema) : _.cloneDeep(this.state.schema);
223
285
  const tabIndex = currentTab || this.state.currentTab;
224
286
  const inputFields = get(schema, `containers[0].panes[${tabIndex - 1}].sections[0].childSections[0].childSections[0].inputFields`);
@@ -334,27 +396,41 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
334
396
  this.setState({formData, accountsOptions: accounts.map((acc) => ({key: acc.id, label: acc.name, value: acc.id}))});
335
397
  };
336
398
 
399
+ createDefinition = (account) => ({
400
+ accountId: account?.id,
401
+ licenseCode: account?.sourceAccountIdentifier,
402
+ gatewayId: account?.configs?.gatewayId,
403
+ gatewayAccountId: account?.configs?.gatewayAccountId,
404
+ sourceType: account?.sourceTypeName,
405
+ });
406
+
337
407
  getTransformedData = (formData) => {
338
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount : this.props.Edit.selectedWeChatAccount);
408
+ const selectedWeChatAccount = this.getWeChatAccount();
339
409
  const obj = _.cloneDeep(this.state.editData);
340
410
  obj.versions = {
341
411
  base: {},
342
412
  };
343
413
  obj.type = 'MOBILEPUSH';
344
414
  obj.name = formData['template-name'];
345
- if(this.props?.Templates?.selectedWeChatAccount?.sourceTypeName === 'MAPP_SDK') {
346
- obj.definition = {
347
- accountId: selectedWeChatAccount.id,
348
- licenseCode: selectedWeChatAccount.sourceAccountIdentifier,
349
- gatewayId: selectedWeChatAccount.configs.gatewayId,
350
- gatewayAccountId: selectedWeChatAccount.configs.gatewayAccountId,
351
- sourceType: selectedWeChatAccount.sourceTypeName,
352
- };
415
+ const queryType = String(get(this.props, 'location.query.type', ''))?.toLowerCase();
416
+ const creativesMode = String(get(this.props, 'creativesMode', ''))?.toLowerCase();
417
+ if (isEmbeddedEditOrPreview(queryType, creativesMode)) {
418
+ if (get(this.props, 'Edit.selectedWeChatAccount.sourceTypeName') === MAPP_SDK) {
419
+ obj.definition = this.createDefinition(selectedWeChatAccount);
420
+ } else {
421
+ obj.definition = {
422
+ accountId: selectedWeChatAccount?.id,
423
+ licenseCode: selectedWeChatAccount?.sourceAccountIdentifier,
424
+ sourceType: selectedWeChatAccount?.sourceTypeName,
425
+ };
426
+ }
427
+ } else if (get(this.props, 'Templates.selectedWeChatAccount.sourceTypeName') === MAPP_SDK) {
428
+ obj.definition = this.createDefinition(selectedWeChatAccount);
353
429
  } else {
354
430
  obj.definition = {
355
431
  accountId: selectedWeChatAccount?.id,
356
- licenseCode: selectedWeChatAccount.sourceAccountIdentifier,
357
- sourceType: selectedWeChatAccount.sourceTypeName,
432
+ licenseCode: selectedWeChatAccount?.sourceAccountIdentifier,
433
+ sourceType: selectedWeChatAccount?.sourceTypeName,
358
434
  };
359
435
  }
360
436
  if (this.props.location.query && this.props.location.query.module !== 'dvs') {
@@ -565,7 +641,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
565
641
  };
566
642
 
567
643
  getLinkName = (link) => {
568
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount : this.props.Edit.selectedWeChatAccount);
644
+ const selectedWeChatAccount = this.getWeChatAccount();
569
645
  const ck = selectedWeChatAccount.configs ? !!selectedWeChatAccount.configs.deeplink : false;
570
646
  const deepLinkOptions = _.filter(JSON.parse(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (l) => l.link === link);
571
647
  if (deepLinkOptions[0]) {
@@ -964,7 +1040,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
964
1040
  showSelectedIosCta = (inputSchema, field, tab, selectedConfig) => {
965
1041
  const currentTab = tab || this.state.currentTab;
966
1042
  const schema = inputSchema ? _.cloneDeep(inputSchema) : _.cloneDeep(this.state.schema);
967
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount : this.props.Edit.selectedWeChatAccount);
1043
+ const selectedWeChatAccount = this.getWeChatAccount();
968
1044
  const ck = selectedWeChatAccount.configs ? !!selectedWeChatAccount.configs.deeplink : false;
969
1045
  const deepLinkOptions = _.map(JSON.parse(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (link) => ({label: link.name, value: link.link, title: link.link }) );
970
1046
 
@@ -1092,7 +1168,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1092
1168
  };
1093
1169
 
1094
1170
  deletePrimaryCTA = (event) => {
1095
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount : this.props.Edit.selectedWeChatAccount);
1171
+ const selectedWeChatAccount = this.getWeChatAccount();
1096
1172
  const id = event.currentTarget.id;
1097
1173
  const schema = _.cloneDeep(this.state.schema);
1098
1174
  // const eventsMap = _.cloneDeep(this.state.eventsMap);
@@ -1192,7 +1268,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1192
1268
  };
1193
1269
 
1194
1270
  deleteSecondaryCTA = (event) => {
1195
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount : this.props.Edit.selectedWeChatAccount);
1271
+ const selectedWeChatAccount = this.getWeChatAccount();
1196
1272
  const id = event.currentTarget.id;
1197
1273
  if (id === "secondary-cta-0-delete") {
1198
1274
  const secCta2 = document.getElementById("secondary-cta-1-delete");
@@ -1479,8 +1555,18 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1479
1555
  if (this.props.location.query.type === 'embedded' && temp.id === "mobilepush-accounts" ) {
1480
1556
  temp.options = this.state.templateOptions ? this.state.accountsOptions : [];
1481
1557
  }
1482
- if (temp.id === "mobile-push-preview" && this.props.Templates.selectedWeChatAccount && !_.isEmpty(this.props.Templates.selectedWeChatAccount)) {
1483
- temp.content.appName = this.props.Templates.selectedWeChatAccount.name;
1558
+ if (temp.id === "mobile-push-preview") {
1559
+ const { location, creativesMode, Edit: EditProps, Templates } = this.props || {};
1560
+ const { query } = location || {};
1561
+ const { selectedWeChatAccount: editSelectedWeChatAccount } = EditProps || {};
1562
+ const { selectedWeChatAccount: templateSelectedWeChatAccount } = Templates || {};
1563
+ const queryType = String(get(query, 'type', ''))?.toLowerCase();
1564
+ const mode = String(creativesMode).toLowerCase();
1565
+ if (isEmbeddedEditOrPreview(queryType, mode) && !_.isEmpty(editSelectedWeChatAccount)) {
1566
+ temp.content.appName = editSelectedWeChatAccount?.name;
1567
+ } else if (!_.isEmpty(templateSelectedWeChatAccount)) {
1568
+ temp.content.appName = templateSelectedWeChatAccount?.name;
1569
+ }
1484
1570
  }
1485
1571
  _.forEach(col.supportedEvents, (event) => {
1486
1572
  temp.injectedEvents[event] = this.getMappedEvent(col.id, event);
@@ -1565,7 +1651,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1565
1651
  };
1566
1652
 
1567
1653
  showCtaKeys = (eventTriggered, formData, field, tabIndex, schemaInput) => {
1568
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount : this.props.Edit.selectedWeChatAccount);
1654
+ const selectedWeChatAccount = this.getWeChatAccount();
1569
1655
  const currentTab = tabIndex || this.state.currentTab;
1570
1656
  const schema = _.cloneDeep(schemaInput || this.state.schema);
1571
1657
  const eventsMap = _.cloneDeep(this.state.eventsMap);
@@ -1620,7 +1706,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1620
1706
  return schema;
1621
1707
  };
1622
1708
  addPrimaryCta = (flag, formData, field, inputSchema, currentTab) => {
1623
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount : this.props.Edit.selectedWeChatAccount);
1709
+ const selectedWeChatAccount = this.getWeChatAccount();
1624
1710
  const id = field.id;
1625
1711
  const schema = inputSchema ? _.cloneDeep(inputSchema) : _.cloneDeep(this.state.schema);
1626
1712
  const ck = selectedWeChatAccount.configs ? !!selectedWeChatAccount.configs.deeplink : false;
@@ -1653,7 +1739,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1653
1739
  const tabIndex = currentTab || this.state.currentTab;
1654
1740
  const formDataCopy = cloneDeep(formData);
1655
1741
  const schema = inputSchema ? _.cloneDeep(inputSchema) : _.cloneDeep(this.state.schema);
1656
- const selectedWeChatAccount = (!_.isEmpty(this.props.Templates.selectedWeChatAccount) ? this.props.Templates.selectedWeChatAccount : this.props.Edit.selectedWeChatAccount);
1742
+ const selectedWeChatAccount = this.getWeChatAccount();
1657
1743
  const ck = selectedWeChatAccount.configs ? !!selectedWeChatAccount.configs.deeplink : false;
1658
1744
  const deepLinkOptions = selectedWeChatAccount ? _.map(JSON.parse(ck ? selectedWeChatAccount.configs.deeplink : '[]'), (link) => ({label: link.name, value: link.link, title: link.link }) ) : [];
1659
1745
  const inputFields = get(schema, `containers[0].panes[${tabIndex - 1}].sections[0].childSections[0].childSections[0].inputFields`);
@@ -1702,7 +1788,14 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1702
1788
  if (!_.isEmpty(actionText)) {
1703
1789
  this.deleteSecondaryCtaIos();
1704
1790
  }
1705
- this.props.actions.getIosCtas(this.props.Templates.selectedWeChatAccount.sourceAccountIdentifier);//TODO: need to get license code of accoutn and send as arg
1791
+ const queryType = String(get(this.props, 'location.query.type', ''))?.toLowerCase();
1792
+ const creativesMode = String(get(this.props, 'creativesMode', ''))?.toLowerCase();
1793
+ if (isEmbeddedEditOrPreview(queryType, creativesMode)) {
1794
+ this.props.actions.getIosCtas(this.props.Edit.selectedWeChatAccount.sourceAccountIdentifier);
1795
+ } else {
1796
+ this.props.actions.getIosCtas(this.props.Templates.selectedWeChatAccount.sourceAccountIdentifier);
1797
+ }
1798
+ //TODO: need to get license code of accoutn and send as arg
1706
1799
  } else {
1707
1800
  this.deleteSecondaryCtaIos(() => { // oncick of change
1708
1801
  this.setState({showIosCtaTable: true});
@@ -1957,6 +2050,7 @@ Edit.propTypes = {
1957
2050
  onValidationFail: PropTypes.bool,
1958
2051
  onPreviewContentClicked: PropTypes.func,
1959
2052
  onTestContentClicked: PropTypes.func,
2053
+ creativesMode: PropTypes.string,
1960
2054
  };
1961
2055
 
1962
2056
  const mapStateToProps = createStructuredSelector({