@capillarytech/creatives-library 7.9.14 → 7.9.16

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 (35) hide show
  1. package/assets/group.png +0 -0
  2. package/containers/App/constants.js +2 -1
  3. package/index.js +6 -0
  4. package/package.json +3 -2
  5. package/routes.js +5 -0
  6. package/services/api.js +9 -15
  7. package/utils/common.js +6 -1
  8. package/v2Containers/Cap/index.js +9 -2
  9. package/v2Containers/CreativesContainer/SlideBoxContent.js +16 -5
  10. package/v2Containers/CreativesContainer/SlideBoxHeader.js +6 -1
  11. package/v2Containers/CreativesContainer/messages.js +4 -0
  12. package/v2Containers/Sms/Create/index.js +5 -6
  13. package/v2Containers/Sms/Edit/sagas.js +1 -1
  14. package/v2Containers/SmsTrai/Create/actions.js +25 -0
  15. package/v2Containers/SmsTrai/Create/constants.js +74 -0
  16. package/v2Containers/SmsTrai/Create/index.js +710 -0
  17. package/v2Containers/SmsTrai/Create/index.scss +92 -0
  18. package/v2Containers/SmsTrai/Create/messages.js +116 -0
  19. package/v2Containers/SmsTrai/Create/reducer.js +43 -0
  20. package/v2Containers/SmsTrai/Create/sagas.js +36 -0
  21. package/v2Containers/SmsTrai/Create/selectors.js +26 -0
  22. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +10351 -0
  23. package/v2Containers/SmsTrai/Create/tests/index.test.js +77 -0
  24. package/v2Containers/SmsTrai/Create/tests/mockData.js +58 -0
  25. package/v2Containers/SmsTrai/Edit/constants.js +16 -0
  26. package/v2Containers/SmsTrai/Edit/index.js +483 -0
  27. package/v2Containers/SmsTrai/Edit/messages.js +58 -0
  28. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +16103 -0
  29. package/v2Containers/SmsTrai/Edit/tests/index.test.js +61 -0
  30. package/v2Containers/SmsTrai/Edit/tests/mockData.js +36 -0
  31. package/v2Containers/SmsWrapper/index.js +75 -0
  32. package/v2Containers/SmsWrapper/tests/index.test.js +10 -0
  33. package/v2Containers/Templates/_templates.scss +2 -0
  34. package/v2Containers/Templates/index.js +88 -11
  35. package/v2Containers/Templates/messages.js +16 -0
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import { browserHistory } from 'react-router';
3
+ import configureStore from '../../../../store';
4
+ import { Provider } from 'react-redux';
5
+ import { mountWithIntl } from '../../../../../app/helpers/intl-enzym-test-helpers';
6
+ import { SmsTraiEdit } from '../index';
7
+ import { mockData } from './mockData';
8
+
9
+ let store;
10
+ beforeAll(() => {
11
+ store = configureStore({}, browserHistory);
12
+ });
13
+
14
+ describe('Creatives SmsTraiEdit test/>', () => {
15
+ let renderedComponent;
16
+ const getTemplateDetails = jest.fn();
17
+ const resetEditTemplate = jest.fn();
18
+ const clearEditResponse = jest.fn();
19
+ const editTemplate = jest.fn();
20
+ const fetchSchemaForEntity = jest.fn();
21
+ const formatMessage = jest.fn();
22
+ const handleClose = jest.fn();
23
+ const params = {
24
+ id: mockData.templateDetails._id,
25
+ };
26
+ const location = mockData.location;
27
+ const templateDetails = mockData.templateDetails;
28
+ beforeEach(() => {
29
+ renderedComponent = mountWithIntl(
30
+ <Provider store={store}>
31
+ <SmsTraiEdit
32
+ actions={{
33
+ getTemplateDetails,
34
+ resetEditTemplate,
35
+ clearEditResponse,
36
+ editTemplate,
37
+ }}
38
+ globalActions={{ fetchSchemaForEntity }}
39
+ handleClose={handleClose}
40
+ params={params}
41
+ templateDetails={templateDetails}
42
+ location={location}
43
+ intl={{ formatMessage }}
44
+ />
45
+ </Provider>,
46
+ );
47
+ });
48
+ it('should render', () => {
49
+ expect(renderedComponent).toMatchSnapshot();
50
+ });
51
+ it('should save', () => {
52
+ renderedComponent.find('button.create-msg').props().onClick();
53
+ renderedComponent.update();
54
+ expect(renderedComponent).toMatchSnapshot();
55
+ });
56
+ it('should cancel', () => {
57
+ renderedComponent.find('button.cancel-msg').props().onClick();
58
+ renderedComponent.update();
59
+ expect(renderedComponent).toMatchSnapshot();
60
+ });
61
+ });
@@ -0,0 +1,36 @@
1
+ export const mockData = {
2
+ templateDetails: {
3
+ _id: '6125eec5feae248f88e6a634',
4
+ name: 'CAP71871_4',
5
+ type: 'SMS',
6
+ versions: {
7
+ history: [],
8
+ base: {
9
+ template_id: "'1107160207324585172'",
10
+ template_name: 'CAP71871_4',
11
+ type: 'Service-Explicit',
12
+ header: 'VISHMM',
13
+ category: '--',
14
+ 'sms-editor':
15
+ 'LATEST FASHION@VISHAL\n{#var#}\n\nBUY1GET1-\n{#var#}\n{#var#}\n{#var#}\n\nFREE GIFTS-\n{#var#}\n{#var#}',
16
+ 'consent-type': 'Explicit',
17
+ 'unicode-validity': false,
18
+ tabKey: 1,
19
+ },
20
+ },
21
+ isActive: true,
22
+ orgId: 50146,
23
+ createdBy: '15000449',
24
+ updatedBy: '15000449',
25
+ createdAt: '2021-08-25T07:25:12.559Z',
26
+ updatedAt: '2021-08-30T05:54:59.951Z',
27
+ },
28
+ location: {
29
+ pathname: '/sms/edit',
30
+ query: {
31
+ type: false,
32
+ module: 'default',
33
+ },
34
+ search: '',
35
+ },
36
+ };
@@ -0,0 +1,75 @@
1
+ /*
2
+ *
3
+ * SmsWrapper
4
+ *
5
+ */
6
+ import PropTypes from 'prop-types';
7
+ import React from 'react';
8
+ import SmsCreate from '../Sms/Create';
9
+ import { hasTraiDltFeature } from '../../utils/common';
10
+ import SmsEdit from '../Sms/Edit';
11
+ import SmsTraiCreate from '../SmsTrai/Create';
12
+ import SmsTraiEdit from '../SmsTrai/Edit';
13
+ const SmsWrapper = (props) => {
14
+ const {
15
+ isCreateSms,
16
+ isEditSms,
17
+ setIsLoadingContent,
18
+ location,
19
+ isGetFormData,
20
+ getFormSubscriptionData,
21
+ isFullMode,
22
+ templateData,
23
+ getDefaultTags,
24
+ forwardedTags,
25
+ selectedOfferDetails,
26
+ onPreviewContentClicked,
27
+ onTestContentClicked,
28
+ onCreateComplete,
29
+ handleClose
30
+ } = props;
31
+
32
+ const smsProps = {
33
+ onCreateComplete,
34
+ setIsLoadingContent,
35
+ location,
36
+ route: { name: 'sms' },
37
+ isGetFormData,
38
+ getFormSubscriptionData,
39
+ getDefaultTags,
40
+ isFullMode,
41
+ forwardedTags,
42
+ selectedOfferDetails,
43
+ onPreviewContentClicked,
44
+ onTestContentClicked,
45
+ };
46
+ const isTraiDltFeature = hasTraiDltFeature();
47
+ return <>
48
+ {
49
+ isCreateSms && (isTraiDltFeature ?
50
+ <SmsTraiCreate
51
+ isComponent
52
+ {...smsProps}/> :
53
+ <SmsCreate
54
+ isComponent {
55
+ ...smsProps
56
+ }
57
+ />
58
+ )
59
+ }
60
+ {isEditSms && (isTraiDltFeature ?
61
+ <SmsTraiEdit
62
+ {...smsProps}
63
+ params={{id: templateData._id}}
64
+ templateData={templateData}
65
+ handleClose={handleClose}
66
+ />:<SmsEdit
67
+ {...smsProps}
68
+ params={{id: templateData._id}}
69
+ templateData={templateData}
70
+ />
71
+ )}
72
+ </>;
73
+ };
74
+
75
+ export default SmsWrapper;
@@ -0,0 +1,10 @@
1
+ // import React from 'react';
2
+ // import { shallow } from 'enzyme';
3
+
4
+ // import { SmsWrapper } from '../index';
5
+
6
+ describe('<SmsWrapper />', () => {
7
+ it('Expect to have unit tests specified', () => {
8
+ expect(true).toEqual(false);
9
+ });
10
+ });
@@ -481,6 +481,7 @@
481
481
  .line-filters {
482
482
  width: 100%;
483
483
  padding-left: 12px;
484
+ padding-bottom: 16px;
484
485
  .ant-radio-button-wrapper {
485
486
  line-height: 32px;
486
487
  border-radius: 16px;
@@ -494,6 +495,7 @@
494
495
  }
495
496
  .ant-radio-button-wrapper-checked {
496
497
  background-color: #ecece7;
498
+ border: 0px white;
497
499
  box-shadow: none;
498
500
  }
499
501
  }
