@capillarytech/creatives-library 8.0.318 → 8.0.320
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 +15 -0
- package/package.json +1 -1
- package/services/api.js +6 -0
- package/services/tests/api.test.js +7 -0
- package/utils/common.js +6 -1
- package/utils/templateVarUtils.js +172 -0
- package/utils/tests/templateVarUtils.test.js +160 -0
- package/v2Components/CapTagList/index.js +10 -0
- package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
- package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
- package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +207 -21
- package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
- package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
- package/v2Components/CommonTestAndPreview/SendTestMessage.js +11 -5
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
- package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +12 -0
- package/v2Components/CommonTestAndPreview/constants.js +38 -0
- package/v2Components/CommonTestAndPreview/index.js +693 -155
- package/v2Components/CommonTestAndPreview/messages.js +41 -3
- package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
- package/v2Components/CommonTestAndPreview/sagas.js +15 -6
- package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +269 -1
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
- package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +25 -4
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
- package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -4
- package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
- package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
- package/v2Components/FormBuilder/index.js +7 -1
- package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
- package/v2Components/SmsFallback/constants.js +73 -0
- package/v2Components/SmsFallback/index.js +956 -0
- package/v2Components/SmsFallback/index.scss +265 -0
- package/v2Components/SmsFallback/messages.js +78 -0
- package/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
- package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
- package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
- package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
- package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
- package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
- package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
- package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +8 -1
- package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
- package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
- package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
- package/v2Components/VarSegmentMessageEditor/index.js +125 -0
- package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
- package/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
- package/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
- package/v2Containers/CommunicationFlow/constants.js +200 -0
- package/v2Containers/CommunicationFlow/index.js +102 -0
- package/v2Containers/CommunicationFlow/messages.js +346 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
- package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
- package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
- package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
- package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
- package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
- package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
- package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
- package/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
- package/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
- package/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
- package/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
- package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +10 -1
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
- package/v2Containers/CreativesContainer/constants.js +12 -0
- package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
- package/v2Containers/CreativesContainer/index.js +289 -99
- package/v2Containers/CreativesContainer/index.scss +51 -1
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +104 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -10
- package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
- package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
- package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
- package/v2Containers/Rcs/constants.js +32 -1
- package/v2Containers/Rcs/index.js +950 -873
- package/v2Containers/Rcs/index.scss +85 -6
- package/v2Containers/Rcs/messages.js +10 -1
- package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +40834 -1963
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
- package/v2Containers/Rcs/tests/index.test.js +41 -38
- package/v2Containers/Rcs/tests/mockData.js +38 -0
- package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
- package/v2Containers/Rcs/tests/utils.test.js +379 -1
- package/v2Containers/Rcs/utils.js +358 -10
- package/v2Containers/Sms/Create/index.js +81 -36
- package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
- package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
- package/v2Containers/SmsTrai/Create/index.js +9 -4
- package/v2Containers/SmsTrai/Edit/constants.js +2 -0
- package/v2Containers/SmsTrai/Edit/index.js +609 -128
- package/v2Containers/SmsTrai/Edit/index.scss +121 -0
- package/v2Containers/SmsTrai/Edit/messages.js +9 -4
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4327 -2374
- package/v2Containers/SmsWrapper/index.js +37 -8
- package/v2Containers/TagList/index.js +6 -0
- package/v2Containers/Templates/TemplatesActionBar.js +101 -0
- package/v2Containers/Templates/_templates.scss +61 -2
- package/v2Containers/Templates/actions.js +11 -0
- package/v2Containers/Templates/constants.js +2 -0
- package/v2Containers/Templates/index.js +90 -40
- package/v2Containers/Templates/sagas.js +57 -12
- package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
- package/v2Containers/Templates/tests/sagas.test.js +193 -12
- package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
- package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
- package/v2Containers/TemplatesV2/index.js +86 -23
- package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
- package/v2Containers/Whatsapp/index.js +3 -20
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/* eslint-disable no-restricted-syntax */
|
|
2
2
|
/* eslint-disable no-undef */
|
|
3
|
-
import React, { useState, useEffect } from 'react';
|
|
3
|
+
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
4
5
|
import { createStructuredSelector } from 'reselect';
|
|
5
6
|
import { bindActionCreators } from 'redux';
|
|
6
7
|
import { FormattedMessage } from 'react-intl';
|
|
7
|
-
import { get, cloneDeep, isEmpty
|
|
8
|
+
import { get, cloneDeep, isEmpty } from 'lodash';
|
|
8
9
|
import styled from 'styled-components';
|
|
9
10
|
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
10
11
|
import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
|
|
@@ -27,13 +28,13 @@ import {
|
|
|
27
28
|
CAP_SPACE_32,
|
|
28
29
|
CAP_SPACE_04,
|
|
29
30
|
CAP_WHITE,
|
|
30
|
-
CAP_G10,
|
|
31
31
|
} from '@capillarytech/cap-ui-library/styled/variables';
|
|
32
32
|
import { makeSelectTemplateDetailsResponse } from '../../Sms/Edit/selectors';
|
|
33
33
|
import { makeSelectMetaEntities, selectLiquidStateDetails, setInjectedTags } from '../../Cap/selectors';
|
|
34
34
|
import * as smsEditActions from '../../Sms/Edit/actions';
|
|
35
35
|
import * as globalActions from '../../Cap/actions';
|
|
36
36
|
import messages from './messages';
|
|
37
|
+
import globalMessages from '../../Cap/messages';
|
|
37
38
|
import TagList from '../../TagList';
|
|
38
39
|
import formBuilderMessages from '../../../v2Components/FormBuilder/messages';
|
|
39
40
|
import UnifiedPreview from '../../../v2Components/CommonTestAndPreview/UnifiedPreview';
|
|
@@ -41,6 +42,8 @@ import TestAndPreviewSlidebox from '../../../v2Components/TestAndPreviewSlidebox
|
|
|
41
42
|
import withCreatives from '../../../hoc/withCreatives';
|
|
42
43
|
import {
|
|
43
44
|
CHARLIMIT,
|
|
45
|
+
SMS,
|
|
46
|
+
SMS_TRAI_CONTENT_MAX_LENGTH,
|
|
44
47
|
SMS_TRAI_VAR,
|
|
45
48
|
TAG,
|
|
46
49
|
EMBEDDED,
|
|
@@ -49,24 +52,39 @@ import {
|
|
|
49
52
|
ALL,
|
|
50
53
|
LIBRARY,
|
|
51
54
|
} from './constants';
|
|
52
|
-
import { SMS } from '../../CreativesContainer/constants';
|
|
53
55
|
import v2EditSmsReducer from '../../Sms/Edit/reducer';
|
|
54
56
|
import { v2SmsEditSagas } from '../../Sms/Edit/sagas';
|
|
55
57
|
import ErrorInfoNote from '../../../v2Components/ErrorInfoNote';
|
|
58
|
+
import { isTraiDLTEnable, hasTraiDltFeature } from '../../../utils/common';
|
|
56
59
|
import { validateLiquidTemplateContent } from '../../../utils/commonUtils';
|
|
57
60
|
import { validateTags } from '../../../utils/tagValidations';
|
|
58
|
-
import globalMessages from '../../Cap/messages';
|
|
59
61
|
import { ANDROID } from '../../../v2Components/CommonTestAndPreview/constants';
|
|
62
|
+
import {
|
|
63
|
+
getFallbackResolvedContent,
|
|
64
|
+
splitTemplateVarString,
|
|
65
|
+
COMBINED_SMS_TEMPLATE_VAR_REGEX,
|
|
66
|
+
isAnyTemplateVarToken,
|
|
67
|
+
isDltHashVarToken,
|
|
68
|
+
} from '../../../utils/templateVarUtils';
|
|
69
|
+
import VarSegmentMessageEditor from '../../../v2Components/VarSegmentMessageEditor';
|
|
70
|
+
import rcsMessages from '../../Rcs/messages';
|
|
71
|
+
|
|
72
|
+
import './index.scss';
|
|
60
73
|
|
|
61
|
-
let varMap = {};
|
|
62
|
-
let traiData = {};
|
|
63
74
|
const { TextArea } = CapInput;
|
|
64
75
|
const { CapLabelInline } = CapLabel;
|
|
65
76
|
|
|
77
|
+
/** Redux `metaEntities` may be an Immutable.Map; TagList needs plain `tags.standard`. */
|
|
78
|
+
const getStandardTagsFromMeta = (metaEntities) => {
|
|
79
|
+
if (!metaEntities) return [];
|
|
80
|
+
const plain = typeof metaEntities.toJS === 'function' ? metaEntities.toJS() : metaEntities;
|
|
81
|
+
const standard = get(plain, 'tags.standard');
|
|
82
|
+
return Array.isArray(standard) ? standard : [];
|
|
83
|
+
};
|
|
84
|
+
|
|
66
85
|
export const SmsTraiEdit = (props) => {
|
|
67
86
|
const {
|
|
68
87
|
intl,
|
|
69
|
-
handleClose,
|
|
70
88
|
params,
|
|
71
89
|
actions,
|
|
72
90
|
templateDetails,
|
|
@@ -85,6 +103,17 @@ export const SmsTraiEdit = (props) => {
|
|
|
85
103
|
fetchingLiquidTags,
|
|
86
104
|
getLiquidTags,
|
|
87
105
|
showLiquidErrorInFooter,
|
|
106
|
+
smsRegister,
|
|
107
|
+
// RCS -> SMS fallback edit mode
|
|
108
|
+
isRcsSmsFallback = false,
|
|
109
|
+
/** When editing an existing RCS template, lock Unicode (matches product: no mid-edit toggle). */
|
|
110
|
+
isRcsEditFlow = false,
|
|
111
|
+
showPreviewInRcsFallback = false,
|
|
112
|
+
hidePreview = false,
|
|
113
|
+
isOverview = false,
|
|
114
|
+
forceFullTagContext = false,
|
|
115
|
+
/** RCS parent: merge `rcsSmsFallbackVarMapped` into `smsFallbackData` (same idea as `cardVarMapped`). */
|
|
116
|
+
onRcsFallbackEditorStateChange,
|
|
88
117
|
} = props || {};
|
|
89
118
|
|
|
90
119
|
const { formatMessage } = intl;
|
|
@@ -94,14 +123,149 @@ export const SmsTraiEdit = (props) => {
|
|
|
94
123
|
const [tags, updateTags] = useState([]);
|
|
95
124
|
const [textAreaId, updateTextAreaId] = useState();
|
|
96
125
|
const [isValidationError, updateIsValidationError] = useState(false);
|
|
126
|
+
const [isTagValidationError, updateIsTagValidationError] = useState(false);
|
|
97
127
|
const [totalMessageLength, setTotalMessageLength] = useState(0);
|
|
98
128
|
const [isUnicodeAllowed, updateIsUnicodeAllowed] = useState(true);
|
|
129
|
+
const [fallbackText, setFallbackText] = useState('');
|
|
130
|
+
const [fallbackVarMappedData, setFallbackVarMappedData] = useState({});
|
|
131
|
+
const [fallbackFocusedId, setFallbackFocusedId] = useState('');
|
|
99
132
|
const [showMsgLengthNote, updateshowMsgLengthNote] = useState(false);
|
|
100
133
|
const [liquidErrorMessages, setLiquidErrorMessages] = useState({});
|
|
101
134
|
const [isLiquidValidationError, setIsLiquidValidationError] = useState(false);
|
|
102
135
|
/** After user closes the validation panel, keep it hidden until Save is clicked again (even if ErrorInfoNote remounts). */
|
|
103
136
|
const [liquidErrorPanelDismissed, setLiquidErrorPanelDismissed] = useState(false);
|
|
104
137
|
const [showTestAndPreviewSlidebox, setShowTestAndPreviewSlidebox] = useState(false);
|
|
138
|
+
|
|
139
|
+
/** Per-instance only — was module-level (leaked across mounts / multiple editors). */
|
|
140
|
+
const varMapRef = useRef({});
|
|
141
|
+
const traiDataRef = useRef({});
|
|
142
|
+
const tagValidationResponseRef = useRef({});
|
|
143
|
+
/** De-dupe repeated /meta/TAG fetches from popover/context callbacks. */
|
|
144
|
+
const lastTagSchemaQueryKeyRef = useRef(null);
|
|
145
|
+
/** Latest template props for RCS fallback init — avoids effect deps on unstable `templateData` references. */
|
|
146
|
+
const rcsFallbackTemplateSourceRef = useRef({ isFullMode, templateDetails, templateData });
|
|
147
|
+
rcsFallbackTemplateSourceRef.current = { isFullMode, templateDetails, templateData };
|
|
148
|
+
|
|
149
|
+
const fetchTagSchemaIfNewQuery = (query) => {
|
|
150
|
+
const key = JSON.stringify(query);
|
|
151
|
+
if (lastTagSchemaQueryKeyRef.current === key) return;
|
|
152
|
+
lastTagSchemaQueryKeyRef.current = key;
|
|
153
|
+
globalActions.fetchSchemaForEntity(query);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const traiDltEnabled = useMemo(
|
|
157
|
+
() => isTraiDLTEnable(isFullMode, smsRegister),
|
|
158
|
+
[isFullMode, smsRegister],
|
|
159
|
+
);
|
|
160
|
+
/**
|
|
161
|
+
* VarSegment for RCS SMS fallback when:
|
|
162
|
+
* - `isTraiDLTEnable` passes (library + `smsRegister === 'DLT'`, or full-mode library), or
|
|
163
|
+
* - org has TRAI DLT (`hasTraiDltFeature`) — needed when slidebox used to force `isFullMode={false}`
|
|
164
|
+
* or `smsRegister` is missing so `isTraiDLTEnable` alone is false, or
|
|
165
|
+
* - RCS template inline edit (`isRcsEditFlow`).
|
|
166
|
+
*/
|
|
167
|
+
const useRcsFallbackVarSegment = useMemo(() => {
|
|
168
|
+
if (!isRcsSmsFallback) return false;
|
|
169
|
+
return traiDltEnabled || hasTraiDltFeature() || isRcsEditFlow;
|
|
170
|
+
}, [isRcsSmsFallback, traiDltEnabled, isRcsEditFlow]);
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* RCS SMS fallback: always show character count vs TRAI max (`SMS_TRAI_CONTENT_MAX_LENGTH`).
|
|
174
|
+
* Do not use `totalCharacters` ({smsCount} SMS via length/160) here: resolved template + variable
|
|
175
|
+
* values can exceed one GSM segment while DLT still shows a single registered template — length/160
|
|
176
|
+
* is only a rough segment hint and reads as “wrong SMS count” in campaigns.
|
|
177
|
+
*/
|
|
178
|
+
const renderDescriptionCharacterCount = (className = "rcs-character-count") => (
|
|
179
|
+
<CapLabel type="label1" className={className}>
|
|
180
|
+
{formatMessage(messages.charactersCountLabel, {
|
|
181
|
+
current: totalMessageLength,
|
|
182
|
+
max: SMS_TRAI_CONTENT_MAX_LENGTH,
|
|
183
|
+
})}
|
|
184
|
+
</CapLabel>
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
const dltConsecutiveRunLength = (segments, index) => {
|
|
188
|
+
if (!Array.isArray(segments) || typeof segments[index] !== 'string' || !isDltHashVarToken(segments[index])) {
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
191
|
+
let lo = index;
|
|
192
|
+
while (lo > 0 && isDltHashVarToken(segments[lo - 1])) lo -= 1;
|
|
193
|
+
let hi = index;
|
|
194
|
+
while (hi < segments.length - 1 && isDltHashVarToken(segments[hi + 1])) hi += 1;
|
|
195
|
+
return hi - lo + 1;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const renderRcsFallbackMessage = (str = '') => {
|
|
199
|
+
if (!useRcsFallbackVarSegment) {
|
|
200
|
+
return (
|
|
201
|
+
<CapRow className="rcs-create-template-message-input">
|
|
202
|
+
<div className="rcs_text_area_wrapper">
|
|
203
|
+
<TextArea
|
|
204
|
+
id="rcs_fallback_message_textarea"
|
|
205
|
+
autosize={{ minRows: 4, maxRows: 12 }}
|
|
206
|
+
value={fallbackText}
|
|
207
|
+
onChange={(e) => setFallbackText(e.target.value)}
|
|
208
|
+
placeholder={formatMessage(rcsMessages.fallbackMsgPlaceholder)}
|
|
209
|
+
data-testid="rcs_fallback_plain_text_area"
|
|
210
|
+
/>
|
|
211
|
+
{renderDescriptionCharacterCount()}
|
|
212
|
+
</div>
|
|
213
|
+
</CapRow>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
return (
|
|
217
|
+
<CapRow className="rcs-create-template-message-input">
|
|
218
|
+
<div className="rcs_text_area_wrapper">
|
|
219
|
+
<VarSegmentMessageEditor
|
|
220
|
+
templateString={str}
|
|
221
|
+
valueMap={fallbackVarMappedData || {}}
|
|
222
|
+
onChange={(varSegmentFieldId, nextSlotValue) => {
|
|
223
|
+
setFallbackVarMappedData((previousSlotMap) => ({
|
|
224
|
+
...(previousSlotMap || {}),
|
|
225
|
+
[varSegmentFieldId]: nextSlotValue,
|
|
226
|
+
}));
|
|
227
|
+
}}
|
|
228
|
+
onFocus={setFallbackFocusedId}
|
|
229
|
+
varRegex={COMBINED_SMS_TEMPLATE_VAR_REGEX}
|
|
230
|
+
placeholderPrefix=""
|
|
231
|
+
getPlaceholder={() => formatMessage(rcsMessages.fallbackMsgPlaceholder)}
|
|
232
|
+
renderVarFooter={(dltSegmentToken, dltSegmentIndex) => {
|
|
233
|
+
if (!isDltHashVarToken(dltSegmentToken)) return null;
|
|
234
|
+
const segments = splitTemplateVarString(str, COMBINED_SMS_TEMPLATE_VAR_REGEX);
|
|
235
|
+
const varCounts = dltConsecutiveRunLength(segments, dltSegmentIndex);
|
|
236
|
+
if (varCounts < 1) return null;
|
|
237
|
+
/* Inline layout/color so hint is visible even if CapSpin / load order blocks SCSS */
|
|
238
|
+
const dltVarSlotHintStyle = {
|
|
239
|
+
display: 'block',
|
|
240
|
+
marginTop: CAP_SPACE_04,
|
|
241
|
+
marginLeft: 'auto',
|
|
242
|
+
marginRight: 0,
|
|
243
|
+
width: 'fit-content',
|
|
244
|
+
maxWidth: '100%',
|
|
245
|
+
textAlign: 'right',
|
|
246
|
+
color: 'rgba(0, 0, 0, 0.45)',
|
|
247
|
+
fontSize: 12,
|
|
248
|
+
fontWeight: 400,
|
|
249
|
+
lineHeight: '16px',
|
|
250
|
+
};
|
|
251
|
+
return (
|
|
252
|
+
<span className="sms-trai-rcs-fallback-var-hint" style={dltVarSlotHintStyle}>
|
|
253
|
+
{formatMessage(messages.textAreaCounts, {
|
|
254
|
+
varCounts,
|
|
255
|
+
var: SMS_TRAI_VAR,
|
|
256
|
+
charCounts: varCounts * CHARLIMIT,
|
|
257
|
+
})}
|
|
258
|
+
</span>
|
|
259
|
+
);
|
|
260
|
+
}}
|
|
261
|
+
/>
|
|
262
|
+
{(!isFullMode)
|
|
263
|
+
? renderDescriptionCharacterCount('rcs-character-count rcs-character-count--compact')
|
|
264
|
+
: (isFullMode && renderDescriptionCharacterCount())}
|
|
265
|
+
</div>
|
|
266
|
+
</CapRow>
|
|
267
|
+
);
|
|
268
|
+
};
|
|
105
269
|
const SMSTraiFooter = styled.div`
|
|
106
270
|
background-color: ${CAP_WHITE};
|
|
107
271
|
padding: ${CAP_SPACE_32} ${CAP_SPACE_24};
|
|
@@ -117,7 +281,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
117
281
|
.ant-btn {
|
|
118
282
|
margin-right: ${CAP_SPACE_16};
|
|
119
283
|
}
|
|
120
|
-
}
|
|
121
284
|
`;
|
|
122
285
|
const TraiEditTemplateDetails = styled.div`
|
|
123
286
|
margin-bottom: ${CAP_SPACE_16};
|
|
@@ -126,41 +289,127 @@ export const SmsTraiEdit = (props) => {
|
|
|
126
289
|
}
|
|
127
290
|
`;
|
|
128
291
|
|
|
292
|
+
/**
|
|
293
|
+
* RCS embedded SMS fallback receives a new `templateData` object from `mapFallbackValueToEditTemplateData`
|
|
294
|
+
* on every parent render. Depending on `[templateDetails || templateData]` re-ran init and wiped
|
|
295
|
+
* VarSegmentMessageEditor state whenever Test & Preview (or any) re-rendered Rcs. Key only changes
|
|
296
|
+
* when template id / sms-editor / header actually change.
|
|
297
|
+
*
|
|
298
|
+
* Do NOT include `unicode-validity` in the key: parent merges `onRcsFallbackEditorStateChange`
|
|
299
|
+
* unicode patches into `templateData`, which would change the key every toggle and re-run init —
|
|
300
|
+
* resetting local checkbox state (visible as the unicode control flipping).
|
|
301
|
+
*
|
|
302
|
+
* Do NOT include `rcs-sms-fallback-var-mapped` in the key: the parent merges slot edits into
|
|
303
|
+
* `templateData` on every change, so the key would change each keystroke and this effect would
|
|
304
|
+
* re-run and reset slots — visible as toggling between old and new values.
|
|
305
|
+
*/
|
|
306
|
+
const rcsFallbackTemplateInitKey = useMemo(() => {
|
|
307
|
+
if (!isRcsSmsFallback) return null;
|
|
308
|
+
// RCS fallback slidebox always passes `templateData` from `mapFallbackValueToEditTemplateData`.
|
|
309
|
+
// `templateDetails` stays empty there (no route id fetch) — do not branch on `isFullMode` or init
|
|
310
|
+
// key is null, the effect never runs, and `loading` stays true forever.
|
|
311
|
+
const activeSmsTemplateSource = templateData;
|
|
312
|
+
if (!activeSmsTemplateSource || isEmpty(activeSmsTemplateSource)) return null;
|
|
313
|
+
const templateBase = get(activeSmsTemplateSource, 'versions.base', {}) || {};
|
|
314
|
+
const smsEditorTemplateString = templateBase?.['sms-editor'] ?? '';
|
|
315
|
+
const registeredSenderHeaderList = templateBase?.header;
|
|
316
|
+
const headerListFingerprint = Array.isArray(registeredSenderHeaderList)
|
|
317
|
+
? registeredSenderHeaderList.join('\u001f')
|
|
318
|
+
: '';
|
|
319
|
+
const templateRecordId = activeSmsTemplateSource?._id ?? '';
|
|
320
|
+
return [
|
|
321
|
+
templateRecordId,
|
|
322
|
+
smsEditorTemplateString,
|
|
323
|
+
headerListFingerprint,
|
|
324
|
+
].join('\u0000');
|
|
325
|
+
}, [isRcsSmsFallback, templateData]);
|
|
326
|
+
|
|
129
327
|
useEffect(() => {
|
|
130
|
-
//fetching tags
|
|
131
328
|
const { type, module } = location.query || {};
|
|
132
329
|
const isEmbedded = type === EMBEDDED;
|
|
133
330
|
const query = {
|
|
134
331
|
layout: SMS,
|
|
135
332
|
type: TAG,
|
|
136
333
|
context: isEmbedded ? module : DEFAULT,
|
|
137
|
-
embedded: isEmbedded ? type : FULL,
|
|
334
|
+
embedded: forceFullTagContext ? FULL : (isEmbedded ? type : FULL),
|
|
138
335
|
};
|
|
139
336
|
if (getDefaultTags) {
|
|
140
337
|
query.context = getDefaultTags;
|
|
141
338
|
}
|
|
142
|
-
|
|
143
|
-
//fetching template data in fullmode
|
|
339
|
+
fetchTagSchemaIfNewQuery(query);
|
|
144
340
|
const { id } = params || {};
|
|
145
341
|
if (id) {
|
|
146
342
|
actions.getTemplateDetails(id);
|
|
147
343
|
}
|
|
148
|
-
//cleanup code
|
|
149
344
|
return () => {
|
|
150
345
|
actions.resetEditTemplate();
|
|
151
|
-
|
|
346
|
+
varMapRef.current = {};
|
|
152
347
|
};
|
|
153
348
|
}, []);
|
|
154
349
|
|
|
155
|
-
//computing placeholder array for mapping values and rendering dynamic form
|
|
156
350
|
useEffect(() => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
351
|
+
if (!isRcsSmsFallback || rcsFallbackTemplateInitKey == null) return;
|
|
352
|
+
const {
|
|
353
|
+
isFullMode: isFullModeFromRef,
|
|
354
|
+
templateDetails: templateDetailsFromRef,
|
|
355
|
+
templateData: templateDataFromRef,
|
|
356
|
+
} = rcsFallbackTemplateSourceRef.current;
|
|
357
|
+
const activeTemplateSourceForInit = isRcsSmsFallback
|
|
358
|
+
? templateDataFromRef
|
|
359
|
+
: (isFullModeFromRef ? templateDetailsFromRef : templateDataFromRef);
|
|
360
|
+
if (!activeTemplateSourceForInit || isEmpty(activeTemplateSourceForInit)) return;
|
|
361
|
+
traiDataRef.current = activeTemplateSourceForInit;
|
|
362
|
+
const templateBase = get(activeTemplateSourceForInit, 'versions.base', {});
|
|
363
|
+
const unicodeValidity = get(templateBase, 'unicode-validity', true);
|
|
364
|
+
const templateMsg = get(activeTemplateSourceForInit, 'versions.base.sms-editor', '') || '';
|
|
365
|
+
if (!useRcsFallbackVarSegment) {
|
|
366
|
+
setFallbackText(templateMsg);
|
|
367
|
+
setFallbackVarMappedData({});
|
|
368
|
+
setUpdatedSmsEditor(String(templateMsg).split(''));
|
|
369
|
+
setTotalMessageLength(String(templateMsg).length);
|
|
370
|
+
updateIsUnicodeAllowed(unicodeValidity);
|
|
371
|
+
updateLoading(false);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
const savedVarMap = get(templateBase, 'rcs-sms-fallback-var-mapped', {}) || {};
|
|
375
|
+
const initialVarMap = {};
|
|
376
|
+
const templateSegments = splitTemplateVarString(templateMsg, COMBINED_SMS_TEMPLATE_VAR_REGEX);
|
|
377
|
+
let varOrdinal = 0;
|
|
378
|
+
templateSegments.forEach((segmentToken, segmentIndexInTemplate) => {
|
|
379
|
+
const isVar =
|
|
380
|
+
typeof segmentToken === 'string' && isAnyTemplateVarToken(segmentToken);
|
|
381
|
+
if (!isVar) return;
|
|
382
|
+
varOrdinal += 1;
|
|
383
|
+
const varSegmentSlotId = `${segmentToken}_${segmentIndexInTemplate}`;
|
|
384
|
+
const persistedSlotValue =
|
|
385
|
+
savedVarMap?.[varSegmentSlotId]
|
|
386
|
+
?? savedVarMap?.[`${segmentToken}_${varOrdinal}`];
|
|
387
|
+
// Persisted '' means the user cleared the slot — must not fall back to `segmentToken` for mustache
|
|
388
|
+
// (that would resurrect {{…}} in the input and look like the tag "came back").
|
|
389
|
+
if (typeof persistedSlotValue === 'string') {
|
|
390
|
+
initialVarMap[varSegmentSlotId] = persistedSlotValue;
|
|
391
|
+
} else if (isDltHashVarToken(segmentToken)) {
|
|
392
|
+
initialVarMap[varSegmentSlotId] = '';
|
|
393
|
+
} else {
|
|
394
|
+
initialVarMap[varSegmentSlotId] = segmentToken;
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
setFallbackText(templateMsg);
|
|
398
|
+
setFallbackVarMappedData(initialVarMap);
|
|
399
|
+
const initialResolvedFallbackDisplay = getFallbackResolvedContent(templateMsg, initialVarMap);
|
|
400
|
+
setUpdatedSmsEditor(initialResolvedFallbackDisplay.split(''));
|
|
401
|
+
setTotalMessageLength(initialResolvedFallbackDisplay.length);
|
|
402
|
+
updateIsUnicodeAllowed(unicodeValidity);
|
|
403
|
+
updateLoading(false);
|
|
404
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- init only when semantic key changes; template props are read from ref
|
|
405
|
+
}, [isRcsSmsFallback, rcsFallbackTemplateInitKey, useRcsFallbackVarSegment]);
|
|
406
|
+
|
|
407
|
+
useEffect(() => {
|
|
408
|
+
if (isRcsSmsFallback) return;
|
|
409
|
+
traiDataRef.current = isFullMode ? templateDetails : templateData;
|
|
410
|
+
if (traiDataRef.current && !isEmpty(traiDataRef.current)) {
|
|
411
|
+
let msg = get(traiDataRef.current, `versions.base.sms-editor`, '');
|
|
160
412
|
const templateMessageArray = [];
|
|
161
|
-
//converting sms-editor string to an array split at '{#var#}'
|
|
162
|
-
//split and push string before '{#var#}[0 to index]', push '{#var#}',
|
|
163
|
-
//split and repeat for remaining string[index+7 to length]
|
|
164
413
|
while (msg.length !== 0) {
|
|
165
414
|
const index = msg.search(SMS_TRAI_VAR);
|
|
166
415
|
if (index !== -1) {
|
|
@@ -174,30 +423,59 @@ export const SmsTraiEdit = (props) => {
|
|
|
174
423
|
}
|
|
175
424
|
const filteredTemplateMessageArray = templateMessageArray.filter((i) => i === 0 || i);
|
|
176
425
|
updateTempMsgArray(filteredTemplateMessageArray);
|
|
177
|
-
//stop spinner
|
|
178
426
|
updateLoading(false);
|
|
179
427
|
}
|
|
180
|
-
}, [templateDetails || templateData]);
|
|
428
|
+
}, [templateDetails || templateData, isRcsSmsFallback, isFullMode]);
|
|
181
429
|
|
|
182
|
-
//compute/get varMapped and updated-sms-editor
|
|
183
430
|
useEffect(() => {
|
|
431
|
+
if (!isRcsSmsFallback) return;
|
|
432
|
+
if (!useRcsFallbackVarSegment) {
|
|
433
|
+
const plainFallbackSmsText = fallbackText || '';
|
|
434
|
+
setUpdatedSmsEditor(plainFallbackSmsText.split(''));
|
|
435
|
+
setTotalMessageLength(plainFallbackSmsText.length);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
const resolvedFallbackDisplay = getFallbackResolvedContent(
|
|
439
|
+
fallbackText || '',
|
|
440
|
+
fallbackVarMappedData || {},
|
|
441
|
+
);
|
|
442
|
+
setUpdatedSmsEditor(resolvedFallbackDisplay.split(''));
|
|
443
|
+
setTotalMessageLength(resolvedFallbackDisplay.length);
|
|
444
|
+
}, [isRcsSmsFallback, useRcsFallbackVarSegment, fallbackText, fallbackVarMappedData]);
|
|
445
|
+
|
|
446
|
+
useEffect(() => {
|
|
447
|
+
if (!isRcsSmsFallback) return;
|
|
448
|
+
if (typeof onRcsFallbackEditorStateChange !== 'function') return;
|
|
449
|
+
onRcsFallbackEditorStateChange({
|
|
450
|
+
rcsSmsFallbackVarMapped: fallbackVarMappedData || {},
|
|
451
|
+
});
|
|
452
|
+
}, [isRcsSmsFallback, fallbackVarMappedData, onRcsFallbackEditorStateChange]);
|
|
453
|
+
|
|
454
|
+
useEffect(() => {
|
|
455
|
+
if (!isRcsSmsFallback) return;
|
|
456
|
+
if (typeof onRcsFallbackEditorStateChange !== 'function') return;
|
|
457
|
+
onRcsFallbackEditorStateChange({
|
|
458
|
+
unicodeValidity: isUnicodeAllowed,
|
|
459
|
+
});
|
|
460
|
+
}, [isRcsSmsFallback, isUnicodeAllowed, onRcsFallbackEditorStateChange]);
|
|
461
|
+
|
|
462
|
+
useEffect(() => {
|
|
463
|
+
if (isRcsSmsFallback) return;
|
|
184
464
|
if (tempMsgArray.length !== 0) {
|
|
185
|
-
const traiBase =
|
|
465
|
+
const traiBase = traiDataRef.current?.versions?.base || {};
|
|
186
466
|
const {
|
|
187
467
|
'var-mapped': varMapped = {},
|
|
188
468
|
'updated-sms-editor': traiSmsEditor = '',
|
|
189
469
|
'unicode-validity': unicodeValidity = true,
|
|
190
470
|
} = traiBase;
|
|
191
|
-
//if varMap and updated-sms-editor is already present on non first edits,use those values
|
|
192
471
|
if (!isEmpty(varMapped)) {
|
|
193
|
-
|
|
472
|
+
varMapRef.current = cloneDeep(varMapped);
|
|
194
473
|
if (isFullMode) {
|
|
195
474
|
setUpdatedSmsEditor(traiSmsEditor);
|
|
196
475
|
} else {
|
|
197
476
|
computeUpdatedSmsEditor();
|
|
198
477
|
}
|
|
199
478
|
} else {
|
|
200
|
-
//computing and setting varMap for first edit
|
|
201
479
|
let varCount = 1;
|
|
202
480
|
let horizontalSpaceCount = 0;
|
|
203
481
|
for (let i = 0; i < tempMsgArray.length; i += 1) {
|
|
@@ -208,7 +486,7 @@ export const SmsTraiEdit = (props) => {
|
|
|
208
486
|
horizontalSpaceCount += 1;
|
|
209
487
|
}
|
|
210
488
|
if (tempMsgArray[i] !== nextElem && nextElem?.replace(/[^\S\r\n]/gm, '') !== '') {
|
|
211
|
-
|
|
489
|
+
varMapRef.current[`${tempMsgArray[i]}_${(i - varCount - horizontalSpaceCount) + 1}`] = {
|
|
212
490
|
data: '',
|
|
213
491
|
count: varCount,
|
|
214
492
|
};
|
|
@@ -222,7 +500,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
222
500
|
setUpdatedSmsEditor(tempMsgArray);
|
|
223
501
|
}
|
|
224
502
|
updateIsUnicodeAllowed(unicodeValidity);
|
|
225
|
-
// calcaulate message length here
|
|
226
503
|
calculateTotalMessageLength();
|
|
227
504
|
}
|
|
228
505
|
}, [tempMsgArray]);
|
|
@@ -236,17 +513,84 @@ export const SmsTraiEdit = (props) => {
|
|
|
236
513
|
}
|
|
237
514
|
}, []);
|
|
238
515
|
|
|
516
|
+
useEffect(() => {
|
|
517
|
+
const runValidateTags = (content) =>
|
|
518
|
+
validateTags({
|
|
519
|
+
content,
|
|
520
|
+
tagsParam: tags,
|
|
521
|
+
location,
|
|
522
|
+
tagModule: getDefaultTags,
|
|
523
|
+
isFullMode,
|
|
524
|
+
}) || {};
|
|
525
|
+
|
|
526
|
+
if (isRcsSmsFallback) {
|
|
527
|
+
if (isFullMode) {
|
|
528
|
+
tagValidationResponseRef.current = {};
|
|
529
|
+
updateIsTagValidationError(false);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
// TRAI/DLT VarSegment: `validateIfTagClosed` only understands paired `{{…}}` and breaks on
|
|
533
|
+
// legitimate `{#…#}` / mixed TRAI shapes (extra `{`/`}` counts). Do not tie Done to it;
|
|
534
|
+
// slot completeness is enforced by `areAllRcsSmsFallbackVarSlotsFilled` on the RCS screen.
|
|
535
|
+
if (useRcsFallbackVarSegment) {
|
|
536
|
+
tagValidationResponseRef.current = {};
|
|
537
|
+
updateIsTagValidationError(false);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
const validationContent = fallbackText || '';
|
|
541
|
+
if (!validationContent.trim()) {
|
|
542
|
+
tagValidationResponseRef.current = {};
|
|
543
|
+
updateIsTagValidationError(false);
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
tagValidationResponseRef.current = validateTags({
|
|
547
|
+
content: validationContent,
|
|
548
|
+
tagsParam: tags,
|
|
549
|
+
location,
|
|
550
|
+
tagModule: getDefaultTags,
|
|
551
|
+
isFullMode: true,
|
|
552
|
+
}) || {};
|
|
553
|
+
const braceErr = !!tagValidationResponseRef.current.isBraceError;
|
|
554
|
+
// Plain (non-VarSegment) fallback textarea: only unbalanced `{{…}}` disables Done.
|
|
555
|
+
updateIsTagValidationError(braceErr);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
if (
|
|
559
|
+
!isFullMode &&
|
|
560
|
+
updatedSmsEditor?.length > 0 &&
|
|
561
|
+
!updatedSmsEditor.includes(SMS_TRAI_VAR)
|
|
562
|
+
) {
|
|
563
|
+
tagValidationResponseRef.current = runValidateTags(updatedSmsEditor.join(''));
|
|
564
|
+
const missing = (tagValidationResponseRef.current.missingTags || []).length > 0;
|
|
565
|
+
const braceErr = !!tagValidationResponseRef.current.isBraceError;
|
|
566
|
+
updateIsTagValidationError(missing || braceErr);
|
|
567
|
+
} else if (!isRcsSmsFallback) {
|
|
568
|
+
tagValidationResponseRef.current = {};
|
|
569
|
+
updateIsTagValidationError(false);
|
|
570
|
+
}
|
|
571
|
+
}, [
|
|
572
|
+
updatedSmsEditor,
|
|
573
|
+
tags,
|
|
574
|
+
isRcsSmsFallback,
|
|
575
|
+
isFullMode,
|
|
576
|
+
useRcsFallbackVarSegment,
|
|
577
|
+
fallbackText,
|
|
578
|
+
fallbackVarMappedData,
|
|
579
|
+
getDefaultTags,
|
|
580
|
+
location,
|
|
581
|
+
]);
|
|
582
|
+
|
|
239
583
|
const computeUpdatedSmsEditor = () => {
|
|
240
584
|
const arr = [...tempMsgArray];
|
|
241
|
-
const varMapKeys = Object.keys(
|
|
242
|
-
for (const key in
|
|
243
|
-
if (
|
|
585
|
+
const varMapKeys = Object.keys(varMapRef.current)?.map((key) => Number(key.slice(8)))?.sort((a, b) => a - b) || [];
|
|
586
|
+
for (const key in varMapRef.current) {
|
|
587
|
+
if (varMapRef.current[key].data !== '') {
|
|
244
588
|
const _id = Number(key.slice(8)); //Eg: -> extracting index 1 from keys like {#var# } _1
|
|
245
589
|
const loopIndex =
|
|
246
590
|
varMapKeys[varMapKeys?.indexOf(_id) + 1] || arr.length;
|
|
247
591
|
for (let i = _id; i < loopIndex; i += 1) {
|
|
248
592
|
if (i === _id) {
|
|
249
|
-
arr[i] =
|
|
593
|
+
arr[i] = varMapRef.current[key].data; //data for first #var# of the textbox
|
|
250
594
|
} else if (arr[i] === SMS_TRAI_VAR) {
|
|
251
595
|
arr[i] = ''; //'' for remaining #var# of a textbox
|
|
252
596
|
}
|
|
@@ -256,8 +600,8 @@ export const SmsTraiEdit = (props) => {
|
|
|
256
600
|
setUpdatedSmsEditor(arr);
|
|
257
601
|
};
|
|
258
602
|
|
|
259
|
-
//Saving on done start
|
|
260
603
|
const onUpdateTemplateComplete = (editResponse, errorMsg) => {
|
|
604
|
+
updateLoading(false);
|
|
261
605
|
if (editResponse?.templateId) {
|
|
262
606
|
CapNotification.success({
|
|
263
607
|
message: formatMessage(messages.smsEditNotification),
|
|
@@ -336,66 +680,121 @@ export const SmsTraiEdit = (props) => {
|
|
|
336
680
|
};
|
|
337
681
|
|
|
338
682
|
const onDoneCallback = () => {
|
|
339
|
-
|
|
340
|
-
|
|
683
|
+
// RCS fallback: allow Save when only "missing tags" ({{name}} may not be in TagList); still block unbalanced braces.
|
|
684
|
+
if (isTagValidationError) {
|
|
685
|
+
if (!isRcsSmsFallback) return;
|
|
686
|
+
const tagValidationSnapshot = tagValidationResponseRef.current ?? {};
|
|
687
|
+
if (tagValidationSnapshot.isBraceError) return;
|
|
688
|
+
}
|
|
689
|
+
const editorJoined = Array.isArray(updatedSmsEditor)
|
|
690
|
+
? updatedSmsEditor.join('')
|
|
691
|
+
: String(updatedSmsEditor || '');
|
|
692
|
+
if (!isRcsSmsFallback && editorJoined.includes(SMS_TRAI_VAR) && !isFullMode) {
|
|
341
693
|
updateIsValidationError(true);
|
|
342
694
|
} else {
|
|
343
|
-
//
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
695
|
+
// Only show full-screen spinner when waiting on full-mode SMS edit API — not for RCS SMS fallback
|
|
696
|
+
// handoff (getFormSubscriptionData → SmsFallback closeSlidebox) and not for embedded sync handoff.
|
|
697
|
+
if (isFullMode && !isRcsSmsFallback) {
|
|
698
|
+
updateLoading(true);
|
|
699
|
+
}
|
|
700
|
+
if (!traiDataRef.current.versions) {
|
|
701
|
+
traiDataRef.current.versions = { base: {}, history: [] };
|
|
702
|
+
}
|
|
703
|
+
const traiVersions = traiDataRef.current.versions;
|
|
704
|
+
if (isRcsSmsFallback) {
|
|
705
|
+
const {
|
|
706
|
+
'var-mapped': _ignoredVarMapped,
|
|
707
|
+
'updated-sms-editor': _ignoredUpdatedSmsEditor,
|
|
708
|
+
'rcs-sms-fallback-var-mapped': _ignoredFallbackVarMapped,
|
|
709
|
+
...baseWithoutDerivedFields
|
|
710
|
+
} = traiVersions.base || {};
|
|
711
|
+
traiVersions.base = {
|
|
712
|
+
...baseWithoutDerivedFields,
|
|
713
|
+
'sms-editor': fallbackText || '',
|
|
714
|
+
'unicode-validity': isUnicodeAllowed,
|
|
715
|
+
...(useRcsFallbackVarSegment && {
|
|
716
|
+
'rcs-sms-fallback-var-mapped': fallbackVarMappedData || {},
|
|
717
|
+
}),
|
|
718
|
+
};
|
|
719
|
+
} else {
|
|
720
|
+
traiVersions.base = {
|
|
721
|
+
...traiVersions.base,
|
|
722
|
+
'var-mapped': varMapRef.current,
|
|
723
|
+
'updated-sms-editor': updatedSmsEditor,
|
|
724
|
+
'unicode-validity': isUnicodeAllowed,
|
|
725
|
+
};
|
|
726
|
+
}
|
|
352
727
|
traiVersions.history = [traiVersions.base];
|
|
353
|
-
|
|
354
|
-
|
|
728
|
+
// RCS → SMS fallback (slidebox / inline): always hand off via getFormSubscriptionData so parent
|
|
729
|
+
// can persist fallback state and close the slide — never the standalone TRAI editTemplate API here.
|
|
730
|
+
if (isFullMode && !isRcsSmsFallback) {
|
|
731
|
+
actions.editTemplate(traiDataRef.current, onUpdateTemplateComplete);
|
|
355
732
|
} else {
|
|
356
733
|
getFormSubscriptionData({
|
|
357
|
-
value:
|
|
734
|
+
value: traiVersions,
|
|
735
|
+
// Consumers/tests read `versions.base` first (see getBaseFromSmsTraiFormData, rcsDltEditCompletionHandler).
|
|
736
|
+
versions: traiVersions,
|
|
358
737
|
_id: params && params.id,
|
|
359
738
|
validity: true,
|
|
360
739
|
type: SMS,
|
|
361
740
|
});
|
|
741
|
+
updateLoading(false);
|
|
362
742
|
}
|
|
363
743
|
}
|
|
364
744
|
};
|
|
365
|
-
//Saving on done end
|
|
366
745
|
|
|
367
|
-
|
|
746
|
+
const locationQueryType = location?.query?.type;
|
|
747
|
+
const locationQueryModule = location?.query?.module;
|
|
748
|
+
|
|
368
749
|
useEffect(() => {
|
|
369
|
-
let tag =
|
|
370
|
-
|
|
371
|
-
const { type, module } = location.query || {};
|
|
372
|
-
if (type === EMBEDDED && module === LIBRARY && !getDefaultTags) {
|
|
750
|
+
let tag = getStandardTagsFromMeta(metaEntities);
|
|
751
|
+
if ((!Array.isArray(tag) || tag.length === 0) && Array.isArray(supportedTags) && supportedTags.length > 0) {
|
|
373
752
|
tag = supportedTags;
|
|
374
753
|
}
|
|
375
|
-
|
|
376
|
-
|
|
754
|
+
if (
|
|
755
|
+
locationQueryType === EMBEDDED &&
|
|
756
|
+
locationQueryModule === LIBRARY &&
|
|
757
|
+
!getDefaultTags
|
|
758
|
+
) {
|
|
759
|
+
tag = supportedTags || [];
|
|
760
|
+
}
|
|
761
|
+
updateTags(Array.isArray(tag) ? tag : []);
|
|
762
|
+
}, [metaEntities, getDefaultTags, supportedTags, locationQueryType, locationQueryModule]);
|
|
377
763
|
|
|
378
764
|
const handleOnTagsContextChange = (data) => {
|
|
765
|
+
// CapTagList passes "Outbound" | "Loyalty" from the module filter; TagList may pass "Outbound" on init.
|
|
766
|
+
if (data == null || data === '') return;
|
|
767
|
+
const normalizedContext = String(data).toLowerCase();
|
|
379
768
|
const { type } = location.query || {};
|
|
380
769
|
const isEmbedded = type === EMBEDDED;
|
|
381
770
|
const query = {
|
|
382
771
|
layout: SMS,
|
|
383
772
|
type: TAG,
|
|
384
|
-
context:
|
|
385
|
-
|
|
386
|
-
? DEFAULT
|
|
387
|
-
: (data || '').toLowerCase(),
|
|
388
|
-
embedded: isEmbedded ? type : FULL,
|
|
773
|
+
context: normalizedContext === ALL ? DEFAULT : normalizedContext,
|
|
774
|
+
embedded: forceFullTagContext ? FULL : (isEmbedded ? type : FULL),
|
|
389
775
|
};
|
|
390
|
-
|
|
776
|
+
fetchTagSchemaIfNewQuery(query);
|
|
391
777
|
};
|
|
392
778
|
|
|
393
779
|
const onTagSelect = (data) => {
|
|
394
|
-
if (
|
|
780
|
+
if (isRcsSmsFallback) {
|
|
781
|
+
if (!useRcsFallbackVarSegment) {
|
|
782
|
+
setFallbackText((prev) => `${prev || ''}{{${data}}}`);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
if (!fallbackFocusedId) return;
|
|
786
|
+
const prevVal = fallbackVarMappedData?.[fallbackFocusedId] ?? '';
|
|
787
|
+
const nextVal = `${prevVal}{{${data}}}`;
|
|
788
|
+
setFallbackVarMappedData((prev) => ({
|
|
789
|
+
...(prev || {}),
|
|
790
|
+
[fallbackFocusedId]: nextVal,
|
|
791
|
+
}));
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
if (textAreaId >= 0 && varMapRef.current && updatedSmsEditor) {
|
|
395
795
|
const arr = [...updatedSmsEditor];
|
|
396
|
-
const varMapKeys = Object.keys(
|
|
796
|
+
const varMapKeys = Object.keys(varMapRef.current)?.map((key) => Number(key.slice(8)))?.sort((a, b) => a - b) || [];
|
|
397
797
|
const loopIndex = varMapKeys[varMapKeys?.indexOf(textAreaId) + 1] || arr.length;
|
|
398
|
-
//when trying to insert tag in empty textarea,{#var#} is replaced with "" and then tag is added
|
|
399
798
|
for (let i = textAreaId; i < loopIndex; i += 1) {
|
|
400
799
|
if (arr[i] === SMS_TRAI_VAR) {
|
|
401
800
|
arr[i] = '';
|
|
@@ -403,26 +802,23 @@ export const SmsTraiEdit = (props) => {
|
|
|
403
802
|
}
|
|
404
803
|
const messageData = `${arr[textAreaId]}{{${data}}}`;
|
|
405
804
|
arr[textAreaId] = messageData;
|
|
406
|
-
|
|
805
|
+
varMapRef.current[`${SMS_TRAI_VAR}_${textAreaId}`].data = messageData;
|
|
407
806
|
setUpdatedSmsEditor(arr);
|
|
408
807
|
}
|
|
409
808
|
};
|
|
410
|
-
|
|
809
|
+
|
|
411
810
|
const setTextAreaId = (event) => {
|
|
412
811
|
updateTextAreaId(Number(event.target.id));
|
|
413
812
|
};
|
|
414
|
-
// tag code end
|
|
415
813
|
|
|
416
|
-
// on change event of Text Area
|
|
417
814
|
const textAreaValueChange = ({ target: { value, id } }) => {
|
|
815
|
+
if (isRcsSmsFallback) return;
|
|
418
816
|
const _id = Number(id);
|
|
419
817
|
const arr = [...updatedSmsEditor];
|
|
420
|
-
const varMapKeys = Object.keys(
|
|
818
|
+
const varMapKeys = Object.keys(varMapRef.current)?.map((key) => Number(key.slice(8)))?.sort((a, b) => a - b) || [];
|
|
421
819
|
const loopIndex = varMapKeys[varMapKeys?.indexOf(_id) + 1] || arr.length;
|
|
422
820
|
|
|
423
|
-
|
|
424
|
-
varMap[`${SMS_TRAI_VAR}_${_id}`].data = value;
|
|
425
|
-
//based on entered value update updatedSmsEditor
|
|
821
|
+
varMapRef.current[`${SMS_TRAI_VAR}_${_id}`].data = value;
|
|
426
822
|
if (value === '') {
|
|
427
823
|
for (let i = _id; i < loopIndex; i += 1) {
|
|
428
824
|
if (i === _id || arr[i] === '') {
|
|
@@ -432,7 +828,7 @@ export const SmsTraiEdit = (props) => {
|
|
|
432
828
|
} else {
|
|
433
829
|
for (let i = _id; i < loopIndex; i += 1) {
|
|
434
830
|
if (i === _id) {
|
|
435
|
-
arr[i] =
|
|
831
|
+
arr[i] = varMapRef.current[`${SMS_TRAI_VAR}_${_id}`].data;
|
|
436
832
|
} else if (arr[i] === SMS_TRAI_VAR) {
|
|
437
833
|
arr[i] = '';
|
|
438
834
|
}
|
|
@@ -535,18 +931,33 @@ export const SmsTraiEdit = (props) => {
|
|
|
535
931
|
};
|
|
536
932
|
|
|
537
933
|
const smsLengthForVar = () => (
|
|
538
|
-
<CapHeading
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
934
|
+
<CapHeading
|
|
935
|
+
type="h5"
|
|
936
|
+
className={isRcsSmsFallback ? 'rcs-character-count rcs-character-count--compact' : ''}
|
|
937
|
+
style={isRcsSmsFallback ? {} : { marginTop: CAP_SPACE_04, marginBottom: 0 }}
|
|
938
|
+
>
|
|
939
|
+
{isRcsSmsFallback
|
|
940
|
+
? formatMessage(messages.charactersCountLabel, {
|
|
941
|
+
current: totalMessageLength,
|
|
942
|
+
max: SMS_TRAI_CONTENT_MAX_LENGTH,
|
|
943
|
+
})
|
|
944
|
+
: formatMessage(messages.totalCharacters, {
|
|
945
|
+
smsCount: Math.ceil(totalMessageLength / 160),
|
|
946
|
+
number: totalMessageLength,
|
|
947
|
+
})}
|
|
543
948
|
</CapHeading>
|
|
544
949
|
);
|
|
545
950
|
|
|
546
|
-
// to compute the length of the message
|
|
547
|
-
//40 characters is blocked per'{#var#}' if textbox is empty otherwise it will be textbox length
|
|
548
|
-
// and the remaining string length is added to it
|
|
549
951
|
const calculateTotalMessageLength = () => {
|
|
952
|
+
if (isRcsSmsFallback) {
|
|
953
|
+
if (useRcsFallbackVarSegment) {
|
|
954
|
+
const resolved = getFallbackResolvedContent(fallbackText || '', fallbackVarMappedData || {});
|
|
955
|
+
setTotalMessageLength(resolved.length);
|
|
956
|
+
} else {
|
|
957
|
+
setTotalMessageLength((fallbackText || '').length);
|
|
958
|
+
}
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
550
961
|
const msgLenWithoutVar = tempMsgArray
|
|
551
962
|
?.filter((i) => i !== SMS_TRAI_VAR)
|
|
552
963
|
.join('');
|
|
@@ -557,22 +968,43 @@ export const SmsTraiEdit = (props) => {
|
|
|
557
968
|
|
|
558
969
|
const calculateLenForTextBox = () => {
|
|
559
970
|
let countVarChar = 0;
|
|
560
|
-
Object.keys(
|
|
561
|
-
if (
|
|
562
|
-
countVarChar +=
|
|
563
|
-
if (!showMsgLengthNote &&
|
|
971
|
+
Object.keys(varMapRef.current).forEach((i) => {
|
|
972
|
+
if (varMapRef.current[i].data) {
|
|
973
|
+
countVarChar += varMapRef.current[i].data?.length;
|
|
974
|
+
if (!showMsgLengthNote && varMapRef.current[i].data?.length > varMapRef.current[i].count * CHARLIMIT) {
|
|
564
975
|
updateshowMsgLengthNote(true);
|
|
565
976
|
}
|
|
566
977
|
} else {
|
|
567
|
-
countVarChar +=
|
|
978
|
+
countVarChar += varMapRef.current[i].count * CHARLIMIT;
|
|
568
979
|
}
|
|
569
980
|
});
|
|
570
981
|
return countVarChar;
|
|
571
982
|
};
|
|
572
983
|
|
|
984
|
+
const tagValidationErrorMessage = () => {
|
|
985
|
+
const { missingTags = [], unsupportedTags = [], isBraceError } = tagValidationResponseRef.current || {};
|
|
986
|
+
const listForMessage = (unsupportedTags && unsupportedTags.length > 0)
|
|
987
|
+
? unsupportedTags
|
|
988
|
+
: missingTags;
|
|
989
|
+
if (isBraceError) {
|
|
990
|
+
return <CapError>{formatMessage(globalMessages.unbalanacedCurlyBraces)}</CapError>;
|
|
991
|
+
}
|
|
992
|
+
if (listForMessage.length > 0) {
|
|
993
|
+
return (
|
|
994
|
+
<CapError>
|
|
995
|
+
{formatMessage(messages.unsupportedTagsValidationError, {
|
|
996
|
+
unsupportedTags: listForMessage,
|
|
997
|
+
})}
|
|
998
|
+
</CapError>
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
return null;
|
|
1002
|
+
};
|
|
1003
|
+
|
|
573
1004
|
const disablehandler = () => {
|
|
574
|
-
if (
|
|
575
|
-
|
|
1005
|
+
if (isRcsSmsFallback) return false;
|
|
1006
|
+
if (traiDataRef.current && !isEmpty(traiDataRef.current)) {
|
|
1007
|
+
const msg = get(traiDataRef.current, `versions.base.sms-editor`, '');
|
|
576
1008
|
const index = msg.search(SMS_TRAI_VAR);
|
|
577
1009
|
if (index === -1) {
|
|
578
1010
|
return true;
|
|
@@ -586,7 +1018,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
586
1018
|
updateIsUnicodeAllowed(checked);
|
|
587
1019
|
};
|
|
588
1020
|
|
|
589
|
-
// Get template content for test and preview
|
|
590
1021
|
const getTemplateContent = () => {
|
|
591
1022
|
if (!updatedSmsEditor || updatedSmsEditor.length === 0) {
|
|
592
1023
|
return '';
|
|
@@ -594,42 +1025,69 @@ export const SmsTraiEdit = (props) => {
|
|
|
594
1025
|
return updatedSmsEditor.join('');
|
|
595
1026
|
};
|
|
596
1027
|
|
|
597
|
-
// Build formData for TestAndPreviewSlidebox - templateConfigs with templateId and template for DLT test
|
|
598
1028
|
const getFormDataForTestAndPreview = () => {
|
|
599
|
-
const smsBase = get(
|
|
1029
|
+
const smsBase = get(traiDataRef.current, 'versions.base') || get(templateDetails, 'versions.base') || get(templateData, 'versions.base');
|
|
600
1030
|
if (!smsBase || !smsBase.template_id) {
|
|
601
1031
|
return {};
|
|
602
1032
|
}
|
|
603
1033
|
const templateRaw = smsBase['updated-sms-editor'] || smsBase['sms-editor'] || '';
|
|
604
1034
|
const template = Array.isArray(templateRaw) ? templateRaw.join('') : templateRaw;
|
|
1035
|
+
const traiDlt = isTraiDLTEnable(isFullMode, smsRegister);
|
|
1036
|
+
const headerIds = get(traiDataRef.current, 'versions.base.header', []) || [];
|
|
605
1037
|
return {
|
|
606
1038
|
templateConfigs: {
|
|
607
|
-
templateId: smsBase.template_id,
|
|
1039
|
+
templateId: smsBase.template_id,
|
|
1040
|
+
template,
|
|
1041
|
+
traiDltEnabled: traiDlt,
|
|
1042
|
+
registeredSenderIds: traiDlt ? headerIds : [],
|
|
608
1043
|
},
|
|
609
1044
|
};
|
|
610
1045
|
};
|
|
611
1046
|
|
|
612
|
-
// Handle test and preview button click
|
|
613
1047
|
const handleTestAndPreview = () => {
|
|
614
1048
|
setShowTestAndPreviewSlidebox(true);
|
|
615
1049
|
};
|
|
616
1050
|
|
|
617
|
-
// Handle close test and preview slidebox
|
|
618
1051
|
const handleCloseTestAndPreview = () => {
|
|
619
1052
|
setShowTestAndPreviewSlidebox(false);
|
|
620
1053
|
};
|
|
621
1054
|
|
|
1055
|
+
const shouldShowPreview =
|
|
1056
|
+
!isRcsSmsFallback || (showPreviewInRcsFallback && !hidePreview);
|
|
1057
|
+
const smsSidePreviewColumn = (
|
|
1058
|
+
<CapColumn span={8} offset={1}>
|
|
1059
|
+
<UnifiedPreview
|
|
1060
|
+
channel={SMS}
|
|
1061
|
+
content={updatedSmsEditor.join('')}
|
|
1062
|
+
device={ANDROID}
|
|
1063
|
+
showDeviceToggle={false}
|
|
1064
|
+
showHeader={false}
|
|
1065
|
+
formatMessage={formatMessage}
|
|
1066
|
+
senderId={isUnicodeAllowed ? 'Unicode' : 'ASCII'}
|
|
1067
|
+
/>
|
|
1068
|
+
</CapColumn>
|
|
1069
|
+
);
|
|
1070
|
+
|
|
622
1071
|
return (
|
|
623
1072
|
<>
|
|
624
|
-
<CapSpin
|
|
1073
|
+
<CapSpin
|
|
1074
|
+
spinning={loading || fetchingLiquidTags}
|
|
1075
|
+
tip={fetchingLiquidTags && formatMessage(formBuilderMessages.liquidSpinText)}
|
|
1076
|
+
className={[
|
|
1077
|
+
isRcsSmsFallback && 'sms-trai-edit-rcs-fallback',
|
|
1078
|
+
isOverview && 'sms-trai-edit--overview',
|
|
1079
|
+
]
|
|
1080
|
+
.filter(Boolean)
|
|
1081
|
+
.join(' ') || undefined}
|
|
1082
|
+
>
|
|
625
1083
|
<CapRow>
|
|
626
|
-
{
|
|
1084
|
+
{traiDataRef.current && !isEmpty(traiDataRef.current) && !isRcsSmsFallback && (
|
|
627
1085
|
<TraiEditTemplateDetails>
|
|
628
1086
|
<CapLabelInline type="label1">
|
|
629
1087
|
{formatMessage(messages.templateLabel)}
|
|
630
1088
|
</CapLabelInline>
|
|
631
1089
|
<CapLabelInline type="label2">
|
|
632
|
-
{get(
|
|
1090
|
+
{get(traiDataRef.current, `versions.base.template_name`, '')}
|
|
633
1091
|
</CapLabelInline>
|
|
634
1092
|
|
|
635
1093
|
<CapLabelInline type="label1">
|
|
@@ -640,15 +1098,15 @@ export const SmsTraiEdit = (props) => {
|
|
|
640
1098
|
{formatMessage(messages.senderIdlabel)}
|
|
641
1099
|
</CapLabelInline>
|
|
642
1100
|
<CapLabelInline type="label2">
|
|
643
|
-
{[...get(
|
|
1101
|
+
{[...get(traiDataRef.current, `versions.base.header`, [])].join(', ')}
|
|
644
1102
|
</CapLabelInline>
|
|
645
1103
|
</TraiEditTemplateDetails>
|
|
646
1104
|
)}
|
|
647
|
-
<CapColumn span={14}>
|
|
1105
|
+
<CapColumn span={shouldShowPreview ? 14 : 24}>
|
|
648
1106
|
<CapRow>
|
|
649
1107
|
<CapHeader
|
|
650
1108
|
title={formatMessage(messages.traiEditTitle)}
|
|
651
|
-
size=
|
|
1109
|
+
size={isRcsSmsFallback ? 'label1' : 'regular'}
|
|
652
1110
|
suffix={(
|
|
653
1111
|
<TagList
|
|
654
1112
|
label={formatMessage(messages.addLabels)}
|
|
@@ -657,42 +1115,55 @@ export const SmsTraiEdit = (props) => {
|
|
|
657
1115
|
tags={tags || []}
|
|
658
1116
|
onContextChange={handleOnTagsContextChange}
|
|
659
1117
|
injectedTags={injectedTags || {}}
|
|
660
|
-
|
|
1118
|
+
channel={SMS}
|
|
1119
|
+
hidePopover={false}
|
|
1120
|
+
disabled={!isRcsSmsFallback && disablehandler()}
|
|
661
1121
|
selectedOfferDetails={selectedOfferDetails}
|
|
662
1122
|
eventContextTags={eventContextTags}
|
|
1123
|
+
popoverOverlayStyle={isRcsSmsFallback ? { zIndex: 10020 } : undefined}
|
|
1124
|
+
popoverOverlayClassName={isRcsSmsFallback ? 'sms-fallback-taglist-popover rcs-sms-fallback-taglist-popover' : undefined}
|
|
663
1125
|
/>
|
|
664
1126
|
)}
|
|
665
1127
|
/>
|
|
666
1128
|
</CapRow>
|
|
667
1129
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
1130
|
+
{isRcsSmsFallback ? (
|
|
1131
|
+
<>
|
|
1132
|
+
{renderRcsFallbackMessage(fallbackText)}
|
|
1133
|
+
</>
|
|
1134
|
+
) : (
|
|
1135
|
+
<>
|
|
1136
|
+
<CapRow className="sms-trai-editor-segment-row">
|
|
1137
|
+
<div className="sms-trai-segmented-editor">
|
|
1138
|
+
{renderedContent()}
|
|
1139
|
+
</div>
|
|
1140
|
+
</CapRow>
|
|
1141
|
+
<CapRow className="sms-trai-length-row">
|
|
1142
|
+
{smsLengthForVar()}
|
|
1143
|
+
</CapRow>
|
|
1144
|
+
</>
|
|
1145
|
+
)}
|
|
1146
|
+
{isRcsSmsFallback && isTagValidationError && (
|
|
1147
|
+
<CapRow>
|
|
1148
|
+
{tagValidationErrorMessage()}
|
|
1149
|
+
</CapRow>
|
|
1150
|
+
)}
|
|
1151
|
+
{!isRcsSmsFallback && isTagValidationError && tagValidationErrorMessage()}
|
|
1152
|
+
<CapCheckbox
|
|
1153
|
+
onChange={unicodeHandler}
|
|
1154
|
+
checked={isUnicodeAllowed}
|
|
1155
|
+
disabled={
|
|
1156
|
+
isRcsSmsFallback
|
|
1157
|
+
? isRcsEditFlow
|
|
1158
|
+
: disablehandler()
|
|
1159
|
+
}
|
|
673
1160
|
>
|
|
674
|
-
{renderedContent()}
|
|
675
|
-
</CapRow>
|
|
676
|
-
<CapRow>
|
|
677
|
-
{smsLengthForVar()}
|
|
678
|
-
</CapRow>
|
|
679
|
-
<CapCheckbox onChange={unicodeHandler} checked={isUnicodeAllowed} disabled={disablehandler()}>
|
|
680
1161
|
{formatMessage(messages.unicodeLabel)}
|
|
681
1162
|
</CapCheckbox>
|
|
682
1163
|
{showMsgLengthNote && <CapInfoNote message={<FormattedMessage {...messages.msgLengthNote} values={{ var: '{#var#}' }} />} />}
|
|
683
|
-
<div
|
|
684
|
-
</CapColumn>
|
|
685
|
-
<CapColumn span={8} offset={1}>
|
|
686
|
-
<UnifiedPreview
|
|
687
|
-
channel={SMS}
|
|
688
|
-
content={updatedSmsEditor.join('')}
|
|
689
|
-
device={ANDROID}
|
|
690
|
-
showDeviceToggle={false}
|
|
691
|
-
showHeader={false}
|
|
692
|
-
formatMessage={formatMessage}
|
|
693
|
-
senderId={isUnicodeAllowed ? 'Unicode' : 'ASCII'}
|
|
694
|
-
/>
|
|
1164
|
+
<div className="sms-trai-edit-bottom-spacer" />
|
|
695
1165
|
</CapColumn>
|
|
1166
|
+
{shouldShowPreview && smsSidePreviewColumn}
|
|
696
1167
|
</CapRow>
|
|
697
1168
|
<SMSTraiFooter>
|
|
698
1169
|
{isLiquidValidationError && !liquidErrorPanelDismissed && (
|
|
@@ -718,8 +1189,9 @@ export const SmsTraiEdit = (props) => {
|
|
|
718
1189
|
<FormattedMessage {...messages.testAndPreviewButtonLabel} />
|
|
719
1190
|
</CapButton>
|
|
720
1191
|
<CapButton
|
|
721
|
-
onClick={
|
|
1192
|
+
onClick={onDoneCallback}
|
|
722
1193
|
className="create-msg"
|
|
1194
|
+
disabled={isTagValidationError}
|
|
723
1195
|
>
|
|
724
1196
|
<FormattedMessage {...messages.saveButtonLabel} />
|
|
725
1197
|
</CapButton>
|
|
@@ -736,6 +1208,15 @@ export const SmsTraiEdit = (props) => {
|
|
|
736
1208
|
);
|
|
737
1209
|
};
|
|
738
1210
|
|
|
1211
|
+
SmsTraiEdit.propTypes = {
|
|
1212
|
+
isRcsSmsFallback: PropTypes.bool,
|
|
1213
|
+
isRcsEditFlow: PropTypes.bool,
|
|
1214
|
+
showPreviewInRcsFallback: PropTypes.bool,
|
|
1215
|
+
hidePreview: PropTypes.bool,
|
|
1216
|
+
isOverview: PropTypes.bool,
|
|
1217
|
+
onRcsFallbackEditorStateChange: PropTypes.func,
|
|
1218
|
+
};
|
|
1219
|
+
|
|
739
1220
|
const mapStateToProps = createStructuredSelector({
|
|
740
1221
|
templateDetails: makeSelectTemplateDetailsResponse(),
|
|
741
1222
|
metaEntities: makeSelectMetaEntities(),
|