@capillarytech/creatives-library 8.0.345-alpha.13 → 8.0.345-alpha.15

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 (138) hide show
  1. package/constants/unified.js +29 -0
  2. package/package.json +1 -1
  3. package/services/api.js +0 -20
  4. package/services/tests/api.test.js +13 -59
  5. package/utils/commonUtils.js +19 -1
  6. package/utils/rcsPayloadUtils.js +92 -0
  7. package/utils/templateVarUtils.js +201 -0
  8. package/utils/tests/templateVarUtils.test.js +204 -0
  9. package/v2Components/CapActionButton/constants.js +7 -0
  10. package/v2Components/CapActionButton/index.js +167 -109
  11. package/v2Components/CapActionButton/index.scss +157 -6
  12. package/v2Components/CapActionButton/messages.js +19 -3
  13. package/v2Components/CapActionButton/tests/index.test.js +41 -17
  14. package/v2Components/CapCustomSkeleton/index.js +1 -1
  15. package/v2Components/CapCustomSkeleton/tests/__snapshots__/index.test.js.snap +12 -12
  16. package/v2Components/CapTagList/index.js +10 -0
  17. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
  18. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  19. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +207 -21
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  21. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
  22. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  23. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
  24. package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
  25. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +160 -15
  26. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js.rej +18 -0
  27. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +341 -76
  28. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
  29. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
  30. package/v2Components/CommonTestAndPreview/constants.js +38 -2
  31. package/v2Components/CommonTestAndPreview/index.js +676 -186
  32. package/v2Components/CommonTestAndPreview/messages.js +49 -3
  33. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  34. package/v2Components/CommonTestAndPreview/sagas.js +15 -6
  35. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +308 -284
  36. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +231 -65
  37. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  38. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
  39. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
  40. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +34 -13
  41. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
  42. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
  43. package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -4
  44. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  45. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
  46. package/v2Components/FormBuilder/index.js +8 -10
  47. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
  48. package/v2Components/SmsFallback/constants.js +73 -0
  49. package/v2Components/SmsFallback/index.js +955 -0
  50. package/v2Components/SmsFallback/index.scss +265 -0
  51. package/v2Components/SmsFallback/messages.js +78 -0
  52. package/v2Components/SmsFallback/smsFallbackUtils.js +118 -0
  53. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  54. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  55. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  56. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
  57. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +277 -0
  58. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  59. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  60. package/v2Components/TemplatePreview/_templatePreview.scss +33 -23
  61. package/v2Components/TemplatePreview/constants.js +2 -0
  62. package/v2Components/TemplatePreview/index.js +143 -28
  63. package/v2Components/TemplatePreview/tests/index.test.js +142 -0
  64. package/v2Components/TestAndPreviewSlidebox/index.js +13 -1
  65. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  66. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  67. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  68. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  69. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  70. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  71. package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
  72. package/v2Containers/CreativesContainer/SlideBoxFooter.js +11 -4
  73. package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  74. package/v2Containers/CreativesContainer/constants.js +9 -0
  75. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
  76. package/v2Containers/CreativesContainer/index.js +300 -108
  77. package/v2Containers/CreativesContainer/index.scss +51 -1
  78. package/v2Containers/CreativesContainer/messages.js +0 -4
  79. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  80. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +78 -34
  81. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +79 -16
  82. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
  83. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +357 -98
  84. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -18
  85. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  86. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  87. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  88. package/v2Containers/Rcs/constants.js +119 -8
  89. package/v2Containers/Rcs/index.js +2379 -807
  90. package/v2Containers/Rcs/index.js.rej +1336 -0
  91. package/v2Containers/Rcs/index.scss +276 -6
  92. package/v2Containers/Rcs/index.scss.rej +74 -0
  93. package/v2Containers/Rcs/messages.js +38 -3
  94. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +225 -0
  95. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +98018 -70073
  96. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  97. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap.rej +128 -0
  98. package/v2Containers/Rcs/tests/index.test.js +152 -121
  99. package/v2Containers/Rcs/tests/mockData.js +38 -0
  100. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +318 -0
  101. package/v2Containers/Rcs/tests/utils.test.js +646 -30
  102. package/v2Containers/Rcs/utils.js +478 -11
  103. package/v2Containers/Sms/Create/index.js +100 -40
  104. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  105. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  106. package/v2Containers/SmsTrai/Create/index.js +9 -4
  107. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  108. package/v2Containers/SmsTrai/Edit/index.js +636 -130
  109. package/v2Containers/SmsTrai/Edit/index.scss +121 -0
  110. package/v2Containers/SmsTrai/Edit/messages.js +14 -4
  111. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4328 -2375
  112. package/v2Containers/SmsWrapper/index.js +37 -8
  113. package/v2Containers/TagList/index.js +6 -0
  114. package/v2Containers/Templates/ChannelTypeIllustration.js +6 -23
  115. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  116. package/v2Containers/Templates/_templates.scss +181 -126
  117. package/v2Containers/Templates/actions.js +11 -36
  118. package/v2Containers/Templates/constants.js +2 -23
  119. package/v2Containers/Templates/index.js +142 -333
  120. package/v2Containers/Templates/messages.js +0 -68
  121. package/v2Containers/Templates/reducer.js +0 -68
  122. package/v2Containers/Templates/sagas.js +55 -98
  123. package/v2Containers/Templates/selectors.js +0 -12
  124. package/v2Containers/Templates/tests/ChannelTypeIllustration.test.js +0 -12
  125. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  126. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1042 -1256
  127. package/v2Containers/Templates/tests/index.test.js +0 -6
  128. package/v2Containers/Templates/tests/reducer.test.js +0 -178
  129. package/v2Containers/Templates/tests/sagas.test.js +200 -436
  130. package/v2Containers/Templates/tests/selector.test.js +0 -32
  131. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -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/Whatsapp/index.js +3 -20
  137. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
  138. package/v2Containers/Assets/images/archive_Empty_Illustration.svg +0 -9
