@capillarytech/creatives-library 6.8.3 → 6.8.5

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 (61) hide show
  1. package/app.js +1 -0
  2. package/package.json +1 -1
  3. package/utils/tagValidations.js +137 -0
  4. package/v2Components/TemplatePreview/WechatRichmediaTemplatePreview/_wechatRichmediaTemplatePrev.scss +151 -151
  5. package/v2Components/TemplatePreview/WechatRichmediaTemplatePreview/messages.js +33 -33
  6. package/v2Components/TemplatePreview/WechatRichmediaTemplatePreview/tests/index.test.js +10 -10
  7. package/v2Components/TemplatePreview/_templatePreview.scss +380 -380
  8. package/v2Components/TemplatePreview/assets/images/androidPushMessage.svg +44 -44
  9. package/v2Components/TemplatePreview/assets/images/home-screen-android.svg +21 -21
  10. package/v2Components/TemplatePreview/assets/images/home-screen-ios.svg +16 -16
  11. package/v2Components/TemplatePreview/assets/images/iPhonePushMessage.svg +134 -134
  12. package/v2Components/TemplatePreview/assets/images/mobile.svg +23 -23
  13. package/v2Components/TemplatePreview/assets/images/sms_mobile_android.svg +22 -22
  14. package/v2Components/TemplatePreview/assets/images/user-icon.svg +18 -18
  15. package/v2Components/TemplatePreview/assets/images/wechat-home-screen-android.svg +21 -21
  16. package/v2Components/TemplatePreview/assets/images/wechat-mobile.svg +77 -77
  17. package/v2Components/TemplatePreview/assets/images/wechat_mobile_android.svg +20 -20
  18. package/v2Components/TemplatePreview/index.js +1 -1
  19. package/v2Components/TemplatePreview/tests/index.test.js +10 -10
  20. package/v2Containers/CreativesContainer/SlideBoxFooter.js +51 -51
  21. package/v2Containers/CreativesContainer/actions.js +27 -27
  22. package/v2Containers/CreativesContainer/constants.js +17 -17
  23. package/v2Containers/CreativesContainer/index.scss +44 -44
  24. package/v2Containers/CreativesContainer/messages.js +305 -305
  25. package/v2Containers/CreativesContainer/reducer.js +29 -29
  26. package/v2Containers/CreativesContainer/sagas.js +11 -11
  27. package/v2Containers/CreativesContainer/selectors.js +30 -30
  28. package/v2Containers/CreativesContainer/tests/actions.test.js +18 -18
  29. package/v2Containers/CreativesContainer/tests/index.test.js +10 -10
  30. package/v2Containers/CreativesContainer/tests/reducer.test.js +9 -9
  31. package/v2Containers/CreativesContainer/tests/sagas.test.js +15 -15
  32. package/v2Containers/CreativesContainer/tests/selectors.test.js +10 -10
  33. package/v2Containers/Line/Container/Drawer/index.js +31 -3
  34. package/v2Containers/Line/Container/Drawer/messages.js +20 -0
  35. package/v2Containers/Line/Container/Image/index.js +35 -6
  36. package/v2Containers/Line/Container/ImageMap/constants.js +1 -1
  37. package/v2Containers/Line/Container/ImageMap/index.js +9 -8
  38. package/v2Containers/Line/Container/Text/index.js +20 -4
  39. package/v2Containers/Line/Container/Text/messages.js +4 -0
  40. package/v2Containers/Line/Container/Wrapper/index.js +1 -0
  41. package/v2Containers/Line/Container/index.js +33 -1
  42. package/v2Containers/Templates/_templates.scss +405 -405
  43. package/v2Containers/Templates/actions.js +117 -117
  44. package/v2Containers/Templates/constants.js +47 -47
  45. package/v2Containers/Templates/reducer.js +145 -145
  46. package/v2Containers/Templates/sagas.js +179 -179
  47. package/v2Containers/Templates/tests/actions.test.js +18 -18
  48. package/v2Containers/Templates/tests/index.test.js +10 -10
  49. package/v2Containers/Templates/tests/reducer.test.js +9 -9
  50. package/v2Containers/Templates/tests/sagas.test.js +15 -15
  51. package/v2Containers/Templates/tests/selectors.test.js +10 -10
  52. package/v2Containers/TemplatesV2/TemplatesV2.style.js +29 -29
  53. package/v2Containers/TemplatesV2/actions.js +16 -16
  54. package/v2Containers/TemplatesV2/constants.js +10 -10
  55. package/v2Containers/TemplatesV2/messages.js +61 -61
  56. package/v2Containers/TemplatesV2/selectors.js +25 -25
  57. package/v2Containers/TemplatesV2/tests/actions.test.js +18 -18
  58. package/v2Containers/TemplatesV2/tests/index.test.js +10 -10
  59. package/v2Containers/TemplatesV2/tests/reducer.test.js +9 -9
  60. package/v2Containers/TemplatesV2/tests/sagas.test.js +15 -15
  61. package/v2Containers/TemplatesV2/tests/selectors.test.js +10 -10
