@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.
Files changed (103) hide show
  1. package/lib/designSystemExtension/Banner/Banner.css +1 -1
  2. package/lib/designSystemExtension/Banner/Banner.tsx +7 -7
  3. package/lib/designSystemExtension/CaseSummaryFields/CaseSummaryFields.tsx +8 -10
  4. package/lib/designSystemExtension/DetailsFields/DetailsFields.tsx +11 -13
  5. package/lib/designSystemExtension/FieldGroup/FieldGroup.tsx +7 -8
  6. package/lib/designSystemExtension/FieldGroupList/FieldGroupList.tsx +9 -9
  7. package/lib/designSystemExtension/FieldValueList/FieldValueList.tsx +7 -8
  8. package/lib/designSystemExtension/Operator/Operator.tsx +11 -12
  9. package/lib/designSystemExtension/RichTextEditor/RichTextEditor.tsx +28 -3
  10. package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.css +4 -4
  11. package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.tsx +1 -1
  12. package/lib/field/CancelAlert/CancelAlert.css +4 -4
  13. package/lib/field/CancelAlert/CancelAlert.tsx +5 -5
  14. package/lib/field/Checkbox/Checkbox.tsx +96 -3
  15. package/lib/field/Currency/currency-utils.ts +1 -2
  16. package/lib/field/Dropdown/Dropdown.tsx +0 -2
  17. package/lib/field/Group/Group.tsx +5 -5
  18. package/lib/field/Location/Location.tsx +256 -0
  19. package/lib/field/Location/config-ext.json +8 -0
  20. package/lib/field/Location/index.tsx +1 -0
  21. package/lib/field/ObjectReference/ObjectReference.tsx +235 -0
  22. package/lib/field/ObjectReference/index.tsx +1 -0
  23. package/lib/field/ObjectReference/utils.ts +111 -0
  24. package/lib/field/RadioButtons/RadioButtons.tsx +46 -1
  25. package/lib/field/ScalarList/ScalarList.tsx +1 -2
  26. package/lib/field/SelectableCard/SelectableCard.tsx +175 -0
  27. package/lib/field/SelectableCard/index.tsx +1 -0
  28. package/lib/field/SelectableCard/utils.tsx +226 -0
  29. package/lib/field/SemanticLink/SemanticLink.tsx +159 -27
  30. package/lib/field/SemanticLink/utils.ts +1 -1
  31. package/lib/field/TextContent/TextContent.tsx +0 -1
  32. package/lib/field/UserReference/UserReference.tsx +0 -1
  33. package/lib/helpers/attachmentHelpers.ts +56 -35
  34. package/lib/helpers/common-utils.ts +2 -2
  35. package/lib/helpers/data_page.ts +0 -1
  36. package/lib/helpers/formatters/CurrencyMap.ts +0 -2
  37. package/lib/helpers/simpleTableHelpers.ts +117 -5
  38. package/lib/helpers/utils.ts +8 -1
  39. package/lib/helpers/versionHelpers.ts +0 -1
  40. package/lib/infra/ActionButtons/ActionButtons.tsx +28 -21
  41. package/lib/infra/Assignment/Assignment.tsx +2 -2
  42. package/lib/infra/Containers/FlowContainer/FlowContainer.tsx +14 -93
  43. package/lib/infra/Containers/ModalViewContainer/ListViewActionButtons/ListViewActionButtons.tsx +0 -1
  44. package/lib/infra/Containers/ModalViewContainer/ModalViewContainer.tsx +2 -2
  45. package/lib/infra/Containers/ViewContainer/ViewContainer.tsx +3 -4
  46. package/lib/infra/Containers/container-helpers.ts +47 -1
  47. package/lib/infra/DashboardFilter/DashboardFilter.tsx +0 -2
  48. package/lib/infra/DashboardFilter/filterUtils.tsx +3 -4
  49. package/lib/infra/DeferLoad/DeferLoad.tsx +1 -3
  50. package/lib/infra/ErrorBoundary/ErrorBoundary.tsx +0 -2
  51. package/lib/infra/MultiStep/MultiStep.css +8 -8
  52. package/lib/infra/NavBar/NavBar.css +1 -1
  53. package/lib/infra/NavBar/NavBar.tsx +3 -4
  54. package/lib/infra/Reference/Reference.tsx +2 -3
  55. package/lib/infra/RootContainer/RootContainer.tsx +0 -1
  56. package/lib/template/AdvancedSearch/AdvancedSearch.tsx +0 -1
  57. package/lib/template/AdvancedSearch/SearchGroup/persistUtils.ts +3 -9
  58. package/lib/template/AdvancedSearch/SearchGroups/SearchGroups.tsx +3 -4
  59. package/lib/template/AdvancedSearch/SearchGroups/hooks.ts +1 -1
  60. package/lib/template/AppShell/AppShell.css +1 -1
  61. package/lib/template/AppShell/AppShell.tsx +4 -8
  62. package/lib/template/CaseSummary/CaseSummary.tsx +0 -1
  63. package/lib/template/CaseView/CaseView.tsx +13 -19
  64. package/lib/template/Confirmation/Confirmation.tsx +0 -1
  65. package/lib/template/DataReference/DataReference.tsx +7 -10
  66. package/lib/template/DataReference/SearchForm.tsx +6 -5
  67. package/lib/template/DataReference/{utils.js → utils.ts} +3 -3
  68. package/lib/template/DefaultForm/DefaultForm.tsx +1 -1
  69. package/lib/template/Details/Details/Details.tsx +10 -10
  70. package/lib/template/Details/DetailsThreeColumn/DetailsThreeColumn.tsx +10 -10
  71. package/lib/template/Details/DetailsTwoColumn/DetailsTwoColumn.tsx +10 -10
  72. package/lib/template/FieldGroupTemplate/FieldGroupTemplate.tsx +1 -2
  73. package/lib/template/InlineDashboard/InlineDashboard.tsx +12 -14
  74. package/lib/template/ListView/ListView.tsx +8 -20
  75. package/lib/template/ListView/hooks.ts +1 -5
  76. package/lib/template/ListView/utils.ts +1 -1
  77. package/lib/template/NarrowWide/NarrowWide/NarrowWide.tsx +3 -3
  78. package/lib/template/NarrowWide/NarrowWideDetails/NarrowWideDetails.tsx +10 -10
  79. package/lib/template/OneColumn/OneColumn/OneColumn.tsx +5 -5
  80. package/lib/template/PromotedFilters/PromotedFilters.tsx +0 -1
  81. package/lib/template/SimpleTable/SimpleTable/SimpleTable.tsx +1 -2
  82. package/lib/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +33 -30
  83. package/lib/template/TwoColumn/TwoColumn/TwoColumn.tsx +1 -2
  84. package/lib/template/TwoColumn/TwoColumnTab/TwoColumnTab.tsx +1 -2
  85. package/lib/template/WideNarrow/WideNarrow/WideNarrow.tsx +3 -3
  86. package/lib/template/WideNarrow/WideNarrowDetails/WideNarrowDetails.tsx +10 -10
  87. package/lib/template/WssNavBar/WssNavBar.css +1 -1
  88. package/lib/template/WssNavBar/WssNavBar.tsx +4 -4
  89. package/lib/widget/Attachment/Attachment.css +6 -8
  90. package/lib/widget/Attachment/Attachment.tsx +61 -57
  91. package/lib/widget/CaseHistory/CaseHistory.tsx +3 -3
  92. package/lib/widget/FileUtility/ActionButtonsForFileUtil/ActionButtonsForFileUtil.css +0 -14
  93. package/lib/widget/FileUtility/ActionButtonsForFileUtil/ActionButtonsForFileUtil.tsx +2 -2
  94. package/lib/widget/FileUtility/FileUtility/FileUtility.css +7 -6
  95. package/lib/widget/FileUtility/FileUtility/FileUtility.tsx +4 -6
  96. package/lib/widget/Followers/Followers.tsx +0 -2
  97. package/lib/widget/QuickCreate/QuickCreate.tsx +0 -1
  98. package/lib/widget/SummaryItem/SummaryItem.css +9 -11
  99. package/lib/widget/SummaryItem/SummaryItem.tsx +1 -1
  100. package/lib/widget/ToDo/ToDo.css +1 -13
  101. package/lib/widget/ToDo/ToDo.tsx +15 -7
  102. package/package.json +1 -1
  103. /package/lib/template/DataReference/{DataReferenceAdvancedSearchContext.js → DataReferenceAdvancedSearchContext.ts} +0 -0
