@capillarytech/creatives-library 2.0.75 → 2.0.76
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.
- package/components/EmailPreview/assets/images/iPad.svg +10 -0
- package/components/EmailPreview/assets/images/mobile.png +0 -0
- package/components/FormBuilder/test +1845 -0
- package/containers/CallTask/_callTask.scss +5 -0
- package/containers/CallTask/actions.js +15 -0
- package/containers/CallTask/constants.js +7 -0
- package/containers/CallTask/index.js +141 -0
- package/containers/CallTask/messages.js +21 -0
- package/containers/CallTask/reducer.js +23 -0
- package/containers/CallTask/sagas.js +11 -0
- package/containers/CallTask/selectors.js +25 -0
- package/containers/CallTask/tests/actions.test.js +18 -0
- package/containers/CallTask/tests/index.test.js +10 -0
- package/containers/CallTask/tests/reducer.test.js +9 -0
- package/containers/CallTask/tests/sagas.test.js +15 -0
- package/containers/CallTask/tests/selectors.test.js +10 -0
- package/containers/ChannelTemplates/actions.js +20 -0
- package/containers/ChannelTemplates/constants.js +8 -0
- package/containers/ChannelTemplates/index.js +48 -0
- package/containers/ChannelTemplates/messages.js +13 -0
- package/containers/ChannelTemplates/reducer.js +34 -0
- package/containers/ChannelTemplates/sagas.js +32 -0
- package/containers/ChannelTemplates/selectors.js +25 -0
- package/containers/ChannelTemplates/tests/actions.test.js +18 -0
- package/containers/ChannelTemplates/tests/index.test.js +10 -0
- package/containers/ChannelTemplates/tests/reducer.test.js +9 -0
- package/containers/ChannelTemplates/tests/sagas.test.js +15 -0
- package/containers/ChannelTemplates/tests/selectors.test.js +10 -0
- package/containers/CreativesContainer/SlideBoxContent.js +248 -0
- package/containers/CreativesContainer/SlideBoxFooter.js +38 -0
- package/containers/CreativesContainer/SlideBoxHeader.js +65 -0
- package/containers/CreativesContainer/actions.js +27 -0
- package/containers/CreativesContainer/constants.js +13 -0
- package/containers/CreativesContainer/index.js +418 -0
- package/containers/CreativesContainer/index.scss +27 -0
- package/containers/CreativesContainer/messages.js +17 -0
- package/containers/CreativesContainer/reducer.js +29 -0
- package/containers/CreativesContainer/sagas.js +11 -0
- package/containers/CreativesContainer/selectors.js +30 -0
- package/containers/CreativesContainer/tests/actions.test.js +18 -0
- package/containers/CreativesContainer/tests/index.test.js +10 -0
- package/containers/CreativesContainer/tests/reducer.test.js +9 -0
- package/containers/CreativesContainer/tests/sagas.test.js +15 -0
- package/containers/CreativesContainer/tests/selectors.test.js +10 -0
- package/containers/EmailWrapper/actions.js +15 -0
- package/containers/EmailWrapper/constants.js +7 -0
- package/containers/EmailWrapper/index.js +238 -0
- package/containers/EmailWrapper/messages.js +57 -0
- package/containers/EmailWrapper/reducer.js +23 -0
- package/containers/EmailWrapper/sagas.js +11 -0
- package/containers/EmailWrapper/selectors.js +25 -0
- package/containers/EmailWrapper/tests/actions.test.js +18 -0
- package/containers/EmailWrapper/tests/index.test.js +10 -0
- package/containers/EmailWrapper/tests/reducer.test.js +9 -0
- package/containers/EmailWrapper/tests/sagas.test.js +15 -0
- package/containers/EmailWrapper/tests/selectors.test.js +10 -0
- package/containers/MobilePush/commonMethods.js +249 -0
- package/containers/MobilePush/eventsMap.js +127 -0
- package/containers/MobilePush/initialSchema.js +1739 -0
- package/containers/MobilepushWrapper/_mobilepushWrapper.scss +18 -0
- package/containers/MobilepushWrapper/index.js +97 -0
- package/containers/MobilepushWrapper/messages.js +25 -0
- package/containers/MobilepushWrapper/tests/index.test.js +10 -0
- package/containers/TemplatesV2/_templatesV2.scss +5 -0
- package/containers/TemplatesV2/actions.js +16 -0
- package/containers/TemplatesV2/constants.js +10 -0
- package/containers/TemplatesV2/index.js +207 -0
- package/containers/TemplatesV2/messages.js +29 -0
- package/containers/TemplatesV2/selectors.js +25 -0
- package/containers/TemplatesV2/tests/actions.test.js +18 -0
- package/containers/TemplatesV2/tests/index.test.js +10 -0
- package/containers/TemplatesV2/tests/reducer.test.js +9 -0
- package/containers/TemplatesV2/tests/sagas.test.js +15 -0
- package/containers/TemplatesV2/tests/selectors.test.js +10 -0
- package/containers/WeChat/RichmediaTemplates/Create/testschema.js +379 -0
- package/containers/WeChat/_wechat.scss +8 -0
- package/containers/WeChat/actions.js +52 -0
- package/containers/WeChat/constants.js +28 -0
- package/containers/WeChat/index.js +1635 -0
- package/containers/WeChat/messages.js +73 -0
- package/containers/WeChat/reducer.js +74 -0
- package/containers/WeChat/sagas.js +86 -0
- package/containers/WeChat/selectors.js +25 -0
- package/containers/WeChat/tests/actions.test.js +18 -0
- package/containers/WeChat/tests/index.test.js +10 -0
- package/containers/WeChat/tests/reducer.test.js +9 -0
- package/containers/WeChat/tests/sagas.test.js +15 -0
- package/containers/WeChat/tests/selectors.test.js +10 -0
- package/package.json +1 -1
- package/routes.js +1 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +1 -0
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +11 -2
- package/v2Containers/CreativesContainer/index.js +4 -0
- package/v2Containers/CreativesContainer/messages.js +1 -1
- package/v2Containers/MobilePush/Edit/index.js +1 -3
- package/v2Containers/MobilepushWrapper/index.js +3 -1
- package/v2Containers/Templates/_templates.scss +1 -3
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { PropTypes } from 'prop-types';
|
|
3
|
+
import {
|
|
4
|
+
CapSlideBox,
|
|
5
|
+
} from '@capillarytech/cap-ui-library';
|
|
6
|
+
import { injectIntl } from 'react-intl';
|
|
7
|
+
import classnames from 'classnames';
|
|
8
|
+
import {isEmpty, get, forEach} from 'lodash';
|
|
9
|
+
import { connect } from 'react-redux';
|
|
10
|
+
import { createStructuredSelector } from 'reselect';
|
|
11
|
+
import { bindActionCreators } from 'redux';
|
|
12
|
+
import * as actions from './actions';
|
|
13
|
+
import {selectEmailLayout, uploadSelector, templateUserList} from '../Templates/selectors';
|
|
14
|
+
import SlideBoxContent from './SlideBoxContent';
|
|
15
|
+
import SlideBoxHeader from './SlideBoxHeader';
|
|
16
|
+
import SlideBoxFooter from './SlideBoxFooter';
|
|
17
|
+
import * as constants from './constants';
|
|
18
|
+
import * as commonUtil from '../../utils/common';
|
|
19
|
+
|
|
20
|
+
import './index.scss';
|
|
21
|
+
import * as templateActions from '../Templates/actions';
|
|
22
|
+
import * as globalActions from '../Cap/actions';
|
|
23
|
+
import {isLoading as isLoadingSelector} from './selectors';
|
|
24
|
+
|
|
25
|
+
const classPrefix = 'add-creatives-section';
|
|
26
|
+
class Creatives extends React.Component {
|
|
27
|
+
constructor(props) {
|
|
28
|
+
super(props);
|
|
29
|
+
this.state = {
|
|
30
|
+
isLoadingContent: true,
|
|
31
|
+
templateStep: 1, //modeSelection: for template name and (for email selecting upload or editor), and createTemplate to create template create based on modeSelection
|
|
32
|
+
showSlideBox: true,
|
|
33
|
+
slidBoxContent: this.getSlideBocContent({mode: props.creativesMode, templateData: props.templateData, isFullMode: props.isFullMode}),
|
|
34
|
+
templateData: this.getTemplateData(props.templateData),
|
|
35
|
+
currentChannel: this.props.channel || 'sms',
|
|
36
|
+
};
|
|
37
|
+
this.creativesTemplateSteps = {
|
|
38
|
+
1: 'modeSelection',
|
|
39
|
+
2: 'templateSelection', // only for email in current flows wil be used for mpush, line and wechat as well.
|
|
40
|
+
3: 'createTemplateContent',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
componentWillUnmount() {
|
|
44
|
+
if (!this.props.isFullMode) {
|
|
45
|
+
this.props.templateActions.resetTemplateStoreData();
|
|
46
|
+
this.props.globalActions.clearMetaEntities();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
onSelectTemplate = (template) => {
|
|
52
|
+
this.setState({ slidBoxContent: 'editTemplate', templateData: template });
|
|
53
|
+
};
|
|
54
|
+
onPreviewTemplate = (template) => {
|
|
55
|
+
const templateData = template;
|
|
56
|
+
const usersList = commonUtil.getMergedUserList(this.props.templateUserList);
|
|
57
|
+
const userId = parseInt(template.updatedBy, 10);
|
|
58
|
+
templateData.updatedByName = commonUtil.getUserNameById(userId, usersList );
|
|
59
|
+
this.setState({ slidBoxContent: 'preview', templateData });
|
|
60
|
+
};
|
|
61
|
+
onEditTemplate = () => {
|
|
62
|
+
this.setState({ slidBoxContent: 'editTemplate', showSlideBox: true });
|
|
63
|
+
};
|
|
64
|
+
onCreateNew = () => {
|
|
65
|
+
this.setState({ slidBoxContent: 'createTemplate', showSlideBox: true });
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
onShowTemplates = () => {
|
|
69
|
+
this.setState({ slidBoxContent: 'templates', showSlideBox: true, isGetFormData: false });
|
|
70
|
+
};
|
|
71
|
+
onChannelChange = (channel) => {
|
|
72
|
+
this.setState({currentChannel: channel});
|
|
73
|
+
}
|
|
74
|
+
onCreateNextStep = () => {
|
|
75
|
+
this.setState((prevState) => {
|
|
76
|
+
let templateStep = prevState.templateStep + 1;
|
|
77
|
+
const {emailCreateMode, currentChannel} = prevState;
|
|
78
|
+
if ((currentChannel.toUpperCase() === constants.EMAIL && emailCreateMode === "upload") || currentChannel.toUpperCase() === constants.MOBILE_PUSH) {
|
|
79
|
+
templateStep = prevState.templateStep + 2;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
templateStep,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
onEmailModeChange = (mode) => {
|
|
89
|
+
this.setState({ emailCreateMode: mode});
|
|
90
|
+
}
|
|
91
|
+
onMobilepushModeChange = (mode) => {
|
|
92
|
+
this.setState({ mobilePushCreateMode: mode});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
onCallTaskSubmit = (data) => {
|
|
96
|
+
this.props.getCreativesData({
|
|
97
|
+
channel: 'CALL_TASK',
|
|
98
|
+
...data,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
getTemplateData = (templateData) => { //from consumers to creatives
|
|
103
|
+
const {isFullMode} = this.props;
|
|
104
|
+
if (!isFullMode && templateData) { // for component mode
|
|
105
|
+
const {channel} = templateData;
|
|
106
|
+
let creativesTeplateData = {type: channel };
|
|
107
|
+
if (channel === constants.SMS) {
|
|
108
|
+
const formData = {
|
|
109
|
+
"sms-editor": templateData.messageBody,
|
|
110
|
+
};
|
|
111
|
+
creativesTeplateData = {
|
|
112
|
+
type: channel,
|
|
113
|
+
name: "Campaign message SMS content",
|
|
114
|
+
versions: {
|
|
115
|
+
base: formData,
|
|
116
|
+
history: [formData],
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
} else if (channel === constants.EMAIL) {
|
|
120
|
+
const formData = {
|
|
121
|
+
subject: templateData.emailSubject,
|
|
122
|
+
html_content: templateData.emailBody,
|
|
123
|
+
is_drag_drop: templateData.is_drag_drop,
|
|
124
|
+
lang_id: templateData.lang_id,
|
|
125
|
+
iso_code: templateData.iso_code,
|
|
126
|
+
language: templateData.language,
|
|
127
|
+
drag_drop_id: templateData.drag_drop_id,
|
|
128
|
+
};
|
|
129
|
+
creativesTeplateData = {
|
|
130
|
+
base: formData,
|
|
131
|
+
edit: true,
|
|
132
|
+
type: channel,
|
|
133
|
+
};
|
|
134
|
+
} else if (channel === constants.CALL_TASK) {
|
|
135
|
+
creativesTeplateData = {
|
|
136
|
+
subject: templateData.subject,
|
|
137
|
+
messageBody: templateData.messageBody,
|
|
138
|
+
description: templateData.description,
|
|
139
|
+
edit: true,
|
|
140
|
+
type: channel,
|
|
141
|
+
};
|
|
142
|
+
} else if (channel === constants.MOBILE_PUSH) {
|
|
143
|
+
const mode = get(templateData, 'androidContent.type') || get(templateData, 'iosContent.type');
|
|
144
|
+
creativesTeplateData = {
|
|
145
|
+
type: channel,
|
|
146
|
+
name: templateData.messageSubject,
|
|
147
|
+
versions: {
|
|
148
|
+
base: {
|
|
149
|
+
ANDROID: templateData.androidContent,
|
|
150
|
+
IOS: templateData.iosContent,
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
definition: {accountId: templateData.accountId, mode: mode.toLowerCase()},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return creativesTeplateData;
|
|
157
|
+
}
|
|
158
|
+
return templateData || null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
getCreativesData = (channel, template) => { //from creatives to consumers
|
|
162
|
+
let templateData = {channel };
|
|
163
|
+
if (channel === constants.SMS && template.value.base) {
|
|
164
|
+
templateData.messageBody = template.value.base['sms-editor'];
|
|
165
|
+
} else if (channel === constants.EMAIL && template.value.base) {
|
|
166
|
+
const emailBase = template.value.base;
|
|
167
|
+
templateData = {...templateData, ...emailBase, emailBody: emailBase.html_content, emailSubject: emailBase.subject};
|
|
168
|
+
delete templateData.html_content;
|
|
169
|
+
delete templateData.subject;
|
|
170
|
+
} else if (channel === constants.MOBILE_PUSH && get(template, "value.versions.base")) {
|
|
171
|
+
const mobilpushTemplate = template.value;
|
|
172
|
+
templateData.accountId = get(mobilpushTemplate, 'definition.accountId');
|
|
173
|
+
const androidContent = get(mobilpushTemplate, 'versions.base.ANDROID');
|
|
174
|
+
if (!isEmpty(androidContent)) {
|
|
175
|
+
delete androidContent.cuid;
|
|
176
|
+
delete androidContent.luid;
|
|
177
|
+
delete androidContent.communicationId;
|
|
178
|
+
const custom = {};
|
|
179
|
+
forEach(androidContent.custom, (customKeyValue) => {
|
|
180
|
+
custom[customKeyValue.key] = customKeyValue.value;
|
|
181
|
+
} );
|
|
182
|
+
androidContent.custom = custom;
|
|
183
|
+
templateData.androidContent = androidContent;
|
|
184
|
+
templateData.androidContent.type = get(mobilpushTemplate, 'definition.mode').toUpperCase();
|
|
185
|
+
templateData.androidContent.deviceType = 'ANDROID';
|
|
186
|
+
}
|
|
187
|
+
const iosContent = get(mobilpushTemplate, 'versions.base.IOS');
|
|
188
|
+
if (!isEmpty(iosContent)) {
|
|
189
|
+
delete iosContent.cuid;
|
|
190
|
+
delete iosContent.luid;
|
|
191
|
+
delete iosContent.communicationId;
|
|
192
|
+
const custom = {};
|
|
193
|
+
forEach(iosContent.custom, (customKeyValue) => {
|
|
194
|
+
custom[customKeyValue.key] = customKeyValue.value;
|
|
195
|
+
} );
|
|
196
|
+
iosContent.custom = custom;
|
|
197
|
+
templateData.iosContent = iosContent;
|
|
198
|
+
templateData.iosContent.type = get(mobilpushTemplate, 'definition.mode').toUpperCase();
|
|
199
|
+
templateData.iosContent.deviceType = 'IOS';
|
|
200
|
+
}
|
|
201
|
+
templateData.messageSubject = mobilpushTemplate.name;
|
|
202
|
+
}
|
|
203
|
+
return templateData;
|
|
204
|
+
};
|
|
205
|
+
getSlideBocContent({mode, templateData, isFullMode}) {
|
|
206
|
+
let creativesMode = isFullMode ? 'createTemplate' : 'templates';// for library mode templates page is initial mode and for full mode createTemplates
|
|
207
|
+
if (mode === 'create' && isFullMode) {
|
|
208
|
+
creativesMode = 'createTemplate';
|
|
209
|
+
} else if (mode === 'create' && isEmpty(templateData)) {
|
|
210
|
+
creativesMode = 'templates';
|
|
211
|
+
} else if (mode === 'edit') {
|
|
212
|
+
creativesMode = 'editTemplate';
|
|
213
|
+
}
|
|
214
|
+
return creativesMode;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
getFormData = (template) => {
|
|
218
|
+
if (template.validity) {
|
|
219
|
+
this.setState(
|
|
220
|
+
{
|
|
221
|
+
isGetFormData: false,
|
|
222
|
+
},
|
|
223
|
+
() => {
|
|
224
|
+
const templateData = this.state.templateData ? this.state.templateData : template; //select existing or create new content
|
|
225
|
+
const channel = templateData.type;
|
|
226
|
+
const creativesData = this.getCreativesData(channel, template);// convers data to consumer understandable format
|
|
227
|
+
this.props.getCreativesData(creativesData);// send data to consumer
|
|
228
|
+
},
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
setIsLoadingContent = (isLoadingContent) => {
|
|
233
|
+
if (this.state.isLoadingContent !== isLoadingContent) {
|
|
234
|
+
this.setState({isLoadingContent });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
resetStep = () => {
|
|
238
|
+
this.setState((prevState) => {
|
|
239
|
+
let newState = {
|
|
240
|
+
templateStep: 1,
|
|
241
|
+
};
|
|
242
|
+
if (prevState.currentChannel.toUpperCase() === constants.EMAIL) {
|
|
243
|
+
newState = { ...newState, emailCreateMode: null };
|
|
244
|
+
}
|
|
245
|
+
return newState;
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
handleCloseSlideBox = () => {
|
|
249
|
+
this.setState((prevState) => ({
|
|
250
|
+
...prevState,
|
|
251
|
+
templateData: undefined,
|
|
252
|
+
showSlideBox: false,
|
|
253
|
+
}), this.props.handleCloseCreatives);
|
|
254
|
+
};
|
|
255
|
+
saveMessage = () => {
|
|
256
|
+
this.setState({ isGetFormData: true });
|
|
257
|
+
};
|
|
258
|
+
shouldShowFooter = () => {
|
|
259
|
+
const {isFullMode } = this.props;
|
|
260
|
+
const {slidBoxContent, currentChannel, emailCreateMode, templateStep, mobilePushCreateMode} = this.state;
|
|
261
|
+
const channel = currentChannel.toUpperCase();
|
|
262
|
+
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
263
|
+
let showFooter = false;
|
|
264
|
+
const isMobilepush = channel === constants.MOBILE_PUSH;
|
|
265
|
+
if (!isFullMode ) {
|
|
266
|
+
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
267
|
+
const isCreate = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
268
|
+
const isCallTask = channel === constants.CALL_TASK;
|
|
269
|
+
showFooter = (isCreate || (isEmailCreate && emailCreateMode) || slidBoxContent === 'preview') && !isCallTask;
|
|
270
|
+
if (isMobilepush) {
|
|
271
|
+
showFooter = currentStep === "modeSelection" || (currentStep === 'createTemplateContent' && !isEmpty(mobilePushCreateMode));
|
|
272
|
+
}
|
|
273
|
+
} else if (channel === constants.EMAIL && isFullMode) {
|
|
274
|
+
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
275
|
+
showFooter = isEmailCreate && emailCreateMode;
|
|
276
|
+
}
|
|
277
|
+
if (channel === constants.EMAIL && emailCreateMode === "upload") {
|
|
278
|
+
showFooter = showFooter && !this.props.isUploading;
|
|
279
|
+
}
|
|
280
|
+
if (showFooter) {
|
|
281
|
+
if (slidBoxContent === "createTemplate" && ((channel === constants.EMAIL && currentStep === 'createTemplateContent') || (channel === constants.SMS && currentStep === 'modeSelection'))) {
|
|
282
|
+
showFooter = showFooter && !this.state.isLoadingContent;
|
|
283
|
+
} else if (slidBoxContent === "editTemplate" && ((channel === constants.EMAIL && currentStep === 'modeSelection') || (channel === constants.SMS && currentStep === 'modeSelection'))) {
|
|
284
|
+
showFooter = showFooter && !this.state.isLoadingContent;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return showFooter;
|
|
288
|
+
}
|
|
289
|
+
shouldShowDoneFooter = () => {
|
|
290
|
+
const {slidBoxContent, templateStep, currentChannel} = this.state;
|
|
291
|
+
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
292
|
+
let showDone = false;
|
|
293
|
+
const channel = currentChannel.toUpperCase();
|
|
294
|
+
if (channel === constants.EMAIL || channel === constants.SMS) {
|
|
295
|
+
const isEmailCreate = slidBoxContent === 'createTemplate' && currentChannel.toUpperCase() === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
296
|
+
showDone = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
297
|
+
} else if (channel === constants.MOBILE_PUSH) {
|
|
298
|
+
showDone = currentStep === "createTemplateContent" || slidBoxContent === "editTemplate";
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return showDone;
|
|
302
|
+
}
|
|
303
|
+
shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
|
|
304
|
+
const {slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode} = this.state;
|
|
305
|
+
let isShowContinueFooter = false;
|
|
306
|
+
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
307
|
+
const channel = currentChannel.toUpperCase();
|
|
308
|
+
if (channel === constants.EMAIL || channel === constants.SMS) {
|
|
309
|
+
if ((emailCreateMode === "upload" && !isEmpty(this.props.EmailLayout)) || emailCreateMode === "editor") {
|
|
310
|
+
let isEmailCreate = slidBoxContent === 'createTemplate';
|
|
311
|
+
isEmailCreate = currentChannel.toUpperCase() === constants.EMAIL && ((emailCreateMode === "upload" && currentStep !== 'createTemplateContent') || ( emailCreateMode === "editor" && currentStep !== 'createTemplateContent' && currentStep !== "templateSelection"));
|
|
312
|
+
isShowContinueFooter = isEmailCreate && emailCreateMode;
|
|
313
|
+
}
|
|
314
|
+
} else if (currentChannel.toUpperCase() === constants.MOBILE_PUSH) {
|
|
315
|
+
isShowContinueFooter = !isEmpty(mobilePushCreateMode) && currentStep === "modeSelection";
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return isShowContinueFooter;
|
|
319
|
+
}
|
|
320
|
+
render() {
|
|
321
|
+
const {slidBoxContent, isGetFormData, showSlideBox, templateData, currentChannel, emailCreateMode, templateStep, isLoadingContent, mobilePushCreateMode} = this.state;
|
|
322
|
+
const {isFullMode, creativesMode, cap, isUploading} = this.props;
|
|
323
|
+
return (
|
|
324
|
+
<div className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'}`)}>
|
|
325
|
+
<CapSlideBox
|
|
326
|
+
header={
|
|
327
|
+
<SlideBoxHeader
|
|
328
|
+
messages={this.props.messages}
|
|
329
|
+
slidBoxContent={this.state.slidBoxContent}
|
|
330
|
+
templateData={templateData}
|
|
331
|
+
onShowTemplates={this.onShowTemplates}
|
|
332
|
+
creativesMode={creativesMode}
|
|
333
|
+
isFullMode={isFullMode}
|
|
334
|
+
isLoadingContent={isLoadingContent}
|
|
335
|
+
showPrefix={!isUploading} // not show back button when email template is being uploaded
|
|
336
|
+
/>
|
|
337
|
+
}
|
|
338
|
+
content={
|
|
339
|
+
<SlideBoxContent
|
|
340
|
+
onSelectTemplate={this.onSelectTemplate}
|
|
341
|
+
onPreviewTemplate={this.onPreviewTemplate}
|
|
342
|
+
slidBoxContent={slidBoxContent}
|
|
343
|
+
templateData={templateData}
|
|
344
|
+
location={this.props.location}
|
|
345
|
+
messageDetails={this.props.messageDetails}
|
|
346
|
+
getFormData={this.getFormData}
|
|
347
|
+
onCallTaskSubmit={this.onCallTaskSubmit}
|
|
348
|
+
onCreateNew={this.onCreateNew}
|
|
349
|
+
isGetFormData={isGetFormData}
|
|
350
|
+
isFullMode={isFullMode}
|
|
351
|
+
currentChannel={currentChannel.toUpperCase()}
|
|
352
|
+
onChannelChange={this.onChannelChange}
|
|
353
|
+
onEmailModeChange={this.onEmailModeChange}//used when create is clicked in email
|
|
354
|
+
emailCreateMode={emailCreateMode}// upload zip || use editor are values
|
|
355
|
+
templateStep={this.creativesTemplateSteps[templateStep]}
|
|
356
|
+
onCreateNextStep={this.onCreateNextStep}
|
|
357
|
+
onResetStep={this.resetStep}
|
|
358
|
+
cap={cap}
|
|
359
|
+
setIsLoadingContent={this.setIsLoadingContent}
|
|
360
|
+
onMobilepushModeChange={this.onMobilepushModeChange}
|
|
361
|
+
mobilePushCreateMode={mobilePushCreateMode}
|
|
362
|
+
/>
|
|
363
|
+
}
|
|
364
|
+
footer={this.shouldShowFooter() &&
|
|
365
|
+
<SlideBoxFooter
|
|
366
|
+
messages={this.props.messages}
|
|
367
|
+
onSave={this.saveMessage}
|
|
368
|
+
onEditTemplate={this.onEditTemplate}
|
|
369
|
+
slidBoxContent={slidBoxContent}
|
|
370
|
+
onCreateNextStep={this.onCreateNextStep}
|
|
371
|
+
currentChannel={currentChannel.toUpperCase()}
|
|
372
|
+
templateStep={this.creativesTemplateSteps[templateStep]}
|
|
373
|
+
emailCreateMode={emailCreateMode}
|
|
374
|
+
shouldShowContinueFooter={this.shouldShowContinueFooter}
|
|
375
|
+
shouldShowDoneFooter={this.shouldShowDoneFooter}
|
|
376
|
+
/>
|
|
377
|
+
}
|
|
378
|
+
handleClose={this.handleCloseSlideBox}
|
|
379
|
+
show={showSlideBox}
|
|
380
|
+
size="size-l"
|
|
381
|
+
/>
|
|
382
|
+
</div>
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
Creatives.propTypes = {
|
|
388
|
+
getCreativesData: PropTypes.func,
|
|
389
|
+
messages: PropTypes.object,
|
|
390
|
+
messageDetails: PropTypes.object,
|
|
391
|
+
creativesMode: PropTypes.string,
|
|
392
|
+
location: PropTypes.object,
|
|
393
|
+
handleCloseCreatives: PropTypes.func,
|
|
394
|
+
templateData: PropTypes.object,
|
|
395
|
+
isFullMode: PropTypes.bool,
|
|
396
|
+
channel: PropTypes.string,
|
|
397
|
+
templateActions: PropTypes.object,
|
|
398
|
+
globalActions: PropTypes.object,
|
|
399
|
+
cap: PropTypes.object,
|
|
400
|
+
// isLoading: PropTypes.bool,
|
|
401
|
+
templateUserList: PropTypes.array,
|
|
402
|
+
isUploading: PropTypes.bool,
|
|
403
|
+
EmailLayout: PropTypes.string,
|
|
404
|
+
};
|
|
405
|
+
const mapStatesToProps = () => createStructuredSelector({
|
|
406
|
+
isLoading: isLoadingSelector(),
|
|
407
|
+
templateUserList: templateUserList(),
|
|
408
|
+
EmailLayout: selectEmailLayout(),
|
|
409
|
+
isUploading: uploadSelector(),
|
|
410
|
+
});
|
|
411
|
+
function mapDispatchToProps(dispatch) {
|
|
412
|
+
return {
|
|
413
|
+
templateActions: bindActionCreators(templateActions, dispatch),
|
|
414
|
+
globalActions: bindActionCreators(globalActions, dispatch),
|
|
415
|
+
actions: bindActionCreators(actions, dispatch),
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
export default connect(mapStatesToProps, mapDispatchToProps)(injectIntl(Creatives));
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
@import '~@capillarytech/cap-ui-library/styles/_variables.scss';
|
|
2
|
+
|
|
3
|
+
$classPrefix: add-creatives-section;
|
|
4
|
+
|
|
5
|
+
.#{$classPrefix} {
|
|
6
|
+
&.creatives-library-mode{
|
|
7
|
+
.sms-create-container, .sms-email-container{
|
|
8
|
+
.ant-tabs-top-bar{
|
|
9
|
+
display: none;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
.#{$classPrefix}-footer {
|
|
14
|
+
position: absolute;
|
|
15
|
+
bottom: 0;
|
|
16
|
+
left: 1px;
|
|
17
|
+
padding: 0 12px;
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
height: 48px;
|
|
21
|
+
border-top: 1px solid $CAP_G07;
|
|
22
|
+
|
|
23
|
+
&.with-creative {
|
|
24
|
+
width: 100%;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* EmailWrapper Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the EmailWrapper component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
header: {
|
|
10
|
+
id: 'app.containers.EmailWrapper.header',
|
|
11
|
+
defaultMessage: 'This is EmailWrapper container !',
|
|
12
|
+
},
|
|
13
|
+
continue: {
|
|
14
|
+
id: 'app.containers.EmailWrapper.continue',
|
|
15
|
+
defaultMessage: 'Continue',
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* CreativesContainer reducer
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { fromJS } from 'immutable';
|
|
8
|
+
import {
|
|
9
|
+
DEFAULT_ACTION,
|
|
10
|
+
SHOW_CONTANER_LOADER,
|
|
11
|
+
HIDE_CONTAINER_LOADER,
|
|
12
|
+
} from './constants';
|
|
13
|
+
|
|
14
|
+
const initialState = fromJS({containerLoader: true});
|
|
15
|
+
|
|
16
|
+
function creativesContainerReducer(state = initialState, action) {
|
|
17
|
+
switch (action.type) {
|
|
18
|
+
case DEFAULT_ACTION:
|
|
19
|
+
return state;
|
|
20
|
+
case SHOW_CONTANER_LOADER:
|
|
21
|
+
return state.set('containerLoader', true);
|
|
22
|
+
case HIDE_CONTAINER_LOADER:
|
|
23
|
+
return state.set('containerLoader', false);
|
|
24
|
+
default:
|
|
25
|
+
return state;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default creativesContainerReducer;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// import { take, call, put, select } from 'redux-saga/effects';
|
|
2
|
+
|
|
3
|
+
// Individual exports for testing
|
|
4
|
+
export function* defaultSaga() {
|
|
5
|
+
// See example in containers/HomePage/sagas.js
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// All sagas to be loaded
|
|
9
|
+
export default [
|
|
10
|
+
defaultSaga,
|
|
11
|
+
];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createSelector } from 'reselect';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Direct selector to the creativesContainer state domain
|
|
5
|
+
*/
|
|
6
|
+
const selectCreativesContainerDomain = () => (state) => state.get('creativesContainer');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Other specific selectors
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default selector used by CreativesContainer
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const makeSelectCreativesContainer = () => createSelector(
|
|
18
|
+
selectCreativesContainerDomain(),
|
|
19
|
+
(substate) => substate.toJS()
|
|
20
|
+
);
|
|
21
|
+
const isLoading = () => createSelector(
|
|
22
|
+
makeSelectCreativesContainer(),
|
|
23
|
+
(substate) => substate.containerLoader
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export default makeSelectCreativesContainer;
|
|
27
|
+
export {
|
|
28
|
+
selectCreativesContainerDomain,
|
|
29
|
+
isLoading,
|
|
30
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import {
|
|
3
|
+
defaultAction,
|
|
4
|
+
} from '../actions';
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_ACTION,
|
|
7
|
+
} from '../constants';
|
|
8
|
+
|
|
9
|
+
describe('CreativesContainer actions', () => {
|
|
10
|
+
describe('Default Action', () => {
|
|
11
|
+
it('has a type of DEFAULT_ACTION', () => {
|
|
12
|
+
const expected = {
|
|
13
|
+
type: DEFAULT_ACTION,
|
|
14
|
+
};
|
|
15
|
+
expect(defaultAction()).toEqual(expected);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// import React from 'react';
|
|
2
|
+
// import { shallow } from 'enzyme';
|
|
3
|
+
|
|
4
|
+
// import { CreativesContainer } from '../index';
|
|
5
|
+
|
|
6
|
+
describe('<CreativesContainer />', () => {
|
|
7
|
+
it('Expect to have unit tests specified', () => {
|
|
8
|
+
expect(true).toEqual(true);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
import { fromJS } from 'immutable';
|
|
3
|
+
import creativesContainerReducer from '../reducer';
|
|
4
|
+
|
|
5
|
+
describe('creativesContainerReducer', () => {
|
|
6
|
+
it('returns the initial state', () => {
|
|
7
|
+
expect(creativesContainerReducer(undefined, {})).toEqual(fromJS({}));
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test sagas
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* eslint-disable redux-saga/yield-effects */
|
|
6
|
+
// import { take, call, put, select } from 'redux-saga/effects';
|
|
7
|
+
// import { defaultSaga } from '../sagas';
|
|
8
|
+
|
|
9
|
+
// const generator = defaultSaga();
|
|
10
|
+
|
|
11
|
+
describe('defaultSaga Saga', () => {
|
|
12
|
+
it('Expect to have unit tests specified', () => {
|
|
13
|
+
expect(true).toEqual(true);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// import { fromJS } from 'immutable';
|
|
2
|
+
// import { makeSelectCreativesContainerDomain } from '../selectors';
|
|
3
|
+
|
|
4
|
+
// const selector = makeSelectCreativesContainerDomain();
|
|
5
|
+
|
|
6
|
+
describe('makeSelectCreativesContainerDomain', () => {
|
|
7
|
+
it('Expect to have unit tests specified', () => {
|
|
8
|
+
expect(true).toEqual(true);
|
|
9
|
+
});
|
|
10
|
+
});
|