@capillarytech/creatives-library 3.4.5 → 3.4.6

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 (45) hide show
  1. package/config/app.js +2 -0
  2. package/containers/Sms/Create/messages.js +1 -1
  3. package/containers/Sms/Edit/messages.js +1 -1
  4. package/containers/WeChat/MapTemplates/messages.js +1 -1
  5. package/index.js +6 -0
  6. package/initialState.js +3 -0
  7. package/package.json +2 -1
  8. package/routes.js +6 -1
  9. package/services/api.js +25 -9
  10. package/translations/en.json +61 -5
  11. package/translations/zh.json +56 -0
  12. package/v2Components/MarketingObjective/MarketingObjective.style.js +73 -0
  13. package/v2Components/MarketingObjective/index.js +107 -0
  14. package/v2Components/MarketingObjective/messages.js +23 -0
  15. package/v2Components/NavigationBar/index.js +5 -10
  16. package/v2Components/NavigationBar/messages.js +28 -0
  17. package/v2Containers/App/constants.js +30 -0
  18. package/v2Containers/Cap/index.js +5 -0
  19. package/v2Containers/CreativesContainer/SlideBoxContent.js +18 -0
  20. package/v2Containers/CreativesContainer/constants.js +1 -0
  21. package/v2Containers/CreativesContainer/index.js +10 -1
  22. package/v2Containers/Email/index.js +9 -1
  23. package/v2Containers/Email/messages.js +8 -0
  24. package/v2Containers/EmailWrapper/index.js +15 -1
  25. package/v2Containers/Facebook/Facebook.style.js +75 -0
  26. package/v2Containers/Facebook/actions.js +13 -0
  27. package/v2Containers/Facebook/constants.js +25 -0
  28. package/v2Containers/Facebook/index.js +358 -0
  29. package/v2Containers/Facebook/messages.js +167 -0
  30. package/v2Containers/Facebook/reducer.js +31 -0
  31. package/v2Containers/Facebook/sagas.js +41 -0
  32. package/v2Containers/Facebook/selectors.js +20 -0
  33. package/v2Containers/MobilePush/Create/index.js +8 -0
  34. package/v2Containers/MobilePush/Edit/index.js +8 -0
  35. package/v2Containers/Sms/Create/_smsCreate.scss +3 -0
  36. package/v2Containers/Sms/Create/index.js +6 -1
  37. package/v2Containers/Sms/Create/messages.js +2 -2
  38. package/v2Containers/Sms/Edit/index.js +6 -1
  39. package/v2Containers/Sms/Edit/messages.js +2 -2
  40. package/v2Containers/Templates/index.js +9 -3
  41. package/v2Containers/TemplatesV2/index.js +53 -22
  42. package/v2Containers/TemplatesV2/messages.js +4 -0
  43. package/v2Containers/WeChat/MapTemplates/index.js +9 -1
  44. package/v2Containers/WeChat/RichmediaTemplates/Create/index.js +9 -2
  45. package/v2Containers/WeChat/RichmediaTemplates/Create/messages.js +1 -1
