@capillarytech/creatives-library 8.0.255-alpha.4 → 8.0.256

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 (164) hide show
  1. package/constants/unified.js +0 -1
  2. package/package.json +1 -1
  3. package/services/api.js +0 -5
  4. package/translations/en.json +3 -4
  5. package/utils/common.js +0 -6
  6. package/utils/tests/transformerUtils.test.js +0 -297
  7. package/utils/transformerUtils.js +0 -40
  8. package/v2Components/CapImageUpload/constants.js +0 -2
  9. package/v2Components/CapImageUpload/index.js +16 -65
  10. package/v2Components/CapImageUpload/index.scss +1 -4
  11. package/v2Components/CapImageUpload/messages.js +1 -5
  12. package/v2Components/CommonTestAndPreview/UnifiedPreview/InAppPreviewContent.js +3 -3
  13. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +3 -3
  14. package/v2Components/CommonTestAndPreview/UnifiedPreview/SmsPreviewContent.js +3 -3
  15. package/v2Components/CommonTestAndPreview/UnifiedPreview/ViberPreviewContent.js +3 -3
  16. package/v2Components/CommonTestAndPreview/UnifiedPreview/WhatsAppPreviewContent.js +1 -1
  17. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +37 -6
  18. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +0 -2
  19. package/v2Components/TemplatePreview/_templatePreview.scss +1 -2
  20. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +0 -1
  21. package/v2Containers/App/constants.js +0 -5
  22. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +3 -4
  23. package/v2Containers/CreativesContainer/SlideBoxContent.js +2 -57
  24. package/v2Containers/CreativesContainer/SlideBoxHeader.js +0 -1
  25. package/v2Containers/CreativesContainer/constants.js +0 -3
  26. package/v2Containers/CreativesContainer/index.js +0 -168
  27. package/v2Containers/CreativesContainer/messages.js +0 -4
  28. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +0 -210
  29. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -304
  30. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +12 -36
  31. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +6 -8
  32. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +75 -100
  33. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +54 -72
  34. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +214 -286
  35. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +12 -16
  36. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +48 -60
  37. package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
  38. package/v2Containers/Templates/_templates.scss +0 -205
  39. package/v2Containers/Templates/actions.js +1 -2
  40. package/v2Containers/Templates/constants.js +0 -1
  41. package/v2Containers/Templates/index.js +34 -274
  42. package/v2Containers/Templates/messages.js +0 -24
  43. package/v2Containers/Templates/reducer.js +0 -2
  44. package/v2Containers/Templates/tests/index.test.js +0 -10
  45. package/v2Containers/TemplatesV2/index.js +7 -15
  46. package/v2Containers/TemplatesV2/messages.js +0 -4
  47. package/v2Containers/Whatsapp/index.js +1 -1
  48. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +870 -1442
  49. package/utils/imageUrlUpload.js +0 -141
  50. package/v2Components/CapImageUrlUpload/constants.js +0 -26
  51. package/v2Components/CapImageUrlUpload/index.js +0 -365
  52. package/v2Components/CapImageUrlUpload/index.scss +0 -35
  53. package/v2Components/CapImageUrlUpload/messages.js +0 -47
  54. package/v2Containers/WebPush/Create/components/BrandIconSection.js +0 -108
  55. package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -172
  56. package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
  57. package/v2Containers/WebPush/Create/components/ButtonList.js +0 -145
  58. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +0 -164
  59. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +0 -463
  60. package/v2Containers/WebPush/Create/components/FormActions.js +0 -54
  61. package/v2Containers/WebPush/Create/components/FormActions.test.js +0 -163
  62. package/v2Containers/WebPush/Create/components/MediaSection.js +0 -142
  63. package/v2Containers/WebPush/Create/components/MediaSection.test.js +0 -341
  64. package/v2Containers/WebPush/Create/components/MessageSection.js +0 -103
  65. package/v2Containers/WebPush/Create/components/MessageSection.test.js +0 -268
  66. package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +0 -87
  67. package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +0 -210
  68. package/v2Containers/WebPush/Create/components/TemplateNameSection.js +0 -54
  69. package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +0 -143
  70. package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +0 -86
  71. package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +0 -16
  72. package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +0 -41
  73. package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +0 -54
  74. package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +0 -37
  75. package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +0 -21
  76. package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
  77. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
  78. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
  79. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -633
  80. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
  81. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
  82. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -78
  83. package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +0 -138
  84. package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +0 -406
  85. package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +0 -30
  86. package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +0 -151
  87. package/v2Containers/WebPush/Create/hooks/useImageUpload.js +0 -104
  88. package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +0 -538
  89. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -122
  90. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -633
  91. package/v2Containers/WebPush/Create/index.js +0 -1148
  92. package/v2Containers/WebPush/Create/index.scss +0 -134
  93. package/v2Containers/WebPush/Create/messages.js +0 -203
  94. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -228
  95. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -294
  96. package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -90
  97. package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -305
  98. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -23
  99. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -155
  100. package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
  101. package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
  102. package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +0 -9
  103. package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +0 -9
  104. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  105. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  106. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
  107. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
  108. package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +0 -9
  109. package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +0 -9
  110. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
  111. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
  112. package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +0 -9
  113. package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +0 -9
  114. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -47
  115. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -141
  116. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
  117. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -68
  118. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -61
  119. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -99
  120. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -733
  121. package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +0 -571
  122. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -81
  123. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +0 -81
  124. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -50
  125. package/v2Containers/WebPush/Create/preview/constants.js +0 -637
  126. package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -79
  127. package/v2Containers/WebPush/Create/preview/preview.scss +0 -351
  128. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -370
  129. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
  130. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
  131. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
  132. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -47
  133. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
  134. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
  135. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
  136. package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -207
  137. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -153
  138. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
  139. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -101
  140. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -229
  141. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
  142. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1081
  143. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
  144. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -1327
  145. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -131
  146. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -112
  147. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
  148. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -129
  149. package/v2Containers/WebPush/Create/utils/payloadBuilder.js +0 -96
  150. package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +0 -396
  151. package/v2Containers/WebPush/Create/utils/previewUtils.js +0 -89
  152. package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -115
  153. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
  154. package/v2Containers/WebPush/Create/utils/validation.js +0 -75
  155. package/v2Containers/WebPush/Create/utils/validation.test.js +0 -283
  156. package/v2Containers/WebPush/actions.js +0 -60
  157. package/v2Containers/WebPush/constants.js +0 -132
  158. package/v2Containers/WebPush/index.js +0 -2
  159. package/v2Containers/WebPush/reducer.js +0 -104
  160. package/v2Containers/WebPush/sagas.js +0 -119
  161. package/v2Containers/WebPush/selectors.js +0 -65
  162. package/v2Containers/WebPush/tests/reducer.test.js +0 -863
  163. package/v2Containers/WebPush/tests/sagas.test.js +0 -566
  164. package/v2Containers/WebPush/tests/selectors.test.js +0 -960
