@capillarytech/creatives-library 7.17.81 → 7.17.82-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.
Files changed (38) hide show
  1. package/containers/Cap/sagas.js +7 -5
  2. package/containers/Cap/tests/saga.test.js +81 -1
  3. package/package.json +3 -2
  4. package/services/api.js +5 -0
  5. package/services/tests/api.test.js +9 -1
  6. package/v2Components/CapWhatsappQuickReply/index.js +243 -0
  7. package/v2Components/CapWhatsappQuickReply/index.scss +43 -0
  8. package/v2Components/CapWhatsappQuickReply/messages.js +24 -0
  9. package/v2Components/TemplatePreview/_templatePreview.scss +23 -0
  10. package/v2Components/TemplatePreview/index.js +51 -1
  11. package/v2Components/TemplatePreview/messages.js +4 -0
  12. package/v2Components/TemplatePreview/tests/__snapshots__/index.test.js.snap +0 -14
  13. package/v2Containers/CreativesContainer/index.js +22 -2
  14. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +2 -0
  15. package/v2Containers/Templates/index.js +5 -2
  16. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +6 -0
  17. package/v2Containers/Whatsapp/actions.js +16 -0
  18. package/v2Containers/Whatsapp/constants.js +22 -0
  19. package/v2Containers/Whatsapp/index.js +699 -187
  20. package/v2Containers/Whatsapp/index.scss +55 -1
  21. package/v2Containers/Whatsapp/messages.js +37 -0
  22. package/v2Containers/Whatsapp/reducer.js +19 -0
  23. package/v2Containers/Whatsapp/sagas.js +40 -1
  24. package/v2Containers/Whatsapp/styles.scss +29 -0
  25. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +40962 -24255
  26. package/v2Containers/Whatsapp/tests/__snapshots__/utils.test.js.snap +12 -0
  27. package/v2Containers/Whatsapp/tests/actions.test.js +21 -0
  28. package/v2Containers/Whatsapp/tests/index.test.js +8 -0
  29. package/v2Containers/Whatsapp/tests/mockData.js +6 -0
  30. package/v2Containers/Whatsapp/tests/reducer.test.js +67 -0
  31. package/v2Containers/Whatsapp/tests/saga.test.js +90 -0
  32. package/v2Containers/Whatsapp/tests/utils.test.js +11 -0
  33. package/v2Containers/Whatsapp/utils.js +45 -3
  34. package/v2Containers/mockdata.js +105 -4
  35. package/v2Containers/InApp/constants.js +0 -0
  36. package/v2Containers/InApp/index.js +0 -499
  37. package/v2Containers/InApp/index.scss +0 -0
  38. package/v2Containers/InApp/messages.js +0 -0
