@capillarytech/creatives-library 9.0.15-alpha.0 → 9.0.15-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.
- package/constants/unified.js +29 -0
- package/global-styles.js +1 -1
- package/package.json +1 -1
- package/services/tests/api.test.js +35 -20
- package/utils/commonUtils.js +19 -1
- package/utils/rcsPayloadUtils.js +92 -0
- package/utils/templateVarUtils.js +201 -0
- package/utils/tests/rcsPayloadUtils.test.js +226 -0
- package/utils/tests/templateVarUtils.test.js +204 -0
- package/v2Components/CapActionButton/constants.js +7 -0
- package/v2Components/CapActionButton/index.js +168 -109
- package/v2Components/CapActionButton/index.scss +156 -5
- package/v2Components/CapActionButton/messages.js +19 -3
- package/v2Components/CapActionButton/tests/index.test.js +42 -18
- package/v2Components/CapImageUpload/index.js +2 -2
- package/v2Components/CapTagList/index.js +10 -0
- package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -48
- package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
- package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +214 -21
- package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +83 -9
- package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
- package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +60 -11
- package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +201 -23
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +355 -76
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +155 -8
- package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
- package/v2Components/CommonTestAndPreview/constants.js +38 -2
- package/v2Components/CommonTestAndPreview/index.js +761 -222
- package/v2Components/CommonTestAndPreview/messages.js +45 -3
- package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
- package/v2Components/CommonTestAndPreview/sagas.js +25 -6
- package/v2Components/CommonTestAndPreview/tests/CommonTestAndPreview.addTestCustomer.test.js +1 -0
- package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +284 -267
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +231 -65
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
- package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
- package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +34 -13
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
- package/v2Components/CommonTestAndPreview/tests/index.test.js +133 -4
- package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
- package/v2Components/CommonTestAndPreview/tests/sagas.test.js +31 -24
- package/v2Components/CommonTestAndPreview/utils.js +84 -0
- package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +91 -0
- package/v2Components/SmsFallback/constants.js +94 -0
- package/v2Components/SmsFallback/index.js +958 -0
- package/v2Components/SmsFallback/index.scss +266 -0
- package/v2Components/SmsFallback/messages.js +78 -0
- package/v2Components/SmsFallback/smsFallbackUtils.js +120 -0
- package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
- package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
- package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
- package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +208 -0
- package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +309 -0
- package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
- package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +41 -22
- package/v2Components/TemplatePreview/constants.js +2 -0
- package/v2Components/TemplatePreview/index.js +143 -31
- package/v2Components/TemplatePreview/tests/index.test.js +142 -0
- package/v2Components/TestAndPreviewSlidebox/CustomValuesEditor.js +6 -6
- package/v2Components/TestAndPreviewSlidebox/index.js +13 -1
- package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
- package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
- package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
- package/v2Components/VarSegmentMessageEditor/index.js +125 -0
- package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +4 -1
- package/v2Containers/CommunicationFlow/index.js +3 -3
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +4 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +20 -20
- package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +17 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +14 -5
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +36 -5
- package/v2Containers/CreativesContainer/constants.js +11 -0
- package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +79 -0
- package/v2Containers/CreativesContainer/index.js +323 -104
- package/v2Containers/CreativesContainer/index.scss +83 -1
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +79 -34
- package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +79 -16
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +333 -90
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -15
- package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
- package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
- package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
- package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
- package/v2Containers/Rcs/constants.js +131 -11
- package/v2Containers/Rcs/index.js +2602 -807
- package/v2Containers/Rcs/index.scss +289 -8
- package/v2Containers/Rcs/messages.js +34 -3
- package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +227 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +73535 -38537
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -8
- package/v2Containers/Rcs/tests/index.test.js +147 -36
- package/v2Containers/Rcs/tests/mockData.js +38 -0
- package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +318 -0
- package/v2Containers/Rcs/tests/utils.test.js +646 -30
- package/v2Containers/Rcs/utils.js +478 -11
- package/v2Containers/Sms/Create/index.js +115 -48
- package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
- package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
- package/v2Containers/SmsTrai/Create/index.js +9 -4
- package/v2Containers/SmsTrai/Edit/constants.js +2 -0
- package/v2Containers/SmsTrai/Edit/index.js +678 -169
- package/v2Containers/SmsTrai/Edit/index.scss +126 -0
- package/v2Containers/SmsTrai/Edit/messages.js +14 -4
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +5615 -3014
- package/v2Containers/SmsWrapper/index.js +37 -8
- package/v2Containers/TagList/index.js +6 -0
- package/v2Containers/Templates/TemplatesActionBar.js +101 -0
- package/v2Containers/Templates/_templates.scss +171 -12
- package/v2Containers/Templates/actions.js +11 -0
- package/v2Containers/Templates/constants.js +2 -0
- package/v2Containers/Templates/index.js +125 -55
- package/v2Containers/Templates/sagas.js +57 -13
- package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1060 -1015
- package/v2Containers/Templates/tests/sagas.test.js +199 -16
- package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
- package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
- package/v2Containers/TemplatesV2/index.js +86 -23
- package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
- package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
- package/v2Containers/Whatsapp/index.js +3 -20
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
|
@@ -12,7 +12,7 @@ export default defineMessages({
|
|
|
12
12
|
},
|
|
13
13
|
ctaQr: {
|
|
14
14
|
id: `${prefix}.ctaQr`,
|
|
15
|
-
defaultMessage: 'Quick
|
|
15
|
+
defaultMessage: 'Quick reply',
|
|
16
16
|
},
|
|
17
17
|
ctaPhoneNo: {
|
|
18
18
|
id: `${prefix}.ctaPhoneNo`,
|
|
@@ -47,9 +47,17 @@ export default defineMessages({
|
|
|
47
47
|
id: `${prefix}.templateMessageLength`,
|
|
48
48
|
defaultMessage: 'Characters count: {currentLength}/{maxLength}',
|
|
49
49
|
},
|
|
50
|
+
ctaFieldCharCountInline: {
|
|
51
|
+
id: `${prefix}.ctaFieldCharCountInline`,
|
|
52
|
+
defaultMessage: '{current}/{max}',
|
|
53
|
+
},
|
|
50
54
|
ctaType: {
|
|
51
55
|
id: `${prefix}.ctaType`,
|
|
52
|
-
defaultMessage: '
|
|
56
|
+
defaultMessage: 'Button type',
|
|
57
|
+
},
|
|
58
|
+
ctaUrlRadio: {
|
|
59
|
+
id: `${prefix}.ctaUrlRadio`,
|
|
60
|
+
defaultMessage: 'URL',
|
|
53
61
|
},
|
|
54
62
|
templateButtonTextPlaceholder: {
|
|
55
63
|
id: `${prefix}.templateButtonTextPlaceholder`,
|
|
@@ -145,7 +153,15 @@ export default defineMessages({
|
|
|
145
153
|
},
|
|
146
154
|
ctaWebsiteType: {
|
|
147
155
|
id: `${prefix}.ctaWebsiteType`,
|
|
148
|
-
defaultMessage: 'URL
|
|
156
|
+
defaultMessage: 'URL type',
|
|
157
|
+
},
|
|
158
|
+
ctaUrlField: {
|
|
159
|
+
id: `${prefix}.ctaUrlField`,
|
|
160
|
+
defaultMessage: 'URL',
|
|
161
|
+
},
|
|
162
|
+
ctaEnterUrlPlaceholder: {
|
|
163
|
+
id: `${prefix}.ctaEnterUrlPlaceholder`,
|
|
164
|
+
defaultMessage: 'Enter URL',
|
|
149
165
|
},
|
|
150
166
|
ctaWebsiteTypeStatic: {
|
|
151
167
|
id: `${prefix}.ctaWebsiteTypeStatic`,
|
|
@@ -5,7 +5,7 @@ import { render, screen, fireEvent } from '../../../utils/test-utils';
|
|
|
5
5
|
import { waitFor } from '@testing-library/react';
|
|
6
6
|
import { CapActionButton } from '../index';
|
|
7
7
|
import { BTN_MAX_LENGTH, PHONE_NUMBER_MAX_LENGTH, URL_MAX_LENGTH } from '../constants';
|
|
8
|
-
import { RCS_BUTTON_TYPES } from '../../../v2Containers/Rcs/constants';
|
|
8
|
+
import { RCS_BUTTON_TYPES, HOST_ICS } from '../../../v2Containers/Rcs/constants';
|
|
9
9
|
|
|
10
10
|
const updateHandler = jest.fn();
|
|
11
11
|
const deleteHandler = jest.fn();
|
|
@@ -13,6 +13,7 @@ const initializeComponent = (
|
|
|
13
13
|
data,
|
|
14
14
|
isEditFlow = false,
|
|
15
15
|
maxButtons = 3,
|
|
16
|
+
host = '',
|
|
16
17
|
) => {
|
|
17
18
|
// Normalize legacy test data shape to match component props
|
|
18
19
|
const normalizeType = (legacyType) => {
|
|
@@ -38,6 +39,7 @@ const initializeComponent = (
|
|
|
38
39
|
isEditFlow={isEditFlow}
|
|
39
40
|
maxButtons={maxButtons}
|
|
40
41
|
isFullMode={true}
|
|
42
|
+
host={host}
|
|
41
43
|
/>,
|
|
42
44
|
);
|
|
43
45
|
};
|
|
@@ -60,7 +62,7 @@ describe('CapActionButton', () => {
|
|
|
60
62
|
isSaved: false,
|
|
61
63
|
},
|
|
62
64
|
]);
|
|
63
|
-
expect(screen.getByText('
|
|
65
|
+
expect(screen.getByText('Button type')).toBeInTheDocument();
|
|
64
66
|
expect(screen.getByText('Button text')).toBeInTheDocument();
|
|
65
67
|
expect(screen.getAllByText('Phone number')[1]).toBeInTheDocument();
|
|
66
68
|
expect(screen.getByRole('button', { name: /save/i })).toBeDisabled();
|
|
@@ -123,7 +125,7 @@ describe('CapActionButton', () => {
|
|
|
123
125
|
id: 1,
|
|
124
126
|
},
|
|
125
127
|
};
|
|
126
|
-
const urlInput = await screen.getByPlaceholderText('Enter
|
|
128
|
+
const urlInput = await screen.getByPlaceholderText('Enter URL');
|
|
127
129
|
fireEvent.change(urlInput, urlEvent);
|
|
128
130
|
expect(updateHandler).toHaveBeenCalledWith(
|
|
129
131
|
{
|
|
@@ -163,6 +165,27 @@ describe('CapActionButton', () => {
|
|
|
163
165
|
);
|
|
164
166
|
});
|
|
165
167
|
|
|
168
|
+
it('should show delete for quick reply index 0 for non-ICS hosts but hide it for ICS (stop button)', () => {
|
|
169
|
+
const button = {
|
|
170
|
+
index: 0,
|
|
171
|
+
type: RCS_BUTTON_TYPES.QUICK_REPLY,
|
|
172
|
+
text: 'Reply',
|
|
173
|
+
phoneNumber: '',
|
|
174
|
+
url: '',
|
|
175
|
+
postback: 'Reply',
|
|
176
|
+
isSaved: false,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Non-ICS (Infobip/others): delete should be available
|
|
180
|
+
const { unmount } = initializeComponent([button], false, 3, 'rcsinfobipbulk');
|
|
181
|
+
expect(screen.getByRole('button', { name: /delete/i })).toBeInTheDocument();
|
|
182
|
+
unmount();
|
|
183
|
+
|
|
184
|
+
// ICS: index 0 is reserved; delete should be hidden
|
|
185
|
+
initializeComponent([button], false, 3, HOST_ICS);
|
|
186
|
+
expect(screen.queryByRole('button', { name: /delete/i })).not.toBeInTheDocument();
|
|
187
|
+
});
|
|
188
|
+
|
|
166
189
|
it('should respect character length limits', async () => {
|
|
167
190
|
const initialData = {
|
|
168
191
|
index: 0,
|
|
@@ -201,7 +224,7 @@ describe('CapActionButton', () => {
|
|
|
201
224
|
isSaved: false,
|
|
202
225
|
};
|
|
203
226
|
initializeComponent([initialData]);
|
|
204
|
-
const urlInput = await screen.getByPlaceholderText('Enter
|
|
227
|
+
const urlInput = await screen.getByPlaceholderText('Enter URL');
|
|
205
228
|
const longUrl = 'https://example.com/' + 'a'.repeat(URL_MAX_LENGTH + 1);
|
|
206
229
|
fireEvent.change(urlInput, { target: { value: longUrl, id: 0 } });
|
|
207
230
|
expect(urlInput.value.length).toBeLessThanOrEqual(URL_MAX_LENGTH);
|
|
@@ -248,7 +271,8 @@ describe('CapActionButton', () => {
|
|
|
248
271
|
{ index: 0, ctaType: RCS_BUTTON_TYPES.QUICK_REPLY, displayText: 'stop', phoneNumber: '', url: '', postback: 'stop', isSaved: true },
|
|
249
272
|
{ index: 1, ctaType: RCS_BUTTON_TYPES.QUICK_REPLY, displayText: 'Saved', phoneNumber: '', url: '', postback: 'Saved', isSaved: true },
|
|
250
273
|
];
|
|
251
|
-
|
|
274
|
+
// Use ICS host so index 0 (STOP) stays non-deletable and we only get delete icon for index 1
|
|
275
|
+
const { container } = initializeComponent(suggestions, false, 3, HOST_ICS);
|
|
252
276
|
const deleteIcons = container.querySelectorAll('.rcs-saved-cta-delete-icon');
|
|
253
277
|
expect(deleteIcons.length).toBeGreaterThan(0);
|
|
254
278
|
fireEvent.click(deleteIcons[0]);
|
|
@@ -306,7 +330,8 @@ describe('CapActionButton', () => {
|
|
|
306
330
|
postback: 'stop',
|
|
307
331
|
isSaved: true,
|
|
308
332
|
};
|
|
309
|
-
|
|
333
|
+
// Only ICS treats index 0 as a mandatory STOP quick reply
|
|
334
|
+
const { container } = initializeComponent([stopButton], false, 3, HOST_ICS);
|
|
310
335
|
expect(container.querySelector('.rcs-saved-cta-delete-icon')).not.toBeInTheDocument();
|
|
311
336
|
});
|
|
312
337
|
|
|
@@ -427,7 +452,7 @@ describe('CapActionButton', () => {
|
|
|
427
452
|
isSaved: false,
|
|
428
453
|
};
|
|
429
454
|
initializeComponent([button]);
|
|
430
|
-
expect(screen.getByPlaceholderText(/enter
|
|
455
|
+
expect(screen.getByPlaceholderText(/enter url/i)).toBeInTheDocument();
|
|
431
456
|
});
|
|
432
457
|
|
|
433
458
|
it('should update both displayText and postback when button text changes (updateDisplayAndPostback)', () => {
|
|
@@ -507,7 +532,7 @@ describe('CapActionButton', () => {
|
|
|
507
532
|
isSaved: false,
|
|
508
533
|
};
|
|
509
534
|
initializeComponent([initial]);
|
|
510
|
-
const urlInput = screen.getByPlaceholderText('Enter
|
|
535
|
+
const urlInput = screen.getByPlaceholderText('Enter URL');
|
|
511
536
|
fireEvent.change(urlInput, { target: { value: 'http://localhost:3030/creatives/ui/v2', id: 1 } });
|
|
512
537
|
expect(screen.getByText(/url is not valid/i)).toBeInTheDocument();
|
|
513
538
|
});
|
|
@@ -607,12 +632,12 @@ describe('CapActionButton', () => {
|
|
|
607
632
|
);
|
|
608
633
|
};
|
|
609
634
|
render(<StatefulWrapper />);
|
|
610
|
-
let urlInput = screen.getByPlaceholderText('Enter
|
|
635
|
+
let urlInput = screen.getByPlaceholderText('Enter URL');
|
|
611
636
|
// Enter invalid URL
|
|
612
637
|
fireEvent.change(urlInput, { target: { value: 'badurl', id: 0 } });
|
|
613
638
|
expect(await screen.findByText(/url is not valid/i)).toBeInTheDocument();
|
|
614
639
|
// Re-grab input after re-render and enter valid URL
|
|
615
|
-
urlInput = screen.getByPlaceholderText('Enter
|
|
640
|
+
urlInput = screen.getByPlaceholderText('Enter URL');
|
|
616
641
|
fireEvent.change(urlInput, { target: { value: 'https://good.com', id: 0 } });
|
|
617
642
|
await waitFor(() => expect(screen.queryByText(/url is not valid/i)).not.toBeInTheDocument());
|
|
618
643
|
});
|
|
@@ -867,15 +892,14 @@ describe('CapActionButton function logic', () => {
|
|
|
867
892
|
expect(renderCtaOptions(label, tooltipLabel, false)).toBe('Test');
|
|
868
893
|
});
|
|
869
894
|
|
|
870
|
-
it('
|
|
871
|
-
const
|
|
872
|
-
const
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
</CapHeading>
|
|
895
|
+
it('inner char count uses current/max format', () => {
|
|
896
|
+
const formatMessage = (msg, values) => `${values.current}/${values.max}`;
|
|
897
|
+
const renderInnerCharCount = (len, max) => (
|
|
898
|
+
<span className="rcs-cta-inner-char-count">
|
|
899
|
+
{formatMessage({}, { current: len, max })}
|
|
900
|
+
</span>
|
|
877
901
|
);
|
|
878
|
-
const result =
|
|
902
|
+
const result = renderInnerCharCount(5, 25);
|
|
879
903
|
expect(result.props.children).toBe('5/25');
|
|
880
904
|
});
|
|
881
905
|
});
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React, { useState, useEffect, useCallback } from 'react';
|
|
8
|
+
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
|
9
9
|
import PropTypes from "prop-types";
|
|
10
10
|
|
|
11
11
|
import LabelHOC from '@capillarytech/cap-ui-library/assets/HOCs/ComponentWithLabelHOC';
|
|
@@ -92,7 +92,7 @@ function CapImageUpload(props) {
|
|
|
92
92
|
[imageSrc],
|
|
93
93
|
);
|
|
94
94
|
|
|
95
|
-
const WithLabel = LabelHOC(ImageComponent);
|
|
95
|
+
const WithLabel = useMemo(() => LabelHOC(ImageComponent), [ImageComponent]);
|
|
96
96
|
|
|
97
97
|
const uploadImages = useCallback((e, { files }) => {
|
|
98
98
|
if (e) {
|
|
@@ -346,6 +346,9 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
346
346
|
render() {
|
|
347
347
|
const {
|
|
348
348
|
hidePopover = false, intl = {}, moduleFilterEnabled, label, modalProps, channel, fetchingSchemaError = false,
|
|
349
|
+
overlayStyle,
|
|
350
|
+
overlayClassName,
|
|
351
|
+
getPopupContainer,
|
|
349
352
|
} = this.props;
|
|
350
353
|
const {formatMessage} = intl;
|
|
351
354
|
const {
|
|
@@ -439,6 +442,9 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
439
442
|
classNames={{
|
|
440
443
|
container: 'tag-list-popover-container'
|
|
441
444
|
}}
|
|
445
|
+
overlayStyle={overlayStyle}
|
|
446
|
+
overlayClassName={overlayClassName}
|
|
447
|
+
getPopupContainer={getPopupContainer}
|
|
442
448
|
>
|
|
443
449
|
<CapTooltip
|
|
444
450
|
title={
|
|
@@ -510,6 +516,10 @@ CapTagList.propTypes = {
|
|
|
510
516
|
disableTooltipMsg: PropTypes.string,
|
|
511
517
|
fetchingSchemaError: PropTypes.bool,
|
|
512
518
|
popoverPlacement: PropTypes.string,
|
|
519
|
+
overlayStyle: PropTypes.object,
|
|
520
|
+
overlayClassName: PropTypes.string,
|
|
521
|
+
/** e.g. () => document.body — avoids overflow/stacking issues inside slideboxes */
|
|
522
|
+
getPopupContainer: PropTypes.func,
|
|
513
523
|
};
|
|
514
524
|
|
|
515
525
|
CapTagList.defaultValue = {
|
|
@@ -8,6 +8,8 @@ import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
|
8
8
|
import CapInput from '@capillarytech/cap-ui-library/CapInput';
|
|
9
9
|
import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
|
|
10
10
|
import messages from './messages';
|
|
11
|
+
import { CUSTOM_VALUES_EDITOR_SECTION_FALLBACK_KEY } from './constants';
|
|
12
|
+
import { getPersonalizationTagColumnLabel } from './utils';
|
|
11
13
|
|
|
12
14
|
const CustomValuesEditor = ({
|
|
13
15
|
isExtractingTags,
|
|
@@ -16,9 +18,7 @@ const CustomValuesEditor = ({
|
|
|
16
18
|
setShowJSON,
|
|
17
19
|
customValues,
|
|
18
20
|
handleJSONTextChange,
|
|
19
|
-
|
|
20
|
-
requiredTags,
|
|
21
|
-
optionalTags,
|
|
21
|
+
sections,
|
|
22
22
|
handleCustomValueChange,
|
|
23
23
|
handleDiscardCustomValues,
|
|
24
24
|
handleUpdatePreview,
|
|
@@ -77,51 +77,70 @@ const CustomValuesEditor = ({
|
|
|
77
77
|
</CapRow>
|
|
78
78
|
) : (
|
|
79
79
|
<>
|
|
80
|
-
{
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
{(sections || []).filter((tagsSection) =>
|
|
81
|
+
(tagsSection?.requiredTags?.length || 0) + (tagsSection?.optionalTags?.length || 0) > 0).map((section) => (
|
|
82
|
+
<React.Fragment key={section.key || section.title?.id || section.title || CUSTOM_VALUES_EDITOR_SECTION_FALLBACK_KEY}>
|
|
83
|
+
{section.title ? (
|
|
84
|
+
<CapLabel type="label2" className="tags-section-title">
|
|
85
|
+
{typeof section.title === 'string' ? section.title : <FormattedMessage {...section.title} />}
|
|
85
86
|
</CapLabel>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<
|
|
93
|
-
{
|
|
94
|
-
</
|
|
95
|
-
<CapRow className="tag-input">
|
|
96
|
-
<CapInput
|
|
97
|
-
type="text"
|
|
98
|
-
isRequired
|
|
99
|
-
className="tag-input-field"
|
|
100
|
-
value={customValues[tag.fullPath] || ''}
|
|
101
|
-
onChange={(e) => handleCustomValueChange(tag.fullPath, e.target.value)}
|
|
102
|
-
placeholder={formatMessage(messages.enterValue)}
|
|
103
|
-
size="small"
|
|
104
|
-
/>
|
|
105
|
-
</CapRow>
|
|
87
|
+
) : null}
|
|
88
|
+
<CapRow className="values-table">
|
|
89
|
+
<CapRow type="flex" className="table-header">
|
|
90
|
+
<CapLabel type="label31" className="header-cell">
|
|
91
|
+
<FormattedMessage {...messages.personalizationTags} />
|
|
92
|
+
</CapLabel>
|
|
93
|
+
<CapLabel type="label31" className="header-cell">
|
|
94
|
+
<FormattedMessage {...messages.customValues} />
|
|
95
|
+
</CapLabel>
|
|
106
96
|
</CapRow>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
<CapRow className="
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
className="tag-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
97
|
+
{(section?.requiredTags || []).map((tag, tagIndex) => {
|
|
98
|
+
const personalizationTagColumnText = getPersonalizationTagColumnLabel(tag);
|
|
99
|
+
const tagKey = tag?.fullPath ?? `required-${tagIndex}`;
|
|
100
|
+
return (
|
|
101
|
+
<CapRow key={tagKey} type="flex" noWrap className="value-row">
|
|
102
|
+
<CapRow type="flex" className="tag-name">
|
|
103
|
+
{personalizationTagColumnText}
|
|
104
|
+
<span className="required-tag-indicator" aria-hidden="true">*</span>
|
|
105
|
+
</CapRow>
|
|
106
|
+
<CapRow type="flex" className="tag-input">
|
|
107
|
+
<CapInput
|
|
108
|
+
type="text"
|
|
109
|
+
isRequired
|
|
110
|
+
className="tag-input-field"
|
|
111
|
+
value={customValues?.[tagKey] ?? ''}
|
|
112
|
+
onChange={(e) => handleCustomValueChange(tagKey, e.target.value)}
|
|
113
|
+
placeholder={formatMessage(messages.enterValue)}
|
|
114
|
+
size="small"
|
|
115
|
+
/>
|
|
116
|
+
</CapRow>
|
|
120
117
|
</CapRow>
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
118
|
+
);
|
|
119
|
+
})}
|
|
120
|
+
{(section?.optionalTags || []).map((tag, tagIndex) => {
|
|
121
|
+
const personalizationTagColumnText = getPersonalizationTagColumnLabel(tag);
|
|
122
|
+
const tagKey = tag?.fullPath ?? `optional-${tagIndex}`;
|
|
123
|
+
return (
|
|
124
|
+
<CapRow key={tagKey} type="flex" noWrap className="value-row">
|
|
125
|
+
<CapRow type="flex" className="tag-name">
|
|
126
|
+
{personalizationTagColumnText}
|
|
127
|
+
</CapRow>
|
|
128
|
+
<CapRow type="flex" className="tag-input">
|
|
129
|
+
<CapInput
|
|
130
|
+
type="text"
|
|
131
|
+
className="tag-input-field"
|
|
132
|
+
value={customValues?.[tagKey] ?? ''}
|
|
133
|
+
onChange={(e) => handleCustomValueChange(tagKey, e.target.value)}
|
|
134
|
+
placeholder={formatMessage(messages.enterValue)}
|
|
135
|
+
size="small"
|
|
136
|
+
/>
|
|
137
|
+
</CapRow>
|
|
138
|
+
</CapRow>
|
|
139
|
+
);
|
|
140
|
+
})}
|
|
141
|
+
</CapRow>
|
|
142
|
+
</React.Fragment>
|
|
143
|
+
))}
|
|
125
144
|
</>
|
|
126
145
|
)}
|
|
127
146
|
<CapRow type='flex' align='middle' justify='space-between' className="editor-actions">
|
|
@@ -155,9 +174,12 @@ CustomValuesEditor.propTypes = {
|
|
|
155
174
|
setShowJSON: PropTypes.func.isRequired,
|
|
156
175
|
customValues: PropTypes.object.isRequired,
|
|
157
176
|
handleJSONTextChange: PropTypes.func.isRequired,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
177
|
+
sections: PropTypes.arrayOf(PropTypes.shape({
|
|
178
|
+
key: PropTypes.string,
|
|
179
|
+
title: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
|
180
|
+
requiredTags: PropTypes.array,
|
|
181
|
+
optionalTags: PropTypes.array,
|
|
182
|
+
})).isRequired,
|
|
161
183
|
handleCustomValueChange: PropTypes.func.isRequired,
|
|
162
184
|
handleDiscardCustomValues: PropTypes.func.isRequired,
|
|
163
185
|
handleUpdatePreview: PropTypes.func.isRequired,
|
|
@@ -18,11 +18,17 @@
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
&__summary-entry {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: baseline;
|
|
23
|
+
gap: 0;
|
|
21
24
|
margin-right: $CAP_SPACE_18;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
&__summary-key
|
|
25
|
-
|
|
27
|
+
&__summary-key,
|
|
28
|
+
&__summary-value {
|
|
29
|
+
line-height: 1.4;
|
|
30
|
+
margin-top: 0;
|
|
31
|
+
margin-bottom: 0;
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
&__edit-icon {
|