@@ -0,0 +1,358 @@
1
+ /*
2
+ *
3
+ * Facebook
4
+ *
5
+ */
6
+ import PropTypes from "prop-types";
7
+ import React, { useState, useEffect } from "react";
8
+ import { injectIntl, FormattedMessage, intlShape } from "react-intl";
9
+ import {
10
+ CapHeading,
11
+ CapLabel,
12
+ CapRow,
13
+ CapColumn,
14
+ CapButton,
15
+ CapDrawer,
16
+ CapCustomCard,
17
+ CapIcon,
18
+ } from '@capillarytech/cap-ui-library';
19
+ import { createStructuredSelector } from 'reselect';
20
+ import { connect } from 'react-redux';
21
+ import { bindActionCreators } from 'redux';
22
+ import messages from "./messages";
23
+ import styles, { CampaignDetailCapColumn } from './Facebook.style';
24
+ import * as actions from './actions';
25
+ import withStyles from '../../hoc/withStyles';
26
+ import MarketingObjective from '../../v2Components/MarketingObjective';
27
+ import { makeSelectMarketingObjectiveList } from './selectors';
28
+ import {
29
+ VALUE_APP_INSTALLS,
30
+ VALUE_BRAND_AWARENESS,
31
+ VALUE_CONVERSIONS,
32
+ VALUE_LEAD_GENERATION,
33
+ VALUE_LOCAL_AWARENESS,
34
+ VALUE_MESSAGES,
35
+ VALUE_POST_ENGAGEMENT,
36
+ VALUE_PRODUCT_CATALOG_SALES,
37
+ VALUE_REACH,
38
+ VALUE_VIDEO_VIEWS,
39
+ VALUE_LINK_CLICKS,
40
+ } from './constants';
41
+
42
+ const StyledCampaignDetailCapColumn = withStyles(CapColumn, CampaignDetailCapColumn);
43
+
44
+ const panesMapList = {
45
+ [VALUE_APP_INSTALLS]: 'fbMarketingObjectiveAppInstallTitle',
46
+ [VALUE_BRAND_AWARENESS]: 'fbMarketingObjectiveBrandAwarenessTitle',
47
+ [VALUE_CONVERSIONS]: 'fbMarketingObjectiveConversionsTitle',
48
+ [VALUE_LEAD_GENERATION]: 'fbMarketingObjectiveLeadGenerationTitle',
49
+ [VALUE_LOCAL_AWARENESS]: 'fbMarketingObjectiveStoreTrafficTitle',
50
+ [VALUE_MESSAGES]: 'fbMarketingObjectiveMessagesTitle',
51
+ [VALUE_POST_ENGAGEMENT]: 'fbMarketingObjectiveEngagementTitle',
52
+ [VALUE_PRODUCT_CATALOG_SALES]: 'fbMarketingObjectiveCatalogSalesTitle',
53
+ [VALUE_REACH]: 'fbMarketingObjectiveReachTitle',
54
+ [VALUE_VIDEO_VIEWS]: 'fbMarketingObjectiveVideoViewsTitle',
55
+ [VALUE_LINK_CLICKS]: 'fbMarketingObjectiveTrafficTitle',
56
+ };
57
+
58
+ const getCategorizedMarketingObjectiveList = (marketingObjectivesList, formatMessage) => {
59
+ const marketingObjectives = [
60
+ {
61
+ label: formatMessage(messages.fbMarketingObjectiveAwareness),
62
+ panes: [
63
+ {
64
+ title: formatMessage(messages.fbMarketingObjectiveBrandAwarenessTitle),
65
+ content: formatMessage(messages.fbMarketingObjectiveBrandAwarenessDescription),
66
+ value: VALUE_BRAND_AWARENESS,
67
+ icon: <CapIcon type="speaker" />,
68
+ },
69
+ {
70
+ title: formatMessage(messages.fbMarketingObjectiveReachTitle),
71
+ content: formatMessage(messages.fbMarketingObjectiveReachDescription),
72
+ value: VALUE_REACH,
73
+ icon: <CapIcon type="connect" />,
74
+ },
75
+ ],
76
+ },
77
+ {
78
+ label: formatMessage(messages.fbMarketingObjectiveConsideration),
79
+ panes: [
80
+ {
81
+ title: formatMessage(messages.fbMarketingObjectiveTrafficTitle),
82
+ content: formatMessage(messages.fbMarketingObjectiveTrafficDescription),
83
+ value: VALUE_LINK_CLICKS,
84
+ icon: <CapIcon type="pointer" />,
85
+ },
86
+ {
87
+ title: formatMessage(messages.fbMarketingObjectiveEngagementTitle),
88
+ content: formatMessage(messages.fbMarketingObjectiveEngagementDescription),
89
+ value: VALUE_POST_ENGAGEMENT,
90
+ icon: <CapIcon type="group-chat" />,
91
+ },
92
+ {
93
+ title: formatMessage(messages.fbMarketingObjectiveAppInstallTitle),
94
+ content: formatMessage(messages.fbMarketingObjectiveAppInstallDescription),
95
+ value: VALUE_APP_INSTALLS,
96
+ icon: <CapIcon type="apps" />,
97
+ },
98
+ {
99
+ title: formatMessage(messages.fbMarketingObjectiveVideoViewsTitle),
100
+ content: formatMessage(messages.fbMarketingObjectiveVideoViewsDescription),
101
+ value: VALUE_VIDEO_VIEWS,
102
+ icon: <CapIcon type="video" />,
103
+ },
104
+ {
105
+ title: formatMessage(messages.fbMarketingObjectiveLeadGenerationTitle),
106
+ content: formatMessage(messages.fbMarketingObjectiveLeadGenerationDescription),
107
+ value: VALUE_LEAD_GENERATION,
108
+ icon: <CapIcon type="funnel" />,
109
+ },
110
+ {
111
+ title: formatMessage(messages.fbMarketingObjectiveMessagesTitle),
112
+ content: formatMessage(messages.fbMarketingObjectiveMessagesDescription),
113
+ value: VALUE_MESSAGES,
114
+ icon: <CapIcon type="message-filled" />,
115
+ },
116
+ ],
117
+ },
118
+ {
119
+ label: formatMessage(messages.fbMarketingObjectiveConversionsTitle),
120
+ panes: [
121
+ {
122
+ title: formatMessage(messages.fbMarketingObjectiveConversionsTitle),
123
+ content: formatMessage(messages.fbMarketingObjectiveConversionsDescription),
124
+ value: VALUE_CONVERSIONS,
125
+ icon: <CapIcon type="global" style={{fontSize: 20 }}/>,
126
+ },
127
+ {
128
+ title: formatMessage(messages.fbMarketingObjectiveCatalogSalesTitle),
129
+ content: formatMessage(messages.fbMarketingObjectiveCatalogSalesDescription),
130
+ value: VALUE_PRODUCT_CATALOG_SALES,
131
+ icon: <CapIcon type="basket" />,
132
+ },
133
+ {
134
+ title: formatMessage(messages.fbMarketingObjectiveStoreTrafficTitle),
135
+ content: formatMessage(messages.fbMarketingObjectiveStoreTrafficDescription),
136
+ value: VALUE_LOCAL_AWARENESS,
137
+ icon: <CapIcon type="store-traffic" />,
138
+ },
139
+ ],
140
+ },
141
+ ];
142
+
143
+ return marketingObjectives.map(({ label, panes }) => ({
144
+ label,
145
+ panes: panes.filter((pane) => !!marketingObjectivesList.includes(pane.value)),
146
+ }));
147
+ };
148
+
149
+ const Facebook = (props) => {
150
+ const {
151
+ className,
152
+ templateData: {
153
+ selectedMarketingObjective: fbMarketingObjectiveValue = VALUE_REACH,
154
+ } = {},
155
+ cap: {
156
+ campaignDetails: {
157
+ name: fbCampaignValue,
158
+ socialRemoteCampaignId,
159
+ socialObjective,
160
+ } = {},
161
+ orgSettings: {
162
+ accountSettings: {
163
+ socialAccountSettings: {
164
+ facebookAccountSettings: [{
165
+ accountName,
166
+ accountId,
167
+ }] = [{}],
168
+ } = {},
169
+ } = {},
170
+ } = {},
171
+ } = {},
172
+ messageDetails: {
173
+ name: fbAdSetValue,
174
+ targetAudience: {
175
+ label: fbAudienceValue,
176
+ } = {},
177
+ } = {},
178
+ onFacebookSubmit,
179
+ marketingObjectiveList,
180
+ facebookActions,
181
+ intl,
182
+ } = props;
183
+
184
+ const [isDrawerVisible, setDrawerVisibility] = useState(false);
185
+ const [selectedMarketingObjective, setMarketingObjective] = useState(socialObjective || fbMarketingObjectiveValue);
186
+
187
+ useEffect(() => {
188
+ facebookActions.getMarketingObjectives();
189
+ }, []);
190
+
191
+ const categorizedMarketingObjectiveList = getCategorizedMarketingObjectiveList(marketingObjectiveList, intl.formatMessage);
192
+
193
+ const campaignDataList = [
194
+ {
195
+ label: 'fbCampaignName',
196
+ value: fbCampaignValue,
197
+ },
198
+ {
199
+ label: 'fbMarketingObjective',
200
+ value: selectedMarketingObjective ? intl.formatMessage(messages[panesMapList[selectedMarketingObjective]]) : '',
201
+ onChange: () => setDrawerVisibility(!isDrawerVisible),
202
+ },
203
+ {
204
+ label: 'fbAdSetName',
205
+ value: fbAdSetValue,
206
+ },
207
+ {
208
+ label: 'fbAudience',
209
+ value: fbAudienceValue || <FormattedMessage {...messages.fbNoAudienceSelected} />,
210
+ },
211
+ ];
212
+
213
+ const adSetParameters = ['fbAdsDetailOne', 'fbAdsDetailTwo', 'fbAdsDetailThree'];
214
+
215
+ const onMarketingObjectiveSelect = (value) => setMarketingObjective(value);
216
+
217
+ return (
218
+ <div className={className}>
219
+ <div className="is-scrollable-section">
220
+ <div className="account-details-wrapper">
221
+ <div className="account-name-section">
222
+ <CapHeading type="h4">
223
+ <FormattedMessage {...messages.fbAccount} />
224
+ </CapHeading>
225
+ <CapHeading type="h3">{accountName}</CapHeading>
226
+ </div>
227
+
228
+ <div className="account-section-container">
229
+ <CapHeading type="h3">
230
+ <FormattedMessage {...messages.fbAdCampaignSetDetailsTitle} />
231
+ </CapHeading>
232
+ <CapLabel type="label1">
233
+ <FormattedMessage
234
+ {...messages.fbAdCampaignSetDetailsDescription}
235
+ />
236
+ </CapLabel>
237
+ </div>
238
+
239
+ <CapRow span={12} type="flex">
240
+ {campaignDataList.map(({ label, value, onChange }, index) => (
241
+ <StyledCampaignDetailCapColumn
242
+ span={index % 2 === 0 ? 6 : 14}
243
+ key={label}
244
+ >
245
+ <CapRow>
246
+ <CapLabel type="label2">
247
+ <FormattedMessage {...messages[label]} />
248
+ </CapLabel>
249
+ <CapHeading type="h4">
250
+ {value}
251
+ {!socialRemoteCampaignId && onChange && (
252
+ <CapButton
253
+ type="flat"
254
+ className="marketingObjective-change-button"
255
+ onClick={onChange}
256
+ >
257
+ <FormattedMessage {...messages.fbChange} />
258
+ </CapButton>
259
+ )}
260
+ </CapHeading>
261
+ </CapRow>
262
+ </StyledCampaignDetailCapColumn>
263
+ ))}
264
+ </CapRow>
265
+ <CapDrawer
266
+ content={
267
+ <MarketingObjective
268
+ selectedMarketingObjective={selectedMarketingObjective}
269
+ onMarketingObjectiveSelect={onMarketingObjectiveSelect}
270
+ defaultmarketingObjective={socialObjective || fbMarketingObjectiveValue}
271
+ onSubmit={setDrawerVisibility}
272
+ marketingObjectiveList={categorizedMarketingObjectiveList}
273
+ />
274
+ }
275
+ visible={isDrawerVisible}
276
+ width={372}
277
+ onClose={() => setDrawerVisibility(false)}
278
+ />
279
+ </div>
280
+
281
+ <div className="ad-section">
282
+ <div className="account-section-container">
283
+ <CapHeading type="h3">
284
+ <FormattedMessage {...messages.fbAdsTitle} />
285
+ </CapHeading>
286
+ <CapLabel type="label1">
287
+ <FormattedMessage {...messages.fbAdsDescription} />
288
+ </CapLabel>
289
+ </div>
290
+
291
+ <div>
292
+ <CapRow span={12} type="flex">
293
+ <CapColumn span={6}>
294
+ <CapCustomCard
295
+ type="Facebook"
296
+ FBDynamicComponent={() => (
297
+ <CapIcon
298
+ size="l"
299
+ type="scenery"
300
+ className="facebook-dynamic-content"
301
+ />
302
+ )}
303
+ />
304
+ </CapColumn>
305
+ <CapColumn span={16}>
306
+ <ul className="parameter-list">
307
+ {adSetParameters.map((parameter, index) => (
308
+ <li key={parameter} className="parameter-list-item">
309
+ <CapLabel type="label2" className="parameter-index">
310
+ {index + 1}
311
+ </CapLabel>
312
+ <CapHeading type="h5">
313
+ <FormattedMessage {...messages[parameter]} />
314
+ </CapHeading>
315
+ </li>
316
+ ))}
317
+ </ul>
318
+ </CapColumn>
319
+ </CapRow>
320
+ </div>
321
+ </div>
322
+ </div>
323
+ <CapButton
324
+ type="primary"
325
+ onClick={() =>
326
+ onFacebookSubmit({ channel: "FACEBOOK", selectedMarketingObjective, accountId })
327
+ }
328
+ >
329
+ <FormattedMessage {...messages.fbConfirm} />
330
+ </CapButton>
331
+ </div>
332
+ );
333
+ };
334
+
335
+ Facebook.propTypes = {
336
+ className: PropTypes.string.isRequired,
337
+ templateData: PropTypes.object,
338
+ cap: PropTypes.object,
339
+ messageDetails: PropTypes.object,
340
+ onFacebookSubmit: PropTypes.func.isRequired,
341
+ marketingObjectiveList: PropTypes.arrayOf(PropTypes.string),
342
+ facebookActions: PropTypes.func.isRequired,
343
+ intl: intlShape.isRequired,
344
+ };
345
+
346
+ Facebook.defaultProps = {
347
+ marketingObjectiveList: [],
348
+ };
349
+
350
+ const mapStateToProps = createStructuredSelector({
351
+ marketingObjectiveList: makeSelectMarketingObjectiveList(),
352
+ });
353
+
354
+ const mapDispatchToProps = (dispatch) => ({
355
+ facebookActions: bindActionCreators(actions, dispatch),
356
+ });
357
+
358
+ export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(withStyles(Facebook, styles)));
@@ -0,0 +1,167 @@
1
+ /*
2
+ * Facebook Messages
3
+ *
4
+ * This contains all the text for the Facebook component.
5
+ */
6
+ import { defineMessages } from 'react-intl';
7
+
8
+ const messagePrefix = 'creatives.containersV2.Facebook';
9
+
10
+ export default defineMessages({
11
+ fbAccount: {
12
+ id: `${messagePrefix}.fbAccount`,
13
+ defaultMessage: 'Facebook Account',
14
+ },
15
+ fbAdCampaignSetDetailsTitle: {
16
+ id: `${messagePrefix}.fbAdCampaignSetDetailsTitle`,
17
+ defaultMessage: 'Ad campaign & ad set details',
18
+ },
19
+ fbAdCampaignSetDetailsDescription: {
20
+ id: `${messagePrefix}.fbAdCampaignSetDetailsDescription`,
21
+ defaultMessage: 'Once this message is approved, a campaign and an ad set will be created on Facebook Ad Manager with the same name as the current campaign and message name.',
22
+ },
23
+ fbCampaignName: {
24
+ id: `${messagePrefix}.fbCampaignName`,
25
+ defaultMessage: 'FB Campaign name',
26
+ },
27
+ fbMarketingObjective: {
28
+ id: `${messagePrefix}.fbMarketingObjective`,
29
+ defaultMessage: 'FB Marketing objective',
30
+ },
31
+ fbAdSetName: {
32
+ id: `${messagePrefix}.fbAdSetName`,
33
+ defaultMessage: 'Ad set name',
34
+ },
35
+ fbAudience: {
36
+ id: `${messagePrefix}.fbAudience`,
37
+ defaultMessage: 'Audience',
38
+ },
39
+ fbAdsTitle: {
40
+ id: `${messagePrefix}.fbAdsTitle`,
41
+ defaultMessage: 'Facebook ads',
42
+ },
43
+ fbAdsDescription: {
44
+ id: `${messagePrefix}.fbAdsDescription`,
45
+ defaultMessage: 'You may create ads in Facebook Ad Manager under the below mentioned ad set. The performance of these ads will be reported here in Engage+.',
46
+ },
47
+ fbAdsDetailOne: {
48
+ id: `${messagePrefix}.fbAdsDetailOne`,
49
+ defaultMessage: 'Only FB campaign & ad set creation is supported in Engage+',
50
+ },
51
+ fbAdsDetailTwo: {
52
+ id: `${messagePrefix}.fbAdsDetailTwo`,
53
+ defaultMessage: 'You can proceed with an empty content block',
54
+ },
55
+ fbAdsDetailThree: {
56
+ id: `${messagePrefix}.fbAdsDetailThree`,
57
+ defaultMessage: 'You can create ads later in Facebook ad manager.',
58
+ },
59
+ fbConfirm: {
60
+ id: `${messagePrefix}.fbConfirm`,
61
+ defaultMessage: 'Confirm',
62
+ },
63
+ fbChange: {
64
+ id: `${messagePrefix}.fbChange`,
65
+ defaultMessage: 'Change',
66
+ },
67
+ fbNoAudienceSelected: {
68
+ id: `${messagePrefix}.fbNoAudienceSelected`,
69
+ defaultMessage: 'Not Selected',
70
+ },
71
+ fbMarketingObjectiveAwareness: {
72
+ id: `${messagePrefix}.fbMarketingObjectiveAwareness`,
73
+ defaultMessage: 'Awareness',
74
+ },
75
+ fbMarketingObjectiveBrandAwarenessTitle: {
76
+ id: `${messagePrefix}.fbMarketingObjectiveBrandAwarenessTitle`,
77
+ defaultMessage: 'Brand awareness',
78
+ },
79
+ fbMarketingObjectiveBrandAwarenessDescription: {
80
+ id: `${messagePrefix}.fbMarketingObjectiveBrandAwarenessDescription`,
81
+ defaultMessage: 'Increase awareness for your brand by reaching people who are more likely to be interested in it.',
82
+ },
83
+ fbMarketingObjectiveReachTitle: {
84
+ id: `${messagePrefix}.fbMarketingObjectiveReachTitle`,
85
+ defaultMessage: 'Reach',
86
+ },
87
+ fbMarketingObjectiveReachDescription: {
88
+ id: `${messagePrefix}.fbMarketingObjectiveReachDescription`,
89
+ defaultMessage: 'Show your ad to the maximum number of people.',
90
+ },
91
+ fbMarketingObjectiveConsideration: {
92
+ id: `${messagePrefix}.fbMarketingObjectiveConsideration`,
93
+ defaultMessage: 'Consideration',
94
+ },
95
+ fbMarketingObjectiveTrafficTitle: {
96
+ id: `${messagePrefix}.fbMarketingObjectiveTrafficTitle`,
97
+ defaultMessage: 'Traffic',
98
+ },
99
+ fbMarketingObjectiveTrafficDescription: {
100
+ id: `${messagePrefix}.fbMarketingObjectiveTrafficDescription`,
101
+ defaultMessage: 'Send more people to a destination such as a website, app or Messenger conversation.',
102
+ },
103
+ fbMarketingObjectiveEngagementTitle: {
104
+ id: `${messagePrefix}.fbMarketingObjectiveEngagementTitle`,
105
+ defaultMessage: 'Engagement',
106
+ },
107
+ fbMarketingObjectiveEngagementDescription: {
108
+ id: `${messagePrefix}.fbMarketingObjectiveEngagementDescription`,
109
+ defaultMessage: 'Get more post engagements',
110
+ },
111
+ fbMarketingObjectiveAppInstallTitle: {
112
+ id: `${messagePrefix}.fbMarketingObjectiveAppInstallTitle`,
113
+ defaultMessage: 'App Installs',
114
+ },
115
+ fbMarketingObjectiveAppInstallDescription: {
116
+ id: `${messagePrefix}.fbMarketingObjectiveAppInstallsDescription`,
117
+ defaultMessage: 'Get more people to install your app.',
118
+ },
119
+ fbMarketingObjectiveVideoViewsTitle: {
120
+ id: `${messagePrefix}.fbMarketingObjectiveVideoViewsTitle`,
121
+ defaultMessage: 'Video Views',
122
+ },
123
+ fbMarketingObjectiveVideoViewsDescription: {
124
+ id: `${messagePrefix}.fbMarketingObjectiveVideoViewsDescription`,
125
+ defaultMessage: 'Get more people to view your video content.',
126
+ },
127
+ fbMarketingObjectiveLeadGenerationTitle: {
128
+ id: `${messagePrefix}.fbMarketingObjectiveLeadGenerationTitle`,
129
+ defaultMessage: 'Lead Generation',
130
+ },
131
+ fbMarketingObjectiveLeadGenerationDescription: {
132
+ id: `${messagePrefix}.fbMarketingObjectiveLeadGenerationDescription`,
133
+ defaultMessage: 'Drive more sales leads, such as email addresses, from people interested in your brand or business.',
134
+ },
135
+ fbMarketingObjectiveMessagesTitle: {
136
+ id: `${messagePrefix}.fbMarketingObjectiveMessagesTitle`,
137
+ defaultMessage: 'Messages',
138
+ },
139
+ fbMarketingObjectiveMessagesDescription: {
140
+ id: `${messagePrefix}.fbMarketingObjectiveMessagesDescription`,
141
+ defaultMessage: 'Get more people to send messages to your business in Messenger.',
142
+ },
143
+ fbMarketingObjectiveConversionsTitle: {
144
+ id: `${messagePrefix}.fbMarketingObjectiveConversionsTitle`,
145
+ defaultMessage: 'Conversions',
146
+ },
147
+ fbMarketingObjectiveConversionsDescription: {
148
+ id: `${messagePrefix}.fbMarketingObjectiveConversionsDescription`,
149
+ defaultMessage: 'Drive valuable actions on your website, app or in Messenger.',
150
+ },
151
+ fbMarketingObjectiveCatalogSalesTitle: {
152
+ id: `${messagePrefix}.fbMarketingObjectiveCatalogSalesTitle`,
153
+ defaultMessage: 'Catalog Sales',
154
+ },
155
+ fbMarketingObjectiveCatalogSalesDescription: {
156
+ id: `${messagePrefix}.fbMarketingObjectiveCatalogSalesDescription`,
157
+ defaultMessage: 'Create ads that automatically show items from your catalog based on your target audience.',
158
+ },
159
+ fbMarketingObjectiveStoreTrafficTitle: {
160
+ id: `${messagePrefix}.fbMarketingObjectiveStoreTrafficTitle`,
161
+ defaultMessage: 'Store Traffic',
162
+ },
163
+ fbMarketingObjectiveStoreTrafficDescription: {
164
+ id: `${messagePrefix}.fbMarketingObjectiveStoreTrafficDescription`,
165
+ defaultMessage: 'Drive visits to your physical stores by showing ads to people who are nearby.',
166
+ },
167
+ });
@@ -0,0 +1,31 @@
1
+ /*
2
+ *
3
+ * Faceboook reducer
4
+ *
5
+ */
6
+
7
+ import { fromJS } from 'immutable';
8
+ import {
9
+ SET_MARKETING_OBJECTIVES_SUCCESS,
10
+ SET_MARKETING_OBJECTIVES_FAILURE,
11
+ } from './constants';
12
+
13
+ export const initialState = fromJS({
14
+ marketinObjectives: {},
15
+ });
16
+
17
+ function facebookReducer(state = initialState, action) {
18
+ const { type, payload } = action;
19
+ switch (type) {
20
+ case SET_MARKETING_OBJECTIVES_SUCCESS: {
21
+ return state.set('marketinObjectivesData', payload).set('marketinObjectivesError', null);
22
+ }
23
+ case SET_MARKETING_OBJECTIVES_FAILURE: {
24
+ return state.set('marketinObjectivesData', []).set('marketinObjectivesError', payload);
25
+ }
26
+ default:
27
+ return state;
28
+ }
29
+ }
30
+
31
+ export default facebookReducer;
@@ -0,0 +1,41 @@
1
+ import { take, call, put, takeLatest, cancel } from 'redux-saga/effects';
2
+ import { LOCATION_CHANGE } from 'react-router-redux';
3
+ import * as Api from '../../services/api';
4
+ import {
5
+ GET_MARKETING_OBJECTIVES,
6
+ SET_MARKETING_OBJECTIVES_SUCCESS,
7
+ SET_MARKETING_OBJECTIVES_FAILURE,
8
+ } from './constants';
9
+
10
+ export function* fetchMarketingObjectives() {
11
+ try {
12
+ const response = yield call(Api.getMarketingObjectives, 'FACEBOOK');
13
+ const { errors, data } = response;
14
+ if (errors && errors.length) {
15
+ yield put({
16
+ type: SET_MARKETING_OBJECTIVES_FAILURE,
17
+ payload: errors,
18
+ });
19
+ } else {
20
+ yield put({
21
+ type: SET_MARKETING_OBJECTIVES_SUCCESS,
22
+ payload: data,
23
+ });
24
+ }
25
+ } catch (error) {
26
+ yield put({
27
+ type: SET_MARKETING_OBJECTIVES_FAILURE,
28
+ payload: error,
29
+ });
30
+ }
31
+ }
32
+
33
+ function* watchFetchMarketingObjective() {
34
+ const watcher = yield takeLatest(GET_MARKETING_OBJECTIVES, fetchMarketingObjectives);
35
+ yield take(LOCATION_CHANGE);
36
+ yield cancel(watcher);
37
+ }
38
+
39
+ export default [
40
+ watchFetchMarketingObjective,
41
+ ];
@@ -0,0 +1,20 @@
1
+ import { createSelector } from 'reselect';
2
+
3
+ /**
4
+ * Direct selector to the facebook state domain
5
+ */
6
+ const selectFacebookDomain = () => (state) => state.get('facebook');
7
+
8
+ /**
9
+ * Other specific selectors
10
+ */
11
+
12
+
13
+ /**
14
+ * Default selector used by Facebook
15
+ */
16
+
17
+ export const makeSelectMarketingObjectiveList = () => createSelector(
18
+ selectFacebookDomain(),
19
+ (substate) => substate && substate.get('marketinObjectivesData'),
20
+ );
@@ -25,6 +25,8 @@ import {getMessageObject} from '../../../utils/messageUtils';
25
25
  import { makeSelectTemplates } from '../../Templates/selectors';
