@capillarytech/creatives-library 7.17.45 → 7.17.46

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.
@@ -182,8 +182,8 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
182
182
  visible={this.state.visible}
183
183
  onVisibleChange={this.togglePopoverVisibility}
184
184
  content={<div>
185
- <Spin tip="Getting tags..." spinning={this.props.loading}>
186
- <Search style={{ marginBottom: 8, width: '250px'}} placeholder="Search" onChange={this.onChange} />
185
+ <Spin tip={this.props?.intl?.formatMessage(messages.gettingTags)} spinning={this.props.loading}>
186
+ <Search style={{ marginBottom: 8, width: '250px'}} placeholder={this.props?.intl?.formatMessage(messages.searchText)} onChange={this.onChange} />
187
187
  {this.props.moduleFilterEnabled ? <CapSelect getPopupContainer={(triggerNode) => triggerNode.parentNode} style={{width: '250px', marginBottom: '16px', minWidth: 'initial', display: 'inherit'}} onChange={this.props.onContextChange} defaultValue="All" options={options}>
188
188
  </CapSelect> : ''}
189
189
  <Tree
@@ -34,4 +34,12 @@ export default defineMessages({
34
34
  id: 'creatives.components.CapTagList.loyalty',
35
35
  defaultMessage: 'Loyalty',
36
36
  },
37
+ "searchText": {
38
+ id: 'creatives.components.CapTagList.searchText',
39
+ defaultMessage: 'Search',
40
+ },
41
+ "gettingTags": {
42
+ id: 'creatives.components.CapTagList.gettingTags',
43
+ defaultMessage: "Getting tags...",
44
+ },
37
45
  });
@@ -24,6 +24,7 @@ import EDMEditor from "../../components/Edmeditor";
24
24
  import CustomPopOver from '../../components/CustomPopOver';
25
25
  import './_formBuilder.scss';
26
26
  import {updateCharCount, checkUnicode} from "../../utils/smsCharCountV2";
27
+ import globalMessages from '../../v2Containers/Cap/messages';
27
28
  import messages from './messages';
28
29
  const TabPane = Tabs.TabPane;
29
30
  const {Column} = Table;
@@ -1516,8 +1517,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
1516
1517
  this.setState({errorData: formData});
