@capillarytech/creatives-library 8.0.273 → 8.0.274
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/package.json +1 -1
- package/utils/imageUrlUpload.js +14 -13
- package/v2Containers/Email/index.js +34 -1
package/package.json
CHANGED
package/utils/imageUrlUpload.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utility functions for uploading images from URLs
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* NOTE: CORS-limited; will be replaced with backend implementation.
|
|
5
5
|
* Flow currently hidden (not removed) from frontend.
|
|
6
6
|
*/
|
|
@@ -13,14 +13,14 @@ import {
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Fetches an image from a URL
|
|
16
|
-
*
|
|
16
|
+
*
|
|
17
17
|
* @param {string} url - The image URL to fetch
|
|
18
18
|
* @returns {Promise<Response>} - The fetch response object
|
|
19
19
|
* @throws {Error} - If the fetch fails (network/CORS error)
|
|
20
20
|
*/
|
|
21
21
|
export const fetchImageFromUrl = async (url) => {
|
|
22
22
|
const trimmedUrl = url?.trim() || '';
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
if (!trimmedUrl) {
|
|
25
25
|
throw new Error('URL is required');
|
|
26
26
|
}
|
|
@@ -42,7 +42,7 @@ export const fetchImageFromUrl = async (url) => {
|
|
|
42
42
|
/**
|
|
43
43
|
* Helper function to upload image from URL
|
|
44
44
|
* Fetches image, validates content type and size, converts to File, and uploads via uploadAsset
|
|
45
|
-
*
|
|
45
|
+
*
|
|
46
46
|
* @param {string} url - The image URL to upload
|
|
47
47
|
* @param {Function} formatMessage - React Intl formatMessage function
|
|
48
48
|
* @param {Object} messages - React Intl messages object
|
|
@@ -51,7 +51,7 @@ export const fetchImageFromUrl = async (url) => {
|
|
|
51
51
|
* @param {number} maxSize - Maximum file size in bytes
|
|
52
52
|
* @param {string[]} allowedContentTypes - Array of allowed MIME types (defaults to DEFAULT_ALLOWED_CONTENT_TYPES)
|
|
53
53
|
* @returns {Promise<{success: boolean, error: string}>} - Result object with success status and error message
|
|
54
|
-
*
|
|
54
|
+
*
|
|
55
55
|
* @example
|
|
56
56
|
* const result = await uploadImageFromUrlHelper(
|
|
57
57
|
* 'https://example.com/image.jpg',
|
|
@@ -73,14 +73,14 @@ export const uploadImageFromUrlHelper = async (
|
|
|
73
73
|
allowedContentTypes = DEFAULT_ALLOWED_CONTENT_TYPES,
|
|
74
74
|
) => {
|
|
75
75
|
const trimmedUrl = url?.trim() || '';
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
try {
|
|
78
78
|
const response = await fetchImageFromUrl(trimmedUrl);
|
|
79
79
|
|
|
80
80
|
// Validate Content-Type
|
|
81
81
|
const contentType = response.headers?.get('Content-Type') || '';
|
|
82
82
|
const normalizedContentType = contentType.split(';')[0].toLowerCase().trim();
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
if (!allowedContentTypes.includes(normalizedContentType)) {
|
|
85
85
|
return {
|
|
86
86
|
success: false,
|
|
@@ -89,7 +89,7 @@ export const uploadImageFromUrlHelper = async (
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
const blob = await response.blob();
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
if (blob.size > maxSize) {
|
|
94
94
|
return {
|
|
95
95
|
success: false,
|
|
@@ -101,7 +101,7 @@ export const uploadImageFromUrlHelper = async (
|
|
|
101
101
|
return new Promise((resolve) => {
|
|
102
102
|
const img = new Image();
|
|
103
103
|
const objectUrl = URL.createObjectURL(blob);
|
|
104
|
-
|
|
104
|
+
|
|
105
105
|
img.onload = () => {
|
|
106
106
|
const extension = MIME_TYPE_TO_EXTENSION[normalizedContentType] || DEFAULT_IMAGE_EXTENSION;
|
|
107
107
|
const fileName = `${fileNamePrefix}.${extension}`;
|
|
@@ -111,16 +111,16 @@ export const uploadImageFromUrlHelper = async (
|
|
|
111
111
|
height: img.height,
|
|
112
112
|
error: false,
|
|
113
113
|
};
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
uploadAssetFn(file, 'image', fileParams);
|
|
116
116
|
URL.revokeObjectURL(objectUrl);
|
|
117
|
-
|
|
117
|
+
|
|
118
118
|
resolve({
|
|
119
119
|
success: true,
|
|
120
120
|
error: '',
|
|
121
121
|
});
|
|
122
122
|
};
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
img.onerror = () => {
|
|
125
125
|
URL.revokeObjectURL(objectUrl);
|
|
126
126
|
resolve({
|
|
@@ -128,7 +128,7 @@ export const uploadImageFromUrlHelper = async (
|
|
|
128
128
|
error: formatMessage(messages.imageLoadError),
|
|
129
129
|
});
|
|
130
130
|
};
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
img.src = objectUrl;
|
|
133
133
|
});
|
|
134
134
|
} catch (error) {
|
|
@@ -138,3 +138,4 @@ export const uploadImageFromUrlHelper = async (
|
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
140
|
};
|
|
141
|
+
|
|
@@ -26,7 +26,7 @@ import * as globalActions from '../Cap/actions';
|
|
|
26
26
|
import './_email.scss';
|
|
27
27
|
import {getMessageObject} from '../../utils/messageUtils';
|
|
28
28
|
import EmailPreview from '../../v2Components/EmailPreview';
|
|
29
|
-
import { getDecodedFileName ,
|
|
29
|
+
import { getDecodedFileName, hasLiquidSupportFeature, hasSupportCKEditor } from '../../utils/common';
|
|
30
30
|
import Pagination from '../../v2Components/Pagination';
|
|
31
31
|
import * as creativesContainerActions from '../CreativesContainer/actions';
|
|
32
32
|
import withCreatives from '../../hoc/withCreatives';
|
|
@@ -325,6 +325,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
325
325
|
}
|
|
326
326
|
if (nextProps.metaEntities && nextProps.metaEntities.layouts && nextProps.metaEntities.layouts.length > 0 && _.isEmpty(this.state.schema)) {
|
|
327
327
|
const newSchema = this.injectEvents(nextProps.metaEntities.layouts[0].definition);
|
|
328
|
+
this.applyTabOptionIconVisibility(newSchema);
|
|
328
329
|
|
|
329
330
|
this.setState({schema: newSchema, loadingStatus: this.state.loadingStatus + 1});
|
|
330
331
|
if (this.props.location.query.module !== 'library' || (this.props.location.query.module === 'library' && this.props.getDefaultTags)) {
|
|
@@ -1752,6 +1753,16 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
1752
1753
|
newTabPopoverSection.cols[0].style.display = isDragDrop ? "" : "none";
|
|
1753
1754
|
}
|
|
1754
1755
|
});
|
|
1756
|
+
// Hide tab-option-icon (switch editor trigger) when SUPPORT_CK_EDITOR is disabled
|
|
1757
|
+
if (containerInputFieldCol.value && containerInputFieldCol.value.sections) {
|
|
1758
|
+
_.forEach(containerInputFieldCol.value.sections[0].inputFields, (valueInputField) => {
|
|
1759
|
+
_.forEach(valueInputField.cols, (valueCol) => {
|
|
1760
|
+
if (valueCol.id === 'tab-option-icon') {
|
|
1761
|
+
valueCol.colStyle = { ...valueCol.colStyle, display: hasSupportCKEditor() ? 'flex' : 'none' };
|
|
1762
|
+
}
|
|
1763
|
+
});
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1755
1766
|
}
|
|
1756
1767
|
});
|
|
1757
1768
|
}
|
|
@@ -1760,6 +1771,28 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
1760
1771
|
this.setState({schema, isSchemaChanged: true});
|
|
1761
1772
|
}
|
|
1762
1773
|
|
|
1774
|
+
/**
|
|
1775
|
+
* Hides the tab-option-icon (switch editor trigger) in schema when SUPPORT_CK_EDITOR is disabled,
|
|
1776
|
+
* so users cannot switch editor if the feature is not enabled.
|
|
1777
|
+
*/
|
|
1778
|
+
applyTabOptionIconVisibility = (schema) => {
|
|
1779
|
+
if (!schema || !schema.containers) return;
|
|
1780
|
+
_.forEach(schema.containers, (container) => {
|
|
1781
|
+
if (!container.isActive || !container.tabBarExtraContent?.sections?.[0]?.inputFields?.[0]?.cols) return;
|
|
1782
|
+
_.forEach(container.tabBarExtraContent.sections[0].inputFields[0].cols, (col) => {
|
|
1783
|
+
if (col.id === 'tab-options-popover' && col.value?.sections?.[0]?.inputFields) {
|
|
1784
|
+
_.forEach(col.value.sections[0].inputFields, (inputField) => {
|
|
1785
|
+
_.forEach(inputField.cols, (c) => {
|
|
1786
|
+
if (c.id === 'tab-option-icon') {
|
|
1787
|
+
c.colStyle = { ...(c.colStyle || {}), display: hasSupportCKEditor() ? 'flex' : 'none' };
|
|
1788
|
+
}
|
|
1789
|
+
});
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
});
|
|
1793
|
+
});
|
|
1794
|
+
};
|
|
1795
|
+
|
|
1763
1796
|
showInsertImageButton = (passedSchema) => {
|
|
1764
1797
|
const schema = passedSchema || _.cloneDeep(this.state.schema);
|
|
1765
1798
|
_.forEach(schema.containers, (container) => {
|