@@ -1,11 +1,11 @@
1
- // import { take, call, put, select } from 'redux-saga/effects';
2
-
3
- // Individual exports for testing
4
- export function* defaultSaga() {
5
- // See example in v2Containers/HomePage/sagas.js
6
- }
7
-
8
- // All sagas to be loaded
9
- export default [
10
- defaultSaga,
11
- ];
1
+ // import { take, call, put, select } from 'redux-saga/effects';
2
+
3
+ // Individual exports for testing
4
+ export function* defaultSaga() {
5
+ // See example in v2Containers/HomePage/sagas.js
6
+ }
7
+
8
+ // All sagas to be loaded
9
+ export default [
10
+ defaultSaga,
11
+ ];
@@ -1,30 +1,30 @@
1
- import { createSelector } from 'reselect';
2
-
3
- /**
4
- * Direct selector to the creativesContainer state domain
5
- */
6
- const selectCreativesContainerDomain = () => (state) => state.get('creativesContainer');
7
-
8
- /**
9
- * Other specific selectors
10
- */
11
-
12
-
13
- /**
14
- * Default selector used by CreativesContainer
15
- */
16
-
17
- const makeSelectCreativesContainer = () => createSelector(
18
- selectCreativesContainerDomain(),
19
- (substate) => substate.toJS()
20
- );
21
- const isLoading = () => createSelector(
22
- makeSelectCreativesContainer(),
23
- (substate) => substate.containerLoader
24
- );
25
-
26
- export default makeSelectCreativesContainer;
27
- export {
28
- selectCreativesContainerDomain,
29
- isLoading,
30
- };
1
+ import { createSelector } from 'reselect';
2
+
3
+ /**
4
+ * Direct selector to the creativesContainer state domain
5
+ */
6
+ const selectCreativesContainerDomain = () => (state) => state.get('creativesContainer');
7
+
8
+ /**
9
+ * Other specific selectors
10
+ */
11
+
12
+
13
+ /**
14
+ * Default selector used by CreativesContainer
15
+ */
16
+
17
+ const makeSelectCreativesContainer = () => createSelector(
18
+ selectCreativesContainerDomain(),
19
+ (substate) => substate.toJS()
20
+ );
21
+ const isLoading = () => createSelector(
22
+ makeSelectCreativesContainer(),
23
+ (substate) => substate.containerLoader
24
+ );
25
+
26
+ export default makeSelectCreativesContainer;
27
+ export {
28
+ selectCreativesContainerDomain,
29
+ isLoading,
30
+ };
@@ -1,18 +1,18 @@
1
-
2
- import {
3
- defaultAction,
4
- } from '../actions';
5
- import {
6
- DEFAULT_ACTION,
7
- } from '../constants';
8
-
9
- describe('CreativesContainer actions', () => {
10
- describe('Default Action', () => {
11
- it('has a type of DEFAULT_ACTION', () => {
12
- const expected = {
13
- type: DEFAULT_ACTION,
14
- };
15
- expect(defaultAction()).toEqual(expected);
16
- });
17
- });
18
- });
1
+
2
+ import {
3
+ defaultAction,
4
+ } from '../actions';
5
+ import {
6
+ DEFAULT_ACTION,
7
+ } from '../constants';
8
+
9
+ describe('CreativesContainer actions', () => {
10
+ describe('Default Action', () => {
11
+ it('has a type of DEFAULT_ACTION', () => {
12
+ const expected = {
13
+ type: DEFAULT_ACTION,
14
+ };
15
+ expect(defaultAction()).toEqual(expected);
16
+ });
17
+ });
18
+ });
@@ -1,10 +1,10 @@
1
- // import React from 'react';
2
- // import { shallow } from 'enzyme';
3
-
4
- // import { CreativesContainer } from '../index';
5
-
6
- describe('<CreativesContainer />', () => {
7
- it('Expect to have unit tests specified', () => {
8
- expect(true).toEqual(true);
9
- });
10
- });
1
+ // import React from 'react';
2
+ // import { shallow } from 'enzyme';
3
+
4
+ // import { CreativesContainer } from '../index';
5
+
6
+ describe('<CreativesContainer />', () => {
7
+ it('Expect to have unit tests specified', () => {
8
+ expect(true).toEqual(true);
9
+ });
10
+ });
@@ -1,9 +1,9 @@
1
-
2
- import { fromJS } from 'immutable';
3
- import creativesContainerReducer from '../reducer';
4
-
5
- describe('creativesContainerReducer', () => {
6
- it('returns the initial state', () => {
7
- expect(creativesContainerReducer(undefined, {})).toEqual(fromJS({}));
8
- });
9
- });
1
+
2
+ import { fromJS } from 'immutable';
3
+ import creativesContainerReducer from '../reducer';
4
+
5
+ describe('creativesContainerReducer', () => {
6
+ it('returns the initial state', () => {
7
+ expect(creativesContainerReducer(undefined, {})).toEqual(fromJS({}));
8
+ });
9
+ });
@@ -1,15 +1,15 @@
1
- /**
2
- * Test sagas
3
- */
4
-
5
- /* eslint-disable redux-saga/yield-effects */
6
- // import { take, call, put, select } from 'redux-saga/effects';
7
- // import { defaultSaga } from '../sagas';
8
-
9
- // const generator = defaultSaga();
10
-
11
- describe('defaultSaga Saga', () => {
12
- it('Expect to have unit tests specified', () => {
13
- expect(true).toEqual(true);
14
- });
15
- });
1
+ /**
2
+ * Test sagas
3
+ */
4
+
5
+ /* eslint-disable redux-saga/yield-effects */
6
+ // import { take, call, put, select } from 'redux-saga/effects';
7
+ // import { defaultSaga } from '../sagas';
8
+
9
+ // const generator = defaultSaga();
10
+
11
+ describe('defaultSaga Saga', () => {
12
+ it('Expect to have unit tests specified', () => {
13
+ expect(true).toEqual(true);
14
+ });
15
+ });
@@ -1,10 +1,10 @@
1
- // import { fromJS } from 'immutable';
2
- // import { makeSelectCreativesContainerDomain } from '../selectors';
3
-
4
- // const selector = makeSelectCreativesContainerDomain();
5
-
6
- describe('makeSelectCreativesContainerDomain', () => {
7
- it('Expect to have unit tests specified', () => {
8
- expect(true).toEqual(true);
9
- });
10
- });
1
+ // import { fromJS } from 'immutable';
2
+ // import { makeSelectCreativesContainerDomain } from '../selectors';
3
+
4
+ // const selector = makeSelectCreativesContainerDomain();
5
+
6
+ describe('makeSelectCreativesContainerDomain', () => {
7
+ it('Expect to have unit tests specified', () => {
8
+ expect(true).toEqual(true);
9
+ });
10
+ });
@@ -1,7 +1,11 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import CapInput from '@capillarytech/cap-ui-library/CapInput';
3
+ import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
4
+ import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
3
5
  import CapCustomCard from '@capillarytech/cap-ui-library/CapCustomCard';