@@ -1,13 +1,11 @@
1
- import Typography from '@mui/material/Typography';
2
- import Grid from '@mui/material/Grid';
1
+ import { Link } from '@mui/material';
3
2
  import makeStyles from '@mui/styles/makeStyles';
4
3
 
5
- import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
6
4
  import type { PConnFieldProps } from '@pega/react-sdk-components/lib/types/PConnProps';
7
5
 
8
- /* although this is called the SemanticLink component, we are not yet displaying as a
9
- SemanticLink in SDK and only showing the value as a read only text field. */
6
+ import semanticUtils from './utils';
10
7
 
8
+ // eslint-disable-next-line
11
9
  const useStyles = makeStyles(theme => ({
12
10
  root: {
13
11
  paddingRight: theme.spacing(1),
@@ -41,36 +39,170 @@ const useStyles = makeStyles(theme => ({
41
39
 
42
40
  interface SemanticLinkProps extends PConnFieldProps {
43
41
  // If any, enter additional props that only exist on SemanticLink here
44
- // from previous PropTypes
45
42
  text: string;
43
+ resourcePayload: any;
44
+ resourceParams: any;
45
+ previewKey: string | null;
46
+ onClick: (event: any) => void;
47
+ testId: string;
48
+ referenceType: string | null;
49
+ dataRelationshipContext: string | null;
50
+ contextPage: any;
46
51
  }
47
52
 
48
53
  export default function SemanticLink(props: SemanticLinkProps) {
49
- // Get emitted components from map (so we can get any override that may exist)
50
- const FieldValueList = getComponentFromMap('FieldValueList');
54
+ const {
55
+ text,
56
+ resourcePayload = {},
57
+ resourceParams = {},
58
+ getPConnect,
59
+ previewKey,
60
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
61
+ onClick,
62
+ testId = '',
63
+ referenceType,
64
+ dataRelationshipContext = null,
65
+ contextPage,
66
+ ...restProps
67
+ } = props;
68
+ const { ACTION_OPENWORKBYHANDLE, ACTION_SHOWDATA }: any = PCore.getSemanticUrlUtils().getActions();
69
+ const pConnect = getPConnect();
70
+ const dataResourcePayLoad = resourcePayload?.resourceType === 'DATA' ? resourcePayload : null;
51
71
 
52
- const { text, displayMode, label, hideLabel } = props;
53
- const classes = useStyles();
72
+ const {
73
+ RESOURCE_TYPES: { DATA },
74
+ WORKCLASS,
75
+ CASE_INFO: { CASE_INFO_CLASSID }
76
+ } = PCore.getConstants();
54
77
 
55
- if (displayMode === 'DISPLAY_ONLY' || (!displayMode && label !== undefined)) {
56
- const value = text || '---';
57
- return (
58
- <Grid container spacing={1} style={{ padding: '4px 0px' }} id='semantic-link-grid'>
59
- <Grid item xs={6}>
60
- <Typography variant='body2' component='span' className={`${classes.fieldLabel} ${classes.fieldMargin}`}>
61
- {label}
62
- </Typography>
63
- </Grid>
64
- <Grid item xs={6}>
65
- <Typography variant='body2' component='span' className={classes.fieldValue}>
66
- {value}
67
- </Typography>
68
- </Grid>
69
- </Grid>
78
+ let linkURL = '';
79
+ let payload = {};
80
+ let dataViewName;
81
+ let linkComponentProps = {
82
+ href: linkURL
83
+ };
84
+ if (text) {
85
+ (linkComponentProps as any).href = linkURL;
86
+ }
87
+ let isData = false;
88
+ const shouldTreatAsDataReference = !previewKey && resourcePayload.caseClassName;
89
+ if (contextPage?.classID) {
90
+ resourcePayload.caseClassName = contextPage.classID;
91
+ }
92
+ /* TODO : In case of duplicate search case the classID is Work- need to set it to
93
+ the current case class ID */
94
+ if (resourcePayload.caseClassName === WORKCLASS) {
95
+ resourcePayload.caseClassName = pConnect.getValue(CASE_INFO_CLASSID);
96
+ }
97
+
98
+ function showDataAction() {
99
+ if (dataResourcePayLoad && dataResourcePayLoad.resourceType === 'DATA') {
100
+ const { content } = dataResourcePayLoad;
101
+ const lookUpDataPageInfo = PCore.getDataTypeUtils().getLookUpDataPageInfo(dataResourcePayLoad?.className);
102
+ const lookUpDataPage = PCore.getDataTypeUtils().getLookUpDataPage(dataResourcePayLoad?.className);
103
+ if (lookUpDataPageInfo) {
104
+ const { parameters }: any = lookUpDataPageInfo;
105
+ payload = Object.keys(parameters).reduce((acc, param) => {
106
+ const paramValue = parameters[param];
107
+ return {
108
+ ...acc,
109
+ [param]: PCore.getAnnotationUtils().isProperty(paramValue) ? content[PCore.getAnnotationUtils().getPropertyName(paramValue)] : paramValue
110
+ };
111
+ }, {});
112
+ }
113
+ getPConnect()
114
+ .getActionsApi()
115
+ .showData('pyDetails', lookUpDataPage, {
116
+ ...payload
117
+ });
118
+ }
119
+ if ((referenceType && referenceType.toUpperCase() === DATA) || shouldTreatAsDataReference) {
120
+ getPConnect()
121
+ .getActionsApi()
122
+ .showData('pyDetails', dataViewName, {
123
+ ...payload
124
+ });
125
+ }
126
+ }
127
+
128
+ function openLinkClick(e) {
129
+ if (!e.metaKey && !e.ctrlKey) {
130
+ e.preventDefault();
131
+ if (
132
+ (dataResourcePayLoad && dataResourcePayLoad.resourceType === 'DATA') ||
133
+ (referenceType && referenceType.toUpperCase() === DATA) ||
134
+ shouldTreatAsDataReference
135
+ ) {
136
+ showDataAction();
137
+ } else if (previewKey) {
138
+ getPConnect().getActionsApi().openWorkByHandle(previewKey, resourcePayload.caseClassName);
139
+ }
140
+ }
141
+ }
142
+
143
+ if ((referenceType && referenceType.toUpperCase() === DATA) || shouldTreatAsDataReference) {
144
+ try {
145
+ isData = true;
146
+ // @ts-expect-error
147
+ const dataRefContext = semanticUtils.getDataReferenceInfo(pConnect, dataRelationshipContext, contextPage);
148
+ dataViewName = dataRefContext.dataContext;
149
+ payload = dataRefContext.dataContextParameters as any;
150
+ } catch (error) {
151
+ console.log('Error in getting the data reference info', error);
152
+ }
153
+ } else if (resourcePayload && resourcePayload.resourceType === 'DATA') {
154
+ isData = true;
155
+ dataViewName = PCore.getDataTypeUtils().getLookUpDataPage(resourcePayload.className);
156
+ const lookUpDataPageInfo = PCore.getDataTypeUtils().getLookUpDataPageInfo(resourcePayload.className);
157
+ const { content } = resourcePayload;
158
+ if (lookUpDataPageInfo) {
159
+ const { parameters }: any = lookUpDataPageInfo;
160
+ payload = Object.keys(parameters).reduce((acc, param) => {
161
+ const paramValue = parameters[param];
162
+ return {
163
+ ...acc,
164
+ [param]: PCore.getAnnotationUtils().isProperty(paramValue) ? content[PCore.getAnnotationUtils().getPropertyName(paramValue)] : paramValue
165
+ };
166
+ }, {});
167
+ } else {
168
+ const keysInfo = PCore.getDataTypeUtils().getDataPageKeys(dataViewName) ?? [];
169
+ payload = keysInfo.reduce((acc, curr) => {
170
+ return {
171
+ ...acc,
172
+ [curr.keyName]: content[curr.isAlternateKeyStorage ? curr.linkedField : curr.keyName]
173
+ };
174
+ }, {});
175
+ }
176
+ }
177
+
178
+ if (isData && dataViewName && payload) {
179
+ linkURL = PCore.getSemanticUrlUtils().getResolvedSemanticURL(
180
+ ACTION_SHOWDATA,
181
+ { pageName: 'pyDetails', dataViewName },
182
+ {
183
+ ...payload
184
+ }
70
185
  );
186
+ } else {
187
+ // BUG-678282 fix to handle scenario when workID was not populated.
188
+ // Check renderParentLink in Caseview / CasePreview
189
+ resourceParams.objectID = resourceParams.workID === '' && typeof previewKey === 'string' ? previewKey.split(' ')[1] : resourceParams.workID;
190
+ if (previewKey) {
191
+ resourceParams.id = previewKey;
192
+ }
193
+ linkURL = PCore.getSemanticUrlUtils().getResolvedSemanticURL(ACTION_OPENWORKBYHANDLE, resourcePayload, resourceParams);
71
194
  }
72
195
 
73
- if (displayMode === 'STACKED_LARGE_VAL') {
74
- return <FieldValueList name={hideLabel ? '' : label} value={text} variant='stacked' />;
196
+ if (text) {
197
+ linkComponentProps = {
198
+ ...linkComponentProps,
199
+ href: linkURL
200
+ };
75
201
  }
202
+
203
+ return (
204
+ <Link component='button' {...linkComponentProps} {...restProps} onClick={openLinkClick} data-testid={testId}>
205
+ {text}
206
+ </Link>
207
+ );
76
208
  }
@@ -32,7 +32,7 @@ function getDataReferenceInfo(pConnect, dataRelationshipContext) {
32
32
  dataContext = name;
33
33
  for (const [key, value] of Object.entries(parameters)) {
34
34
  const property =
35
- // @ts-ignore - Property 'getLeafPropertyName' is private and only accessible within class 'AnnotationUtils'
35
+ // @ts-expect-error - Property 'getLeafPropertyName' is private and only accessible within class 'AnnotationUtils'
36
36
  dataRelationshipContext !== null ? annotationUtils.getPropertyName(value as string) : annotationUtils.getLeafPropertyName(value);
37
37
  payload[key] = pConnect.getValue(`.${property}`);
38
38
  }
@@ -38,7 +38,6 @@ export default function TextContent(props: TextContentProps) {
38
38
  break;
39
39
 
40
40
  default:
41
- // eslint-disable-next-line no-console
42
41
  console.error(`TextContent got an expected displayAs prop: ${displayAs}`);
43
42
  break;
44
43
  }
@@ -89,7 +89,6 @@ const UserReference = (props: UserReferenceProps) => {
89
89
  setDropDownDataSource(ddDataSource);
90
90
  })
91
91
  .catch(err => {
92
- // eslint-disable-next-line no-console
93
92
  console.error(err);
94
93
  });
95
94
  }
@@ -1,20 +1,67 @@
1
+ import { useCallback } from 'react';
1
2
  import download from 'downloadjs';
2
3
 
3
- export const validateMaxSize = (fileObj: any, maxSizeInMB: string): boolean => {
4
- const fileSize = (fileObj.size / 1048576).toFixed(2);
5
- return parseFloat(fileSize) < parseFloat(maxSizeInMB);
4
+ export const isContentBinary = headers => {
5
+ return headers && headers['content-transfer-encoding'] === 'binary';
6
6
  };
7
7
 
8
- export const fileDownload = (data, fileName, ext) => {
8
+ export const isContentBase64 = headers => {
9
+ return headers && headers['content-transfer-encoding'] === 'base64';
10
+ };
11
+
12
+ export const fileDownload = (data, fileName, ext, headers) => {
9
13
  const name = ext ? `${fileName}.${ext}` : fileName;
10
14
  // Temp fix: downloading EMAIl type attachment as html file
11
15
  if (ext === 'html') {
12
- download(data, name, 'text/html');
16
+ download(isContentBase64(headers) ? atob(data) : data, name, 'text/html');
17
+ } else if (isContentBinary(headers)) {
18
+ download(data, name);
13
19
  } else {
14
20
  download(atob(data), name);
15
21
  }
16
22
  };
17
23
 
24
+ export const fileDownloadVar = (content, type, name, extension) => {
25
+ if (type === 'FILE' || type === undefined) {
26
+ fileDownload(content.data, name, extension, content.headers);
27
+ } else if (type === 'URL') {
28
+ let { data } = content;
29
+ if (!/^(http|https):\/\//.test(data)) {
30
+ data = `//${data}`;
31
+ }
32
+ window.open(content.data, '_blank');
33
+ } else if (type === 'EMAIL') {
34
+ // Temp Fix: for EMAIL type attachment
35
+ fileDownload(content.data, name, 'html', content.headers);
36
+ }
37
+ };
38
+
39
+ export const useFileDownload = context => {
40
+ return useCallback(
41
+ ({ ID, name, extension, type, category, responseType }) => {
42
+ if (category !== 'pxDocument') {
43
+ PCore.getAttachmentUtils()
44
+ .downloadAttachment(ID, context, responseType)
45
+ .then(content => {
46
+ fileDownloadVar(content, type, name, extension);
47
+ })
48
+
49
+ .catch(console.error);
50
+ } else {
51
+ PCore.getAttachmentUtils()
52
+ // @ts-expect-error
53
+ .downloadDocument(ID, context, responseType)
54
+ .then(content => {
55
+ fileDownloadVar(content, type, name, extension);
56
+ })
57
+
58
+ .catch(console.error);
59
+ }
60
+ },
61
+ [context]
62
+ );
63
+ };
64
+
18
65
  export const getIconFromFileType = (fileType): string => {
19
66
  let icon = 'document-doc';
20
67
  if (!fileType) return icon;
@@ -42,35 +89,9 @@ export const getIconFromFileType = (fileType): string => {
42
89
  return icon;
43
90
  };
44
91
 
45
- export const getIconForAttachment = (inThis: any, attachment: any): string => {
46
- let icon;
47
- switch (attachment.type) {
48
- case 'FILE':
49
- icon = inThis.getIconFromFileType(attachment.mimeType);
50
- break;
51
- case 'URL':
52
- icon = 'chain';
53
- break;
54
- default:
55
- icon = 'document-doc';
56
- }
57
- return icon;
92
+ export const validateMaxSize = (fileObj: any, maxSizeInMB: string): boolean => {
93
+ const fileSize = (fileObj.size / 1048576).toFixed(2);
94
+ return parseFloat(fileSize) < parseFloat(maxSizeInMB);
58
95
  };
59
96
 
60
- export const buildFilePropsFromResponse = (
61
- respObj
62
- ): {
63
- props: { meta: string; name: string; icon: string };
64
- responseProps: any;
65
- } => {
66
- return {
67
- props: {
68
- meta: `${respObj.pyCategoryName}, ${respObj.pxCreateOperator}`,
69
- name: respObj.pyAttachName,
70
- icon: getIconFromFileType(respObj.pyMimeFileExtension)
71
- },
72
- responseProps: {
73
- ...respObj
74
- }
75
- };
76
- };
97
+ export const isFileUploadedToServer = file => file.responseProps && !file.responseProps.ID?.includes('temp');
@@ -1,4 +1,4 @@
1
- export function isEmptyObject(obj: Object): boolean {
1
+ export function isEmptyObject(obj: object): boolean {
2
2
  return Object.keys(obj).length === 0;
3
3
  }
4
4
 
@@ -16,7 +16,7 @@ export function getGenericFieldsLocalizedValue(path: string, key: string): strin
16
16
 
17
17
  // Split the path and traverse the object
18
18
  const pathParts = path.split('.');
19
- let currentObj = localeStore;
19
+ let currentObj: any = localeStore;
20
20
 
21
21
  for (const part of pathParts) {
22
22
  if (!currentObj[part]) return key;
@@ -1,4 +1,3 @@
1
- // eslint-disable-next-line import/prefer-default-export
2
1
  export const getDataPage = (dataPageName, parameters, context) => {
3
2
  let dataViewParams;
4
3
  if (parameters) {
@@ -1,5 +1,3 @@
1
- /* eslint-disable no-template-curly-in-string */
2
-
3
1
  type CurrencyMapType = {
4
2
  name: string;
5
3
  symbolFormat: string;
@@ -89,6 +89,51 @@ export const getApiContext = (processedData, pConnect, reorderCB) => {
89
89
  };
90
90
  };
91
91
 
92
+ const PRIMARY_FIELDS = 'pyPrimaryFields';
93
+ const SUPPORTED_FIELD_TYPES = [
94
+ 'Address',
95
+ 'TextArea',
96
+ 'TextInput',
97
+ 'Phone',
98
+ 'Email',
99
+ 'Time',
100
+ 'URL',
101
+ 'Percentage',
102
+ 'Integer',
103
+ 'Decimal',
104
+ 'Date',
105
+ 'DateTime',
106
+ 'Currency',
107
+ 'Checkbox',
108
+ 'Dropdown',
109
+ 'AutoComplete',
110
+ 'UserReference',
111
+ 'RichText'
112
+ ];
113
+
114
+ export const getConfigFields = (rawFields, contextClass, primaryFieldsViewIndex) => {
115
+ let primaryFields: any = [];
116
+ let configFields: any = [];
117
+
118
+ if (primaryFieldsViewIndex > -1) {
119
+ let primaryFieldVMD: any = PCore.getMetadataUtils().resolveView(PRIMARY_FIELDS);
120
+ if (Array.isArray(primaryFieldVMD)) {
121
+ primaryFieldVMD = primaryFieldVMD.find(primaryFieldView => primaryFieldView.classID === contextClass);
122
+ primaryFields = primaryFieldVMD?.children?.[0]?.children || [];
123
+ } else if (primaryFieldVMD?.classID === contextClass) {
124
+ primaryFields = primaryFieldVMD?.children?.[0]?.children || [];
125
+ }
126
+
127
+ if (primaryFields.length) {
128
+ primaryFields = primaryFields.filter(primaryField => SUPPORTED_FIELD_TYPES.includes(primaryField.type));
129
+ }
130
+ }
131
+
132
+ configFields = [...rawFields.slice(0, primaryFieldsViewIndex), ...primaryFields, ...rawFields.slice(primaryFieldsViewIndex + 1)];
133
+ // filter duplicate fields after combining raw fields and primary fields
134
+ return configFields.filter((field, index) => configFields.findIndex(_field => field.config?.value === _field.config?.value) === index);
135
+ };
136
+
92
137
  export const buildMetaForListView = (fieldMetadata, fields, type, ruleClass, name, propertyLabel, isDataObject, parameters) => {
93
138
  return {
94
139
  name,
@@ -126,11 +171,80 @@ export const buildMetaForListView = (fieldMetadata, fields, type, ruleClass, nam
126
171
  };
127
172
  };
128
173
 
129
- export const buildFieldsForTable = (configFields, fields, showDeleteButton) => {
174
+ export function isFLProperty(label) {
175
+ return label?.startsWith('@FL');
176
+ }
177
+
178
+ /**
179
+ * [getFieldLabel]
180
+ * Description - A utility that returns resolved field label for "@FL" annotation i.e from data model.
181
+ * @param {Object} fieldConfig
182
+ * @returns {string} resolved label string
183
+ *
184
+ * example:
185
+ * fieldConfig = {label: "@FL .pyID", classID: "TestCase-Work"};
186
+ * return "Case ID"
187
+ */
188
+ export function getFieldLabel(fieldConfig) {
189
+ const { label, classID, caption } = fieldConfig;
190
+ let fieldLabel = (label ?? caption)?.substring(4);
191
+ const labelSplit = fieldLabel?.split('.');
192
+ const propertyName = labelSplit?.pop();
193
+ const fieldMetaData: any = PCore.getMetadataUtils().getPropertyMetadata(propertyName, classID) ?? {};
194
+ fieldLabel = fieldMetaData.label ?? fieldMetaData.caption ?? propertyName;
195
+ return fieldLabel;
196
+ }
197
+
198
+ export const updateFieldLabels = (fields, configFields, primaryFieldsViewIndex, pConnect, options) => {
199
+ const labelsOfFields: any = [];
200
+ const { columnsRawConfig = [] } = options;
201
+ fields.forEach((field, idx) => {
202
+ const rawColumnConfig = columnsRawConfig[idx]?.config;
203
+ if (field.config.value === PRIMARY_FIELDS) {
204
+ labelsOfFields.push('');
205
+ } else if (isFLProperty(rawColumnConfig?.label ?? rawColumnConfig?.caption)) {
206
+ labelsOfFields.push(getFieldLabel(rawColumnConfig) || field.config.label || field.config.caption);
207
+ } else {
208
+ labelsOfFields.push(field.config.label || field.config.caption);
209
+ }
210
+ });
211
+
212
+ if (primaryFieldsViewIndex > -1) {
213
+ const totalPrimaryFieldsColumns = configFields.length - fields.length + 1;
214
+ if (totalPrimaryFieldsColumns) {
215
+ const primaryFieldLabels: any = [];
216
+ for (let i = primaryFieldsViewIndex; i < primaryFieldsViewIndex + totalPrimaryFieldsColumns; i += 1) {
217
+ let label = configFields[i].config?.label;
218
+ if (isFLProperty(label)) {
219
+ label = getFieldLabel(configFields[i].config);
220
+ } else if (label.startsWith('@')) {
221
+ label = label.substring(3);
222
+ }
223
+ if (pConnect) {
224
+ label = pConnect.getLocalizedValue(label);
225
+ }
226
+ primaryFieldLabels.push(label);
227
+ }
228
+ labelsOfFields.splice(primaryFieldsViewIndex, 1, ...primaryFieldLabels);
229
+ } else {
230
+ labelsOfFields.splice(primaryFieldsViewIndex, 1);
231
+ }
232
+ }
233
+ return labelsOfFields;
234
+ };
235
+
236
+ export const buildFieldsForTable = (configFields, pConnect, showDeleteButton, options) => {
237
+ const { primaryFieldsViewIndex, fields } = options;
238
+
239
+ // get resolved field labels for primary fields raw config included in configFields
240
+ const fieldsLabels = updateFieldLabels(fields, configFields, primaryFieldsViewIndex, pConnect, {
241
+ columnsRawConfig: pConnect.getRawConfigProps()?.children.find(item => item?.name === 'Columns')?.children
242
+ });
243
+
130
244
  const fieldDefs = configFields.map((field, index) => {
131
245
  return {
132
246
  type: 'text',
133
- label: fields[index].config.label || fields[index].config.caption,
247
+ label: fieldsLabels[index],
134
248
  fillAvailableSpace: !!field.config.fillAvailableSpace,
135
249
  id: `${index}`,
136
250
  name: field.config.value.substr(4),
@@ -213,7 +327,7 @@ export function createPConnect(contextName, referenceList, pageReference): any {
213
327
  };
214
328
 
215
329
  // create PConnect object
216
- const config = { meta: {}, options };
330
+ const config: any = { meta: {}, options };
217
331
  const { getPConnect } = PCore.createPConnect(config);
218
332
 
219
333
  return getPConnect();
@@ -235,7 +349,6 @@ export const filterData = filterByColumns => {
235
349
  filterValue =
236
350
  filterObj.containsFilterValue !== null && filterObj.containsFilterValue !== '' ? Utils.getSeconds(filterObj.containsFilterValue) : null;
237
351
 
238
- // eslint-disable-next-line sonarjs/no-nested-switch
239
352
  switch (filterObj.containsFilter) {
240
353
  case 'notequal':
241
354
  // becasue filterValue is in minutes, need to have a range of less than 60 secons
@@ -302,7 +415,6 @@ export const filterData = filterByColumns => {
302
415
  value = item[filterObj.ref].toLowerCase();
303
416
  filterValue = filterObj.containsFilterValue.toLowerCase();
304
417
 
305
- // eslint-disable-next-line sonarjs/no-nested-switch
306
418
  switch (filterObj.containsFilter) {
307
419
  case 'contains':
308
420
  if (value.indexOf(filterValue) < 0) {
@@ -48,7 +48,6 @@ export class Utils {
48
48
  // eslint-disable-next-line no-case-declarations
49
49
  const dataPage = configProps.datasource;
50
50
  if (typeof dataPage === 'string' && dataObject[dataPage]) {
51
- // eslint-disable-next-line no-alert
52
51
  alert('need to handle data page');
53
52
  } else {
54
53
  let listSourceItems = configProps.listOutput;
@@ -337,6 +336,14 @@ export class Utils {
337
336
  static isObject(objValue) {
338
337
  return objValue && typeof objValue === 'object' && objValue.constructor === Object;
339
338
  }
339
+
340
+ static getMappedKey(key) {
341
+ const mappedKey = PCore.getEnvironmentInfo().getKeyMapping(key);
342
+ if (!mappedKey) {
343
+ return key;
344
+ }
345
+ return mappedKey;
346
+ }
340
347
  }
341
348
 
342
349
  export default Utils;
@@ -10,6 +10,5 @@ export const sdkVersion = '8.7';
10
10
  export function compareSdkPCoreVersions() {
11
11
  // const theConstellationVersion = PCore.getPCoreVersion();
12
12
 
13
- // eslint-disable-next-line no-console
14
13
  console.warn(`Using Constellation version ${PCore.getPCoreVersion()}. Ensure this is the same version as your Infinity server.`);
15
14
  }
@@ -1,6 +1,6 @@
1
1
  import makeStyles from '@mui/styles/makeStyles';
2
2
  import Button from '@mui/material/Button';
3
- import { Grid, Divider } from '@mui/material';
3
+ import { Grid2, Divider } from '@mui/material';
4
4
 
5
5
  // ActionButtons does NOT have getPConnect. So, no need to extend from PConnProps
6
6
  interface ActionButtonsProps {
@@ -10,13 +10,18 @@ interface ActionButtonsProps {
10
10
  onButtonPress: any;
11
11
  }
12
12
 
13
- const useStyles = makeStyles((/* theme */) => ({
14
- button: {
15
- padding: '0px 5px'
16
- },
13
+ const useStyles = makeStyles(theme => ({
17
14
  divider: {
18
15
  marginTop: '10px',
19
16
  marginBottom: '10px'
17
+ },
18
+ secondaryButton: {
19
+ backgroundColor: theme.actionButtons.secondary.backgroundColor,
20
+ color: theme.actionButtons.secondary.color
21
+ },
22
+ primaryButton: {
23
+ backgroundColor: theme.actionButtons.primary.backgroundColor,
24
+ color: theme.actionButtons.primary.color
20
25
  }
21
26
  }));
22
27
 
@@ -33,42 +38,44 @@ export default function ActionButtons(props: ActionButtonsProps) {
33
38
  return (
34
39
  <>
35
40
  <Divider className={classes.divider} />
36
- <Grid container spacing={4} justifyContent='space-between'>
37
- <Grid item>
38
- <Grid container spacing={1}>
41
+ <Grid2 container spacing={4} justifyContent='space-between'>
42
+ <Grid2>
43
+ <Grid2 container spacing={1}>
39
44
  {arSecondaryButtons.map(sButton => (
40
- <Grid item key={sButton.name}>
45
+ <Grid2 key={sButton.name}>
41
46
  <Button
42
- variant='contained'
47
+ className={classes.secondaryButton}
43
48
  color='secondary'
49
+ variant='contained'
44
50
  onClick={() => {
45
51
  _onButtonPress(sButton.jsAction, 'secondary');
46
52
  }}
47
53
  >
48
54
  {localizedVal(sButton.name, localeCategory)}
49
55
  </Button>
50
- </Grid>
56
+ </Grid2>
51
57
  ))}
52
- </Grid>
53
- </Grid>
54
- <Grid item>
55
- <Grid container spacing={1}>
58
+ </Grid2>
59
+ </Grid2>
60
+ <Grid2>
61
+ <Grid2 container spacing={1}>
56
62
  {arMainButtons.map(mButton => (
57
- <Grid item key={mButton.name}>
63
+ <Grid2 key={mButton.name}>
58
64
  <Button
59
- variant='contained'
65
+ className={classes.primaryButton}
60
66
  color='primary'
67
+ variant='contained'
61
68
  onClick={() => {
62
69
  _onButtonPress(mButton.jsAction, 'primary');
63
70
  }}
64
71
  >
65
72
  {localizedVal(mButton.name, localeCategory)}
66
73
  </Button>
67
- </Grid>
74
+ </Grid2>
68
75
  ))}
69
- </Grid>
70
- </Grid>
71
- </Grid>
76
+ </Grid2>
77
+ </Grid2>
78
+ </Grid2>
72
79
  </>
73
80
  );
74
81
  }
@@ -13,7 +13,7 @@ interface AssignmentProps extends PConnProps {
13
13
  itemKey: string;
14
14
  isInModal: boolean;
15
15
  banners: any[];
16
- // eslint-disable-next-line react/no-unused-prop-types
16
+
17
17
  actionButtons: any[];
18
18
  }
19
19
 
@@ -133,7 +133,7 @@ export default function Assignment(props: PropsWithChildren<AssignmentProps>) {
133
133
 
134
134
  function showToast(message: string) {
135
135
  const theMessage = `Assignment: ${message}`;
136
- // eslint-disable-next-line no-console
136
+
137
137
  console.error(theMessage);
138
138
  setSnackbarMessage(message);
139
139
  setShowSnackbar(true);