cap-creatives-ui 8.0.280 → 8.0.321
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/.github/workflows/pr-title-check.yml +88 -0
- package/app/constants/unified.js +21 -1
- package/app/containers/App/constants.js +0 -1
- package/app/containers/Login/test/index.test.js +123 -0
- package/app/containers/Login/test/selectors.test.js +165 -0
- package/app/initialState.js +0 -2
- package/app/services/api.js +6 -0
- package/app/services/tests/api.test.js +7 -0
- package/app/services/tests/getSchema.test.js +95 -0
- package/app/utils/common.js +23 -9
- package/app/utils/commonUtils.js +64 -93
- package/app/utils/tagValidations.js +83 -219
- package/app/utils/templateVarUtils.js +172 -0
- package/app/utils/tests/common.test.js +265 -323
- package/app/utils/tests/commonUtil.test.js +461 -118
- package/app/utils/tests/commonUtils.test.js +581 -0
- package/app/utils/tests/messageUtils.test.js +95 -0
- package/app/utils/tests/smsCharCount.test.js +304 -0
- package/app/utils/tests/smsCharCountV2.test.js +213 -10
- package/app/utils/tests/tagValidations.test.js +474 -357
- package/app/utils/tests/templateVarUtils.test.js +160 -0
- package/app/v2Components/CapDeviceContent/index.js +10 -7
- package/app/v2Components/CapTagList/index.js +32 -24
- package/app/v2Components/CapTagList/style.scss +48 -0
- package/app/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
- package/app/v2Components/CapTagListWithInput/index.js +8 -0
- package/app/v2Components/CapWhatsappCTA/index.js +2 -0
- package/app/v2Components/CapWhatsappCarouselButton/index.js +32 -14
- package/app/v2Components/CapWhatsappCarouselButton/tests/index.test.js +120 -2
- package/app/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +39 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +606 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.scss +36 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +79 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/index.js +314 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +141 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +156 -0
- package/app/v2Components/CommonTestAndPreview/SendTestMessage.js +57 -1
- package/app/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
- package/app/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
- package/app/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +210 -4
- package/app/v2Components/CommonTestAndPreview/actions.js +20 -0
- package/app/v2Components/CommonTestAndPreview/constants.js +57 -1
- package/app/v2Components/CommonTestAndPreview/index.js +878 -156
- package/app/v2Components/CommonTestAndPreview/messages.js +41 -3
- package/app/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
- package/app/v2Components/CommonTestAndPreview/reducer.js +47 -0
- package/app/v2Components/CommonTestAndPreview/sagas.js +75 -5
- package/app/v2Components/CommonTestAndPreview/selectors.js +51 -0
- package/app/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
- package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +1156 -0
- package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +334 -0
- package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +576 -0
- package/app/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +156 -0
- package/app/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
- package/app/v2Components/CommonTestAndPreview/tests/actions.test.js +50 -0
- package/app/v2Components/CommonTestAndPreview/tests/constants.test.js +18 -7
- package/app/v2Components/CommonTestAndPreview/tests/index.test.js +914 -5
- package/app/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
- package/app/v2Components/CommonTestAndPreview/tests/reducer.test.js +118 -0
- package/app/v2Components/CommonTestAndPreview/tests/sagas.test.js +146 -378
- package/app/v2Components/CommonTestAndPreview/tests/selectors.test.js +146 -0
- package/app/v2Components/ErrorInfoNote/index.js +24 -26
- package/app/v2Components/FormBuilder/index.js +182 -204
- package/app/v2Components/FormBuilder/messages.js +4 -8
- package/app/v2Components/HtmlEditor/HTMLEditor.js +7 -6
- package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -1
- package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +928 -17
- package/app/v2Components/HtmlEditor/components/CodeEditorPane/index.js +4 -2
- package/app/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +452 -3
- package/app/v2Components/HtmlEditor/hooks/useValidation.js +12 -9
- package/app/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +132 -0
- package/app/v2Components/HtmlEditor/utils/htmlValidator.js +4 -2
- package/app/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
- package/app/v2Components/SmsFallback/constants.js +73 -0
- package/app/v2Components/SmsFallback/index.js +956 -0
- package/app/v2Components/SmsFallback/index.scss +265 -0
- package/app/v2Components/SmsFallback/messages.js +78 -0
- package/app/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
- package/app/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
- package/app/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
- package/app/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
- package/app/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
- package/app/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
- package/app/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
- package/app/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
- package/app/v2Components/TestAndPreviewSlidebox/index.js +22 -1
- package/app/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
- package/app/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
- package/app/v2Components/VarSegmentMessageEditor/constants.js +2 -0
- package/app/v2Components/VarSegmentMessageEditor/index.js +125 -0
- package/app/v2Components/VarSegmentMessageEditor/index.scss +46 -0
- package/app/v2Containers/BeeEditor/index.js +3 -0
- package/app/v2Containers/BeePopupEditor/index.js +9 -2
- package/app/v2Containers/Cap/mockData.js +0 -14
- package/app/v2Containers/Cap/reducer.js +3 -55
- package/app/v2Containers/Cap/tests/reducer.test.js +0 -102
- package/app/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
- package/app/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
- package/app/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
- package/app/v2Containers/CommunicationFlow/constants.js +200 -0
- package/app/v2Containers/CommunicationFlow/index.js +102 -0
- package/app/v2Containers/CommunicationFlow/messages.js +346 -0
- package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
- package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
- package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
- package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
- package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
- package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
- package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
- package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
- package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
- package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
- package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
- package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
- package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
- package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
- package/app/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
- package/app/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
- package/app/v2Containers/CreativesContainer/SlideBoxContent.js +127 -11
- package/app/v2Containers/CreativesContainer/SlideBoxFooter.js +62 -9
- package/app/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
- package/app/v2Containers/CreativesContainer/constants.js +24 -0
- package/app/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
- package/app/v2Containers/CreativesContainer/index.js +346 -71
- package/app/v2Containers/CreativesContainer/index.scss +51 -1
- package/app/v2Containers/CreativesContainer/messages.js +12 -0
- package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
- package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +69 -1
- package/app/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +443 -0
- package/app/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
- package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +147 -4
- package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
- package/app/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +57 -10
- package/app/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
- package/app/v2Containers/CreativesContainer/tests/index.test.js +71 -9
- package/app/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
- package/app/v2Containers/Email/index.js +2 -5
- package/app/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +58 -77
- package/app/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
- package/app/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +158 -89
- package/app/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
- package/app/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +17 -12
- package/app/v2Containers/EmailWrapper/index.js +4 -0
- package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
- package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +133 -0
- package/app/v2Containers/FTP/index.js +2 -51
- package/app/v2Containers/FTP/messages.js +0 -4
- package/app/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +110 -155
- package/app/v2Containers/InApp/index.js +297 -118
- package/app/v2Containers/InApp/tests/index.test.js +17 -6
- package/app/v2Containers/InApp/tests/mockData.js +1 -1
- package/app/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +19 -0
- package/app/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +3 -0
- package/app/v2Containers/InAppWrapper/index.js +3 -0
- package/app/v2Containers/InappAdvance/index.js +5 -104
- package/app/v2Containers/InappAdvance/tests/index.test.js +2 -0
- package/app/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
- package/app/v2Containers/Line/Container/Text/index.js +0 -1
- package/app/v2Containers/MobilePush/Create/index.js +105 -28
- package/app/v2Containers/MobilePush/Create/messages.js +4 -0
- package/app/v2Containers/MobilePush/Edit/index.js +250 -68
- package/app/v2Containers/MobilePush/Edit/messages.js +4 -0
- package/app/v2Containers/MobilePushNew/components/PlatformContentFields.js +36 -12
- package/app/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +68 -27
- package/app/v2Containers/MobilePushNew/index.js +78 -35
- package/app/v2Containers/MobilePushNew/messages.js +8 -0
- package/app/v2Containers/MobilepushWrapper/index.js +11 -1
- package/app/v2Containers/Rcs/constants.js +32 -1
- package/app/v2Containers/Rcs/index.js +963 -916
- package/app/v2Containers/Rcs/index.scss +85 -6
- package/app/v2Containers/Rcs/messages.js +10 -1
- package/app/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
- package/app/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +41136 -1566
- package/app/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
- package/app/v2Containers/Rcs/tests/index.test.js +41 -38
- package/app/v2Containers/Rcs/tests/mockData.js +38 -0
- package/app/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
- package/app/v2Containers/Rcs/tests/utils.test.js +379 -1
- package/app/v2Containers/Rcs/utils.js +358 -10
- package/app/v2Containers/Sms/Create/index.js +122 -39
- package/app/v2Containers/Sms/Create/messages.js +4 -0
- package/app/v2Containers/Sms/Edit/index.js +37 -3
- package/app/v2Containers/Sms/commonMethods.js +3 -6
- package/app/v2Containers/Sms/smsFormDataHelpers.js +67 -0
- package/app/v2Containers/Sms/tests/commonMethods.test.js +122 -0
- package/app/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
- package/app/v2Containers/SmsTrai/Create/index.js +9 -4
- package/app/v2Containers/SmsTrai/Create/index.scss +1 -1
- package/app/v2Containers/SmsTrai/Edit/constants.js +2 -0
- package/app/v2Containers/SmsTrai/Edit/index.js +667 -160
- package/app/v2Containers/SmsTrai/Edit/index.scss +121 -0
- package/app/v2Containers/SmsTrai/Edit/messages.js +9 -4
- package/app/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4590 -2436
- package/app/v2Containers/SmsWrapper/index.js +41 -8
- package/app/v2Containers/TagList/index.js +63 -2
- package/app/v2Containers/TagList/messages.js +8 -0
- package/app/v2Containers/TagList/tests/TagList.test.js +122 -20
- package/app/v2Containers/TagList/tests/mockdata.js +17 -0
- package/app/v2Containers/Templates/TemplatesActionBar.js +101 -0
- package/app/v2Containers/Templates/_templates.scss +61 -2
- package/app/v2Containers/Templates/actions.js +11 -0
- package/app/v2Containers/Templates/constants.js +2 -0
- package/app/v2Containers/Templates/index.js +90 -40
- package/app/v2Containers/Templates/reducer.js +3 -1
- package/app/v2Containers/Templates/sagas.js +57 -12
- package/app/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
- package/app/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
- package/app/v2Containers/Templates/tests/reducer.test.js +12 -0
- package/app/v2Containers/Templates/tests/sagas.test.js +193 -12
- package/app/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
- package/app/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
- package/app/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
- package/app/v2Containers/TemplatesV2/index.js +147 -49
- package/app/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
- package/app/v2Containers/Viber/index.js +9 -10
- package/app/v2Containers/Viber/index.scss +1 -1
- package/app/v2Containers/WebPush/Create/components/BrandIconSection.test.js +264 -0
- package/app/v2Containers/WebPush/Create/components/MessageSection.js +78 -19
- package/app/v2Containers/WebPush/Create/components/MessageSection.test.js +82 -0
- package/app/v2Containers/WebPush/Create/components/__snapshots__/BrandIconSection.test.js.snap +187 -0
- package/app/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +25 -17
- package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.js +80 -0
- package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.test.js +210 -0
- package/app/v2Containers/WebPush/Create/hooks/useTagManagement.js +1 -5
- package/app/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -7
- package/app/v2Containers/WebPush/Create/index.js +36 -6
- package/app/v2Containers/WebPush/Create/index.scss +5 -0
- package/app/v2Containers/WebPush/Create/messages.js +8 -1
- package/app/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +269 -0
- package/app/v2Containers/WebPush/Create/utils/validation.js +31 -15
- package/app/v2Containers/WebPush/Create/utils/validation.test.js +72 -24
- package/app/v2Containers/Whatsapp/index.js +28 -53
- package/app/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +26939 -3982
- package/app/v2Containers/Whatsapp/tests/index.test.js +172 -0
- package/app/v2Containers/Zalo/index.js +5 -11
- package/package.json +2 -2
- package/version +9 -0
|
@@ -52,6 +52,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
52
52
|
modalContent: {title: "Alert", body: "Do you really want to delete this version?", type: 'confirm', id: 'sms-version-modal'},
|
|
53
53
|
showTestAndPreviewSlidebox: false,
|
|
54
54
|
isTestAndPreviewMode: false,
|
|
55
|
+
pendingGetFormData: false,
|
|
55
56
|
};
|
|
56
57
|
this.saveFormData = this.saveFormData.bind(this);
|
|
57
58
|
this.onFormDataChange = this.onFormDataChange.bind(this);
|
|
@@ -134,8 +135,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
componentWillReceiveProps(nextProps) {
|
|
137
|
-
if (nextProps.
|
|
138
|
-
|
|
138
|
+
if (!nextProps.isFullMode && nextProps.isGetFormData && !this.props.isGetFormData) {
|
|
139
|
+
this.setState({ startValidation: true, pendingGetFormData: true });
|
|
139
140
|
}
|
|
140
141
|
if ( nextProps.location.query.module === 'library' && nextProps.subscriptionTemplateDetails && nextProps.subscriptionTemplateDetails.name && _.isEmpty(this.state.editData) && !_.isEmpty(this.state.schema)) {
|
|
141
142
|
this.setEditState(nextProps.subscriptionTemplateDetails);
|
|
@@ -189,6 +190,9 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
189
190
|
}
|
|
190
191
|
|
|
191
192
|
componentWillUnmount() {
|
|
193
|
+
if (this.pendingGetFormDataTimeout) {
|
|
194
|
+
clearTimeout(this.pendingGetFormDataTimeout);
|
|
195
|
+
}
|
|
192
196
|
if (this.props.setIsLoadingContent) {
|
|
193
197
|
this.props.setIsLoadingContent(true); // setting isLoading of CreativesContainer so that slidebox foot can be hidden till content is loaded
|
|
194
198
|
}
|
|
@@ -214,6 +218,10 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
214
218
|
if (currentTab) {
|
|
215
219
|
this.setState({currentTab});
|
|
216
220
|
}
|
|
221
|
+
// Clear footer validation errors on input change so they refresh on next validation
|
|
222
|
+
if (this.props.showLiquidErrorInFooter) {
|
|
223
|
+
this.props.showLiquidErrorInFooter({ STANDARD_ERROR_MSG: [], LIQUID_ERROR_MSG: [] });
|
|
224
|
+
}
|
|
217
225
|
}
|
|
218
226
|
|
|
219
227
|
onVersionNameChange() {
|
|
@@ -317,7 +325,23 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
317
325
|
}
|
|
318
326
|
|
|
319
327
|
setFormValidity(isFormValid, errorData) {
|
|
320
|
-
this.setState({isFormValid, errorData})
|
|
328
|
+
this.setState({ isFormValid, errorData }, () => {
|
|
329
|
+
if (this.state.pendingGetFormData && !isFormValid) {
|
|
330
|
+
this.setState({ pendingGetFormData: false, startValidation: false });
|
|
331
|
+
if (this.props.onValidationFail) {
|
|
332
|
+
this.props.onValidationFail();
|
|
333
|
+
}
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if (this.state.pendingGetFormData && this.props.getFormSubscriptionData && this.props.isFullMode) {
|
|
337
|
+
if (this.pendingGetFormDataTimeout) {
|
|
338
|
+
clearTimeout(this.pendingGetFormDataTimeout);
|
|
339
|
+
this.pendingGetFormDataTimeout = null;
|
|
340
|
+
}
|
|
341
|
+
this.props.getFormSubscriptionData(this.getFormData());
|
|
342
|
+
this.setState({ pendingGetFormData: false, startValidation: false });
|
|
343
|
+
}
|
|
344
|
+
});
|
|
321
345
|
}
|
|
322
346
|
|
|
323
347
|
getFormData(e, value) {
|
|
@@ -923,6 +947,14 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
923
947
|
this.setState({startValidation: false});
|
|
924
948
|
}
|
|
925
949
|
saveFormData() {
|
|
950
|
+
// In library mode: FormBuilder calls onSubmit only after liquid validation succeeds.
|
|
951
|
+
if (!this.props.isFullMode) {
|
|
952
|
+
if (this.state.pendingGetFormData && this.props.getFormSubscriptionData) {
|
|
953
|
+
this.props.getFormSubscriptionData(this.getFormData());
|
|
954
|
+
this.setState({ pendingGetFormData: false, startValidation: false });
|
|
955
|
+
}
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
926
958
|
//Logic to save in db etc
|
|
927
959
|
//saveFormData gets called only when validation result is true
|
|
928
960
|
|
|
@@ -1059,6 +1091,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1059
1091
|
onPreviewContentClicked={this.props.onPreviewContentClicked}
|
|
1060
1092
|
onTestContentClicked={this.props.onTestContentClicked}
|
|
1061
1093
|
eventContextTags={this.props?.eventContextTags}
|
|
1094
|
+
waitEventContextTags={this.props?.waitEventContextTags}
|
|
1062
1095
|
messageDetails={this.props?.messageDetails}
|
|
1063
1096
|
/>
|
|
1064
1097
|
</CapColumn>
|
|
@@ -1099,6 +1132,7 @@ Edit.propTypes = {
|
|
|
1099
1132
|
injectedTags: PropTypes.object,
|
|
1100
1133
|
selectedOfferDetails: PropTypes.array,
|
|
1101
1134
|
eventContextTags: PropTypes.array,
|
|
1135
|
+
waitEventContextTags: PropTypes.object,
|
|
1102
1136
|
messageDetails: PropTypes.object,
|
|
1103
1137
|
showTestAndPreviewSlidebox: PropTypes.bool,
|
|
1104
1138
|
handleTestAndPreview: PropTypes.func,
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import isEmpty from 'lodash/isEmpty';
|
|
2
|
-
import
|
|
2
|
+
import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
|
|
3
3
|
import messages from './Create/messages';
|
|
4
4
|
export function showError() {
|
|
5
5
|
const {intl} = this.props;
|
|
6
6
|
const {errorData} = this.state;
|
|
7
7
|
const errorMessage = {key: 'validation-error', message: intl.formatMessage(messages.validationError)};
|
|
8
8
|
if (!isEmpty(this.state.formData) && !this.state.isFormValid) {
|
|
9
|
-
const
|
|
9
|
+
const err0 = errorData[0] || {};
|
|
10
|
+
const isSmsInvalid = Object.values(err0).includes(true);
|
|
10
11
|
if (isSmsInvalid) {
|
|
11
|
-
const invalidTags = errorData[0]['invalid-tags'];
|
|
12
|
-
if (!isEmpty(invalidTags)) {
|
|
13
|
-
errorMessage.description = `${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
|
|
14
|
-
}
|
|
15
12
|
CapNotification.error(errorMessage);
|
|
16
13
|
}
|
|
17
14
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared SMS FormBuilder formData helpers for Sms/Create (and any embedded host).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {object} formData FormBuilder state (same shape as Sms/Create `this.state.formData`)
|
|
7
|
+
* @param {number} currentTab 1-based tab index
|
|
8
|
+
* @returns {string} Raw message body or ''
|
|
9
|
+
*/
|
|
10
|
+
export function getSmsMessageFromFormData(formData, currentTab) {
|
|
11
|
+
if (formData == null || typeof formData !== 'object') {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
const tab = currentTab != null && currentTab > 0 ? currentTab : 1;
|
|
15
|
+
const currentTabData = formData[tab - 1];
|
|
16
|
+
if (currentTabData && typeof currentTabData === 'object') {
|
|
17
|
+
const versionedKey = tab > 1 ? `sms-editor${tab}` : 'sms-editor';
|
|
18
|
+
if (Object.prototype.hasOwnProperty.call(currentTabData, versionedKey)) {
|
|
19
|
+
const v = currentTabData[versionedKey];
|
|
20
|
+
// Key exists — commit to this version's value rather than falling through to base.
|
|
21
|
+
// Treat null/undefined as empty so a cleared version correctly reports as empty.
|
|
22
|
+
return (v != null && v !== '') ? String(v) : '';
|
|
23
|
+
}
|
|
24
|
+
if (currentTabData['sms-editor'] != null) {
|
|
25
|
+
return String(currentTabData['sms-editor']);
|
|
26
|
+
}
|
|
27
|
+
const activeTab = currentTabData.activeTab || 'base';
|
|
28
|
+
if (currentTabData[activeTab]?.['sms-editor'] != null) {
|
|
29
|
+
return String(currentTabData[activeTab]['sms-editor']);
|
|
30
|
+
}
|
|
31
|
+
if (currentTabData.base?.['sms-editor'] != null) {
|
|
32
|
+
return String(currentTabData.base['sms-editor']);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const rootBase = formData.base;
|
|
36
|
+
if (rootBase && typeof rootBase === 'object' && rootBase['sms-editor'] != null) {
|
|
37
|
+
return String(rootBase['sms-editor']);
|
|
38
|
+
}
|
|
39
|
+
return '';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {number} [tabCount] Total number of versions/tabs. When >1 all versions are checked.
|
|
44
|
+
* @returns {{ isTemplateNameEmpty: boolean, isMessageEmpty: boolean }}
|
|
45
|
+
*/
|
|
46
|
+
export function getSmsEmbeddedFooterValidity(formData, tabCount) {
|
|
47
|
+
const rawName = formData?.['template-name'];
|
|
48
|
+
const name = rawName != null && rawName !== '' ? String(rawName).trim() : '';
|
|
49
|
+
|
|
50
|
+
// Check ALL versions: if any version's message is empty, Done should be disabled.
|
|
51
|
+
// With a single version this is equivalent to the previous single-tab check.
|
|
52
|
+
const count = tabCount != null && tabCount > 1 ? tabCount : 1;
|
|
53
|
+
let isMessageEmpty = false;
|
|
54
|
+
for (let i = 1; i <= count; i++) {
|
|
55
|
+
const content = getSmsMessageFromFormData(formData, i);
|
|
56
|
+
const msg = content != null && content !== '' ? String(content).trim() : '';
|
|
57
|
+
if (!msg) {
|
|
58
|
+
isMessageEmpty = true;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
isTemplateNameEmpty: !name,
|
|
65
|
+
isMessageEmpty,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
|
|
2
|
+
import { showError } from '../commonMethods';
|
|
3
|
+
|
|
4
|
+
jest.mock('@capillarytech/cap-ui-library/CapNotification', () => ({
|
|
5
|
+
error: jest.fn(),
|
|
6
|
+
}));
|
|
7
|
+
|
|
8
|
+
jest.mock('../Create/messages', () => ({
|
|
9
|
+
__esModule: true,
|
|
10
|
+
default: {
|
|
11
|
+
validationError: { defaultMessage: 'Validation error' },
|
|
12
|
+
},
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
describe('Sms commonMethods', () => {
|
|
16
|
+
describe('showError', () => {
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
jest.clearAllMocks();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should call CapNotification.error when formData is not empty, isFormValid is false, and errorData has at least one true value', () => {
|
|
22
|
+
const context = {
|
|
23
|
+
props: {
|
|
24
|
+
intl: { formatMessage: jest.fn((msg) => msg.defaultMessage || 'Validation error') },
|
|
25
|
+
},
|
|
26
|
+
state: {
|
|
27
|
+
formData: { message: 'test' },
|
|
28
|
+
isFormValid: false,
|
|
29
|
+
errorData: [{ message: true }],
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
showError.call(context);
|
|
33
|
+
expect(CapNotification.error).toHaveBeenCalledWith({
|
|
34
|
+
key: 'validation-error',
|
|
35
|
+
message: 'Validation error',
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should not call CapNotification.error when formData is empty', () => {
|
|
40
|
+
const context = {
|
|
41
|
+
props: { intl: { formatMessage: jest.fn() } },
|
|
42
|
+
state: {
|
|
43
|
+
formData: {},
|
|
44
|
+
isFormValid: false,
|
|
45
|
+
errorData: [{ message: true }],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
showError.call(context);
|
|
49
|
+
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should not call CapNotification.error when isFormValid is true', () => {
|
|
53
|
+
const context = {
|
|
54
|
+
props: { intl: { formatMessage: jest.fn() } },
|
|
55
|
+
state: {
|
|
56
|
+
formData: { message: 'test' },
|
|
57
|
+
isFormValid: true,
|
|
58
|
+
errorData: [{ message: true }],
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
showError.call(context);
|
|
62
|
+
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should not call CapNotification.error when no errorData entry has a true value', () => {
|
|
66
|
+
const context = {
|
|
67
|
+
props: { intl: { formatMessage: jest.fn() } },
|
|
68
|
+
state: {
|
|
69
|
+
formData: { message: 'test' },
|
|
70
|
+
isFormValid: false,
|
|
71
|
+
errorData: [{ message: false, title: false }],
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
showError.call(context);
|
|
75
|
+
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should not call CapNotification.error when errorData is empty', () => {
|
|
79
|
+
const context = {
|
|
80
|
+
props: { intl: { formatMessage: jest.fn() } },
|
|
81
|
+
state: {
|
|
82
|
+
formData: { message: 'test' },
|
|
83
|
+
isFormValid: false,
|
|
84
|
+
errorData: [],
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
showError.call(context);
|
|
88
|
+
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should not call CapNotification.error when errorData[0] is undefined', () => {
|
|
92
|
+
const context = {
|
|
93
|
+
props: { intl: { formatMessage: jest.fn() } },
|
|
94
|
+
state: {
|
|
95
|
+
formData: { message: 'test' },
|
|
96
|
+
isFormValid: false,
|
|
97
|
+
errorData: [],
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
showError.call(context);
|
|
101
|
+
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should call CapNotification.error when errorData[0] has multiple keys and one is true', () => {
|
|
105
|
+
const context = {
|
|
106
|
+
props: {
|
|
107
|
+
intl: { formatMessage: jest.fn((msg) => msg.defaultMessage || 'Validation error') },
|
|
108
|
+
},
|
|
109
|
+
state: {
|
|
110
|
+
formData: { message: 'hello' },
|
|
111
|
+
isFormValid: false,
|
|
112
|
+
errorData: [{ message: false, title: true }],
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
showError.call(context);
|
|
116
|
+
expect(CapNotification.error).toHaveBeenCalledWith({
|
|
117
|
+
key: 'validation-error',
|
|
118
|
+
message: 'Validation error',
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getSmsMessageFromFormData,
|
|
3
|
+
getSmsEmbeddedFooterValidity,
|
|
4
|
+
} from '../smsFormDataHelpers';
|
|
5
|
+
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// getSmsMessageFromFormData
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
describe('getSmsMessageFromFormData', () => {
|
|
11
|
+
describe('null / invalid formData guard', () => {
|
|
12
|
+
it('returns empty string when formData is null', () => {
|
|
13
|
+
expect(getSmsMessageFromFormData(null, 1)).toBe('');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('returns empty string when formData is undefined', () => {
|
|
17
|
+
expect(getSmsMessageFromFormData(undefined, 1)).toBe('');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('returns empty string when formData is a string (not an object)', () => {
|
|
21
|
+
expect(getSmsMessageFromFormData('bad', 1)).toBe('');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('returns empty string when formData is a number', () => {
|
|
25
|
+
expect(getSmsMessageFromFormData(42, 1)).toBe('');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('currentTab normalisation', () => {
|
|
30
|
+
it('defaults to tab 1 when currentTab is null', () => {
|
|
31
|
+
const formData = { 0: { 'sms-editor': 'hello' } };
|
|
32
|
+
expect(getSmsMessageFromFormData(formData, null)).toBe('hello');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('defaults to tab 1 when currentTab is undefined', () => {
|
|
36
|
+
const formData = { 0: { 'sms-editor': 'hello' } };
|
|
37
|
+
expect(getSmsMessageFromFormData(formData, undefined)).toBe('hello');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('defaults to tab 1 when currentTab is 0', () => {
|
|
41
|
+
const formData = { 0: { 'sms-editor': 'hello' } };
|
|
42
|
+
expect(getSmsMessageFromFormData(formData, 0)).toBe('hello');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('defaults to tab 1 when currentTab is negative', () => {
|
|
46
|
+
const formData = { 0: { 'sms-editor': 'hello' } };
|
|
47
|
+
expect(getSmsMessageFromFormData(formData, -5)).toBe('hello');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('versioned key lookup', () => {
|
|
52
|
+
it('uses "sms-editor" key for tab 1', () => {
|
|
53
|
+
const formData = { 0: { 'sms-editor': 'tab1 msg' } };
|
|
54
|
+
expect(getSmsMessageFromFormData(formData, 1)).toBe('tab1 msg');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('uses "sms-editor2" versioned key for tab 2', () => {
|
|
58
|
+
const formData = { 1: { 'sms-editor2': 'tab2 msg', 'sms-editor': 'fallback' } };
|
|
59
|
+
expect(getSmsMessageFromFormData(formData, 2)).toBe('tab2 msg');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('uses "sms-editor3" versioned key for tab 3', () => {
|
|
63
|
+
const formData = { 2: { 'sms-editor3': 'tab3 msg' } };
|
|
64
|
+
expect(getSmsMessageFromFormData(formData, 3)).toBe('tab3 msg');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('returns empty string when versioned key exists but is null (cleared version)', () => {
|
|
68
|
+
const formData = { 1: { 'sms-editor2': null } };
|
|
69
|
+
expect(getSmsMessageFromFormData(formData, 2)).toBe('');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('returns empty string when versioned key exists but is empty string', () => {
|
|
73
|
+
const formData = { 1: { 'sms-editor2': '' } };
|
|
74
|
+
expect(getSmsMessageFromFormData(formData, 2)).toBe('');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('coerces a numeric value in versioned key to string', () => {
|
|
78
|
+
const formData = { 1: { 'sms-editor2': 12345 } };
|
|
79
|
+
expect(getSmsMessageFromFormData(formData, 2)).toBe('12345');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('"sms-editor" flat key fallback (versioned key absent)', () => {
|
|
84
|
+
it('falls back to "sms-editor" when versioned key is absent for tab 2', () => {
|
|
85
|
+
const formData = { 1: { 'sms-editor': 'flat fallback' } };
|
|
86
|
+
expect(getSmsMessageFromFormData(formData, 2)).toBe('flat fallback');
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('activeTab nested fallback', () => {
|
|
91
|
+
it('falls back to activeTab["sms-editor"] when neither versioned key nor flat "sms-editor" is present', () => {
|
|
92
|
+
// The versioned key must be absent entirely for the activeTab fallback to be reached.
|
|
93
|
+
// (If 'sms-editor' exists but is null, the function commits to '' without falling through.)
|
|
94
|
+
const formData = {
|
|
95
|
+
0: {
|
|
96
|
+
activeTab: 'variant1',
|
|
97
|
+
variant1: { 'sms-editor': 'variant msg' },
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
expect(getSmsMessageFromFormData(formData, 1)).toBe('variant msg');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('falls back to base["sms-editor"] when activeTab entry lacks "sms-editor" and flat key is absent', () => {
|
|
104
|
+
const formData = {
|
|
105
|
+
0: {
|
|
106
|
+
activeTab: 'variant1',
|
|
107
|
+
variant1: {},
|
|
108
|
+
base: { 'sms-editor': 'base msg' },
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
expect(getSmsMessageFromFormData(formData, 1)).toBe('base msg');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('defaults activeTab to "base" when activeTab prop is not set and flat key is absent', () => {
|
|
115
|
+
const formData = {
|
|
116
|
+
0: {
|
|
117
|
+
base: { 'sms-editor': 'default base msg' },
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
expect(getSmsMessageFromFormData(formData, 1)).toBe('default base msg');
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('root formData.base fallback', () => {
|
|
125
|
+
it('falls back to formData.base["sms-editor"] when tab slot is missing', () => {
|
|
126
|
+
const formData = {
|
|
127
|
+
base: { 'sms-editor': 'root base msg' },
|
|
128
|
+
};
|
|
129
|
+
expect(getSmsMessageFromFormData(formData, 1)).toBe('root base msg');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('returns empty string when even root base has no "sms-editor"', () => {
|
|
133
|
+
const formData = { base: {} };
|
|
134
|
+
expect(getSmsMessageFromFormData(formData, 1)).toBe('');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('returns empty string when formData has no relevant keys at all', () => {
|
|
138
|
+
expect(getSmsMessageFromFormData({}, 1)).toBe('');
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
// getSmsEmbeddedFooterValidity
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
|
|
147
|
+
describe('getSmsEmbeddedFooterValidity', () => {
|
|
148
|
+
describe('isTemplateNameEmpty', () => {
|
|
149
|
+
it('is true when template-name is absent', () => {
|
|
150
|
+
const formData = { 0: { 'sms-editor': 'msg' } };
|
|
151
|
+
const { isTemplateNameEmpty } = getSmsEmbeddedFooterValidity(formData, 1);
|
|
152
|
+
expect(isTemplateNameEmpty).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('is true when template-name is empty string', () => {
|
|
156
|
+
const formData = { 'template-name': '', 0: { 'sms-editor': 'msg' } };
|
|
157
|
+
const { isTemplateNameEmpty } = getSmsEmbeddedFooterValidity(formData, 1);
|
|
158
|
+
expect(isTemplateNameEmpty).toBe(true);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('is true when template-name is whitespace only', () => {
|
|
162
|
+
const formData = { 'template-name': ' ', 0: { 'sms-editor': 'msg' } };
|
|
163
|
+
const { isTemplateNameEmpty } = getSmsEmbeddedFooterValidity(formData, 1);
|
|
164
|
+
expect(isTemplateNameEmpty).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('is false when template-name is a non-empty string', () => {
|
|
168
|
+
const formData = { 'template-name': 'My Template', 0: { 'sms-editor': 'msg' } };
|
|
169
|
+
const { isTemplateNameEmpty } = getSmsEmbeddedFooterValidity(formData, 1);
|
|
170
|
+
expect(isTemplateNameEmpty).toBe(false);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe('isMessageEmpty — single tab', () => {
|
|
175
|
+
it('is true when message is empty string', () => {
|
|
176
|
+
const formData = { 'template-name': 'T', 0: { 'sms-editor': '' } };
|
|
177
|
+
const { isMessageEmpty } = getSmsEmbeddedFooterValidity(formData, 1);
|
|
178
|
+
expect(isMessageEmpty).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('is true when message is whitespace only', () => {
|
|
182
|
+
const formData = { 'template-name': 'T', 0: { 'sms-editor': ' ' } };
|
|
183
|
+
const { isMessageEmpty } = getSmsEmbeddedFooterValidity(formData, 1);
|
|
184
|
+
expect(isMessageEmpty).toBe(true);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('is true when no sms-editor key at all', () => {
|
|
188
|
+
const formData = { 'template-name': 'T', 0: {} };
|
|
189
|
+
const { isMessageEmpty } = getSmsEmbeddedFooterValidity(formData, 1);
|
|
190
|
+
expect(isMessageEmpty).toBe(true);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('is false when message is non-empty', () => {
|
|
194
|
+
const formData = { 'template-name': 'T', 0: { 'sms-editor': 'Hello world' } };
|
|
195
|
+
const { isMessageEmpty } = getSmsEmbeddedFooterValidity(formData, 1);
|
|
196
|
+
expect(isMessageEmpty).toBe(false);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe('isMessageEmpty — multiple tabs', () => {
|
|
201
|
+
it('is false when all tabs have non-empty messages', () => {
|
|
202
|
+
const formData = {
|
|
203
|
+
'template-name': 'T',
|
|
204
|
+
0: { 'sms-editor': 'Tab 1 message' },
|
|
205
|
+
1: { 'sms-editor2': 'Tab 2 message' },
|
|
206
|
+
2: { 'sms-editor3': 'Tab 3 message' },
|
|
207
|
+
};
|
|
208
|
+
const { isMessageEmpty } = getSmsEmbeddedFooterValidity(formData, 3);
|
|
209
|
+
expect(isMessageEmpty).toBe(false);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('is true when the second tab has an empty message', () => {
|
|
213
|
+
const formData = {
|
|
214
|
+
'template-name': 'T',
|
|
215
|
+
0: { 'sms-editor': 'Tab 1 message' },
|
|
216
|
+
1: { 'sms-editor2': '' },
|
|
217
|
+
};
|
|
218
|
+
const { isMessageEmpty } = getSmsEmbeddedFooterValidity(formData, 2);
|
|
219
|
+
expect(isMessageEmpty).toBe(true);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('is true when the third tab has no message', () => {
|
|
223
|
+
const formData = {
|
|
224
|
+
'template-name': 'T',
|
|
225
|
+
0: { 'sms-editor': 'msg1' },
|
|
226
|
+
1: { 'sms-editor2': 'msg2' },
|
|
227
|
+
2: {},
|
|
228
|
+
};
|
|
229
|
+
const { isMessageEmpty } = getSmsEmbeddedFooterValidity(formData, 3);
|
|
230
|
+
expect(isMessageEmpty).toBe(true);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('treats tabCount=1 as single-tab check even when not explicitly provided', () => {
|
|
234
|
+
const formData = { 'template-name': 'T', 0: { 'sms-editor': 'msg' } };
|
|
235
|
+
const { isMessageEmpty } = getSmsEmbeddedFooterValidity(formData);
|
|
236
|
+
expect(isMessageEmpty).toBe(false);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe('both fields together', () => {
|
|
241
|
+
it('returns both empty when template name absent and message empty', () => {
|
|
242
|
+
const formData = { 0: { 'sms-editor': '' } };
|
|
243
|
+
const result = getSmsEmbeddedFooterValidity(formData, 1);
|
|
244
|
+
expect(result).toEqual({ isTemplateNameEmpty: true, isMessageEmpty: true });
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('returns both non-empty when template name and message are present', () => {
|
|
248
|
+
const formData = { 'template-name': 'My Template', 0: { 'sms-editor': 'Hello!' } };
|
|
249
|
+
const result = getSmsEmbeddedFooterValidity(formData, 1);
|
|
250
|
+
expect(result).toEqual({ isTemplateNameEmpty: false, isMessageEmpty: false });
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
});
|
|
@@ -70,6 +70,7 @@ export const SmsTraiCreate = (props) => {
|
|
|
70
70
|
onCreateComplete,
|
|
71
71
|
isFullMode,
|
|
72
72
|
onShowTemplates,
|
|
73
|
+
embeddedSmsFallback,
|
|
73
74
|
traiSms: {
|
|
74
75
|
duplicateDetails = {},
|
|
75
76
|
duplicateDetailsError = '',
|
|
@@ -659,9 +660,11 @@ export const SmsTraiCreate = (props) => {
|
|
|
659
660
|
|
|
660
661
|
const createCallback = ({ errorMessage }) => {
|
|
661
662
|
if (!errorMessage) {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
663
|
+
if (!embeddedSmsFallback) {
|
|
664
|
+
CapNotification.success({
|
|
665
|
+
message: formatMessage(messages.smsCreateNotification),
|
|
666
|
+
});
|
|
667
|
+
}
|
|
665
668
|
actions.clearCreateResponse();
|
|
666
669
|
} else {
|
|
667
670
|
CapNotification.error({
|
|
@@ -741,7 +744,9 @@ export const SmsTraiCreate = (props) => {
|
|
|
741
744
|
{ templates: savedData },
|
|
742
745
|
(resp, errorMessage) => {
|
|
743
746
|
createCallback({ errorMessage });
|
|
744
|
-
if (
|
|
747
|
+
if (embeddedSmsFallback) {
|
|
748
|
+
if (!errorMessage) onCreateComplete(savedData[0]);
|
|
749
|
+
} else if (isFullMode) {
|
|
745
750
|
onCreateComplete();
|
|
746
751
|
} else {
|
|
747
752
|
onShowTemplates();
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
export const CHARLIMIT = 40;
|
|
8
|
+
/** Display / soft cap label for DLT SMS body length (matches product UI). */
|
|
9
|
+
export const SMS_TRAI_CONTENT_MAX_LENGTH = 1024;
|
|
8
10
|
export const SMS = 'SMS';
|
|
9
11
|
export const SMS_TRAI_VAR = '{#var#}';
|
|
10
12
|
export const TAG = 'TAG';
|