6
+ import { injectIntl, FormattedMessage } from 'react-intl';
4
7
  import Pagination from '../../../../v2Components/Pagination';
8
+ import messages from './messages';
5
9
 
6
10
  const {CapCustomCardList} = CapCustomCard;
7
11
 
@@ -10,10 +14,22 @@ export const LineDrawer = ({
10
14
  cardDataList,
11
15
  isDrawer,
12
16
  searchPlaceholder,
17
+ intl: {
18
+ formatMessage,
19
+ },
20
+ Templates
13
21
  }) => {
14
22
 
15
23
  const [currentPage, updateCurrentPage] = useState(0);
16
24
  const [searchText, updateSearchText] = useState('');
25
+ const [isSearching, updateSearchStatus] = useState(false);
26
+
27
+ useEffect(() => {
28
+ const { getAllTemplatesInProgress } = Templates || {};
29
+ if (getAllTemplatesInProgress !== undefined) {
30
+ updateSearchStatus(getAllTemplatesInProgress);
31
+ }
32
+ }, [Templates]);
17
33
 
18
34
  useEffect(() => {
19
35
  if (!isDrawer) {
@@ -22,6 +38,9 @@ export const LineDrawer = ({
22
38
  }
23
39
  }, [isDrawer]);
24
40
 
41
+ useEffect(() => {
42
+ }, [cardDataList]);
43
+
25
44
  let delayTimer = 0;
26
45
 
27
46
  const getAllLineTemplate = ({params = {} , getNextPage, resetPage}, isReRender = false) => {
@@ -67,7 +86,7 @@ export const LineDrawer = ({
67
86
  }
68
87
 
69
88
  return (
70
- <>
89
+ <CapSpin spinning={isSearching} tip={formatMessage(messages.gettingAllTemplates)} style={{width: '100%'}}>
71
90
  <CapInput.Search
72
91
  className="search-text"
73
92
  style={{width: 324}}
@@ -77,6 +96,15 @@ export const LineDrawer = ({
77
96
  onClear={() => searchTemplate('')}
78
97
  />
79
98
  <Pagination onPageChange={() => { getAllLineTemplate({getNextPage: true}); }} paginationSelector="pagination-container">
99
+ {
100
+ !cardDataList.length
101
+ ? (
102
+ <CapHeading type="h6" style={{ textAlign: 'center', padding: 20 }}>
103
+ <FormattedMessage {...messages.noTemplatesFound} />
104
+ </CapHeading>
105
+ )
106
+ : null
107
+ }
80
108
  <div className="pagination-container">
81
109
  <CapCustomCardList
82
110
  key={'LINE-card-list'}
@@ -86,8 +114,8 @@ export const LineDrawer = ({
86
114
  />
87
115
  </div>
88
116
  </Pagination>
89
- </>
117
+ </CapSpin>
90
118
  )
91
119
  }
92
120
 
93
- export default LineDrawer;
121
+ export default injectIntl(LineDrawer);
@@ -0,0 +1,20 @@
1
+
2
+
3
+ /*
4
+ * LineDrawer Messages
5
+ *
6
+ * This contains all the text for the LineDrawer component.
7
+ */
8
+ import { defineMessages } from 'react-intl';
9
+ const scope = `creatives.containersV2.LineDrawer`;
10
+
11
+ export default defineMessages({
12
+ "noTemplatesFound": {
13
+ id: `${scope}.noTemplatesFound`,
14
+ defaultMessage: 'No templates found',
15
+ },
16
+ "gettingAllTemplates": {
17
+ id: `${scope}.gettingAllTemplates`,
18
+ defaultMessage: "Getting all templates...",
19
+ },
20
+ });
@@ -39,6 +39,9 @@ export const LineImage = ({
39
39
  activeKey,
40
40
  Templates,
41
41
  getAllTemplates,
42
+ uploadedAssetList,
43
+ updateUploadedAssetList,
44
+ deleteUploadedImgList,
42
45
  }) => {
43
46
  if (activeKey !== 'image') {
44
47
  return null;
@@ -81,17 +84,40 @@ export const LineImage = ({
81
84
  }, [errorMessageTitle, imageSrc, messageTitle, isImageError]);
82
85
 
83
86
  useEffect(() => {
84
- const imgSrc = get(Line, 'uploadedAssetData.metaInfo.secure_file_path', '');
85
- const imgPreview = get(Line, 'uploadedAssetData.metaInfo.secure_file_path_preview', '');
87
+ if (Line.uploadedAssetData && Object.keys(Line.uploadedAssetData).length) {
88
+ const imgSrc = get(Line, 'uploadedAssetData.metaInfo.secure_file_path', '');
89
+ const imgPreview = get(Line, 'uploadedAssetData.metaInfo.secure_file_path_preview', '');
90
+ updateUploadedAssetList({
91
+ ...uploadedAssetList,
92
+ [index]: {
93
+ imgPreview,
94
+ imgSrc,
95
+ },
96
+ });
97
+ actions.clearAsset();
98
+ }
99
+ }, [Line.uploadedAssetData]);
100
+
101
+ useEffect(() => {
102
+ const imgSrc = get(uploadedAssetList[index], 'imgSrc', '');
103
+ const imgPreview = get(uploadedAssetList[index], 'imgPreview', '');
86
104
 
87
105
  if (imgSrc) {
88
106
  updateImageSrc(imgSrc);
89
107
  updateImageStatus(true);
90
- }
91
- if (imgPreview) {
92
108
  updateImagePreview(imgPreview);
109
+
110
+ updateMessageState({
111
+ isError: !imgSrc || !(isFullMode ? messageTitle : true) || errorMessageTitle,
112
+ originalContentUrl: imgSrc,
113
+ previewImageUrl: imgPreview,
114
+ messageTitle,
115
+ index,
116
+ type: 'image',
117
+ messageType: 'originalContentUrl',
118
+ });
93
119
  }
94
- }, [Line]);
120
+ }, [uploadedAssetList]);
95
121
 
96
122
  const submitAction = (data, incorrectFile) => {
97
123
  const {
@@ -105,8 +131,9 @@ export const LineImage = ({
105
131
  type,
106
132
  } = data;
107
133
  if (incorrectFile || size > LINE_IMG_SIZE || height > LINE_IMG_HEIGHT || width > LINE_IMG_WIDTH) {
108
- updateImageErrorMessage(formatMessage(messages.lineImageIncorrectSize))
134
+ updateImageErrorMessage(formatMessage(messages.lineImageIncorrectSize));
109
135
  } else {
136
+ updateImageErrorMessage('');
110
137
  data.fileParams.isGeneratePreview = true;
111
138
  actions.uploadAsset(
112
139
  data.file,
@@ -207,6 +234,7 @@ export const LineImage = ({
207
234
  if (!isFullMode) {
208
235
  updateCreateNew(false);
209
236
  }
237
+ deleteUploadedImgList(index);
210
238
  updateImageSrc('');
211
239
  updateImagePreview('');
212
240
  updateMessageState({
@@ -363,6 +391,7 @@ export const LineImage = ({
363
391
  getAllTemplates={getAllTemplates}
364
392
  cardDataList={cardDataList}
365
393
  isDrawer={isTemplateDrawerRequired}
394
+ Templates={Templates}
366
395
  searchPlaceholder={formatMessage(messages.searchImages)}
367
396
  />
368
397
  </>
@@ -1,7 +1,7 @@
1
1
  export const LINE_ASSET_WIDTH = 1040;
2
2
  export const LINE_ASSET_HEIGHT = 1040;
3
3
  export const LINE_CUSTOM_ASSET_HEIGHT_MIN = 520;
4
- export const LINE_CUSTOM_ASSET_HEIGHT_MAX= 1040;
4
+ export const LINE_CUSTOM_ASSET_HEIGHT_MAX= 2080;
5
5
  export const DEFAULT_ASSET_TYPE = 'default';
6
6
  export const CUSTOM_ASSET_TYPE = 'custom';
7
7
  export const DEFAULT_TEMPLATES = [
@@ -164,11 +164,12 @@ export const LineImageMap = ({
164
164
  type,
165
165
  } = data;
166
166
  const validWidth = width === LINE_ASSET_WIDTH;
167
- const validHeight = assetType === CUSTOM_ASSET_TYPE ? ( LINE_CUSTOM_ASSET_HEIGHT_MIN <= height && height <= LINE_CUSTOM_ASSET_HEIGHT_MAX) : height === LINE_ASSET_HEIGHT;
168
- if (incorrectFile || size > LINE_IMG_SIZE || !validWidth || !validHeight) {
169
- updateImageErrorMessage(formatMessage(messages.lineImageMapIncorrectSize))
167
+ const isCustom = assetType === CUSTOM_ASSET_TYPE;
168
+ const validHeight = isCustom ? ( LINE_CUSTOM_ASSET_HEIGHT_MIN <= height && height <= LINE_CUSTOM_ASSET_HEIGHT_MAX) : height === LINE_ASSET_HEIGHT;
169
+ if (incorrectFile || !validWidth || !validHeight) {
170
+ updateImageErrorMessage(formatMessage(messages.lineImageMapIncorrectSize));
170
171
  } else {
171
- updateImageErrorMessage('')
172
+ updateImageErrorMessage('');
172
173
  data.fileParams.isGeneratePreview = true;
173
174
  updateBaseSize({
174
175
  height,
@@ -176,7 +177,7 @@ export const LineImageMap = ({
176
177
  });
177
178
  actions.uploadAsset(
178
179
  data.file,
179
- data.type,
180
+ isCustom ? `${data.type}?assetType=${CUSTOM_ASSET_TYPE}` : data.type,
180
181
  data.fileParams,
181
182
  );
182
183
  }
@@ -323,12 +324,12 @@ export const LineImageMap = ({
323
324
  <CapHeading className="dragger-or" type="label6">
324
325
  <FormattedMessage {...messages.or} />
325
326
  </CapHeading>
326
- <CapButton className="dragger-button" type="secondary" style={{marginRight: CAP_SPACE_08}}>
327
+ <CapButton className="dragger-button" type="secondary" style={{marginRight: CAP_SPACE_08}} disabled={!imageMapTemplate}>
327
328
  <FormattedMessage {...messages.uploadComputer} />
328
329
  </CapButton>
329
330
  </CapUploader.CapDragger>
330
331
  <CapLabel type="label9" style={{marginTop: CAP_SPACE_12 }}>
331
- {formatMessage(messages.imageDimenstionDescription, {dimensions: assetType === DEFAULT_ASSET_TYPE ? '1040 X 1040 px' : '1040 X 520 - 2040 px'})}
332
+ {formatMessage(messages.imageDimenstionDescription, {dimensions: assetType === DEFAULT_ASSET_TYPE ? '1040 X 1040 px' : '1040 X 520 - 2080 px'})}
332
333
  </CapLabel>
333
334
  <CapDivider />
334
335
  </>);
@@ -337,7 +338,7 @@ export const LineImageMap = ({
337
338
  <>
338
339
  <CapImage className="base-image-preview" src={`${imageSrc}/1040`} />
339
340
  <CapLabel type="label9" style={{marginTop: CAP_SPACE_12 }}>
340
- {formatMessage(messages.imageDimenstionDescription, {dimensions: assetType === DEFAULT_ASSET_TYPE ? '1040 X 1040 px' : '1040 X 520 - 2040 px'})}
341
+ {formatMessage(messages.imageDimenstionDescription, {dimensions: assetType === DEFAULT_ASSET_TYPE ? '1040 X 1040 px' : '1040 X 520 - 2080 px'})}
341
342
  </CapLabel>
342
343
  <CapDivider />
343
344
  </>
@@ -15,6 +15,8 @@ import messages from './messages';
15
15
  import style from './style';
16
16
  import withStyles from '../../../../hoc/withStyles';
17
17
 
18
+ import { validateTags } from '../../../../utils/tagValidations';
19
+
18
20
  const { TextArea } = CapInput;
19
21
  const {CapCustomCardList} = CapCustomCard;
20
22
 
@@ -71,7 +73,7 @@ export const LineText = ({
71
73
  useEffect(() => {
72
74
  if (messageContent && (isFullMode ? messageTitle : true)) {
73
75
  updateMessageState({
74
- isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? messageTitle : true) || (errorMessageTextarea && errorMessageTitle)),
76
+ isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? messageTitle : true) || (errorMessageTextarea || errorMessageTitle)),
75
77
  messageContent,
76
78
  messageTitle,
77
79
  index,
@@ -116,10 +118,19 @@ export const LineText = ({
116
118
 
117
119
  const updateTextContentError = (value) => {
118
120
  let errorMessage = false;
121
+ const { valid } = validateTags({
122
+ content: value,
123
+ tagsParam: tags,
124
+ injectedTagsParams: injectedTags,
125
+ location,
126
+ tagModule: 'outbound',
127
+ }) || {};
119
128
  if (value === '') {
120
129
  errorMessage = formatMessage(messages.emptyTitleErrorMessage);
121
130
  } else if (value.length > charLimit) {
122
131
  errorMessage = formatMessage(messages.limitExceededContentErrorMessage);
132
+ } else if (!valid && !isFullMode) {
133
+ errorMessage = formatMessage(messages.invalidTagError);
123
134
  }
124
135
  updateErrorMessageTextArea(errorMessage);
125
136
  }
@@ -128,7 +139,7 @@ export const LineText = ({
128
139
  updateTextMessageContent(value);
129
140
  updateTextContentError(value);
130
141
  updateMessageState({
131
- isError: (value.length > charLimit) || (!value || !(isFullMode ? messageTitle : true) || (!value && errorMessageTitle)),
142
+ isError: (value.length > charLimit) || (!value || !(isFullMode ? messageTitle : true) || (!value || errorMessageTitle)),
132
143
  messageContent: value,
133
144
  messageTitle,
134
145
  index,
@@ -149,7 +160,7 @@ export const LineText = ({
149
160
  updateTextMessageTitle(value);
150
161
  updateTextTitleError(value);
151
162
  updateMessageState({
152
- isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? value : true) || (!value && errorMessageTextarea)),
163
+ isError: (messageContent.length > charLimit) || (!messageContent || !(isFullMode ? value : true) || (!value || errorMessageTextarea)),
153
164
  messageContent,
154
165
  messageTitle: value,
155
166
  index,
@@ -158,7 +169,11 @@ export const LineText = ({
158
169
  });
159
170
  }
160
171
 
161
- const onTagSelect = (data) => updateTextMessageContent(`${messageContent}{{${data}}}`);
172
+ const onTagSelect = (data) => {
173
+ const messageData = `${messageContent}{{${data}}}`;
174
+ updateTextMessageContent(messageData);
175
+ updateTextContentError(messageData);
176
+ }
162
177
 
163
178
  const setNewContent = () => updateCreateNew(true);
164
179
 
@@ -296,6 +311,7 @@ export const LineText = ({
296
311
  isDrawer={isDrawerRequired}
297
312
  className="drawer-head"
298
313
  searchPlaceholder={formatMessage(messages.searchText)}
314
+ Templates={Templates}
299
315
  />
300
316
  </>
301
317
  );
@@ -71,4 +71,8 @@ export default defineMessages({
71
71
  id: `${scope}.searchText`,
72
72
  defaultMessage: 'Search Text',
73
73
  },
74
+ "invalidTagError": {
75
+ id: `${scope}.invalidTagError`,
76
+ defaultMessage: 'Please check the message content for unsupported/missing tags',
77
+ },
74
78
  });
@@ -71,6 +71,7 @@ export const LineWrapper = ({
71
71
  });
72
72
  } else {
73
73
  togglePopup(true);
74
+ rest.deleteUploadedImgList(index);
74
75
  updateSelectedKey(type);
75
76
  updateActiveKey(activeKey);
76
77
  }
@@ -62,6 +62,7 @@ export const LineContainer = ({
62
62
  const [isEditFlow, checkEditFlow] = useState(false);
63
63
  const [isEditLoading, updateEditLoading] = useState(false);
64
64
  const [accountSelectFlow, updateAccountSelectFlow] = useState(false);
65
+ const [uploadedAssetList, updateUploadedAssetList] = useState({});
65
66
  const [selectedAccount, updateSelectedAccount] = useState('');
66
67
 
67
68
  useEffect(() => {
@@ -71,6 +72,7 @@ export const LineContainer = ({
71
72
  const queryParams = {"sortBy":"Most Recent","page":1,"perPage":25};
72
73
  templateActions.getAllTemplates('Line', queryParams);
73
74
  }
75
+ return () => actions.clearAsset();
74
76
  }, []);
75
77
 
76
78
  const onAccountSelect = (account) => {
@@ -174,6 +176,12 @@ export const LineContainer = ({
174
176
  }
175
177
  }, [templateData]);
176
178
 
179
+ const deleteUploadedImgList = (selectedIndex) => {
180
+ const newUploadedAssetList = { ...uploadedAssetList };
181
+ delete newUploadedAssetList[selectedIndex];
182
+ updateUploadedAssetList(newUploadedAssetList);
183
+ }
184
+
177
185
  const addLineWrappers = () => {
178
186
  updateLineWrapperContent([...lineWrapperContents, ...initialWrapperContent])
179
187
  }
@@ -181,6 +189,11 @@ export const LineContainer = ({
181
189
  const deleteWrapper = index => {
182
190
  const selectedIndex = lineWrapperContents.findIndex((el, i) => i === index);
183
191
  if (selectedIndex > -1) {
192
+ // change uploaded img sequence
193
+ const newUploadedAssetList = { ...uploadedAssetList };
194
+ delete newUploadedAssetList[index];
195
+ updateUploadedAssetList(newUploadedAssetList);
196
+
184
197
  const newLineWrapperContents = [...lineWrapperContents];
185
198
  newLineWrapperContents.splice(selectedIndex, 1);
186
199
  updateLineWrapperContent(newLineWrapperContents);
@@ -191,6 +204,14 @@ export const LineContainer = ({
191
204
  const selectedIndex = lineWrapperContents.findIndex((el, i) => i === index);
192
205
  const selectedElement = lineWrapperContents.find((el, i) => i === index);
193
206
  if (selectedIndex > -1) {
207
+ // change uploaded img sequence
208
+ const newUploadedAssetList = { ...uploadedAssetList };
209
+ const selectedUploadedAsset = uploadedAssetList[index];
210
+ const newPositionUploadedAsset = uploadedAssetList[index - 1];
211
+ newUploadedAssetList[index - 1] = selectedUploadedAsset;
212
+ newUploadedAssetList[index] = newPositionUploadedAsset;
213
+ updateUploadedAssetList(newUploadedAssetList);
214
+
194
215
  const newLineWrapperContents = [...lineWrapperContents];
195
216
  newLineWrapperContents.splice(selectedIndex, 1);
196
217
  newLineWrapperContents.splice(selectedIndex - 1, 0, selectedElement);
@@ -202,6 +223,14 @@ export const LineContainer = ({
202
223
  const selectedIndex = lineWrapperContents.findIndex((el, i) => i === index);
203
224
  const selectedElement = lineWrapperContents.find((el, i) => i === index);
204
225
  if (selectedIndex > -1) {
226
+ // change uploaded img sequence
227
+ const newUploadedAssetList = { ...uploadedAssetList };
228
+ const selectedUploadedAsset = uploadedAssetList[index];
229
+ const newPositionUploadedAsset = uploadedAssetList[index + 1];
230
+ newUploadedAssetList[index + 1] = selectedUploadedAsset;
231
+ newUploadedAssetList[index] = newPositionUploadedAsset;
232
+ updateUploadedAssetList(newUploadedAssetList);
233
+
205
234
  const newLineWrapperContents = [...lineWrapperContents];
206
235
  newLineWrapperContents.splice(selectedIndex, 1);
207
236
  newLineWrapperContents.splice(selectedIndex + 1, 0, selectedElement);
@@ -258,6 +287,9 @@ export const LineContainer = ({
258
287
  lineWrappers={lineWrapperContents.length}
259
288
  Templates={Templates}
260
289
  getAllTemplates={templateActions.getAllTemplates}
290
+ uploadedAssetList={uploadedAssetList}
291
+ deleteUploadedImgList={deleteUploadedImgList}
292
+ updateUploadedAssetList={updateUploadedAssetList}
261
293
  />
262
294
  );
263
295
  });
@@ -505,7 +537,7 @@ export const LineContainer = ({
505
537
  <div className={className}>
506
538
  <CapSpin spinning={isLoading}>
507
539
  <CapRow>
508
- <CapColumn span={14}>
540
+ <CapColumn span={14} style={{ zIndex: 1 }}>
509
541
  {getAccountSection()}
510
542
  <CapHeader
511
543
  title={formatMessage(messages.lineCreativeTitle)}