@pega/react-sdk-overrides 8.23.10 → 8.23.11-debug
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/lib/designSystemExtension/AlertBanner/AlertBanner.tsx +43 -0
- package/lib/designSystemExtension/AlertBanner/index.tsx +1 -0
- package/lib/designSystemExtension/FieldGroupList/FieldGroupList.tsx +1 -3
- package/lib/designSystemExtension/Operator/Operator.tsx +16 -11
- package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.tsx +2 -2
- package/lib/field/CancelAlert/CancelAlert.tsx +12 -8
- package/lib/field/Checkbox/Checkbox.tsx +3 -2
- package/lib/field/Currency/currency-utils.ts +4 -1
- package/lib/field/Date/Date.tsx +12 -5
- package/lib/field/DateTime/DateTime.tsx +1 -1
- package/lib/field/Decimal/Decimal.tsx +66 -14
- package/lib/field/Dropdown/Dropdown.tsx +49 -10
- package/lib/field/Phone/Phone.tsx +2 -1
- package/lib/field/RadioButtons/RadioButtons.tsx +43 -4
- package/lib/field/SemanticLink/utils.ts +2 -1
- package/lib/field/TextInput/TextInput.tsx +26 -6
- package/lib/field/Time/Time.tsx +9 -1
- package/lib/field/URL/URL.tsx +8 -0
- package/lib/field/UserReference/UserReference.tsx +2 -0
- package/lib/helpers/{attachmentHelpers.js → attachmentHelpers.ts} +2 -2
- package/lib/helpers/auth.js +10 -3
- package/lib/helpers/authManager.js +16 -13
- package/lib/helpers/case-utils.tsx +104 -0
- package/lib/helpers/common-utils.ts +4 -0
- package/lib/helpers/config_access.js +122 -131
- package/lib/helpers/data_page.ts +2 -1
- package/lib/helpers/date-format-utils.ts +28 -18
- package/lib/helpers/{field-group-utils.js → field-group-utils.ts} +4 -3
- package/lib/helpers/formatters/{Currency.js → Currency.ts} +4 -3
- package/lib/helpers/formatters/{Date.js → Date.ts} +1 -1
- package/lib/helpers/formatters/common.ts +18 -0
- package/lib/helpers/simpleTableHelpers.ts +6 -2
- package/lib/helpers/state-utils.tsx +50 -0
- package/lib/helpers/template-utils.ts +3 -1
- package/lib/helpers/utils.ts +12 -4
- package/lib/helpers/versionHelpers.ts +3 -1
- package/lib/infra/ActionButtons/ActionButtons.tsx +7 -2
- package/lib/infra/Assignment/Assignment.tsx +23 -10
- package/lib/infra/Containers/FlowContainer/FlowContainer.tsx +24 -11
- package/lib/infra/Containers/FlowContainer/{helpers.js → helpers.ts} +21 -16
- package/lib/infra/Containers/ModalViewContainer/ModalViewContainer.tsx +28 -9
- package/lib/infra/Containers/ViewContainer/ViewContainer.tsx +7 -5
- package/lib/infra/DashboardFilter/DashboardFilter.tsx +5 -1
- package/lib/infra/DashboardFilter/filterUtils.tsx +2 -0
- package/lib/infra/DeferLoad/DeferLoad.tsx +4 -1
- package/lib/infra/ErrorBoundary/ErrorBoundary.tsx +10 -5
- package/lib/infra/MultiStep/MultiStep.tsx +2 -2
- package/lib/infra/NavBar/NavBar.tsx +11 -5
- package/lib/infra/RootContainer/RootContainer.tsx +16 -14
- package/lib/infra/Stages/Stages.tsx +5 -1
- package/lib/infra/View/View.tsx +7 -34
- package/lib/template/AppShell/AppShell.tsx +15 -9
- package/lib/template/CaseView/CaseView.tsx +116 -78
- package/lib/template/CaseViewActionsMenu/CaseViewActionsMenu.tsx +26 -17
- package/lib/template/Confirmation/Confirmation.tsx +4 -1
- package/lib/template/DataReference/DataReference.tsx +2 -0
- package/lib/template/DefaultForm/DefaultForm.tsx +15 -8
- package/lib/template/DefaultForm/utils/index.ts +33 -0
- package/lib/template/FieldGroupTemplate/FieldGroupTemplate.tsx +5 -2
- package/lib/template/ListView/ListView.tsx +3 -1
- package/lib/template/ListView/{hooks.js → hooks.ts} +3 -1
- package/lib/template/ListView/{utils.js → utils.ts} +12 -10
- package/lib/template/MultiReferenceReadOnly/MultiReferenceReadOnly.tsx +5 -1
- package/lib/template/PromotedFilters/PromotedFilters.tsx +9 -5
- package/lib/template/SimpleTable/SimpleTable/SimpleTable.tsx +4 -1
- package/lib/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +8 -4
- package/lib/template/SimpleTable/SimpleTableSelect/SimpleTableSelect.tsx +6 -1
- package/lib/template/SubTabs/tabUtils.ts +3 -1
- package/lib/template/WssNavBar/WssNavBar.tsx +2 -2
- package/lib/widget/Attachment/Attachment.css +15 -3
- package/lib/widget/Attachment/Attachment.tsx +32 -25
- package/lib/widget/CaseHistory/CaseHistory.tsx +5 -5
- package/lib/widget/FileUtility/FileUtility/FileUtility.tsx +20 -19
- package/lib/widget/QuickCreate/QuickCreate.tsx +6 -3
- package/lib/widget/SummaryItem/SummaryItem.tsx +2 -4
- package/lib/widget/ToDo/ToDo.tsx +17 -9
- package/package.json +1 -1
- package/lib/helpers/formatters/common.js +0 -14
- /package/lib/helpers/{event-utils.js → event-utils.ts} +0 -0
- /package/lib/helpers/formatters/{Boolean.js → Boolean.ts} +0 -0
- /package/lib/helpers/formatters/{CurrencyMap.js → CurrencyMap.ts} +0 -0
- /package/lib/helpers/formatters/{index.js → index.ts} +0 -0
- /package/lib/helpers/{reactContextHelpers.js → reactContextHelpers.ts} +0 -0
- /package/lib/template/ListView/{DefaultViewMeta.js → DefaultViewMeta.ts} +0 -0
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
2
|
import { TextField } from '@material-ui/core';
|
|
3
3
|
import FieldValueList from '@pega/react-sdk-components/lib/components/designSystemExtension/FieldValueList';
|
|
4
|
+
import handleEvent from '@pega/react-sdk-components/lib/components/helpers/event-utils';
|
|
4
5
|
|
|
5
6
|
export default function TextInput(props) {
|
|
6
7
|
const {
|
|
8
|
+
getPConnect,
|
|
7
9
|
label,
|
|
8
10
|
required,
|
|
9
11
|
disabled,
|
|
10
12
|
value = '',
|
|
11
13
|
validatemessage,
|
|
12
14
|
status,
|
|
13
|
-
onChange,
|
|
14
|
-
onBlur,
|
|
15
|
+
/* onChange, onBlur */
|
|
15
16
|
readOnly,
|
|
16
17
|
testId,
|
|
17
18
|
fieldMetadata,
|
|
@@ -19,12 +20,22 @@ export default function TextInput(props) {
|
|
|
19
20
|
displayMode,
|
|
20
21
|
hideLabel
|
|
21
22
|
} = props;
|
|
23
|
+
|
|
24
|
+
const pConn = getPConnect();
|
|
25
|
+
const actions = pConn.getActionsApi();
|
|
26
|
+
const propName = pConn.getStateProps().value;
|
|
27
|
+
|
|
22
28
|
const helperTextToDisplay = validatemessage || helperText;
|
|
23
29
|
|
|
30
|
+
const [inputValue, setInputValue] = useState();
|
|
24
31
|
const maxLength = fieldMetadata?.maxLength;
|
|
25
32
|
|
|
26
33
|
let readOnlyProp = {}; // Note: empty if NOT ReadOnly
|
|
27
34
|
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
setInputValue(value);
|
|
37
|
+
}, [value]);
|
|
38
|
+
|
|
28
39
|
if (displayMode === 'LABELS_LEFT') {
|
|
29
40
|
return <FieldValueList name={hideLabel ? '' : label} value={value} />;
|
|
30
41
|
}
|
|
@@ -43,6 +54,15 @@ export default function TextInput(props) {
|
|
|
43
54
|
'data-test-id': testId
|
|
44
55
|
};
|
|
45
56
|
|
|
57
|
+
function handleChange(event) {
|
|
58
|
+
// update internal value
|
|
59
|
+
setInputValue(event?.target?.value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function handleBlur() {
|
|
63
|
+
handleEvent(actions, 'changeNblur', propName, inputValue);
|
|
64
|
+
}
|
|
65
|
+
|
|
46
66
|
return (
|
|
47
67
|
<TextField
|
|
48
68
|
fullWidth
|
|
@@ -52,11 +72,11 @@ export default function TextInput(props) {
|
|
|
52
72
|
size='small'
|
|
53
73
|
required={required}
|
|
54
74
|
disabled={disabled}
|
|
55
|
-
onChange={
|
|
56
|
-
onBlur={!readOnly ?
|
|
75
|
+
onChange={handleChange}
|
|
76
|
+
onBlur={!readOnly ? handleBlur : undefined}
|
|
57
77
|
error={status === 'error'}
|
|
58
78
|
label={label}
|
|
59
|
-
value={
|
|
79
|
+
value={inputValue}
|
|
60
80
|
InputProps={{ ...readOnlyProp, inputProps: { maxLength, ...testProp } }}
|
|
61
81
|
/>
|
|
62
82
|
);
|
package/lib/field/Time/Time.tsx
CHANGED
|
@@ -17,7 +17,8 @@ export default function Time(props) {
|
|
|
17
17
|
readOnly,
|
|
18
18
|
helperText,
|
|
19
19
|
displayMode,
|
|
20
|
-
hideLabel
|
|
20
|
+
hideLabel,
|
|
21
|
+
testId
|
|
21
22
|
} = props;
|
|
22
23
|
const helperTextToDisplay = validatemessage || helperText;
|
|
23
24
|
|
|
@@ -33,6 +34,12 @@ export default function Time(props) {
|
|
|
33
34
|
return <TextInput {...props} />;
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
let testProp = {};
|
|
38
|
+
|
|
39
|
+
testProp = {
|
|
40
|
+
'data-test-id': testId
|
|
41
|
+
};
|
|
42
|
+
|
|
36
43
|
const handleChange = date => {
|
|
37
44
|
const theValue = date && date.isValid() ? date.format('HH:mm') : null;
|
|
38
45
|
onChange({ value: theValue });
|
|
@@ -68,6 +75,7 @@ export default function Time(props) {
|
|
|
68
75
|
format='hh:mm a'
|
|
69
76
|
value={timeValue}
|
|
70
77
|
onChange={handleChange}
|
|
78
|
+
InputProps={{ inputProps: { ...testProp } }}
|
|
71
79
|
/>
|
|
72
80
|
);
|
|
73
81
|
}
|
package/lib/field/URL/URL.tsx
CHANGED
|
@@ -17,6 +17,7 @@ export default function URLComponent(props) {
|
|
|
17
17
|
onChange,
|
|
18
18
|
onBlur,
|
|
19
19
|
readOnly,
|
|
20
|
+
testId,
|
|
20
21
|
helperText,
|
|
21
22
|
displayMode,
|
|
22
23
|
hideLabel
|
|
@@ -35,6 +36,12 @@ export default function URLComponent(props) {
|
|
|
35
36
|
return <TextInput {...props} />;
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
let testProp = {};
|
|
40
|
+
|
|
41
|
+
testProp = {
|
|
42
|
+
'data-test-id': testId
|
|
43
|
+
};
|
|
44
|
+
|
|
38
45
|
return (
|
|
39
46
|
<TextField
|
|
40
47
|
type='url'
|
|
@@ -50,6 +57,7 @@ export default function URLComponent(props) {
|
|
|
50
57
|
error={status === 'error'}
|
|
51
58
|
label={label}
|
|
52
59
|
value={value}
|
|
60
|
+
InputProps={{ inputProps: { ...testProp } }}
|
|
53
61
|
/>
|
|
54
62
|
);
|
|
55
63
|
}
|
|
@@ -5,7 +5,9 @@ import AutoComplete from '@pega/react-sdk-components/lib/components/field/AutoCo
|
|
|
5
5
|
import Dropdown from '@pega/react-sdk-components/lib/components/field/Dropdown';
|
|
6
6
|
import { getUserId, isUserNameAvailable } from './UserReferenceUtils';
|
|
7
7
|
|
|
8
|
+
// Remove this and use "real" PCore type once .d.ts is fixed (currently shows 1 errors)
|
|
8
9
|
declare const PCore: any;
|
|
10
|
+
|
|
9
11
|
const DROPDOWN_LIST = 'Drop-down list';
|
|
10
12
|
const SEARCH_BOX = 'Search box';
|
|
11
13
|
|
|
@@ -42,11 +42,11 @@ export const getIconFromFileType = (fileType) => {
|
|
|
42
42
|
return icon;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
export const getIconForAttachment = (attachment) => {
|
|
45
|
+
export const getIconForAttachment = (inThis:any , attachment:any) => {
|
|
46
46
|
let icon;
|
|
47
47
|
switch (attachment.type) {
|
|
48
48
|
case "FILE":
|
|
49
|
-
icon =
|
|
49
|
+
icon = inThis.getIconFromFileType(attachment.mimeType);
|
|
50
50
|
break;
|
|
51
51
|
case "URL":
|
|
52
52
|
icon = "chain";
|
package/lib/helpers/auth.js
CHANGED
|
@@ -228,7 +228,12 @@ class PegaAuth {
|
|
|
228
228
|
fnCloseIframe();
|
|
229
229
|
} else {
|
|
230
230
|
clearInterval(checkWindowClosed);
|
|
231
|
-
|
|
231
|
+
try {
|
|
232
|
+
myWindow.close();
|
|
233
|
+
} catch (e) {
|
|
234
|
+
// eslint-disable-next-line no-console
|
|
235
|
+
console.warn(`attempt to close opened window failed`);
|
|
236
|
+
}
|
|
232
237
|
}
|
|
233
238
|
resolve(token);
|
|
234
239
|
})
|
|
@@ -239,8 +244,10 @@ class PegaAuth {
|
|
|
239
244
|
/* Handler to receive the auth code */
|
|
240
245
|
authMessageReceiver = (event) => {
|
|
241
246
|
// Check origin to make sure it is the redirect origin
|
|
242
|
-
if( event.origin !== redirectOrigin )
|
|
243
|
-
|
|
247
|
+
if( event.origin !== redirectOrigin ) {
|
|
248
|
+
// eslint-disable-next-line no-console
|
|
249
|
+
console.info(`Received event from unexpected origin: ${event.origin} (was expecting: ${redirectOrigin})`);
|
|
250
|
+
}
|
|
244
251
|
if( !event.data || !event.data.type || event.data.type !== "PegaAuth" )
|
|
245
252
|
return;
|
|
246
253
|
// eslint-disable-next-line no-console
|
|
@@ -139,7 +139,7 @@ const initOAuth = (bInit) => {
|
|
|
139
139
|
if( 'silentTimeout' in sdkConfigAuth ) {
|
|
140
140
|
authConfig.silentTimeout = sdkConfigAuth.silentTimeout;
|
|
141
141
|
}
|
|
142
|
-
if( bNoInitialRedirect ) {
|
|
142
|
+
if( bNoInitialRedirect && sdkConfigAuth.mashupUserIdentifier && sdkConfigAuth.mashupPassword ) {
|
|
143
143
|
authConfig.userIdentifier = sdkConfigAuth.mashupUserIdentifier;
|
|
144
144
|
authConfig.password = sdkConfigAuth.mashupPassword;
|
|
145
145
|
}
|
|
@@ -154,15 +154,21 @@ const initOAuth = (bInit) => {
|
|
|
154
154
|
let sSI = sessionStorage.getItem("rsdk_CI");
|
|
155
155
|
if( sSI ) {
|
|
156
156
|
try {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
157
|
+
const oSI = JSON.parse(sSI);
|
|
158
|
+
const aProps = ['authorizeUri', 'appAlias', 'clientId', 'authService', 'userIdentifier'];
|
|
159
|
+
for( let i = 0; i < aProps.length; i += 1 ) {
|
|
160
|
+
const prop = aProps[i];
|
|
161
|
+
const currValue = oSI[prop];
|
|
162
|
+
const newValue = authConfig[prop];
|
|
163
|
+
if( currValue !== newValue ) {
|
|
164
|
+
// eslint-disable-next-line no-console
|
|
165
|
+
console.warn(`Clearing credentials due to mismatch for property: ${prop};` +
|
|
166
|
+
`currValue (${currValue}) does not match new desired value (${newValue})`);
|
|
167
|
+
clearAuthMgr();
|
|
168
|
+
sSI = null;
|
|
169
|
+
break;
|
|
165
170
|
}
|
|
171
|
+
}
|
|
166
172
|
} catch(e) {
|
|
167
173
|
// do nothing
|
|
168
174
|
}
|
|
@@ -269,21 +275,18 @@ const constellationInit = (authConfig, tokenInfo, authTokenUpdated, fnReauth) =>
|
|
|
269
275
|
window.myLoadPortal = bootstrapShell.loadPortal;
|
|
270
276
|
window.myLoadDefaultPortal = bootstrapShell.loadDefaultPortal;
|
|
271
277
|
|
|
272
|
-
bootstrapShell.bootstrapWithAuthHeader(constellationBootConfig, '
|
|
278
|
+
bootstrapShell.bootstrapWithAuthHeader(constellationBootConfig, 'pega-root').then(() => {
|
|
273
279
|
// eslint-disable-next-line no-console
|
|
274
280
|
console.log('Bootstrap successful!');
|
|
275
281
|
gbC11NBootstrapInProgress = false;
|
|
276
282
|
|
|
277
283
|
// Setup listener for the reauth event
|
|
278
284
|
if( tokenInfo ) {
|
|
279
|
-
// eslint-disable-next-line no-undef
|
|
280
285
|
PCore.getPubSubUtils().subscribe(PCore.getConstants().PUB_SUB_EVENTS.EVENT_FULL_REAUTH, fnReauth, "authFullReauth");
|
|
281
286
|
} else {
|
|
282
287
|
// customReauth event introduced with 8.8
|
|
283
|
-
// eslint-disable-next-line no-undef
|
|
284
288
|
const sEvent = PCore.getConstants().PUB_SUB_EVENTS.EVENT_CUSTOM_REAUTH;
|
|
285
289
|
if( sEvent ) {
|
|
286
|
-
// eslint-disable-next-line no-undef
|
|
287
290
|
PCore.getPubSubUtils().subscribe(sEvent, fnReauth, "doReauth");
|
|
288
291
|
}
|
|
289
292
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import AlertBanner from '@pega/react-sdk-components/lib/components/designSystemExtension/AlertBanner';
|
|
3
|
+
|
|
4
|
+
declare let PCore: any;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Function that accepts array of messages as input and group them by their type and returns the resulting object
|
|
8
|
+
* @param {Array} inputMessages
|
|
9
|
+
* Eg: [
|
|
10
|
+
* {message: 'First Name is required', type: 'error'},
|
|
11
|
+
* {message: 'Last Name is required', type: 'error'},
|
|
12
|
+
* {message: 'Address field should be clear and precise', type: 'info'}
|
|
13
|
+
* ]
|
|
14
|
+
*
|
|
15
|
+
* @returns {object}
|
|
16
|
+
*
|
|
17
|
+
* Eg: {
|
|
18
|
+
* error: ['First Name is required', 'Last Name is required'],
|
|
19
|
+
* info: ['Address field should be clear and precise']
|
|
20
|
+
* }
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
function getMessagesGrouped(inputMessages) {
|
|
24
|
+
const messages = {};
|
|
25
|
+
|
|
26
|
+
if (inputMessages && inputMessages instanceof Array && inputMessages.length > 0) {
|
|
27
|
+
inputMessages.forEach(item => {
|
|
28
|
+
const { message, type } = item;
|
|
29
|
+
messages[type] = [...(messages[type] || []), message];
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return messages;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Function accepts a error type and variant of the banner
|
|
37
|
+
* @param {string} type
|
|
38
|
+
* Eg: 'error'
|
|
39
|
+
* @returns {string}
|
|
40
|
+
* Eg: 'urgent'
|
|
41
|
+
*/
|
|
42
|
+
function getVariant(type) {
|
|
43
|
+
const { BANNER_VARIANT_SUCCESS, BANNER_VARIANT_INFO, BANNER_VARIANT_URGENT, MESSAGES } =
|
|
44
|
+
PCore.getConstants();
|
|
45
|
+
const { MESSAGES_TYPE_ERROR, MESSAGES_TYPE_INFO, MESSAGES_TYPE_SUCCESS } = MESSAGES;
|
|
46
|
+
|
|
47
|
+
let variant;
|
|
48
|
+
switch (type) {
|
|
49
|
+
case MESSAGES_TYPE_ERROR:
|
|
50
|
+
variant = BANNER_VARIANT_URGENT;
|
|
51
|
+
break;
|
|
52
|
+
case MESSAGES_TYPE_INFO:
|
|
53
|
+
variant = BANNER_VARIANT_INFO;
|
|
54
|
+
break;
|
|
55
|
+
case MESSAGES_TYPE_SUCCESS:
|
|
56
|
+
variant = BANNER_VARIANT_SUCCESS;
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
variant = '';
|
|
60
|
+
}
|
|
61
|
+
return variant;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getBanners(config) {
|
|
65
|
+
const { target, pageMessages, httpMessages } = config;
|
|
66
|
+
const { PAGE } = PCore.getConstants();
|
|
67
|
+
const { clearMessages } = PCore.getMessageManager();
|
|
68
|
+
const banners: any = [];
|
|
69
|
+
const groupedPageMessages = getMessagesGrouped(pageMessages);
|
|
70
|
+
|
|
71
|
+
Object.keys(groupedPageMessages).forEach(type => {
|
|
72
|
+
const messagesByType = groupedPageMessages[type];
|
|
73
|
+
const variant = getVariant(type);
|
|
74
|
+
const pageMessagesBannerID = `${target}_${PAGE}_${type}`.toLowerCase().replace('/', '_');
|
|
75
|
+
banners.push(
|
|
76
|
+
<AlertBanner
|
|
77
|
+
id={pageMessagesBannerID}
|
|
78
|
+
variant={variant}
|
|
79
|
+
messages={messagesByType}
|
|
80
|
+
onDismiss={
|
|
81
|
+
variant === 'urgent'
|
|
82
|
+
? ''
|
|
83
|
+
: () => {
|
|
84
|
+
clearMessages({
|
|
85
|
+
category: PAGE,
|
|
86
|
+
type,
|
|
87
|
+
context: target
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/>
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (httpMessages && httpMessages.length > 0) {
|
|
96
|
+
banners.push(
|
|
97
|
+
<AlertBanner id='modalViewContainerBanner' variant='urgent' messages={httpMessages} />
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return banners;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { getMessagesGrouped, getBanners };
|