@capillarytech/creatives-library 7.9.11 → 7.9.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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "7.9.11",
4
+ "version": "7.9.12",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/utils/common.js CHANGED
@@ -38,9 +38,11 @@ export const hasStore2DoorFeature = Auth.hasFeatureAccess.bind(
38
38
  STORE2DOOR_PLUS_ENABLED,
39
39
  );
40
40
 
41
- export function getTreeStructuredTags({tagsList, userLocale = 'en', offerDetails = []}) {
41
+ export function getTreeStructuredTags({tagsList, userLocale = 'en', offerDetails = [], disableTagsDetails = {}}) {
42
42
  console.log('populating tags', (tagsList || []).length);
43
43
  const mainTags = {};
44
+ const { disableRelatedTags, childTagsToDisable, parentTagstoDisable} = disableTagsDetails;
45
+
44
46
 
45
47
  _.forEach(tagsList, (temp) => {
46
48
  const tag = temp.definition;
@@ -48,6 +50,7 @@ export function getTreeStructuredTags({tagsList, userLocale = 'en', offerDetails
48
50
  mainTags[tag.value] = {
49
51
  name: tag.label[userLocale] || tag.label.en,
50
52
  value: tag.value,
53
+ disabled: disableRelatedTags ? childTagsToDisable.includes(tag.value) : false,
51
54
  };
52
55
  } else if (tag['tag-header'] && mainTags[tag.value]) {
53
56
  // to check it this tag header is already available in mainTags object,
@@ -60,6 +63,7 @@ export function getTreeStructuredTags({tagsList, userLocale = 'en', offerDetails
60
63
  "name": tag.label[userLocale] || tag.label.en,
61
64
  "subtags": tag.subtags,
62
65
  "value": tag.value,
66
+ "disabled": disableRelatedTags ? parentTagstoDisable.includes(tag.value) : false,
63
67
  };
64
68
  }
65
69
  });
@@ -175,17 +179,19 @@ function populateTagForChildren(targetTag, tagsObject, tagValue) {
175
179
  function getTreeStructureData(data) {
176
180
  const result = [];
177
181
  _.forOwn(data, (mainTag) => {
178
- const { name, value, subtags = [] } = mainTag;
182
+ const { name, value, subtags = [], disabled } = mainTag;
179
183
  if (!mainTag['tag-header']) {
180
184
  result.push({
181
185
  title: name,
182
186
  value: `{{${value}}}`,
187
+ disabled,
183
188
  });
184
189
  } else {
185
190
  const obj = {
186
191
  title: name,
187
192
  value: `{{${value}}}`,
188
193
  selectable: false,
194
+ disabled,
189
195
  };
190
196
  obj.children = getSubTags(subtags);
191
197
  result.push(obj);
@@ -197,17 +203,19 @@ function getTreeStructureData(data) {
197
203
  function getSubTags(subtagsParam) {
198
204
  const result = [];
199
205
  _.forOwn(subtagsParam, (subTag) => {
200
- const { name, value, subtags = [] } = subTag;
206
+ const { name, value, subtags = [], disabled } = subTag;
201
207
  if (_.isEmpty(subtags)) {
202
208
  result.push({
203
209
  title: name,
204
210
  value: `{{${value}}}`,
211
+ disabled,
205
212
  });
206
213
  } else {
207
214
  const obj = {
208
215
  title: name,
209
216
  value: `{{${value}}}`,
210
217
  selectable: false,
218
+ disabled,
211
219
  };
212
220
  obj.children = getSubTags(subtags);
213
221
  result.push(obj);
@@ -8,16 +8,18 @@ import PropTypes from 'prop-types';
8
8
 
9
9
  import React from 'react';
10
10
  // import styled from 'styled-components';
11
- import { CapSpin, CapModal, CapButton, CapPopover, CapInput, CapTree, CapSelect } from '@capillarytech/cap-ui-library';
11
+ import { CapSpin, CapModal, CapButton, CapPopover, CapInput, CapTree, CapSelect, CapTooltip } from '@capillarytech/cap-ui-library';
12
12
 
13
13
  import _ from 'lodash';
14
- import { injectIntl, intlShape } from 'react-intl';
14
+ import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
15
+ import { createStructuredSelector } from 'reselect';
15
16
  import messages from './messages';
17
+ import { makeSelectLoyaltyPromotionDisplay } from '../../v2Containers/Cap/selectors';
18
+ import withCreatives from '../../hoc/withCreatives';
16
19
 
17
20
  const {Search} = CapInput;
18
21
  const {CapTreeNode} = CapTree;
19
22
  class CapTagList extends React.Component { // eslint-disable-line react/prefer-stateless-function
20
-
21
23
  constructor(props) {
22
24
  super(props);
23
25
  this.state = {
@@ -132,23 +134,39 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
132
134
  };
133
135
 
134
136
  renderTags(tags, searchString = '') {
137
+ const { disableRelatedTags, childTagsToDisable, parentTagstoDisable} = this.props.disableTagsDetails;
135
138
  const list = [];
139
+ const loyaltyAttrDisableText = <FormattedMessage {...messages.loyaltyAttributeDisable} />;
136
140
  _.forEach(tags, (val = '', key) => {
137
141
  let supportedTagsString = '';
138
142
  _.forEach(val.supportedTags, (supportedTag) => {
139
143
  supportedTagsString += `${supportedTag} ,`;
140
144
  });
141
145
  supportedTagsString = supportedTagsString.replace(/,\s*$/, "");
142
-
143
146
  if (_.has(val, 'subtags')) {
144
- const temp = this.renderTags(val.subtags);
147
+ const disabled = disableRelatedTags ? parentTagstoDisable.includes(key) : false;
148
+ const temp = this.renderTags(val.subtags, '', disabled);
145
149
  list.push((
146
- <CapTreeNode title={val.name} tag={val} key={val.couponSeriesId ? `${key}(${val.couponSeriesId})` : `${key}`}>
150
+ <CapTreeNode
151
+ title={disabled ? <CapTooltip title={loyaltyAttrDisableText}>{val.name}</CapTooltip> : val.name}
152
+ tag={val}
153
+ key={val.couponSeriesId ? `${key}(${val.couponSeriesId})` : `${key}`}
154
+ disabled={disabled}
155
+ >
147
156
  {temp}
148
157
  </CapTreeNode>
149
158
  ));
150
159
  } else if (searchString === '' || !searchString || ((val.name || '').toLowerCase().indexOf(searchString.toLowerCase()) !== -1)) {
151
- const tempNode = (<CapTreeNode title={val.desc || val.name} tag={val} isLeaf key={val.couponSeriesId ? `${key}(${val.couponSeriesId})` : `${key}`}></CapTreeNode>);
160
+ const childDisabled = disableRelatedTags ? childTagsToDisable.includes(key) : false;
161
+ const tempNode = (
162
+ <CapTreeNode
163
+ title={childDisabled ? <CapTooltip title={loyaltyAttrDisableText}>{val.desc || val.name}</CapTooltip> : (val.desc || val.name)}
164
+ tag={val}
165
+ isLeaf
166
+ key={val.couponSeriesId ? `${key}(${val.couponSeriesId})` : `${key}`}
167
+ disabled={childDisabled}
168
+ >
169
+ </CapTreeNode>);
152
170
  list.push(tempNode);
153
171
  }
154
172
  });
@@ -253,10 +271,27 @@ CapTagList.propTypes = {
253
271
  visibleTaglist: PropTypes.bool,
254
272
  hidePopover: PropTypes.bool,
255
273
  modalProps: PropTypes.any,
274
+ disableTagsDetails: PropTypes.object,
256
275
  };
257
276
 
258
277
  CapTagList.defaultValue = {
259
278
  hidePopover: false,
260
279
  };
261
280
 
262
- export default injectIntl(CapTagList);
281
+ function mapDispatchToProps() {
282
+ return {
283
+ };
284
+ }
285
+
286
+ const mapStateToProps = createStructuredSelector({
287
+ disableTagsDetails: makeSelectLoyaltyPromotionDisplay(),
288
+ });
289
+
290
+ export default withCreatives({
291
+ WrappedComponent: CapTagList,
292
+ mapStateToProps,
293
+ mapDispatchToProps,
294
+ suserAuth: true,
295
+ });
296
+
297
+ // export default injectIntl(CapTagList);
@@ -42,4 +42,8 @@ export default defineMessages({
42
42
  id: 'creatives.componentsV2.CapTagList.search',
43
43
  defaultMessage: 'Search',
44
44
  },
45
+ "loyaltyAttributeDisable": {
46
+ id: `creatives.componentsV2.CapTagList.loyaltyAttributeDisable`,
47
+ defaultMessage: 'You won’t be able to add loyalty related attributes since the loyalty program/ card series is None.',
48
+ },
45
49
  });
@@ -205,7 +205,27 @@ class Ckeditor extends React.Component { // eslint-disable-line react/prefer-sta
205
205
  //this.editorInstance.name = this.id;
206
206
 
207
207
  //Register listener for custom events if any
208
- this.editorInstance.on('change', this.handleContentChange);
208
+ // this.editorInstance.on('change', this.handleContentChange);
209
+
210
+ // mode event is fired whenever mode is toggled from normal to source mode or vice versa
211
+ // change event works only in wysiwyg(non-source) mode, key event works in both source & wysiwyg(non-source) mode but,
212
+ // key event doesn't get fired up while setting text to bold,italic etc..
213
+ this.editorInstance.on('mode',()=>{
214
+ if(this.editorInstance.mode==="source"){
215
+ this.editorInstance.on('key',this.handleContentChange)
216
+ }
217
+ else{
218
+ if(this.editorInstance.hasListeners("key")){
219
+ /*Removing the 'key' listener is necessary. If not removed and the mode is switched in the following manner :
220
+ source mode -> Non-source mode -> source mode,
221
+ then under this scenario both 'key' and 'change' listener will get fired on entering text. Except that 'key' listener will not get fired when setting text to 'bold', 'italic' etc.
222
+ */
223
+ this.editorInstance.removeListener("key",this.handleContentChange)
224
+ }
225
+ this.editorInstance.on('change',this.handleContentChange)
226
+ }
227
+ })
228
+
209
229
  _.forEach(this.props.events, (event, index) => {
210
230
  this.editorInstance.on(index, event);
211
231
  });
@@ -11,9 +11,9 @@ export const LOGOUT_SUCCESS_V2 = 'cap/LOGOUT_SUCCESS_V2';
11
11
  export const LOGOUT_FAILURE_V2 = 'cap/LOGOUT_FAILURE_V2';
12
12
  export const ADD_MESSAGE = 'cap/ADD_MESSAGE';
13
13
  export const REMOVE_MESSAGE = 'cap/REMOVE_MESSAGE';
14
- export const GET_USER_DATA_REQUEST = 'cap/GET_USER_DATA_REQUEST';
15
- export const GET_USER_DATA_SUCCESS = 'cap/GET_USER_DATA_SUCCESS';
16
- export const GET_USER_DATA_FAILURE = 'cap/GET_USER_DATA_FAILURE';
14
+ export const GET_USER_DATA_REQUEST = 'cap/GET_USER_DATA_REQUEST_V2';
15
+ export const GET_USER_DATA_SUCCESS = 'cap/GET_USER_DATA_SUCCESS_V2';
16
+ export const GET_USER_DATA_FAILURE = 'cap/GET_USER_DATA_FAILURE_V2';
17
17
 
18
18
  export const GET_SCHEMA_FOR_ENTITY_FAILURE = 'cap/GET_SCHEMA_FOR_ENTITY_FAILURE';
19
19
  export const GET_SCHEMA_FOR_ENTITY_REQUEST = 'cap/GET_SCHEMA_FOR_ENTITY_REQUEST';
@@ -28,6 +28,8 @@ export const GET_TOPBAR_MENU_DATA_SUCCESS = 'creatives/cap/GET_TOPBAR_MENU_DATA_
28
28
  export const GET_TOPBAR_MENU_DATA_FAILURE = 'creatives/cap/GET_TOPBAR_MENU_DATA_FAILURE';
29
29
  export const CLEAR_TOPBAR_MENU_DATA = 'creatives/cap/CLEAR_TOPBAR_MENU_DATA';
30
30
 
31
+ export const SET_LOYALTY_PROMOTION_RELATED_CREATIVE_TAGS_DISPLAY = 'SET_LOYALTY_PROMOTION_RELATED_CREATIVE_TAGS_DISPLAY';
32
+
31
33
  export const CAMPAIGN_SETTINGS_URL = '/creatives/settings/message';
32
34
  export const ORG_SETTINGS_URL = '/org/index';
33
35
  export const HELP_URL = 'https://support.capillarytech.com/en/support/solutions/4000007853';
@@ -82,7 +82,6 @@ function capReducer(state = fromJS(initialState.cap), action) {
82
82
  .set('fetchingSchema', false);
83
83
  case types.GET_SCHEMA_FOR_ENTITY_SUCCESS: {
84
84
  const stateMeta = state.get('metaEntities');
85
-
86
85
  return state
87
86
  .set('fetchingSchema', false)
88
87
  .set('metaEntities', {
@@ -117,6 +116,11 @@ function capReducer(state = fromJS(initialState.cap), action) {
117
116
  );
118
117
  case types.CLEAR_TOPBAR_MENU_DATA:
119
118
  return state.set('topbarMenuData', fromJS({}));
119
+ case types.SET_LOYALTY_PROMOTION_RELATED_CREATIVE_TAGS_DISPLAY: {
120
+ return state.set('disableLoyaltyPromotionRelatedTags', action.disable)
121
+ .set('tagsToDisable', action.tagsToDisable)
122
+ .set('parentTagsToDisable', action.parentTagsToDisable);
123
+ }
120
124
  default:
121
125
  return state;
122
126
  }
@@ -31,7 +31,6 @@ const setInjectedTags = () => createSelector(
31
31
  const { tags } = metaEntities;
32
32
  const customTags = tags && (tags.custom || {});
33
33
  const extendedTags = tags && (tags.extended || {});
34
-
35
34
  return (injectedTags = _.merge({}, injectedTags, customTags, extendedTags));
36
35
  }
37
36
  );
@@ -74,6 +73,15 @@ const makeSelectFetchingSchema = () => createSelector(
74
73
  (globalState) => globalState.get('fetchingSchema')
75
74
  );
76
75
 
76
+ const makeSelectLoyaltyPromotionDisplay = () => createSelector(
77
+ selectCapDomain,
78
+ (globalState) => ({
79
+ disableRelatedTags: globalState.get('disableLoyaltyPromotionRelatedTags'),
80
+ childTagsToDisable: globalState.get('tagsToDisable') || [],
81
+ parentTagstoDisable: globalState.get('parentTagsToDisable') || [],
82
+ }),
83
+ );
84
+
77
85
  export {
78
86
  makeSelectLocationState,
79
87
  makeSelectAuthenticated,
@@ -85,4 +93,5 @@ export {
85
93
  isLoadingMetaEntities,
86
94
  makeSelectFetchingSchema,
87
95
  setInjectedTags,
96
+ makeSelectLoyaltyPromotionDisplay,
88
97
  };
@@ -214,14 +214,15 @@ function SlideBoxContent(props) {
214
214
  stickerId,
215
215
  packageId,
216
216
  baseUrl,
217
- video: {
217
+ video,
218
+ template,
219
+ }) => {
220
+ const {
218
221
  originalContentUrl,
219
222
  externalLink: {
220
223
  linkUri,
221
224
  } = {},
222
- } = {},
223
- template,
224
- }) => {
225
+ } = video || {};
225
226
  const previewContent = {};
226
227
  previewContent.messageContent = text;
227
228
  previewContent.previewImageUrl = previewImageUrl;
@@ -2179,7 +2179,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2179
2179
  } else {
2180
2180
  this.setState({injectedTags: data.tags});
2181
2181
  }
2182
- data.tags && this.props.globalActions.setInjectedTags(data.tags);
2182
+ this.props.globalActions.setInjectedTags(data.tags);
2183
2183
  }
2184
2184
 
2185
2185
  startLoading = (ifEdit) => {
@@ -25,7 +25,7 @@ import { FONT_SIZE_L } from '@capillarytech/cap-ui-library/styled/variables';
25
25
  import { find, cloneDeep, findIndex, isEmpty, isEqual, filter, flattenDeep, replace } from 'lodash';
26
26
  import * as actions from './actions';
27
27
  import { makeSelectFTP, makeSelectMetaEntities } from './selectors';
28
- import { setInjectedTags } from '../Cap/selectors';
28
+ import { makeSelectLoyaltyPromotionDisplay, setInjectedTags } from '../Cap/selectors';
29
29
  import withCreatives from '../../hoc/withCreatives';
30
30
  import messages from './messages';
31
31
  import './_FTP.scss';
@@ -132,7 +132,11 @@ export class FTP extends React.Component {
132
132
  ) || !isEqual(injectedTags, thisInjectedTags)
133
133
  ) {
134
134
  const tags = _.concat(
135
- getTreeStructuredTags({ tagsList: ((metaEntities.tags || {}).standard || []), offerDetails: selectedOfferDetails }),
135
+ getTreeStructuredTags({
136
+ tagsList: ((metaEntities.tags || {}).standard || []),
137
+ offerDetails: selectedOfferDetails,
138
+ disableTagsDetails: this.props.disableTagsDetails,
139
+ }),
136
140
  this.getTreeStructuredInjectedTags(injectedTags)
137
141
  );
138
142
  this.setState({ tagsTree: tags}, () => this.disableUsedColumns());
@@ -491,9 +495,13 @@ export class FTP extends React.Component {
491
495
 
492
496
  disableUsedColumns = () => {
493
497
  const { headerTagList = [] } = this.state;
494
- const { selectedOfferDetails = [], metaEntities = {}, injectedTags } = this.props;
498
+ const { selectedOfferDetails = [], metaEntities = {}, injectedTags, disableTagsDetails } = this.props;
495
499
  const tags = _.concat(
496
- getTreeStructuredTags({ tagsList: ((metaEntities.tags || {}).standard || []), offerDetails: selectedOfferDetails }),
500
+ getTreeStructuredTags({
501
+ tagsList: ((metaEntities.tags || {}).standard || []),
502
+ offerDetails: selectedOfferDetails,
503
+ disableTagsDetails,
504
+ }),
497
505
  this.getTreeStructuredInjectedTags(injectedTags)
498
506
  );
499
507
  const clonnedTagsTree = cloneDeep(tags);
@@ -636,6 +644,7 @@ FTP.propTypes = {
636
644
  contents: PropTypes.array,
637
645
  metaEntities: PropTypes.object,
638
646
  selectedOfferDetails: PropTypes.array,
647
+ disableTagsDetails: PropTypes.func,
639
648
  };
640
649
 
641
650
 
@@ -650,6 +659,7 @@ const mapStateToProps = createStructuredSelector({
650
659
  FTP: makeSelectFTP(),
651
660
  metaEntities: makeSelectMetaEntities(),
652
661
  injectedTags: setInjectedTags(),
662
+ disableTagsDetails: makeSelectLoyaltyPromotionDisplay(),
653
663
  });
654
664
 
655
665
  export default withCreatives({
@@ -207,26 +207,11 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
207
207
  if (this.props.location.query.type === 'embedded') {
208
208
  this.props.actions.resetAccount();
209
209
  }
210
- if ((['line', VIBER_CHANNEL, FACEBOOK_CHANNEL, 'sms', 'email', 'ebill'].includes((this.state.channel || '').toLowerCase())) || ((['wechat', 'mobilepush'].includes(this.state.channel.toLowerCase()) && !isEmpty(this.props.Templates.selectedWeChatAccount)))) {
210
+ if (['line', VIBER_CHANNEL, FACEBOOK_CHANNEL, 'sms', 'email', 'ebill'].includes((this.state.channel || '').toLowerCase())) {
211
211
  const queryParams = {
212
212
  // name: this.state.searchText,
213
213
  // sortBy: this.state.sortBy,
214
214
  };
215
- if (this.state.channel.toLowerCase() === 'wechat' && get(this.props, 'Templates.selectedWeChatAccount.configs', false)) {
216
- queryParams.wecrmId = this.props.Templates.selectedWeChatAccount.configs.wecrm_app_id;
217
- queryParams.wecrmToken = this.props.Templates.selectedWeChatAccount.configs.wecrm_token;
218
- queryParams.originalId = this.props.Templates.selectedWeChatAccount.sourceAccountIdentifier;
219
- }
220
- if (this.state.channel.toLowerCase() === "mobilepush" && !isEmpty(this.props.Templates.selectedWeChatAccount)) {
221
- const account = this.props.Templates.selectedWeChatAccount;
222
- queryParams.accountId = account.id;
223
- const isAndroidSupported = get(account, "configs.android") === '1';
224
- const isIosSupported = get(account, "configs.ios") === '1';
225
- if (!(isAndroidSupported || isIosSupported)) {
226
- this.props.actions.resetAccount();
227
- return;
228
- }
229
- }
230
215
  queryParams.page = this.state.page;
231
216
  queryParams.perPage = this.state.perPageLimit;
232
217
  const channel = this.state.channel;
@@ -810,7 +795,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
810
795
  { [WECHAT, MOBILE_PUSH].includes(currentChannel) && this.showAccountName() }
811
796
  {filterContent}
812
797
  <CapSpin spinning={isLoading} tip={loadingTip} style={{width: '100%'}}>
813
- {!isLoading && <div>
798
+ {<div>
814
799
  {!isEmpty(filteredTemplates) || !isEmpty(this.state.searchText) || !isEmpty(this.props.Templates.templateError) ? (
815
800
  <div className={!isEmpty(this.state.searchText) && isEmpty(cardDataList) ? '' : "pagination-container"}>
816
801
  <CapCustomCardList
@@ -821,7 +806,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
821
806
  fbType={"list"}
822
807
  />
823
808
  </div>)
824
- : ['sms', "email"].includes(this.state.channel.toLowerCase()) && <CapIllustration buttonClassName={`create-new-${channelLowerCase}`} {...this.getChannelTypeIllustrationInfo(currentChannel)} />
809
+ : ['sms', "email"].includes(this.state.channel.toLowerCase()) && !isLoading && <CapIllustration buttonClassName={`create-new-${channelLowerCase}`} {...this.getChannelTypeIllustrationInfo(currentChannel)} />
825
810
  }
826
811
 
827
812
  {(this.state.selectedAccount === '' && isEmpty(this.props.Templates.selectedWeChatAccount)) && (this.state.channel.toLowerCase() === 'wechat' || this.state.channel.toLowerCase() === "mobilepush") &&