@@ -10,12 +10,14 @@ import { isTraiDLTEnable } from '../../utils/common';
10
10
  import SmsEdit from '../Sms/Edit';
11
11
  import SmsTraiCreate from '../SmsTrai/Create';
12
12
  import SmsTraiEdit from '../SmsTrai/Edit';
13
+
13
14
  const SmsWrapper = (props) => {
14
15
  const {
15
16
  isCreateSms,
16
17
  isEditSms,
17
18
  setIsLoadingContent,
18
19
  location,
20
+ route: routeFromProps,
19
21
  isGetFormData,
20
22
  getFormSubscriptionData,
21
23
  isFullMode,
@@ -38,15 +40,33 @@ const SmsWrapper = (props) => {
38
40
  handleCloseTestAndPreview,
39
41
  isTestAndPreviewMode,
40
42
  onValidationFail,
43
+ embeddedSmsFallback = false,
44
+ onEmbeddedSmsFooterValidity,
45
+ forceFullTagContext = false,
41
46
  } = props;
42
47
 
48
+ /** FormBuilder / SMS Create assume `location.query`; connected-router shapes may omit it. */
49
+ const smsLocation = (() => {
50
+ const loc = location || {};
51
+ const q = loc.query;
52
+ if (q && typeof q === 'object') {
53
+ return { ...loc, query: { ...q } };
54
+ }
55
+ return {
56
+ pathname: loc.pathname || '/sms/create',
57
+ search: loc.search || '',
58
+ query: { type: 'embedded', module: 'library' },
59
+ };
60
+ })();
61
+
43
62
  const smsProps = {
44
63
  onCreateComplete,
45
64
  setIsLoadingContent,
46
- location,
47
- route: { name: 'sms' },
65
+ location: smsLocation,
66
+ route: routeFromProps || { name: 'sms' },
48
67
  isGetFormData,
49
68
  getFormSubscriptionData,
69
+ templateData,
50
70
  getDefaultTags,
51
71
  isFullMode,
52
72
  forwardedTags,
@@ -62,24 +82,33 @@ const SmsWrapper = (props) => {
62
82
  handleCloseTestAndPreview,
63
83
  isTestAndPreviewMode,
64
84
  onValidationFail,
85
+ forceFullTagContext,
86
+ embeddedSmsFallback,
87
+ onEmbeddedSmsFooterValidity,
88
+ ...(embeddedSmsFallback
89
+ ? {
90
+ tagListGetPopupContainer: () => document.body,
91
+ tagListPopoverOverlayStyle: { zIndex: 10020 },
92
+ tagListPopoverOverlayClassName: 'sms-fallback-taglist-popover rcs-sms-fallback-taglist-popover',
93
+ }
94
+ : {}),
65
95
  };
66
- const isTraiDlt = isTraiDLTEnable(isFullMode, smsRegister);
96
+ const useTraiSmsFlow = isTraiDLTEnable(isFullMode, smsRegister);
67
97
  return <>
68
98
  {
69
- isCreateSms && (isTraiDlt ?
99
+ isCreateSms && (useTraiSmsFlow ?
70
100
  <SmsTraiCreate
71
101
  isComponent
72
102
  {...smsProps}
73
103
  onShowTemplates={onShowTemplates}
74
104
  /> :
75
105
  <SmsCreate
76
- isComponent {
77
- ...smsProps
78
- }
106
+ isComponent
107
+ {...smsProps}
79
108
  />
80
109
  )
81
110
  }
82
- {isEditSms && (isTraiDlt ?
111
+ {isEditSms && (useTraiSmsFlow ?
83
112
  <SmsTraiEdit
84
113
  {...smsProps}
85
114
  params={{id: templateData._id}}
@@ -477,6 +477,9 @@ export class TagList extends React.Component { // eslint-disable-line react/pref
477
477
  disableTooltipMsg={tooltipMsg}
478
478
  fetchingSchemaError={this?.state?.tagsError}
479
479
  popoverPlacement={this.props.popoverPlacement}
480
+ overlayStyle={this.props.popoverOverlayStyle}
481
+ overlayClassName={this.props.popoverOverlayClassName}
482
+ getPopupContainer={this.props.getPopupContainer}
480
483
  />
481
484
  </div>
482
485
  );
@@ -513,6 +516,9 @@ TagList.propTypes = {
513
516
  // message to show when Add Label button is disabled (e.g. personalization restriction)
514
517
  disableTooltipMsg: PropTypes.string,
515
518
  restrictPersonalization: PropTypes.bool,
519
+ popoverOverlayStyle: PropTypes.object,
520
+ popoverOverlayClassName: PropTypes.string,
521
+ getPopupContainer: PropTypes.func,
516
522
  intl: PropTypes.shape({
517
523
  formatMessage: PropTypes.func.isRequired,
518
524
  locale: PropTypes.string,
@@ -1,9 +1,5 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import zaloillustration from '@capillarytech/cap-ui-library/assets/images/featureUiNotEnabledIllustration.svg';
4
- import inAppIllustration from '@capillarytech/cap-ui-library/assets/images/featureUiNotEnabledIllustration.svg';
5
- import { FormattedMessage } from 'react-intl';
6
- import { CapIllustration } from "@capillarytech/cap-ui-library";
7
3
  import emailIllustration from '../Assets/images/emailIllustration.svg';
8
4
  import smsIllustration from '../Assets/images/smsIllustration.svg';
9
5
  import pushIllustration from '../Assets/images/pushIllustration.svg';
@@ -12,12 +8,13 @@ import lineIllustration from '../Assets/images/lineIllustration.svg';
12
8
  import facebookIllustration from '../Assets/images/facebookIllustration.svg';
13
9
  import whatsappIllustration from '../Assets/images/whatsappIllustration.png';
14
10
  import whatsappOrZaloAccountIllustration from '../Assets/images/whatsappOrZaloAccountIllustration.svg';
15
- import archiveEmptyStateIllustration from '../Assets/images/archive_Empty_Illustration.svg';
16
11
  import rcsIllustration from '../Assets/images/rcsIllustration.png';
12
+ import zaloillustration from '@capillarytech/cap-ui-library/assets/images/featureUiNotEnabledIllustration.svg';
13
+ import inAppIllustration from '@capillarytech/cap-ui-library/assets/images/featureUiNotEnabledIllustration.svg';
17
14
  import messages from './messages';
18
- import {
19
- MOBILE_PUSH, SMS, EMAIL, LINE, VIBER, FACEBOOK, WHATSAPP, RCS, ZALO, INAPP, WEBPUSH,
20
- } from '../CreativesContainer/constants';
15
+ import { FormattedMessage } from 'react-intl';
16
+ import { CapIllustration } from "@capillarytech/cap-ui-library";
17
+ import { MOBILE_PUSH, SMS, EMAIL, LINE, VIBER, FACEBOOK, WHATSAPP, RCS, ZALO, INAPP, WEBPUSH } from '../CreativesContainer/constants';
21
18
 
22
19
 
23
20
  // Configuration object for channel types
@@ -83,8 +80,7 @@ function ChannelTypeIllustration(props) {
83
80
  isFullMode,
84
81
  createTemplate,
85
82
  currentChannel,
86
- hostName,
87
- isArchivedMode,
83
+ hostName
88
84
  } = props;
89
85
 
90
86
  const templateText = useMemo(() => {
@@ -92,18 +88,6 @@ function ChannelTypeIllustration(props) {
92
88
  return isFullMode ? templateIntlMsg : '';
93
89
  }, [isFullMode]);
94
90
 
95
- if (isArchivedMode) {
96
- return (
97
- <CapIllustration
98
- illustrationImage={archiveEmptyStateIllustration}
99
- title={<FormattedMessage {...messages.noArchivedCreatives} />}
100
- description={<FormattedMessage {...messages.noArchivedCreativesDesc} />}
101
- descriptionPosition="bottom"
102
- descriptionClassName="illustration-desc archive-illustration"
103
- />
104
- );
105
- }
106
-
107
91
  const getChannelTypeIllustrationInfo = (type, hostName) => {
108
92
  // Handle special cases with hostName dependency
109
93
  if (type === WHATSAPP) {
@@ -212,6 +196,5 @@ ChannelTypeIllustration.propTypes = {
212
196
  createTemplate: PropTypes.func.isRequired,
213
197
  currentChannel: PropTypes.string,
214
198
  hostName: PropTypes.string,
215
- isArchivedMode: PropTypes.bool,
216
199
  };
217
200
  export default ChannelTypeIllustration;
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import CapInput from '@capillarytech/cap-ui-library/CapInput';
4
+ import CapButton from '@capillarytech/cap-ui-library/CapButton';
5
+
6
+ /**
7
+ * Reusable action bar for template pickers.
8
+ * Layout and spacing live in `_templates.scss` (`.action-container`, `.action-container__toolbar-row`).
9
+ * Default search field width: `.action-container__toolbar-row .search-text` (13.125rem).
10
+ * Pass `searchInputClassName` / `searchInputStyle` to override (defaults match Templates list: 210px per master).
11
+ */
12
+ const TemplatesActionBar = ({
13
+ searchValue,
14
+ onSearchChange,
15
+ onSearch,
16
+ onClear,
17
+ searchPlaceholder,
18
+ searchInputClassName,
19
+ searchInputStyle,
20
+ ctaLabel,
21
+ onCtaClick,
22
+ ctaDisabled,
23
+ ctaClassName,
24
+ ctaNode,
25
+ children,
26
+ showCta = true,
27
+ }) => (
28
+ <div className="action-container">
29
+ <div className="action-container__toolbar-row">
30
+ {searchPlaceholder && (
31
+ <CapInput.Search
32
+ className={['search-text', searchInputClassName].filter(Boolean).join(' ')}
33
+ placeholder={searchPlaceholder}
34
+ value={searchValue}
35
+ onChange={onSearchChange}
36
+ /* antd `Input` (used by CapInput.Search) has no `onSearch`; only `Input.Search` does. */
37
+ onPressEnter={(e) => {
38
+ if (onSearch) {
39
+ const v = e?.target && 'value' in e.target ? e.target.value : searchValue;
40
+ onSearch(v);
41
+ }
42
+ }}
43
+ onSearch={onSearch}
44
+ onClear={onClear}
45
+ onScroll={(e) => e.stopPropagation()}
46
+ />
47
+ )}
48
+ {children}
49
+ </div>
50
+ {showCta && (
51
+ <div>
52
+ {ctaNode || (
53
+ <CapButton
54
+ className={ctaClassName}
55
+ type="primary"
56
+ disabled={ctaDisabled}
57
+ onClick={onCtaClick}
58
+ >
59
+ {ctaLabel}
60
+ </CapButton>
61
+ )}
62
+ </div>
63
+ )}
64
+ </div>
65
+ );
66
+
67
+ TemplatesActionBar.propTypes = {
68
+ searchValue: PropTypes.string,
69
+ onSearchChange: PropTypes.func,
70
+ onSearch: PropTypes.func,
71
+ onClear: PropTypes.func,
72
+ searchPlaceholder: PropTypes.string,
73
+ searchInputClassName: PropTypes.string,
74
+ searchInputStyle: PropTypes.object,
75
+ ctaLabel: PropTypes.node,
76
+ onCtaClick: PropTypes.func,
77
+ ctaDisabled: PropTypes.bool,
78
+ ctaClassName: PropTypes.string,
79
+ ctaNode: PropTypes.node,
80
+ children: PropTypes.node,
81
+ showCta: PropTypes.bool,
82
+ };
83
+
84
+ TemplatesActionBar.defaultProps = {
85
+ searchValue: '',
86
+ onSearchChange: () => {},
87
+ onSearch: () => {},
88
+ onClear: () => {},
89
+ searchPlaceholder: '',
90
+ searchInputClassName: '',
91
+ searchInputStyle: { width: '210px' },
92
+ ctaLabel: null,
93
+ onCtaClick: () => {},
94
+ ctaDisabled: false,
95
+ ctaClassName: '',
96
+ ctaNode: null,
97
+ children: null,
98
+ };
99
+
100
+ export default TemplatesActionBar;
101
+
@@ -1,36 +1,59 @@
1
1
  @import '~@capillarytech/cap-ui-library/styles/_variables.scss';
2
2
 
3
3
  .ant-tabs-content{
4
- margin-top: $CAP_SPACE_16;
4
+ margin-top: 16px;
5
+ // .creatives-templates-list.full-mode{
6
+ .v2-pagination-container, .v2-pagination-container-half {
5
7
  .ant-tabs-tabpane-active{
6
8
  padding: unset;
7
9
  }
8
10
  }
11
+ }
9
12
 
10
- // 3 cards per row across all breakpoints
11
- .creatives-templates-list {
12
- .v2-pagination-container,
13
- .v2-pagination-container-half {
14
- .cap-custom-card-list-row {
15
- .cap-custom-card-list-col {
16
- width: calc(33.33% - #{$CAP_SPACE_08});
17
- margin-right: $CAP_SPACE_12;
18
- &:nth-child(3n) {
19
- margin-right: 0;
13
+ @media screen and (max-width: 1172px) {
14
+ .creatives-templates-list.full-mode{
15
+ .v2-pagination-container {
16
+ .cap-custom-card-list-row {
17
+ .cap-custom-card-list-col{
18
+ &:nth-child(3n+3) { //every 4th child
19
+ margin-right: unset;
20
+ }
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
26
+ // }
27
+
28
+ @media screen and (min-width: 1172px) {
29
+ .creatives-templates-list.full-mode{
30
+ .v2-pagination-container, .v2-pagination-container-half {
31
+ .creatives-templates-list.full-mode{
32
+ .v2-pagination-container {
33
+ .cap-custom-card-list-row {
34
+ .cap-custom-card-list-col{
35
+ &:nth-child(4n+4) { //every 4th child
36
+ margin-right: unset;
37
+ }
20
38
  }
21
39
  }
22
40
  }
23
41
  }
42
+ }
43
+ }
24
44
  }
25
45
 
46
+
26
47
  .creatives-templates-list {
27
48
 
28
49
  .delete-template-confirm {
29
50
  .ant-modal-footer {
30
51
  padding: $CAP_SPACE_16 $CAP_SPACE_24 $CAP_SPACE_24 $CAP_SPACE_24;
31
52
  }
53
+ }
32
54
 
33
55
  .ant-modal-header {
56
+ .v2-pagination-container, .v2-pagination-container-half {
34
57
  padding: $CAP_SPACE_24 $CAP_SPACE_24 $CAP_SPACE_08 $CAP_SPACE_24;
35
58
  }
36
59
 
@@ -169,10 +192,13 @@
169
192
  .whatsapp-container {
170
193
  background-color: $CAP_WHITE;
171
194
  padding: $CAP_SPACE_12;
195
+ overflow-y: hidden;
172
196
  }
173
197
  .scroll-container {
174
198
  overflow-x: auto;
175
199
  display: flex;
200
+ flex-wrap: nowrap;
201
+ width: 100%;
176
202
  padding-top: $CAP_SPACE_06;
177
203
  padding-right: $CAP_SPACE_06;
178
204
  white-space: nowrap;
@@ -206,6 +232,92 @@
206
232
  }
207
233
  }
208
234
 
235
+ // RCS template listing preview: match WhatsApp carousel "peek" behavior
236
+ .RCS {
237
+ .cap-custom-card {
238
+ .ant-card-body {
239
+ .ant-card-meta {
240
+ background-color: $CAP_G09;
241
+ padding: 0;
242
+ .ant-card-meta-description {
243
+ .whatsapp-container,.cap-rcs-creatives {
244
+ background-color: $CAP_WHITE;
245
+ padding: $CAP_SPACE_12;
246
+ border-radius: 0.25rem;
247
+ .cap-divider-v2{
248
+ margin: $CAP_SPACE_12 0;
249
+ }
250
+ }
251
+ .scroll-container {
252
+ overflow-x: auto;
253
+ overflow-y: hidden;
254
+ display: flex;
255
+ flex-wrap: nowrap;
256
+ padding-top: $CAP_SPACE_06;
257
+ padding-right: $CAP_SPACE_06;
258
+ white-space: nowrap;
259
+ scrollbar-width: none; // Hide scrollbar in Firefox
260
+ &::-webkit-scrollbar {
261
+ display: none; // Hide scrollbar in Chrome/Safari/Opera
262
+ }
263
+ .whatsapp-carousel-container {
264
+ padding: $CAP_SPACE_04 0px $CAP_SPACE_08;
265
+ border-radius: $CAP_SPACE_06;
266
+ background-color: $CAP_WHITE;
267
+ width: 80%;
268
+ flex-shrink: 0;
269
+ margin-right: $CAP_SPACE_04;
270
+ white-space: pre-wrap;
271
+ word-break: break-word;
272
+ overflow: auto;
273
+ text-align: left;
274
+ .whatsapp-carousel-card {
275
+ margin: $CAP_SPACE_02 $CAP_SPACE_06 $CAP_SPACE_01 $CAP_SPACE_08;
276
+ .whatsapp-carousel-body {
277
+ margin-bottom: $CAP_SPACE_08;
278
+ white-space: pre-wrap;
279
+ }
280
+ }
281
+ }
282
+ }
283
+
284
+ // RCS CTA buttons in listing (reuse WhatsApp-ish look)
285
+ .rcs-cta-preview {
286
+ margin: $CAP_SPACE_12 0;
287
+ display: flex;
288
+ justify-content: center;
289
+ font-size: $FONT_SIZE_M;
290
+ align-items: center;
291
+ color: #1970DA;
292
+ svg {
293
+ margin-right: $CAP_SPACE_04;
294
+ }
295
+ }
296
+
297
+ .rcs-video-preview-placeholder {
298
+ background: #f5f5f5;
299
+ display: flex;
300
+ align-items: center;
301
+ justify-content: center;
302
+ }
303
+
304
+ .rcs-video-preview-label {
305
+ color: #7a7a7a;
306
+ }
307
+
308
+ .rcs-listing-title {
309
+ font-weight: 600;
310
+ }
311
+
312
+ .whatsapp-divider {
313
+ margin: 0;
314
+ }
315
+ }
316
+ }
317
+ }
318
+ }
319
+ }
320
+
209
321
  .MOBILEPUSH {
210
322
  .ant-card-body {
211
323
  padding: 0;
@@ -647,11 +759,29 @@
647
759
  }
648
760
 
649
761
  .action-container{
650
- margin-top: 8px;
651
- margin-bottom: 16px;
762
+ margin-top: $CAP_SPACE_08;
763
+ margin-bottom: $CAP_SPACE_16;
652
764
  display: flex;
653
765
  justify-content: space-between;
654
766
  align-items: center;
767
+
768
+ &__toolbar-row {
769
+ display: flex;
770
+ align-items: center;
771
+ gap: 0.75rem;
772
+ }
773
+
774
+ &__toolbar-row .search-text {
775
+ width: 13.125rem;
776
+ min-width: 13.125rem;
777
+ flex: 1;
778
+ }
779
+
780
+ &__create-row {
781
+ display: flex;
782
+ justify-content: space-between;
783
+ align-items: center;
784
+ }
655
785
  }
656
786
 
657
787
  .popover-action-container:hover{
@@ -662,32 +792,6 @@
662
792
  font-size: 14px;
663
793
  }
664
794
 
665
- // Archive/Unarchive confirm modal overrides — scoped to avoid affecting other modals
666
- .archive-confirm-modal {
667
- // Remove the left margin added when an icon is present
668
- .ant-modal-confirm-body {
669
- > .anticon + .ant-modal-confirm-title + .ant-modal-confirm-content {
670
- margin-left: 0;
671
- }
672
- }
673
-
674
- // Left-align buttons, remove float
675
- .ant-modal-confirm-btns {
676
- float: none;
677
- display: flex;
678
- align-items: center;
679
- gap: $CAP_SPACE_08;
680
- margin-top: $CAP_SPACE_16;
681
-
682
- // Cancel button styling
683
- .ant-btn:not(.ant-btn-primary) {
684
- background-color: $CAP_G08;
685
- border-color: $CAP_G08;
686
- color: $CAP_G01;
687
- }
688
- }
689
- }
690
-
691
795
  .popover-action-container {
692
796
  line-height: 24px;
693
797
  }
@@ -1117,94 +1221,45 @@
1117
1221
  overflow: 'auto';
1118
1222
  }
1119
1223
 
1120
- // Archive feature layout classes
1121
- .illustration-scroll-wrapper {
1122
- height: calc(100vh - 20.3125rem);
1123
- overflow: auto;
1124
- }
1125
-
1126
- .filter-row {
1127
- display: flex;
1128
- align-items: center;
1129
- justify-content: space-between;
1130
- width: 100%;
1131
- }
1132
-
1133
- .filter-row-content {
1134
- flex: 1;
1135
- }
1136
-
1137
- .bulk-selection-bar {
1138
- display: flex;
1139
- align-items: center;
1140
- gap: $CAP_SPACE_12;
1141
- flex-shrink: 0;
1142
- }
1143
-
1144
- .archived-mode-header {
1145
- display: flex;
1146
- align-items: center;
1147
- gap: $CAP_SPACE_12;
1148
- margin-bottom: $CAP_SPACE_16;
1149
-
1150
- .archived-mode-back-icon {
1151
- cursor: pointer;
1152
- font-size: 1.428rem;
1224
+ /* Local SMS / slidebox: viewport-based .v2-pagination-container-half height leaves empty space below and clips cards */
1225
+ .creatives-templates-container--local-sms.library-mode {
1226
+ .creatives-templates-list.library-mode > .cap-row:first-of-type > div {
1227
+ display: flex;
1228
+ flex-direction: column;
1229
+ flex: 1 1 auto;
1230
+ min-height: 0;
1231
+ overflow: hidden;
1153
1232
  }
1154
- }
1155
-
1156
- .archived-tag {
1157
- margin-left: $CAP_SPACE_08;
1158
- font-size: 0.786rem;
1159
- }
1160
-
1161
- .popover-archive-action {
1162
- cursor: pointer;
1163
- padding: $CAP_SPACE_08 0;
1164
- }
1165
-
1166
- .archive-menu-item {
1167
- display: inline-flex;
1168
- align-items: center;
1169
- gap: $CAP_SPACE_08;
1170
- margin-top: 1rem;
1171
- }
1172
-
1173
- .archive-btn-label {
1174
- margin-right: 0.714rem;
1175
- }
1176
-
1177
- .bulk-selection-bar .cap-button-v2-prefix {
1178
- margin-top: 1rem;
1179
- }
1180
-
1181
- .bulk-selection-bar .ant-btn.cap-button-v2 > .cap-button-v2-prefix + span {
1182
- margin-left: -$CAP_SPACE_06;
1183
- }
1184
-
1185
- .template-card-top-bar {
1186
- display: flex;
1187
- align-items: center;
1188
- justify-content: space-between;
1189
- padding: $CAP_SPACE_08 $CAP_SPACE_12 0;
1190
- }
1191
1233
 
1192
- .template-listing-header-actions {
1193
- display: flex;
1194
- justify-content: space-between;
1195
- align-items: center;
1196
- gap: $CAP_SPACE_08;
1197
- }
1198
-
1199
- .template-listing-more-btn {
1200
- padding: 0 $CAP_SPACE_08;
1201
- min-width: auto;
1202
- }
1234
+ .creatives-templates-list.library-mode > .cap-row:first-of-type > div > div:first-child {
1235
+ display: flex;
1236
+ flex-direction: column;
1237
+ flex: 1 1 auto;
1238
+ min-height: 0;
1239
+ overflow: hidden;
1240
+ }
1203
1241
 
1204
- .notification-template-label {
1205
- color: #5E6C84;
1206
- }
1242
+ /* Block below search/filter: grid + skeletons — must grow to use space above footer */
1243
+ .creatives-templates-list.library-mode > .cap-row:first-of-type > div > div:first-child > div:nth-child(2) {
1244
+ flex: 1 1 auto;
1245
+ min-height: 0;
1246
+ display: flex;
1247
+ flex-direction: column;
1248
+ overflow: hidden;
1249
+ }
1207
1250
 
1208
- .notification-template-name {
1209
- color: #091E42;
1210
- }
1251
+ /*
1252
+ * Scroll needs a definite height. Pure flex + height:auto + max-height:100% often won’t bound (no % base), so no scrollbar.
1253
+ * Use a taller slice than global 100vh-20rem so the grid uses space under search; still overflow-y:auto for long lists.
1254
+ */
1255
+ .v2-pagination-container,
1256
+ .v2-pagination-container-half {
1257
+ flex: 0 1 auto;
1258
+ min-height: 0;
1259
+ height: calc(100vh - 12rem);
1260
+ max-height: calc(100vh - 12rem);
1261
+ overflow-y: auto;
1262
+ overflow-x: hidden;
1263
+ -webkit-overflow-scrolling: touch;
1264
+ }
1265
+ }
@@ -15,6 +15,17 @@ export function getAllTemplates(channel, queryParams, intlCopyOf = '') {
15
15
  };
16
16
  }
17
17
 
18
+
19
+ export function getLocalSmsTemplates(queryParams, intlCopyOf = '', onSuccess, onFailure) {
20
+ return {
21
+ type: types.GET_LOCAL_SMS_TEMPLATES_REQUEST,
22
+ queryParams,
23
+ intlCopyOf,
24
+ onSuccess,
25
+ onFailure,
26
+ };
27
+ }
28
+
18
29
  export function resetTemplate() {
19
30
  return {
20
31
  type: types.RESET_TEMPLATE,
@@ -167,39 +178,3 @@ export function getCdnTransformationConfig() {
167
178
  type: types.GET_CDN_TRANSFORMATION_CONFIG_REQUEST,
168
179
  };
169
180
  }
170
-
171
- export function archiveTemplate(channel, id, templateName) {
172
- return { type: types.ARCHIVE_TEMPLATE_REQUEST, channel, id, templateName };
173
- }
174
-
175
- export function unarchiveTemplate(channel, id, templateName) {
176
- return { type: types.UNARCHIVE_TEMPLATE_REQUEST, channel, id, templateName };
177
- }
178
-
179
- export function bulkArchiveTemplates(channel, ids) {
180
- return { type: types.BULK_ARCHIVE_REQUEST, channel, ids };
181
- }
182
-
183
- export function bulkUnarchiveTemplates(channel, ids) {
184
- return { type: types.BULK_UNARCHIVE_REQUEST, channel, ids };
185
- }
186
-
187
- export function setArchiveFilter(filter) {
188
- return { type: types.SET_ARCHIVE_FILTER, filter };
189
- }
190
-
191
- export function toggleTemplateSelection(id) {
192
- return { type: types.TOGGLE_TEMPLATE_SELECTION, id };
193
- }
194
-
195
- export function selectAllTemplates(ids) {
196
- return { type: types.SELECT_ALL_TEMPLATES, ids };
197
- }
198
-
199
- export function clearTemplateSelection() {
200
- return { type: types.CLEAR_TEMPLATE_SELECTION };
201
- }
202
-
203
- export function setArchivedMode(isArchived) {
204
- return { type: types.SET_ARCHIVED_MODE, isArchived };
205
- }