@capillarytech/creatives-library 8.0.345-alpha.12 → 8.0.345-alpha.14
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/constants/unified.js +0 -29
- package/package.json +1 -1
- package/services/tests/api.test.js +0 -13
- package/utils/commonUtils.js +1 -19
- package/v2Components/CapActionButton/constants.js +0 -7
- package/v2Components/CapActionButton/index.js +109 -167
- package/v2Components/CapActionButton/index.scss +6 -157
- package/v2Components/CapActionButton/messages.js +3 -19
- package/v2Components/CapActionButton/tests/index.test.js +17 -41
- package/v2Components/CapTagList/index.js +0 -10
- package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +49 -70
- package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +2 -8
- package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +21 -207
- package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +0 -16
- package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +10 -85
- package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +0 -30
- package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +11 -79
- package/v2Components/CommonTestAndPreview/SendTestMessage.js +5 -10
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +15 -160
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +76 -341
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +4 -133
- package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +0 -11
- package/v2Components/CommonTestAndPreview/constants.js +2 -38
- package/v2Components/CommonTestAndPreview/index.js +186 -676
- package/v2Components/CommonTestAndPreview/messages.js +3 -49
- package/v2Components/CommonTestAndPreview/sagas.js +6 -15
- package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +284 -308
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +65 -231
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +5 -118
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +0 -341
- package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +1 -8
- package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +13 -34
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +283 -281
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +1 -199
- package/v2Components/CommonTestAndPreview/tests/index.test.js +4 -132
- package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
- package/v2Components/FormBuilder/index.js +10 -8
- package/v2Components/TemplatePreview/_templatePreview.scss +23 -33
- package/v2Components/TemplatePreview/index.js +28 -143
- package/v2Components/TemplatePreview/tests/index.test.js +0 -142
- package/v2Components/TestAndPreviewSlidebox/index.js +1 -13
- package/v2Components/TestAndPreviewSlidebox/sagas.js +4 -11
- package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +1 -3
- package/v2Containers/CreativesContainer/SlideBoxContent.js +4 -36
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +1 -10
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +4 -29
- package/v2Containers/CreativesContainer/constants.js +0 -9
- package/v2Containers/CreativesContainer/index.js +103 -300
- package/v2Containers/CreativesContainer/index.scss +1 -51
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +34 -78
- package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +16 -79
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -8
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +98 -357
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +15 -20
- package/v2Containers/CreativesContainer/tests/index.test.js +9 -71
- package/v2Containers/Email/reducer.js +11 -3
- package/v2Containers/Email/sagas.js +9 -5
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +4 -0
- package/v2Containers/Email/tests/sagas.test.js +21 -3
- package/v2Containers/Rcs/constants.js +8 -119
- package/v2Containers/Rcs/index.js +812 -2375
- package/v2Containers/Rcs/index.scss +6 -276
- package/v2Containers/Rcs/messages.js +3 -38
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +70345 -98302
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +5 -0
- package/v2Containers/Rcs/tests/index.test.js +121 -152
- package/v2Containers/Rcs/tests/mockData.js +0 -38
- package/v2Containers/Rcs/tests/utils.test.js +30 -646
- package/v2Containers/Rcs/utils.js +11 -478
- package/v2Containers/Sms/Create/index.js +40 -100
- package/v2Containers/SmsTrai/Create/index.js +4 -9
- package/v2Containers/SmsTrai/Edit/constants.js +0 -2
- package/v2Containers/SmsTrai/Edit/index.js +130 -636
- package/v2Containers/SmsTrai/Edit/messages.js +4 -14
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +2296 -4249
- package/v2Containers/SmsWrapper/index.js +8 -37
- package/v2Containers/TagList/index.js +0 -6
- package/v2Containers/Templates/_templates.scss +2 -163
- package/v2Containers/Templates/actions.js +0 -11
- package/v2Containers/Templates/constants.js +0 -2
- package/v2Containers/Templates/index.js +54 -119
- package/v2Containers/Templates/sagas.js +12 -57
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1079 -1043
- package/v2Containers/Templates/tests/sagas.test.js +123 -193
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -72
- package/v2Containers/TemplatesV2/index.js +23 -86
- package/v2Containers/Whatsapp/index.js +20 -3
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -578
- package/utils/rcsPayloadUtils.js +0 -92
- package/utils/templateVarUtils.js +0 -201
- package/utils/tests/templateVarUtils.test.js +0 -204
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js.rej +0 -18
- package/v2Components/CommonTestAndPreview/previewApiUtils.js +0 -59
- package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +0 -67
- package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +0 -87
- package/v2Components/SmsFallback/constants.js +0 -73
- package/v2Components/SmsFallback/index.js +0 -955
- package/v2Components/SmsFallback/index.scss +0 -265
- package/v2Components/SmsFallback/messages.js +0 -78
- package/v2Components/SmsFallback/smsFallbackUtils.js +0 -118
- package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +0 -50
- package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +0 -147
- package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +0 -304
- package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +0 -197
- package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +0 -277
- package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +0 -422
- package/v2Components/SmsFallback/useLocalTemplateList.js +0 -92
- package/v2Components/TemplatePreview/constants.js +0 -2
- package/v2Components/VarSegmentMessageEditor/constants.js +0 -2
- package/v2Components/VarSegmentMessageEditor/index.js +0 -125
- package/v2Components/VarSegmentMessageEditor/index.scss +0 -46
- package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +0 -43
- package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +0 -67
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +0 -90
- package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +0 -258
- package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +0 -125
- package/v2Containers/Rcs/index.js.rej +0 -1336
- package/v2Containers/Rcs/index.scss.rej +0 -74
- package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +0 -225
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap.rej +0 -128
- package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -318
- package/v2Containers/Sms/smsFormDataHelpers.js +0 -67
- package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +0 -253
- package/v2Containers/SmsTrai/Edit/index.scss +0 -121
- package/v2Containers/Templates/TemplatesActionBar.js +0 -101
- package/v2Containers/Templates/tests/TemplatesActionBar.test.js +0 -120
- package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +0 -180
- package/v2Containers/Templates/utils/smsTemplatesListApi.js +0 -79
- package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +0 -131
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
+
import {
|
|
4
|
+
CAP_SPACE_16, CAP_SPACE_32, CAP_SPACE_56, CAP_SPACE_64,
|
|
5
|
+
} from '@capillarytech/cap-ui-library/styled/variables';
|
|
6
|
+
|
|
3
7
|
import CapSlideBox from '@capillarytech/cap-ui-library/CapSlideBox';
|
|
4
8
|
import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
|
|
5
9
|
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
@@ -9,11 +13,12 @@ import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
|
|
|
9
13
|
import { injectIntl, FormattedMessage } from 'react-intl';
|
|
10
14
|
import classnames from 'classnames';
|
|
11
15
|
import {
|
|
12
|
-
isEmpty, get, forEach, cloneDeep, debounce,
|
|
16
|
+
isEmpty, get, forEach, cloneDeep, debounce,
|
|
13
17
|
} from 'lodash';
|
|
14
18
|
import { connect } from 'react-redux';
|
|
15
19
|
import { createStructuredSelector } from 'reselect';
|
|
16
20
|
import { bindActionCreators, compose } from 'redux';
|
|
21
|
+
import styled from 'styled-components';
|
|
17
22
|
import { GA } from '@capillarytech/cap-ui-utils';
|
|
18
23
|
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
|
|
19
24
|
|
|
@@ -27,7 +32,6 @@ import SlideBoxContent from './SlideBoxContent';
|
|
|
27
32
|
import * as constants from './constants';
|
|
28
33
|
import * as commonUtil from '../../utils/common';
|
|
29
34
|
import { gtmPush } from '../../utils/gtmTrackers';
|
|
30
|
-
import { normalizeRcsMessageContentForApi } from '../../utils/rcsPayloadUtils';
|
|
31
35
|
import './index.scss';
|
|
32
36
|
import * as templateActions from '../Templates/actions';
|
|
33
37
|
import * as globalActions from '../Cap/actions';
|
|
@@ -43,9 +47,6 @@ import {
|
|
|
43
47
|
import {EXTERNAL_URL, SITE_URL, WEBPUSH_MEDIA_TYPES} from '../WebPush/constants';
|
|
44
48
|
import { IMAGE, VIDEO } from '../Facebook/Advertisement/constant';
|
|
45
49
|
import { RCS_STATUSES } from '../Rcs/constants';
|
|
46
|
-
import { mapRcsCardContentForConsumerWithResolvedTags } from '../Rcs/utils';
|
|
47
|
-
import { pickRcsCardVarMappedEntries } from '../Rcs/rcsLibraryHydrationUtils';
|
|
48
|
-
import { RCS_SMS_FALLBACK_VAR_MAPPED_PROP } from '../../v2Components/CommonTestAndPreview/constants';
|
|
49
50
|
import { CREATIVE } from '../Facebook/constants';
|
|
50
51
|
import { LOYALTY } from '../App/constants';
|
|
51
52
|
import {
|
|
@@ -60,11 +61,6 @@ import { capSagaForFetchSchemaForEntity, capSagaLiquidEntity } from '../Cap/saga
|
|
|
60
61
|
import { v2TemplateSagaWatchGetDefaultBeeTemplates } from '../Templates/sagas';
|
|
61
62
|
import { DYNAMIC_URL } from '../../v2Components/CapWhatsappCTA/constants';
|
|
62
63
|
import ErrorInfoNote from '../../v2Components/ErrorInfoNote';
|
|
63
|
-
import SlideBoxWrapper from './CreativesSlideBoxWrapper';
|
|
64
|
-
import {
|
|
65
|
-
computeLiquidFooterUpdateFromFormBuilder,
|
|
66
|
-
getSlideBoxWrapperMarginFromLiquidErrors,
|
|
67
|
-
} from './embeddedSlideboxUtils';
|
|
68
64
|
|
|
69
65
|
import {
|
|
70
66
|
transformChannelPayload,
|
|
@@ -73,24 +69,51 @@ import {
|
|
|
73
69
|
import { MANUAL_CAROUSEL } from '../MobilePushNew/constants';
|
|
74
70
|
import { BIG_HTML } from '../InApp/constants';
|
|
75
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Returns true if value is "deep empty": no errors present.
|
|
74
|
+
* - null/undefined: empty
|
|
75
|
+
* - string: empty if length === 0
|
|
76
|
+
* - array: empty if length === 0
|
|
77
|
+
* - plain object (e.g. { android: [], ios: [], generic: [] }): empty only if every value is deep-empty
|
|
78
|
+
*/
|
|
79
|
+
function isDeepEmpty(value) {
|
|
80
|
+
if (value == null) return true;
|
|
81
|
+
if (typeof value === 'string') return value.length === 0;
|
|
82
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
83
|
+
if (typeof value === 'object') {
|
|
84
|
+
return Object.values(value).every(isDeepEmpty);
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
76
89
|
const classPrefix = 'add-creatives-section';
|
|
77
90
|
const CREATIVES_CONTAINER = 'creativesContainer';
|
|
78
91
|
|
|
92
|
+
const SlideBoxWrapper = styled.div`
|
|
93
|
+
.cap-slide-box-v2-container{
|
|
94
|
+
.slidebox-header, .slidebox-content-container{
|
|
95
|
+
margin-bottom: ${({ slideBoxWrapperMargin }) => `${slideBoxWrapperMargin}`};
|
|
96
|
+
padding: 0 rem;
|
|
97
|
+
&.has-footer{
|
|
98
|
+
overflow-x: hidden;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
.slidebox-footer{
|
|
102
|
+
/* Only apply margin-bottom to footer when ErrorInfoNote is shown in footer (BEE editor) */
|
|
103
|
+
/* For HTML Editor, errors are shown in ValidationErrorDisplay (inside content area), so no footer margin needed */
|
|
104
|
+
margin-bottom: ${({ shouldApplyFooterMargin }) => (shouldApplyFooterMargin ? `${CAP_SPACE_16}` : '0')};
|
|
105
|
+
padding: 0 rem;
|
|
106
|
+
&.has-footer{
|
|
107
|
+
overflow-x: hidden;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
79
112
|
export class Creatives extends React.Component {
|
|
80
113
|
constructor(props) {
|
|
81
114
|
super(props);
|
|
82
115
|
|
|
83
|
-
const
|
|
84
|
-
props,
|
|
85
|
-
'localTemplatesConfig.useLocalTemplates',
|
|
86
|
-
get(props, 'useLocalTemplates', false),
|
|
87
|
-
);
|
|
88
|
-
const initialSlidBoxContent = this.getSlideBoxContent({
|
|
89
|
-
mode: props.creativesMode,
|
|
90
|
-
templateData: props.templateData,
|
|
91
|
-
isFullMode: props.isFullMode,
|
|
92
|
-
useLocalTemplates,
|
|
93
|
-
});
|
|
116
|
+
const initialSlidBoxContent = this.getSlideBoxContent({ mode: props.creativesMode, templateData: props.templateData, isFullMode: props.isFullMode });
|
|
94
117
|
|
|
95
118
|
this.state = {
|
|
96
119
|
isLoadingContent: true,
|
|
@@ -137,13 +160,7 @@ export class Creatives extends React.Component {
|
|
|
137
160
|
}
|
|
138
161
|
|
|
139
162
|
componentWillUnmount() {
|
|
140
|
-
|
|
141
|
-
const useLocalTemplates = get(
|
|
142
|
-
this.props,
|
|
143
|
-
'localTemplatesConfig.useLocalTemplates',
|
|
144
|
-
get(this.props, 'useLocalTemplates', false),
|
|
145
|
-
);
|
|
146
|
-
if (isEmbedded && !useLocalTemplates) {
|
|
163
|
+
if (get(this.props, 'location.query.type', '') === "embedded") {
|
|
147
164
|
this.props.templateActions.resetTemplateStoreData();
|
|
148
165
|
}
|
|
149
166
|
this.props.globalActions.clearMetaEntities();
|
|
@@ -745,56 +762,25 @@ export class Creatives extends React.Component {
|
|
|
745
762
|
smsFallBackContent = {},
|
|
746
763
|
creativeName = "",
|
|
747
764
|
channel = constants.RCS,
|
|
748
|
-
|
|
765
|
+
accountId = "",
|
|
749
766
|
} = templateData || {};
|
|
750
|
-
const
|
|
751
|
-
const firstCardIn = (rcsContent.cardContent && rcsContent.cardContent[0]) || {};
|
|
752
|
-
const {
|
|
753
|
-
cardDisplayTitle: _omitDispTitleIn,
|
|
754
|
-
cardDisplayDescription: _omitDispDescIn,
|
|
755
|
-
...cardContent
|
|
756
|
-
} = firstCardIn;
|
|
767
|
+
const cardContent = (rcsContent.cardContent && rcsContent.cardContent[0]) || {};
|
|
757
768
|
const Status = RCS_STATUSES.approved || '';
|
|
758
|
-
const mergedCardVarMapped = (() => {
|
|
759
|
-
const nestedCardVarMapped = cardContent?.cardVarMapped;
|
|
760
|
-
const rootMirrorCardVarMapped = rcsCardVarMapped;
|
|
761
|
-
const nestedRecord =
|
|
762
|
-
nestedCardVarMapped != null && typeof nestedCardVarMapped === 'object'
|
|
763
|
-
? nestedCardVarMapped
|
|
764
|
-
: {};
|
|
765
|
-
const rootRecord =
|
|
766
|
-
rootMirrorCardVarMapped != null && typeof rootMirrorCardVarMapped === 'object'
|
|
767
|
-
? rootMirrorCardVarMapped
|
|
768
|
-
: {};
|
|
769
|
-
const mergedFromRootAndNested = {
|
|
770
|
-
...pickRcsCardVarMappedEntries(rootRecord),
|
|
771
|
-
...pickRcsCardVarMappedEntries(nestedRecord),
|
|
772
|
-
};
|
|
773
|
-
return Object.keys(mergedFromRootAndNested).length > 0
|
|
774
|
-
? mergedFromRootAndNested
|
|
775
|
-
: null;
|
|
776
|
-
})();
|
|
777
|
-
// Campaigns (embedded): do not duplicate `cardVarMapped` as root `rcsCardVarMapped` on send —
|
|
778
|
-
// slot map stays on `versions…cardContent[0].cardVarMapped` only. Library full mode keeps root mirror.
|
|
779
|
-
// Use `=== true` so omitted/undefined `isFullMode` does not behave like library (avoids duplicate on approval payload).
|
|
780
|
-
const includeRootRcsCardVarMapped =
|
|
781
|
-
mergedCardVarMapped && isFullModeForRcsPayload === true;
|
|
782
769
|
|
|
783
770
|
creativesTemplateData = {
|
|
784
771
|
type: channel,
|
|
785
772
|
edit: true,
|
|
786
773
|
name: creativeName,
|
|
787
|
-
...(includeRootRcsCardVarMapped ? { rcsCardVarMapped: mergedCardVarMapped } : {}),
|
|
788
774
|
versions: {
|
|
789
775
|
base: {
|
|
790
776
|
content: {
|
|
791
777
|
RCS: {
|
|
792
778
|
rcsContent: {
|
|
793
779
|
...rcsContent,
|
|
780
|
+
...(accountId && !isFullMode && { accountId }),
|
|
794
781
|
cardContent: [
|
|
795
782
|
{
|
|
796
783
|
...cardContent,
|
|
797
|
-
...(mergedCardVarMapped ? { cardVarMapped: mergedCardVarMapped } : {}),
|
|
798
784
|
Status,
|
|
799
785
|
},
|
|
800
786
|
],
|
|
@@ -945,10 +931,7 @@ export class Creatives extends React.Component {
|
|
|
945
931
|
return newExpandableDetails;
|
|
946
932
|
}
|
|
947
933
|
|
|
948
|
-
getCreativesData = async (
|
|
949
|
-
const channel = String(
|
|
950
|
-
channelParam || template?.type || get(template, 'value.type') || '',
|
|
951
|
-
).toUpperCase();
|
|
934
|
+
getCreativesData = async (channel, template, templateRecords) => { //from creatives to consumers
|
|
952
935
|
let templateData = { channel };
|
|
953
936
|
switch (channel) {
|
|
954
937
|
case constants.SMS:
|
|
@@ -1242,7 +1225,7 @@ export class Creatives extends React.Component {
|
|
|
1242
1225
|
};
|
|
1243
1226
|
}
|
|
1244
1227
|
break;
|
|
1245
|
-
case constants.FACEBOOK:
|
|
1228
|
+
case constants.FACEBOOK:
|
|
1246
1229
|
if (template.value) {
|
|
1247
1230
|
const FacebookAd = template?.value?.versions?.base?.content?.FacebookAd;
|
|
1248
1231
|
const { type } = FacebookAd[0];
|
|
@@ -1286,110 +1269,34 @@ export class Creatives extends React.Component {
|
|
|
1286
1269
|
selectedMarketingObjective: template.value.selectedMarketingObjective,
|
|
1287
1270
|
};
|
|
1288
1271
|
}
|
|
1289
|
-
}
|
|
1290
1272
|
break;
|
|
1291
|
-
case constants.RCS:
|
|
1273
|
+
case constants.RCS:
|
|
1292
1274
|
if (template.value) {
|
|
1293
|
-
const {
|
|
1294
|
-
|
|
1295
|
-
const
|
|
1296
|
-
const fromRecords = {
|
|
1297
|
-
...(templateRecords?.smsFallBackContent || {}),
|
|
1298
|
-
...(get(templateRecords, 'versions.base.content.RCS.smsFallBackContent') || {}),
|
|
1299
|
-
};
|
|
1300
|
-
const hasMeaningfulRcsSmsFallback = (smsFallbackPayload) => {
|
|
1301
|
-
if (
|
|
1302
|
-
!smsFallbackPayload
|
|
1303
|
-
|| typeof smsFallbackPayload !== 'object'
|
|
1304
|
-
|| Object.keys(smsFallbackPayload).length === 0
|
|
1305
|
-
) {
|
|
1306
|
-
return false;
|
|
1307
|
-
}
|
|
1308
|
-
const fallbackBodyText = String(
|
|
1309
|
-
smsFallbackPayload.smsContent
|
|
1310
|
-
?? smsFallbackPayload.smsTemplateContent
|
|
1311
|
-
?? smsFallbackPayload.message
|
|
1312
|
-
?? smsFallbackPayload.content
|
|
1313
|
-
?? '',
|
|
1314
|
-
).trim();
|
|
1315
|
-
const fallbackTemplateName = String(
|
|
1316
|
-
smsFallbackPayload.smsTemplateName ?? smsFallbackPayload.templateName ?? '',
|
|
1317
|
-
).trim();
|
|
1318
|
-
const rcsSmsFallbackVarMapped =
|
|
1319
|
-
smsFallbackPayload?.[RCS_SMS_FALLBACK_VAR_MAPPED_PROP];
|
|
1320
|
-
const hasVarMappedEntries =
|
|
1321
|
-
rcsSmsFallbackVarMapped != null
|
|
1322
|
-
&& typeof rcsSmsFallbackVarMapped === 'object'
|
|
1323
|
-
&& Object.keys(rcsSmsFallbackVarMapped).length > 0;
|
|
1324
|
-
return (
|
|
1325
|
-
fallbackBodyText !== ''
|
|
1326
|
-
|| fallbackTemplateName !== ''
|
|
1327
|
-
|| hasVarMappedEntries
|
|
1328
|
-
);
|
|
1329
|
-
};
|
|
1330
|
-
// If submit has only empty strings, do not let it wipe fallback mirrored on templateRecords (library round-trip).
|
|
1331
|
-
const smsFallBackContent = hasMeaningfulRcsSmsFallback(fromSubmit)
|
|
1332
|
-
? { ...fromRecords, ...fromSubmit }
|
|
1333
|
-
: { ...fromSubmit, ...fromRecords };
|
|
1275
|
+
const { name = "", versions = {} } = {
|
|
1276
|
+
} = template.value || {};
|
|
1277
|
+
const smsFallBackContent = get(versions, 'base.content.RCS.smsFallBackContent', {});
|
|
1334
1278
|
const {
|
|
1335
|
-
cardContent
|
|
1279
|
+
cardContent = [],
|
|
1336
1280
|
contentType = "",
|
|
1337
1281
|
cardType = "",
|
|
1338
1282
|
cardSettings = {},
|
|
1283
|
+
accountId = "",
|
|
1339
1284
|
} = get(versions, 'base.content.RCS.rcsContent', {});
|
|
1340
|
-
const rootRcsCardVarMappedFromSubmit = get(template, 'value.rcsCardVarMapped');
|
|
1341
|
-
const firstCardFromSubmit = Array.isArray(cardContentFromSubmit)
|
|
1342
|
-
? cardContentFromSubmit[0]
|
|
1343
|
-
: null;
|
|
1344
|
-
const cardContent = mapRcsCardContentForConsumerWithResolvedTags(
|
|
1345
|
-
cardContentFromSubmit,
|
|
1346
|
-
rootRcsCardVarMappedFromSubmit,
|
|
1347
|
-
isFullModeForRcsConsumerPayload,
|
|
1348
|
-
);
|
|
1349
1285
|
const rcsContent = {
|
|
1350
1286
|
contentType,
|
|
1351
1287
|
cardType,
|
|
1352
1288
|
cardSettings,
|
|
1353
1289
|
cardContent,
|
|
1354
1290
|
};
|
|
1355
|
-
const cardVarMappedFromFirstRcsCard =
|
|
1356
|
-
firstCardFromSubmit?.cardVarMapped != null
|
|
1357
|
-
&& typeof firstCardFromSubmit.cardVarMapped === 'object'
|
|
1358
|
-
? pickRcsCardVarMappedEntries(firstCardFromSubmit.cardVarMapped)
|
|
1359
|
-
: null;
|
|
1360
|
-
const includeRootRcsCardVarMappedOnConsumerPayload =
|
|
1361
|
-
cardVarMappedFromFirstRcsCard
|
|
1362
|
-
&& Object.keys(cardVarMappedFromFirstRcsCard).length > 0
|
|
1363
|
-
&& isFullModeForRcsConsumerPayload === true;
|
|
1364
1291
|
templateData = {
|
|
1365
1292
|
channel,
|
|
1366
1293
|
creativeName: name,
|
|
1367
1294
|
rcsContent,
|
|
1368
|
-
|
|
1369
|
-
? { rcsCardVarMapped: cardVarMappedFromFirstRcsCard }
|
|
1370
|
-
: {}),
|
|
1295
|
+
accountId,
|
|
1371
1296
|
};
|
|
1372
|
-
// Library / campaign consumers round-trip templateData via getTemplateData; include SMS fallback
|
|
1373
|
-
// so reopening the editor restores fallback text and tag mappings.
|
|
1374
|
-
// cap-campaigns-v2 API expects `smsFallBackContent.message` (see normalizeRcsMessageContentForApi).
|
|
1375
|
-
if (hasMeaningfulRcsSmsFallback(smsFallBackContent)) {
|
|
1376
|
-
const smsText =
|
|
1377
|
-
smsFallBackContent.message
|
|
1378
|
-
?? smsFallBackContent.smsContent
|
|
1379
|
-
?? smsFallBackContent.smsTemplateContent
|
|
1380
|
-
?? '';
|
|
1381
|
-
templateData.smsFallBackContent = {
|
|
1382
|
-
...smsFallBackContent,
|
|
1383
|
-
...(String(smsText).trim() !== ''
|
|
1384
|
-
? { message: String(smsText).trim() }
|
|
1385
|
-
: {}),
|
|
1386
|
-
};
|
|
1387
|
-
}
|
|
1388
|
-
normalizeRcsMessageContentForApi(templateData);
|
|
1389
1297
|
}
|
|
1390
|
-
}
|
|
1391
1298
|
break;
|
|
1392
|
-
case constants.ZALO:
|
|
1299
|
+
case constants.ZALO:
|
|
1393
1300
|
if (template.value) {
|
|
1394
1301
|
templateData = {
|
|
1395
1302
|
...template.value,
|
|
@@ -1398,7 +1305,6 @@ export class Creatives extends React.Component {
|
|
|
1398
1305
|
delete templateData.type;
|
|
1399
1306
|
}
|
|
1400
1307
|
}
|
|
1401
|
-
}
|
|
1402
1308
|
break;
|
|
1403
1309
|
case constants.WEBPUSH: {
|
|
1404
1310
|
if (template.value) {
|
|
@@ -1505,10 +1411,7 @@ export class Creatives extends React.Component {
|
|
|
1505
1411
|
return templateData;
|
|
1506
1412
|
};
|
|
1507
1413
|
|
|
1508
|
-
getSlideBoxContent({ mode, templateData, isFullMode
|
|
1509
|
-
if (useLocalTemplates && mode === 'create' && isEmpty(templateData)) {
|
|
1510
|
-
return 'templates';
|
|
1511
|
-
}
|
|
1414
|
+
getSlideBoxContent({ mode, templateData, isFullMode }) {
|
|
1512
1415
|
let creativesMode = isFullMode ? 'createTemplate' : 'templates';// for library mode templates page is initial mode and for full mode createTemplates
|
|
1513
1416
|
if (mode === 'create' && isFullMode) {
|
|
1514
1417
|
creativesMode = 'createTemplate';
|
|
@@ -1596,110 +1499,24 @@ export class Creatives extends React.Component {
|
|
|
1596
1499
|
getFormData = (template) => {
|
|
1597
1500
|
// Always reset isGetFormData so the child does not re-send form data on every re-render
|
|
1598
1501
|
// (e.g. when user fixes validation error by typing, we must not auto-close the slidebox)
|
|
1599
|
-
this.setState(
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|| ''
|
|
1611
|
-
).toUpperCase();
|
|
1612
|
-
// Library mode: persist last submitted creatives shape so reopening still hydrates the editor
|
|
1613
|
-
// (parent may not merge getCreativesData back into templateData).
|
|
1614
|
-
if (this.props.isFullMode === false && template.value) {
|
|
1615
|
-
if (channel === constants.RCS) {
|
|
1616
|
-
const smsFallBackFromPayload = get(
|
|
1617
|
-
template.value,
|
|
1618
|
-
'versions.base.content.RCS.smsFallBackContent',
|
|
1619
|
-
);
|
|
1620
|
-
const rcsCardVarMappedFromPayload = get(
|
|
1621
|
-
template.value,
|
|
1622
|
-
'versions.base.content.RCS.rcsContent.cardContent[0].cardVarMapped',
|
|
1623
|
-
);
|
|
1624
|
-
next.templateData = {
|
|
1625
|
-
...baseTd,
|
|
1626
|
-
type: constants.RCS,
|
|
1627
|
-
name: template?.value?.name,
|
|
1628
|
-
versions: template?.value?.versions,
|
|
1629
|
-
...(smsFallBackFromPayload != null
|
|
1630
|
-
&& typeof smsFallBackFromPayload === 'object'
|
|
1631
|
-
&& Object.keys(smsFallBackFromPayload).length > 0
|
|
1632
|
-
? { smsFallBackContent: smsFallBackFromPayload }
|
|
1633
|
-
: {}),
|
|
1634
|
-
...(rcsCardVarMappedFromPayload != null
|
|
1635
|
-
&& typeof rcsCardVarMappedFromPayload === 'object'
|
|
1636
|
-
? { rcsCardVarMapped: rcsCardVarMappedFromPayload }
|
|
1637
|
-
: {}),
|
|
1638
|
-
};
|
|
1639
|
-
if (template._id) {
|
|
1640
|
-
next.templateData._id = template._id;
|
|
1641
|
-
}
|
|
1642
|
-
} else if (channel === constants.SMS) {
|
|
1643
|
-
const submittedSmsTemplateValue = template?.value;
|
|
1644
|
-
const smsVersions =
|
|
1645
|
-
submittedSmsTemplateValue?.history != null
|
|
1646
|
-
? submittedSmsTemplateValue
|
|
1647
|
-
: {
|
|
1648
|
-
base: submittedSmsTemplateValue?.base,
|
|
1649
|
-
history: submittedSmsTemplateValue?.base
|
|
1650
|
-
? [submittedSmsTemplateValue.base]
|
|
1651
|
-
: [],
|
|
1652
|
-
};
|
|
1653
|
-
next.templateData = {
|
|
1654
|
-
...baseTd,
|
|
1655
|
-
type: constants.SMS,
|
|
1656
|
-
name: baseTd?.name || 'Campaign message SMS content',
|
|
1657
|
-
versions: smsVersions,
|
|
1658
|
-
};
|
|
1659
|
-
if (template?._id) {
|
|
1660
|
-
next.templateData._id = template._id;
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
return next;
|
|
1665
|
-
},
|
|
1666
|
-
() => {
|
|
1667
|
-
if (!template.validity) {
|
|
1668
|
-
return;
|
|
1669
|
-
}
|
|
1670
|
-
const templateData = this.state.templateData ? this.state.templateData : template; //select existing or create new content
|
|
1671
|
-
const channelForConsumer = String(
|
|
1672
|
-
templateData.type
|
|
1673
|
-
|| template.type
|
|
1674
|
-
|| get(template, 'value.type')
|
|
1675
|
-
|| '',
|
|
1676
|
-
).toUpperCase();
|
|
1677
|
-
const creativesData = this.getCreativesData(
|
|
1678
|
-
channelForConsumer,
|
|
1679
|
-
template,
|
|
1680
|
-
this.state.templateData || template,
|
|
1681
|
-
);// convers data to consumer understandable format
|
|
1682
|
-
creativesData.then((data) => {
|
|
1683
|
-
this.logGTMEvent(channelForConsumer, data);
|
|
1684
|
-
this.processCentralCommsMetaId(channelForConsumer, data, {
|
|
1685
|
-
closeSlideBoxAfterSubmit: template.closeSlideBoxAfterSubmit,
|
|
1502
|
+
this.setState({ isGetFormData: false });
|
|
1503
|
+
if (template.validity) {
|
|
1504
|
+
this.setState(
|
|
1505
|
+
{},
|
|
1506
|
+
() => {
|
|
1507
|
+
const templateData = this.state.templateData ? this.state.templateData : template; //select existing or create new content
|
|
1508
|
+
const channel = templateData.type;
|
|
1509
|
+
const creativesData = this.getCreativesData(channel, template, templateData);// convers data to consumer understandable format
|
|
1510
|
+
creativesData.then((data) => {
|
|
1511
|
+
this.logGTMEvent(channel, data);
|
|
1512
|
+
this.processCentralCommsMetaId(channel, data);
|
|
1686
1513
|
});
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
|
-
|
|
1514
|
+
},
|
|
1515
|
+
);
|
|
1516
|
+
}
|
|
1690
1517
|
}
|
|
1691
1518
|
|
|
1692
|
-
processCentralCommsMetaId = (channel, creativesData
|
|
1693
|
-
const { closeSlideBoxAfterSubmit = false } = options;
|
|
1694
|
-
const maybeCloseLibrarySlideBox = () => {
|
|
1695
|
-
if (
|
|
1696
|
-
closeSlideBoxAfterSubmit
|
|
1697
|
-
&& this.props.isFullMode === false
|
|
1698
|
-
&& typeof this.handleCloseSlideBox === 'function'
|
|
1699
|
-
) {
|
|
1700
|
-
this.handleCloseSlideBox();
|
|
1701
|
-
}
|
|
1702
|
-
};
|
|
1519
|
+
processCentralCommsMetaId = (channel, creativesData) => {
|
|
1703
1520
|
// Create the payload for the centralcommnsmetaId API call
|
|
1704
1521
|
const { isLoyaltyModule = false, loyaltyMetaData = {} } = this.props;
|
|
1705
1522
|
const { actionName, setMetaData = () => { } } = loyaltyMetaData;
|
|
@@ -1725,7 +1542,6 @@ export class Creatives extends React.Component {
|
|
|
1725
1542
|
if (result?.status?.code === 200) {
|
|
1726
1543
|
setMetaData(result);
|
|
1727
1544
|
this.props.getCreativesData(creativesData);
|
|
1728
|
-
maybeCloseLibrarySlideBox();
|
|
1729
1545
|
} else {
|
|
1730
1546
|
CapNotification.error({ message: <FormattedMessage {...messages.somethingWentWrong} /> });
|
|
1731
1547
|
}
|
|
@@ -1736,7 +1552,6 @@ export class Creatives extends React.Component {
|
|
|
1736
1552
|
} else {
|
|
1737
1553
|
// If not a loyalty module or different action, should work as usual
|
|
1738
1554
|
this.props.getCreativesData(creativesData);
|
|
1739
|
-
maybeCloseLibrarySlideBox();
|
|
1740
1555
|
}
|
|
1741
1556
|
};
|
|
1742
1557
|
|
|
@@ -1769,9 +1584,7 @@ export class Creatives extends React.Component {
|
|
|
1769
1584
|
}
|
|
1770
1585
|
this.setState((prevState) => ({
|
|
1771
1586
|
...prevState,
|
|
1772
|
-
|
|
1773
|
-
// Undefined isFullMode defaults to full-mode close behavior (clear templateData).
|
|
1774
|
-
...(this.props.isFullMode !== false ? { templateData: undefined } : {}),
|
|
1587
|
+
templateData: undefined,
|
|
1775
1588
|
showSlideBox: false,
|
|
1776
1589
|
liquidErrorMessage: { STANDARD_ERROR_MSG: [], LIQUID_ERROR_MSG: [] },
|
|
1777
1590
|
isLiquidValidationError: false,
|
|
@@ -1982,12 +1795,21 @@ export class Creatives extends React.Component {
|
|
|
1982
1795
|
}
|
|
1983
1796
|
|
|
1984
1797
|
showLiquidErrorInFooter = (errorMessagesFromFormBuilder, currentFormBuilderTab) => {
|
|
1985
|
-
const
|
|
1986
|
-
|
|
1987
|
-
|
|
1798
|
+
const liquidMsgs = get(errorMessagesFromFormBuilder, constants.LIQUID_ERROR_MSG, []);
|
|
1799
|
+
const standardMsgs = get(errorMessagesFromFormBuilder, constants.STANDARD_ERROR_MSG, []);
|
|
1800
|
+
const hasLiquid = !isDeepEmpty(liquidMsgs);
|
|
1801
|
+
const hasStandard = !isDeepEmpty(standardMsgs);
|
|
1802
|
+
const isLiquidValidationError = hasLiquid || hasStandard;
|
|
1803
|
+
// Don't overwrite existing liquid error with empty only for Mobile Push OLD (FormBuilder/clear calls empty there); SMS/others clear on input change
|
|
1804
|
+
const isMobilePush = this.state.currentChannel?.toUpperCase() === constants.MOBILE_PUSH;
|
|
1805
|
+
if (!hasLiquid && !hasStandard && this.state.isLiquidValidationError && isMobilePush) {
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1808
|
+
this.setState({
|
|
1809
|
+
isLiquidValidationError,
|
|
1810
|
+
liquidErrorMessage: errorMessagesFromFormBuilder,
|
|
1811
|
+
activeFormBuilderTab: currentFormBuilderTab === 1 ? constants.ANDROID : (currentFormBuilderTab === 2 ? constants.IOS : null), // Update activeFormBuilderTab, default to 1 if undefined
|
|
1988
1812
|
});
|
|
1989
|
-
if (next == null) return;
|
|
1990
|
-
this.setState(next);
|
|
1991
1813
|
}
|
|
1992
1814
|
|
|
1993
1815
|
// Callback to update HTML Editor validation state (called from EmailWrapper)
|
|
@@ -2110,11 +1932,6 @@ export class Creatives extends React.Component {
|
|
|
2110
1932
|
inAppEditorType,
|
|
2111
1933
|
htmlEditorValidationState,
|
|
2112
1934
|
} = this.state;
|
|
2113
|
-
const useLocalTemplates = get(
|
|
2114
|
-
this.props,
|
|
2115
|
-
'localTemplatesConfig.useLocalTemplates',
|
|
2116
|
-
get(this.props, 'useLocalTemplates', false),
|
|
2117
|
-
);
|
|
2118
1935
|
const {
|
|
2119
1936
|
isFullMode,
|
|
2120
1937
|
creativesMode,
|
|
@@ -2133,6 +1950,7 @@ export class Creatives extends React.Component {
|
|
|
2133
1950
|
smsRegister,
|
|
2134
1951
|
enableNewChannels,
|
|
2135
1952
|
eventContextTags,
|
|
1953
|
+
waitEventContextTags = {},
|
|
2136
1954
|
isLoyaltyModule,
|
|
2137
1955
|
loyaltyMetaData = {},
|
|
2138
1956
|
} = this.props;
|
|
@@ -2166,7 +1984,14 @@ export class Creatives extends React.Component {
|
|
|
2166
1984
|
// IMPORTANT: Never show ErrorInfoNote in footer when in HTML Editor mode, even if liquidErrorMessage exists
|
|
2167
1985
|
const shouldShowErrorInfoNoteInFooter = isHTMLEditorMode ? false : hasBEEEditorErrors;
|
|
2168
1986
|
|
|
2169
|
-
|
|
1987
|
+
// Calculate margin for header/content (always apply if there are errors, regardless of editor type)
|
|
1988
|
+
const slideBoxWrapperMargin = (get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0 && get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0)
|
|
1989
|
+
? CAP_SPACE_64
|
|
1990
|
+
: get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0
|
|
1991
|
+
? CAP_SPACE_56
|
|
1992
|
+
: get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0
|
|
1993
|
+
? CAP_SPACE_32
|
|
1994
|
+
: 0;
|
|
2170
1995
|
/* TODO: Instead of passing down same props separately to each component down, write common function to these props and pass it accordingly */
|
|
2171
1996
|
|
|
2172
1997
|
// Compute anonymous user type and channel restrictions
|
|
@@ -2195,10 +2020,7 @@ export class Creatives extends React.Component {
|
|
|
2195
2020
|
<SlideBoxWrapper
|
|
2196
2021
|
slideBoxWrapperMargin={slideBoxWrapperMargin}
|
|
2197
2022
|
shouldApplyFooterMargin={shouldShowErrorInfoNoteInFooter}
|
|
2198
|
-
className={classnames(
|
|
2199
|
-
`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`,
|
|
2200
|
-
useLocalTemplates && slidBoxContent === 'templates' && 'creatives-slidebox--local-sms-templates',
|
|
2201
|
-
)}
|
|
2023
|
+
className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}
|
|
2202
2024
|
>
|
|
2203
2025
|
<CapSlideBox
|
|
2204
2026
|
header={
|
|
@@ -2223,13 +2045,12 @@ export class Creatives extends React.Component {
|
|
|
2223
2045
|
smsRegister={smsRegister}
|
|
2224
2046
|
handleClose={this.handleCloseSlideBox}
|
|
2225
2047
|
moduleType={this.props.messageDetails?.type}
|
|
2226
|
-
useLocalTemplates={useLocalTemplates}
|
|
2227
2048
|
/>
|
|
2228
2049
|
)}
|
|
2229
2050
|
content={(
|
|
2230
2051
|
<SlideBoxContent
|
|
2231
2052
|
key="creatives-container-slidebox-content"
|
|
2232
|
-
onSelectTemplate={this.
|
|
2053
|
+
onSelectTemplate={this.onSelectTemplate}
|
|
2233
2054
|
onCreateComplete={getCreativesData}
|
|
2234
2055
|
onPreviewTemplate={this.onPreviewTemplate}
|
|
2235
2056
|
slidBoxContent={slidBoxContent}
|
|
@@ -2297,6 +2118,7 @@ export class Creatives extends React.Component {
|
|
|
2297
2118
|
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.
|
|
2298
2119
|
hostName={this.props?.hostName || ''}
|
|
2299
2120
|
eventContextTags={eventContextTags}
|
|
2121
|
+
waitEventContextTags={waitEventContextTags}
|
|
2300
2122
|
isLoyaltyModule={isLoyaltyModule}
|
|
2301
2123
|
loyaltyMetaData={loyaltyMetaData}
|
|
2302
2124
|
showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
|
|
@@ -2305,8 +2127,7 @@ export class Creatives extends React.Component {
|
|
|
2305
2127
|
isTestAndPreviewMode={(() => this.state.isTestAndPreviewMode)()}
|
|
2306
2128
|
onHtmlEditorValidationStateChange={this.updateHtmlEditorValidationState}
|
|
2307
2129
|
onPersonalizationTokensChange={this.handlePersonalizationTokensChange}
|
|
2308
|
-
|
|
2309
|
-
/>
|
|
2130
|
+
/>
|
|
2310
2131
|
)}
|
|
2311
2132
|
footer={this.shouldShowFooter() ? (
|
|
2312
2133
|
<SlideBoxFooter
|
|
@@ -2390,31 +2211,13 @@ Creatives.propTypes = {
|
|
|
2390
2211
|
orgUnitId: PropTypes.number,
|
|
2391
2212
|
hostName: PropTypes.string,
|
|
2392
2213
|
eventContextTags: PropTypes.array,
|
|
2214
|
+
waitEventContextTags: PropTypes.object,
|
|
2393
2215
|
loyaltyTagFetchingDependencies: PropTypes.object,
|
|
2394
2216
|
customerType: PropTypes.string,
|
|
2395
2217
|
intl: PropTypes.shape({
|
|
2396
2218
|
formatMessage: PropTypes.func,
|
|
2397
2219
|
}),
|
|
2398
2220
|
stopValidation: PropTypes.func,
|
|
2399
|
-
// Local template list (e.g. for SMS fallback): when set, TemplatesV2 uses these instead of Redux.
|
|
2400
|
-
// All optional. Pass either localTemplatesConfig (object) or individual props below.
|
|
2401
|
-
localTemplatesConfig: PropTypes.shape({
|
|
2402
|
-
useLocalTemplates: PropTypes.bool,
|
|
2403
|
-
localTemplates: PropTypes.arrayOf(PropTypes.object),
|
|
2404
|
-
localTemplatesLoading: PropTypes.bool,
|
|
2405
|
-
localTemplatesFilterContent: PropTypes.node,
|
|
2406
|
-
localTemplatesSentinelContent: PropTypes.node,
|
|
2407
|
-
localTemplatesScrollContainerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
|
|
2408
|
-
localTemplatesUseSkeleton: PropTypes.bool,
|
|
2409
|
-
}),
|
|
2410
|
-
useLocalTemplates: PropTypes.bool,
|
|
2411
|
-
localTemplates: PropTypes.arrayOf(PropTypes.object),
|
|
2412
|
-
localTemplatesLoading: PropTypes.bool,
|
|
2413
|
-
localTemplatesFilterContent: PropTypes.node,
|
|
2414
|
-
localTemplatesSentinelContent: PropTypes.node,
|
|
2415
|
-
localTemplatesScrollContainerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
|
|
2416
|
-
localTemplatesUseSkeleton: PropTypes.bool,
|
|
2417
|
-
onSelectTemplate: PropTypes.func,
|
|
2418
2221
|
};
|
|
2419
2222
|
const mapStatesToProps = () => createStructuredSelector({
|
|
2420
2223
|
isLoading: isLoadingSelector(),
|