@capillarytech/creatives-library 9.0.61 → 9.0.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constants/unified.js +8 -2
- package/package.json +1 -1
- package/services/api.js +5 -0
- package/services/tests/api.test.js +44 -0
- package/utils/common.js +8 -0
- package/utils/downloadFile.js +57 -0
- package/utils/tests/downloadFile.test.js +219 -0
- package/v2Components/FormBuilder/Classic.js +43 -9
- package/v2Components/FormBuilder/Functional/FormBuilderShell.js +324 -69
- package/v2Components/FormBuilder/Functional/channels/mobilepush/buildSubmitPayload.js +10 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/config.js +75 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/getEditorErrorDescriptor.js +74 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/index.js +28 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/modals.js +21 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/runSubmitPipeline.js +45 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/getEditorErrorDescriptor.test.js +162 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/modals.test.js +37 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/runSubmitPipeline.test.js +70 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/validate.test.js +274 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/validate.js +251 -0
- package/v2Components/FormBuilder/Functional/channels/registry.js +2 -0
- package/v2Components/FormBuilder/Functional/constants.js +46 -8
- package/v2Components/FormBuilder/Functional/core/schema/initializeFormState.js +175 -28
- package/v2Components/FormBuilder/Functional/core/store/formReducer.js +75 -6
- package/v2Components/FormBuilder/Functional/core/store/toLegacyFormData.js +10 -20
- package/v2Components/FormBuilder/Functional/layout/FieldSlot.js +9 -1
- package/v2Components/FormBuilder/Functional/layout/SchemaForm.js +20 -3
- package/v2Components/FormBuilder/Functional/layout/Section.js +6 -1
- package/v2Components/FormBuilder/Functional/layout/TabsContainer.js +85 -0
- package/v2Components/FormBuilder/Functional/renderers/mpushRenderers.js +451 -0
- package/v2Components/FormBuilder/Functional/tests/fieldSlot.test.js +9 -2
- package/v2Components/FormBuilder/Functional/tests/manual.typingPerf.test.js +135 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.crossFlowParity.test.js +430 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.ctaFlows.parity.test.js +320 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.editContainer.parity.test.js +148 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.engine.test.js +306 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.libraryValidity.parity.test.js +152 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.shellEvents.test.js +200 -0
- package/v2Components/FormBuilder/Functional/tests/mpushRenderers.test.js +382 -0
- package/v2Components/FormBuilder/Functional/tests/schemaForm.test.js +17 -0
- package/v2Components/FormBuilder/Functional/tests/tabsContainer.test.js +112 -0
- package/v2Components/FormBuilder/_formBuilder.scss +11 -0
- package/v2Components/FormBuilder/index.js +27 -17
- package/v2Components/FormBuilder/tests/entryGate.test.js +90 -7
- package/v2Components/FormBuilder/tests/mpush.characterization.test.js +459 -0
- package/v2Containers/BeeEditor/index.js +8 -0
- package/v2Containers/Email/index.js +118 -16
- package/v2Containers/Email/initialSchema.js +25 -3
- package/v2Containers/Email/messages.js +16 -0
- package/v2Containers/Email/tests/index.test.js +597 -0
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +55 -1
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +141 -0
- package/v2Containers/EmailWrapper/components/_emailHTMLEditor.scss +11 -0
- package/v2Containers/Templates/index.js +53 -0
- package/v2Containers/Templates/messages.js +8 -0
- package/v2Containers/Templates/tests/index.test.js +170 -0
|
@@ -21,6 +21,7 @@ import * as templatesActions from '../Templates/actions';
|
|
|
21
21
|
import {makeSelectEmail} from './selectors';
|
|
22
22
|
import { makeSelectTemplates } from '../Templates/selectors';
|
|
23
23
|
import messages from './messages';
|
|
24
|
+
import { sanitizeFileName, exportEmailTemplateHtml, getExportHtmlDisabledTooltip } from '../../utils/downloadFile';
|
|
24
25
|
import * as globalActions from '../Cap/actions';
|
|
25
26
|
// import PageHeader from '../../v2Components/PageHeader';
|
|
26
27
|
import './_email.scss';
|
|
@@ -37,7 +38,7 @@ import { FONT_COLOR_05 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
|
37
38
|
import { gtmPush } from '../../utils/gtmTrackers';
|
|
38
39
|
const {CapCustomCardList} = CapCustomCard;
|
|
39
40
|
import {storeS3FileSizeDetails, CREATIVES_S3_ASSET_FILESIZES} from '../../utils/cdnTransformation';
|
|
40
|
-
import { CUSTOMER_BARCODE_TAG } from '../../constants/unified';
|
|
41
|
+
import { CUSTOMER_BARCODE_TAG, EXPORT_HTML_LABEL_ID, DEFAULT_LOCALE, DISPLAY_NONE } from '../../constants/unified';
|
|
41
42
|
|
|
42
43
|
import { containsBase64Images } from '../../utils/content';
|
|
43
44
|
import injectReducer from '../../utils/injectReducer';
|
|
@@ -49,6 +50,10 @@ import TestAndPreviewSlidebox from '../../v2Components/TestAndPreviewSlidebox';
|
|
|
49
50
|
export class Email extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
50
51
|
constructor(props) {
|
|
51
52
|
super(props);
|
|
53
|
+
// Baseline content (set in componentWillReceiveProps) to detect a real edit vs. a resync and permanently lock Export HTML.
|
|
54
|
+
this.originalContentCaptured = false;
|
|
55
|
+
this.originalBaseTemplateContent = undefined;
|
|
56
|
+
|
|
52
57
|
this.state = {
|
|
53
58
|
loadingStatus: 0,
|
|
54
59
|
formData: {},
|
|
@@ -85,6 +90,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
85
90
|
saveObj: {},
|
|
86
91
|
showEdmEmailTemplates: false,
|
|
87
92
|
editDataSet: false,
|
|
93
|
+
exportHtmlContentLocked: false,
|
|
88
94
|
languageDataSet: false,
|
|
89
95
|
addLanguageType: '',
|
|
90
96
|
startValidation: false,
|
|
@@ -157,6 +163,9 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
157
163
|
"switch-editor-label": {
|
|
158
164
|
switchEditor: this.switchEditor,
|
|
159
165
|
},
|
|
166
|
+
[EXPORT_HTML_LABEL_ID]: {
|
|
167
|
+
exportHtml: this.exportHtml,
|
|
168
|
+
},
|
|
160
169
|
"pane": {
|
|
161
170
|
onTabChange: this.onTabChange,
|
|
162
171
|
},
|
|
@@ -459,6 +468,13 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
459
468
|
}
|
|
460
469
|
}
|
|
461
470
|
|
|
471
|
+
if (this.state.isEdit && !this.originalContentCaptured && !_.isEmpty(nextProps.Email.templateDetails)) {
|
|
472
|
+
this.originalContentCaptured = true;
|
|
473
|
+
const baseLanguageForCapture = nextProps.currentOrgDetails?.basic_details?.base_language || DEFAULT_LOCALE;
|
|
474
|
+
const baseVersionForCapture = nextProps.Email.templateDetails.versions?.base?.[baseLanguageForCapture] || {};
|
|
475
|
+
this.originalBaseTemplateContent = baseVersionForCapture['template-content'];
|
|
476
|
+
}
|
|
477
|
+
|
|
462
478
|
if (this.state.isEdit && !this.state.editDataSet && !_.isEmpty(nextProps.Email.templateDetails) && !_.isEmpty(this.state.schema)) {
|
|
463
479
|
this.setState({editDataSet: true}, () => {
|
|
464
480
|
this.setEditData(nextProps.Email.templateDetails);
|
|
@@ -523,17 +539,16 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
523
539
|
col.style.display = isDragDropForHide ? 'none' : '';
|
|
524
540
|
}
|
|
525
541
|
if (col.id === 'tab-options-popover') {
|
|
526
|
-
col.colStyle.display = isDragDropForHide ? 'flex' : 'none';
|
|
527
542
|
_.forEach(col.content.sections[0].inputFields, (tabPopoverSection) => {
|
|
528
543
|
if (tabPopoverSection.cols[0].id === 'switch-editor-label') {
|
|
529
|
-
tabPopoverSection.cols[0].style.display = isDragDropForHide ? '' :
|
|
544
|
+
tabPopoverSection.cols[0].style.display = (isDragDropForHide && hasSupportCKEditor()) ? '' : DISPLAY_NONE;
|
|
530
545
|
}
|
|
531
546
|
});
|
|
532
547
|
if (col.value && col.value.sections) {
|
|
533
548
|
_.forEach(col.value.sections[0].inputFields, (valueInputField) => {
|
|
534
549
|
_.forEach(valueInputField.cols, (valueCol) => {
|
|
535
550
|
if (valueCol.id === 'tab-option-icon') {
|
|
536
|
-
valueCol.colStyle = { ...valueCol.colStyle, display:
|
|
551
|
+
valueCol.colStyle = { ...valueCol.colStyle, display: 'flex' };
|
|
537
552
|
}
|
|
538
553
|
});
|
|
539
554
|
});
|
|
@@ -846,6 +861,11 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
846
861
|
showTemplateName({formData, onFormDataChange: this.onFormDataChange});
|
|
847
862
|
}
|
|
848
863
|
});
|
|
864
|
+
|
|
865
|
+
const baseLanguage = this.props.currentOrgDetails?.basic_details?.base_language || DEFAULT_LOCALE;
|
|
866
|
+
if (!this.state.exportHtmlContentLocked && activeTab === baseLanguage && newContent !== this.originalBaseTemplateContent) {
|
|
867
|
+
this.lockExportHtml();
|
|
868
|
+
}
|
|
849
869
|
}
|
|
850
870
|
}
|
|
851
871
|
|
|
@@ -1753,7 +1773,12 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
1753
1773
|
|
|
1754
1774
|
temp.panes[langTab].sections[0].inputFields[0].cols[0].colStyle = {display: ""};
|
|
1755
1775
|
temp.panes[langTab].sections[0].inputFields[0].cols[1].colStyle = {display: "none"};
|
|
1756
|
-
|
|
1776
|
+
// One-way Bee -> CKEditor switch: hide permanently once switched (see getBEEData).
|
|
1777
|
+
_.forEach(temp.tabBarExtraContent?.sections?.[0]?.inputFields?.[0]?.cols, (col) => {
|
|
1778
|
+
if (col.id === 'tab-options-popover') {
|
|
1779
|
+
this.hideSwitchEditorLabel(col);
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1757
1782
|
}
|
|
1758
1783
|
});
|
|
1759
1784
|
schema = this.showInsertImageButton(schema);
|
|
@@ -1799,20 +1824,18 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
1799
1824
|
newContainerInputFieldCol.style.display = isDragDrop ? "none" : '';
|
|
1800
1825
|
}
|
|
1801
1826
|
if (containerInputFieldCol.id === 'tab-options-popover') {
|
|
1802
|
-
// eslint-disable-next-line no-param-reassign
|
|
1803
|
-
containerInputFieldCol.colStyle.display = isDragDrop ? "flex" : "none";
|
|
1804
1827
|
_.forEach(containerInputFieldCol.content.sections[0].inputFields, (tabPopoverSection) => {
|
|
1805
1828
|
if (tabPopoverSection.cols[0].id === 'switch-editor-label') {
|
|
1806
1829
|
const newTabPopoverSection = tabPopoverSection;
|
|
1807
|
-
newTabPopoverSection.cols[0].style.display = isDragDrop ? "" :
|
|
1830
|
+
newTabPopoverSection.cols[0].style.display = (isDragDrop && hasSupportCKEditor()) ? "" : DISPLAY_NONE;
|
|
1808
1831
|
}
|
|
1809
1832
|
});
|
|
1810
|
-
//
|
|
1833
|
+
// tab-option-icon (popover trigger) is always visible regardless of editor type
|
|
1811
1834
|
if (containerInputFieldCol.value && containerInputFieldCol.value.sections) {
|
|
1812
1835
|
_.forEach(containerInputFieldCol.value.sections[0].inputFields, (valueInputField) => {
|
|
1813
1836
|
_.forEach(valueInputField.cols, (valueCol) => {
|
|
1814
1837
|
if (valueCol.id === 'tab-option-icon') {
|
|
1815
|
-
valueCol.colStyle = { ...valueCol.colStyle, display:
|
|
1838
|
+
valueCol.colStyle = { ...valueCol.colStyle, display: 'flex' };
|
|
1816
1839
|
}
|
|
1817
1840
|
});
|
|
1818
1841
|
});
|
|
@@ -1826,8 +1849,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
1826
1849
|
}
|
|
1827
1850
|
|
|
1828
1851
|
/**
|
|
1829
|
-
*
|
|
1830
|
-
* so users cannot switch editor if the feature is not enabled.
|
|
1852
|
+
* Ensures the tab-option-icon (popover trigger) is visible in schema, regardless of editor type.
|
|
1831
1853
|
*/
|
|
1832
1854
|
applyTabOptionIconVisibility = (schema) => {
|
|
1833
1855
|
if (!schema || !schema.containers) return;
|
|
@@ -1838,7 +1860,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
1838
1860
|
_.forEach(col.value.sections[0].inputFields, (inputField) => {
|
|
1839
1861
|
_.forEach(inputField.cols, (c) => {
|
|
1840
1862
|
if (c.id === 'tab-option-icon') {
|
|
1841
|
-
c.colStyle = { ...(c.colStyle || {}), display:
|
|
1863
|
+
c.colStyle = { ...(c.colStyle || {}), display: 'flex' };
|
|
1842
1864
|
}
|
|
1843
1865
|
});
|
|
1844
1866
|
});
|
|
@@ -1995,6 +2017,67 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
1995
2017
|
this.setState({showConfirmationModal: true, isGetBeeData: true});
|
|
1996
2018
|
}
|
|
1997
2019
|
|
|
2020
|
+
// Finds a tab-options-popover menu item (e.g. switch-editor-label, EXPORT_HTML_LABEL_ID) by id.
|
|
2021
|
+
findTabPopoverLabelCol = (tabOptionsPopoverCol, targetId) => (
|
|
2022
|
+
_.find(tabOptionsPopoverCol?.content?.sections?.[0]?.inputFields, (field) => field.cols[0].id === targetId)?.cols[0]
|
|
2023
|
+
)
|
|
2024
|
+
|
|
2025
|
+
// One-way Bee -> CKEditor switch: hide the switch-editor-label permanently within a tab-options-popover col.
|
|
2026
|
+
hideSwitchEditorLabel = (tabOptionsPopoverCol) => {
|
|
2027
|
+
const switchEditorCol = this.findTabPopoverLabelCol(tabOptionsPopoverCol, 'switch-editor-label');
|
|
2028
|
+
if (switchEditorCol) {
|
|
2029
|
+
switchEditorCol.style.display = DISPLAY_NONE;
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
setExportHtmlLabelStyle = (tabOptionsPopoverCol, styleOverrides) => {
|
|
2034
|
+
const exportCol = this.findTabPopoverLabelCol(tabOptionsPopoverCol, EXPORT_HTML_LABEL_ID);
|
|
2035
|
+
if (exportCol) {
|
|
2036
|
+
exportCol.style = { ...exportCol.style, ...styleOverrides };
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
// Targeted schema mutation to permanently disable Export HTML, skipping injectEvents() to avoid its unrelated schema-rebuild work.
|
|
2041
|
+
// Only the active container is cloned (others are reused by reference) since it's the only one being mutated.
|
|
2042
|
+
lockExportHtml = () => {
|
|
2043
|
+
this.setState((prevState) => {
|
|
2044
|
+
const containers = _.map(prevState.schema.containers, (container) => {
|
|
2045
|
+
if (!container.isActive) return container;
|
|
2046
|
+
const activeContainer = _.cloneDeep(container);
|
|
2047
|
+
const tabOptionsPopoverCol = _.find(activeContainer?.tabBarExtraContent?.sections?.[0]?.inputFields?.[0]?.cols, { id: 'tab-options-popover' });
|
|
2048
|
+
if (tabOptionsPopoverCol) {
|
|
2049
|
+
this.setExportHtmlLabelStyle(tabOptionsPopoverCol, { opacity: 0.5, cursor: 'not-allowed', pointerEvents: 'none' });
|
|
2050
|
+
}
|
|
2051
|
+
return activeContainer;
|
|
2052
|
+
});
|
|
2053
|
+
return { exportHtmlContentLocked: true, schema: { ...prevState.schema, containers } };
|
|
2054
|
+
});
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
// Bee's per-edit signal: deliberately never touches `schema` (unlike lockExportHtml) so it can't trigger Classic.js's formData rebuild and reinitialize the live Bee editor mid-edit.
|
|
2058
|
+
handleBeeContentChange = () => {
|
|
2059
|
+
if (this.state.exportHtmlContentLocked) return;
|
|
2060
|
+
const { formData, currentTab } = this.state;
|
|
2061
|
+
const activeTab = formData[currentTab - 1]?.activeTab;
|
|
2062
|
+
const baseLanguage = this.props.currentOrgDetails?.basic_details?.base_language || DEFAULT_LOCALE;
|
|
2063
|
+
if (activeTab !== baseLanguage) return;
|
|
2064
|
+
this.setState({ exportHtmlContentLocked: true });
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
exportHtml = () => {
|
|
2068
|
+
const templateDetails = this.props.Email.templateDetails;
|
|
2069
|
+
if (_.isEmpty(templateDetails) || this.state.exportHtmlContentLocked) {
|
|
2070
|
+
CapNotification.error({ message: this.props.intl.formatMessage(messages.exportHtmlError) });
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
const filename = `${sanitizeFileName(templateDetails.name)}.html`;
|
|
2074
|
+
const baseLanguage = this.props.currentOrgDetails?.basic_details?.base_language || DEFAULT_LOCALE;
|
|
2075
|
+
exportEmailTemplateHtml(templateDetails, filename, baseLanguage).catch((error) => {
|
|
2076
|
+
console.error('Error exporting EMAIL template HTML:', error);
|
|
2077
|
+
CapNotification.error({ message: this.props.intl.formatMessage(messages.exportHtmlError) });
|
|
2078
|
+
});
|
|
2079
|
+
}
|
|
2080
|
+
|
|
1998
2081
|
renameVersion = () => {
|
|
1999
2082
|
|
|
2000
2083
|
}
|
|
@@ -2376,6 +2459,14 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2376
2459
|
newContainerInputFieldCol.colStyle.display = "none";
|
|
2377
2460
|
}
|
|
2378
2461
|
}
|
|
2462
|
+
if (containerInputFieldCol.id === "tab-options-popover") {
|
|
2463
|
+
const canExportHtml = this.state.isEdit && !this.state.exportHtmlContentLocked;
|
|
2464
|
+
this.setExportHtmlLabelStyle(containerInputFieldCol, {
|
|
2465
|
+
opacity: canExportHtml ? 1 : 0.5,
|
|
2466
|
+
cursor: canExportHtml ? 'pointer' : 'not-allowed',
|
|
2467
|
+
pointerEvents: canExportHtml ? 'auto' : 'none',
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2379
2470
|
// if (containerInputFieldCol.id === "tab-options-popover") {
|
|
2380
2471
|
// const newContainerInputFieldCol = containerInputFieldCol;
|
|
2381
2472
|
// newContainerInputFieldCol.colStyle.display = "none";
|
|
@@ -2443,10 +2534,13 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2443
2534
|
_.forEach(section.inputFields, (inputFields) => {
|
|
2444
2535
|
if (section.type === "multicols") {
|
|
2445
2536
|
_.forEach(inputFields.cols, (col) => {
|
|
2446
|
-
if (
|
|
2537
|
+
if (col.id === "add-language-button" && !this.props.isFullMode) {
|
|
2447
2538
|
const colStyle = col.colStyle;
|
|
2448
2539
|
colStyle.display = "none";
|
|
2449
2540
|
}
|
|
2541
|
+
if (col.id === "tab-options-popover" && !this.props.isFullMode) {
|
|
2542
|
+
this.hideSwitchEditorLabel(col);
|
|
2543
|
+
}
|
|
2450
2544
|
});
|
|
2451
2545
|
}
|
|
2452
2546
|
});
|
|
@@ -3060,7 +3154,12 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
3060
3154
|
const langTab = formData[`${currentTab - 1}`].selectedLanguages.indexOf(activeLangTab);
|
|
3061
3155
|
container.panes[langTab].sections[0].inputFields[0].cols[0].colStyle = { display: "" };
|
|
3062
3156
|
container.panes[langTab].sections[0].inputFields[0].cols[1].colStyle = { display: "none" };
|
|
3063
|
-
|
|
3157
|
+
// One-way Bee -> CKEditor switch: hide permanently, since isDragDrop isn't re-fetched to drive the usual toggle.
|
|
3158
|
+
_.forEach(container.tabBarExtraContent?.sections?.[0]?.inputFields?.[0]?.cols, (col) => {
|
|
3159
|
+
if (col.id === 'tab-options-popover') {
|
|
3160
|
+
this.hideSwitchEditorLabel(col);
|
|
3161
|
+
}
|
|
3162
|
+
});
|
|
3064
3163
|
}
|
|
3065
3164
|
});
|
|
3066
3165
|
|
|
@@ -3076,7 +3175,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
3076
3175
|
this.setState((prevState) => {
|
|
3077
3176
|
const { currentTab, formData } = _.cloneDeep(prevState);
|
|
3078
3177
|
const activeTab = formData[currentTab - 1].activeTab;
|
|
3079
|
-
|
|
3178
|
+
|
|
3080
3179
|
// Update content in both formData and base
|
|
3081
3180
|
formData[currentTab - 1][activeTab]['template-content'] = html;
|
|
3082
3181
|
formData[currentTab - 1][activeTab]['json-content'] = json;
|
|
@@ -3175,6 +3274,9 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
3175
3274
|
isLoyaltyModule={this.props?.isLoyaltyModule}
|
|
3176
3275
|
isGetBeeData={this.state.isGetBeeData}
|
|
3177
3276
|
getBEEData={this.getBEEData}
|
|
3277
|
+
onContentChange={this.handleBeeContentChange}
|
|
3278
|
+
exportHtmlLocked={this.state.exportHtmlContentLocked}
|
|
3279
|
+
exportHtmlTooltip={getExportHtmlDisabledTooltip(this.state.isEdit, this.state.exportHtmlContentLocked, this.props.intl.formatMessage)}
|
|
3178
3280
|
isTestAndPreviewMode={this.state.isTestAndPreviewMode} // Add flag to prevent validation
|
|
3179
3281
|
/> : ''}
|
|
3180
3282
|
</CapColumn>
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import {CapButton} from '@capillarytech/cap-ui-library';
|
|
3
3
|
import {FormattedMessage} from 'react-intl';
|
|
4
4
|
import messages from './messages';
|
|
5
|
+
import { EXPORT_HTML_LABEL_ID } from '../../constants/unified';
|
|
5
6
|
export const response = {
|
|
6
7
|
metaEntities: [
|
|
7
8
|
{
|
|
@@ -285,6 +286,7 @@ export const response = {
|
|
|
285
286
|
fontStyle: "normal",
|
|
286
287
|
fontWeight: "600",
|
|
287
288
|
justifyContent: "flex-end",
|
|
289
|
+
marginLeft: "31.25rem",
|
|
288
290
|
},
|
|
289
291
|
width: 3,
|
|
290
292
|
offset: 10,
|
|
@@ -358,7 +360,7 @@ export const response = {
|
|
|
358
360
|
colStyle: {
|
|
359
361
|
textAlign: "right",
|
|
360
362
|
flex: 0,
|
|
361
|
-
display: "
|
|
363
|
+
display: "flex",
|
|
362
364
|
alignItems: "center",
|
|
363
365
|
},
|
|
364
366
|
type: "popover",
|
|
@@ -395,6 +397,25 @@ export const response = {
|
|
|
395
397
|
},
|
|
396
398
|
],
|
|
397
399
|
},
|
|
400
|
+
{
|
|
401
|
+
cols: [
|
|
402
|
+
{
|
|
403
|
+
id: EXPORT_HTML_LABEL_ID,
|
|
404
|
+
metaType: "label",
|
|
405
|
+
type: "div",
|
|
406
|
+
primitive: true,
|
|
407
|
+
value: "Export HTML",
|
|
408
|
+
onlyDisplay: true,
|
|
409
|
+
customComponent: false,
|
|
410
|
+
order: 5,
|
|
411
|
+
fluid: false,
|
|
412
|
+
className: "version-popover",
|
|
413
|
+
submitAction: "exportHtml",
|
|
414
|
+
supportedEvents: ["exportHtml"],
|
|
415
|
+
style: { display: '' },
|
|
416
|
+
},
|
|
417
|
+
],
|
|
418
|
+
},
|
|
398
419
|
],
|
|
399
420
|
actionFields: [],
|
|
400
421
|
},
|
|
@@ -410,10 +431,11 @@ export const response = {
|
|
|
410
431
|
{
|
|
411
432
|
id: "tab-option-icon",
|
|
412
433
|
metaType: "display",
|
|
413
|
-
type: "icon",
|
|
434
|
+
type: "cap-icon",
|
|
414
435
|
onlyDisplay: true,
|
|
415
436
|
primitive: false,
|
|
416
|
-
value: "
|
|
437
|
+
value: "more",
|
|
438
|
+
rotate: 90,
|
|
417
439
|
customComponent: false,
|
|
418
440
|
order: 3,
|
|
419
441
|
fluid: false,
|
|
@@ -18,6 +18,22 @@ export default defineMessages({
|
|
|
18
18
|
id: 'creatives.containersV2.Email.mostRecentOption',
|
|
19
19
|
defaultMessage: "Most recent",
|
|
20
20
|
},
|
|
21
|
+
"exportHtmlError": {
|
|
22
|
+
id: 'creatives.containersV2.Email.exportHtmlError',
|
|
23
|
+
defaultMessage: "Failed to export template HTML. Please try again.",
|
|
24
|
+
},
|
|
25
|
+
"exportHtmlButton": {
|
|
26
|
+
id: 'creatives.containersV2.Email.exportHtmlButton',
|
|
27
|
+
defaultMessage: "Export HTML",
|
|
28
|
+
},
|
|
29
|
+
"exportHtmlDisabledCreateTooltip": {
|
|
30
|
+
id: 'creatives.containersV2.Email.exportHtmlDisabledCreateTooltip',
|
|
31
|
+
defaultMessage: "HTML export isn’t available while creating a template.",
|
|
32
|
+
},
|
|
33
|
+
"exportHtmlDisabledEditedTooltip": {
|
|
34
|
+
id: 'creatives.containersV2.Email.exportHtmlDisabledEditedTooltip',
|
|
35
|
+
defaultMessage: "HTML export is unavailable because the template has been edited in this session.",
|
|
36
|
+
},
|
|
21
37
|
"alphabeticallyOption": {
|
|
22
38
|
id: 'creatives.containersV2.Email.alphabeticallyOption',
|
|
23
39
|
defaultMessage: "Alphabetically",
|