@capillarytech/creatives-library 8.0.353-alpha.6 → 8.0.354

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 (127) hide show
  1. package/constants/unified.js +0 -29
  2. package/index.html +1 -0
  3. package/package.json +1 -1
  4. package/services/tests/api.test.js +20 -35
  5. package/utils/cdnTransformation.js +63 -3
  6. package/utils/commonUtils.js +1 -19
  7. package/utils/tests/cdnTransformation.test.js +111 -0
  8. package/v2Components/CapActionButton/constants.js +0 -7
  9. package/v2Components/CapActionButton/index.js +108 -166
  10. package/v2Components/CapActionButton/index.scss +6 -157
  11. package/v2Components/CapActionButton/messages.js +3 -19
  12. package/v2Components/CapActionButton/tests/index.test.js +17 -41
  13. package/v2Components/CapTagList/index.js +0 -10
  14. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +49 -72
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +2 -8
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +21 -213
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +0 -16
  18. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +10 -85
  19. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +0 -30
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +11 -79
  21. package/v2Components/CommonTestAndPreview/SendTestMessage.js +5 -10
  22. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +15 -157
  23. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +76 -346
  24. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +4 -133
  25. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +0 -11
  26. package/v2Components/CommonTestAndPreview/constants.js +2 -38
  27. package/v2Components/CommonTestAndPreview/index.js +186 -691
  28. package/v2Components/CommonTestAndPreview/messages.js +3 -45
  29. package/v2Components/CommonTestAndPreview/sagas.js +6 -25
  30. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +284 -308
  31. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +65 -231
  32. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +5 -118
  33. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +0 -341
  34. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +1 -8
  35. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +13 -34
  36. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +283 -281
  37. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +1 -199
  38. package/v2Components/CommonTestAndPreview/tests/index.test.js +4 -132
  39. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +26 -36
  40. package/v2Components/FormBuilder/index.js +6 -11
  41. package/v2Components/TemplatePreview/_templatePreview.scss +23 -38
  42. package/v2Components/TemplatePreview/index.js +31 -143
  43. package/v2Components/TemplatePreview/tests/index.test.js +0 -142
  44. package/v2Components/TestAndPreviewSlidebox/index.js +1 -13
  45. package/v2Components/TestAndPreviewSlidebox/sagas.js +4 -11
  46. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +1 -3
  47. package/v2Containers/CreativesContainer/SlideBoxContent.js +4 -36
  48. package/v2Containers/CreativesContainer/SlideBoxFooter.js +1 -10
  49. package/v2Containers/CreativesContainer/SlideBoxHeader.js +4 -29
  50. package/v2Containers/CreativesContainer/constants.js +0 -9
  51. package/v2Containers/CreativesContainer/index.js +103 -322
  52. package/v2Containers/CreativesContainer/index.scss +1 -51
  53. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +34 -78
  54. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +16 -79
  55. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -8
  56. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +98 -357
  57. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +15 -20
  58. package/v2Containers/CreativesContainer/tests/index.test.js +9 -71
  59. package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
  60. package/v2Containers/Rcs/constants.js +10 -119
  61. package/v2Containers/Rcs/index.js +818 -2450
  62. package/v2Containers/Rcs/index.scss +8 -280
  63. package/v2Containers/Rcs/messages.js +3 -34
  64. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +70073 -98018
  65. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +5 -0
  66. package/v2Containers/Rcs/tests/index.test.js +121 -152
  67. package/v2Containers/Rcs/tests/mockData.js +0 -38
  68. package/v2Containers/Rcs/tests/utils.test.js +30 -646
  69. package/v2Containers/Rcs/utils.js +11 -478
  70. package/v2Containers/Sms/Create/index.js +40 -106
  71. package/v2Containers/SmsTrai/Create/index.js +4 -9
  72. package/v2Containers/SmsTrai/Edit/constants.js +0 -2
  73. package/v2Containers/SmsTrai/Edit/index.js +130 -640
  74. package/v2Containers/SmsTrai/Edit/messages.js +4 -14
  75. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +2296 -4249
  76. package/v2Containers/SmsWrapper/index.js +8 -37
  77. package/v2Containers/TagList/index.js +0 -6
  78. package/v2Containers/Templates/_templates.scss +9 -166
  79. package/v2Containers/Templates/actions.js +0 -11
  80. package/v2Containers/Templates/constants.js +0 -2
  81. package/v2Containers/Templates/index.js +52 -120
  82. package/v2Containers/Templates/sagas.js +18 -57
  83. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1017 -1062
  84. package/v2Containers/Templates/tests/sagas.test.js +39 -205
  85. package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -72
  86. package/v2Containers/TemplatesV2/index.js +23 -86
  87. package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
  88. package/v2Containers/Whatsapp/index.js +20 -3
  89. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -578
  90. package/utils/rcsPayloadUtils.js +0 -92
  91. package/utils/templateVarUtils.js +0 -201
  92. package/utils/tests/rcsPayloadUtils.test.js +0 -226
  93. package/utils/tests/templateVarUtils.test.js +0 -204
  94. package/v2Components/CommonTestAndPreview/previewApiUtils.js +0 -59
  95. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +0 -67
  96. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +0 -91
  97. package/v2Components/SmsFallback/constants.js +0 -73
  98. package/v2Components/SmsFallback/index.js +0 -956
  99. package/v2Components/SmsFallback/index.scss +0 -265
  100. package/v2Components/SmsFallback/messages.js +0 -78
  101. package/v2Components/SmsFallback/smsFallbackUtils.js +0 -119
  102. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +0 -50
  103. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +0 -147
  104. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +0 -304
  105. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +0 -223
  106. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +0 -309
  107. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +0 -422
  108. package/v2Components/SmsFallback/useLocalTemplateList.js +0 -92
  109. package/v2Components/TemplatePreview/constants.js +0 -2
  110. package/v2Components/VarSegmentMessageEditor/constants.js +0 -2
  111. package/v2Components/VarSegmentMessageEditor/index.js +0 -125
  112. package/v2Components/VarSegmentMessageEditor/index.scss +0 -46
  113. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +0 -43
  114. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +0 -79
  115. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +0 -90
  116. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +0 -258
  117. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +0 -125
  118. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +0 -225
  119. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -318
  120. package/v2Containers/Sms/smsFormDataHelpers.js +0 -67
  121. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +0 -253
  122. package/v2Containers/SmsTrai/Edit/index.scss +0 -121
  123. package/v2Containers/Templates/TemplatesActionBar.js +0 -101
  124. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +0 -120
  125. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +0 -180
  126. package/v2Containers/Templates/utils/smsTemplatesListApi.js +0 -79
  127. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +0 -131