26
26
  import messages from './messages';
27
27
  import getEventsMap from '../eventsMap';
28
+ import { GA } from '@capillarytech/cap-ui-utils';
29
+ import { TRACK_CREATE_MPUSH } from '../../App/constants';
28
30
 
29
31
  const PrefixWrapper = styled.div`
30
32
  margin-right: 16px;
@@ -1402,7 +1404,13 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
1402
1404
  saveFormData = (formData) => {
1403
1405
  //this function gets called from form bulder only when the form data is valid
1404
1406
  const obj = this.getTransformedData(formData);
1407
+ const label = this.props.location.pathname.indexOf('image') >= 0 ? 'image' : 'text';
1405
1408
  this.props.actions.createTemplate(obj, () => {
1409
+ GA.timeTracker.stopTimer(TRACK_CREATE_MPUSH, {
1410
+ category: 'Creatives',
1411
+ action: 'Create',
1412
+ label,
1413
+ });
1406
1414
  this.discardValues();
1407
1415
  const message = this.props.intl.formatMessage(messages.messageCreateSuccess);
1408
1416
  CapNotification.success({message, key: 'createMpushSuccess'});
@@ -29,6 +29,8 @@ import withCreatives from '../../../hoc/withCreatives';
29
29
 
30
30
  import getEventsMap from '../eventsMap';
31
31
  import {getPrimaryCtaFields, getSecondaryCtaFields, getLinkTypeFields} from '../commonMethods';
32
+ import { GA } from '@capillarytech/cap-ui-utils';
33
+ import { TRACK_EDIT_MPUSH } from '../../App/constants';
32
34
 
33
35
  const PrefixWrapper = styled.div`
