@capillarytech/creatives-library 9.0.29-alpha.1 → 9.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "9.0.29-alpha.1",
4
+ "version": "9.0.30",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -230,6 +230,7 @@ export const CapActionButton = (props) => {
230
230
  const urlSubtype = type === RCS_BUTTON_TYPES.CTA
231
231
  ? (cta.urlType || RCS_CTA_URL_TYPE.STATIC)
232
232
  : RCS_CTA_URL_TYPE.STATIC;
233
+ const isDynamicUrlSubtype = urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC;
233
234
  const phoneNumber = type !== RCS_BUTTON_TYPES.PHONE_NUMBER ? null : cta.phoneNumber;
234
235
  if (isFullMode && !isEditFlow && !isSaved) {
235
236
  renderArray.push(
@@ -342,7 +343,7 @@ export const CapActionButton = (props) => {
342
343
  <CapColumn span={18} className="rcs-cta-url-value-col">
343
344
  <CapHeading type="h4" className="cta-label">
344
345
  {formatMessage(messages.ctaWebsiteUrl)}
345
- {urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC && (
346
+ {isDynamicUrlSubtype && (
346
347
  <CapTooltipWithInfo
347
348
  infoIconProps={{
348
349
  style: { marginLeft: CAP_SPACE_04 },
@@ -356,14 +357,14 @@ export const CapActionButton = (props) => {
356
357
  <CapInput
357
358
  id={index}
358
359
  addonAfter={
359
- urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC
360
+ isDynamicUrlSubtype
360
361
  && !(url || '').includes(DYNAMIC_URL_SUFFIX)
361
362
  && DYNAMIC_URL_SUFFIX
362
363
  }
363
364
  className="rcs-cta-url"
364
365
  onChange={onUrlChange}
365
366
  placeholder={
366
- urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC
367
+ isDynamicUrlSubtype
367
368
  ? formatMessage(messages.ctaDynamicPlaceholder)
368
369
  : formatMessage(messages.ctaEnterUrlPlaceholder)
369
370
  }
@@ -475,7 +476,7 @@ export const CapActionButton = (props) => {
475
476
  </CapTooltip>
476
477
  </>
477
478
  )}
478
- {isEditFlow && urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC && (url || '').includes(DYNAMIC_URL_SUFFIX) && (
479
+ {isDynamicUrlSubtype && (url || '').includes(DYNAMIC_URL_SUFFIX) && (
479
480
  <TagList
480
481
  className="rcs-cta-taglist"
481
482
  label={formatMessage(messages.ctaTagListLabel)}
@@ -487,7 +488,7 @@ export const CapActionButton = (props) => {
487
488
  onContextChange={onContextChange}
488
489
  />
489
490
  )}
490
- {isEditFlow && urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC && !(url || '').includes(DYNAMIC_URL_SUFFIX) && (
491
+ {isDynamicUrlSubtype && !(url || '').includes(DYNAMIC_URL_SUFFIX) && (
491
492
  <CapTooltip title={formatMessage(messages.ctaTagListRevert)} placement="top">
492
493
  <CapIcon
493
494
  size="s"
@@ -90,7 +90,6 @@ import {
90
90
  import {EXTERNAL_URL, SITE_URL, WEBPUSH_MEDIA_TYPES} from '../WebPush/constants';
91
91
  import { IMAGE, VIDEO } from '../Facebook/Advertisement/constant';
92
92
  import { RCS_STATUSES, contentType as RCS_CONTENT_TYPE, EMBEDDED } from '../Rcs/constants';
93
- import { mapRcsCardContentForConsumerWithResolvedTags } from '../Rcs/utils';
94
93
  import { pickRcsCardVarMappedEntries } from '../Rcs/rcsLibraryHydrationUtils';
95
94
  import { RCS_SMS_FALLBACK_VAR_MAPPED_PROP } from '../../v2Components/CommonTestAndPreview/constants';
96
95
  import { CREATIVE } from '../Facebook/constants';
@@ -1442,15 +1441,10 @@ export class Creatives extends React.Component {
1442
1441
  cardSettings = {},
1443
1442
  accountId = "",
1444
1443
  } = get(versions, 'base.content.RCS.rcsContent', {});
1445
- const rootRcsCardVarMappedFromSubmit = get(template, 'value.rcsCardVarMapped');
1446
1444
  const firstCardFromSubmit = Array.isArray(cardContentFromSubmit)
1447
1445
  ? cardContentFromSubmit[0]
1448
1446
  : null;
1449
- const cardContent = mapRcsCardContentForConsumerWithResolvedTags(
1450
- cardContentFromSubmit,
1451
- rootRcsCardVarMappedFromSubmit,
1452
- isFullModeForRcsConsumerPayload,
1453
- );
1447
+ const cardContent = cardContentFromSubmit;
1454
1448
  const rcsContent = {
1455
1449
  contentType,
1456
1450
  cardType,
@@ -1214,6 +1214,13 @@ export const Rcs = (props) => {
1214
1214
  setSelectedCarousel(`${firstHeight}_${cardWidth}`);
1215
1215
  setActiveCarouselIndex('0');
1216
1216
 
1217
+ if (cards.length > 1) {
1218
+ setCardVarMapped((previousVarMap) => cards.reduce((merged, c) => {
1219
+ const cardMap = c?.cardVarMapped;
1220
+ return cardMap != null && typeof cardMap === 'object' ? { ...merged, ...cardMap } : merged;
1221
+ }, { ...(previousVarMap || {}) }));
1222
+ }
1223
+
1217
1224
  const hydratedCards = cards.map((c = {}, idx) => {
1218
1225
  const mediaType = c.mediaType;
1219
1226
  const media = c.media || {};
@@ -1939,6 +1946,11 @@ const onTitleAddVar = () => {
1939
1946
  isFullMode={isFullMode}
1940
1947
  maxButtons={MAX_BUTTONS}
1941
1948
  host={hostName}
1949
+ location={location}
1950
+ tags={getRcsTags()}
1951
+ injectedTags={injectedTags || {}}
1952
+ selectedOfferDetails={selectedOfferDetails}
1953
+ onContextChange={handleOnTagsContextChange}
1942
1954
  />
1943
1955
  </>
1944
1956
  );
@@ -2968,6 +2980,19 @@ const onTitleAddVar = () => {
2968
2980
  return unfilledVar;
2969
2981
  };
2970
2982
 
2983
+ // Mirror WhatsApp's isEditDoneDisabled: block Done while a CTA button's dynamic URL still
2984
+ // holds the unresolved {{1}} placeholder (no real personalization tag assigned yet).
2985
+ const hasUnresolvedDynamicCtaUrl = () =>
2986
+ isCarouselType
2987
+ ? (carouselData || []).some((card) =>
2988
+ (card?.suggestions || []).some((suggestion) =>
2989
+ suggestion?.type === CTA && (suggestion?.url || '').includes('{{1}}')
2990
+ )
2991
+ )
2992
+ : suggestions.some((suggestion) =>
2993
+ suggestion?.type === CTA && (suggestion?.url || '').includes('{{1}}')
2994
+ );
2995
+
2971
2996
  const isDisableDone = () => {
2972
2997
  if(isEditFlow){
2973
2998
  return false;
@@ -3009,6 +3034,9 @@ const onTitleAddVar = () => {
3009
3034
  return true;
3010
3035
  }
3011
3036
  }
3037
+ if (hasUnresolvedDynamicCtaUrl()) {
3038
+ return true;
3039
+ }
3012
3040
  if (templateDescError || templateTitleError) {
3013
3041
  return true;
3014
3042
  }
@@ -3053,18 +3081,7 @@ const onTitleAddVar = () => {
3053
3081
  return true;
3054
3082
  }
3055
3083
  }
3056
- // Mirror WhatsApp's isEditDoneDisabled: block Done while a CTA button's dynamic URL still
3057
- // holds the unresolved {{1}} placeholder (no real personalization tag assigned yet).
3058
- const hasUnresolvedDynamicCtaUrl = isCarouselType
3059
- ? (carouselData || []).some((card) =>
3060
- (card?.suggestions || []).some((suggestion) =>
3061
- suggestion?.type === CTA && (suggestion?.url || '').includes('{{1}}')
3062
- )
3063
- )
3064
- : suggestions.some((suggestion) =>
3065
- suggestion?.type === CTA && (suggestion?.url || '').includes('{{1}}')
3066
- );
3067
- if (hasUnresolvedDynamicCtaUrl) {
3084
+ if (hasUnresolvedDynamicCtaUrl()) {
3068
3085
  return true;
3069
3086
  }
3070
3087
  if (templateTitleError || templateDescError) {
@@ -302,11 +302,21 @@ export function resolveSmsFallbackHydrationFromDetails(details) {
302
302
  || '';
303
303
  const varMappedFromPayload = smsFallbackContent[RCS_SMS_FALLBACK_VAR_MAPPED_PROP] || {};
304
304
  const hasVarMapped = Object.keys(varMappedFromPayload).length > 0;
305
+ const templateConfigsRecord =
306
+ smsFallbackContent.templateConfigs && typeof smsFallbackContent.templateConfigs === 'object'
307
+ ? smsFallbackContent.templateConfigs
308
+ : {};
309
+ const smsFallbackTemplateName =
310
+ smsFallbackContent.templateName
311
+ || smsFallbackContent.smsTemplateName
312
+ || templateConfigsRecord.templateName
313
+ || templateConfigsRecord.name
314
+ || '';
305
315
  const hasFallbackPayload =
306
316
  smsFallbackContent
307
317
  && Object.keys(smsFallbackContent).length > 0
308
318
  && (
309
- !!smsFallbackContent.smsTemplateName
319
+ !!smsFallbackTemplateName
310
320
  || !!fallbackMessage
311
321
  || hasVarMapped
312
322
  );
@@ -325,7 +335,7 @@ export function resolveSmsFallbackHydrationFromDetails(details) {
325
335
  : (typeof base['unicode-validity'] === 'boolean' ? base['unicode-validity'] : true);
326
336
  const registeredSenderIds = extractRegisteredSenderIdsFromSmsFallbackRecord(smsFallbackContent);
327
337
  const nextSmsState = {
328
- templateName: smsFallbackContent.smsTemplateName || '',
338
+ templateName: smsFallbackTemplateName,
329
339
  content: fallbackMessage,
330
340
  templateContent: fallbackMessage,
331
341
  unicodeValidity: unicodeFromApi,
@@ -6782,10 +6782,23 @@ new message content.",
6782
6782
  buttonType="NONE"
6783
6783
  deleteButtonHandler={[Function]}
6784
6784
  host=""
6785
+ injectedTags={Object {}}
6785
6786
  isEditFlow={false}
6786
6787
  isFullMode={true}
6788
+ location={
6789
+ Object {
6790
+ "pathname": "/rcs/create",
6791
+ "query": Object {
6792
+ "module": "default",
6793
+ "type": false,
6794
+ },
6795
+ "search": "",
6796
+ }
6797
+ }
6787
6798
  maxButtons={4}
6799
+ onContextChange={[Function]}
6788
6800
  suggestions={Array []}
6801
+ tags={Array []}
6789
6802
  updateButtonChange={[Function]}
6790
6803
  >
6791
6804
  <div
@@ -6793,10 +6806,23 @@ new message content.",
6793
6806
  className="cap-action-button-mock"
6794
6807
  deleteButtonHandler={[Function]}
6795
6808
  host=""
6809
+ injectedTags={Object {}}
6796
6810
  isEditFlow={false}
6797
6811
  isFullMode={true}
6812
+ location={
6813
+ Object {
6814
+ "pathname": "/rcs/create",
6815
+ "query": Object {
6816
+ "module": "default",
6817
+ "type": false,
6818
+ },
6819
+ "search": "",
6820
+ }
6821
+ }
6798
6822
  maxButtons={4}
6823
+ onContextChange={[Function]}
6799
6824
  suggestions={Array []}
6825
+ tags={Array []}
6800
6826
  updateButtonChange={[Function]}
6801
6827
  >
6802
6828
  CapActionButton
@@ -22673,10 +22699,23 @@ new message content.",
22673
22699
  buttonType="NONE"
22674
22700
  deleteButtonHandler={[Function]}
22675
22701
  host=""
22702
+ injectedTags={Object {}}
22676
22703
  isEditFlow={false}
22677
22704
  isFullMode={true}
22705
+ location={
22706
+ Object {
22707
+ "pathname": "/rcs/create",
22708
+ "query": Object {
22709
+ "module": "default",
22710
+ "type": false,
22711
+ },
22712
+ "search": "",
22713
+ }
22714
+ }
22678
22715
  maxButtons={4}
22716
+ onContextChange={[Function]}
22679
22717
  suggestions={Array []}
22718
+ tags={Array []}
22680
22719
  updateButtonChange={[Function]}
22681
22720
  >
22682
22721
  <div
@@ -22684,10 +22723,23 @@ new message content.",
22684
22723
  className="cap-action-button-mock"
22685
22724
  deleteButtonHandler={[Function]}
22686
22725
  host=""
22726
+ injectedTags={Object {}}
22687
22727
  isEditFlow={false}
22688
22728
  isFullMode={true}
22729
+ location={
22730
+ Object {
22731
+ "pathname": "/rcs/create",
22732
+ "query": Object {
22733
+ "module": "default",
22734
+ "type": false,
22735
+ },
22736
+ "search": "",
22737
+ }
22738
+ }
22689
22739
  maxButtons={4}
22740
+ onContextChange={[Function]}
22690
22741
  suggestions={Array []}
22742
+ tags={Array []}
22691
22743
  updateButtonChange={[Function]}
22692
22744
  >
22693
22745
  CapActionButton
@@ -38738,10 +38790,23 @@ new message content.",
38738
38790
  buttonType="NONE"
38739
38791
  deleteButtonHandler={[Function]}
38740
38792
  host=""
38793
+ injectedTags={Object {}}
38741
38794
  isEditFlow={false}
38742
38795
  isFullMode={true}
38796
+ location={
38797
+ Object {
38798
+ "pathname": "/rcs/create",
38799
+ "query": Object {
38800
+ "module": "default",
38801
+ "type": false,
38802
+ },
38803
+ "search": "",
38804
+ }
38805
+ }
38743
38806
  maxButtons={4}
38807
+ onContextChange={[Function]}
38744
38808
  suggestions={Array []}
38809
+ tags={Array []}
38745
38810
  updateButtonChange={[Function]}
38746
38811
  >
38747
38812
  <div
@@ -38749,10 +38814,23 @@ new message content.",
38749
38814
  className="cap-action-button-mock"
38750
38815
  deleteButtonHandler={[Function]}
38751
38816
  host=""
38817
+ injectedTags={Object {}}
38752
38818
  isEditFlow={false}
38753
38819
  isFullMode={true}
38820
+ location={
38821
+ Object {
38822
+ "pathname": "/rcs/create",
38823
+ "query": Object {
38824
+ "module": "default",
38825
+ "type": false,
38826
+ },
38827
+ "search": "",
38828
+ }
38829
+ }
38754
38830
  maxButtons={4}
38831
+ onContextChange={[Function]}
38755
38832
  suggestions={Array []}
38833
+ tags={Array []}
38756
38834
  updateButtonChange={[Function]}
38757
38835
  >
38758
38836
  CapActionButton
@@ -55393,10 +55471,23 @@ new message content.",
55393
55471
  buttonType="NONE"
55394
55472
  deleteButtonHandler={[Function]}
55395
55473
  host=""
55474
+ injectedTags={Object {}}
55396
55475
  isEditFlow={false}
55397
55476
  isFullMode={true}
55477
+ location={
55478
+ Object {
55479
+ "pathname": "/rcs/create",
55480
+ "query": Object {
55481
+ "module": "default",
55482
+ "type": false,
55483
+ },
55484
+ "search": "",
55485
+ }
55486
+ }
55398
55487
  maxButtons={4}
55488
+ onContextChange={[Function]}
55399
55489
  suggestions={Array []}
55490
+ tags={Array []}
55400
55491
  updateButtonChange={[Function]}
55401
55492
  >
55402
55493
  <div
@@ -55404,10 +55495,23 @@ new message content.",
55404
55495
  className="cap-action-button-mock"
55405
55496
  deleteButtonHandler={[Function]}
55406
55497
  host=""
55498
+ injectedTags={Object {}}
55407
55499
  isEditFlow={false}
55408
55500
  isFullMode={true}
55501
+ location={
55502
+ Object {
55503
+ "pathname": "/rcs/create",
55504
+ "query": Object {
55505
+ "module": "default",
55506
+ "type": false,
55507
+ },
55508
+ "search": "",
55509
+ }
55510
+ }
55409
55511
  maxButtons={4}
55512
+ onContextChange={[Function]}
55410
55513
  suggestions={Array []}
55514
+ tags={Array []}
55411
55515
  updateButtonChange={[Function]}
55412
55516
  >
55413
55517
  CapActionButton
@@ -72080,10 +72184,23 @@ new message content.",
72080
72184
  buttonType="NONE"
72081
72185
  deleteButtonHandler={[Function]}
72082
72186
  host=""
72187
+ injectedTags={Object {}}
72083
72188
  isEditFlow={false}
72084
72189
  isFullMode={true}
72190
+ location={
72191
+ Object {
72192
+ "pathname": "/rcs/create",
72193
+ "query": Object {
72194
+ "module": "default",
72195
+ "type": false,
72196
+ },
72197
+ "search": "",
72198
+ }
72199
+ }
72085
72200
  maxButtons={4}
72201
+ onContextChange={[Function]}
72086
72202
  suggestions={Array []}
72203
+ tags={Array []}
72087
72204
  updateButtonChange={[Function]}
72088
72205
  >
72089
72206
  <div
@@ -72091,10 +72208,23 @@ new message content.",
72091
72208
  className="cap-action-button-mock"
72092
72209
  deleteButtonHandler={[Function]}
72093
72210
  host=""
72211
+ injectedTags={Object {}}
72094
72212
  isEditFlow={false}
72095
72213
  isFullMode={true}
72214
+ location={
72215
+ Object {
72216
+ "pathname": "/rcs/create",
72217
+ "query": Object {
72218
+ "module": "default",
72219
+ "type": false,
72220
+ },
72221
+ "search": "",
72222
+ }
72223
+ }
72096
72224
  maxButtons={4}
72225
+ onContextChange={[Function]}
72097
72226
  suggestions={Array []}
72227
+ tags={Array []}
72098
72228
  updateButtonChange={[Function]}
72099
72229
  >
72100
72230
  CapActionButton
@@ -90173,10 +90303,23 @@ new message content.",
90173
90303
  buttonType="NONE"
90174
90304
  deleteButtonHandler={[Function]}
90175
90305
  host=""
90306
+ injectedTags={Object {}}
90176
90307
  isEditFlow={false}
90177
90308
  isFullMode={true}
90309
+ location={
90310
+ Object {
90311
+ "pathname": "/rcs/create",
90312
+ "query": Object {
90313
+ "module": "default",
90314
+ "type": false,
90315
+ },
90316
+ "search": "",
90317
+ }
90318
+ }
90178
90319
  maxButtons={4}
90320
+ onContextChange={[Function]}
90179
90321
  suggestions={Array []}
90322
+ tags={Array []}
90180
90323
  updateButtonChange={[Function]}
90181
90324
  >
90182
90325
  <div
@@ -90184,10 +90327,23 @@ new message content.",
90184
90327
  className="cap-action-button-mock"
90185
90328
  deleteButtonHandler={[Function]}
90186
90329
  host=""
90330
+ injectedTags={Object {}}
90187
90331
  isEditFlow={false}
90188
90332
  isFullMode={true}
90333
+ location={
90334
+ Object {
90335
+ "pathname": "/rcs/create",
90336
+ "query": Object {
90337
+ "module": "default",
90338
+ "type": false,
90339
+ },
90340
+ "search": "",
90341
+ }
90342
+ }
90189
90343
  maxButtons={4}
90344
+ onContextChange={[Function]}
90190
90345
  suggestions={Array []}
90346
+ tags={Array []}
90191
90347
  updateButtonChange={[Function]}
90192
90348
  >
90193
90349
  CapActionButton
@@ -110019,10 +110175,23 @@ new message content.",
110019
110175
  buttonType="NONE"
110020
110176
  deleteButtonHandler={[Function]}
110021
110177
  host=""
110178
+ injectedTags={Object {}}
110022
110179
  isEditFlow={false}
110023
110180
  isFullMode={true}
110181
+ location={
110182
+ Object {
110183
+ "pathname": "/rcs/create",
110184
+ "query": Object {
110185
+ "module": "default",
110186
+ "type": false,
110187
+ },
110188
+ "search": "",
110189
+ }
110190
+ }
110024
110191
  maxButtons={4}
110192
+ onContextChange={[Function]}
110025
110193
  suggestions={Array []}
110194
+ tags={Array []}
110026
110195
  updateButtonChange={[Function]}
110027
110196
  >
110028
110197
  <div
@@ -110030,10 +110199,23 @@ new message content.",
110030
110199
  className="cap-action-button-mock"
110031
110200
  deleteButtonHandler={[Function]}
110032
110201
  host=""
110202
+ injectedTags={Object {}}
110033
110203
  isEditFlow={false}
110034
110204
  isFullMode={true}
110205
+ location={
110206
+ Object {
110207
+ "pathname": "/rcs/create",
110208
+ "query": Object {
110209
+ "module": "default",
110210
+ "type": false,
110211
+ },
110212
+ "search": "",
110213
+ }
110214
+ }
110035
110215
  maxButtons={4}
110216
+ onContextChange={[Function]}
110036
110217
  suggestions={Array []}
110218
+ tags={Array []}
110037
110219
  updateButtonChange={[Function]}
110038
110220
  >
110039
110221
  CapActionButton
@@ -129104,10 +129286,23 @@ new message content.",
129104
129286
  buttonType="NONE"
129105
129287
  deleteButtonHandler={[Function]}
129106
129288
  host=""
129289
+ injectedTags={Object {}}
129107
129290
  isEditFlow={false}
129108
129291
  isFullMode={true}
129292
+ location={
129293
+ Object {
129294
+ "pathname": "/rcs/create",
129295
+ "query": Object {
129296
+ "module": "default",
129297
+ "type": false,
129298
+ },
129299
+ "search": "",
129300
+ }
129301
+ }
129109
129302
  maxButtons={4}
129303
+ onContextChange={[Function]}
129110
129304
  suggestions={Array []}
129305
+ tags={Array []}
129111
129306
  updateButtonChange={[Function]}
129112
129307
  >
129113
129308
  <div
@@ -129115,10 +129310,23 @@ new message content.",
129115
129310
  className="cap-action-button-mock"
129116
129311
  deleteButtonHandler={[Function]}
129117
129312
  host=""
129313
+ injectedTags={Object {}}
129118
129314
  isEditFlow={false}
129119
129315
  isFullMode={true}
129316
+ location={
129317
+ Object {
129318
+ "pathname": "/rcs/create",
129319
+ "query": Object {
129320
+ "module": "default",
129321
+ "type": false,
129322
+ },
129323
+ "search": "",
129324
+ }
129325
+ }
129120
129326
  maxButtons={4}
129327
+ onContextChange={[Function]}
129121
129328
  suggestions={Array []}
129329
+ tags={Array []}
129122
129330
  updateButtonChange={[Function]}
129123
129331
  >
129124
129332
  CapActionButton
@@ -147843,10 +148051,23 @@ new message content.",
147843
148051
  buttonType="NONE"
147844
148052
  deleteButtonHandler={[Function]}
147845
148053
  host=""
148054
+ injectedTags={Object {}}
147846
148055
  isEditFlow={false}
147847
148056
  isFullMode={true}
148057
+ location={
148058
+ Object {
148059
+ "pathname": "/rcs/create",
148060
+ "query": Object {
148061
+ "module": "default",
148062
+ "type": false,
148063
+ },
148064
+ "search": "",
148065
+ }
148066
+ }
147848
148067
  maxButtons={4}
148068
+ onContextChange={[Function]}
147849
148069
  suggestions={Array []}
148070
+ tags={Array []}
147850
148071
  updateButtonChange={[Function]}
147851
148072
  >
147852
148073
  <div
@@ -147854,10 +148075,23 @@ new message content.",
147854
148075
  className="cap-action-button-mock"
147855
148076
  deleteButtonHandler={[Function]}
147856
148077
  host=""
148078
+ injectedTags={Object {}}
147857
148079
  isEditFlow={false}
147858
148080
  isFullMode={true}
148081
+ location={
148082
+ Object {
148083
+ "pathname": "/rcs/create",
148084
+ "query": Object {
148085
+ "module": "default",
148086
+ "type": false,
148087
+ },
148088
+ "search": "",
148089
+ }
148090
+ }
147859
148091
  maxButtons={4}
148092
+ onContextChange={[Function]}
147860
148093
  suggestions={Array []}
148094
+ tags={Array []}
147861
148095
  updateButtonChange={[Function]}
147862
148096
  >
147863
148097
  CapActionButton
@@ -163714,10 +163948,23 @@ new message content.",
163714
163948
  buttonType="NONE"
163715
163949
  deleteButtonHandler={[Function]}
163716
163950
  host=""
163951
+ injectedTags={Object {}}
163717
163952
  isEditFlow={false}
163718
163953
  isFullMode={true}
163954
+ location={
163955
+ Object {
163956
+ "pathname": "/rcs/create",
163957
+ "query": Object {
163958
+ "module": "default",
163959
+ "type": false,
163960
+ },
163961
+ "search": "",
163962
+ }
163963
+ }
163719
163964
  maxButtons={4}
163965
+ onContextChange={[Function]}
163720
163966
  suggestions={Array []}
163967
+ tags={Array []}
163721
163968
  updateButtonChange={[Function]}
163722
163969
  >
163723
163970
  <div
@@ -163725,10 +163972,23 @@ new message content.",
163725
163972
  className="cap-action-button-mock"
163726
163973
  deleteButtonHandler={[Function]}
163727
163974
  host=""
163975
+ injectedTags={Object {}}
163728
163976
  isEditFlow={false}
163729
163977
  isFullMode={true}
163978
+ location={
163979
+ Object {
163980
+ "pathname": "/rcs/create",
163981
+ "query": Object {
163982
+ "module": "default",
163983
+ "type": false,
163984
+ },
163985
+ "search": "",
163986
+ }
163987
+ }
163730
163988
  maxButtons={4}
163989
+ onContextChange={[Function]}
163731
163990
  suggestions={Array []}
163991
+ tags={Array []}
163732
163992
  updateButtonChange={[Function]}
163733
163993
  >
163734
163994
  CapActionButton
@@ -179585,10 +179845,23 @@ new message content.",
179585
179845
  buttonType="NONE"
179586
179846
  deleteButtonHandler={[Function]}
179587
179847
  host=""
179848
+ injectedTags={Object {}}
179588
179849
  isEditFlow={false}
179589
179850
  isFullMode={true}
179851
+ location={
179852
+ Object {
179853
+ "pathname": "/rcs/create",
179854
+ "query": Object {
179855
+ "module": "default",
179856
+ "type": false,
179857
+ },
179858
+ "search": "",
179859
+ }
179860
+ }
179590
179861
  maxButtons={4}
179862
+ onContextChange={[Function]}
179591
179863
  suggestions={Array []}
179864
+ tags={Array []}
179592
179865
  updateButtonChange={[Function]}
179593
179866
  >
179594
179867
  <div
@@ -179596,10 +179869,23 @@ new message content.",
179596
179869
  className="cap-action-button-mock"
179597
179870
  deleteButtonHandler={[Function]}
179598
179871
  host=""
179872
+ injectedTags={Object {}}
179599
179873
  isEditFlow={false}
179600
179874
  isFullMode={true}
179875
+ location={
179876
+ Object {
179877
+ "pathname": "/rcs/create",
179878
+ "query": Object {
179879
+ "module": "default",
179880
+ "type": false,
179881
+ },
179882
+ "search": "",
179883
+ }
179884
+ }
179601
179885
  maxButtons={4}
179886
+ onContextChange={[Function]}
179602
179887
  suggestions={Array []}
179888
+ tags={Array []}
179603
179889
  updateButtonChange={[Function]}
179604
179890
  >
179605
179891
  CapActionButton
@@ -1008,6 +1008,62 @@ describe('RCS createPayload', () => {
1008
1008
  expect(doneBtn.prop('disabled')).toBe(true);
1009
1009
  });
1010
1010
 
1011
+ it('disables Send for Approval in full-mode creation when a CTA button URL still holds the unresolved {{1}} placeholder', () => {
1012
+ const wrapper = mountWithIntl(
1013
+ <Provider store={store}>
1014
+ <Rcs
1015
+ actions={{
1016
+ clearCreateResponse: jest.fn(),
1017
+ getTemplateDetails: jest.fn(),
1018
+ uploadRcsAsset: jest.fn(),
1019
+ clearRcsMediaAsset: jest.fn(),
1020
+ editTemplate: jest.fn(),
1021
+ clearEditResponse: jest.fn(),
1022
+ }}
1023
+ globalActions={{ fetchSchemaForEntity }}
1024
+ onCreateComplete={onCreateComplete}
1025
+ handleClose={handleClose}
1026
+ intl={{ formatMessage }}
1027
+ location={{ pathname: '/rcs/create', query: { type: false, module: 'default' }, search: '' }}
1028
+ params={params}
1029
+ templateData={{}}
1030
+ rcsData={{}}
1031
+ isFullMode
1032
+ isEditFlow={false}
1033
+ loadingTags={false}
1034
+ metaEntities={[]}
1035
+ isDltEnabled={false}
1036
+ smsRegister={'DLT'}
1037
+ getFormData={jest.fn()}
1038
+ />
1039
+ </Provider>,
1040
+ );
1041
+
1042
+ act(() => {
1043
+ wrapper.find('#rcs_template_name_input').at(0).simulate('change', { target: { value: 'PromoCard' } });
1044
+ });
1045
+ wrapper.update();
1046
+
1047
+ act(() => {
1048
+ wrapper.find('#rcs_template_message_textarea').at(0).simulate('change', { target: { value: 'Hello there' } });
1049
+ });
1050
+ wrapper.update();
1051
+
1052
+ const actionButton = wrapper.find('.cap-action-button-mock').at(0);
1053
+ expect(actionButton.exists()).toBe(true);
1054
+ act(() => {
1055
+ actionButton.prop('updateButtonChange')(
1056
+ { type: 'CTA', text: 'Visit here', url: 'https://example.com{{1}}' },
1057
+ 0,
1058
+ );
1059
+ });
1060
+ wrapper.update();
1061
+
1062
+ const doneBtn = wrapper.find('CapButton.rcs-done-btn').at(0);
1063
+ expect(doneBtn.exists()).toBe(true);
1064
+ expect(doneBtn.prop('disabled')).toBe(true);
1065
+ });
1066
+
1011
1067
  it('should sync duplicate placeholders via cardVarMapped in non-full mode (typing once updates all occurrences)', () => {
1012
1068
  const templateData = {
1013
1069
  name: 'DupVarsTemplate',
@@ -656,6 +656,45 @@ describe('rcsLibraryHydrationUtils', () => {
656
656
  expect(warnSpy).toHaveBeenCalled();
657
657
  });
658
658
 
659
+ it('falls back to templateConfigs.templateName when root-level name fields are absent', () => {
660
+ const out = resolveSmsFallbackHydrationFromDetails({
661
+ smsFallBackContent: {
662
+ templateConfigs: { templateName: 'ConfigTemplateName' },
663
+ },
664
+ });
665
+ expect(out.nextSmsState.templateName).toBe('ConfigTemplateName');
666
+ });
667
+
668
+ it('falls back to templateConfigs.name when no other name field is present anywhere', () => {
669
+ const out = resolveSmsFallbackHydrationFromDetails({
670
+ smsFallBackContent: {
671
+ templateConfigs: { name: 'ConfigName' },
672
+ },
673
+ });
674
+ expect(out.nextSmsState.templateName).toBe('ConfigName');
675
+ });
676
+
677
+ it('falls back to the root-level templateName when templateConfigs has no name field', () => {
678
+ const out = resolveSmsFallbackHydrationFromDetails({
679
+ smsFallBackContent: {
680
+ templateName: 'RootName',
681
+ templateConfigs: { registeredSenderIds: ['123'] },
682
+ },
683
+ });
684
+ expect(out.nextSmsState.templateName).toBe('RootName');
685
+ });
686
+
687
+ it('prefers the root templateName over a conflicting nested templateConfigs.name', () => {
688
+ const out = resolveSmsFallbackHydrationFromDetails({
689
+ smsFallBackContent: {
690
+ templateName: 'RootName',
691
+ smsTemplateName: '',
692
+ templateConfigs: { name: 'NestedName', header: ['H1'] },
693
+ },
694
+ });
695
+ expect(out.nextSmsState.templateName).toBe('RootName');
696
+ });
697
+
659
698
  it('is meaningful from var map alone, with no template name or message text', () => {
660
699
  const out = resolveSmsFallbackHydrationFromDetails({
661
700
  smsFallBackContent: { rcsSmsFallbackVarMapped: { '{#a#}_0': 'v' } },