@capillarytech/creatives-library 8.0.200 → 8.0.201-alpha.0
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 +0 -1
- package/package.json +1 -1
- package/utils/common.js +1 -7
- package/utils/createMobilePushPayload.js +29 -8
- package/utils/tests/createMobilePushPayload.test.js +53 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +3 -4
- package/v2Components/TemplatePreview/index.js +2 -2
- package/v2Containers/CreativesContainer/SlideBoxContent.js +2 -6
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +293 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +493 -0
- package/v2Containers/MobilePushNew/components/MediaUploaders.js +13 -6
- package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +3 -15
- package/v2Containers/MobilePushNew/index.js +172 -70
- package/v2Containers/MobilePushNew/messages.js +21 -0
- package/v2Containers/MobilePushNew/sagas.js +12 -2
- package/v2Containers/MobilePushNew/tests/sagas.test.js +9 -45
- package/v2Containers/Templates/index.js +11 -15
|
@@ -21,6 +21,7 @@ import { intlShape } from "react-intl";
|
|
|
21
21
|
import "./index.scss";
|
|
22
22
|
import { GA } from "@capillarytech/cap-ui-utils";
|
|
23
23
|
import CapNotification from "@capillarytech/cap-ui-library/CapNotification";
|
|
24
|
+
import { CapModal } from "@capillarytech/cap-react-ui-library";
|
|
24
25
|
import { DAEMON } from "@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes";
|
|
25
26
|
import globalMessages from "../Cap/messages";
|
|
26
27
|
import * as actions from "./actions";
|
|
@@ -529,6 +530,9 @@ const MobilePushNew = ({
|
|
|
529
530
|
STANDARD_ERROR_MSG: {},
|
|
530
531
|
LIQUID_ERROR_MSG: {},
|
|
531
532
|
});
|
|
533
|
+
// Modal state for single platform confirmation
|
|
534
|
+
const [showModal, setShowModal] = useState(false);
|
|
535
|
+
const [modalContent, setModalContent] = useState({});
|
|
532
536
|
const [androidContent, setAndroidContent] = useState(INITIAL_CONTENT);
|
|
533
537
|
|
|
534
538
|
const [iosContent, setIosContent] = useState(INITIAL_CONTENT);
|
|
@@ -2130,39 +2134,93 @@ const MobilePushNew = ({
|
|
|
2130
2134
|
return panes;
|
|
2131
2135
|
}, [isAndroidSupported, isIosSupported, renderContentFields, formatMessage]);
|
|
2132
2136
|
|
|
2133
|
-
// Save button disabled logic:
|
|
2137
|
+
// Save button disabled logic: require at least one platform to have data
|
|
2138
|
+
const hasAndroidData = isAndroidSupported && androidContent?.title?.trim() && androidContent?.message?.trim();
|
|
2139
|
+
const hasIosData = isIosSupported && iosContent?.title?.trim() && iosContent?.message?.trim();
|
|
2140
|
+
const hasAnyPlatformData = hasAndroidData || hasIosData;
|
|
2141
|
+
|
|
2142
|
+
// Validation checks for save button
|
|
2143
|
+
const carouselErrors = Object.values(carouselLinkErrors).some((error) => error !== null && error !== "");
|
|
2144
|
+
const carouselValid = isCarouselDataValid();
|
|
2145
|
+
|
|
2134
2146
|
const isSaveDisabled = (
|
|
2135
|
-
|
|
2136
|
-
|| (
|
|
2137
|
-
||
|
|
2138
|
-
||
|
|
2139
|
-
|| !isCarouselDataValid()
|
|
2147
|
+
!hasAnyPlatformData // At least one supported platform must have data
|
|
2148
|
+
|| (isFullMode && (!templateName || !templateName.trim())) // Template name required in full mode
|
|
2149
|
+
|| carouselErrors
|
|
2150
|
+
|| !carouselValid
|
|
2140
2151
|
);
|
|
2141
2152
|
|
|
2142
|
-
//
|
|
2143
|
-
const
|
|
2144
|
-
if (
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2153
|
+
// Modal handler functions
|
|
2154
|
+
const setModalContentHandler = useCallback((type) => {
|
|
2155
|
+
if (type === 'ios') {
|
|
2156
|
+
const content = {
|
|
2157
|
+
title: formatMessage(messages.alertMessage),
|
|
2158
|
+
body: formatMessage(messages.iosTemplateNotConfigured),
|
|
2159
|
+
type: 'confirm',
|
|
2160
|
+
id: 'ios',
|
|
2161
|
+
};
|
|
2162
|
+
setModalContent(content);
|
|
2163
|
+
setShowModal(true);
|
|
2164
|
+
} else if (type === 'android') {
|
|
2165
|
+
const content = {
|
|
2166
|
+
title: formatMessage(messages.alertMessage),
|
|
2167
|
+
body: formatMessage(messages.androidTemplateNotConfigured),
|
|
2168
|
+
type: 'confirm',
|
|
2169
|
+
id: 'android',
|
|
2170
|
+
};
|
|
2171
|
+
setModalContent(content);
|
|
2172
|
+
setShowModal(true);
|
|
2150
2173
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2174
|
+
}, [formatMessage]);
|
|
2175
|
+
|
|
2176
|
+
const handleCancelModal = useCallback(() => {
|
|
2177
|
+
setShowModal(false);
|
|
2178
|
+
setModalContent({});
|
|
2179
|
+
}, []);
|
|
2180
|
+
|
|
2181
|
+
// Internal save function with optional modal validation skip
|
|
2182
|
+
const handleSaveInternal = useCallback((skipModalValidation = false) => {
|
|
2183
|
+
// Check for single platform data and show modal confirmation (unless skipped)
|
|
2184
|
+
if (!skipModalValidation) {
|
|
2185
|
+
const androidHasData = androidContent?.title?.trim() && androidContent?.message?.trim();
|
|
2186
|
+
const iosHasData = iosContent?.title?.trim() && iosContent?.message?.trim();
|
|
2187
|
+
|
|
2188
|
+
// If both platforms are supported but only one has data, show confirmation modal
|
|
2189
|
+
if (isAndroidSupported && isIosSupported) {
|
|
2190
|
+
if (androidHasData && !iosHasData) {
|
|
2191
|
+
setModalContentHandler('ios'); // Show iOS not configured modal
|
|
2192
|
+
return;
|
|
2193
|
+
}
|
|
2194
|
+
if (iosHasData && !androidHasData) {
|
|
2195
|
+
setModalContentHandler('android'); // Show Android not configured modal
|
|
2196
|
+
return;
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2157
2199
|
}
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2200
|
+
|
|
2201
|
+
// Only validate platforms that have data or are required
|
|
2202
|
+
// If user confirmed via modal, we allow single platform data
|
|
2203
|
+
if (!skipModalValidation) {
|
|
2204
|
+
// In normal flow, require data for all supported platforms
|
|
2205
|
+
if (isAndroidSupported && (!androidContent?.title?.trim() || !androidContent?.message?.trim())) {
|
|
2206
|
+
CapNotification.error({
|
|
2207
|
+
message: formatMessage(messages.androidValidationError),
|
|
2208
|
+
});
|
|
2209
|
+
if (onValidationFail) onValidationFail();
|
|
2210
|
+
return;
|
|
2211
|
+
}
|
|
2212
|
+
if (isIosSupported && (!iosContent?.title?.trim() || !iosContent?.message?.trim())) {
|
|
2213
|
+
CapNotification.error({
|
|
2214
|
+
message: formatMessage(messages.iosValidationError),
|
|
2215
|
+
});
|
|
2216
|
+
if (onValidationFail) onValidationFail();
|
|
2217
|
+
return;
|
|
2218
|
+
}
|
|
2163
2219
|
}
|
|
2164
|
-
//
|
|
2165
|
-
//
|
|
2220
|
+
// Note: In modal-confirmed flow (skipModalValidation = true), we skip platform validation
|
|
2221
|
+
// since user has already confirmed they want to save with incomplete platform data
|
|
2222
|
+
|
|
2223
|
+
// Template name validation - only required in full mode
|
|
2166
2224
|
const currentTemplateName = templateNameRef.current || templateName;
|
|
2167
2225
|
if (isFullMode && !currentTemplateName?.trim()) {
|
|
2168
2226
|
CapNotification.error({
|
|
@@ -2327,6 +2385,8 @@ const MobilePushNew = ({
|
|
|
2327
2385
|
}
|
|
2328
2386
|
|
|
2329
2387
|
// Create payload with enabled platform content and intl
|
|
2388
|
+
// In modal-confirmed flow, we may have intentionally missing platform data
|
|
2389
|
+
const allowSinglePlatform = skipModalValidation;
|
|
2330
2390
|
const payload = createMobilePushPayloadWithIntl({
|
|
2331
2391
|
templateName: finalTemplateName,
|
|
2332
2392
|
androidContent: isAndroidSupported ? processedAndroidContent : undefined,
|
|
@@ -2337,6 +2397,7 @@ const MobilePushNew = ({
|
|
|
2337
2397
|
sameContent,
|
|
2338
2398
|
options: {
|
|
2339
2399
|
mode: params?.mode,
|
|
2400
|
+
allowSinglePlatform,
|
|
2340
2401
|
},
|
|
2341
2402
|
intl,
|
|
2342
2403
|
});
|
|
@@ -2516,6 +2577,68 @@ const MobilePushNew = ({
|
|
|
2516
2577
|
isCarouselDataValid,
|
|
2517
2578
|
isFullMode,
|
|
2518
2579
|
templateId,
|
|
2580
|
+
activeTab,
|
|
2581
|
+
setModalContentHandler,
|
|
2582
|
+
]);
|
|
2583
|
+
|
|
2584
|
+
// Public save function (with modal validation)
|
|
2585
|
+
const handleSave = useCallback(() => {
|
|
2586
|
+
handleSaveInternal(false);
|
|
2587
|
+
}, [handleSaveInternal]);
|
|
2588
|
+
|
|
2589
|
+
// Save function that skips single platform modal validation
|
|
2590
|
+
const handleSaveWithoutModal = useCallback(() => {
|
|
2591
|
+
handleSaveInternal(true);
|
|
2592
|
+
}, [handleSaveInternal]);
|
|
2593
|
+
|
|
2594
|
+
const handleConfirmModal = useCallback(() => {
|
|
2595
|
+
setShowModal(false);
|
|
2596
|
+
setModalContent({});
|
|
2597
|
+
// Proceed with save after modal confirmation - skip single platform validation
|
|
2598
|
+
handleSaveWithoutModal();
|
|
2599
|
+
}, [handleSaveWithoutModal]);
|
|
2600
|
+
|
|
2601
|
+
const liquidMiddleWare = useCallback(() => {
|
|
2602
|
+
const onError = ({ standardErrors, liquidErrors }) => {
|
|
2603
|
+
setErrorMessage((prev) => ({
|
|
2604
|
+
STANDARD_ERROR_MSG: { ...prev.STANDARD_ERROR_MSG, ...standardErrors },
|
|
2605
|
+
LIQUID_ERROR_MSG: { ...prev.LIQUID_ERROR_MSG, ...liquidErrors },
|
|
2606
|
+
}));
|
|
2607
|
+
};
|
|
2608
|
+
const onSuccess = () => handleSave();
|
|
2609
|
+
|
|
2610
|
+
validateMobilePushContent([androidContent, iosContent], {
|
|
2611
|
+
currentTab: activeTab === ANDROID ? 1 : 2,
|
|
2612
|
+
onError,
|
|
2613
|
+
onSuccess,
|
|
2614
|
+
getLiquidTags: globalActionsProps.getLiquidTags,
|
|
2615
|
+
formatMessage,
|
|
2616
|
+
messages: formBuilderMessages,
|
|
2617
|
+
tagLookupMap: metaEntities?.tagLookupMap || {},
|
|
2618
|
+
eventContextTags: metaEntities?.eventContextTags || [],
|
|
2619
|
+
isLiquidFlow: hasLiquidSupportFeature(),
|
|
2620
|
+
forwardedTags: {},
|
|
2621
|
+
skipTags: (tag) => {
|
|
2622
|
+
const skipRegexes = [
|
|
2623
|
+
/dynamic_expiry_date_after_\d+_days\.FORMAT_\d/,
|
|
2624
|
+
/unsubscribe\(#[a-zA-Z\d]{6}\)/,
|
|
2625
|
+
/Link_to_[a-zA-z]/,
|
|
2626
|
+
/SURVEY.*\.TOKEN/,
|
|
2627
|
+
/^[A-Za-z].*\([a-zA-Z\d]*\)/,
|
|
2628
|
+
];
|
|
2629
|
+
return skipRegexes.some((regex) => regex.test(tag));
|
|
2630
|
+
},
|
|
2631
|
+
singleTab: getSingleTab(accountData),
|
|
2632
|
+
});
|
|
2633
|
+
}, [
|
|
2634
|
+
androidContent,
|
|
2635
|
+
iosContent,
|
|
2636
|
+
activeTab,
|
|
2637
|
+
globalActionsProps,
|
|
2638
|
+
formatMessage,
|
|
2639
|
+
metaEntities,
|
|
2640
|
+
accountData,
|
|
2641
|
+
handleSave,
|
|
2519
2642
|
]);
|
|
2520
2643
|
|
|
2521
2644
|
// Helper to sync content between platforms
|
|
@@ -2547,7 +2670,9 @@ const MobilePushNew = ({
|
|
|
2547
2670
|
setTemplateName(value);
|
|
2548
2671
|
// Update ref to always have the latest value
|
|
2549
2672
|
templateNameRef.current = value;
|
|
2550
|
-
|
|
2673
|
+
// Only set error if user has interacted and field is empty
|
|
2674
|
+
// In full mode, template name is required only at save time, not during typing
|
|
2675
|
+
const isInvalid = isFullMode && value.trim() === "";
|
|
2551
2676
|
setTemplateNameError(isInvalid);
|
|
2552
2677
|
if (value && onEnterTemplateName) {
|
|
2553
2678
|
onEnterTemplateName();
|
|
@@ -2555,7 +2680,7 @@ const MobilePushNew = ({
|
|
|
2555
2680
|
onRemoveTemplateName();
|
|
2556
2681
|
}
|
|
2557
2682
|
},
|
|
2558
|
-
[onEnterTemplateName, onRemoveTemplateName]
|
|
2683
|
+
[onEnterTemplateName, onRemoveTemplateName, isFullMode]
|
|
2559
2684
|
);
|
|
2560
2685
|
|
|
2561
2686
|
// --- Only show template name input in full mode (not library/consumer mode) ---
|
|
@@ -2584,47 +2709,6 @@ const MobilePushNew = ({
|
|
|
2584
2709
|
[isFullMode, formatMessage, templateName, onTemplateNameChange, templateNameError, params?.id]
|
|
2585
2710
|
);
|
|
2586
2711
|
|
|
2587
|
-
const liquidMiddleWare = useCallback(() => {
|
|
2588
|
-
const onError = ({ standardErrors, liquidErrors }) => {
|
|
2589
|
-
setErrorMessage((prev) => ({
|
|
2590
|
-
STANDARD_ERROR_MSG: { ...prev.STANDARD_ERROR_MSG, ...standardErrors },
|
|
2591
|
-
LIQUID_ERROR_MSG: { ...prev.LIQUID_ERROR_MSG, ...liquidErrors },
|
|
2592
|
-
}));
|
|
2593
|
-
};
|
|
2594
|
-
const onSuccess = () => handleSave();
|
|
2595
|
-
|
|
2596
|
-
validateMobilePushContent([androidContent, iosContent], {
|
|
2597
|
-
currentTab: activeTab === ANDROID ? 1 : 2,
|
|
2598
|
-
onError,
|
|
2599
|
-
onSuccess,
|
|
2600
|
-
getLiquidTags: globalActionsProps.getLiquidTags,
|
|
2601
|
-
formatMessage,
|
|
2602
|
-
messages: formBuilderMessages,
|
|
2603
|
-
tagLookupMap: metaEntities?.tagLookupMap || {},
|
|
2604
|
-
eventContextTags: metaEntities?.eventContextTags || [],
|
|
2605
|
-
isLiquidFlow: hasLiquidSupportFeature(),
|
|
2606
|
-
forwardedTags: {},
|
|
2607
|
-
skipTags: (tag) => {
|
|
2608
|
-
const skipRegexes = [
|
|
2609
|
-
/dynamic_expiry_date_after_\d+_days\.FORMAT_\d/,
|
|
2610
|
-
/unsubscribe\(#[a-zA-Z\d]{6}\)/,
|
|
2611
|
-
/Link_to_[a-zA-z]/,
|
|
2612
|
-
/SURVEY.*\.TOKEN/,
|
|
2613
|
-
/^[A-Za-z].*\([a-zA-Z\d]*\)/,
|
|
2614
|
-
];
|
|
2615
|
-
return skipRegexes.some((regex) => regex.test(tag));
|
|
2616
|
-
},
|
|
2617
|
-
singleTab: getSingleTab(accountData),
|
|
2618
|
-
});
|
|
2619
|
-
}, [
|
|
2620
|
-
androidContent,
|
|
2621
|
-
iosContent,
|
|
2622
|
-
activeTab,
|
|
2623
|
-
globalActionsProps,
|
|
2624
|
-
formatMessage,
|
|
2625
|
-
metaEntities,
|
|
2626
|
-
accountData,
|
|
2627
|
-
]);
|
|
2628
2712
|
|
|
2629
2713
|
const isLiquidFlow = hasLiquidSupportFeature();
|
|
2630
2714
|
|
|
@@ -2945,6 +3029,24 @@ const MobilePushNew = ({
|
|
|
2945
3029
|
/>
|
|
2946
3030
|
</CapColumn>
|
|
2947
3031
|
</CapRow>
|
|
3032
|
+
|
|
3033
|
+
{/* Modal for single platform confirmation */}
|
|
3034
|
+
<CapModal
|
|
3035
|
+
visible={showModal}
|
|
3036
|
+
title={modalContent.title}
|
|
3037
|
+
onOk={handleConfirmModal}
|
|
3038
|
+
onCancel={handleCancelModal}
|
|
3039
|
+
footer={[
|
|
3040
|
+
<CapButton key="cancel" onClick={handleCancelModal}>
|
|
3041
|
+
No
|
|
3042
|
+
</CapButton>,
|
|
3043
|
+
<CapButton key="confirm" type="primary" onClick={handleConfirmModal}>
|
|
3044
|
+
Yes
|
|
3045
|
+
</CapButton>,
|
|
3046
|
+
]}
|
|
3047
|
+
>
|
|
3048
|
+
{modalContent.body}
|
|
3049
|
+
</CapModal>
|
|
2948
3050
|
</CapSpin>
|
|
2949
3051
|
);
|
|
2950
3052
|
};
|
|
@@ -91,6 +91,10 @@ export default defineMessages({
|
|
|
91
91
|
id: `${scope}.actionOnClickBody`,
|
|
92
92
|
defaultMessage: 'Action on click of notification body',
|
|
93
93
|
},
|
|
94
|
+
carouselActionDisabledMessage: {
|
|
95
|
+
id: `${scope}.carouselActionDisabledMessage`,
|
|
96
|
+
defaultMessage: 'This section is being revamped. Till then it will remain disabled.',
|
|
97
|
+
},
|
|
94
98
|
actionDescription: {
|
|
95
99
|
id: `${scope}.actionDescription`,
|
|
96
100
|
defaultMessage: 'Define where the users will redirect when they click on the body of the push notification',
|
|
@@ -252,6 +256,10 @@ export default defineMessages({
|
|
|
252
256
|
id: `${scope}.contentValidationError`,
|
|
253
257
|
defaultMessage: '{platform} content must have title and message',
|
|
254
258
|
},
|
|
259
|
+
singlePlatformContentMissing: {
|
|
260
|
+
id: `${scope}.singlePlatformContentMissing`,
|
|
261
|
+
defaultMessage: 'At least one platform must have title and message',
|
|
262
|
+
},
|
|
255
263
|
// File validation error messages for useUpload.js
|
|
256
264
|
fileSizeError: {
|
|
257
265
|
id: `${scope}.fileSizeError`,
|
|
@@ -269,4 +277,17 @@ export default defineMessages({
|
|
|
269
277
|
id: `${scope}.gifFileTypeError`,
|
|
270
278
|
defaultMessage: 'Only GIF files are allowed',
|
|
271
279
|
},
|
|
280
|
+
// Modal confirmation messages for single platform data
|
|
281
|
+
alertMessage: {
|
|
282
|
+
id: `${scope}.alertMessage`,
|
|
283
|
+
defaultMessage: 'Alert',
|
|
284
|
+
},
|
|
285
|
+
androidTemplateNotConfigured: {
|
|
286
|
+
id: `${scope}.androidTemplateNotConfigured`,
|
|
287
|
+
defaultMessage: 'Android template is not configured. Continue save?',
|
|
288
|
+
},
|
|
289
|
+
iosTemplateNotConfigured: {
|
|
290
|
+
id: `${scope}.iosTemplateNotConfigured`,
|
|
291
|
+
defaultMessage: 'IOS template is not configured, Save without IOS template',
|
|
292
|
+
},
|
|
272
293
|
});
|
|
@@ -24,7 +24,12 @@ export function* createTemplate({template, callback}) {
|
|
|
24
24
|
errorMsg,
|
|
25
25
|
});
|
|
26
26
|
} catch (error) {
|
|
27
|
-
|
|
27
|
+
// Call callback with error if provided, otherwise dispatch failure action
|
|
28
|
+
if (callback) {
|
|
29
|
+
yield call(callback, new Error(errorMsg || error.message || error.toString()));
|
|
30
|
+
} else {
|
|
31
|
+
yield put({ type: types.CREATE_TEMPLATE_FAILURE, error, errorMsg });
|
|
32
|
+
}
|
|
28
33
|
}
|
|
29
34
|
}
|
|
30
35
|
export function* uploadAsset(action) {
|
|
@@ -91,7 +96,12 @@ export function* editTemplate({ template, callback }) {
|
|
|
91
96
|
yield call(callback, editResponseData);
|
|
92
97
|
}
|
|
93
98
|
} catch (error) {
|
|
94
|
-
|
|
99
|
+
// Call callback with error if provided, otherwise dispatch failure action
|
|
100
|
+
if (callback) {
|
|
101
|
+
yield call(callback, new Error(errorMsg || error.message || error.toString()));
|
|
102
|
+
} else {
|
|
103
|
+
yield put({ type: types.EDIT_TEMPLATE_FAILURE, error, errorMsg });
|
|
104
|
+
}
|
|
95
105
|
}
|
|
96
106
|
}
|
|
97
107
|
|
|
@@ -87,11 +87,7 @@ describe('MobilePushNew Sagas', () => {
|
|
|
87
87
|
[matchers.call.fn(Api.createMobilePushTemplateV2), mockResponse],
|
|
88
88
|
])
|
|
89
89
|
.call(Api.createMobilePushTemplateV2, template)
|
|
90
|
-
.
|
|
91
|
-
type: types.CREATE_TEMPLATE_FAILURE,
|
|
92
|
-
error: 'Bad Request',
|
|
93
|
-
errorMsg: 'Bad Request',
|
|
94
|
-
})
|
|
90
|
+
.call(callback, new Error('Bad Request'))
|
|
95
91
|
.run();
|
|
96
92
|
});
|
|
97
93
|
|
|
@@ -125,11 +121,7 @@ describe('MobilePushNew Sagas', () => {
|
|
|
125
121
|
[matchers.call.fn(Api.createMobilePushTemplateV2), throwError(error)],
|
|
126
122
|
])
|
|
127
123
|
.call(Api.createMobilePushTemplateV2, template)
|
|
128
|
-
.
|
|
129
|
-
type: types.CREATE_TEMPLATE_FAILURE,
|
|
130
|
-
error,
|
|
131
|
-
errorMsg: undefined,
|
|
132
|
-
})
|
|
124
|
+
.call(callback, new Error('Network error'))
|
|
133
125
|
.run();
|
|
134
126
|
});
|
|
135
127
|
|
|
@@ -372,11 +364,7 @@ describe('MobilePushNew Sagas', () => {
|
|
|
372
364
|
[matchers.call.fn(Api.createMobilePushTemplateV2), mockResponse],
|
|
373
365
|
])
|
|
374
366
|
.call(Api.createMobilePushTemplateV2, template)
|
|
375
|
-
.
|
|
376
|
-
type: types.EDIT_TEMPLATE_FAILURE,
|
|
377
|
-
error: 'Bad Request',
|
|
378
|
-
errorMsg: 'Bad Request',
|
|
379
|
-
})
|
|
367
|
+
.call(callback, new Error('Bad Request'))
|
|
380
368
|
.run();
|
|
381
369
|
});
|
|
382
370
|
|
|
@@ -392,11 +380,7 @@ describe('MobilePushNew Sagas', () => {
|
|
|
392
380
|
[matchers.call.fn(Api.createMobilePushTemplateV2), mockResponse],
|
|
393
381
|
])
|
|
394
382
|
.call(Api.createMobilePushTemplateV2, template)
|
|
395
|
-
.
|
|
396
|
-
type: types.EDIT_TEMPLATE_FAILURE,
|
|
397
|
-
error: 'Internal Server Error',
|
|
398
|
-
errorMsg: 'Internal Server Error',
|
|
399
|
-
})
|
|
383
|
+
.call(callback, new Error('Internal Server Error'))
|
|
400
384
|
.run();
|
|
401
385
|
});
|
|
402
386
|
|
|
@@ -408,11 +392,7 @@ describe('MobilePushNew Sagas', () => {
|
|
|
408
392
|
[matchers.call.fn(Api.createMobilePushTemplateV2), throwError(error)],
|
|
409
393
|
])
|
|
410
394
|
.call(Api.createMobilePushTemplateV2, template)
|
|
411
|
-
.
|
|
412
|
-
type: types.EDIT_TEMPLATE_FAILURE,
|
|
413
|
-
error,
|
|
414
|
-
errorMsg: undefined,
|
|
415
|
-
})
|
|
395
|
+
.call(callback, new Error('Network error'))
|
|
416
396
|
.run();
|
|
417
397
|
});
|
|
418
398
|
|
|
@@ -459,11 +439,7 @@ describe('MobilePushNew Sagas', () => {
|
|
|
459
439
|
[matchers.call.fn(Api.createMobilePushTemplateV2), mockResponse],
|
|
460
440
|
])
|
|
461
441
|
.call(Api.createMobilePushTemplateV2, template)
|
|
462
|
-
.
|
|
463
|
-
type: types.EDIT_TEMPLATE_FAILURE,
|
|
464
|
-
error: 'HTTP Error 400',
|
|
465
|
-
errorMsg: 'HTTP Error 400',
|
|
466
|
-
})
|
|
442
|
+
.call(callback, new Error('HTTP Error 400'))
|
|
467
443
|
.run();
|
|
468
444
|
});
|
|
469
445
|
|
|
@@ -479,11 +455,7 @@ describe('MobilePushNew Sagas', () => {
|
|
|
479
455
|
[matchers.call.fn(Api.createMobilePushTemplateV2), mockResponse],
|
|
480
456
|
])
|
|
481
457
|
.call(Api.createMobilePushTemplateV2, template)
|
|
482
|
-
.
|
|
483
|
-
type: types.EDIT_TEMPLATE_FAILURE,
|
|
484
|
-
error: 'HTTP Error 404',
|
|
485
|
-
errorMsg: 'HTTP Error 404',
|
|
486
|
-
})
|
|
458
|
+
.call(callback, new Error('HTTP Error 404'))
|
|
487
459
|
.run();
|
|
488
460
|
});
|
|
489
461
|
|
|
@@ -499,11 +471,7 @@ describe('MobilePushNew Sagas', () => {
|
|
|
499
471
|
[matchers.call.fn(Api.createMobilePushTemplateV2), mockResponse],
|
|
500
472
|
])
|
|
501
473
|
.call(Api.createMobilePushTemplateV2, template)
|
|
502
|
-
.
|
|
503
|
-
type: types.EDIT_TEMPLATE_FAILURE,
|
|
504
|
-
error: 'HTTP Error 422',
|
|
505
|
-
errorMsg: 'HTTP Error 422',
|
|
506
|
-
})
|
|
474
|
+
.call(callback, new Error('HTTP Error 422'))
|
|
507
475
|
.run();
|
|
508
476
|
});
|
|
509
477
|
|
|
@@ -519,11 +487,7 @@ describe('MobilePushNew Sagas', () => {
|
|
|
519
487
|
[matchers.call.fn(Api.createMobilePushTemplateV2), mockResponse],
|
|
520
488
|
])
|
|
521
489
|
.call(Api.createMobilePushTemplateV2, template)
|
|
522
|
-
.
|
|
523
|
-
type: types.EDIT_TEMPLATE_FAILURE,
|
|
524
|
-
error: 'HTTP Error 403',
|
|
525
|
-
errorMsg: 'HTTP Error 403',
|
|
526
|
-
})
|
|
490
|
+
.call(callback, new Error('HTTP Error 403'))
|
|
527
491
|
.run();
|
|
528
492
|
});
|
|
529
493
|
|
|
@@ -1357,19 +1357,16 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1357
1357
|
break;
|
|
1358
1358
|
}
|
|
1359
1359
|
case MOBILE_PUSH:
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
const { title, message, expandableDetails: { style = '', image, carouselData = [], ctas = [], media = [] } = {} } = mpushListingData || {};
|
|
1371
|
-
const {url = ''} = media?.[0] || {};
|
|
1372
|
-
templateData.content = (
|
|
1360
|
+
const mpushData = get(template, 'versions.base', template);
|
|
1361
|
+
const androidData = get(mpushData, 'ANDROID') || get(mpushData, 'androidContent');
|
|
1362
|
+
const iosData = get(mpushData, 'IOS') || get(mpushData, 'iosContent');
|
|
1363
|
+
let mpushListingData = androidData;
|
|
1364
|
+
if (isEmpty(androidData) || !androidData?.title) {
|
|
1365
|
+
mpushListingData = iosData;
|
|
1366
|
+
};
|
|
1367
|
+
const { title, message, expandableDetails: { style = '', image, carouselData = [], ctas = [], media = [] } = {} } = mpushListingData || {};
|
|
1368
|
+
const {url = ''} = media?.[0] || {};
|
|
1369
|
+
templateData.content = (
|
|
1373
1370
|
<div className='mobilepush-container'>
|
|
1374
1371
|
<div className="app-header">
|
|
1375
1372
|
<div className="app-header-left">
|
|
@@ -1441,8 +1438,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1441
1438
|
)}
|
|
1442
1439
|
</div>
|
|
1443
1440
|
);
|
|
1444
|
-
|
|
1445
|
-
}
|
|
1441
|
+
templateData.isNewMobilePush = true;
|
|
1446
1442
|
break;
|
|
1447
1443
|
case INAPP:
|
|
1448
1444
|
templateData.content = template;
|