@capillarytech/creatives-library 7.1.11 → 7.2.1

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 (62) hide show
  1. package/assets/viber.png +0 -0
  2. package/index.js +8 -1
  3. package/package.json +2 -1
  4. package/reducers.js +2 -0
  5. package/routes.js +7 -1
  6. package/services/api.js +5 -0
  7. package/v2Components/TemplatePreview/_templatePreview.scss +8 -2
  8. package/v2Components/TemplatePreview/assets/images/viberMobile.svg +135 -0
  9. package/v2Components/TemplatePreview/index.js +108 -18
  10. package/v2Containers/App/constants.js +1 -1
  11. package/v2Containers/CreativesContainer/SlideBoxContent.js +67 -2
  12. package/v2Containers/CreativesContainer/constants.js +2 -0
  13. package/v2Containers/CreativesContainer/index.js +40 -5
  14. package/v2Containers/FTP/_FTP.scss +103 -0
  15. package/v2Containers/FTP/actions.js +7 -0
  16. package/v2Containers/FTP/constants.js +3 -0
  17. package/v2Containers/FTP/index.js +534 -0
  18. package/v2Containers/FTP/messages.js +60 -0
  19. package/v2Containers/FTP/reducer.js +32 -0
  20. package/v2Containers/FTP/sagas.js +26 -0
  21. package/v2Containers/FTP/selectors.js +20 -0
  22. package/v2Containers/Templates/_templates.scss +57 -0
  23. package/v2Containers/Templates/actions.js +117 -110
  24. package/v2Containers/Templates/constants.js +2 -0
  25. package/v2Containers/Templates/index.js +88 -7
  26. package/v2Containers/Templates/messages.js +4 -0
  27. package/v2Containers/Templates/reducer.js +2 -0
  28. package/v2Containers/TemplatesV2/index.js +9 -1
  29. package/v2Containers/TemplatesV2/messages.js +4 -0
  30. package/v2Containers/Viber/actions.js +74 -0
  31. package/v2Containers/Viber/constants.js +30 -0
  32. package/v2Containers/Viber/index.js +727 -0
  33. package/v2Containers/Viber/messages.js +145 -0
  34. package/v2Containers/Viber/reducer.js +84 -0
  35. package/v2Containers/Viber/sagas.js +107 -0
  36. package/v2Containers/Viber/selectors.js +21 -0
  37. package/v2Components/TemplatePreview/assets/images/mobile.svg +0 -24
  38. package/v2Containers/Line/Create/_lineCreate.scss +0 -64
  39. package/v2Containers/Line/Create/actions.js +0 -94
  40. package/v2Containers/Line/Create/constants.js +0 -43
  41. package/v2Containers/Line/Create/index.js +0 -1132
  42. package/v2Containers/Line/Create/initialSchema.js +0 -378
  43. package/v2Containers/Line/Create/messages.js +0 -229
  44. package/v2Containers/Line/Create/reducer.js +0 -99
  45. package/v2Containers/Line/Create/sagas.js +0 -113
  46. package/v2Containers/Line/Create/selectors.js +0 -30
  47. package/v2Containers/Line/CreateWrapper/constants.js +0 -2
  48. package/v2Containers/Line/CreateWrapper/index.js +0 -117
  49. package/v2Containers/Line/CreateWrapper/messages.js +0 -55
  50. package/v2Containers/Line/Edit/_lineEdit.scss +0 -23
  51. package/v2Containers/Line/Edit/actions.js +0 -79
  52. package/v2Containers/Line/Edit/constants.js +0 -27
  53. package/v2Containers/Line/Edit/index.js +0 -1051
  54. package/v2Containers/Line/Edit/messages.js +0 -173
  55. package/v2Containers/Line/Edit/reducer.js +0 -83
  56. package/v2Containers/Line/Edit/sagas.js +0 -81
  57. package/v2Containers/Line/Edit/selectors.js +0 -29
  58. package/v2Containers/Line/Edit/tests/actions.test.js +0 -18
  59. package/v2Containers/Line/Edit/tests/index.test.js +0 -10
  60. package/v2Containers/Line/Edit/tests/reducer.test.js +0 -9
  61. package/v2Containers/Line/Edit/tests/sagas.test.js +0 -15
  62. package/v2Containers/Line/Edit/tests/selectors.test.js +0 -10
