@capillarytech/creatives-library 7.10.52 → 7.10.54
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/TemplatePreview/index.js +1 -1
- package/v2Components/WhatsappStatusContainer/_whatsappStatusContainer.scss +4 -2
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +17 -12
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/SmsTrai/Create/constants.js +3 -7
- package/v2Containers/SmsTrai/Create/index.js +74 -28
- package/v2Containers/SmsTrai/Edit/constants.js +0 -1
- package/v2Containers/TemplatesV2/index.js +1 -1
package/package.json
CHANGED
|
@@ -683,7 +683,7 @@ class TemplatePreview extends React.Component { // eslint-disable-line react/pre
|
|
|
683
683
|
) : ''
|
|
684
684
|
}
|
|
685
685
|
{
|
|
686
|
-
channel
|
|
686
|
+
channel?.toUpperCase() === WHATSAPP ? (
|
|
687
687
|
<>
|
|
688
688
|
<div className='shell-v2 align-center'>
|
|
689
689
|
<CapImage
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
@import '~@capillarytech/cap-ui-library/styles/_variables.scss';
|
|
2
|
+
|
|
1
3
|
.whatsapp-status-container {
|
|
2
|
-
margin-top:
|
|
4
|
+
margin-top: $CAP_SPACE_12;
|
|
3
5
|
width: 150%;
|
|
4
6
|
height: 20px;
|
|
5
7
|
|
|
@@ -8,6 +10,6 @@
|
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
.whatsapp-category-tag {
|
|
11
|
-
margin-left:
|
|
13
|
+
margin-left: $CAP_SPACE_08;
|
|
12
14
|
}
|
|
13
15
|
}
|
|
@@ -22,24 +22,15 @@ const StyledLabel = styled(CapLabelInline)`
|
|
|
22
22
|
const PrefixWrapper = styled.div`
|
|
23
23
|
margin-right: 16px;
|
|
24
24
|
`;
|
|
25
|
-
|
|
26
|
-
const labels = {
|
|
27
|
-
sms: 'SMS',
|
|
28
|
-
email: 'Email',
|
|
29
|
-
mobilepush: 'Push notification',
|
|
30
|
-
wechat: 'Wechat',
|
|
31
|
-
no_communication: 'NO_COMMUNICATION',
|
|
32
|
-
ftp: 'FTP',
|
|
33
|
-
whatsapp: 'WhatsApp template',
|
|
34
|
-
};
|
|
35
|
-
return labels[channel.toLowerCase()];
|
|
36
|
-
}
|
|
25
|
+
|
|
37
26
|
const renderWhatsappData = (type, value) => (
|
|
38
27
|
<StyledLabel type={type}>
|
|
39
28
|
{value}
|
|
40
29
|
</StyledLabel>
|
|
41
30
|
)
|
|
42
31
|
function SlideBoxHeader(props) {
|
|
32
|
+
|
|
33
|
+
|
|
43
34
|
const { slidBoxContent, templateData, onShowTemplates, creativesMode, isFullMode, showPrefix, shouldShowTemplateName, channel, templateNameRenderProp, weChatTemplateType, onWeChatMaptemplateStepChange, weChatMaptemplateStep, templateStep, smsRegister } = props;
|
|
44
35
|
const showTemplateNameHeader = isFullMode && shouldShowTemplateName;
|
|
45
36
|
const mapTemplateCreate = !showTemplateNameHeader && slidBoxContent === 'createTemplate' && weChatTemplateType === MAP_TEMPLATE && templateStep !== 'modeSelection';
|
|
@@ -55,6 +46,20 @@ function SlideBoxHeader(props) {
|
|
|
55
46
|
const whatsappName = whatsappTemplateName || templateData?.name;
|
|
56
47
|
const whatsappCategory = whatsappTemplateCategory || get(templateData, `versions.base.content.whatsapp.category`, '');
|
|
57
48
|
|
|
49
|
+
|
|
50
|
+
const getChannelLabel = (currentChannel = '') => {
|
|
51
|
+
const labels = {
|
|
52
|
+
sms: 'SMS',
|
|
53
|
+
email: 'Email',
|
|
54
|
+
mobilepush: 'Push notification',
|
|
55
|
+
wechat: 'Wechat',
|
|
56
|
+
no_communication: 'NO_COMMUNICATION',
|
|
57
|
+
ftp: 'FTP',
|
|
58
|
+
whatsapp: <FormattedMessage {...messages.whatsappTemplate} />,
|
|
59
|
+
};
|
|
60
|
+
return labels[currentChannel.toLowerCase()];
|
|
61
|
+
};
|
|
62
|
+
|
|
58
63
|
return (
|
|
59
64
|
<div key="creatives-container-slidebox-header-content">
|
|
60
65
|
{slidBoxContent === 'templates' && !showTemplateNameHeader && (
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
export const DEFAULT_ACTION = 'app/SmsTrai/DEFAULT_ACTION';
|
|
2
|
-
export const STATUS = 'status';
|
|
3
1
|
export const TEMPLATE_NAME = 'template name';
|
|
4
|
-
export const HEADER = 'header';
|
|
5
|
-
export const TEMPLATE_ID = 'template id';
|
|
6
2
|
export const SMS = 'SMS';
|
|
7
3
|
export const MAPPED_SAVED_COLUMN = {
|
|
8
4
|
'TEMPLATE ID': 'template_id',
|
|
@@ -22,12 +18,12 @@ export const MAPPED_SAVED_COLUMN = {
|
|
|
22
18
|
'CONSENT TYPE': 'consent-type',
|
|
23
19
|
};
|
|
24
20
|
export const HEADER_ALIASES = [
|
|
25
|
-
|
|
21
|
+
'header',
|
|
26
22
|
'sender id',
|
|
27
23
|
'senders',
|
|
28
24
|
'header id',
|
|
29
25
|
'headers',
|
|
30
|
-
'linked headers'
|
|
26
|
+
'linked headers',
|
|
31
27
|
];
|
|
32
28
|
export const TEMPLATE_ID_ALIASES = [
|
|
33
29
|
'template id',
|
|
@@ -76,4 +72,4 @@ export const CHECK_TRAI_SMS_DUPLICATE_TEMPLATE_NAME_FAILURE =
|
|
|
76
72
|
export const REQUEST = 'REQUEST';
|
|
77
73
|
export const SUCCESS = 'SUCCESS';
|
|
78
74
|
export const FAILURE = 'FAILURE';
|
|
79
|
-
export const DUPLICATE = 'Duplicate';
|
|
75
|
+
export const DUPLICATE = 'Duplicate';
|
|
@@ -77,7 +77,8 @@ export const SmsTraiCreate = (props) => {
|
|
|
77
77
|
const [traiFileMeta, setTraiFileMeta] = useState(null);
|
|
78
78
|
const [validatedData, setValidatedData] = useState([]);
|
|
79
79
|
const [files, setFiles] = useState([]);
|
|
80
|
-
const [templateRegistrationIndex, setTemplateRegistrationIndex] =
|
|
80
|
+
const [templateRegistrationIndex, setTemplateRegistrationIndex] =
|
|
81
|
+
useState(null);
|
|
81
82
|
const [errorText, setErrorText] = useState('');
|
|
82
83
|
const [dropZone, setDropZone] = useState(true);
|
|
83
84
|
const [previewFileIndex, setPreviewFileIndex] = useState(null);
|
|
@@ -110,7 +111,10 @@ export const SmsTraiCreate = (props) => {
|
|
|
110
111
|
const colCounts = {};
|
|
111
112
|
const traiFileDataCopy = cloneDeep(traiFileData);
|
|
112
113
|
//removing last empty row if each cell is empty
|
|
113
|
-
|
|
114
|
+
const removeLastEmptyRow = traiFileDataCopy?.data[
|
|
115
|
+
traiFileDataCopy?.data?.length - 1
|
|
116
|
+
]?.every((cell) => !cell);
|
|
117
|
+
if (removeLastEmptyRow) {
|
|
114
118
|
traiFileDataCopy.data.pop();
|
|
115
119
|
}
|
|
116
120
|
const fileLen = traiFileDataCopy?.data?.length || 0;
|
|
@@ -259,14 +263,27 @@ export const SmsTraiCreate = (props) => {
|
|
|
259
263
|
} else if (uploadValidated && duplicateDetailsStatus === FAILURE) {
|
|
260
264
|
deleteOrCancelCSV();
|
|
261
265
|
CapNotification.error({ message: duplicateDetailsError || FAILURE });
|
|
262
|
-
} else if (
|
|
263
|
-
|
|
266
|
+
} else if (
|
|
267
|
+
uploadValidated &&
|
|
268
|
+
duplicateDetailsStatus === SUCCESS &&
|
|
269
|
+
!isEmpty(validatedData)
|
|
270
|
+
) {
|
|
271
|
+
if (
|
|
272
|
+
!isEmpty(duplicateDetails) &&
|
|
273
|
+
count > 0 &&
|
|
274
|
+
templateRegistrationIndex !== null
|
|
275
|
+
) {
|
|
264
276
|
const clonedValidatedData = cloneDeep(validatedData);
|
|
265
277
|
let duplicateTemplateNameCounts = 0;
|
|
266
278
|
const apiResponseIds = [...new Set(template_ids)];
|
|
267
|
-
|
|
279
|
+
|
|
268
280
|
for (let i = 1; i < clonedValidatedData.length; i += 1) {
|
|
269
|
-
const duplicatePresent = apiResponseIds?.includes(
|
|
281
|
+
const duplicatePresent = apiResponseIds?.includes(
|
|
282
|
+
clonedValidatedData[i][templateRegistrationIndex]?.replace(
|
|
283
|
+
/[“”"'‘’`´]/g,
|
|
284
|
+
'',
|
|
285
|
+
),
|
|
286
|
+
);
|
|
270
287
|
if (duplicatePresent) {
|
|
271
288
|
//if rejection reason for this row is empty, consider as new error
|
|
272
289
|
if (!clonedValidatedData[i][clonedValidatedData[i]?.length - 1]) {
|
|
@@ -291,7 +308,10 @@ export const SmsTraiCreate = (props) => {
|
|
|
291
308
|
const selectedFiles = cloneDeep(files);
|
|
292
309
|
const traiFileDataCopy = cloneDeep(traiFileData);
|
|
293
310
|
//removing last empty row if each cell is empty
|
|
294
|
-
|
|
311
|
+
const removeLastEmptyRow = traiFileDataCopy?.data[
|
|
312
|
+
traiFileDataCopy?.data?.length - 1
|
|
313
|
+
]?.every((cell) => !cell);
|
|
314
|
+
if (removeLastEmptyRow) {
|
|
295
315
|
traiFileDataCopy.data.pop();
|
|
296
316
|
}
|
|
297
317
|
//remove capillary rejection reason column if already present on reupload
|
|
@@ -340,8 +360,8 @@ export const SmsTraiCreate = (props) => {
|
|
|
340
360
|
const headerValidationHandler = (senderIdString) => {
|
|
341
361
|
//each row must contain atleast 1 header
|
|
342
362
|
//each header can be either 6 letters or 6 numbers, no mixing
|
|
343
|
-
//it cannot contain special characters
|
|
344
|
-
//eg: valid: "123456" "abcdef" invalid: "abc123" "abc$ef" "1234567"
|
|
363
|
+
//it cannot contain special characters except {}
|
|
364
|
+
//eg: valid: "123456" "abcdef" "{123456}" invalid: "abc123" "abc$ef" "1234567"
|
|
345
365
|
if (senderIdString.length < 6) {
|
|
346
366
|
return true;
|
|
347
367
|
}
|
|
@@ -349,7 +369,7 @@ export const SmsTraiCreate = (props) => {
|
|
|
349
369
|
const numbersOnly = /^\d+$/;
|
|
350
370
|
let isError = false;
|
|
351
371
|
senderIdString.split(',').forEach((value) => {
|
|
352
|
-
const _value = value.trim();
|
|
372
|
+
const _value = value.trim()?.replace(/[{}]/g, '');
|
|
353
373
|
if (_value) {
|
|
354
374
|
if (_value.length !== 6) {
|
|
355
375
|
isError = true;
|
|
@@ -363,6 +383,19 @@ export const SmsTraiCreate = (props) => {
|
|
|
363
383
|
return isError;
|
|
364
384
|
};
|
|
365
385
|
|
|
386
|
+
const statusValidationHandler = (columnName, value) => {
|
|
387
|
+
//Approval status should be Approved or Status/Template status should be Active/Registered.
|
|
388
|
+
switch (columnName) {
|
|
389
|
+
case STATUS_ALIASES[0]:
|
|
390
|
+
case STATUS_ALIASES[1]:
|
|
391
|
+
return ![ACTIVE, REGISTERED].includes(value);
|
|
392
|
+
case STATUS_ALIASES[2]:
|
|
393
|
+
return value !== APPROVED;
|
|
394
|
+
default:
|
|
395
|
+
return true;
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
|
|
366
399
|
const templateIdValidation = (templateId) => {
|
|
367
400
|
let isError = false;
|
|
368
401
|
const _templateId = templateId?.replace(/[“”"'‘’`´]/g, '');
|
|
@@ -389,7 +422,9 @@ export const SmsTraiCreate = (props) => {
|
|
|
389
422
|
};
|
|
390
423
|
}
|
|
391
424
|
})
|
|
392
|
-
?.filter(
|
|
425
|
+
?.filter(
|
|
426
|
+
(obj) => obj && obj.template_name !== '' && obj.template_id !== '',
|
|
427
|
+
);
|
|
393
428
|
setUploadValidated(true);
|
|
394
429
|
setValidatedData(transformedResults);
|
|
395
430
|
setTemplateRegistrationIndex(templateIdIndex);
|
|
@@ -458,20 +493,26 @@ export const SmsTraiCreate = (props) => {
|
|
|
458
493
|
const errorArray = [];
|
|
459
494
|
const columnErrorArray = [];
|
|
460
495
|
let rejectionReasons = '';
|
|
461
|
-
let statusErrorIndicator =
|
|
496
|
+
let statusErrorIndicator = false;
|
|
462
497
|
//adding rejection reasons
|
|
463
498
|
transformedResults[row].forEach((cell, index) => {
|
|
464
499
|
if (index === headerIndex && headerValidationHandler(cell)) {
|
|
465
500
|
columnErrorArray.push(
|
|
466
501
|
`${selectedHeaderAlias.toUpperCase()} is mandatory and each ${selectedHeaderAlias.toUpperCase()} must contain either 6 letters or 6 digits. It cannot contain special characters. `,
|
|
467
502
|
);
|
|
468
|
-
} else if (statusIndexes.includes(index) &&
|
|
469
|
-
statusErrorIndicator =
|
|
503
|
+
} else if (statusIndexes.includes(index) && !statusErrorIndicator) {
|
|
504
|
+
statusErrorIndicator = statusValidationHandler(
|
|
505
|
+
transformedResults[0][index].toLowerCase(),
|
|
506
|
+
cell.toLowerCase(),
|
|
507
|
+
);
|
|
470
508
|
} else if (index === templateIdIndex && templateIdValidation(cell)) {
|
|
471
509
|
columnErrorArray.push(
|
|
472
510
|
`${selectedTemplateIdAlias.toUpperCase()} is mandatory and ${selectedTemplateIdAlias.toUpperCase()} must be numeric.`,
|
|
473
511
|
);
|
|
474
|
-
} else if (
|
|
512
|
+
} else if (
|
|
513
|
+
!cell &&
|
|
514
|
+
![headerIndex, templateIdIndex, ...statusIndexes].includes(index)
|
|
515
|
+
) {
|
|
475
516
|
errorArray.push(`"${transformedResults[0][index]}"`);
|
|
476
517
|
} else if (index === templateNameIndex && cell) {
|
|
477
518
|
if (templateNameObj[cell]) {
|
|
@@ -485,7 +526,7 @@ export const SmsTraiCreate = (props) => {
|
|
|
485
526
|
|
|
486
527
|
if (statusErrorIndicator) {
|
|
487
528
|
columnErrorArray.push(
|
|
488
|
-
`
|
|
529
|
+
`Approval status should be Approved or Status/Template status should be Active/Registered.`,
|
|
489
530
|
);
|
|
490
531
|
}
|
|
491
532
|
if (errorArray.length !== 0) {
|
|
@@ -671,7 +712,7 @@ export const SmsTraiCreate = (props) => {
|
|
|
671
712
|
obj['unicode-validity'] = true;
|
|
672
713
|
obj['updated-sms-editor'] = '';
|
|
673
714
|
obj['var-mapped'] = {};
|
|
674
|
-
obj.header = obj.header?.replace(
|
|
715
|
+
obj.header = obj.header?.replace(/[\s{}]/g, '')?.split(',');
|
|
675
716
|
const history = obj;
|
|
676
717
|
history.tabKey = 1;
|
|
677
718
|
savedData.push({
|
|
@@ -745,7 +786,10 @@ export const SmsTraiCreate = (props) => {
|
|
|
745
786
|
{previewFileIndex === null && dropZone && (
|
|
746
787
|
<>
|
|
747
788
|
<CapSpin spinning={isFileDropped}>
|
|
748
|
-
<Dropzone
|
|
789
|
+
<Dropzone
|
|
790
|
+
onDrop={onDrop}
|
|
791
|
+
onFileDialogCancel={deleteOrCancelCSV}
|
|
792
|
+
>
|
|
749
793
|
{({ getRootProps, getInputProps }) => (
|
|
750
794
|
<div {...getRootProps()} className="file-drop-zone">
|
|
751
795
|
<input {...getInputProps()} />
|
|
@@ -789,16 +833,18 @@ export const SmsTraiCreate = (props) => {
|
|
|
789
833
|
<CapLabel.CapLabelInline type="label9">
|
|
790
834
|
{fileMeta.name}
|
|
791
835
|
</CapLabel.CapLabelInline>
|
|
792
|
-
{saveTemplate &&
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
836
|
+
{saveTemplate && (
|
|
837
|
+
<CapLabel.CapLabelInline
|
|
838
|
+
type="label1"
|
|
839
|
+
className="number-of-records"
|
|
840
|
+
>
|
|
841
|
+
(
|
|
842
|
+
{formatMessage(messages.numberOfRecords, {
|
|
843
|
+
value: fileData.data.length - 1,
|
|
844
|
+
})}
|
|
845
|
+
)
|
|
846
|
+
</CapLabel.CapLabelInline>
|
|
847
|
+
)}
|
|
802
848
|
</CapColumn>
|
|
803
849
|
{errorText && (
|
|
804
850
|
<>
|