@capillarytech/creatives-library 7.17.195 → 7.17.196

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 (40) hide show
  1. package/config/app.js +2 -0
  2. package/containers/App/constants.js +1 -0
  3. package/initialState.js +3 -0
  4. package/package.json +1 -1
  5. package/services/api.js +20 -0
  6. package/services/tests/api.test.js +148 -0
  7. package/utils/common.js +7 -0
  8. package/utils/tagValidations.js +99 -1
  9. package/utils/tests/tagValidations.test.js +392 -2
  10. package/v2Components/Ckeditor/index.js +1 -1
  11. package/v2Components/ErrorInfoNote/index.js +89 -0
  12. package/v2Components/ErrorInfoNote/messages.js +29 -0
  13. package/v2Components/ErrorInfoNote/style.scss +72 -0
  14. package/v2Components/FormBuilder/_formBuilder.scss +4 -1
  15. package/v2Components/FormBuilder/index.js +170 -69
  16. package/v2Components/FormBuilder/messages.js +8 -0
  17. package/v2Containers/Cap/actions.js +8 -0
  18. package/v2Containers/Cap/constants.js +4 -0
  19. package/v2Containers/Cap/mockData.js +74 -0
  20. package/v2Containers/Cap/reducer.js +12 -0
  21. package/v2Containers/Cap/sagas.js +28 -1
  22. package/v2Containers/Cap/selectors.js +5 -0
  23. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +1 -0
  24. package/v2Containers/Cap/tests/reducer.test.js +50 -0
  25. package/v2Containers/Cap/tests/saga.test.js +81 -1
  26. package/v2Containers/CreativesContainer/SlideBoxContent.js +4 -3
  27. package/v2Containers/CreativesContainer/SlideBoxFooter.js +40 -17
  28. package/v2Containers/CreativesContainer/constants.js +1 -0
  29. package/v2Containers/CreativesContainer/index.js +45 -6
  30. package/v2Containers/CreativesContainer/index.scss +13 -1
  31. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +16 -0
  32. package/v2Containers/Email/_email.scss +3 -0
  33. package/v2Containers/Email/index.js +2 -0
  34. package/v2Containers/EmailWrapper/index.js +3 -0
  35. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +3 -0
  36. package/v2Containers/MobilePush/Edit/constants.js +0 -5
  37. package/v2Containers/MobilePush/Edit/index.js +15 -73
  38. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +93 -0
  39. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +12 -0
  40. 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,7 +153,7 @@ export function SlideBoxContent(props) {
153
153
  hideTestAndPreviewBtn,
154
154
  getCmsTemplatesInProgress = false,
155
155
  moduleType,
156
- creativesMode,
156
+ showLiquidErrorInFooter,
157
157
  } = props;
158
158
  const type = (messageDetails.type || '').toLowerCase(); // type is context in get tags values : outbound | dvs | referral | loyalty | coupons
159
159
  const query = { type: !isFullMode && 'embedded', module: isFullMode ? 'default' : 'library', isEditFromCampaigns: (templateData || {}).isEditFromCampaigns};
@@ -602,6 +602,7 @@ export function SlideBoxContent(props) {
602
602
  onTestContentClicked={onTestContentClicked}
603
603
  getCmsTemplatesInProgress={getCmsTemplatesInProgress}
604
604
  moduleType={moduleType}
605
+ showLiquidErrorInFooter={showLiquidErrorInFooter}
605
606
  />
606
607
  )}
