@capillarytech/creatives-library 8.0.298 → 8.0.299-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/constants/unified.js +1 -0
- package/package.json +1 -1
- package/services/api.js +17 -0
- package/services/tests/api.test.js +85 -0
- package/utils/common.js +6 -1
- package/utils/commonUtils.js +10 -0
- package/utils/tests/commonUtil.test.js +169 -0
- package/v2Components/CapDeviceContent/index.js +10 -7
- package/v2Components/CommonTestAndPreview/AddTestCustomer.js +42 -0
- package/v2Components/CommonTestAndPreview/CustomerCreationModal.js +284 -0
- package/v2Components/CommonTestAndPreview/ExistingCustomerModal.js +72 -0
- package/v2Components/CommonTestAndPreview/SendTestMessage.js +78 -49
- package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +189 -4
- package/v2Components/CommonTestAndPreview/actions.js +10 -0
- package/v2Components/CommonTestAndPreview/constants.js +18 -1
- package/v2Components/CommonTestAndPreview/index.js +259 -14
- package/v2Components/CommonTestAndPreview/messages.js +94 -0
- package/v2Components/CommonTestAndPreview/reducer.js +10 -0
- package/v2Components/CommonTestAndPreview/tests/AddTestCustomer.test.js +66 -0
- package/v2Components/CommonTestAndPreview/tests/CommonTestAndPreview.addTestCustomer.test.js +653 -0
- package/v2Components/CommonTestAndPreview/tests/CustomerCreationModal.test.js +316 -0
- package/v2Components/CommonTestAndPreview/tests/ExistingCustomerModal.test.js +114 -0
- package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +53 -0
- package/v2Components/CommonTestAndPreview/tests/constants.test.js +25 -2
- package/v2Components/CommonTestAndPreview/tests/index.test.js +7 -0
- package/v2Components/CommonTestAndPreview/tests/reducer.test.js +71 -0
- package/v2Components/CommonTestAndPreview/tests/selectors.test.js +17 -0
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +320 -0
- package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +132 -0
- package/v2Containers/BeePopupEditor/index.js +9 -2
- package/v2Containers/CreativesContainer/SlideBoxContent.js +35 -3
- package/v2Containers/InApp/index.js +182 -13
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +1408 -1276
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +321 -288
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +5246 -4872
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import CapModal from "@capillarytech/cap-ui-library/CapModal";
|
|
2
|
+
import CapButton from "@capillarytech/cap-ui-library/CapButton";
|
|
3
|
+
import CapInput from "@capillarytech/cap-ui-library/CapInput";
|
|
4
|
+
import CapLabel from "@capillarytech/cap-ui-library/CapLabel";
|
|
5
|
+
import CapRow from "@capillarytech/cap-ui-library/CapRow";
|
|
6
|
+
import CapColumn from "@capillarytech/cap-ui-library/CapColumn";
|
|
7
|
+
import CapSpin from "@capillarytech/cap-ui-library/CapSpin";
|
|
8
|
+
import { FormattedMessage, injectIntl } from "react-intl";
|
|
9
|
+
import messages from "./messages";
|
|
10
|
+
import React, { useState, useCallback, useEffect, useRef } from "react";
|
|
11
|
+
import { CHANNELS, IDENTIFIER_TYPE_EMAIL, IDENTIFIER_TYPE_MOBILE, INPUT_HAS_ERROR_CLASS } from "./constants";
|
|
12
|
+
import { getMembersLookup } from '../../services/api';
|
|
13
|
+
import { isValidEmail, isValidMobile, formatPhoneNumber } from "../../utils/commonUtils";
|
|
14
|
+
|
|
15
|
+
const CustomerCreationModal = ({
|
|
16
|
+
customerModal,
|
|
17
|
+
setCustomerModal,
|
|
18
|
+
channel,
|
|
19
|
+
customerData,
|
|
20
|
+
setCustomerData,
|
|
21
|
+
onSave,
|
|
22
|
+
intl,
|
|
23
|
+
}) => {
|
|
24
|
+
const [validationErrors, setValidationErrors] = useState({
|
|
25
|
+
email: "",
|
|
26
|
+
mobile: ""
|
|
27
|
+
});
|
|
28
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
29
|
+
const [lookupLoading, setLookupLoading] = useState(null); // null | IDENTIFIER_TYPE_EMAIL | IDENTIFIER_TYPE_MOBILE
|
|
30
|
+
|
|
31
|
+
// Refs to track the latest values for async validation
|
|
32
|
+
const latestEmailRef = useRef(customerData.email || "");
|
|
33
|
+
const latestMobileRef = useRef(customerData.mobile || "");
|
|
34
|
+
|
|
35
|
+
// Helper function to render validation errors
|
|
36
|
+
const renderValidationError = (error) => {
|
|
37
|
+
if (!error) return null;
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className="customer-creation-modal-validation-error">
|
|
41
|
+
{typeof error === 'string' ? error : <FormattedMessage {...error} />}
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Check if required fields are filled based on channel
|
|
47
|
+
const isRequiredFieldMissing = () => {
|
|
48
|
+
if (channel === CHANNELS.EMAIL && !customerData.email) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
if (channel === CHANNELS.SMS && !customerData.mobile) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Check if save button should be disabled
|
|
58
|
+
const isSaveDisabled = () => {
|
|
59
|
+
return (
|
|
60
|
+
validationErrors.email ||
|
|
61
|
+
validationErrors.mobile ||
|
|
62
|
+
isRequiredFieldMissing() ||
|
|
63
|
+
!!lookupLoading
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Perform lookup (same logic as in index.js)
|
|
68
|
+
const performLookup = useCallback(async (identifierType, value) => {
|
|
69
|
+
try {
|
|
70
|
+
const response = await getMembersLookup(identifierType, value);
|
|
71
|
+
const success = response?.success && !response?.status?.isError;
|
|
72
|
+
const res = response?.response || {};
|
|
73
|
+
const exists = res.exists || false;
|
|
74
|
+
const details = res.customerDetails || [];
|
|
75
|
+
if (!success) {
|
|
76
|
+
const errorMessage = response?.message || response?.status?.message
|
|
77
|
+
if (errorMessage.toLowerCase().includes("merged customer found")) {
|
|
78
|
+
return { success: true, exists: true, details: [] };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return { success, exists, details };
|
|
83
|
+
} catch (error) {
|
|
84
|
+
return { success: false, exists: false, details: [] };
|
|
85
|
+
}
|
|
86
|
+
}, []);
|
|
87
|
+
|
|
88
|
+
// Handle validation and lookup for email or mobile
|
|
89
|
+
const handleLookupValidation = useCallback(async (type, value) => {
|
|
90
|
+
const isEmail = type === IDENTIFIER_TYPE_EMAIL;
|
|
91
|
+
const ref = isEmail ? latestEmailRef : latestMobileRef;
|
|
92
|
+
const field = isEmail ? IDENTIFIER_TYPE_EMAIL : IDENTIFIER_TYPE_MOBILE;
|
|
93
|
+
|
|
94
|
+
if (!value) {
|
|
95
|
+
if (ref.current === value) {
|
|
96
|
+
setValidationErrors(prev => ({ ...prev, [field]: "" }));
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (isEmail && !isValidEmail(value)) {
|
|
102
|
+
if (ref.current === value) {
|
|
103
|
+
setValidationErrors(prev => ({ ...prev, [IDENTIFIER_TYPE_EMAIL]: "Please enter a valid email address" }));
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (!isEmail && !isValidMobile(value)) {
|
|
108
|
+
if (ref.current === value) {
|
|
109
|
+
setValidationErrors(prev => ({ ...prev, [IDENTIFIER_TYPE_MOBILE]: "Please enter a valid mobile number" }));
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
setLookupLoading(field);
|
|
115
|
+
try {
|
|
116
|
+
const { success, exists } = await performLookup(type, value);
|
|
117
|
+
|
|
118
|
+
if (ref.current === value) {
|
|
119
|
+
if (success && exists) {
|
|
120
|
+
setValidationErrors(prev => ({
|
|
121
|
+
...prev,
|
|
122
|
+
[field]: isEmail ? messages.emailAlreadyExists : messages.mobileAlreadyExists
|
|
123
|
+
}));
|
|
124
|
+
} else {
|
|
125
|
+
setValidationErrors(prev => ({ ...prev, [field]: "" }));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} finally {
|
|
129
|
+
setLookupLoading(null);
|
|
130
|
+
}
|
|
131
|
+
}, [performLookup]);
|
|
132
|
+
|
|
133
|
+
// Debounce timer refs
|
|
134
|
+
const emailTimeoutRef = React.useRef(null);
|
|
135
|
+
const mobileTimeoutRef = React.useRef(null);
|
|
136
|
+
|
|
137
|
+
// Handle email change with debounced validation
|
|
138
|
+
const handleEmailChange = (e) => {
|
|
139
|
+
const email = e.target.value;
|
|
140
|
+
latestEmailRef.current = email; // Update the latest email ref
|
|
141
|
+
setCustomerData({ ...customerData, email });
|
|
142
|
+
|
|
143
|
+
// Clear previous timeout
|
|
144
|
+
if (emailTimeoutRef.current) {
|
|
145
|
+
clearTimeout(emailTimeoutRef.current);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Set new timeout for validation
|
|
149
|
+
emailTimeoutRef.current = setTimeout(() => {
|
|
150
|
+
handleLookupValidation(IDENTIFIER_TYPE_EMAIL, email);
|
|
151
|
+
}, 500);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// Handle mobile change with debounced validation
|
|
155
|
+
const handleMobileChange = (e) => {
|
|
156
|
+
const rawValue = e.target.value;
|
|
157
|
+
const formattedMobile = formatPhoneNumber(rawValue);
|
|
158
|
+
latestMobileRef.current = formattedMobile; // Update the latest mobile ref
|
|
159
|
+
setCustomerData({ ...customerData, mobile: formattedMobile });
|
|
160
|
+
|
|
161
|
+
// Clear previous timeout
|
|
162
|
+
if (mobileTimeoutRef.current) {
|
|
163
|
+
clearTimeout(mobileTimeoutRef.current);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Set new timeout for validation
|
|
167
|
+
mobileTimeoutRef.current = setTimeout(() => {
|
|
168
|
+
handleLookupValidation(IDENTIFIER_TYPE_MOBILE, formattedMobile);
|
|
169
|
+
}, 500);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Update refs when customerData changes externally
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
latestEmailRef.current = customerData.email || "";
|
|
175
|
+
latestMobileRef.current = customerData.mobile || "";
|
|
176
|
+
}, [customerData.email, customerData.mobile]);
|
|
177
|
+
|
|
178
|
+
// Cleanup timeouts on unmount
|
|
179
|
+
useEffect(() => {
|
|
180
|
+
return () => {
|
|
181
|
+
if (emailTimeoutRef.current) {
|
|
182
|
+
clearTimeout(emailTimeoutRef.current);
|
|
183
|
+
}
|
|
184
|
+
if (mobileTimeoutRef.current) {
|
|
185
|
+
clearTimeout(mobileTimeoutRef.current);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}, []);
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<CapModal
|
|
192
|
+
visible={customerModal[0]}
|
|
193
|
+
onCancel={() => setCustomerModal([false, ""])}
|
|
194
|
+
centered={true}
|
|
195
|
+
width={500}
|
|
196
|
+
maskStyle={{ backgroundColor: 'rgba(244, 245, 247, 0.9)' }}
|
|
197
|
+
footer={
|
|
198
|
+
<CapRow justify="start" text-align="left" gutter={8}>
|
|
199
|
+
<CapButton
|
|
200
|
+
type="primary"
|
|
201
|
+
onClick={() => onSave(validationErrors, setIsLoading)}
|
|
202
|
+
disabled={isSaveDisabled() || lookupLoading}
|
|
203
|
+
loading={isLoading}
|
|
204
|
+
>
|
|
205
|
+
<FormattedMessage {...messages.saveButton} />
|
|
206
|
+
</CapButton>
|
|
207
|
+
<CapButton
|
|
208
|
+
type="secondary"
|
|
209
|
+
onClick={() => setCustomerModal([false, ""])}
|
|
210
|
+
disabled={isLoading || lookupLoading}
|
|
211
|
+
>
|
|
212
|
+
<FormattedMessage {...messages.cancelButton} />
|
|
213
|
+
</CapButton>
|
|
214
|
+
</CapRow>
|
|
215
|
+
}
|
|
216
|
+
title={<FormattedMessage {...messages.customerCreationModalTitle} />}
|
|
217
|
+
wrapClassName="common-test-preview-modal-wrap"
|
|
218
|
+
className="common-test-preview-modal"
|
|
219
|
+
>
|
|
220
|
+
<CapRow className="customer-creation-modal-row">
|
|
221
|
+
<CapColumn span={24}>
|
|
222
|
+
<span className="customer-creation-modal-description">
|
|
223
|
+
<FormattedMessage {...messages.customerCreationModalDescription} />
|
|
224
|
+
</span>
|
|
225
|
+
</CapColumn>
|
|
226
|
+
</CapRow>
|
|
227
|
+
|
|
228
|
+
<CapRow className="customer-creation-modal-row">
|
|
229
|
+
<CapColumn span={24}>
|
|
230
|
+
<CapLabel type="label1" className="customer-creation-modal-label">
|
|
231
|
+
<FormattedMessage {...messages.customerName} /> <span className="customer-creation-modal-optional">(Optional)</span>
|
|
232
|
+
</CapLabel>
|
|
233
|
+
<CapInput
|
|
234
|
+
value={customerData.name || ""}
|
|
235
|
+
onChange={e =>
|
|
236
|
+
setCustomerData({ ...customerData, name: e.target.value })
|
|
237
|
+
}
|
|
238
|
+
placeholder={intl.formatMessage(messages.customerNamePlaceholder)}
|
|
239
|
+
size="default"
|
|
240
|
+
className="customer-creation-modal-input"
|
|
241
|
+
/>
|
|
242
|
+
</CapColumn>
|
|
243
|
+
</CapRow>
|
|
244
|
+
|
|
245
|
+
<CapRow className="customer-creation-modal-row">
|
|
246
|
+
<CapColumn span={24}>
|
|
247
|
+
<CapLabel type="label1" className="customer-creation-modal-label">
|
|
248
|
+
<FormattedMessage {...messages.customerEmail} /> {channel !== CHANNELS.EMAIL && <span className="customer-creation-modal-optional">(Optional)</span>}
|
|
249
|
+
</CapLabel>
|
|
250
|
+
<CapInput
|
|
251
|
+
value={customerData.email || ""}
|
|
252
|
+
onChange={handleEmailChange}
|
|
253
|
+
placeholder={intl.formatMessage(messages.customerEmailPlaceholder)}
|
|
254
|
+
size="default"
|
|
255
|
+
className={`customer-creation-modal-input${validationErrors.email ? INPUT_HAS_ERROR_CLASS : ''}`}
|
|
256
|
+
disabled={!!lookupLoading}
|
|
257
|
+
suffix={lookupLoading === IDENTIFIER_TYPE_EMAIL ? <CapSpin size="small" /> : null}
|
|
258
|
+
/>
|
|
259
|
+
{renderValidationError(validationErrors.email)}
|
|
260
|
+
</CapColumn>
|
|
261
|
+
</CapRow>
|
|
262
|
+
|
|
263
|
+
<CapRow className="customer-creation-modal-row customer-creation-modal-row--last">
|
|
264
|
+
<CapColumn span={24}>
|
|
265
|
+
<CapLabel type="label1" className="customer-creation-modal-label">
|
|
266
|
+
<FormattedMessage {...messages.customerMobile} /> {channel !== CHANNELS.SMS && <span className="customer-creation-modal-optional">(Optional)</span>}
|
|
267
|
+
</CapLabel>
|
|
268
|
+
<CapInput
|
|
269
|
+
value={customerData.mobile || ""}
|
|
270
|
+
onChange={handleMobileChange}
|
|
271
|
+
placeholder={intl.formatMessage(messages.customerMobilePlaceholder)}
|
|
272
|
+
size="default"
|
|
273
|
+
className={`customer-creation-modal-input${validationErrors.mobile ? INPUT_HAS_ERROR_CLASS : ''}`}
|
|
274
|
+
disabled={!!lookupLoading}
|
|
275
|
+
suffix={lookupLoading === IDENTIFIER_TYPE_MOBILE ? <CapSpin size="small" /> : null}
|
|
276
|
+
/>
|
|
277
|
+
{renderValidationError(validationErrors.mobile)}
|
|
278
|
+
</CapColumn>
|
|
279
|
+
</CapRow>
|
|
280
|
+
</CapModal>
|
|
281
|
+
);
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
export default injectIntl(CustomerCreationModal);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import CapModal from "@capillarytech/cap-ui-library/CapModal";
|
|
2
|
+
import { FormattedMessage, injectIntl } from "react-intl";
|
|
3
|
+
import messages from "./messages";
|
|
4
|
+
import React, { useState } from "react";
|
|
5
|
+
import { CapCard, CapRow, CapColumn, CapLabel } from "@capillarytech/cap-ui-library";
|
|
6
|
+
import { CHANNELS } from "./constants";
|
|
7
|
+
import CapButton from "@capillarytech/cap-ui-library/CapButton";
|
|
8
|
+
import CapIcon from "@capillarytech/cap-ui-library/CapIcon";
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const ExistingCustomerModal = ({ customerModal, setCustomerModal, customerData, channel, onSave, intl }) => {
|
|
12
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
13
|
+
return (
|
|
14
|
+
<CapModal
|
|
15
|
+
visible={customerModal[0]}
|
|
16
|
+
onCancel={() => setCustomerModal([false, ""])}
|
|
17
|
+
centered={true}
|
|
18
|
+
width={500}
|
|
19
|
+
maskStyle={{ backgroundColor: 'rgba(244, 245, 247, 0.9)' }}
|
|
20
|
+
footer={
|
|
21
|
+
<CapRow justify="start">
|
|
22
|
+
<CapButton
|
|
23
|
+
type="primary"
|
|
24
|
+
onClick={() => onSave({},setIsLoading)}
|
|
25
|
+
loading={isLoading}
|
|
26
|
+
>
|
|
27
|
+
<FormattedMessage {...messages.saveButton} />
|
|
28
|
+
</CapButton>
|
|
29
|
+
<CapButton
|
|
30
|
+
type="secondary"
|
|
31
|
+
onClick={() => setCustomerModal([false, ""])}
|
|
32
|
+
disabled={isLoading}
|
|
33
|
+
>
|
|
34
|
+
<FormattedMessage {...messages.cancelButton} />
|
|
35
|
+
</CapButton>
|
|
36
|
+
</CapRow>
|
|
37
|
+
}
|
|
38
|
+
title={intl.formatMessage(messages.customerCreationModalTitle)}
|
|
39
|
+
wrapClassName="common-test-preview-modal-wrap existing-customer-modal-wrap"
|
|
40
|
+
className="common-test-preview-modal"
|
|
41
|
+
>
|
|
42
|
+
<div className="existing-customer-modal">
|
|
43
|
+
<CapRow className="existing-customer-modal-intro-row">
|
|
44
|
+
<FormattedMessage {...messages.existingCustomerModalDescription} />
|
|
45
|
+
</CapRow>
|
|
46
|
+
<CapCard className="existing-customer-modal-card">
|
|
47
|
+
<CapRow className="existing-customer-modal-card-row">
|
|
48
|
+
<CapColumn className="existing-customer-modal-avatar">
|
|
49
|
+
<CapIcon type="user-profile" className="existing-customer-modal-avatar-icon" />
|
|
50
|
+
</CapColumn>
|
|
51
|
+
<CapColumn className="existing-customer-modal-details">
|
|
52
|
+
<CapRow className="existing-customer-modal-name">
|
|
53
|
+
{customerData.name || "-"}
|
|
54
|
+
</CapRow>
|
|
55
|
+
<CapColumn className="existing-customer-modal-meta">
|
|
56
|
+
{channel === CHANNELS.EMAIL && customerData.email && (
|
|
57
|
+
<CapRow><span className="existing-customer-modal-meta-label"><FormattedMessage {...messages.customerEmail} />: </span> {customerData.email}</CapRow>
|
|
58
|
+
)}
|
|
59
|
+
{channel === CHANNELS.SMS && customerData.mobile && (
|
|
60
|
+
<CapRow><span className="existing-customer-modal-meta-label"><FormattedMessage {...messages.customerMobile} />: </span>{customerData.mobile}</CapRow>
|
|
61
|
+
)}
|
|
62
|
+
<CapRow><span className="existing-customer-modal-meta-label"><FormattedMessage {...messages.customerID} />: </span>{customerData.customerId}</CapRow>
|
|
63
|
+
</CapColumn>
|
|
64
|
+
</CapColumn>
|
|
65
|
+
</CapRow>
|
|
66
|
+
</CapCard>
|
|
67
|
+
</div>
|
|
68
|
+
</CapModal>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default injectIntl(ExistingCustomerModal);
|
|
@@ -24,6 +24,9 @@ const SendTestMessage = ({
|
|
|
24
24
|
channel,
|
|
25
25
|
isSendingTestMessage,
|
|
26
26
|
formatMessage,
|
|
27
|
+
renderAddTestCustomerButton,
|
|
28
|
+
searchValue,
|
|
29
|
+
setSearchValue,
|
|
27
30
|
deliverySettings,
|
|
28
31
|
senderDetailsOptions,
|
|
29
32
|
wecrmAccounts,
|
|
@@ -31,57 +34,77 @@ const SendTestMessage = ({
|
|
|
31
34
|
isLoadingSenderDetails,
|
|
32
35
|
smsTraiDltEnabled,
|
|
33
36
|
registeredSenderIds,
|
|
34
|
-
}) =>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<CapHeader size="label1" title={<FormattedMessage {...messages.testCustomers} />} />
|
|
49
|
-
<CapTreeSelect
|
|
50
|
-
className="test-customers-tree-select"
|
|
51
|
-
loading={isFetchingTestCustomers || isFetchingTestGroups}
|
|
52
|
-
treeData={testEntitiesTreeData}
|
|
53
|
-
onChange={handleTestEntitiesChange}
|
|
54
|
-
value={selectedTestEntities}
|
|
55
|
-
multiple
|
|
56
|
-
placeholder={formatMessage(messages.testCustomersPlaceholder)}
|
|
37
|
+
}) => {
|
|
38
|
+
const addCustomerContent = renderAddTestCustomerButton ? renderAddTestCustomerButton() : null;
|
|
39
|
+
return (
|
|
40
|
+
<CapStepsAccordian
|
|
41
|
+
showNumberSteps={false}
|
|
42
|
+
isChevronIcon
|
|
43
|
+
expandIconPosition="right"
|
|
44
|
+
items={[
|
|
45
|
+
{
|
|
46
|
+
header: (
|
|
47
|
+
<CapHeader
|
|
48
|
+
size="regular"
|
|
49
|
+
description={<FormattedMessage {...messages.testMessageDescription} />}
|
|
50
|
+
title={<FormattedMessage {...messages.sendTestMessage} />}
|
|
57
51
|
/>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
52
|
+
),
|
|
53
|
+
content: (
|
|
54
|
+
<CapRow className="send-test-content">
|
|
55
|
+
<CapHeader size="label1" title={<FormattedMessage {...messages.testCustomers} />} />
|
|
56
|
+
<CapTreeSelect
|
|
57
|
+
className="test-customers-tree-select"
|
|
58
|
+
dropdownMatchSelectWidth
|
|
59
|
+
dropdownClassName="test-customers-tree-select-dropdown"
|
|
60
|
+
listHeight={280}
|
|
61
|
+
loading={isFetchingTestCustomers || isFetchingTestGroups}
|
|
62
|
+
treeData={testEntitiesTreeData}
|
|
63
|
+
onChange={handleTestEntitiesChange}
|
|
64
|
+
value={selectedTestEntities}
|
|
65
|
+
showSearch
|
|
66
|
+
searchValue={searchValue}
|
|
67
|
+
onSearch={setSearchValue}
|
|
68
|
+
treeNodeFilterProp="title"
|
|
69
|
+
{...(addCustomerContent ? { notFoundContent: addCustomerContent } : {})}
|
|
70
|
+
multiple
|
|
71
|
+
placeholder={formatMessage(messages.testCustomersPlaceholder)}
|
|
72
|
+
dropdownStyle={{ zIndex: 900, maxHeight: 320 }}
|
|
73
|
+
placement="bottomLeft"
|
|
74
|
+
getPopupContainer={(node) => node.closest('.send-test-section') || document.body}
|
|
74
75
|
/>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
76
|
+
{CHANNELS_WITH_DELIVERY_SETTINGS.includes(channel) && (
|
|
77
|
+
<DeliverySettings
|
|
78
|
+
channel={channel}
|
|
79
|
+
deliverySettings={deliverySettings || {}}
|
|
80
|
+
senderDetailsOptions={senderDetailsOptions || []}
|
|
81
|
+
wecrmAccounts={wecrmAccounts || []}
|
|
82
|
+
onSaveDeliverySettings={onSaveDeliverySettings}
|
|
83
|
+
isLoadingSenderDetails={isLoadingSenderDetails}
|
|
84
|
+
formatMessage={formatMessage}
|
|
85
|
+
smsTraiDltEnabled={smsTraiDltEnabled}
|
|
86
|
+
registeredSenderIds={registeredSenderIds}
|
|
87
|
+
whatsappAccountFromForm={
|
|
88
|
+
channel === CHANNELS.WHATSAPP && formData?.accountName
|
|
89
|
+
? { accountName: formData.accountName }
|
|
90
|
+
: undefined
|
|
91
|
+
}
|
|
92
|
+
/>
|
|
93
|
+
)}
|
|
94
|
+
<CapButton
|
|
95
|
+
onClick={handleSendTestMessage}
|
|
96
|
+
disabled={isEmpty(selectedTestEntities) || isSendingTestMessage}
|
|
97
|
+
>
|
|
98
|
+
<FormattedMessage {...messages.sendTestButton} />
|
|
99
|
+
</CapButton>
|
|
100
|
+
</CapRow>
|
|
101
|
+
),
|
|
102
|
+
key: 1,
|
|
103
|
+
},
|
|
104
|
+
]}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
};
|
|
85
108
|
|
|
86
109
|
SendTestMessage.propTypes = {
|
|
87
110
|
isFetchingTestCustomers: PropTypes.bool.isRequired,
|
|
@@ -94,6 +117,9 @@ SendTestMessage.propTypes = {
|
|
|
94
117
|
channel: PropTypes.string,
|
|
95
118
|
isSendingTestMessage: PropTypes.bool.isRequired,
|
|
96
119
|
formatMessage: PropTypes.func.isRequired,
|
|
120
|
+
renderAddTestCustomerButton: PropTypes.func,
|
|
121
|
+
searchValue: PropTypes.string,
|
|
122
|
+
setSearchValue: PropTypes.func,
|
|
97
123
|
deliverySettings: PropTypes.object,
|
|
98
124
|
senderDetailsOptions: PropTypes.array,
|
|
99
125
|
wecrmAccounts: PropTypes.array,
|
|
@@ -106,6 +132,9 @@ SendTestMessage.propTypes = {
|
|
|
106
132
|
SendTestMessage.defaultProps = {
|
|
107
133
|
formData: undefined,
|
|
108
134
|
channel: undefined,
|
|
135
|
+
renderAddTestCustomerButton: undefined,
|
|
136
|
+
searchValue: '',
|
|
137
|
+
setSearchValue: undefined,
|
|
109
138
|
deliverySettings: {},
|
|
110
139
|
senderDetailsOptions: [],
|
|
111
140
|
wecrmAccounts: [],
|