@@ -98,6 +98,13 @@ const LINE_FILTERS = {
98
98
  IMAGE_MAP_VIDEO: 'video',
99
99
  };
100
100
 
101
+ const SMS_FILTERS = {
102
+ ALL: 'all',
103
+ PROMOTIONAL: 'promotional',
104
+ SERVICE_EXPLICIT: 'service-explicit',
105
+ SERVICE_IMPLICIT: 'service-implicit',
106
+ };
107
+
101
108
  export class Templates extends React.Component { // eslint-disable-line react/prefer-stateless-function
102
109
  constructor(props) {
103
110
  super(props);
@@ -125,6 +132,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
125
132
  activeMode: TEMPLATES_MODE,
126
133
  wechatFilter: WECHAT_FILTERS.ALL,
127
134
  lineFilter: LINE_FILTERS.ALL,
135
+ smsFilter: SMS_FILTERS.ALL,
128
136
  };
129
137
 
130
138
  this.handleOnHoverItem = this.handleOnHoverItem.bind(this);
@@ -147,7 +155,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
147
155
  this.prepareMobilePushPreviewData = this.prepareMobilePushPreviewData.bind(this);
148
156
  this.menuOnClickEvent = this.menuOnClickEvent.bind(this);
149
157
  }
150
-
158
+
151
159
  componentWillMount() {
152
160
  if (this.state.channel === '') {
153
161
  let channel = '';
@@ -215,6 +223,10 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
215
223
  queryParams.page = this.state.page;
216
224
  queryParams.perPage = this.state.perPageLimit;
217
225
  const channel = this.state.channel;
226
+ const isTraiDltFeature = commonUtil.hasTraiDltFeature();
227
+ if ((this.state.channel || '').toLowerCase() === "sms" && isTraiDltFeature) {
228
+ queryParams.traiEnable = true;
229
+ }
218
230
  this.props.actions.getAllTemplates(channel, queryParams);
219
231
  }
220
232
 
@@ -230,7 +242,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
230
242
  const { templatesCount } = this.state || {};
231
243
 
232
244
  if (nextPropsTotalTemplatesCount && nextPropsTotalTemplatesCount !== propsTotalTemplatesCount && templatesCount === 0) {
233
- this.setState({ templatesCount: nextPropsTotalTemplatesCount });
245
+ this.setState({ templatesCount: nextPropsTotalTemplatesCount });
234
246
  }
235
247
  if (!isEqual(nextProps.route.name, this.props.route.name)) {
236
248
  let channel = '';
@@ -503,7 +515,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
503
515
  this.getAllTemplates({params, resetPage: true});
504
516
  });