@@ -57,6 +57,7 @@ import {
57
57
  WHATSAPP_MEDIA_TYPES,
58
58
  WHATSAPP_BUTTON_TYPES,
59
59
  INITIAL_CTA_DATA,
60
+ INITIAL_QUICK_REPLY_DATA,
60
61
  ALLOWED_IMAGE_EXTENSIONS_REGEX,
61
62
  WHATSAPP_IMG_SIZE,
62
63
  HOST_TWILIO,
@@ -68,6 +69,12 @@ import {
68
69
  WHATSAPP_VIDEO_SIZE,
69
70
  DOCUMENT_FORMAT,
70
71
  DOCUMENT_SIZE,
72
+ TEMPLATE_HEADER_MAX_LENGTH,
73
+ QUICK_REPLY_BUTTON_TEXT_MAX_LENGTH,
74
+ HEADER_TEXT,
75
+ FOOTER_TEXT,
76
+ MESSAGE_TEXT,
77
+ BUTTON_TEXT
71
78
  } from './constants';
72
79
  import { DATE_DISPLAY_FORMAT, TIME_DISPLAY_FORMAT } from '../App/constants';
73
80
  import messages from './messages';
@@ -87,10 +94,12 @@ import { getCdnUrl } from '../../utils/cdnTransformation';
87
94
  import CapVideoUpload from '../../v2Components/CapVideoUpload';
88
95
  import CapDocumentUpload from '../../v2Components/CapDocumentUpload';
89
96
  import { getWhatsappDocPreview } from './utils';
97
+ import CapWhatsappQuickReply from '../../v2Components/CapWhatsappQuickReply';
90
98
 
91
99
  let varMap = {};
92
100
  let editContent = {};
93
101
  let tagValidationResponse = {};
102
+ let headerTagValidationResponse = {};
94
103
 
95
104
  export const Whatsapp = (props) => {
96
105
  const {
@@ -128,6 +137,10 @@ export const Whatsapp = (props) => {
128
137
  );
129
138
  const [templateMessage, setTemplateMessage] = useState('');
130
139
  const [templateMessageError, setTemplateMessageError] = useState(false);
140
+ const [templateHeader, setTemplateHeader] = useState('');
141
+ const [templateHeaderError, setTemplateHeaderError] = useState(false);
142
+ const [templateFooter, setTemplateFooter] = useState('');
143
+ const [templateFooterError, setTemplateFooterError] = useState(false);
131
144
  const [addedVarCount, setAddedVarCount] = useState(0);
132
145
  const [accountId, setAccountId] = useState('');
133
146
  const [accessToken, setAccessToken] = useState('');
@@ -159,14 +172,29 @@ export const Whatsapp = (props) => {
159
172
  //buttons
160
173
  const [buttonType, setButtonType] = useState(WHATSAPP_BUTTON_TYPES.NONE);
161
174
  const [ctaData, setCtadata] = useState(INITIAL_CTA_DATA);
175
+ const [quickReplyData, setQuickReplyData] = useState(
176
+ INITIAL_QUICK_REPLY_DATA
177
+ );
178
+ const [tempHeaderData, setTempHeaderData] = useState([]);
179
+ const [headerVarMappedData, setHeaderVarMappedData] = useState({});
180
+ const [updatedHeaderData, setUpdatedHeaderData] = useState([]);
181
+ const [headerTextAreaId, setHeaderTextAreaId] = useState('');
182
+ const [isHeaderTagValidationError, updateIsHeaderTagValidationError] =
183
+ useState(false);
184
+ const [isPreviewUrl, setIsPreviewUrl] = useState(false);
185
+ const [previewUrl, setPreviewUrl] = useState('');
162
186
 
163
187
  const validVarRegex = /{{([1-9]|1[0-9])}}/g;
188
+ const headerValidVarRegex = /{{(1)}}/g;
189
+ const urlMatchingRegex = /(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])/g;
164
190
 
165
191
  const isBtnTypeCta = buttonType === WHATSAPP_BUTTON_TYPES.CTA;
192
+ const isBtnTypeQuickReply = buttonType === WHATSAPP_BUTTON_TYPES.QUICK_REPLY;
166
193
  const isMediaTypeText = templateMediaType === WHATSAPP_MEDIA_TYPES.TEXT;
167
194
  const isMediaTypeImage = templateMediaType === WHATSAPP_MEDIA_TYPES.IMAGE;
168
195
  const isMediaTypeVideo = templateMediaType === WHATSAPP_MEDIA_TYPES.VIDEO;
169
196
  const isMediaTypeDoc = templateMediaType === WHATSAPP_MEDIA_TYPES.DOCUMENT;
197
+ const isHostIsNotTwilio = host !== HOST_TWILIO;
170
198
  const WhatsappFooter = styled.div`
171
199
  background-color: ${CAP_WHITE};
172
200
  position: fixed;
@@ -213,6 +241,7 @@ export const Whatsapp = (props) => {
213
241
  return () => {
214
242
  actions.resetEditTemplate();
215
243
  varMap = {};
244
+ setHeaderVarMappedData({});
216
245
  };
217
246
  }, [paramObj.id]);
218
247
 
@@ -241,6 +270,8 @@ export const Whatsapp = (props) => {
241
270
  buttons = [],
242
271
  videoPreviewImg = '',
243
272
  whatsappDocParams = {},
273
+ whatsappMedia: { header = '', footer = '' } = {},
274
+ isPreviewUrl: showUrlPreview = false,
244
275
  } = editContent;
245
276
  setTemplateCategory(category);
246
277
  setTemplateStatus(status);
@@ -262,6 +293,9 @@ export const Whatsapp = (props) => {
262
293
  });
263
294
  setKarixFileHandle(karixFileHandle);
264
295
  setButtonType(btnType);
296
+ setTemplateFooter(footer);
297
+ setTemplateHeader(header);
298
+ setIsPreviewUrl(showUrlPreview);
265
299
  if (btnType === WHATSAPP_BUTTON_TYPES.CTA && buttons.length > 0) {
266
300
  setCtadata(
267
301
  buttons.map((cta) => {
@@ -288,16 +322,70 @@ export const Whatsapp = (props) => {
288
322
  }),
289
323
  );
290
324
  }
325
+ if (btnType === WHATSAPP_BUTTON_TYPES.QUICK_REPLY && buttons?.length > 0) {
326
+ setQuickReplyData(buttons);
327
+ }
291
328
  computeTempMsgArray();
329
+ if (header && (mediaType === WHATSAPP_MEDIA_TYPES.TEXT && isHostIsNotTwilio)) {
330
+ computeHeaderMsgArray();
331
+ }
292
332
  }
293
333
  }, [editData.templateDetails || templateData]);
294
334
 
335
+ const converStringToVarArr = (validVarArr, content) => {
336
+ const templateVarArray = [];
337
+ while (content?.length !== 0) {
338
+ //converting content string to an array split at var
339
+ const index = content.indexOf(validVarArr?.[0]);
340
+ if (index !== -1) {
341
+ templateVarArray.push(content.substring(0, index)); //push string before var
342
+ templateVarArray.push(validVarArr?.[0]); //push var
343
+ content = content.substring(index + validVarArr?.[0]?.length, content?.length); //remaining str
344
+ validVarArr?.shift(); //remove considered var
345
+ } else {
346
+ templateVarArray.push(content); //remaining str
347
+ break;
348
+ }
349
+ }
350
+ return templateVarArray;
351
+ }
352
+
353
+ const computeHeaderMsgArray = () => {
354
+ let msg = get(editContent, `whatsappMedia.header`, '');
355
+ const validVarArr = msg?.match(headerValidVarRegex) || [];
356
+ //conerting msg string to variable arr
357
+ const templateHeaderArray = converStringToVarArr(validVarArr, msg);
358
+ setTempHeaderData(templateHeaderArray);
359
+ if (templateHeaderArray?.length !== 0) {
360
+ let headerVarMap = {};
361
+ const {
362
+ whatsappMedia: { headerVarMapped = {} },
363
+ } = editContent;
364
+ if (!isEmpty(headerVarMapped)) {
365
+ headerVarMap = cloneDeep(headerVarMapped);
366
+ } else {
367
+ templateHeaderArray?.forEach((headerValue, i) => {
368
+ if (headerValue?.match(headerValidVarRegex)?.length > 0) {
369
+ headerVarMap[`${headerValue}_${i}`] = '';
370
+ }
371
+ })
372
+ }
373
+ const arr = [...templateHeaderArray];
374
+ for (const key in headerVarMap) {
375
+ if (headerVarMap[key] !== '') {
376
+ arr[key.slice(key.indexOf('_') + 1)] = headerVarMap[key];
377
+ }
378
+ }
379
+ setHeaderVarMappedData(headerVarMap);
380
+ setUpdatedHeaderData(arr);
381
+ }
382
+ };
383
+
295
384
  const computeTempMsgArray = () => {
296
385
  let msg = get(editContent, `languages[0].content`, '');
297
386
  const validVarArr = msg.match(validVarRegex) || [];
298
387
  const unsubscribeRegex1 = /Click {{([1-9]|1[0-9])}} to unsubscribe/g;
299
388
  const unsubscribeRegex2 = /Click {{unsubscribe}} to unsubscribe/g;
300
- const templateMessageArray = [];
301
389
  //removing $'' which was added for twilio enter handling
302
390
  // msg = msg.slice(2, -1);
303
391
  if (
@@ -317,19 +405,8 @@ export const Whatsapp = (props) => {
317
405
  }
318
406
  setUnsubscribeRequired(true);
319
407
  }
320
- while (msg.length !== 0) {
321
- //converting content string to an array split at var
322
- const index = msg.indexOf(validVarArr[0]);
323
- if (index !== -1) {
324
- templateMessageArray.push(msg.substring(0, index)); //push string before var
325
- templateMessageArray.push(validVarArr[0]); //push var
326
- msg = msg.substring(index + validVarArr[0].length, msg.length); //remaining str
327
- validVarArr.shift(); //remove considered var
328
- } else {
329
- templateMessageArray.push(msg); //remaining str
330
- break;
331
- }
332
- }
408
+ //conerting msg string to variable arr
409
+ const templateMessageArray = converStringToVarArr(validVarArr, msg);
333
410
  updateTempMsgArray(templateMessageArray.filter((i) => i === 0 || i));
334
411
  };
335
412
 
@@ -353,15 +430,21 @@ export const Whatsapp = (props) => {
353
430
  arr[key.slice(key.indexOf('_') + 1)] = varMap[key];
354
431
  }
355
432
  }
433
+ if (arr?.length) {
434
+ const validUrls = arr.join("").match(urlMatchingRegex) || [];
435
+ if (validUrls && validUrls?.length) {
436
+ setPreviewUrl(validUrls?.[0] || '')
437
+ }
438
+ }
356
439
  setUpdatedSmsEditor(arr);
357
440
  }
358
441
  }, [tempMsgArray]);
359
442
 
360
443
  useEffect(() => {
361
- if (tempMsgArray?.length && !loadingTags) {
444
+ if ((tempMsgArray?.length || tempHeaderData?.length) && !loadingTags) {
362
445
  setSpin(false);
363
446
  }
364
- }, [tempMsgArray, loadingTags]);
447
+ }, [tempMsgArray, loadingTags, tempHeaderData]);
365
448
 
366
449
  // tag Code start from here
367
450
  useEffect(() => {
@@ -393,27 +476,66 @@ export const Whatsapp = (props) => {
393
476
  }
394
477
  }, [metaEntities, isEditFlow]);
395
478
 
396
- //performs tag validation
397
- useEffect(() => {
398
- if (
399
- !isFullMode &&
400
- updatedSmsEditor?.length > 0 &&
401
- !updatedSmsEditor.join('').match(validVarRegex)
402
- ) {
403
- tagValidationResponse =
479
+ const tagValidation = (contentData, regex, type) => {
480
+ if (contentData?.length > 0 && !contentData.join("").match(regex)) {
481
+ let validationResponse =
404
482
  validateTags({
405
- content: updatedSmsEditor.join(''),
483
+ content: contentData.join(""),
406
484
  tagsParam: tags,
407
485
  injectedTagsParams: injectedTags,
408
486
  location,
409
487
  tagModule: getDefaultTags,
410
488
  }) || {};
411
- updateIsTagValidationError(
412
- tagValidationResponse.unsupportedTags.length > 0,
413
- );
489
+ if (type === HEADER_TEXT) {
490
+ headerTagValidationResponse = validationResponse;
491
+ updateIsHeaderTagValidationError(
492
+ validationResponse?.unsupportedTags?.length > 0
493
+ );
494
+ } else {
495
+ tagValidationResponse = validationResponse;
496
+ updateIsTagValidationError(
497
+ validationResponse?.unsupportedTags?.length > 0
498
+ );
499
+ }
500
+ }
501
+ };
502
+
503
+ useEffect(() => {
504
+ if (updatedSmsEditor?.length > 0) {
505
+ const previewUrlArr = updatedSmsEditor.join("").match(urlMatchingRegex) || [];
506
+ if (previewUrlArr && previewUrlArr?.length) {
507
+ setPreviewUrl(previewUrlArr[0]);
508
+ } else {
509
+ setPreviewUrl('');
510
+ }
511
+ }
512
+ }, [updatedSmsEditor])
513
+
514
+ useEffect(() => {
515
+ if (!isEmpty(previewUrl) && isPreviewUrl) {
516
+ const watingTimeFn = setTimeout(() => {
517
+ actions.getMetaTags({
518
+ previewUrl,
519
+ callBack: actionCallback,
520
+ })
521
+ }, 1000);
522
+ return () => clearTimeout(watingTimeFn);
523
+ } else {
524
+ actions.resetMetaTags();
414
525
  }
526
+ }, [previewUrl, isPreviewUrl])
527
+
528
+ //performs tag validation
529
+ useEffect(() => {
530
+ if (!isFullMode)
531
+ tagValidation(updatedSmsEditor, validVarRegex, MESSAGE_TEXT);
415
532
  }, [updatedSmsEditor, tags]);
416
533
 
534
+ useEffect(() => {
535
+ if (!isFullMode)
536
+ tagValidation(updatedHeaderData, headerValidVarRegex, HEADER_TEXT);
537
+ }, [updatedHeaderData, tags]);
538
+
417
539
  const handleOnTagsContextChange = (data) => {
418
540
  const { type } = location.query || {};
419
541
  const isEmbedded = type === EMBEDDED;
@@ -429,26 +551,68 @@ export const Whatsapp = (props) => {
429
551
  globalActions.fetchSchemaForEntity(query);
430
552
  };
431
553
 
432
- const onTagSelect = (data) => {
433
- if (varMap && updatedSmsEditor) {
434
- const numId = Number(textAreaId?.slice(textAreaId?.indexOf('_') + 1));
435
- if (numId != NaN) {
436
- const arr = [...updatedSmsEditor];
554
+ const onTagSelect = (tagSelectData) => {
555
+ const {
556
+ data = "",
557
+ type = MESSAGE_TEXT,
558
+ mapData = {},
559
+ updatedData = [],
560
+ areaId = "",
561
+ regex,
562
+ } = tagSelectData;
563
+ if (mapData && updatedData) {
564
+ const numId = Number(areaId?.slice(areaId?.indexOf("_") + 1));
565
+ if (!isNaN(numId)) {
566
+ const arr = [...updatedData];
437
567
  //when trying to insert tag in empty textarea,{#var#} is replaced with "" and then tag is added
438
- if (arr[numId]?.match(validVarRegex)?.length > 0) {
439
- arr[numId] = '';
568
+ if (arr?.[numId]?.match(regex)?.length > 0) {
569
+ arr[numId] = "";
440
570
  }
441
571
  const messageData = `${arr[numId]}{{${data}}}`;
442
572
  arr[numId] = messageData;
443
- varMap[textAreaId] = messageData;
444
- setUpdatedSmsEditor(arr);
573
+ if (type === HEADER_TEXT) {
574
+ setHeaderVarMappedData((prevState) => ({
575
+ ...prevState,
576
+ [areaId]: messageData,
577
+ }));
578
+ setUpdatedHeaderData(arr);
579
+ } else {
580
+ varMap[areaId] = messageData;
581
+ setUpdatedSmsEditor(arr);
582
+ }
445
583
  }
446
584
  }
447
585
  };
448
586
 
587
+ const onMessageTagSelect = (data) => {
588
+ onTagSelect({
589
+ data,
590
+ type: MESSAGE_TEXT,
591
+ mapData: varMap,
592
+ updatedData: updatedSmsEditor,
593
+ areaId: textAreaId,
594
+ regex: validVarRegex,
595
+ });
596
+ };
597
+
598
+ const onHeaderTagSelect = (data) => {
599
+ onTagSelect({
600
+ data,
601
+ type: HEADER_TEXT,
602
+ mapData: headerVarMappedData,
603
+ updatedData: updatedHeaderData,
604
+ areaId: headerTextAreaId,
605
+ regex: headerValidVarRegex,
606
+ });
607
+ };
608
+
449
609
  //setting the id of currently selected text area, is used onTagSelect
450
- const setTextAreaId = ({ target: { id } }) => {
451
- updateTextAreaId(id);
610
+ const setTextAreaId = ({ target: { id } }, type) => {
611
+ if (type === HEADER_TEXT) {
612
+ setHeaderTextAreaId(id);
613
+ } else {
614
+ updateTextAreaId(id);
615
+ }
452
616
  };
453
617
  // tag Code end
454
618
 
@@ -532,6 +696,7 @@ export const Whatsapp = (props) => {
532
696
  const onChangeButtonType = ({ target: { value } }) => {
533
697
  setButtonType(value);
534
698
  setCtadata(INITIAL_CTA_DATA);
699
+ setQuickReplyData(INITIAL_QUICK_REPLY_DATA);
535
700
  };
536
701
 
537
702
  const updateHandler = (data, index, full) => {
@@ -557,6 +722,42 @@ export const Whatsapp = (props) => {
557
722
  });
558
723
  };
559
724
 
725
+ const computeTextLength = (type) => {
726
+ switch (type) {
727
+ case MESSAGE_TEXT:
728
+ let whatsappContentLen = 0;
729
+ whatsappContentLen = isEditFlow
730
+ ? updatedSmsEditor?.join("")?.length
731
+ : templateMessage?.length;
732
+ whatsappContentLen += unsubscribeRequired ? UNSUBSCRIBE_TEXT_LENGTH : 0;
733
+ return whatsappContentLen;
734
+ case HEADER_TEXT:
735
+ let headerContentLen = 0;
736
+ headerContentLen = isEditFlow
737
+ ? updatedHeaderData?.join("")?.length
738
+ : templateHeader?.length;
739
+ return headerContentLen || 0;
740
+ case FOOTER_TEXT:
741
+ return templateFooter?.length || 0;
742
+ default:
743
+ let overallLength =
744
+ computeTextLength(MESSAGE_TEXT) +
745
+ computeTextLength(HEADER_TEXT) +
746
+ computeTextLength(FOOTER_TEXT);
747
+ return overallLength;
748
+ }
749
+ };
750
+
751
+ //used by create and edit
752
+ const renderMessageLength = (type, currentLength) => (
753
+ <CapHeading type="label1" className="whatsapp-render-message-length">
754
+ {formatMessage(messages.templateMessageLength, {
755
+ currentLength: currentLength ? currentLength : computeTextLength(type),
756
+ maxLength: maxLengthByType(type),
757
+ })}
758
+ </CapHeading>
759
+ );
760
+
560
761
  const buttonRadioOptions = [
561
762
  {
562
763
  value: WHATSAPP_BUTTON_TYPES.NONE,
@@ -591,25 +792,26 @@ export const Whatsapp = (props) => {
591
792
  {
592
793
  value: WHATSAPP_BUTTON_TYPES.QUICK_REPLY,
593
794
  label: (
594
- <CapTooltip
595
- placement="bottom"
596
- title={!isEditFlow && formatMessage(messages.disabledFeatureTooltip)}
597
- >
795
+ <>
598
796
  <div
599
797
  className="whatsapp-button-quick-reply"
600
- style={{
601
- marginTop: isBtnTypeCta ? '0px' : '24px',
602
- opacity: isEditFlow ? '' : '0.4',
603
- }}
604
798
  >
605
799
  <CapHeading type="h4">
606
800
  {formatMessage(messages.btnTypeQuickReply)}
607
801
  </CapHeading>
608
802
  <CapLabel>{formatMessage(messages.quickReplyDesc)}</CapLabel>
609
803
  </div>
610
- </CapTooltip>
804
+ {isBtnTypeQuickReply && (
805
+ <CapWhatsappQuickReply
806
+ quickReplyData={quickReplyData}
807
+ isEditFlow={isEditFlow}
808
+ renderMessageLength={renderMessageLength}
809
+ setQuickReplyData={setQuickReplyData}
810
+ />
811
+ )}
812
+ </>
611
813
  ),
612
- disabled: true,
814
+ disabled: host === HOST_TWILIO
613
815
  },
614
816
  ];
615
817
 
@@ -625,6 +827,10 @@ export const Whatsapp = (props) => {
625
827
  setTemplateMessageError(error);
626
828
  };
627
829
 
830
+ const previewUrlHandler = ({ target: { checked } }) => {
831
+ setIsPreviewUrl(checked);
832
+ }
833
+
628
834
  const renderUnsubscribeText = () => {
629
835
  const isDisabled =
630
836
  isEditFlow ||
@@ -664,25 +870,18 @@ export const Whatsapp = (props) => {
664
870
  );
665
871
  };
666
872
 
667
- const computeTextLength = () => {
668
- let whatsappContentLen = 0;
669
- whatsappContentLen = isEditFlow
670
- ? updatedSmsEditor.join('').length
671
- : templateMessage.length;
672
- whatsappContentLen += unsubscribeRequired ? UNSUBSCRIBE_TEXT_LENGTH : 0;
673
- return whatsappContentLen;
873
+ const maxLengthByType = (type) => {
874
+ switch (type) {
875
+ case MESSAGE_TEXT:
876
+ return TEMPLATE_MESSAGE_MAX_LENGTH;
877
+ case HEADER_TEXT:
878
+ case FOOTER_TEXT:
879
+ return TEMPLATE_HEADER_MAX_LENGTH;
880
+ case BUTTON_TEXT:
881
+ return QUICK_REPLY_BUTTON_TEXT_MAX_LENGTH;
882
+ }
674
883
  };
675
884
 
676
- //used by create and edit
677
- const renderMessageLength = () => (
678
- <CapHeading type="label1" className="whatsapp-render-message-length">
679
- {formatMessage(messages.templateMessageLength, {
680
- currentLength: computeTextLength(),
681
- maxLength: TEMPLATE_MESSAGE_MAX_LENGTH,
682
- })}
683
- </CapHeading>
684
- );
685
-
686
885
  const renderButtonsSection = () => (
687
886
  <>
688
887
  <CapHeader
@@ -858,18 +1057,56 @@ export const Whatsapp = (props) => {
858
1057
  setTemplateMediaType(value);
859
1058
  };
860
1059
 
861
- const onAddVar = () => {
862
- const validVarArr = templateMessage.match(validVarRegex) || [];
863
- const tempMsg = `${templateMessage}{{${validVarArr.length + 1}}}`;
864
- const error = templateMessageErrorHandler(tempMsg);
865
- setTemplateMessage(tempMsg);
866
- setTemplateMessageError(error);
1060
+ const onMessageAddVar = () => {
1061
+ onAddVar(MESSAGE_TEXT, templateMessage, validVarRegex);
867
1062
  };
868
1063
 
869
- const onTemplateMessageChange = ({ target: { value } }) => {
870
- const error = templateMessageErrorHandler(value);
871
- setTemplateMessage(value);
872
- setTemplateMessageError(error);
1064
+ const onHeaderAddVar = () => {
1065
+ onAddVar(HEADER_TEXT, templateHeader, headerValidVarRegex);
1066
+ };
1067
+
1068
+ const onAddVar = (type, messageContent, regex) => {
1069
+ const validVarArr = messageContent.match(regex) || [];
1070
+ const tempMsg = `${messageContent}{{${validVarArr.length + 1}}}`;
1071
+ const error = type === HEADER_TEXT ? templateHeaderErrorHandler(tempMsg) : templateMessageErrorHandler(tempMsg);
1072
+ if (type === HEADER_TEXT) {
1073
+ setTemplateHeader(tempMsg);
1074
+ setTemplateHeaderError(error);
1075
+ } else {
1076
+ setTemplateMessage(tempMsg);
1077
+ setTemplateMessageError(error);
1078
+ }
1079
+ }
1080
+
1081
+ const onTemplateValueChange = ({ target: { value } }, type) => {
1082
+ if (type === HEADER_TEXT) {
1083
+ const error = templateHeaderErrorHandler(value);
1084
+ setTemplateHeader(value);
1085
+ setTemplateHeaderError(error);
1086
+ } else {
1087
+ const error = templateMessageErrorHandler(value);
1088
+ setTemplateMessage(value);
1089
+ setTemplateMessageError(error);
1090
+ }
1091
+ }
1092
+
1093
+ const onTemplateFooterChanges = ({ target: { value } }) => {
1094
+ let error = false;
1095
+ if (value?.length > TEMPLATE_HEADER_MAX_LENGTH) {
1096
+ error = formatMessage(messages.templateFooterLengthError);
1097
+ }
1098
+ setTemplateFooter(value);
1099
+ setTemplateFooterError(error);
1100
+ };
1101
+
1102
+ const templateHeaderErrorHandler = (value) => {
1103
+ let errorMessage = false;
1104
+ if (value?.length > TEMPLATE_HEADER_MAX_LENGTH) {
1105
+ errorMessage = formatMessage(messages.templateHeaderLengthError);
1106
+ } else {
1107
+ errorMessage = variableErrorHandling(value, HEADER_TEXT);
1108
+ }
1109
+ return errorMessage;
873
1110
  };
874
1111
 
875
1112
  const templateMessageErrorHandler = (value) => {
@@ -882,41 +1119,54 @@ export const Whatsapp = (props) => {
882
1119
  ) {
883
1120
  errorMessage = formatMessage(messages.templateMessageLengthError);
884
1121
  } else {
885
- const validVarArr = value.match(validVarRegex) || [];
886
- const validVarSet = [...new Set(validVarArr)];
887
-
888
- const invalidVarRegex = /{{(.*?)}}/g;
889
- const invalidVarArr = value.match(invalidVarRegex) || [];
890
- const invalidVarSet = [...new Set(invalidVarArr)];
891
-
892
- const noContentBetweenVars = /}}\s*{{/g;
893
- const moreThanTwoBrackets = /{{3,}([1-9]|1[0-9])}{3,}/g;
894
- const consecutiveNewLines = /\n\s*\n\s*\n/;
895
- if (value.match(consecutiveNewLines)) {
896
- errorMessage = formatMessage(messages.removeMultinewlineChars);
897
- } else if (validVarArr?.length > 0 || invalidVarArr?.length > 0) {
898
- if (validVarArr?.length !== validVarSet?.length) {
899
- //checks for repetations like Hi {{1}}, offer for you {{1}}
900
- errorMessage = formatMessage(messages.repetativeVars);
901
- } else if (invalidVarSet?.length !== validVarSet?.length) {
902
- //checks for invalid vars like Hi {{abcd}}, offer for you {{^_^}}
903
- errorMessage = formatMessage(messages.unknownVars, {one: '{{1}}', nineteen: '{{19}}'});
904
- } else if (value.match(noContentBetweenVars)?.length > 0) {
905
- //checks for text between vars like Hi {{1}}{{2}}
906
- errorMessage = formatMessage(messages.noContentBetweenVars);
907
- } else if (value.match(moreThanTwoBrackets)?.length > 0) {
908
- //checks for >2 brackets {{{1}}}
909
- errorMessage = formatMessage(messages.useTwoBracketsOnly);
1122
+ errorMessage = variableErrorHandling(value, MESSAGE_TEXT);
1123
+ }
1124
+ return errorMessage;
1125
+ };
1126
+
1127
+ const variableErrorHandling = (value, type) => {
1128
+ let errorMessage = false;
1129
+ const validVarArr = value.match(type === HEADER_TEXT ? headerValidVarRegex : validVarRegex) || [];
1130
+ const validVarSet = [...new Set(validVarArr)];
1131
+
1132
+ const invalidVarRegex = /{{(.*?)}}/g;
1133
+ const invalidVarArr = value.match(invalidVarRegex) || [];
1134
+ const invalidVarSet = [...new Set(invalidVarArr)];
1135
+
1136
+ const noContentBetweenVars = /}}\s*{{/g;
1137
+ const moreThanTwoBrackets = /{{3,}([1-9]|1[0-9])}{3,}/g;
1138
+ const consecutiveNewLines = /\n\s*\n\s*\n/;
1139
+ if (value.match(consecutiveNewLines)) {
1140
+ errorMessage = formatMessage(messages.removeMultinewlineChars);
1141
+ } else if (validVarArr?.length > 0 || invalidVarArr?.length > 0) {
1142
+ if (validVarArr?.length !== validVarSet?.length) {
1143
+ //checks for repetations like Hi {{1}}, offer for you {{1}}
1144
+ errorMessage = formatMessage(messages.repetativeVars);
1145
+ } else if (invalidVarSet?.length !== validVarSet?.length) {
1146
+ //checks for invalid vars like Hi {{abcd}}, offer for you {{^_^}}
1147
+ if (type === HEADER_TEXT) {
1148
+ errorMessage = formatMessage(messages.headerUnknownVars);
910
1149
  } else {
911
- //checks if vars are added sequentially like, Hi {{1}}, offer for you {{2}} today {{3}}
912
- const checkSequence = [...validVarSet].filter(
913
- (validVar, index) => `{{${index + 1}}}` !== validVar,
914
- );
915
- if (checkSequence?.length > 0) {
916
- errorMessage = formatMessage(messages.sequenceVars, {one: '{{1}}'});
917
- } else {
918
- setAddedVarCount(validVarSet?.length || 0);
919
- }
1150
+ errorMessage = formatMessage(messages.unknownVars, {
1151
+ one: "{{1}}",
1152
+ nineteen: "{{19}}",
1153
+ });
1154
+ }
1155
+ } else if (value.match(noContentBetweenVars)?.length > 0) {
1156
+ //checks for text between vars like Hi {{1}}{{2}}
1157
+ errorMessage = formatMessage(messages.noContentBetweenVars);
1158
+ } else if (value.match(moreThanTwoBrackets)?.length > 0) {
1159
+ //checks for >2 brackets {{{1}}}
1160
+ errorMessage = formatMessage(messages.useTwoBracketsOnly);
1161
+ } else {
1162
+ //checks if vars are added sequentially like, Hi {{1}}, offer for you {{2}} today {{3}}
1163
+ const checkSequence = [...validVarSet].filter(
1164
+ (validVar, index) => `{{${index + 1}}}` !== validVar
1165
+ );
1166
+ if (checkSequence?.length > 0) {
1167
+ errorMessage = formatMessage(messages.sequenceVars, { one: "{{1}}" });
1168
+ } else {
1169
+ if (type === MESSAGE_TEXT) setAddedVarCount(validVarSet?.length || 0);
920
1170
  }
921
1171
  }
922
1172
  }
@@ -965,13 +1215,23 @@ export const Whatsapp = (props) => {
965
1215
  };
966
1216
  });
967
1217
 
1218
+ const getQuickReplyData = () =>
1219
+ quickReplyData.map((quickReply) => {
1220
+ const { index, text, type } = quickReply;
1221
+ return {
1222
+ index,
1223
+ text,
1224
+ type,
1225
+ };
1226
+ });
1227
+
968
1228
  const createPayload = () => {
969
1229
  let mediaParams = {};
970
1230
  const { whatsappVideoSrc = '', whatsappVideoPreviewImg = '' } = whatsappVideoSrcAndPreview;
971
1231
  switch (templateMediaType) {
972
1232
  case WHATSAPP_MEDIA_TYPES.IMAGE:
973
1233
  mediaParams = {
974
- imageUrl: getCdnUrl({url: whatsappImageSrc, channelName: WHATSAPP }),
1234
+ imageUrl: getCdnUrl({ url: whatsappImageSrc, channelName: WHATSAPP }),
975
1235
  karixFileHandle,
976
1236
  };
977
1237
  break;
@@ -992,7 +1252,7 @@ export const Whatsapp = (props) => {
992
1252
  default:
993
1253
  break;
994
1254
  }
995
- return ({
1255
+ return {
996
1256
  name: templateName,
997
1257
  versions: {
998
1258
  base: {
@@ -1012,16 +1272,33 @@ export const Whatsapp = (props) => {
1012
1272
  mediaType: templateMediaType,
1013
1273
  ...mediaParams,
1014
1274
  varMapped: !isFullMode ? varMap : {},
1015
- templateEditor: !isFullMode && tempMsgArray.join(''),
1275
+ templateEditor: !isFullMode && tempMsgArray.join(""),
1016
1276
  accountId,
1017
1277
  accessToken,
1018
1278
  hostName: host,
1279
+ ...(isBtnTypeQuickReply && {
1280
+ buttonType,
1281
+ buttons: getQuickReplyData(),
1282
+ }),
1283
+ whatsappMedia: {
1284
+ ...(isMediaTypeText && isHostIsNotTwilio && {
1285
+ header: isEditFlow && !isFullMode ? updatedHeaderData.join("") : templateHeader,
1286
+ headerVarMapped: !isFullMode ? headerVarMappedData : {},
1287
+ headerTemplate: !isFullMode && tempHeaderData.join(""),
1288
+ }),
1289
+ ...(isHostIsNotTwilio && {
1290
+ footer: templateFooter || ""
1291
+ }),
1292
+ },
1293
+ ...(isEditFlow && !isFullMode && {
1294
+ isPreviewUrl
1295
+ })
1019
1296
  },
1020
1297
  },
1021
1298
  },
1022
1299
  },
1023
1300
  type: WHATSAPP,
1024
- });
1301
+ };
1025
1302
  };
1026
1303
 
1027
1304
  const actionCallback = ({ errorMessage }) => {
@@ -1087,6 +1364,9 @@ export const Whatsapp = (props) => {
1087
1364
  if (!isMediaTypeText && host === HOST_KARIX && karixFileHandle === '') {
1088
1365
  return true;
1089
1366
  }
1367
+ if (templateHeaderError || templateFooterError) {
1368
+ return true;
1369
+ }
1090
1370
  //cta
1091
1371
  if (isBtnTypeCta) {
1092
1372
  if (ctaData.length === 1 && ctaData[0].isSaved) {
@@ -1103,6 +1383,10 @@ export const Whatsapp = (props) => {
1103
1383
  //if button type is cta and there are no buttons saved
1104
1384
  return true;
1105
1385
  }
1386
+
1387
+ if (isBtnTypeQuickReply) {
1388
+ return !quickReplyData.every((quickReply) => quickReply?.isSaved === true);
1389
+ }
1106
1390
  return false;
1107
1391
  };
1108
1392
 
@@ -1135,9 +1419,7 @@ export const Whatsapp = (props) => {
1135
1419
  <CapHeading type="h4">
1136
1420
  {formatMessage(globalMessages.templateNameLabel)}
1137
1421
  <CapTooltipWithInfo
1138
- infoIconProps={{
1139
- style: { marginLeft: CAP_SPACE_04 },
1140
- }}
1422
+ className="whatsapp-text-field_spacing"
1141
1423
  autoAdjustOverflow
1142
1424
  title={<FormattedMessage {...messages.templateNameTooltip} />}
1143
1425
  />
@@ -1154,22 +1436,24 @@ export const Whatsapp = (props) => {
1154
1436
  onChange={onTemplateNameChange}
1155
1437
  errorMessage={templateNameError}
1156
1438
  placeholder={formatMessage(globalMessages.templateNamePlaceholder)}
1157
- defaultValue={templateName || ''}
1158
- value={templateName || ''}
1439
+ defaultValue={templateName || ""}
1440
+ value={templateName || ""}
1159
1441
  size="default"
1160
1442
  />
1161
1443
  {/* template category */}
1162
- {renderLabel('templateCategoryLabel')}
1444
+ {renderLabel("templateCategoryLabel")}
1163
1445
  <CapSelect
1164
1446
  id="select-whatsapp-category"
1165
1447
  options={
1166
- host === HOST_TWILIO ? twilioCategoryOptions : karixGupshupCategoryOptions
1448
+ host === HOST_TWILIO
1449
+ ? twilioCategoryOptions
1450
+ : karixGupshupCategoryOptions
1167
1451
  }
1168
1452
  onChange={onTemplateCategoryChange}
1169
1453
  value={templateCategory}
1170
1454
  />
1171
1455
  {/* template language */}
1172
- {renderLabel('messageLanguageLabel')}
1456
+ {renderLabel("messageLanguageLabel")}
1173
1457
  <CapSelect
1174
1458
  id="select-whatsapp-language"
1175
1459
  options={LANGUAGE_OPTIONS || []}
@@ -1179,24 +1463,77 @@ export const Whatsapp = (props) => {
1179
1463
  {/* template media type */}
1180
1464
  {renderMediaSection()}
1181
1465
  {renderMediaComponent()}
1466
+ {/* this section is for header section in create mode */}
1467
+ {isMediaTypeText && isHostIsNotTwilio && (
1468
+ <>
1469
+ <CapHeader
1470
+ title={
1471
+ <CapHeading type="h4" className="whatsapp-create-mode-heading">
1472
+ {formatMessage(messages.templateHeaderLabel)}
1473
+ <CapTooltipWithInfo
1474
+ placement="right"
1475
+ className="whatsapp-text-field_spacing"
1476
+ autoAdjustOverflow
1477
+ title={
1478
+ <FormattedMessage {...messages.templateHeaderTooltip} />
1479
+ }
1480
+ />
1481
+ <CapHeading className="whatsapp-optional-label1 align-item-center">
1482
+ {formatMessage(messages.optional)}
1483
+ </CapHeading>
1484
+ </CapHeading>
1485
+ }
1486
+ suffix={
1487
+ <CapButton
1488
+ type="flat"
1489
+ isAddBtn
1490
+ onClick={onHeaderAddVar}
1491
+ disabled={
1492
+ ((templateHeader.match(headerValidVarRegex) || []).length >
1493
+ 0 ||
1494
+ templateHeaderError) &&
1495
+ templateHeader
1496
+ }
1497
+ >
1498
+ {formatMessage(messages.addVar)}
1499
+ </CapButton>
1500
+ }
1501
+ />
1502
+ <CapRow className="whatsapp-create-template-message-input whatsapp-create-template-header-input">
1503
+ <TextArea
1504
+ id="whatsapp-create-template-message-input"
1505
+ autosize={{ minRows: 1, maxRows: 5 }}
1506
+ placeholder={formatMessage(messages.templateMessagePlaceholder)}
1507
+ onChange={(e) => onTemplateValueChange(e, HEADER_TEXT)}
1508
+ errorMessage={
1509
+ templateHeaderError && (
1510
+ <CapError className="whatsapp-template-message-error">
1511
+ {templateHeaderError}
1512
+ </CapError>
1513
+ )
1514
+ }
1515
+ value={templateHeader || ""}
1516
+ />
1517
+ </CapRow>
1518
+ {renderMessageLength(HEADER_TEXT)}
1519
+ </>
1520
+ )}
1182
1521
  {/* template message create flow */}
1183
1522
  <CapHeader
1184
- className={`${isMediaTypeImage ? 'whatsapp-heading-spacing' : ''}`}
1523
+ className={`${isMediaTypeImage ? "whatsapp-heading-spacing" : ""}`}
1185
1524
  title={
1186
1525
  <CapHeading type="h4" className="whatsapp-render-heading">
1187
1526
  {formatMessage(messages.templateMessageLabel)}
1188
1527
  <CapTooltipWithInfo
1189
1528
  placement="right"
1190
- infoIconProps={{
1191
- style: { marginLeft: CAP_SPACE_04 },
1192
- }}
1529
+ className="whatsapp-text-field_spacing"
1193
1530
  autoAdjustOverflow
1194
1531
  title={
1195
1532
  <FormattedMessage
1196
1533
  {...messages.templateMessageTooltip}
1197
1534
  values={{
1198
1535
  br: <br />,
1199
- var: '{{1}}',
1536
+ var: "{{1}}",
1200
1537
  }}
1201
1538
  />
1202
1539
  }
@@ -1207,7 +1544,7 @@ export const Whatsapp = (props) => {
1207
1544
  <CapButton
1208
1545
  type="flat"
1209
1546
  isAddBtn
1210
- onClick={onAddVar}
1547
+ onClick={onMessageAddVar}
1211
1548
  disabled={
1212
1549
  (addedVarCount >= 19 || templateMessageError) && templateMessage
1213
1550
  }
@@ -1221,7 +1558,7 @@ export const Whatsapp = (props) => {
1221
1558
  id="whatsapp-create-template-message-input"
1222
1559
  autosize={{ minRows: 3, maxRows: 5 }}
1223
1560
  placeholder={formatMessage(messages.templateMessagePlaceholder)}
1224
- onChange={onTemplateMessageChange}
1561
+ onChange={(e) => onTemplateValueChange(e, MESSAGE_TEXT)}
1225
1562
  errorMessage={
1226
1563
  templateMessageError && (
1227
1564
  <CapError className="whatsapp-template-message-error">
@@ -1229,11 +1566,52 @@ export const Whatsapp = (props) => {
1229
1566
  </CapError>
1230
1567
  )
1231
1568
  }
1232
- value={templateMessage || ''}
1569
+ value={templateMessage || ""}
1233
1570
  />
1234
1571
  {renderUnsubscribeText()}
1235
1572
  </CapRow>
1236
- {renderMessageLength()}
1573
+ {renderMessageLength(MESSAGE_TEXT)}
1574
+ {/* this section if for footer in create mode */}
1575
+ {isHostIsNotTwilio && (
1576
+ <>
1577
+ <CapHeader
1578
+ className={`${isMediaTypeImage ? "whatsapp-heading-spacing" : ""}`}
1579
+ title={
1580
+ <CapHeading type="h4" className="whatsapp-create-mode-heading">
1581
+ {formatMessage(messages.templateFooterLabel)}
1582
+ <CapTooltipWithInfo
1583
+ placement="right"
1584
+ className="whatsapp-text-field_spacing"
1585
+ autoAdjustOverflow
1586
+ title={
1587
+ <FormattedMessage {...messages.templateFooterTooltip} />
1588
+ }
1589
+ />
1590
+ <CapHeading className="whatsapp-optional-label1 align-item-center">
1591
+ {formatMessage(messages.optional)}
1592
+ </CapHeading>
1593
+ </CapHeading>
1594
+ }
1595
+ />
1596
+ <CapRow className="whatsapp-create-template-message-input whatsapp-create-template-header-input">
1597
+ <TextArea
1598
+ id="whatsapp-create-template-message-input"
1599
+ autosize={{ minRows: 1, maxRows: 5 }}
1600
+ placeholder={formatMessage(messages.templateMessagePlaceholder)}
1601
+ onChange={onTemplateFooterChanges}
1602
+ errorMessage={
1603
+ templateFooterError && (
1604
+ <CapError className="whatsapp-template-message-error">
1605
+ {templateFooterError}
1606
+ </CapError>
1607
+ )
1608
+ }
1609
+ value={templateFooter || ""}
1610
+ />
1611
+ </CapRow>
1612
+ {renderMessageLength(FOOTER_TEXT)}
1613
+ </>
1614
+ )}
1237
1615
  {renderButtonsSection()}
1238
1616
  </>
1239
1617
  );
@@ -1317,39 +1695,55 @@ export const Whatsapp = (props) => {
1317
1695
  };
1318
1696
 
1319
1697
  // on change event of Text Area
1320
- const textAreaValueChange = ({ target: { value, id } }) => {
1321
- const numId = Number(id.slice(id.indexOf('_') + 1));
1322
- const arr = [...updatedSmsEditor];
1323
-
1698
+ const textAreaValueChange = ({ target: { value, id } }, type) => {
1699
+ const numId = Number(id.slice(id.indexOf("_") + 1));
1324
1700
  //assign entered value to varMap
1325
- varMap[id] = value;
1326
- //based on entered value update updatedSmsEditor
1327
- if (value === '') {
1328
- arr[numId] = id.slice(0, id.indexOf('_'));
1701
+ if (type === HEADER_TEXT) {
1702
+ const arr = [...updatedHeaderData];
1703
+ setHeaderVarMappedData((prevState) => ({
1704
+ ...prevState,
1705
+ [id]: value,
1706
+ }));
1707
+ if (value === "") {
1708
+ arr[numId] = id.slice(0, id.indexOf("_"));
1709
+ } else {
1710
+ arr[numId] = value;
1711
+ }
1712
+ setUpdatedHeaderData(arr);
1329
1713
  } else {
1330
- arr[numId] = value;
1714
+ const arr = [...updatedSmsEditor];
1715
+ varMap[id] = value;
1716
+ //based on entered value update updatedSmsEditor
1717
+ if (value === "") {
1718
+ arr[numId] = id.slice(0, id.indexOf("_"));
1719
+ } else {
1720
+ arr[numId] = value;
1721
+ }
1722
+ setUpdatedSmsEditor(arr);
1331
1723
  }
1332
- setUpdatedSmsEditor(arr);
1333
1724
  };
1334
1725
 
1335
- const textAreaValue = (idValue) => {
1336
- if (idValue >= 0 && updatedSmsEditor) {
1337
- const value = updatedSmsEditor[idValue];
1726
+ const textAreaValue = (idValue, type) => {
1727
+ if (idValue >= 0) {
1728
+ const value =
1729
+ type === HEADER_TEXT
1730
+ ? updatedHeaderData[idValue]
1731
+ : updatedSmsEditor[idValue];
1338
1732
  //if value is there and it is not a variable return it
1339
- if (value && (value.match(validVarRegex) || []).length === 0) {
1733
+ if (value && (value.match(type === HEADER_TEXT ? headerValidVarRegex : validVarRegex) || []).length === 0) {
1340
1734
  return value;
1341
1735
  }
1342
1736
  }
1343
- return '';
1737
+ return "";
1344
1738
  };
1345
1739
 
1346
- const renderedEditMessage = () => {
1740
+ const renderedEditMessage = (messageData, type) => {
1347
1741
  const renderArray = [];
1348
- if (tempMsgArray?.length !== 0) {
1742
+ if (messageData?.length !== 0) {
1349
1743
  let varCount = 0;
1350
- tempMsgArray.forEach((elem, index) => {
1744
+ messageData.forEach((elem, index) => {
1351
1745
  // if var return textarea else return text
1352
- if (elem.match(validVarRegex)?.length > 0) {
1746
+ if (elem.match(type === HEADER_TEXT ? headerValidVarRegex : validVarRegex)?.length > 0) {
1353
1747
  varCount += 1;
1354
1748
  renderArray.push(
1355
1749
  <TextArea
@@ -1359,11 +1753,11 @@ export const Whatsapp = (props) => {
1359
1753
  value: `{{${varCount}}}`,
1360
1754
  })}
1361
1755
  autosize={{ minRows: 1, maxRows: 3 }}
1362
- onChange={textAreaValueChange}
1363
- value={textAreaValue(index)}
1364
- onFocus={setTextAreaId}
1756
+ onChange={(e) => textAreaValueChange(e, type)}
1757
+ value={textAreaValue(index, type)}
1758
+ onFocus={(e) => setTextAreaId(e, type)}
1365
1759
  disabled={templateStatus !== WHATSAPP_STATUSES.approved}
1366
- />,
1760
+ />
1367
1761
  );
1368
1762
  } else {
1369
1763
  renderArray.push(
@@ -1373,19 +1767,21 @@ export const Whatsapp = (props) => {
1373
1767
  className="whatsapp-edit-template-message-heading"
1374
1768
  >
1375
1769
  {elem}
1376
- </CapHeading>,
1770
+ </CapHeading>
1377
1771
  );
1378
1772
  }
1379
1773
  });
1380
1774
  }
1381
- renderArray.push(renderUnsubscribeText());
1775
+ if (type !== HEADER_TEXT) {
1776
+ renderArray.push(renderUnsubscribeText());
1777
+ }
1382
1778
  return renderArray;
1383
1779
  };
1384
1780
 
1385
1781
  const disabledEditTooltipRender = () => {
1386
1782
  switch (templateStatus) {
1387
1783
  case WHATSAPP_STATUSES.approved:
1388
- return '';
1784
+ return "";
1389
1785
  case WHATSAPP_STATUSES.rejected:
1390
1786
  return formatMessage(messages.disabledEditTooltip, {
1391
1787
  status: templateStatus,
@@ -1397,9 +1793,10 @@ export const Whatsapp = (props) => {
1397
1793
  }
1398
1794
  };
1399
1795
 
1400
- const tagValidationErrorMessage = () => {
1401
- const { unsupportedTags = [], isBraceError} = tagValidationResponse;
1402
- let tagError = '';
1796
+ const tagValidationErrorMessage = (type) => {
1797
+ const { unsupportedTags = [], isBraceError } =
1798
+ type === HEADER_TEXT ? headerTagValidationResponse : tagValidationResponse;
1799
+ let tagError = "";
1403
1800
  if (unsupportedTags.length > 0) {
1404
1801
  tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
1405
1802
  unsupportedTags,
@@ -1420,9 +1817,53 @@ export const Whatsapp = (props) => {
1420
1817
  />
1421
1818
  )}
1422
1819
  {/* template media type */}
1423
- {renderLabel('mediaLabel')}
1820
+ {renderLabel("mediaLabel")}
1424
1821
  <CapLabel type="label15">{capitalizeString(templateMediaType)}</CapLabel>
1425
1822
  {renderMediaComponent()}
1823
+ {/* this section is for render header section */}
1824
+ {(templateHeader && isMediaTypeText && isHostIsNotTwilio) && (
1825
+ <>
1826
+ <CapRow className="whatsapp-render-heading">
1827
+ <CapHeader
1828
+ title={
1829
+ <CapHeading type="h4">
1830
+ {formatMessage(messages.templateHeaderLabel)}
1831
+ </CapHeading>
1832
+ }
1833
+ suffix={
1834
+ templateStatus === WHATSAPP_STATUSES.approved && (
1835
+ <TagList
1836
+ label={formatMessage(globalMessages.addLabels)}
1837
+ onTagSelect={onHeaderTagSelect}
1838
+ location={location}
1839
+ tags={tags || []}
1840
+ onContextChange={handleOnTagsContextChange}
1841
+ injectedTags={injectedTags || {}}
1842
+ selectedOfferDetails={selectedOfferDetails}
1843
+ />
1844
+ )
1845
+ }
1846
+ />
1847
+ </CapRow>
1848
+ <CapTooltip placement="bottom" title={disabledEditTooltipRender()}>
1849
+ <CapRow
1850
+ className={`whatsapp-edit-template-message-input ${
1851
+ templateStatus !== WHATSAPP_STATUSES.approved &&
1852
+ "whatsapp-edit-disabled"
1853
+ }`}
1854
+ >
1855
+ {renderedEditMessage(tempHeaderData, HEADER_TEXT)}
1856
+ </CapRow>
1857
+ </CapTooltip>
1858
+ {renderMessageLength(HEADER_TEXT)}
1859
+ {isHeaderTagValidationError && tagValidationErrorMessage(HEADER_TEXT)}
1860
+ {computeTextLength(HEADER_TEXT) > TEMPLATE_HEADER_MAX_LENGTH && (
1861
+ <CapError>
1862
+ {formatMessage(messages.templateHeaderLengthError)}
1863
+ </CapError>
1864
+ )}
1865
+ </>
1866
+ )}
1426
1867
  <CapRow className="whatsapp-render-heading">
1427
1868
  <CapHeader
1428
1869
  title={
@@ -1434,7 +1875,7 @@ export const Whatsapp = (props) => {
1434
1875
  templateStatus === WHATSAPP_STATUSES.approved && (
1435
1876
  <TagList
1436
1877
  label={formatMessage(globalMessages.addLabels)}
1437
- onTagSelect={onTagSelect}
1878
+ onTagSelect={onMessageTagSelect}
1438
1879
  location={location}
1439
1880
  tags={tags || []}
1440
1881
  onContextChange={handleOnTagsContextChange}
@@ -1452,29 +1893,68 @@ export const Whatsapp = (props) => {
1452
1893
  'whatsapp-edit-disabled'
1453
1894
  }`}
1454
1895
  >
1455
- {renderedEditMessage()}
1896
+ {renderedEditMessage(tempMsgArray)}
1456
1897
  </CapRow>
1457
1898
  </CapTooltip>
1458
1899
 
1459
- {renderMessageLength()}
1460
- {isTagValidationError && tagValidationErrorMessage()}
1461
- {computeTextLength() > TEMPLATE_MESSAGE_MAX_LENGTH ? (
1900
+ {renderMessageLength(MESSAGE_TEXT)}
1901
+ {isTagValidationError && tagValidationErrorMessage(MESSAGE_TEXT)}
1902
+ {computeTextLength(MESSAGE_TEXT) > TEMPLATE_MESSAGE_MAX_LENGTH ? (
1462
1903
  <CapError>
1463
1904
  {formatMessage(messages.templateMessageLengthError)}
1464
1905
  </CapError>
1465
1906
  ) : (
1466
- ''
1907
+ ""
1908
+ )}
1909
+ <CapRow>
1910
+ <CapCheckbox
1911
+ className={`whatsapp-unsubscribe-checkbox ${'whatsapp-create-unsubscribe-checkbox'}`}
1912
+ onChange={previewUrlHandler}
1913
+ checked={isPreviewUrl}
1914
+ disabled={!isMediaTypeText}
1915
+ autoFocus={true}
1916
+ >
1917
+ <span className="whatsapp-render-url-preview-textt">
1918
+ {formatMessage(messages.showUrlPreview)}
1919
+ </span>
1920
+ </CapCheckbox>
1921
+ </CapRow>
1922
+ {templateFooter && isHostIsNotTwilio && (
1923
+ <>
1924
+ <CapHeader
1925
+ className={`${isMediaTypeImage ? "whatsapp-heading-spacing" : ""}`}
1926
+ title={
1927
+ <CapHeading type="h4" className="whatsapp-render-heading">
1928
+ {formatMessage(messages.templateFooterLabel)}
1929
+ </CapHeading>
1930
+ }
1931
+ />
1932
+ <CapRow className="whatsapp-footer-edit-container">
1933
+ <CapHeading type="h4" className="whatsapp-footer-edit-text">
1934
+ {templateFooter}
1935
+ </CapHeading>
1936
+ </CapRow>
1937
+ {renderMessageLength(FOOTER_TEXT)}
1938
+ </>
1467
1939
  )}
1468
1940
  {/* button section view in edit mode*/}
1469
1941
  <CapRow>
1470
- <CapHeading type="h4" className="whatsapp-render-heading">
1471
- {formatMessage(messages.btnLabel)}
1472
- </CapHeading>
1473
- <CapLabel type="label15">
1474
- {isBtnTypeCta
1475
- ? formatMessage(messages.btnTypeCTA)
1476
- : formatMessage(messages.btnTypeNone)}
1477
- </CapLabel>
1942
+ {isBtnTypeQuickReply ? (
1943
+ <CapHeading type="h4" className="whatsapp-render-heading">
1944
+ {formatMessage(messages.quickReplyButtons)}
1945
+ </CapHeading>
1946
+ ) : (
1947
+ <>
1948
+ <CapHeading type="h4" className="whatsapp-render-heading">
1949
+ {formatMessage(messages.btnLabel)}
1950
+ </CapHeading>
1951
+ <CapLabel type="label15">
1952
+ {isBtnTypeCta
1953
+ ? formatMessage(messages.btnTypeCTA)
1954
+ : formatMessage(messages.btnTypeNone)}
1955
+ </CapLabel>
1956
+ </>
1957
+ )}
1478
1958
  {isBtnTypeCta && (
1479
1959
  <CapWhatsappCTA
1480
1960
  ctaData={ctaData}
@@ -1487,6 +1967,14 @@ export const Whatsapp = (props) => {
1487
1967
  selectedOfferDetails={selectedOfferDetails}
1488
1968
  />
1489
1969
  )}
1970
+ {isBtnTypeQuickReply && (
1971
+ <CapWhatsappQuickReply
1972
+ quickReplyData={quickReplyData}
1973
+ isEditFlow={isEditFlow}
1974
+ renderMessageLength={renderMessageLength}
1975
+ setQuickReplyData={setQuickReplyData}
1976
+ />
1977
+ )}
1490
1978
  </CapRow>
1491
1979
  </>
1492
1980
  );
@@ -1494,10 +1982,11 @@ export const Whatsapp = (props) => {
1494
1982
 
1495
1983
  //used by create and edit
1496
1984
  const getPreviewSection = () => {
1985
+ const { metaTagsDetails = {} } = editData || {};
1497
1986
  const templateMsg = (
1498
1987
  <>
1499
1988
  <CapLabel type="label5">
1500
- {isEditFlow ? updatedSmsEditor.join('') : templateMessage}
1989
+ {isEditFlow ? updatedSmsEditor.join("") : templateMessage}
1501
1990
  </CapLabel>
1502
1991
  {unsubscribeRequired && (
1503
1992
  <CapLabel type="label5">
@@ -1506,13 +1995,24 @@ export const Whatsapp = (props) => {
1506
1995
  )}
1507
1996
  </>
1508
1997
  );
1998
+ const templateHeaderPreview = (
1999
+ <CapLabel className="whatsapp-template-header-preview">
2000
+ {isEditFlow ? updatedHeaderData.join("") : templateHeader}
2001
+ </CapLabel>
2002
+ );
2003
+ const templateFooterPreview = (
2004
+ <CapLabel className="whatsapp-template-footer-preview">
2005
+ {templateFooter}
2006
+ </CapLabel>
2007
+ );
1509
2008
  const mediaPreview = {};
1510
2009
  switch (templateMediaType) {
1511
2010
  case WHATSAPP_MEDIA_TYPES.IMAGE:
1512
2011
  mediaPreview.whatsappImageSrc = whatsappImageSrc;
1513
2012
  break;
1514
2013
  case WHATSAPP_MEDIA_TYPES.VIDEO:
1515
- mediaPreview.whatsappVideoPreviewImg = whatsappVideoSrcAndPreview?.whatsappVideoPreviewImg;
2014
+ mediaPreview.whatsappVideoPreviewImg =
2015
+ whatsappVideoSrcAndPreview?.whatsappVideoPreviewImg;
1516
2016
  break;
1517
2017
  case WHATSAPP_MEDIA_TYPES.DOCUMENT:
1518
2018
  mediaPreview.docPreview = docPreview;
@@ -1526,9 +2026,18 @@ export const Whatsapp = (props) => {
1526
2026
  content={{
1527
2027
  ...mediaPreview,
1528
2028
  templateMsg,
2029
+ templateHeaderPreview,
2030
+ templateFooterPreview,
1529
2031
  ...(isBtnTypeCta && {
1530
2032
  ctaData,
1531
2033
  }),
2034
+ ...(isBtnTypeQuickReply && {
2035
+ quickReplyData,
2036
+ }),
2037
+ ...(isMediaTypeText && isPreviewUrl && {
2038
+ isPreviewUrl,
2039
+ metaTagsDetails,
2040
+ }),
1532
2041
  }}
1533
2042
  whatsappContentLen={computeTextLength()}
1534
2043
  whatsappAccountName={accountName}
@@ -1538,12 +2047,15 @@ export const Whatsapp = (props) => {
1538
2047
 
1539
2048
  const isEditDoneDisabled = () =>
1540
2049
  isTagValidationError ||
1541
- Object.values(varMap).some((inputValue) => inputValue === '') ||
1542
- computeTextLength() > TEMPLATE_MESSAGE_MAX_LENGTH ||
1543
- (isBtnTypeCta && ctaData.some((btn) => btn?.url?.includes('{{1}}'))) ||
1544
- (isMediaTypeImage && whatsappImageSrc === '') ||
1545
- (isMediaTypeVideo && whatsappVideoSrcAndPreview?.whatsappVideoSrc === '') ||
1546
- (isMediaTypeDoc && whatsappDocSource === '');
2050
+ isHeaderTagValidationError ||
2051
+ Object.values(varMap).some((inputValue) => inputValue === "") ||
2052
+ Object.values(headerVarMappedData).some((inputValue) => inputValue === "") ||
2053
+ computeTextLength(MESSAGE_TEXT) > TEMPLATE_MESSAGE_MAX_LENGTH ||
2054
+ computeTextLength(HEADER_TEXT) > TEMPLATE_HEADER_MAX_LENGTH ||
2055
+ (isBtnTypeCta && ctaData.some((btn) => btn?.url?.includes("{{1}}"))) ||
2056
+ (isMediaTypeImage && whatsappImageSrc === "") ||
2057
+ (isMediaTypeVideo && whatsappVideoSrcAndPreview?.whatsappVideoSrc === "") ||
2058
+ (isMediaTypeDoc && whatsappDocSource === "");
1547
2059
 
1548
2060
  return (
1549
2061
  <CapSpin spinning={spin}>
@@ -1563,9 +2075,9 @@ export const Whatsapp = (props) => {
1563
2075
  title={
1564
2076
  isDisableDone()
1565
2077
  ? formatMessage(messages.btnDisabledTooltip)
1566
- : ''
2078
+ : ""
1567
2079
  }
1568
- placement={'right'}
2080
+ placement={"right"}
1569
2081
  >
1570
2082
  <div className="button-disabled-tooltip-wrapper">
1571
2083
  <CapButton
@@ -1591,9 +2103,9 @@ export const Whatsapp = (props) => {
1591
2103
  title={
1592
2104
  isEditDoneDisabled()
1593
2105
  ? formatMessage(messages.btnDisabledTooltip)
1594
- : ''
2106
+ : ""
1595
2107
  }
1596
- placement={'right'}
2108
+ placement={"right"}
1597
2109
  >
1598
2110
  <div className="button-disabled-tooltip-wrapper">
1599
2111
  <CapButton