@capillarytech/creatives-library 7.17.22 → 7.17.24

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 (28) hide show
  1. package/containers/App/constants.js +4 -0
  2. package/package.json +1 -1
  3. package/utils/common.js +63 -0
  4. package/utils/commonUtils.js +6 -0
  5. package/utils/tests/common.test.js +81 -1
  6. package/v2Components/CapTagList/index.js +16 -5
  7. package/v2Containers/App/constants.js +1 -1
  8. package/v2Containers/Cap/constants.js +3 -3
  9. package/v2Containers/ChannelTemplates/actions.js +20 -0
  10. package/v2Containers/ChannelTemplates/constants.js +8 -0
  11. package/v2Containers/ChannelTemplates/index.js +47 -0
  12. package/v2Containers/ChannelTemplates/messages.js +13 -0
  13. package/v2Containers/ChannelTemplates/reducer.js +34 -0
  14. package/v2Containers/ChannelTemplates/sagas.js +32 -0
  15. package/v2Containers/ChannelTemplates/selectors.js +25 -0
  16. package/v2Containers/LanguageProvider/reducer.js +3 -1
  17. package/v2Containers/LanguageProvider/tests/reducer.test.js +9 -0
  18. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +3 -3
  19. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +120 -120
  20. package/v2Containers/Sms/Create/tests/sagas.test.js +82 -0
  21. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +16 -16
  22. package/v2Containers/TagList/index.js +40 -22
  23. package/v2Containers/TagList/messages.js +2 -1
  24. package/v2Containers/TagList/tests/TagList.test.js +41 -0
  25. package/v2Containers/TagList/tests/mockdata.js +108 -0
  26. package/v2Containers/TemplatesV2/index.js +3 -3
  27. package/v2Containers/TemplatesV2/tests/mockData.js +2 -2
  28. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +16 -16
@@ -6,6 +6,10 @@ export const STORE2DOOR_PLUS_ENABLED = 'STORE2DOOR_PLUS_ENABLED';
6
6
  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
+ export const REGISTRATION_CUSTOM_FIELD = 'Registration custom fields';
10
+ export const CUSTOM_TAG = 'CustomTagMessage';
11
+ export const CUSTOMER_EXTENDED_FIELD = 'Customer extended fields';
12
+ export const EXTENDED_TAG = 'ExtendedTagMessage';
9
13
 