@@ -1,956 +0,0 @@
1
- import React, { useCallback, useRef, useEffect, useMemo, useReducer } from 'react';
2
- import { connect } from 'react-redux';
3
- import ReactDOM from 'react-dom';
4
- import PropTypes from 'prop-types';
5
- import classnames from 'classnames';
6
- import { injectIntl, FormattedMessage } from 'react-intl';
7
- import get from 'lodash/get';
8
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
9
- import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
10
- import { CapIcons, CapLabel, CapRadio } from '@capillarytech/cap-ui-library';
11
- import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
12
- import CapButton from '@capillarytech/cap-ui-library/CapButton';
13
- import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
14
- import CapDropdown from '@capillarytech/cap-ui-library/CapDropdown';
15
- import CapMenu from '@capillarytech/cap-ui-library/CapMenu';
16
- import CapCustomCard from '@capillarytech/cap-ui-library/CapCustomCard';
17
- import CapSlideBox from '@capillarytech/cap-ui-library/CapSlideBox';
18
- import * as Api from '../../services/api';
19
- import globalMessages from '../../v2Containers/Cap/messages';
20
- import { isTraiDLTEnable } from '../../utils/common';
21
- import TemplatesActionBar from '../../v2Containers/Templates/TemplatesActionBar';
22
- import * as templatesActions from '../../v2Containers/Templates/actions';
23
- import templatesListMessages from '../../v2Containers/Templates/messages';
24
- import SmsWrapper from '../../v2Containers/SmsWrapper';
25
- import SmsTraiEdit from '../../v2Containers/SmsTrai/Edit';
26
-
27
- import SmsFallbackLocalSelector from './SmsFallbackLocalSelector';
28
- import { useLocalTemplateList } from './useLocalTemplateList';
29
- import {
30
- SMS_FALLBACK_VIEW,
31
- CHANNELS_TO_HIDE_FOR_SMS_ONLY,
32
- EMBEDDED_SMS_CREATIVES_LOCATION,
33
- EMBEDDED_SMS_CREATIVES_EDIT_LOCATION,
34
- SMS_FALLBACK_ROUTE,
35
- SMS_TEMPLATE_DETAILS_API_CHANNEL,
36
- SMS_CATEGORY_FILTERS,
37
- } from './constants';
38
- import SlideBoxFooter from '../../v2Containers/CreativesContainer/SlideBoxFooter';
39
- import CreativesSlideBoxWrapper from '../../v2Containers/CreativesContainer/CreativesSlideBoxWrapper';
40
- import {
41
- computeLiquidFooterUpdateFromFormBuilder,
42
- getSlideBoxWrapperMarginFromLiquidErrors,
43
- } from '../../v2Containers/CreativesContainer/embeddedSlideboxUtils';
44
- import { SMS } from '../../v2Containers/CreativesContainer/constants';
45
- import creativesMessages from '../../v2Containers/CreativesContainer/messages';
46
- import messages from './messages';
47
- import {
48
- buildFallbackDataFromTemplate,
49
- buildFallbackDataFromCreativesPayload,
50
- mapFallbackValueToEditTemplateData,
51
- getBaseFromSmsTraiFormData,
52
- getSmsFallbackCardDisplayContent,
53
- resolveContentFromTraiBase,
54
- filterSmsTemplatesByCategory,
55
- } from './smsFallbackUtils';
56
-
57
- import './index.scss';
58
-
59
- // ---------------------------------------------------------------------------
60
- // Reducer — replaces the 10 individual useState declarations
61
- // ---------------------------------------------------------------------------
62
-
63
- const SLIDEBOX_INITIAL_STATE = {
64
- view: null,
65
- fetchDetailsLoading: false,
66
- pendingFallbackData: null,
67
- smsCategoryFilter: SMS_CATEGORY_FILTERS.ALL,
68
- isGetFormData: false,
69
- liquidErrorMessage: { STANDARD_ERROR_MSG: [], LIQUID_ERROR_MSG: [] },
70
- isLiquidValidationError: false,
71
- isLoadingContent: true,
72
- showTestAndPreviewSlidebox: false,
73
- isTestAndPreviewMode: false,
74
- smsCreateRequiredFieldsInvalid: true,
75
- };
76
-
77
- function slideboxReducer(state, action) {
78
- switch (action.type) {
79
- case 'OPEN_SELECTOR':
80
- return { ...state, view: SMS_FALLBACK_VIEW.SELECTING };
81
- case 'OPEN_EDITING':
82
- return { ...state, view: SMS_FALLBACK_VIEW.EDITING };
83
- case 'OPEN_CREATING':
84
- return { ...state, view: SMS_FALLBACK_VIEW.CREATING, fetchDetailsLoading: false, smsCreateRequiredFieldsInvalid: true };
85
- case 'SELECT_TEMPLATE_START':
86
- return { ...state, fetchDetailsLoading: true };
87
- case 'SELECT_TEMPLATE_DONE':
88
- return { ...state, fetchDetailsLoading: false, pendingFallbackData: action.payload, view: SMS_FALLBACK_VIEW.EDITING };
89
- case 'SET_FETCH_LOADING':
90
- return { ...state, fetchDetailsLoading: action.payload };
91
- case 'GO_BACK_TO_LIST':
92
- return {
93
- ...state,
94
- fetchDetailsLoading: false,
95
- pendingFallbackData: null,
96
- smsCategoryFilter: SMS_CATEGORY_FILTERS.ALL,
97
- view: SMS_FALLBACK_VIEW.SELECTING,
98
- };
99
- case 'CLOSE':
100
- return SLIDEBOX_INITIAL_STATE;
101
- case 'SET_IS_GET_FORM_DATA':
102
- return { ...state, isGetFormData: action.payload };
103
- case 'SET_LIQUID_ERROR':
104
- return { ...state, liquidErrorMessage: action.liquidErrorMessage, isLiquidValidationError: action.isLiquidValidationError };
105
- case 'SET_LOADING_CONTENT':
106
- // Bail out when value is unchanged — prevents re-render loop: SmsCreate calls
107
- // setIsLoadingContent(true) in componentWillReceiveProps on any prop change, and a
108
- // new state object (even with the same value) would cause SmsFallbackPortalContent
109
- // to re-render, giving SmsCreate new prop references and triggering the cycle again.
110
- if (state.isLoadingContent === action.payload) return state;
111
- return { ...state, isLoadingContent: action.payload };
112
- case 'OPEN_TEST_PREVIEW':
113
- return { ...state, showTestAndPreviewSlidebox: true, isTestAndPreviewMode: true };
114
- case 'CLOSE_TEST_PREVIEW':
115
- return { ...state, showTestAndPreviewSlidebox: false, isTestAndPreviewMode: false };
116
- case 'SET_CREATE_FIELDS_INVALID':
117
- if (state.smsCreateRequiredFieldsInvalid === action.payload) return state;
118
- return { ...state, smsCreateRequiredFieldsInvalid: action.payload };
119
- case 'SET_CATEGORY_FILTER':
120
- return { ...state, smsCategoryFilter: action.payload };
121
- default:
122
- return state;
123
- }
124
- }
125
-
126
- // ---------------------------------------------------------------------------
127
- // SmsFallbackEditForm — shared by the inline editor and the EDITING slidebox
128
- // ---------------------------------------------------------------------------
129
-
130
- function SmsFallbackEditForm({
131
- skipCloseOnSave,
132
- dataSource,
133
- value,
134
- view,
135
- embeddedEditLocation,
136
- closeSlidebox,
137
- handleEditComplete,
138
- isRcsEditFlow,
139
- isFullMode,
140
- smsRegister,
141
- selectedOfferDetails,
142
- eventContextTags,
143
- onRcsFallbackEditorStateChange,
144
- }) {
145
- const templateData = mapFallbackValueToEditTemplateData(dataSource ?? value);
146
- if (!templateData) return null;
147
- return (
148
- <SmsTraiEdit
149
- location={embeddedEditLocation}
150
- route={SMS_FALLBACK_ROUTE}
151
- /* Required when embedded `module` is `library`: Sms/Create skips TAG fetch without this (see componentWillReceiveProps). */
152
- getDefaultTags="outbound"
153
- forceFullTagContext
154
- handleClose={closeSlidebox}
155
- templateData={templateData}
156
- getFormSubscriptionData={(formData) => handleEditComplete(formData, skipCloseOnSave)}
157
- isRcsSmsFallback
158
- isRcsEditFlow={isRcsEditFlow}
159
- showPreviewInRcsFallback={view === SMS_FALLBACK_VIEW.EDITING}
160
- isFullMode={isFullMode}
161
- smsRegister={smsRegister}
162
- selectedOfferDetails={selectedOfferDetails}
163
- eventContextTags={eventContextTags}
164
- onRcsFallbackEditorStateChange={onRcsFallbackEditorStateChange}
165
- />
166
- );
167
- }
168
-
169
- SmsFallbackEditForm.propTypes = {
170
- skipCloseOnSave: PropTypes.bool,
171
- dataSource: PropTypes.object,
172
- value: PropTypes.object,
173
- view: PropTypes.string,
174
- embeddedEditLocation: PropTypes.object.isRequired,
175
- closeSlidebox: PropTypes.func.isRequired,
176
- handleEditComplete: PropTypes.func.isRequired,
177
- isRcsEditFlow: PropTypes.bool,
178
- isFullMode: PropTypes.bool,
179
- smsRegister: PropTypes.any,
180
- selectedOfferDetails: PropTypes.object,
181
- eventContextTags: PropTypes.array,
182
- onRcsFallbackEditorStateChange: PropTypes.func,
183
- };
184
-
185
- // ---------------------------------------------------------------------------
186
- // SmsFallbackPortalContent — selector + slidebox overlay rendered via portal
187
- // ---------------------------------------------------------------------------
188
-
189
- function SmsFallbackPortalContent({
190
- slideboxState,
191
- slideboxDispatch,
192
- setIsLoadingContent,
193
- value,
194
- channelsToHide,
195
- smsRegister,
196
- isFullMode,
197
- selectedOfferDetails,
198
- eventContextTags,
199
- isRcsEditFlow,
200
- onRcsFallbackEditorStateChange,
201
- intl,
202
- embeddedCreateLocation,
203
- embeddedEditLocation,
204
- templateListForSelector,
205
- templateList,
206
- scheduleTemplateListSearch,
207
- flushTemplateListSearch,
208
- slideBoxWrapperMargin,
209
- closeSlidebox,
210
- goBackToTemplateList,
211
- handleSelectTemplate,
212
- handleEmbeddedCreativesSave,
213
- openSmsCreate,
214
- showLiquidErrorInFooter,
215
- saveMessage,
216
- handleFooterTestAndPreview,
217
- handleCloseTestAndPreview,
218
- handleEmbeddedSmsFooterValidity,
219
- onValidationFail,
220
- handleSmsTraiCreateComplete,
221
- handleSmsCreateFormSubscription,
222
- handleEditComplete,
223
- // Stable no-op refs kept in parent with useCallback/useMemo so SmsCreate does not
224
- // receive new prop references on every slideboxState change (prevents re-render loop).
225
- getLiquidTags,
226
- forwardedTags,
227
- onPreviewContentClicked,
228
- onTestContentClicked,
229
- }) {
230
- const { formatMessage } = intl;
231
- const {
232
- view,
233
- fetchDetailsLoading,
234
- pendingFallbackData,
235
- smsCategoryFilter,
236
- isGetFormData,
237
- liquidErrorMessage,
238
- isLiquidValidationError,
239
- isLoadingContent,
240
- showTestAndPreviewSlidebox,
241
- isTestAndPreviewMode,
242
- smsCreateRequiredFieldsInvalid,
243
- } = slideboxState;
244
-
245
- const isTrai = isTraiDLTEnable(isFullMode, smsRegister);
246
-
247
- const getSearchTerm = (input) => {
248
- if (typeof input === 'string') return input;
249
- return input?.target?.value || '';
250
- };
251
-
252
- const dltCategoryFilters = isTrai ? (
253
- <CapRadio.CapRadioGroup
254
- className="line-filters"
255
- value={smsCategoryFilter}
256
- onChange={(e) => slideboxDispatch({ type: 'SET_CATEGORY_FILTER', payload: e.target.value })}
257
- >
258
- <CapRadio.Button value={SMS_CATEGORY_FILTERS.ALL}>
259
- <CapLabel type="label2"><FormattedMessage {...templatesListMessages.all} /></CapLabel>
260
- </CapRadio.Button>
261
- <CapRadio.Button value={SMS_CATEGORY_FILTERS.PROMOTIONAL}>
262
- <CapLabel type="label2"><FormattedMessage {...templatesListMessages.promotional} /></CapLabel>
263
- </CapRadio.Button>
264
- <CapRadio.Button value={SMS_CATEGORY_FILTERS.SERVICE_EXPLICIT}>
265
- <CapLabel type="label2"><FormattedMessage {...templatesListMessages.serviceExplicit} /></CapLabel>
266
- </CapRadio.Button>
267
- <CapRadio.Button value={SMS_CATEGORY_FILTERS.SERVICE_IMPLICIT}>
268
- <CapLabel type="label2"><FormattedMessage {...templatesListMessages.serviceImplicit} /></CapLabel>
269
- </CapRadio.Button>
270
- </CapRadio.CapRadioGroup>
271
- ) : null;
272
-
273
- const filterContent = (
274
- <TemplatesActionBar
275
- searchValue={templateList.search}
276
- onSearchChange={(val) => {
277
- const term = getSearchTerm(val);
278
- templateList.setSearch(term);
279
- scheduleTemplateListSearch(term);
280
- }}
281
- onSearch={(val) => {
282
- const term = typeof val === 'string' ? val : (getSearchTerm(val) || templateList.search);
283
- flushTemplateListSearch(term);
284
- }}
285
- onClear={() => flushTemplateListSearch('')}
286
- searchPlaceholder={formatMessage(messages.searchByCreativeName)}
287
- ctaClassName="create-new-sms"
288
- ctaLabel={formatMessage(isTrai ? messages.uploadNew : messages.createNew)}
289
- onCtaClick={openSmsCreate}
290
- >
291
- {dltCategoryFilters}
292
- </TemplatesActionBar>
293
- );
294
-
295
- const showSelector =
296
- view === SMS_FALLBACK_VIEW.SELECTING ||
297
- view === SMS_FALLBACK_VIEW.EDITING ||
298
- view === SMS_FALLBACK_VIEW.CREATING;
299
-
300
- const selectorEl = showSelector ? (
301
- <SmsFallbackLocalSelector
302
- key="sms-fallback-selector"
303
- hidden={view !== SMS_FALLBACK_VIEW.SELECTING}
304
- fetchDetailsLoading={fetchDetailsLoading}
305
- templateList={templateListForSelector}
306
- channelsToHide={channelsToHide}
307
- smsRegister={smsRegister}
308
- onCloseCreatives={closeSlidebox}
309
- onSelectTemplate={handleSelectTemplate}
310
- filterContent={filterContent}
311
- getCreativesData={handleEmbeddedCreativesSave}
312
- location={embeddedCreateLocation}
313
- />
314
- ) : null;
315
-
316
- if (view !== SMS_FALLBACK_VIEW.EDITING && view !== SMS_FALLBACK_VIEW.CREATING) {
317
- return <>{selectorEl}</>;
318
- }
319
-
320
- let slideHeader = null;
321
- let slideContent = null;
322
-
323
- if (view === SMS_FALLBACK_VIEW.CREATING) {
324
- slideHeader = (
325
- <CapHeader
326
- className="support-video-elements sms-fallback-create-slidebox-header"
327
- title={(
328
- <FormattedMessage
329
- {...creativesMessages.createMessageContent}
330
- values={{ channel: <FormattedMessage {...creativesMessages.smsHeader} /> }}
331
- />
332
- )}
333
- prefix={
334
- !isFullMode ? (
335
- <span className="sms-fallback-create-slidebox-header__prefix">
336
- <CapIcons.backIcon onClick={goBackToTemplateList} />
337
- </span>
338
- ) : null
339
- }
340
- />
341
- );
342
- slideContent = (
343
- <SmsWrapper
344
- isCreateSms
345
- embeddedSmsFallback
346
- showLiquidErrorInFooter={showLiquidErrorInFooter}
347
- setIsLoadingContent={setIsLoadingContent}
348
- location={embeddedCreateLocation}
349
- route={SMS_FALLBACK_ROUTE}
350
- isGetFormData={isGetFormData}
351
- getFormSubscriptionData={handleSmsCreateFormSubscription}
352
- onValidationFail={onValidationFail}
353
- showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
354
- handleTestAndPreview={handleFooterTestAndPreview}
355
- handleCloseTestAndPreview={handleCloseTestAndPreview}
356
- isTestAndPreviewMode={isTestAndPreviewMode}
357
- /* Same as campaign embedded SMS + library: triggers full /meta/TAG (outbound) instead of partial supportedTags-only path. */
358
- getDefaultTags="outbound"
359
- forceFullTagContext
360
- getLiquidTags={getLiquidTags}
361
- isFullMode={isFullMode}
362
- forwardedTags={forwardedTags}
363
- selectedOfferDetails={selectedOfferDetails}
364
- onPreviewContentClicked={onPreviewContentClicked}
365
- onTestContentClicked={onTestContentClicked}
366
- onCreateComplete={handleSmsTraiCreateComplete}
367
- onShowTemplates={closeSlidebox}
368
- onEmbeddedSmsFooterValidity={handleEmbeddedSmsFooterValidity}
369
- smsRegister={smsRegister}
370
- eventContextTags={eventContextTags}
371
- />
372
- );
373
- } else if (view === SMS_FALLBACK_VIEW.EDITING && (pendingFallbackData || value)) {
374
- slideHeader = (
375
- <CapHeader
376
- className="sms-fallback-slidebox-header sms-fallback-slidebox-header--edit"
377
- title={formatMessage(messages.editTitle)}
378
- description=""
379
- prefix={(
380
- <div className="sms-fallback-slidebox-header__prefix">
381
- <button
382
- type="button"
383
- className="sms-fallback-slidebox-header__back"
384
- onClick={goBackToTemplateList}
385
- aria-label={formatMessage(messages.backToTemplates)}
386
- >
387
- <CapIcon type="arrow-left" />
388
- </button>
389
- </div>
390
- )}
391
- />
392
- );
393
- slideContent = (
394
- <SmsFallbackEditForm
395
- dataSource={pendingFallbackData || value}
396
- value={value}
397
- view={view}
398
- embeddedEditLocation={embeddedEditLocation}
399
- closeSlidebox={closeSlidebox}
400
- handleEditComplete={handleEditComplete}
401
- isRcsEditFlow={isRcsEditFlow}
402
- isFullMode={isFullMode}
403
- smsRegister={smsRegister}
404
- selectedOfferDetails={selectedOfferDetails}
405
- eventContextTags={eventContextTags}
406
- onRcsFallbackEditorStateChange={onRcsFallbackEditorStateChange}
407
- />
408
- );
409
- }
410
-
411
- const showSmsFormSlideboxFooter =
412
- view === SMS_FALLBACK_VIEW.CREATING &&
413
- !isTraiDLTEnable(false, smsRegister) &&
414
- !isLoadingContent;
415
-
416
- const smsFormSlideboxFooter = showSmsFormSlideboxFooter ? (
417
- <SlideBoxFooter
418
- isFullMode={false}
419
- primarySaveButtonMessage={globalMessages.save}
420
- slidBoxContent="createTemplate"
421
- onSave={saveMessage}
422
- onDiscard={() => {}}
423
- onEditTemplate={() => {}}
424
- onCreateNextStep={() => {}}
425
- shouldShowContinueFooter={() => false}
426
- shouldShowDoneFooter={() => true}
427
- fetchingCmsData={false}
428
- isTemplateNameEmpty={smsCreateRequiredFieldsInvalid}
429
- isLiquidValidationError={isLiquidValidationError}
430
- errorMessages={liquidErrorMessage}
431
- currentTab=""
432
- onTestAndPreview={handleFooterTestAndPreview}
433
- showTestAndPreviewButton
434
- isContinueButtonDisabled={false}
435
- htmlEditorValidationState={{}}
436
- isCreatingTemplate={false}
437
- currentChannel={SMS}
438
- restrictPersonalization={false}
439
- isAnonymousType={false}
440
- templateData={{}}
441
- hasPersonalizationTokenError={false}
442
- />
443
- ) : null;
444
-
445
- return (
446
- <>
447
- {selectorEl}
448
- <CreativesSlideBoxWrapper
449
- slideBoxWrapperMargin={slideBoxWrapperMargin}
450
- shouldApplyFooterMargin={false}
451
- className={classnames(
452
- 'add-creatives-section',
453
- 'creatives-library-mode',
454
- view === SMS_FALLBACK_VIEW.CREATING && 'sms-fallback-slidebox--embedded-sms-create',
455
- )}
456
- >
457
- <CapSlideBox
458
- key="sms-fallback-edit-slidebox"
459
- className="sms-fallback-slidebox rcs-sms-fallback-slidebox"
460
- show
461
- handleClose={closeSlidebox}
462
- header={slideHeader}
463
- content={slideContent}
464
- footer={smsFormSlideboxFooter}
465
- size="size-xl"
466
- />
467
- </CreativesSlideBoxWrapper>
468
- </>
469
- );
470
- }
471
-
472
- // ---------------------------------------------------------------------------
473
- // SmsFallback — main component
474
- // ---------------------------------------------------------------------------
475
-
476
- export function SmsFallback({
477
- dispatch,
478
- value,
479
- onChange,
480
- smsRegister,
481
- selectedOfferDetails,
482
- channelsToHide = CHANNELS_TO_HIDE_FOR_SMS_ONLY,
483
- sectionTitle,
484
- intl,
485
- showAsCard = true,
486
- disableSelectTemplate = false,
487
- eventContextTags,
488
- isFullMode = false,
489
- onRcsFallbackEditorStateChange,
490
- parentLocation,
491
- /** RCS container: true when editing an existing template (Unicode toggle locked in SMS fallback). */
492
- isRcsEditFlow = false,
493
- }) {
494
- const { formatMessage } = intl;
495
- const [slideboxState, slideboxDispatch] = useReducer(slideboxReducer, SLIDEBOX_INITIAL_STATE);
496
- const { view, pendingFallbackData, isLiquidValidationError, liquidErrorMessage } = slideboxState;
497
-
498
- const slideBoxWrapperMargin = useMemo(
499
- () => getSlideBoxWrapperMarginFromLiquidErrors(liquidErrorMessage),
500
- [liquidErrorMessage],
501
- );
502
-
503
- const perPage = 25;
504
- const fetchTemplates = useCallback(
505
- ({ page, search: searchTerm }) =>
506
- new Promise((resolve, reject) => {
507
- dispatch(
508
- templatesActions.getLocalSmsTemplates(
509
- {
510
- page,
511
- perPage,
512
- sortBy: 'Most Recent',
513
- name: searchTerm || '',
514
- ...(isTraiDLTEnable(isFullMode, smsRegister) ? { traiEnable: true } : {}),
515
- },
516
- formatMessage(globalMessages.copyOf),
517
- ({ channelTemplates }) => {
518
- const templates = channelTemplates?.templates || [];
519
- const totalCount = channelTemplates?.totalCount || channelTemplates?.total || 0;
520
- resolve({ templates, totalCount });
521
- },
522
- (error) => reject(error),
523
- )
524
- );
525
- }),
526
- [dispatch, smsRegister, isFullMode, perPage, formatMessage]
527
- );
528
-
529
- const templateList = useLocalTemplateList({ fetchTemplates, perPage });
530
-
531
- /** Same 500ms debounce as `Templates.searchTemplate` (`delay` → `getAllTemplates`). */
532
- const SMS_TEMPLATE_LIST_SEARCH_DEBOUNCE_MS = 500;
533
- const templateSearchDebounceRef = useRef(null);
534
-
535
- const clearTemplateSearchDebounce = useCallback(() => {
536
- if (templateSearchDebounceRef.current != null) {
537
- clearTimeout(templateSearchDebounceRef.current);
538
- templateSearchDebounceRef.current = null;
539
- }
540
- }, []);
541
-
542
- const { reset: resetTemplateList } = templateList;
543
-
544
- const flushTemplateListSearch = useCallback(
545
- (term) => {
546
- clearTemplateSearchDebounce();
547
- resetTemplateList(term);
548
- },
549
- [clearTemplateSearchDebounce, resetTemplateList],
550
- );
551
-
552
- const scheduleTemplateListSearch = useCallback(
553
- (term) => {
554
- clearTemplateSearchDebounce();
555
- templateSearchDebounceRef.current = setTimeout(() => {
556
- templateSearchDebounceRef.current = null;
557
- resetTemplateList(term);
558
- }, SMS_TEMPLATE_LIST_SEARCH_DEBOUNCE_MS);
559
- },
560
- [clearTemplateSearchDebounce, resetTemplateList],
561
- );
562
-
563
- useEffect(() => () => clearTemplateSearchDebounce(), [clearTemplateSearchDebounce]);
564
-
565
- const filteredTemplatesForGrid = useMemo(
566
- () => filterSmsTemplatesByCategory(templateList.templates, slideboxState.smsCategoryFilter),
567
- [templateList.templates, slideboxState.smsCategoryFilter],
568
- );
569
-
570
- const templateListForSelector = useMemo(
571
- () => ({ ...templateList, templates: filteredTemplatesForGrid }),
572
- [templateList, filteredTemplatesForGrid],
573
- );
574
-
575
- const embeddedQueryBase = useMemo(() => {
576
- const parentQuery = get(parentLocation, 'query', {});
577
- const moduleFromParent = parentQuery?.module && parentQuery.module !== 'library'
578
- ? parentQuery.module
579
- : 'default';
580
- return { ...parentQuery, type: 'embedded', module: moduleFromParent };
581
- }, [parentLocation]);
582
-
583
- const embeddedCreateLocation = useMemo(() => ({
584
- ...EMBEDDED_SMS_CREATIVES_LOCATION,
585
- pathname: '/sms/create',
586
- query: embeddedQueryBase,
587
- }), [embeddedQueryBase]);
588
-
589
- const embeddedEditLocation = useMemo(() => ({
590
- ...EMBEDDED_SMS_CREATIVES_EDIT_LOCATION,
591
- pathname: '/sms/edit',
592
- query: embeddedQueryBase,
593
- }), [embeddedQueryBase]);
594
-
595
- /** Bumped when the user dismisses the slidebox or navigates away; in-flight getTemplateDetails ignores stale completions. */
596
- const templateDetailsFetchGenerationRef = useRef(0);
597
-
598
- // resetRef: lets the SELECTING useEffect call the latest templateList.reset without
599
- // adding it as a dep (which would re-run the effect on every templateList update).
600
- const didInitialFetchRef = useRef(false);
601
- const resetRef = useRef(templateList.reset);
602
- resetRef.current = templateList.reset;
603
- useEffect(() => {
604
- if (view !== SMS_FALLBACK_VIEW.SELECTING) {
605
- didInitialFetchRef.current = false;
606
- return;
607
- }
608
- if (didInitialFetchRef.current) return;
609
- didInitialFetchRef.current = true;
610
- resetRef.current();
611
- }, [view]);
612
-
613
- const openSelector = useCallback(() => {
614
- slideboxDispatch({ type: 'OPEN_SELECTOR' });
615
- }, []);
616
-
617
- const closeSlidebox = useCallback(() => {
618
- clearTemplateSearchDebounce();
619
- templateDetailsFetchGenerationRef.current += 1;
620
- slideboxDispatch({ type: 'CLOSE' });
621
- }, [clearTemplateSearchDebounce]);
622
-
623
- const goBackToTemplateList = useCallback(() => {
624
- clearTemplateSearchDebounce();
625
- templateDetailsFetchGenerationRef.current += 1;
626
- slideboxDispatch({ type: 'GO_BACK_TO_LIST' });
627
- templateList.reset();
628
- }, [clearTemplateSearchDebounce, templateList]);
629
-
630
- const showLiquidErrorInFooter = useCallback((errorMessagesFromFormBuilder, currentFormBuilderTab) => {
631
- const next = computeLiquidFooterUpdateFromFormBuilder(errorMessagesFromFormBuilder, liquidErrorMessage, currentFormBuilderTab, {
632
- previousIsLiquidValidationError: isLiquidValidationError,
633
- currentChannelUpper: SMS,
634
- });
635
- if (next == null) return;
636
- slideboxDispatch({ type: 'SET_LIQUID_ERROR', liquidErrorMessage: next.liquidErrorMessage, isLiquidValidationError: next.isLiquidValidationError });
637
- }, [isLiquidValidationError]);
638
-
639
- const onValidationFail = useCallback(() => {
640
- slideboxDispatch({ type: 'SET_IS_GET_FORM_DATA', payload: false });
641
- }, []);
642
-
643
- const saveMessage = useCallback(() => {
644
- slideboxDispatch({ type: 'SET_IS_GET_FORM_DATA', payload: true });
645
- }, []);
646
-
647
- const handleFooterTestAndPreview = useCallback(() => {
648
- slideboxDispatch({ type: 'OPEN_TEST_PREVIEW' });
649
- }, []);
650
-
651
- const handleCloseTestAndPreview = useCallback(() => {
652
- slideboxDispatch({ type: 'CLOSE_TEST_PREVIEW' });
653
- }, []);
654
-
655
- const handleEmbeddedSmsFooterValidity = useCallback((validity) => {
656
- const { isTemplateNameEmpty, isMessageEmpty } = validity || {};
657
- slideboxDispatch({ type: 'SET_CREATE_FIELDS_INVALID', payload: !!isTemplateNameEmpty || !!isMessageEmpty });
658
- }, []);
659
-
660
- // Stable no-ops for SmsWrapper props that have no meaningful implementation in fallback context.
661
- // Must be stable refs — SmsCreate's componentWillReceiveProps calls setIsLoadingContent(true)
662
- // whenever it detects a prop reference change, so any inline arrow here restarts the loading cycle.
663
- const getLiquidTagsNoop = useCallback(() => {}, []);
664
- const onPreviewContentClickedNoop = useCallback(() => {}, []);
665
- const onTestContentClickedNoop = useCallback(() => {}, []);
666
- const emptyForwardedTags = useMemo(() => ({}), []);
667
- const stableEventContextTags = useMemo(() => eventContextTags ?? [], [eventContextTags]);
668
-
669
- // Stable reference required: SmsCreate calls setIsLoadingContent(true) in componentWillReceiveProps
670
- // when it detects a prop change. An inline arrow would create a new reference every render,
671
- // causing SmsCreate to keep resetting loading to true and the footer to never appear.
672
- const setIsLoadingContent = useCallback((v) => {
673
- slideboxDispatch({ type: 'SET_LOADING_CONTENT', payload: v });
674
- }, []);
675
-
676
- const openSmsCreate = useCallback(() => {
677
- clearTemplateSearchDebounce();
678
- templateDetailsFetchGenerationRef.current += 1;
679
- slideboxDispatch({ type: 'OPEN_CREATING' });
680
- }, [clearTemplateSearchDebounce]);
681
-
682
- const handleSelectTemplate = useCallback(
683
- async (template) => {
684
- if (!template) return;
685
- const templateId = template._id;
686
- if (!templateId) {
687
- slideboxDispatch({ type: 'SELECT_TEMPLATE_DONE', payload: buildFallbackDataFromTemplate(template) });
688
- return;
689
- }
690
- const fetchGeneration = ++templateDetailsFetchGenerationRef.current;
691
- slideboxDispatch({ type: 'SELECT_TEMPLATE_START' });
692
- try {
693
- const result = await Api.getTemplateDetails({ id: templateId, channel: SMS_TEMPLATE_DETAILS_API_CHANNEL });
694
- if (fetchGeneration !== templateDetailsFetchGenerationRef.current) return;
695
- slideboxDispatch({
696
- type: 'SELECT_TEMPLATE_DONE',
697
- payload: buildFallbackDataFromTemplate(get(result, 'response', template)),
698
- });
699
- } catch (err) {
700
- if (fetchGeneration !== templateDetailsFetchGenerationRef.current) return;
701
- slideboxDispatch({ type: 'SELECT_TEMPLATE_DONE', payload: buildFallbackDataFromTemplate(template) });
702
- } finally {
703
- if (fetchGeneration === templateDetailsFetchGenerationRef.current) {
704
- slideboxDispatch({ type: 'SET_FETCH_LOADING', payload: false });
705
- }
706
- }
707
- },
708
- []
709
- );
710
-
711
- /**
712
- * Non-Trai SMS create: FormBuilder submits here. Parent `onChange` updates RCS fallback state.
713
- * Do **not** call `onCreateComplete` — in Creatives-embedded Rcs it is `getCreativesData`, which would
714
- * finish the whole creative flow and send the user back to the templates list while RCS edit is still open.
715
- */
716
- const handleSmsCreateFormSubscription = useCallback(
717
- (formPayload) => {
718
- if (!formPayload?.validity) return;
719
- const base = get(formPayload, 'value.base', {});
720
- const smsEditor = base['sms-editor'] || '';
721
- const templateName = base['template-name'] || base.template_name || '';
722
- const nameOk = String(templateName || '').trim();
723
- const bodyOk = String(smsEditor || '').trim();
724
- if (!nameOk || !bodyOk) {
725
- slideboxDispatch({ type: 'SET_IS_GET_FORM_DATA', payload: false });
726
- return;
727
- }
728
- slideboxDispatch({ type: 'SET_IS_GET_FORM_DATA', payload: false });
729
- onChange({
730
- ...(value && typeof value === 'object' ? value : {}),
731
- templateName: nameOk,
732
- content: smsEditor,
733
- templateContent: smsEditor,
734
- unicodeValidity: typeof base['unicode-validity'] === 'boolean'
735
- ? base['unicode-validity']
736
- : true,
737
- });
738
- closeSlidebox();
739
- },
740
- [onChange, closeSlidebox, value],
741
- );
742
-
743
- const handleSmsTraiCreateComplete = useCallback((uploadedTemplate) => {
744
- if (uploadedTemplate) {
745
- const base = uploadedTemplate.versions?.base || {};
746
- const content = base.template_message || base['sms-editor'] || '';
747
- const templateName = uploadedTemplate.name || base.template_name || '';
748
- if (content || templateName) {
749
- onChange({
750
- templateName,
751
- content,
752
- templateContent: content,
753
- unicodeValidity: typeof base['unicode-validity'] === 'boolean'
754
- ? base['unicode-validity']
755
- : true,
756
- });
757
- }
758
- }
759
- closeSlidebox();
760
- }, [onChange, closeSlidebox]);
761
-
762
- /** Embedded template picker: map Creatives payload into fallback value. Same rule as create — no `onCreateComplete`. */
763
- const handleEmbeddedCreativesSave = useCallback(
764
- (creativesData) => {
765
- const next = buildFallbackDataFromCreativesPayload(creativesData);
766
- if (!next) return;
767
- onChange(next);
768
- closeSlidebox();
769
- },
770
- [onChange, closeSlidebox],
771
- );
772
-
773
- const handleEditComplete = useCallback(
774
- (formData, skipClose) => {
775
- const { base } = getBaseFromSmsTraiFormData(formData);
776
- const smsEditor = base['sms-editor'] || '';
777
- const baseForSave = pendingFallbackData || value;
778
- const rcsFallbackVarMappedFromBase = base['rcs-sms-fallback-var-mapped'];
779
- onChange({
780
- ...baseForSave,
781
- content: resolveContentFromTraiBase(base),
782
- templateContent: smsEditor,
783
- unicodeValidity: typeof base['unicode-validity'] === 'boolean'
784
- ? base['unicode-validity']
785
- : baseForSave?.unicodeValidity,
786
- ...(Object.prototype.hasOwnProperty.call(base, 'rcs-sms-fallback-var-mapped')
787
- && rcsFallbackVarMappedFromBase != null
788
- && typeof rcsFallbackVarMappedFromBase === 'object'
789
- ? { rcsSmsFallbackVarMapped: rcsFallbackVarMappedFromBase }
790
- : {}),
791
- });
792
- if (!skipClose) closeSlidebox();
793
- },
794
- [onChange, closeSlidebox, value, pendingFallbackData]
795
- );
796
-
797
- const handleRemove = useCallback(() => {
798
- onChange(null);
799
- }, [onChange]);
800
-
801
- const handleEdit = useCallback(() => {
802
- if (!value) return;
803
- slideboxDispatch({ type: 'OPEN_EDITING' });
804
- }, [value]);
805
-
806
- const extra = value
807
- ? [
808
- <CapDropdown
809
- key="more"
810
- data-testid="test-rcs-sms-fallback-template-more"
811
- overlay={
812
- <CapMenu>
813
- <CapMenu.Item data-testid="test-rcs-sms-fallback-edit" className="ant-dropdown-menu-item" onClick={handleEdit}>
814
- {formatMessage(messages.editTemplate)}
815
- </CapMenu.Item>
816
- <CapMenu.Item data-testid="test-rcs-sms-fallback-delete" className="ant-dropdown-menu-item" onClick={handleRemove}>
817
- {formatMessage(messages.removeTemplate)}
818
- </CapMenu.Item>
819
- </CapMenu>
820
- }
821
- >
822
- <CapIcon type="more" />
823
- </CapDropdown>,
824
- ]
825
- : [];
826
-
827
- const cardData = value
828
- ? {
829
- title: value.templateName?.trim()
830
- ? value.templateName
831
- : formatMessage(messages.fallbackCardUntitled),
832
- content: getSmsFallbackCardDisplayContent(value),
833
- cardType: SMS,
834
- extra,
835
- }
836
- : null;
837
-
838
- return (
839
- <>
840
- <CapRow className="sms-fallback-header-row">
841
- <CapHeader
842
- title={
843
- <CapHeading type="h4">
844
- {value
845
- ? (sectionTitle ?? formatMessage(messages.sectionTitleWithoutOptional))
846
- : (sectionTitle ?? formatMessage(messages.sectionTitle))}
847
- </CapHeading>
848
- }
849
- />
850
- </CapRow>
851
-
852
- {!value ? (
853
- <CapRow className="sms-fallback-select-wrap">
854
- <CapButton
855
- type="flat"
856
- data-testid="test-rcs-sms-fallback-select-template"
857
- className="sms-fallback-select-btn rcs-sms-fallback-select-btn"
858
- onClick={openSelector}
859
- disabled={disableSelectTemplate}
860
- >
861
- {formatMessage(messages.selectTemplate)}
862
- </CapButton>
863
- </CapRow>
864
- ) : showAsCard ? (
865
- <CapRow>
866
- <div className="sms-fallback-card-wrap">
867
- <CapCustomCard.CapCustomCardList cardList={[cardData]} className="sms-fallback-card rcs-sms-fallback-card" type={SMS} />
868
- </div>
869
- </CapRow>
870
- ) : (
871
- <CapRow className="sms-fallback-inline-editor">
872
- <SmsFallbackEditForm
873
- skipCloseOnSave
874
- value={value}
875
- view={view}
876
- embeddedEditLocation={embeddedEditLocation}
877
- closeSlidebox={closeSlidebox}
878
- handleEditComplete={handleEditComplete}
879
- isRcsEditFlow={isRcsEditFlow}
880
- isFullMode={isFullMode}
881
- smsRegister={smsRegister}
882
- selectedOfferDetails={selectedOfferDetails}
883
- eventContextTags={eventContextTags}
884
- onRcsFallbackEditorStateChange={onRcsFallbackEditorStateChange}
885
- />
886
- </CapRow>
887
- )}
888
-
889
- {view && ReactDOM.createPortal(
890
- <SmsFallbackPortalContent
891
- slideboxState={slideboxState}
892
- slideboxDispatch={slideboxDispatch}
893
- value={value}
894
- channelsToHide={channelsToHide}
895
- smsRegister={smsRegister}
896
- isFullMode={isFullMode}
897
- selectedOfferDetails={selectedOfferDetails}
898
- eventContextTags={stableEventContextTags}
899
- isRcsEditFlow={isRcsEditFlow}
900
- onRcsFallbackEditorStateChange={onRcsFallbackEditorStateChange}
901
- intl={intl}
902
- embeddedCreateLocation={embeddedCreateLocation}
903
- embeddedEditLocation={embeddedEditLocation}
904
- templateListForSelector={templateListForSelector}
905
- templateList={templateList}
906
- scheduleTemplateListSearch={scheduleTemplateListSearch}
907
- flushTemplateListSearch={flushTemplateListSearch}
908
- slideBoxWrapperMargin={slideBoxWrapperMargin}
909
- closeSlidebox={closeSlidebox}
910
- goBackToTemplateList={goBackToTemplateList}
911
- handleSelectTemplate={handleSelectTemplate}
912
- handleEmbeddedCreativesSave={handleEmbeddedCreativesSave}
913
- openSmsCreate={openSmsCreate}
914
- showLiquidErrorInFooter={showLiquidErrorInFooter}
915
- saveMessage={saveMessage}
916
- handleFooterTestAndPreview={handleFooterTestAndPreview}
917
- handleCloseTestAndPreview={handleCloseTestAndPreview}
918
- handleEmbeddedSmsFooterValidity={handleEmbeddedSmsFooterValidity}
919
- onValidationFail={onValidationFail}
920
- handleSmsTraiCreateComplete={handleSmsTraiCreateComplete}
921
- handleSmsCreateFormSubscription={handleSmsCreateFormSubscription}
922
- handleEditComplete={handleEditComplete}
923
- setIsLoadingContent={setIsLoadingContent}
924
- getLiquidTags={getLiquidTagsNoop}
925
- forwardedTags={emptyForwardedTags}
926
- onPreviewContentClicked={onPreviewContentClickedNoop}
927
- onTestContentClicked={onTestContentClickedNoop}
928
- />,
929
- document.body,
930
- )}
931
- </>
932
- );
933
- }
934
-
935
- SmsFallback.propTypes = {
936
- dispatch: PropTypes.func,
937
- value: PropTypes.object,
938
- onChange: PropTypes.func.isRequired,
939
- smsRegister: PropTypes.any,
940
- selectedOfferDetails: PropTypes.object,
941
- onPreviewTemplate: PropTypes.func,
942
- channelsToHide: PropTypes.arrayOf(PropTypes.string),
943
- sectionTitle: PropTypes.node,
944
- templateListTitle: PropTypes.node,
945
- templateListDescription: PropTypes.node,
946
- intl: PropTypes.object.isRequired,
947
- showAsCard: PropTypes.bool,
948
- disableSelectTemplate: PropTypes.bool,
949
- eventContextTags: PropTypes.array,
950
- isFullMode: PropTypes.bool,
951
- onRcsFallbackEditorStateChange: PropTypes.func,
952
- parentLocation: PropTypes.object,
953
- isRcsEditFlow: PropTypes.bool,
954
- };
955
-
956
- export default connect()(injectIntl(SmsFallback));