@capillarytech/creatives-library 8.0.186 → 8.0.188

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/config/app.js CHANGED
@@ -21,7 +21,6 @@ const config = {
21
21
  },
22
22
  development: {
23
23
  api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/creatives',
24
- // api_endpoint: 'http://localhost:2022/arya/api/v1/creatives',
25
24
  campaigns_api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/campaigns',
26
25
  campaigns_api_org_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/org/campaign',
27
26
  auth_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/auth',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.186",
4
+ "version": "8.0.188",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/services/api.js CHANGED
@@ -264,7 +264,6 @@ export const getUserData = () => {
264
264
 
265
265
  export const createTemplate = ({template}) => {
266
266
  const url = `${API_ENDPOINT}/templates/SMS`;
267
- console.log("creating template",template);
268
267
  return request(url, getAPICallObject('POST', template));
269
268
  };
270
269
 
@@ -83,7 +83,9 @@ export const CapActionButton = (props) => {
83
83
  const onButtonTextChange = ({target}) => {
84
84
  const { value, id } = target;
85
85
  let errorMessage = '';
86
- if (!isValidText(value)) {
86
+ if (value.length > BTN_MAX_LENGTH) {
87
+ errorMessage = formatMessage(messages.ctaButtonTextLengthError);
88
+ } if (!isValidText(value)) {
87
89
  errorMessage = formatMessage(messages.ctaButtonErrorMessage);
88
90
  }
89
91
  setButtonError(errorMessage);
@@ -378,7 +378,6 @@ export function SlideBoxContent(props) {
378
378
  };
379
379
  }
380
380
  case constants.RCS: {
381
- console.log("in slidebox content .js");
382
381
  const template = cloneDeep(templateDataObject);
383
382
  const { description = "", media: { mediaUrl = "" } = {}, title = "", suggestions = [] } = get(template, 'versions.base.content.RCS.rcsContent.cardContent[0]', {});
384
383
  return {
@@ -393,10 +392,7 @@ export function SlideBoxContent(props) {
393
392
  };
394
393
  }
395
394
  default:
396
- {
397
- console.log("in default case");
398
395
  return get(templateDataObject, `versions.base.content`);
399
- }
400
396
  }
401
397
  };
402
398
 
@@ -633,34 +633,7 @@ export class Creatives extends React.Component {
633
633
  channel = constants.RCS,
634
634
  } = templateData || {};
635
635
  const cardContent = (rcsContent.cardContent && rcsContent.cardContent[0]) || {};
636
- const cardVarMapped = cardContent.cardVarMapped || {};
637
- const reverseMapText = (text, cardVarMapped) => {
638
- if (!text || !cardVarMapped || Object.keys(cardVarMapped).length === 0) {
639
- return text;
640
- }
641
-
642
- let reversedText = text;
643
- Object.entries(cardVarMapped).forEach(([key, value]) => {
644
- const cleanValue = value.replace(/^\{\{|\}\}$/g, '');
645
- const valuePattern = new RegExp(`\\{\\{${cleanValue}\\}\\}`, 'g');
646
- reversedText = reversedText.replace(valuePattern, `{{${key}}}`);
647
- });
648
- return reversedText;
649
- };
650
-
651
- const updatedRcsContent = {
652
- ...rcsContent,
653
- cardContent: [
654
- {
655
- ...cardContent,
656
- Status: RCS_STATUSES.approved,
657
- title: reverseMapText(cardContent.title, cardVarMapped),
658
- description: reverseMapText(cardContent.description, cardVarMapped),
659
- cardVarMapped: {},
660
- },
661
- ...(rcsContent.cardContent?.slice(1) || []),
662
- ],
663
- };
636
+ const Status = RCS_STATUSES.approved || '';
664
637
 
665
638
  creativesTemplateData = {
666
639
  type: channel,
@@ -670,7 +643,15 @@ export class Creatives extends React.Component {
670
643
  base: {
671
644
  content: {
672
645
  RCS: {
673
- rcsContent: updatedRcsContent,
646
+ rcsContent: {
647
+ ...rcsContent,
648
+ cardContent: [
649
+ {
650
+ ...cardContent,
651
+ Status,
652
+ },
653
+ ],
654
+ },
674
655
  smsFallBackContent,
675
656
  },
676
657
  },
@@ -1063,7 +1044,6 @@ export class Creatives extends React.Component {
1063
1044
  }
1064
1045
  break;
1065
1046
  case constants.RCS: {
1066
- console.log("in creatives container .js");
1067
1047
  if (template.value) {
1068
1048
  const { name = "", versions = {} } = {
1069
1049
  } = template.value || {};
@@ -1074,14 +1054,12 @@ export class Creatives extends React.Component {
1074
1054
  cardType = "",
1075
1055
  cardSettings = {},
1076
1056
  } = get(versions, 'base.content.RCS.rcsContent',{});
1077
- console.log("versions--->", versions);
1078
1057
  const rcsContent = {
1079
1058
  contentType,
1080
1059
  cardType,
1081
1060
  cardSettings,
1082
1061
  cardContent,
1083
1062
  };
1084
- console.log("rcsContent--->", rcsContent);
1085
1063
  templateData = {
1086
1064
  channel,
1087
1065
  creativeName: name,
@@ -1104,7 +1082,6 @@ export class Creatives extends React.Component {
1104
1082
  default:
1105
1083
  break;
1106
1084
  }
1107
- console.log("templateData--->", templateData);
1108
1085
  return templateData;
1109
1086
  };
1110
1087
 
@@ -298,7 +298,7 @@ export const Rcs = (props) => {
298
298
  // );
299
299
  // }
300
300
  if (type === titletype) {
301
- const error =
301
+ const errorMsg =
302
302
  (unsupportedTagsLengthCheck &&
303
303
  formatMessage(globalMessages.unsupportedTagsValidationError, {
304
304
  unsupportedTags: validationResponse.unsupportedTags,
@@ -306,10 +306,10 @@ export const Rcs = (props) => {
306
306
  (validationResponse.isBraceError &&
307
307
  formatMessage(globalMessages.unbalanacedCurlyBraces)) ||
308
308
  false;
309
-
310
- setTemplateTitleError(error);
309
+ // Only update if changed to prevent flicker
310
+ setTemplateTitleError((prev) => (prev !== errorMsg ? errorMsg : prev));
311
311
  } else if (type === descType) {
312
- const error =
312
+ const errorMsg =
313
313
  (unsupportedTagsLengthCheck &&
314
314
  formatMessage(globalMessages.unsupportedTagsValidationError, {
315
315
  unsupportedTags: validationResponse.unsupportedTags,
@@ -317,18 +317,29 @@ export const Rcs = (props) => {
317
317
  (validationResponse.isBraceError &&
318
318
  formatMessage(globalMessages.unbalanacedCurlyBraces)) ||
319
319
  false;
320
-
321
- setTemplateDescError(error);
320
+ setTemplateDescError((prev) => (prev !== errorMsg ? errorMsg : prev));
322
321
  }
323
322
  };
324
323
 
325
324
  useEffect(() => {
326
- tagValidation(templateTitle, titletype);
327
- }, [templateTitle, tags, injectedTags]);
325
+ const hasInteraction = !isEmpty(cardVarMapped) || Object.values(rcsTextVariables || {}).some(group => Object.values(group || {}).some(v => (v || '').trim() !== ''));
326
+ if (!hasInteraction) {
327
+ setTemplateTitleError(false);
328
+ return;
329
+ }
330
+ const mapped = getMappedDesc(templateTitle, cardVarMapped);
331
+ tagValidation(mapped, titletype);
332
+ }, [templateTitle, tags, injectedTags, cardVarMapped, rcsTextVariables]);
328
333
 
329
334
  useEffect(() => {
330
- tagValidation(templateDesc, descType);
331
- }, [templateDesc, tags, injectedTags]);
335
+ const hasInteraction = !isEmpty(cardVarMapped) || Object.values(rcsTextVariables || {}).some(group => Object.values(group || {}).some(v => (v || '').trim() !== ''));
336
+ if (!hasInteraction) {
337
+ setTemplateDescError(false);
338
+ return;
339
+ }
340
+ const mapped = getMappedDesc(templateDesc, cardVarMapped);
341
+ tagValidation(mapped, descType);
342
+ }, [templateDesc, tags, injectedTags, cardVarMapped, rcsTextVariables]);
332
343
 
333
344
 
334
345
  const RcsLabel = styled.div`
@@ -384,6 +395,33 @@ export const Rcs = (props) => {
384
395
  return updated;
385
396
  });
386
397
  }, [templateTitle]);
398
+
399
+ // Prefill variable inputs from existing mapping on load/edit
400
+ useEffect(() => {
401
+ if (!templateTitle && !templateDesc) return;
402
+ const buildPrefill = (targetString) => {
403
+ const arr = splitTemplateVarString(targetString);
404
+ const pre = {};
405
+ arr.forEach((elem, idx) => {
406
+ if (rcsVarTestRegex.test(elem)) {
407
+ const varName = elem.replace(/^\{\{|\}\}$/g, '');
408
+ const mapped = cardVarMapped[varName] ?? cardVarMapped[elem];
409
+ if (mapped) {
410
+ pre[idx] = /^\{\{[\s\S]*\}\}$/.test(mapped) ? mapped : `{{${mapped}}}`;
411
+ }
412
+ }
413
+ });
414
+ return pre;
415
+ };
416
+ const prefilledTitle = buildPrefill(templateTitle);
417
+ const prefilledDesc = buildPrefill(templateDesc);
418
+ if (Object.keys(prefilledTitle).length === 0 && Object.keys(prefilledDesc).length === 0) return;
419
+ setRcsTextVariables(prev => ({
420
+ ...prev,
421
+ [TITLE_TEXT]: { ...(prev[TITLE_TEXT] || {}), ...prefilledTitle },
422
+ [MESSAGE_TEXT]: { ...(prev[MESSAGE_TEXT] || {}), ...prefilledDesc },
423
+ }));
424
+ }, [templateTitle, templateDesc, cardVarMapped]);
387
425
 
388
426
  useEffect(() => {
389
427
  if(!isEditFlow && isFullMode){
@@ -477,8 +515,13 @@ export const Rcs = (props) => {
477
515
  }
478
516
  setEditFlow(true);
479
517
  setTemplateName(details.name || '');
480
- setTemplateTitle(get(details, 'versions.base.content.RCS.rcsContent.cardContent[0].title', ''));
481
- setTemplateDesc(get(details, 'versions.base.content.RCS.rcsContent.cardContent[0].description', ''));
518
+ const loadedTitle = get(details, 'versions.base.content.RCS.rcsContent.cardContent[0].title', '');
519
+ const loadedDesc = get(details, 'versions.base.content.RCS.rcsContent.cardContent[0].description', '');
520
+ const loadedMap = get(details, 'versions.base.content.RCS.rcsContent.cardContent[0].cardVarMapped', {});
521
+ const normalizedTitle = (!isFullMode && !isEmpty(loadedMap)) ? getUnmappedDesc(loadedTitle, loadedMap) : loadedTitle;
522
+ const normalizedDesc = (!isFullMode && !isEmpty(loadedMap)) ? getUnmappedDesc(loadedDesc, loadedMap) : loadedDesc;
523
+ setTemplateTitle(normalizedTitle);
524
+ setTemplateDesc(normalizedDesc);
482
525
  setSuggestions(get(details, 'versions.base.content.RCS.rcsContent.cardContent[0].suggestions', []));
483
526
  templateStatusHelper(details);
484
527
  const mediaData = get(details, 'versions.base.content.RCS.rcsContent.cardContent[0].media', '');
@@ -556,44 +599,99 @@ export const Rcs = (props) => {
556
599
  };
557
600
 
558
601
  const onTagSelect = (tag) => {
602
+ // Determine target input (index and type). If nothing focused, pick the first available variable slot.
603
+ let targetType = focusedVarType;
604
+ let targetIndex;
605
+ let tokenAtIndex = '';
559
606
  if (!focusedVarId) {
560
- CapNotification.error({
561
- message: formatMessage(messages.noVariableFocused) || "Please select a variable to insert the label.",
562
- });
563
- return;
607
+ // Try description first
608
+ const descArray = splitTemplateVarString(templateDesc);
609
+ let found = false;
610
+ for (let i = 0; i < descArray.length; i += 1) {
611
+ const elem = descArray[i];
612
+ if (rcsVarTestRegex.test(elem)) {
613
+ const currentVal = (rcsTextVariables?.[MESSAGE_TEXT]?.[i]) || '';
614
+ if (!currentVal) {
615
+ targetType = MESSAGE_TEXT;
616
+ targetIndex = i;
617
+ tokenAtIndex = elem;
618
+ found = true;
619
+ break;
620
+ }
621
+ }
622
+ }
623
+ // If no empty slot in description, try title
624
+ if (!found) {
625
+ const titleArray = splitTemplateVarString(templateTitle);
626
+ for (let i = 0; i < titleArray.length; i += 1) {
627
+ const elem = titleArray[i];
628
+ if (rcsVarTestRegex.test(elem)) {
629
+ const currentVal = (rcsTextVariables?.[TITLE_TEXT]?.[i]) || '';
630
+ if (!currentVal) {
631
+ targetType = TITLE_TEXT;
632
+ targetIndex = i;
633
+ tokenAtIndex = elem;
634
+ found = true;
635
+ break;
636
+ }
637
+ }
638
+ }
639
+ }
640
+ if (!targetType || targetIndex === undefined) {
641
+ CapNotification.error({
642
+ message: formatMessage(messages.noVariableFocused) || "Please select a variable to insert the label.",
643
+ });
644
+ return;
645
+ }
646
+ } else {
647
+ targetIndex = parseInt(focusedVarId.split('_').pop(), 10);
648
+ const arr = splitTemplateVarString(targetType === TITLE_TEXT ? templateTitle : templateDesc);
649
+ tokenAtIndex = arr[targetIndex] || '';
564
650
  }
565
- const index = parseInt(focusedVarId.split("_").pop(), 10);
566
- console.log('tags---> focusedVarType', focusedVarType);
567
- console.log('tags---> index', index);
568
- console.log('tags---> tag', tag);
569
- console.log('tags---> rcsTextVariables', rcsTextVariables);
570
- setRcsTextVariables((prev) => {
571
- const newState = {
572
- ...prev,
573
- [focusedVarType]: {
574
- ...(prev[focusedVarType] || {}),
575
- [index]: `{{${tag}}}`,
576
- },
577
- };
578
- return newState;
579
- });
651
+
652
+ // Update the visual input field
653
+ setRcsTextVariables((prev) => ({
654
+ ...prev,
655
+ [targetType]: {
656
+ ...(prev[targetType] || {}),
657
+ [targetIndex]: `{{${tag}}}`,
658
+ },
659
+ }));
660
+
580
661
  // Store the variable-to-tag mapping
581
- setCardVarMapped(prev => {
582
- console.log("tags---> ------------- setCardVarMapped START -------------");
583
- console.log("tags---> prev:", prev);
584
- console.log("tags---> focusedVarId:", focusedVarId);
585
- console.log("tags---> tag:", tag);
586
- console.log("tags---> isFullMode:", isFullMode);
587
-
588
- const variableName = focusedVarId.replace(/^\{\{|\}\}_\d+$/g, '');
589
- const newCardVarMapped = {
590
- ...prev,
591
- // In non-full mode store the mapped tag with braces: {{tagName}}
592
- [variableName]: isFullMode ? tag : `{{${tag}}}`,
662
+ setCardVarMapped((prev) => {
663
+ // Determine stable variable name
664
+ const defaultVarName = (focusedVarId ? focusedVarId.split('_')[0] : tokenAtIndex).replace(/^\{\{|\}\}$/g, '');
665
+ const tokenName = tokenAtIndex.replace(/^\{\{|\}\}$/g, '');
666
+
667
+ // If this template had been saved with resolved tags, infer original key via inverse lookup
668
+ let variableName = defaultVarName;
669
+ if (prev && Object.keys(prev).length > 0) {
670
+ const entry = Object.entries(prev).find(([, v]) => {
671
+ const val = v || '';
672
+ const braced = /^\{\{[\s\S]*\}\}$/.test(val) ? val : `{{${val}}}`;
673
+ return braced === `{{${tokenName}}}`;
674
+ });
675
+ if (entry) {
676
+ const [keyFromMap] = entry;
677
+ variableName = keyFromMap;
678
+ }
679
+ }
680
+
681
+ const mappedValue = isFullMode ? tag : `{{${tag}}}`;
682
+
683
+ // Clean up any accidental keys equal to the tag token name (e.g., 'gt') to avoid duplicates
684
+ const cleaned = { ...prev };
685
+ if (tokenName && Object.prototype.hasOwnProperty.call(cleaned, tokenName)) {
686
+ delete cleaned[tokenName];
687
+ }
688
+
689
+ return {
690
+ ...cleaned,
691
+ [variableName]: mappedValue,
593
692
  };
594
- return newCardVarMapped;
595
- });
596
-
693
+ });
694
+
597
695
  };
598
696
 
599
697
  const onTagSelectFallback = (data) => {
@@ -907,15 +1005,32 @@ const splitTemplateVarString = (str) => {
907
1005
  });
908
1006
 
909
1007
  if (type === TITLE_TEXT) {
910
- const error = templateHeaderErrorHandler(reconstructed);
911
- setTemplateTitleError(error);
1008
+ // Only run tag-based validation to avoid flicker from multiple setters
1009
+ tagValidation(reconstructed, titletype);
912
1010
  } else {
913
- const error = templateDescErrorHandler(reconstructed);
914
- setTemplateDescError(error);
1011
+ // Only run tag-based validation to avoid flicker from multiple setters
1012
+ tagValidation(reconstructed, descType);
915
1013
  }
916
1014
 
917
1015
  return updated;
918
1016
  });
1017
+
1018
+ // Keep mapping in sync with what user types in the variable input
1019
+ const targetStringForMap = type === TITLE_TEXT ? templateTitle : templateDesc;
1020
+ const arrForMap = splitTemplateVarString(targetStringForMap);
1021
+ const token = arrForMap[index] || '';
1022
+ if (rcsVarTestRegex.test(token)) {
1023
+ const variableName = token.replace(/^\{\{|\}\}$/g, '');
1024
+ const normalized = value
1025
+ ? (/^\{\{[\s\S]*\}\}$/.test(value) ? value : `{{${value}}}`)
1026
+ : '';
1027
+ setCardVarMapped(prev => {
1028
+ const next = { ...prev };
1029
+ // Keep the variable key even when empty; store empty string as value
1030
+ next[variableName] = (normalized && normalized.trim() !== '') ? normalized : '';
1031
+ return next;
1032
+ });
1033
+ }
919
1034
  };
920
1035
 
921
1036
  const setTextAreaId = (e, type) => {
@@ -1055,6 +1170,11 @@ const splitTemplateVarString = (str) => {
1055
1170
  />
1056
1171
  )}
1057
1172
  </div>
1173
+ {(isEditFlow || !isFullMode) && templateTitleError && (
1174
+ <CapError className="rcs-template-title-error">
1175
+ {templateTitleError}
1176
+ </CapError>
1177
+ )}
1058
1178
  </>
1059
1179
  )}
1060
1180
 
@@ -1138,6 +1258,11 @@ const splitTemplateVarString = (str) => {
1138
1258
  )
1139
1259
  }
1140
1260
  </div>
1261
+ {(isEditFlow || !isFullMode) && templateDescError && (
1262
+ <CapError className="rcs-template-message-error">
1263
+ {templateDescError}
1264
+ </CapError>
1265
+ )}
1141
1266
  </CapRow>
1142
1267
  {renderButtonComponent()}
1143
1268
  </>
@@ -1674,8 +1799,9 @@ const splitTemplateVarString = (str) => {
1674
1799
  const getRcsPreview = () => {
1675
1800
 
1676
1801
  const dimensionObj = RCS_IMAGE_DIMENSIONS[selectedDimension];
1677
- const mappedDesc = !isFullMode ? getMappedDesc(templateDesc, cardVarMapped) : templateDesc;
1678
- const mappedTitle = !isFullMode ? getMappedDesc(templateTitle, cardVarMapped) : templateTitle;
1802
+ // Always show resolved values in preview
1803
+ const mappedDesc = getMappedDesc(templateDesc, cardVarMapped);
1804
+ const mappedTitle = getMappedDesc(templateTitle, cardVarMapped);
1679
1805
  return (
1680
1806
  <TemplatePreview
1681
1807
  channel={RCS}
@@ -1712,6 +1838,21 @@ const splitTemplateVarString = (str) => {
1712
1838
  return elem;
1713
1839
  }).join('');
1714
1840
  };
1841
+
1842
+ const getUnmappedDesc = (str, mapping) => {
1843
+ if (!str) return '';
1844
+ if (!mapping || Object.keys(mapping).length === 0) return str;
1845
+ let result = str;
1846
+ Object.keys(mapping).forEach((key) => {
1847
+ const value = mapping[key];
1848
+ if (!value) return;
1849
+ const bracedValue = /^\{\{[\s\S]*\}\}$/.test(value) ? value : `{{${value}}}`;
1850
+ const escaped = bracedValue.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
1851
+ const regex = new RegExp(escaped, 'g');
1852
+ result = result.replace(regex, `{{${key}}}`);
1853
+ });
1854
+ return result;
1855
+ };
1715
1856
 
1716
1857
  const createPayload = () => {
1717
1858
  const base = get(dltEditData, `versions.base`, {});
@@ -1804,7 +1945,6 @@ const splitTemplateVarString = (str) => {
1804
1945
 
1805
1946
 
1806
1947
  const onEditRcs = () => {
1807
- console.log("onEditRcs");
1808
1948
  const payload = createPayload();
1809
1949
  const formDataParams = {
1810
1950
  value: payload,
@@ -1843,21 +1983,47 @@ const splitTemplateVarString = (str) => {
1843
1983
  }
1844
1984
  }
1845
1985
 
1986
+ if(!isFullMode){
1987
+ const titleVars = splitTemplateVarString(templateTitle).filter(elem => rcsVarTestRegex.test(elem)).map(v => v.replace(/^\{\{|\}\}$/g, ''));
1988
+ const descVars = splitTemplateVarString(templateDesc).filter(elem => rcsVarTestRegex.test(elem)).map(v => v.replace(/^\{\{|\}\}$/g, ''));
1989
+ const allVars = Array.from(new Set([ ...titleVars, ...descVars ]));
1990
+
1991
+ if (allVars.length > 0 && isEmpty(cardVarMapped)) {
1992
+ return true;
1993
+ }
1994
+
1995
+ const hasEmptyMapping =
1996
+ cardVarMapped &&
1997
+ Object.keys(cardVarMapped).length > 0 &&
1998
+ Object.entries(cardVarMapped).some(([_, v]) => {
1999
+ if (typeof v !== 'string') return !v; // null/undefined
2000
+ return v.trim() === ''; // empty string
2001
+ });
2002
+
2003
+ if (hasEmptyMapping) {
2004
+ return true;
2005
+ }
2006
+
2007
+ const anyMissing = allVars.some(name => {
2008
+ const v = cardVarMapped?.[name];
2009
+ if (typeof v !== 'string') return !v;
2010
+ return v.trim() === '';
2011
+ });
2012
+ if (anyMissing) {
2013
+ return true;
2014
+ }
2015
+ }
2016
+
1846
2017
  if (isMediaTypeText && templateDesc.trim() === '') {
1847
- console.log("isMediaTypeText", isMediaTypeText);
1848
- console.log("templateDesc", templateDesc);
1849
- console.log("disabled becuase template desc is empty");
1850
2018
  return true;
1851
2019
 
1852
2020
  }
1853
2021
  if (isMediaTypeImage && (rcsImageSrc === '' || templateTitle === '' || templateDesc === '' )) {
1854
- console.log("disabled becuase template desc and title are empty");
1855
2022
  return true;
1856
2023
  }
1857
2024
 
1858
2025
  if (isMediaTypeVideo && (rcsVideoSrc.videoSrc === '' || rcsThumbnailSrc === '' || templateTitle === '' || templateDesc === '' )) {
1859
- console.log("disabled becuase template desc and title and thumbnail are empty");
1860
- return true;
2026
+ return true;
1861
2027
  }
1862
2028
  if (buttonType.includes(CTA)) {
1863
2029
 
@@ -1865,12 +2031,10 @@ const splitTemplateVarString = (str) => {
1865
2031
  suggestion.text && suggestion.url && !suggestionError
1866
2032
  );
1867
2033
  if (!hasValidButtons) {
1868
- console.log("disabled becuase no valid buttons");
1869
2034
  return true;
1870
2035
  }
1871
2036
  }
1872
- if (templateDescError || fallbackMessageError) {
1873
- console.log("disabled becuase template desc or fallback message has error");
2037
+ if (templateDescError || templateTitleError || fallbackMessageError) {
1874
2038
  return true;
1875
2039
  }
1876
2040
  return false;
@@ -1887,17 +2051,43 @@ const splitTemplateVarString = (str) => {
1887
2051
  return true;
1888
2052
  }
1889
2053
  }
2054
+ if(!isFullMode){
2055
+ const titleVars = splitTemplateVarString(templateTitle).filter(elem => rcsVarTestRegex.test(elem)).map(v => v.replace(/^\{\{|\}\}$/g, ''));
2056
+ const descVars = splitTemplateVarString(templateDesc).filter(elem => rcsVarTestRegex.test(elem)).map(v => v.replace(/^\{\{|\}\}$/g, ''));
2057
+ const allVars = Array.from(new Set([ ...titleVars, ...descVars ]));
2058
+
2059
+ if (allVars.length > 0 && isEmpty(cardVarMapped)) {
2060
+ return true;
2061
+ }
1890
2062
 
2063
+ const hasEmptyMapping =
2064
+ cardVarMapped &&
2065
+ Object.keys(cardVarMapped).length > 0 &&
2066
+ Object.entries(cardVarMapped).some(([_, v]) => {
2067
+ if (typeof v !== 'string') return !v; // null/undefined
2068
+ return v.trim() === ''; // empty string
2069
+ });
2070
+
2071
+ if (hasEmptyMapping) {
2072
+ return true;
2073
+ }
2074
+
2075
+ const anyMissing = allVars.some(name => {
2076
+ const v = cardVarMapped?.[name];
2077
+ if (typeof v !== 'string') return !v;
2078
+ return v.trim() === '';
2079
+ });
2080
+ if (anyMissing) {
2081
+ return true;
2082
+ }
2083
+ }
1891
2084
  if (isMediaTypeText && templateDesc.trim() === '') {
1892
- console.log('disabled becuase template desc is empty');
1893
2085
  return true;
1894
2086
  }
1895
2087
  if (isMediaTypeImage && rcsImageSrc === '') {
1896
- console.log('disabled becuase image src is empty');
1897
2088
  return true;
1898
2089
  }
1899
2090
  if(isMediaTypeVideo && (rcsThumbnailSrc === '' || rcsVideoSrc.videoSrc === '')) {
1900
- console.log('disabled becuase thumbnail src or video src is empty');
1901
2091
  return true;
1902
2092
  }
1903
2093
 
@@ -1906,10 +2096,12 @@ const splitTemplateVarString = (str) => {
1906
2096
  suggestion.text && suggestion.url && !suggestionError
1907
2097
  );
1908
2098
  if (!hasValidButtons) {
1909
- console.log('disabled becuase no valid buttons');
1910
2099
  return true;
1911
2100
  }
1912
2101
  }
2102
+ if (templateTitleError || templateDescError || fallbackMessageError) {
2103
+ return true;
2104
+ }
1913
2105
  return false;
1914
2106
  };
1915
2107
 
@@ -94,7 +94,6 @@
94
94
  margin-top: 1.25rem;
95
95
  }
96
96
  .rcs-template-title-input {
97
- padding-right: 10%;
98
97
  .rcs-edit-disabled {
99
98
  cursor: not-allowed;
100
99
  opacity: 0.5;