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

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 (130) hide show
  1. package/constants/unified.js +0 -29
  2. package/package.json +1 -1
  3. package/services/tests/api.test.js +0 -13
  4. package/utils/commonUtils.js +1 -19
  5. package/v2Components/CapActionButton/constants.js +0 -7
  6. package/v2Components/CapActionButton/index.js +109 -167
  7. package/v2Components/CapActionButton/index.scss +6 -157
  8. package/v2Components/CapActionButton/messages.js +3 -19
  9. package/v2Components/CapActionButton/tests/index.test.js +17 -41
  10. package/v2Components/CapTagList/index.js +0 -10
  11. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +49 -70
  12. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +2 -8
  13. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +21 -207
  14. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +0 -16
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +10 -85
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +0 -30
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +11 -79
  18. package/v2Components/CommonTestAndPreview/SendTestMessage.js +5 -10
  19. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +15 -160
  20. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +76 -341
  21. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +4 -133
  22. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +0 -11
  23. package/v2Components/CommonTestAndPreview/constants.js +2 -38
  24. package/v2Components/CommonTestAndPreview/index.js +186 -676
  25. package/v2Components/CommonTestAndPreview/messages.js +3 -49
  26. package/v2Components/CommonTestAndPreview/sagas.js +6 -15
  27. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +284 -308
  28. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +65 -231
  29. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +5 -118
  30. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +0 -341
  31. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +1 -8
  32. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +13 -34
  33. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +283 -281
  34. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +1 -199
  35. package/v2Components/CommonTestAndPreview/tests/index.test.js +4 -132
  36. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
  37. package/v2Components/FormBuilder/index.js +10 -8
  38. package/v2Components/TemplatePreview/_templatePreview.scss +23 -33
  39. package/v2Components/TemplatePreview/index.js +28 -143
  40. package/v2Components/TemplatePreview/tests/index.test.js +0 -142
  41. package/v2Components/TestAndPreviewSlidebox/index.js +1 -13
  42. package/v2Components/TestAndPreviewSlidebox/sagas.js +4 -11
  43. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +1 -3
  44. package/v2Containers/CreativesContainer/SlideBoxContent.js +4 -36
  45. package/v2Containers/CreativesContainer/SlideBoxFooter.js +1 -10
  46. package/v2Containers/CreativesContainer/SlideBoxHeader.js +4 -29
  47. package/v2Containers/CreativesContainer/constants.js +0 -9
  48. package/v2Containers/CreativesContainer/index.js +103 -300
  49. package/v2Containers/CreativesContainer/index.scss +1 -51
  50. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +34 -78
  51. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +16 -79
  52. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -8
  53. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +98 -357
  54. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +15 -20
  55. package/v2Containers/CreativesContainer/tests/index.test.js +9 -71
  56. package/v2Containers/Email/reducer.js +12 -3
  57. package/v2Containers/Email/sagas.js +9 -4
  58. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +4 -0
  59. package/v2Containers/Email/tests/reducer.test.js +47 -0
  60. package/v2Containers/Email/tests/sagas.test.js +146 -6
  61. package/v2Containers/Rcs/constants.js +8 -119
  62. package/v2Containers/Rcs/index.js +811 -2383
  63. package/v2Containers/Rcs/index.scss +6 -276
  64. package/v2Containers/Rcs/messages.js +3 -38
  65. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +70073 -98018
  66. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +5 -0
  67. package/v2Containers/Rcs/tests/index.test.js +121 -152
  68. package/v2Containers/Rcs/tests/mockData.js +0 -38
  69. package/v2Containers/Rcs/tests/utils.test.js +30 -646
  70. package/v2Containers/Rcs/utils.js +11 -478
  71. package/v2Containers/Sms/Create/index.js +40 -100
  72. package/v2Containers/SmsTrai/Create/index.js +4 -9
  73. package/v2Containers/SmsTrai/Edit/constants.js +0 -2
  74. package/v2Containers/SmsTrai/Edit/index.js +130 -636
  75. package/v2Containers/SmsTrai/Edit/messages.js +4 -14
  76. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +2296 -4249
  77. package/v2Containers/SmsWrapper/index.js +8 -37
  78. package/v2Containers/TagList/index.js +0 -6
  79. package/v2Containers/Templates/_templates.scss +2 -163
  80. package/v2Containers/Templates/actions.js +0 -11
  81. package/v2Containers/Templates/constants.js +0 -2
  82. package/v2Containers/Templates/index.js +54 -119
  83. package/v2Containers/Templates/sagas.js +12 -57
  84. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1079 -1043
  85. package/v2Containers/Templates/tests/sagas.test.js +123 -193
  86. package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -72
  87. package/v2Containers/TemplatesV2/index.js +23 -86
  88. package/v2Containers/Whatsapp/index.js +20 -3
  89. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -578
  90. package/utils/rcsPayloadUtils.js +0 -92
  91. package/utils/templateVarUtils.js +0 -201
  92. package/utils/tests/templateVarUtils.test.js +0 -204
  93. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js.rej +0 -18
  94. package/v2Components/CommonTestAndPreview/previewApiUtils.js +0 -59
  95. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +0 -67
  96. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +0 -87
  97. package/v2Components/SmsFallback/constants.js +0 -73
  98. package/v2Components/SmsFallback/index.js +0 -955
  99. package/v2Components/SmsFallback/index.scss +0 -265
  100. package/v2Components/SmsFallback/messages.js +0 -78
  101. package/v2Components/SmsFallback/smsFallbackUtils.js +0 -118
  102. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +0 -50
  103. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +0 -147
  104. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +0 -304
  105. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +0 -197
  106. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +0 -277
  107. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +0 -422
  108. package/v2Components/SmsFallback/useLocalTemplateList.js +0 -92
  109. package/v2Components/TemplatePreview/constants.js +0 -2
  110. package/v2Components/VarSegmentMessageEditor/constants.js +0 -2
  111. package/v2Components/VarSegmentMessageEditor/index.js +0 -125
  112. package/v2Components/VarSegmentMessageEditor/index.scss +0 -46
  113. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +0 -43
  114. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +0 -67
  115. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +0 -90
  116. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +0 -258
  117. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +0 -125
  118. package/v2Containers/Rcs/index.js.rej +0 -1336
  119. package/v2Containers/Rcs/index.scss.rej +0 -74
  120. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +0 -225
  121. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap.rej +0 -128
  122. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -318
  123. package/v2Containers/Sms/smsFormDataHelpers.js +0 -67
  124. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +0 -253
  125. package/v2Containers/SmsTrai/Edit/index.scss +0 -121
  126. package/v2Containers/Templates/TemplatesActionBar.js +0 -101
  127. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +0 -120
  128. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +0 -180
  129. package/v2Containers/Templates/utils/smsTemplatesListApi.js +0 -79
  130. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +0 -131
