@pega/react-sdk-overrides 0.25.2 → 0.25.3
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/Banner/Banner.css +1 -1
- package/lib/designSystemExtension/Banner/Banner.tsx +7 -7
- package/lib/designSystemExtension/CaseSummaryFields/CaseSummaryFields.tsx +8 -10
- package/lib/designSystemExtension/DetailsFields/DetailsFields.tsx +11 -13
- package/lib/designSystemExtension/FieldGroup/FieldGroup.tsx +7 -8
- package/lib/designSystemExtension/FieldGroupList/FieldGroupList.tsx +9 -9
- package/lib/designSystemExtension/FieldValueList/FieldValueList.tsx +7 -8
- package/lib/designSystemExtension/Operator/Operator.tsx +11 -12
- package/lib/designSystemExtension/RichTextEditor/RichTextEditor.tsx +28 -3
- package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.css +4 -4
- package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.tsx +1 -1
- package/lib/field/CancelAlert/CancelAlert.css +4 -4
- package/lib/field/CancelAlert/CancelAlert.tsx +5 -5
- package/lib/field/Checkbox/Checkbox.tsx +96 -3
- package/lib/field/Currency/currency-utils.ts +1 -2
- package/lib/field/Dropdown/Dropdown.tsx +0 -2
- package/lib/field/Group/Group.tsx +5 -5
- package/lib/field/Location/Location.tsx +256 -0
- package/lib/field/Location/config-ext.json +8 -0
- package/lib/field/Location/index.tsx +1 -0
- package/lib/field/ObjectReference/ObjectReference.tsx +235 -0
- package/lib/field/ObjectReference/index.tsx +1 -0
- package/lib/field/ObjectReference/utils.ts +111 -0
- package/lib/field/RadioButtons/RadioButtons.tsx +46 -1
- package/lib/field/ScalarList/ScalarList.tsx +1 -2
- package/lib/field/SelectableCard/SelectableCard.tsx +175 -0
- package/lib/field/SelectableCard/index.tsx +1 -0
- package/lib/field/SelectableCard/utils.tsx +226 -0
- package/lib/field/SemanticLink/SemanticLink.tsx +159 -27
- package/lib/field/SemanticLink/utils.ts +1 -1
- package/lib/field/TextContent/TextContent.tsx +0 -1
- package/lib/field/UserReference/UserReference.tsx +0 -1
- package/lib/helpers/attachmentHelpers.ts +56 -35
- package/lib/helpers/common-utils.ts +2 -2
- package/lib/helpers/data_page.ts +0 -1
- package/lib/helpers/formatters/CurrencyMap.ts +0 -2
- package/lib/helpers/simpleTableHelpers.ts +117 -5
- package/lib/helpers/utils.ts +8 -1
- package/lib/helpers/versionHelpers.ts +0 -1
- package/lib/infra/ActionButtons/ActionButtons.tsx +28 -21
- package/lib/infra/Assignment/Assignment.tsx +2 -2
- package/lib/infra/Containers/FlowContainer/FlowContainer.tsx +14 -93
- package/lib/infra/Containers/ModalViewContainer/ListViewActionButtons/ListViewActionButtons.tsx +0 -1
- package/lib/infra/Containers/ModalViewContainer/ModalViewContainer.tsx +2 -2
- package/lib/infra/Containers/ViewContainer/ViewContainer.tsx +3 -4
- package/lib/infra/Containers/container-helpers.ts +47 -1
- package/lib/infra/DashboardFilter/DashboardFilter.tsx +0 -2
- package/lib/infra/DashboardFilter/filterUtils.tsx +3 -4
- package/lib/infra/DeferLoad/DeferLoad.tsx +1 -3
- package/lib/infra/ErrorBoundary/ErrorBoundary.tsx +0 -2
- package/lib/infra/MultiStep/MultiStep.css +8 -8
- package/lib/infra/NavBar/NavBar.css +1 -1
- package/lib/infra/NavBar/NavBar.tsx +3 -4
- package/lib/infra/Reference/Reference.tsx +2 -3
- package/lib/infra/RootContainer/RootContainer.tsx +0 -1
- package/lib/template/AdvancedSearch/AdvancedSearch.tsx +0 -1
- package/lib/template/AdvancedSearch/SearchGroup/persistUtils.ts +3 -9
- package/lib/template/AdvancedSearch/SearchGroups/SearchGroups.tsx +3 -4
- package/lib/template/AdvancedSearch/SearchGroups/hooks.ts +1 -1
- package/lib/template/AppShell/AppShell.css +1 -1
- package/lib/template/AppShell/AppShell.tsx +4 -8
- package/lib/template/CaseSummary/CaseSummary.tsx +0 -1
- package/lib/template/CaseView/CaseView.tsx +13 -19
- package/lib/template/Confirmation/Confirmation.tsx +0 -1
- package/lib/template/DataReference/DataReference.tsx +7 -10
- package/lib/template/DataReference/SearchForm.tsx +6 -5
- package/lib/template/DataReference/{utils.js → utils.ts} +3 -3
- package/lib/template/DefaultForm/DefaultForm.tsx +1 -1
- package/lib/template/Details/Details/Details.tsx +10 -10
- package/lib/template/Details/DetailsThreeColumn/DetailsThreeColumn.tsx +10 -10
- package/lib/template/Details/DetailsTwoColumn/DetailsTwoColumn.tsx +10 -10
- package/lib/template/FieldGroupTemplate/FieldGroupTemplate.tsx +1 -2
- package/lib/template/InlineDashboard/InlineDashboard.tsx +12 -14
- package/lib/template/ListView/ListView.tsx +8 -20
- package/lib/template/ListView/hooks.ts +1 -5
- package/lib/template/ListView/utils.ts +1 -1
- package/lib/template/NarrowWide/NarrowWide/NarrowWide.tsx +3 -3
- package/lib/template/NarrowWide/NarrowWideDetails/NarrowWideDetails.tsx +10 -10
- package/lib/template/OneColumn/OneColumn/OneColumn.tsx +5 -5
- package/lib/template/PromotedFilters/PromotedFilters.tsx +0 -1
- package/lib/template/SimpleTable/SimpleTable/SimpleTable.tsx +1 -2
- package/lib/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +33 -30
- package/lib/template/TwoColumn/TwoColumn/TwoColumn.tsx +1 -2
- package/lib/template/TwoColumn/TwoColumnTab/TwoColumnTab.tsx +1 -2
- package/lib/template/WideNarrow/WideNarrow/WideNarrow.tsx +3 -3
- package/lib/template/WideNarrow/WideNarrowDetails/WideNarrowDetails.tsx +10 -10
- package/lib/template/WssNavBar/WssNavBar.css +1 -1
- package/lib/template/WssNavBar/WssNavBar.tsx +4 -4
- package/lib/widget/Attachment/Attachment.css +6 -8
- package/lib/widget/Attachment/Attachment.tsx +61 -57
- package/lib/widget/CaseHistory/CaseHistory.tsx +3 -3
- package/lib/widget/FileUtility/ActionButtonsForFileUtil/ActionButtonsForFileUtil.css +0 -14
- package/lib/widget/FileUtility/ActionButtonsForFileUtil/ActionButtonsForFileUtil.tsx +2 -2
- package/lib/widget/FileUtility/FileUtility/FileUtility.css +7 -6
- package/lib/widget/FileUtility/FileUtility/FileUtility.tsx +4 -6
- package/lib/widget/Followers/Followers.tsx +0 -2
- package/lib/widget/QuickCreate/QuickCreate.tsx +0 -1
- package/lib/widget/SummaryItem/SummaryItem.css +9 -11
- package/lib/widget/SummaryItem/SummaryItem.tsx +1 -1
- package/lib/widget/ToDo/ToDo.css +1 -13
- package/lib/widget/ToDo/ToDo.tsx +15 -7
- package/package.json +1 -1
- /package/lib/template/DataReference/{DataReferenceAdvancedSearchContext.js → DataReferenceAdvancedSearchContext.ts} +0 -0
|
@@ -170,7 +170,6 @@ export default function Dropdown(props: DropdownProps) {
|
|
|
170
170
|
return (
|
|
171
171
|
<FieldValueList
|
|
172
172
|
name={hideLabel ? '' : label}
|
|
173
|
-
// @ts-ignore - Property 'getLocaleRuleNameFromKeys' is private and only accessible within class 'C11nEnv'
|
|
174
173
|
value={thePConn.getLocalizedValue(val, localePath, thePConn.getLocaleRuleNameFromKeys(localeClass, localeContext, localeName))}
|
|
175
174
|
/>
|
|
176
175
|
);
|
|
@@ -180,7 +179,6 @@ export default function Dropdown(props: DropdownProps) {
|
|
|
180
179
|
return (
|
|
181
180
|
<FieldValueList
|
|
182
181
|
name={hideLabel ? '' : label}
|
|
183
|
-
// @ts-ignore - Property 'getLocaleRuleNameFromKeys' is private and only accessible within class 'C11nEnv'
|
|
184
182
|
value={thePConn.getLocalizedValue(val, localePath, thePConn.getLocaleRuleNameFromKeys(localeClass, localeContext, localeName))}
|
|
185
183
|
variant='stacked'
|
|
186
184
|
/>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactElement, useMemo } from 'react';
|
|
2
|
-
import
|
|
2
|
+
import Grid2 from '@mui/material/Grid2';
|
|
3
3
|
import FieldGroup from '@pega/react-sdk-components/lib/components/designSystemExtension/FieldGroup';
|
|
4
4
|
import type { PConnFieldProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
5
5
|
|
|
@@ -19,13 +19,13 @@ export default function Group(props: GroupProps) {
|
|
|
19
19
|
|
|
20
20
|
const content = useMemo(() => {
|
|
21
21
|
return (
|
|
22
|
-
<
|
|
22
|
+
<Grid2 container spacing={2}>
|
|
23
23
|
{children?.map(child => (
|
|
24
|
-
<
|
|
24
|
+
<Grid2 size={{ xs: 12 }} key={child.key}>
|
|
25
25
|
{child}
|
|
26
|
-
</
|
|
26
|
+
</Grid2>
|
|
27
27
|
))}
|
|
28
|
-
</
|
|
28
|
+
</Grid2>
|
|
29
29
|
);
|
|
30
30
|
}, [children, type, isReadOnly]);
|
|
31
31
|
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { useEffect, useState, useCallback, useRef } from 'react';
|
|
2
|
+
import { Box, TextField, Alert } from '@mui/material';
|
|
3
|
+
import AddLocationAltIcon from '@mui/icons-material/AddLocationAlt';
|
|
4
|
+
import InputAdornment from '@mui/material/InputAdornment';
|
|
5
|
+
import IconButton from '@mui/material/IconButton';
|
|
6
|
+
import { GoogleMap, Marker, useLoadScript } from '@react-google-maps/api';
|
|
7
|
+
import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
|
|
8
|
+
import type { PConnFieldProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
9
|
+
import handleEvent from '@pega/react-sdk-components/lib/components/helpers/event-utils';
|
|
10
|
+
|
|
11
|
+
interface LocationProps extends PConnFieldProps {
|
|
12
|
+
coordinates?: string;
|
|
13
|
+
onlyCoordinates?: boolean;
|
|
14
|
+
showMap?: boolean;
|
|
15
|
+
showMapReadOnly?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const mapContainerStyle = {
|
|
19
|
+
width: '100%',
|
|
20
|
+
height: '300px',
|
|
21
|
+
marginTop: '0px'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const defaultCenter = {
|
|
25
|
+
lat: 18.5204,
|
|
26
|
+
lng: 73.8567
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const disabledMapOptions = {
|
|
30
|
+
gestureHandling: 'none',
|
|
31
|
+
keyboardShortcuts: false,
|
|
32
|
+
disableDefaultUI: true,
|
|
33
|
+
clickableIcons: false,
|
|
34
|
+
zoomControl: false,
|
|
35
|
+
mapTypeControl: false,
|
|
36
|
+
scaleControl: false,
|
|
37
|
+
streetViewControl: false,
|
|
38
|
+
rotateControl: false,
|
|
39
|
+
fullscreenControl: false
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default function Location(props: LocationProps) {
|
|
43
|
+
const TextInput = getComponentFromMap('TextInput');
|
|
44
|
+
const FieldValueList = getComponentFromMap('FieldValueList');
|
|
45
|
+
|
|
46
|
+
const {
|
|
47
|
+
getPConnect,
|
|
48
|
+
label,
|
|
49
|
+
required = false,
|
|
50
|
+
disabled = false,
|
|
51
|
+
value = '',
|
|
52
|
+
validatemessage,
|
|
53
|
+
status,
|
|
54
|
+
readOnly = false,
|
|
55
|
+
testId,
|
|
56
|
+
displayMode,
|
|
57
|
+
hideLabel = false,
|
|
58
|
+
placeholder,
|
|
59
|
+
helperText,
|
|
60
|
+
coordinates = '',
|
|
61
|
+
onlyCoordinates = false,
|
|
62
|
+
showMap,
|
|
63
|
+
showMapReadOnly
|
|
64
|
+
} = props;
|
|
65
|
+
|
|
66
|
+
const pConn = getPConnect();
|
|
67
|
+
const actions = pConn.getActionsApi();
|
|
68
|
+
const propName = (pConn.getStateProps() as any).value;
|
|
69
|
+
const coordPropName = (pConn.getStateProps() as any).coordinates;
|
|
70
|
+
|
|
71
|
+
const [inputValue, setInputValue] = useState<string>(value ?? '');
|
|
72
|
+
const [mapCenter, setMapCenter] = useState(defaultCenter);
|
|
73
|
+
const [markerPosition, setMarkerPosition] = useState<google.maps.LatLngLiteral | null>(null);
|
|
74
|
+
|
|
75
|
+
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
76
|
+
const autocompleteRef = useRef<google.maps.places.Autocomplete | null>(null);
|
|
77
|
+
|
|
78
|
+
const { isLoaded } = useLoadScript({
|
|
79
|
+
googleMapsApiKey: pConn.getGoogleMapsAPIKey?.() || '',
|
|
80
|
+
libraries: ['places', 'geocoding']
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const hasError = status === 'error' && !!validatemessage && !disabled;
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (onlyCoordinates && coordinates) {
|
|
87
|
+
setInputValue(coordinates);
|
|
88
|
+
} else {
|
|
89
|
+
setInputValue(value ?? '');
|
|
90
|
+
}
|
|
91
|
+
if (coordinates) {
|
|
92
|
+
const [lat, lng] = coordinates.split(',').map(parseFloat);
|
|
93
|
+
|
|
94
|
+
if (!isNaN(lat) && !isNaN(lng)) {
|
|
95
|
+
setMapCenter({ lat, lng });
|
|
96
|
+
setMarkerPosition({ lat, lng });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}, [value, coordinates, onlyCoordinates]);
|
|
100
|
+
|
|
101
|
+
const handleChange = useCallback(
|
|
102
|
+
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
103
|
+
const newValue = event.target.value ?? '';
|
|
104
|
+
setInputValue(newValue);
|
|
105
|
+
handleEvent(actions, 'changeNblur', propName, newValue);
|
|
106
|
+
|
|
107
|
+
if (newValue === '' && coordPropName) {
|
|
108
|
+
actions.updateFieldValue(coordPropName, '');
|
|
109
|
+
setMarkerPosition(null);
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
[actions, propName, coordPropName]
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const handlePlaceChanged = useCallback(() => {
|
|
116
|
+
if (autocompleteRef.current) {
|
|
117
|
+
const place = autocompleteRef.current.getPlace();
|
|
118
|
+
if (place.geometry?.location) {
|
|
119
|
+
const lat = place.geometry.location.lat();
|
|
120
|
+
const lng = place.geometry.location.lng();
|
|
121
|
+
const address = place.formatted_address || place.name || '';
|
|
122
|
+
const coordinateString = `${lat}, ${lng}`;
|
|
123
|
+
|
|
124
|
+
setMapCenter({ lat, lng });
|
|
125
|
+
setMarkerPosition({ lat, lng });
|
|
126
|
+
|
|
127
|
+
if (onlyCoordinates) {
|
|
128
|
+
setInputValue(coordinateString);
|
|
129
|
+
handleEvent(actions, 'changeNblur', propName, coordinateString);
|
|
130
|
+
if (coordPropName) {
|
|
131
|
+
actions.updateFieldValue(coordPropName, coordinateString);
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
setInputValue(address);
|
|
135
|
+
handleEvent(actions, 'changeNblur', propName, address);
|
|
136
|
+
if (coordPropName) {
|
|
137
|
+
actions.updateFieldValue(coordPropName, coordinateString);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}, [actions, propName, coordPropName, onlyCoordinates]);
|
|
143
|
+
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
if (isLoaded && inputRef.current && !autocompleteRef.current) {
|
|
146
|
+
autocompleteRef.current = new google.maps.places.Autocomplete(inputRef.current);
|
|
147
|
+
autocompleteRef.current.addListener('place_changed', handlePlaceChanged);
|
|
148
|
+
}
|
|
149
|
+
}, [isLoaded, handlePlaceChanged]);
|
|
150
|
+
|
|
151
|
+
const handleGetCurrentLocation = useCallback(() => {
|
|
152
|
+
if (navigator.geolocation) {
|
|
153
|
+
navigator.geolocation.getCurrentPosition(
|
|
154
|
+
position => {
|
|
155
|
+
const lat = position.coords.latitude;
|
|
156
|
+
const lng = position.coords.longitude;
|
|
157
|
+
const coordinateString = `${lat}, ${lng}`;
|
|
158
|
+
|
|
159
|
+
setMapCenter({ lat, lng });
|
|
160
|
+
setMarkerPosition({ lat, lng });
|
|
161
|
+
|
|
162
|
+
if (onlyCoordinates) {
|
|
163
|
+
setInputValue(coordinateString);
|
|
164
|
+
handleEvent(actions, 'changeNblur', propName, coordinateString);
|
|
165
|
+
if (coordPropName) {
|
|
166
|
+
actions.updateFieldValue(coordPropName, coordinateString);
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
const geocoder = new window.google.maps.Geocoder();
|
|
170
|
+
geocoder.geocode({ location: { lat, lng } }, (results, responseStatus) => {
|
|
171
|
+
if (responseStatus === 'OK' && results && results[0]) {
|
|
172
|
+
const address = results[0].formatted_address;
|
|
173
|
+
setInputValue(address);
|
|
174
|
+
handleEvent(actions, 'changeNblur', propName, address);
|
|
175
|
+
if (coordPropName) {
|
|
176
|
+
actions.updateFieldValue(coordPropName, coordinateString);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
error => {
|
|
183
|
+
console.error('Error getting current location: ', error);
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}, [actions, propName, coordPropName, onlyCoordinates]);
|
|
188
|
+
|
|
189
|
+
if (displayMode === 'DISPLAY_ONLY') {
|
|
190
|
+
return <FieldValueList name={hideLabel ? '' : label} value={value} />;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (displayMode === 'STACKED_LARGE_VAL') {
|
|
194
|
+
return <FieldValueList name={hideLabel ? '' : label} value={value} variant='stacked' />;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const map = (
|
|
198
|
+
<div style={{ opacity: disabled ? 0.7 : 1 }}>
|
|
199
|
+
<Box mt={1} style={{ flex: 1 }}>
|
|
200
|
+
<GoogleMap mapContainerStyle={mapContainerStyle} center={mapCenter} zoom={14} options={disabled ? disabledMapOptions : undefined}>
|
|
201
|
+
{markerPosition && <Marker position={markerPosition} />}
|
|
202
|
+
</GoogleMap>
|
|
203
|
+
</Box>
|
|
204
|
+
</div>
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
if (readOnly) {
|
|
208
|
+
return (
|
|
209
|
+
<div>
|
|
210
|
+
<TextInput {...props} />
|
|
211
|
+
{isLoaded && showMapReadOnly && map}
|
|
212
|
+
</div>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const testProps: any = { 'data-test-id': testId };
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<div>
|
|
220
|
+
{hasError && (
|
|
221
|
+
<Alert severity='error' sx={{ mb: 1 }}>
|
|
222
|
+
{validatemessage}
|
|
223
|
+
</Alert>
|
|
224
|
+
)}
|
|
225
|
+
|
|
226
|
+
{isLoaded && (
|
|
227
|
+
<TextField
|
|
228
|
+
fullWidth
|
|
229
|
+
label={hideLabel ? '' : label}
|
|
230
|
+
required={required}
|
|
231
|
+
disabled={disabled}
|
|
232
|
+
error={hasError}
|
|
233
|
+
placeholder={placeholder ?? 'Search location'}
|
|
234
|
+
helperText={helperText}
|
|
235
|
+
value={inputValue}
|
|
236
|
+
onChange={handleChange}
|
|
237
|
+
inputRef={inputRef}
|
|
238
|
+
slotProps={{
|
|
239
|
+
input: {
|
|
240
|
+
endAdornment: (
|
|
241
|
+
<InputAdornment position='end'>
|
|
242
|
+
<IconButton onClick={handleGetCurrentLocation} disabled={disabled} edge='end'>
|
|
243
|
+
<AddLocationAltIcon />
|
|
244
|
+
</IconButton>
|
|
245
|
+
</InputAdornment>
|
|
246
|
+
),
|
|
247
|
+
inputProps: { ...testProps }
|
|
248
|
+
}
|
|
249
|
+
}}
|
|
250
|
+
/>
|
|
251
|
+
)}
|
|
252
|
+
|
|
253
|
+
{isLoaded && showMap && map}
|
|
254
|
+
</div>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Location';
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import Grid2 from '@mui/material/Grid2';
|
|
4
|
+
|
|
5
|
+
import { SELECTION_MODE, generateColumns, getDataRelationshipContextFromKey } from './utils';
|
|
6
|
+
import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
|
|
7
|
+
import type { PConnFieldProps } from '@pega/react-sdk-components/lib/types/PConnProps';
|
|
8
|
+
|
|
9
|
+
interface ObjectReferenceProps extends Omit<PConnFieldProps, 'value'> {
|
|
10
|
+
// If any, enter additional props that only exist on ObjectReference here
|
|
11
|
+
getPConnect: any;
|
|
12
|
+
displayMode;
|
|
13
|
+
allowAndPersistChangesInReviewMode: any;
|
|
14
|
+
targetObjectType: any;
|
|
15
|
+
mode: string;
|
|
16
|
+
parameters: object;
|
|
17
|
+
hideLabel: boolean;
|
|
18
|
+
inline: boolean;
|
|
19
|
+
showPromotedFilters: boolean;
|
|
20
|
+
additionalFields: any;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default function ObjectReference(props: ObjectReferenceProps) {
|
|
24
|
+
const {
|
|
25
|
+
getPConnect,
|
|
26
|
+
displayMode,
|
|
27
|
+
allowAndPersistChangesInReviewMode: editableInReview = false,
|
|
28
|
+
targetObjectType,
|
|
29
|
+
mode = '',
|
|
30
|
+
parameters,
|
|
31
|
+
hideLabel = false,
|
|
32
|
+
inline = false,
|
|
33
|
+
showPromotedFilters = false,
|
|
34
|
+
additionalFields
|
|
35
|
+
} = props;
|
|
36
|
+
|
|
37
|
+
const SingleReferenceReadonly = getComponentFromMap('SingleReferenceReadOnly');
|
|
38
|
+
|
|
39
|
+
// Configs
|
|
40
|
+
const pConn = getPConnect();
|
|
41
|
+
const referenceType = targetObjectType === 'case' ? 'Case' : 'Data';
|
|
42
|
+
const rawViewMetadata = pConn.getRawMetadata();
|
|
43
|
+
const refFieldMetadata = pConn.getFieldMetadata(rawViewMetadata?.config?.value?.split('.', 2)[1]);
|
|
44
|
+
|
|
45
|
+
// Destructured properties
|
|
46
|
+
const propsToUse = { ...pConn.getInheritedProps(), ...props };
|
|
47
|
+
|
|
48
|
+
// Computed variables
|
|
49
|
+
const isDisplayModeEnabled = displayMode === 'DISPLAY_ONLY';
|
|
50
|
+
const canBeChangedInReviewMode = editableInReview && ['Autocomplete', 'Dropdown'].includes(rawViewMetadata.config.componentType);
|
|
51
|
+
|
|
52
|
+
// Editable first child on change handler
|
|
53
|
+
const onRecordChange = event => {
|
|
54
|
+
const caseKey = pConn.getCaseInfo().getKey();
|
|
55
|
+
const refreshOptions = { autoDetectRefresh: true, propertyName: '' };
|
|
56
|
+
refreshOptions.propertyName = rawViewMetadata.config?.value;
|
|
57
|
+
|
|
58
|
+
if (!canBeChangedInReviewMode || !pConn.getValue('__currentPageTabViewName')) {
|
|
59
|
+
const pgRef = pConn.getPageReference().replace('caseInfo.content', '');
|
|
60
|
+
const viewName = rawViewMetadata.name;
|
|
61
|
+
if (viewName && viewName.length > 0) {
|
|
62
|
+
getPConnect().getActionsApi().refreshCaseView(caseKey, viewName, pgRef, refreshOptions);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// AutoComplete sets value on event.id whereas Dropdown sets it on event.target.value if event.id is unset
|
|
67
|
+
// When value is empty propValue will be undefined here and no value will be set for the reference
|
|
68
|
+
const propValue = event?.id || event?.target?.value;
|
|
69
|
+
const propName =
|
|
70
|
+
rawViewMetadata.type === 'SimpleTableSelect' && mode === SELECTION_MODE.MULTI
|
|
71
|
+
? PCore.getAnnotationUtils().getPropertyName(rawViewMetadata.config.selectionList)
|
|
72
|
+
: PCore.getAnnotationUtils().getPropertyName(rawViewMetadata.config?.value);
|
|
73
|
+
|
|
74
|
+
if (propValue && canBeChangedInReviewMode && isDisplayModeEnabled) {
|
|
75
|
+
PCore.getCaseUtils()
|
|
76
|
+
.getCaseEditLock(caseKey, '')
|
|
77
|
+
.then(caseResponse => {
|
|
78
|
+
const pageTokens = pConn.getPageReference().replace('caseInfo.content', '').split('.');
|
|
79
|
+
let curr = {};
|
|
80
|
+
const commitData = curr;
|
|
81
|
+
|
|
82
|
+
pageTokens.forEach(el => {
|
|
83
|
+
if (el !== '') {
|
|
84
|
+
curr[el] = {};
|
|
85
|
+
curr = curr[el];
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// expecting format like {Customer: {pyID:"C-100"}}
|
|
90
|
+
const propArr = propName.split('.');
|
|
91
|
+
propArr.forEach((element, idx) => {
|
|
92
|
+
if (idx + 1 === propArr.length) {
|
|
93
|
+
curr[element] = propValue;
|
|
94
|
+
} else {
|
|
95
|
+
curr[element] = {};
|
|
96
|
+
curr = curr[element];
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
PCore.getCaseUtils()
|
|
101
|
+
.updateCaseEditFieldsData(caseKey, { [caseKey]: commitData }, caseResponse.headers.etag, pConn.getContextName())
|
|
102
|
+
.then(response => {
|
|
103
|
+
PCore.getContainerUtils().updateParentLastUpdateTime(pConn.getContextName(), (response.data as any).data.caseInfo.lastUpdateTime);
|
|
104
|
+
PCore.getContainerUtils().updateRelatedContextEtag(pConn.getContextName(), response.headers.etag);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Prepare first child
|
|
111
|
+
const recreatedFirstChild = useMemo(() => {
|
|
112
|
+
const type = rawViewMetadata.config.componentType;
|
|
113
|
+
|
|
114
|
+
/* Read-only variants */
|
|
115
|
+
if (type === 'SemanticLink' && !canBeChangedInReviewMode) {
|
|
116
|
+
const config = {
|
|
117
|
+
...rawViewMetadata.config,
|
|
118
|
+
primaryField: rawViewMetadata.config.displayField
|
|
119
|
+
};
|
|
120
|
+
config.caseClass = rawViewMetadata.config.targetObjectClass;
|
|
121
|
+
config.text = config.primaryField;
|
|
122
|
+
config.caseID = config.value;
|
|
123
|
+
config.contextPage = `@P .${
|
|
124
|
+
rawViewMetadata.config?.displayField ? getDataRelationshipContextFromKey(rawViewMetadata.config.displayField) : null
|
|
125
|
+
}`;
|
|
126
|
+
config.resourceParams = {
|
|
127
|
+
workID: config.value
|
|
128
|
+
};
|
|
129
|
+
config.resourcePayload = {
|
|
130
|
+
caseClassName: config.caseClass
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return getPConnect().createComponent({
|
|
134
|
+
type: 'SemanticLink',
|
|
135
|
+
config: {
|
|
136
|
+
...config,
|
|
137
|
+
displayMode,
|
|
138
|
+
referenceType,
|
|
139
|
+
hideLabel,
|
|
140
|
+
dataRelationshipContext: rawViewMetadata.config?.displayField
|
|
141
|
+
? getDataRelationshipContextFromKey(rawViewMetadata.config.displayField)
|
|
142
|
+
: null
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (isDisplayModeEnabled && !canBeChangedInReviewMode) {
|
|
147
|
+
return (
|
|
148
|
+
<SingleReferenceReadonly
|
|
149
|
+
config={{
|
|
150
|
+
...rawViewMetadata.config,
|
|
151
|
+
primaryField: rawViewMetadata.config.displayField
|
|
152
|
+
}}
|
|
153
|
+
getPConnect={getPConnect}
|
|
154
|
+
label={propsToUse.label}
|
|
155
|
+
type={type}
|
|
156
|
+
displayAs='readonly'
|
|
157
|
+
displayMode={displayMode}
|
|
158
|
+
activeViewRuleClass={rawViewMetadata.config.targetObjectClass} // for older views which may not have context class set, fall back to previous behavior
|
|
159
|
+
referenceType={referenceType}
|
|
160
|
+
hideLabel={hideLabel}
|
|
161
|
+
dataRelationshipContext={
|
|
162
|
+
rawViewMetadata.config?.displayField ? getDataRelationshipContextFromKey(rawViewMetadata.config.displayField) : null
|
|
163
|
+
}
|
|
164
|
+
additionalFields={additionalFields}
|
|
165
|
+
/>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// 1) Set datasource
|
|
170
|
+
generateColumns(rawViewMetadata.config, pConn, referenceType);
|
|
171
|
+
rawViewMetadata.config.deferDatasource = true;
|
|
172
|
+
rawViewMetadata.config.listType = 'datapage';
|
|
173
|
+
if (['Dropdown', 'AutoComplete'].includes(type) && !rawViewMetadata.config.placeholder) {
|
|
174
|
+
rawViewMetadata.config.placeholder = '@L Select...';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 2) Pass through configs
|
|
178
|
+
rawViewMetadata.config.showPromotedFilters = showPromotedFilters;
|
|
179
|
+
|
|
180
|
+
if (!canBeChangedInReviewMode) {
|
|
181
|
+
rawViewMetadata.config.displayMode = displayMode;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 3) Define field meta
|
|
185
|
+
let fieldMetaData: any = null;
|
|
186
|
+
|
|
187
|
+
fieldMetaData = {
|
|
188
|
+
datasourceMetadata: {
|
|
189
|
+
datasource: {
|
|
190
|
+
parameters: {}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
if (rawViewMetadata.config?.parameters) {
|
|
195
|
+
fieldMetaData.datasourceMetadata.datasource.parameters = parameters;
|
|
196
|
+
}
|
|
197
|
+
fieldMetaData.datasourceMetadata.datasource.propertyForDisplayText = rawViewMetadata?.config?.datasource?.fields?.text.startsWith('@P')
|
|
198
|
+
? rawViewMetadata?.config?.datasource?.fields?.text?.substring(3)
|
|
199
|
+
: rawViewMetadata?.config?.datasource?.fields?.text;
|
|
200
|
+
fieldMetaData.datasourceMetadata.datasource.propertyForValue = rawViewMetadata?.config?.datasource?.fields?.value.startsWith('@P')
|
|
201
|
+
? rawViewMetadata?.config?.datasource?.fields?.value?.substring(3)
|
|
202
|
+
: rawViewMetadata?.config?.datasource?.fields?.value;
|
|
203
|
+
fieldMetaData.datasourceMetadata.datasource.name = rawViewMetadata.config?.referenceList;
|
|
204
|
+
|
|
205
|
+
return getPConnect().createComponent({
|
|
206
|
+
type,
|
|
207
|
+
config: {
|
|
208
|
+
...rawViewMetadata.config,
|
|
209
|
+
descriptors: mode === SELECTION_MODE.SINGLE ? refFieldMetadata?.descriptors : null,
|
|
210
|
+
datasourceMetadata: fieldMetaData?.datasourceMetadata,
|
|
211
|
+
required: propsToUse.required,
|
|
212
|
+
visibility: propsToUse.visibility,
|
|
213
|
+
disabled: propsToUse.disabled,
|
|
214
|
+
label: propsToUse.label,
|
|
215
|
+
parameters: rawViewMetadata.config.parameters,
|
|
216
|
+
readOnly: false,
|
|
217
|
+
localeReference: rawViewMetadata.config.localeReference,
|
|
218
|
+
...(mode === SELECTION_MODE.SINGLE ? { referenceType } : ''),
|
|
219
|
+
contextClass: rawViewMetadata.config.targetObjectClass,
|
|
220
|
+
primaryField: rawViewMetadata.config?.displayField,
|
|
221
|
+
dataRelationshipContext: rawViewMetadata.config?.displayField ? getDataRelationshipContextFromKey(rawViewMetadata.config.displayField) : null,
|
|
222
|
+
hideLabel,
|
|
223
|
+
onRecordChange,
|
|
224
|
+
inline
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}, [rawViewMetadata.config?.datasource?.source, parameters, propsToUse.required, propsToUse.disabled, getPConnect().getPageReference()]);
|
|
228
|
+
|
|
229
|
+
// Prepare children to render
|
|
230
|
+
return (
|
|
231
|
+
<Grid2 container>
|
|
232
|
+
<Grid2>{recreatedFirstChild}</Grid2>
|
|
233
|
+
</Grid2>
|
|
234
|
+
);
|
|
235
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './ObjectReference';
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Utils } from '@pega/react-sdk-components/lib/components/helpers/utils';
|
|
2
|
+
|
|
3
|
+
export const SELECTION_MODE = { SINGLE: 'single', MULTI: 'multi' };
|
|
4
|
+
|
|
5
|
+
const getLeafNameFromPropertyName = property => property?.substr(property.lastIndexOf('.'));
|
|
6
|
+
|
|
7
|
+
const isSelfReferencedProperty = (param, referenceProp) => param === referenceProp?.split('.', 2)[1];
|
|
8
|
+
|
|
9
|
+
export const AT_FILTEREDLIST = '@FILTERED_LIST';
|
|
10
|
+
export const AT_PROPERTY = '@P';
|
|
11
|
+
export const SQUARE_BRACKET_START = '[';
|
|
12
|
+
export const SQUARE_BRACKET_END = ']';
|
|
13
|
+
|
|
14
|
+
export const SIMPLE_TABLE_MANUAL_READONLY = 'SimpleTableManualReadOnly';
|
|
15
|
+
export const PAGE = '!P!';
|
|
16
|
+
export const PAGELIST = '!PL!';
|
|
17
|
+
export const PERIOD = '.';
|
|
18
|
+
const AT = '@';
|
|
19
|
+
|
|
20
|
+
export function updatePageListPropertyValue(value) {
|
|
21
|
+
value = value.substring(0, value.indexOf(SQUARE_BRACKET_START)) + value.substring(value.indexOf(SQUARE_BRACKET_END) + 1);
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getPropertyValue(value) {
|
|
26
|
+
if (value.startsWith(AT)) {
|
|
27
|
+
value = value.substring(value.indexOf(' ') + 1);
|
|
28
|
+
if (value.startsWith(PERIOD)) value = value.substring(1);
|
|
29
|
+
}
|
|
30
|
+
if (value.includes(SQUARE_BRACKET_START)) {
|
|
31
|
+
value = updatePageListPropertyValue(value);
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const getCompositeKeys = (c11nEnv, property) => {
|
|
37
|
+
const { datasource: { parameters = {} } = {} } = c11nEnv.getFieldMetadata(property) || {};
|
|
38
|
+
return Object.values(parameters).reduce((compositeKeys: any, param) => {
|
|
39
|
+
if (isSelfReferencedProperty(property, param)) {
|
|
40
|
+
let propName = getPropertyValue(param);
|
|
41
|
+
propName = propName.substring(propName.indexOf('.'));
|
|
42
|
+
compositeKeys.push(propName);
|
|
43
|
+
}
|
|
44
|
+
return compositeKeys;
|
|
45
|
+
}, []);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const generateColumns = (config, pConn, referenceType) => {
|
|
49
|
+
const displayField = getLeafNameFromPropertyName(config.displayField);
|
|
50
|
+
const referenceProp = config.value.split('.', 2)[1];
|
|
51
|
+
const compositeKeys: any = getCompositeKeys(pConn, referenceProp);
|
|
52
|
+
let value = getLeafNameFromPropertyName(config.value);
|
|
53
|
+
|
|
54
|
+
const columns: any = [];
|
|
55
|
+
if (displayField) {
|
|
56
|
+
columns.push({
|
|
57
|
+
value: displayField,
|
|
58
|
+
display: 'true',
|
|
59
|
+
useForSearch: true,
|
|
60
|
+
primary: 'true'
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (value && compositeKeys.indexOf(value) !== -1) {
|
|
64
|
+
columns.push({
|
|
65
|
+
value,
|
|
66
|
+
setProperty: 'Associated property',
|
|
67
|
+
key: 'true'
|
|
68
|
+
});
|
|
69
|
+
} else {
|
|
70
|
+
const actualValue = compositeKeys.length > 0 ? compositeKeys[0] : value;
|
|
71
|
+
config.value = `@P .${referenceProp}${actualValue}`;
|
|
72
|
+
value = actualValue;
|
|
73
|
+
columns.push({
|
|
74
|
+
value: actualValue,
|
|
75
|
+
setProperty: 'Associated property',
|
|
76
|
+
key: 'true'
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
config.datasource = {
|
|
81
|
+
fields: {
|
|
82
|
+
key: getLeafNameFromPropertyName(config.value),
|
|
83
|
+
text: getLeafNameFromPropertyName(config.displayField),
|
|
84
|
+
value: getLeafNameFromPropertyName(config.value)
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
if (referenceType === 'Case') {
|
|
89
|
+
columns.push({
|
|
90
|
+
secondary: 'true',
|
|
91
|
+
display: 'true',
|
|
92
|
+
value: Utils.getMappedKey('pyID'),
|
|
93
|
+
useForSearch: true
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
compositeKeys.forEach(key => {
|
|
98
|
+
if (value !== key)
|
|
99
|
+
columns.push({
|
|
100
|
+
value: key,
|
|
101
|
+
display: 'false',
|
|
102
|
+
secondary: 'true',
|
|
103
|
+
useForSearch: false,
|
|
104
|
+
setProperty: `.${referenceProp}${key}`
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
config.columns = columns;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const getDataRelationshipContextFromKey = key => key.split('.', 2)[1];
|