@@ -0,0 +1,534 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import { bindActionCreators } from 'redux';
4
+ import { FormattedMessage, intlShape } from 'react-intl';
5
+ import { createStructuredSelector } from 'reselect';
6
+ import {
7
+ CapRadioCard,
8
+ CapSpin,
9
+ CapHeading,
10
+ CapHeader,
11
+ CapButton,
12
+ CapIcon,
13
+ CapLink,
14
+ CapRow,
15
+ CapColumn,
16
+ CapInput,
17
+ CapLabel,
18
+ CapTag,
19
+ CapTreeSelect,
20
+ CapDivider,
21
+ } from '@capillarytech/cap-ui-library';
22
+ import { find, cloneDeep, findIndex, isEmpty, isEqual, filter } from 'lodash';
23
+ import * as actions from './actions';
24
+ import { makeSelectFTP, makeSelectMetaEntities } from './selectors';
25
+ import withCreatives from '../../hoc/withCreatives';
26
+ import messages from './messages';
27
+ import './_FTP.scss';
28
+ import * as globalActions from '../../containers/Cap/actions';
29
+ import { TagList } from '../TagList';
30
+ import { NO_COMMUNICATION, CREATE, EDIT, PREVIEW } from '../App/constants';
31
+ import { getTreeStructuredTags } from '../../utils/common';
32
+
33
+ const UIView = {
34
+ serverSelection: 'serverSelection',
35
+ configureMessage: 'configureMessage',
36
+ };
37
+ const { CapLabelInline } = CapLabel;
38
+ export class FTP extends React.Component {
39
+ constructor(props) {
40
+ super(props);
41
+ this.state = this.getInitialState();
42
+ }
43
+ getInitialState = () => {
44
+ const mode = this.props.mode || CREATE;
45
+ let stateObj = {};
46
+ if (mode === CREATE) {
47
+ const { formatMessage } = this.props.intl;
48
+ const headerTagList = [{
49
+ header: formatMessage(messages.customerID),
50
+ tag: '{{user_id}}',
51
+ }];
52
+ stateObj = {
53
+ mode,
54
+ selectedServer: null,
55
+ viewMode: UIView.serverSelection,
56
+ headerTagList,
57
+ messageContent: '',
58
+ tagsTree: [],
59
+ };
60
+ } else {
61
+ const { messageContent = {} } = this.props.messageDetails || {};
62
+ const { headerTagList = [], messageBody = '' } = messageContent['message_content_id_1'] || {};
63
+ stateObj = {
64
+ mode,
65
+ selectedServer: null,
66
+ viewMode: UIView.configureMessage,
67
+ headerTagList,
68
+ messageContent: messageBody,
69
+ tagsTree: [],
70
+ };
71
+ }
72
+ return stateObj;
73
+ };
74
+
75
+ setFTPServerInState = (FTPServers) => {
76
+ const { deliverySetting = { channelSetting: {} }} = this.props.messageDetails;
77
+ const configId = (deliverySetting.channelSetting[NO_COMMUNICATION].endPointConfigs || {}).ftpConfigId;
78
+ const selectedServer = find(FTPServers, {id: configId});
79
+ this.setState({ selectedServer });
80
+ };
81
+
82
+ componentDidMount() {
83
+ this.props.actions.getFTPServers();
84
+ const query = {
85
+ layout: 'SMS',
86
+ type: 'TAG',
87
+ context: 'outbound',
88
+ embedded: 'embedded',
89
+ };
90
+ //This call is to fetch tags that are populated in csv columns.
91
+ this.props.globalActions.fetchSchemaForEntity(query);
92
+ }
93
+
94
+ componentWillReceiveProps(nextProps) {
95
+ const { metaEntities = {}, selectedOfferDetails = [], mode, FTP: nextFTP = {} } = nextProps;
96
+ const { metaEntities: thisMetaEntities = {}, FTP: thisFTP = {}} = this.props;
97
+ const { tags: thisTags = {}} = thisMetaEntities;
98
+ if (
99
+ !isEmpty((metaEntities.tags || {}).standard) &&
100
+ !isEqual((metaEntities.tags || {}).standard, thisTags.standard)
101
+ ) {
102
+ const tags = getTreeStructuredTags({tagsList: metaEntities.tags.standard, offerDetails: selectedOfferDetails});
103
+ this.setState({ tagsTree: tags}, () => this.disableUsedColumns());
104
+ }
105
+
106
+ if (
107
+ mode === EDIT &&
108
+ nextFTP.FTPServers.length &&
109
+ !isEqual(nextFTP.FTPServers, thisFTP.FTPServers)
110
+ ) {
111
+ this.setFTPServerInState(nextFTP.FTPServers);
112
+ }
113
+ }
114
+
115
+ onChangeFTPServer = (e) => {
116
+ const { value } = e.target;
117
+ const { FTPServers = [] } = this.props.FTP || {};
118
+ const selectedServer = find(FTPServers, {id: value});
119
+ this.setState({ selectedServer, viewMode: UIView.configureMessage});
120
+ };
121
+
122
+ onTagSelect = (data) => {
123
+ this.insertAtCursor(`{{${data}}}`);
124
+ };
125
+
126
+ setInputRef = (textarea) => {
127
+ this.textArea = textarea;
128
+ };
129
+
130
+ getServerSelectionContent = () => {
131
+ const { getFTPServersInProgress } = this.props.FTP || {};
132
+ const { formatMessage } = this.props.intl;
133
+ const serverOptions = this.getServerOptions();
134
+ const { selectedServer } = this.state;
135
+ return (
136
+ <CapSpin spinning={getFTPServersInProgress}>
137
+ <CapHeading
138
+ type="h3"
139
+ className="select-account-header"
140
+ >
141
+ {formatMessage(messages.ftpServer)}
142
+ </CapHeading>
143
+ <CapHeading type="h6" className="manage-ftp-setting-div">
144
+ {formatMessage(messages.ftpServerDesc)}
145
+ <CapLink
146
+ title={formatMessage(messages.manageFTPSettings)}
147
+ className="select-server"
148
+ onClick={this.handleManageFTPSettings}
149
+ />
150
+ </CapHeading>
151
+ <CapRadioCard
152
+ className="select-account"
153
+ onChange={this.onChangeFTPServer}
154
+ panes={serverOptions}
155
+ cardHeight="48px"
156
+ cardWidth="276px"
157
+ size="small"
158
+ defaultValue={selectedServer}
159
+ selected={selectedServer}
160
+ />
161
+ </CapSpin>
162
+ );
163
+ };
164
+
165
+ getServerOptions = () => {
166
+ const { FTPServers = [] } = this.props.FTP || {};
167
+ return (FTPServers).map(({
168
+ // eslint-disable-next-line camelcase
169
+ ftp_tag = '',
170
+ id,
171
+ }) => ({
172
+ key: ftp_tag,
173
+ value: id,
174
+ title: ftp_tag,
175
+ icon: <CapIcon.CapIconAvatar text={ftp_tag[0]} width="auto" height="2rem"/>,
176
+ }));
177
+ };
178
+
179
+ getMessageContent = () => {
180
+ const { messageContent } = this.state;
181
+ const { formatMessage } = this.props.intl;
182
+ const { metaEntities, selectedOfferDetails } = this.props;
183
+ const tagsRaw = metaEntities && metaEntities.tags ? metaEntities.tags.standard : [];
184
+ return (
185
+ <CapRow>
186
+ <CapColumn span={11}>
187
+ <div className="message-content-title">
188
+ <TagList
189
+ className="FTP-tagList"
190
+ label={formatMessage(messages.addLabel)}
191
+ tags={tagsRaw}
192
+ onTagSelect={this.onTagSelect}
193
+ selectedOfferDetails={selectedOfferDetails}
194
+ />
195
+ <CapInput.TextArea
196
+ setInputRef={this.setInputRef}
197
+ label={formatMessage(messages.messageHeader)}
198
+ onChange={this.updateMessageBody}
199
+ value={messageContent}
200
+ />
201
+ </div>
202
+ </CapColumn>
203
+ </CapRow>
204
+ );
205
+ };
206
+
207
+ getCsvColumns = () => {
208
+ const { headerTagList = [], tagsTree = [] } = this.state;
209
+ const { formatMessage } = this.props.intl;
210
+ const tagsWithoutOptout = tagsTree.length && tagsTree.filter((tag) => tag.value !== '{{optout}}');
211
+ const headerTagElements = headerTagList.map((item, index) => (
212
+ index !== 0 && <div className="column-selection-container">
213
+ <CapSpin spinning={!tagsWithoutOptout.length}>
214
+ <CapTreeSelect
215
+ dropdownClassName="select-csv-col-dropdown"
216
+ treeData={tagsWithoutOptout}
217
+ className="select-csv-column"
218
+ value={!isEmpty(item.header) ? item.header : formatMessage(messages.selectTag)}
219
+ onChange={(option, label) => this.selectCsvColumn(option, label, index)}
220
+ showSearch
221
+ />
222
+ <CapIcon
223
+ type="close"
224
+ size="m"
225
+ onClick={() => this.removeCsvColumn(item)}
226
+ className="remove-csv-column"
227
+ />
228
+ </CapSpin>
229
+ </div>
230
+ ));
231
+ headerTagElements.unshift(
232
+ <CapLabelInline
233
+ className="column-selection-container-cid"
234
+ type="label2"
235
+ style={{fontSize: 14, fontWeight: 500}}
236
+ >
237
+ <FormattedMessage {...messages.customerID}/>
238
+ </CapLabelInline>
239
+ );
240
+ return headerTagElements;
241
+ };
242
+
243
+ getConfigureCsvContent = () => {
244
+ const { formatMessage } = this.props.intl;
245
+ return (
246
+ <>
247
+ <CapRow className="configure-csv-container">
248
+ <CapColumn span={8} className="configure-csv">
249
+ <CapHeader
250
+ title={formatMessage(messages.configureCsv)}
251
+ size="regular"
252
+ className="select-account-header"
253
+ />
254
+ </CapColumn>
255
+ <CapColumn span={3} offset={13} className="add-column">
256
+ <CapButton
257
+ type="flat"
258
+ isAddBtn
259
+ onClick={this.addNewColumn}
260
+ >
261
+ <FormattedMessage {...messages.addColumn} />
262
+ </CapButton>
263
+ </CapColumn>
264
+ </CapRow>
265
+ {this.getCsvColumns()}
266
+ </>
267
+ );
268
+ }
269
+
270
+ getConfigureMessageContent = () => {
271
+ const { formatMessage } = this.props.intl;
272
+ const { selectedServer = {}, headerTagList = [] } = this.state;
273
+ const emptyHeaderTagList = filter(headerTagList, {tag: ''});
274
+ const disableDoneButton = isEmpty(selectedServer) || emptyHeaderTagList.length;
275
+ return (
276
+ <CapSpin spinning={false}>
277
+ <div className="scrollable-section">
278
+ <CapHeader
279
+ title={formatMessage(messages.ftpServer)}
280
+ size="regular"
281
+ className="select-account-header"
282
+ />
283
+ <div className="selected-server-name">
284
+ <CapIcon.CapIconAvatar
285
+ className="server-avtar"
286
+ text={((selectedServer || {}).ftp_tag || [])[0]}
287
+ width="auto"
288
+ height="2rem"
289
+ />
290
+ <CapHeading
291
+ type="h4"
292
+ className="server-name"
293
+ >
294
+ {(selectedServer || {}).ftp_tag}
295
+ </CapHeading>
296
+ <CapLink
297
+ title={formatMessage(messages.change)}
298
+ className="server-change"
299
+ onClick={this.showAccountSelection}
300
+ />
301
+ </div>
302
+ <CapDivider />
303
+ {this.getConfigureCsvContent()}
304
+ <CapDivider />
305
+ <div className="ftp-message-container">
306
+ <CapHeader
307
+ title={formatMessage(messages.messageContent)}
308
+ description={formatMessage(messages.optional)}
309
+ size="regular"
310
+ inline
311
+ />
312
+ {this.getMessageContent()}
313
+ </div>
314
+ </div>
315
+ <CapButton
316
+ type="primary"
317
+ disabled={disableDoneButton}
318
+ onClick={this.saveFtpMessage}
319
+ >
320
+ <FormattedMessage {...messages.done} />
321
+ </CapButton>
322
+ </CapSpin>
323
+ );
324
+ };
325
+
326
+ getColumnsHeaderPreview = (headerTagList) => (
327
+ <div className="ftp-preview-data-col-container">
328
+ { headerTagList.map((tag) => (
329
+ <CapTag type="static" className="ftp-preview-data-col-tag">
330
+ {tag.header}
331
+ </CapTag>
332
+ ))}
333
+ </div>
334
+ );
335
+
336
+ getPreviewModeContents = () => {
337
+ const { contents = [] } = this.props;
338
+ const { messageBody = '', headerTagList = [] } = contents[0] || {};
339
+ return (
340
+ <div className="ftp-preview-container">
341
+ <CapHeading className="ftp-preview-message-title" type="h3">
342
+ <FormattedMessage {...messages.messageContent}/>
343
+ </CapHeading>
344
+ <CapLabel type="label2" className="ftp-preview-message-content">
345
+ {messageBody}
346
+ </CapLabel>
347
+ <CapHeading className="ftp-preview-data-title" type="h3">
348
+ <FormattedMessage {...messages.dataPreview}/>
349
+ </CapHeading>
350
+ {this.getColumnsHeaderPreview(headerTagList)}
351
+ </div>
352
+ );
353
+ };
354
+
355
+ showAccountSelection = () => {
356
+ this.setState({ viewMode: UIView.serverSelection, selectedServer: null, headerTagList: [], messageContent: ''});
357
+ };
358
+
359
+ selectCsvColumn = (option, label, index) => {
360
+ const { headerTagList } = this.state;
361
+ const clonedHeaderTagList = cloneDeep(headerTagList);
362
+ const obj = {
363
+ header: label[0],
364
+ tag: option,
365
+ };
366
+ clonedHeaderTagList[index] = obj;
367
+ this.setState({ headerTagList: clonedHeaderTagList}, () => this.disableUsedColumns());
368
+ };
369
+
370
+ disableUsedColumns = () => {
371
+ const { headerTagList = [] } = this.state;
372
+ const { selectedOfferDetails = [], metaEntities = {} } = this.props;
373
+ const tags = getTreeStructuredTags({tagsList: (metaEntities.tags || {}).standard, offerDetails: selectedOfferDetails});
374
+ const clonnedTagsTree = cloneDeep(tags);
375
+ headerTagList.map((headerTag) => {
376
+ clonnedTagsTree.map((tag, index) => {
377
+ if (!isEmpty(tag.children)) { //if we have subtags it will first resolve subtag values.
378
+ const subTags = this.disableUsedSubTag(tag.children, headerTag);
379
+ clonnedTagsTree[index] = {
380
+ ...clonnedTagsTree[index],
381
+ children: subTags,
382
+ };
383
+ } else { // If first level itself is leaf node then I will match the usedtag value and disable it accordingly.
384
+ const pos = findIndex(clonnedTagsTree, {value: headerTag.tag});
385
+ if (pos > -1) {
386
+ clonnedTagsTree[pos] = {
387
+ disabled: true,
388
+ ...clonnedTagsTree[pos],
389
+ };
390
+ }
391
+ }
392
+ });
393
+ });
394
+ this.setState({tagsTree: clonnedTagsTree});
395
+ };
396
+
397
+ disableUsedSubTag = (subTags, headerTag) => {
398
+ const clonnedSubTags = cloneDeep(subTags);
399
+ clonnedSubTags.map((tag, index) => {
400
+ if (!isEmpty(tag.children)) { //Using recursion here to dig deep into further level if they have subtags.
401
+ //if we still have subtags, it will call same function to resolved deepest subtag value first.
402
+ const subTags1 = this.disableUsedSubTag(tag.children, headerTag);
403
+ clonnedSubTags[index] = {
404
+ ...clonnedSubTags[index],
405
+ children: subTags1,
406
+ };
407
+ } else if (isEqual(tag.value, headerTag.tag)) { // when Leaf node, it will match usedtag value and disable usedtags from tags tree.
408
+ clonnedSubTags[index] = {
409
+ disabled: true,
410
+ ...clonnedSubTags[index],
411
+ };
412
+ }
413
+ return null;
414
+ });
415
+ return clonnedSubTags;
416
+ }
417
+
418
+ handleManageFTPSettings = () => {
419
+ const path = `/exports/configurations`;
420
+ window.open(path, '_blank');
421
+ };
422
+
423
+ removeCsvColumn = (item) => {
424
+ const { headerTagList } = this.state;
425
+ const clonedHeaderTagList = cloneDeep(headerTagList);
426
+ const index = findIndex(headerTagList, (val) => val.tag === item.tag);
427
+ clonedHeaderTagList.splice(index, 1);
428
+ this.setState({ headerTagList: clonedHeaderTagList}, () => this.disableUsedColumns());
429
+ };
430
+
431
+ addNewColumn = () => {
432
+ const { headerTagList } = this.state;
433
+ const clonedHeaderTagList = cloneDeep(headerTagList);
434
+ const newCsvObj = {
435
+ header: '',
436
+ tag: '',
437
+ };
438
+ clonedHeaderTagList.push(newCsvObj);
439
+ this.setState({ headerTagList: clonedHeaderTagList});
440
+ };
441
+
442
+ insertAtCursor = (myValue) => {
443
+ this.textArea.focus();
444
+ const textAreaRef = this.textArea.textAreaRef;
445
+ let pos = textAreaRef.selectionEnd + myValue.length;
446
+ //IE support
447
+ let newMessage = textAreaRef.value + myValue;
448
+ if (document.selection) {
449
+ this.textArea.focus();
450
+ const sel = document.selection.createRange();
451
+ sel.text = myValue;
452
+ } else if (textAreaRef.selectionStart || textAreaRef.selectionStart === '0') { //MOZILLA and others
453
+ const startPos = textAreaRef.selectionStart;
454
+ const endPos = textAreaRef.selectionEnd;
455
+ newMessage = textAreaRef.value.substring(0, startPos) + myValue + textAreaRef.value.substring(endPos, textAreaRef.value.length);
456
+ pos = startPos + myValue.length;
457
+ }
458
+ this.setState({
459
+ messageContent: newMessage,
460
+ }, () => {
461
+ textAreaRef.selectionStart = pos;
462
+ textAreaRef.selectionEnd = pos;
463
+ });
464
+ };
465
+
466
+ updateMessageBody = (e) => {
467
+ this.setState({
468
+ messageContent: e.target.value,
469
+ });
470
+ };
471
+
472
+ saveFtpMessage = () => {
473
+ const { onFTPSubmit } = this.props;
474
+ const { FTPServers = [] } = this.props.FTP || {};
475
+ const { selectedServer = {}, headerTagList = [], messageContent = '' } = this.state;
476
+ onFTPSubmit({
477
+ channel: "FTP",
478
+ endPointConfigs: {
479
+ endPointType: "FTP",
480
+ ftpConfigId: selectedServer.id,
481
+ },
482
+ headerTagList,
483
+ messageContent,
484
+ FTPServers,
485
+ });
486
+ };
487
+
488
+ render() {
489
+ const { viewMode } = this.state;
490
+ const { serverSelection } = UIView;
491
+ const { mode } = this.props;
492
+ return (
493
+ mode === PREVIEW ?
494
+ this.getPreviewModeContents() :
495
+ (viewMode === serverSelection ?
496
+ this.getServerSelectionContent() :
497
+ this.getConfigureMessageContent()
498
+ )
499
+ );
500
+ }
501
+ }
502
+
503
+ FTP.propTypes = {
504
+ actions: PropTypes.object.isRequired,
505
+ FTP: PropTypes.object,
506
+ intl: intlShape.isRequired,
507
+ globalActions: PropTypes.object,
508
+ onFTPSubmit: PropTypes.func,
509
+ messageDetails: PropTypes.object,
510
+ mode: PropTypes.string,
511
+ contents: PropTypes.array,
512
+ metaEntities: PropTypes.object,
513
+ selectedOfferDetails: PropTypes.array,
514
+ };
515
+
516
+
517
+ function mapDispatchToProps(dispatch) {
518
+ return {
519
+ actions: bindActionCreators(actions, dispatch),
520
+ globalActions: bindActionCreators(globalActions, dispatch),
521
+ };
522
+ }
523
+
524
+ const mapStateToProps = createStructuredSelector({
525
+ FTP: makeSelectFTP(),
526
+ metaEntities: makeSelectMetaEntities(),
527
+ });
528
+
529
+ export default withCreatives({
530
+ WrappedComponent: FTP,
531
+ mapStateToProps,
532
+ mapDispatchToProps,
533
+ suserAuth: true,
534
+ });
@@ -0,0 +1,60 @@
1
+ import { defineMessages } from 'react-intl';
2
+
3
+ export default defineMessages({
4
+ ftpServerDesc: {
5
+ id: 'creatives.containersV2.FTP.ftpServerDesc',
6
+ defaultMessage: 'Select the FTP server to send the message data. To add another FTP location, ',
7
+ },
8
+ ftpServer: {
9
+ id: 'creatives.containersV2.FTP.ftpServer',
10
+ defaultMessage: 'FTP Server',
11
+ },
12
+ configureCsv: {
13
+ id: 'creatives.containersV2.FTP.configureCsv',
14
+ defaultMessage: 'Configure CSV',
15
+ },
16
+ addColumn: {
17
+ id: 'creatives.containersV2.FTP.addColumn',
18
+ defaultMessage: 'Add column',
19
+ },
20
+ selectTag: {
21
+ id: 'creatives.containersV2.FTP.selectTag',
22
+ defaultMessage: 'Select tag',
23
+ },
24
+ done: {
25
+ id: 'creatives.containersV2.FTP.done',
26
+ defaultMessage: 'Done',
27
+ },
28
+ customerID: {
29
+ id: 'creatives.containersV2.FTP.customerID',
30
+ defaultMessage: 'Customer ID',
31
+ },
32
+ change: {
33
+ id: 'creatives.containersV2.FTP.change',
34
+ defaultMessage: 'Change',
35
+ },
36
+ manageFTPSettings: {
37
+ id: 'creatives.containersV2.FTP.manageFTPSettings',
38
+ defaultMessage: 'manage FTP settings',
39
+ },
40
+ addLabel: {
41
+ id: 'creatives.containersV2.FTP.addLabel',
42
+ defaultMessage: 'Add Labels',
43
+ },
44
+ messageHeader: {
45
+ id: 'creatives.containersV2.FTP.messageHeader',
46
+ defaultMessage: 'Message',
47
+ },
48
+ messageContent: {
49
+ id: 'creatives.containersV2.FTP.messageContent',
50
+ defaultMessage: 'Message Content',
51
+ },
52
+ optional: {
53
+ id: 'creatives.containersV2.FTP.optional',
54
+ defaultMessage: '(optional)',
55
+ },
56
+ dataPreview: {
57
+ id: 'creatives.containersV2.FTP.dataPreview',
58
+ defaultMessage: 'Data Preview',
59
+ },
60
+ });
@@ -0,0 +1,32 @@
1
+ import { fromJS } from 'immutable';
2
+ import * as types from './constants';
3
+
4
+ const initialState = fromJS({
5
+ getFTPServersInProgress: false,
6
+ FTPServers: [],
7
+ getFTPServersError: false,
8
+ });
9
+
10
+ function createReducer(state = initialState, action) {
11
+ switch (action.type) {
12
+ case types.GET_FTP_SERVERS_REQUEST:
13
+ return state
14
+ .set('getFTPServersInProgress', true)
15
+ .set('FTPServers', [])
16
+ .set('getFTPServersInProgress', true);
17
+ case types.GET_FTP_SERVERS_SUCCESS:
18
+ return state
19
+ .set('getFTPServersInProgress', false)
20
+ .set('FTPServers', action.data)
21
+ .set('getFTPServersInProgress', false);
22
+ case types.GET_FTP_SERVERS_FAILURE:
23
+ return state
24
+ .set('getFTPServersInProgress', false)
25
+ .set('FTPServers', [])
26
+ .set('getFTPServersInProgress', true);
27
+ default:
28
+ return state;
29
+ }
30
+ }
31
+
32
+ export default createReducer;
@@ -0,0 +1,26 @@
1
+ import { take, cancel, call, put, takeLatest } from 'redux-saga/effects';
2
+ import { LOCATION_CHANGE } from 'react-router-redux';
3
+ import * as Api from '../../services/api';
4
+ import * as types from './constants';
5
+
6
+ // Individual exports for testing
7
+ export function* getFTPServers() {
8
+ try {
9
+ const result = yield call(Api.getFTPServers);
10
+ yield put({ type: types.GET_FTP_SERVERS_SUCCESS, data: result.response });
11
+ } catch (error) {
12
+ yield put({ type: types.GET_FTP_SERVERS_FAILURE, error });
13
+ }
14
+ }
15
+
16
+
17
+ function* watchGetFTPServers() {
18
+ const watcher = yield takeLatest(types.GET_FTP_SERVERS_REQUEST, getFTPServers);
19
+ yield take(LOCATION_CHANGE);
20
+ yield cancel(watcher);
21
+ }
22
+
23
+ // All sagas to be loaded
24
+ export default [
25
+ watchGetFTPServers,
26
+ ];
@@ -0,0 +1,20 @@
1
+ import { createSelector } from 'reselect';
2
+ import { fromJS } from 'immutable';
3
+
4
+ const selectFTPMessageCreateDomain = () => (state) => state.get('FTP') || fromJS({});
5
+ const selectCapDomain = (state) => state.get('cap');
6
+
7
+ const makeSelectFTP = () => createSelector(
8
+ selectFTPMessageCreateDomain(),
9
+ (substate = fromJS({})) => substate.toJS()
10
+ );
11
+ const makeSelectMetaEntities = () => createSelector(
12
+ selectCapDomain,
13
+ (globalState = fromJS({})) => globalState.get('metaEntities')
14
+ );
15
+
16
+
17
+ export {
18
+ makeSelectFTP,
19
+ makeSelectMetaEntities,
20
+ };