@capillarytech/creatives-library 6.13.3 → 6.13.5

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 (51) hide show
  1. package/app.js +3 -3
  2. package/assets/viber.png +0 -0
  3. package/containers/Templates/index.js +0 -3
  4. package/index.js +8 -1
  5. package/package.json +2 -2
  6. package/reducers.js +2 -0
  7. package/routes.js +7 -1
  8. package/services/api.js +5 -0
  9. package/v2Components/TemplatePreview/_templatePreview.scss +8 -2
  10. package/v2Components/TemplatePreview/index.js +104 -18
  11. package/v2Containers/App/constants.js +1 -1
  12. package/v2Containers/CreativesContainer/SlideBoxContent.js +65 -2
  13. package/v2Containers/CreativesContainer/constants.js +2 -0
  14. package/v2Containers/CreativesContainer/index.js +29 -2
  15. package/v2Containers/Templates/_templates.scss +57 -0
  16. package/v2Containers/Templates/index.js +59 -6
  17. package/v2Containers/TemplatesV2/index.js +9 -1
  18. package/v2Containers/TemplatesV2/messages.js +4 -0
  19. package/v2Containers/Viber/_viber.scss +3 -0
  20. package/v2Containers/Viber/actions.js +74 -0
  21. package/v2Containers/Viber/constants.js +30 -0
  22. package/v2Containers/Viber/index.js +707 -0
  23. package/v2Containers/Viber/messages.js +137 -0
  24. package/v2Containers/Viber/reducer.js +84 -0
  25. package/v2Containers/Viber/sagas.js +107 -0
  26. package/v2Containers/Viber/selectors.js +21 -0
  27. package/v2Containers/Line/Create/_lineCreate.scss +0 -64
  28. package/v2Containers/Line/Create/actions.js +0 -94
  29. package/v2Containers/Line/Create/constants.js +0 -43
  30. package/v2Containers/Line/Create/index.js +0 -1112
  31. package/v2Containers/Line/Create/initialSchema.js +0 -378
  32. package/v2Containers/Line/Create/messages.js +0 -229
  33. package/v2Containers/Line/Create/reducer.js +0 -99
  34. package/v2Containers/Line/Create/sagas.js +0 -113
  35. package/v2Containers/Line/Create/selectors.js +0 -30
  36. package/v2Containers/Line/CreateWrapper/constants.js +0 -2
  37. package/v2Containers/Line/CreateWrapper/index.js +0 -117
  38. package/v2Containers/Line/CreateWrapper/messages.js +0 -55
  39. package/v2Containers/Line/Edit/_lineEdit.scss +0 -23
  40. package/v2Containers/Line/Edit/actions.js +0 -79
  41. package/v2Containers/Line/Edit/constants.js +0 -27
  42. package/v2Containers/Line/Edit/index.js +0 -1051
  43. package/v2Containers/Line/Edit/messages.js +0 -173
  44. package/v2Containers/Line/Edit/reducer.js +0 -83
  45. package/v2Containers/Line/Edit/sagas.js +0 -81
  46. package/v2Containers/Line/Edit/selectors.js +0 -29
  47. package/v2Containers/Line/Edit/tests/actions.test.js +0 -18
  48. package/v2Containers/Line/Edit/tests/index.test.js +0 -10
  49. package/v2Containers/Line/Edit/tests/reducer.test.js +0 -9
  50. package/v2Containers/Line/Edit/tests/sagas.test.js +0 -15
  51. package/v2Containers/Line/Edit/tests/selectors.test.js +0 -10
@@ -1,1112 +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 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
- });