@capillarytech/creatives-library 8.0.263 → 8.0.265
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/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/constants/unified.js +1 -3
- package/initialReducer.js +0 -2
- package/package.json +1 -1
- package/services/api.js +0 -15
- package/services/tests/api.test.js +0 -34
- package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +35 -17
- package/tests/integration/TemplateCreation/api-response.js +1 -31
- package/tests/integration/TemplateCreation/msw-handler.js +0 -2
- package/utils/common.js +0 -11
- package/utils/commonUtils.js +5 -28
- package/utils/tests/commonUtil.test.js +0 -224
- package/utils/tests/transformerUtils.test.js +0 -297
- package/utils/transformTemplateConfig.js +10 -0
- package/utils/transformerUtils.js +0 -40
- package/v2Components/CapDeviceContent/index.js +56 -61
- package/v2Components/CapImageUpload/constants.js +0 -2
- package/v2Components/CapImageUpload/index.js +16 -65
- package/v2Components/CapImageUpload/index.scss +1 -4
- package/v2Components/CapImageUpload/messages.js +1 -5
- package/v2Components/CapTagList/index.js +1 -6
- package/v2Components/CapTagListWithInput/index.js +1 -5
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +0 -5
- package/v2Components/ErrorInfoNote/index.js +72 -402
- package/v2Components/ErrorInfoNote/messages.js +6 -32
- package/v2Components/ErrorInfoNote/style.scss +6 -278
- package/v2Components/FormBuilder/tests/index.test.js +4 -13
- package/v2Components/HtmlEditor/HTMLEditor.js +99 -418
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +133 -1882
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +16 -27
- package/v2Components/HtmlEditor/_htmlEditor.scss +45 -108
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -0
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +102 -23
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +140 -148
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -2
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +1 -9
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +6 -31
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +0 -22
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +7 -4
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +45 -35
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +3 -1
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +6 -7
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +10 -7
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +43 -22
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +152 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/_validationErrorDisplay.scss +0 -18
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +31 -36
- package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +34 -46
- package/v2Components/HtmlEditor/components/ValidationPanel/index.js +46 -52
- package/v2Components/HtmlEditor/constants.js +20 -45
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +16 -373
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +16 -351
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +2 -5
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +146 -88
- package/v2Components/HtmlEditor/hooks/useValidation.js +56 -213
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +94 -102
- package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +45 -214
- package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +0 -134
- package/v2Components/HtmlEditor/utils/contentSanitizer.js +41 -40
- package/v2Components/HtmlEditor/utils/htmlValidator.js +72 -71
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +124 -158
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +25 -23
- package/v2Components/HtmlEditor/utils/validationAdapter.js +41 -66
- package/v2Components/MobilePushPreviewV2/index.js +7 -33
- package/v2Components/TemplatePreview/_templatePreview.scss +24 -55
- package/v2Components/TemplatePreview/index.js +32 -47
- package/v2Components/TemplatePreview/messages.js +0 -4
- package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +0 -1
- package/v2Containers/App/constants.js +0 -5
- package/v2Containers/BeeEditor/index.js +90 -172
- package/v2Containers/CreativesContainer/SlideBoxContent.js +53 -184
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +13 -163
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +1 -3
- package/v2Containers/CreativesContainer/constants.js +0 -4
- package/v2Containers/CreativesContainer/index.js +46 -408
- package/v2Containers/CreativesContainer/messages.js +0 -12
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +0 -210
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +2 -11
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +50 -342
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +0 -103
- package/v2Containers/Email/actions.js +0 -7
- package/v2Containers/Email/constants.js +1 -5
- package/v2Containers/Email/index.js +36 -237
- package/v2Containers/Email/messages.js +0 -32
- package/v2Containers/Email/reducer.js +1 -12
- package/v2Containers/Email/sagas.js +7 -61
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +0 -2
- package/v2Containers/Email/tests/reducer.test.js +0 -46
- package/v2Containers/Email/tests/sagas.test.js +29 -320
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +21 -211
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +74 -40
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +67 -2
- package/v2Containers/EmailWrapper/constants.js +0 -2
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +77 -629
- package/v2Containers/EmailWrapper/index.js +23 -103
- package/v2Containers/EmailWrapper/messages.js +1 -65
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +214 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +77 -594
- package/v2Containers/InApp/actions.js +0 -7
- package/v2Containers/InApp/constants.js +4 -20
- package/v2Containers/InApp/index.js +359 -802
- package/v2Containers/InApp/index.scss +3 -4
- package/v2Containers/InApp/messages.js +3 -7
- package/v2Containers/InApp/reducer.js +3 -21
- package/v2Containers/InApp/sagas.js +9 -29
- package/v2Containers/InApp/selectors.js +5 -25
- package/v2Containers/InApp/tests/index.test.js +50 -154
- package/v2Containers/InApp/tests/reducer.test.js +0 -34
- package/v2Containers/InApp/tests/sagas.test.js +9 -61
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +0 -3
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +0 -2
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +0 -2
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +0 -9
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +0 -12
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +0 -4
- package/v2Containers/TagList/index.js +19 -62
- package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
- package/v2Containers/Templates/_templates.scss +1 -265
- package/v2Containers/Templates/actions.js +1 -2
- package/v2Containers/Templates/constants.js +0 -1
- package/v2Containers/Templates/index.js +38 -363
- package/v2Containers/Templates/messages.js +0 -28
- package/v2Containers/Templates/reducer.js +0 -2
- package/v2Containers/Templates/tests/index.test.js +0 -10
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +2 -4
- package/v2Containers/TemplatesV2/index.js +7 -15
- package/v2Containers/TemplatesV2/messages.js +0 -4
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +0 -34
- package/utils/imageUrlUpload.js +0 -141
- package/v2Components/CapImageUrlUpload/constants.js +0 -26
- package/v2Components/CapImageUrlUpload/index.js +0 -365
- package/v2Components/CapImageUrlUpload/index.scss +0 -35
- package/v2Components/CapImageUrlUpload/messages.js +0 -47
- package/v2Components/ErrorInfoNote/constants.js +0 -1
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +0 -870
- package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +0 -6
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +0 -281
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +0 -295
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +0 -51
- package/v2Components/HtmlEditor/utils/validationConstants.js +0 -38
- package/v2Components/MobilePushPreviewV2/constants.js +0 -6
- package/v2Containers/BeePopupEditor/_beePopupEditor.scss +0 -14
- package/v2Containers/BeePopupEditor/constants.js +0 -10
- package/v2Containers/BeePopupEditor/index.js +0 -194
- package/v2Containers/BeePopupEditor/tests/index.test.js +0 -627
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +0 -1246
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +0 -2472
- package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +0 -520
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +0 -956
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +0 -376
- package/v2Containers/InApp/__tests__/sagas.test.js +0 -363
- package/v2Containers/InApp/tests/selectors.test.js +0 -612
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +0 -151
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +0 -267
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +0 -23
- package/v2Containers/InAppWrapper/constants.js +0 -16
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +0 -473
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +0 -198
- package/v2Containers/InAppWrapper/index.js +0 -148
- package/v2Containers/InAppWrapper/messages.js +0 -49
- package/v2Containers/InappAdvance/index.js +0 -1099
- package/v2Containers/InappAdvance/index.scss +0 -10
- package/v2Containers/InappAdvance/tests/index.test.js +0 -448
- package/v2Containers/WebPush/Create/components/BrandIconSection.js +0 -108
- package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -172
- package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
- package/v2Containers/WebPush/Create/components/ButtonList.js +0 -145
- package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +0 -164
- package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +0 -463
- package/v2Containers/WebPush/Create/components/FormActions.js +0 -54
- package/v2Containers/WebPush/Create/components/FormActions.test.js +0 -163
- package/v2Containers/WebPush/Create/components/MediaSection.js +0 -142
- package/v2Containers/WebPush/Create/components/MediaSection.test.js +0 -341
- package/v2Containers/WebPush/Create/components/MessageSection.js +0 -103
- package/v2Containers/WebPush/Create/components/MessageSection.test.js +0 -268
- package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +0 -87
- package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +0 -210
- package/v2Containers/WebPush/Create/components/TemplateNameSection.js +0 -54
- package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +0 -143
- package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +0 -86
- package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +0 -16
- package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +0 -41
- package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +0 -54
- package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +0 -37
- package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +0 -21
- package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
- package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
- package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
- package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -633
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
- package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -78
- package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +0 -138
- package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +0 -406
- package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +0 -30
- package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +0 -151
- package/v2Containers/WebPush/Create/hooks/useImageUpload.js +0 -104
- package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +0 -538
- package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -122
- package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -633
- package/v2Containers/WebPush/Create/index.js +0 -1148
- package/v2Containers/WebPush/Create/index.scss +0 -134
- package/v2Containers/WebPush/Create/messages.js +0 -211
- package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -228
- package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -294
- package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -90
- package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -305
- package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -25
- package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -155
- package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
- package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
- package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +0 -9
- package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +0 -9
- package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
- package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
- package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
- package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
- package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +0 -9
- package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +0 -9
- package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
- package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
- package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +0 -9
- package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +0 -9
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -51
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -145
- package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
- package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -68
- package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -61
- package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -99
- package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -733
- package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +0 -571
- package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -85
- package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +0 -81
- package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -50
- package/v2Containers/WebPush/Create/preview/constants.js +0 -637
- package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -79
- package/v2Containers/WebPush/Create/preview/preview.scss +0 -358
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -370
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -47
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
- package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
- package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -207
- package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -153
- package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
- package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -101
- package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -229
- package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
- package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1081
- package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
- package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -1327
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -131
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -112
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -129
- package/v2Containers/WebPush/Create/utils/payloadBuilder.js +0 -96
- package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +0 -396
- package/v2Containers/WebPush/Create/utils/previewUtils.js +0 -89
- package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -115
- package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
- package/v2Containers/WebPush/Create/utils/validation.js +0 -75
- package/v2Containers/WebPush/Create/utils/validation.test.js +0 -283
- package/v2Containers/WebPush/actions.js +0 -60
- package/v2Containers/WebPush/constants.js +0 -132
- package/v2Containers/WebPush/index.js +0 -2
- package/v2Containers/WebPush/reducer.js +0 -104
- package/v2Containers/WebPush/sagas.js +0 -119
- package/v2Containers/WebPush/selectors.js +0 -65
- package/v2Containers/WebPush/tests/reducer.test.js +0 -863
- package/v2Containers/WebPush/tests/sagas.test.js +0 -566
- package/v2Containers/WebPush/tests/selectors.test.js +0 -960
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
useState, useEffect, useCallback, useMemo, useRef,
|
|
3
|
-
} from "react";
|
|
1
|
+
import React, { useState, useEffect, useCallback } from "react";
|
|
4
2
|
import isEmpty from 'lodash/isEmpty';
|
|
5
3
|
import get from 'lodash/get';
|
|
6
4
|
import { bindActionCreators } from "redux";
|
|
@@ -9,19 +7,21 @@ import { injectIntl, FormattedMessage } from "react-intl";
|
|
|
9
7
|
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
|
|
10
8
|
import CapHeading from "@capillarytech/cap-ui-library/CapHeading";
|
|
11
9
|
import CapSpin from "@capillarytech/cap-ui-library/CapSpin";
|
|
10
|
+
import CapInput from "@capillarytech/cap-ui-library/CapInput";
|
|
12
11
|
import CapRadioGroup from "@capillarytech/cap-ui-library/CapRadioGroup";
|
|
13
12
|
import CapRow from "@capillarytech/cap-ui-library/CapRow";
|
|
14
13
|
import CapColumn from "@capillarytech/cap-ui-library/CapColumn";
|
|
15
14
|
import CapButton from "@capillarytech/cap-ui-library/CapButton";
|
|
15
|
+
import CapTab from "@capillarytech/cap-ui-library/CapTab";
|
|
16
16
|
import CapNotification from "@capillarytech/cap-ui-library/CapNotification";
|
|
17
|
-
import { makeSelectInApp, makeSelectAccount
|
|
17
|
+
import { makeSelectInApp, makeSelectAccount } from "./selectors";
|
|
18
18
|
import * as globalActions from '../Cap/actions';
|
|
19
19
|
import {
|
|
20
20
|
isLoadingMetaEntities,
|
|
21
21
|
makeSelectMetaEntities,
|
|
22
22
|
setInjectedTags,
|
|
23
23
|
selectCurrentOrgDetails,
|
|
24
|
-
selectLiquidStateDetails
|
|
24
|
+
selectLiquidStateDetails
|
|
25
25
|
} from "../Cap/selectors";
|
|
26
26
|
import * as inAppActions from "./actions";
|
|
27
27
|
import './index.scss';
|
|
@@ -40,7 +40,6 @@ import {
|
|
|
40
40
|
ANDROID,
|
|
41
41
|
BIG_PICTURE,
|
|
42
42
|
BIG_TEXT,
|
|
43
|
-
BIG_HTML,
|
|
44
43
|
DEEP_LINK,
|
|
45
44
|
DEVICE_SUPPORTED,
|
|
46
45
|
INAPP_BUTTON_TYPES,
|
|
@@ -49,22 +48,19 @@ import {
|
|
|
49
48
|
INITIAL_CTA_DATA,
|
|
50
49
|
IOS,
|
|
51
50
|
LAYOUT_RADIO_OPTIONS,
|
|
52
|
-
|
|
51
|
+
AI_CONTENT_BOT_DISABLED,
|
|
53
52
|
} from "./constants";
|
|
54
53
|
import { INAPP, SMS } from "../CreativesContainer/constants";
|
|
55
54
|
import {
|
|
56
55
|
ALL, TAG, EMBEDDED, DEFAULT, FULL, LIBRARY,
|
|
57
56
|
} from "../Whatsapp/constants";
|
|
57
|
+
import CapDeviceContent from "../../v2Components/CapDeviceContent";
|
|
58
58
|
import { getCdnUrl } from "../../utils/cdnTransformation";
|
|
59
59
|
import { getCtaObject, hasAnyErrors, getSingleTab } from "./utils";
|
|
60
60
|
import { validateInAppContent } from "../../utils/commonUtils";
|
|
61
|
+
import ErrorInfoNote from "../../v2Components/ErrorInfoNote";
|
|
61
62
|
import { hasLiquidSupportFeature } from "../../utils/common";
|
|
62
63
|
import formBuilderMessages from "../../v2Components/FormBuilder/messages";
|
|
63
|
-
import HTMLEditor from "../../v2Components/HtmlEditor";
|
|
64
|
-
import { HTML_EDITOR_VARIANTS } from "../../v2Components/HtmlEditor/constants";
|
|
65
|
-
import { INAPP_EDITOR_TYPES } from "../InAppWrapper/constants";
|
|
66
|
-
import InappAdvanced from "../InappAdvance/index";
|
|
67
|
-
import { ErrorInfoNote } from "../../v2Components/ErrorInfoNote";
|
|
68
64
|
|
|
69
65
|
let editContent = {};
|
|
70
66
|
|
|
@@ -72,14 +68,13 @@ export const InApp = (props) => {
|
|
|
72
68
|
const {
|
|
73
69
|
intl,
|
|
74
70
|
actions,
|
|
75
|
-
globalActions,
|
|
76
71
|
isFullMode,
|
|
77
72
|
onCreateComplete,
|
|
78
73
|
params,
|
|
79
74
|
templateData = {},
|
|
80
|
-
defaultData = {},
|
|
81
75
|
editData = {},
|
|
82
76
|
accountData = {},
|
|
77
|
+
globalActions,
|
|
83
78
|
location,
|
|
84
79
|
getDefaultTags,
|
|
85
80
|
supportedTags,
|
|
@@ -87,19 +82,8 @@ export const InApp = (props) => {
|
|
|
87
82
|
injectedTags,
|
|
88
83
|
getFormData,
|
|
89
84
|
selectedOfferDetails,
|
|
90
|
-
fetchingLiquidValidation,
|
|
91
|
-
templateName,
|
|
92
|
-
getTemplateDetailsInProgress,
|
|
93
|
-
isEditInApp,
|
|
94
|
-
setIsLoadingContent,
|
|
95
|
-
query,
|
|
96
|
-
inAppCreateMode,
|
|
97
|
-
isGetFormData,
|
|
98
|
-
showTemplateName,
|
|
99
|
-
onValidationFail,
|
|
100
|
-
type,
|
|
101
|
-
forwardedTags,
|
|
102
85
|
currentOrgDetails,
|
|
86
|
+
fetchingLiquidValidation,
|
|
103
87
|
// TestAndPreviewSlidebox props
|
|
104
88
|
showTestAndPreviewSlidebox: propsShowTestAndPreviewSlidebox,
|
|
105
89
|
handleTestAndPreview: propsHandleTestAndPreview,
|
|
@@ -112,7 +96,7 @@ export const InApp = (props) => {
|
|
|
112
96
|
const [templateMediaType, setTemplateMediaType] = useState(
|
|
113
97
|
INAPP_MEDIA_TYPES.TEXT
|
|
114
98
|
);
|
|
115
|
-
const [
|
|
99
|
+
const [templateName, setTemplateName] = useState("");
|
|
116
100
|
const [templateLayoutType, setTemplateLayoutType] = useState(
|
|
117
101
|
INAPP_MESSAGE_LAYOUT_TYPES.MODAL
|
|
118
102
|
);
|
|
@@ -126,25 +110,6 @@ export const InApp = (props) => {
|
|
|
126
110
|
const [templateMessageErrorIos, setTemplateMessageErrorIos] = useState(false);
|
|
127
111
|
const [templateTitleErrorAndroid, setTemplateTitleErrorAndroid] = useState(false);
|
|
128
112
|
const [templateTitleErrorIos, setTemplateTitleErrorIos] = useState(false);
|
|
129
|
-
// HTML Editor content state (for INAPP HTML variant)
|
|
130
|
-
// Initialize HTML content from edit data if available
|
|
131
|
-
const getInitialHtmlContent = (device) => {
|
|
132
|
-
const editContent = isFullMode
|
|
133
|
-
? get(editData?.templateDetails?.versions, `base.content`, {})
|
|
134
|
-
: get(templateData?.versions, `base.content`, {});
|
|
135
|
-
const deviceContent = editContent?.[device];
|
|
136
|
-
return deviceContent?.message || "";
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
const [htmlContentAndroid, setHtmlContentAndroid] = useState(() => getInitialHtmlContent("ANDROID"));
|
|
140
|
-
const [htmlContentIos, setHtmlContentIos] = useState(() => getInitialHtmlContent("IOS"));
|
|
141
|
-
// Track if this is an HTML template (type === HTML or style === BIG_HTML)
|
|
142
|
-
const [isHTMLTemplate, setIsHTMLTemplate] = useState(false);
|
|
143
|
-
// Version to force HTMLEditor remount on layout changes
|
|
144
|
-
const [htmlEditorContentVersion, setHtmlEditorContentVersion] = useState(0);
|
|
145
|
-
// Refs to store latest content before layout changes
|
|
146
|
-
const htmlContentAndroidRef = useRef(htmlContentAndroid);
|
|
147
|
-
const htmlContentIosRef = useRef(htmlContentIos);
|
|
148
113
|
const [accountId, setAccountId] = useState("");
|
|
149
114
|
const [accessToken, setAccessToken] = useState("");
|
|
150
115
|
const [accountName, setAccountName] = useState("");
|
|
@@ -253,6 +218,9 @@ export const InApp = (props) => {
|
|
|
253
218
|
}
|
|
254
219
|
}, [propsHandleCloseTestAndPreview]);
|
|
255
220
|
const { accessibleFeatures = [] } = currentOrgDetails || {};
|
|
221
|
+
const isAiContentBotDisabled = accessibleFeatures?.includes(
|
|
222
|
+
AI_CONTENT_BOT_DISABLED
|
|
223
|
+
);
|
|
256
224
|
const [errorMessage, setErrorMessage] = useState({
|
|
257
225
|
STANDARD_ERROR_MSG: {
|
|
258
226
|
ANDROID: [],
|
|
@@ -280,7 +248,7 @@ export const InApp = (props) => {
|
|
|
280
248
|
// DEVICE_SUPPORTED is '1', which indicates if the particular account is supported, and '0' if the devive is not supported
|
|
281
249
|
//get deep link keys in an array
|
|
282
250
|
const deepLinkKeys = Object.values(JSON.parse(deepLinkObj || '{}'));
|
|
283
|
-
const keys = deepLinkKeys?.map((link) => ({
|
|
251
|
+
const keys = deepLinkKeys?.map((link) => ({label: link.name, value: link.link, title: link.link }));
|
|
284
252
|
setPanes(isAndroidSupported ? ANDROID : IOS);
|
|
285
253
|
setDeepLink(keys);
|
|
286
254
|
setAccountId(sourceAccountIdentifier);
|
|
@@ -305,32 +273,6 @@ export const InApp = (props) => {
|
|
|
305
273
|
};
|
|
306
274
|
}, [paramObj.id]);
|
|
307
275
|
|
|
308
|
-
// Initialize template name from defaultData (from wrapper) or editData/templateData
|
|
309
|
-
useEffect(() => {
|
|
310
|
-
const defaultTemplateName = defaultData?.['template-name'] || '';
|
|
311
|
-
if (defaultTemplateName && !isEditFlow) {
|
|
312
|
-
setTempName(defaultTemplateName);
|
|
313
|
-
// Call showTemplateName callback if provided (for header display)
|
|
314
|
-
if (isFullMode && showTemplateName && defaultTemplateName) {
|
|
315
|
-
showTemplateName({
|
|
316
|
-
formData: { 'template-name': defaultTemplateName },
|
|
317
|
-
onFormDataChange: (updatedFormData) => {
|
|
318
|
-
const newName = updatedFormData?.['template-name'] || '';
|
|
319
|
-
setTempName(newName);
|
|
320
|
-
if (showTemplateName) {
|
|
321
|
-
showTemplateName({
|
|
322
|
-
formData: { 'template-name': newName },
|
|
323
|
-
onFormDataChange: (formData) => {
|
|
324
|
-
setTempName(formData?.['template-name'] || '');
|
|
325
|
-
},
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
},
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}, [defaultData?.['template-name'], showTemplateName, isEditFlow]);
|
|
333
|
-
|
|
334
276
|
useEffect(() => {
|
|
335
277
|
const {
|
|
336
278
|
name = "",
|
|
@@ -338,48 +280,16 @@ export const InApp = (props) => {
|
|
|
338
280
|
createdAt = "",
|
|
339
281
|
} = isFullMode ? editData?.templateDetails || {} : templateData || {};
|
|
340
282
|
editContent = get(versions, `base.content`, {});
|
|
341
|
-
|
|
342
|
-
// LIBRARY MODE FIX: Backend stores bodyType as 'POPUP' but UI expects 'MODAL'
|
|
343
|
-
// Convert back to MODAL for display
|
|
344
|
-
if (!isFullMode && editContent) {
|
|
345
|
-
if (editContent.ANDROID?.bodyType === INAPP_MESSAGE_LAYOUT_TYPES.POPUP) {
|
|
346
|
-
editContent.ANDROID.bodyType = INAPP_MESSAGE_LAYOUT_TYPES.MODAL;
|
|
347
|
-
}
|
|
348
|
-
if (editContent.IOS?.bodyType === INAPP_MESSAGE_LAYOUT_TYPES.POPUP) {
|
|
349
|
-
editContent.IOS.bodyType = INAPP_MESSAGE_LAYOUT_TYPES.MODAL;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
283
|
if (editContent && !isEmpty(editContent)) {
|
|
354
284
|
setEditFlow(true);
|
|
355
|
-
|
|
285
|
+
setTemplateName(name);
|
|
356
286
|
setTemplateDate(createdAt);
|
|
357
287
|
setTemplateLayoutType(editContent?.ANDROID?.bodyType);
|
|
358
|
-
// Call showTemplateName callback when in edit mode + full mode to show template name header
|
|
359
|
-
if (showTemplateName && name) {
|
|
360
|
-
showTemplateName({
|
|
361
|
-
formData: { 'template-name': name },
|
|
362
|
-
onFormDataChange: (updatedFormData) => {
|
|
363
|
-
const newName = updatedFormData?.['template-name'] || '';
|
|
364
|
-
setTempName(newName);
|
|
365
|
-
if (showTemplateName) {
|
|
366
|
-
showTemplateName({
|
|
367
|
-
formData: { 'template-name': newName },
|
|
368
|
-
onFormDataChange: (formData) => {
|
|
369
|
-
setTempName(formData?.['template-name'] || '');
|
|
370
|
-
},
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
},
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
288
|
const androidContent = editContent?.ANDROID;
|
|
377
|
-
let androidIsHTML = false;
|
|
378
289
|
if (!isEmpty(androidContent)) {
|
|
379
290
|
const {
|
|
380
291
|
title: androidTitle = '',
|
|
381
292
|
message: androidMessage = '',
|
|
382
|
-
type: androidType = '',
|
|
383
293
|
ctas: androidCta = {},
|
|
384
294
|
expandableDetails: androidExpandableDetails = {},
|
|
385
295
|
} = androidContent || {};
|
|
@@ -389,30 +299,12 @@ export const InApp = (props) => {
|
|
|
389
299
|
ctas: androidCtas,
|
|
390
300
|
} = androidExpandableDetails || {};
|
|
391
301
|
const androidCtaLength = androidCtas?.length;
|
|
392
|
-
// Check if this is a Bee editor template
|
|
393
|
-
const isBEEeditor = get(androidContent, 'isBEEeditor');
|
|
394
|
-
const isBeeFreeTemplate = !isEmpty(androidTitle) && androidTitle.toLowerCase() === 'bee free template';
|
|
395
|
-
// Check if this is an HTML editor template (identified by special title)
|
|
396
|
-
const isHTMLEditorTemplate = !isEmpty(androidTitle) && androidTitle.toLowerCase() === 'html editor template';
|
|
397
|
-
// Check if this is an HTML template
|
|
398
|
-
// Prioritize HTML editor template title, then check type/style
|
|
399
|
-
// But exclude if it's a Bee editor template
|
|
400
|
-
androidIsHTML = isHTMLEditorTemplate || ((androidType === INAPP_MEDIA_TYPES.HTML || androidStyle === BIG_HTML)
|
|
401
|
-
&& !isBEEeditor
|
|
402
|
-
&& !isBeeFreeTemplate);
|
|
403
|
-
setIsHTMLTemplate(androidIsHTML);
|
|
404
|
-
|
|
405
302
|
setTitleAndroid(androidTitle);
|
|
406
303
|
setTemplateMessageAndroid(androidMessage);
|
|
407
|
-
// Initialize HTML content for HTMLEditor if feature is enabled and it's an HTML template
|
|
408
|
-
if (androidIsHTML) {
|
|
409
|
-
setHtmlContentAndroid(androidMessage);
|
|
410
|
-
}
|
|
411
304
|
setTemplateMediaType(
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
: INAPP_MEDIA_TYPES.IMAGE
|
|
305
|
+
androidStyle === BIG_TEXT
|
|
306
|
+
? INAPP_MEDIA_TYPES.TEXT
|
|
307
|
+
: INAPP_MEDIA_TYPES.IMAGE
|
|
416
308
|
);
|
|
417
309
|
setInAppImageSrcAndroid(androidImage);
|
|
418
310
|
setDeepLinkValueAndroid(androidCta[0]?.actionLink || '');
|
|
@@ -429,7 +321,6 @@ export const InApp = (props) => {
|
|
|
429
321
|
const {
|
|
430
322
|
title: iosTitle = '',
|
|
431
323
|
message: iosMessage = '',
|
|
432
|
-
type: iosType = '',
|
|
433
324
|
ctas: iosCta = {},
|
|
434
325
|
expandableDetails: iosExpandableDetails = {},
|
|
435
326
|
} = iosContent || {};
|
|
@@ -439,53 +330,9 @@ export const InApp = (props) => {
|
|
|
439
330
|
ctas: iosCtas,
|
|
440
331
|
} = iosExpandableDetails || {};
|
|
441
332
|
const iosCtaLength = iosCtas?.length;
|
|
442
|
-
|
|
443
|
-
// Check if this is an HTML template (if Android wasn't HTML, check iOS)
|
|
444
|
-
// Note: androidIsHTML is in the outer scope from the Android content check above
|
|
445
|
-
if (!androidIsHTML) {
|
|
446
|
-
// Check if this is a Bee editor template
|
|
447
|
-
const isBEEeditor = get(iosContent, 'isBEEeditor');
|
|
448
|
-
const isBeeFreeTemplate = !isEmpty(iosTitle) && iosTitle.toLowerCase() === 'bee free template';
|
|
449
|
-
// Check if this is an HTML editor template (identified by special title)
|
|
450
|
-
const isHTMLEditorTemplate = !isEmpty(iosTitle) && iosTitle.toLowerCase() === 'html editor template';
|
|
451
|
-
// Check if this is an HTML template
|
|
452
|
-
// Prioritize HTML editor template title, then check type/style
|
|
453
|
-
// But exclude if it's a Bee editor template
|
|
454
|
-
const iosIsHTML = isHTMLEditorTemplate || ((iosType === INAPP_MEDIA_TYPES.HTML || iosStyle === BIG_HTML)
|
|
455
|
-
&& !isBEEeditor
|
|
456
|
-
&& !isBeeFreeTemplate);
|
|
457
|
-
setIsHTMLTemplate(iosIsHTML);
|
|
458
|
-
// Initialize HTML content for HTMLEditor if feature is enabled and it's an HTML template
|
|
459
|
-
if (iosIsHTML) {
|
|
460
|
-
setHtmlContentIos(iosMessage);
|
|
461
|
-
}
|
|
462
|
-
} else {
|
|
463
|
-
// If Android is HTML, also initialize iOS HTML content if available
|
|
464
|
-
if (androidIsHTML) {
|
|
465
|
-
setHtmlContentIos(iosMessage);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
333
|
setTitleIos(iosTitle);
|
|
470
334
|
setTemplateMessageIos(iosMessage);
|
|
471
|
-
|
|
472
|
-
if (!androidIsHTML) {
|
|
473
|
-
// Check if this is a Bee editor template
|
|
474
|
-
const isBEEeditor = get(iosContent, 'isBEEeditor');
|
|
475
|
-
const isBeeFreeTemplate = !isEmpty(iosTitle) && iosTitle.toLowerCase() === 'bee free template';
|
|
476
|
-
// Check if this is an HTML editor template (identified by special title)
|
|
477
|
-
const isHTMLEditorTemplate = !isEmpty(iosTitle) && iosTitle.toLowerCase() === 'html editor template';
|
|
478
|
-
// Check if this is an HTML template
|
|
479
|
-
// Prioritize HTML editor template title, then check type/style
|
|
480
|
-
const iosIsHTML = isHTMLEditorTemplate || ((iosType === INAPP_MEDIA_TYPES.HTML || iosStyle === BIG_HTML)
|
|
481
|
-
&& !isBEEeditor
|
|
482
|
-
&& !isBeeFreeTemplate);
|
|
483
|
-
if (iosIsHTML) {
|
|
484
|
-
setTemplateMediaType(INAPP_MEDIA_TYPES.HTML);
|
|
485
|
-
} else {
|
|
486
|
-
setTemplateMediaType(iosStyle === BIG_TEXT ? INAPP_MEDIA_TYPES.TEXT : INAPP_MEDIA_TYPES.IMAGE);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
335
|
+
setTemplateMediaType(iosStyle === BIG_TEXT ? INAPP_MEDIA_TYPES.TEXT : INAPP_MEDIA_TYPES.IMAGE);
|
|
489
336
|
setInAppImageSrcIos(iosImage);
|
|
490
337
|
setButtonTypeIos(iosCtaLength ? INAPP_BUTTON_TYPES.CTA : INAPP_BUTTON_TYPES.NONE);
|
|
491
338
|
setAddActionLinkIos(!isEmpty(iosCta) && true);
|
|
@@ -494,47 +341,12 @@ export const InApp = (props) => {
|
|
|
494
341
|
setCtaDataIos(getCtaObject(iosCtas));
|
|
495
342
|
}
|
|
496
343
|
}
|
|
497
|
-
} else {
|
|
498
|
-
// Explicitly set edit flow to false if there's no edit content
|
|
499
|
-
setEditFlow(false);
|
|
500
344
|
}
|
|
501
345
|
}, [editData.templateDetails || templateData]);
|
|
502
346
|
|
|
503
|
-
// Extract editor type from defaultData for stable reference
|
|
504
|
-
const editorType = useMemo(() => {
|
|
505
|
-
const type = defaultData?.['editor-type'];
|
|
506
|
-
return type;
|
|
507
|
-
}, [defaultData]);
|
|
508
|
-
|
|
509
|
-
// Separate effect for handling editor type from wrapper in create mode
|
|
510
|
-
useEffect(() => {
|
|
511
|
-
// Only process editor type if we're not in edit flow
|
|
512
|
-
if (!isEditFlow) {
|
|
513
|
-
if (editorType === INAPP_EDITOR_TYPES.HTML_EDITOR) {
|
|
514
|
-
setIsHTMLTemplate(true);
|
|
515
|
-
setTemplateMediaType(INAPP_MEDIA_TYPES.HTML);
|
|
516
|
-
} else if (editorType === INAPP_EDITOR_TYPES.DRAG_DROP_EDITOR) {
|
|
517
|
-
setIsHTMLTemplate(false);
|
|
518
|
-
} else if (!editorType) {
|
|
519
|
-
// If no editor type is set yet, ensure we start with false
|
|
520
|
-
setIsHTMLTemplate(false);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
}, [editorType, isEditFlow]);
|
|
524
|
-
|
|
525
347
|
// tag Code start from here
|
|
526
348
|
useEffect(() => {
|
|
527
|
-
//
|
|
528
|
-
tagsFetchedRef.current = false;
|
|
529
|
-
|
|
530
|
-
// Only fetch tags if HTML Editor is not being used (legacy flow)
|
|
531
|
-
// For HTML Editor, tags will be fetched via handleOnTagsContextChange
|
|
532
|
-
if (isHTMLTemplate) {
|
|
533
|
-
// HTML Editor will handle tag fetching via onContextChange
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
//fetching tags for legacy editor
|
|
349
|
+
//fetching tags
|
|
538
350
|
const { type, module } = location.query || {};
|
|
539
351
|
const isEmbedded = type === EMBEDDED;
|
|
540
352
|
const context = isEmbedded ? module : DEFAULT;
|
|
@@ -549,7 +361,7 @@ export const InApp = (props) => {
|
|
|
549
361
|
query.context = getDefaultTags;
|
|
550
362
|
}
|
|
551
363
|
globalActions.fetchSchemaForEntity(query);
|
|
552
|
-
}, [
|
|
364
|
+
}, []);
|
|
553
365
|
|
|
554
366
|
useEffect(() => {
|
|
555
367
|
let tag = get(metaEntities, `tags.standard`, []);
|
|
@@ -560,17 +372,7 @@ export const InApp = (props) => {
|
|
|
560
372
|
updateTags(tag);
|
|
561
373
|
}, [metaEntities]);
|
|
562
374
|
|
|
563
|
-
|
|
564
|
-
const tagsFetchedRef = React.useRef(false);
|
|
565
|
-
|
|
566
|
-
const handleOnTagsContextChange = useCallback((data) => {
|
|
567
|
-
// This function is called when TagList needs to fetch tags
|
|
568
|
-
// It triggers the API call to /meta/TAG endpoint via fetchSchemaForEntity
|
|
569
|
-
// Only fetch if we haven't already fetched for this context
|
|
570
|
-
if (tagsFetchedRef.current) {
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
573
|
-
|
|
375
|
+
const handleOnTagsContextChange = (data) => {
|
|
574
376
|
const { type } = location.query || {};
|
|
575
377
|
const tempData = (data || '').toLowerCase();
|
|
576
378
|
const isEmbedded = type === EMBEDDED;
|
|
@@ -582,192 +384,259 @@ export const InApp = (props) => {
|
|
|
582
384
|
context,
|
|
583
385
|
embedded,
|
|
584
386
|
};
|
|
585
|
-
// Mark as fetched to prevent duplicate calls
|
|
586
|
-
tagsFetchedRef.current = true;
|
|
587
|
-
// Call the API via Redux action - this will trigger the saga which calls Api.fetchSchemaForEntity
|
|
588
|
-
// The API endpoint will be: /meta/TAG?query={...}
|
|
589
387
|
globalActions.fetchSchemaForEntity(query);
|
|
590
|
-
}
|
|
388
|
+
};
|
|
591
389
|
|
|
390
|
+
const templateDescErrorHandler = (value) => {
|
|
391
|
+
let errorMessage = false;
|
|
392
|
+
const { unsupportedTags, isBraceError } = validateTags({
|
|
393
|
+
content: value,
|
|
394
|
+
tagsParam: tags,
|
|
395
|
+
injectedTagsParams: injectedTags,
|
|
396
|
+
location,
|
|
397
|
+
tagModule: getDefaultTags,
|
|
398
|
+
}) || {};
|
|
399
|
+
if (value === '' && INAPP_MEDIA_TYPES.NONE) {
|
|
400
|
+
errorMessage = formatMessage(messages.emptyTemplateDescErrorMessage);
|
|
401
|
+
} else if (unsupportedTags?.length > 0) {
|
|
402
|
+
errorMessage = formatMessage(
|
|
403
|
+
globalMessages.unsupportedTagsValidationError,
|
|
404
|
+
{
|
|
405
|
+
unsupportedTags,
|
|
406
|
+
},
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
if (isBraceError) {
|
|
410
|
+
errorMessage = formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
411
|
+
}
|
|
412
|
+
return errorMessage;
|
|
413
|
+
};
|
|
592
414
|
|
|
415
|
+
const onTagSelect = (data, id) => {
|
|
416
|
+
if (id === 0) {
|
|
417
|
+
const tempTitle = `${panes === ANDROID ? titleAndroid : titleIos}{{${data}}}`;
|
|
418
|
+
if (panes === ANDROID) {
|
|
419
|
+
setTitleAndroid(tempTitle);
|
|
420
|
+
} else {
|
|
421
|
+
setTitleIos(tempTitle);
|
|
422
|
+
}
|
|
423
|
+
} else {
|
|
424
|
+
const tempMsg = `${panes === ANDROID ? templateMessageAndroid : templateMessageIos}{{${data}}}`;
|
|
425
|
+
const error = templateDescErrorHandler(tempMsg);
|
|
426
|
+
if (panes === ANDROID) {
|
|
427
|
+
setTemplateMessageAndroid(tempMsg);
|
|
428
|
+
setTemplateMessageErrorAndroid(error);
|
|
429
|
+
} else {
|
|
430
|
+
setTemplateMessageIos(tempMsg);
|
|
431
|
+
setTemplateMessageErrorIos(error);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
};
|
|
593
435
|
// tag Code end
|
|
594
436
|
|
|
437
|
+
const onTemplateNameChange = ({ target: { value } }) => {
|
|
438
|
+
setTemplateName(value);
|
|
439
|
+
};
|
|
440
|
+
|
|
595
441
|
const onTemplateLayoutTypeChange = ({ target: { value } }) => {
|
|
596
|
-
// Update layout type and force HTMLEditor to remount with latest content
|
|
597
|
-
// Increment version to force remount - this ensures editor displays current content
|
|
598
442
|
setTemplateLayoutType(value);
|
|
599
|
-
setHtmlEditorContentVersion((prev) => prev + 1);
|
|
600
443
|
};
|
|
601
444
|
|
|
445
|
+
const onCopyTitleAndContent = () => {
|
|
446
|
+
if (panes === ANDROID) {
|
|
447
|
+
setTitleAndroid(titleIos);
|
|
448
|
+
setTemplateMessageAndroid(templateMessageIos);
|
|
449
|
+
} else {
|
|
450
|
+
setTitleIos(titleAndroid);
|
|
451
|
+
setTemplateMessageIos(templateMessageAndroid);
|
|
452
|
+
}
|
|
453
|
+
};
|
|
602
454
|
|
|
455
|
+
const PANES = [
|
|
456
|
+
{
|
|
457
|
+
content: (
|
|
458
|
+
<CapDeviceContent
|
|
459
|
+
intl={intl}
|
|
460
|
+
location={location}
|
|
461
|
+
injectedTags={injectIntl}
|
|
462
|
+
selectedOfferDetails={selectedOfferDetails}
|
|
463
|
+
panes={panes}
|
|
464
|
+
actions={actions}
|
|
465
|
+
editData={editData}
|
|
466
|
+
isFullMode={isFullMode}
|
|
467
|
+
inAppImageSrc={inAppImageSrcAndroid}
|
|
468
|
+
setInAppImageSrc={setInAppImageSrcAndroid}
|
|
469
|
+
isEditFlow={isEditFlow}
|
|
470
|
+
ctaData={ctaDataAndroid}
|
|
471
|
+
setCtaData={setCtaDataAndroid}
|
|
472
|
+
buttonType={buttonTypeAndroid}
|
|
473
|
+
setButtonType={setButtonTypeAndroid}
|
|
474
|
+
accountId={accountId}
|
|
475
|
+
accessToken={accessToken}
|
|
476
|
+
templateMediaType={templateMediaType}
|
|
477
|
+
setTemplateMediaType={setTemplateMediaType}
|
|
478
|
+
title={titleAndroid}
|
|
479
|
+
setTitle={setTitleAndroid}
|
|
480
|
+
templateMessageError={templateMessageErrorAndroid}
|
|
481
|
+
templateMessage={templateMessageAndroid}
|
|
482
|
+
setTemplateMessage={setTemplateMessageAndroid}
|
|
483
|
+
setTemplateMessageError={setTemplateMessageErrorAndroid}
|
|
484
|
+
templateTitleError={templateTitleErrorAndroid}
|
|
485
|
+
setTemplateTitleError={setTemplateTitleErrorAndroid}
|
|
486
|
+
addActionLink={addActionLinkAndroid}
|
|
487
|
+
setAddActionLink={setAddActionLinkAndroid}
|
|
488
|
+
deepLink={deepLink}
|
|
489
|
+
deepLinkValue={deepLinkValueAndroid}
|
|
490
|
+
setDeepLinkValue={setDeepLinkValueAndroid}
|
|
491
|
+
onCopyTitleAndContent={onCopyTitleAndContent}
|
|
492
|
+
tags={tags}
|
|
493
|
+
onTagSelect={onTagSelect}
|
|
494
|
+
handleOnTagsContextChange={handleOnTagsContextChange}
|
|
495
|
+
templateDescErrorHandler={templateDescErrorHandler}
|
|
496
|
+
isAiContentBotDisabled={isAiContentBotDisabled}
|
|
497
|
+
/>
|
|
498
|
+
),
|
|
499
|
+
tab: <FormattedMessage {...messages.Android} />,
|
|
500
|
+
key: ANDROID,
|
|
501
|
+
isSupported: get(accountData, 'selectedWeChatAccount.configs.android') === DEVICE_SUPPORTED,
|
|
502
|
+
// DEVICE_SUPPORTED is '1', which indicates if the particular account is supported, and '0' if the devive is not supported
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
content: (
|
|
506
|
+
<CapDeviceContent
|
|
507
|
+
intl={intl}
|
|
508
|
+
location={location}
|
|
509
|
+
injectedTags={injectIntl}
|
|
510
|
+
selectedOfferDetails={selectedOfferDetails}
|
|
511
|
+
panes={panes}
|
|
512
|
+
actions={actions}
|
|
513
|
+
editData={editData}
|
|
514
|
+
isFullMode={isFullMode}
|
|
515
|
+
inAppImageSrc={inAppImageSrcIos}
|
|
516
|
+
setInAppImageSrc={setInAppImageSrcIos}
|
|
517
|
+
isEditFlow={isEditFlow}
|
|
518
|
+
ctaData={ctaDataIos}
|
|
519
|
+
setCtaData={setCtaDataIos}
|
|
520
|
+
buttonType={buttonTypeIos}
|
|
521
|
+
setButtonType={setButtonTypeIos}
|
|
522
|
+
accountId={accountId}
|
|
523
|
+
accessToken={accessToken}
|
|
524
|
+
templateMediaType={templateMediaType}
|
|
525
|
+
setTemplateMediaType={setTemplateMediaType}
|
|
526
|
+
title={titleIos}
|
|
527
|
+
setTitle={setTitleIos}
|
|
528
|
+
templateMessageError={templateMessageErrorIos}
|
|
529
|
+
templateMessage={templateMessageIos}
|
|
530
|
+
setTemplateMessage={setTemplateMessageIos}
|
|
531
|
+
setTemplateMessageError={setTemplateMessageErrorIos}
|
|
532
|
+
templateTitleError={templateTitleErrorIos}
|
|
533
|
+
setTemplateTitleError={setTemplateTitleErrorIos}
|
|
534
|
+
addActionLink={addActionLinkIos}
|
|
535
|
+
setAddActionLink={setAddActionLinkIos}
|
|
536
|
+
deepLink={deepLink}
|
|
537
|
+
deepLinkValue={deepLinkValueIos}
|
|
538
|
+
setDeepLinkValue={setDeepLinkValueIos}
|
|
539
|
+
onCopyTitleAndContent={onCopyTitleAndContent}
|
|
540
|
+
tags={tags}
|
|
541
|
+
onTagSelect={onTagSelect}
|
|
542
|
+
handleOnTagsContextChange={handleOnTagsContextChange}
|
|
543
|
+
templateDescErrorHandler={templateDescErrorHandler}
|
|
544
|
+
isAiContentBotDisabled={isAiContentBotDisabled}
|
|
545
|
+
/>
|
|
546
|
+
),
|
|
547
|
+
tab: <FormattedMessage {...messages.Ios} />,
|
|
548
|
+
key: IOS,
|
|
549
|
+
isSupported: get(accountData, 'selectedWeChatAccount.configs.ios') === DEVICE_SUPPORTED,
|
|
550
|
+
},
|
|
551
|
+
];
|
|
552
|
+
|
|
553
|
+
const createModeContent = (
|
|
554
|
+
<CapRow>
|
|
555
|
+
{/* template name */}
|
|
556
|
+
<CapHeading type="h4">
|
|
557
|
+
<FormattedMessage {...messages.creativeName} />
|
|
558
|
+
</CapHeading>
|
|
559
|
+
<CapInput
|
|
560
|
+
id="inapp-template-name-input"
|
|
561
|
+
className="inapp-template-name-input"
|
|
562
|
+
onChange={onTemplateNameChange}
|
|
563
|
+
placeholder={formatMessage(globalMessages.templateNamePlaceholder)}
|
|
564
|
+
value={templateName}
|
|
565
|
+
size="default"
|
|
566
|
+
/>
|
|
567
|
+
</CapRow>
|
|
568
|
+
);
|
|
603
569
|
//create methods end
|
|
604
570
|
|
|
605
571
|
//used by create and edit
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
const
|
|
609
|
-
const
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
// Get account-level device support restrictions
|
|
620
|
-
const androidSupported = get(accountData, 'selectedWeChatAccount.configs.android') === DEVICE_SUPPORTED || get(editContent, 'ANDROID.deviceType') === ANDROID;
|
|
621
|
-
const iosSupported = get(accountData, 'selectedWeChatAccount.configs.ios') === DEVICE_SUPPORTED || get(editContent, 'IOS.deviceType') === IOS_CAPITAL;
|
|
622
|
-
|
|
623
|
-
// Check if devices have content - ensure content is a string before calling trim
|
|
624
|
-
let hasAndroidContent = htmlContentAndroid && typeof htmlContentAndroid === 'string' && htmlContentAndroid?.trim() !== '';
|
|
625
|
-
let hasIosContent = htmlContentIos && typeof htmlContentIos === 'string' && htmlContentIos?.trim() !== '';
|
|
626
|
-
|
|
627
|
-
// LIBRARY MODE FIX: In library mode edit, htmlContent states might not be set yet
|
|
628
|
-
// because HTMLEditor loads content via initialContent prop, not via onContentChange
|
|
629
|
-
// Fallback to checking template data content
|
|
630
|
-
if (!hasAndroidContent && isEditFlow && !isFullMode && templateData) {
|
|
631
|
-
const androidTemplateContent = get(templateData, 'versions.base.content.ANDROID.message')
|
|
632
|
-
|| get(templateData, 'versions.base.content.ANDROID.beeHtml.value');
|
|
633
|
-
hasAndroidContent = androidTemplateContent && androidTemplateContent.trim() !== '';
|
|
634
|
-
}
|
|
635
|
-
if (!hasIosContent && isEditFlow && !isFullMode && templateData) {
|
|
636
|
-
const iosTemplateContent = get(templateData, 'versions.base.content.IOS.message')
|
|
637
|
-
|| get(templateData, 'versions.base.content.IOS.beeHtml.value');
|
|
638
|
-
hasIosContent = iosTemplateContent && iosTemplateContent.trim() !== '';
|
|
572
|
+
const getPreviewSection = () => {
|
|
573
|
+
const templateTitle = panes === ANDROID ? titleAndroid : titleIos;
|
|
574
|
+
const templateMsg = panes === ANDROID ? templateMessageAndroid : templateMessageIos;
|
|
575
|
+
const mediaPreview = {};
|
|
576
|
+
let ctaData = {};
|
|
577
|
+
if (panes === ANDROID) {
|
|
578
|
+
ctaData = ctaDataAndroid;
|
|
579
|
+
switch (templateMediaType) {
|
|
580
|
+
case INAPP_MEDIA_TYPES.IMAGE:
|
|
581
|
+
mediaPreview.inAppImageSrcAndroid = inAppImageSrcAndroid;
|
|
582
|
+
break;
|
|
583
|
+
default:
|
|
584
|
+
break;
|
|
639
585
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
}
|
|
649
|
-
return false;
|
|
650
|
-
}
|
|
651
|
-
// Android not supported and no content in template - skip validation
|
|
652
|
-
return false;
|
|
653
|
-
}
|
|
654
|
-
if (isIosDevice) {
|
|
655
|
-
// Only validate iOS if it's supported by account
|
|
656
|
-
// But in library mode edit, check template data too
|
|
657
|
-
if (iosSupported || (isEditFlow && !isFullMode && hasIosContent)) {
|
|
658
|
-
if (!hasIosContent) {
|
|
659
|
-
return true;
|
|
660
|
-
}
|
|
661
|
-
return false;
|
|
662
|
-
}
|
|
663
|
-
// iOS not supported and no content in template - skip validation
|
|
664
|
-
return false;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// If no specific device, check if at least one supported device has content
|
|
668
|
-
// Users can create templates with content in Android-only, iOS-only, or both devices
|
|
669
|
-
// Even when both devices are supported, user can create template with content in just one device
|
|
670
|
-
if (androidSupported && iosSupported) {
|
|
671
|
-
// Both devices supported - user can create template with content in Android, iOS, or both
|
|
672
|
-
// Only disable if NEITHER device has content
|
|
673
|
-
if (!hasAndroidContent && !hasIosContent) {
|
|
674
|
-
return true;
|
|
675
|
-
}
|
|
676
|
-
// At least one device has content - enable Done button
|
|
677
|
-
return false;
|
|
678
|
-
}
|
|
679
|
-
if (androidSupported) {
|
|
680
|
-
// Only Android supported - require Android content
|
|
681
|
-
if (!hasAndroidContent) {
|
|
682
|
-
return true;
|
|
683
|
-
}
|
|
684
|
-
// Android has content - enable Done button
|
|
685
|
-
return false;
|
|
686
|
-
}
|
|
687
|
-
if (iosSupported) {
|
|
688
|
-
// Only iOS supported - require iOS content
|
|
689
|
-
if (!hasIosContent) {
|
|
690
|
-
return true;
|
|
691
|
-
}
|
|
692
|
-
// iOS has content - enable Done button
|
|
693
|
-
return false;
|
|
586
|
+
} else {
|
|
587
|
+
ctaData = ctaDataIos;
|
|
588
|
+
switch (templateMediaType) {
|
|
589
|
+
case INAPP_MEDIA_TYPES.IMAGE:
|
|
590
|
+
mediaPreview.inAppImageSrcIos = inAppImageSrcIos;
|
|
591
|
+
break;
|
|
592
|
+
default:
|
|
593
|
+
break;
|
|
694
594
|
}
|
|
695
|
-
// Neither device supported - this shouldn't happen, but handle gracefully
|
|
696
|
-
return true;
|
|
697
595
|
}
|
|
596
|
+
return (
|
|
597
|
+
<UnifiedPreview
|
|
598
|
+
channel={INAPP}
|
|
599
|
+
content={{
|
|
600
|
+
inAppPreviewContent: {
|
|
601
|
+
mediaPreview,
|
|
602
|
+
templateTitle,
|
|
603
|
+
templateMsg,
|
|
604
|
+
...((isBtnTypeCtaAndroid || isBtnTypeCTaIos) && {
|
|
605
|
+
ctaData,
|
|
606
|
+
}),
|
|
607
|
+
},
|
|
608
|
+
templateLayoutType,
|
|
609
|
+
}}
|
|
610
|
+
device={panes}
|
|
611
|
+
showDeviceToggle={false}
|
|
612
|
+
showHeader={false}
|
|
613
|
+
formatMessage={formatMessage}
|
|
614
|
+
/>
|
|
615
|
+
);
|
|
616
|
+
};
|
|
698
617
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
const
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
// If no tags are available (e.g., in tests), allow submission even with minimal content
|
|
705
|
-
// This is to support test scenarios where full content validation might not be set up
|
|
706
|
-
const hasTags = tags && tags.length > 0;
|
|
707
|
-
const isTestScenario = !hasTags;
|
|
708
|
-
|
|
709
|
-
// If no device specified, check if at least one supported device has valid content
|
|
710
|
-
if (isNoDevice) {
|
|
711
|
-
// In test scenarios, only require message content (title is optional)
|
|
712
|
-
// In production, require both title and message
|
|
713
|
-
const hasAndroidContent = androidSupported && templateMessageAndroid && templateMessageAndroid?.trim() !== '' && !templateMessageErrorAndroid && (isTestScenario || (titleAndroid && titleAndroid?.trim() !== '' && !templateTitleErrorAndroid));
|
|
714
|
-
const hasIosContent = iosSupported && templateMessageIos && templateMessageIos?.trim() !== '' && !templateMessageErrorIos && (isTestScenario || (titleIos && titleIos?.trim() !== '' && !templateTitleErrorIos));
|
|
715
|
-
|
|
716
|
-
// Check media requirements
|
|
717
|
-
const androidMediaValid = !androidSupported || (templateMediaType === INAPP_MEDIA_TYPES.TEXT || inAppImageSrcAndroid !== '');
|
|
718
|
-
const iosMediaValid = !iosSupported || (templateMediaType === INAPP_MEDIA_TYPES.TEXT || inAppImageSrcIos !== '');
|
|
719
|
-
|
|
720
|
-
// Check CTA requirements
|
|
721
|
-
const androidCtaValid = !isBtnTypeCtaAndroid || (ctaDataAndroid[0]?.isSaved);
|
|
722
|
-
const iosCtaValid = !isBtnTypeCTaIos || (ctaDataIos[0]?.isSaved);
|
|
723
|
-
|
|
724
|
-
// Check action link requirements
|
|
725
|
-
const androidActionLinkValid = !addActionLinkAndroid || deepLinkValueAndroid;
|
|
726
|
-
const iosActionLinkValid = !addActionLinkIos || deepLinkValueIos;
|
|
727
|
-
|
|
728
|
-
// If both devices are supported, at least one should have valid content
|
|
729
|
-
if (androidSupported && iosSupported) {
|
|
730
|
-
const androidValid = hasAndroidContent && androidMediaValid && androidCtaValid && androidActionLinkValid;
|
|
731
|
-
const iosValid = hasIosContent && iosMediaValid && iosCtaValid && iosActionLinkValid;
|
|
732
|
-
return !(androidValid || iosValid);
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
// If only Android is supported, it must have valid content
|
|
736
|
-
if (androidSupported) {
|
|
737
|
-
return !(hasAndroidContent && androidMediaValid && androidCtaValid && androidActionLinkValid);
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// If only iOS is supported, it must have valid content
|
|
741
|
-
if (iosSupported) {
|
|
742
|
-
return !(hasIosContent && iosMediaValid && iosCtaValid && iosActionLinkValid);
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
// Neither device supported - disable
|
|
618
|
+
const isDisableDone = (device) => {
|
|
619
|
+
const isIosDevice = device === IOS;
|
|
620
|
+
const isAndroidDevice = device === ANDROID;
|
|
621
|
+
//if template name is not entered
|
|
622
|
+
if (isFullMode && templateName.trim() === '') {
|
|
746
623
|
return true;
|
|
747
624
|
}
|
|
748
|
-
|
|
749
625
|
//if template message is not entered
|
|
750
626
|
//for android
|
|
751
|
-
if (isAndroidDevice) {
|
|
752
|
-
|
|
753
|
-
if (androidMessage?.trim() === '' || templateMessageErrorAndroid) {
|
|
754
|
-
return true;
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
//for ios
|
|
758
|
-
if (isIosDevice) {
|
|
759
|
-
const iosMessage = templateMessageIos;
|
|
760
|
-
if (iosMessage?.trim() === '' || templateMessageErrorIos) {
|
|
761
|
-
return true;
|
|
762
|
-
}
|
|
627
|
+
if (isAndroidDevice && (templateMessageAndroid.trim() === '' || templateMessageErrorAndroid)) {
|
|
628
|
+
return true;
|
|
763
629
|
}
|
|
630
|
+
if (isIosDevice && (templateMessageIos.trim() === '' || templateMessageErrorIos)) {
|
|
631
|
+
return true;
|
|
632
|
+
}//for ios
|
|
764
633
|
|
|
765
634
|
//if template title is not entered
|
|
766
635
|
//for android
|
|
767
|
-
if (isAndroidDevice && (titleAndroid
|
|
636
|
+
if (isAndroidDevice && (titleAndroid.trim() === '' || templateTitleErrorAndroid)) {
|
|
768
637
|
return true;
|
|
769
638
|
}
|
|
770
|
-
if (isIosDevice && (titleIos
|
|
639
|
+
if (isIosDevice && (titleIos.trim() === '' || templateTitleErrorIos)) {
|
|
771
640
|
return true;
|
|
772
641
|
}//for ios
|
|
773
642
|
//if media type is image and the mediaType file is not uploaded
|
|
@@ -826,11 +695,11 @@ export const InApp = (props) => {
|
|
|
826
695
|
switch (templateMediaType) {
|
|
827
696
|
case INAPP_MEDIA_TYPES.IMAGE:
|
|
828
697
|
androidMediaParams = {
|
|
829
|
-
image: getCdnUrl({
|
|
698
|
+
image: getCdnUrl({url: inAppImageSrcAndroid, channelName: INAPP }),
|
|
830
699
|
style: BIG_PICTURE,
|
|
831
700
|
};
|
|
832
701
|
iosMediaParams = {
|
|
833
|
-
image: getCdnUrl({
|
|
702
|
+
image: getCdnUrl({url: inAppImageSrcIos, channelName: INAPP }),
|
|
834
703
|
style: BIG_PICTURE,
|
|
835
704
|
};
|
|
836
705
|
break;
|
|
@@ -842,46 +711,16 @@ export const InApp = (props) => {
|
|
|
842
711
|
sourceAccountIdentifier = "",
|
|
843
712
|
id,
|
|
844
713
|
} = accountObj;
|
|
845
|
-
|
|
846
|
-
//
|
|
847
|
-
const
|
|
848
|
-
? htmlContentAndroid
|
|
849
|
-
: templateMessageAndroid;
|
|
850
|
-
|
|
851
|
-
// Determine type and style for Android
|
|
852
|
-
const androidType = isHTMLTemplate ? INAPP_MEDIA_TYPES.HTML : templateMediaType;
|
|
853
|
-
const androidExpandableStyle = isHTMLTemplate ? BIG_HTML : BIG_TEXT;
|
|
854
|
-
|
|
855
|
-
// LIBRARY MODE FIX: Backend doesn't support 'MODAL' bodyType, convert to 'POPUP'
|
|
856
|
-
const bodyTypeForBackend = templateLayoutType === INAPP_MESSAGE_LAYOUT_TYPES.MODAL ? INAPP_MESSAGE_LAYOUT_TYPES.POPUP : templateLayoutType;
|
|
857
|
-
|
|
858
|
-
// Check account-level device support
|
|
859
|
-
const androidSupported = get(accountData, 'selectedWeChatAccount.configs.android') === DEVICE_SUPPORTED || get(editContent, 'ANDROID.deviceType') === ANDROID;
|
|
860
|
-
const iosSupported = get(accountData, 'selectedWeChatAccount.configs.ios') === DEVICE_SUPPORTED || get(editContent, 'IOS.deviceType') === IOS_CAPITAL;
|
|
861
|
-
|
|
862
|
-
// Check if devices have content (for HTML Editor)
|
|
863
|
-
const hasAndroidContent = htmlContentAndroid && htmlContentAndroid?.trim() !== '';
|
|
864
|
-
const hasIosContent = htmlContentIos && htmlContentIos?.trim() !== '';
|
|
865
|
-
|
|
866
|
-
// For HTML Editor, check if device has content and is supported
|
|
867
|
-
// For legacy editor, use isDisableDone check
|
|
868
|
-
// Only include devices that have content - allows Android-only, iOS-only, or both
|
|
869
|
-
const shouldIncludeAndroid = isHTMLTemplate
|
|
870
|
-
? (androidSupported && hasAndroidContent)
|
|
871
|
-
: !isDisableDone(ANDROID);
|
|
872
|
-
|
|
873
|
-
// Construct Android content if device is supported and has content
|
|
874
|
-
// Even when both devices are supported, only include devices that have content
|
|
875
|
-
const androidContent = shouldIncludeAndroid ? {
|
|
714
|
+
|
|
715
|
+
// Construct Android content if not disabled
|
|
716
|
+
const androidContent = !isDisableDone(ANDROID) ? {
|
|
876
717
|
...commonDevicePayload,
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
title: isHTMLTemplate ? 'html editor template' : titleAndroid,
|
|
880
|
-
message: androidMessage,
|
|
718
|
+
title: titleAndroid,
|
|
719
|
+
message: templateMessageAndroid,
|
|
881
720
|
bodyType: templateLayoutType,
|
|
882
721
|
expandableDetails: {
|
|
883
|
-
style:
|
|
884
|
-
message:
|
|
722
|
+
style: BIG_TEXT,
|
|
723
|
+
message: templateMessageAndroid,
|
|
885
724
|
...androidMediaParams,
|
|
886
725
|
...(isBtnTypeCtaAndroid && {
|
|
887
726
|
ctas: getCtaPayload(ANDROID),
|
|
@@ -889,38 +728,19 @@ export const InApp = (props) => {
|
|
|
889
728
|
},
|
|
890
729
|
custom: [],
|
|
891
730
|
...(deepLinkValueAndroid && {
|
|
892
|
-
ctas: [{
|
|
731
|
+
ctas: [{type: DEEP_LINK, actionLink: deepLinkValueAndroid}],
|
|
893
732
|
}),
|
|
894
733
|
} : {};
|
|
895
|
-
|
|
896
|
-
//
|
|
897
|
-
const
|
|
898
|
-
? htmlContentIos
|
|
899
|
-
: templateMessageIos;
|
|
900
|
-
|
|
901
|
-
// Determine type and style for iOS
|
|
902
|
-
const iosType = isHTMLTemplate ? INAPP_MEDIA_TYPES.HTML : templateMediaType;
|
|
903
|
-
const iosExpandableStyle = isHTMLTemplate ? BIG_HTML : BIG_TEXT;
|
|
904
|
-
|
|
905
|
-
// For HTML Editor, check if device has content and is supported
|
|
906
|
-
// For legacy editor, use isDisableDone check
|
|
907
|
-
// Only include devices that have content - allows Android-only, iOS-only, or both
|
|
908
|
-
const shouldIncludeIos = isHTMLTemplate
|
|
909
|
-
? (iosSupported && hasIosContent)
|
|
910
|
-
: !isDisableDone(IOS);
|
|
911
|
-
|
|
912
|
-
// Construct iOS content if device is supported and has content
|
|
913
|
-
// Even when both devices are supported, only include devices that have content
|
|
914
|
-
const iosContent = shouldIncludeIos ? {
|
|
734
|
+
|
|
735
|
+
// Construct iOS content if not disabled
|
|
736
|
+
const iosContent = !isDisableDone(IOS) ? {
|
|
915
737
|
...commonDevicePayload,
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
message: iosMessage,
|
|
920
|
-
bodyType: bodyTypeForBackend,
|
|
738
|
+
title: titleIos,
|
|
739
|
+
message: templateMessageIos,
|
|
740
|
+
bodyType: templateLayoutType,
|
|
921
741
|
expandableDetails: {
|
|
922
|
-
style:
|
|
923
|
-
message:
|
|
742
|
+
style: BIG_TEXT,
|
|
743
|
+
message: templateMessageIos,
|
|
924
744
|
...iosMediaParams,
|
|
925
745
|
...(isBtnTypeCTaIos && {
|
|
926
746
|
ctas: getCtaPayload(IOS),
|
|
@@ -928,16 +748,12 @@ export const InApp = (props) => {
|
|
|
928
748
|
},
|
|
929
749
|
custom: [],
|
|
930
750
|
...(deepLinkValueIos && {
|
|
931
|
-
ctas: [{
|
|
751
|
+
ctas: [{type: DEEP_LINK, actionLink: deepLinkValueIos}],
|
|
932
752
|
}),
|
|
933
753
|
} : {};
|
|
934
|
-
|
|
935
|
-
// Ensure name is always set - use tempName as fallback if templateName is empty
|
|
936
|
-
const templateNameValue = isEditFlow ? tempName : (templateName || tempName || '');
|
|
937
|
-
const trimmedName = (templateNameValue && typeof templateNameValue === 'string') ? templateNameValue?.trim() : '';
|
|
938
|
-
|
|
754
|
+
|
|
939
755
|
const data = {
|
|
940
|
-
name:
|
|
756
|
+
name: templateName,
|
|
941
757
|
versions: {
|
|
942
758
|
base: {
|
|
943
759
|
content: {
|
|
@@ -956,26 +772,28 @@ export const InApp = (props) => {
|
|
|
956
772
|
return data;
|
|
957
773
|
};
|
|
958
774
|
|
|
959
|
-
const actionCallback = ({
|
|
960
|
-
if (!
|
|
775
|
+
const actionCallback = ({ errorMessage }) => {
|
|
776
|
+
if (!errorMessage) {
|
|
961
777
|
CapNotification.success({
|
|
962
|
-
message: isEditFlow
|
|
963
|
-
|
|
964
|
-
|
|
778
|
+
message: isEditFlow ? formatMessage(messages.inAppEditNotification, {
|
|
779
|
+
name: templateName,
|
|
780
|
+
}) : formatMessage(messages.inAppCreateNotification, {
|
|
781
|
+
name: templateName,
|
|
782
|
+
}),
|
|
965
783
|
});
|
|
966
784
|
actions.clearCreateResponse();
|
|
967
785
|
} else {
|
|
968
786
|
CapNotification.error({
|
|
969
|
-
message: JSON.stringify(
|
|
787
|
+
message: JSON.stringify(errorMessage),
|
|
970
788
|
});
|
|
971
789
|
}
|
|
972
790
|
};
|
|
973
791
|
|
|
974
792
|
const onCreateInApp = () => {
|
|
975
793
|
setSpin(true);
|
|
976
|
-
actions.createInAppTemplate(createPayload(), (resp,
|
|
977
|
-
actionCallback({ resp,
|
|
978
|
-
if (!
|
|
794
|
+
actions.createInAppTemplate(createPayload(), (resp, errorMessage) => {
|
|
795
|
+
actionCallback({ resp, errorMessage });
|
|
796
|
+
if (!errorMessage) {
|
|
979
797
|
onCreateComplete();
|
|
980
798
|
} else {
|
|
981
799
|
setSpin(false);
|
|
@@ -990,9 +808,9 @@ export const InApp = (props) => {
|
|
|
990
808
|
...createPayload(),
|
|
991
809
|
_id: params.id,
|
|
992
810
|
},
|
|
993
|
-
(resp,
|
|
994
|
-
actionCallback({ resp,
|
|
995
|
-
if (!
|
|
811
|
+
(resp, errorMessage) => {
|
|
812
|
+
actionCallback({ resp, errorMessage });
|
|
813
|
+
if (!errorMessage) {
|
|
996
814
|
onCreateComplete();
|
|
997
815
|
} else {
|
|
998
816
|
setSpin(false);
|
|
@@ -1001,67 +819,6 @@ export const InApp = (props) => {
|
|
|
1001
819
|
);
|
|
1002
820
|
};
|
|
1003
821
|
|
|
1004
|
-
// Handle HTML content changes from HTMLEditor
|
|
1005
|
-
const handleHtmlContentChange = useCallback((deviceContent, changedDevice) => {
|
|
1006
|
-
// The onChange callback from useInAppContent passes the full deviceContent object
|
|
1007
|
-
// But we only want to update the state for the device that actually changed
|
|
1008
|
-
// Use the second parameter (changedDevice) if provided, otherwise update both
|
|
1009
|
-
|
|
1010
|
-
// Clear validation errors when content changes (similar to Bee Editor)
|
|
1011
|
-
// This ensures Done button re-enables after user fixes errors
|
|
1012
|
-
if (changedDevice) {
|
|
1013
|
-
setErrorMessage((prev) => ({
|
|
1014
|
-
STANDARD_ERROR_MSG: {
|
|
1015
|
-
...prev.STANDARD_ERROR_MSG,
|
|
1016
|
-
[changedDevice.toUpperCase()]: [],
|
|
1017
|
-
GENERIC: [],
|
|
1018
|
-
},
|
|
1019
|
-
LIQUID_ERROR_MSG: {
|
|
1020
|
-
...prev.LIQUID_ERROR_MSG,
|
|
1021
|
-
[changedDevice.toUpperCase()]: [],
|
|
1022
|
-
GENERIC: [],
|
|
1023
|
-
},
|
|
1024
|
-
}));
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
if (changedDevice) {
|
|
1028
|
-
// Only update the device that actually changed
|
|
1029
|
-
if (changedDevice.toUpperCase() === ANDROID && deviceContent?.android !== undefined) {
|
|
1030
|
-
setHtmlContentAndroid(deviceContent.android || '');
|
|
1031
|
-
} else if (changedDevice.toUpperCase() === IOS_CAPITAL && deviceContent?.ios !== undefined) {
|
|
1032
|
-
setHtmlContentIos(deviceContent.ios || '');
|
|
1033
|
-
}
|
|
1034
|
-
} else {
|
|
1035
|
-
// Fallback: update both if changedDevice not provided (for backward compatibility)
|
|
1036
|
-
// Only update if value actually changed to avoid unnecessary re-renders
|
|
1037
|
-
if (deviceContent?.android !== undefined) {
|
|
1038
|
-
setHtmlContentAndroid((prev) => {
|
|
1039
|
-
const newValue = deviceContent.android || '';
|
|
1040
|
-
return prev !== newValue ? newValue : prev;
|
|
1041
|
-
});
|
|
1042
|
-
}
|
|
1043
|
-
if (deviceContent?.ios !== undefined) {
|
|
1044
|
-
setHtmlContentIos((prev) => {
|
|
1045
|
-
const newValue = deviceContent.ios || '';
|
|
1046
|
-
return prev !== newValue ? newValue : prev;
|
|
1047
|
-
});
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
}, [ANDROID, IOS, setErrorMessage]);
|
|
1051
|
-
|
|
1052
|
-
// Handle HTML save from HTMLEditor
|
|
1053
|
-
const handleHtmlSave = useCallback((deviceContent) => {
|
|
1054
|
-
// Update state for both devices if present in the callback
|
|
1055
|
-
if (deviceContent?.android !== undefined) {
|
|
1056
|
-
setHtmlContentAndroid(deviceContent.android || '');
|
|
1057
|
-
}
|
|
1058
|
-
if (deviceContent?.ios !== undefined) {
|
|
1059
|
-
setHtmlContentIos(deviceContent.ios || '');
|
|
1060
|
-
}
|
|
1061
|
-
// Auto-save can trigger this, but we don't want to submit automatically
|
|
1062
|
-
// The user will click the Create/Update button to submit
|
|
1063
|
-
}, []);
|
|
1064
|
-
|
|
1065
822
|
const onDoneCallback = () => {
|
|
1066
823
|
if (isFullMode) {
|
|
1067
824
|
if (isEditFlow) {
|
|
@@ -1069,17 +826,15 @@ export const InApp = (props) => {
|
|
|
1069
826
|
}
|
|
1070
827
|
return onCreateInApp();
|
|
1071
828
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
value: payload,
|
|
829
|
+
return getFormData({
|
|
830
|
+
value: createPayload(),
|
|
1075
831
|
_id: params && params.id,
|
|
1076
832
|
validity: true,
|
|
1077
833
|
type: INAPP,
|
|
1078
834
|
});
|
|
1079
835
|
};
|
|
1080
836
|
|
|
1081
|
-
|
|
1082
|
-
const validationMiddleWare = async () => {
|
|
837
|
+
const liquidMiddleWare = () => {
|
|
1083
838
|
// Set up callbacks for validation results
|
|
1084
839
|
const onError = ({ standardErrors, liquidErrors }) => {
|
|
1085
840
|
setErrorMessage((prev) => ({
|
|
@@ -1092,200 +847,45 @@ export const InApp = (props) => {
|
|
|
1092
847
|
onDoneCallback();
|
|
1093
848
|
};
|
|
1094
849
|
|
|
1095
|
-
//
|
|
1096
|
-
const
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
return skipRegexes.some((regex) => regex.test(tag));
|
|
1124
|
-
},
|
|
1125
|
-
singleTab: getSingleTab(accountData),
|
|
1126
|
-
});
|
|
1127
|
-
} else if (hasTags) {
|
|
1128
|
-
// For non-liquid flow, validate tags using validateTags (only if tags are available)
|
|
1129
|
-
const androidContent = htmlContentAndroid || '';
|
|
1130
|
-
const iosContent = htmlContentIos || '';
|
|
1131
|
-
|
|
1132
|
-
const androidSupported = get(accountData, 'selectedWeChatAccount.configs.android') === DEVICE_SUPPORTED || get(editContent, 'ANDROID.deviceType') === ANDROID;
|
|
1133
|
-
const iosSupported = get(accountData, 'selectedWeChatAccount.configs.ios') === DEVICE_SUPPORTED || get(editContent, 'IOS.deviceType') === IOS_CAPITAL;
|
|
1134
|
-
|
|
1135
|
-
let hasErrors = false;
|
|
1136
|
-
const newErrors = {
|
|
1137
|
-
STANDARD_ERROR_MSG: {
|
|
1138
|
-
ANDROID: [],
|
|
1139
|
-
IOS: [],
|
|
1140
|
-
GENERIC: [],
|
|
1141
|
-
},
|
|
1142
|
-
LIQUID_ERROR_MSG: {
|
|
1143
|
-
ANDROID: [],
|
|
1144
|
-
IOS: [],
|
|
1145
|
-
GENERIC: [],
|
|
1146
|
-
},
|
|
1147
|
-
};
|
|
1148
|
-
|
|
1149
|
-
// Validate Android content
|
|
1150
|
-
if (androidSupported && androidContent && androidContent?.trim() !== '') {
|
|
1151
|
-
const validationResponse = validateTags({
|
|
1152
|
-
content: androidContent,
|
|
1153
|
-
tagsParam: tags,
|
|
1154
|
-
injectedTagsParams: injectedTags || {},
|
|
1155
|
-
location,
|
|
1156
|
-
tagModule: getDefaultTags,
|
|
1157
|
-
eventContextTags: metaEntities?.eventContextTags || [],
|
|
1158
|
-
}) || {};
|
|
1159
|
-
|
|
1160
|
-
if (validationResponse?.unsupportedTags?.length > 0) {
|
|
1161
|
-
hasErrors = true;
|
|
1162
|
-
newErrors.LIQUID_ERROR_MSG.ANDROID.push(
|
|
1163
|
-
formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
1164
|
-
unsupportedTags: validationResponse.unsupportedTags.join(", "),
|
|
1165
|
-
})
|
|
1166
|
-
);
|
|
1167
|
-
}
|
|
1168
|
-
if (validationResponse?.isBraceError) {
|
|
1169
|
-
hasErrors = true;
|
|
1170
|
-
newErrors.LIQUID_ERROR_MSG.ANDROID.push(
|
|
1171
|
-
formatMessage(globalMessages.unbalanacedCurlyBraces)
|
|
1172
|
-
);
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
// Validate iOS content
|
|
1177
|
-
if (iosSupported && iosContent && iosContent?.trim() !== '') {
|
|
1178
|
-
const validationResponse = validateTags({
|
|
1179
|
-
content: iosContent,
|
|
1180
|
-
tagsParam: tags,
|
|
1181
|
-
injectedTagsParams: injectedTags || {},
|
|
1182
|
-
location,
|
|
1183
|
-
tagModule: getDefaultTags,
|
|
1184
|
-
eventContextTags: metaEntities?.eventContextTags || [],
|
|
1185
|
-
}) || {};
|
|
1186
|
-
|
|
1187
|
-
if (validationResponse?.unsupportedTags?.length > 0) {
|
|
1188
|
-
hasErrors = true;
|
|
1189
|
-
newErrors.LIQUID_ERROR_MSG.IOS.push(
|
|
1190
|
-
formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
1191
|
-
unsupportedTags: validationResponse.unsupportedTags.join(", "),
|
|
1192
|
-
})
|
|
1193
|
-
);
|
|
1194
|
-
}
|
|
1195
|
-
if (validationResponse?.isBraceError) {
|
|
1196
|
-
hasErrors = true;
|
|
1197
|
-
newErrors.LIQUID_ERROR_MSG.IOS.push(
|
|
1198
|
-
formatMessage(globalMessages.unbalanacedCurlyBraces)
|
|
1199
|
-
);
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
if (hasErrors) {
|
|
1204
|
-
setErrorMessage(newErrors);
|
|
1205
|
-
} else {
|
|
1206
|
-
// No errors, proceed with submission
|
|
1207
|
-
onSuccess();
|
|
1208
|
-
}
|
|
1209
|
-
} else {
|
|
1210
|
-
// No tags available, skip validation and proceed directly
|
|
1211
|
-
onSuccess();
|
|
1212
|
-
}
|
|
850
|
+
// Validate the INAPP content
|
|
851
|
+
const payload = createPayload();
|
|
852
|
+
validateInAppContent(payload, {
|
|
853
|
+
currentTab: panes === ANDROID ? 1 : 2, // Convert ANDROID/IOS to tab numbers
|
|
854
|
+
onError,
|
|
855
|
+
onSuccess,
|
|
856
|
+
getLiquidTags: (content, callback) => globalActions.getLiquidTags(content, callback),
|
|
857
|
+
formatMessage,
|
|
858
|
+
messages: formBuilderMessages,
|
|
859
|
+
tagLookupMap: metaEntities?.tagLookupMap || {},
|
|
860
|
+
eventContextTags: metaEntities?.eventContextTags || [],
|
|
861
|
+
isLiquidFlow,
|
|
862
|
+
forwardedTags: {},
|
|
863
|
+
skipTags: (tag) => {
|
|
864
|
+
// Skip certain tags if needed
|
|
865
|
+
const skipRegexes = [
|
|
866
|
+
/dynamic_expiry_date_after_\d+_days\.FORMAT_\d/,
|
|
867
|
+
/unsubscribe\(#[a-zA-Z\d]{6}\)/,
|
|
868
|
+
/Link_to_[a-zA-z]/,
|
|
869
|
+
/SURVEY.*\.TOKEN/,
|
|
870
|
+
/^[A-Za-z].*\([a-zA-Z\d]*\)/,
|
|
871
|
+
];
|
|
872
|
+
|
|
873
|
+
return skipRegexes.some((regex) => regex.test(tag));
|
|
874
|
+
},
|
|
875
|
+
singleTab: getSingleTab(accountData),
|
|
876
|
+
});
|
|
1213
877
|
};
|
|
1214
878
|
|
|
1215
879
|
const isLiquidFlow = hasLiquidSupportFeature();
|
|
1216
|
-
|
|
1217
|
-
// Check template data to determine editor type (for render decision)
|
|
1218
|
-
const templateDetails = isFullMode ? editData?.templateDetails : templateData;
|
|
1219
|
-
const versions = templateDetails?.versions || {};
|
|
1220
|
-
const templateContent = get(versions, 'base.content', {});
|
|
1221
|
-
const androidContent = templateContent?.ANDROID || {};
|
|
1222
|
-
const iosContent = templateContent?.IOS || {};
|
|
1223
|
-
|
|
1224
|
-
// Check if this is a Bee editor template
|
|
1225
|
-
const isBEEeditor = get(androidContent, 'isBEEeditor') || get(iosContent, 'isBEEeditor');
|
|
1226
|
-
const androidTitle = androidContent?.title || '';
|
|
1227
|
-
const iosTitle = iosContent?.title || '';
|
|
1228
|
-
const isBeeFreeTemplate = (!isEmpty(androidTitle) && androidTitle.toLowerCase() === 'bee free template')
|
|
1229
|
-
|| (!isEmpty(iosTitle) && iosTitle.toLowerCase() === 'bee free template');
|
|
1230
|
-
|
|
1231
|
-
// Check if this is an HTML template from content data
|
|
1232
|
-
const androidType = androidContent?.type || '';
|
|
1233
|
-
const androidStyle = androidContent?.expandableDetails?.style || '';
|
|
1234
|
-
const iosType = iosContent?.type || '';
|
|
1235
|
-
const iosStyle = iosContent?.expandableDetails?.style || '';
|
|
1236
|
-
const isHTMLTemplateFromData = (androidType === INAPP_MEDIA_TYPES.HTML || androidStyle === BIG_HTML
|
|
1237
|
-
|| iosType === INAPP_MEDIA_TYPES.HTML || iosStyle === BIG_HTML)
|
|
1238
|
-
&& !isBEEeditor
|
|
1239
|
-
&& !isBeeFreeTemplate;
|
|
1240
|
-
|
|
1241
|
-
// Use state if available, otherwise fall back to direct data check
|
|
1242
|
-
const shouldUseHTMLEditor = isHTMLTemplate || isHTMLTemplateFromData;
|
|
1243
|
-
|
|
1244
|
-
// Only route to Bee editor if it's explicitly a Bee editor AND not an HTML template
|
|
1245
|
-
const shouldUseBeeEditor = (isBEEeditor || isBeeFreeTemplate) && !shouldUseHTMLEditor;
|
|
1246
|
-
|
|
1247
|
-
// Early returns to avoid nested ternary
|
|
1248
|
-
if (isEditInApp && getTemplateDetailsInProgress) {
|
|
1249
|
-
return <CapSpin spinning={getTemplateDetailsInProgress} />;
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
// Allow BEE editor in both full mode edit (isEditInApp) AND library mode edit (isEditFlow && !isFullMode)
|
|
1253
|
-
if ((isEditInApp || (isEditFlow && !isFullMode)) && shouldUseBeeEditor) {
|
|
1254
|
-
return (
|
|
1255
|
-
<InappAdvanced
|
|
1256
|
-
getFormData={getFormData}
|
|
1257
|
-
setIsLoadingContent={setIsLoadingContent}
|
|
1258
|
-
defaultData={{ "template-name": tempName }}
|
|
1259
|
-
location={{
|
|
1260
|
-
pathname: `/inapp/edit`,
|
|
1261
|
-
query,
|
|
1262
|
-
search: '',
|
|
1263
|
-
}}
|
|
1264
|
-
params={{ mode: inAppCreateMode, id: params.id }}
|
|
1265
|
-
isFullMode={isFullMode}
|
|
1266
|
-
isGetFormData={isGetFormData}
|
|
1267
|
-
showTemplateName={showTemplateName}
|
|
1268
|
-
route={{ name: "inapp" }}
|
|
1269
|
-
getDefaultTags={type}
|
|
1270
|
-
onValidationFail={onValidationFail}
|
|
1271
|
-
templateData={templateData}
|
|
1272
|
-
templateName={tempName}
|
|
1273
|
-
setTemplateName={setTempName}
|
|
1274
|
-
forwardedTags={forwardedTags}
|
|
1275
|
-
selectedOfferDetails={selectedOfferDetails}
|
|
1276
|
-
onCreateComplete={onCreateComplete}
|
|
1277
|
-
/>
|
|
1278
|
-
);
|
|
1279
|
-
}
|
|
1280
|
-
|
|
1281
880
|
return (
|
|
1282
881
|
<CapSpin spinning={spin || fetchingLiquidValidation} tip={fetchingLiquidValidation ? <FormattedMessage {...formBuilderMessages.liquidSpinText} /> : ""}>
|
|
1283
882
|
<CapRow className="cap-inapp-creatives">
|
|
1284
|
-
<CapColumn span={
|
|
1285
|
-
{
|
|
1286
|
-
{
|
|
883
|
+
<CapColumn span={14}>
|
|
884
|
+
{isFullMode && createModeContent}
|
|
885
|
+
{/* Creative layout type*/}
|
|
886
|
+
{(isFullMode || !isEditFlow) && (
|
|
1287
887
|
<>
|
|
1288
|
-
<CapRow>
|
|
888
|
+
<CapRow className="inapp-creative-layout">
|
|
1289
889
|
<CapHeading type="h4">
|
|
1290
890
|
<FormattedMessage {...messages.creativeLayout} />
|
|
1291
891
|
</CapHeading>
|
|
@@ -1302,64 +902,26 @@ export const InApp = (props) => {
|
|
|
1302
902
|
/>
|
|
1303
903
|
</>
|
|
1304
904
|
)}
|
|
1305
|
-
{
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
// Tag insertion is handled by HTMLEditor's CodeEditorPane at cursor position
|
|
1322
|
-
// Content updates will be propagated via onContentChange callback
|
|
1323
|
-
}}
|
|
1324
|
-
// Don't pass globalActions to prevent duplicate API calls
|
|
1325
|
-
// HTMLEditor will use onContextChange instead
|
|
1326
|
-
onContextChange={handleOnTagsContextChange}
|
|
1327
|
-
// Pass validation errors to HTMLEditor for display
|
|
1328
|
-
errors={errorMessage}
|
|
1329
|
-
isFullMode={isFullMode}
|
|
1330
|
-
data-test="inapp-html-editor"
|
|
1331
|
-
style={{ width: '138%' }}
|
|
1332
|
-
/>
|
|
1333
|
-
) : (
|
|
1334
|
-
<InappAdvanced
|
|
1335
|
-
getFormData={getFormData}
|
|
1336
|
-
setIsLoadingContent={setIsLoadingContent}
|
|
1337
|
-
defaultData={{ "template-name": tempName }}
|
|
1338
|
-
location={{
|
|
1339
|
-
pathname: `/inapp/create`,
|
|
1340
|
-
query,
|
|
1341
|
-
search: '',
|
|
1342
|
-
}}
|
|
1343
|
-
params={{ mode: inAppCreateMode }}
|
|
1344
|
-
isFullMode={isFullMode}
|
|
1345
|
-
isGetFormData={isGetFormData}
|
|
1346
|
-
showTemplateName={showTemplateName}
|
|
1347
|
-
route={{ name: "inapp" }}
|
|
1348
|
-
getDefaultTags={type}
|
|
1349
|
-
onValidationFail={onValidationFail}
|
|
1350
|
-
templateData={templateData}
|
|
1351
|
-
templateName={tempName}
|
|
1352
|
-
setTemplateName={setTempName}
|
|
1353
|
-
forwardedTags={forwardedTags}
|
|
1354
|
-
selectedOfferDetails={selectedOfferDetails}
|
|
1355
|
-
onCreateComplete={onCreateComplete}
|
|
1356
|
-
/>
|
|
1357
|
-
)}
|
|
905
|
+
{/* device tab */}
|
|
906
|
+
<CapTab
|
|
907
|
+
panes={PANES.filter(
|
|
908
|
+
(devicePane) => devicePane?.isSupported === true
|
|
909
|
+
)}
|
|
910
|
+
onChange={(value) => {
|
|
911
|
+
setPanes(value);
|
|
912
|
+
}}
|
|
913
|
+
activeKey={panes}
|
|
914
|
+
defaultActiveKey={panes}
|
|
915
|
+
className="inapp-template-device-tab"
|
|
916
|
+
/>
|
|
917
|
+
<div className="inapp-scroll-div" />
|
|
918
|
+
</CapColumn>
|
|
919
|
+
<CapColumn span={10} className="inapp-preview-container">
|
|
920
|
+
{getPreviewSection()}
|
|
1358
921
|
</CapColumn>
|
|
1359
922
|
</CapRow>
|
|
1360
|
-
{
|
|
1361
|
-
|
|
1362
|
-
shouldUseHTMLEditor && (
|
|
923
|
+
<div className={`inapp-footer ${!isFullMode && `inapp-footer-lib`}`}>
|
|
924
|
+
{
|
|
1363
925
|
<>
|
|
1364
926
|
{hasAnyErrors(errorMessage) && (
|
|
1365
927
|
<ErrorInfoNote
|
|
@@ -1367,28 +929,24 @@ export const InApp = (props) => {
|
|
|
1367
929
|
currentTab={panes}
|
|
1368
930
|
/>
|
|
1369
931
|
)}
|
|
1370
|
-
<
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
);
|
|
1389
|
-
})()}
|
|
1390
|
-
</CapButton>
|
|
1391
|
-
{/* {!isFullMode && ( */}
|
|
932
|
+
<CapButton
|
|
933
|
+
onClick={isLiquidFlow ? liquidMiddleWare : onDoneCallback}
|
|
934
|
+
disabled={isDisableDone(panes)}
|
|
935
|
+
className="inapp-create-btn"
|
|
936
|
+
>
|
|
937
|
+
{isEditFlow ? (
|
|
938
|
+
isFullMode ? (
|
|
939
|
+
<FormattedMessage {...messages.update} />
|
|
940
|
+
) : (
|
|
941
|
+
<FormattedMessage {...globalMessages.done} />
|
|
942
|
+
)
|
|
943
|
+
) : isFullMode ? (
|
|
944
|
+
<FormattedMessage {...messages.create} />
|
|
945
|
+
) : (
|
|
946
|
+
<FormattedMessage {...globalMessages.done} />
|
|
947
|
+
)}
|
|
948
|
+
</CapButton>
|
|
949
|
+
{/* {!isFullMode && ( */}
|
|
1392
950
|
<CapButton
|
|
1393
951
|
onClick={handleTestAndPreview}
|
|
1394
952
|
className="inapp-test-preview-btn"
|
|
@@ -1397,10 +955,10 @@ export const InApp = (props) => {
|
|
|
1397
955
|
>
|
|
1398
956
|
<FormattedMessage {...creativesMessages.testAndPreview} />
|
|
1399
957
|
</CapButton>
|
|
1400
|
-
|
|
1401
|
-
</div>
|
|
958
|
+
{/* )} */}
|
|
1402
959
|
</>
|
|
1403
|
-
|
|
960
|
+
}
|
|
961
|
+
</div>
|
|
1404
962
|
<TestAndPreviewSlidebox
|
|
1405
963
|
show={propsShowTestAndPreviewSlidebox || showTestAndPreviewSlidebox}
|
|
1406
964
|
onClose={handleCloseTestAndPreview}
|
|
@@ -1420,8 +978,7 @@ const mapStateToProps = createStructuredSelector({
|
|
|
1420
978
|
loadingTags: isLoadingMetaEntities(),
|
|
1421
979
|
injectedTags: setInjectedTags(),
|
|
1422
980
|
currentOrgDetails: selectCurrentOrgDetails(),
|
|
1423
|
-
fetchingLiquidValidation: selectLiquidStateDetails()
|
|
1424
|
-
getTemplateDetailsInProgress: makeSelectGetTemplateDetailsInProgress(),
|
|
981
|
+
fetchingLiquidValidation: selectLiquidStateDetails()
|
|
1425
982
|
});
|
|
1426
983
|
|
|
1427
984
|
const mapDispatchToProps = (dispatch) => ({
|