@@ -1,108 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { FormattedMessage } from 'react-intl';
4
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
5
- import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
6
- import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
7
- import CapDivider from '@capillarytech/cap-ui-library/CapDivider';
8
- import CapImageUpload from '../../../../v2Components/CapImageUpload';
9
- import { WEBPUSH_BRAND_ICON } from '../../../CreativesContainer/constants';
10
- import {
11
- BRAND_ICON_OPTIONS,
12
- ALLOWED_IMAGE_EXTENSIONS_REGEX,
13
- WEBPUSH_BRAND_ICON_SIZE,
14
- WEBPUSH_BRAND_ICON_RECOMMENDED_DIMENSIONS,
15
- } from '../../constants';
16
-
17
- /**
18
- * BrandIconSection component - Brand icon/logo upload options
19
- */
20
- export const BrandIconSection = ({
21
- brandIconOption,
22
- onBrandIconChange,
23
- brandIconUpload,
24
- isLocked,
25
- isAnyUploadActive,
26
- formatMessage,
27
- messages,
28
- webPush,
29
- isFullMode,
30
- }) => {
31
- const {
32
- imageSrc: brandIconSrc,
33
- uploadAsset: uploadBrandIconAsset,
34
- setUpdateImageSrc: setUpdateBrandIconSrc,
35
- updateOnReUpload: updateOnBrandIconReUpload,
36
- } = brandIconUpload;
37
-
38
- const brandIconOptions = [
39
- { value: BRAND_ICON_OPTIONS.DONT_SHOW, label: formatMessage(messages.dontShow) },
40
- { value: BRAND_ICON_OPTIONS.UPLOAD_IMAGE, label: formatMessage(messages.uploadImage) },
41
- // NOTE: Commented out due to technical blocker - "Add image URL" option for Brand icon/logo
42
- // { value: BRAND_ICON_OPTIONS.ADD_IMAGE_URL, label: formatMessage(messages.addImageUrl) },
43
- ];
44
-
45
- return (
46
- <>
47
- <CapRow className="creatives-webpush-brand-icon">
48
- <CapHeading type="h4" className="webpush-brand-icon">
49
- <FormattedMessage {...messages.brandIconLogo} />
50
- </CapHeading>
51
- <CapRadioGroup
52
- options={brandIconOptions}
53
- value={brandIconOption}
54
- onChange={onBrandIconChange}
55
- disabled={isAnyUploadActive}
56
- />
57
- </CapRow>
58
- {brandIconOption === BRAND_ICON_OPTIONS.UPLOAD_IMAGE && (
59
- <CapRow
60
- className="webpush-brand-icon-upload-section"
61
- style={isLocked ? { pointerEvents: 'none', opacity: 0.5 } : undefined}
62
- aria-disabled={isLocked}
63
- >
64
- <CapImageUpload
65
- allowedExtensionsRegex={ALLOWED_IMAGE_EXTENSIONS_REGEX}
66
- imgSize={WEBPUSH_BRAND_ICON_SIZE}
67
- uploadAsset={uploadBrandIconAsset}
68
- isFullMode={isFullMode}
69
- imageSrc={brandIconSrc}
70
- updateImageSrc={setUpdateBrandIconSrc}
71
- updateOnReUpload={updateOnBrandIconReUpload}
72
- index={1}
73
- className="cap-custom-image-upload"
74
- key="webpush-brand-icon-uploaded-image"
75
- imageData={webPush}
76
- channel={WEBPUSH_BRAND_ICON}
77
- showReUploadButton
78
- recommendedDimensions={WEBPUSH_BRAND_ICON_RECOMMENDED_DIMENSIONS}
79
- disabled={isLocked}
80
- />
81
- </CapRow>
82
- )}
83
- <CapDivider />
84
- </>
85
- );
86
- };
87
-
88
- BrandIconSection.propTypes = {
89
- brandIconOption: PropTypes.string.isRequired,
90
- onBrandIconChange: PropTypes.func.isRequired,
91
- brandIconUpload: PropTypes.object.isRequired,
92
- isLocked: PropTypes.bool,
93
- isAnyUploadActive: PropTypes.bool,
94
- formatMessage: PropTypes.func.isRequired,
95
- messages: PropTypes.object.isRequired,
96
- webPush: PropTypes.object,
97
- isFullMode: PropTypes.bool,
98
- };
99
-
100
- BrandIconSection.defaultProps = {
101
- isLocked: false,
102
- isAnyUploadActive: false,
103
- webPush: {},
104
- isFullMode: true,
105
- };
106
-
107
- export default BrandIconSection;
108
-
@@ -1,172 +0,0 @@
1
- import React, { useState, useCallback } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { FormattedMessage } from 'react-intl';
4
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
5
- import CapInput from '@capillarytech/cap-ui-library/CapInput';
6
- import CapButton from '@capillarytech/cap-ui-library/CapButton';
7
- import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
8
- import messages from '../messages';
9
- import { isValidHttpUrl } from '../utils/urlValidation';
10
- import { WEBPUSH_BUTTON_TYPES, BUTTON_TEXT_MAX_LENGTH } from '../../constants';
11
-
12
- const ButtonForm = ({
13
- buttonType, // 'primary' or 'secondary'
14
- formatMessage,
15
- onSave,
16
- onCancel,
17
- initialData,
18
- isEditMode,
19
- }) => {
20
- const [buttonText, setButtonText] = useState(initialData?.text || '');
21
- const [buttonUrl, setButtonUrl] = useState(initialData?.url || '');
22
- const [buttonTextError, setButtonTextError] = useState('');
23
- const [buttonUrlError, setButtonUrlError] = useState('');
24
-
25
- const validateButtonText = useCallback((value) => {
26
- if (!value || value.trim() === '') {
27
- return formatMessage(messages.buttonTextRequired);
28
- }
29
- return '';
30
- }, [formatMessage]);
31
-
32
- const validateButtonUrl = useCallback((value) => {
33
- if (!value || value.trim() === '') {
34
- return formatMessage(messages.buttonUrlRequired);
35
- }
36
-
37
- if (!isValidHttpUrl(value)) {
38
- return formatMessage(messages.buttonUrlInvalid);
39
- }
40
-
41
- return '';
42
- }, [formatMessage]);
43
-
44
- const handleButtonTextChange = useCallback((e) => {
45
- const { value } = e.target;
46
- setButtonText(value);
47
- const nextError = validateButtonText(value);
48
- setButtonTextError((prev) => (prev === nextError ? prev : nextError));
49
- }, [validateButtonText]);
50
-
51
- const handleButtonUrlChange = useCallback((e) => {
52
- const { value } = e.target;
53
- setButtonUrl(value);
54
- const nextError = validateButtonUrl(value);
55
- setButtonUrlError((prev) => (prev === nextError ? prev : nextError));
56
- }, [validateButtonUrl]);
57
-
58
- const handleSave = useCallback(() => {
59
- const textError = validateButtonText(buttonText);
60
- const urlError = validateButtonUrl(buttonUrl);
61
-
62
- if (textError || urlError) {
63
- setButtonTextError(textError);
64
- setButtonUrlError(urlError);
65
- return;
66
- }
67
-
68
- onSave({
69
- text: buttonText.trim(),
70
- url: buttonUrl.trim(),
71
- type: buttonType,
72
- });
73
- }, [buttonText, buttonUrl, buttonType, onSave, validateButtonText, validateButtonUrl]);
74
-
75
- const handleCancel = useCallback(() => {
76
- onCancel();
77
- }, [onCancel]);
78
-
79
- const isSaveDisabled = !buttonText.trim() || !buttonUrl.trim() || buttonTextError || buttonUrlError;
80
-
81
- const renderCharacterCountSuffix = () => {
82
- const currentLength = buttonText.length;
83
- const maxLength = BUTTON_TEXT_MAX_LENGTH;
84
-
85
- return (
86
- <span className="button-character-count-suffix">
87
- {`${currentLength}/${maxLength}`}
88
- </span>
89
- );
90
- };
91
-
92
- const handleKeyDown = useCallback((e) => {
93
- if (e.key === 'Enter' && !isSaveDisabled) {
94
- e.preventDefault();
95
- handleSave();
96
- }
97
- }, [handleSave, isSaveDisabled]);
98
-
99
- return (
100
- <div className="webpush-button-form" onKeyDown={handleKeyDown}>
101
- <CapRow className="button-form-row">
102
- <CapHeading type="h4" className="button-form-heading">
103
- <FormattedMessage {...messages.buttonText} />
104
- </CapHeading>
105
- <div className="button-form-field">
106
- <CapInput
107
- id={`webpush-button-text-input-${buttonType}`}
108
- placeholder={formatMessage(messages.buttonTextPlaceholder)}
109
- value={buttonText}
110
- onChange={handleButtonTextChange}
111
- maxLength={BUTTON_TEXT_MAX_LENGTH}
112
- size="default"
113
- status={buttonTextError ? 'error' : ''}
114
- help={buttonTextError || ''}
115
- suffix={renderCharacterCountSuffix()}
116
- />
117
- </div>
118
- </CapRow>
119
- <CapRow className="button-form-row">
120
- <CapHeading type="h4" className="button-form-heading">
121
- <FormattedMessage {...messages.buttonUrlLabel} />
122
- </CapHeading>
123
- <CapInput
124
- id={`webpush-button-url-input-${buttonType}`}
125
- placeholder={formatMessage(messages.buttonUrlPlaceholder)}
126
- value={buttonUrl}
127
- onChange={handleButtonUrlChange}
128
- size="default"
129
- status={buttonUrlError ? 'error' : ''}
130
- help={buttonUrlError || ''}
131
- />
132
- </CapRow>
133
- <CapRow className="button-form-actions">
134
- <CapButton
135
- type="primary"
136
- onClick={handleSave}
137
- disabled={isSaveDisabled}
138
- className="button-form-save"
139
- >
140
- <FormattedMessage {...messages.saveButton} />
141
- </CapButton>
142
- <CapButton
143
- type="secondary"
144
- onClick={handleCancel}
145
- className="button-form-cancel"
146
- >
147
- <FormattedMessage {...(isEditMode ? messages.cancelButton : messages.deleteButton)} />
148
- </CapButton>
149
- </CapRow>
150
- </div>
151
- );
152
- };
153
-
154
- ButtonForm.propTypes = {
155
- buttonType: PropTypes.oneOf([WEBPUSH_BUTTON_TYPES.PRIMARY, WEBPUSH_BUTTON_TYPES.SECONDARY]).isRequired,
156
- formatMessage: PropTypes.func.isRequired,
157
- onSave: PropTypes.func.isRequired,
158
- onCancel: PropTypes.func.isRequired,
159
- initialData: PropTypes.shape({
160
- text: PropTypes.string,
161
- url: PropTypes.string,
162
- }),
163
- isEditMode: PropTypes.bool,
164
- };
165
-
166
- ButtonForm.defaultProps = {
167
- initialData: null,
168
- isEditMode: false,
169
- };
170
-
171
- export default ButtonForm;
172
-
@@ -1,101 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
4
- import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
5
- import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
6
-
7
- const ButtonItem = ({
8
- button,
9
- index,
10
- onEdit,
11
- onDelete,
12
- onDragStart,
13
- onDragOver,
14
- onDrop,
15
- onDragEnd,
16
- disabled,
17
- }) => {
18
- const handleDragStart = (e) => {
19
- if (disabled) return;
20
- e.dataTransfer.effectAllowed = 'move';
21
- e.dataTransfer.setData('text/html', e.currentTarget);
22
- onDragStart(index);
23
- };
24
-
25
- const handleDragOver = (e) => {
26
- if (disabled) return;
27
- e.preventDefault();
28
- e.dataTransfer.dropEffect = 'move';
29
- onDragOver(index);
30
- };
31
-
32
- const handleDrop = (e) => {
33
- if (disabled) return;
34
- e.preventDefault();
35
- e.stopPropagation();
36
- onDrop(index);
37
- };
38
-
39
- return (
40
- <div
41
- className={`webpush-button-item ${disabled ? 'disabled' : ''}`}
42
- draggable={!disabled}
43
- onDragStart={handleDragStart}
44
- onDragOver={handleDragOver}
45
- onDrop={handleDrop}
46
- onDragEnd={onDragEnd}
47
- >
48
- <CapRow align="middle" className="button-item-content">
49
- <CapColumn span={1} className="button-item-drag-handle">
50
- <CapIcon type="drag" className="drag-icon" />
51
- </CapColumn>
52
- <CapColumn span={1} className="button-item-icon">
53
- <CapIcon type="link" className="link-icon" />
54
- </CapColumn>
55
- <CapColumn span={14} className="button-item-info">
56
- <div className="button-item-text-row">
57
- <span className="button-item-text">{button.text}</span>
58
- </div>
59
- </CapColumn>
60
- <CapColumn span={8} className="button-item-actions">
61
- <div className="button-item-url">{button.url}</div>
62
- <div className="action-icons">
63
- <CapIcon
64
- type="edit"
65
- className="action-icon"
66
- onClick={() => !disabled && onEdit(index)}
67
- />
68
- <CapIcon
69
- type="delete"
70
- className="action-icon delete-icon"
71
- onClick={() => !disabled && onDelete(index)}
72
- />
73
- </div>
74
- </CapColumn>
75
- </CapRow>
76
- </div>
77
- );
78
- };
79
-
80
- ButtonItem.propTypes = {
81
- button: PropTypes.shape({
82
- text: PropTypes.string.isRequired,
83
- url: PropTypes.string.isRequired,
84
- type: PropTypes.string.isRequired,
85
- }).isRequired,
86
- index: PropTypes.number.isRequired,
87
- onEdit: PropTypes.func.isRequired,
88
- onDelete: PropTypes.func.isRequired,
89
- onDragStart: PropTypes.func.isRequired,
90
- onDragOver: PropTypes.func.isRequired,
91
- onDrop: PropTypes.func.isRequired,
92
- onDragEnd: PropTypes.func.isRequired,
93
- disabled: PropTypes.bool,
94
- };
95
-
96
- ButtonItem.defaultProps = {
97
- disabled: false,
98
- };
99
-
100
- export default ButtonItem;
101
-
@@ -1,145 +0,0 @@
1
- import React, { useState } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { FormattedMessage } from 'react-intl';
4
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
5
- import CapButton from '@capillarytech/cap-ui-library/CapButton';
6
- import ButtonItem from './ButtonItem';
7
- import messages from '../messages';
8
-
9
- const ButtonList = ({
10
- buttons,
11
- onEdit,
12
- onDelete,
13
- onReorder,
14
- onAddPrimary,
15
- onAddSecondary,
16
- showAddPrimary,
17
- showAddSecondary,
18
- disabled,
19
- disableSecondaryButton,
20
- isInlineFormVisible,
21
- inlineFormIndex,
22
- renderInlineForm,
23
- }) => {
24
- const [draggedIndex, setDraggedIndex] = useState(null);
25
-
26
- const handleDragStart = (index) => {
27
- if (disabled) return;
28
- setDraggedIndex(index);
29
- };
30
-
31
- const handleDragOver = (index) => {
32
- if (disabled) return;
33
- if (draggedIndex === null || draggedIndex === index) return;
34
-
35
- // Reorder buttons
36
- onReorder(draggedIndex, index);
37
- setDraggedIndex(index);
38
- };
39
-
40
- const handleDrop = () => {
41
- if (disabled) return;
42
- };
43
-
44
- const handleDragEnd = () => {
45
- if (disabled) return;
46
- setDraggedIndex(null);
47
- };
48
-
49
- const shouldRenderInlineForm = isInlineFormVisible
50
- && typeof inlineFormIndex === 'number'
51
- && inlineFormIndex >= 0;
52
-
53
- // Don't render the container if there are no buttons
54
- if (buttons.length === 0) {
55
- return null;
56
- }
57
-
58
- return (
59
- <div className="webpush-button-list">
60
- {buttons.map((button, index) => {
61
- if (shouldRenderInlineForm && inlineFormIndex === index && typeof renderInlineForm === 'function') {
62
- return (
63
- <div key={`button-inline-form-${button.id}`} className="button-inline-form">
64
- {renderInlineForm()}
65
- </div>
66
- );
67
- }
68
- // Only disable items that are not being edited
69
- const isItemDisabled = disabled || (isInlineFormVisible && inlineFormIndex !== null && inlineFormIndex !== index);
70
- return (
71
- <ButtonItem
72
- key={button.id}
73
- button={button}
74
- index={index}
75
- onEdit={onEdit}
76
- onDelete={onDelete}
77
- onDragStart={handleDragStart}
78
- onDragOver={handleDragOver}
79
- onDrop={handleDrop}
80
- onDragEnd={handleDragEnd}
81
- disabled={isItemDisabled}
82
- />
83
- );
84
- })}
85
- {showAddPrimary && (
86
- <CapRow className="button-list-add-button">
87
- <CapButton
88
- type="flat"
89
- onClick={onAddPrimary}
90
- className="add-primary-button button-add-trigger"
91
- icon="plus"
92
- disabled={disabled}
93
- >
94
- <FormattedMessage {...messages.addPrimaryButton} />
95
- </CapButton>
96
- </CapRow>
97
- )}
98
- {showAddSecondary && (
99
- <CapRow className="button-list-add-button">
100
- <CapButton
101
- type="flat"
102
- onClick={onAddSecondary}
103
- className="add-secondary-button button-add-trigger"
104
- icon="plus"
105
- disabled={disableSecondaryButton || disabled}
106
- >
107
- <FormattedMessage {...messages.addSecondaryButton} />
108
- </CapButton>
109
- </CapRow>
110
- )}
111
- </div>
112
- );
113
- };
114
-
115
- ButtonList.propTypes = {
116
- buttons: PropTypes.arrayOf(PropTypes.shape({
117
- id: PropTypes.string.isRequired,
118
- text: PropTypes.string.isRequired,
119
- url: PropTypes.string.isRequired,
120
- type: PropTypes.string.isRequired,
121
- })).isRequired,
122
- onEdit: PropTypes.func.isRequired,
123
- onDelete: PropTypes.func.isRequired,
124
- onReorder: PropTypes.func.isRequired,
125
- onAddPrimary: PropTypes.func.isRequired,
126
- onAddSecondary: PropTypes.func.isRequired,
127
- showAddPrimary: PropTypes.bool.isRequired,
128
- showAddSecondary: PropTypes.bool.isRequired,
129
- disabled: PropTypes.bool,
130
- disableSecondaryButton: PropTypes.bool,
131
- isInlineFormVisible: PropTypes.bool,
132
- inlineFormIndex: PropTypes.number,
133
- renderInlineForm: PropTypes.func,
134
- };
135
-
136
- ButtonList.defaultProps = {
137
- disabled: false,
138
- disableSecondaryButton: false,
139
- isInlineFormVisible: false,
140
- inlineFormIndex: null,
141
- renderInlineForm: null,
142
- };
143
-
144
- export default ButtonList;
145
-
@@ -1,164 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { FormattedMessage } from 'react-intl';
4
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
5
- import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
6
- import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
7
- import CapInput from '@capillarytech/cap-ui-library/CapInput';
8
- import CapButton from '@capillarytech/cap-ui-library/CapButton';
9
- import ButtonList from './ButtonList';
10
- import ButtonForm from './ButtonForm';
11
- import { ON_CLICK_BEHAVIOUR_OPTIONS } from '../../constants';
12
-
13
- /**
14
- * ButtonsLinksSection component - On-click behavior and CTA buttons management
15
- */
16
- export const ButtonsLinksSection = ({
17
- onClickBehaviour,
18
- onClickBehaviourOptions,
19
- onClickBehaviourChange,
20
- redirectUrl,
21
- redirectUrlError,
22
- onRedirectUrlChange,
23
- buttonState,
24
- formatMessage,
25
- messages,
26
- }) => {
27
- const {
28
- buttons,
29
- isAddingButton,
30
- buttonBeingAdded,
31
- editingButtonIndex,
32
- handleAddPrimaryButton,
33
- handleAddSecondaryButton,
34
- handleButtonSave,
35
- handleButtonCancel,
36
- handleButtonEdit,
37
- handleButtonDelete,
38
- handleButtonReorder,
39
- isAddFlow,
40
- isEditFlow,
41
- showAddPrimaryButton,
42
- showAddSecondaryButton,
43
- showDisabledSecondaryDuringPrimary,
44
- disableSecondaryAddButton,
45
- } = buttonState;
46
-
47
- const renderButtonForm = (isEditMode) => (
48
- <ButtonForm
49
- buttonType={buttonBeingAdded}
50
- formatMessage={formatMessage}
51
- onSave={handleButtonSave}
52
- onCancel={handleButtonCancel}
53
- initialData={isEditMode && editingButtonIndex !== null ? buttons[editingButtonIndex] : null}
54
- isEditMode={isEditMode}
55
- />
56
- );
57
-
58
- return (
59
- <>
60
- <CapRow className="creatives-webpush-buttons-links">
61
- <CapHeading type="h4" className="webpush-buttons-links">
62
- <FormattedMessage {...messages.buttonsAndLinks} />
63
- </CapHeading>
64
- <CapHeading type="h5" className="webpush-on-click-behaviour">
65
- <FormattedMessage {...messages.onClickBehaviour} />
66
- </CapHeading>
67
- <CapRadioGroup
68
- options={onClickBehaviourOptions}
69
- value={onClickBehaviour}
70
- onChange={onClickBehaviourChange}
71
- />
72
- {onClickBehaviour === ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL && (
73
- <CapInput
74
- id="webpush-redirect-url-input"
75
- className="webpush-redirect-url-input"
76
- placeholder={formatMessage(messages.enterUrl)}
77
- value={redirectUrl}
78
- onChange={onRedirectUrlChange}
79
- size="default"
80
- status={redirectUrlError ? 'error' : ''}
81
- help={redirectUrlError || ''}
82
- />
83
- )}
84
- </CapRow>
85
- <CapRow className="creatives-webpush-buttons-section">
86
- <CapHeading type="h5" className="webpush-buttons-section-heading">
87
- <FormattedMessage {...messages.buttons} />{' '}
88
- <span className="optional-text">
89
- <FormattedMessage {...messages.optional} />
90
- </span>
91
- </CapHeading>
92
- <ButtonList
93
- buttons={buttons}
94
- onEdit={handleButtonEdit}
95
- onDelete={handleButtonDelete}
96
- onReorder={handleButtonReorder}
97
- onAddPrimary={handleAddPrimaryButton}
98
- onAddSecondary={handleAddSecondaryButton}
99
- showAddPrimary={false}
100
- showAddSecondary={false}
101
- disabled={isAddFlow}
102
- disableSecondaryButton={disableSecondaryAddButton}
103
- isInlineFormVisible={isEditFlow}
104
- inlineFormIndex={isEditFlow ? editingButtonIndex : null}
105
- renderInlineForm={isEditFlow ? () => renderButtonForm(true) : null}
106
- />
107
- {isAddFlow && buttonBeingAdded && renderButtonForm(false)}
108
- {(showAddPrimaryButton || showAddSecondaryButton || showDisabledSecondaryDuringPrimary) && (
109
- <div className="button-add-controls">
110
- {showAddPrimaryButton && (
111
- <CapButton
112
- type="flat"
113
- onClick={handleAddPrimaryButton}
114
- className="add-primary-button button-add-trigger"
115
- icon="plus"
116
- >
117
- <FormattedMessage {...messages.addButton} />
118
- </CapButton>
119
- )}
120
- {showAddSecondaryButton && (
121
- <CapButton
122
- type="flat"
123
- onClick={handleAddSecondaryButton}
124
- className="add-secondary-button button-add-trigger"
125
- icon="plus"
126
- >
127
- <FormattedMessage {...messages.addButton} />
128
- </CapButton>
129
- )}
130
- {showDisabledSecondaryDuringPrimary && (
131
- <CapButton
132
- type="flat"
133
- className="add-secondary-button button-add-trigger"
134
- icon="plus"
135
- disabled
136
- >
137
- <FormattedMessage {...messages.addButton} />
138
- </CapButton>
139
- )}
140
- </div>
141
- )}
142
- </CapRow>
143
- </>
144
- );
145
- };
146
-
147
- ButtonsLinksSection.propTypes = {
148
- onClickBehaviour: PropTypes.string.isRequired,
149
- onClickBehaviourOptions: PropTypes.array.isRequired,
150
- onClickBehaviourChange: PropTypes.func.isRequired,
151
- redirectUrl: PropTypes.string.isRequired,
152
- redirectUrlError: PropTypes.string,
153
- onRedirectUrlChange: PropTypes.func.isRequired,
154
- buttonState: PropTypes.object.isRequired,
155
- formatMessage: PropTypes.func.isRequired,
156
- messages: PropTypes.object.isRequired,
157
- };
158
-
159
- ButtonsLinksSection.defaultProps = {
160
- redirectUrlError: '',
161
- };
162
-
163
- export default ButtonsLinksSection;
164
-