@capillarytech/creatives-library 9.0.29 → 9.0.31
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 +22 -1
- package/utils/rcsPayloadUtils.js +102 -0
- package/utils/templateVarUtils.js +198 -0
- package/utils/tests/rcsPayloadUtils.test.js +295 -0
- package/utils/tests/templateVarUtils.test.js +204 -0
- package/v2Components/CapActionButton/constants.js +21 -1
- package/v2Components/CapActionButton/index.js +261 -144
- package/v2Components/CapActionButton/index.scss +245 -14
- package/v2Components/CapActionButton/messages.js +32 -3
- package/v2Components/CapActionButton/tests/index.test.js +74 -19
- package/v2Components/CapImageUpload/index.js +2 -2
- package/v2Components/CapTagList/index.js +9 -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 +58 -11
- package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +186 -22
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +381 -80
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +155 -8
- package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
- package/v2Components/CommonTestAndPreview/constants.js +35 -2
- package/v2Components/CommonTestAndPreview/index.js +774 -231
- 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 +412 -257
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +337 -63
- 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 +108 -15
- 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/tests/utils.test.js +151 -0
- 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 +471 -0
- package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +45 -25
- package/v2Components/TemplatePreview/constants.js +2 -0
- package/v2Components/TemplatePreview/index.js +147 -32
- 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/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +4 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +20 -20
- package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +27 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +37 -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 +77 -0
- package/v2Containers/CreativesContainer/index.js +322 -106
- package/v2Containers/CreativesContainer/index.scss +102 -1
- package/v2Containers/CreativesContainer/tests/CreativesSlideBoxWrapper.test.js +58 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.smsDltPreview.test.js +73 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +37 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +103 -34
- package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +193 -15
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +88 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +549 -57
- 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/carouselUtils.js +224 -0
- package/v2Containers/Rcs/components/CarouselCard.js +317 -0
- package/v2Containers/Rcs/components/CarouselCardButtons.js +113 -0
- package/v2Containers/Rcs/components/CarouselCardMedia.js +136 -0
- package/v2Containers/Rcs/components/CarouselCharacterCount.js +31 -0
- package/v2Containers/Rcs/components/CarouselDimensionSelection.js +80 -0
- package/v2Containers/Rcs/constants.js +132 -16
- package/v2Containers/Rcs/index.js +1822 -946
- package/v2Containers/Rcs/index.scss +443 -8
- package/v2Containers/Rcs/messages.js +45 -22
- package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +494 -0
- package/v2Containers/Rcs/tests/CarouselCard.test.js +464 -0
- package/v2Containers/Rcs/tests/CarouselCardButtons.test.js +211 -0
- package/v2Containers/Rcs/tests/CarouselCardMedia.test.js +160 -0
- package/v2Containers/Rcs/tests/CarouselCharacterCount.test.js +50 -0
- package/v2Containers/Rcs/tests/CarouselDimensionSelection.test.js +119 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +74440 -39387
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +10 -74
- package/v2Containers/Rcs/tests/carouselUtils.test.js +916 -0
- package/v2Containers/Rcs/tests/index.test.js +275 -40
- package/v2Containers/Rcs/tests/mockData.js +38 -0
- package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +912 -0
- package/v2Containers/Rcs/tests/utils.test.js +682 -30
- package/v2Containers/Rcs/utils.js +514 -12
- 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 +5 -0
- package/v2Containers/Templates/TemplatesActionBar.js +101 -0
- package/v2Containers/Templates/_templates.scss +196 -12
- package/v2Containers/Templates/actions.js +11 -0
- package/v2Containers/Templates/constants.js +2 -0
- package/v2Containers/Templates/index.js +131 -59
- package/v2Containers/Templates/sagas.js +57 -13
- package/v2Containers/Templates/tests/TemplatesActionBar.test.js +129 -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 +88 -25
- 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
|
@@ -8,6 +8,7 @@ import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
|
8
8
|
import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
|
|
9
9
|
import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
|
|
10
10
|
import CapHeader from "@capillarytech/cap-ui-library/CapHeader";
|
|
11
|
+
import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
|
|
11
12
|
import CapSelect from '@capillarytech/cap-ui-library/CapSelect';
|
|
12
13
|
import CapInput from '@capillarytech/cap-ui-library/CapInput';
|
|
13
14
|
import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
|
|
@@ -16,13 +17,24 @@ import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
|
16
17
|
import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
|
|
17
18
|
import CapTooltipWithInfo from '@capillarytech/cap-ui-library/CapTooltipWithInfo';
|
|
18
19
|
import { CAP_SPACE_04 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
19
|
-
import globalMessages from '../../v2Containers/Cap/messages';
|
|
20
|
+
import globalMessages from '../../v2Containers/Cap/messages';
|
|
21
|
+
import TagList from '../../v2Containers/TagList';
|
|
20
22
|
|
|
21
23
|
import { isUrl, isValidText } from '../../v2Containers/Line/Container/Wrapper/utils';
|
|
22
24
|
import messages from './messages';
|
|
23
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
BTN_MAX_LENGTH,
|
|
27
|
+
URL_MAX_LENGTH,
|
|
28
|
+
PHONE_NUMBER_MAX_LENGTH,
|
|
29
|
+
invalidVarRegex,
|
|
30
|
+
HANDLERS,
|
|
31
|
+
RCS_CTA_URL_TYPE,
|
|
32
|
+
CTA_TYPE_RADIO_OPTIONS,
|
|
33
|
+
CTA_URL_TYPE_SELECT_OPTIONS,
|
|
34
|
+
DYNAMIC_URL_SUFFIX,
|
|
35
|
+
} from './constants';
|
|
24
36
|
import './index.scss';
|
|
25
|
-
import { INITIAL_SUGGESTIONS, RCS_BUTTON_TYPES} from '../../v2Containers/Rcs/constants';
|
|
37
|
+
import { INITIAL_SUGGESTIONS, RCS_BUTTON_TYPES, HOST_ICS} from '../../v2Containers/Rcs/constants';
|
|
26
38
|
|
|
27
39
|
const { TextArea } = CapInput;
|
|
28
40
|
|
|
@@ -41,9 +53,13 @@ export const CapActionButton = (props) => {
|
|
|
41
53
|
injectedTags = {},
|
|
42
54
|
location = {},
|
|
43
55
|
selectedOfferDetails = [],
|
|
44
|
-
|
|
56
|
+
host = '',
|
|
45
57
|
onContextChange,
|
|
58
|
+
minSavedSuggestions = 0,
|
|
59
|
+
hideDeleteSuggestionIndexes = [],
|
|
46
60
|
} = props;
|
|
61
|
+
const { formatMessage } = intl;
|
|
62
|
+
const isHostIcs = host === HOST_ICS;
|
|
47
63
|
const [urlError, setUrlError] = useState(false);
|
|
48
64
|
const [buttonError, setButtonError] = useState(false);
|
|
49
65
|
const updateHandler = (type, value, index) => {
|
|
@@ -66,6 +82,7 @@ export const CapActionButton = (props) => {
|
|
|
66
82
|
|
|
67
83
|
const onCtaTypeChange = (value, index) => {
|
|
68
84
|
let clonedCta = cloneDeep(suggestions[index]);
|
|
85
|
+
const isCta = value === RCS_BUTTON_TYPES.CTA;
|
|
69
86
|
clonedCta = {
|
|
70
87
|
...clonedCta,
|
|
71
88
|
type: value,
|
|
@@ -73,6 +90,7 @@ export const CapActionButton = (props) => {
|
|
|
73
90
|
phoneNumber: '',
|
|
74
91
|
postback: '',
|
|
75
92
|
url: value === RCS_BUTTON_TYPES.PHONE_NUMBER ? null : '',
|
|
93
|
+
urlType: isCta ? RCS_CTA_URL_TYPE.STATIC : undefined,
|
|
76
94
|
isSaved: false,
|
|
77
95
|
};
|
|
78
96
|
setUrlError(false);
|
|
@@ -84,7 +102,7 @@ export const CapActionButton = (props) => {
|
|
|
84
102
|
const { value, id } = target;
|
|
85
103
|
let errorMessage = '';
|
|
86
104
|
if (value.length > BTN_MAX_LENGTH) {
|
|
87
|
-
errorMessage = formatMessage(messages.ctaButtonTextLengthError);
|
|
105
|
+
errorMessage = formatMessage(messages.ctaButtonTextLengthError, { maxLength: BTN_MAX_LENGTH });
|
|
88
106
|
} if (!isValidText(value)) {
|
|
89
107
|
errorMessage = formatMessage(messages.ctaButtonErrorMessage);
|
|
90
108
|
}
|
|
@@ -92,44 +110,91 @@ export const CapActionButton = (props) => {
|
|
|
92
110
|
updateDisplayAndPostback(value, id);
|
|
93
111
|
};
|
|
94
112
|
|
|
95
|
-
const
|
|
96
|
-
<CapHeading type="
|
|
97
|
-
{formatMessage(messages.
|
|
98
|
-
currentLength: len,
|
|
99
|
-
maxLength: max,
|
|
100
|
-
})}
|
|
113
|
+
const renderInnerCharCount = (len, max) => (
|
|
114
|
+
<CapHeading type="h5" className="rcs-cta-inner-char-count">
|
|
115
|
+
{formatMessage(messages.ctaFieldCharCountInline, { current: len, max })}
|
|
101
116
|
</CapHeading>
|
|
102
117
|
);
|
|
103
118
|
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
const validateCtaUrlValue = (value, urlSubtype) => {
|
|
120
|
+
const trimmedUrl = String(value || '').trim();
|
|
121
|
+
if (!trimmedUrl) {
|
|
122
|
+
return formatMessage(messages.ctaWebsiteUrlErrorMessage);
|
|
123
|
+
}
|
|
124
|
+
if (trimmedUrl.length > URL_MAX_LENGTH) {
|
|
125
|
+
return formatMessage(messages.ctaWebsiteUrlErrorMessage);
|
|
126
|
+
}
|
|
127
|
+
if (urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC) {
|
|
128
|
+
const baseUrl = trimmedUrl.replace(invalidVarRegex, '');
|
|
129
|
+
return isUrl(baseUrl) ? false : formatMessage(messages.ctaWebsiteUrlErrorMessage);
|
|
130
|
+
}
|
|
131
|
+
if (!isUrl(trimmedUrl)) {
|
|
132
|
+
return formatMessage(messages.ctaWebsiteUrlErrorMessage);
|
|
111
133
|
}
|
|
112
|
-
|
|
134
|
+
if (trimmedUrl.match(invalidVarRegex)?.length > 0) {
|
|
135
|
+
return formatMessage(messages.staticUrlWithVarErrorMessage);
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const onUrlChange = ({ target }) => {
|
|
141
|
+
const { id } = target;
|
|
142
|
+
const row = suggestions[id] || {};
|
|
143
|
+
const subtype = row.urlType || RCS_CTA_URL_TYPE.STATIC;
|
|
144
|
+
const value = subtype === RCS_CTA_URL_TYPE.DYNAMIC
|
|
145
|
+
? target.value.replace(invalidVarRegex, '')
|
|
146
|
+
: target.value;
|
|
147
|
+
setUrlError(validateCtaUrlValue(value, subtype));
|
|
113
148
|
updateHandler(HANDLERS.URL, value, id);
|
|
114
149
|
};
|
|
115
150
|
|
|
151
|
+
const onUrlSubtypeChange = (nextSubtype, index) => {
|
|
152
|
+
const cloned = cloneDeep(suggestions[index]);
|
|
153
|
+
cloned.urlType = nextSubtype;
|
|
154
|
+
cloned.isSaved = false;
|
|
155
|
+
setUrlError(validateCtaUrlValue(cloned.url || '', nextSubtype));
|
|
156
|
+
updateButtonChange(cloned, index);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const onTagSelect = (data, index, url) => {
|
|
160
|
+
updateHandler(HANDLERS.URL, (url || '').replace(DYNAMIC_URL_SUFFIX, `{{${data}}}`), index);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const revertTagSelect = (index, url) => {
|
|
164
|
+
updateHandler(HANDLERS.URL, (url || '').replace(invalidVarRegex, DYNAMIC_URL_SUFFIX), index);
|
|
165
|
+
};
|
|
166
|
+
|
|
116
167
|
const onPhoneNoChange = (value, index) => {
|
|
117
168
|
updateHandler(HANDLERS.PHONE_NUMBER, value, index);
|
|
118
169
|
};
|
|
119
170
|
|
|
120
171
|
const ctaSaveDisabled = (index) => {
|
|
121
|
-
const { type, text, phoneNumber, url } = suggestions[index] || {};
|
|
172
|
+
const { type, text, phoneNumber, url, urlType } = suggestions[index] || {};
|
|
122
173
|
if (text === '' || buttonError) {
|
|
123
174
|
return true;
|
|
124
|
-
} if (type === RCS_BUTTON_TYPES.PHONE_NUMBER && phoneNumber.length < 5) {
|
|
125
|
-
return true;
|
|
126
|
-
} if (type === RCS_BUTTON_TYPES.CTA && (url === '' || urlError)) {
|
|
175
|
+
} if (type === RCS_BUTTON_TYPES.PHONE_NUMBER && (phoneNumber || '').length < 5) {
|
|
127
176
|
return true;
|
|
177
|
+
} if (type === RCS_BUTTON_TYPES.CTA) {
|
|
178
|
+
const subtype = urlType || RCS_CTA_URL_TYPE.STATIC;
|
|
179
|
+
if (validateCtaUrlValue(url, subtype)) {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
// A dynamic URL still holding the unresolved {{1}} placeholder has no real
|
|
183
|
+
// personalization tag assigned yet — block save until one is picked via "Add URL label".
|
|
184
|
+
return subtype === RCS_CTA_URL_TYPE.DYNAMIC && (url || '').includes(DYNAMIC_URL_SUFFIX);
|
|
128
185
|
}
|
|
129
186
|
return false;
|
|
130
187
|
};
|
|
131
188
|
|
|
132
189
|
const saveCta = (index) => {
|
|
190
|
+
const cta = suggestions[index];
|
|
191
|
+
if (
|
|
192
|
+
cta?.type === RCS_BUTTON_TYPES.CTA
|
|
193
|
+
&& cta?.urlType === RCS_CTA_URL_TYPE.DYNAMIC
|
|
194
|
+
&& !(cta?.url || '').includes(DYNAMIC_URL_SUFFIX)
|
|
195
|
+
) {
|
|
196
|
+
cta.url = `${cta.url || ''}${DYNAMIC_URL_SUFFIX}`;
|
|
197
|
+
}
|
|
133
198
|
updateHandler(HANDLERS.IS_SAVED, true, index);
|
|
134
199
|
};
|
|
135
200
|
|
|
@@ -143,64 +208,47 @@ export const CapActionButton = (props) => {
|
|
|
143
208
|
updateButtonChange(newSuggestion, suggestions?.length);
|
|
144
209
|
};
|
|
145
210
|
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
return (
|
|
149
|
-
<CapRow>
|
|
150
|
-
<CapColumn span={23}>{label}</CapColumn>
|
|
151
|
-
<CapColumn span={1}>
|
|
152
|
-
<CapTooltipWithInfo
|
|
153
|
-
// autoAdjustOverflow
|
|
154
|
-
placement="right"
|
|
155
|
-
title={tooltipLabel}
|
|
156
|
-
/>
|
|
157
|
-
</CapColumn>
|
|
158
|
-
</CapRow>
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
return label;
|
|
162
|
-
};
|
|
211
|
+
const hideDeleteForSuggestionIndex = (idx) =>
|
|
212
|
+
Array.isArray(hideDeleteSuggestionIndexes) && hideDeleteSuggestionIndexes.includes(idx);
|
|
163
213
|
|
|
164
|
-
const { formatMessage } = intl;
|
|
165
214
|
const renderedContent = () => {
|
|
166
215
|
const renderArray = [];
|
|
167
|
-
const addBtnDisabled = suggestions.length >= maxButtons || !suggestions[suggestions.length - 1]?.isSaved;
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
return
|
|
173
|
-
|
|
174
|
-
label: renderCtaOptions(label, formatMessage(messages.ctaButtonTypeDisabled), isDisabled),
|
|
175
|
-
disabled: isDisabled,
|
|
176
|
-
};
|
|
177
|
-
});
|
|
216
|
+
const addBtnDisabled = suggestions?.length > 0 && (suggestions.length >= maxButtons || !suggestions[suggestions.length - 1]?.isSaved);
|
|
217
|
+
const savedSuggestionsCount = (suggestions || []).filter((s) => s && s.isSaved).length;
|
|
218
|
+
const cannotDeleteSavedMandatory = (idx) => {
|
|
219
|
+
const row = suggestions[idx];
|
|
220
|
+
if (!row || !row.isSaved) return false;
|
|
221
|
+
return minSavedSuggestions > 0 && savedSuggestionsCount <= minSavedSuggestions;
|
|
222
|
+
};
|
|
178
223
|
|
|
179
|
-
suggestions.forEach((cta) => {
|
|
224
|
+
suggestions?.length > 0 && suggestions.forEach((cta) => {
|
|
180
225
|
const {
|
|
181
226
|
index, type, text, isSaved,
|
|
182
227
|
} = cta || {};
|
|
183
228
|
|
|
184
229
|
const url = type !== RCS_BUTTON_TYPES.CTA ? null : cta.url;
|
|
230
|
+
const urlSubtype = type === RCS_BUTTON_TYPES.CTA
|
|
231
|
+
? (cta.urlType || RCS_CTA_URL_TYPE.STATIC)
|
|
232
|
+
: RCS_CTA_URL_TYPE.STATIC;
|
|
233
|
+
const isDynamicUrlSubtype = urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC;
|
|
185
234
|
const phoneNumber = type !== RCS_BUTTON_TYPES.PHONE_NUMBER ? null : cta.phoneNumber;
|
|
186
235
|
if (isFullMode && !isEditFlow && !isSaved) {
|
|
187
236
|
renderArray.push(
|
|
188
|
-
<
|
|
189
|
-
<CapRow
|
|
190
|
-
<CapColumn span={
|
|
191
|
-
|
|
192
|
-
<CapHeading type="h4" className="cta-label">
|
|
237
|
+
<CapRow className="rcs-button-cta-create-container" key={`cta-edit-${index}`} gutter={0}>
|
|
238
|
+
<CapRow className="rcs-button-cta-create" gutter={0}>
|
|
239
|
+
<CapColumn span={24}>
|
|
240
|
+
<CapHeading type="h4">
|
|
193
241
|
{formatMessage(messages.ctaType)}
|
|
194
242
|
</CapHeading>
|
|
195
|
-
<
|
|
196
|
-
id=
|
|
197
|
-
|
|
198
|
-
|
|
243
|
+
<CapRadioGroup
|
|
244
|
+
id={`rcs-cta-type-radio-${index}`}
|
|
245
|
+
className="cap-rcs-cta-type-radio"
|
|
246
|
+
options={CTA_TYPE_RADIO_OPTIONS}
|
|
199
247
|
value={type}
|
|
200
|
-
|
|
248
|
+
onChange={(e) => onCtaTypeChange(e.target.value, index)}
|
|
201
249
|
/>
|
|
202
250
|
</CapColumn>
|
|
203
|
-
<CapColumn span={
|
|
251
|
+
<CapColumn span={24}>
|
|
204
252
|
<CapHeading type="h4" className="cta-label">
|
|
205
253
|
{formatMessage(messages.ctaButtonText)}
|
|
206
254
|
<CapTooltipWithInfo
|
|
@@ -221,28 +269,34 @@ export const CapActionButton = (props) => {
|
|
|
221
269
|
size="large"
|
|
222
270
|
maxLength={BTN_MAX_LENGTH}
|
|
223
271
|
errorMessage={buttonError}
|
|
272
|
+
suffix={renderInnerCharCount((text || '').length, BTN_MAX_LENGTH)}
|
|
224
273
|
/>
|
|
225
|
-
{renderLength(text.length, BTN_MAX_LENGTH)}
|
|
226
274
|
</CapColumn>
|
|
227
275
|
</CapRow>
|
|
228
276
|
{type === RCS_BUTTON_TYPES.PHONE_NUMBER && (
|
|
229
277
|
<>
|
|
230
278
|
<CapRow>
|
|
231
|
-
<CapColumn span={
|
|
232
|
-
{/* phone number */}
|
|
279
|
+
<CapColumn span={24}>
|
|
233
280
|
<CapHeading type="h4" className="cta-label">
|
|
234
281
|
{formatMessage(messages.ctaPhoneNo)}
|
|
235
282
|
</CapHeading>
|
|
236
|
-
<
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
283
|
+
<CapRow
|
|
284
|
+
className="rcs-cta-input-with-inner-count rcs-cta-input-with-inner-count--phone"
|
|
285
|
+
gutter={0}
|
|
286
|
+
>
|
|
287
|
+
<CapColumn span={24}>
|
|
288
|
+
<PhoneInput
|
|
289
|
+
placeholder={formatMessage(messages.ctaPhoneNoPlaceholder)}
|
|
290
|
+
autoFormat={false}
|
|
291
|
+
countryCodeEditable={false}
|
|
292
|
+
value={phoneNumber}
|
|
293
|
+
onChange={(value) => onPhoneNoChange(value, index)}
|
|
294
|
+
country="in"
|
|
295
|
+
className="cta-phone-number rcs-cta-phone-input"
|
|
296
|
+
/>
|
|
297
|
+
{renderInnerCharCount((phoneNumber || '').length, PHONE_NUMBER_MAX_LENGTH)}
|
|
298
|
+
</CapColumn>
|
|
299
|
+
</CapRow>
|
|
246
300
|
</CapColumn>
|
|
247
301
|
</CapRow>
|
|
248
302
|
<CapRow useLegacy className="rcs-cta-save-delete-btn">
|
|
@@ -250,7 +304,7 @@ export const CapActionButton = (props) => {
|
|
|
250
304
|
title={ctaSaveDisabled(index) && formatMessage(messages.ctaSaveDisabled)}
|
|
251
305
|
placement="bottom"
|
|
252
306
|
>
|
|
253
|
-
<
|
|
307
|
+
<CapRow className="button-disabled-tooltip-wrapper">
|
|
254
308
|
<CapButton
|
|
255
309
|
onClick={() => saveCta(index)}
|
|
256
310
|
disabled={ctaSaveDisabled(index)}
|
|
@@ -258,36 +312,68 @@ export const CapActionButton = (props) => {
|
|
|
258
312
|
>
|
|
259
313
|
{formatMessage(globalMessages.save)}
|
|
260
314
|
</CapButton>
|
|
261
|
-
</
|
|
315
|
+
</CapRow>
|
|
262
316
|
</CapTooltip>
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
317
|
+
{!hideDeleteForSuggestionIndex(index) && !cannotDeleteSavedMandatory(index) && (
|
|
318
|
+
<CapButton
|
|
319
|
+
onClick={() => deleteButtonHandler(index)}
|
|
320
|
+
className="rcs-cta-delete-btn"
|
|
321
|
+
type="secondary"
|
|
322
|
+
>
|
|
323
|
+
{formatMessage(globalMessages.delete)}
|
|
324
|
+
</CapButton>
|
|
325
|
+
)}
|
|
270
326
|
</CapRow>
|
|
271
327
|
</>
|
|
272
328
|
)}
|
|
273
329
|
{type === RCS_BUTTON_TYPES.CTA && (
|
|
274
330
|
<>
|
|
275
|
-
<CapRow>
|
|
276
|
-
<CapColumn span={
|
|
331
|
+
<CapRow className="rcs-cta-url-fields-row" gutter={8}>
|
|
332
|
+
<CapColumn span={6} className="rcs-cta-url-type-col">
|
|
333
|
+
<CapHeading type="h4" className="cta-label">
|
|
334
|
+
{formatMessage(messages.ctaWebsiteType)}
|
|
335
|
+
</CapHeading>
|
|
336
|
+
<CapSelect
|
|
337
|
+
id={`rcs-cta-url-type-${index}`}
|
|
338
|
+
options={CTA_URL_TYPE_SELECT_OPTIONS}
|
|
339
|
+
value={urlSubtype}
|
|
340
|
+
onChange={(value) => onUrlSubtypeChange(value, index)}
|
|
341
|
+
/>
|
|
342
|
+
</CapColumn>
|
|
343
|
+
<CapColumn span={18} className="rcs-cta-url-value-col">
|
|
277
344
|
<CapHeading type="h4" className="cta-label">
|
|
278
|
-
{formatMessage(messages.
|
|
345
|
+
{formatMessage(messages.ctaWebsiteUrl)}
|
|
346
|
+
{isDynamicUrlSubtype && (
|
|
347
|
+
<CapTooltipWithInfo
|
|
348
|
+
infoIconProps={{
|
|
349
|
+
style: { marginLeft: CAP_SPACE_04 },
|
|
350
|
+
}}
|
|
351
|
+
autoAdjustOverflow
|
|
352
|
+
placement="right"
|
|
353
|
+
title={formatMessage(messages.ctaDynamicUrlTooltip, { one: DYNAMIC_URL_SUFFIX })}
|
|
354
|
+
/>
|
|
355
|
+
)}
|
|
279
356
|
</CapHeading>
|
|
280
357
|
<CapInput
|
|
281
358
|
id={index}
|
|
359
|
+
addonAfter={
|
|
360
|
+
isDynamicUrlSubtype
|
|
361
|
+
&& !(url || '').includes(DYNAMIC_URL_SUFFIX)
|
|
362
|
+
&& DYNAMIC_URL_SUFFIX
|
|
363
|
+
}
|
|
282
364
|
className="rcs-cta-url"
|
|
283
365
|
onChange={onUrlChange}
|
|
284
|
-
placeholder={
|
|
285
|
-
|
|
366
|
+
placeholder={
|
|
367
|
+
isDynamicUrlSubtype
|
|
368
|
+
? formatMessage(messages.ctaDynamicPlaceholder)
|
|
369
|
+
: formatMessage(messages.ctaEnterUrlPlaceholder)
|
|
370
|
+
}
|
|
371
|
+
value={url || ''}
|
|
286
372
|
size="large"
|
|
287
373
|
maxLength={URL_MAX_LENGTH}
|
|
288
374
|
errorMessage={urlError}
|
|
375
|
+
suffix={renderInnerCharCount((url || '').length, URL_MAX_LENGTH)}
|
|
289
376
|
/>
|
|
290
|
-
{renderLength(url.length, URL_MAX_LENGTH)}
|
|
291
377
|
</CapColumn>
|
|
292
378
|
</CapRow>
|
|
293
379
|
<CapRow useLegacy className="rcs-cta-save-delete-btn">
|
|
@@ -297,7 +383,7 @@ export const CapActionButton = (props) => {
|
|
|
297
383
|
}
|
|
298
384
|
placement="bottom"
|
|
299
385
|
>
|
|
300
|
-
<
|
|
386
|
+
<CapRow className="button-disabled-tooltip-wrapper">
|
|
301
387
|
<CapButton
|
|
302
388
|
onClick={() => saveCta(index)}
|
|
303
389
|
disabled={ctaSaveDisabled(index)}
|
|
@@ -305,15 +391,17 @@ export const CapActionButton = (props) => {
|
|
|
305
391
|
>
|
|
306
392
|
{formatMessage(globalMessages.save)}
|
|
307
393
|
</CapButton>
|
|
308
|
-
</
|
|
394
|
+
</CapRow>
|
|
309
395
|
</CapTooltip>
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
396
|
+
{!hideDeleteForSuggestionIndex(index) && !cannotDeleteSavedMandatory(index) && (
|
|
397
|
+
<CapButton
|
|
398
|
+
onClick={() => deleteButtonHandler(index)}
|
|
399
|
+
className="rcs-cta-delete-btn"
|
|
400
|
+
type="secondary"
|
|
401
|
+
>
|
|
402
|
+
{formatMessage(globalMessages.delete)}
|
|
403
|
+
</CapButton>
|
|
404
|
+
)}
|
|
317
405
|
</CapRow>
|
|
318
406
|
</>
|
|
319
407
|
)}
|
|
@@ -323,7 +411,7 @@ export const CapActionButton = (props) => {
|
|
|
323
411
|
title={ctaSaveDisabled(index) && formatMessage(messages.ctaSaveDisabled)}
|
|
324
412
|
placement="bottom"
|
|
325
413
|
>
|
|
326
|
-
<
|
|
414
|
+
<CapRow className="button-disabled-tooltip-wrapper">
|
|
327
415
|
<CapButton
|
|
328
416
|
onClick={() => saveCta(index)}
|
|
329
417
|
disabled={ctaSaveDisabled(index)}
|
|
@@ -331,9 +419,9 @@ export const CapActionButton = (props) => {
|
|
|
331
419
|
>
|
|
332
420
|
{formatMessage(globalMessages.save)}
|
|
333
421
|
</CapButton>
|
|
334
|
-
</
|
|
422
|
+
</CapRow>
|
|
335
423
|
</CapTooltip>
|
|
336
|
-
{index
|
|
424
|
+
{!(isHostIcs && index === 0) && !hideDeleteForSuggestionIndex(index) && !cannotDeleteSavedMandatory(index) && (
|
|
337
425
|
<CapButton
|
|
338
426
|
onClick={() => deleteButtonHandler(index)}
|
|
339
427
|
className="rcs-cta-delete-btn"
|
|
@@ -344,23 +432,24 @@ export const CapActionButton = (props) => {
|
|
|
344
432
|
)}
|
|
345
433
|
</CapRow>
|
|
346
434
|
)}
|
|
347
|
-
</
|
|
435
|
+
</CapRow>
|
|
348
436
|
);
|
|
349
437
|
} else {
|
|
350
438
|
const ctaIsPhone = type === RCS_BUTTON_TYPES.PHONE_NUMBER;
|
|
351
439
|
const ctaIsReply = type === RCS_BUTTON_TYPES.QUICK_REPLY;
|
|
352
|
-
renderArray
|
|
440
|
+
suggestions?.length > 0 && renderArray?.push(
|
|
353
441
|
<CapRow
|
|
354
442
|
key={`cta-saved-${index}`}
|
|
355
443
|
className="cap-rcs-saved-cta margin-t-12"
|
|
356
444
|
align="middle"
|
|
357
445
|
type="flex"
|
|
446
|
+
gutter={9}
|
|
358
447
|
>
|
|
359
448
|
<CapColumn
|
|
360
449
|
span={1}
|
|
361
450
|
className={`${ctaIsPhone ? 'whatsapp-saved-cta-phone-icon' : ''}`}
|
|
362
451
|
>
|
|
363
|
-
<CapIcon size="s" type={ctaIsPhone ? 'call' : '
|
|
452
|
+
<CapIcon size="s" type={ctaIsPhone ? 'call' : (ctaIsReply ? 'small-link' : 'open-in-new')} />
|
|
364
453
|
</CapColumn>
|
|
365
454
|
<CapColumn span={6}>
|
|
366
455
|
<CapLabel
|
|
@@ -370,49 +459,71 @@ export const CapActionButton = (props) => {
|
|
|
370
459
|
{text}
|
|
371
460
|
</CapLabel>
|
|
372
461
|
</CapColumn>
|
|
373
|
-
{
|
|
374
|
-
<
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
<CapTooltip title={url} placement="top">
|
|
387
|
-
<CapColumn span={14} className="margin-r-0">
|
|
462
|
+
<CapColumn flex={1} className="rcs-saved-cta-value-column">
|
|
463
|
+
<div className="rcs-saved-cta-value-actions">
|
|
464
|
+
{ctaIsPhone && (
|
|
465
|
+
<CapLabel className="phone">+{phoneNumber}</CapLabel>
|
|
466
|
+
)}
|
|
467
|
+
{!ctaIsPhone && !ctaIsReply && (
|
|
468
|
+
<>
|
|
469
|
+
<CapLabel className="url-type" type="label2">
|
|
470
|
+
{(cta.urlType || RCS_CTA_URL_TYPE.STATIC) === RCS_CTA_URL_TYPE.DYNAMIC
|
|
471
|
+
? formatMessage(messages.ctaWebsiteTypeDynamic)
|
|
472
|
+
: formatMessage(messages.ctaWebsiteTypeStatic)}
|
|
473
|
+
</CapLabel>
|
|
474
|
+
<CapTooltip title={url} placement="top">
|
|
388
475
|
<CapLabel className="url">{url}</CapLabel>
|
|
389
|
-
</
|
|
476
|
+
</CapTooltip>
|
|
477
|
+
</>
|
|
478
|
+
)}
|
|
479
|
+
{isDynamicUrlSubtype && (url || '').includes(DYNAMIC_URL_SUFFIX) && (
|
|
480
|
+
<TagList
|
|
481
|
+
className="rcs-cta-taglist"
|
|
482
|
+
label={formatMessage(messages.ctaTagListLabel)}
|
|
483
|
+
onTagSelect={(data) => onTagSelect(data, index, url)}
|
|
484
|
+
location={location}
|
|
485
|
+
tags={tags}
|
|
486
|
+
injectedTags={injectedTags}
|
|
487
|
+
selectedOfferDetails={selectedOfferDetails}
|
|
488
|
+
onContextChange={onContextChange}
|
|
489
|
+
/>
|
|
490
|
+
)}
|
|
491
|
+
{isDynamicUrlSubtype && !(url || '').includes(DYNAMIC_URL_SUFFIX) && (
|
|
492
|
+
<CapTooltip title={formatMessage(messages.ctaTagListRevert)} placement="top">
|
|
493
|
+
<CapIcon
|
|
494
|
+
size="s"
|
|
495
|
+
type="return"
|
|
496
|
+
className="rcs-cta-tag-revert"
|
|
497
|
+
onClick={() => revertTagSelect(index, url)}
|
|
498
|
+
/>
|
|
390
499
|
</CapTooltip>
|
|
391
|
-
</CapRow>
|
|
392
|
-
</>
|
|
393
|
-
)}
|
|
394
|
-
{(isFullMode && !isEditFlow) && (
|
|
395
|
-
<>
|
|
396
|
-
<CapColumn
|
|
397
|
-
span={1}
|
|
398
|
-
className="rcs-saved-cta-edit-icon"
|
|
399
|
-
onClick={() => editCta(index)}
|
|
400
|
-
>
|
|
401
|
-
<CapIcon size="s" type="edit" />
|
|
402
|
-
</CapColumn>
|
|
403
|
-
{index !== 0 && (
|
|
404
|
-
<CapColumn className="rcs-saved-cta-delete-icon" span={1} onClick={() => deleteButtonHandler(index)}>
|
|
405
|
-
<CapIcon size="s" type="delete" />
|
|
406
|
-
</CapColumn>
|
|
407
500
|
)}
|
|
408
|
-
|
|
409
|
-
|
|
501
|
+
{(isFullMode && !isEditFlow) && (
|
|
502
|
+
<div className="rcs-saved-cta-action-icons">
|
|
503
|
+
<CapIcon
|
|
504
|
+
size="s"
|
|
505
|
+
type="edit"
|
|
506
|
+
className="rcs-saved-cta-edit-icon"
|
|
507
|
+
onClick={() => editCta(index)}
|
|
508
|
+
/>
|
|
509
|
+
{!(isHostIcs && index === 0) && !hideDeleteForSuggestionIndex(index) && !cannotDeleteSavedMandatory(index) && (
|
|
510
|
+
<CapIcon
|
|
511
|
+
size="s"
|
|
512
|
+
type="delete"
|
|
513
|
+
className="rcs-saved-cta-delete-icon"
|
|
514
|
+
onClick={() => deleteButtonHandler(index)}
|
|
515
|
+
/>
|
|
516
|
+
)}
|
|
517
|
+
</div>
|
|
518
|
+
)}
|
|
519
|
+
</div>
|
|
520
|
+
</CapColumn>
|
|
410
521
|
</CapRow>
|
|
411
522
|
);
|
|
412
523
|
}
|
|
413
524
|
});
|
|
414
525
|
{
|
|
415
|
-
suggestions
|
|
526
|
+
suggestions?.length < maxButtons &&
|
|
416
527
|
(isFullMode && !isEditFlow)
|
|
417
528
|
&& renderArray.push(
|
|
418
529
|
<CapRow useLegacy>
|
|
@@ -422,7 +533,7 @@ export const CapActionButton = (props) => {
|
|
|
422
533
|
}
|
|
423
534
|
placement={'right'}
|
|
424
535
|
>
|
|
425
|
-
<
|
|
536
|
+
<CapRow className="button-disabled-tooltip-wrapper">
|
|
426
537
|
<CapButton
|
|
427
538
|
type="flat"
|
|
428
539
|
id="rcs-cta-add-button"
|
|
@@ -433,7 +544,7 @@ export const CapActionButton = (props) => {
|
|
|
433
544
|
>
|
|
434
545
|
{formatMessage(messages.addButton)}
|
|
435
546
|
</CapButton>
|
|
436
|
-
</
|
|
547
|
+
</CapRow>
|
|
437
548
|
</CapTooltip>
|
|
438
549
|
</CapRow>,
|
|
439
550
|
);
|
|
@@ -446,6 +557,8 @@ export const CapActionButton = (props) => {
|
|
|
446
557
|
CapActionButton.propTypes = {
|
|
447
558
|
intl: intlShape.isRequired,
|
|
448
559
|
updateButtonChange: PropTypes.func,
|
|
560
|
+
minSavedSuggestions: PropTypes.number,
|
|
561
|
+
hideDeleteSuggestionIndexes: PropTypes.arrayOf(PropTypes.number),
|
|
449
562
|
suggestions: PropTypes.array,
|
|
450
563
|
tags: PropTypes.array,
|
|
451
564
|
injectedTags: PropTypes.object,
|
|
@@ -453,12 +566,15 @@ CapActionButton.propTypes = {
|
|
|
453
566
|
selectedOfferDetails: PropTypes.array,
|
|
454
567
|
onTagSelect: PropTypes.func,
|
|
455
568
|
onContextChange: PropTypes.func,
|
|
569
|
+
host: PropTypes.string,
|
|
456
570
|
};
|
|
457
571
|
|
|
458
572
|
CapActionButton.defaultProps = {
|
|
459
573
|
buttonTextlen: 20,
|
|
460
574
|
type: '',
|
|
461
575
|
updateButtonChange: () => {},
|
|
576
|
+
minSavedSuggestions: 0,
|
|
577
|
+
hideDeleteSuggestionIndexes: [],
|
|
462
578
|
suggestions: [],
|
|
463
579
|
tags: [],
|
|
464
580
|
injectedTags: {},
|
|
@@ -466,6 +582,7 @@ CapActionButton.defaultProps = {
|
|
|
466
582
|
selectedOfferDetails: [],
|
|
467
583
|
onTagSelect: () => {},
|
|
468
584
|
onContextChange: () => {},
|
|
585
|
+
host: '',
|
|
469
586
|
};
|
|
470
587
|
|
|
471
588
|
export default injectIntl(CapActionButton);
|