34
36
  margin-right: 16px;
@@ -271,6 +273,12 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
271
273
  };
272
274
  onUpdateTemplateComplete = () => {
273
275
  console.log('reseting schema');
276
+ const label = this.props.location.pathname.indexOf('image') >= 0 ? 'image' : 'text';
277
+ GA.timeTracker.stopTimer(TRACK_EDIT_MPUSH, {
278
+ category: 'Creatives',
279
+ action: 'Edit',
280
+ label,
281
+ });
274
282
  this.resetSchema();
275
283
  this.setState({
276
284
  formData: {},
@@ -12,3 +12,6 @@
12
12
  }
13
13
  }
14
14
 
15
+ .sms-message-content .error-message{
16
+ width:75%;
17
+ }
@@ -26,7 +26,8 @@ import {SMS} from '../../CreativesContainer/constants';
26
26
  // import callNativeEvent from '../../../utils/callNativeEvent';
27
27
  import {showError} from '../commonMethods';
28
28
  import withCreatives from '../../../hoc/withCreatives';
29
-
29
+ import { GA } from '@capillarytech/cap-ui-utils';
30
+ import { TRACK_CREATE_SMS } from '../../App/constants'
30
31
  export class Create extends React.Component { // eslint-disable-line react/prefer-stateless-function
31
32
  constructor(props) {
32
33
  super(props);
@@ -201,6 +202,10 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
201
202
  this.setState({currentTab: data});
202
203
  }
203
204
  onCreateTemplateComplete = (editResponse) => {
205
+ GA.timeTracker.stopTimer(TRACK_CREATE_SMS, {
206
+ category: 'Creatives',
207
+ action: 'Create',
208
+ });
204
209
  if (editResponse.templateId) {
205
210
  this.resetSchema();
206
211
  this.setState({