@capillarytech/creatives-library 8.0.9 → 8.0.11
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/config/app.js +2 -0
- package/containers/App/constants.js +1 -0
- package/initialState.js +3 -0
- package/package.json +1 -1
- package/services/api.js +20 -0
- package/services/tests/api.test.js +148 -0
- package/utils/common.js +7 -0
- package/utils/commonUtils.js +7 -1
- package/utils/tagValidations.js +99 -1
- package/utils/tests/commonUtil.test.js +37 -1
- package/utils/tests/tagValidations.test.js +392 -2
- package/v2Components/Ckeditor/index.js +12 -10
- package/v2Components/ErrorInfoNote/index.js +89 -0
- package/v2Components/ErrorInfoNote/messages.js +29 -0
- package/v2Components/ErrorInfoNote/style.scss +72 -0
- package/v2Components/FormBuilder/_formBuilder.scss +4 -1
- package/v2Components/FormBuilder/index.js +171 -70
- package/v2Components/FormBuilder/messages.js +8 -0
- package/v2Containers/Cap/actions.js +8 -0
- package/v2Containers/Cap/constants.js +4 -0
- package/v2Containers/Cap/mockData.js +74 -0
- package/v2Containers/Cap/reducer.js +12 -0
- package/v2Containers/Cap/sagas.js +28 -1
- package/v2Containers/Cap/selectors.js +5 -0
- package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +1 -0
- package/v2Containers/Cap/tests/reducer.test.js +50 -0
- package/v2Containers/Cap/tests/saga.test.js +81 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +7 -0
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +40 -17
- package/v2Containers/CreativesContainer/constants.js +1 -0
- package/v2Containers/CreativesContainer/index.js +45 -4
- package/v2Containers/CreativesContainer/index.scss +13 -1
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +16 -0
- package/v2Containers/Email/_email.scss +3 -0
- package/v2Containers/Email/index.js +2 -0
- package/v2Containers/EmailWrapper/index.js +3 -0
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +3 -0
- package/v2Containers/Line/Container/sagas.js +1 -1
- package/v2Containers/MobilePush/Edit/constants.js +2 -0
- package/v2Containers/MobilePush/Edit/index.js +91 -24
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +93 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +12 -0
- package/v2Containers/Viber/constants.js +1 -1
- package/v2Containers/Viber/index.js +19 -19
- package/v2Containers/Viber/messages.js +0 -4
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +12 -0
|
@@ -6,9 +6,20 @@ import {
|
|
|
6
6
|
REQUEST,
|
|
7
7
|
SUCCESS,
|
|
8
8
|
FAILURE,
|
|
9
|
+
GET_LIQUID_TAGS_SUCCESS,
|
|
10
|
+
GET_LIQUID_TAGS_FAILURE,
|
|
11
|
+
GET_LIQUID_TAGS_REQUEST,
|
|
12
|
+
GET_SCHEMA_FOR_ENTITY_SUCCESS,
|
|
9
13
|
} from '../constants';
|
|
10
14
|
import reducer from '../reducer';
|
|
11
15
|
import initialState from '../../../initialState';
|
|
16
|
+
import {
|
|
17
|
+
expectedStateGetLiquidTagsRequest,
|
|
18
|
+
expectedStateGetLiquidTagsFailure,
|
|
19
|
+
expectedStateGetLiquidTagsSuccess,
|
|
20
|
+
expectedStateGetSchemaForEntitySuccessTAG,
|
|
21
|
+
expectedStateGetSchemaForEntitySuccess
|
|
22
|
+
} from '../mockData';
|
|
12
23
|
|
|
13
24
|
const mockedInitialState = fromJS(initialState.cap);
|
|
14
25
|
|
|
@@ -56,4 +67,43 @@ describe('should handle GET_SUPPORT_VIDEOS_CONFIG', () => {
|
|
|
56
67
|
demoVideoAndLinkJSONStatus: FAILURE,
|
|
57
68
|
});
|
|
58
69
|
});
|
|
70
|
+
it('handles the GET_LIQUID_TAGS_REQUEST action', () => {
|
|
71
|
+
const action = {
|
|
72
|
+
type: GET_LIQUID_TAGS_REQUEST,
|
|
73
|
+
};
|
|
74
|
+
expect(reducer(mockedInitialState, action).toJS()).toEqual(expectedStateGetLiquidTagsRequest);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('handles the GET_LIQUID_TAGS_FAILURE action', () => {
|
|
78
|
+
const action = {
|
|
79
|
+
type: GET_LIQUID_TAGS_FAILURE,
|
|
80
|
+
};
|
|
81
|
+
expect(reducer(mockedInitialState, action).toJS()).toEqual(expectedStateGetLiquidTagsFailure);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('handles the GET_LIQUID_TAGS_SUCCESS action', () => {
|
|
85
|
+
const action = {
|
|
86
|
+
type: GET_LIQUID_TAGS_SUCCESS,
|
|
87
|
+
};
|
|
88
|
+
expect(reducer(mockedInitialState, action).toJS()).toEqual(expectedStateGetLiquidTagsSuccess);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('handles the GET_SCHEMA_FOR_ENTITY_SUCCESS action with action type as TAG', () => {
|
|
92
|
+
const action = {
|
|
93
|
+
type: GET_SCHEMA_FOR_ENTITY_SUCCESS,
|
|
94
|
+
data: {metaEntities:{standard:{"random": "32"}}},
|
|
95
|
+
entityType: "TAG"
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
expect(reducer(mockedInitialState, action).toJS()).toEqual(expectedStateGetSchemaForEntitySuccessTAG);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('handles the GET_SCHEMA_FOR_ENTITY_SUCCESS action', () => {
|
|
102
|
+
const action = {
|
|
103
|
+
type: GET_SCHEMA_FOR_ENTITY_SUCCESS,
|
|
104
|
+
data: {metaEntities:{standard:{"random": "32"}}},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
expect(reducer(mockedInitialState, action).toJS()).toEqual(expectedStateGetSchemaForEntitySuccess);
|
|
108
|
+
});
|
|
59
109
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { take, fork, cancel, takeLatest } from 'redux-saga/effects';
|
|
2
2
|
import { expectSaga } from 'redux-saga-test-plan';
|
|
3
3
|
import * as matchers from 'redux-saga-test-plan/matchers';
|
|
4
|
-
import { authorize, loginFlow, fetchSchemaForEntity, getSupportVideosConfig, watchForGetVideosConfig, watchFetchSchemaForEntity } from '../sagas';
|
|
4
|
+
import { authorize, loginFlow, fetchSchemaForEntity, getSupportVideosConfig, watchForGetVideosConfig, watchFetchSchemaForEntity,watchLiquidEntity, getLiquidTags } from '../sagas';
|
|
5
5
|
import { throwError } from 'redux-saga-test-plan/providers';
|
|
6
6
|
import * as api from '../../../services/api';
|
|
7
7
|
import {
|
|
@@ -14,6 +14,9 @@ import {
|
|
|
14
14
|
GET_SUPPORT_VIDEOS_CONFIG_SUCCESS,
|
|
15
15
|
GET_SUPPORT_VIDEOS_CONFIG_FAILURE,
|
|
16
16
|
GET_SCHEMA_FOR_ENTITY_REQUEST,
|
|
17
|
+
GET_LIQUID_TAGS_SUCCESS,
|
|
18
|
+
GET_LIQUID_TAGS_FAILURE,
|
|
19
|
+
GET_LIQUID_TAGS_REQUEST,
|
|
17
20
|
} from '../constants';
|
|
18
21
|
import { callback, error, error2, videoConfigData } from '../../mockdata';
|
|
19
22
|
|
|
@@ -207,4 +210,81 @@ describe('watchFetchSchemaForEntity saga', () => {
|
|
|
207
210
|
takeLatest(GET_SCHEMA_FOR_ENTITY_REQUEST, fetchSchemaForEntity),
|
|
208
211
|
);
|
|
209
212
|
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
describe('getLiquidTags saga', () => {
|
|
217
|
+
it('handles successful API response', () => {
|
|
218
|
+
const action = { data: 'templateContent', callback: () =>{}};
|
|
219
|
+
const result = { result :{errors: [{message: "error in content"}]} };
|
|
220
|
+
|
|
221
|
+
expectSaga(getLiquidTags, action)
|
|
222
|
+
.provide([
|
|
223
|
+
[matchers.call.fn(api.getLiquidTags, 'templateContent'), result],
|
|
224
|
+
[matchers.call.fn(api.askAiraForLiquid, { templateContent: 'templateContent', errorMessage: result?.result?.errors[0]?.message }), { result: { errors: [] } }],
|
|
225
|
+
])
|
|
226
|
+
.call.fn(action.callback, result)
|
|
227
|
+
.put({ type: GET_LIQUID_TAGS_SUCCESS })
|
|
228
|
+
.run();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('handles successful API response for askAira', () => {
|
|
232
|
+
const action = { data: 'templateContent', callback: () =>{}};
|
|
233
|
+
const result = { result :{errors: [{message: "error in content"}]} };
|
|
234
|
+
|
|
235
|
+
expectSaga(getLiquidTags, action)
|
|
236
|
+
.provide([
|
|
237
|
+
[matchers.call.fn(api.getLiquidTags, 'templateContent'), result],
|
|
238
|
+
[matchers.call.fn(api.askAiraForLiquid, { templateContent: 'templateContent', errorMessage: result?.result?.errors[0]?.message }), {result: { errors: [{message: "Something went wrong"}]} }],
|
|
239
|
+
])
|
|
240
|
+
.call.fn(action.callback, result)
|
|
241
|
+
.put({ type: GET_LIQUID_TAGS_SUCCESS })
|
|
242
|
+
.run();
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('handles API response with errors', () => {
|
|
246
|
+
const action = { data: 'templateContent' };
|
|
247
|
+
const result = { errors: [{ message: 'Error message' }] };
|
|
248
|
+
|
|
249
|
+
expectSaga(getLiquidTags, action)
|
|
250
|
+
.provide([
|
|
251
|
+
[matchers.call.fn(api.getLiquidTags, 'templateContent'), result],
|
|
252
|
+
[matchers.call.fn(api.askAiraForLiquid, { templateContent: 'templateContent', errorMessage: result.errors[0].message }), {result: { errors: [{message: "Something went wrong"}]} }],
|
|
253
|
+
])
|
|
254
|
+
.not.call.fn(action.callback, result)
|
|
255
|
+
.put({ type: GET_LIQUID_TAGS_FAILURE, error: true })
|
|
256
|
+
.run();
|
|
257
|
+
});
|
|
258
|
+
it('handles API response with undefined', () => {
|
|
259
|
+
const action = { data: 'templateContent' };
|
|
260
|
+
const result = undefined;
|
|
261
|
+
|
|
262
|
+
expectSaga(getLiquidTags, action)
|
|
263
|
+
.provide([
|
|
264
|
+
[matchers.call.fn(api.getLiquidTags, 'templateContent'), result],
|
|
265
|
+
])
|
|
266
|
+
.not.call.fn(action.callback, result)
|
|
267
|
+
.put({ type: GET_LIQUID_TAGS_FAILURE, error: true })
|
|
268
|
+
.run();
|
|
269
|
+
});
|
|
270
|
+
it('handles error thrown during API call', () => {
|
|
271
|
+
const action = { data: 'templateContent' };
|
|
272
|
+
const error = new Error('API error');
|
|
273
|
+
|
|
274
|
+
expectSaga(getLiquidTags, action)
|
|
275
|
+
.provide([
|
|
276
|
+
[matchers.call.fn(api.getLiquidTags, 'templateContent'), throwError(error)],
|
|
277
|
+
])
|
|
278
|
+
.put({ type: GET_LIQUID_TAGS_FAILURE, error })
|
|
279
|
+
.run();
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
describe('watchForGetLiquidTags saga', () => {
|
|
284
|
+
const generator = watchLiquidEntity();
|
|
285
|
+
it('should call watchers functions', () => {
|
|
286
|
+
expect(generator.next().value).toEqual(
|
|
287
|
+
takeLatest(GET_LIQUID_TAGS_REQUEST, getLiquidTags),
|
|
288
|
+
);
|
|
289
|
+
});
|
|
210
290
|
});
|
|
@@ -153,6 +153,8 @@ export function SlideBoxContent(props) {
|
|
|
153
153
|
hideTestAndPreviewBtn,
|
|
154
154
|
getCmsTemplatesInProgress = false,
|
|
155
155
|
moduleType,
|
|
156
|
+
showLiquidErrorInFooter,
|
|
157
|
+
creativesMode,
|
|
156
158
|
} = props;
|
|
157
159
|
const type = (messageDetails.type || '').toLowerCase(); // type is context in get tags values : outbound | dvs | referral | loyalty | coupons
|
|
158
160
|
const query = { type: !isFullMode && 'embedded', module: isFullMode ? 'default' : 'library', isEditFromCampaigns: (templateData || {}).isEditFromCampaigns};
|
|
@@ -601,6 +603,7 @@ export function SlideBoxContent(props) {
|
|
|
601
603
|
onTestContentClicked={onTestContentClicked}
|
|
602
604
|
getCmsTemplatesInProgress={getCmsTemplatesInProgress}
|
|
603
605
|
moduleType={moduleType}
|
|
606
|
+
showLiquidErrorInFooter={showLiquidErrorInFooter}
|
|
604
607
|
/>
|
|
605
608
|
)}
|
|
606
609
|
{(isEditEmailWithId || isEmailEditWithContent) && (
|
|
@@ -628,6 +631,7 @@ export function SlideBoxContent(props) {
|
|
|
628
631
|
onPreviewContentClicked={onPreviewContentClicked}
|
|
629
632
|
onTestContentClicked={onTestContentClicked}
|
|
630
633
|
moduleType={moduleType}
|
|
634
|
+
showLiquidErrorInFooter={showLiquidErrorInFooter}
|
|
631
635
|
/>
|
|
632
636
|
)}
|
|
633
637
|
{isEditMPush &&
|
|
@@ -652,6 +656,7 @@ export function SlideBoxContent(props) {
|
|
|
652
656
|
onTestContentClicked={onTestContentClicked}
|
|
653
657
|
type={type}
|
|
654
658
|
hideTestAndPreviewBtn={hideTestAndPreviewBtn}
|
|
659
|
+
creativesMode={creativesMode}
|
|
655
660
|
/>
|
|
656
661
|
}
|
|
657
662
|
{isCreateMPush &&
|
|
@@ -917,5 +922,7 @@ SlideBoxContent.propTypes = {
|
|
|
917
922
|
smsRegister: PropTypes.any,
|
|
918
923
|
getCmsTemplatesInProgress: PropTypes.bool,
|
|
919
924
|
moduleType: PropTypes.string,
|
|
925
|
+
showLiquidErrorInFooter: PropTypes.bool,
|
|
926
|
+
creativesMode: PropTypes.string,
|
|
920
927
|
};
|
|
921
928
|
export default SlideBoxContent;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { FormattedMessage } from 'react-intl';
|
|
3
|
-
import
|
|
3
|
+
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
4
|
+
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
5
|
+
import CapError from '@capillarytech/cap-ui-library/CapError';
|
|
4
6
|
import PropTypes from 'prop-types';
|
|
5
7
|
import messages from './messages';
|
|
8
|
+
import ErrorInfoNote from '../../v2Components/ErrorInfoNote';
|
|
9
|
+
import { PREVIEW } from './constants';
|
|
10
|
+
|
|
6
11
|
function getFullModeSaveBtn(slidBoxContent) {
|
|
7
12
|
return slidBoxContent === "editTemplate" ?
|
|
8
13
|
<FormattedMessage {...messages.creativesTemplatesUpdate}/>
|
|
@@ -10,36 +15,53 @@ function getFullModeSaveBtn(slidBoxContent) {
|
|
|
10
15
|
<FormattedMessage {...messages.creativesTemplatesSaveFullMode}/>;
|
|
11
16
|
}
|
|
12
17
|
function SlideBoxFooter(props) {
|
|
13
|
-
const {
|
|
18
|
+
const {
|
|
19
|
+
slidBoxContent,
|
|
20
|
+
onSave,
|
|
21
|
+
onEditTemplate,
|
|
22
|
+
onCreateNextStep,
|
|
23
|
+
isFullMode,
|
|
24
|
+
fetchingCmsData,
|
|
25
|
+
isTemplateNameEmpty,
|
|
26
|
+
errorMessages,
|
|
27
|
+
isLiquidValidationError,
|
|
28
|
+
} = props;
|
|
14
29
|
return (
|
|
15
|
-
<div>
|
|
30
|
+
<div className='template-footer-width'>
|
|
31
|
+
{isLiquidValidationError && (<ErrorInfoNote errorMessages={errorMessages} />)}
|
|
16
32
|
<div>
|
|
17
33
|
{props.shouldShowDoneFooter() && (
|
|
18
34
|
<div>
|
|
19
|
-
{
|
|
35
|
+
{isFullMode && isTemplateNameEmpty && (
|
|
20
36
|
<CapError type="error">
|
|
21
37
|
<FormattedMessage {...messages.templateNameEmpty} />
|
|
22
38
|
</CapError>
|
|
23
|
-
}
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
)}
|
|
40
|
+
<CapRow>
|
|
41
|
+
<CapButton
|
|
42
|
+
onClick={onSave}
|
|
43
|
+
disabled={isTemplateNameEmpty || fetchingCmsData || false}
|
|
44
|
+
>
|
|
45
|
+
{isFullMode ? (
|
|
46
|
+
getFullModeSaveBtn(slidBoxContent)
|
|
47
|
+
) : (
|
|
48
|
+
<FormattedMessage {...messages.creativesTemplatesSave} />
|
|
49
|
+
)}
|
|
50
|
+
</CapButton>
|
|
51
|
+
</CapRow>
|
|
31
52
|
{/* {isFullMode && <CapButton type="secondary" onClick={onDiscard}><FormattedMessage {...messages.creativesTemplatesDiscard}/></CapButton>} */}
|
|
32
|
-
</div>
|
|
33
|
-
|
|
53
|
+
</div>
|
|
54
|
+
)}
|
|
55
|
+
{props.shouldShowContinueFooter() && (
|
|
34
56
|
<CapButton onClick={onCreateNextStep}>
|
|
35
57
|
<FormattedMessage {...messages.continue} />
|
|
36
58
|
</CapButton>
|
|
37
|
-
|
|
38
|
-
{slidBoxContent ===
|
|
59
|
+
)}
|
|
60
|
+
{slidBoxContent === PREVIEW && (
|
|
39
61
|
<CapButton onClick={onEditTemplate} type="secondary">
|
|
40
62
|
<FormattedMessage {...messages.creativesTemplatesEdit} />
|
|
41
63
|
</CapButton>
|
|
42
|
-
|
|
64
|
+
)}
|
|
43
65
|
</div>
|
|
44
66
|
</div>
|
|
45
67
|
);
|
|
@@ -53,5 +75,6 @@ SlideBoxFooter.propTypes = {
|
|
|
53
75
|
shouldShowDoneFooter: PropTypes.func,
|
|
54
76
|
isFullMode: PropTypes.bool,
|
|
55
77
|
isTemplateNameEmpty: PropTypes.bool,
|
|
78
|
+
isLiquidValidationError: PropTypes.bool,
|
|
56
79
|
};
|
|
57
80
|
export default SlideBoxFooter;
|
|
@@ -30,3 +30,4 @@ export const HIDE_CONTAINER_LOADER = "app/CreativesContainer/HIDE_CONTAINER_LOAD
|
|
|
30
30
|
export const WHATSAPP_HELP_DOC_LINK = "https://docs.capillarytech.com/docs/create-whatsapp-template";
|
|
31
31
|
|
|
32
32
|
export const ENABLE_AI_SUGGESTIONS = "ENABLE_AI_SUGGESTIONS";
|
|
33
|
+
export const LIQUID_SUPPORTED_CHANNELS = [EMAIL];
|
|
@@ -47,6 +47,7 @@ import creativesContainerReducer from './reducer';
|
|
|
47
47
|
import { compose } from 'redux';
|
|
48
48
|
import { capSagaForFetchSchemaForEntity } from '../Cap/sagas';
|
|
49
49
|
import { v2TemplateSagaWatchGetDefaultBeeTemplates } from '../Templates/sagas';
|
|
50
|
+
import { CAP_SPACE_28, CAP_SPACE_32, CAP_SPACE_56, CAP_SPACE_64, CAP_SPACE_72, CAP_SPACE_80 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
50
51
|
|
|
51
52
|
const classPrefix = 'add-creatives-section';
|
|
52
53
|
const CREATIVES_CONTAINER = 'creativesContainer';
|
|
@@ -54,7 +55,8 @@ const CREATIVES_CONTAINER = 'creativesContainer';
|
|
|
54
55
|
const SlideBoxWrapper = styled.div`
|
|
55
56
|
.cap-slide-box-v2-container{
|
|
56
57
|
.slidebox-header, .slidebox-content-container, .slidebox-footer{
|
|
57
|
-
|
|
58
|
+
margin-bottom: ${({ slideBoxWrapperMargin }) => `${slideBoxWrapperMargin}`};
|
|
59
|
+
padding: 0 rem;
|
|
58
60
|
&.has-footer{
|
|
59
61
|
overflow-x: hidden;
|
|
60
62
|
}
|
|
@@ -74,6 +76,8 @@ export class Creatives extends React.Component {
|
|
|
74
76
|
currentChannel: this.props.channel || 'sms',
|
|
75
77
|
weChatTemplateType: '',
|
|
76
78
|
weChatMaptemplateStep: 0,
|
|
79
|
+
isLiquidValidationError: false,
|
|
80
|
+
errorMessages: [],
|
|
77
81
|
};
|
|
78
82
|
this.creativesTemplateSteps = {
|
|
79
83
|
1: 'modeSelection',
|
|
@@ -1135,6 +1139,12 @@ export class Creatives extends React.Component {
|
|
|
1135
1139
|
}
|
|
1136
1140
|
}
|
|
1137
1141
|
}
|
|
1142
|
+
|
|
1143
|
+
showLiquidErrorInFooter = (errorMessages) => {
|
|
1144
|
+
const isError = ( errorMessages?.STANDARD_ERROR_MSG?.length > 0 || errorMessages?.LIQUID_ERROR_MSG?.length > 0);
|
|
1145
|
+
this.setState({isLiquidValidationError: isError, errorMessages});
|
|
1146
|
+
};
|
|
1147
|
+
|
|
1138
1148
|
shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
|
|
1139
1149
|
const {slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode, inAppCreateMode, weChatTemplateType} = this.state;
|
|
1140
1150
|
let isShowContinueFooter = false;
|
|
@@ -1175,7 +1185,23 @@ export class Creatives extends React.Component {
|
|
|
1175
1185
|
return true;
|
|
1176
1186
|
}
|
|
1177
1187
|
render() {
|
|
1178
|
-
const {
|
|
1188
|
+
const {
|
|
1189
|
+
slidBoxContent,
|
|
1190
|
+
isGetFormData,
|
|
1191
|
+
showSlideBox,
|
|
1192
|
+
templateData,
|
|
1193
|
+
currentChannel,
|
|
1194
|
+
emailCreateMode,
|
|
1195
|
+
templateStep,
|
|
1196
|
+
isLoadingContent,
|
|
1197
|
+
mobilePushCreateMode,
|
|
1198
|
+
isDiscardMessage,
|
|
1199
|
+
weChatTemplateType,
|
|
1200
|
+
weChatMaptemplateStep,
|
|
1201
|
+
isTemplateNameEmpty,
|
|
1202
|
+
isLiquidValidationError,
|
|
1203
|
+
errorMessages,
|
|
1204
|
+
} = this.state;
|
|
1179
1205
|
const {
|
|
1180
1206
|
isFullMode,
|
|
1181
1207
|
creativesMode,
|
|
@@ -1194,10 +1220,21 @@ export class Creatives extends React.Component {
|
|
|
1194
1220
|
smsRegister,
|
|
1195
1221
|
enableNewChannels,
|
|
1196
1222
|
} = this.props;
|
|
1197
|
-
const mapTemplateCreate =
|
|
1223
|
+
const mapTemplateCreate =
|
|
1224
|
+
slidBoxContent === "createTemplate" &&
|
|
1225
|
+
weChatTemplateType === MAP_TEMPLATE &&
|
|
1226
|
+
templateStep !== "modeSelection";
|
|
1227
|
+
const slideBoxWrapperMargin =
|
|
1228
|
+
errorMessages?.STANDARD_ERROR_MSG?.length > 0 && errorMessages?.LIQUID_ERROR_MSG?.length > 0
|
|
1229
|
+
? CAP_SPACE_64
|
|
1230
|
+
: errorMessages?.LIQUID_ERROR_MSG?.length > 0
|
|
1231
|
+
? CAP_SPACE_56
|
|
1232
|
+
: errorMessages?.STANDARD_ERROR_MSG?.length > 0
|
|
1233
|
+
? CAP_SPACE_32
|
|
1234
|
+
: 0;
|
|
1198
1235
|
/* TODO: Instead of passing down same props separately to each component down, write common function to these props and pass it accordingly */
|
|
1199
1236
|
return (
|
|
1200
|
-
<SlideBoxWrapper className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}>
|
|
1237
|
+
<SlideBoxWrapper slideBoxWrapperMargin={slideBoxWrapperMargin} className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}>
|
|
1201
1238
|
<CapSlideBox
|
|
1202
1239
|
header={
|
|
1203
1240
|
this.shouldShowHeader() && <SlideBoxHeader
|
|
@@ -1280,6 +1317,8 @@ export class Creatives extends React.Component {
|
|
|
1280
1317
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
1281
1318
|
getCmsTemplatesInProgress={this.props.Templates?.getCmsTemplatesInProgress}
|
|
1282
1319
|
moduleType={this.props.messageDetails?.type}
|
|
1320
|
+
showLiquidErrorInFooter={this.showLiquidErrorInFooter}
|
|
1321
|
+
creativesMode={creativesMode} // An existing prop that we're using here. Required to ensure correct account details in Edit or Preview in case of Embedded mode.
|
|
1283
1322
|
/>
|
|
1284
1323
|
}
|
|
1285
1324
|
footer={this.shouldShowFooter() &&
|
|
@@ -1298,6 +1337,8 @@ export class Creatives extends React.Component {
|
|
|
1298
1337
|
shouldShowDoneFooter={this.shouldShowDoneFooter}
|
|
1299
1338
|
fetchingCmsData={fetchingCmsData}
|
|
1300
1339
|
isTemplateNameEmpty={isTemplateNameEmpty}
|
|
1340
|
+
isLiquidValidationError ={isLiquidValidationError}
|
|
1341
|
+
errorMessages={errorMessages}
|
|
1301
1342
|
/>
|
|
1302
1343
|
}
|
|
1303
1344
|
handleClose={this.handleCloseSlideBox}
|
|
@@ -69,4 +69,16 @@ $classPrefix: add-creatives-section;
|
|
|
69
69
|
i {
|
|
70
70
|
height: $ICON_SIZE_M;
|
|
71
71
|
}
|
|
72
|
-
}
|
|
72
|
+
}
|
|
73
|
+
.liquid-error {
|
|
74
|
+
display: flex;
|
|
75
|
+
gap: $CAP_SPACE_04;
|
|
76
|
+
color: $CAP_COLOR_03;
|
|
77
|
+
vertical-align: text-top;
|
|
78
|
+
align-items: center;
|
|
79
|
+
margin-left: $CAP_SPACE_24;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.template-footer-width {
|
|
83
|
+
width: 100%;;
|
|
84
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
exports[`Test SlideBoxContent container campaign message, add creative click rcs 1`] = `
|
|
4
4
|
<CreativesContainer__SlideBoxWrapper
|
|
5
5
|
className="add-creatives-section creatives-library-mode "
|
|
6
|
+
slideBoxWrapperMargin={0}
|
|
6
7
|
>
|
|
7
8
|
<CapSlideBox
|
|
8
9
|
closeIconPosition="right"
|
|
@@ -33,6 +34,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
|
|
|
33
34
|
onWechatTemplateChange={[Function]}
|
|
34
35
|
saveMessage={[Function]}
|
|
35
36
|
setIsLoadingContent={[Function]}
|
|
37
|
+
showLiquidErrorInFooter={[Function]}
|
|
36
38
|
showTemplateName={[Function]}
|
|
37
39
|
slidBoxContent="templates"
|
|
38
40
|
templateData={
|
|
@@ -77,6 +79,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
|
|
|
77
79
|
exports[`Test SlideBoxContent container campaign message, add creative click whatsapp 1`] = `
|
|
78
80
|
<CreativesContainer__SlideBoxWrapper
|
|
79
81
|
className="add-creatives-section creatives-library-mode "
|
|
82
|
+
slideBoxWrapperMargin={0}
|
|
80
83
|
>
|
|
81
84
|
<CapSlideBox
|
|
82
85
|
closeIconPosition="right"
|
|
@@ -107,6 +110,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
|
|
|
107
110
|
onWechatTemplateChange={[Function]}
|
|
108
111
|
saveMessage={[Function]}
|
|
109
112
|
setIsLoadingContent={[Function]}
|
|
113
|
+
showLiquidErrorInFooter={[Function]}
|
|
110
114
|
showTemplateName={[Function]}
|
|
111
115
|
slidBoxContent="templates"
|
|
112
116
|
templateData={
|
|
@@ -151,6 +155,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
|
|
|
151
155
|
exports[`Test SlideBoxContent container campaign message, whatsapp edit all data 1`] = `
|
|
152
156
|
<CreativesContainer__SlideBoxWrapper
|
|
153
157
|
className="add-creatives-section creatives-library-mode "
|
|
158
|
+
slideBoxWrapperMargin={0}
|
|
154
159
|
>
|
|
155
160
|
<CapSlideBox
|
|
156
161
|
closeIconPosition="right"
|
|
@@ -181,6 +186,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
|
|
|
181
186
|
onWechatTemplateChange={[Function]}
|
|
182
187
|
saveMessage={[Function]}
|
|
183
188
|
setIsLoadingContent={[Function]}
|
|
189
|
+
showLiquidErrorInFooter={[Function]}
|
|
184
190
|
showTemplateName={[Function]}
|
|
185
191
|
slidBoxContent="editTemplate"
|
|
186
192
|
templateStep="modeSelection"
|
|
@@ -191,6 +197,8 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
|
|
|
191
197
|
footer={
|
|
192
198
|
<SlideBoxFooter
|
|
193
199
|
currentChannel="WHATSAPP"
|
|
200
|
+
errorMessages={Array []}
|
|
201
|
+
isLiquidValidationError={false}
|
|
194
202
|
onCreateNextStep={[Function]}
|
|
195
203
|
onDiscard={[Function]}
|
|
196
204
|
onEditTemplate={[Function]}
|
|
@@ -227,6 +235,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
|
|
|
227
235
|
exports[`Test SlideBoxContent container campaign message, whatsapp edit min data 1`] = `
|
|
228
236
|
<CreativesContainer__SlideBoxWrapper
|
|
229
237
|
className="add-creatives-section creatives-library-mode "
|
|
238
|
+
slideBoxWrapperMargin={0}
|
|
230
239
|
>
|
|
231
240
|
<CapSlideBox
|
|
232
241
|
closeIconPosition="right"
|
|
@@ -257,6 +266,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
|
|
|
257
266
|
onWechatTemplateChange={[Function]}
|
|
258
267
|
saveMessage={[Function]}
|
|
259
268
|
setIsLoadingContent={[Function]}
|
|
269
|
+
showLiquidErrorInFooter={[Function]}
|
|
260
270
|
showTemplateName={[Function]}
|
|
261
271
|
slidBoxContent="editTemplate"
|
|
262
272
|
templateStep="modeSelection"
|
|
@@ -267,6 +277,8 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
|
|
|
267
277
|
footer={
|
|
268
278
|
<SlideBoxFooter
|
|
269
279
|
currentChannel="WHATSAPP"
|
|
280
|
+
errorMessages={Array []}
|
|
281
|
+
isLiquidValidationError={false}
|
|
270
282
|
onCreateNextStep={[Function]}
|
|
271
283
|
onDiscard={[Function]}
|
|
272
284
|
onEditTemplate={[Function]}
|
|
@@ -303,6 +315,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
|
|
|
303
315
|
exports[`Test SlideBoxContent container it should clear the url, on channel change from new whatsapp to another 1`] = `
|
|
304
316
|
<CreativesContainer__SlideBoxWrapper
|
|
305
317
|
className="add-creatives-section creatives-library-mode "
|
|
318
|
+
slideBoxWrapperMargin={0}
|
|
306
319
|
>
|
|
307
320
|
<CapSlideBox
|
|
308
321
|
closeIconPosition="right"
|
|
@@ -333,6 +346,7 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
|
|
|
333
346
|
onWechatTemplateChange={[Function]}
|
|
334
347
|
saveMessage={[Function]}
|
|
335
348
|
setIsLoadingContent={[Function]}
|
|
349
|
+
showLiquidErrorInFooter={[Function]}
|
|
336
350
|
showTemplateName={[Function]}
|
|
337
351
|
slidBoxContent="editTemplate"
|
|
338
352
|
templateStep="modeSelection"
|
|
@@ -343,6 +357,8 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
|
|
|
343
357
|
footer={
|
|
344
358
|
<SlideBoxFooter
|
|
345
359
|
currentChannel="WHATSAPP"
|
|
360
|
+
errorMessages={Array []}
|
|
361
|
+
isLiquidValidationError={false}
|
|
346
362
|
onCreateNextStep={[Function]}
|
|
347
363
|
onDiscard={[Function]}
|
|
348
364
|
onEditTemplate={[Function]}
|
|
@@ -2740,6 +2740,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2740
2740
|
type={CmsSettings.type}
|
|
2741
2741
|
isEmailLoading={isLoading}
|
|
2742
2742
|
moduleType={moduleType}
|
|
2743
|
+
showLiquidErrorInFooter={this.props.showLiquidErrorInFooter}
|
|
2743
2744
|
/> : ''}
|
|
2744
2745
|
</Col>
|
|
2745
2746
|
</Row>
|
|
@@ -2796,6 +2797,7 @@ Email.propTypes = {
|
|
|
2796
2797
|
onPreviewContentClicked: PropTypes.func,
|
|
2797
2798
|
onTestContentClicked: PropTypes.func,
|
|
2798
2799
|
moduleType: PropTypes.string,
|
|
2800
|
+
showLiquidErrorInFooter: PropTypes.func,
|
|
2799
2801
|
};
|
|
2800
2802
|
|
|
2801
2803
|
const mapStateToProps = (state, props) => createStructuredSelector({
|
|
@@ -214,6 +214,7 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
|
|
|
214
214
|
editor,
|
|
215
215
|
currentOrgDetails,
|
|
216
216
|
moduleType,
|
|
217
|
+
showLiquidErrorInFooter,
|
|
217
218
|
} = this.props;
|
|
218
219
|
const {
|
|
219
220
|
templateName,
|
|
@@ -278,6 +279,7 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
|
|
|
278
279
|
defaultData={{ 'template-name': templateName }}
|
|
279
280
|
cap={cap}
|
|
280
281
|
showTemplateName={showTemplateName}
|
|
282
|
+
showLiquidErrorInFooter = {showLiquidErrorInFooter}
|
|
281
283
|
onValidationFail={onValidationFail}
|
|
282
284
|
forwardedTags={forwardedTags}
|
|
283
285
|
selectedOfferDetails={selectedOfferDetails}
|
|
@@ -321,6 +323,7 @@ EmailWrapper.propTypes = {
|
|
|
321
323
|
isUploading: PropTypes.bool,
|
|
322
324
|
setIsLoadingContent: PropTypes.func,
|
|
323
325
|
showTemplateName: PropTypes.func,
|
|
326
|
+
showLiquidErrorInFooter: PropTypes.func,
|
|
324
327
|
onValidationFail: PropTypes.func,
|
|
325
328
|
forwardedTags: PropTypes.object,
|
|
326
329
|
selectedOfferDetails: PropTypes.array,
|
|
@@ -23084,11 +23084,14 @@ new message content.",
|
|
|
23084
23084
|
Object {
|
|
23085
23085
|
"app": Object {},
|
|
23086
23086
|
"cap": Object {
|
|
23087
|
+
"fetchingLiquidTags": false,
|
|
23087
23088
|
"fetchingSchema": true,
|
|
23088
23089
|
"fetchingSchemaError": "",
|
|
23090
|
+
"liquidTags": Array [],
|
|
23089
23091
|
"messages": Array [],
|
|
23090
23092
|
"metaEntities": Object {
|
|
23091
23093
|
"layouts": Array [],
|
|
23094
|
+
"tagLookupMap": Object {},
|
|
23092
23095
|
"tags": Array [],
|
|
23093
23096
|
},
|
|
23094
23097
|
"orgID": "",
|
|
@@ -50,7 +50,7 @@ function* watchUploadAsset() {
|
|
|
50
50
|
export function* editTemplate({ template, callback }) {
|
|
51
51
|
let errorMsg;
|
|
52
52
|
try {
|
|
53
|
-
const result = yield call(Api.createLineTemplate,
|
|
53
|
+
const result = yield call(Api.createLineTemplate, template);
|
|
54
54
|
if (result.status.code >= 400) {
|
|
55
55
|
errorMsg = result.message;
|
|
56
56
|
throw errorMsg;
|
|
@@ -33,3 +33,5 @@ export const GET_WECRM_ACCOUNTS_FAILURE = "app/v2Containers/MobilePush/GET_WECRM
|
|
|
33
33
|
export const GET_MOBILEPUSH_TEMPLATES_LIST_REQUEST = 'app/v2Containers/WeChat/GET_MOBILEPUSH_TEMPLATES_LIST_REQUEST';
|
|
34
34
|
export const GET_MOBILEPUSH_TEMPLATES_LIST_SUCCESS = 'app/v2Containers/WeChat/GET_MOBILEPUSH_TEMPLATES_LIST_SUCCESS';
|
|
35
35
|
export const GET_MOBILEPUSH_TEMPLATES_LIST_FAILURE = 'app/v2Containers/WeChat/GET_MOBILEPUSH_TEMPLATES_LIST_FAILURE';
|
|
36
|
+
|
|
37
|
+
export const MAPP_SDK = 'MAPP_SDK';
|