@capillarytech/creatives-library 8.0.242-alpha.0 → 8.0.242-alpha.1
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 +2 -1
- package/initialReducer.js +2 -0
- package/package.json +1 -1
- package/sagas/__tests__/assetPolling.test.js +74 -3
- package/sagas/assetPolling.js +8 -1
- package/services/api.js +10 -5
- package/services/tests/api.test.js +18 -0
- package/translations/en.json +0 -1
- package/utils/common.js +5 -0
- package/utils/commonUtils.js +14 -1
- package/utils/tests/commonUtil.test.js +224 -0
- package/utils/transformTemplateConfig.js +0 -10
- package/utils/transformerUtils.js +0 -42
- package/v2Components/CapDeviceContent/index.js +61 -56
- package/v2Components/CapImageUpload/constants.js +0 -2
- package/v2Components/CapImageUpload/index.js +14 -54
- package/v2Components/CapImageUpload/index.scss +1 -4
- package/v2Components/CapImageUpload/messages.js +0 -4
- package/v2Components/CapTagList/index.js +6 -1
- package/v2Components/CapTagListWithInput/index.js +5 -1
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
- package/v2Components/ErrorInfoNote/index.js +412 -72
- package/v2Components/ErrorInfoNote/messages.js +22 -0
- package/v2Components/ErrorInfoNote/style.scss +279 -2
- package/v2Components/HtmlEditor/HTMLEditor.js +210 -89
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1132 -133
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +17 -12
- package/v2Components/HtmlEditor/_htmlEditor.scss +8 -23
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +13 -101
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -139
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +1 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +10 -11
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +87 -62
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +362 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
- package/v2Components/HtmlEditor/constants.js +29 -20
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +95 -85
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +99 -101
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
- package/v2Components/HtmlEditor/utils/validationAdapter.js +34 -41
- package/v2Components/MobilePushPreviewV2/index.js +32 -7
- package/v2Components/TemplatePreview/_templatePreview.scss +44 -24
- package/v2Components/TemplatePreview/index.js +47 -32
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +31 -25
- package/v2Containers/App/constants.js +0 -5
- package/v2Containers/BeeEditor/index.js +82 -80
- package/v2Containers/BeePopupEditor/constants.js +10 -0
- package/v2Containers/BeePopupEditor/index.js +193 -0
- package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
- package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +0 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +148 -120
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +9 -3
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
- package/v2Containers/CreativesContainer/constants.js +1 -2
- package/v2Containers/CreativesContainer/index.js +173 -193
- package/v2Containers/CreativesContainer/messages.js +4 -4
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +36 -0
- package/v2Containers/Email/actions.js +7 -0
- package/v2Containers/Email/constants.js +5 -1
- package/v2Containers/Email/index.js +13 -0
- package/v2Containers/Email/messages.js +32 -0
- package/v2Containers/Email/reducer.js +12 -1
- package/v2Containers/Email/sagas.js +41 -6
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1045 -0
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +193 -7
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
- package/v2Containers/EmailWrapper/constants.js +2 -0
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +436 -67
- package/v2Containers/EmailWrapper/index.js +99 -23
- package/v2Containers/EmailWrapper/messages.js +61 -1
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +26 -1
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +111 -77
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
- package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
- package/v2Containers/InApp/actions.js +7 -0
- package/v2Containers/InApp/constants.js +20 -4
- package/v2Containers/InApp/index.js +800 -357
- package/v2Containers/InApp/index.scss +4 -3
- package/v2Containers/InApp/messages.js +7 -3
- package/v2Containers/InApp/reducer.js +21 -3
- package/v2Containers/InApp/sagas.js +29 -9
- package/v2Containers/InApp/selectors.js +25 -5
- package/v2Containers/InApp/tests/index.test.js +154 -50
- package/v2Containers/InApp/tests/reducer.test.js +34 -0
- package/v2Containers/InApp/tests/sagas.test.js +61 -9
- package/v2Containers/InApp/tests/selectors.test.js +612 -0
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
- package/v2Containers/InAppWrapper/constants.js +16 -0
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
- package/v2Containers/InAppWrapper/index.js +148 -0
- package/v2Containers/InAppWrapper/messages.js +49 -0
- package/v2Containers/InappAdvance/index.js +1099 -0
- package/v2Containers/InappAdvance/index.scss +10 -0
- package/v2Containers/InappAdvance/tests/index.test.js +448 -0
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -3
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -2
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -25
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -18
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -46
- package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +0 -4
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -8
- package/v2Containers/TagList/index.js +67 -1
- package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
- package/v2Containers/Templates/_templates.scss +56 -200
- package/v2Containers/Templates/actions.js +1 -2
- package/v2Containers/Templates/constants.js +0 -1
- package/v2Containers/Templates/index.js +124 -277
- package/v2Containers/Templates/messages.js +4 -24
- package/v2Containers/Templates/reducer.js +0 -2
- package/v2Containers/Templates/tests/index.test.js +0 -10
- package/v2Containers/TemplatesV2/index.js +2 -3
- package/v2Containers/TemplatesV2/messages.js +0 -4
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -132
- package/v2Components/CapImageUrlUpload/constants.js +0 -19
- package/v2Components/CapImageUrlUpload/index.js +0 -455
- package/v2Components/CapImageUrlUpload/index.scss +0 -35
- package/v2Components/CapImageUrlUpload/messages.js +0 -47
- package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -175
- package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
- package/v2Containers/WebPush/Create/components/ButtonList.js +0 -144
- 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 -80
- package/v2Containers/WebPush/Create/index.js +0 -1755
- package/v2Containers/WebPush/Create/index.scss +0 -123
- package/v2Containers/WebPush/Create/messages.js +0 -199
- package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -241
- package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -290
- package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -81
- package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -240
- package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -23
- package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -144
- 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/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/opera-icon.svg +0 -18
- package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -44
- package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -110
- package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
- package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -72
- package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -55
- package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -70
- package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -512
- package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -77
- package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -527
- package/v2Containers/WebPush/Create/preview/constants.js +0 -162
- package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -104
- package/v2Containers/WebPush/Create/preview/preview.scss +0 -409
- package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -300
- 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 -303
- 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 -188
- package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -106
- package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
- package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -75
- package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -174
- package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
- package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1077
- package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
- package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -943
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -128
- package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -121
- 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 -127
- package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -116
- package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
- package/v2Containers/WebPush/actions.js +0 -60
- package/v2Containers/WebPush/constants.js +0 -108
- 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
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
* Note: Uses injectIntl with forwardRef to provide direct access to CodeEditorPane via ref
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import React, {
|
|
15
|
+
import React, {
|
|
16
|
+
useRef, useCallback, useMemo, useState, useEffect,
|
|
17
|
+
} from 'react';
|
|
16
18
|
import PropTypes from 'prop-types';
|
|
17
|
-
import { Layout } from 'antd'; // Fallback - no Cap UI equivalent
|
|
18
19
|
import { injectIntl, intlShape } from 'react-intl';
|
|
19
20
|
|
|
20
21
|
// Cap UI Components (First Preference)
|
|
21
22
|
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
22
|
-
import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
|
|
23
23
|
import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
|
|
24
24
|
import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
|
|
25
25
|
import CapModal from '@capillarytech/cap-ui-library/CapModal';
|
|
@@ -40,7 +40,9 @@ import { useLayoutState } from './hooks/useLayoutState';
|
|
|
40
40
|
import { useValidation } from './hooks/useValidation';
|
|
41
41
|
|
|
42
42
|
// Constants
|
|
43
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
HTML_EDITOR_VARIANTS, DEVICE_TYPES, DEFAULT_HTML_CONTENT, TAG, EMBEDDED, DEFAULT, FULL, ALL, SMS, EMAIL,
|
|
45
|
+
} from './constants';
|
|
44
46
|
|
|
45
47
|
// Styles
|
|
46
48
|
import './_htmlEditor.scss';
|
|
@@ -61,6 +63,20 @@ const HTMLEditor = ({
|
|
|
61
63
|
showFullscreenButton = true,
|
|
62
64
|
autoSave = true,
|
|
63
65
|
autoSaveInterval = 30000, // 30 seconds
|
|
66
|
+
// Tag-related props - tags are fetched and managed by parent component (EmailHTMLEditor, INAPP, etc.)
|
|
67
|
+
tags = [],
|
|
68
|
+
injectedTags = {},
|
|
69
|
+
location,
|
|
70
|
+
eventContextTags = [],
|
|
71
|
+
selectedOfferDetails = [],
|
|
72
|
+
channel,
|
|
73
|
+
userLocale = 'en',
|
|
74
|
+
moduleFilterEnabled = true,
|
|
75
|
+
onTagContextChange, // Parent component handles tag fetching
|
|
76
|
+
onTagSelect = null,
|
|
77
|
+
onContextChange = null,
|
|
78
|
+
globalActions = null,
|
|
79
|
+
isLiquidEnabled = false, // Controls Liquid tab visibility in ValidationTabs
|
|
64
80
|
...props
|
|
65
81
|
}) => {
|
|
66
82
|
// Separate refs for main and modal editors to avoid conflicts
|
|
@@ -69,9 +85,7 @@ const HTMLEditor = ({
|
|
|
69
85
|
const [isFullscreenModalOpen, setIsFullscreenModalOpen] = useState(false);
|
|
70
86
|
|
|
71
87
|
// Get the currently active editor ref based on fullscreen state
|
|
72
|
-
const getActiveEditorRef = useCallback(() =>
|
|
73
|
-
return isFullscreenModalOpen ? modalEditorRef : mainEditorRef;
|
|
74
|
-
}, [isFullscreenModalOpen]);
|
|
88
|
+
const getActiveEditorRef = useCallback(() => isFullscreenModalOpen ? modalEditorRef : mainEditorRef, [isFullscreenModalOpen]);
|
|
75
89
|
|
|
76
90
|
// Initialize custom hooks for state management - always call both hooks to follow Rules of Hooks
|
|
77
91
|
const isEmailVariant = variant === HTML_EDITOR_VARIANTS.EMAIL;
|
|
@@ -80,7 +94,7 @@ const HTMLEditor = ({
|
|
|
80
94
|
autoSave: isEmailVariant ? autoSave : false,
|
|
81
95
|
autoSaveInterval,
|
|
82
96
|
onSave: isEmailVariant ? onSave : null,
|
|
83
|
-
onChange: isEmailVariant ? onContentChange : null
|
|
97
|
+
onChange: isEmailVariant ? onContentChange : null,
|
|
84
98
|
};
|
|
85
99
|
|
|
86
100
|
const emailContent = useEditorContent(
|
|
@@ -97,7 +111,7 @@ const HTMLEditor = ({
|
|
|
97
111
|
// Convert string content to device-specific format
|
|
98
112
|
inAppInitialContent = {
|
|
99
113
|
[DEVICE_TYPES.ANDROID]: initialContent,
|
|
100
|
-
[DEVICE_TYPES.IOS]: initialContent
|
|
114
|
+
[DEVICE_TYPES.IOS]: initialContent,
|
|
101
115
|
};
|
|
102
116
|
} else {
|
|
103
117
|
// Use provided device-specific content
|
|
@@ -109,7 +123,7 @@ const HTMLEditor = ({
|
|
|
109
123
|
autoSave: isInAppVariant ? autoSave : false,
|
|
110
124
|
autoSaveInterval,
|
|
111
125
|
onSave: isInAppVariant ? onSave : null,
|
|
112
|
-
onChange: isInAppVariant ? onContentChange : null
|
|
126
|
+
onChange: isInAppVariant ? onContentChange : null,
|
|
113
127
|
};
|
|
114
128
|
|
|
115
129
|
const inAppContent = useInAppContent(inAppInitialContent, inAppOptions);
|
|
@@ -117,6 +131,64 @@ const HTMLEditor = ({
|
|
|
117
131
|
// Use appropriate content hook based on variant
|
|
118
132
|
const content = variant === HTML_EDITOR_VARIANTS.EMAIL ? emailContent : inAppContent;
|
|
119
133
|
|
|
134
|
+
// Update content when initialContent prop changes (for edit mode)
|
|
135
|
+
// This ensures the editor updates when template data loads
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
if (isEmailVariant && emailContent && initialContent !== undefined && initialContent !== null) {
|
|
138
|
+
// Only update if content is different to avoid unnecessary updates
|
|
139
|
+
if (emailContent.content !== initialContent) {
|
|
140
|
+
emailContent.updateContent(initialContent, true); // immediate update
|
|
141
|
+
}
|
|
142
|
+
} else if (isInAppVariant && inAppContent && initialContent !== undefined && initialContent !== null) {
|
|
143
|
+
// Handle InApp variant updates
|
|
144
|
+
const contentToUpdate = typeof initialContent === 'string'
|
|
145
|
+
? { [DEVICE_TYPES.ANDROID]: initialContent, [DEVICE_TYPES.IOS]: initialContent }
|
|
146
|
+
: initialContent;
|
|
147
|
+
if (inAppContent.updateContent) {
|
|
148
|
+
const currentContent = inAppContent.getDeviceContent?.(inAppContent.activeDevice);
|
|
149
|
+
const newContent = contentToUpdate[inAppContent.activeDevice] || contentToUpdate[DEVICE_TYPES.ANDROID] || '';
|
|
150
|
+
if (currentContent !== newContent) {
|
|
151
|
+
inAppContent.updateContent(newContent, true);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}, [initialContent, isEmailVariant, isInAppVariant]);
|
|
156
|
+
// Handle context change for tag API calls
|
|
157
|
+
// If variant is INAPP, use SMS layout; otherwise use the channel (EMAIL)
|
|
158
|
+
const handleContextChange = useCallback((contextData) => {
|
|
159
|
+
// If onContextChange is provided, use it instead of making our own API call
|
|
160
|
+
// This prevents duplicate API calls when parent component handles tag fetching
|
|
161
|
+
if (onContextChange) {
|
|
162
|
+
onContextChange(contextData);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Only make API call if onContextChange is not provided and globalActions is available
|
|
167
|
+
if (!globalActions || !location) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const { type } = location.query || {};
|
|
172
|
+
const tempData = (contextData || '').toLowerCase();
|
|
173
|
+
const isEmbedded = type === EMBEDDED;
|
|
174
|
+
const embedded = isEmbedded ? type : FULL;
|
|
175
|
+
const context = tempData === ALL ? DEFAULT : tempData;
|
|
176
|
+
|
|
177
|
+
// Determine layout: INAPP variant uses SMS, EMAIL variant uses EMAIL
|
|
178
|
+
const layout = variant === HTML_EDITOR_VARIANTS.INAPP ? SMS : EMAIL;
|
|
179
|
+
|
|
180
|
+
const query = {
|
|
181
|
+
layout,
|
|
182
|
+
type: TAG,
|
|
183
|
+
context,
|
|
184
|
+
embedded,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// Call the API via Redux action - this will trigger the saga which calls Api.fetchSchemaForEntity
|
|
188
|
+
// The API endpoint will be: /meta/TAG?query={...}
|
|
189
|
+
globalActions.fetchSchemaForEntity(query);
|
|
190
|
+
}, [variant, globalActions, location, onContextChange]);
|
|
191
|
+
|
|
120
192
|
// Destructure content properties for cleaner access throughout component
|
|
121
193
|
const {
|
|
122
194
|
activeDevice,
|
|
@@ -124,14 +196,14 @@ const HTMLEditor = ({
|
|
|
124
196
|
switchDevice,
|
|
125
197
|
toggleContentSync,
|
|
126
198
|
getDeviceContent,
|
|
127
|
-
markAsSaved
|
|
199
|
+
markAsSaved,
|
|
128
200
|
} = content || {};
|
|
129
201
|
|
|
130
202
|
const layout = useLayoutState({
|
|
131
203
|
splitSizes: [50, 50],
|
|
132
204
|
viewMode: 'desktop',
|
|
133
205
|
mobileWidth: 375,
|
|
134
|
-
isFullscreen: false
|
|
206
|
+
isFullscreen: false,
|
|
135
207
|
});
|
|
136
208
|
|
|
137
209
|
// Get current content for validation based on variant
|
|
@@ -158,7 +230,7 @@ const HTMLEditor = ({
|
|
|
158
230
|
'sanitizer.productionValidHtml': messages.sanitizer.productionValidHtml,
|
|
159
231
|
'sanitizer.productionSanitized': messages.sanitizer.productionSanitized,
|
|
160
232
|
'sanitizer.productionInlineCss': messages.sanitizer.productionInlineCss,
|
|
161
|
-
'sanitizer.productionLargeContent': messages.sanitizer.productionLargeContent
|
|
233
|
+
'sanitizer.productionLargeContent': messages.sanitizer.productionLargeContent,
|
|
162
234
|
};
|
|
163
235
|
|
|
164
236
|
const messageObj = messageMap[messageKey];
|
|
@@ -179,7 +251,7 @@ const HTMLEditor = ({
|
|
|
179
251
|
'validator.largeImageDetected': messages.validator.largeImageDetected,
|
|
180
252
|
'validator.unclosedCssRule': messages.validator.unclosedCssRule,
|
|
181
253
|
'validator.emptyCssRule': messages.validator.emptyCssRule,
|
|
182
|
-
'validator.cssValidationFailed': messages.validator.cssValidationFailed
|
|
254
|
+
'validator.cssValidationFailed': messages.validator.cssValidationFailed,
|
|
183
255
|
};
|
|
184
256
|
|
|
185
257
|
const messageObj = messageMap[messageKey];
|
|
@@ -190,57 +262,69 @@ const HTMLEditor = ({
|
|
|
190
262
|
enableRealTime: true,
|
|
191
263
|
debounceMs: 500,
|
|
192
264
|
enableSanitization: true,
|
|
193
|
-
securityLevel: 'standard'
|
|
265
|
+
securityLevel: 'standard',
|
|
194
266
|
}, formatSanitizerMessage, formatValidatorMessage);
|
|
195
267
|
|
|
196
268
|
// Handle label insertion at cursor position
|
|
269
|
+
// Note: This is called for notification purposes only when tag is inserted via CodeEditorPane
|
|
270
|
+
// The actual insertion happens in CodeEditorPane.handleTagSelect
|
|
197
271
|
const handleLabelInsert = useCallback((label, position) => {
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
CapNotification.error({
|
|
214
|
-
message: intl.formatMessage(messages.labelInsertError),
|
|
215
|
-
description: intl.formatMessage(messages.editorMethodNotAvailable),
|
|
216
|
-
duration: 4
|
|
217
|
-
});
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
try {
|
|
222
|
-
// Get current cursor position or use provided position
|
|
223
|
-
const cursor = position !== undefined
|
|
224
|
-
? position
|
|
225
|
-
: (typeof editor?.getCursor === 'function' ? editor.getCursor() : 0);
|
|
226
|
-
|
|
227
|
-
// Insert label at cursor position
|
|
228
|
-
editor.insertText(label, cursor);
|
|
272
|
+
// If position is explicitly null, it means the editor wasn't ready when tag was selected
|
|
273
|
+
// In this case, CodeEditorPane couldn't insert the tag, so we should try here
|
|
274
|
+
if (position === null) {
|
|
275
|
+
// With injectIntl({ forwardRef: true }), ref points directly to CodeEditorPane
|
|
276
|
+
const activeEditorRef = getActiveEditorRef();
|
|
277
|
+
const editor = activeEditorRef.current;
|
|
278
|
+
|
|
279
|
+
if (!editor) {
|
|
280
|
+
CapNotification.warning({
|
|
281
|
+
message: intl.formatMessage(messages.labelInsertError),
|
|
282
|
+
description: intl.formatMessage(messages.editorNotReady),
|
|
283
|
+
duration: 3,
|
|
284
|
+
});
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
229
287
|
|
|
230
|
-
//
|
|
231
|
-
editor?.
|
|
288
|
+
// Check if the required methods exist
|
|
289
|
+
if (typeof editor?.insertText !== 'function') {
|
|
290
|
+
CapNotification.error({
|
|
291
|
+
message: intl.formatMessage(messages.labelInsertError),
|
|
292
|
+
description: intl.formatMessage(messages.editorMethodNotAvailable),
|
|
293
|
+
duration: 4,
|
|
294
|
+
});
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
232
297
|
|
|
233
|
-
|
|
298
|
+
try {
|
|
299
|
+
// Get current cursor position
|
|
300
|
+
const cursor = typeof editor?.getCursor === 'function' ? editor.getCursor() : 0;
|
|
301
|
+
|
|
302
|
+
// Insert label at cursor position
|
|
303
|
+
editor.insertText(label, cursor);
|
|
304
|
+
|
|
305
|
+
// Focus the editor if focus method is available
|
|
306
|
+
editor?.focus?.();
|
|
307
|
+
|
|
308
|
+
// Show success notification
|
|
309
|
+
CapNotification.success({
|
|
310
|
+
message: intl.formatMessage(messages.labelInserted),
|
|
311
|
+
description: intl.formatMessage(messages.labelInsertedDescription, { label }),
|
|
312
|
+
duration: 2,
|
|
313
|
+
});
|
|
314
|
+
} catch (error) {
|
|
315
|
+
CapNotification.error({
|
|
316
|
+
message: intl.formatMessage(messages.labelInsertError),
|
|
317
|
+
description: error.message,
|
|
318
|
+
duration: 4,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
// Tag was already inserted by CodeEditorPane (position is a valid number)
|
|
323
|
+
// Just show success notification - no need to access editor
|
|
234
324
|
CapNotification.success({
|
|
235
325
|
message: intl.formatMessage(messages.labelInserted),
|
|
236
326
|
description: intl.formatMessage(messages.labelInsertedDescription, { label }),
|
|
237
|
-
duration: 2
|
|
238
|
-
});
|
|
239
|
-
} catch (error) {
|
|
240
|
-
CapNotification.error({
|
|
241
|
-
message: intl.formatMessage(messages.labelInsertError),
|
|
242
|
-
description: error.message,
|
|
243
|
-
duration: 4
|
|
327
|
+
duration: 2,
|
|
244
328
|
});
|
|
245
329
|
}
|
|
246
330
|
}, [intl, getActiveEditorRef]);
|
|
@@ -259,13 +343,13 @@ const HTMLEditor = ({
|
|
|
259
343
|
|
|
260
344
|
CapNotification.success({
|
|
261
345
|
message: intl.formatMessage(messages.contentSaved),
|
|
262
|
-
duration: 2
|
|
346
|
+
duration: 2,
|
|
263
347
|
});
|
|
264
348
|
} catch (error) {
|
|
265
349
|
CapNotification.error({
|
|
266
350
|
message: intl.formatMessage(messages.saveError),
|
|
267
351
|
description: error.message,
|
|
268
|
-
duration: 4
|
|
352
|
+
duration: 4,
|
|
269
353
|
});
|
|
270
354
|
}
|
|
271
355
|
}, [content, onSave, intl, markAsSaved]);
|
|
@@ -307,6 +391,7 @@ const HTMLEditor = ({
|
|
|
307
391
|
content,
|
|
308
392
|
layout,
|
|
309
393
|
validation,
|
|
394
|
+
isLiquidEnabled,
|
|
310
395
|
editorRef: getActiveEditorRef(),
|
|
311
396
|
handleLabelInsert,
|
|
312
397
|
handleSave,
|
|
@@ -319,13 +404,14 @@ const HTMLEditor = ({
|
|
|
319
404
|
switchDevice,
|
|
320
405
|
toggleContentSync,
|
|
321
406
|
getDeviceContent,
|
|
322
|
-
layoutType
|
|
323
|
-
})
|
|
407
|
+
layoutType,
|
|
408
|
+
}),
|
|
324
409
|
}), [
|
|
325
410
|
variant,
|
|
326
411
|
content,
|
|
327
412
|
layout,
|
|
328
413
|
validation,
|
|
414
|
+
isLiquidEnabled,
|
|
329
415
|
getActiveEditorRef,
|
|
330
416
|
handleLabelInsert,
|
|
331
417
|
handleSave,
|
|
@@ -336,7 +422,7 @@ const HTMLEditor = ({
|
|
|
336
422
|
switchDevice,
|
|
337
423
|
toggleContentSync,
|
|
338
424
|
getDeviceContent,
|
|
339
|
-
layoutType
|
|
425
|
+
layoutType,
|
|
340
426
|
]);
|
|
341
427
|
|
|
342
428
|
// Loading state
|
|
@@ -387,19 +473,23 @@ const HTMLEditor = ({
|
|
|
387
473
|
ref={mainEditorRef}
|
|
388
474
|
readOnly={readOnly}
|
|
389
475
|
onLabelInsert={handleLabelInsert}
|
|
476
|
+
onErrorClick={handleValidationErrorClick}
|
|
477
|
+
tags={tags}
|
|
478
|
+
injectedTags={injectedTags}
|
|
479
|
+
location={location}
|
|
480
|
+
eventContextTags={eventContextTags}
|
|
481
|
+
selectedOfferDetails={selectedOfferDetails}
|
|
482
|
+
channel={channel}
|
|
483
|
+
userLocale={userLocale}
|
|
484
|
+
moduleFilterEnabled={moduleFilterEnabled}
|
|
485
|
+
onTagContextChange={onTagContextChange}
|
|
486
|
+
onTagSelect={onTagSelect}
|
|
487
|
+
onContextChange={handleContextChange}
|
|
390
488
|
/>
|
|
391
489
|
|
|
392
490
|
{/* Preview Pane */}
|
|
393
491
|
<PreviewPane />
|
|
394
492
|
</SplitContainer>
|
|
395
|
-
|
|
396
|
-
{/* Validation Display - Full Width Below Split Container */}
|
|
397
|
-
<ValidationErrorDisplay
|
|
398
|
-
validation={validation}
|
|
399
|
-
onErrorClick={handleValidationErrorClick}
|
|
400
|
-
variant={variant}
|
|
401
|
-
className="html-editor-validation"
|
|
402
|
-
/>
|
|
403
493
|
</CapRow>
|
|
404
494
|
|
|
405
495
|
{/* Fullscreen Modal */}
|
|
@@ -411,17 +501,17 @@ const HTMLEditor = ({
|
|
|
411
501
|
maskClosable={false}
|
|
412
502
|
centered
|
|
413
503
|
closable={false}
|
|
414
|
-
width=
|
|
504
|
+
width="90vw"
|
|
415
505
|
className="html-editor-fullscreen-modal"
|
|
416
506
|
>
|
|
417
507
|
<CapRow className="html-editor-fullscreen">
|
|
418
508
|
{/* Editor Toolbar - Conditional based on variant */}
|
|
419
509
|
{variant === HTML_EDITOR_VARIANTS.EMAIL ? (
|
|
420
510
|
<EditorToolbar
|
|
421
|
-
showFullscreenButton
|
|
511
|
+
showFullscreenButton // Show fullscreen button in modal to allow closing
|
|
422
512
|
onLabelInsert={handleLabelInsert}
|
|
423
513
|
onSave={handleSave}
|
|
424
|
-
isFullscreenMode
|
|
514
|
+
isFullscreenMode
|
|
425
515
|
onToggleFullscreen={handleCloseFullscreen} // Close modal when clicked in fullscreen mode
|
|
426
516
|
/>
|
|
427
517
|
) : (
|
|
@@ -434,10 +524,10 @@ const HTMLEditor = ({
|
|
|
434
524
|
onKeepContentSameChange={toggleContentSync}
|
|
435
525
|
/>
|
|
436
526
|
<EditorToolbar
|
|
437
|
-
showFullscreenButton
|
|
527
|
+
showFullscreenButton // Show fullscreen button in modal to allow closing
|
|
438
528
|
onLabelInsert={handleLabelInsert}
|
|
439
529
|
onSave={handleSave}
|
|
440
|
-
isFullscreenMode
|
|
530
|
+
isFullscreenMode
|
|
441
531
|
onToggleFullscreen={handleCloseFullscreen} // Close modal when clicked in fullscreen mode
|
|
442
532
|
variant={variant}
|
|
443
533
|
showTitle={false} // Hide title in InApp variant
|
|
@@ -452,21 +542,23 @@ const HTMLEditor = ({
|
|
|
452
542
|
<CodeEditorPane
|
|
453
543
|
ref={modalEditorRef}
|
|
454
544
|
readOnly={readOnly}
|
|
455
|
-
isFullscreenMode
|
|
545
|
+
isFullscreenMode
|
|
456
546
|
onLabelInsert={handleLabelInsert}
|
|
547
|
+
onErrorClick={handleValidationErrorClick}
|
|
548
|
+
tags={tags}
|
|
549
|
+
injectedTags={injectedTags}
|
|
550
|
+
location={location}
|
|
551
|
+
eventContextTags={eventContextTags}
|
|
552
|
+
selectedOfferDetails={selectedOfferDetails}
|
|
553
|
+
channel={channel}
|
|
554
|
+
userLocale={userLocale}
|
|
555
|
+
moduleFilterEnabled={moduleFilterEnabled}
|
|
556
|
+
onTagContextChange={onTagContextChange}
|
|
457
557
|
/>
|
|
458
558
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
{/* Validation Display in Modal */}
|
|
464
|
-
<ValidationErrorDisplay
|
|
465
|
-
validation={validation}
|
|
466
|
-
onErrorClick={handleValidationErrorClick}
|
|
467
|
-
variant={variant}
|
|
468
|
-
className="html-editor-validation"
|
|
469
|
-
/>
|
|
559
|
+
{/* Preview Pane */}
|
|
560
|
+
<PreviewPane isFullscreenMode isModalContext />
|
|
561
|
+
</SplitContainer>
|
|
470
562
|
</CapRow>
|
|
471
563
|
</CapRow>
|
|
472
564
|
</CapModal>
|
|
@@ -481,7 +573,7 @@ HTMLEditor.propTypes = {
|
|
|
481
573
|
layoutType: PropTypes.string, // Layout type for InApp variant
|
|
482
574
|
initialContent: PropTypes.oneOfType([
|
|
483
575
|
PropTypes.string,
|
|
484
|
-
PropTypes.objectOf(PropTypes.string) // Per-device content for INAPP variant
|
|
576
|
+
PropTypes.objectOf(PropTypes.string), // Per-device content for INAPP variant
|
|
485
577
|
]),
|
|
486
578
|
onSave: PropTypes.func,
|
|
487
579
|
onContentChange: PropTypes.func,
|
|
@@ -489,11 +581,26 @@ HTMLEditor.propTypes = {
|
|
|
489
581
|
readOnly: PropTypes.bool,
|
|
490
582
|
showFullscreenButton: PropTypes.bool,
|
|
491
583
|
autoSave: PropTypes.bool,
|
|
492
|
-
autoSaveInterval: PropTypes.number
|
|
584
|
+
autoSaveInterval: PropTypes.number,
|
|
585
|
+
// Tag-related props - tags are fetched and managed by parent component
|
|
586
|
+
tags: PropTypes.array,
|
|
587
|
+
injectedTags: PropTypes.object,
|
|
588
|
+
location: PropTypes.object,
|
|
589
|
+
eventContextTags: PropTypes.array,
|
|
590
|
+
selectedOfferDetails: PropTypes.array,
|
|
591
|
+
channel: PropTypes.string,
|
|
592
|
+
userLocale: PropTypes.string,
|
|
593
|
+
moduleFilterEnabled: PropTypes.bool,
|
|
594
|
+
onTagContextChange: PropTypes.func, // Required - parent must handle tag fetching
|
|
595
|
+
onTagSelect: PropTypes.func,
|
|
596
|
+
onContextChange: PropTypes.func, // Deprecated: use globalActions instead
|
|
597
|
+
globalActions: PropTypes.object,
|
|
598
|
+
isLiquidEnabled: PropTypes.bool, // Controls Liquid tab visibility in validation
|
|
493
599
|
};
|
|
494
600
|
|
|
495
601
|
HTMLEditor.defaultProps = {
|
|
496
602
|
variant: HTML_EDITOR_VARIANTS.EMAIL, // Default to email variant
|
|
603
|
+
layoutType: null,
|
|
497
604
|
initialContent: null, // Will use default from useEditorContent hook
|
|
498
605
|
onSave: null,
|
|
499
606
|
onContentChange: null,
|
|
@@ -501,7 +608,21 @@ HTMLEditor.defaultProps = {
|
|
|
501
608
|
readOnly: false,
|
|
502
609
|
showFullscreenButton: true,
|
|
503
610
|
autoSave: true,
|
|
504
|
-
autoSaveInterval: 30000
|
|
611
|
+
autoSaveInterval: 30000,
|
|
612
|
+
// Tag-related defaults - tags are fetched and managed by parent component
|
|
613
|
+
tags: [],
|
|
614
|
+
injectedTags: {},
|
|
615
|
+
location: null,
|
|
616
|
+
eventContextTags: [],
|
|
617
|
+
selectedOfferDetails: [],
|
|
618
|
+
channel: null,
|
|
619
|
+
userLocale: 'en',
|
|
620
|
+
moduleFilterEnabled: true,
|
|
621
|
+
onTagContextChange: null, // Parent component should provide this
|
|
622
|
+
onTagSelect: null,
|
|
623
|
+
onContextChange: null,
|
|
624
|
+
globalActions: null, // Redux actions for API calls
|
|
625
|
+
isLiquidEnabled: false,
|
|
505
626
|
};
|
|
506
627
|
|
|
507
628
|
// Export with forwardRef to allow direct access to CodeEditorPane via ref
|