10
14
  export const CARD_RELATED_TAGS = [
11
15
  'card_series',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "7.17.22",
4
+ "version": "7.17.24",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/utils/common.js CHANGED
@@ -7,7 +7,12 @@ import {
7
7
  CARD_BASED_SCOPE,
8
8
  HOSPITALITY_RELATED_TAGS,
9
9
  HOSPITALITY_BASED_SCOPE,
10
+ EXTENDED_TAG,
11
+ CUSTOMER_EXTENDED_FIELD,
12
+ CUSTOM_TAG,
13
+ REGISTRATION_CUSTOM_FIELD
10
14
  } from '../containers/App/constants';
15
+ import { apiMessageFormatHandler } from './commonUtils';
11
16
 
12
17
  export function getUserNameById(userId, allUserList) {
13
18
  let userName = "";
@@ -276,3 +281,61 @@ export const isTraiDLTEnable = (isFullMode, smsRegister) => {
276
281
  const isTraiDltFeature = isTraiDltFeatureForOrg && isTraiEnableforLib;
277
282
  return isTraiDltFeature;
278
283
  };
284
+
285
+ export const intlKeyGenerator = (value = "") => {
286
+ return value.replace(/[^a-zA-Z0-9_]/g, "");
287
+ };
288
+
289
+ export const handleInjectedData = (data, scope) => {
290
+ const temp = _.cloneDeep(data);
291
+ let tagType;
292
+ for (const tagKey in temp) {
293
+ if (temp.hasOwnProperty(tagKey)) {
294
+ const tag = temp[tagKey];
295
+
296
+ if (tag?.name === REGISTRATION_CUSTOM_FIELD) {
297
+ tagType = CUSTOM_TAG;
298
+ } else if (tag?.name === CUSTOMER_EXTENDED_FIELD) {
299
+ tagType = EXTENDED_TAG;
300
+ }
301
+
302
+ if (tag?.name) {
303
+ const name = tag?.name;
304
+ const key = intlKeyGenerator(name);
305
+ const id = tagType
306
+ ? `${scope}.${key}_name.${tagType}`
307
+ : `${scope}.${key}`;
308
+
309
+ tag["name"] = apiMessageFormatHandler(id, name);
310
+ }
311
+
312
+ if (tag?.subtags) {
313
+ for (const subtagKey in tag.subtags) {
314
+ if (tag["subtags"].hasOwnProperty(subtagKey)) {
315
+ const subtag = tag["subtags"][subtagKey];
316
+ if (subtag?.name) {
317
+ const name = subtag?.name;
318
+ const key = intlKeyGenerator(name);
319
+ const id = tagType
320
+ ? `${scope}.${key}_name.${tagType}`
321
+ : `${scope}.${key}`;
322
+
323
+ subtag["name"] = apiMessageFormatHandler(id, name);
324
+ }
325
+ if (subtag?.desc) {
326
+ const desc = subtag?.desc;
327
+ const key = intlKeyGenerator(desc);
328
+ const id = tagType
329
+ ? `${scope}.${key}_desc.${tagType}`
330
+ : `${scope}.${key}`;
331
+
332
+ subtag["desc"] = apiMessageFormatHandler(id, desc);
333
+ }
334
+ }
335
+ }
336
+ }
337
+ tagType = "";
338
+ }
339
+ }
340
+ return temp;
341
+ };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { FormattedMessage } from 'react-intl';
3
+
4
+ export const apiMessageFormatHandler = (id, fallback) => (
5
+ <FormattedMessage id={id} defaultMessage={fallback} />
6
+ );
@@ -1,5 +1,7 @@
1
+ import React from 'react';
2
+ import { FormattedMessage } from 'react-intl';
1
3
  import "@testing-library/jest-dom";
2
- import { filterTags, getTreeStructuredTags } from "../common";
4
+ import { filterTags, getTreeStructuredTags, handleInjectedData } from "../common";
3
5
  import * as mockdata from "./common.mockdata";
4
6
 
5
7
  describe("getTreeStructuredTags test", () => {
@@ -16,3 +18,81 @@ describe("getTreeStructuredTags test", () => {
16
18
  expect(filterTags([], [])).toEqual([]);
17
19
  });
18
20
  });
21
+
22
+ describe("handleInjectedData", () => {
23
+ it("replaces name with intl key for top level tag", () => {
24
+ const data = {
25
+ tag1: {
26
+ name: "Registration Fields",
27
+ },
28
+ };
29
+
30
+ const result = handleInjectedData(data, "scope");
31
+
32
+ expect(result.tag1.name).toEqual(<FormattedMessage defaultMessage="Registration Fields" id="scope.RegistrationFields" values={{}} />);
33
+ });
34
+
35
+ it("adds tagType for Registration custom fields", () => {
36
+ const data = {
37
+ tag1: {
38
+ name: "Registration custom fields",
39
+ },
40
+ };
41
+
42
+ const result = handleInjectedData(data, "scope");
43
+
44
+ expect(result.tag1.name).toEqual(
45
+ <FormattedMessage defaultMessage="Registration custom fields" id="scope.Registrationcustomfields_name.CustomTagMessage" values={{}} />
46
+ );
47
+ });
48
+
49
+ it("adds tagType for Customer extended fields fields", () => {
50
+ const data = {
51
+ tag1: {
52
+ name: "Customer extended fields",
53
+ },
54
+ };
55
+
56
+ const result = handleInjectedData(data, "scope");
57
+
58
+ expect(result.tag1.name).toEqual(
59
+ <FormattedMessage defaultMessage="Customer extended fields" id="scope.Customerextendedfields_name.ExtendedTagMessage" values={{}} />
60
+ );
61
+ });
62
+
63
+
64
+ it("replaces subtag name with intl key", () => {
65
+ const data = {
66
+ tag1: {
67
+ subtags: {
68
+ subtag1: {
69
+ name: "First Name",
70
+ },
71
+ },
72
+ },
73
+ };
74
+
75
+ const result = handleInjectedData(data, "scope");
76
+
77
+ expect(result.tag1.subtags.subtag1.name).toEqual(<FormattedMessage defaultMessage="First Name" id="scope.FirstName" values={{}} />);
78
+ });
79
+
80
+ it("replaces subtag desc with intl key", () => {
81
+ const data = {
82
+ tag1: {
83
+ subtags: {
84
+ subtag1: {
85
+ desc: "Enter your first name",
86
+ },
87
+ },
88
+ },
89
+ };
90
+
91
+ const result = handleInjectedData(data, "scope");
92
+
93
+ expect(result.tag1.subtags.subtag1.desc).toEqual(
94
+ <FormattedMessage defaultMessage="Enter your first name" id="scope.Enteryourfirstname" values={{}} />
95
+ );
96
+ });
97
+ });
98
+
@@ -25,7 +25,7 @@ import {
25
25
  JAPANESE_HELP_TEXT,
26
26
  TAG_TRANSLATION_DOC,
27
27
  } from "../../containers/TagList/constants";
28
- import { HIDE_FOR_JP_LOCALE } from '../../v2Containers/App/constants';
28
+ import { HIDE_ENGAGEMENT_CHANNELS } from '../../v2Containers/App/constants';
29
29
  import { hidingDateTagsForJpLocale } from '../../v2Containers/TagList/utils';
30
30
 
31
31
 
@@ -44,6 +44,7 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
44
44
  dynamicDateValue: '',
45
45
  showModal: false,
46
46
  translationLang: '',
47
+ tagsList: []
47
48
  };
48
49
  this.renderTags = this.renderTags.bind(this);
49
50
  this.getSearchedExpandedKeys = this.getSearchedExpandedKeys.bind(this);
@@ -64,6 +65,15 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
64
65
  });