@@ -1,92 +0,0 @@
1
- import { useState, useCallback, useRef } from 'react';
2
-
3
- /**
4
- * @param {Object} options
5
- * @param {(params: { page: number, search: string, reset: boolean }) => Promise<{ templates: Array, totalCount: number }>} options.fetchTemplates
6
- * @param {number} [options.perPage=25]
7
- */
8
- export function useLocalTemplateList({ fetchTemplates, perPage = 25 }) {
9
- const [listData, setListData] = useState({ templates: [], totalCount: 0 });
10
- const [loading, setLoading] = useState(false);
11
- const [page, setPage] = useState(1);
12
- const [search, setSearchState] = useState('');
13
- const searchRef = useRef('');
14
- /** Drops stale responses when a newer fetch starts (search / reset while a request is in flight). */
15
- const fetchGenerationRef = useRef(0);
16
- const setSearch = useCallback((value) => {
17
- const term = typeof value === 'string' ? value : '';
18
- searchRef.current = term;
19
- setSearchState(term);
20
- }, []);
21
- const lastFetchFullPageRef = useRef(false);
22
-
23
- const { templates = [], totalCount = 0 } = listData ?? {};
24
- const hasKnownTotal = (totalCount ?? 0) > 0;
25
- const hasMoreByTotal = (totalCount ?? 0) > (templates?.length ?? 0);
26
- const hasMoreByFullPage =
27
- !hasKnownTotal && lastFetchFullPageRef.current && (templates?.length ?? 0) > 0;
28
- const canLoadMore = (hasMoreByTotal || hasMoreByFullPage) && !loading;
29
-
30
- const runFetch = useCallback(
31
- async ({ page: p = 1, reset = true, search: searchTerm } = {}) => {
32
- const term = searchTerm !== undefined ? searchTerm : searchRef.current;
33
- const gen = ++fetchGenerationRef.current;
34
- setLoading(true);
35
- try {
36
- const result = await fetchTemplates({ page: p, search: term, reset });
37
- if (gen !== fetchGenerationRef.current) {
38
- return;
39
- }
40
- const nextTemplates = result?.templates ?? [];
41
- const nextTotalCount = result?.totalCount ?? 0;
42
- lastFetchFullPageRef.current = nextTemplates.length >= perPage;
43
- setListData((prev) => ({
44
- templates: reset ? nextTemplates : [...(prev.templates || []), ...nextTemplates],
45
- totalCount: nextTotalCount > 0 ? nextTotalCount : (reset ? 0 : prev.totalCount),
46
- }));
47
- setPage(p);
48
- } catch (e) {
49
- if (gen !== fetchGenerationRef.current) {
50
- return;
51
- }
52
- lastFetchFullPageRef.current = false;
53
- if (reset) {
54
- setListData({ templates: [], totalCount: 0 });
55
- setPage(1);
56
- }
57
- } finally {
58
- if (gen === fetchGenerationRef.current) {
59
- setLoading(false);
60
- }
61
- }
62
- },
63
- [fetchTemplates, perPage]
64
- );
65
-
66
- const loadMore = useCallback(() => {
67
- if (!canLoadMore) return;
68
- runFetch({ page: page + 1, reset: false, search: searchRef.current });
69
- }, [canLoadMore, page, runFetch]);
70
-
71
- const reset = useCallback(
72
- (searchTerm) => {
73
- const term = searchTerm !== undefined ? searchTerm : searchRef.current;
74
- setSearch(term);
75
- lastFetchFullPageRef.current = false;
76
- runFetch({ page: 1, reset: true, search: term });
77
- },
78
- [runFetch, setSearch]
79
- );
80
-
81
- return {
82
- templates,
83
- totalCount,
84
- loading,
85
- page,
86
- search,
87
- setSearch,
88
- loadMore,
89
- reset,
90
- canLoadMore,
91
- };
92
- }
@@ -1,2 +0,0 @@
1
- /** Matches {{ varName }} placeholders (alphanumeric + underscore) */
2
- export const TEMPLATE_VAR_REGEX = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g;
@@ -1,2 +0,0 @@
1
- /** Default prefix before variable name in variable-slot placeholders. */
2
- export const VAR_SEGMENT_PLACEHOLDER_PREFIX = 'enter the value for ';
@@ -1,125 +0,0 @@
1
- /**
2
- * Shared message editor that renders template text with {{var}} and/or DLT `{#var#}` segments as
3
- * variable inputs and static text as headings.
4
- * Reused by RCS (title/description), SmsTrai Edit (SMS fallback), and WhatsApp (edit message/header).
5
- */
6
- import React from 'react';
7
- import PropTypes from 'prop-types';
8
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
9
- import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
10
- import CapInput from '@capillarytech/cap-ui-library/CapInput';
11
- import {
12
- splitTemplateVarString,
13
- DEFAULT_MUSTACHE_VAR_REGEX,
14
- isAnyTemplateVarToken,
15
- } from '../../utils/templateVarUtils';
16
-
17
- import './index.scss';
18
- import { VAR_SEGMENT_PLACEHOLDER_PREFIX } from './constants';
19
-
20
- const { TextArea } = CapInput;
21
-
22
- export function VarSegmentMessageEditor({
23
- templateString = '',
24
- valueMap = {},
25
- onChange,
26
- onFocus,
27
- placeholderPrefix = VAR_SEGMENT_PLACEHOLDER_PREFIX,
28
- getPlaceholder,
29
- wrapperClassName = 'rcs_text_area_wrapper',
30
- rowClassName = 'rcs-edit-template-message-input',
31
- headingClassName = 'rcs-edit-template-message-split',
32
- varRegex,
33
- readOnly = false,
34
- disabled = false,
35
- footerContent,
36
- renderVarFooter,
37
- }) {
38
- const segments = splitTemplateVarString(templateString, varRegex || DEFAULT_MUSTACHE_VAR_REGEX);
39
- if (!segments?.length) return null;
40
-
41
- return (
42
- <div className={wrapperClassName}>
43
- <CapRow className={rowClassName}>
44
- {segments.map((segmentToken, segmentIndex) => {
45
- const isVar =
46
- typeof segmentToken === 'string' && isAnyTemplateVarToken(segmentToken);
47
- if (isVar) {
48
- const varSegmentFieldId = `${segmentToken}_${segmentIndex}`;
49
- const slotValueFromMap = valueMap?.[varSegmentFieldId];
50
- // Missing key: show empty (not the raw {{…}} token) so cleared slots and incomplete maps
51
- // cannot resurrect the token; placeholder still guides the user.
52
- const value =
53
- slotValueFromMap !== undefined && slotValueFromMap !== null ? slotValueFromMap : '';
54
- if (readOnly) {
55
- return (
56
- <CapHeading
57
- key={varSegmentFieldId}
58
- type="h4"
59
- className={`${headingClassName} var-segment-message-editor__read-only-value`.trim()}
60
- >
61
- {value}
62
- </CapHeading>
63
- );
64
- }
65
- const fromGet = getPlaceholder && getPlaceholder(segmentToken, segmentIndex);
66
- const placeholder =
67
- fromGet !== undefined && fromGet !== null && fromGet !== ''
68
- ? fromGet
69
- : `${placeholderPrefix}${segmentToken}`;
70
- return (
71
- <div key={varSegmentFieldId} className="var-segment-message-editor__var-slot">
72
- <TextArea
73
- id={varSegmentFieldId}
74
- placeholder={placeholder}
75
- autosize={{ minRows: 1, maxRows: 3 }}
76
- value={value}
77
- onFocus={() => onFocus && onFocus(varSegmentFieldId)}
78
- onChange={(e) =>
79
- onChange && onChange(varSegmentFieldId, e?.target?.value ?? '')}
80
- disabled={disabled}
81
- />
82
- {renderVarFooter
83
- ? renderVarFooter(segmentToken, segmentIndex, varSegmentFieldId)
84
- : null}
85
- </div>
86
- );
87
- }
88
- if (segmentToken) {
89
- return (
90
- <CapHeading
91
- key={`static_${segmentIndex}_${segmentToken}`}
92
- type="h4"
93
- className={headingClassName}
94
- >
95
- {segmentToken}
96
- </CapHeading>
97
- );
98
- }
99
- return null;
100
- })}
101
- </CapRow>
102
- {footerContent}
103
- </div>
104
- );
105
- }
106
-
107
- VarSegmentMessageEditor.propTypes = {
108
- templateString: PropTypes.string,
109
- valueMap: PropTypes.object,
110
- onChange: PropTypes.func,
111
- onFocus: PropTypes.func,
112
- placeholderPrefix: PropTypes.string,
113
- getPlaceholder: PropTypes.func,
114
- wrapperClassName: PropTypes.string,
115
- rowClassName: PropTypes.string,
116
- headingClassName: PropTypes.string,
117
- varRegex: PropTypes.object,
118
- readOnly: PropTypes.bool,
119
- disabled: PropTypes.bool,
120
- footerContent: PropTypes.node,
121
- /** Optional hint below a variable field (e.g. DLT `{#var#}` max length). */
122
- renderVarFooter: PropTypes.func,
123
- };
124
-
125
- export default VarSegmentMessageEditor;
@@ -1,46 +0,0 @@
1
- @import '~@capillarytech/cap-ui-library/styles/_variables';
2
-
3
- /* Same look as RCS edit message block: background, spacing, text color */
4
- .rcs_text_area_wrapper {
5
- .rcs-edit-template-message-input {
6
- background-color: $CAP_G10;
7
- padding: $CAP_SPACE_12 $CAP_SPACE_16 $CAP_SPACE_16;
8
- }
9
-
10
- .rcs-edit-template-message-split {
11
- margin: 0 0 $CAP_SPACE_04 0;
12
- overflow: hidden;
13
- text-overflow: ellipsis;
14
- color: $FONT_COLOR_04;
15
- font-weight: 500;
16
- }
17
-
18
- /* Variable chips: match RCS edit (white field, light border, 4px radius) */
19
- .rcs-edit-template-message-input .ant-input,
20
- .rcs-edit-template-message-input textarea.ant-input {
21
- margin: 0 0 0.125rem 0;
22
- border-radius: 0.25rem;
23
- border: 0.0625rem solid $CAP_G07;
24
- background-color: $CAP_WHITE;
25
- overflow: hidden;
26
- }
27
-
28
- /* Small gap between tag border and the next line (static text) */
29
- .rcs-edit-template-message-input :not(:first-child) {
30
- margin-top: $CAP_SPACE_08;
31
- }
32
-
33
- .rcs-edit-template-message-input > *:last-child {
34
- margin-bottom: 0;
35
- }
36
-
37
- .var-segment-message-editor__var-slot {
38
- display: flex;
39
- flex-direction: column;
40
- width: 100%;
41
- }
42
- }
43
-
44
- .var-segment-message-editor__read-only-value {
45
- margin: 0;
46
- }
@@ -1,43 +0,0 @@
1
- /**
2
- * Styled wrapper for CapSlideBox used by CreativesContainer and RCS SMS fallback
3
- * so header/content/footer margins match.
4
- */
5
- import styled from 'styled-components';
6
- import { CAP_SPACE_16 } from '@capillarytech/cap-ui-library/styled/variables';
7
-
8
- const CreativesSlideBoxWrapper = styled.div`
9
- .cap-slide-box-v2-container {
10
- /*
11
- * Liquid-error spacing must stay *inside* the content column. margin-bottom on
12
- * .slidebox-content-container added to the in-flow height past 100vh, so the outer
13
- * .cap-slide-box-v2-container (overflow-y: auto in cap-ui) gained a second scrollbar.
14
- */
15
- .slidebox-header {
16
- margin-bottom: ${({ slideBoxWrapperMargin }) => `${slideBoxWrapperMargin}`};
17
- padding: 0 rem;
18
- &.has-footer {
19
- overflow-x: hidden;
20
- }
21
- }
22
- .slidebox-content-container {
23
- margin-bottom: 0;
24
- padding: 0 rem;
25
- padding-bottom: ${({ slideBoxWrapperMargin }) => `${slideBoxWrapperMargin}`};
26
- box-sizing: border-box;
27
- &.has-footer {
28
- overflow-x: hidden;
29
- }
30
- }
31
- .slidebox-footer {
32
- /* Only apply margin-bottom to footer when ErrorInfoNote is shown in footer (BEE editor) */
33
- /* For HTML Editor, errors are shown in ValidationErrorDisplay (inside content area), so no footer margin needed */
34
- margin-bottom: ${({ shouldApplyFooterMargin }) => (shouldApplyFooterMargin ? `${CAP_SPACE_16}` : '0')};
35
- padding: 0 rem;
36
- &.has-footer {
37
- overflow-x: hidden;
38
- }
39
- }
40
- }
41
- `;
42
-
43
- export default CreativesSlideBoxWrapper;
@@ -1,67 +0,0 @@
1
- /**
2
- * Shared logic for CreativesContainer slidebox + embedded flows (e.g. RCS SMS fallback)
3
- * that mirror the same footer liquid errors and layout margins.
4
- */
5
- import get from 'lodash/get';
6
- import {
7
- CAP_SPACE_32,
8
- CAP_SPACE_56,
9
- CAP_SPACE_64,
10
- } from '@capillarytech/cap-ui-library/styled/variables';
11
- import * as constants from './constants';
12
-
13
- /**
14
- * Returns true if value is "deep empty": no errors present.
15
- * Same rules as CreativesContainer (used for liquid / standard error payloads).
16
- */
17
- export function isDeepEmpty(value) {
18
- if (value == null) return true;
19
- if (typeof value === 'string') return value.length === 0;
20
- if (Array.isArray(value)) return value.length === 0;
21
- if (typeof value === 'object') {
22
- return Object.values(value).every(isDeepEmpty);
23
- }
24
- return false;
25
- }
26
-
27
- /**
28
- * Header/content margin below slidebox chrome when ErrorInfoNote stacks errors — same formula as CreativesContainer#render.
29
- */
30
- export function getSlideBoxWrapperMarginFromLiquidErrors(liquidErrorMessage) {
31
- return (get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0
32
- && get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0)
33
- ? CAP_SPACE_64
34
- : get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0
35
- ? CAP_SPACE_56
36
- : get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0
37
- ? CAP_SPACE_32
38
- : 0;
39
- }
40
-
41
- /**
42
- * Maps FormBuilder `showLiquidErrorInFooter` args to slidebox footer state.
43
- * Returns `null` when CreativesContainer intentionally skips updating (Mobile Push OLD empty clear).
44
- */
45
- export function computeLiquidFooterUpdateFromFormBuilder(
46
- errorMessagesFromFormBuilder,
47
- currentFormBuilderTab,
48
- { previousIsLiquidValidationError, currentChannelUpper } = {},
49
- ) {
50
- const liquidMsgs = get(errorMessagesFromFormBuilder, constants.LIQUID_ERROR_MSG, []);
51
- const standardMsgs = get(errorMessagesFromFormBuilder, constants.STANDARD_ERROR_MSG, []);
52
- const hasLiquid = !isDeepEmpty(liquidMsgs);
53
- const hasStandard = !isDeepEmpty(standardMsgs);
54
- const isLiquidValidationError = hasLiquid || hasStandard;
55
- const isMobilePush = currentChannelUpper === constants.MOBILE_PUSH;
56
- if (!hasLiquid && !hasStandard && previousIsLiquidValidationError && isMobilePush) {
57
- return null;
58
- }
59
- return {
60
- isLiquidValidationError,
61
- liquidErrorMessage: errorMessagesFromFormBuilder,
62
- activeFormBuilderTab:
63
- currentFormBuilderTab === 1
64
- ? constants.ANDROID
65
- : (currentFormBuilderTab === 2 ? constants.IOS : null),
66
- };
67
- }
@@ -1,90 +0,0 @@
1
- /**
2
- * Covers `localTemplatesConfig` / `useLocalTemplates` branch in SlideBoxContent → TemplatesV2
3
- * (embedded SMS template list / RCS SMS fallback).
4
- */
5
- import React from 'react';
6
- import { mountWithIntl, shallowWithIntl } from '../../../helpers/intl-enzym-test-helpers';
7
- import { SlideBoxContent } from '../SlideBoxContent';
8
-
9
- const mockTemplatesV2 = jest.fn(() => <div data-testid="templates-v2-mock" />);
10
- jest.mock('../../TemplatesV2', () => ({
11
- __esModule: true,
12
- default: (props) => mockTemplatesV2(props),
13
- }));
14
-
15
- const baseProps = {
16
- slidBoxContent: 'templates',
17
- currentChannel: 'SMS',
18
- onSelectTemplate: jest.fn(),
19
- onPreviewTemplate: jest.fn(),
20
- onCreateNew: jest.fn(),
21
- onChannelChange: jest.fn(),
22
- location: { pathname: '/sms', query: {}, search: '' },
23
- cap: {},
24
- channelsToHide: [],
25
- channelsToDisable: [],
26
- handleClose: jest.fn(),
27
- messageDetails: {},
28
- onCreateComplete: jest.fn(),
29
- };
30
-
31
- describe('SlideBoxContent local templates (TemplatesV2)', () => {
32
- beforeEach(() => {
33
- mockTemplatesV2.mockClear();
34
- });
35
-
36
- // Use mount when asserting TemplatesV2 mock calls: shallow does not invoke children under styled CreativesWrapper.
37
- it('renders TemplatesV2 in full mode when useLocalTemplates is true', () => {
38
- mountWithIntl(
39
- <SlideBoxContent
40
- {...baseProps}
41
- isFullMode
42
- localTemplatesConfig={{
43
- useLocalTemplates: true,
44
- localTemplates: [],
45
- localTemplatesLoading: false,
46
- }}
47
- />,
48
- );
49
- expect(mockTemplatesV2).toHaveBeenCalled();
50
- const passed = mockTemplatesV2.mock.calls[mockTemplatesV2.mock.calls.length - 1][0];
51
- expect(passed.localTemplatesConfig.useLocalTemplates).toBe(true);
52
- });
53
-
54
- it('does not render TemplatesV2 in full mode when useLocalTemplates is false', () => {
55
- shallowWithIntl(
56
- <SlideBoxContent
57
- {...baseProps}
58
- isFullMode
59
- localTemplatesConfig={{ useLocalTemplates: false }}
60
- />,
61
- );
62
- expect(mockTemplatesV2).not.toHaveBeenCalled();
63
- });
64
-
65
- it('renders TemplatesV2 in library mode without localTemplates flag', () => {
66
- mountWithIntl(
67
- <SlideBoxContent
68
- {...baseProps}
69
- isFullMode={false}
70
- />,
71
- );
72
- expect(mockTemplatesV2).toHaveBeenCalled();
73
- });
74
-
75
- it('merges top-level local template props via pick when localTemplatesConfig is omitted', () => {
76
- mountWithIntl(
77
- <SlideBoxContent
78
- {...baseProps}
79
- isFullMode
80
- useLocalTemplates
81
- localTemplates={[{ _id: '1' }]}
82
- localTemplatesLoading={false}
83
- />,
84
- );
85
- expect(mockTemplatesV2).toHaveBeenCalled();
86
- const passed = mockTemplatesV2.mock.calls[mockTemplatesV2.mock.calls.length - 1][0];
87
- expect(passed.localTemplatesConfig.useLocalTemplates).toBe(true);
88
- expect(passed.localTemplatesConfig.localTemplates).toEqual([{ _id: '1' }]);
89
- });
90
- });