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