@capillarytech/creatives-library 8.0.359-alpha.0 → 8.0.359-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 (147) hide show
  1. package/constants/unified.js +29 -0
  2. package/index.html +1 -0
  3. package/package.json +1 -1
  4. package/services/tests/api.test.js +35 -20
  5. package/utils/cdnTransformation.js +75 -3
  6. package/utils/commonUtils.js +19 -1
  7. package/utils/rcsPayloadUtils.js +92 -0
  8. package/utils/templateVarUtils.js +201 -0
  9. package/utils/tests/cdnTransformation.test.js +127 -0
  10. package/utils/tests/rcsPayloadUtils.test.js +226 -0
  11. package/utils/tests/templateVarUtils.test.js +204 -0
  12. package/v2Components/CapActionButton/constants.js +7 -0
  13. package/v2Components/CapActionButton/index.js +166 -108
  14. package/v2Components/CapActionButton/index.scss +157 -6
  15. package/v2Components/CapActionButton/messages.js +19 -3
  16. package/v2Components/CapActionButton/tests/index.test.js +41 -17
  17. package/v2Components/CapImageUpload/index.js +2 -2
  18. package/v2Components/CapTagList/index.js +10 -0
  19. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +72 -49
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  21. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +214 -21
  22. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  23. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +83 -9
  24. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  25. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
  26. package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
  27. package/v2Components/CommonTestAndPreview/UnifiedPreview/PreviewHeader.js +16 -0
  28. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +157 -15
  29. package/v2Components/CommonTestAndPreview/UnifiedPreview/ViberPreviewContent.js +14 -132
  30. package/v2Components/CommonTestAndPreview/UnifiedPreview/WebPushPreviewContent.js +169 -0
  31. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +400 -239
  32. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +202 -10
  33. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
  34. package/v2Components/CommonTestAndPreview/constants.js +40 -2
  35. package/v2Components/CommonTestAndPreview/index.js +887 -453
  36. package/v2Components/CommonTestAndPreview/messages.js +45 -3
  37. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  38. package/v2Components/CommonTestAndPreview/sagas.js +25 -6
  39. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +308 -284
  40. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +231 -65
  41. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  42. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
  43. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
  44. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +34 -13
  45. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/PreviewHeader.test.js +163 -0
  46. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
  47. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/ViberPreviewContent.test.js +0 -364
  48. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/WebPushPreviewContent.test.js +522 -0
  49. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +454 -1
  50. package/v2Components/CommonTestAndPreview/tests/constants.test.js +2 -1
  51. package/v2Components/CommonTestAndPreview/tests/index.test.js +327 -4
  52. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  53. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +31 -24
  54. package/v2Components/FormBuilder/index.js +167 -56
  55. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +91 -0
  56. package/v2Components/SmsFallback/constants.js +73 -0
  57. package/v2Components/SmsFallback/index.js +956 -0
  58. package/v2Components/SmsFallback/index.scss +265 -0
  59. package/v2Components/SmsFallback/messages.js +78 -0
  60. package/v2Components/SmsFallback/smsFallbackUtils.js +119 -0
  61. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  62. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  63. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  64. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +223 -0
  65. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +309 -0
  66. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  67. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  68. package/v2Components/TemplatePreview/_templatePreview.scss +37 -22
  69. package/v2Components/TemplatePreview/constants.js +2 -0
  70. package/v2Components/TemplatePreview/index.js +143 -31
  71. package/v2Components/TemplatePreview/tests/index.test.js +142 -0
  72. package/v2Components/TestAndPreviewSlidebox/index.js +15 -3
  73. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  74. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  75. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  76. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  77. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  78. package/v2Containers/App/constants.js +3 -0
  79. package/v2Containers/App/tests/constants.test.js +61 -0
  80. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +17 -0
  81. package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
  82. package/v2Containers/CreativesContainer/SlideBoxFooter.js +14 -5
  83. package/v2Containers/CreativesContainer/SlideBoxHeader.js +36 -5
  84. package/v2Containers/CreativesContainer/constants.js +9 -0
  85. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +79 -0
  86. package/v2Containers/CreativesContainer/index.js +382 -127
  87. package/v2Containers/CreativesContainer/index.scss +83 -1
  88. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  89. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +79 -34
  90. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +79 -16
  91. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
  92. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +357 -98
  93. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -15
  94. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  95. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  96. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  97. package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
  98. package/v2Containers/Rcs/constants.js +120 -11
  99. package/v2Containers/Rcs/index.js +2577 -812
  100. package/v2Containers/Rcs/index.scss +281 -8
  101. package/v2Containers/Rcs/messages.js +34 -3
  102. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +225 -0
  103. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +98036 -70145
  104. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  105. package/v2Containers/Rcs/tests/index.test.js +152 -121
  106. package/v2Containers/Rcs/tests/mockData.js +38 -0
  107. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +318 -0
  108. package/v2Containers/Rcs/tests/utils.test.js +646 -30
  109. package/v2Containers/Rcs/utils.js +478 -11
  110. package/v2Containers/Sms/Create/index.js +106 -40
  111. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  112. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  113. package/v2Containers/SmsTrai/Create/index.js +9 -4
  114. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  115. package/v2Containers/SmsTrai/Edit/index.js +640 -130
  116. package/v2Containers/SmsTrai/Edit/index.scss +121 -0
  117. package/v2Containers/SmsTrai/Edit/messages.js +14 -4
  118. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4328 -2375
  119. package/v2Containers/SmsWrapper/index.js +37 -8
  120. package/v2Containers/TagList/index.js +6 -0
  121. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  122. package/v2Containers/Templates/_templates.scss +166 -86
  123. package/v2Containers/Templates/actions.js +11 -0
  124. package/v2Containers/Templates/constants.js +2 -0
  125. package/v2Containers/Templates/index.js +203 -145
  126. package/v2Containers/Templates/sagas.js +62 -13
  127. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  128. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1062 -1017
  129. package/v2Containers/Templates/tests/sagas.test.js +222 -22
  130. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  131. package/v2Containers/Templates/tests/webpush.test.js +375 -0
  132. package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  133. package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  134. package/v2Containers/TemplatesV2/index.js +86 -23
  135. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  136. package/v2Containers/Viber/constants.js +0 -19
  137. package/v2Containers/Viber/index.js +47 -714
  138. package/v2Containers/Viber/index.scss +0 -148
  139. package/v2Containers/Viber/messages.js +0 -116
  140. package/v2Containers/Viber/tests/index.test.js +0 -80
  141. package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
  142. package/v2Containers/WebPush/Create/index.js +91 -8
  143. package/v2Containers/WebPush/Create/index.scss +7 -0
  144. package/v2Containers/WebPush/Create/tests/getTemplateContent.test.js +348 -0
  145. package/v2Containers/WebPush/Create/tests/testAndPreviewIntegration.test.js +325 -0
  146. package/v2Containers/Whatsapp/index.js +3 -20
  147. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
