@capillarytech/creatives-library 0.1.26 → 0.1.28

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 (34) hide show
  1. package/components/CardGrid/index.js +1 -1
  2. package/components/FormBuilder/index.js +72 -0
  3. package/components/PreviewSideBar/index.js +10 -1
  4. package/components/TemplatePreview/index.js +16 -1
  5. package/containers/Cap/index.js +5 -1
  6. package/containers/Email/index.js +12 -2
  7. package/containers/Email/reducer.js +1 -1
  8. package/containers/Line/Create/_lineCreate.scss +37 -0
  9. package/containers/Line/Create/actions.js +90 -0
  10. package/containers/Line/Create/constants.js +39 -0
  11. package/containers/Line/Create/index.js +810 -0
  12. package/containers/Line/Create/messages.js +173 -0
  13. package/containers/Line/Create/reducer.js +99 -0
  14. package/containers/Line/Create/sagas.js +108 -0
  15. package/containers/Line/Create/selectors.js +36 -0
  16. package/containers/Line/Edit/_lineEdit.scss +25 -0
  17. package/containers/Line/Edit/actions.js +72 -0
  18. package/containers/Line/Edit/constants.js +27 -0
  19. package/containers/Line/Edit/index.js +1043 -0
  20. package/containers/Line/Edit/messages.js +157 -0
  21. package/containers/Line/Edit/reducer.js +83 -0
  22. package/containers/Line/Edit/sagas.js +81 -0
  23. package/containers/Line/Edit/selectors.js +29 -0
  24. package/containers/Line/Edit/tests/actions.test.js +18 -0
  25. package/containers/Line/Edit/tests/index.test.js +10 -0
  26. package/containers/Line/Edit/tests/reducer.test.js +9 -0
  27. package/containers/Line/Edit/tests/sagas.test.js +15 -0
  28. package/containers/Line/Edit/tests/selectors.test.js +10 -0
  29. package/containers/MobilePush/Create/index.js +0 -1
  30. package/containers/Templates/index.js +105 -22
  31. package/containers/Templates/messages.js +4 -0
  32. package/package.json +1 -1
  33. package/routes.js +110 -0
  34. package/services/api.js +8 -0