65
66
  }
66
67
 
68
+ componentDidUpdate(prevProps, prevState){
69
+ if (this.props.tags !== prevProps.tags || this.state.searchValue !== prevState.searchValue) {
70
+ let temp = this.renderTags(this.props.tags, this.state.searchValue);
71
+ this.setState({
72
+ tagsList: temp
73
+ });
74
+ }
75
+ }
76
+
67
77
  onChange = (e) => {
68
78
  const value = e.target.value;
69
79
  let expandedKeys = this.getSearchedExpandedKeys(this.props.tags, value);
@@ -84,12 +94,12 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
84
94
  let list = [];
85
95
  _.forEach(tags, (val = {}, key) => {
86
96
  if (_.has(val, 'subtags')) {
87
- if ((val.name || '').toLowerCase().indexOf(value.toLowerCase()) !== -1) {
97
+ if (val.name && typeof val.name === 'string' && (val.name || '').toLowerCase().indexOf(value.toLowerCase()) !== -1) {
88
98
  list.push(key);
89
99
  }
90
100
  const temp = this.getSearchedExpandedKeys(val.subtags, value);
91
101
  list = list.concat(temp);
92
- } else if ((val.name || '').toLowerCase().indexOf(value.toLowerCase()) !== -1) {
102
+ } else if (val.name && typeof val.name === 'string' && (val.name || '').toLowerCase().indexOf(value.toLowerCase()) !== -1) {
93
103
  list.push(key);
94
104
  }
95
105
  });
@@ -165,7 +175,7 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
165
175
  renderTags(tags, searchString = '') {
166
176
  const { disableRelatedTags, childTagsToDisable, parentTagstoDisable, showCardsRelatedTags } = this?.props?.disableTagsDetails;
167
177
  const { accessibleFeatures = [] } = this?.props?.currentOrgDetails || {};
168
- const hideDateTagsForJpLocale = accessibleFeatures.includes(HIDE_FOR_JP_LOCALE);
178
+ const hideDateTagsForJpLocale = accessibleFeatures.includes(HIDE_ENGAGEMENT_CHANNELS);
169
179
  const list = [];
170
180
  const loyaltyAttrDisableText = <FormattedMessage {...messages.loyaltyAttributeDisable} />;
171
181
  let clonedTags = _.cloneDeep(tags);
@@ -259,7 +269,8 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
259
269
  autoExpandParent={autoExpandParent}
260
270
  onExpand={this.onExpand}
261
271
  >
262
- {this.renderTags(tg, searchValue)}
272
+ {/* {this.renderTags(tg, searchValue)} */}
273
+ {this.state.tagsList}
263
274
  </CapTree>
264
275
  {translationLang === "ja-JP" &&
265
276
  <div className="tag-list-footer">
@@ -54,7 +54,7 @@ export const LINE = 'line';
54
54
  export const EMAIL = 'email';
55
55
  export const ASSETS = 'assets';
56
56
 
57
- export const HIDE_FOR_JP_LOCALE = 'HIDE_FOR_JP_LOCALE';
57
+ export const HIDE_ENGAGEMENT_CHANNELS = 'HIDE_ENGAGEMENT_CHANNELS';
58
58
 
59
59
  export const TRACK_EDIT_SMS = 'editSms';
60
60
  export const TRACK_EDIT_EMAIL = 'editEmail';
@@ -15,9 +15,9 @@ export const GET_USER_DATA_REQUEST = 'cap/GET_USER_DATA_REQUEST_V2';
15
15
  export const GET_USER_DATA_SUCCESS = 'cap/GET_USER_DATA_SUCCESS_V2';
16
16
  export const GET_USER_DATA_FAILURE = 'cap/GET_USER_DATA_FAILURE_V2';
17
17
 
18
- export const GET_SCHEMA_FOR_ENTITY_FAILURE = 'cap/GET_SCHEMA_FOR_ENTITY_FAILURE';
19
- export const GET_SCHEMA_FOR_ENTITY_REQUEST = 'cap/GET_SCHEMA_FOR_ENTITY_REQUEST';
20
- export const GET_SCHEMA_FOR_ENTITY_SUCCESS = 'cap/GET_SCHEMA_FOR_ENTITY_SUCCESS';
18
+ export const GET_SCHEMA_FOR_ENTITY_FAILURE = 'cap/GET_SCHEMA_FOR_ENTITY_FAILURE_V2';
19
+ export const GET_SCHEMA_FOR_ENTITY_REQUEST = 'cap/GET_SCHEMA_FOR_ENTITY_REQUEST_V2';
20
+ export const GET_SCHEMA_FOR_ENTITY_SUCCESS = 'cap/GET_SCHEMA_FOR_ENTITY_SUCCESS_V2';
21
21
  export const CLEAR_META_ENTITIES = 'cap/CLEAR_META_ENTITIES';
22
22
  export const HIDE_TAGS = 'cap/HIDE_TAGS';
23
23
 
@@ -0,0 +1,20 @@
1
+ /*
2
+ *
3
+ * ChannelTemplates actions
4
+ *
5
+ */
6
+
7
+ import * as types from './constants';
8
+
9
+ export function defaultAction() {
10
+ return {
11
+ type: types.DEFAULT_ACTION,
12
+ };
13
+ }
14
+
15
+ export function getTemplates(channel) {
16
+ return {
17
+ type: types.GET_TEMPLATES_REQUEST,
18
+ channel,
19
+ };
20
+ }
@@ -0,0 +1,8 @@
1
+ /*
2
+ *
3
+ * ChannelTemplates constants
4
+ *
5
+ */
6
+
7
+ export const DEFAULT_ACTION = 'app/ChannelTemplates/DEFAULT_ACTION';
8
+
@@ -0,0 +1,47 @@
1
+ /*
2
+ *
3
+ * ChannelTemplates
4
+ *
5
+ */
6
+
7
+ import PropTypes from 'prop-types';
8
+
9
+ import React from 'react';
10
+ import { connect } from 'react-redux';
11
+ import { FormattedMessage } from 'react-intl';
12
+ import { bindActionCreators } from 'redux';
13
+ import { createStructuredSelector } from 'reselect';
14
+ import makeSelectChannelTemplates from './selectors';
15
+ import * as actions from './actions';
16
+ import messages from './messages';
17
+
18
+
19
+ export class ChannelTemplates extends React.Component { // eslint-disable-line react/prefer-stateless-function
20
+ componentDidMount() {
21
+ this.props.actions.getTemplates(this.props.channel);
22
+ }
23
+ render() {
24
+ return (
25
+ <CardGrid
26
+ cardDataList={[]}
27
+ />
28
+ );
29
+ }
30
+ }
31
+
32
+ ChannelTemplates.propTypes = {
33
+ actions: PropTypes.object.isRequired,
34
+ channel: PropTypes.string,
35
+ };
36
+
37
+ const mapStateToProps = createStructuredSelector({
38
+ ChannelTemplates: makeSelectChannelTemplates(),
39
+ });
40
+
41
+ function mapDispatchToProps(dispatch) {
42
+ return {
43
+ actions: bindActionCreators(actions, dispatch),
44
+ };
45
+ }
46
+
47
+ export default connect(mapStateToProps, mapDispatchToProps)(ChannelTemplates);
@@ -0,0 +1,13 @@
1
+ /*
2
+ * ChannelTemplates Messages
3
+ *
4
+ * This contains all the text for the ChannelTemplates component.
5
+ */
6
+ import { defineMessages } from 'react-intl';
7
+
8
+ export default defineMessages({
9
+ header: {
10
+ id: 'creatives.containersV2.ChannelTemplates.header',
11
+ defaultMessage: 'This is ChannelTemplates container !',
12
+ },
13
+ });
@@ -0,0 +1,34 @@
1
+ /*
2
+ *
3
+ * ChannelTemplates reducer
4
+ *
5
+ */
6
+
7
+ import { fromJS } from 'immutable';
8
+ import * as types from './constants';
9
+
10
+ const initialState = fromJS({
11
+ loadingTemplates: true,
12
+ smsTemplates: [],
13
+ emailTemplates: [],
14
+ wechatTemplates: [],
15
+ mobilepushTemplates: [],
16
+ });
17
+
18
+ function channelTemplatesReducer(state = initialState, action) {
19
+ const channelTemplates = `${action.channel}Templates`;
20
+ switch (action.type) {
21
+ case types.DEFAULT_ACTION:
22
+ return state;
23
+ case types.GET_TEMPLATES_REQUEST:
24
+ return state.set('loadingTemplates', true);
25
+ case types.GET_TEMPLATES_SUCESS:
26
+ return state.set('loadingTemplates', false).set(channelTemplates, action.templates);
27
+ case types.GET_TEMPLATES_FAILURE:
28
+ return state.set('loadingTemplates', false).set('error', action.error);
29
+ default:
30
+ return state;
31
+ }
32
+ }
33
+
34
+ export default channelTemplatesReducer;
@@ -0,0 +1,32 @@
1
+ import { take, takeLatest, call, put, cancel } from 'redux-saga/effects';
2
+ import { LOCATION_CHANGE } from 'react-router-redux';
3
+ import * as Api from '../../services/api';
4
+
5
+
6
+ import * as types from './constants';
7
+ // Individual exports for testing
8
+ export function* defaultSaga() {
9
+ // See example in v2Containers/HomePage/sagas.js
10
+ }
11
+ function* getTemplates(action) {
12
+ try {
13
+ const req = {
14
+ channel: action.channel,
15
+ queryParams: action.query,
16
+ };
17
+ const res = call(Api.getAllTemplates, req);
18
+ put({type: types.GET_TEMPLATES_SUCESS, templates: res.response, channel: action.channel});
19
+ } catch (error) {
20
+ put({type: types.GET_TEMPLATES_FAILURE, error});
21
+ }
22
+ }
23
+ function* getTemplatesWatcher() {
24
+ const watcher = yield takeLatest(types.GET_TEMPLATES_REQUEST, getTemplates);
25
+ yield take(LOCATION_CHANGE);
26
+ yield cancel(watcher);
27
+ }
28
+ // All sagas to be loaded
29
+ export default [
30
+ defaultSaga,
31
+ getTemplatesWatcher,
32
+ ];
@@ -0,0 +1,25 @@
1
+ import { createSelector } from 'reselect';
2
+
3
+ /**
4
+ * Direct selector to the channelTemplates state domain
5
+ */
6
+ const selectChannelTemplatesDomain = () => (state) => state.get('templates');
7
+
8
+ /**
9
+ * Other specific selectors
10
+ */
11
+
12
+
13
+ /**
14
+ * Default selector used by ChannelTemplates
15
+ */
16
+
17
+ const makeSelectChannelTemplates = () => createSelector(
18
+ selectChannelTemplatesDomain(),
19
+ (substate) => substate.toJS()
20
+ );
21
+
22
+ export default makeSelectChannelTemplates;
23
+ export {
24
+ selectChannelTemplatesDomain,
25
+ };
@@ -17,7 +17,9 @@ const initialState = fromJS({
17
17
  function languageProviderReducer(state = initialState, action) {
18
18
  switch (action.type) {
19
19
  case types.GET_LOCIZ_MESSAGE_REQUEST:
20
- return state.set('localeLoading', true);
20
+ return state
21
+ .set('localeLoading', true)
22
+ .set('locale', action.locale);
21
23
  case types.GET_LOCIZ_MESSAGE_SUCCESS:
22
24
  return state
23
25
  .set('localeLoading', false)
@@ -3,6 +3,7 @@ import { fromJS } from 'immutable';
3
3
  import languageProviderReducer from '../reducer';
4
4
  import {
5
5
  CHANGE_LOCALE,
6
+ GET_LOCIZ_MESSAGE_REQUEST,
6
7
  } from '../constants';
7
8
 
8
9
  describe('languageProviderReducer', () => {
@@ -21,4 +22,12 @@ describe('languageProviderReducer', () => {
21
22
  messages: {},
22
23
  });
23
24
  });
25
+
26
+ it('make locize message request', () => {
27
+ expect(languageProviderReducer(undefined, { type: GET_LOCIZ_MESSAGE_REQUEST, locale: 'de' }).toJS()).toEqual({
28
+ locale: "de",
29
+ localeLoading: true,
30
+ messages: {},
31
+ });
32
+ });
24
33
  });
@@ -23058,7 +23058,7 @@ new message content.",
23058
23058
  </div>
23059
23059
  </ComponentWithLabelHOC__CapComponentStyled>
23060
23060
  </_class>
23061
- <Connect(UserIsAuthenticated(Connect(TagList)))
23061
+ <Connect(UserIsAuthenticated(Connect(InjectIntl(TagList))))
23062
23062
  id="undefined_tags"
23063
23063
  injectedTags={Object {}}
23064
23064
  key="undefined_tags"
@@ -23079,7 +23079,7 @@ new message content.",
23079
23079
  tags={Array []}
23080
23080
  userLocale="en-US"
23081
23081
  >
23082
- <UserIsAuthenticated(Connect(TagList))
23082
+ <UserIsAuthenticated(Connect(InjectIntl(TagList)))
23083
23083
  authData={
23084
23084
  Object {
23085
23085
  "app": Object {},
@@ -23125,7 +23125,7 @@ new message content.",
23125
23125
  tags={Array []}
23126
23126
  userLocale="en-US"
23127
23127
  />
23128
- </Connect(UserIsAuthenticated(Connect(TagList)))>
23128
+ </Connect(UserIsAuthenticated(Connect(InjectIntl(TagList))))>
23129
23129
  <CapDrawer
23130
23130
  content={
23131
23131
  <React.Fragment>