@capillarytech/creatives-library 6.13.2 → 6.13.3

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.
@@ -0,0 +1,1112 @@
1
+ import PropTypes from 'prop-types';
2
+ import React, { Component } from 'react';
3
+ import get from 'lodash/get';
4
+ import set from 'lodash/set';
5
+ import { bindActionCreators } from 'redux';
6
+ import { intlShape } from 'react-intl';
7
+ import { createStructuredSelector } from 'reselect';
8
+ import _ from 'lodash';
9
+ import { CapSpin, CapHeading, CapRow, CapColumn, CapNotification } from '@capillarytech/cap-ui-library';
10
+ import messages from './messages';
11
+ import * as actions from './actions';
12
+ import Gallery from '../../Assets/Gallery';
13
+ import FormBuilder from '../../../v2Components/FormBuilder';
14
+ //import { makeSelectCreate, makeSelectCreateResponse, makeSelectEdit, makeSelectEditResponse, makeSelectTemplateDetailsResponse } from './selectors';
15
+ import {makeSelectCreateLine, makeSelectLine} from './selectors';
16
+ import { makeSelectMetaEntities, setInjectedTags } from '../../Cap/selectors';
17
+ import {getMessageObject} from '../../../utils/messageUtils';
18
+ import { makeSelectTemplates } from '../../Templates/selectors';
19
+ import './_lineCreate.scss';
20
+ import withCreatives from '../../../hoc/withCreatives';
21
+ import {
22
+ LINE_IMG_HEIGHT,
23
+ LINE_IMG_WIDTH,
24
+ LINE_IMG_SIZE,
25
+ } from './constants';
26
+
27
+ export class Line extends Component {
28
+ constructor(props) {
29
+ super(props);
30
+ const map = {
31
+ 'save-button': {
32
+ saveFormData: this.saveFormData,
33
+ },
34
+ 'template-name': {
35
+ onChange: this.onTemplateNameChange,
36
+ },
37
+ 'discard-button': {
38
+ discardValues: this.discardValues,
39
+ },
40
+ 'message-editor': {
41
+ onChange: this.onTemplateContentChange,
42
+ },
43
+ 'message-editor2': {
44
+ onChange: this.onTemplateContentChange,
45
+ },
46
+ 'message-tagList': {
47
+ onTagSelect: this.onTagSelect,
48
+ },
49
+ 'title-tagList': {
50
+ onTagSelect: this.onTagSelectTitle,
51
+ },
52
+ 'pane': {
53
+ onTabChange: this.onTabChange,
54
+ },
55
+ 'line-template': {
56
+ onSelect: this.onTemplateChange,
57
+ },
58
+ 'image-upload-line': {
59
+ onUpload: this.uploadImage,
60
+ },
61
+ 'tagList': {
62
+ onTagSelect: this.onTagSelect,
63
+ },
64
+ 'line-editor': {
65
+ onChange: this.onTemplateContentChange,
66
+ },
67
+ };
68
+
69
+ this.state = {
70
+ schema: {},
71
+ isSchemaChanged: false,
72
+ formData: {},
73
+ tabCount: 1,
74
+ currentTab: 1,
75
+ loading: false,
76
+ isFormValid: true,
77
+ tabKey: '',
78
+ checkValidation: false,
79
+ eventsMap: map,
80
+ errorData: {},
81
+ displayProps: {},
82
+ modalContent: {
83
+ title: this.props.intl.formatMessage(messages.alertMessage),
84
+ body: this.props.intl.formatMessage(
85
+ messages.templateNotConfigured
86
+ ),
87
+ type: 'confirm',
88
+ },
89
+ injectedTags: {},
90
+ isEdit: false,
91
+ isEdited: false,
92
+ editTemplateData: {},
93
+ isReady: false,
94
+ modeType: null,
95
+ isDrawerRequired: false,
96
+ startValidation: false,
97
+ };
98
+ }
99
+
100
+ componentWillMount() {
101
+ if (this.props.params.id) {
102
+ const editTemplateId = this.props.params.id;
103
+ this.props.actions.getTemplateDetails(editTemplateId, 'LINE');
104
+ this.setState({ isEdit: true });
105
+ }
106
+ }
107
+
108
+ componentDidMount() {
109
+ const getSchemaQuery = {
110
+ layout: 'LINE',
111
+ type: 'LAYOUT',
112
+ version: 'v2',
113
+ };
114
+ this.props.globalActions.fetchSchemaForEntity(getSchemaQuery);
115
+ }
116
+
117
+ componentWillReceiveProps(nextProps) {
118
+ //// Create template logic ////
119
+
120
+ let modeType;
121
+ const { layouts, tags } = nextProps.metaEntities;
122
+ const isSchemaReady = layouts !== undefined && layouts.length > 0;
123
+ const editModeType = nextProps.route.name;
124
+ if (
125
+ nextProps.params.mode === 'text' ||
126
+ nextProps.route.name === 'edit_text'
127
+ ) {
128
+ modeType = 'text';
129
+ } else {
130
+ modeType = 'image';
131
+ }
132
+ if (modeType) {
133
+ this.setState({ modeType, schema: {} });
134
+ }
135
+ const {
136
+ isGetFormData,
137
+ templateData,
138
+ } = nextProps;
139
+ if (isGetFormData) {
140
+ const {
141
+ lineData,
142
+ getFormSubscriptionData,
143
+ } = nextProps;
144
+ let selectedAccount = {};
145
+ if (lineData) {
146
+ const {
147
+ weCrmAccounts = [],
148
+ } = lineData;
149
+ selectedAccount = weCrmAccounts.filter((account) => account === selectedAccount);
150
+ }
151
+ getFormSubscriptionData({ ...this.getFormData(), accountDetails: selectedAccount, type: 'LINE' });
152
+ }
153
+ if (templateData && templateData.edit) {
154
+ this.setEditState(templateData);
155
+ }
156
+ if (isSchemaReady) {
157
+ // set schema value as per mode type. Supported mode (text & image)
158
+ const { textSchema, imageSchema } = this.updateSchemaWithLabels(
159
+ layouts[0].definition
160
+ );
161
+ const schema =
162
+ modeType === 'text' || editModeType === 'edit_text'
163
+ ? textSchema
164
+ : imageSchema;
165
+ this.setState({ schema }, () => {
166
+ // Once schema is ready and set, then inject the available events from the schema
167
+ if (!_.isEmpty(this.state.schema)) {
168
+ this.injectEvents(this.state.schema);
169
+ }
170
+ // Once schema is ready, then only get the tags.
171
+ const getTagsQuery = {
172
+ layout: 'LINE',
173
+ type: 'TAG',
174
+ context:
175
+ this.props.location.query.type === 'embedded'
176
+ ? 'outbound'
177
+ : 'default',
178
+ embedded:
179
+ this.props.location.query.type === 'embedded'
180
+ ? this.props.location.query.type
181
+ : 'full',
182
+ };
183
+ if (this.props.getDefaultTags) {
184
+ getTagsQuery.context = this.props.getDefaultTags;
185
+ }
186
+ if (!Object.keys(tags || {}).length && modeType !== 'image') {
187
+ this.props.globalActions.fetchSchemaForEntity(getTagsQuery);
188
+ } else {
189
+ this.setState({ isReady: true });
190
+ }
191
+ });
192
+ }
193
+
194
+ const lineTemplateId = get(nextProps, 'Line.response.templateId', '');
195
+ if (lineTemplateId) {
196
+ this.discardValues();
197
+ const message = getMessageObject(
198
+ 'success',
199
+ this.props.intl.formatMessage(
200
+ messages.lineTemplateCreatedSuccessfully
201
+ ),
202
+ true
203
+ );
204
+ this.props.globalActions.addMessageToQueue(message);
205
+ this.props.actions.clearCreateResponse();
206
+ }
207
+
208
+ if (
209
+ nextProps.Line.createTemplateError &&
210
+ !_.isEqual(
211
+ nextProps.Line.createTemplateError,
212
+ this.props.Line.createTemplateError
213
+ )
214
+ ) {
215
+ const {
216
+ Line: {
217
+ createTemplateErrorMessage,
218
+ },
219
+ } = nextProps;
220
+ const message = getMessageObject(
221
+ 'error',
222
+ createTemplateErrorMessage || this.props.intl.formatMessage(messages.somethingWentWrong),
223
+ true
224
+ );
225
+ this.props.globalActions.addMessageToQueue(message);
226
+ }
227
+
228
+ //// Edit Template Logic ////
229
+ const isEdit =
230
+ this.state.isEdit &&
231
+ this.props.params.id &&
232
+ (this.props.route.name === 'edit_text' ||
233
+ this.props.route.name === 'edit_image') &&
234
+ this.props.Line.templateDetails &&
235
+ this.props.Line.templateDetails.versions;
236
+ if (isEdit) {
237
+ const formData = this.getEditTransformedData(
238
+ this.props.Line.templateDetails
239
+ );
240
+ this.setState({
241
+ formData,
242
+ editTemplateData: this.props.Line.templateDetails,
243
+ });
244
+ this.props.actions.clearData();
245
+ }
246
+
247
+ if (
248
+ nextProps.Line.editTemplateError &&
249
+ !_.isEqual(
250
+ nextProps.Line.editTemplateError,
251
+ this.props.Line.editTemplateError
252
+ )
253
+ ) {
254
+ const message = getMessageObject(
255
+ 'error',
256
+ nextProps.Line.editTemplateErrorMessage &&
257
+ nextProps.Line.editTemplateErrorMessage !== ''
258
+ ? nextProps.Line.editTemplateErrorMessage
259
+ : this.props.intl.formatMessage(messages.somethingWentWrong),
260
+ true
261
+ );
262
+ this.props.globalActions.addMessageToQueue(message);
263
+ }
264
+
265
+ if (
266
+ nextProps.Line.uploadAssetSuccess &&
267
+ nextProps.Line.uploadedAssetData
268
+ ) {
269
+ const formData = _.cloneDeep(this.state.formData);
270
+ // TODO: if multiple image upload supports, change below accordingly.
271
+ formData[this.state.currentTab - 1].image =
272
+ nextProps.Line.uploadedAssetData.metaInfo.secure_file_path;
273
+ formData[this.state.currentTab - 1].imagePreview =
274
+ nextProps.Line.uploadedAssetData.metaInfo.secure_file_path_preview;
275
+ this.setState({ formData });
276
+ this.props.actions.clearAsset();
277
+ }
278
+ }
279
+
280
+ setEditSuccessMessage = () => {
281
+ this.setState({ formData: {} });
282
+ const message = getMessageObject(
283
+ 'success',
284
+ this.props.intl.formatMessage(
285
+ messages['Line Template Edited Successfully']
286
+ ),
287
+ true
288
+ );
289
+ this.props.globalActions.addMessageToQueue(message);
290
+ this.props.actions.clearEditResponse();
291
+ }
292
+
293
+ setEditState = (data) => {
294
+ const { formData: previousFormData } = this.state;
295
+ const { text, originalContentUrl, imagePreview, image, previewImageUrl } = get(data, "versions.base.content.messages[0]", {});
296
+ const retrievedData = {
297
+ ...previousFormData[0],
298
+ };
299
+ if (text) {
300
+ retrievedData["message-editor"] = text;
301
+ }
302
+ const lineImage = originalContentUrl || image;
303
+ if (lineImage) {
304
+ retrievedData.image = lineImage;
305
+ retrievedData.imagePreview = imagePreview || previewImageUrl;
306
+ }
307
+ const formData = {
308
+ 0: retrievedData,
309
+ base: retrievedData,
310
+ };
311
+ this.setState({ formData });
312
+ }
313
+
314
+ componentWillUnmount() {
315
+ window.removeEventListener('message', this.handleFrameTasks);
316
+ }
317
+
318
+ onTagSelect(data, currentTab) {
319
+ const editorId = 'message-editor';
320
+ this.insertAtCursor(
321
+ document.getElementById(editorId),
322
+ `{{${data}}}`,
323
+ currentTab
324
+ );
325
+ document.getElementById(editorId).focus();
326
+ }
327
+
328
+ onTagSelectTitle(data, currentTab) {
329
+ const editorId = 'message-title';
330
+ this.insertAtCursor(
331
+ document.getElementById(editorId),
332
+ `{{${data}}}`,
333
+ currentTab
334
+ );
335
+ document.getElementById(editorId).focus();
336
+ }
337
+
338
+ onFormDataChange = (formData, tabCount, currentTab) => {
339
+ this.setState({ formData: { ...formData } });
340
+ if (tabCount) {
341
+ this.setState({ tabCount });
342
+ }
343
+ if (currentTab) {
344
+ this.setState({ currentTab });
345
+ }
346
+ };
347
+
348
+ getTransformedData = (formData) => {
349
+ const modeType = this.state.modeType;
350
+ const obj = {};
351
+ const msgData = {};
352
+ obj.versions = {
353
+ base: {
354
+ content: {
355
+ to: '{{line_id}}',
356
+ messages: [],
357
+ },
358
+ },
359
+ };
360
+ obj.type = 'LINE';
361
+ obj.name = formData['template-name'];
362
+ obj.definition = {
363
+ mode: modeType,
364
+ };
365
+ if (modeType && modeType !== undefined) {
366
+ msgData.type = modeType;
367
+ }
368
+ if (modeType === 'text') {
369
+ if (this.state.isEdit) {
370
+ const editTemplateId = this.state.editTemplateData._id;
371
+ if (editTemplateId && editTemplateId !== undefined) {
372
+ obj._id = this.state.editTemplateData._id;
373
+ msgData.text = formData['0']['message-editor'];
374
+ }
375
+ } else {
376
+ msgData.text = formData.base['message-editor'];
377
+ }
378
+ } else if (modeType === 'image') {
379
+ const formImage = formData['0'].image;
380
+ if (formImage && formImage.length < 1) {
381
+ return 'IMAGE_ERROR';
382
+ }
383
+ if (this.state.isEdit) {
384
+ const editTemplateId = this.state.editTemplateData._id;
385
+ if (editTemplateId && editTemplateId !== undefined) {
386
+ obj._id = editTemplateId;
387
+ msgData.originalContentUrl = formData['0'].image;
388
+ msgData.previewImageUrl = formData['0'].imagePreview;
389
+ }
390
+ } else {
391
+ msgData.originalContentUrl = formData['0'].image;
392
+ msgData.previewImageUrl = formData['0'].imagePreview;
393
+ }
394
+ }
395
+ obj.versions.base.content.messages.push(msgData);
396
+ return obj;
397
+ };
398
+
399
+ getEditTransformedData = ({ name, versions }) => {
400
+ const modeType = this.state.modeType;
401
+ const obj = {};
402
+ obj['0'] = {};
403
+ obj.base = {
404
+ base: true,
405
+ };
406
+ obj['template-name'] = name;
407
+ if (modeType === 'text') {
408
+ obj.base['message-editor'] =
409
+ versions.base.content.messages[0].text;
410
+ obj['0']['message-editor'] =
411
+ versions.base.content.messages[0].text;
412
+ } else if (modeType === 'image') {
413
+ const {
414
+ base: {
415
+ content: {
416
+ messages: [{
417
+ originalContentUrl,
418
+ previewImageUrl,
419
+ }],
420
+ },
421
+ },
422
+ } = versions;
423
+ obj.base.image = originalContentUrl;
424
+ obj['0'].image = originalContentUrl;
425
+ obj['0'].imagePreview = previewImageUrl;
426
+ obj.base.imagePreview = previewImageUrl;
427
+ }
428
+ return obj;
429
+ };
430
+
431
+ setFormValidity = (isFormValid) => {
432
+ this.setState({ isFormValid });
433
+ };
434
+
435
+ getMappedEvent = (id, event) => {
436
+ const map = this.state.eventsMap;
437
+ return map[id][event];
438
+ };
439
+
440
+ getCurrentWindow(e) {
441
+ const response = {
442
+ action: e.action,
443
+ value: 'edit',
444
+ direction: e.value,
445
+ };
446
+ parent.postMessage(JSON.stringify(response), '*');
447
+ }
448
+
449
+ getFormData = (e) => {
450
+ const response = {
451
+ action: 'getFormData',
452
+ value: this.getTransformedData(this.state.formData),
453
+ validity: this.state.isFormValid,
454
+ };
455
+ this.setState({ checkValidation: true });
456
+ if (e) {
457
+ e.source.postMessage(JSON.stringify(response), e.origin);
458
+ }
459
+ return response;
460
+ };
461
+
462
+ injectEvents = (schema) => {
463
+ const temp = schema;
464
+ if (temp.standalone) {
465
+ temp.standalone.sections = this.injectSections(
466
+ temp.standalone.sections
467
+ );
468
+ }
469
+ _.forEach(temp.containers, (container) => {
470
+ let tempContainer = container;
471
+ tempContainer = this.injectContainer(tempContainer);
472
+ return tempContainer;
473
+ });
474
+ this.setState({ schema, isSchemaChanged: true }, () => {
475
+ this.removeStandAlone();
476
+ });
477
+ return schema;
478
+ };
479
+
480
+ saveFormData = () => {
481
+ const obj = this.getTransformedData(this.state.formData);
482
+ if (obj === 'IMAGE_ERROR') {
483
+ const message = getMessageObject(
484
+ 'error',
485
+ this.props.intl.formatMessage(
486
+ messages['Please upload an image to proceed']
487
+ ),
488
+ true
489
+ );
490
+ this.props.globalActions.addMessageToQueue(message);
491
+ return;
492
+ }
493
+ if (
494
+ obj !== 'IMAGE_ERROR' &&
495
+ obj.versions.base.content.messages[0].type === 'text'
496
+ ) {
497
+ const text = obj.versions.base.content.messages[0].text;
498
+ const charCount = text ? text.length : 0;
499
+ if (charCount > 1600) {
500
+ const message = getMessageObject(
501
+ 'error',
502
+ this.props.intl.formatMessage(
503
+ messages['Maximum characters length exceeds']
504
+ ),
505
+ true
506
+ );
507
+ this.props.globalActions.addMessageToQueue(message);
508
+ return;
509
+ }
510
+ }
511
+ if (!this.state.startValidation) {
512
+ this.setState({
513
+ startValidation: true,
514
+ });
515
+ } else {
516
+ const {
517
+ isFullMode,
518
+ saveMessage,
519
+ actions,
520
+ onCreateComplete,
521
+ } = this.props;
522
+ const { text, originalContentUrl, image } = get(obj, "versions.base.content.messages[0]", {});
523
+ const { name } = obj || {};
524
+ if ((text || originalContentUrl || image) && (isFullMode ? name : true)) {
525
+ if (!isFullMode) {
526
+ saveMessage();
527
+ } else if (this.state.isEdit) {
528
+ actions.editTemplate(obj, () => {
529
+ this.setEditSuccessMessage();
530
+ onCreateComplete();
531
+ });
532
+ } else {
533
+ actions.createTemplate(
534
+ obj,
535
+ onCreateComplete
536
+ );
537
+ }
538
+ }
539
+ }
540
+ };
541
+
542
+ injectSections = (sections) => {
543
+ _.forEach(sections, (section) => {
544
+ let temp = section;
545
+ if (temp.type === 'col-label') {
546
+ temp = this.injectColLabelSection(temp);
547
+ } else if (section.type === 'multicols') {
548
+ temp = this.injectMultiColSection(temp);
549
+ } else if (section.type === 'parent') {
550
+ temp = this.injectSections(temp.childSections);
551
+ }
552
+ });
553
+ return sections;
554
+ };
555
+
556
+ injectMultiColSection = (section) => {
557
+ _.forEach(section.inputFields, (inputField) => {
558
+ _.forEach(inputField.cols, (col) => {
559
+ const temp = col;
560
+ if (temp.type === 'popover') {
561
+ temp.content.sections = this.injectSections(
562
+ temp.content.sections
563
+ );
564
+ temp.value.sections = this.injectSections(temp.value.sections);
565
+ return true;
566
+ }
567
+ if (temp.id === 'discard-button') {
568
+ temp.colStyle = { ...temp.colStyle, display: 'none' };
569
+ }
570
+ if (temp.id === 'cancel-button') {
571
+ temp.offset = 11;
572
+ }
573
+ if (temp.id === 'line-push-preview') {
574
+ temp.content.appName = this.props.Templates.selectedWeChatAccount.name;
575
+ }
576
+ temp.injectedEvents = {};
577
+
578
+ _.forEach(col.supportedEvents, (event) => {
579
+ temp.injectedEvents[event] = this.getMappedEvent(
580
+ col.id,
581
+ event
582
+ );
583
+ });
584
+ return true;
585
+ });
586
+ });
587
+ _.forEach(section.actionFields, (actionField) => {
588
+ _.forEach(actionField.cols, (col) => {
589
+ const temp = col;
590
+ if (temp.type === 'popover') {
591
+ temp.content.sections = this.injectSections(
592
+ temp.content.sections
593
+ );
594
+ temp.value.sections = this.injectSections(temp.value.sections);
595
+ return true;
596
+ }
597
+ temp.injectedEvents = {};
598
+ _.forEach(col.supportedEvents, (event) => {
599
+ temp.injectedEvents[event] = this.getMappedEvent(
600
+ col.id,
601
+ event
602
+ );
603
+ });
604
+ return true;
605
+ });
606
+ });
607
+ return section;
608
+ };
609
+
610
+ injectColLabelSection = (section) => {
611
+ _.forEach(section.inputFields, (inputField) => {
612
+ const temp = inputField;
613
+ if (temp.type === 'popover') {
614
+ temp.content.sections = this.injectSections(
615
+ temp.content.sections
616
+ );
617
+ temp.value.sections = this.injectSections(temp.value.sections);
618
+ return true;
619
+ }
620
+ temp.injectedEvents = {};
621
+ _.forEach(inputField.supportedEvents, (event) => {
622
+ temp.injectedEvents[event] = this.getMappedEvent(
623
+ inputField.id,
624
+ event
625
+ );
626
+ });
627
+ return true;
628
+ });
629
+ _.forEach(section.actionFields, (actionField) => {
630
+ const temp = actionField;
631
+ if (temp.type === 'popover') {
632
+ temp.content.sections = this.injectSections(
633
+ temp.content.sections
634
+ );
635
+ temp.value.sections = this.injectSections(temp.value.sections);
636
+ return true;
637
+ }
638
+ temp.injectedEvents = {};
639
+ _.forEach(actionField.supportedEvents, (event) => {
640
+ temp.injectedEvents[event] = this.getMappedEvent(
641
+ actionField.id,
642
+ event
643
+ );
644
+ });
645
+ return true;
646
+ });
647
+ return section;
648
+ };
649
+
650
+ injectParentSection = (section) => {
651
+ _.forEach(section.childSections, (childSection) => {
652
+ let temp = childSection;
653
+ if (temp.type === 'col-label') {
654
+ temp = this.injectColLabelSection(temp);
655
+ } else if (section.type === 'multicols') {
656
+ temp = this.injectMultiColSection(temp);
657
+ } else if (section.type === 'parent') {
658
+ temp = this.injectParentSection(temp);
659
+ }
660
+ });
661
+ return section;
662
+ };
663
+
664
+ insertAtCursor = (field, myValue, currentTab) => {
665
+ //IE support
666
+ const myField = field;
667
+ if (document.selection) {
668
+ myField.focus();
669
+ const sel = document.selection.createRange();
670
+ sel.text = myValue;
671
+ } else if (
672
+ myField.selectionStart ||
673
+ myField.selectionStart === '0'
674
+ ) {
675
+ //MOZILLA and others
676
+ const startPos = myField.selectionStart;
677
+ const endPos = myField.selectionEnd;
678
+ myField.value =
679
+ myField.value.substring(0, startPos) +
680
+ myValue +
681
+ myField.value.substring(endPos, myField.value.length);
682
+ myField.selectionStart = startPos + myValue.length;
683
+ myField.selectionEnd = startPos + myValue.length;
684
+ } else {
685
+ myField.value += myValue;
686
+ }
687
+ const formData = _.cloneDeep(this.state.formData);
688
+ formData[currentTab - 1][field.id] = myField.value;
689
+ this.setState({ formData });
690
+ };
691
+
692
+ startTemplateCreation = (data) => {
693
+ const getSchemaQuery = {
694
+ layout: 'LINE',
695
+ type: 'LAYOUT',
696
+ };
697
+ this.props.globalActions.fetchSchemaForEntity(getSchemaQuery);
698
+ const content = data.content;
699
+ const obj = {};
700
+ obj['0'] = {};
701
+ obj.base = {
702
+ base: true,
703
+ };
704
+ if (data.type === 'text') {
705
+ obj.base['message-editor'] = content;
706
+ obj['0']['message-editor'] = content;
707
+ } else {
708
+ obj.base.image = content;
709
+ obj['0'].image = content;
710
+ }
711
+ this.setState({
712
+ formData: obj,
713
+ loading: false,
714
+ injectedTags: data.tags,
715
+ });
716
+ this.props.globalActions.setInjectedTags(data.tags);
717
+ };
718
+
719
+ startLoading = (ifEdit) => {
720
+ if (ifEdit) {
721
+ this.setState({ loading: true });
722
+ }
723
+ };
724
+
725
+ injectContainer = (container) => {
726
+ const temp = container;
727
+ if (temp.type === 'tabs') {
728
+ temp.injectedEvents = {};
729
+ _.forEach(temp.supportedEvents, (event) => {
730
+ temp.injectedEvents[event] = this.getMappedEvent(temp.id, event);
731
+ });
732
+ _.forEach(temp.panes, (pane) => {
733
+ const tempPane = pane;
734
+ tempPane.sectionsHeaders = this.injectSections(
735
+ tempPane.sectionsHeaders
736
+ );
737
+ tempPane.sections = this.injectSections(tempPane.sections);
738
+ });
739
+ }
740
+ return temp;
741
+ };
742
+
743
+ resetSchema = () => {
744
+ this.setState({
745
+ schema: this.state.initialState
746
+ ? this.state.initialState
747
+ : this.state.schema,
748
+ });
749
+ };
750
+
751
+ resetState = () => {
752
+ this.setState({
753
+ formData: {},
754
+ tabCount: 1,
755
+ currentTab: 1,
756
+ });
757
+ };
758
+
759
+ discardValues = () => {
760
+ this.resetSchema();
761
+ this.resetState();
762
+ };
763
+
764
+ moveToTemplates() {
765
+ const modalContent = {
766
+ title: this.props.intl.formatMessage(messages.alertMessage),
767
+ body: this.props.intl.formatMessage(messages.goBackTemporaryLost),
768
+ type: 'confirm',
769
+ id: 'template-back-confirm-modal',
770
+ show: true,
771
+ };
772
+ this.setState({ modalContent, showModal: true });
773
+ }
774
+
775
+ showNext() {
776
+ const response = {
777
+ action: 'showNext',
778
+ value: true,
779
+ };
780
+ parent.postMessage(JSON.stringify(response), '*');
781
+ }
782
+
783
+ discardValues = () => {
784
+ this.resetSchema();
785
+ this.resetState();
786
+ };
787
+
788
+ handleFrameTasks = (e) => {
789
+ const type = e.data;
790
+ if (typeof type === 'object') {
791
+ const action = type.action;
792
+ switch (action) {
793
+ case 'startTemplateCreation':
794
+ this.startTemplateCreation(type.value);
795
+ break;
796
+ case 'startLoading':
797
+ this.startLoading(type.edit);
798
+ break;
799
+ case 'getCurrentWindow':
800
+ this.getCurrentWindow(type);
801
+ break;
802
+ default:
803
+ break;
804
+ }
805
+ } else {
806
+ switch (type) {
807
+ case 'getFormData':
808
+ this.getFormData(e);
809
+ break;
810
+ case 'startTemplateCreation':
811
+ //this.getFormData(e);
812
+ break;
813
+ case 'moveToTemplates':
814
+ this.moveToTemplates();
815
+ break;
816
+ case 'validateContent':
817
+ this.validateContent(e);
818
+ break;
819
+ default:
820
+ break;
821
+ }
822
+ }
823
+ };
824
+
825
+ removeStandAlone = () => {
826
+ const schema = _.cloneDeep(this.state.schema);
827
+ const {
828
+ location: {
829
+ query: {
830
+ type,
831
+ mode,
832
+ module,
833
+ },
834
+ },
835
+ } = this.props;
836
+ if (type === 'embedded' && module === 'loyalty') {
837
+ schema.standalone.sections.splice(0, 1);
838
+ } else if (type === 'embedded' && typeof mode !== 'undefined') {
839
+ delete schema.standalone;
840
+ } else if (!this.props.isFullMode) {
841
+ const childSections = get(schema, 'standalone.sections[0].childSections');
842
+ const fields = get(childSections, '[1].childSections[0].childSections');//removing template name section
843
+ fields.splice(0, 1);
844
+ set(childSections, '[1].childSections[0].childSections', fields);
845
+ } else {
846
+ schema.standalone.sections.splice(1, 1);
847
+ }
848
+ this.setState({ schema });
849
+ };
850
+
851
+ validateContent = (e) => {
852
+ const response = {
853
+ action: 'validateContent',
854
+ value: this.state.isFormValid,
855
+ };
856
+ e.source.postMessage(JSON.stringify(response), e.origin);
857
+ };
858
+
859
+ handleOnTagsContextChange = (data) => {
860
+ const query = {
861
+ layout: 'LINE',
862
+ type: 'TAG',
863
+ context:
864
+ data.toLowerCase() === 'all' ? 'default' : data.toLowerCase(),
865
+ embedded:
866
+ this.props.location.query.type === 'embedded'
867
+ ? this.props.location.query.type
868
+ : 'full',
869
+ };
870
+ this.props.globalActions.fetchSchemaForEntity(query);
871
+ };
872
+
873
+ uploadImage = (pearmData) => {
874
+ const data = pearmData;
875
+ const {
876
+ file: {
877
+ size,
878
+ },
879
+ fileParams: {
880
+ height,
881
+ width,
882
+ },
883
+ type,
884
+ } = pearmData;
885
+ if (type === "wrong file" || size > LINE_IMG_SIZE || height > LINE_IMG_HEIGHT || width > LINE_IMG_WIDTH) {
886
+ CapNotification.error({
887
+ message: this.props.intl.formatMessage(
888
+ messages.lineImageIncorrectSize
889
+ ),
890
+ });
891
+ } else {
892
+ data.fileParams.isGeneratePreview = true;
893
+ this.props.actions.uploadAsset(
894
+ data.file,
895
+ data.type,
896
+ data.fileParams,
897
+ );
898
+ }
899
+ };
900
+
901
+ onGalleryImageSelect = (imageTemplate) => {
902
+ const { formData } = this.state;
903
+ const image = get(imageTemplate, 'metaInfo.secure_file_path');
904
+ const imagePreview = get(imageTemplate, 'metaInfo.secure_file_path_preview');
905
+ this.setState({
906
+ isDrawerRequired: false,
907
+ formData: {
908
+ ...formData,
909
+ 0: {
910
+ ...formData[0],
911
+ image,
912
+ imagePreview,
913
+ },
914
+ base: {
915
+ ...formData.base,
916
+ image,
917
+ imagePreview,
918
+ },
919
+ },
920
+ });
921
+ }
922
+
923
+ getGalleryDrawerContent = () => {
924
+ const location = {
925
+ pathname: `/assets`,
926
+ search: '',
927
+ query: !this.props.isFullMode ? {type: 'embedded', module: 'library'} : {},
928
+ };
929
+ const content = (
930
+ <Gallery
931
+ location={location}
932
+ isFullMode={this.props.isFullMode}
933
+ isLineAsset
934
+ onGalleryImageSelect={this.onGalleryImageSelect}
935
+ />);
936
+ return (
937
+ <>
938
+ <CapHeading type="h3">
939
+ {this.props.intl.formatMessage(messages.imageGallery)}
940
+ </CapHeading>
941
+ {content}
942
+ </>
943
+ );
944
+ };
945
+
946
+ updateSchemaWithLabels = (schema) => {
947
+ /* eslint-disable no-param-reassign */
948
+ schema.textSchema.standalone.sections[0].childSections[1].childSections[0].childSections[0].inputFields[0].cols[0].placeholder = this.props.intl.formatMessage(
949
+ messages.templatePlaceholder
950
+ );
951
+ schema.textSchema.standalone.sections[0].childSections[1].childSections[0].childSections[0].inputFields[0].cols[0].errorMessage = this.props.intl.formatMessage(
952
+ messages.templateNameErrorPlaceholder
953
+ );
954
+ schema.textSchema.standalone.sections[0].childSections[1].childSections[0].childSections[1].inputFields[0].cols[0].label = this.props.intl.formatMessage(
955
+ messages.templateAddTag
956
+ );
957
+ schema.textSchema.standalone.sections[0].childSections[1].childSections[0].childSections[2].inputFields[0].cols[0].placeholder = this.props.intl.formatMessage(
958
+ messages.templateMessagePlaceholder
959
+ );
960
+ schema.textSchema.standalone.sections[0].childSections[1].childSections[0].childSections[2].inputFields[0].cols[0].errorMessage = this.props.intl.formatMessage(
961
+ messages.templateMessageError
962
+ );
963
+ schema.imageSchema.standalone.sections[0].childSections[1].childSections[0].childSections[0].inputFields[0].cols[0].placeholder = this.props.intl.formatMessage(
964
+ messages.templatePlaceholder
965
+ );
966
+ schema.imageSchema.standalone.sections[0].childSections[1].childSections[0].childSections[0].inputFields[0].cols[0].errorMessage = this.props.intl.formatMessage(
967
+ messages.templateNameErrorPlaceholder
968
+ );
969
+ schema.imageSchema.standalone.sections[0].childSections[1].childSections[0].childSections[1].inputFields[0].cols[0].previewProps.label = this.props.intl.formatMessage(
970
+ messages.templateMessagePreviewPropsLabel
971
+ );
972
+ schema.imageSchema.standalone.sections[0].childSections[1].childSections[0].childSections[1].inputFields[0].cols[0].previewProps.inductiveText = this.props.intl.formatMessage(
973
+ messages.templateMessagePreviewPropsInductiveText
974
+ );
975
+ schema.imageSchema.standalone.sections[0].childSections[1].childSections[0].childSections[1].inputFields[0].cols[0].previewProps.errorMessage = this.props.intl.formatMessage(
976
+ messages.templateMessagePreviewPropsError
977
+ );
978
+ return schema;
979
+ };
980
+
981
+ stopValidation = () => {
982
+ this.setState({
983
+ startValidation: false,
984
+ })
985
+ }
986
+
987
+ render() {
988
+ const {
989
+ Line: {
990
+ createTemplateInProgress,
991
+ assetUploading,
992
+ } = {},
993
+ templateData,
994
+ params: {
995
+ id,
996
+ } = {},
997
+ isFullMode,
998
+ } = this.props;
999
+ const {
1000
+ edit,
1001
+ mode,
1002
+ orgId,
1003
+ isDefault,
1004
+ } = templateData || {};
1005
+ let loading = createTemplateInProgress || false;
1006
+ loading = !!assetUploading;
1007
+ if (!isDefault && (edit || mode === 'edit' || (orgId && id))) {
1008
+ const {
1009
+ base: {
1010
+ 'message-editor': msgEditor,
1011
+ image: uploadedAsset,
1012
+ } = {},
1013
+ reUpload,
1014
+ } = this.state.formData;
1015
+ loading = typeof reUpload === 'undefined' ? !(msgEditor || uploadedAsset) : !reUpload;
1016
+ if (templateData && !isFullMode) {
1017
+ const { text, originalContentUrl } = get(templateData, "versions.base.content.messages[0]", {});
1018
+ loading = !(text || originalContentUrl);
1019
+ }
1020
+ }
1021
+ let tags =
1022
+ this.props.metaEntities && this.props.metaEntities.tags
1023
+ ? this.props.metaEntities.tags.standard
1024
+ : [];
1025
+ if (this.props.supportedTags) {
1026
+ tags = this.props.supportedTags;
1027
+ }
1028
+ return (
1029
+ <CapSpin spinning={loading}>
1030
+ <CapRow>
1031
+ <CapColumn>
1032
+ <FormBuilder
1033
+ key={'form builder'}
1034
+ schema={this.state.schema}
1035
+ onSubmit={this.saveFormData}
1036
+ onChange={this.onFormDataChange}
1037
+ currentTab={this.state.currentTab}
1038
+ parent={this}
1039
+ formData={_.cloneDeep(this.state.formData)}
1040
+ location={this.props.location}
1041
+ tags={tags}
1042
+ injectedTags={
1043
+ this.props.injectedTags ? this.props.injectedTags : {}
1044
+ }
1045
+ onFormValidityChange={this.setFormValidity}
1046
+ usingTabContainer
1047
+ checkValidation={this.state.checkValidation}
1048
+ tabKey={this.state.tabKey}
1049
+ tabCount={2}
1050
+ showModal={this.state.showModal}
1051
+ isSchemaChanged={this.state.isSchemaChanged}
1052
+ modal={this.state.modalContent}
1053
+ handleCancelModal={this.handleCancelModal}
1054
+ iframeParent={parent}
1055
+ router={this.props.router}
1056
+ onContextChange={this.handleOnTagsContextChange}
1057
+ setModalContent={this.setModalContent}
1058
+ capDrawerContent={this.getGalleryDrawerContent()}
1059
+ isDrawerRequired={this.state.isDrawerRequired}
1060
+ setDrawerVisibility={(drawervisibleFlag) =>
1061
+ this.setState({ isDrawerRequired: drawervisibleFlag })
1062
+ }
1063
+ startValidation={this.state.startValidation}
1064
+ stopValidation={this.stopValidation}
1065
+ />
1066
+ </CapColumn>
1067
+ </CapRow>
1068
+ </CapSpin>
1069
+ );
1070
+ }
1071
+ }
1072
+
1073
+ Line.propTypes = {
1074
+ actions: PropTypes.object.isRequired,
1075
+ globalActions: PropTypes.object,
1076
+ Templates: PropTypes.object,
1077
+ location: PropTypes.object,
1078
+ router: PropTypes.object,
1079
+ params: PropTypes.object,
1080
+ metaEntities: PropTypes.object,
1081
+ intl: intlShape.isRequired,
1082
+ route: PropTypes.object,
1083
+ Line: PropTypes.object,
1084
+ supportedTags: PropTypes.any,
1085
+ getDefaultTags: PropTypes.string,
1086
+ injectedTags: PropTypes.object,
1087
+ onCreateComplete: PropTypes.func,
1088
+ isFullMode: PropTypes.bool,
1089
+ saveMessage: PropTypes.func,
1090
+ templateData: PropTypes.object,
1091
+ };
1092
+
1093
+ const mapStateToProps = createStructuredSelector({
1094
+ Line: makeSelectCreateLine(),
1095
+ lineData: makeSelectLine(),
1096
+ Templates: makeSelectTemplates(),
1097
+ metaEntities: makeSelectMetaEntities(),
1098
+ injectedTags: setInjectedTags(),
1099
+ });
1100
+
1101
+ function mapDispatchToProps(dispatch) {
1102
+ return {
1103
+ actions: bindActionCreators(actions, dispatch),
1104
+ };
1105
+ }
1106
+
1107
+ export default withCreatives({
1108
+ WrappedComponent: Line,
1109
+ mapStateToProps,
1110
+ mapDispatchToProps,
1111
+ userAuth: true,
1112
+ });