@capillarytech/creatives-library 6.7.1 → 6.8.1
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/assets/line-image-placeholder.svg +14 -0
- package/assets/line.png +0 -0
- package/assets/smiley-placeholder.svg +11 -0
- package/components/TemplatePreview/index.js +185 -8
- package/index.js +3 -3
- package/package.json +1 -1
- package/routes.js +2 -2
- package/services/api.js +3 -0
- package/styles/vendor/semantic/src/definitions/modules/accordion.less +219 -219
- package/v2Components/TemplatePreview/WechatRichmediaTemplatePreview/index.js +1 -1
- package/v2Components/TemplatePreview/index.js +164 -12
- package/v2Components/TemplatePreview/messages.js +8 -0
- package/v2Containers/Assets/Gallery/index.js +3 -0
- package/v2Containers/Assets/Gallery/selectors.js +12 -5
- package/v2Containers/CreativesContainer/SlideBoxContent.js +51 -17
- package/v2Containers/CreativesContainer/index.js +23 -17
- package/v2Containers/Line/Container/Drawer/index.js +93 -0
- package/v2Containers/Line/Container/Image/constants.js +3 -0
- package/v2Containers/Line/Container/Image/index.js +460 -0
- package/v2Containers/Line/Container/Image/messages.js +86 -0
- package/v2Containers/Line/Container/Image/style.js +32 -0
- package/v2Containers/Line/Container/ImageMap/assets/hover/custom.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/hover/templateEight.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/hover/templateFive.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/hover/templateFour.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/hover/templateOne.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/hover/templateSeven.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/hover/templateSix.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/hover/templateThree.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/hover/templateTwo.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/selected/custom.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/selected/templateEight.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/selected/templateFive.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/selected/templateFour.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/selected/templateOne.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/selected/templateSeven.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/selected/templateSix.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/selected/templateThree.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/selected/templateTwo.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates/custom.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates/templateEight.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates/templateFive.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates/templateFour.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates/templateOne.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates/templateSeven.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates/templateSix.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates/templateThree.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates/templateTwo.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/custom.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateEight.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateFive.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateFour.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateOne.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateSeven.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateSix.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateThree.png +0 -0
- package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateTwo.png +0 -0
- package/v2Containers/Line/Container/ImageMap/constants.js +19 -0
- package/v2Containers/Line/Container/ImageMap/index.js +603 -0
- package/v2Containers/Line/Container/ImageMap/messages.js +126 -0
- package/v2Containers/Line/Container/ImageMap/style.js +94 -0
- package/v2Containers/Line/Container/ImageMap/templates.json +195 -0
- package/v2Containers/Line/Container/Sticker/index.js +224 -0
- package/v2Containers/Line/Container/Sticker/messages.js +34 -0
- package/v2Containers/Line/Container/Sticker/style.js +36 -0
- package/v2Containers/Line/Container/Sticker/utils.js +68 -0
- package/v2Containers/Line/Container/Text/index.js +338 -0
- package/v2Containers/Line/Container/Text/messages.js +74 -0
- package/v2Containers/Line/Container/Text/style.js +37 -0
- package/v2Containers/Line/Container/Wrapper/index.js +152 -0
- package/v2Containers/Line/Container/Wrapper/messages.js +46 -0
- package/v2Containers/Line/Container/Wrapper/style.js +44 -0
- package/v2Containers/Line/Container/Wrapper/utils.js +67 -0
- package/v2Containers/Line/Container/_lineCreate.scss +108 -0
- package/v2Containers/Line/Container/actions.js +99 -0
- package/v2Containers/Line/Container/constants.js +48 -0
- package/v2Containers/Line/Container/index.js +581 -0
- package/v2Containers/Line/Container/messages.js +66 -0
- package/v2Containers/Line/Container/reducer.js +103 -0
- package/v2Containers/Line/Container/sagas.js +137 -0
- package/v2Containers/Line/Container/selectors.js +30 -0
- package/v2Containers/Line/Container/style.js +57 -0
- package/v2Containers/Line/Create/index.js +1 -1
- package/v2Containers/Templates/index.js +40 -22
- package/v2Containers/Templates/messages.js +8 -0
- package/v2Containers/TemplatesV2/index.js +13 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import get from 'lodash/get';
|
|
3
|
+
import CapImage from '@capillarytech/cap-ui-library/CapImage';
|
|
4
|
+
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
5
|
+
import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
|
|
6
|
+
|
|
7
|
+
export const groupLineStickers = (lineStickers) => {
|
|
8
|
+
const stickerGroup = {};
|
|
9
|
+
lineStickers.forEach((lineSticker) => {
|
|
10
|
+
const packageId = get(lineSticker, 'definition.packageId');
|
|
11
|
+
if (packageId) {
|
|
12
|
+
const stickerGroupPackageId = stickerGroup[packageId];
|
|
13
|
+
if (stickerGroupPackageId && Array.isArray(stickerGroupPackageId)) {
|
|
14
|
+
stickerGroup[packageId].push(lineSticker);
|
|
15
|
+
} else {
|
|
16
|
+
stickerGroup[packageId] = [];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
return stickerGroup;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const getContent = ({ lineStickers, onStickerSelect }) => (
|
|
24
|
+
<>
|
|
25
|
+
{
|
|
26
|
+
lineStickers.map(({
|
|
27
|
+
_id,
|
|
28
|
+
definition = {},
|
|
29
|
+
}) => (
|
|
30
|
+
<CapColumn span={6} key={_id}>
|
|
31
|
+
<CapButton
|
|
32
|
+
type="flat"
|
|
33
|
+
style={{ padding: 0, margin: 10, height: 'auto' }}
|
|
34
|
+
onClick={() => onStickerSelect(definition)}
|
|
35
|
+
>
|
|
36
|
+
<CapImage
|
|
37
|
+
src={definition.stickerUrl}
|
|
38
|
+
rest={{ height: 70 }}
|
|
39
|
+
rest={{
|
|
40
|
+
height: 70,
|
|
41
|
+
onMouseOut: e => (e.currentTarget.src = definition.stickerUrl),
|
|
42
|
+
onMouseOver: e => (e.currentTarget.src = definition.animatedStickerUrl || definition.stickerUrl)
|
|
43
|
+
}}
|
|
44
|
+
/>
|
|
45
|
+
</CapButton>
|
|
46
|
+
</CapColumn>
|
|
47
|
+
))
|
|
48
|
+
}
|
|
49
|
+
</>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
export const getTabPanes = ({ lineStickers, onStickerSelect }) => {
|
|
53
|
+
const groupedStickers = groupLineStickers(lineStickers);
|
|
54
|
+
const tableKeys = Object.keys(groupedStickers);
|
|
55
|
+
return tableKeys.map((packageId) => {
|
|
56
|
+
const stickerUrl = get(groupedStickers[packageId], '[0].definition.stickerUrl', '');
|
|
57
|
+
return {
|
|
58
|
+
key: packageId,
|
|
59
|
+
tab: (
|
|
60
|
+
<CapImage
|
|
61
|
+
src={stickerUrl}
|
|
62
|
+
rest={{ height: 33 }}
|
|
63
|
+
/>
|
|
64
|
+
),
|
|
65
|
+
content: getContent({ lineStickers: groupedStickers[packageId], onStickerSelect }),
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
};
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { injectIntl, FormattedMessage } from 'react-intl';
|
|
3
|
+
import get from 'lodash/get';
|
|
4
|
+
import CapInput from '@capillarytech/cap-ui-library/CapInput';
|
|
5
|
+
import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
|
|
6
|
+
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
7
|
+
import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
|
|
8
|
+
import CapDrawer from '@capillarytech/cap-ui-library/CapDrawer';
|
|
9
|
+
import CapCustomCard from '@capillarytech/cap-ui-library/CapCustomCard';
|
|
10
|
+
import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
|
|
11
|
+
import { CAP_SPACE_12, CAP_SPACE_08, FONT_COLOR_05, FONT_COLOR_04 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
12
|
+
import TagList from '../../../TagList';
|
|
13
|
+
import LineDrawer from '../Drawer';
|
|
14
|
+
import messages from './messages';
|
|
15
|
+
import style from './style';
|
|
16
|
+
import withStyles from '../../../../hoc/withStyles';
|
|
17
|
+
|
|
18
|
+
const { TextArea } = CapInput;
|
|
19
|
+
const {CapCustomCardList} = CapCustomCard;
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const charLimit = 1600;
|
|
23
|
+
|
|
24
|
+
export const LineText = ({
|
|
25
|
+
className,
|
|
26
|
+
id,
|
|
27
|
+
intl: { formatMessage },
|
|
28
|
+
isFullMode,
|
|
29
|
+
tags,
|
|
30
|
+
injectedTags,
|
|
31
|
+
inheritedTitleStyle,
|
|
32
|
+
inheritedContentStyle,
|
|
33
|
+
getDefaultTags,
|
|
34
|
+
globalActions,
|
|
35
|
+
location,
|
|
36
|
+
index,
|
|
37
|
+
updateMessageState,
|
|
38
|
+
content,
|
|
39
|
+
activeKey,
|
|
40
|
+
Templates,
|
|
41
|
+
getAllTemplates,
|
|
42
|
+
}) => {
|
|
43
|
+
if (activeKey !== 'text') {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const [errorMessageTextarea, updateErrorMessageTextArea] = useState(false);
|
|
48
|
+
const [isCreateNew, updateCreateNew] = useState(isFullMode);
|
|
49
|
+
const [errorMessageTitle, updateErrorMessageTitle] = useState(false);
|
|
50
|
+
const [messageContent, updateTextMessageContent] = useState('');
|
|
51
|
+
const [messageTitle, updateTextMessageTitle] = useState('');
|
|
52
|
+
const [isDrawerRequired, updateDrawerRequirement] = useState(false);
|
|
53
|
+
const [selectedTemplate, updateSelectedTemplate] = useState();
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const { messageTitle = '', messageContent = '', type, isInit } = content;
|
|
57
|
+
if (type === 'text') {
|
|
58
|
+
if (messageContent) {
|
|
59
|
+
updateCreateNew(true);
|
|
60
|
+
updateTextMessageContent(messageContent);
|
|
61
|
+
updateTextMessageTitle(messageTitle);
|
|
62
|
+
}
|
|
63
|
+
if (isInit) {
|
|
64
|
+
updateCreateNew(isFullMode);
|
|
65
|
+
updateTextMessageContent('');
|
|
66
|
+
updateTextMessageTitle('');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}, [content]);
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (messageContent && (isFullMode ? messageTitle : true)) {
|
|
73
|
+
updateMessageState({
|
|
74
|
+
isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? messageTitle : true) || (errorMessageTextarea && errorMessageTitle)),
|
|
75
|
+
messageContent,
|
|
76
|
+
messageTitle,
|
|
77
|
+
index,
|
|
78
|
+
type: 'text',
|
|
79
|
+
messageType: 'text',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}, [errorMessageTitle, messageContent, messageTitle, errorMessageTextarea]);
|
|
83
|
+
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const getTagsQuery = {
|
|
86
|
+
layout: 'LINE',
|
|
87
|
+
type: 'TAG',
|
|
88
|
+
context:
|
|
89
|
+
location.query.type === 'embedded'
|
|
90
|
+
? 'outbound'
|
|
91
|
+
: 'default',
|
|
92
|
+
embedded:
|
|
93
|
+
location.query.type === 'embedded'
|
|
94
|
+
? location.query.type
|
|
95
|
+
: 'full',
|
|
96
|
+
};
|
|
97
|
+
if (getDefaultTags) {
|
|
98
|
+
getTagsQuery.context = getDefaultTags;
|
|
99
|
+
}
|
|
100
|
+
globalActions.fetchSchemaForEntity(getTagsQuery);
|
|
101
|
+
}, []);
|
|
102
|
+
|
|
103
|
+
const handleOnTagsContextChange = (data) => {
|
|
104
|
+
const query = {
|
|
105
|
+
layout: 'LINE',
|
|
106
|
+
type: 'TAG',
|
|
107
|
+
context:
|
|
108
|
+
(data || '').toLowerCase() === 'all' ? 'default' : (data || '').toLowerCase(),
|
|
109
|
+
embedded:
|
|
110
|
+
location.query.type === 'embedded'
|
|
111
|
+
? location.query.type
|
|
112
|
+
: 'full',
|
|
113
|
+
};
|
|
114
|
+
globalActions.fetchSchemaForEntity(query);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const updateTextContentError = (value) => {
|
|
118
|
+
let errorMessage = false;
|
|
119
|
+
if (value === '') {
|
|
120
|
+
errorMessage = formatMessage(messages.emptyTitleErrorMessage);
|
|
121
|
+
} else if (value.length > charLimit) {
|
|
122
|
+
errorMessage = formatMessage(messages.limitExceededContentErrorMessage);
|
|
123
|
+
}
|
|
124
|
+
updateErrorMessageTextArea(errorMessage);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const onTextContentChange = ({ target: { value } }) => {
|
|
128
|
+
updateTextMessageContent(value);
|
|
129
|
+
updateTextContentError(value);
|
|
130
|
+
updateMessageState({
|
|
131
|
+
isError: (value.length > charLimit) || (!value || !(isFullMode ? messageTitle : true) || (!value && errorMessageTitle)),
|
|
132
|
+
messageContent: value,
|
|
133
|
+
messageTitle,
|
|
134
|
+
index,
|
|
135
|
+
type: 'text',
|
|
136
|
+
messageType: 'text',
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const updateTextTitleError = (value) => {
|
|
141
|
+
let errorMessage = false;
|
|
142
|
+
if (value === '') {
|
|
143
|
+
errorMessage = formatMessage(messages.emptyTitleErrorMessage);
|
|
144
|
+
}
|
|
145
|
+
updateErrorMessageTitle(errorMessage);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const onTextTitleChange = ({ target: { value } }) => {
|
|
149
|
+
updateTextMessageTitle(value);
|
|
150
|
+
updateTextTitleError(value);
|
|
151
|
+
updateMessageState({
|
|
152
|
+
isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? value : true) || (!value && errorMessageTextarea)),
|
|
153
|
+
messageContent,
|
|
154
|
+
messageTitle: value,
|
|
155
|
+
index,
|
|
156
|
+
type: 'text',
|
|
157
|
+
messageType: 'text',
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const onTagSelect = (data) => updateTextMessageContent(`${messageContent}{{${data}}}`);
|
|
162
|
+
|
|
163
|
+
const setNewContent = () => updateCreateNew(true);
|
|
164
|
+
|
|
165
|
+
const onSelectTemplate = (event) => {
|
|
166
|
+
event.stopPropagation();
|
|
167
|
+
updateDrawerRequirement(true);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const getLineTextSection = () => {
|
|
171
|
+
if (!isCreateNew) {
|
|
172
|
+
return (
|
|
173
|
+
<div className="form-builder-dragger" style={{
|
|
174
|
+
textAlign: 'center',
|
|
175
|
+
border: '2px dashed lightgrey',
|
|
176
|
+
minHeight: 120,
|
|
177
|
+
padding: 60
|
|
178
|
+
}}>
|
|
179
|
+
<CapHeader
|
|
180
|
+
className="choice-title"
|
|
181
|
+
size="regular"
|
|
182
|
+
title={formatMessage(messages.textMessageAddLabel)}
|
|
183
|
+
style={{ marginBottom: 12 }}
|
|
184
|
+
/>
|
|
185
|
+
|
|
186
|
+
<CapButton
|
|
187
|
+
className="create-button"
|
|
188
|
+
type="secondary"
|
|
189
|
+
style={{marginRight: CAP_SPACE_08}}
|
|
190
|
+
onClick={setNewContent}
|
|
191
|
+
>
|
|
192
|
+
<FormattedMessage {...messages.textMessageCreateNew} />
|
|
193
|
+
</CapButton>
|
|
194
|
+
|
|
195
|
+
<CapHeading className="" type="label6" style={{ display: 'inline-block' }}>
|
|
196
|
+
<FormattedMessage {...messages.textMessageORLabel} />
|
|
197
|
+
</CapHeading>
|
|
198
|
+
|
|
199
|
+
<CapButton
|
|
200
|
+
className="dragger-button"
|
|
201
|
+
type="secondary"
|
|
202
|
+
style={{marginLeft: CAP_SPACE_08}}
|
|
203
|
+
onClick={onSelectTemplate}
|
|
204
|
+
>
|
|
205
|
+
<FormattedMessage {...messages.textMessageSelectTemplate} />
|
|
206
|
+
</CapButton>
|
|
207
|
+
</div>);
|
|
208
|
+
}
|
|
209
|
+
return (
|
|
210
|
+
<>
|
|
211
|
+
<TextArea
|
|
212
|
+
id={`${id}_textarea`}
|
|
213
|
+
placeholder={formatMessage(messages.textMessagePlaceholder)}
|
|
214
|
+
className={`${errorMessageTextarea ? 'error' : ''}`}
|
|
215
|
+
errorMessage={errorMessageTextarea}
|
|
216
|
+
label={(
|
|
217
|
+
<>
|
|
218
|
+
<FormattedMessage {...messages.textMessage} />
|
|
219
|
+
<CapLabel type="label2" className="word-count">
|
|
220
|
+
<FormattedMessage {...messages.charCount} />
|
|
221
|
+
{(messageContent || '').length}/{charLimit}
|
|
222
|
+
</CapLabel>
|
|
223
|
+
</>
|
|
224
|
+
)}
|
|
225
|
+
autosize={false}
|
|
226
|
+
onChange={onTextContentChange}
|
|
227
|
+
style={inheritedContentStyle || {}}
|
|
228
|
+
className="text-template-content"
|
|
229
|
+
defaultValue={messageContent || ''}
|
|
230
|
+
value={messageContent || ''}
|
|
231
|
+
rows={5}
|
|
232
|
+
cols={2}
|
|
233
|
+
/>
|
|
234
|
+
<TagList
|
|
235
|
+
key={`${id}_tags`}
|
|
236
|
+
moduleFilterEnabled={location && location.query && location.query.type !== 'embedded'}
|
|
237
|
+
label={formatMessage(messages.addLabels)}
|
|
238
|
+
onTagSelect={onTagSelect}
|
|
239
|
+
onContextChange={handleOnTagsContextChange}
|
|
240
|
+
location={location}
|
|
241
|
+
tags={tags || []}
|
|
242
|
+
injectedTags={injectedTags || {}}
|
|
243
|
+
// className={val.className ? val.className : ''}
|
|
244
|
+
id={`${id}_tags`}
|
|
245
|
+
userLocale={localStorage.getItem('jlocale') || 'en'}
|
|
246
|
+
/>
|
|
247
|
+
</>
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const onTemplateSelection = (template) => {
|
|
252
|
+
const content = get(template, 'versions.base.content.messages[0].text', '');
|
|
253
|
+
updateSelectedTemplate(template);
|
|
254
|
+
updateTextMessageContent(content);
|
|
255
|
+
updateErrorMessageTextArea(!content);
|
|
256
|
+
updateDrawerRequirement(false);
|
|
257
|
+
updateCreateNew(true);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const getLineTextDrawerContent = () => {
|
|
261
|
+
const lineTextTemplates = Templates.templates;
|
|
262
|
+
if (!lineTextTemplates) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const cardDataList = [];
|
|
267
|
+
lineTextTemplates.forEach(template => {
|
|
268
|
+
let templateData = {};
|
|
269
|
+
const {
|
|
270
|
+
content: {
|
|
271
|
+
messages: [{
|
|
272
|
+
text = '',
|
|
273
|
+
}] = [{}],
|
|
274
|
+
} = {},
|
|
275
|
+
} = template.versions.base;
|
|
276
|
+
templateData.content = text;
|
|
277
|
+
templateData.title = template.name;
|
|
278
|
+
templateData.key = template.name;
|
|
279
|
+
templateData.hoverOption = (
|
|
280
|
+
<CapButton onClick={() => onTemplateSelection(template)}>
|
|
281
|
+
<FormattedMessage {...messages.select} />
|
|
282
|
+
</CapButton>
|
|
283
|
+
);
|
|
284
|
+
if (text) {
|
|
285
|
+
cardDataList.push(templateData);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
return (
|
|
289
|
+
<>
|
|
290
|
+
<CapHeading type="h3" className="drawer-head">
|
|
291
|
+
{formatMessage(messages.lineTemplateText)}
|
|
292
|
+
</CapHeading>
|
|
293
|
+
<LineDrawer
|
|
294
|
+
getAllTemplates={getAllTemplates}
|
|
295
|
+
cardDataList={cardDataList}
|
|
296
|
+
isDrawer={isDrawerRequired}
|
|
297
|
+
className="drawer-head"
|
|
298
|
+
searchPlaceholder={formatMessage(messages.searchText)}
|
|
299
|
+
/>
|
|
300
|
+
</>
|
|
301
|
+
);
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
return (
|
|
305
|
+
<div className={className}>
|
|
306
|
+
{
|
|
307
|
+
isFullMode
|
|
308
|
+
? (
|
|
309
|
+
<CapInput
|
|
310
|
+
id={`${id}_input`}
|
|
311
|
+
onChange={onTextTitleChange}
|
|
312
|
+
errorMessage={errorMessageTitle}
|
|
313
|
+
className="text-template-title"
|
|
314
|
+
style={inheritedTitleStyle || {}}
|
|
315
|
+
placeholder={formatMessage(messages.textMessageTitlePlaceholder)}
|
|
316
|
+
defaultValue={messageTitle || ''}
|
|
317
|
+
value={messageTitle || ''}
|
|
318
|
+
size="default"
|
|
319
|
+
label={formatMessage(messages.textMessageTitleLabel)}
|
|
320
|
+
/>
|
|
321
|
+
)
|
|
322
|
+
: null
|
|
323
|
+
}
|
|
324
|
+
{
|
|
325
|
+
getLineTextSection()
|
|
326
|
+
}
|
|
327
|
+
<CapDrawer
|
|
328
|
+
content={getLineTextDrawerContent()}
|
|
329
|
+
visible={isDrawerRequired}
|
|
330
|
+
width={624}
|
|
331
|
+
onClose={() => updateDrawerRequirement(false)}
|
|
332
|
+
/>
|
|
333
|
+
</div>
|
|
334
|
+
)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
export default injectIntl(withStyles(LineText, style));
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* LineText Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the LineText component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
const scope = `creatives.containersV2.LineText`;
|
|
8
|
+
|
|
9
|
+
export default defineMessages({
|
|
10
|
+
"textMessageAddLabel": {
|
|
11
|
+
id: `${scope}.textMessageAddLabel`,
|
|
12
|
+
defaultMessage: 'How do you want to add the text message?',
|
|
13
|
+
},
|
|
14
|
+
"textMessageCreateNew": {
|
|
15
|
+
id: `${scope}.textMessageCreateNew`,
|
|
16
|
+
defaultMessage: 'Create new',
|
|
17
|
+
},
|
|
18
|
+
"textMessageSelectTemplate": {
|
|
19
|
+
id: `${scope}.textMessageSelectTemplate`,
|
|
20
|
+
defaultMessage: 'Select template',
|
|
21
|
+
},
|
|
22
|
+
"textMessageORLabel": {
|
|
23
|
+
id: `${scope}.textMessageORLabel`,
|
|
24
|
+
defaultMessage: 'OR',
|
|
25
|
+
},
|
|
26
|
+
"textMessagePlaceholder": {
|
|
27
|
+
id: `${scope}.textMessagePlaceholder`,
|
|
28
|
+
defaultMessage: 'Enter text message',
|
|
29
|
+
},
|
|
30
|
+
"textMessageTitlePlaceholder": {
|
|
31
|
+
id: `${scope}.textMessageTitlePlaceholder`,
|
|
32
|
+
defaultMessage: 'Enter template name',
|
|
33
|
+
},
|
|
34
|
+
"textMessage": {
|
|
35
|
+
id: `${scope}.textMessage`,
|
|
36
|
+
defaultMessage: 'Text message',
|
|
37
|
+
},
|
|
38
|
+
"charCount": {
|
|
39
|
+
id: `${scope}.charCount`,
|
|
40
|
+
defaultMessage: 'Characters count:',
|
|
41
|
+
},
|
|
42
|
+
"addLabels": {
|
|
43
|
+
id: `${scope}.addLabels`,
|
|
44
|
+
defaultMessage: 'Add labels',
|
|
45
|
+
},
|
|
46
|
+
"emptyTitleErrorMessage": {
|
|
47
|
+
id: `${scope}.emptyTitleErrorMessage`,
|
|
48
|
+
defaultMessage: 'Template title can not be empty',
|
|
49
|
+
},
|
|
50
|
+
"emptyContentErrorMessage": {
|
|
51
|
+
id: `${scope}.emptyContentErrorMessage`,
|
|
52
|
+
defaultMessage: 'Template content can not be empty',
|
|
53
|
+
},
|
|
54
|
+
"limitExceededContentErrorMessage": {
|
|
55
|
+
id: `${scope}.limitExceededContentErrorMessage`,
|
|
56
|
+
defaultMessage: 'Template content can not be more than 1600',
|
|
57
|
+
},
|
|
58
|
+
"textMessageTitleLabel": {
|
|
59
|
+
id: `${scope}.textMessageTitleLabel`,
|
|
60
|
+
defaultMessage: 'Template name',
|
|
61
|
+
},
|
|
62
|
+
"lineTemplateText": {
|
|
63
|
+
id: `${scope}.lineTemplateText`,
|
|
64
|
+
defaultMessage: 'Line templates - Text',
|
|
65
|
+
},
|
|
66
|
+
"select": {
|
|
67
|
+
id: `${scope}.select`,
|
|
68
|
+
defaultMessage: 'Select',
|
|
69
|
+
},
|
|
70
|
+
"searchText": {
|
|
71
|
+
id: `${scope}.searchText`,
|
|
72
|
+
defaultMessage: 'Search Text',
|
|
73
|
+
},
|
|
74
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { css } from 'styled-components';
|
|
2
|
+
import {
|
|
3
|
+
CAP_SPACE_44,
|
|
4
|
+
CAP_SPACE_28,
|
|
5
|
+
CAP_SPACE_20,
|
|
6
|
+
CAP_SPACE_12,
|
|
7
|
+
CAP_SPACE_08,
|
|
8
|
+
CAP_G07,
|
|
9
|
+
CAP_G12,
|
|
10
|
+
CAP_G06,
|
|
11
|
+
FONT_COLOR_05,
|
|
12
|
+
CAP_SPACE_16,
|
|
13
|
+
CAP_SPACE_24,
|
|
14
|
+
FONT_COLOR_02,
|
|
15
|
+
} from '@capillarytech/cap-ui-library/styled/variables';
|
|
16
|
+
|
|
17
|
+
export default css`
|
|
18
|
+
position: relative;
|
|
19
|
+
padding: 0 ${CAP_SPACE_16} ${CAP_SPACE_16};
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
.text-template-content {
|
|
23
|
+
margin-bottom: 10px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.word-count {
|
|
27
|
+
display: inline-block;
|
|
28
|
+
float: right;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.choice-title {
|
|
32
|
+
margin-bottom: ${CAP_SPACE_24};
|
|
33
|
+
color: ${FONT_COLOR_02};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
`;
|
|
37
|
+
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { injectIntl, FormattedMessage } from 'react-intl';
|
|
3
|
+
import CapTab from '@capillarytech/cap-ui-library/CapTab';
|
|
4
|
+
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
5
|
+
import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
|
|
6
|
+
import CapModal from '@capillarytech/cap-ui-library/CapModal';
|
|
7
|
+
import style, { CapModalStyles } from './style';
|
|
8
|
+
import withStyles from '../../../../hoc/withStyles';
|
|
9
|
+
import { TEXT, IMAGE, IMAGE_MAP, STICKER, MAX_LINE_WRAPPER_LIMIT, MAX_LINE_WRAPPER_LIMIT_FULL_MODE } from '../constants';
|
|
10
|
+
import { getTabPanes } from './utils';
|
|
11
|
+
import messages from './messages';
|
|
12
|
+
import { CAP_SPACE_16, CAP_SPACE_08 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
13
|
+
|
|
14
|
+
const StyledCapModal = withStyles(CapModal, CapModalStyles);
|
|
15
|
+
|
|
16
|
+
export const LineWrapper = ({
|
|
17
|
+
className,
|
|
18
|
+
index,
|
|
19
|
+
deleteWrapper,
|
|
20
|
+
selectedType,
|
|
21
|
+
shiftUp,
|
|
22
|
+
shiftDown,
|
|
23
|
+
lineWrappers,
|
|
24
|
+
intl,
|
|
25
|
+
...rest
|
|
26
|
+
}) => {
|
|
27
|
+
|
|
28
|
+
const [activeKey, updateActiveKey] = useState(TEXT);
|
|
29
|
+
const [selectedKey, updateSelectedKey] = useState(TEXT);
|
|
30
|
+
const [isConfirmModalVisible, togglePopup] = useState(false);
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
updateActiveKey(selectedType);
|
|
34
|
+
}, [selectedType]);
|
|
35
|
+
|
|
36
|
+
const onTabChange = (type) => {
|
|
37
|
+
const { content = {} } = rest;
|
|
38
|
+
const {
|
|
39
|
+
originalContentUrl,
|
|
40
|
+
previewImageUrl,
|
|
41
|
+
stickerUrl,
|
|
42
|
+
animatedStickerUrl,
|
|
43
|
+
selectedSticker,
|
|
44
|
+
stickerId,
|
|
45
|
+
packageId,
|
|
46
|
+
messageContent,
|
|
47
|
+
messageTitle,
|
|
48
|
+
baseUrl,
|
|
49
|
+
selectedTemplate
|
|
50
|
+
} = content;
|
|
51
|
+
|
|
52
|
+
const isTouched = (
|
|
53
|
+
originalContentUrl
|
|
54
|
+
|| previewImageUrl
|
|
55
|
+
|| stickerUrl
|
|
56
|
+
|| animatedStickerUrl
|
|
57
|
+
|| selectedSticker
|
|
58
|
+
|| stickerId
|
|
59
|
+
|| packageId
|
|
60
|
+
|| messageTitle
|
|
61
|
+
|| messageContent
|
|
62
|
+
|| baseUrl
|
|
63
|
+
|| selectedTemplate
|
|
64
|
+
);
|
|
65
|
+
if (!isTouched) {
|
|
66
|
+
updateActiveKey(type);
|
|
67
|
+
rest.updateMessageState({
|
|
68
|
+
isError: true,
|
|
69
|
+
index,
|
|
70
|
+
type,
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
togglePopup(true);
|
|
74
|
+
updateSelectedKey(type);
|
|
75
|
+
updateActiveKey(activeKey);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const saveChangesOnLeave = () => {
|
|
80
|
+
updateActiveKey(selectedKey);
|
|
81
|
+
rest.updateMessageState({
|
|
82
|
+
isError: true,
|
|
83
|
+
index,
|
|
84
|
+
type: selectedKey,
|
|
85
|
+
});
|
|
86
|
+
togglePopup(false);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const discardChangesOnLeave = () => {
|
|
90
|
+
updateActiveKey(activeKey);
|
|
91
|
+
togglePopup(false);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const operations = (
|
|
95
|
+
<>
|
|
96
|
+
<CapButton
|
|
97
|
+
type="flat"
|
|
98
|
+
onClick={() => shiftUp(index)}
|
|
99
|
+
disabled={index === 0 || rest.isFullMode}
|
|
100
|
+
style={{ padding: 0 }}
|
|
101
|
+
>
|
|
102
|
+
<CapIcon type="back" size="s" style={{ transform: 'rotate(90deg)'}}/>
|
|
103
|
+
</CapButton>
|
|
104
|
+
<CapButton
|
|
105
|
+
type="flat"
|
|
106
|
+
onClick={() => shiftDown(index)}
|
|
107
|
+
style={{ padding: `0 0 0 ${CAP_SPACE_08}` }}
|
|
108
|
+
disabled={(index+1) === lineWrappers || rest.isFullMode}
|
|
109
|
+
>
|
|
110
|
+
<CapIcon type="back" size="s" style={{ transform: 'rotate(270deg)'}}/>
|
|
111
|
+
</CapButton>
|
|
112
|
+
<CapButton
|
|
113
|
+
type="flat"
|
|
114
|
+
onClick={() => deleteWrapper(index)}
|
|
115
|
+
disabled={rest.isFullMode || lineWrappers === 1}
|
|
116
|
+
style={{ padding: `0 ${CAP_SPACE_16} 0 ${CAP_SPACE_16}`, marginRight: -20 }}
|
|
117
|
+
>
|
|
118
|
+
<CapIcon type="close" size="s"/>
|
|
119
|
+
</CapButton>
|
|
120
|
+
</>
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<div className={className}>
|
|
125
|
+
<CapTab
|
|
126
|
+
defaultActiveKey={TEXT}
|
|
127
|
+
activeKey={activeKey}
|
|
128
|
+
tabBarExtraContent={operations}
|
|
129
|
+
onChange={onTabChange}
|
|
130
|
+
panes={getTabPanes({ ...rest, index, activeKey, formatMessage: intl.formatMessage })}
|
|
131
|
+
/>
|
|
132
|
+
<StyledCapModal
|
|
133
|
+
title={intl.formatMessage(messages.changeModalTitle)}
|
|
134
|
+
visible={isConfirmModalVisible}
|
|
135
|
+
onOk={saveChangesOnLeave}
|
|
136
|
+
onCancel={discardChangesOnLeave}
|
|
137
|
+
centered
|
|
138
|
+
okText={intl.formatMessage(messages.modalSaveChangesButtonLabel)}
|
|
139
|
+
cancelText={intl.formatMessage(messages.modalDiscardChangesButtonLabel)}
|
|
140
|
+
closeText={intl.formatMessage(messages.modalDiscardChangesButtonLabel)}
|
|
141
|
+
width="450px"
|
|
142
|
+
>
|
|
143
|
+
<FormattedMessage {...messages.changeModalDescription} />
|
|
144
|
+
<div className="modal-description">
|
|
145
|
+
<FormattedMessage {...messages.changeModalLabel} />
|
|
146
|
+
</div>
|
|
147
|
+
</StyledCapModal>
|
|
148
|
+
</div>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export default injectIntl(withStyles(LineWrapper, style));
|