607
608
  {(isEditEmailWithId || isEmailEditWithContent) && (
@@ -629,6 +630,7 @@ export function SlideBoxContent(props) {
629
630
  onPreviewContentClicked={onPreviewContentClicked}
630
631
  onTestContentClicked={onTestContentClicked}
631
632
  moduleType={moduleType}
633
+ showLiquidErrorInFooter={showLiquidErrorInFooter}
632
634
  />
633
635
  )}
634
636
  {isEditMPush &&
@@ -653,7 +655,6 @@ export function SlideBoxContent(props) {
653
655
  onTestContentClicked={onTestContentClicked}
654
656
  type={type}
655
657
  hideTestAndPreviewBtn={hideTestAndPreviewBtn}
656
- creativesMode={creativesMode}
657
658
  />
658
659
  }
659
660
  {isCreateMPush &&
@@ -919,6 +920,6 @@ SlideBoxContent.propTypes = {
919
920
  smsRegister: PropTypes.any,
920
921
  getCmsTemplatesInProgress: PropTypes.bool,
921
922
  moduleType: PropTypes.string,
922
- creativesMode: PropTypes.string,
923
+ showLiquidErrorInFooter: PropTypes.bool,
923
924
  };
924
925
  export default SlideBoxContent;
@@ -1,8 +1,13 @@
1
1
  import React from 'react';
2
2
  import { FormattedMessage } from 'react-intl';
3
- import { CapButton, CapError } from '@capillarytech/cap-ui-library';
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 { slidBoxContent, onSave, onEditTemplate, onCreateNextStep, isFullMode, fetchingCmsData, isTemplateNameEmpty} = props;
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
- { isFullMode && isTemplateNameEmpty &&
35
+ {isFullMode && isTemplateNameEmpty && (
20
36
  <CapError type="error">
21
37
  <FormattedMessage {...messages.templateNameEmpty} />
22
38
  </CapError>
23
- }
24
- <CapButton onClick={onSave} disabled={isTemplateNameEmpty || fetchingCmsData || false}>
25
- {isFullMode ?
26
- getFullModeSaveBtn(slidBoxContent)
27
- :
28
- <FormattedMessage {...messages.creativesTemplatesSave} />
29
- }
30
- </CapButton>
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
- {props.shouldShowContinueFooter() &&
53
+ </div>
54
+ )}
55
+ {props.shouldShowContinueFooter() && (
34
56
  <CapButton onClick={onCreateNextStep}>
35
57
  <FormattedMessage {...messages.continue} />
36
58
  </CapButton>
37
- }
38
- {slidBoxContent === 'preview' && (
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];
@@ -41,6 +41,7 @@ import { WHATSAPP_STATUSES, WHATSAPP_MEDIA_TYPES } from '../Whatsapp/constants';
41
41
 
42
42
  import { updateImagesInHtml } from '../../utils/cdnTransformation';
43
43
  import { IOS } from '../InApp/constants';
44
+ 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';
44
45
 
45
46
  const classPrefix = 'add-creatives-section';
46
47
  const CREATIVES_CONTAINER = 'creativesContainer';
@@ -48,7 +49,8 @@ const CREATIVES_CONTAINER = 'creativesContainer';
48
49
  const SlideBoxWrapper = styled.div`
49
50
  .cap-slide-box-v2-container{
50
51
  .slidebox-header, .slidebox-content-container, .slidebox-footer{
51
- padding: 0 3rem;
52
+ margin-bottom: ${({ slideBoxWrapperMargin }) => `${slideBoxWrapperMargin}`};
53
+ padding: 0 rem;
52
54
  &.has-footer{
53
55
  overflow-x: hidden;
54
56
  }
@@ -68,6 +70,8 @@ export class Creatives extends React.Component {
68
70
  currentChannel: this.props.channel || 'sms',
69
71
  weChatTemplateType: '',
70
72
  weChatMaptemplateStep: 0,
73
+ isLiquidValidationError: false,
74
+ errorMessages: [],
71
75
  };
72
76
  this.creativesTemplateSteps = {
73
77
  1: 'modeSelection',
@@ -1129,6 +1133,12 @@ export class Creatives extends React.Component {
1129
1133
  }
1130
1134
  }
1131
1135
  }
1136
+
1137
+ showLiquidErrorInFooter = (errorMessages) => {
1138
+ const isError = ( errorMessages?.STANDARD_ERROR_MSG?.length > 0 || errorMessages?.LIQUID_ERROR_MSG?.length > 0);
1139
+ this.setState({isLiquidValidationError: isError, errorMessages});
1140
+ };
1141
+
1132
1142
  shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
1133
1143
  const {slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode, inAppCreateMode, weChatTemplateType} = this.state;
1134
1144
  let isShowContinueFooter = false;
@@ -1169,7 +1179,23 @@ export class Creatives extends React.Component {
1169
1179
  return true;
1170
1180
  }
1171
1181
  render() {
1172
- const {slidBoxContent, isGetFormData, showSlideBox, templateData, currentChannel, emailCreateMode, templateStep, isLoadingContent, mobilePushCreateMode, isDiscardMessage, weChatTemplateType, weChatMaptemplateStep, isTemplateNameEmpty} = this.state;
1182
+ const {
1183
+ slidBoxContent,
1184
+ isGetFormData,
1185
+ showSlideBox,
1186
+ templateData,
1187
+ currentChannel,
1188
+ emailCreateMode,
1189
+ templateStep,
1190
+ isLoadingContent,
1191
+ mobilePushCreateMode,
1192
+ isDiscardMessage,
1193
+ weChatTemplateType,
1194
+ weChatMaptemplateStep,
1195
+ isTemplateNameEmpty,
1196
+ isLiquidValidationError,
1197
+ errorMessages,
1198
+ } = this.state;
1173
1199
  const {
1174
1200
  isFullMode,
1175
1201
  creativesMode,
@@ -1188,10 +1214,21 @@ export class Creatives extends React.Component {
1188
1214
  smsRegister,
1189
1215
  enableNewChannels,
1190
1216
  } = this.props;
1191
- const mapTemplateCreate = slidBoxContent === 'createTemplate' && weChatTemplateType === MAP_TEMPLATE && templateStep !== 'modeSelection';
1217
+ const mapTemplateCreate =
1218
+ slidBoxContent === "createTemplate" &&
1219
+ weChatTemplateType === MAP_TEMPLATE &&
1220
+ templateStep !== "modeSelection";
1221
+ const slideBoxWrapperMargin =
1222
+ errorMessages?.STANDARD_ERROR_MSG?.length > 0 && errorMessages?.LIQUID_ERROR_MSG?.length > 0
1223
+ ? CAP_SPACE_64
1224
+ : errorMessages?.LIQUID_ERROR_MSG?.length > 0
1225
+ ? CAP_SPACE_56
1226
+ : errorMessages?.STANDARD_ERROR_MSG?.length > 0
1227
+ ? CAP_SPACE_32
1228
+ : 0;
1192
1229
  /* TODO: Instead of passing down same props separately to each component down, write common function to these props and pass it accordingly */
1193
1230
  return (
1194
- <SlideBoxWrapper className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}>
1231
+ <SlideBoxWrapper slideBoxWrapperMargin={slideBoxWrapperMargin} className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}>
1195
1232
  <CapSlideBox
1196
1233
  header={
1197
1234
  this.shouldShowHeader() && <SlideBoxHeader
@@ -1274,8 +1311,8 @@ export class Creatives extends React.Component {
1274
1311
  hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
1275
1312
  getCmsTemplatesInProgress={this.props.Templates?.getCmsTemplatesInProgress}
1276
1313
  moduleType={this.props.messageDetails?.type}
1277
- creativesMode={creativesMode}
1278
- />
1314
+ showLiquidErrorInFooter={this.showLiquidErrorInFooter}
1315
+ />
1279
1316
  }
1280
1317
  footer={this.shouldShowFooter() &&
1281
1318
  <SlideBoxFooter
@@ -1293,6 +1330,8 @@ export class Creatives extends React.Component {
1293
1330
  shouldShowDoneFooter={this.shouldShowDoneFooter}
1294
1331
  fetchingCmsData={fetchingCmsData}
1295
1332
  isTemplateNameEmpty={isTemplateNameEmpty}
1333
+ isLiquidValidationError ={isLiquidValidationError}
1334
+ errorMessages={errorMessages}
1296
1335
  />
1297
1336
  }
1298
1337
  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]}
@@ -1,4 +1,7 @@
1
+ @import '~@capillarytech/cap-ui-library/styles/_variables.scss';
2
+
1
3
  .email-container {
4
+ padding-bottom: $CAP_SPACE_80;
2
5
  .email-text{
3
6
  height: 100%;
4
7
  overflow: hidden;
@@ -2732,6 +2732,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2732
2732
  type={CmsSettings.type}
2733
2733
  isEmailLoading={isLoading}
2734
2734
  moduleType={moduleType}
2735
+ showLiquidErrorInFooter={this.props.showLiquidErrorInFooter}
2735
2736
  /> : ''}
2736
2737
  </Col>
2737
2738
  </Row>
@@ -2788,6 +2789,7 @@ Email.propTypes = {
2788
2789
  onPreviewContentClicked: PropTypes.func,
2789
2790
  onTestContentClicked: PropTypes.func,
2790
2791
  moduleType: PropTypes.string,
2792
+ showLiquidErrorInFooter: PropTypes.func,
2791
2793
  };
2792
2794
 
2793
2795
  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": "",
@@ -33,8 +33,3 @@ 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';
38
- export const EMBEDDED = 'EMBEDDED';
39
- export const EDIT = 'EDIT';
40
- export const PREVIEW = 'PREVIEW';