@capillarytech/creatives-library 6.9.2 → 6.9.7
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/TemplatePreview/_templatePreview.scss +6 -0
- package/components/TemplatePreview/index.js +35 -28
- package/config/app.js +1 -1
- package/index.html +0 -2
- package/package.json +1 -1
- package/v2Components/Carousel/index.js +120 -0
- package/v2Components/Carousel/style.scss +40 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +1 -0
- package/v2Components/TemplatePreview/index.js +36 -29
- package/v2Containers/CreativesContainer/SlideBoxContent.js +7 -1
- package/v2Containers/Line/Container/Image/index.js +21 -19
- package/v2Containers/Line/Container/ImageCarousel/Content.js +554 -0
- package/v2Containers/Line/Container/ImageCarousel/constants.js +10 -0
- package/v2Containers/Line/Container/ImageCarousel/index.js +526 -0
- package/v2Containers/Line/Container/ImageCarousel/messages.js +178 -0
- package/v2Containers/Line/Container/ImageCarousel/style.js +61 -0
- package/v2Containers/Line/Container/ImageMap/constants.js +2 -1
- package/v2Containers/Line/Container/ImageMap/index.js +31 -6
- package/v2Containers/Line/Container/ImageMap/messages.js +12 -0
- package/v2Containers/Line/Container/Wrapper/index.js +5 -1
- package/v2Containers/Line/Container/Wrapper/messages.js +4 -0
- package/v2Containers/Line/Container/Wrapper/utils.js +15 -16
- package/v2Containers/Line/Container/_lineCreate.scss +2 -2
- package/v2Containers/Line/Container/actions.js +4 -2
- package/v2Containers/Line/Container/constants.js +3 -0
- package/v2Containers/Line/Container/index.js +49 -11
- package/v2Containers/Line/Container/reducer.js +2 -2
- package/v2Containers/Line/Container/sagas.js +2 -2
- package/v2Containers/Line/Container/style.js +2 -1
- package/v2Containers/Templates/_templates.scss +9 -0
- package/v2Containers/Templates/index.js +28 -1
- package/v2Containers/Templates/messages.js +4 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { css } from 'styled-components';
|
|
2
|
+
import {
|
|
3
|
+
CAP_G06,
|
|
4
|
+
CAP_SPACE_16,
|
|
5
|
+
CAP_SPACE_24,
|
|
6
|
+
FONT_COLOR_02,
|
|
7
|
+
} from '@capillarytech/cap-ui-library/styled/variables';
|
|
8
|
+
|
|
9
|
+
export default css`
|
|
10
|
+
padding: 0 ${CAP_SPACE_16} ${CAP_SPACE_16};
|
|
11
|
+
position: relative;
|
|
12
|
+
|
|
13
|
+
.carousel-content {
|
|
14
|
+
position: relative;
|
|
15
|
+
margin-top: 20px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.image-container {
|
|
19
|
+
background-color: ${CAP_G06};
|
|
20
|
+
margin-top: 20px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.choice-title {
|
|
24
|
+
margin-bottom: ${CAP_SPACE_24};
|
|
25
|
+
color: ${FONT_COLOR_02};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.image-template-title {
|
|
29
|
+
margin-top: ${CAP_SPACE_24};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.cap-tab-v2-wrapper {
|
|
33
|
+
.ant-tabs-bar.ant-tabs-top-bar {
|
|
34
|
+
padding: 0;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.extra-button-group {
|
|
39
|
+
button {
|
|
40
|
+
padding: 0;
|
|
41
|
+
margin-left: 6px;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.action-type-section {
|
|
46
|
+
margin: ${CAP_SPACE_24} 0;
|
|
47
|
+
|
|
48
|
+
.ant-input-group-addon {
|
|
49
|
+
background-color: transparent;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.title-textarea {
|
|
54
|
+
margin-top: ${CAP_SPACE_16};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.card-message-header {
|
|
58
|
+
margin-bottom: ${CAP_SPACE_16};
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
|
|
@@ -26,7 +26,7 @@ import messages from './messages';
|
|
|
26
26
|
import {
|
|
27
27
|
LINE_ASSET_WIDTH,
|
|
28
28
|
LINE_ASSET_HEIGHT,
|
|
29
|
-
|
|
29
|
+
MAX_ALLOWED_TITLE_LENGTH,
|
|
30
30
|
CUSTOM_ASSET_TYPE,
|
|
31
31
|
DEFAULT_ASSET_TYPE,
|
|
32
32
|
DEFAULT_TEMPLATES,
|
|
@@ -80,6 +80,8 @@ export const LineImageMap = ({
|
|
|
80
80
|
const [isImageError, updateImageErrorMessage] = useState(false);
|
|
81
81
|
const [templateSchema, updateTemplateSchema] = useState([]);
|
|
82
82
|
const [isTemplateDrawerRequired, updateTemplateDrawerRequirement] = useState(false);
|
|
83
|
+
const [altText, updateTitle] = useState('');
|
|
84
|
+
const [errorTitle, updateErrorTitle] = useState(false);
|
|
83
85
|
|
|
84
86
|
useEffect(() => {
|
|
85
87
|
const { messageTitle = '',
|
|
@@ -88,7 +90,8 @@ export const LineImageMap = ({
|
|
|
88
90
|
baseSize = {},
|
|
89
91
|
selectedTemplate,
|
|
90
92
|
assetType,
|
|
91
|
-
actionLinks
|
|
93
|
+
actionLinks,
|
|
94
|
+
altText,
|
|
92
95
|
} = content;
|
|
93
96
|
if ( baseUrl && type === IMAGE_MAP) {
|
|
94
97
|
updateImageStatus(true);
|
|
@@ -100,13 +103,14 @@ export const LineImageMap = ({
|
|
|
100
103
|
updateActionLinks(actionLinks);
|
|
101
104
|
updateTemplateSchema(TEMPLATES_JSON[selectedTemplate]);
|
|
102
105
|
updateBaseSize(baseSize);
|
|
106
|
+
updateTitle(altText);
|
|
103
107
|
}
|
|
104
108
|
}, [content]);
|
|
105
109
|
|
|
106
110
|
useEffect(() => {
|
|
107
111
|
if (imageSrc && (isFullMode ? messageTitle: true) && imageMapTemplate && actionLinks) {
|
|
108
112
|
updateMessageState({
|
|
109
|
-
isError: !imageSrc || !(isFullMode ? messageTitle : true) || !imageMapTemplate || (isImageError && errorMessageTitle),
|
|
113
|
+
isError: !imageSrc || !(isFullMode ? messageTitle : true) || !imageMapTemplate || (isImageError && errorMessageTitle) || errorTitle || !altText,
|
|
110
114
|
baseUrl: imageSrc,
|
|
111
115
|
messageTitle,
|
|
112
116
|
index,
|
|
@@ -116,10 +120,11 @@ export const LineImageMap = ({
|
|
|
116
120
|
messageContent: getActions(),
|
|
117
121
|
selectedTemplate: imageMapTemplate,
|
|
118
122
|
assetType,
|
|
119
|
-
actionLinks
|
|
123
|
+
actionLinks,
|
|
124
|
+
altText,
|
|
120
125
|
});
|
|
121
126
|
}
|
|
122
|
-
}, [errorMessageTitle, imageSrc, messageTitle, isImageError, imageMapTemplate, actionLinks, assetType, isImage, templateSchema]);
|
|
127
|
+
}, [errorMessageTitle, imageSrc, messageTitle, isImageError, imageMapTemplate, actionLinks, assetType, isImage, templateSchema, altText]);
|
|
123
128
|
|
|
124
129
|
useEffect(() => {
|
|
125
130
|
const imgSrc = get(Line, 'uploadedAssetData', false);
|
|
@@ -195,6 +200,15 @@ export const LineImageMap = ({
|
|
|
195
200
|
updateErrorMessageTitle(errorMessage);
|
|
196
201
|
}
|
|
197
202
|
|
|
203
|
+
const onTitleChange = ({ target: { value } }) => {
|
|
204
|
+
updateTitle(value);
|
|
205
|
+
let errorMessage = false;
|
|
206
|
+
if (value === '') {
|
|
207
|
+
errorMessage = formatMessage(messages.emptyAltTextErrorMessage);
|
|
208
|
+
}
|
|
209
|
+
updateErrorTitle(errorMessage);
|
|
210
|
+
}
|
|
211
|
+
|
|
198
212
|
const uploadImages = (e, {files}) => {
|
|
199
213
|
if (e) {
|
|
200
214
|
e.preventDefault();
|
|
@@ -467,10 +481,12 @@ export const LineImageMap = ({
|
|
|
467
481
|
const baseSize = get(template, 'versions.base.content.messages[0].baseSize', '');
|
|
468
482
|
const selectedTemplate = get(template, 'definition.selectedTemplate', '');
|
|
469
483
|
const assetType = get(template, 'definition.assetType', '');
|
|
484
|
+
const altText = get(template, 'versions.base.content.messages[0].altText', '');
|
|
470
485
|
const actionLinks = get(template, 'definition.actionLinks', {});
|
|
471
486
|
updateImageStatus(true);
|
|
472
487
|
updateCreateNew(true);
|
|
473
488
|
updateImageSrc(baseUrl);
|
|
489
|
+
updateTitle(altText);
|
|
474
490
|
updateBaseSize(baseSize);
|
|
475
491
|
updateImageMapTemplate(selectedTemplate);
|
|
476
492
|
updateAssetType(assetType);
|
|
@@ -502,11 +518,20 @@ export const LineImageMap = ({
|
|
|
502
518
|
<CapButton
|
|
503
519
|
className="dragger-button"
|
|
504
520
|
type="flat"
|
|
505
|
-
style={{ top:
|
|
521
|
+
style={{ top: 180 , position: 'absolute', right: 0, color: FONT_COLOR_05 }}
|
|
506
522
|
onClick={onReUpload}
|
|
507
523
|
>
|
|
508
524
|
<FormattedMessage {...messages.imageReUpload} />
|
|
509
525
|
</CapButton>}
|
|
526
|
+
<CapInput.TextArea
|
|
527
|
+
maxLength={MAX_ALLOWED_TITLE_LENGTH}
|
|
528
|
+
label={<FormattedMessage {...messages.titleLabel} />}
|
|
529
|
+
inductiveText={<FormattedMessage {...messages.titleDescription} />}
|
|
530
|
+
onChange={onTitleChange}
|
|
531
|
+
value={altText}
|
|
532
|
+
errorMessage={errorTitle}
|
|
533
|
+
className="title-textarea"
|
|
534
|
+
/>
|
|
510
535
|
<CapHeading type="h4">{formatMessage(messages.uploadImageLabel)}</CapHeading>
|
|
511
536
|
<CapLabel type="label1" style={{paddingTop: CAP_SPACE_12, paddingBottom: CAP_SPACE_08}}>{formatMessage(messages.uploadImageDesc)}</CapLabel>
|
|
512
537
|
<CapError key={`${id}-with-label`}>{isImageError}</CapError>
|
|
@@ -27,6 +27,10 @@ export default defineMessages({
|
|
|
27
27
|
id: `${scope}.emptyTitleErrorMessage`,
|
|
28
28
|
defaultMessage: 'Template title can not be empty',
|
|
29
29
|
},
|
|
30
|
+
"emptyAltTextErrorMessage": {
|
|
31
|
+
id: `${scope}.emptyAltTextErrorMessage`,
|
|
32
|
+
defaultMessage: 'Title can not be empty',
|
|
33
|
+
},
|
|
30
34
|
"imageDimenstionDescription": {
|
|
31
35
|
id: `${scope}.imageDimenstionDescription`,
|
|
32
36
|
defaultMessage: 'Dimensions: {dimensions} Size: Up to 10MB',
|
|
@@ -123,4 +127,12 @@ export default defineMessages({
|
|
|
123
127
|
id: `${scope}.select`,
|
|
124
128
|
defaultMessage: 'Select',
|
|
125
129
|
},
|
|
130
|
+
"titleLabel": {
|
|
131
|
+
id: `${scope}.titleLabel`,
|
|
132
|
+
defaultMessage: 'Title',
|
|
133
|
+
},
|
|
134
|
+
"titleDescription": {
|
|
135
|
+
id: `${scope}.titleDescription`,
|
|
136
|
+
defaultMessage: 'The title is shown in push notifications and in the user\'s chat list.',
|
|
137
|
+
},
|
|
126
138
|
});
|
|
@@ -46,7 +46,9 @@ export const LineWrapper = ({
|
|
|
46
46
|
messageContent,
|
|
47
47
|
messageTitle,
|
|
48
48
|
baseUrl,
|
|
49
|
-
selectedTemplate
|
|
49
|
+
selectedTemplate,
|
|
50
|
+
template,
|
|
51
|
+
altText,
|
|
50
52
|
} = content;
|
|
51
53
|
|
|
52
54
|
const isTouched = (
|
|
@@ -61,6 +63,8 @@ export const LineWrapper = ({
|
|
|
61
63
|
|| messageContent
|
|
62
64
|
|| baseUrl
|
|
63
65
|
|| selectedTemplate
|
|
66
|
+
|| template
|
|
67
|
+
|| altText
|
|
64
68
|
);
|
|
65
69
|
if (!isTouched) {
|
|
66
70
|
updateActiveKey(type);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
|
|
3
3
|
import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
|
|
4
|
-
import { CAP_WHITE, FONT_SIZE_VL } from '@capillarytech/cap-ui-library/styled/variables';
|
|
5
4
|
|
|
6
|
-
import { TEXT, IMAGE, IMAGE_MAP, STICKER } from '../constants';
|
|
5
|
+
import { TEXT, IMAGE, IMAGE_MAP, STICKER, IMAGE_CAROUSEL, TEMPLATE } from '../constants';
|
|
7
6
|
import LineText from '../Text';
|
|
8
7
|
import LineImage from '../Image';
|
|
9
8
|
import LineSticker from '../Sticker';
|
|
10
9
|
import LineImageMap from '../ImageMap';
|
|
10
|
+
import LineImageCarousel from '../ImageCarousel';
|
|
11
11
|
import messages from './messages';
|
|
12
12
|
|
|
13
13
|
export const getTabContent = ({ item, props }) => {
|
|
@@ -24,20 +24,24 @@ export const getTabContent = ({ item, props }) => {
|
|
|
24
24
|
case IMAGE_MAP: {
|
|
25
25
|
return <LineImageMap {...props} />;
|
|
26
26
|
}
|
|
27
|
+
case TEMPLATE: {
|
|
28
|
+
return <LineImageCarousel {...props} />;
|
|
29
|
+
}
|
|
27
30
|
}
|
|
28
31
|
};
|
|
29
32
|
|
|
30
33
|
export const itemIcons = {
|
|
31
|
-
[TEXT]: '
|
|
32
|
-
[IMAGE]: '
|
|
33
|
-
[STICKER]: '
|
|
34
|
-
[IMAGE_MAP]: '
|
|
34
|
+
[TEXT]: 'text-message',
|
|
35
|
+
[IMAGE]: 'image-message',
|
|
36
|
+
[STICKER]: 'smiley-message',
|
|
37
|
+
[IMAGE_MAP]: 'rich-message',
|
|
38
|
+
[TEMPLATE]: 'carousel-message',
|
|
35
39
|
};
|
|
36
40
|
|
|
37
41
|
|
|
38
42
|
export const getTabPanes = (props) => {
|
|
39
|
-
const tableKeys = [TEXT, IMAGE, STICKER, IMAGE_MAP];
|
|
40
|
-
const tableKeysCreatives = [TEXT, IMAGE, IMAGE_MAP];
|
|
43
|
+
const tableKeys = [TEXT, IMAGE, STICKER, IMAGE_MAP, TEMPLATE];
|
|
44
|
+
const tableKeysCreatives = [TEXT, IMAGE, IMAGE_MAP, TEMPLATE];
|
|
41
45
|
return (props.isFullMode ? tableKeysCreatives : tableKeys).map((item) => {
|
|
42
46
|
const isSelected = props.activeKey === item;
|
|
43
47
|
return {
|
|
@@ -47,14 +51,9 @@ export const getTabPanes = (props) => {
|
|
|
47
51
|
title={props.formatMessage(messages[`${item}Label`])}
|
|
48
52
|
>
|
|
49
53
|
<CapIcon
|
|
50
|
-
type={itemIcons[item]}
|
|
51
|
-
size="
|
|
52
|
-
style={{
|
|
53
|
-
theme={isSelected ? 'filled' : ''}
|
|
54
|
-
svgProps={{
|
|
55
|
-
fill: isSelected ? '#000' : CAP_WHITE,
|
|
56
|
-
stroke: isSelected ? CAP_WHITE : '#000',
|
|
57
|
-
}}
|
|
54
|
+
type={isSelected ? `${itemIcons[item]}-filled`: itemIcons[item]}
|
|
55
|
+
size="m"
|
|
56
|
+
style={{ margin: 0 }}
|
|
58
57
|
/>
|
|
59
58
|
</CapTooltip>
|
|
60
59
|
),
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
bottom: 20px;
|
|
38
38
|
}
|
|
39
39
|
.cancel-msg {
|
|
40
|
-
margin-left:
|
|
40
|
+
margin-left: 100px;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
.image-container {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
object-fit: cover;
|
|
54
54
|
max-width: 100%;
|
|
55
55
|
max-height: 100%;
|
|
56
|
-
height:
|
|
56
|
+
height: 152px !important;
|
|
57
57
|
width: auto !important;
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -28,18 +28,20 @@ export function defaultAction() {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export function uploadAsset(file, assetType, fileParams) {
|
|
31
|
+
export function uploadAsset(file, assetType, fileParams, templateType) {
|
|
32
32
|
return {
|
|
33
33
|
type: types.UPLOAD_ASSET_REQUEST,
|
|
34
34
|
file,
|
|
35
35
|
assetType,
|
|
36
36
|
fileParams,
|
|
37
|
+
templateType,
|
|
37
38
|
};
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
export function clearAsset() {
|
|
41
|
+
export function clearAsset(templateType) {
|
|
41
42
|
return {
|
|
42
43
|
type: types.CLEAR_ASSET,
|
|
44
|
+
templateType,
|
|
43
45
|
};
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -2,8 +2,11 @@ export const TEXT = 'text';
|
|
|
2
2
|
export const STICKER = 'sticker';
|
|
3
3
|
export const IMAGE = 'image';
|
|
4
4
|
export const IMAGE_MAP = 'imagemap';
|
|
5
|
+
export const IMAGE_CAROUSEL = 'image_carousel';
|
|
6
|
+
export const TEMPLATE = 'template';
|
|
5
7
|
export const MAX_LINE_WRAPPER_LIMIT = 5;
|
|
6
8
|
export const MAX_LINE_WRAPPER_LIMIT_FULL_MODE = 1;
|
|
9
|
+
export const IMAGE_MAP_CAMEL_CASE = 'imageMap';
|
|
7
10
|
|
|
8
11
|
/*
|
|
9
12
|
*
|
|
@@ -16,9 +16,13 @@ import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
|
|
|
16
16
|
import CapRadioCard from '@capillarytech/cap-ui-library/CapRadioCard';
|
|
17
17
|
import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
|
|
18
18
|
import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
|
|
19
|
+
// GA
|
|
20
|
+
import { GA } from '@capillarytech/cap-ui-utils';
|
|
21
|
+
import { TRACK_CREATE_LINE, TRACK_EDIT_LINE } from '../../App/constants';
|
|
22
|
+
|
|
19
23
|
import LineWrapper from './Wrapper';
|
|
20
24
|
import messages from './messages';
|
|
21
|
-
import { TEXT, IMAGE, IMAGE_MAP,
|
|
25
|
+
import { TEXT, IMAGE, IMAGE_MAP, IMAGE_CAROUSEL, MAX_LINE_WRAPPER_LIMIT, MAX_LINE_WRAPPER_LIMIT_FULL_MODE } from './constants';
|
|
22
26
|
import { FONT_COLOR_05 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
23
27
|
|
|
24
28
|
import { makeSelectMetaEntities, setInjectedTags } from '../../Cap/selectors';
|
|
@@ -29,7 +33,7 @@ import * as compActions from './actions';
|
|
|
29
33
|
import * as templateActionsConfig from '../../Templates/actions';
|
|
30
34
|
import withCreatives from '../../../hoc/withCreatives';
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
const { stopTimer } = GA.timeTracker;
|
|
33
37
|
|
|
34
38
|
export const LineContainer = ({
|
|
35
39
|
isFullMode,
|
|
@@ -105,9 +109,11 @@ export const LineContainer = ({
|
|
|
105
109
|
const messageTitle = get(Line, 'templateDetails.name');
|
|
106
110
|
const baseUrl = get(Line, `templateDetails.versions.base.content.messages.0.baseUrl`);
|
|
107
111
|
const baseSize = get(Line, `templateDetails.versions.base.content.messages.0.baseSize`);
|
|
112
|
+
const altText = get(Line, `templateDetails.versions.base.content.messages.0.altText`);
|
|
108
113
|
const selectedTemplate = get(Line, 'templateDetails.selectedTemplate');
|
|
109
114
|
const assetType = get(Line, 'templateDetails.assetType');
|
|
110
115
|
const actionLinks = get(Line, 'templateDetails.actionLinks');
|
|
116
|
+
const template = get(Line, `templateDetails.versions.base.content.messages.0.template`);
|
|
111
117
|
const lineContent = {
|
|
112
118
|
type,
|
|
113
119
|
messageContent,
|
|
@@ -125,6 +131,8 @@ export const LineContainer = ({
|
|
|
125
131
|
baseUrl,
|
|
126
132
|
actionLinks,
|
|
127
133
|
baseSize,
|
|
134
|
+
template,
|
|
135
|
+
altText,
|
|
128
136
|
};
|
|
129
137
|
updateLineWrapperContent([lineContent]);
|
|
130
138
|
}
|
|
@@ -148,7 +156,9 @@ export const LineContainer = ({
|
|
|
148
156
|
baseSize,
|
|
149
157
|
actionLinks,
|
|
150
158
|
assetType,
|
|
151
|
-
selectedTemplate
|
|
159
|
+
selectedTemplate,
|
|
160
|
+
template,
|
|
161
|
+
altText,
|
|
152
162
|
}) => {
|
|
153
163
|
const obj = {
|
|
154
164
|
type,
|
|
@@ -160,7 +170,9 @@ export const LineContainer = ({
|
|
|
160
170
|
baseSize,
|
|
161
171
|
actionLinks,
|
|
162
172
|
assetType,
|
|
163
|
-
selectedTemplate
|
|
173
|
+
selectedTemplate,
|
|
174
|
+
template,
|
|
175
|
+
altText,
|
|
164
176
|
};
|
|
165
177
|
if (stickerUrl) {
|
|
166
178
|
obj.selectedSticker = {
|
|
@@ -322,7 +334,9 @@ export const LineContainer = ({
|
|
|
322
334
|
baseSize,
|
|
323
335
|
selectedTemplate,
|
|
324
336
|
assetType,
|
|
325
|
-
actionLinks
|
|
337
|
+
actionLinks,
|
|
338
|
+
template,
|
|
339
|
+
altText,
|
|
326
340
|
} = {}] = lineWrapperContents;
|
|
327
341
|
let messageData = { type };
|
|
328
342
|
messageData[messageType] = messageContent;
|
|
@@ -340,11 +354,15 @@ export const LineContainer = ({
|
|
|
340
354
|
}
|
|
341
355
|
if (baseUrl) {
|
|
342
356
|
messageData.baseUrl = baseUrl;
|
|
343
|
-
messageData.altText =
|
|
357
|
+
messageData.altText = altText;
|
|
344
358
|
}
|
|
345
359
|
if (baseSize) {
|
|
346
360
|
messageData.baseSize = baseSize;
|
|
347
361
|
}
|
|
362
|
+
if (template) {
|
|
363
|
+
messageData.template = template;
|
|
364
|
+
messageData.altText = altText;
|
|
365
|
+
}
|
|
348
366
|
return {
|
|
349
367
|
versions: {
|
|
350
368
|
base: {
|
|
@@ -377,7 +395,9 @@ export const LineContainer = ({
|
|
|
377
395
|
baseSize,
|
|
378
396
|
selectedTemplate,
|
|
379
397
|
assetType,
|
|
380
|
-
actionLinks
|
|
398
|
+
actionLinks,
|
|
399
|
+
template,
|
|
400
|
+
altText,
|
|
381
401
|
}) => {
|
|
382
402
|
let messageData = { type };
|
|
383
403
|
messageData[messageType] = messageContent;
|
|
@@ -395,12 +415,16 @@ export const LineContainer = ({
|
|
|
395
415
|
}
|
|
396
416
|
if (baseUrl) {
|
|
397
417
|
messageData.baseUrl = baseUrl;
|
|
398
|
-
messageData.altText =
|
|
418
|
+
messageData.altText = altText;
|
|
399
419
|
messageData.baseSize = baseSize;
|
|
400
420
|
messageData.selectedTemplate = selectedTemplate;
|
|
401
421
|
messageData.assetType = assetType;
|
|
402
422
|
messageData.actionLinks = actionLinks;
|
|
403
423
|
}
|
|
424
|
+
if (template) {
|
|
425
|
+
messageData.template = template;
|
|
426
|
+
messageData.altText = altText;
|
|
427
|
+
}
|
|
404
428
|
return messageData;
|
|
405
429
|
});
|
|
406
430
|
return ({
|
|
@@ -415,10 +439,18 @@ export const LineContainer = ({
|
|
|
415
439
|
});
|
|
416
440
|
}
|
|
417
441
|
|
|
442
|
+
const getLineType = lineWrapperContents => get(lineWrapperContents, '0.type', TEXT);
|
|
443
|
+
|
|
418
444
|
const onCreateLine = () => {
|
|
419
445
|
actions.createTemplate(
|
|
420
446
|
formatSubmitPayload(lineWrapperContents),
|
|
421
447
|
() => {
|
|
448
|
+
// stop timer for create line
|
|
449
|
+
stopTimer(TRACK_CREATE_LINE, {
|
|
450
|
+
category: 'Creatives',
|
|
451
|
+
action: TRACK_CREATE_LINE,
|
|
452
|
+
label: getLineType(lineWrapperContents),
|
|
453
|
+
});
|
|
422
454
|
createCallback();
|
|
423
455
|
onCreateComplete();
|
|
424
456
|
}
|
|
@@ -427,17 +459,17 @@ export const LineContainer = ({
|
|
|
427
459
|
|
|
428
460
|
const getPreviewSection = () => {
|
|
429
461
|
const accountName = get(lineData, 'selectedLineAccount.name', '');
|
|
430
|
-
const templateContent = lineWrapperContents.map(({ messageContent, type, previewImageUrl, selectedSticker, baseUrl }) => ({
|
|
462
|
+
const templateContent = lineWrapperContents.map(({ messageContent, type, previewImageUrl, selectedSticker, baseUrl, template }) => ({
|
|
431
463
|
messageContent,
|
|
432
464
|
previewImageUrl,
|
|
433
465
|
selectedSticker,
|
|
434
466
|
type,
|
|
435
|
-
baseUrl
|
|
467
|
+
baseUrl,
|
|
468
|
+
imageCarousel: get(template, 'columns', [{}]).map(({ imageUrl, action: { label: actionLabel } = {} }) => ({ imageUrl, actionLabel }) ),
|
|
436
469
|
}));
|
|
437
470
|
|
|
438
471
|
return (
|
|
439
472
|
<TemplatePreview
|
|
440
|
-
// style={val.customStyling ? val.customStyling : {}}
|
|
441
473
|
channel="LINE"
|
|
442
474
|
content={templateContent}
|
|
443
475
|
LineAccountName={accountName[0]}
|
|
@@ -452,6 +484,12 @@ export const LineContainer = ({
|
|
|
452
484
|
_id: params.id,
|
|
453
485
|
},
|
|
454
486
|
() => {
|
|
487
|
+
// stop timer for edit line
|
|
488
|
+
stopTimer(TRACK_EDIT_LINE, {
|
|
489
|
+
category: 'Creatives',
|
|
490
|
+
action: TRACK_EDIT_LINE,
|
|
491
|
+
label: getLineType(lineWrapperContents),
|
|
492
|
+
});
|
|
455
493
|
editCallback();
|
|
456
494
|
onCreateComplete();
|
|
457
495
|
});
|
|
@@ -42,14 +42,14 @@ function createReducer(state = initialState, action) {
|
|
|
42
42
|
return state
|
|
43
43
|
.set('uploadAssetSuccess', (action.statusCode !== undefined && action.statusCode !== '' && action.statusCode < 300))
|
|
44
44
|
.set('assetUploading', false)
|
|
45
|
-
.set('uploadedAssetData', action.data);
|
|
45
|
+
.set(action.templateType ? `uploadedAssetData${action.templateType}` : 'uploadedAssetData', action.data);
|
|
46
46
|
case types.UPLOAD_ASSET_FAILURE:
|
|
47
47
|
return state
|
|
48
48
|
.set('uploadAssetSuccess', false)
|
|
49
49
|
.set('assetUploading', false);
|
|
50
50
|
case types.CLEAR_ASSET:
|
|
51
51
|
return state
|
|
52
|
-
.delete('uploadedAssetData');
|
|
52
|
+
.delete(action.templateType ? `uploadedAssetData${action.templateType}` : 'uploadedAssetData');
|
|
53
53
|
// FOR EDIT
|
|
54
54
|
case types.EDIT_TEMPLATE_REQUEST:
|
|
55
55
|
return state
|
|
@@ -21,10 +21,10 @@ export function* createTemplate({ template, callback }) {
|
|
|
21
21
|
yield put({ type: types.CREATE_TEMPLATE_FAILURE, error, errorMsg });
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
export function* uploadAsset(file, assetType, fileParams) {
|
|
24
|
+
export function* uploadAsset(file, assetType, fileParams ) {
|
|
25
25
|
try {
|
|
26
26
|
const result = yield call(Api.uploadFile, file, assetType, fileParams);
|
|
27
|
-
yield put({ type: types.UPLOAD_ASSET_SUCCESS, data: result.response.asset, statusCode: result.status ? result.status.code : '' });
|
|
27
|
+
yield put({ type: types.UPLOAD_ASSET_SUCCESS, data: result.response.asset, statusCode: result.status ? result.status.code : '', templateType: file.templateType });
|
|
28
28
|
} catch (error) {
|
|
29
29
|
yield put({ type: types.UPLOAD_ASSET_FAILURE, error });
|
|
30
30
|
}
|
|
@@ -82,6 +82,7 @@ const LINE_FILTERS = {
|
|
|
82
82
|
TEXT: 'text',
|
|
83
83
|
IMAGE_VIDEO: 'image',
|
|
84
84
|
IMAGE_MAP: 'imagemap',
|
|
85
|
+
IMAGE_CAROUSEL: 'template',
|
|
85
86
|
};
|
|
86
87
|
|
|
87
88
|
export class Templates extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
@@ -635,11 +636,34 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
635
636
|
stickerUrl = '',
|
|
636
637
|
animatedStickerUrl = '',
|
|
637
638
|
baseUrl = '',
|
|
639
|
+
template: carouselTemplate,
|
|
638
640
|
}] = [{}],
|
|
639
641
|
} = {},
|
|
640
642
|
} = template.versions.base;
|
|
641
643
|
templateData.content = text;
|
|
642
644
|
templateData.url = originalContentUrl || animatedStickerUrl || stickerUrl || (baseUrl ? `${baseUrl}/1040` : '');
|
|
645
|
+
if (carouselTemplate) {
|
|
646
|
+
const carouselContent = get(carouselTemplate, 'columns', [{}]).map(({ imageUrl, action: { label: actionLabel } = {} }) => ({ imageUrl, actionLabel }) );
|
|
647
|
+
templateData.content = (
|
|
648
|
+
<div style={{ display: 'flex'}}>
|
|
649
|
+
{
|
|
650
|
+
carouselContent.map(({
|
|
651
|
+
imageUrl,
|
|
652
|
+
actionLabel,
|
|
653
|
+
}) => (
|
|
654
|
+
<img
|
|
655
|
+
width={208}
|
|
656
|
+
height={279}
|
|
657
|
+
src={imageUrl}
|
|
658
|
+
alt={actionLabel}
|
|
659
|
+
key={`${imageUrl}_${actionLabel}`}
|
|
660
|
+
/>
|
|
661
|
+
))
|
|
662
|
+
}
|
|
663
|
+
</div>
|
|
664
|
+
);
|
|
665
|
+
templateData.className = 'carousel-img-section';
|
|
666
|
+
}
|
|
643
667
|
break;
|
|
644
668
|
}
|
|
645
669
|
default:
|
|
@@ -1789,7 +1813,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1789
1813
|
<CapRadio.CapRadioGroup className="line-filters" defaultValue={lineFilter} onChange={this.setLineFilter}>
|
|
1790
1814
|
{
|
|
1791
1815
|
(() => {
|
|
1792
|
-
const { ALL, TEXT, IMAGE_VIDEO,
|
|
1816
|
+
const { ALL, TEXT, IMAGE_VIDEO, IMAGE_CAROUSEL, IMAGE_MAP } = LINE_FILTERS;
|
|
1793
1817
|
return (
|
|
1794
1818
|
<>
|
|
1795
1819
|
<CapRadio.Button value={ALL}><CapLabel type="label2">
|
|
@@ -1804,6 +1828,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1804
1828
|
<CapRadio.Button value={IMAGE_MAP}><CapLabel type="label2">
|
|
1805
1829
|
<FormattedMessage {...messages.imageMapTemplate} />
|
|
1806
1830
|
</CapLabel></CapRadio.Button>
|
|
1831
|
+
<CapRadio.Button value={IMAGE_CAROUSEL}><CapLabel type="label2">
|
|
1832
|
+
<FormattedMessage {...messages.imageCarouselTemplate} />
|
|
1833
|
+
</CapLabel></CapRadio.Button>
|
|
1807
1834
|
</>
|
|
1808
1835
|
);
|
|
1809
1836
|
})()
|
|
@@ -242,6 +242,10 @@ export default defineMessages({
|
|
|
242
242
|
id: `${scope}.imageMapTemplate`,
|
|
243
243
|
defaultMessage: `Rich message`,
|
|
244
244
|
},
|
|
245
|
+
"imageCarouselTemplate": {
|
|
246
|
+
id: `${scope}.imageCarouselTemplate`,
|
|
247
|
+
defaultMessage: `Card message`,
|
|
248
|
+
},
|
|
245
249
|
"selectDefaultButton": {
|
|
246
250
|
id: `${scope}.selectDefaultButton`,
|
|
247
251
|
defaultMessage: `Select`,
|