@capillarytech/creatives-library 6.7.1 → 6.8.0

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 (85) hide show
  1. package/assets/line-image-placeholder.svg +14 -0
  2. package/assets/line.png +0 -0
  3. package/assets/smiley-placeholder.svg +11 -0
  4. package/components/TemplatePreview/index.js +185 -8
  5. package/index.js +3 -3
  6. package/package.json +1 -1
  7. package/routes.js +2 -2
  8. package/services/api.js +3 -0
  9. package/styles/vendor/semantic/src/definitions/modules/accordion.less +219 -219
  10. package/v2Components/TemplatePreview/WechatRichmediaTemplatePreview/index.js +1 -1
  11. package/v2Components/TemplatePreview/assets/images/WECHAT_5x.png +0 -0
  12. package/v2Components/TemplatePreview/index.js +164 -12
  13. package/v2Components/TemplatePreview/messages.js +8 -0
  14. package/v2Containers/CreativesContainer/SlideBoxContent.js +51 -17
  15. package/v2Containers/CreativesContainer/index.js +23 -17
  16. package/v2Containers/Line/Container/Drawer/index.js +93 -0
  17. package/v2Containers/Line/Container/Image/constants.js +3 -0
  18. package/v2Containers/Line/Container/Image/index.js +460 -0
  19. package/v2Containers/Line/Container/Image/messages.js +86 -0
  20. package/v2Containers/Line/Container/Image/style.js +32 -0
  21. package/v2Containers/Line/Container/ImageMap/assets/hover/custom.png +0 -0
  22. package/v2Containers/Line/Container/ImageMap/assets/hover/templateEight.png +0 -0
  23. package/v2Containers/Line/Container/ImageMap/assets/hover/templateFive.png +0 -0
  24. package/v2Containers/Line/Container/ImageMap/assets/hover/templateFour.png +0 -0
  25. package/v2Containers/Line/Container/ImageMap/assets/hover/templateOne.png +0 -0
  26. package/v2Containers/Line/Container/ImageMap/assets/hover/templateSeven.png +0 -0
  27. package/v2Containers/Line/Container/ImageMap/assets/hover/templateSix.png +0 -0
  28. package/v2Containers/Line/Container/ImageMap/assets/hover/templateThree.png +0 -0
  29. package/v2Containers/Line/Container/ImageMap/assets/hover/templateTwo.png +0 -0
  30. package/v2Containers/Line/Container/ImageMap/assets/selected/custom.png +0 -0
  31. package/v2Containers/Line/Container/ImageMap/assets/selected/templateEight.png +0 -0
  32. package/v2Containers/Line/Container/ImageMap/assets/selected/templateFive.png +0 -0
  33. package/v2Containers/Line/Container/ImageMap/assets/selected/templateFour.png +0 -0
  34. package/v2Containers/Line/Container/ImageMap/assets/selected/templateOne.png +0 -0
  35. package/v2Containers/Line/Container/ImageMap/assets/selected/templateSeven.png +0 -0
  36. package/v2Containers/Line/Container/ImageMap/assets/selected/templateSix.png +0 -0
  37. package/v2Containers/Line/Container/ImageMap/assets/selected/templateThree.png +0 -0
  38. package/v2Containers/Line/Container/ImageMap/assets/selected/templateTwo.png +0 -0
  39. package/v2Containers/Line/Container/ImageMap/assets/templates/custom.png +0 -0
  40. package/v2Containers/Line/Container/ImageMap/assets/templates/templateEight.png +0 -0
  41. package/v2Containers/Line/Container/ImageMap/assets/templates/templateFive.png +0 -0
  42. package/v2Containers/Line/Container/ImageMap/assets/templates/templateFour.png +0 -0
  43. package/v2Containers/Line/Container/ImageMap/assets/templates/templateOne.png +0 -0
  44. package/v2Containers/Line/Container/ImageMap/assets/templates/templateSeven.png +0 -0
  45. package/v2Containers/Line/Container/ImageMap/assets/templates/templateSix.png +0 -0
  46. package/v2Containers/Line/Container/ImageMap/assets/templates/templateThree.png +0 -0
  47. package/v2Containers/Line/Container/ImageMap/assets/templates/templateTwo.png +0 -0
  48. package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/custom.png +0 -0
  49. package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateEight.png +0 -0
  50. package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateFive.png +0 -0
  51. package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateFour.png +0 -0
  52. package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateOne.png +0 -0
  53. package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateSeven.png +0 -0
  54. package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateSix.png +0 -0
  55. package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateThree.png +0 -0
  56. package/v2Containers/Line/Container/ImageMap/assets/templates_with_alphabets/templateTwo.png +0 -0
  57. package/v2Containers/Line/Container/ImageMap/constants.js +19 -0
  58. package/v2Containers/Line/Container/ImageMap/index.js +603 -0
  59. package/v2Containers/Line/Container/ImageMap/messages.js +126 -0
  60. package/v2Containers/Line/Container/ImageMap/style.js +94 -0
  61. package/v2Containers/Line/Container/ImageMap/templates.json +195 -0
  62. package/v2Containers/Line/Container/Sticker/index.js +224 -0
  63. package/v2Containers/Line/Container/Sticker/messages.js +34 -0
  64. package/v2Containers/Line/Container/Sticker/style.js +36 -0
  65. package/v2Containers/Line/Container/Sticker/utils.js +68 -0
  66. package/v2Containers/Line/Container/Text/index.js +338 -0
  67. package/v2Containers/Line/Container/Text/messages.js +74 -0
  68. package/v2Containers/Line/Container/Text/style.js +37 -0
  69. package/v2Containers/Line/Container/Wrapper/index.js +152 -0
  70. package/v2Containers/Line/Container/Wrapper/messages.js +46 -0
  71. package/v2Containers/Line/Container/Wrapper/style.js +44 -0
  72. package/v2Containers/Line/Container/Wrapper/utils.js +67 -0
  73. package/v2Containers/Line/Container/_lineCreate.scss +108 -0
  74. package/v2Containers/Line/Container/actions.js +99 -0
  75. package/v2Containers/Line/Container/constants.js +48 -0
  76. package/v2Containers/Line/Container/index.js +581 -0
  77. package/v2Containers/Line/Container/messages.js +66 -0
  78. package/v2Containers/Line/Container/reducer.js +103 -0
  79. package/v2Containers/Line/Container/sagas.js +137 -0
  80. package/v2Containers/Line/Container/selectors.js +30 -0
  81. package/v2Containers/Line/Container/style.js +57 -0
  82. package/v2Containers/Line/Create/index.js +1 -1
  83. package/v2Containers/Templates/index.js +40 -22
  84. package/v2Containers/Templates/messages.js +8 -0
  85. 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));