1517
1518
  } else {
1518
1519
  const tempTab = ifError ? currentTab : this.state.currentTab;
1519
- const version = `Version ${this.state.currentTab}`;
1520
- formData[tabCount].name = `Copy of ${formData[tempTab - 1].name ? formData[tempTab - 1].name : version}`;
1520
+ const version = `${this.props.intl.formatMessage(messages.version)} ${this.state.currentTab}`;
1521
+ formData[tabCount].name = `${this.props?.intl?.formatMessage(globalMessages.copyOf)} ${formData[tempTab - 1].name ? formData[tempTab - 1].name : version}`;
1521
1522
  formData[tabCount].base = false;
1522
1523
  const initialTab = this.state.currentTab;
1523
1524
  this.setState({formData, tabCount: tabCount + 1, currentTab: tabCount + 1, tabKey: formData[tabCount].tabKey}, () => {
@@ -54,4 +54,8 @@ export default defineMessages({
54
54
  id: 'creatives.components.FormBuilder.ok',
55
55
  defaultMessage: 'Ok',
56
56
  },
57
+ Version: {
58
+ id: 'creatives.components.FormBuilder.version',
59
+ defaultMessage: 'Version',
60
+ },
57
61
  });
@@ -7,6 +7,8 @@ export const TRAI_DLT = 'TRAI_DLT';
7
7
  export const CARD_BASED_SCOPE = 'CARD_BASED_SCOPE';
8
8
  export const HOSPITALITY_BASED_SCOPE = 'HOSPITALITY_BASED_SCOPE';
9
9
  export const REGISTRATION_CUSTOM_FIELD = 'Registration custom fields';
10
+ export const GIFT_CARDS = 'GIFT_CARDS';
11
+ export const PROMO_ENGINE = 'PROMO_ENGINE';
10
12
  export const CUSTOM_TAG = 'CustomTagMessage';
11
13
  export const CUSTOMER_EXTENDED_FIELD = 'Customer extended fields';
12
14
  export const EXTENDED_TAG = 'ExtendedTagMessage';
@@ -43,5 +45,29 @@ export const HOSPITALITY_RELATED_TAGS = [
43
45
  "email",
44
46
  "resID_Source",
45
47
  ];
48
+ export const GIFT_VOUCHER_RELATED_TAGS = [
49
+ "gift_voucher",
50
+ "gift_voucher_expiry_date.FORMAT_1",
51
+ "gift_voucher_expiry_date.FORMAT_2",
52
+ "gift_voucher_expiry_date.FORMAT_3",
53
+ "gift_voucher_expiry_date.FORMAT_4",
54
+ "gift_voucher_expiry_date.FORMAT_5",
55
+ "gift_voucher_expiry_date.FORMAT_6",
56
+ "gift_voucher_expiry_date.FORMAT_7",
57
+ "gift_voucher_expiry_date.FORMAT_8",
58
+ "gift_voucher_expiry_date",
59
+ ];
60
+ export const PROMO_ENGINE_RELATED_TAGS = [
61
+ "promotion",
62
+ "promotion_expiry_date.FORMAT_1",
63
+ "promotion_expiry_date.FORMAT_2",
64
+ "promotion_expiry_date.FORMAT_3",
65
+ "promotion_expiry_date.FORMAT_4",
66
+ "promotion_expiry_date.FORMAT_5",
67
+ "promotion_expiry_date.FORMAT_6",
68
+ "promotion_expiry_date.FORMAT_7",
69
+ "promotion_expiry_date.FORMAT_8",
70
+ "promotion_expiry_date",
71
+ ];
46
72
 
47
73
  export const CUSTOMER_BARCODE_TAG = "customer_barcode";
@@ -336,7 +336,7 @@ export class Gallery extends React.Component { // eslint-disable-line react/pref
336
336
  <CapInput
337
337
  className="search-text"
338
338
  style={{width: '210px'}}
339
- placeholder="Search"
339
+ placeholder={this.props.intl.formatMessage(messages.searchText)}
340
340
  prefix={<i className="material-icons" style={{color: '#707070', fontSize: '16px'}}>search</i>}
341
341
  value={this.state.searchText}
342
342
  onChange={(e) => this.searchAsset(e.target.value)}
@@ -86,4 +86,8 @@ export default defineMessages({
86
86
  id: 'creatives.containers.Assets.Gallery.assetDeleteFailed',
87
87
  defaultMessage: 'Image deletion failed.',
88
88
  },
89
+ searchText: {
90
+ id: 'creatives.components.CapTagList.searchText',
91
+ defaultMessage: 'Search',
92
+ },
89
93
  });
@@ -3104,7 +3104,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
3104
3104
  <CapInput
3105
3105
  className="search-text"
3106
3106
  style={{width: '210px'}}
3107
- placeholder="Search"
3107
+ placeholder={this.props.intl.formatMessage(messages.searchText)}
3108
3108
  prefix={<i className="material-icons" style={{color: '#707070', fontSize: '16px'}}>search</i>}
3109
3109
  value={this.state.searchText}
3110
3110
  onChange={(e) => this.searchAsset(e.target.value)}
@@ -866,7 +866,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
866
866
  duplicateTemplate(template) {
867
867
 
868
868
  const duplicateObj = _.cloneDeep(template);
869
- duplicateObj.name = `Copy of ${template.name} ${moment().format('MM-DD-YYYY HH:mm:ss')}`;
869
+ duplicateObj.name = `${this.props.intl.formatMessage(messages.copyOf)} ${template.name} ${moment().format('MM-DD-YYYY HH:mm:ss')}`;
870
870
  delete duplicateObj._id;
871
871
  if (this.state.channel.toLowerCase() === "sms") {
872
872
  this.props.smsActions.createTemplate(duplicateObj);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "7.17.45",
4
+ "version": "7.17.46",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/utils/common.js CHANGED
@@ -7,6 +7,8 @@ import {
7
7
  CARD_BASED_SCOPE,
8
8
  HOSPITALITY_RELATED_TAGS,
9
9
  HOSPITALITY_BASED_SCOPE,
10
+ GIFT_CARDS,
11
+ PROMO_ENGINE,
10
12
  EXTENDED_TAG,
11
13
  CUSTOMER_EXTENDED_FIELD,
12
14
  CUSTOM_TAG,
@@ -66,7 +68,15 @@ export const hasHospitalityBasedScope = Auth.hasFeatureAccess.bind(
66
68
  null,
67
69
  HOSPITALITY_BASED_SCOPE,
68
70
  );
71
+ export const hasPromoFeature = Auth.hasFeatureAccess.bind(
72
+ null,
73
+ PROMO_ENGINE,
74
+ );
69
75
 
76
+ export const hasGiftVoucherFeature = Auth.hasFeatureAccess.bind(
77
+ null,
78
+ GIFT_CARDS,
79
+ );
70
80
  export const hasJPLocaleHideFeatureEnabled = Auth.hasFeatureAccess.bind(
71
81
  null,
72
82
  JP_LOCALE_HIDE_FEATURE,
@@ -294,8 +304,8 @@ export const isTraiDLTEnable = (isFullMode, smsRegister) => {
294
304
  return isTraiDltFeature;
295
305
  };
296
306
 
297
-
298
- export const intlKeyGenerator = (value = "") => String(value).replace(/[^a-zA-Z0-9_]/g, "").toLowerCase();
307
+ //Input: " Spaces In Input "---> Output: "spaces_in_input"
308
+ export const intlKeyGenerator = (value = "") => String(value).replace(/[^a-zA-Z0-9_ ]/g, "").replace(/ /g, "_").toLowerCase();
299
309
 
300
310
  export const handleInjectedData = (data, scope) => {
301
311
  let tagType;
@@ -307,6 +317,7 @@ export const handleInjectedData = (data, scope) => {
307
317
  } else if (tag?.name === CUSTOMER_EXTENDED_FIELD) {
308
318
  tagType = EXTENDED_TAG;
309
319
  }
320
+
310
321
  if (tag?.name) {
311
322
  const name = tag.name;
312
323
  const key = intlKeyGenerator(name);
@@ -51,7 +51,7 @@ describe("handleInjectedData", () => {
51
51
  const result = handleInjectedData(data, "scope");
52
52
  const intlKey = intlKeyGenerator("scope");
53
53
  expect(intlKey).toEqual('scope');
54
- expect(result.tag1.name).toEqual(<FormattedMessage defaultMessage="Registration Fields" id="scope.registrationfields" values={{}} />);
54
+ expect(result.tag1.name).toEqual(<FormattedMessage defaultMessage="Registration Fields" id="scope.registration_fields" values={{}} />);
55
55
  });
56
56
 
57
57
  it("adds tagType for Registration custom fields", () => {
@@ -65,7 +65,7 @@ describe("handleInjectedData", () => {
65
65
  const intlKey = intlKeyGenerator();
66
66
  expect(intlKey).toEqual('');
67
67
  expect(result.tag1.name).toEqual(
68
- <FormattedMessage defaultMessage="Registration custom fields" id="scope.registrationcustomfields_name.CustomTagMessage" values={{}} />
68
+ <FormattedMessage defaultMessage="Registration custom fields" id="scope.registration_custom_fields_name.CustomTagMessage" values={{}} />
69
69
  );
70
70
  });
71
71
 
@@ -79,7 +79,7 @@ describe("handleInjectedData", () => {
79
79
  const result = handleInjectedData(data, "scope");
80
80
 
81
81
  expect(result.tag1.name).toEqual(
82
- <FormattedMessage defaultMessage="Customer extended fields" id="scope.customerextendedfields_name.ExtendedTagMessage" values={{}} />
82
+ <FormattedMessage defaultMessage="Customer extended fields" id="scope.customer_extended_fields_name.ExtendedTagMessage" values={{}} />
83
83
  );
84
84
  });
85
85
  it("adds tagType for Customer extended fields fields", () => {
@@ -157,7 +157,7 @@ describe("handleInjectedData", () => {
157
157
  const result = handleInjectedData(data, "scope");
158
158
 
159
159
  expect(result.tag1.subtags.subtag1.desc).toEqual(
160
- <FormattedMessage defaultMessage="Enter your first name" id="scope.enteryourfirstname" values={{}} />
160
+ <FormattedMessage defaultMessage="Enter your first name" id="scope.enter_your_first_name" values={{}} />
161
161
  );
162
162
  });
163
163
  it("replaces subtag name desc with intl key", () => {
@@ -175,7 +175,7 @@ describe("handleInjectedData", () => {
175
175
  const result = handleInjectedData(data, "scope");
176
176
 
177
177
  expect(result.tag1.subtags.subtag1.desc).toEqual(
178
- <FormattedMessage defaultMessage="Enter your first name" id="scope.enteryourfirstname" values={{}} />
178
+ <FormattedMessage defaultMessage="Enter your first name" id="scope.enter_your_first_name" values={{}} />
179
179
  );
180
180
  });
181
181
  });
@@ -1669,7 +1669,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
1669
1669
  } else {
1670
1670
  const tempTab = ifError ? currentTab : this.state.currentTab;
1671
1671
  const version = `Version ${this.state.currentTab}`;
1672
- formData[tabCount].name = `Copy of ${formData[tempTab - 1].name ? formData[tempTab - 1].name : version}`;
1672
+ formData[tabCount].name = `${this.props?.intl?.formatMessage(globalMessages.copyOf)} ${formData[tempTab - 1].name ? formData[tempTab - 1].name : version}`;
1673
1673
  formData[tabCount].base = false;
1674
1674
  const initialTab = this.state.currentTab;
1675
1675
  this.setState({formData, tabCount: tabCount + 1, currentTab: tabCount + 1, tabKey: formData[tabCount].tabKey}, () => {
@@ -201,5 +201,9 @@ export default defineMessages({
201
201
  id: `creatives.componentsV2.unbalanacedCurlyBraces`,
202
202
  defaultMessage: 'Invalid label, please close all curly braces'
203
203
  },
204
+ "copyOf": {
205
+ id: 'creatives.componentsV2.copyOf',
206
+ defaultMessage: 'Copy of',
207
+ },
204
208
  });
205
209
 
@@ -61,8 +61,9 @@ export function SlideBoxHeader(props) {
61
61
  email: <FormattedMessage {...messages.emailHeader} />,
62
62
  mobilepush: <FormattedMessage {...messages.pushNotificationHeader} />,
63
63
  wechat: <FormattedMessage {...messages.wechat} />,
64
- no_communication: 'NO_COMMUNICATION',
65
- ftp: 'FTP',
64
+ line: <FormattedMessage {...messages.lineHeader} />,
65
+ no_communication: <FormattedMessage {...messages.noCommunication} />,
66
+ ftp: <FormattedMessage {...messages.ftp} />,
66
67
  whatsapp: <FormattedMessage {...messages.whatsappTemplate} />,
67
68
  rcs: <FormattedMessage {...messages.rcsCreative} />,
68
69
  zalo: <FormattedMessage {...messages.zaloTemplate} />,
@@ -341,5 +341,13 @@ export default defineMessages({
341
341
  "wechat": {
342
342
  id: `${scope}.wechat`,
343
343
  defaultMessage: `Wechat`,
344
- }
344
+ },
345
+ "ftp": {
346
+ id: `${scope}.ftp`,
347
+ defaultMessage: `FTP`,
348
+ },
349
+ "noCommunication": {
350
+ id: `${scope}.noCommunication`,
351
+ defaultMessage: `NO_COMMUNICATION`,
352
+ },
345
353
  });
@@ -22,7 +22,8 @@ import './_tagList.scss';
22
22
  import { selectCurrentOrgDetails } from '../Cap/selectors';
23
23
  import { injectIntl } from 'react-intl';
24
24
  import { scope } from './messages';
25
- import { handleInjectedData } from '../../utils/common';
25
+ import { handleInjectedData, hasGiftVoucherFeature, hasPromoFeature } from '../../utils/common';
26
+ import { GIFT_VOUCHER_RELATED_TAGS, PROMO_ENGINE_RELATED_TAGS } from '../../containers/App/constants';
26
27
 
27
28
  const TreeNode = Tree.TreeNode;
28
29
 
@@ -95,10 +96,24 @@ export class TagList extends React.Component { // eslint-disable-line react/pref
95
96
  }
96
97
  populateTags(tagsList) {
97
98
  const mainTags = {};
99
+ const excludedTags = [];
100
+ if (!hasPromoFeature()) {
101
+ excludedTags.push(...PROMO_ENGINE_RELATED_TAGS);
102
+ //filtering PROMO_ENGINE_RELATED_TAGS if org does not have PROMO_ENGINE feature enabled
103
+ }
104
+ if (!hasGiftVoucherFeature()) {
105
+ //filtering GIFT_VOUCHER_RELATED_TAGS if org does not have GIFT_CARDS feature enabled
106
+ excludedTags.push(...GIFT_VOUCHER_RELATED_TAGS);
107
+ }
98
108
  //Form tags object with tag headers
99
109
  _.forEach(tagsList, (temp) => {
100
110
  const tag = temp.definition;
101
- const { locale : userLocale } = this.props?.intl || {};
111
+ const { locale: userLocale } = this.props?.intl || {};
112
+
113
+ // Check if the tag.value should be skipped based on feature control
114
+ if (_.includes(excludedTags, tag.value)) {
115
+ return; // Skip processing this tag
116
+ }
102
117
  if (!tag['tag-header']) {
103
118
  mainTags[tag.value] = {
104
119
  "name": tag?.label[userLocale] ? tag?.label[userLocale] : tag?.label?.en,
@@ -117,7 +132,7 @@ export class TagList extends React.Component { // eslint-disable-line react/pref
117
132
  });
118
133
 
119
134
  const mainTagsCloned = _.cloneDeep(mainTags);
120
- //Insert subtags in tag headers and reomve them from top level
135
+ //Insert subtags in tag headers and remove them from top level
121
136
  const result = {};
122
137
  _.forEach(mainTagsCloned, (tag, key) => {
123
138
  if (tag['tag-header']) {
@@ -108,7 +108,8 @@ import {
108
108
  import { ZALO_STATUS_OPTIONS, ZALO_STATUSES } from '../Zalo/constants';
109
109
  import { getWhatsappContent, getWhatsappStatus, getWhatsappCategory, getWhatsappCta } from '../Whatsapp/utils';
110
110
  import { getRCSContent } from '../Rcs/utils';
111
- import zaloMessages from '../Zalo/messages'
111
+ import zaloMessages from '../Zalo/messages';
112
+ import globalMessages from '../../v2Containers/Cap/messages';
112
113
  import { handlePreviewInNewTab } from '../../utils/common';
113
114
 
114
115
  import { MOBILE_PUSH, WECHAT, SMS, EMAIL, EBILL, LINE, VIBER, FACEBOOK, WHATSAPP, RCS, ZALO } from '../CreativesContainer/constants';
@@ -1755,7 +1756,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
1755
1756
 
1756
1757
  duplicateTemplate(template) {
1757
1758
  const duplicateObj = cloneDeep(template);
1758
- duplicateObj.name = `${this.props.intl.formatMessage(messages.copyOf)} ${template?.name} ${moment().format('MM-DD-YYYY HH:mm:ss')}`;
1759
+ duplicateObj.name = `${this.props.intl.formatMessage(globalMessages.copyOf)} ${template?.name} ${moment().format('MM-DD-YYYY HH:mm:ss')}`;
1759
1760
  delete duplicateObj._id;
1760
1761
 
1761
1762
  if (this.state.channel.toLowerCase() === "mobilepush") {
@@ -0,0 +1,52 @@
1
+ import { fromJS } from "immutable";
2
+ import { makeSelectZalo, selectZaloDomain } from "../selectors";
3
+ import { zaloTemplateInfoData } from "./mockData";
4
+
5
+ describe("makeSelectZalo", () => {
6
+ it("returns the expected object with default values when substate is empty", () => {
7
+ // Arrange
8
+ const state = fromJS({ zalo: {} });
9
+ const expected = {
10
+ zaloTemplateInfoStatus: undefined,
11
+ zaloTemplateInfoValue: undefined,
12
+ zaloTemplateInfoError: undefined,
13
+ zaloTemplatePreviewData: undefined,
14
+ };
15
+ const selector = makeSelectZalo();
16
+
17
+ // Act
18
+ const result = selector(state);
19
+
20
+ // Assert
21
+ expect(result).toEqual(expected);
22
+ });
23
+
24
+ it("returns the expected object when substate has values", () => {
25
+ // Arrange
26
+ const state = fromJS({
27
+ zalo: zaloTemplateInfoData,
28
+ });
29
+ const expected = {
30
+ zaloTemplateInfoStatus: "success",
31
+ zaloTemplateInfoValue: fromJS(zaloTemplateInfoData.zaloTemplateInfoValue),
32
+ zaloTemplateInfoError: null,
33
+ zaloTemplatePreviewData: undefined,
34
+ };
35
+ const selector = makeSelectZalo();
36
+
37
+ // Act
38
+ const result = selector(state);
39
+
40
+ // Assert
41
+ expect(result).toEqual(expected);
42
+ });
43
+
44
+ it("returns the expected object with default values when substate is empty", () => {
45
+ // Arrange
46
+ const state = fromJS({ zalo: {} });
47
+ const expected = fromJS({});
48
+ const result = selectZaloDomain(state);
49
+ // Assert
50
+ expect(result).toEqual(expected);
51
+ });
52
+ });