@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,4 +1,3 @@
1
- /* eslint-disable react-hooks/rules-of-hooks */
2
1
  import { useRef } from 'react';
3
2
 
4
3
  import { buildMetaForListView, getContext } from '@pega/react-sdk-components/lib/components/helpers/simpleTableHelpers';
@@ -90,7 +89,7 @@ export default function SimpleTable(props: SimpleTableProps) {
90
89
  );
91
90
 
92
91
  const metaForPConnect = JSON.parse(JSON.stringify(metaForListView));
93
- // @ts-ignore - PCore.getMetadataUtils().getPropertyMetadata - An argument for 'currentClassID' was not provided.
92
+ // @ts-expect-error - PCore.getMetadataUtils().getPropertyMetadata - An argument for 'currentClassID' was not provided.
94
93
  metaForPConnect.config.parameters = rawParams ?? PCore.getMetadataUtils().getPropertyMetadata(name)?.datasource?.parameters;
95
94
 
96
95
  const { referenceListStr: referenceList } = getContext(getPConnect());
@@ -74,7 +74,7 @@ const useStyles = makeStyles((/* theme */) => ({
74
74
  fontSize: '14px'
75
75
  },
76
76
  header: {
77
- background: '#f5f5f5'
77
+ background: 'var(--table-header-background)'
78
78
  },
79
79
  tableCell: {
80
80
  borderRight: '1px solid lightgray',
@@ -163,6 +163,7 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
163
163
  const menuIconOverride$ = Utils.getImageSrc('trash', Utils.getSDKStaticConentUrl());
164
164
 
165
165
  const resolvedFields = children?.[0]?.children || presets?.[0].children?.[0].children;
166
+ const primaryFieldsViewIndex = resolvedFields.findIndex(field => field.config.value === 'pyPrimaryFields');
166
167
  // NOTE: props has each child.config with datasource and value undefined
167
168
  // but getRawMetadata() has each child.config with datasource and value showing their unresolved values (ex: "@P thePropName")
168
169
  // We need to use the prop name as the "glue" to tie the table dataSource, displayColumns and data together.
@@ -194,10 +195,8 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
194
195
  });
195
196
 
196
197
  useEffect(() => {
197
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
198
198
  buildElementsForTable();
199
199
  if (readOnlyMode || allowEditingInModal) {
200
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
201
200
  generateRowsData();
202
201
  }
203
202
  }, [referenceList]);
@@ -208,7 +207,10 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
208
207
  // Constellation DX Components do). It will also have the "label", and "meta" contains the original,
209
208
  // unchanged config info. For now, much of the info here is carried over from
210
209
  // Constellation DX Components.
211
- const fieldDefs = buildFieldsForTable(rawFields, resolvedFields, showDeleteButton);
210
+ const fieldDefs = buildFieldsForTable(rawFields, getPConnect(), showDeleteButton, {
211
+ primaryFieldsViewIndex,
212
+ fields: resolvedFields
213
+ });
212
214
 
213
215
  useLayoutEffect(() => {
214
216
  if (allowEditingInModal) {
@@ -219,7 +221,7 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
219
221
  fieldDefs.filter(item => item.name).map(item => item.name)
220
222
  );
221
223
  } else {
222
- // @ts-ignore - An argument for 'fields' was not provided
224
+ // @ts-expect-error - An argument for 'fields' was not provided
223
225
  getPConnect().getListActions().initDefaultPageInstructions(getPConnect().getReferenceList());
224
226
  }
225
227
  }, []);
@@ -246,7 +248,7 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
246
248
 
247
249
  // return the value that should be shown as the contents for the given row data
248
250
  // of the given row field
249
- function getRowValue(inRowData: Object, inColKey: string): any {
251
+ function getRowValue(inRowData: object, inColKey: string): any {
250
252
  // See what data (if any) we have to display
251
253
  const refKeys: string[] = inColKey?.split('.');
252
254
  let valBuilder = inRowData;
@@ -277,7 +279,6 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
277
279
  setRowData(data);
278
280
  })
279
281
  .catch(e => {
280
- // eslint-disable-next-line no-console
281
282
  console.log(e);
282
283
  });