@@ -0,0 +1,810 @@
1
+ import React, { PropTypes, Component } from 'react';
2
+ import {connect} from 'react-redux';
3
+ import { bindActionCreators } from 'redux';
4
+ import { injectIntl, intlShape } from 'react-intl';
5
+ import { createStructuredSelector } from 'reselect';
6
+ import { Row, Col, Spin, Breadcrumb } from 'antd';
7
+ import _ from 'lodash';
8
+ import messages from './messages';
9
+ import * as actions from './actions';
10
+ import FormBuilder from '../../../components/FormBuilder';
11
+ import { UserIsAuthenticated } from '../../../utils/authWrapper';
12
+ import * as globalActions from '../../../containers/Cap/actions';
13
+ //import { makeSelectCreate, makeSelectCreateResponse, makeSelectEdit, makeSelectEditResponse, makeSelectTemplateDetailsResponse } from './selectors';
14
+ import {makeSelectCreateLine} from './selectors';
15
+ import { makeSelectMetaEntities } from '../../Cap/selectors';
16
+ import {getMessageObject} from '../../../utils/messageUtils';
17
+ import { makeSelectTemplates } from '../../Templates/selectors';
18
+ import './_lineCreate.scss';
19
+
20
+ const BreadcrumbItem = Breadcrumb.Item;
21
+
22
+ export class Line extends Component {
23
+
24
+ constructor(props) {
25
+ super(props);
26
+ const map = {
27
+ "save-button": {
28
+ saveFormData: this.saveFormData,
29
+ },
30
+ "template-name": {
31
+ onChange: this.onTemplateNameChange,
32
+ },
33
+ "discard-button": {
34
+ discardValues: this.discardValues,
35
+ },
36
+ "cancel-button": {
37
+ cancelTemplate: this.cancelTemplate,
38
+ },
39
+ "message-editor": {
40
+ onChange: this.onTemplateContentChange,
41
+ },
42
+ "message-editor2": {
43
+ onChange: this.onTemplateContentChange,
44
+ },
45
+ "message-tagList": {
46
+ onTagSelect: this.onTagSelect,
47
+ },
48
+ "title-tagList": {
49
+ onTagSelect: this.onTagSelectTitle,
50
+ },
51
+ "pane": {
52
+ onTabChange: this.onTabChange,
53
+ },
54
+ "line-template": {
55
+ onSelect: this.onTemplateChange,
56
+ },
57
+ "image-upload-line": {
58
+ onUpload: this.uploadImage,
59
+ },
60
+ };
61
+ this.state = {
62
+ schema: {},
63
+ isSchemaChanged: false,
64
+ formData: {},
65
+ tabCount: 1,
66
+ currentTab: 1,
67
+ loading: false,
68
+ isFormValid: true,
69
+ tabKey: '',
70
+ checkValidation: false,
71
+ eventsMap: map,
72
+ errorData: {},
73
+ displayProps: {},
74
+ modalContent: {title: "Alert", body: "template not configured,", type: 'confirm'},
75
+ injectedTags: {},
76
+ isEdit: false,
77
+ isEdited: false,
78
+ editTemplateData: {},
79
+ isReady: false,
80
+ modeType: null,
81
+ };
82
+ }
83
+
84
+ componentWillMount() {
85
+ if (this.props.params.id) {
86
+ const editTemplateId = this.props.params.id;
87
+ this.props.actions.getTemplateDetails(editTemplateId, 'LINE');
88
+ this.setState({isEdit: true});
89
+ }
90
+ }
91
+
92
+ componentDidMount() {
93
+ const getSchemaQuery = {
94
+ layout: 'LINE',
95
+ type: 'LAYOUT',
96
+ };
97
+ this.props.globalActions.fetchSchemaForEntity(getSchemaQuery);
98
+ const type = this.props.location.query.type;
99
+ const name = this.props.route.name;
100
+ window.addEventListener("message", this.handleFrameTasks);
101
+ if (type === 'embedded') {
102
+ const response = {
103
+ action: 'startTemplateCreation',
104
+ window: name === 'view' ? 'view' : '',
105
+ };
106
+ parent.postMessage(JSON.stringify(response), '*');
107
+ }
108
+ }
109
+
110
+ componentWillReceiveProps(nextProps) {
111
+ console.log("nextProps line @@@", nextProps);
112
+
113
+ //// Create template logic ////
114
+
115
+ let modeType;
116
+ const {layouts, tags} = nextProps.metaEntities;
117
+ const isSchemaReady = (layouts !== undefined && layouts.length > 0);
118
+ const editModeType = nextProps.route.name;
119
+ if (nextProps.params.mode === 'text' || nextProps.route.name === 'edit_text') {
120
+ modeType = 'text';
121
+ } else {
122
+ modeType = 'image';
123
+ }
124
+ if (modeType) {
125
+ this.setState({modeType, schema: {}});
126
+ //console.log("ooo", this.state.schema);
127
+ }
128
+ if (isSchemaReady) {
129
+ // set schema value as per mode type. Supported mode (text & image)
130
+ console.log("modeType", this.state.modeType);
131
+ const {textSchema, imageSchema} = layouts[0].definition;
132
+ const schema = (modeType === "text" || editModeType === 'edit_text') ? textSchema : imageSchema;
133
+ this.setState({schema}, () => {
134
+ // Once schema is ready and set, then inject the available events from the schema
135
+ if (!_.isEmpty(this.state.schema)) {
136
+ this.injectEvents(this.state.schema);
137
+ }
138
+ // Once schema is ready, then only get the tags.
139
+ const getTagsQuery = {
140
+ layout: 'LINE',
141
+ type: 'TAG',
142
+ context: 'outbound',
143
+ };
144
+ if (tags === undefined && modeType !== 'image') {
145
+ this.props.globalActions.fetchSchemaForEntity(getTagsQuery);
146
+ } else {
147
+ this.setState({isReady: true});
148
+ }
149
+ if (this.props.location.query.type === 'embedded') {
150
+ this.showNext();
151
+ }
152
+ });
153
+ }
154
+
155
+ if ( nextProps.Line && (nextProps.Line.response && nextProps.Line.response.templateId) ) {
156
+ console.log('create response', nextProps.Line);
157
+ this.discardValues();
158
+ const message = getMessageObject('success', this.props.intl.formatMessage(messages["Line Template Created Successfully"]), true);
159
+ this.props.globalActions.addMessageToQueue(message);
160
+ this.props.actions.clearCreateResponse();
161
+ const type = this.props.location.query.type;
162
+ const module = this.props.location.query.module ? this.props.location.query.module : 'default';
163
+ this.props.router.push({
164
+ pathname: `/line/`,
165
+ query: type === 'embedded' ? {type: 'embedded', module} : {module},
166
+ });
167
+ }
168
+
169
+ if (nextProps.Line.createTemplateError && !_.isEqual(nextProps.Line.createTemplateError, this.props.Line.createTemplateError)) {
170
+ const message = getMessageObject('error', (nextProps.Line.createTemplateErrorMessage && nextProps.Line.createTemplateErrorMessage !== '') ? nextProps.Line.createTemplateErrorMessage : this.props.intl.formatMessage(messages.somethingWentWrong), true);
171
+ this.props.globalActions.addMessageToQueue(message);
172
+ }
173
+
174
+ //// Edit Template Logic ////
175
+
176
+ const isEdit = this.state.isEdit && this.props.params.id && (this.props.route.name === 'edit_text' || this.props.route.name === 'edit_image') && this.props.Line.templateDetails && this.props.Line.templateDetails.versions;
177
+ if (isEdit) {
178
+ const formData = this.getEditTransformedData(this.props.Line.templateDetails);
179
+ this.setState({formData, editTemplateData: this.props.Line.templateDetails});
180
+ this.props.actions.clearData();
181
+ }
182
+
183
+ const isEditSucceed = (this.state.isEdit && nextProps.Line && nextProps.Line.editResponse && nextProps.Line.editResponse.templateId);
184
+ if (isEditSucceed) {
185
+ this.setState({formData: {} });
186
+ const message = getMessageObject('success', this.props.intl.formatMessage(messages['Line Template Edited Successfully']), true);
187
+ this.props.globalActions.addMessageToQueue(message);
188
+ this.props.actions.clearEditResponse();
189
+ const module = this.props.location.query.module ? this.props.location.query.module : 'default';
190
+ const type = this.props.location.query.type;
191
+ this.props.router.push({
192
+ pathname: `/line/`,
193
+ query: type === 'embedded' ? {type: 'embedded', module} : {module},
194
+ });
195
+ }
196
+
197
+ if (nextProps.Line.editTemplateError && !_.isEqual(nextProps.Line.editTemplateError, this.props.Line.editTemplateError)) {
198
+ const message = getMessageObject('error', (nextProps.Line.editTemplateErrorMessage && nextProps.Line.editTemplateErrorMessage !== '') ? nextProps.Line.editTemplateErrorMessage : this.props.intl.formatMessage(messages.somethingWentWrong), true);
199
+ this.props.globalActions.addMessageToQueue(message);
200
+ }
201
+
202
+ if (nextProps.Line.uploadAssetSuccess && nextProps.Line.uploadedAssetData) {
203
+ const formData = _.cloneDeep(this.state.formData);
204
+ // TODO: if multiple image upload supports, change below accordingly.
205
+ formData[this.state.currentTab - 1].image = nextProps.Line.uploadedAssetData.metaInfo.secure_file_path;
206
+ console.log("before 2", formData[this.state.currentTab - 1].image);
207
+ this.setState({formData});
208
+ console.log("ooo", this.state.formData);
209
+ this.props.actions.clearAsset();
210
+ }
211
+ if (nextProps.metaEntities && nextProps.metaEntities.tags && nextProps.metaEntities.tags.custom && this.props.metaEntities.tags !== nextProps.metaEntities.tags) {
212
+ let injectedTags = _.cloneDeep(this.state.injectedTags);
213
+ injectedTags = _.merge({}, injectedTags, nextProps.metaEntities.tags.custom);
214
+ console.log('new injected tags', nextProps.metaEntities.tags.custom);
215
+ if (!_.has(nextProps.metaEntities.tags.custom, "Registration custom fields")) {
216
+ delete injectedTags["Registration custom fields"];
217
+ }
218
+ if (!_.has(nextProps.metaEntities.tags.custom, "Store custom fields")) {
219
+ delete injectedTags["Store custom fields"];
220
+ }
221
+ if (!_.has(nextProps.metaEntities.tags.custom, "Transaction custom fields")) {
222
+ delete injectedTags["Transaction custom fields"];
223
+ }
224
+ this.setState({injectedTags});
225
+ }
226
+ }
227
+
228
+ componentWillUnmount() {
229
+ console.log('removed listener templates');
230
+ window.removeEventListener("message", this.handleFrameTasks);
231
+ }
232
+
233
+ onTagSelect(data, currentTab) {
234
+ console.log('parent data tag', data, currentTab);
235
+ const editorId = 'message-editor';
236
+ this.insertAtCursor(document.getElementById(editorId), `{{${data}}}`);
237
+ document.getElementById(editorId).focus();
238
+ }
239
+
240
+ onTagSelectTitle(data, currentTab) {
241
+ console.log('parent data tag', data, currentTab);
242
+ const editorId = 'message-title';
243
+ this.insertAtCursor(document.getElementById(editorId), `{{${data}}}`);
244
+ document.getElementById(editorId).focus();
245
+ }
246
+
247
+ onFormDataChange = (formData, tabCount, currentTab) => {
248
+ console.log('Form data changed is ', formData, tabCount, currentTab);
249
+ this.setState({formData, tabCount});
250
+ if (currentTab) {
251
+ this.setState({currentTab});
252
+ }
253
+ };
254
+
255
+ getTransformedData = (formData) => {
256
+ console.log("formData before transform@@@", formData);
257
+ const modeType = this.state.modeType;
258
+ const obj = {};
259
+ const msgData = {};
260
+ obj.versions = {
261
+ base: {
262
+ content: {
263
+ to: "{{line_id}}",
264
+ messages: [],
265
+ },
266
+ },
267
+ };
268
+ obj.type = 'LINE';
269
+ obj.name = formData['template-name'];
270
+ obj.definition = {
271
+ mode: modeType,
272
+ };
273
+ if ( modeType && modeType !== undefined) {
274
+ msgData.type = modeType;
275
+ }
276
+ if (modeType === 'text') {
277
+ if (this.state.isEdit) {
278
+ const editTemplateId = this.state.editTemplateData._id;
279
+ if (editTemplateId && editTemplateId !== undefined) {
280
+ obj._id = this.state.editTemplateData._id;
281
+ msgData.text = formData['0']['message-editor'];
282
+ }
283
+ } else {
284
+ msgData.text = formData.base['message-editor'];
285
+ }
286
+ } else if (modeType === 'image') {
287
+ if (formData['0'].image.length < 1) {
288
+ return 'IMAGE_ERROR';
289
+ }
290
+ if (this.state.isEdit) {
291
+ const editTemplateId = this.state.editTemplateData._id;
292
+ if (editTemplateId && editTemplateId !== undefined) {
293
+ obj._id = editTemplateId;
294
+ msgData.originalContentUrl = formData['0'].image;
295
+ msgData.previewImageUrl = formData['0'].image;
296
+ }
297
+ } else {
298
+ // TODO: aspect ration validatio (1024 max) in second cut.
299
+ const img = new Image();
300
+ img.src = formData['0'].image;
301
+ img.onload = () => {
302
+ console.log(`Image aspect ratio details line@@@${img.width} and ${img.height}`);
303
+ };
304
+ // Preview Image set to 240px max
305
+ const prevImgSet = new Image(240, 240);
306
+ prevImgSet.src = formData['0'].image;
307
+
308
+ msgData.originalContentUrl = formData['0'].image;
309
+ msgData.previewImageUrl = formData['0'].image;
310
+ }
311
+ }
312
+ obj.versions.base.content.messages.push(msgData);
313
+ return obj;
314
+ };
315
+
316
+ getEditTransformedData = ({name, versions}) => {
317
+ const modeType = this.state.modeType;
318
+ const obj = {};
319
+ obj['0'] = {};
320
+ obj.base = {
321
+ base: true,
322
+ };
323
+ obj['template-name'] = name;
324
+ if (modeType === 'text') {
325
+ obj.base['message-editor'] = versions.base.content.messages[0].text;
326
+ obj['0']['message-editor'] = versions.base.content.messages[0].text;
327
+ } else if (modeType === 'image') {
328
+ obj.base.image = versions.base.content.messages[0].originalContentUrl;
329
+ obj['0'].image = versions.base.content.messages[0].previewImageUrl;
330
+ }
331
+
332
+ console.log("getEditTransformedData", obj);
333
+ return obj;
334
+ };
335
+
336
+ setFormValidity = (isFormValid) => {
337
+ this.setState({isFormValid});
338
+ };
339
+
340
+ getMappedEvent = (id, event) => {
341
+ const map = this.state.eventsMap;
342
+ if (!map[id] || !map[id][event]) {
343
+ console.log(`error map[id] ${map[id]}` );
344
+ }
345
+ return map[id][event];
346
+ };
347
+
348
+ getCurrentWindow(e) {
349
+ console.log('in Line create@@@', e);
350
+ const response = {
351
+ action: e.action,
352
+ value: 'edit',
353
+ direction: e.value,
354
+ };
355
+ parent.postMessage(JSON.stringify(response), '*');
356
+ }
357
+
358
+ getFormData = (e) => {
359
+ console.log('posting final result', this.state.formData);
360
+ const response = {
361
+ action: "getFormData",
362
+ value: this.getTransformedData(this.state.formData),
363
+ validity: this.state.isFormValid,
364
+ };
365
+ this.setState({checkValidation: true});
366
+ e.source.postMessage(JSON.stringify(response), e.origin);
367
+ };
368
+
369
+ injectEvents = (schema) => {
370
+ const temp = schema;
371
+ if (temp.standalone) {
372
+ temp.standalone.sections = this.injectSections(temp.standalone.sections);
373
+ }
374
+ _.forEach(temp.containers, (container) => {
375
+ let tempContainer = container;
376
+ tempContainer = this.injectContainer(tempContainer);
377
+ return tempContainer;
378
+ });
379
+ console.log('final injected schema', schema);
380
+ this.setState({schema, isSchemaChanged: true}, () => {
381
+ this.removeStandAlone();
382
+ });
383
+ console.log('final returned schema', this.state.schema);
384
+ return schema;
385
+ };
386
+
387
+ saveFormData = (formData) => {
388
+ console.log("ccc", this.props);
389
+ console.log('Saving form data of LINE @@@', formData, this.state.tabCount);
390
+ const obj = this.getTransformedData(formData);
391
+ console.log('obj final@@@', obj);
392
+ if (obj === 'IMAGE_ERROR') {
393
+ const message = getMessageObject('error', this.props.intl.formatMessage(messages['Please upload an image to proceed']), true);
394
+ this.props.globalActions.addMessageToQueue(message);
395
+ return;
396
+ }
397
+ if (obj !== 'IMAGE_ERROR' && obj.versions.base.content.messages[0].type === 'text') {
398
+ const charCount = obj.versions.base.content.messages[0].text.length;
399
+ if (charCount > 1600) {
400
+ const message = getMessageObject('error', this.props.intl.formatMessage(messages['Maximum characters length exceeds']), true);
401
+ this.props.globalActions.addMessageToQueue(message);
402
+ return;
403
+ }
404
+ }
405
+ if (this.state.isEdit) {
406
+ console.log("Inside edit line template@@");
407
+ this.props.actions.editTemplate(obj);
408
+ } else {
409
+ this.props.actions.createTemplate(obj);
410
+ }
411
+ };
412
+
413
+ cancelTemplate = () => {
414
+ const type = this.props.location.query.type;
415
+ const module = this.props.location.query.module ? this.props.location.query.module : 'default';
416
+ this.props.router.push({
417
+ pathname: `/LINE/`,
418
+ query: type === 'embedded' ? {type: 'embedded', module} : {module},
419
+ });
420
+ };
421
+
422
+ injectSections = (sections) => {
423
+ _.forEach(sections, (section) => {
424
+ let temp = section;
425
+ if (temp.type === 'col-label') {
426
+ temp = this.injectColLabelSection(temp);
427
+ } else if (section.type === 'multicols') {
428
+ temp = this.injectMultiColSection(temp);
429
+ } else if (section.type === 'parent') {
430
+ temp = this.injectSections(temp.childSections);
431
+ }
432
+ });
433
+ return sections;
434
+ };
435
+
436
+ injectMultiColSection = (section) => {
437
+ _.forEach(section.inputFields, (inputField) => {
438
+ _.forEach(inputField.cols, (col) => {
439
+ const temp = col;
440
+ if (temp.type === 'popover') {
441
+ temp.content.sections = this.injectSections(temp.content.sections);
442
+ temp.value.sections = this.injectSections(temp.value.sections);
443
+ return true;
444
+ }
445
+ if (temp.id === "discard-button") {
446
+ temp.colStyle = {...temp.colStyle, display: 'none'};
447
+ }
448
+ if (temp.id === "cancel-button") {
449
+ temp.offset = 11;
450
+ }
451
+ if (temp.id === "line-push-preview") {
452
+ temp.content.appName = this.props.Templates.selectedWeChatAccount.name;
453
+ }
454
+ temp.injectedEvents = {};
455
+
456
+ _.forEach(col.supportedEvents, (event) => {
457
+ console.log('injected event for ', col, event, this.getMappedEvent(col.id, event));
458
+ temp.injectedEvents[event] = this.getMappedEvent(col.id, event);
459
+ });
460
+ return true;
461
+ });
462
+ });
463
+ _.forEach(section.actionFields, (actionField) => {
464
+ _.forEach(actionField.cols, (col) => {
465
+ const temp = col;
466
+ if (temp.type === 'popover') {
467
+ temp.content.sections = this.injectSections(temp.content.sections);
468
+ temp.value.sections = this.injectSections(temp.value.sections);
469
+ return true;
470
+ }
471
+ temp.injectedEvents = {};
472
+ _.forEach(col.supportedEvents, (event) => {
473
+ temp.injectedEvents[event] = this.getMappedEvent(col.id, event);
474
+ });
475
+ return true;
476
+ });
477
+ });
478
+ return section;
479
+ };
480
+
481
+ injectColLabelSection = (section) => {
482
+ _.forEach(section.inputFields, (inputField) => {
483
+ const temp = inputField;
484
+ if (temp.type === 'popover') {
485
+ temp.content.sections = this.injectSections(temp.content.sections);
486
+ temp.value.sections = this.injectSections(temp.value.sections);
487
+ return true;
488
+ }
489
+ temp.injectedEvents = {};
490
+ _.forEach(inputField.supportedEvents, (event) => {
491
+ temp.injectedEvents[event] = this.getMappedEvent(inputField.id, event);
492
+ });
493
+ return true;
494
+ });
495
+ _.forEach(section.actionFields, (actionField) => {
496
+ const temp = actionField;
497
+ if (temp.type === 'popover') {
498
+ temp.content.sections = this.injectSections(temp.content.sections);
499
+ temp.value.sections = this.injectSections(temp.value.sections);
500
+ return true;
501
+ }
502
+ temp.injectedEvents = {};
503
+ _.forEach(actionField.supportedEvents, (event) => {
504
+ temp.injectedEvents[event] = this.getMappedEvent(actionField.id, event);
505
+ });
506
+ return true;
507
+ });
508
+ return section;
509
+ };
510
+
511
+ injectParentSection = (section) => {
512
+ _.forEach(section.childSections, (childSection) => {
513
+ let temp = childSection;
514
+ if (temp.type === 'col-label') {
515
+ temp = this.injectColLabelSection(temp);
516
+ } else if (section.type === 'multicols') {
517
+ temp = this.injectMultiColSection(temp);
518
+ } else if (section.type === 'parent') {
519
+ temp = this.injectParentSection(temp);
520
+ }
521
+ });
522
+ return section;
523
+ };
524
+
525
+ insertAtCursor = (field, myValue) => {
526
+ //IE support
527
+ const myField = field;
528
+ if (document.selection) {
529
+ myField.focus();
530
+ const sel = document.selection.createRange();
531
+ sel.text = myValue;
532
+ } else if (myField.selectionStart || myField.selectionStart === '0') { //MOZILLA and others
533
+ const startPos = myField.selectionStart;
534
+ const endPos = myField.selectionEnd;
535
+ myField.value = myField.value.substring(0, startPos)
536
+ + myValue
537
+ + myField.value.substring(endPos, myField.value.length);
538
+ myField.selectionStart = startPos + myValue.length;
539
+ myField.selectionEnd = startPos + myValue.length;
540
+ } else {
541
+ myField.value += myValue;
542
+ }
543
+ const event = new Event('input', { bubbles: true });
544
+ myField.dispatchEvent(event);
545
+ };
546
+
547
+ startTemplateCreation = (data) => {
548
+ const getSchemaQuery = {
549
+ layout: 'LINE',
550
+ type: 'LAYOUT',
551
+ };
552
+ this.props.globalActions.fetchSchemaForEntity(getSchemaQuery);
553
+ console.log('startTemplateCreation');
554
+ const content = data.content;
555
+ const obj = {};
556
+ obj['0'] = {};
557
+ obj.base = {
558
+ base: true,
559
+ };
560
+ if (data.type === 'text') {
561
+ obj.base['message-editor'] = content;
562
+ obj['0']['message-editor'] = content;
563
+ } else {
564
+ obj.base.image = content;
565
+ obj['0'].image = content;
566
+ }
567
+ this.setState({formData: obj, loading: false});
568
+ };
569
+
570
+ startLoading = (ifEdit) => {
571
+ console.log('startLoading', ifEdit);
572
+ if (ifEdit) {
573
+ this.setState({loading: true});
574
+ }
575
+ };
576
+
577
+ injectContainer = (container) => {
578
+ const temp = container;
579
+ if (temp.type === 'tabs') {
580
+ temp.injectedEvents = {};
581
+ _.forEach(temp.supportedEvents, (event) => {
582
+ temp.injectedEvents[event] = this.getMappedEvent(temp.id, event);
583
+ });
584
+ _.forEach(temp.panes, (pane) => {
585
+ const tempPane = pane;
586
+ tempPane.sectionsHeaders = this.injectSections(tempPane.sectionsHeaders);
587
+ tempPane.sections = this.injectSections(tempPane.sections);
588
+ });
589
+ }
590
+ return temp;
591
+ };
592
+
593
+ resetSchema = () => {
594
+ this.setState({ schema: this.state.initialState ? this.state.initialState : this.state.schema});
595
+ };
596
+
597
+ resetState = () => {
598
+ this.setState({
599
+ formData: {},
600
+ tabCount: 1,
601
+ currentTab: 1,
602
+ });
603
+ };
604
+
605
+ discardValues = () => {
606
+ this.resetSchema();
607
+ this.resetState();
608
+ };
609
+
610
+ moveToTemplates() {
611
+ console.log('in move to Templates');
612
+ const modalContent = {
613
+ title: "Alert",
614
+ body: "Do you really want to go back? All your temporary changes will be lost!",
615
+ type: 'confirm',
616
+ id: 'template-back-confirm-modal',
617
+ show: true,
618
+ };
619
+ this.setState({modalContent, showModal: true});
620
+ }
621
+
622
+ showNext() {
623
+ const response = {
624
+ action: "showNext",
625
+ value: true,
626
+ };
627
+ parent.postMessage(JSON.stringify(response), '*');
628
+ }
629
+
630
+ discardValues = () => {
631
+ this.resetSchema();
632
+ this.resetState();
633
+ };
634
+
635
+ handleFrameTasks = (e) => {
636
+ console.log('listened from cheetah@@@', e.data);
637
+ const type = e.data;
638
+ console.log('data type', typeof type);
639
+ if (typeof type === 'object') {
640
+ console.log('received something', type);
641
+ const action = type.action;
642
+ switch (action) {
643
+ case "startTemplateCreation":
644
+ this.startTemplateCreation(type.value);
645
+ break;
646
+ case "startLoading":
647
+ this.startLoading(type.edit);
648
+ break;
649
+ case "getCurrentWindow":
650
+ this.getCurrentWindow(type);
651
+ break;
652
+ default:
653
+ break;
654
+ }
655
+ } else {
656
+ switch (type) {
657
+ case "getFormData":
658
+ this.getFormData(e);
659
+ break;
660
+ case "startTemplateCreation":
661
+ console.log('Starting to create template');
662
+ //this.getFormData(e);
663
+ break;
664
+ case "moveToTemplates":
665
+ console.log('moving to templates');
666
+ this.moveToTemplates();
667
+ break;
668
+ case "validateContent":
669
+ console.log('validating Content');
670
+ this.validateContent(e);
671
+ break;
672
+ default:
673
+ break;
674
+ }
675
+ }
676
+ };
677
+
678
+ removeStandAlone = () => {
679
+ const schema = _.cloneDeep(this.state.schema);
680
+ console.log("schema line", schema);
681
+ if (this.props.location.query.type === 'embedded' && this.props.location.query.module === 'loyalty') {
682
+ schema.standalone.sections.splice(0, 1);
683
+ } else if (this.props.location.query.type === 'embedded') {
684
+ delete schema.standalone;
685
+ } else {
686
+ schema.standalone.sections.splice(1, 1);
687
+ }
688
+ this.setState({ schema });
689
+ };
690
+
691
+ validateContent = (e) => {
692
+ console.log('posting final validation result', this.state.isFormValid);
693
+ const response = {
694
+ action: "validateContent",
695
+ value: this.state.isFormValid,
696
+ };
697
+ e.source.postMessage(JSON.stringify(response), e.origin);
698
+ };
699
+
700
+ handleOnTagsContextChange = (data) => {
701
+ console.log('parent tags context', data);
702
+ const query = {
703
+ layout: 'LINE',
704
+ type: 'TAG',
705
+ context: data.toLowerCase() === 'all' ? 'default' : data.toLowerCase(),
706
+ embedded: this.props.location.query.type === 'embedded' ? this.props.location.query.type : 'full',
707
+ };
708
+ this.props.globalActions.fetchSchemaForEntity(query);
709
+ };
710
+
711
+ uploadImage = (data) => {
712
+ console.log("image data line@@@", data);
713
+ if (data.file.size > 1000000) {
714
+ const message = getMessageObject('error', this.props.intl.formatMessage(messages['File size cannot be more than 1mb']), true);
715
+ this.props.globalActions.addMessageToQueue(message);
716
+ } else {
717
+ const name = data.file.name.split('.');
718
+ const blob = data.file.slice(0, -1, 'image');
719
+ const newFile = new File([blob], `${name[0]}${Date.now()}.${name[1]}`, {type: 'image'});
720
+ this.props.actions.uploadAsset(newFile, data.type, data.fileParams);
721
+ }
722
+ };
723
+
724
+ render() {
725
+ if (this.state.formData && this.state.formData["0"] && this.state.formData["0"].image) {
726
+ console.log("before render@@@", this.state.formData["0"].image);
727
+ }
728
+ console.log("render state", this.state);
729
+ let tipText = this.props.Line.createTemplateInProgress ? "Saving Template..." : "";
730
+ let loading = this.props.Line.createTemplateInProgress ? this.props.Line.createTemplateInProgress : false;
731
+ if (this.props.Line.assetUploading) {
732
+ tipText = "Uploading Image...";
733
+ loading = true;
734
+ }
735
+ // if (!this.state.isReady) {
736
+ // tipText = "Please wait..";
737
+ // loading = true;
738
+ // }
739
+ return (
740
+ <Spin tip={tipText} spinning={loading}>
741
+ <Row style={{marginLeft: '-48px'}}>
742
+ <Col offset={1}>
743
+ <Breadcrumb>
744
+ <BreadcrumbItem>{this.props.intl.formatMessage(messages.Campaigns)}</BreadcrumbItem>
745
+ <BreadcrumbItem>{this.props.intl.formatMessage(messages.Creatives)}</BreadcrumbItem>
746
+ <BreadcrumbItem>{this.props.intl.formatMessage(messages.Line)}</BreadcrumbItem>
747
+ </Breadcrumb>
748
+ </Col>
749
+ </Row>
750
+ <Row>
751
+ <Col>
752
+ <FormBuilder
753
+ key={"form builder"}
754
+ schema={this.state.schema}
755
+ onSubmit={this.saveFormData}
756
+ onChange={this.onFormDataChange}
757
+ currentTab={this.state.currentTab}
758
+ parent={this}
759
+ formData={_.cloneDeep(this.state.formData)}
760
+ location={this.props.location}
761
+ tags={this.props.metaEntities && this.props.metaEntities.tags ? this.props.metaEntities.tags.standard : []}
762
+ injectedTags={this.state.injectedTags ? this.state.injectedTags : {}}
763
+ onFormValidityChange={this.setFormValidity}
764
+ usingTabContainer
765
+ checkValidation={this.state.checkValidation}
766
+ tabKey={this.state.tabKey}
767
+ tabCount={2}
768
+ showModal={this.state.showModal}
769
+ isSchemaChanged={this.state.isSchemaChanged}
770
+ modal={this.state.modalContent}
771
+ handleCancelModal={this.handleCancelModal}
772
+ iframeParent={parent}
773
+ router={this.props.router}
774
+ onContextChange={this.handleOnTagsContextChange}
775
+ setModalContent={this.setModalContent}
776
+ />
777
+ </Col>
778
+ </Row>
779
+ </Spin>
780
+ );
781
+ }
782
+ }
783
+
784
+ Line.propTypes = {
785
+ actions: PropTypes.object.isRequired,
786
+ globalActions: PropTypes.object,
787
+ Templates: PropTypes.object,
788
+ location: PropTypes.object,
789
+ router: PropTypes.object,
790
+ params: PropTypes.object,
791
+ metaEntities: PropTypes.object,
792
+ intl: intlShape.isRequired,
793
+ route: PropTypes.object,
794
+ Line: PropTypes.object,
795
+ };
796
+
797
+ const mapStateToProps = createStructuredSelector({
798
+ Line: makeSelectCreateLine(),
799
+ Templates: makeSelectTemplates(),
800
+ metaEntities: makeSelectMetaEntities(),
801
+ });
802
+
803
+ function mapDispatchToProps(dispatch) {
804
+ return {
805
+ actions: bindActionCreators(actions, dispatch),
806
+ globalActions: bindActionCreators(globalActions, dispatch),
807
+ };
808
+ }
809
+
810
+ export default UserIsAuthenticated(connect(mapStateToProps, mapDispatchToProps)(injectIntl(Line)));