505
517
  }
506
- onPaginationChange = () => { this.getAllTemplates({getNextPage: true}); }
518
+ onPaginationChange = () => {
519
+ this.getAllTemplates({getNextPage: true});
520
+ }
507
521
  onCreateComplete = (isReloadTemplates) => {
508
522
  this.setState({routeParams: null, previewOpen: false}, () => {
509
523
  if (this.isFullMode() && isReloadTemplates) {
@@ -572,6 +586,10 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
572
586
  if (activeMode === ACCOUNT_SELECTION_MODE) {
573
587
  this.setTemplatesMode();
574
588
  }
589
+ const isTraiDltFeature = commonUtil.hasTraiDltFeature();
590
+ if ((this.state.channel || '').toLowerCase() === "sms" && isTraiDltFeature) {
591
+ queryParams.traiEnable = true;
592
+ }
575
593
  if (resetTemplates) {
576
594
  queryParams.name = this.state.searchText;
577
595
  queryParams.sortBy = this.state.sortBy;
@@ -610,6 +628,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
610
628
  }
611
629
  }
612
630
  }
631
+
613
632
  this.setState({page, templatesCount}, () => {
614
633
  queryParams.page = page;
615
634
  queryParams.perPage = this.state.perPageLimit;
@@ -629,18 +648,30 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
629
648
  return templates;
630
649
  }
631
650
  }
651
+ filterSMSTemplates = (templates) => {
652
+ const { smsFilter } = this.state;
653
+ if (SMS_FILTERS.ALL === smsFilter) {
654
+ return templates;
655
+ }
656
+ return templates.filter((template) => template.versions.base.type.toLowerCase() === smsFilter);
657
+ }
632
658
 
633
659
  getTemplateDataForGrid = ({templates, handlers, filterContent, channel, isLoading, loadingTip}) => {
634
660
  const currentChannel = channel.toUpperCase();
635
661
  const {channel: stateChannel} = this.state;
636
662
  const channelLowerCase = stateChannel.toLowerCase();
637
663
  let filteredTemplates = templates;
664
+ let isTraiDltFeature = false;
638
665
  if (currentChannel === WECHAT) {
639
666
  filteredTemplates = this.filterWechatTemplates(templates);
640
667
  }
641
668
  if (currentChannel === LINE) {
642
669
  filteredTemplates = this.filterLineTemplates(templates);
643
670
  }
671
+ if (currentChannel === SMS) {
672
+ filteredTemplates = this.filterSMSTemplates(templates);
673
+ isTraiDltFeature = commonUtil.hasTraiDltFeature();
674
+ }
644
675
  const cardDataList = filteredTemplates && filteredTemplates.length ? map(filteredTemplates, (template) => {
645
676
  const templateData =
646
677
  {
@@ -660,7 +691,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
660
691
  templateData.extra.push(<CapDropdown
661
692
  overlay={
662
693
  <CapMenu>
663
- {this.state.channel.toUpperCase() !== WECHAT && <CapMenu.Item className={`duplicate-${channelLowerCase}`} onClick={() => this.duplicateTemplate(template)}>
694
+ {this.state.channel.toUpperCase() !== WECHAT && !isTraiDltFeature && <CapMenu.Item className={`duplicate-${channelLowerCase}`} onClick={() => this.duplicateTemplate(template)}>
664
695
  <FormattedMessage {...messages.duplicateButton} />
665
696
  </CapMenu.Item>}
666
697
  <CapMenu.Item
@@ -677,7 +708,20 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
677
708
  }
678
709
  switch (currentChannel) {
679
710
  case SMS:
680
- templateData.content = template.versions.base['sms-editor'];
711
+ templateData.content = isTraiDltFeature ? (
712
+ <>
713
+ <CapLabel type="label3" style={{ marginBottom: CAP_SPACE_16 }}>
714
+ {template.versions.base.type}
715
+ </CapLabel>
716
+ <CapLabel type="label1">
717
+ {template.versions.base['updated-sms-editor'] === ''
718
+ ? template.versions.base['sms-editor']
719
+ : template.versions.base['updated-sms-editor']?.join('')}
720
+ </CapLabel>
721
+ </>
722
+ ) : (
723
+ template.versions.base['sms-editor']
724
+ );
681
725
  break;
682
726
  case EMAIL: {
683
727
  const url = template.versions.base.preview_http_url;
@@ -1407,9 +1451,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
1407
1451
  }
1408
1452
  }
1409
1453
  if (this.isEnabledInLibraryModule("callSelectFromProps")) {
1410
- let data =id;
1411
- if(this.props.fbAdManager){
1412
- data = this.selectTemplate(id)
1454
+ let data = id;
1455
+ if (this.props.fbAdManager) {
1456
+ data = this.selectTemplate(id);
1413
1457
  }
1414
1458
  this.props.onSelectTemplate(data, this.props.fbAdManager);
1415
1459
  } else {
@@ -1942,10 +1986,12 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
1942
1986
 
1943
1987
  setWechatFilter = (e) => this.setState({wechatFilter: e.target.value});
1944
1988
  setLineFilter = (e) => this.setState({lineFilter: e.target.value});
1989
+ setSMSFilter = (e) => this.setState({smsFilter: e.target.value});
1990
+
1945
1991
 
1946
1992
  render() {
1947
1993
  const isFullMode = this.isFullMode();
1948
- const { activeMode, channel, wechatFilter, lineFilter } = this.state;
1994
+ const { activeMode, channel, wechatFilter, lineFilter, smsFilter } = this.state;
1949
1995
  let showFbAds = false;
1950
1996
  if (channel.toLowerCase() === FACEBOOK_CHANNEL) {
1951
1997
  const {campaignSettings, fetchedOrgLevelCampaignSettings} = this?.props?.Templates || {};
@@ -2008,6 +2054,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
2008
2054
  const isfilterContentVisisble = true;
2009
2055
  const isWechatEmbedded = !this.props.isFullMode && channel.toUpperCase() === WECHAT;
2010
2056
  const channelLowerCase = (channel || '').toLowerCase();
2057
+ const isTraiDltFeature = commonUtil.hasTraiDltFeature();
2011
2058
  const filterContent = (( isfilterContentVisisble || [WECHAT, MOBILE_PUSH].includes(this.state.channel.toUpperCase())) && <div className="action-container">
2012
2059
  {isfilterContentVisisble && <CapInput.Search
2013
2060
  className="search-text"
@@ -2068,14 +2115,44 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
2068
2115
  )
2069
2116
  : () => null
2070
2117
  }
2118
+ {
2119
+ channel.toUpperCase() === SMS &&
2120
+ isTraiDltFeature
2121
+ ? (
2122
+ <CapRadio.CapRadioGroup className="line-filters" defaultValue={smsFilter} onChange={this.setSMSFilter}>
2123
+ {
2124
+ (() => {
2125
+ const { ALL, SERVICE_IMPLICIT, SERVICE_EXPLICIT, PROMOTIONAL } = SMS_FILTERS;
2126
+ return (
2127
+ <>
2128
+ <CapRadio.Button value={ALL}><CapLabel type="label2">
2129
+ <FormattedMessage {...messages.all} />
2130
+ </CapLabel></CapRadio.Button>
2131
+ <CapRadio.Button value={PROMOTIONAL}><CapLabel type="label2">
2132
+ <FormattedMessage {...messages.promotional} />
2133
+ </CapLabel></CapRadio.Button>
2134
+ <CapRadio.Button value={SERVICE_EXPLICIT}><CapLabel type="label2">
2135
+ <FormattedMessage {...messages.serviceExplicit} />
2136
+ </CapLabel></CapRadio.Button>
2137
+ <CapRadio.Button value={SERVICE_IMPLICIT}><CapLabel type="label2">
2138
+ <FormattedMessage {...messages.serviceImplicit} />
2139
+ </CapLabel></CapRadio.Button>
2140
+ </>
2141
+ );
2142
+ })()
2143
+ }
2144
+ </CapRadio.CapRadioGroup>
2145
+ )
2146
+ : () => null
2147
+ }
2071
2148
  <div style={{display: "flex", justifyContent: "space-between", alignItems: 'center'}}>
2072
2149
  {isfilterContentVisisble && !isWechatEmbedded && <CapButton
2073
2150
  className={`create-new-${channelLowerCase}`}
2074
2151
  type={"primary"}
2075
2152
  disabled={this.isCreateDisabled()}
2076
- style={{marginLeft: '8px'}}
2153
+ style={{marginLeft: '8px', marginBottom: '12px'}}
2077
2154
  onClick={this.createTemplate} >
2078
- { this.props.intl.formatMessage(messages.createNewActionButton) }
2155
+ { this.props.intl.formatMessage((isTraiDltFeature && channel.toUpperCase() === SMS ) ? messages.uploadTemplate : messages.createNewActionButton) }
2079
2156
  </CapButton>}
2080
2157
  </div>
2081
2158
 
@@ -374,4 +374,20 @@ export default defineMessages({
374
374
  id: `${scope}.noAccountsPresentFacebook`,
375
375
  defaultMessage: "Please setup the Facebook account & Facebook page to start creating content in Capillary's FB content creator.",
376
376
  },
377
+ "promotional": {
378
+ id: `${scope}.promotional`,
379
+ defaultMessage: 'Promotional',
380
+ },
381
+ "serviceExplicit": {
382
+ id: `${scope}.serviceExplicit`,
383
+ defaultMessage: 'Service explicit',
384
+ },
385
+ "serviceImplicit": {
386
+ id: `${scope}.serviceImplicit`,
387
+ defaultMessage: 'Service implicit',
388
+ },
389
+ "uploadTemplate": {
390
+ id: `${scope}.uploadTemplate`,
391
+ defaultMessage: 'Upload template',
392
+ },
377
393
  });