@pega/react-sdk-overrides 0.24.4 → 0.25.2
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 +1 -1
- package/lib/designSystemExtension/Banner/Banner.tsx +1 -1
- package/lib/designSystemExtension/CaseSummaryFields/CaseSummaryFields.css +0 -2
- package/lib/designSystemExtension/CaseSummaryFields/CaseSummaryFields.tsx +59 -32
- package/lib/designSystemExtension/DetailsFields/DetailsFields.tsx +4 -4
- package/lib/designSystemExtension/FieldGroup/FieldGroup.tsx +5 -5
- package/lib/designSystemExtension/FieldGroupList/FieldGroupList.tsx +4 -4
- package/lib/designSystemExtension/FieldValueList/FieldValueList.tsx +6 -6
- package/lib/designSystemExtension/Operator/Operator.tsx +16 -12
- package/lib/designSystemExtension/Pulse/Pulse.tsx +3 -3
- package/lib/designSystemExtension/RichTextEditor/RichTextEditor.tsx +3 -2
- package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.tsx +1 -1
- package/lib/field/AutoComplete/AutoComplete.tsx +5 -5
- package/lib/field/CancelAlert/CancelAlert.tsx +5 -8
- package/lib/field/Checkbox/Checkbox.tsx +5 -5
- package/lib/field/Currency/Currency.tsx +12 -9
- package/lib/field/Date/Date.tsx +29 -48
- package/lib/field/DateTime/DateTime.tsx +37 -39
- package/lib/field/Decimal/Decimal.tsx +12 -9
- package/lib/field/Dropdown/Dropdown.tsx +34 -27
- package/lib/field/Email/Email.tsx +39 -20
- package/lib/field/Group/Group.tsx +4 -4
- package/lib/field/Integer/Integer.tsx +27 -15
- package/lib/field/Multiselect/Multiselect.tsx +8 -14
- package/lib/field/Multiselect/utils.ts +1 -1
- package/lib/field/Percentage/Percentage.tsx +11 -11
- package/lib/field/Phone/Phone.tsx +13 -10
- package/lib/field/Phone/config-ext.json +8 -0
- package/lib/field/RadioButtons/RadioButtons.tsx +4 -7
- package/lib/field/RichText/RichText.tsx +2 -2
- package/lib/field/RichText/config-ext.json +10 -0
- package/lib/field/ScalarList/ScalarList.tsx +4 -5
- package/lib/field/SemanticLink/SemanticLink.tsx +5 -5
- package/lib/field/TextArea/TextArea.tsx +30 -14
- package/lib/field/TextContent/TextContent.tsx +2 -2
- package/lib/field/TextInput/TextInput.tsx +7 -9
- package/lib/field/Time/Time.tsx +30 -27
- package/lib/field/URL/URL.tsx +29 -12
- package/lib/field/UserReference/UserReference.tsx +4 -6
- package/lib/helpers/common-utils.ts +24 -1
- package/lib/helpers/field-group-utils.ts +3 -3
- package/lib/helpers/formatters/Currency.ts +11 -16
- package/lib/helpers/formatters/common.ts +2 -1
- package/lib/helpers/formatters/index.ts +2 -4
- package/lib/helpers/simpleTableHelpers.ts +1 -1
- package/lib/infra/ActionButtons/ActionButtons.tsx +3 -3
- package/lib/infra/Assignment/Assignment.tsx +14 -14
- package/lib/infra/AssignmentCard/AssignmentCard.tsx +2 -2
- package/lib/infra/Containers/FlowContainer/FlowContainer.tsx +17 -29
- package/lib/infra/Containers/FlowContainer/helpers.ts +1 -5
- package/lib/infra/Containers/ModalViewContainer/ListViewActionButtons/ListViewActionButtons.tsx +10 -5
- package/lib/infra/Containers/ModalViewContainer/ModalViewContainer.tsx +9 -9
- package/lib/infra/Containers/SimpleView/helper.ts +1 -1
- package/lib/infra/Containers/ViewContainer/ViewContainer.tsx +2 -2
- package/lib/infra/DashboardFilter/DashboardFilter.tsx +6 -8
- package/lib/infra/DashboardFilter/filterUtils.tsx +3 -4
- package/lib/infra/DeferLoad/DeferLoad.tsx +9 -9
- package/lib/infra/ErrorBoundary/ErrorBoundary.tsx +1 -1
- package/lib/infra/MultiStep/MultiStep.tsx +17 -16
- package/lib/infra/NavBar/NavBar.css +1 -0
- package/lib/infra/NavBar/NavBar.tsx +49 -38
- package/lib/infra/Reference/Reference.tsx +1 -1
- package/lib/infra/Region/Region.tsx +1 -1
- package/lib/infra/RootContainer/RootContainer.tsx +7 -8
- package/lib/infra/Stages/Stages.tsx +5 -5
- package/lib/infra/VerticalTabs/LeftAlignVerticalTabs/LeftAlignVerticalTabs.tsx +4 -3
- package/lib/infra/VerticalTabs/VerticalTabs/VerticalTabs.tsx +2 -2
- package/lib/infra/View/View.tsx +38 -4
- package/lib/template/AdvancedSearch/AdvancedSearch.tsx +87 -0
- package/lib/template/AdvancedSearch/SearchGroup/persistUtils.ts +58 -0
- package/lib/template/AdvancedSearch/SearchGroups/SearchGroups.tsx +245 -0
- package/lib/template/AdvancedSearch/SearchGroups/hooks.ts +37 -0
- package/lib/template/AdvancedSearch/SearchGroups/index.tsx +1 -0
- package/lib/template/AdvancedSearch/SearchGroups/utils.ts +29 -0
- package/lib/template/AdvancedSearch/TemplateContext.ts +11 -0
- package/lib/template/AdvancedSearch/config-ext.json +9 -0
- package/lib/template/AdvancedSearch/index.tsx +1 -0
- package/lib/template/AppShell/AppShell.tsx +62 -12
- package/lib/template/BannerPage/BannerPage.tsx +2 -2
- package/lib/template/BannerPage/config-ext.json +9 -0
- package/lib/template/CaseSummary/CaseSummary.tsx +2 -2
- package/lib/template/CaseView/CaseView.tsx +12 -11
- package/lib/template/CaseViewActionsMenu/CaseViewActionsMenu.tsx +8 -8
- package/lib/template/Confirmation/Confirmation.tsx +5 -4
- package/lib/template/DataReference/DataReference.tsx +318 -108
- package/lib/template/DataReference/DataReferenceAdvancedSearchContext.js +10 -0
- package/lib/template/DataReference/SearchForm.tsx +148 -0
- package/lib/template/DataReference/utils.js +90 -0
- package/lib/template/DefaultForm/DefaultForm.tsx +2 -2
- package/lib/template/DefaultForm/utils/index.ts +1 -3
- package/lib/template/Details/Details/Details.tsx +3 -3
- package/lib/template/Details/DetailsSubTabs/DetailsSubTabs.tsx +5 -5
- package/lib/template/Details/DetailsThreeColumn/DetailsThreeColumn.tsx +3 -3
- package/lib/template/Details/DetailsTwoColumn/DetailsTwoColumn.tsx +3 -3
- package/lib/template/Details/DynamicTabs/DynamicTabs.tsx +5 -5
- package/lib/template/FieldGroupTemplate/FieldGroupTemplate.tsx +11 -6
- package/lib/template/InlineDashboard/InlineDashboard.tsx +4 -4
- package/lib/template/InlineDashboardPage/InlineDashboardPage.tsx +2 -2
- package/lib/template/InlineDashboardPage/config-ext.json +9 -0
- package/lib/template/ListPage/ListPage.tsx +1 -1
- package/lib/template/ListView/ListView.tsx +201 -95
- package/lib/template/ListView/utils.ts +38 -6
- package/lib/template/MultiReferenceReadOnly/MultiReferenceReadOnly.tsx +1 -1
- package/lib/template/NarrowWide/NarrowWide/NarrowWide.tsx +2 -2
- package/lib/template/NarrowWide/NarrowWideDetails/NarrowWideDetails.tsx +3 -3
- package/lib/template/NarrowWide/NarrowWideForm/NarrowWideForm.tsx +2 -2
- package/lib/template/NarrowWide/NarrowWidePage/NarrowWidePage.tsx +2 -2
- package/lib/template/OneColumn/OneColumn/OneColumn.tsx +4 -4
- package/lib/template/OneColumn/OneColumnPage/OneColumnPage.tsx +1 -1
- package/lib/template/OneColumn/OneColumnTab/OneColumnTab.tsx +2 -2
- package/lib/template/PromotedFilters/PromotedFilters.tsx +2 -3
- package/lib/template/SimpleTable/SimpleTable/SimpleTable.tsx +1 -3
- package/lib/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +112 -88
- package/lib/template/SimpleTable/SimpleTableSelect/SimpleTableSelect.tsx +3 -5
- package/lib/template/SingleReferenceReadOnly/SingleReferenceReadOnly.tsx +1 -1
- package/lib/template/SubTabs/SubTabs.tsx +4 -4
- package/lib/template/SubTabs/tabUtils.ts +118 -1
- package/lib/template/TwoColumn/TwoColumn/TwoColumn.tsx +10 -10
- package/lib/template/TwoColumn/TwoColumnPage/TwoColumnPage.tsx +1 -1
- package/lib/template/TwoColumn/TwoColumnTab/TwoColumnTab.tsx +10 -10
- package/lib/template/WideNarrow/WideNarrow/WideNarrow.tsx +2 -2
- package/lib/template/WideNarrow/WideNarrowDetails/WideNarrowDetails.tsx +3 -3
- package/lib/template/WideNarrow/WideNarrowForm/WideNarrowForm.tsx +2 -2
- package/lib/template/WideNarrow/WideNarrowPage/WideNarrowPage.tsx +2 -2
- package/lib/template/WssNavBar/WssNavBar.tsx +10 -10
- package/lib/widget/AppAnnouncement/AppAnnouncement.tsx +3 -3
- package/lib/widget/Attachment/Attachment.css +1 -0
- package/lib/widget/Attachment/Attachment.tsx +8 -10
- package/lib/widget/CaseHistory/CaseHistory.tsx +13 -11
- package/lib/widget/FileUtility/ActionButtonsForFileUtil/ActionButtonsForFileUtil.tsx +2 -2
- package/lib/widget/FileUtility/FileUtility/FileUtility.tsx +6 -5
- package/lib/widget/Followers/Followers.tsx +4 -4
- package/lib/widget/QuickCreate/QuickCreate.tsx +1 -2
- package/lib/widget/QuickCreate/config-ext.json +9 -0
- package/lib/widget/SummaryItem/SummaryItem.tsx +5 -4
- package/lib/widget/SummaryList/SummaryList.tsx +1 -1
- package/lib/widget/ToDo/ToDo.tsx +102 -40
- package/package.json +1 -1
- /package/lib/infra/Containers/{helpers.ts → container-helpers.ts} +0 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import React, { createElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { Button, Grid, Select, MenuItem, Box } from '@mui/material';
|
|
3
|
+
|
|
4
|
+
import createPConnectComponent from '@pega/react-sdk-components/lib/bridge/react_pconnect';
|
|
5
|
+
import TemplateContext from '@pega/react-sdk-components/lib/components/template/AdvancedSearch/TemplateContext';
|
|
6
|
+
import componentCachePersistUtils from '@pega/react-sdk-components/lib/components/template/AdvancedSearch/SearchGroup/persistUtils';
|
|
7
|
+
|
|
8
|
+
import { getCacheInfo, isValidInput } from './utils';
|
|
9
|
+
import { useCacheWhenListViewReady } from './hooks';
|
|
10
|
+
|
|
11
|
+
export const initializeSearchFields = (searchFields, getPConnect, referenceListClassID, searchFieldRestoreValues = {}) => {
|
|
12
|
+
const filtersProperties = {};
|
|
13
|
+
searchFields.forEach(field => {
|
|
14
|
+
let val = '';
|
|
15
|
+
const { value, defaultValue = '' } = field.config;
|
|
16
|
+
const propPath = PCore.getAnnotationUtils().getPropertyName(value);
|
|
17
|
+
|
|
18
|
+
if (searchFieldRestoreValues[propPath]) {
|
|
19
|
+
val = searchFieldRestoreValues[propPath];
|
|
20
|
+
} else if (PCore.getAnnotationUtils().isProperty(defaultValue)) {
|
|
21
|
+
val = getPConnect().getValue(defaultValue.split(' ')[1]);
|
|
22
|
+
} else if (defaultValue.startsWith('@L')) {
|
|
23
|
+
val = defaultValue.split(' ')[1];
|
|
24
|
+
} else {
|
|
25
|
+
val = defaultValue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
filtersProperties[propPath] = val;
|
|
29
|
+
|
|
30
|
+
const valueSplit = value.split('@P ')[1]?.split('.').filter(Boolean) ?? [];
|
|
31
|
+
valueSplit.pop();
|
|
32
|
+
|
|
33
|
+
if (valueSplit.length) {
|
|
34
|
+
let path = '';
|
|
35
|
+
let currentClassID = referenceListClassID;
|
|
36
|
+
valueSplit.forEach(item => {
|
|
37
|
+
path = path.length ? `${path}.${item}` : item;
|
|
38
|
+
currentClassID = (PCore.getMetadataUtils().getPropertyMetadata(item, currentClassID) as any).pageClass;
|
|
39
|
+
if (currentClassID) {
|
|
40
|
+
filtersProperties[`${path}.classID`] = currentClassID;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return filtersProperties;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const flattenObj = obj => {
|
|
49
|
+
const result = {};
|
|
50
|
+
Object.keys(obj).forEach(key => {
|
|
51
|
+
if (!['context_data', 'pageInstructions'].includes(key)) {
|
|
52
|
+
if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
|
|
53
|
+
const temp = flattenObj(obj[key]);
|
|
54
|
+
Object.keys(temp).forEach(nestedKey => {
|
|
55
|
+
result[`${key}.${nestedKey}`] = temp[nestedKey];
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
result[key] = obj[key];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default function SearchGroups(props) {
|
|
66
|
+
const localizedVal = PCore.getLocaleUtils().getLocaleValue;
|
|
67
|
+
const { getPConnect, editableField, localeReference, setShowRecords, searchSelectCacheKey, cache } = props;
|
|
68
|
+
const referenceFieldName = editableField.replaceAll('.', '_');
|
|
69
|
+
|
|
70
|
+
const state: any = useRef({ searchFields: {}, activeGroupId: '' }).current;
|
|
71
|
+
const options = componentCachePersistUtils.getComponentStateOptions(getPConnect);
|
|
72
|
+
|
|
73
|
+
const { searchGroups: groups, referenceList } = getPConnect().getConfigProps();
|
|
74
|
+
const { useCache, initialActiveGroupId } = getCacheInfo(cache, groups);
|
|
75
|
+
const [activeGroupId, setActiveGroupId] = useState(initialActiveGroupId);
|
|
76
|
+
const [transientItemID, setTransientItemID] = useState<any>(null);
|
|
77
|
+
const [previousFormValues, setPreviousFormValues] = useState<any>(null);
|
|
78
|
+
const viewName = getPConnect().getCurrentView();
|
|
79
|
+
|
|
80
|
+
const rawGroupsConfig = getPConnect().getRawConfigProps().searchGroups;
|
|
81
|
+
const activeGroupIndex = groups.findIndex(group => group.config.id === activeGroupId);
|
|
82
|
+
const { children: searchFieldsChildren = [] } = activeGroupIndex !== -1 ? rawGroupsConfig[activeGroupIndex] : {};
|
|
83
|
+
const searchFields = searchFieldsChildren.map(field => ({
|
|
84
|
+
...field,
|
|
85
|
+
config: { ...field.config, isSearchField: true }
|
|
86
|
+
}));
|
|
87
|
+
|
|
88
|
+
const searchByRef = useRef(null);
|
|
89
|
+
const searchFieldsRef = useRef(null);
|
|
90
|
+
const isValidatorField = searchFields.some(field => field.config.validator);
|
|
91
|
+
const { classID: referenceListClassID } = PCore.getMetadataUtils().getDataPageMetadata(referenceList) as any;
|
|
92
|
+
|
|
93
|
+
const initialSearchFields = useMemo(
|
|
94
|
+
() =>
|
|
95
|
+
initializeSearchFields(
|
|
96
|
+
searchFields,
|
|
97
|
+
getPConnect,
|
|
98
|
+
referenceListClassID,
|
|
99
|
+
useCache && cache.activeGroupId === activeGroupId ? cache.searchFields : {}
|
|
100
|
+
),
|
|
101
|
+
[activeGroupId, getPConnect, cache.searchFields]
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
if (transientItemID) {
|
|
106
|
+
const filtersWithClassID = {
|
|
107
|
+
...initialSearchFields,
|
|
108
|
+
classID: referenceListClassID
|
|
109
|
+
};
|
|
110
|
+
// @ts-ignore
|
|
111
|
+
PCore.getContainerUtils().replaceTransientData({ transientItemID, data: filtersWithClassID });
|
|
112
|
+
}
|
|
113
|
+
}, [activeGroupId]);
|
|
114
|
+
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
const filtersWithClassID = {
|
|
117
|
+
...initialSearchFields,
|
|
118
|
+
classID: referenceListClassID
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const transientId = getPConnect()
|
|
122
|
+
.getContainerManager()
|
|
123
|
+
.addTransientItem({ id: `${referenceFieldName}-${viewName}`, data: filtersWithClassID });
|
|
124
|
+
setTransientItemID(transientId);
|
|
125
|
+
}, []);
|
|
126
|
+
|
|
127
|
+
const getFilterData = useCallback(() => {
|
|
128
|
+
// @ts-ignore
|
|
129
|
+
let changes = PCore.getFormUtils().getSubmitData(transientItemID, {
|
|
130
|
+
isTransientContext: true,
|
|
131
|
+
includeDisabledFields: true
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
if (Object.keys(cache.searchFields ?? {}).length > 0 && Object.keys(changes).length === 1) {
|
|
135
|
+
changes = cache.searchFields;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const formValues = flattenObj(changes);
|
|
139
|
+
|
|
140
|
+
if (!PCore.isDeepEqual(previousFormValues, formValues) && PCore.getFormUtils().isFormValid(transientItemID) && isValidInput(formValues)) {
|
|
141
|
+
if (isValidatorField) {
|
|
142
|
+
// @ts-ignore
|
|
143
|
+
PCore.getMessageManager().clearContextMessages({ context: transientItemID });
|
|
144
|
+
}
|
|
145
|
+
setPreviousFormValues(formValues);
|
|
146
|
+
setShowRecords(true);
|
|
147
|
+
PCore.getPubSubUtils().publish(PCore.getEvents().getTransientEvent().UPDATE_PROMOTED_FILTERS, {
|
|
148
|
+
payload: formValues,
|
|
149
|
+
showRecords: true,
|
|
150
|
+
viewName
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
state.activeGroupId = activeGroupId;
|
|
155
|
+
state.searchFields = changes;
|
|
156
|
+
state.selectedCategory = viewName;
|
|
157
|
+
|
|
158
|
+
componentCachePersistUtils.setComponentCache({ cacheKey: searchSelectCacheKey, state, options });
|
|
159
|
+
}, [transientItemID, setShowRecords, viewName, activeGroupId, previousFormValues]);
|
|
160
|
+
|
|
161
|
+
const resetFilterData = useCallback(() => {
|
|
162
|
+
// @ts-ignore
|
|
163
|
+
PCore.getNavigationUtils().resetComponentCache(searchSelectCacheKey);
|
|
164
|
+
const resetPayload = {
|
|
165
|
+
transientItemID,
|
|
166
|
+
data: initializeSearchFields(searchFields, getPConnect, referenceListClassID),
|
|
167
|
+
options: { reset: true }
|
|
168
|
+
};
|
|
169
|
+
// @ts-ignore
|
|
170
|
+
PCore.getContainerUtils().updateTransientData(resetPayload);
|
|
171
|
+
}, [transientItemID, initialSearchFields]);
|
|
172
|
+
|
|
173
|
+
useCacheWhenListViewReady(cache, viewName, useCache, getFilterData, searchSelectCacheKey);
|
|
174
|
+
|
|
175
|
+
const searchDropdown = groups.length > 1 && (
|
|
176
|
+
<Grid container spacing={2}>
|
|
177
|
+
<Select value={activeGroupId} onChange={e => setActiveGroupId(e.target.value)} ref={searchByRef} fullWidth>
|
|
178
|
+
{groups.map(group => (
|
|
179
|
+
<MenuItem key={group.config.id} value={group.config.id}>
|
|
180
|
+
{group.config.label}
|
|
181
|
+
</MenuItem>
|
|
182
|
+
))}
|
|
183
|
+
</Select>
|
|
184
|
+
</Grid>
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
const actionButtons = (
|
|
188
|
+
<Box display='flex' gap={2}>
|
|
189
|
+
<Button variant='outlined' onClick={resetFilterData}>
|
|
190
|
+
{localizedVal('Reset', 'SimpleTable')}
|
|
191
|
+
</Button>
|
|
192
|
+
<Button variant='contained' onClick={getFilterData}>
|
|
193
|
+
{localizedVal('Search', 'SimpleTable')}
|
|
194
|
+
</Button>
|
|
195
|
+
</Box>
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const searchFieldsViewConfig = {
|
|
199
|
+
name: 'SearchFields',
|
|
200
|
+
type: 'View',
|
|
201
|
+
config: {
|
|
202
|
+
template: 'DefaultForm',
|
|
203
|
+
NumCols: '3',
|
|
204
|
+
contextName: transientItemID,
|
|
205
|
+
readOnly: false,
|
|
206
|
+
context: transientItemID,
|
|
207
|
+
localeReference
|
|
208
|
+
},
|
|
209
|
+
children: [
|
|
210
|
+
{
|
|
211
|
+
name: 'Fields',
|
|
212
|
+
type: 'Region',
|
|
213
|
+
children: searchFields
|
|
214
|
+
}
|
|
215
|
+
]
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const searchFieldsC11nEnv = PCore.createPConnect({
|
|
219
|
+
meta: searchFieldsViewConfig,
|
|
220
|
+
options: {
|
|
221
|
+
hasForm: true,
|
|
222
|
+
contextName: transientItemID
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const templateContext = useContext(TemplateContext);
|
|
227
|
+
const templateContextValue = useMemo(() => ({ ...templateContext, outerColumnCount: undefined }), []);
|
|
228
|
+
|
|
229
|
+
const searchFieldsViewComp = transientItemID ? (
|
|
230
|
+
<TemplateContext.Provider value={templateContextValue}>
|
|
231
|
+
<div ref={searchFieldsRef}>{createElement(createPConnectComponent(), { ...searchFieldsC11nEnv })}</div>
|
|
232
|
+
</TemplateContext.Provider>
|
|
233
|
+
) : null;
|
|
234
|
+
|
|
235
|
+
const childrenToRender = [searchDropdown, searchFieldsViewComp, actionButtons];
|
|
236
|
+
|
|
237
|
+
return (
|
|
238
|
+
<Box display='flex' flexDirection='column' gap={2}>
|
|
239
|
+
{childrenToRender.map((child, index) => (
|
|
240
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
241
|
+
<React.Fragment key={index}>{child}</React.Fragment>
|
|
242
|
+
))}
|
|
243
|
+
</Box>
|
|
244
|
+
);
|
|
245
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
const listViewConstants = {
|
|
4
|
+
EVENTS: {
|
|
5
|
+
LIST_VIEW_READY: 'LIST_VIEW_READY'
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* This hook registers a callback for the whenever list view component is ready
|
|
10
|
+
* then makes a call to get the data using the search fields pre-filled with cache data.
|
|
11
|
+
*/
|
|
12
|
+
// eslint-disable-next-line import/prefer-default-export
|
|
13
|
+
export function useCacheWhenListViewReady(
|
|
14
|
+
cache: { searchFields: unknown },
|
|
15
|
+
viewName: string,
|
|
16
|
+
useCache: boolean,
|
|
17
|
+
getFilterData: (params: { isCalledFromCache: boolean }) => void,
|
|
18
|
+
searchSelectCacheKey: string
|
|
19
|
+
) {
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (Object.keys(cache.searchFields ?? {}).length > 0) {
|
|
22
|
+
PCore.getPubSubUtils().subscribe(
|
|
23
|
+
listViewConstants.EVENTS.LIST_VIEW_READY,
|
|
24
|
+
({ viewName: viewNameFromListView }: { viewName: string }) => {
|
|
25
|
+
if (viewNameFromListView === viewName && useCache) {
|
|
26
|
+
getFilterData({ isCalledFromCache: true });
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
`${searchSelectCacheKey}-listview-ready`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return () => {
|
|
34
|
+
PCore.getPubSubUtils().unsubscribe(listViewConstants.EVENTS.LIST_VIEW_READY, `${searchSelectCacheKey}-listview-ready`);
|
|
35
|
+
};
|
|
36
|
+
}, []);
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './SearchGroups';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function isEmpty(value: any): boolean {
|
|
2
|
+
return (
|
|
3
|
+
// null or undefined
|
|
4
|
+
value === null ||
|
|
5
|
+
value === undefined ||
|
|
6
|
+
((Array.isArray(value) || typeof value === 'string') && value.length === 0) ||
|
|
7
|
+
// is an Object and has no keys
|
|
8
|
+
(value.constructor === Object && Object.keys(value).length === 0)
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getCacheInfo(
|
|
13
|
+
cache: { selectedCategory: string; activeGroupId: string; searchFields: unknown },
|
|
14
|
+
groups: { config: { id: string } }[]
|
|
15
|
+
) {
|
|
16
|
+
let initialActiveGroupId = groups.length ? groups[0].config.id : '';
|
|
17
|
+
|
|
18
|
+
let useCache = false;
|
|
19
|
+
if (cache.activeGroupId && groups?.find(group => group.config.id === cache.activeGroupId)) {
|
|
20
|
+
initialActiveGroupId = cache.activeGroupId;
|
|
21
|
+
useCache = true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return { useCache, initialActiveGroupId };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isValidInput(input: { [s: string]: unknown }) {
|
|
28
|
+
return Object.values(input).some(value => !isEmpty(value));
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
|
|
3
|
+
const TemplateContext = createContext({
|
|
4
|
+
depth: 0,
|
|
5
|
+
columnCount: 1,
|
|
6
|
+
outerColumnCount: undefined,
|
|
7
|
+
templateOverrideMode: undefined,
|
|
8
|
+
inheritParentLayout: undefined,
|
|
9
|
+
lastContainerItem: undefined
|
|
10
|
+
});
|
|
11
|
+
export default TemplateContext;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './AdvancedSearch';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { PropsWithChildren, useEffect, useState } from 'react';
|
|
2
|
-
import
|
|
3
|
-
import Avatar from '@material
|
|
1
|
+
import { type PropsWithChildren, useEffect, useState } from 'react';
|
|
2
|
+
import makeStyles from '@mui/styles/makeStyles';
|
|
3
|
+
import Avatar from '@mui/material/Avatar';
|
|
4
4
|
|
|
5
5
|
import { Utils } from '@pega/react-sdk-components/lib/components/helpers/utils';
|
|
6
6
|
import { NavContext } from '@pega/react-sdk-components/lib/components/helpers/reactContextHelpers';
|
|
7
7
|
import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
|
|
8
|
-
import { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
8
|
+
import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
9
9
|
|
|
10
10
|
import './AppShell.css';
|
|
11
11
|
|
|
@@ -24,6 +24,8 @@ interface AppShellProps extends PConnProps {
|
|
|
24
24
|
portalName: string;
|
|
25
25
|
portalLogo: string;
|
|
26
26
|
navDisplayOptions: { alignment: string; position: string };
|
|
27
|
+
httpMessages: string[];
|
|
28
|
+
pageMessages: string[];
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
const useStyles = makeStyles(theme => ({
|
|
@@ -49,8 +51,21 @@ export default function AppShell(props: PropsWithChildren<AppShellProps>) {
|
|
|
49
51
|
// Get emitted components from map (so we can get any override that may exist)
|
|
50
52
|
const NavBar = getComponentFromMap('NavBar');
|
|
51
53
|
const WssNavBar = getComponentFromMap('WssNavBar');
|
|
54
|
+
const AlertBanner = getComponentFromMap('AlertBanner');
|
|
52
55
|
|
|
53
|
-
const {
|
|
56
|
+
const {
|
|
57
|
+
pages = [],
|
|
58
|
+
caseTypes = [],
|
|
59
|
+
showAppName,
|
|
60
|
+
children = [],
|
|
61
|
+
getPConnect,
|
|
62
|
+
httpMessages = [],
|
|
63
|
+
pageMessages = [],
|
|
64
|
+
portalTemplate,
|
|
65
|
+
portalName,
|
|
66
|
+
portalLogo,
|
|
67
|
+
navDisplayOptions
|
|
68
|
+
} = props;
|
|
54
69
|
|
|
55
70
|
const [open, setOpen] = useState(true);
|
|
56
71
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -58,7 +73,7 @@ export default function AppShell(props: PropsWithChildren<AppShellProps>) {
|
|
|
58
73
|
const pConn = getPConnect();
|
|
59
74
|
const envInfo = PCore.getEnvironmentInfo();
|
|
60
75
|
const imageKey = envInfo.getOperatorImageInsKey();
|
|
61
|
-
const userName = envInfo.getOperatorName();
|
|
76
|
+
const userName = envInfo.getOperatorName() || '';
|
|
62
77
|
const currentUserInitials = Utils.getInitials(userName);
|
|
63
78
|
const appNameToDisplay = showAppName ? envInfo.getApplicationLabel() : '';
|
|
64
79
|
const portalClass = pConn.getValue('.classID', ''); // 2nd arg empty string until typedef marked correctly
|
|
@@ -75,9 +90,18 @@ export default function AppShell(props: PropsWithChildren<AppShellProps>) {
|
|
|
75
90
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
76
91
|
const [mapChildren, setMapChildren] = useState([]);
|
|
77
92
|
|
|
93
|
+
const messages = [...httpMessages, ...pageMessages];
|
|
94
|
+
|
|
95
|
+
const hasBanner = messages && messages.length ? messages.length > 0 : false;
|
|
96
|
+
let banners: any = null;
|
|
97
|
+
banners = hasBanner && (
|
|
98
|
+
<div style={{ display: 'flex', flexDirection: 'column', padding: '1em 0' }}>
|
|
99
|
+
<AlertBanner id='AppShell' variant='urgent' messages={messages} />
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
78
102
|
// Initial setting of appName and mapChildren
|
|
79
103
|
useEffect(() => {
|
|
80
|
-
setAppName(PCore.getEnvironmentInfo().getApplicationName());
|
|
104
|
+
setAppName(PCore.getEnvironmentInfo().getApplicationName() || '');
|
|
81
105
|
|
|
82
106
|
const tempMap: any = (pConn.getChildren() as any)?.map((child: any, index) => {
|
|
83
107
|
const theChildComp = child.getPConnect().getComponentName();
|
|
@@ -92,6 +116,25 @@ export default function AppShell(props: PropsWithChildren<AppShellProps>) {
|
|
|
92
116
|
setMapChildren(tempMap);
|
|
93
117
|
}, []);
|
|
94
118
|
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
// @ts-ignore
|
|
121
|
+
const caseTypesAvailableToCreateDP = PCore.getEnvironmentInfo().environmentInfoObject?.pxApplication?.pyCaseTypesAvailableToCreateDP;
|
|
122
|
+
if (caseTypesAvailableToCreateDP) {
|
|
123
|
+
const portalID = pConn.getValue('.pyOwner');
|
|
124
|
+
PCore.getDataPageUtils()
|
|
125
|
+
.getPageDataAsync(caseTypesAvailableToCreateDP, pConn.getContextName(), {
|
|
126
|
+
PortalName: portalID
|
|
127
|
+
})
|
|
128
|
+
.then((response: { pyCaseTypesAvailableToCreate?: any }) => {
|
|
129
|
+
if (response?.pyCaseTypesAvailableToCreate) {
|
|
130
|
+
pConn.replaceState('.pyCaseTypesAvailableToCreate', response.pyCaseTypesAvailableToCreate, {
|
|
131
|
+
skipDirtyValidation: true
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}, []);
|
|
137
|
+
|
|
95
138
|
const [iconURL, setIconURL] = useState('');
|
|
96
139
|
const [fullIconURL, setFullIconURL] = useState('');
|
|
97
140
|
useEffect(() => {
|
|
@@ -175,10 +218,10 @@ export default function AppShell(props: PropsWithChildren<AppShellProps>) {
|
|
|
175
218
|
portalName={portalName}
|
|
176
219
|
imageSrc={iconURL}
|
|
177
220
|
fullImageSrc={fullIconURL}
|
|
178
|
-
appName={localizedVal(appNameToDisplay, '', `${portalClass}!PORTAL!${envPortalName}`.toUpperCase())}
|
|
221
|
+
appName={localizedVal(appNameToDisplay || '', '', `${portalClass}!PORTAL!${envPortalName}`.toUpperCase())}
|
|
179
222
|
appInfo={{
|
|
180
223
|
imageSrc: iconURL,
|
|
181
|
-
appName: localizedVal(appNameToDisplay, '', `${portalClass}!PORTAL!${envPortalName}`.toUpperCase()),
|
|
224
|
+
appName: localizedVal(appNameToDisplay || '', '', `${portalClass}!PORTAL!${envPortalName}`.toUpperCase()),
|
|
182
225
|
onClick: links[0] && /* links[0].onClick ? */ links[0].onClick /* : undefined */
|
|
183
226
|
}}
|
|
184
227
|
navLinks={links.filter((link, index) => {
|
|
@@ -187,7 +230,10 @@ export default function AppShell(props: PropsWithChildren<AppShellProps>) {
|
|
|
187
230
|
operator={getOperator()}
|
|
188
231
|
navDisplayOptions={navDisplayOptions}
|
|
189
232
|
/>
|
|
190
|
-
<div className={classes.wsscontent}>
|
|
233
|
+
<div className={classes.wsscontent}>
|
|
234
|
+
{banners}
|
|
235
|
+
{children}
|
|
236
|
+
</div>
|
|
191
237
|
</div>
|
|
192
238
|
);
|
|
193
239
|
}
|
|
@@ -199,11 +245,15 @@ export default function AppShell(props: PropsWithChildren<AppShellProps>) {
|
|
|
199
245
|
<NavBar
|
|
200
246
|
getPConnect={getPConnect}
|
|
201
247
|
pConn={getPConnect()}
|
|
202
|
-
appName={localizedVal(appNameToDisplay, '', `${portalClass}!PORTAL!${envPortalName}`.toUpperCase())}
|
|
248
|
+
appName={localizedVal(appNameToDisplay || '', '', `${portalClass}!PORTAL!${envPortalName}`.toUpperCase())}
|
|
203
249
|
pages={pages}
|
|
204
250
|
caseTypes={caseTypes}
|
|
205
251
|
/>
|
|
206
|
-
|
|
252
|
+
|
|
253
|
+
<div className={classes.content}>
|
|
254
|
+
{banners}
|
|
255
|
+
{children}
|
|
256
|
+
</div>
|
|
207
257
|
</div>
|
|
208
258
|
</NavContext.Provider>
|
|
209
259
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Children, PropsWithChildren, useMemo } from 'react';
|
|
1
|
+
import { Children, type PropsWithChildren, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
|
|
4
|
-
import { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
4
|
+
import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
5
5
|
|
|
6
6
|
interface BannerPageProps extends PConnProps {
|
|
7
7
|
// If any, enter additional props that only exist on this component
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { PropsWithChildren, ReactElement } from 'react';
|
|
1
|
+
import type { PropsWithChildren, ReactElement } from 'react';
|
|
2
2
|
import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
|
|
3
|
-
import { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
3
|
+
import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
4
4
|
|
|
5
5
|
interface CaseSummaryProps extends PConnProps {
|
|
6
6
|
// If any, enter additional props that only exist on this component
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/* eslint-disable react/jsx-boolean-value */
|
|
2
2
|
|
|
3
|
-
import { PropsWithChildren, ReactElement, useContext, useEffect, useState } from 'react';
|
|
4
|
-
import { Avatar, Card, CardHeader, Divider, Typography } from '@material
|
|
5
|
-
import
|
|
6
|
-
import Box from '@material
|
|
7
|
-
import Button from '@material
|
|
8
|
-
import Grid from '@material
|
|
3
|
+
import { type PropsWithChildren, type ReactElement, useContext, useEffect, useState } from 'react';
|
|
4
|
+
import { Avatar, Card, CardHeader, Divider, Typography } from '@mui/material';
|
|
5
|
+
import makeStyles from '@mui/styles/makeStyles';
|
|
6
|
+
import Box from '@mui/material/Box';
|
|
7
|
+
import Button from '@mui/material/Button';
|
|
8
|
+
import Grid from '@mui/material/Grid';
|
|
9
9
|
|
|
10
10
|
import { Utils } from '@pega/react-sdk-components/lib/components/helpers/utils';
|
|
11
11
|
import StoreContext from '@pega/react-sdk-components/lib/bridge/Context/StoreContext';
|
|
12
12
|
import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
|
|
13
|
-
import { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
13
|
+
import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
14
14
|
|
|
15
15
|
interface CaseViewProps extends PConnProps {
|
|
16
16
|
// If any, enter additional props that only exist on this component
|
|
@@ -19,6 +19,7 @@ interface CaseViewProps extends PConnProps {
|
|
|
19
19
|
header: string;
|
|
20
20
|
showIconInHeader: boolean;
|
|
21
21
|
caseInfo: any;
|
|
22
|
+
lastUpdateCaseTime: any;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
const useStyles = makeStyles(theme => ({
|
|
@@ -64,10 +65,10 @@ export default function CaseView(props: PropsWithChildren<CaseViewProps>) {
|
|
|
64
65
|
showIconInHeader = true,
|
|
65
66
|
caseInfo: { availableActions = [], availableProcesses = [], hasNewAttachments, caseTypeID = '', caseTypeName = '' }
|
|
66
67
|
} = props;
|
|
68
|
+
const { lastUpdateCaseTime = getPConnect().getValue('caseInfo.lastUpdateTime') } = props;
|
|
67
69
|
|
|
68
70
|
const currentCaseID = props.caseInfo.ID;
|
|
69
71
|
let isComponentMounted = true;
|
|
70
|
-
|
|
71
72
|
const { displayOnlyFA } = useContext<any>(StoreContext);
|
|
72
73
|
|
|
73
74
|
const thePConn = getPConnect();
|
|
@@ -79,7 +80,6 @@ export default function CaseView(props: PropsWithChildren<CaseViewProps>) {
|
|
|
79
80
|
const localizedVal = PCore.getLocaleUtils().getLocaleValue;
|
|
80
81
|
const localeCategory = 'CaseView';
|
|
81
82
|
const localeKey = `${caseTypeID}!CASE!${caseTypeName}`.toUpperCase();
|
|
82
|
-
|
|
83
83
|
/**
|
|
84
84
|
*
|
|
85
85
|
* @param inName the metadata <em>name</em> that will cause a region to be returned
|
|
@@ -169,7 +169,6 @@ export default function CaseView(props: PropsWithChildren<CaseViewProps>) {
|
|
|
169
169
|
|
|
170
170
|
useEffect(() => {
|
|
171
171
|
if (hasNewAttachments) {
|
|
172
|
-
// @ts-ignore - Argument of type 'boolean' is not assignable to parameter of type 'object'
|
|
173
172
|
PCore.getPubSubUtils().publish((PCore.getEvents().getCaseEvent() as any).CASE_ATTACHMENTS_UPDATED_FROM_CASEVIEW, true);
|
|
174
173
|
}
|
|
175
174
|
}, [hasNewAttachments]);
|
|
@@ -244,7 +243,9 @@ export default function CaseView(props: PropsWithChildren<CaseViewProps>) {
|
|
|
244
243
|
<Grid item xs={6}>
|
|
245
244
|
{theStagesRegion}
|
|
246
245
|
{theTodoRegion}
|
|
247
|
-
{deferLoadInfo.length > 0 &&
|
|
246
|
+
{deferLoadInfo.length > 0 && (
|
|
247
|
+
<DeferLoad getPConnect={getPConnect} name={deferLoadInfo[activeVertTab].config.name} isTab lastUpdateCaseTime={lastUpdateCaseTime} />
|
|
248
|
+
)}
|
|
248
249
|
</Grid>
|
|
249
250
|
|
|
250
251
|
<Grid item xs={3}>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import Button from '@material
|
|
3
|
-
import Menu from '@material
|
|
4
|
-
import MenuItem from '@material
|
|
2
|
+
import Button from '@mui/material/Button';
|
|
3
|
+
import Menu from '@mui/material/Menu';
|
|
4
|
+
import MenuItem from '@mui/material/MenuItem';
|
|
5
5
|
|
|
6
|
-
import { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
7
|
-
import Snackbar from '@material
|
|
8
|
-
import IconButton from '@material
|
|
9
|
-
import CloseIcon from '@
|
|
6
|
+
import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
7
|
+
import Snackbar from '@mui/material/Snackbar';
|
|
8
|
+
import IconButton from '@mui/material/IconButton';
|
|
9
|
+
import CloseIcon from '@mui/icons-material/Close';
|
|
10
10
|
|
|
11
11
|
interface CaseViewActionsMenuProps extends PConnProps {
|
|
12
12
|
// If any, enter additional props that only exist on this component
|
|
@@ -44,7 +44,7 @@ export default function CaseViewActionsMenu(props: CaseViewActionsMenuProps) {
|
|
|
44
44
|
setShowSnackbar(true);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
function handleSnackbarClose(event: React.SyntheticEvent |
|
|
47
|
+
function handleSnackbarClose(event: React.SyntheticEvent<any> | Event, reason?: string) {
|
|
48
48
|
if (reason === 'clickaway') {
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/* eslint-disable no-nested-ternary */
|
|
2
|
-
import { PropsWithChildren, useState } from 'react';
|
|
3
|
-
import { Button, Card
|
|
2
|
+
import { type PropsWithChildren, useState } from 'react';
|
|
3
|
+
import { Button, Card } from '@mui/material';
|
|
4
|
+
import makeStyles from '@mui/styles/makeStyles';
|
|
4
5
|
|
|
5
6
|
import { getToDoAssignments } from '@pega/react-sdk-components/lib/components/infra/Containers/FlowContainer/helpers';
|
|
6
7
|
import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
|
|
7
|
-
import { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
8
|
+
import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
8
9
|
|
|
9
10
|
interface ConfirmationProps extends PConnProps {
|
|
10
11
|
// If any, enter additional props that only exist on this component
|
|
@@ -40,7 +41,7 @@ export default function Confirmation(props: PropsWithChildren<ConfirmationProps>
|
|
|
40
41
|
// Not using whatsNext at the moment, need to figure out the use of it
|
|
41
42
|
// const whatsNext = datasource?.source;
|
|
42
43
|
// const items = whatsNext.length > 0 ? whatsNext.map(item => item.label) : '';
|
|
43
|
-
const activeContainerItemID = PCore.getContainerUtils().getActiveContainerItemName(getPConnect().getTarget());
|
|
44
|
+
const activeContainerItemID = PCore.getContainerUtils().getActiveContainerItemName(getPConnect().getTarget() || '');
|
|
44
45
|
const rootInfo = PCore.getContainerUtils().getContainerItemData(getPConnect().getTarget(), activeContainerItemID);
|
|
45
46
|
const onConfirmViewClose = () => {
|
|
46
47
|
setShowConfirmView(false);
|