@@ -37,6 +37,7 @@ import { createStructuredSelector } from 'reselect';
37
37
  import { CAP_SPACE_12, CAP_SPACE_08, FONT_COLOR_05, FONT_COLOR_04 } from '@capillarytech/cap-ui-library/styled/variables';
38
38
  import UnifiedPreview from '../CommonTestAndPreview/UnifiedPreview';
39
39
  import { ANDROID } from '../CommonTestAndPreview/constants';
40
+ import TemplatePreview from '../TemplatePreview';
40
41
  import TagList from '../../v2Containers/TagList';
41
42
  import CapTagListWithInput from '../CapTagListWithInput';
42
43
  import SlideBox from '../SlideBox';
@@ -79,6 +80,69 @@ const errorMessageForTags = {
79
80
  TAG_BRACKET_COUNT_MISMATCH_ERROR: 'tagBracketCountMismatchError'
80
81
  };
81
82
 
83
+ // Isolated input for EMAIL template-name: only this tiny component re-renders on each keystroke.
84
+ // formData is updated only on blur (onCommit), eliminating all re-renders during typing.
85
+ class HighFreqInput extends React.Component {
86
+ constructor(props) {
87
+ super(props);
88
+ this.state = { localValue: props.value || '' };
89
+ }
90
+
91
+ componentDidUpdate(prevProps) {
92
+ if (prevProps.value !== this.props.value && this.state.localValue !== this.props.value) {
93
+ this.setState({ localValue: this.props.value || '' });
94
+ }
95
+ }
96
+
97
+ handleChange = (e) => {
98
+ this.setState({ localValue: e.target.value });
99
+ };
100
+
101
+ handleBlur = (e) => {
102
+ this.props.onCommit(this.state.localValue);
103
+ if (this.props.onBlur) this.props.onBlur(e);
104
+ };
105
+
106
+ render() {
107
+ const { value: _v, onCommit: _oc, onBlur: _ob, ...rest } = this.props;
108
+ return <CapInput {...rest} value={this.state.localValue} onChange={this.handleChange} onBlur={this.handleBlur} />;
109
+ }
110
+ }
111
+
112
+ // Isolated wrapper for EMAIL template-subject: blur-only commit, same as HighFreqInput.
113
+ class HighFreqTagInput extends React.Component {
114
+ constructor(props) {
115
+ super(props);
116
+ this.state = { localInputValue: props.inputValue || '' };
117
+ }
118
+
119
+ componentDidUpdate(prevProps) {
120
+ if (prevProps.inputValue !== this.props.inputValue && this.state.localInputValue !== this.props.inputValue) {
121
+ this.setState({ localInputValue: this.props.inputValue || '' });
122
+ }
123
+ }
124
+
125
+ handleInputChange = (e) => {
126
+ this.setState({ localInputValue: e.target.value });
127
+ };
128
+
129
+ handleBlur = () => {
130
+ this.props.onCommit(this.state.localInputValue);
131
+ };
132
+
133
+ render() {
134
+ const { inputValue: _iv, onCommit: _oc, inputOnChange: _ic, ...rest } = this.props;
135
+ return (
136
+ <CapTagListWithInput
137
+ {...rest}
138
+ inputValue={this.state.localInputValue}
139
+ inputOnChange={this.handleInputChange}
140
+ inputProps={{ ...(this.props.inputProps || {}), onBlur: this.handleBlur }}
141
+ />
142
+ );
143
+ }
144
+ }
145
+
82
146
  class FormBuilder extends React.Component { // eslint-disable-line react/prefer-stateless-function
83
147
  constructor(props) {
84
148
  super(props);
@@ -352,6 +416,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
352
416
  this.setState({tabCount: nextProps.tabCount});
353
417
  }
354
418
  if (nextProps.startValidation && nextProps.startValidation !== false && this.props.startValidation !== nextProps.startValidation) {
419
+ if (this.debouncedUpdateFormData) this.debouncedUpdateFormData.flush();
355
420
  this.setState({checkValidation: true});
356
421
  this.validateForm(null, null, true, true, () => {
357
422
  //triggering the saveFormData or onSubmit when validation sets isFormValid to TRUE
@@ -2989,8 +3054,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
2989
3054
  userLocale={this.props.userLocale}
2990
3055
  selectedOfferDetails={this.props.selectedOfferDetails}
2991
3056
  eventContextTags={this.props?.eventContextTags}
2992
- restrictPersonalization={this.props.restrictPersonalization}
2993
3057
  waitEventContextTags={this.props?.waitEventContextTags}
3058
+ restrictPersonalization={this.props.restrictPersonalization}
2994
3059
  />
2995
3060
  </CapColumn>
2996
3061
  );
@@ -3410,26 +3475,25 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
3410
3475
  ? formatMessage(messages.personalizationTagsErrorMessage)
3411
3476
  : (errorType === TAG_BRACKET_COUNT_MISMATCH_ERROR ? formatMessage(globalMessages.unbalanacedCurlyBraces) : (val.errorMessage && ifError ? val.errorMessage : ''));
3412
3477
  if (styling === 'semantic') {
3413
- columns.push(
3414
- <CapColumn key={val.id} span={val.width} offset={val.offset} style={val.style || {}}>
3415
- <CapInput
3416
- id={val.id}
3417
- errorMessage={errorMessageText}
3418
- label={val.label}
3419
- inductiveText={val.inductiveText}
3420
- className={`input-primary chart-name-input${ifError ? ' error' : ''}`}
3421
- // fluid={val.fluid}
3422
- style={val.style ? val.style : {}}
3423
- placeholder={val.placeholder}
3424
- onChange={(e) => this.updateFormData(e.target.value, val)}
3425
- onBlur={(e) => this.handleFieldBlur(e, val)}
3426
- value={value || ""}
3427
- defaultValue={isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id]}
3428
- disabled={val.disabled}
3429
- size={val.size || "default"}
3430
- />
3431
- {this.props.schema?.channel === EMAIL &&
3432
- !aiContentBotDisabled && (
3478
+ const isEmailStandaloneHighFreq = val.standalone && this.props.schema?.channel?.toUpperCase() === EMAIL;
3479
+ if (isEmailStandaloneHighFreq) {
3480
+ columns.push(
3481
+ <CapColumn key={val.id} span={val.width} offset={val.offset} style={val.style || {}}>
3482
+ <HighFreqInput
3483
+ id={val.id}
3484
+ errorMessage={errorMessageText}
3485
+ label={val.label}
3486
+ inductiveText={val.inductiveText}
3487
+ className={`input-primary chart-name-input${ifError ? ' error' : ''}`}
3488
+ style={val.style ? val.style : {}}
3489
+ placeholder={val.placeholder}
3490
+ onCommit={(newValue) => this.performFormDataUpdate(newValue, val)}
3491
+ onBlur={(e) => this.handleFieldBlur(e, val)}
3492
+ value={value || ""}
3493
+ disabled={val.disabled}
3494
+ size={val.size || "default"}
3495
+ />
3496
+ {!aiContentBotDisabled && (
3433
3497
  <CapAskAira.ContentGenerationBot
3434
3498
  text={value || ""}
3435
3499
  setText={this.handleSetText.bind(this, val)}
@@ -3438,12 +3502,48 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
3438
3502
  rootStyle={{
3439
3503
  bottom: "0.2rem",
3440
3504
  right: "0.2rem",
3441
- left: "auto",
3505
+ left: "auto",
3442
3506
  }}
3443
3507
  />
3444
3508
  )}
3445
- </CapColumn>
3446
- );
3509
+ </CapColumn>
3510
+ );
3511
+ } else {
3512
+ columns.push(
3513
+ <CapColumn key={val.id} span={val.width} offset={val.offset} style={val.style || {}}>
3514
+ <CapInput
3515
+ id={val.id}
3516
+ errorMessage={errorMessageText}
3517
+ label={val.label}
3518
+ inductiveText={val.inductiveText}
3519
+ className={`input-primary chart-name-input${ifError ? ' error' : ''}`}
3520
+ // fluid={val.fluid}
3521
+ style={val.style ? val.style : {}}
3522
+ placeholder={val.placeholder}
3523
+ onChange={(e) => this.updateFormData(e.target.value, val)}
3524
+ onBlur={(e) => this.handleFieldBlur(e, val)}
3525
+ value={value || ""}
3526
+ defaultValue={isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id]}
3527
+ disabled={val.disabled}
3528
+ size={val.size || "default"}
3529
+ />
3530
+ {this.props.schema?.channel === EMAIL &&
3531
+ !aiContentBotDisabled && (
3532
+ <CapAskAira.ContentGenerationBot
3533
+ text={value || ""}
3534
+ setText={this.handleSetText.bind(this, val)}
3535
+ iconPlacement="float-br"
3536
+ iconSize="1.6rem"
3537
+ rootStyle={{
3538
+ bottom: "0.2rem",
3539
+ right: "0.2rem",
3540
+ left: "auto",
3541
+ }}
3542
+ />
3543
+ )}
3544
+ </CapColumn>
3545
+ );
3546
+ }
3447
3547
  }
3448
3548
  break;
3449
3549
 
@@ -3659,8 +3759,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
3659
3759
  selectedOfferDetails={this.props.selectedOfferDetails}
3660
3760
  channel={channel}
3661
3761
  eventContextTags={this.props?.eventContextTags}
3662
- restrictPersonalization={this.props.restrictPersonalization}
3663
3762
  waitEventContextTags={this.props?.waitEventContextTags}
3763
+ restrictPersonalization={this.props.restrictPersonalization}
3664
3764
  />
3665
3765
  </CapColumn>
3666
3766
  );
@@ -3684,37 +3784,48 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
3684
3784
  isBEEAppEnableForCapTagList === false ||
3685
3785
  channelForCapTagList !== 'EMAIL'
3686
3786
  ) {
3787
+ const isEmailStandaloneSubject = val.standalone && channelForCapTagList === EMAIL && val.id === 'template-subject';
3788
+ const tagListProps = {
3789
+ key: `input-${val.id}`,
3790
+ inputId: val.id,
3791
+ inputValue: this.state.formData[val.id] || '',
3792
+ inputPlaceholder: val.placeholder || '',
3793
+ inputErrorMessage: val.errorMessage && ifError ? val.errorMessage : '',
3794
+ inputRequired: val.required || false,
3795
+ inputDisabled: val.disabled || false,
3796
+ headingText: val.label || '',
3797
+ headingStyle: val.headingStyle || { marginTop: '3%', marginRight: '79%' },
3798
+ headingType: "h4",
3799
+ onTagSelect: (data) => this.callChildEvent(data, val, 'onTagSelect'),
3800
+ onContextChange: this.props.onContextChange,
3801
+ location: this.props.location,
3802
+ tags: this.props.tags ? this.props.tags : [],
3803
+ injectedTags: this.props.injectedTags ? this.props.injectedTags : {},
3804
+ className: val.className ? val.className : '',
3805
+ userLocale: this.state.translationLang,
3806
+ selectedOfferDetails: this.props.selectedOfferDetails,
3807
+ eventContextTags: this.props?.eventContextTags,
3808
+ waitEventContextTags: this.props?.waitEventContextTags,
3809
+ moduleFilterEnabled: moduleFilterEnabledForCapTagList,
3810
+ containerStyle: val.style || {},
3811
+ inputProps: val.inputProps || {},
3812
+ showInput: val.showInput !== false,
3813
+ showTagList: val.showTagList !== false,
3814
+ restrictPersonalization: this.props.restrictPersonalization,
3815
+ };
3687
3816
  columns.push(
3688
3817
  <CapColumn key={`input-${val.id}`} offset={val.offset} span={val.width ? val.width : ''} style={val.style ? val.style : {marginBottom: '16px'}}>
3689
- <CapTagListWithInput
3690
- key={`input-${val.id}`}
3691
- inputId={val.id}
3692
- inputValue={this.state.formData[val.id] || ''}
3693
- inputOnChange={(e) => this.updateFormData(e.target.value, val)}
3694
- inputPlaceholder={val.placeholder || ''}
3695
- inputErrorMessage={val.errorMessage && ifError ? val.errorMessage : ''}
3696
- inputRequired={val.required || false}
3697
- inputDisabled={val.disabled || false}
3698
- headingText={val.label || ''}
3699
- headingStyle={val.headingStyle || { marginTop: '3%', marginRight: '79%' }}
3700
- headingType="h4"
3701
- onTagSelect={(data) => this.callChildEvent(data, val, 'onTagSelect')}
3702
- onContextChange={this.props.onContextChange}
3703
- location={this.props.location}
3704
- tags={this.props.tags ? this.props.tags : []}
3705
- injectedTags={this.props.injectedTags ? this.props.injectedTags : {}}
3706
- className={val.className ? val.className : ''}
3707
- userLocale={this.state.translationLang}
3708
- selectedOfferDetails={this.props.selectedOfferDetails}
3709
- eventContextTags={this.props?.eventContextTags}
3710
- waitEventContextTags={this.props?.waitEventContextTags}
3711
- moduleFilterEnabled={moduleFilterEnabledForCapTagList}
3712
- containerStyle={val.style || {}}
3713
- inputProps={val.inputProps || {}}
3714
- showInput={val.showInput !== false}
3715
- showTagList={val.showTagList !== false}
3716
- restrictPersonalization={this.props.restrictPersonalization}
3717
- />
3818
+ {isEmailStandaloneSubject ? (
3819
+ <HighFreqTagInput
3820
+ {...tagListProps}
3821
+ onCommit={(newValue) => this.performFormDataUpdate(newValue, val)}
3822
+ />
3823
+ ) : (
3824
+ <CapTagListWithInput
3825
+ {...tagListProps}
3826
+ inputOnChange={(e) => this.updateFormData(e.target.value, val)}
3827
+ />
3828
+ )}
3718
3829
  </CapColumn>
3719
3830
  );
3720
3831
  }
@@ -4307,8 +4418,8 @@ FormBuilder.defaultProps = {
4307
4418
  userLocale: localStorage.getItem('jlocale') || 'en',
4308
4419
  showLiquidErrorInFooter: () => {},
4309
4420
  metaDataStatus: "",
4310
- waitEventContextTags: {},
4311
4421
  isTestAndPreviewMode: false, // Default to false to maintain existing behavior
4422
+ waitEventContextTags: {},
4312
4423
  };
4313
4424
 
4314
4425
  FormBuilder.propTypes = {
@@ -4356,7 +4467,7 @@ FormBuilder.propTypes = {
4356
4467
  type: PropTypes.string.isRequired,
4357
4468
  isEmailLoading: PropTypes.bool.isRequired,
4358
4469
  moduleType: PropTypes.string.isRequired,
4359
- showLiquidErrorInFooter: PropTypes.bool.isRequired,
4470
+ showLiquidErrorInFooter: PropTypes.func.isRequired,
4360
4471
  eventContextTags: PropTypes.array.isRequired,
4361
4472
  waitEventContextTags: PropTypes.object,
4362
4473
  forwardedTags: PropTypes.object.isRequired,
@@ -0,0 +1,91 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import CreativesContainer from '../../v2Containers/CreativesContainer';
4
+ import CapPageSpinner from '../CapPageSpinner';
5
+ import {
6
+ EMBEDDED_SMS_CREATIVES_LOCATION,
7
+ SMS_FALLBACK_CHANNEL_KEY,
8
+ SMS_FALLBACK_CREATIVE_EDITOR,
9
+ SMS_FALLBACK_ENABLE_NEW_CHANNELS,
10
+ } from './constants';
11
+
12
+ /**
13
+ * Reuse the exact embedded CreativesContainer SMS flow (same as normal SMS create).
14
+ * Avoid overriding Templates with local config so "Create new" follows built-in createTemplate path.
15
+ */
16
+ export function SmsFallbackLocalSelector({
17
+ hidden,
18
+ fetchDetailsLoading,
19
+ templateList,
20
+ channelsToHide,
21
+ smsRegister,
22
+ onCloseCreatives,
23
+ onSelectTemplate,
24
+ filterContent,
25
+ location,
26
+ /** Required when user completes embedded SMS create/edit — `CreativesContainer` calls this on save (see `processCentralCommsMetaId`). */
27
+ getCreativesData,
28
+ }) {
29
+ const rootClassName = [
30
+ 'sms-fallback-selector',
31
+ hidden ? 'sms-fallback-selector--visually-hidden' : '',
32
+ ]
33
+ .filter(Boolean)
34
+ .join(' ');
35
+
36
+ return (
37
+ <div
38
+ className={rootClassName}
39
+ aria-hidden={hidden}
40
+ inert={hidden ? '' : undefined}
41
+ >
42
+ {fetchDetailsLoading && (
43
+ <div className="sms-fallback-selector__loading" aria-busy="true" aria-live="polite">
44
+ <CapPageSpinner spinning />
45
+ </div>
46
+ )}
47
+ <CreativesContainer
48
+ creativesMode="create"
49
+ location={location || EMBEDDED_SMS_CREATIVES_LOCATION}
50
+ templateData={null}
51
+ handleCloseCreatives={onCloseCreatives}
52
+ isFullMode={false}
53
+ smsRegister={smsRegister}
54
+ editor={SMS_FALLBACK_CREATIVE_EDITOR}
55
+ enableNewChannels={SMS_FALLBACK_ENABLE_NEW_CHANNELS}
56
+ channel={SMS_FALLBACK_CHANNEL_KEY}
57
+ channelsToHide={channelsToHide}
58
+ selectedBadges={[]}
59
+ localTemplatesConfig={{
60
+ useLocalTemplates: true,
61
+ localTemplates: templateList.templates,
62
+ localTemplatesLoading: templateList.loading,
63
+ localTemplatesFilterContent: filterContent,
64
+ localTemplatesOnPageChange: templateList.loadMore,
65
+ localTemplatesUseSkeleton: true,
66
+ }}
67
+ onSelectTemplate={onSelectTemplate}
68
+ getCreativesData={getCreativesData}
69
+ />
70
+ </div>
71
+ );
72
+ }
73
+
74
+ SmsFallbackLocalSelector.propTypes = {
75
+ hidden: PropTypes.bool,
76
+ fetchDetailsLoading: PropTypes.bool,
77
+ templateList: PropTypes.shape({
78
+ templates: PropTypes.array,
79
+ loading: PropTypes.bool,
80
+ loadMore: PropTypes.func,
81
+ }).isRequired,
82
+ channelsToHide: PropTypes.arrayOf(PropTypes.string),
83
+ smsRegister: PropTypes.any,
84
+ onCloseCreatives: PropTypes.func.isRequired,
85
+ onSelectTemplate: PropTypes.func.isRequired,
86
+ filterContent: PropTypes.node,
87
+ location: PropTypes.object,
88
+ getCreativesData: PropTypes.func.isRequired,
89
+ };
90
+
91
+ export default SmsFallbackLocalSelector;
@@ -0,0 +1,73 @@
1
+ import {
2
+ WHATSAPP,
3
+ RCS,
4
+ ZALO,
5
+ WEBPUSH,
6
+ } from '../../v2Containers/CreativesContainer/constants';
7
+
8
+ /**
9
+ * View modes for the SMS fallback slidebox (template list, create, edit).
10
+ * Used by SmsFallback and any channel that reuses it (RCS, etc.).
11
+ */
12
+ export const SMS_FALLBACK_VIEW = {
13
+ SELECTING: 'selecting',
14
+ CREATING: 'creating',
15
+ EDITING: 'editing',
16
+ };
17
+
18
+ /**
19
+ * Channel keys to hide in TemplatesV2 so only SMS tab is shown.
20
+ * Uses normalized keys matching TemplatesV2 pane.key normalization (lowercase).
21
+ * Parent can override via channelsToHide prop.
22
+ */
23
+ export const CHANNELS_TO_HIDE_FOR_SMS_ONLY = [
24
+ 'email',
25
+ 'mobilepush',
26
+ 'webpush',
27
+ 'viber',
28
+ 'whatsapp',
29
+ 'zalo',
30
+ 'facebook',
31
+ 'rcs',
32
+ 'inapp',
33
+ 'line',
34
+ 'wechat',
35
+ 'call_task',
36
+ 'ftp',
37
+ 'assets',
38
+ ];
39
+
40
+ /** DLT category filter values — aligned with Templates `SMS_FILTERS` / `filterSMSTemplates`. */
41
+ export const SMS_CATEGORY_FILTERS = {
42
+ ALL: 'all',
43
+ PROMOTIONAL: 'promo',
44
+ SERVICE_EXPLICIT: 'explicit',
45
+ SERVICE_IMPLICIT: 'implicit',
46
+ };
47
+
48
+ /** `location` for embedded SMS creatives picker (CreativesContainer / TemplatesV2). */
49
+ export const EMBEDDED_SMS_CREATIVES_LOCATION = {
50
+ pathname: '/sms/create',
51
+ query: { type: 'embedded', module: 'library' },
52
+ search: '',
53
+ };
54
+
55
+ /** `location` for embedded SMS TRAI edit inside slidebox. */
56
+ export const EMBEDDED_SMS_CREATIVES_EDIT_LOCATION = {
57
+ pathname: '/sms/edit',
58
+ query: { type: 'embedded', module: 'library' },
59
+ search: '',
60
+ };
61
+
62
+ /** API `channel` param for `getTemplateDetails` when loading an SMS template by id. */
63
+ export const SMS_TEMPLATE_DETAILS_API_CHANNEL = 'Sms';
64
+
65
+ export const SMS_FALLBACK_CREATIVE_EDITOR = 'BEE';
66
+
67
+ export const SMS_FALLBACK_CHANNEL_KEY = 'sms';
68
+
69
+ /** Route shape passed to SmsWrapper / SmsTraiEdit for embedded SMS flows. */
70
+ export const SMS_FALLBACK_ROUTE = { name: SMS_FALLBACK_CHANNEL_KEY };
71
+
72
+ /** Channels enabled in the SMS-only embedded picker (hide others via `channelsToHide`). */
73
+ export const SMS_FALLBACK_ENABLE_NEW_CHANNELS = [WHATSAPP, RCS, ZALO, WEBPUSH];