@capillarytech/creatives-library 7.9.0 → 7.9.2

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