@capillarytech/creatives-library 7.10.34 → 7.10.35

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.
@@ -1,6 +1,10 @@
1
+ /* eslint-disable no-trailing-spaces */
2
+ /* eslint-disable guard-for-in */
3
+ /* eslint-disable no-loop-func */
4
+ /* eslint-disable no-restricted-syntax */
1
5
  /* eslint-disable no-undef */
2
6
  import PropTypes from 'prop-types';
3
- import React, { useState } from 'react';
7
+ import React, { useState, useEffect } from 'react';
4
8
  import { FormattedMessage, injectIntl } from 'react-intl';
5
9
  import { createStructuredSelector } from 'reselect';
6
10
  import styled from 'styled-components';
@@ -17,7 +21,7 @@ import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
17
21
  import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
18
22
  import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
19
23
  import Papa from 'papaparse';
20
- import cloneDeep from 'lodash/cloneDeep';
24
+ import { cloneDeep, isEmpty } from 'lodash';
21
25
  import {
22
26
  CAP_SPACE_16,
23
27
  CAP_SPACE_24,
@@ -27,6 +31,7 @@ import {
27
31
  CAP_PRIMARY,
28
32
  } from '@capillarytech/cap-ui-library/styled/variables';
29
33
  import './index.scss';
34
+ import makeSelectSmsTrai from './selectors';
30
35
  import dragdropImage from '../../../assets/group.png';
31
36
  import * as smsTraiActions from './actions';
32
37
  import {
@@ -47,6 +52,9 @@ import {
47
52
  SAVED_COLUMNS,
48
53
  MAPPED_SAVED_COLUMN,
49
54
  SMS,
55
+ FAILURE,
56
+ SUCCESS,
57
+ DUPLICATE,
50
58
  } from './constants';
51
59
  import messages from './messages';
52
60
  import withCreatives from '../../../hoc/withCreatives';
@@ -58,15 +66,25 @@ export const SmsTraiCreate = (props) => {
58
66
  onCreateComplete,
59
67
  isFullMode,
60
68
  onShowTemplates,
69
+ traiSms: {
70
+ duplicateDetails = {},
71
+ duplicateDetailsError = '',
72
+ duplicateDetailsStatus = '',
73
+ } = {},
61
74
  } = props;
62
75
  const { formatMessage } = intl;
76
+ const [traiFileData, setTraiFileData] = useState({});
77
+ const [traiFileMeta, setTraiFileMeta] = useState(null);
78
+ const [validatedData, setValidatedData] = useState([]);
63
79
  const [files, setFiles] = useState([]);
80
+ const [templateRegistrationIndex, setTemplateRegistrationIndex] = useState(null);
64
81
  const [errorText, setErrorText] = useState('');
65
82
  const [dropZone, setDropZone] = useState(true);
66
83
  const [previewFileIndex, setPreviewFileIndex] = useState(null);
67
84
  const [isFileDropped, setIsFileDropped] = useState(false);
68
85
  const [totalFailCount, setTotalFailCount] = useState(0);
69
86
  const [saveTemplate, updateSaveTemplate] = useState(false);
87
+ const [uploadValidated, setUploadValidated] = useState(false);
70
88
 
71
89
  const SMSTraiFooter = styled.div`
72
90
  background-color: ${CAP_WHITE};
@@ -80,8 +98,229 @@ export const SmsTraiCreate = (props) => {
80
98
  }
81
99
  }
82
100
  `;
101
+ useEffect(() => {
102
+ if (!isEmpty(traiFileData) && traiFileMeta?.name) {
103
+ if (traiFileMeta?.name?.split('.').pop() === 'csv') {
104
+ const mandatoryColNotPresent = [];
105
+ const headerAliasPresent = [];
106
+ const templateIdAliasPresent = [];
107
+ const templateMessageAliasPresent = [];
108
+ const statusAliasPresent = [];
109
+ const typeAliasPresent = [];
110
+ const colCounts = {};
111
+ const traiFileDataCopy = cloneDeep(traiFileData);
112
+ //removing last empty row if each cell is empty
113
+ if (traiFileDataCopy?.data[traiFileDataCopy?.data?.length - 1]?.every((cell) => !cell)) {
114
+ traiFileDataCopy.data.pop();
115
+ }
116
+ const fileLen = traiFileDataCopy?.data?.length || 0;
117
+ // at least 1 records should be available
118
+ if (fileLen < 2) {
119
+ setErrorText(formatMessage(messages.fileMinlengthError));
120
+ return;
121
+ }
122
+ // more then 500 records are not available.
123
+ if (fileLen > 501) {
124
+ setErrorText(formatMessage(messages.fileMaxlengthError));
125
+ return;
126
+ }
127
+
128
+ const cols = getAllColumnNames(traiFileDataCopy.data[0]);
129
+
130
+ for (let i = 0; i < MANDATORY_COLUMNS.length; i += 1) {
131
+ if (!cols.includes(MANDATORY_COLUMNS[i])) {
132
+ mandatoryColNotPresent.push(MANDATORY_COLUMNS[i]);
133
+ }
134
+ }
135
+ if (mandatoryColNotPresent.length > 0) {
136
+ setErrorText(formatMessage(messages.mandatoryColErrorDescription));
137
+ return;
138
+ }
139
+
140
+ //one of the mandatory header alias should be available.
141
+ for (let i = 0; i < HEADER_ALIASES.length; i += 1) {
142
+ if (cols.includes(HEADER_ALIASES[i])) {
143
+ headerAliasPresent.push(HEADER_ALIASES[i]);
144
+ }
145
+ }
146
+ if (headerAliasPresent.length === 0) {
147
+ setErrorText(
148
+ formatMessage(messages.headerAliasErrorDescription, {
149
+ headerAliases: HEADER_ALIASES.join(' / '),
150
+ }),
151
+ );
152
+ return;
153
+ }
154
+ //one of the mandatory template id alias should be available.
155
+ for (let i = 0; i < TEMPLATE_ID_ALIASES.length; i += 1) {
156
+ if (cols.includes(TEMPLATE_ID_ALIASES[i])) {
157
+ templateIdAliasPresent.push(TEMPLATE_ID_ALIASES[i]);
158
+ }
159
+ }
160
+ if (templateIdAliasPresent.length === 0) {
161
+ setErrorText(
162
+ formatMessage(messages.templateIdAliasErrorDescription, {
163
+ templateIdAliases: TEMPLATE_ID_ALIASES.join(' / '),
164
+ }),
165
+ );
166
+ return;
167
+ }
168
+ //one of the mandatory template message alias should be available.
169
+ for (let i = 0; i < TEMPLATE_MESSAGE_ALIASES.length; i += 1) {
170
+ if (cols.includes(TEMPLATE_MESSAGE_ALIASES[i])) {
171
+ templateMessageAliasPresent.push(TEMPLATE_MESSAGE_ALIASES[i]);
172
+ }
173
+ }
174
+ if (templateMessageAliasPresent.length === 0) {
175
+ setErrorText(
176
+ formatMessage(messages.templateMessageAliasErrorDescription, {
177
+ templateMessageAliases: TEMPLATE_MESSAGE_ALIASES.join(' / '),
178
+ }),
179
+ );
180
+ return;
181
+ }
182
+ //one of the mandatory status alias should be available.
183
+ for (let i = 0; i < STATUS_ALIASES.length; i += 1) {
184
+ if (cols.includes(STATUS_ALIASES[i])) {
185
+ statusAliasPresent.push(STATUS_ALIASES[i]);
186
+ }
187
+ }
188
+ if (statusAliasPresent.length === 0) {
189
+ setErrorText(
190
+ formatMessage(messages.statusAliasErrorDescription, {
191
+ statusAliases: STATUS_ALIASES.join(' / '),
192
+ }),
193
+ );
194
+ return;
195
+ }
196
+ //one of the mandatory type alias should be available.
197
+ for (let i = 0; i < TYPE_ALIASES.length; i += 1) {
198
+ if (cols.includes(TYPE_ALIASES[i])) {
199
+ typeAliasPresent.push(TYPE_ALIASES[i]);
200
+ }
201
+ }
202
+ if (typeAliasPresent.length === 0) {
203
+ setErrorText(
204
+ formatMessage(messages.typeAliasErrorDescription, {
205
+ typeAliases: TYPE_ALIASES.join(' / '),
206
+ }),
207
+ );
208
+ return;
209
+ }
210
+ // count of each col to validate repetitive cols
211
+ for (const num of cols) {
212
+ colCounts[num] = colCounts[num] ? colCounts[num] + 1 : 1;
213
+ }
83
214
 
84
- let uploadValidated = false;
215
+ const repetitiveColsArray = Object.keys(
216
+ Object.fromEntries(
217
+ Object.entries(colCounts).filter(
218
+ ([key, value]) => key !== '' && value > 1,
219
+ ),
220
+ ),
221
+ );
222
+ //throw validation if repetitive columns present
223
+ if (repetitiveColsArray.length !== 0) {
224
+ setErrorText(
225
+ formatMessage(messages.repetitiveColsErrorDescription, {
226
+ repetitiveCols: repetitiveColsArray.join(', '),
227
+ }),
228
+ );
229
+ return;
230
+ }
231
+ //perform required data transformation
232
+ dataTransformHandler(
233
+ cols,
234
+ traiFileDataCopy,
235
+ headerAliasPresent,
236
+ templateIdAliasPresent,
237
+ statusAliasPresent,
238
+ );
239
+ } else {
240
+ setErrorText(formatMessage(messages.nonCsvErrorDescription));
241
+ }
242
+ }
243
+ }, [traiFileData, traiFileMeta]);
244
+
245
+ useEffect(() => {
246
+ const { count = 0, template_ids = [] } = duplicateDetails || {};
247
+
248
+ if (errorText && !uploadValidated) {
249
+ setIsFileDropped(false); // Stop the spinner
250
+ const selectedFiles = cloneDeep(files);
251
+ selectedFiles.push({
252
+ fileMeta: traiFileMeta,
253
+ fileData: traiFileData,
254
+ columnMapping: [],
255
+ });
256
+ setFiles(selectedFiles);
257
+ setPreviewFileIndex(selectedFiles.length - 1);
258
+ setDropZone(false);
259
+ } else if (uploadValidated && duplicateDetailsStatus === FAILURE) {
260
+ deleteOrCancelCSV();
261
+ CapNotification.error({ message: duplicateDetailsError || FAILURE });
262
+ } else if (uploadValidated && duplicateDetailsStatus === SUCCESS && !isEmpty(validatedData)) {
263
+ if (!isEmpty(duplicateDetails) && count > 0 && templateRegistrationIndex !== null) {
264
+ const clonedValidatedData = cloneDeep(validatedData);
265
+ let duplicateTemplateNameCounts = 0;
266
+ const apiResponseIds = [...new Set(template_ids)];
267
+
268
+ for (let i = 1; i < clonedValidatedData.length; i += 1) {
269
+ const duplicatePresent = apiResponseIds?.includes(clonedValidatedData[i][templateRegistrationIndex]?.replace(/[“”"'‘’`´]/g, ''));
270
+ if (duplicatePresent) {
271
+ //if rejection reason for this row is empty, consider as new error
272
+ if (!clonedValidatedData[i][clonedValidatedData[i]?.length - 1]) {
273
+ duplicateTemplateNameCounts += 1;
274
+ }
275
+ //add rejection reason to rejection reason column
276
+ clonedValidatedData[i][
277
+ clonedValidatedData[i]?.length - 1
278
+ ] += ` This template name is already present in the database.Duplicate template names are not allowed.`;
279
+ }
280
+ } //Duplicate should match constant DUPLICATE
281
+ setTotalFailCount((prev) => prev + duplicateTemplateNameCounts);
282
+ setValidatedData(clonedValidatedData);
283
+ }
284
+ updateSaveTemplate(true);
285
+ }
286
+ }, [duplicateDetailsStatus, errorText, templateRegistrationIndex]);
287
+
288
+ useEffect(() => {
289
+ if (saveTemplate && !isEmpty(traiFileData) && !isEmpty(validatedData)) {
290
+ setIsFileDropped(false); // Stop the spinner
291
+ const selectedFiles = cloneDeep(files);
292
+ const traiFileDataCopy = cloneDeep(traiFileData);
293
+ //removing last empty row if each cell is empty
294
+ if (traiFileDataCopy?.data[traiFileDataCopy?.data?.length - 1]?.every((cell) => !cell)) {
295
+ traiFileDataCopy.data.pop();
296
+ }
297
+ //remove capillary rejection reason column if already present on reupload
298
+ //ex: user reuploads a csv which was earlier validated and rejection reasons were added for failed templates
299
+ const rejectionIndex = getAllColumnNames(
300
+ traiFileDataCopy.data[0],
301
+ ).indexOf(CAPILLARY_REJECTION_REASON.toLowerCase());
302
+ if (rejectionIndex !== -1) {
303
+ traiFileDataCopy.data.forEach((row) => {
304
+ row.splice(rejectionIndex, 1);
305
+ });
306
+ }
307
+ //adding validated rejection reason column to original results
308
+ for (let i = 0; i < validatedData.length; i += 1) {
309
+ traiFileDataCopy.data[i].push(
310
+ validatedData[i][validatedData[i]?.length - 1],
311
+ );
312
+ }
313
+
314
+ selectedFiles.push({
315
+ fileMeta: traiFileMeta,
316
+ fileData: traiFileDataCopy,
317
+ columnMapping: [],
318
+ });
319
+ setFiles(selectedFiles);
320
+ setPreviewFileIndex(selectedFiles.length - 1);
321
+ setDropZone(false);
322
+ }
323
+ }, [validatedData, saveTemplate]);
85
324
 
86
325
  const getIndexofColumn = (allColumnNames, columnName) =>
87
326
  allColumnNames.findIndex(
@@ -134,9 +373,34 @@ export const SmsTraiCreate = (props) => {
134
373
  return isError;
135
374
  };
136
375
 
137
- const duplicateTemplateNameValidation = (
376
+ const checkDuplicateTemplateNameInDb = (
377
+ transformedResults,
378
+ templateIdIndex,
379
+ templateNameIndex,
380
+ ) => {
381
+ //filtering out rows that have duplicate template name in CSV and rows which have template name/template id missing
382
+ const checkInDb = transformedResults
383
+ ?.map((elem, index) => {
384
+ const rejectionReason = elem[elem?.length - 1]?.trim();
385
+ if (index !== 0 && !rejectionReason?.includes(DUPLICATE)) {
386
+ return {
387
+ template_id: elem[templateIdIndex]?.replace(/[“”"'‘’`´]/g, ''),
388
+ template_name: elem[templateNameIndex],
389
+ };
390
+ }
391
+ })
392
+ ?.filter((obj) => obj && obj.template_name !== '' && obj.template_id !== '');
393
+ setUploadValidated(true);
394
+ setValidatedData(transformedResults);
395
+ setTemplateRegistrationIndex(templateIdIndex);
396
+ actions.checkDuplicatesInDb(checkInDb);
397
+ };
398
+
399
+ const checkDuplicateTemplateNameInCSV = (
138
400
  transformedResults,
139
401
  templateNameObj,
402
+ templateIdIndex,
403
+ templateNameIndex,
140
404
  ) => {
141
405
  //filtering and extracting index of template names with more than 1 occurence
142
406
  const duplicateTemplateNameRows =
@@ -155,11 +419,15 @@ export const SmsTraiCreate = (props) => {
155
419
  }
156
420
  transformedResults[row][
157
421
  transformedResults[row]?.length - 1
158
- ] += ` Duplicate template names are not allowed.`;
422
+ ] += ` This template name is repeated in this CSV.Duplicate template names are not allowed.`;
159
423
  });
160
424
  setTotalFailCount((prev) => prev + duplicateTemplateNameCounts);
161
425
  }
162
- return transformedResults;
426
+ checkDuplicateTemplateNameInDb(
427
+ transformedResults,
428
+ templateIdIndex,
429
+ templateNameIndex,
430
+ );
163
431
  };
164
432
 
165
433
  const checkCSVRowsValidation = (
@@ -207,8 +475,8 @@ export const SmsTraiCreate = (props) => {
207
475
  errorArray.push(`"${transformedResults[0][index]}"`);
208
476
  } else if (index === templateNameIndex && cell) {
209
477
  if (templateNameObj[cell]) {
210
- templateNameObj[cell]['count'] += 1;
211
- templateNameObj[cell]['csvRow']?.push(row);
478
+ templateNameObj[cell].count += 1;
479
+ templateNameObj[cell].csvRow?.push(row);
212
480
  } else {
213
481
  templateNameObj[cell] = { count: 1, csvRow: [row] };
214
482
  }
@@ -236,154 +504,17 @@ export const SmsTraiCreate = (props) => {
236
504
  setTotalFailCount((prev) => prev + 1);
237
505
  }
238
506
  }
239
- uploadValidated = true;
240
- return duplicateTemplateNameValidation(transformedResults, templateNameObj);
241
- };
242
-
243
- const checkCSVValidation = (results, file) => {
244
- if (file?.name?.split('.').pop() === 'csv') {
245
- const mandatoryColNotPresent = [];
246
- const headerAliasPresent = [];
247
- const templateIdAliasPresent = [];
248
- const templateMessageAliasPresent = [];
249
- const statusAliasPresent = [];
250
- const typeAliasPresent = [];
251
- const colCounts = {};
252
- //removing last empty row if each cell is empty
253
- if (results?.data[results.data.length - 1]?.every((cell) => !cell)) {
254
- results.data.pop();
255
- }
256
- const fileLen = results?.data?.length || 0;
257
- // at least 1 records should be available
258
- if (fileLen < 2) {
259
- setErrorText(formatMessage(messages.fileMinlengthError));
260
- return;
261
- }
262
- // more then 500 records are not available.
263
- if (fileLen > 501) {
264
- setErrorText(formatMessage(messages.fileMaxlengthError));
265
- return;
266
- }
267
-
268
- const cols = getAllColumnNames(results.data[0]);
269
-
270
- for (let i = 0; i < MANDATORY_COLUMNS.length; i += 1) {
271
- if (!cols.includes(MANDATORY_COLUMNS[i])) {
272
- mandatoryColNotPresent.push(MANDATORY_COLUMNS[i]);
273
- }
274
- }
275
- if (mandatoryColNotPresent.length > 0) {
276
- setErrorText(formatMessage(messages.mandatoryColErrorDescription));
277
- return;
278
- }
279
-
280
- //one of the mandatory header alias should be available.
281
- for (let i = 0; i < HEADER_ALIASES.length; i += 1) {
282
- if (cols.includes(HEADER_ALIASES[i])) {
283
- headerAliasPresent.push(HEADER_ALIASES[i]);
284
- }
285
- }
286
- if (headerAliasPresent.length === 0) {
287
- setErrorText(
288
- formatMessage(messages.headerAliasErrorDescription, {
289
- headerAliases: HEADER_ALIASES.join(' / '),
290
- }),
291
- );
292
- return;
293
- }
294
- //one of the mandatory template id alias should be available.
295
- for (let i = 0; i < TEMPLATE_ID_ALIASES.length; i += 1) {
296
- if (cols.includes(TEMPLATE_ID_ALIASES[i])) {
297
- templateIdAliasPresent.push(TEMPLATE_ID_ALIASES[i]);
298
- }
299
- }
300
- if (templateIdAliasPresent.length === 0) {
301
- setErrorText(
302
- formatMessage(messages.templateIdAliasErrorDescription, {
303
- templateIdAliases: TEMPLATE_ID_ALIASES.join(' / '),
304
- }),
305
- );
306
- return;
307
- }
308
- //one of the mandatory template message alias should be available.
309
- for (let i = 0; i < TEMPLATE_MESSAGE_ALIASES.length; i += 1) {
310
- if (cols.includes(TEMPLATE_MESSAGE_ALIASES[i])) {
311
- templateMessageAliasPresent.push(TEMPLATE_MESSAGE_ALIASES[i]);
312
- }
313
- }
314
- if (templateMessageAliasPresent.length === 0) {
315
- setErrorText(
316
- formatMessage(messages.templateMessageAliasErrorDescription, {
317
- templateMessageAliases: TEMPLATE_MESSAGE_ALIASES.join(' / '),
318
- }),
319
- );
320
- return;
321
- }
322
- //one of the mandatory status alias should be available.
323
- for (let i = 0; i < STATUS_ALIASES.length; i += 1) {
324
- if (cols.includes(STATUS_ALIASES[i])) {
325
- statusAliasPresent.push(STATUS_ALIASES[i]);
326
- }
327
- }
328
- if (statusAliasPresent.length === 0) {
329
- setErrorText(
330
- formatMessage(messages.statusAliasErrorDescription, {
331
- statusAliases: STATUS_ALIASES.join(' / '),
332
- }),
333
- );
334
- return;
335
- }
336
- //one of the mandatory type alias should be available.
337
- for (let i = 0; i < TYPE_ALIASES.length; i += 1) {
338
- if (cols.includes(TYPE_ALIASES[i])) {
339
- typeAliasPresent.push(TYPE_ALIASES[i]);
340
- }
341
- }
342
- if (typeAliasPresent.length === 0) {
343
- setErrorText(
344
- formatMessage(messages.typeAliasErrorDescription, {
345
- typeAliases: TYPE_ALIASES.join(' / '),
346
- }),
347
- );
348
- return;
349
- }
350
- // count of each col to validate blank and repetitive cols
351
- for (const num of cols) {
352
- colCounts[num] = colCounts[num] ? colCounts[num] + 1 : 1;
353
- }
354
-
355
- const repetitiveColsArray = Object.keys(
356
- Object.fromEntries(
357
- Object.entries(colCounts).filter(
358
- ([key, value]) => key !== '' && value > 1,
359
- ),
360
- ),
361
- );
362
- //throw validation if repetitive columns present
363
- if (repetitiveColsArray.length !== 0) {
364
- setErrorText(
365
- formatMessage(messages.repetitiveColsErrorDescription, {
366
- repetitiveCols: repetitiveColsArray.join(', '),
367
- }),
368
- );
369
- return;
370
- }
371
- //perform required data transformation
372
- return dataTransformHandler(
373
- cols,
374
- results,
375
- headerAliasPresent,
376
- templateIdAliasPresent,
377
- statusAliasPresent,
378
- );
379
- } else {
380
- setErrorText(formatMessage(messages.nonCsvErrorDescription));
381
- }
507
+ checkDuplicateTemplateNameInCSV(
508
+ transformedResults,
509
+ templateNameObj,
510
+ templateIdIndex,
511
+ templateNameIndex,
512
+ );
382
513
  };
383
514
 
384
515
  const dataTransformHandler = (
385
516
  cols,
386
- results,
517
+ traiFileDataCopy,
387
518
  headerAliasPresent,
388
519
  templateIdAliasPresent,
389
520
  statusAliasPresent,
@@ -404,14 +535,14 @@ export const SmsTraiCreate = (props) => {
404
535
  }
405
536
  //transforming data to keep only mandatory cols data using their index
406
537
  const transformedResults = [];
407
- for (const key in results.data) {
538
+ for (const key in traiFileDataCopy.data) {
408
539
  transformedResults.push(
409
- indexArray.map((i) => results.data[key][i]?.trim()),
540
+ indexArray.map((i) => traiFileDataCopy.data[key][i]?.trim()),
410
541
  );
411
542
  }
412
543
  //add rejection header
413
544
  transformedResults[0].push(CAPILLARY_REJECTION_REASON);
414
- return checkCSVRowsValidation(
545
+ checkCSVRowsValidation(
415
546
  transformedResults,
416
547
  headerAliasPresent[0],
417
548
  templateIdAliasPresent[0],
@@ -422,57 +553,18 @@ export const SmsTraiCreate = (props) => {
422
553
  //returns the headers(first row) of the uploaded file in lowercase
423
554
  const getAllColumnNames = (data) => data.map((x) => x?.toLowerCase()?.trim());
424
555
 
425
- const onDrop = (droppedFile) => {
556
+ const onDrop = (traiFile) => {
426
557
  // Sets isFileDropped state to true to load the spinner while the file is being parsed.
427
558
  setIsFileDropped(true);
428
559
 
429
- Papa.parse(droppedFile[0], {
430
- complete: (results, file) => {
431
- setIsFileDropped(false); // Stop the spinner
432
- const validatedResults = checkCSVValidation(results, file);
433
- const selectedFiles = cloneDeep(files);
434
- if (uploadValidated) {
435
- //remove capillary rejection reason column if already present on reupload
436
- //ex: user reuploads a csv which was earlier validated and rejection reasons were added for failed templates
437
- const rejectionIndex = getAllColumnNames(results.data[0]).indexOf(
438
- CAPILLARY_REJECTION_REASON.toLowerCase(),
439
- );
440
- if (rejectionIndex !== -1) {
441
- results.data.forEach((row) => {
442
- row.splice(rejectionIndex, 1);
443
- });
444
- }
445
- //adding validated rejection reason column to original results
446
- for (let i = 0; i < validatedResults.length; i += 1) {
447
- results.data[i].push(
448
- validatedResults[i][validatedResults[i]?.length - 1],
449
- );
450
- }
451
- updateSaveTemplate(true);
452
- }
453
- selectedFiles.push({
454
- file,
455
- fileResult: results,
456
- columnMapping: [],
457
- });
458
-
459
- setFiles(selectedFiles);
460
- setPreviewFileIndex(selectedFiles.length - 1);
461
- setDropZone(false);
560
+ Papa.parse(traiFile[0], {
561
+ complete: (fileData, fileMeta) => {
562
+ setTraiFileData(fileData);
563
+ setTraiFileMeta(fileMeta);
462
564
  },
463
565
  });
464
566
  };
465
567
 
466
- const deleteCSV = () => {
467
- setFiles([]);
468
- setTotalFailCount(0);
469
- setErrorText('');
470
- setIsFileDropped(false);
471
- setPreviewFileIndex(null);
472
- setDropZone(true);
473
- updateSaveTemplate(false);
474
- };
475
-
476
568
  //common function to handle csv downloads
477
569
  const downloadHandler = (event, data, downloadedFileName) => {
478
570
  event.target.setAttribute(
@@ -490,14 +582,14 @@ export const SmsTraiCreate = (props) => {
490
582
  const downloadIssuesCSV = (event) => {
491
583
  let csvContent = [];
492
584
  let tempArray = [];
493
- const fileData = files[0].fileResult.data;
494
- const rejectionIndex = fileData[0].indexOf(CAPILLARY_REJECTION_REASON);
585
+ const csvData = files[0].fileData.data;
586
+ const rejectionIndex = csvData[0].indexOf(CAPILLARY_REJECTION_REASON);
495
587
 
496
588
  if (rejectionIndex !== -1) {
497
- tempArray.push(fileData[0]);
498
- for (let row = 1; row < fileData.length; row += 1) {
499
- if (fileData[row][rejectionIndex]) {
500
- tempArray.push(fileData[row]);
589
+ tempArray.push(csvData[0]);
590
+ for (let row = 1; row < csvData.length; row += 1) {
591
+ if (csvData[row][rejectionIndex]) {
592
+ tempArray.push(csvData[row]);
501
593
  }
502
594
  }
503
595
  tempArray = tempArray.map((row) =>
@@ -527,15 +619,15 @@ export const SmsTraiCreate = (props) => {
527
619
  const onDoneCallback = () => {
528
620
  //start spinner
529
621
  setIsFileDropped(true);
530
- const fileData = files[0].fileResult.data;
531
- const rejectionIndex = fileData[0].indexOf(CAPILLARY_REJECTION_REASON);
622
+ const csvData = files[0].fileData.data;
623
+ const rejectionIndex = csvData[0].indexOf(CAPILLARY_REJECTION_REASON);
532
624
  const tempArray = [];
533
- tempArray.push(fileData[0]);
625
+ tempArray.push(csvData[0]);
534
626
 
535
627
  // filter out non rejected rows
536
- for (let row = 1; row < fileData.length; row += 1) {
537
- if (!fileData[row][rejectionIndex]) {
538
- tempArray.push(fileData[row]);
628
+ for (let row = 1; row < csvData.length; row += 1) {
629
+ if (!csvData[row][rejectionIndex]) {
630
+ tempArray.push(csvData[row]);
539
631
  }
540
632
  }
541
633
  // Filter out the columns index that needs to save
@@ -610,16 +702,26 @@ export const SmsTraiCreate = (props) => {
610
702
  if (
611
703
  previewFileIndex !== null &&
612
704
  saveTemplate &&
613
- files[0].fileResult.data.length - 1 - totalFailCount >= 1
705
+ files[0].fileData.data.length - 1 - totalFailCount >= 1
614
706
  ) {
615
707
  return false;
616
708
  }
617
709
  return true;
618
710
  };
619
711
 
620
- const onCancel = () => {
712
+ const deleteOrCancelCSV = () => {
713
+ setTraiFileData({});
714
+ setTraiFileMeta(null);
715
+ setValidatedData([]);
621
716
  setFiles([]);
717
+ setTemplateRegistrationIndex(null);
718
+ setErrorText('');
719
+ setDropZone(true);
720
+ setPreviewFileIndex(null);
721
+ setIsFileDropped(false);
722
+ setTotalFailCount(0);
622
723
  updateSaveTemplate(false);
724
+ setUploadValidated(false);
623
725
  };
624
726
 
625
727
  const InstructionComp = (inst) => (
@@ -631,8 +733,8 @@ export const SmsTraiCreate = (props) => {
631
733
  </CapRow>
632
734
  );
633
735
 
634
- const fileData = files[previewFileIndex] || {};
635
- const { fileResult, file } = fileData;
736
+ const fileZero = files[previewFileIndex] || {};
737
+ const { fileData, fileMeta } = fileZero;
636
738
  return (
637
739
  <>
638
740
  <CapRow span={24} className="dlt-csv-upload-container">
@@ -643,7 +745,7 @@ export const SmsTraiCreate = (props) => {
643
745
  {previewFileIndex === null && dropZone && (
644
746
  <>
645
747
  <CapSpin spinning={isFileDropped}>
646
- <Dropzone onDrop={onDrop} onFileDialogCancel={onCancel}>
748
+ <Dropzone onDrop={onDrop} onFileDialogCancel={deleteOrCancelCSV}>
647
749
  {({ getRootProps, getInputProps }) => (
648
750
  <div {...getRootProps()} className="file-drop-zone">
649
751
  <input {...getInputProps()} />
@@ -685,7 +787,7 @@ export const SmsTraiCreate = (props) => {
685
787
  <CapRow>
686
788
  <CapColumn span={10}>
687
789
  <CapLabel.CapLabelInline type="label9">
688
- {file.name}
790
+ {fileMeta.name}
689
791
  </CapLabel.CapLabelInline>
690
792
  <CapLabel.CapLabelInline
691
793
  type="label1"
@@ -693,7 +795,7 @@ export const SmsTraiCreate = (props) => {
693
795
  >
694
796
  (
695
797
  {formatMessage(messages.numberOfRecords, {
696
- value: fileResult.data.length - 1,
798
+ value: fileData.data.length - 1,
697
799
  })}
698
800
  )
699
801
  </CapLabel.CapLabelInline>
@@ -729,8 +831,7 @@ export const SmsTraiCreate = (props) => {
729
831
  className="validation-count-label"
730
832
  >
731
833
  {formatMessage(messages.passedVal, {
732
- number:
733
- fileResult.data.length - 1 - totalFailCount,
834
+ number: fileData.data.length - 1 - totalFailCount,
734
835
  })}
735
836
  </CapLabel>
736
837
  <CapIcon
@@ -773,7 +874,7 @@ export const SmsTraiCreate = (props) => {
773
874
  <CapIcon
774
875
  type="delete"
775
876
  size="s"
776
- onClick={deleteCSV}
877
+ onClick={deleteOrCancelCSV}
777
878
  ></CapIcon>
778
879
  </CapColumn>
779
880
  </CapRow>
@@ -852,7 +953,9 @@ SmsTraiCreate.propTypes = {
852
953
  dispatch: PropTypes.func.isRequired,
853
954
  };
854
955
 
855
- const mapStateToProps = createStructuredSelector({});
956
+ const mapStateToProps = createStructuredSelector({
957
+ traiSms: makeSelectSmsTrai(),
958
+ });
856
959
 
857
960
  const mapDispatchToProps = (dispatch) => ({
858
961
  actions: bindActionCreators(smsTraiActions, dispatch),