@capillarytech/creatives-library 8.0.138 → 8.0.139-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/package.json +1 -1
- package/v2Components/CapImageUpload/index.js +1 -1
- package/v2Containers/Line/Container/_lineCreate.scss +2 -2
- package/v2Containers/MobilePushNew/components/MediaUploaders.js +118 -83
- package/v2Containers/MobilePushNew/components/PlatformContentFields.js +1 -1
- package/v2Containers/MobilePushNew/index.js +458 -590
- package/v2Containers/MobilePushNew/index.scss +6 -1
- package/v2Containers/MobilePushNew/messages.js +1 -1
- package/v2Containers/Templates/index.js +1 -1
package/package.json
CHANGED
|
@@ -143,7 +143,7 @@ function CapImageUpload(props) {
|
|
|
143
143
|
|
|
144
144
|
const capUploaderCustomRequest = useCallback((uploadData) => {
|
|
145
145
|
uploadImages(undefined, {files: [uploadData.file]});
|
|
146
|
-
}, []);
|
|
146
|
+
}, [uploadImages]);
|
|
147
147
|
|
|
148
148
|
const setDrawerVisibility = useCallback((drawervisibleFlag) => updateDrawerRequirement(drawervisibleFlag), [isDrawerRequired]);
|
|
149
149
|
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
}
|
|
58
58
|
img {
|
|
59
59
|
object-fit: cover;
|
|
60
|
-
max-height:
|
|
60
|
+
max-height: 9.375rem;
|
|
61
61
|
max-width: 18.75rem;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
.sms-text {
|
|
107
107
|
img {
|
|
108
108
|
display: block;
|
|
109
|
-
max-width: 100%;
|
|
109
|
+
// max-width: 100%;
|
|
110
110
|
object-fit: cover;
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -61,6 +61,22 @@ const CAROUSEL_INITIAL_DATA = {
|
|
|
61
61
|
// Maximum number of carousel cards allowed
|
|
62
62
|
const MAX_CAROUSEL_ALLOWED = 10;
|
|
63
63
|
|
|
64
|
+
// Helper function to find selected deep link with fallback to base URL
|
|
65
|
+
const findSelectedDeepLink = (links, value) => {
|
|
66
|
+
if (!links || !value) return undefined;
|
|
67
|
+
|
|
68
|
+
// Try to find exact match first
|
|
69
|
+
let selectedDeepLink = links.find((link) => link?.value === value);
|
|
70
|
+
|
|
71
|
+
// If no exact match and value contains query parameters, try base URL match
|
|
72
|
+
if (!selectedDeepLink && value?.includes('?')) {
|
|
73
|
+
const baseDeepLinkValue = value.split('?')[0];
|
|
74
|
+
selectedDeepLink = links.find((link) => link?.value === baseDeepLinkValue);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return selectedDeepLink;
|
|
78
|
+
};
|
|
79
|
+
|
|
64
80
|
const MediaUploaders = ({
|
|
65
81
|
mediaType,
|
|
66
82
|
activeTab,
|
|
@@ -93,6 +109,16 @@ const MediaUploaders = ({
|
|
|
93
109
|
// Track re-upload mode to prevent automatic restoration during re-upload
|
|
94
110
|
const [isReUploading, setIsReUploading] = useState(false);
|
|
95
111
|
|
|
112
|
+
// Track which card is currently uploading to handle completion properly
|
|
113
|
+
const [uploadingCardIndex, setUploadingCardIndex] = useState(null);
|
|
114
|
+
|
|
115
|
+
// Track upload ID to prevent processing stale Redux data
|
|
116
|
+
const [currentUploadId, setCurrentUploadId] = useState(null);
|
|
117
|
+
const uploadIdRef = useRef(0); // Counter for generating unique upload IDs
|
|
118
|
+
|
|
119
|
+
// Track previous upload data to detect when a new upload completes
|
|
120
|
+
const previousUploadDataRef = useRef(null);
|
|
121
|
+
|
|
96
122
|
// Track previous media type to handle transitions
|
|
97
123
|
const previousMediaTypeRef = useRef(mediaType);
|
|
98
124
|
|
|
@@ -109,12 +135,25 @@ const MediaUploaders = ({
|
|
|
109
135
|
}
|
|
110
136
|
}, [activeTab, onCarouselDataChange]);
|
|
111
137
|
|
|
138
|
+
// Move updateCarouselCard to top level so useEffect can access it
|
|
139
|
+
const updateCarouselCard = useCallback((index, fields) => {
|
|
140
|
+
const currentData = getCurrentCarouselData();
|
|
141
|
+
setCurrentCarouselData(currentData.map((card, i) => (
|
|
142
|
+
i === index ? { ...card, ...fields } : card
|
|
143
|
+
)));
|
|
144
|
+
}, [getCurrentCarouselData, setCurrentCarouselData]);
|
|
145
|
+
|
|
112
146
|
// Clear previous media data when switching media types
|
|
113
147
|
useEffect(() => {
|
|
114
148
|
// Clear carousel data when switching to non-carousel media types
|
|
115
149
|
if (mediaType !== CAROUSEL) {
|
|
116
150
|
setCurrentCarouselData([]);
|
|
117
151
|
setCarouselActiveTabIndex(0);
|
|
152
|
+
|
|
153
|
+
// Reset carousel upload tracking
|
|
154
|
+
setUploadingCardIndex(null);
|
|
155
|
+
setCurrentUploadId(null);
|
|
156
|
+
previousUploadDataRef.current = null;
|
|
118
157
|
}
|
|
119
158
|
|
|
120
159
|
// Clear image data when switching away from IMAGE media type
|
|
@@ -139,7 +178,14 @@ const MediaUploaders = ({
|
|
|
139
178
|
useEffect(() => {
|
|
140
179
|
// Reset active tab index when switching platforms
|
|
141
180
|
setCarouselActiveTabIndex(0);
|
|
142
|
-
|
|
181
|
+
|
|
182
|
+
// Reset upload tracking when switching platforms to prevent cross-platform conflicts
|
|
183
|
+
if (mediaType === CAROUSEL) {
|
|
184
|
+
setUploadingCardIndex(null);
|
|
185
|
+
setCurrentUploadId(null);
|
|
186
|
+
previousUploadDataRef.current = null;
|
|
187
|
+
}
|
|
188
|
+
}, [activeTab, mediaType]);
|
|
143
189
|
|
|
144
190
|
// Initialize carousel data if empty
|
|
145
191
|
useEffect(() => {
|
|
@@ -148,37 +194,8 @@ const MediaUploaders = ({
|
|
|
148
194
|
}
|
|
149
195
|
}, [mediaType, carouselData, activeTab, setCurrentCarouselData]);
|
|
150
196
|
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
// Skip automatic updates during re-upload mode
|
|
154
|
-
if (isReUploading) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (mediaType === CAROUSEL && imageData) {
|
|
159
|
-
const platformIndex = activeTab === ANDROID ? 0 : 1;
|
|
160
|
-
const uploadedAssetData = imageData[`uploadedAssetData${platformIndex}`];
|
|
161
|
-
|
|
162
|
-
// Only update if there's new upload data and it's different from current carousel data
|
|
163
|
-
if (uploadedAssetData && uploadedAssetData.metaInfo && uploadedAssetData.metaInfo.secure_file_path) {
|
|
164
|
-
const currentData = getCurrentCarouselData();
|
|
165
|
-
if (currentData?.length > carouselActiveTabIndex) {
|
|
166
|
-
const currentCard = currentData[carouselActiveTabIndex];
|
|
167
|
-
const newImageUrl = uploadedAssetData.metaInfo.secure_file_path;
|
|
168
|
-
|
|
169
|
-
// Only update if the image URL is different from the current one and not empty
|
|
170
|
-
if (currentCard?.imageUrl !== newImageUrl && newImageUrl !== '') {
|
|
171
|
-
const updatedData = [...currentData];
|
|
172
|
-
updatedData[carouselActiveTabIndex] = {
|
|
173
|
-
...updatedData[carouselActiveTabIndex],
|
|
174
|
-
imageUrl: newImageUrl,
|
|
175
|
-
};
|
|
176
|
-
setCurrentCarouselData(updatedData);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}, [imageData, mediaType, activeTab, carouselActiveTabIndex, getCurrentCarouselData, setCurrentCarouselData, isReUploading]);
|
|
197
|
+
// Note: Carousel images use standard platform indices (0/1) and are handled
|
|
198
|
+
// by the updateImageSrc callback with CAROUSEL mediaType for proper separation
|
|
182
199
|
|
|
183
200
|
const renderImageComponent = useCallback(() => {
|
|
184
201
|
let imageSource = '';
|
|
@@ -363,46 +380,40 @@ const MediaUploaders = ({
|
|
|
363
380
|
}
|
|
364
381
|
};
|
|
365
382
|
|
|
366
|
-
|
|
367
|
-
const currentData = getCurrentCarouselData();
|
|
368
|
-
setCurrentCarouselData(currentData.map((card, i) => (
|
|
369
|
-
i === index ? { ...card, ...fields } : card
|
|
370
|
-
)));
|
|
371
|
-
// Don't clear assets for carousel cards since they store data in component state, not Redux
|
|
372
|
-
// Only clear assets for non-carousel media types
|
|
373
|
-
};
|
|
383
|
+
// updateCarouselCard moved to top level to be accessible by useEffect
|
|
374
384
|
|
|
375
|
-
const handleCarouselImageChange = (image) => {
|
|
376
|
-
|
|
385
|
+
const handleCarouselImageChange = (image, cardIndex) => {
|
|
386
|
+
// Update the specific card that uploaded the image, not the active card
|
|
387
|
+
updateCarouselCard(cardIndex, { imageUrl: image });
|
|
377
388
|
};
|
|
378
389
|
|
|
379
|
-
// Carousel-specific re-upload handler that clears both Redux and component state
|
|
380
|
-
const handleCarouselImageReUpload = () => {
|
|
390
|
+
// Carousel-specific re-upload handler that clears both Redux and component state for specific card
|
|
391
|
+
const handleCarouselImageReUpload = (cardIndex) => {
|
|
381
392
|
// Set re-upload mode to prevent automatic restoration
|
|
382
393
|
setIsReUploading(true);
|
|
383
394
|
|
|
384
395
|
// Clear Redux state (same as updateOnMpushImageReUpload)
|
|
385
396
|
updateOnMpushImageReUpload();
|
|
386
397
|
|
|
387
|
-
// Clear Redux uploadedAssetData to prevent automatic restoration
|
|
398
|
+
// Clear Redux uploadedAssetData to prevent automatic restoration using standard platform index
|
|
388
399
|
const platformIndex = activeTab === ANDROID ? 0 : 1;
|
|
389
400
|
mobilePushActions.clearAsset(platformIndex);
|
|
390
401
|
|
|
391
|
-
// Clear carousel component state for the
|
|
402
|
+
// Clear carousel component state for the specific card
|
|
392
403
|
const currentData = getCurrentCarouselData();
|
|
393
|
-
if (currentData?.length >
|
|
404
|
+
if (currentData?.length > cardIndex) {
|
|
394
405
|
const updatedData = [...currentData];
|
|
395
|
-
updatedData[
|
|
396
|
-
...updatedData[
|
|
406
|
+
updatedData[cardIndex] = {
|
|
407
|
+
...updatedData[cardIndex],
|
|
397
408
|
imageUrl: '',
|
|
398
409
|
};
|
|
399
410
|
setCurrentCarouselData(updatedData);
|
|
400
411
|
}
|
|
401
412
|
|
|
402
|
-
// Reset re-upload mode after a
|
|
413
|
+
// Reset re-upload mode after a delay
|
|
403
414
|
setTimeout(() => {
|
|
404
415
|
setIsReUploading(false);
|
|
405
|
-
},
|
|
416
|
+
}, 100);
|
|
406
417
|
};
|
|
407
418
|
|
|
408
419
|
// Action link handlers for carousel cards
|
|
@@ -467,6 +478,17 @@ const MediaUploaders = ({
|
|
|
467
478
|
// Each carousel card maintains its own imageUrl
|
|
468
479
|
const imageSource = card?.imageUrl || '';
|
|
469
480
|
|
|
481
|
+
// Custom upload function that tracks which card is uploading
|
|
482
|
+
const handleCarouselUpload = (file, assetType, fileParams, index) => {
|
|
483
|
+
// Generate unique upload ID to track this specific upload
|
|
484
|
+
uploadIdRef.current += 1;
|
|
485
|
+
const uploadId = uploadIdRef.current;
|
|
486
|
+
|
|
487
|
+
setUploadingCardIndex(cardIndex);
|
|
488
|
+
setCurrentUploadId(uploadId);
|
|
489
|
+
return uploadMpushAsset(file, assetType, fileParams, index);
|
|
490
|
+
};
|
|
491
|
+
|
|
470
492
|
return (
|
|
471
493
|
<CapImageUpload
|
|
472
494
|
style={{ paddingTop: "20px" }}
|
|
@@ -474,22 +496,27 @@ const MediaUploaders = ({
|
|
|
474
496
|
imgSize={MPUSH_IMG_SIZE}
|
|
475
497
|
imgWidth={MPUSH_IMG_MAX_WIDTH}
|
|
476
498
|
imgHeight={MPUSH_IMG_MAX_HEIGHT}
|
|
477
|
-
uploadAsset={
|
|
499
|
+
uploadAsset={handleCarouselUpload}
|
|
478
500
|
isFullMode={isFullMode}
|
|
479
501
|
imageSrc={imageSource}
|
|
480
502
|
updateImageSrc={(src) => {
|
|
481
|
-
//
|
|
482
|
-
|
|
503
|
+
// For gallery uploads (direct URL), update immediately
|
|
504
|
+
if (src && (src.includes('http') || src.includes('https'))) {
|
|
505
|
+
handleCarouselImageChange(src, cardIndex);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Always call setUpdateMpushImageSrc for Redux state management
|
|
509
|
+
setUpdateMpushImageSrc(src, activeTab === ANDROID ? 0 : 1, CAROUSEL);
|
|
483
510
|
}}
|
|
484
|
-
updateOnReUpload={handleCarouselImageReUpload}
|
|
511
|
+
updateOnReUpload={() => handleCarouselImageReUpload(cardIndex)}
|
|
485
512
|
index={activeTab === ANDROID ? 0 : 1}
|
|
486
513
|
className="cap-custom-image-upload"
|
|
487
514
|
key={`carousel-image-${activeTab}-${cardIndex}`}
|
|
488
|
-
imageData={
|
|
515
|
+
imageData={imageData}
|
|
489
516
|
channel={MOBILE_PUSH_CHANNEL}
|
|
490
517
|
showReUploadButton
|
|
491
518
|
errorMessage={formatMessage(messages.imageErrorMessage)}
|
|
492
|
-
disableAutoRestore // Disable automatic restoration
|
|
519
|
+
disableAutoRestore // Disable automatic restoration to prevent all cards from showing the same image
|
|
493
520
|
/>
|
|
494
521
|
);
|
|
495
522
|
};
|
|
@@ -572,15 +599,15 @@ const MediaUploaders = ({
|
|
|
572
599
|
options={(() => {
|
|
573
600
|
const options = [...(deepLink || [])];
|
|
574
601
|
// If the current value is not in the options, add it
|
|
575
|
-
if (button
|
|
602
|
+
if (button?.deepLinkValue && !options.find(opt => opt.value === button?.deepLinkValue)) {
|
|
576
603
|
options.push({
|
|
577
|
-
value: button
|
|
578
|
-
label: button
|
|
604
|
+
value: button?.deepLinkValue,
|
|
605
|
+
label: button?.deepLinkValue,
|
|
579
606
|
});
|
|
580
607
|
}
|
|
581
608
|
return options;
|
|
582
609
|
})()}
|
|
583
|
-
value={button
|
|
610
|
+
value={button?.deepLinkValue}
|
|
584
611
|
onChange={(value) => handleCarouselDeepLinkChange(cardIndex, value)}
|
|
585
612
|
key={`mobile-push-deep-link-type-${activeTab}-${cardIndex}`}
|
|
586
613
|
placeholder={formatMessage(messages.selectDeepLink)}
|
|
@@ -616,12 +643,7 @@ const MediaUploaders = ({
|
|
|
616
643
|
</CapRow>
|
|
617
644
|
)}
|
|
618
645
|
{button?.linkType === DEEP_LINK && button?.deepLinkValue && button?.actionOnClick && (() => {
|
|
619
|
-
|
|
620
|
-
let selectedDeepLink = deepLink?.find((link) => link?.value === button?.deepLinkValue);
|
|
621
|
-
if (!selectedDeepLink && button?.deepLinkValue && button?.deepLinkValue.includes('?')) {
|
|
622
|
-
const baseDeepLinkValue = button?.deepLinkValue.split('?')[0];
|
|
623
|
-
selectedDeepLink = deepLink?.find((link) => link?.value === baseDeepLinkValue);
|
|
624
|
-
}
|
|
646
|
+
const selectedDeepLink = findSelectedDeepLink(deepLink, button?.deepLinkValue);
|
|
625
647
|
const deepLinkKeysFromSelection = selectedDeepLink?.keys;
|
|
626
648
|
let deepLinkKeysFromSelectionArray = [];
|
|
627
649
|
if (Array.isArray(deepLinkKeysFromSelection)) {
|
|
@@ -638,12 +660,7 @@ const MediaUploaders = ({
|
|
|
638
660
|
</CapHeading>
|
|
639
661
|
<CapLabel type="label2" className="deep-link-keys-value">
|
|
640
662
|
{(() => {
|
|
641
|
-
|
|
642
|
-
let selectedDeepLink = deepLink?.find((link) => link?.value === button?.deepLinkValue);
|
|
643
|
-
if (!selectedDeepLink && button?.deepLinkValue && button?.deepLinkValue.includes('?')) {
|
|
644
|
-
const baseDeepLinkValue = button?.deepLinkValue.split('?')[0];
|
|
645
|
-
selectedDeepLink = deepLink?.find((link) => link?.value === baseDeepLinkValue);
|
|
646
|
-
}
|
|
663
|
+
const selectedDeepLink = findSelectedDeepLink(deepLink, button?.deepLinkValue);
|
|
647
664
|
const deepLinkKeysFromSelection = selectedDeepLink?.keys;
|
|
648
665
|
let deepLinkKeysArray = [];
|
|
649
666
|
if (Array.isArray(button?.deepLinkKeys)) {
|
|
@@ -671,12 +688,7 @@ const MediaUploaders = ({
|
|
|
671
688
|
onChange={(e) => handleCarouselDeepLinkKeysChange(cardIndex, e.target.value)}
|
|
672
689
|
placeholder={formatMessage(messages.deepLinkKeysPlaceholder, {
|
|
673
690
|
key: (() => {
|
|
674
|
-
|
|
675
|
-
let selectedDeepLink = deepLink?.find((link) => link?.value === button?.deepLinkValue);
|
|
676
|
-
if (!selectedDeepLink && button?.deepLinkValue && button?.deepLinkValue.includes('?')) {
|
|
677
|
-
const baseDeepLinkValue = button?.deepLinkValue.split('?')[0];
|
|
678
|
-
selectedDeepLink = deepLink?.find((link) => link?.value === baseDeepLinkValue);
|
|
679
|
-
}
|
|
691
|
+
const selectedDeepLink = findSelectedDeepLink(deepLink, button?.deepLinkValue);
|
|
680
692
|
const deepLinkKeysFromSelection = selectedDeepLink?.keys;
|
|
681
693
|
let deepLinkKeysFromSelectionArray = [];
|
|
682
694
|
if (Array.isArray(deepLinkKeysFromSelection)) {
|
|
@@ -807,21 +819,44 @@ const MediaUploaders = ({
|
|
|
807
819
|
carouselActiveTabIndex,
|
|
808
820
|
uploadMpushAsset,
|
|
809
821
|
isFullMode,
|
|
810
|
-
setUpdateMpushImageSrc,
|
|
811
|
-
updateOnMpushImageReUpload,
|
|
812
822
|
imageData,
|
|
813
823
|
videoAssetList,
|
|
814
824
|
setUpdateMpushVideoSrc,
|
|
815
825
|
videoDataForVideo,
|
|
816
826
|
formatMessage,
|
|
817
|
-
clearImageDataByMediaType,
|
|
818
827
|
mobilePushActions,
|
|
819
828
|
carouselLinkErrors,
|
|
820
829
|
updateCarouselLinkError,
|
|
821
|
-
carouselActiveTabIndex,
|
|
822
830
|
setCarouselActiveTabIndex,
|
|
831
|
+
deepLink,
|
|
823
832
|
]);
|
|
824
833
|
|
|
834
|
+
// Manually handle upload completion for carousel cards (since automatic restoration is disabled)
|
|
835
|
+
useEffect(() => {
|
|
836
|
+
if (mediaType === CAROUSEL && uploadingCardIndex !== null && currentUploadId && imageData) {
|
|
837
|
+
const platformIndex = activeTab === ANDROID ? 0 : 1;
|
|
838
|
+
const uploadedData = imageData[`uploadedAssetData${platformIndex}`];
|
|
839
|
+
|
|
840
|
+
if (uploadedData && uploadedData.metaInfo && uploadedData.metaInfo.secure_file_path) {
|
|
841
|
+
// Check if this is new upload data (different from what we processed last time)
|
|
842
|
+
const currentDataKey = `${uploadedData.metaInfo.secure_file_path}_${uploadedData.metaInfo.file_name || ''}`;
|
|
843
|
+
const previousDataKey = previousUploadDataRef.current;
|
|
844
|
+
|
|
845
|
+
if (currentDataKey !== previousDataKey) {
|
|
846
|
+
// Update the specific card that was uploading
|
|
847
|
+
updateCarouselCard(uploadingCardIndex, { imageUrl: uploadedData.metaInfo.secure_file_path });
|
|
848
|
+
|
|
849
|
+
// Store this upload data as "processed" to avoid reprocessing
|
|
850
|
+
previousUploadDataRef.current = currentDataKey;
|
|
851
|
+
|
|
852
|
+
// Clear the uploading state
|
|
853
|
+
setUploadingCardIndex(null);
|
|
854
|
+
setCurrentUploadId(null);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}, [mediaType, imageData, uploadingCardIndex, currentUploadId, activeTab, updateCarouselCard]);
|
|
859
|
+
|
|
825
860
|
if (mediaType === IMAGE) return renderImageComponent();
|
|
826
861
|
if (mediaType === VIDEO) return renderVideoComponent();
|
|
827
862
|
if (mediaType === GIF) return renderGifComponent();
|
|
@@ -63,7 +63,7 @@ const PlatformContentFields = ({
|
|
|
63
63
|
let selectedDeepLink = deepLink?.find((link) => link?.value === deepLinkValue);
|
|
64
64
|
|
|
65
65
|
// If no exact match, try to find match without query parameters
|
|
66
|
-
if (!selectedDeepLink && deepLinkValue
|
|
66
|
+
if (!selectedDeepLink && deepLinkValue?.includes('?')) {
|
|
67
67
|
const baseDeepLinkValue = deepLinkValue.split('?')[0];
|
|
68
68
|
selectedDeepLink = deepLink?.find((link) => link?.value === baseDeepLinkValue);
|
|
69
69
|
}
|