283
284
  } else {
@@ -286,7 +287,7 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
286
287
  // we're using as the table's dataSource
287
288
  const data: any = [];
288
289
  for (const row of referenceList) {
289
- const dataForRow: Object = {};
290
+ const dataForRow: object = {};
290
291
  for (const col of displayedColumns) {
291
292
  const colKey: string = col;
292
293
  const theVal = getRowValue(row, colKey);
@@ -318,7 +319,7 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
318
319
  if (allowEditingInModal && defaultView) {
319
320
  pConn
320
321
  .getActionsApi()
321
- // @ts-ignore
322
+ // @ts-expect-error
322
323
  .openEmbeddedDataModal(defaultView, pConn, referenceListStr, referenceList.length, PCore.getConstants().RESOURCE_STATUS.CREATE);
323
324
  } else {
324
325
  pConn.getListActions().insert({ classID: contextClass }, referenceList.length);
@@ -334,7 +335,7 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
334
335
  if (typeof selectedRowIndex.current === 'number') {
335
336
  pConn
336
337
  .getActionsApi()
337
- // @ts-ignore
338
+ // @ts-expect-error
338
339
  .openEmbeddedDataModal(
339
340
  bUseSeparateViewForEdit ? editView : defaultView,
340
341
  pConn,
@@ -360,23 +361,25 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
360
361
  const data: any = [];
361
362
  rawFields.forEach(item => {
362
363
  // removing label field from config to hide title in the table cell
363
- item = { ...item, config: { ...item.config, label: '', displayMode: readOnlyMode || allowEditingInModal ? 'DISPLAY_ONLY' : undefined } };
364
- const referenceListData = getReferenceList(pConn);
365
- const isDatapage = referenceListData.startsWith('D_');
366
- const pageReferenceValue = isDatapage
367
- ? `${referenceListData}[${index}]`
368
- : `${pConn.getPageReference()}${referenceListData.substring(referenceListData.lastIndexOf('.'))}[${index}]`;
369
- const config = {
370
- meta: item,
371
- options: {
372
- context,
373
- pageReference: pageReferenceValue,
374
- referenceList: referenceListData,
375
- hasForm: true
376
- }
377
- };
378
- const view = PCore.createPConnect(config);
379
- data.push(createElement(createPConnectComponent(), view));
364
+ if (!item.config.hide) {
365
+ item = { ...item, config: { ...item.config, label: '', displayMode: readOnlyMode || allowEditingInModal ? 'DISPLAY_ONLY' : undefined } };
366
+ const referenceListData = getReferenceList(pConn);
367
+ const isDatapage = referenceListData.startsWith('D_');
368
+ const pageReferenceValue = isDatapage
369
+ ? `${referenceListData}[${index}]`
370
+ : `${pConn.getPageReference()}${referenceListData.substring(referenceListData.lastIndexOf('.'))}[${index}]`;
371
+ const config = {
372
+ meta: item,
373
+ options: {
374
+ context,
375
+ pageReference: pageReferenceValue,
376
+ referenceList: referenceListData,
377
+ hasForm: true
378
+ }
379
+ };
380
+ const view = PCore.createPConnect(config);
381
+ data.push(createElement(createPConnectComponent(), view));
382
+ }
380
383
  });
381
384
  eleData.push(data);
382
385
  });
@@ -419,7 +422,6 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
419
422
  function stableSort<T>(array: T[], comparator: (a: T, b: T) => number) {
420
423
  const stabilizedThis = array.map((el, index) => [el, index] as [T, number]);
421
424
  stabilizedThis.sort((a, b) => {
422
- // eslint-disable-next-line @typescript-eslint/no-shadow
423
425
  const order = comparator(a[0], b[0]);
424
426
  if (order !== 0) return order;
425
427
  return a[1] - b[1];
@@ -574,7 +576,6 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
574
576
  function _showFilteredIcon(columnId) {
575
577
  for (const filterObj of filterByColumns) {
576
578
  if (filterObj.ref === columnId) {
577
- // eslint-disable-next-line sonarjs/prefer-single-boolean-return
578
579
  if (filterObj.containsFilterValue !== '') {
579
580
  return true;
580
581
  }
@@ -608,6 +609,9 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
608
609
  <TableHead className={classes.header}>
609
610
  <TableRow>
610
611
  {fieldDefs.map((field: any, index) => {
612
+ if (field?.meta?.config?.hide) {
613
+ return null; // Skip rendering if hide = true
614
+ }
611
615
  return (
612
616
  <TableCell key={`head-${displayedColumns[index]}`} className={classes.tableCell}>
613
617
  {(readOnlyMode || allowEditingInModal) && field.cellRenderer !== 'DeleteIcon' ? (
@@ -678,7 +682,6 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
678
682
  .slice(0)
679
683
  .map((row, index) => {
680
684
  return (
681
- // eslint-disable-next-line react/no-array-index-key
682
685
  <TableRow key={index}>
683
686
  {row.map((item, childIndex) => {
684
687
  const theColKey = displayedColumns[childIndex];
@@ -1,5 +1,5 @@
1
1
  import type { PropsWithChildren, ReactElement } from 'react';
2
- import { Grid2, type GridSize } from '@mui/material';
2
+ import Grid2, { type GridSize } from '@mui/material/Grid2';
3
3
  import makeStyles from '@mui/styles/makeStyles';
4
4
  import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
5
5
 
@@ -23,7 +23,6 @@ export default function TwoColumn(props: PropsWithChildren<TwoColumnProps>) {
23
23
  const childrenToRender = children as ReactElement[];
24
24
 
25
25
  if (childrenToRender.length !== 2) {
26
- // eslint-disable-next-line no-console
27
26
  console.error(`TwoColumn template sees more than 2 columns: ${childrenToRender.length}`);
28
27
  }
29
28
 
@@ -1,5 +1,5 @@
1
1
  import type { PropsWithChildren, ReactElement } from 'react';
2
- import { Grid2, type GridSize } from '@mui/material';
2
+ import Grid2, { type GridSize } from '@mui/material/Grid2';
3
3
  import makeStyles from '@mui/styles/makeStyles';
4
4
  import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
5
5
 
@@ -23,7 +23,6 @@ export default function TwoColumnTab(props: PropsWithChildren<TwoColumnTabProps>
23
23
  const childrenToRender = children as ReactElement[];
24
24
 
25
25
  if (childrenToRender.length !== 2) {
26
- // eslint-disable-next-line no-console
27
26
  console.error(`TwoColumn template sees more than 2 columns: ${childrenToRender.length}`);
28
27
  }
29
28
 
@@ -6,11 +6,11 @@ interface WideNarrowProps extends PConnProps {
6
6
  // If any, enter additional props that only exist on this component
7
7
  a: any;
8
8
  b: any;
9
- // eslint-disable-next-line react/no-unused-prop-types
9
+
10
10
  title?: string;
11
- // eslint-disable-next-line react/no-unused-prop-types
11
+
12
12
  cols?: string;
13
- // eslint-disable-next-line react/no-unused-prop-types
13
+
14
14
  icon?: string;
15
15
  }
16
16
 
@@ -1,5 +1,5 @@
1
1
  import { createElement } from 'react';
2
- import Grid, { type GridSize } from '@mui/material/Grid';
2
+ import Grid2, { type GridSize } from '@mui/material/Grid2';
3
3
 
4
4
  import createPConnectComponent from '@pega/react-sdk-components/lib/bridge/react_pconnect';
5
5
  import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
@@ -36,7 +36,7 @@ export default function WideNarrowDetails(props: WideNarrowDetailsProps) {
36
36
 
37
37
  return createElement(createPConnectComponent(), {
38
38
  ...theConfigObject,
39
- // eslint-disable-next-line react/no-array-index-key
39
+
40
40
  key: index.toString()
41
41
  });
42
42
  });
@@ -66,21 +66,21 @@ export default function WideNarrowDetails(props: WideNarrowDetailsProps) {
66
66
  return (
67
67
  <FieldGroup name={theName}>
68
68
  {showHighlightedData && highlightedDataArr.length > 0 && (
69
- <Grid container spacing={1} style={{ padding: '0 0 1em' }}>
69
+ <Grid2 container spacing={1} style={{ padding: '0 0 1em' }}>
70
70
  {highlightedDataArr.map((child, i) => (
71
- <Grid item xs={COLUMN_WIDTHS[i] as GridSize} key={`hf-${i + 1}`}>
71
+ <Grid2 size={{ xs: COLUMN_WIDTHS[i] as GridSize }} key={`hf-${i + 1}`}>
72
72
  {child}
73
- </Grid>
73
+ </Grid2>
74
74
  ))}
75
- </Grid>
75
+ </Grid2>
76
76
  )}
77
- <Grid container spacing={1}>
77
+ <Grid2 container spacing={1}>
78
78
  {children?.map((child, i) => (
79
- <Grid item xs={COLUMN_WIDTHS[i] as GridSize} key={`r-${i + 1}`}>
79
+ <Grid2 size={{ xs: COLUMN_WIDTHS[i] as GridSize }} key={`r-${i + 1}`}>
80
80
  {child}
81
- </Grid>
81
+ </Grid2>
82
82
  ))}
83
- </Grid>
83
+ </Grid2>
84
84
  </FieldGroup>
85
85
  );
86
86
  }
@@ -1,5 +1,5 @@
1
1
  .link-style {
2
- color: white !important;
2
+ color: var(--app-text-color) !important;
3
3
  text-transform: capitalize !important;
4
4
  font-size: 1rem !important;
5
5
  }
@@ -17,10 +17,10 @@ interface WssNavBarProps extends PConnProps {
17
17
  navLinks: any[];
18
18
  operator: { currentUserInitials: string };
19
19
  navDisplayOptions: { alignment: string; position: string };
20
- // eslint-disable-next-line react/no-unused-prop-types
20
+
21
21
  portalName: string;
22
22
  imageSrc: string;
23
- // eslint-disable-next-line react/no-unused-prop-types
23
+
24
24
  fullImageSrc: string;
25
25
  appName: any;
26
26
  }
@@ -36,10 +36,10 @@ const useStyles = makeStyles(theme => ({
36
36
  marginRight: theme.spacing(2)
37
37
  },
38
38
  appListLogo: {
39
- width: '3.6rem'
39
+ width: '3.6rem',
40
+ filter: 'var(--svg-color)'
40
41
  },
41
42
  appName: {
42
- color: 'white',
43
43
  marginLeft: theme.spacing(2),
44
44
  marginRight: theme.spacing(4),
45
45
  fontSize: '1.5rem'
@@ -42,6 +42,10 @@
42
42
  flex-direction: row;
43
43
  padding: 0.25rem 0rem 0.25rem 0.25rem;
44
44
  margin-bottom: 0.5rem;
45
+ align-items: center;
46
+ border: 0.0625rem solid var(--utility-card-border-color);
47
+ border-radius: calc(0.25rem);
48
+ min-height: 3rem;
45
49
  }
46
50
 
47
51
  .psdk-utility-card-icon {
@@ -54,6 +58,7 @@
54
58
  .psdk-utility-card-svg-icon {
55
59
  width: 2.5rem;
56
60
  display: inline-block;
61
+ filter: var(--svg-color);
57
62
  }
58
63
 
59
64
  .psdk-utility-card-main {
@@ -71,14 +76,7 @@
71
76
  .psdk-utility-card-action-svg-icon {
72
77
  width: 1.4rem;
73
78
  display: inline-block;
74
- }
75
-
76
- .psdk-utility-card {
77
- display: flex;
78
- align-items: center;
79
- border: 0.0625rem solid rgb(207, 207, 207);
80
- border-radius: calc(0.25rem);
81
- min-height: 3rem;
79
+ filter: var(--svg-color);
82
80
  }
83
81
 
84
82
  .psdk-utility-button {
@@ -1,12 +1,9 @@
1
- /* eslint-disable react/jsx-boolean-value */
2
- /* eslint-disable react/no-array-index-key */
3
- /* eslint-disable no-nested-ternary */
4
- import { useState, useEffect, useCallback } from 'react';
1
+ import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
5
2
  import { CircularProgress, IconButton, Menu, MenuItem, Button } from '@mui/material';
6
3
  import MoreVertIcon from '@mui/icons-material/MoreVert';
7
- import download from 'downloadjs';
8
4
 
9
- import { buildFilePropsFromResponse, getIconFromFileType, validateMaxSize } from '@pega/react-sdk-components/lib/components/helpers/attachmentHelpers';
5
+ import { getIconFromFileType, isFileUploadedToServer, useFileDownload, validateMaxSize } from '@pega/react-sdk-components/lib/components/helpers/attachmentHelpers';
6
+
10
7
  import { Utils } from '@pega/react-sdk-components/lib/components/helpers/utils';
11
8
  import type { PConnFieldProps } from '@pega/react-sdk-components/lib/types/PConnProps';
12
9
 
@@ -19,7 +16,9 @@ interface AttachmentProps extends Omit<PConnFieldProps, 'value'> {
19
16
  extensions: string;
20
17
  }
21
18
 
22
- const getAttachmentKey = (name = '') => (name ? `attachmentsList.${name}` : 'attachmentsList');
19
+ const getAttachmentKey = (name, embeddedReference) => {
20
+ return `attachmentsList${embeddedReference}.${name}`;
21
+ };
23
22
 
24
23
  const getCurrentAttachmentsList = (key, context) => {
25
24
  return PCore.getStoreValue(`.${key}`, 'context_data', context) || [];
@@ -38,61 +37,65 @@ export default function Attachment(props: AttachmentProps) {
38
37
  let { required, disabled } = props;
39
38
  [required, disabled] = [required, disabled].map(prop => prop === true || (typeof prop === 'string' && prop === 'true'));
40
39
  const pConn = getPConnect();
40
+
41
+ const actionSequencer = useMemo(() => PCore.getActionsSequencer(), []);
41
42
  const caseID = PCore.getStoreValue('.pyID', 'caseInfo.content', pConn.getContextName());
42
43
  const localizedVal = PCore.getLocaleUtils().getLocaleValue;
43
44
  const localeCategory = 'CosmosFields';
44
45
  const uploadMultipleFilesLabel = localizedVal('file_upload_text_multiple', localeCategory);
45
46
  const uploadSingleFileLabel = localizedVal('file_upload_text_one', localeCategory);
46
- let categoryName = '';
47
- if (value && value.pyCategoryName) {
48
- categoryName = value.pyCategoryName;
49
- }
50
47
  const deleteIcon = Utils.getImageSrc('trash', Utils.getSDKStaticConentUrl());
51
48
  const srcImg = Utils.getImageSrc('document-doc', Utils.getSDKStaticConentUrl());
52
49
  let valueRef = (pConn.getStateProps() as any).value;
53
50
  valueRef = valueRef.indexOf('.') === 0 ? valueRef.substring(1) : valueRef;
54
51
  const [anchorEl, setAnchorEl] = useState(null);
55
52
  const open = Boolean(anchorEl);
56
- const [files, setFiles] = useState<any[]>(() =>
57
- value?.pxResults && +value.pyCount > 0 ? value.pxResults.map(f => buildFilePropsFromResponse(f)) : []
58
- );
53
+
54
+ const rawValue = pConn.getComponentConfig().value;
55
+ const isAttachmentAnnotationPresent = typeof rawValue === 'object' ? false : rawValue?.includes('@ATTACHMENT');
56
+ const { hasUploadedFiles, attachments, categoryName } = isAttachmentAnnotationPresent
57
+ ? value
58
+ : PCore.getAttachmentUtils().prepareAttachmentData(value);
59
+
60
+ const fileInputRef = useRef<HTMLInputElement>(null);
61
+ const [files, setFiles] = useState<any[]>(attachments);
59
62
  const [filesWithError, setFilesWithError] = useState<any[]>([]);
60
63
  const [toggleUploadBegin, setToggleUploadBegin] = useState(false);
61
64
 
65
+ const context = pConn.getContextName();
66
+ const onFileDownload = useFileDownload(context);
67
+
68
+ let embeddedProperty = pConn
69
+ .getPageReference()
70
+ .replace(PCore.getConstants().CASE_INFO.CASE_INFO_CONTENT, '')
71
+ .replace(PCore.getConstants().DATA_INFO.DATA_INFO_CONTENT, '');
72
+
73
+ if (valueRef?.indexOf('.') > 0) {
74
+ embeddedProperty = valueRef.substring(0, valueRef.indexOf('.') + 1);
75
+ }
76
+
62
77
  const resetAttachmentStoredState = () => {
63
- PCore.getStateUtils().updateState(pConn.getContextName(), getAttachmentKey(valueRef), undefined, {
78
+ PCore.getStateUtils().updateState(pConn.getContextName(), getAttachmentKey(valueRef, embeddedProperty), undefined, {
64
79
  pageReference: 'context_data',
65
80
  isArrayDeepMerge: false
66
81
  });
67
82
  };
68
83
 
69
- const fileDownload = (data, fileName, ext) => {
70
- const fileData = ext ? `${fileName}.${ext}` : fileName;
71
- download(atob(data), fileData);
72
- };
73
-
74
- const downloadFile = (fileObj: any) => {
75
- setAnchorEl(null);
76
- PCore.getAttachmentUtils()
77
- // @ts-ignore - 3rd parameter "responseEncoding" should be optional
78
- .downloadAttachment(fileObj.pzInsKey, pConn.getContextName())
79
- .then((content: any) => {
80
- const extension = fileObj.pyAttachName.split('.').pop();
81
- fileDownload(content.data, fileObj.pyFileName, extension);
82
- })
83
- .catch(() => {});
84
- };
85
-
86
84
  const deleteFile = useCallback(
87
85
  file => {
88
86
  setAnchorEl(null);
87
+
88
+ // reset the file input so that it will allow re-uploading the same file after deletion
89
+ if (fileInputRef.current) {
90
+ fileInputRef.current.value = ''; // Reset the input
91
+ }
92
+
89
93
  let attachmentsList: any[] = [];
90
- let currentAttachmentList = getCurrentAttachmentsList(getAttachmentKey(valueRef), pConn.getContextName());
94
+ let currentAttachmentList = getCurrentAttachmentsList(getAttachmentKey(valueRef, embeddedProperty), pConn.getContextName());
91
95
 
92
96
  // If file to be deleted is the one added in previous stage i.e. for which a file instance is created in server
93
97
  // no need to filter currentAttachmentList as we will get another entry of file in redux with delete & label
94
- // eslint-disable-next-line no-unsafe-optional-chaining
95
- if (value && value?.pxResults && +value?.pyCount > 0 && file.responseProps && file?.responseProps?.pzInsKey !== 'temp') {
98
+ if (hasUploadedFiles && isFileUploadedToServer(file)) {
96
99
  const updatedAttachments = files.map(f => {
97
100
  if (f.responseProps && f.responseProps.pzInsKey === file.responseProps.pzInsKey) {
98
101
  return { ...f, delete: true, label: valueRef };
@@ -101,27 +104,25 @@ export default function Attachment(props: AttachmentProps) {
101
104
  });
102
105
 
103
106
  // updating the redux store to help form-handler in passing the data to delete the file from server
104
- updateAttachmentState(pConn, getAttachmentKey(valueRef), [...updatedAttachments]);
107
+ updateAttachmentState(pConn, getAttachmentKey(valueRef, embeddedProperty), [...updatedAttachments]);
105
108
  setFiles(current => {
106
109
  const newlyAddedFiles = current.filter(f => !!f.ID);
107
- const filesPostDelete = current.filter(
108
- f => f.responseProps?.pzInsKey !== 'temp' && f.responseProps?.pzInsKey !== file.responseProps?.pzInsKey
109
- );
110
+ const filesPostDelete = current.filter(f => isFileUploadedToServer(f) && f.responseProps?.ID !== file.responseProps?.ID);
110
111
  attachmentsList = [...filesPostDelete, ...newlyAddedFiles];
111
112
  return attachmentsList;
112
113
  });
113
114
  } // if the file being deleted is the added in this stage i.e. whose data is not yet created in server
114
115
  else {
115
116
  // filter newly added files in this stage, later the updated current stage files will be added to redux once files state is updated in below setFiles()
116
- currentAttachmentList = currentAttachmentList.filter(f => f.label !== valueRef);
117
- setFiles(current => {
118
- attachmentsList = current.filter(f => f.ID !== file.ID);
119
- return attachmentsList;
120
- });
121
- updateAttachmentState(pConn, getAttachmentKey(valueRef), [...currentAttachmentList, ...attachmentsList]);
117
+ currentAttachmentList = currentAttachmentList.filter(f => !f.props.error && (f.delete || f.label !== valueRef));
118
+ setFiles(current => current.filter(f => f.ID !== file.ID));
119
+ updateAttachmentState(pConn, getAttachmentKey(valueRef, embeddedProperty), [...currentAttachmentList, ...attachmentsList]);
122
120
  if (file.inProgress) {
123
- // @ts-ignore - 3rd parameter "responseEncoding" should be optional
121
+ // @ts-expect-error - 3rd parameter "responseEncoding" should be optional
124
122
  PCore.getAttachmentUtils().cancelRequest(file.ID, pConn.getContextName());
123
+ actionSequencer.deRegisterBlockingAction(pConn.getContextName()).catch(error => {
124
+ console.log(error);
125
+ });
125
126
  }
126
127
  }
127
128
 
@@ -130,7 +131,7 @@ export default function Attachment(props: AttachmentProps) {
130
131
  return prevFilesWithError.filter(f => f.ID !== file.ID);
131
132
  });
132
133
  },
133
- [pConn, value, valueRef, filesWithError]
134
+ [valueRef, pConn, hasUploadedFiles, filesWithError, hasUploadedFiles, actionSequencer]
134
135
  );
135
136
 
136
137
  const onUploadProgress = () => {};
@@ -152,7 +153,6 @@ export default function Attachment(props: AttachmentProps) {
152
153
  f.props.name = pConn.getLocalizedValue('Unable to upload file', '', '');
153
154
  f.inProgress = false;
154
155
  const fieldName = (pConn.getStateProps() as any).value;
155
- const context = pConn.getContextName();
156
156
  // set errors to property to block submit even on errors in file upload
157
157
  PCore.getMessageManager().addMessages({
158
158
  messages: [
@@ -189,7 +189,6 @@ export default function Attachment(props: AttachmentProps) {
189
189
 
190
190
  const clearFieldErrorMessages = () => {
191
191
  const fieldName = (pConn.getStateProps() as any).value;
192
- const context = pConn.getContextName();
193
192
  PCore.getMessageManager().clearMessages({
194
193
  type: PCore.getConstants().MESSAGES.MESSAGES_TYPE_ERROR,
195
194
  property: fieldName,
@@ -226,7 +225,6 @@ export default function Attachment(props: AttachmentProps) {
226
225
  }
227
226
  if (f.props.error) {
228
227
  const fieldName = (pConn.getStateProps() as any).value;
229
- const context = pConn.getContextName();
230
228
  PCore.getMessageManager().addMessages({
231
229
  messages: [
232
230
  {
@@ -301,7 +299,6 @@ export default function Attachment(props: AttachmentProps) {
301
299
  setToggleUploadBegin(false);
302
300
  })
303
301
  .catch(error => {
304
- // eslint-disable-next-line no-console
305
302
  console.log(error);
306
303
  setToggleUploadBegin(false);
307
304
  });
@@ -315,12 +312,12 @@ export default function Attachment(props: AttachmentProps) {
315
312
 
316
313
  useEffect(() => {
317
314
  if (files.length > 0 && displayMode !== 'DISPLAY_ONLY') {
318
- const currentAttachmentList = getCurrentAttachmentsList(getAttachmentKey(valueRef), pConn.getContextName());
315
+ const currentAttachmentList = getCurrentAttachmentsList(getAttachmentKey(valueRef, embeddedProperty), pConn.getContextName());
319
316
  // block duplicate files to redux store when added 1 after another to prevent multiple duplicates being added to the case on submit
320
317
  const tempFiles = files.filter(f => currentAttachmentList.findIndex(fr => fr.ID === f.ID) === -1 && !f.inProgress && f.responseProps);
321
318
 
322
319
  const updatedAttList = [...currentAttachmentList, ...tempFiles];
323
- updateAttachmentState(pConn, getAttachmentKey(valueRef), updatedAttList);
320
+ updateAttachmentState(pConn, getAttachmentKey(valueRef, embeddedProperty), updatedAttList);
324
321
  }
325
322
  }, [files]);
326
323
 
@@ -331,7 +328,7 @@ export default function Attachment(props: AttachmentProps) {
331
328
  }, [filesWithError]);
332
329
 
333
330
  useEffect(() => {
334
- let tempUploadedFiles = getCurrentAttachmentsList(getAttachmentKey(valueRef), pConn.getContextName());
331
+ let tempUploadedFiles = getCurrentAttachmentsList(getAttachmentKey(valueRef, embeddedProperty), pConn.getContextName());
335
332
  tempUploadedFiles = tempUploadedFiles.filter(f => f.label === valueRef);
336
333
  setFiles(current => {
337
334
  return [
@@ -349,9 +346,13 @@ export default function Attachment(props: AttachmentProps) {
349
346
  ...tempUploadedFiles
350
347
  ];
351
348
  });
352
- PCore.getPubSubUtils().subscribe(PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS.ASSIGNMENT_SUBMISSION, resetAttachmentStoredState, caseID);
349
+ if (displayMode !== 'DISPLAY_ONLY') {
350
+ PCore.getPubSubUtils().subscribe(PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS.ASSIGNMENT_SUBMISSION, resetAttachmentStoredState, caseID);
351
+ }
353
352
  return () => {
354
- PCore.getPubSubUtils().unsubscribe(PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS.ASSIGNMENT_SUBMISSION, caseID);
353
+ if (displayMode !== 'DISPLAY_ONLY') {
354
+ PCore.getPubSubUtils().unsubscribe(PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS.ASSIGNMENT_SUBMISSION, caseID);
355
+ }
355
356
  };
356
357
  }, []);
357
358
 
@@ -435,7 +436,10 @@ export default function Attachment(props: AttachmentProps) {
435
436
  <MenuItem
436
437
  style={{ fontSize: '14px' }}
437
438
  key='download'
438
- onClick={() => downloadFile(item.responseProps ? item.responseProps : {})}
439
+ onClick={() => {
440
+ setAnchorEl(null);
441
+ onFileDownload(item.responseProps ? item.responseProps : {});
442
+ }}
439
443
  >
440
444
  Download
441
445
  </MenuItem>
@@ -66,8 +66,8 @@ export default function CaseHistory(props: CaseHistoryProps) {
66
66
  const dataViewName = 'D_pyWorkHistory';
67
67
  const context = thePConn.getContextName();
68
68
 
69
- function computeRowData(rows: Object[]): void {
70
- const theRowData: Object[] = [];
69
+ function computeRowData(rows: object[]): void {
70
+ const theRowData: object[] = [];
71
71
 
72
72
  rows.forEach((row: any, rowIndex: number) => {
73
73
  // Now, for each property in the index of row properties (displayedColumns), add an object
@@ -142,7 +142,7 @@ export default function CaseHistory(props: CaseHistoryProps) {
142
142
  // Note: using rowData.current since we're using useRef as a mutatable
143
143
  // value that's only updated when it changes.
144
144
  if (rowData.current.length > 0) {
145
- rowData.current.forEach((dataRow: Object[], index) => {
145
+ rowData.current.forEach((dataRow: object[], index) => {
146
146
  // using dataRow[0]-dataRow[1] as the array key since it's a unique value
147
147
  const theKey = `CaseHistory-${index}`;
148
148
  theDataRows.push(
@@ -11,17 +11,3 @@
11
11
  justify-content: center;
12
12
  display: flex;
13
13
  }
14
-
15
- .primary-button {
16
- background-color: #3f51b5 !important;
17
- color: white !important;
18
- padding: 6px 14px !important;
19
- text-transform: unset !important;
20
- font-size: 14px;
21
- }
22
-
23
- .secondary-button {
24
- box-shadow: 0px 5px 10px 0px rgb(0 0 0 / 20%);
25
- text-transform: unset !important;
26
- padding: 6px 14px !important;
27
- }
@@ -15,14 +15,14 @@ export default function ActionButtonsForFileUtil(props: ActionButtonsForFileUtil
15
15
  <div className='psdk-actions'>
16
16
  <div className='psdk-action-buttons'>
17
17
  {props.arSecondaryButtons.map(file => (
18
- <Button className='secondary-button' key={file.actionID} onClick={props.secondaryAction}>
18
+ <Button className='secondary-button' color='secondary' variant='contained' key={file.actionID} onClick={props.secondaryAction}>
19
19
  {file.name}
20
20
  </Button>
21
21
  ))}
22
22
  </div>
23
23
  <div className='psdk-action-buttons'>
24
24
  {props.arMainButtons.map(file => (
25
- <Button className='primary-button' key={file.actionID} onClick={props.primaryAction}>
25
+ <Button className='primary-button' color='primary' variant='contained' key={file.actionID} onClick={props.primaryAction}>
26
26
  {file.name}
27
27
  </Button>
28
28
  ))}