@pega/react-sdk-overrides 25.1.10 → 25.1.11

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 (28) hide show
  1. package/lib/designSystemExtension/AlertBanner/AlertBanner.css +46 -0
  2. package/lib/designSystemExtension/AlertBanner/AlertBanner.tsx +37 -20
  3. package/lib/designSystemExtension/FieldGroupList/FieldGroupList.tsx +1 -1
  4. package/lib/field/SelectableCard/SelectableCard.tsx +17 -3
  5. package/lib/infra/Assignment/Assignment.tsx +10 -1
  6. package/lib/infra/Assignment/useValidationBanner.ts +29 -0
  7. package/lib/infra/Containers/FlowContainer/FlowContainer.tsx +5 -6
  8. package/lib/infra/Containers/ModalViewContainer/ModalViewContainer.tsx +6 -1
  9. package/lib/infra/Containers/ViewContainer/ViewContainer.tsx +4 -8
  10. package/lib/infra/DeferLoad/DeferLoad.tsx +24 -9
  11. package/lib/infra/NavBar/NavBar.tsx +6 -2
  12. package/lib/infra/Reference/Reference.tsx +5 -0
  13. package/lib/infra/RootContainer/RootContainer.tsx +4 -5
  14. package/lib/infra/View/View.tsx +5 -6
  15. package/lib/template/AppShell/AppShell.css +0 -4
  16. package/lib/template/CaseSummary/CaseSummary.tsx +2 -7
  17. package/lib/template/FieldGroupTemplate/FieldGroupTemplate.tsx +10 -3
  18. package/lib/template/HierarchicalForm/HierarchicalForm.tsx +58 -0
  19. package/lib/template/HierarchicalForm/hooks.ts +224 -0
  20. package/lib/template/HierarchicalForm/index.tsx +1 -0
  21. package/lib/template/ListView/ListView.tsx +73 -15
  22. package/lib/template/MultiReferenceReadOnly/MultiReferenceReadOnly.tsx +16 -1
  23. package/lib/template/ObjectPage/index.tsx +1 -0
  24. package/lib/template/SelfServiceCaseView/SelfServiceCaseView.tsx +51 -43
  25. package/lib/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +14 -6
  26. package/lib/template/SimpleTable/SimpleTableSelectReadonly/SimpleTableSelectReadonly.tsx +179 -0
  27. package/lib/template/SimpleTable/SimpleTableSelectReadonly/index.tsx +1 -0
  28. package/package.json +1 -1
@@ -0,0 +1,224 @@
1
+ import { useState, useEffect, useMemo, useCallback, useRef, Children, type PropsWithChildren, type SyntheticEvent } from 'react';
2
+
3
+ import useGetTabsCount from '@pega/react-sdk-components/lib/hooks/useGetTabsCount';
4
+ import { searchtabsClick as tabClick, getActiveTabId, getFirstVisibleTabId } from '@pega/react-sdk-components/lib/components/template/SubTabs/tabUtils';
5
+ import { getInstructions } from '@pega/react-sdk-components/lib/components/helpers/template-utils';
6
+ import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
7
+
8
+ const ComponentName = 'HierarchicalForm';
9
+
10
+ const getLandingPageViewName = (contextName: string) => {
11
+ const target = contextName.substring(0, contextName.lastIndexOf('_'));
12
+ const activeContainerItemID = PCore.getContainerUtils().getActiveContainerItemName(target);
13
+ const containerItemData = PCore.getContainerUtils().getContainerItemData(target, activeContainerItemID);
14
+ return containerItemData?.view?.config?.name;
15
+ };
16
+
17
+ export interface HierarchicalFormProps extends PConnProps {
18
+ tabsVisibility?: Record<string, boolean>;
19
+ template?: string;
20
+ instructions?: string;
21
+ lastUpdateCaseTime?: string | number;
22
+ }
23
+
24
+ export function useHierarchicalForm(props: PropsWithChildren<HierarchicalFormProps>) {
25
+ const { children = [], getPConnect, tabsVisibility = {}, template } = props;
26
+ const [tabErrors, setTabErrors] = useState<Record<string, any>>({});
27
+ const tabErrorsRef = useRef<Record<string, any>>({});
28
+ const submitAttemptedRef = useRef(false);
29
+ const { lastUpdateCaseTime = getPConnect().getValue('caseInfo.lastUpdateTime') } = props;
30
+ const fullCaseId = getPConnect().getValue(PCore.getConstants().CASE_INFO.CASE_INFO_ID);
31
+
32
+ const deferLoadedTabs: any = Children.toArray(children)[0];
33
+ deferLoadedTabs.props.getPConnect().setInheritedProp('template', template);
34
+
35
+ const navigationKey = useMemo(() => {
36
+ const parentNavKey = `${
37
+ getPConnect().getValue(PCore.getConstants().CASE_INFO.CASE_INFO_ID) || getLandingPageViewName(getPConnect().getContextName())
38
+ }`;
39
+ return `${parentNavKey}-${getPConnect().getMetadata()?.name}-${ComponentName}`;
40
+ }, []);
41
+
42
+ const instructions = getInstructions(getPConnect(), props.instructions);
43
+
44
+ const storedTab = (PCore.getNavigationUtils().getComponentState(navigationKey) as any)?.activeTab;
45
+
46
+ const tabsFromChildren = deferLoadedTabs.props.getPConnect().getChildren();
47
+
48
+ const firstTabId = getFirstVisibleTabId(deferLoadedTabs, undefined);
49
+
50
+ const [currentTabId, setCurrentTabId] = useState(getActiveTabId(tabsFromChildren, storedTab || firstTabId));
51
+ const [tabVisibilityStr, setTabVisibilityStr] = useState('');
52
+ const { data: tabData, refreshTabData } = useGetTabsCount(deferLoadedTabs, 'hierarchical', currentTabId, template);
53
+
54
+ const handleCaseRefresh = (message: any) => {
55
+ if (message.subtype === 'tab') {
56
+ refreshTabData();
57
+ }
58
+ };
59
+
60
+ useEffect(() => {
61
+ let index = 0;
62
+ let caseSubId = '';
63
+ deferLoadedTabs.props
64
+ .getPConnect()
65
+ .getChildren()
66
+ ?.forEach((child: any) => {
67
+ const rawConfigProps = child.getPConnect().getRawConfigProps();
68
+ if ('visibility' in rawConfigProps) {
69
+ tabsVisibility[`${index}`] = rawConfigProps.visibility;
70
+ }
71
+ index += 1;
72
+ });
73
+
74
+ getPConnect().registerAdditionalProps({ tabsVisibility });
75
+ getPConnect().registerAdditionalProps({ lastUpdateCaseTime: '@P caseInfo.lastUpdateTime' });
76
+
77
+ if (fullCaseId) {
78
+ caseSubId = PCore.getMessagingServiceManager().getCaseSubscription(fullCaseId).subscribe({ caseId: fullCaseId }, handleCaseRefresh);
79
+ }
80
+
81
+ return () => {
82
+ if (fullCaseId) PCore.getMessagingServiceManager().getCaseSubscription(fullCaseId).unsubscribe(caseSubId);
83
+ };
84
+ }, []);
85
+
86
+ useEffect(() => {
87
+ refreshTabData();
88
+ }, [lastUpdateCaseTime]);
89
+
90
+ useEffect(() => {
91
+ const isVisibilityAvailable =
92
+ Object.values(tabsVisibility).length > 0 && Object.values(tabsVisibility).every(visibility => typeof visibility === 'boolean');
93
+ if (isVisibilityAvailable) {
94
+ let str = '';
95
+ Object.keys(tabsVisibility).forEach(key => {
96
+ str += key + tabsVisibility[key];
97
+ });
98
+ setTabVisibilityStr(str);
99
+ }
100
+ }, [tabsVisibility]);
101
+
102
+ useEffect(() => {
103
+ if (tabData && tabData.length) {
104
+ const activeTabId = getActiveTabId(tabData, currentTabId);
105
+ if (activeTabId !== currentTabId) {
106
+ setCurrentTabId(activeTabId);
107
+ }
108
+ }
109
+ }, [tabVisibilityStr, tabData]);
110
+
111
+ useEffect(() => {
112
+ PCore.getNavigationUtils().setComponentState(navigationKey, { activeTab: currentTabId });
113
+ const activeTabNavKey = `${getPConnect().getValue(PCore.getConstants().CASE_INFO.CASE_INFO_ID)}-CaseView-ActiveTab`;
114
+ PCore.getNavigationUtils().setComponentState(activeTabNavKey, { id: currentTabId });
115
+
116
+ return () => {
117
+ if (getPConnect().getContextName()?.includes('/modal')) {
118
+ PCore.getNavigationUtils().setComponentState(navigationKey, { activeTab: firstTabId });
119
+ }
120
+ };
121
+ }, [currentTabId, children]);
122
+
123
+ const handleTabClick = useCallback(
124
+ (event: SyntheticEvent, id: string) => {
125
+ tabClick(id, tabData, currentTabId, setCurrentTabId);
126
+ },
127
+ [tabData, currentTabId]
128
+ );
129
+
130
+ const tabItems = useMemo(() => tabData?.filter((tab: any) => tab.visibility()) ?? [], [tabData, tabVisibilityStr]);
131
+
132
+ const tabsRef = useRef(tabItems);
133
+ tabsRef.current = tabItems;
134
+
135
+ const updateTabErrorsOnViewMutate = useCallback((messageObject: any, tab: any) => {
136
+ if (!messageObject.type) {
137
+ return;
138
+ }
139
+ const previousTabErrors = tabErrorsRef.current;
140
+ let currentTabState = previousTabErrors[tab.id] || {};
141
+ const { MESSAGES_TYPE_ERROR } = PCore.getConstants().MESSAGES;
142
+ if (messageObject.type !== MESSAGES_TYPE_ERROR) {
143
+ delete currentTabState[messageObject.fieldName];
144
+ currentTabState = Object.keys(currentTabState).length > 0 ? currentTabState : undefined;
145
+ } else {
146
+ currentTabState = { ...currentTabState, [messageObject.fieldName]: messageObject.messages };
147
+ }
148
+ const newErrors = { ...previousTabErrors, [tab.id]: currentTabState };
149
+ tabErrorsRef.current = newErrors;
150
+ setTabErrors(newErrors);
151
+ }, []);
152
+
153
+ useEffect(() => {
154
+ const rawConfig = '_rawConfig';
155
+ tabItems.forEach((tab: any) => {
156
+ PCore.getContextTreeManager().onViewMutate(
157
+ tab.getPConnect().getContextName(),
158
+ tab.getPConnect().getPageReference(),
159
+ tab.getPConnect()[rawConfig].config?.name,
160
+ (messageObject: any) => updateTabErrorsOnViewMutate(messageObject, tab)
161
+ );
162
+ });
163
+ }, [tabItems, updateTabErrorsOnViewMutate]);
164
+
165
+ const navigateToFirstErrorTab = useCallback(() => {
166
+ const currentErrors = tabErrorsRef.current;
167
+ const firstTabWithError = tabsRef.current.find((tab: any) => {
168
+ const tabErrorState = currentErrors[tab.id];
169
+ return tabErrorState && Object.keys(tabErrorState).length > 0;
170
+ });
171
+ if (firstTabWithError) {
172
+ submitAttemptedRef.current = false;
173
+ setCurrentTabId(firstTabWithError.id);
174
+ }
175
+ }, []);
176
+
177
+ const highlightFirstErrorTab = useCallback(() => {
178
+ submitAttemptedRef.current = true;
179
+ navigateToFirstErrorTab();
180
+ }, [navigateToFirstErrorTab]);
181
+
182
+ useEffect(() => {
183
+ const { CURRENT_ASSIGNMENT_UPDATED } = PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS;
184
+ PCore.getPubSubUtils().subscribe(
185
+ CURRENT_ASSIGNMENT_UPDATED,
186
+ () => {
187
+ tabErrorsRef.current = {};
188
+ submitAttemptedRef.current = false;
189
+ setTabErrors({});
190
+ },
191
+ 'CURRENT_ASSIGNMENT_UPDATED-HierarchicalForm'
192
+ );
193
+
194
+ PCore.getPubSubUtils().subscribe(
195
+ PCore.getConstants().PUB_SUB_EVENTS.ERROR_ON_FINISH_ASSIGNMENT,
196
+ highlightFirstErrorTab,
197
+ 'ERROR_ON_FINISH_ASSIGNMENT-HierarchicalForm'
198
+ );
199
+
200
+ return () => {
201
+ PCore.getPubSubUtils().unsubscribe(CURRENT_ASSIGNMENT_UPDATED, 'CURRENT_ASSIGNMENT_UPDATED-HierarchicalForm');
202
+ PCore.getPubSubUtils().unsubscribe(
203
+ PCore.getConstants().PUB_SUB_EVENTS.ERROR_ON_FINISH_ASSIGNMENT,
204
+ 'ERROR_ON_FINISH_ASSIGNMENT-HierarchicalForm'
205
+ );
206
+ };
207
+ }, []);
208
+
209
+ useEffect(() => {
210
+ if (submitAttemptedRef.current) {
211
+ navigateToFirstErrorTab();
212
+ }
213
+ }, [tabErrors, navigateToFirstErrorTab]);
214
+
215
+ const processedTabs = useMemo(() => {
216
+ return tabItems.map(tab => {
217
+ const errorKeys = Object.keys(tabErrors[tab.id] ?? {});
218
+ const errors = errorKeys.length > 0 ? errorKeys.reduce((sum, fieldName) => sum + tabErrors[tab.id][fieldName].length, 0) : undefined;
219
+ return { ...tab, errors };
220
+ });
221
+ }, [tabItems, tabErrors]);
222
+
223
+ return { currentTabId, handleTabClick, processedTabs, instructions };
224
+ }
@@ -0,0 +1 @@
1
+ export { default } from './HierarchicalForm';
@@ -60,6 +60,7 @@ interface ListViewProps extends PConnProps {
60
60
  viewName?: string;
61
61
  showRecords?: boolean;
62
62
  displayAs?: string;
63
+ localeReference?: string;
63
64
  }
64
65
 
65
66
  const SELECTION_MODE = { SINGLE: 'single', MULTI: 'multi' };
@@ -89,7 +90,8 @@ export default function ListView(props: ListViewProps) {
89
90
  viewName,
90
91
  readonlyContextList: selectedValues,
91
92
  value,
92
- displayAs
93
+ displayAs,
94
+ localeReference
93
95
  } = props;
94
96
  let { showRecords } = props;
95
97
  const ref = useRef({}).current;
@@ -135,6 +137,9 @@ export default function ListView(props: ListViewProps) {
135
137
 
136
138
  const [selectedValue, setSelectedValue] = useState(value);
137
139
 
140
+ // Tracks selected row keys for multi-select mode (mirrors Angular's SelectionModel)
141
+ const [selectedRowSet, setSelectedRowSet] = useState<Set<string>>(new Set());
142
+
138
143
  // This basically will hold the list of all current filters
139
144
  const filters = useRef({});
140
145
 
@@ -208,6 +213,7 @@ export default function ListView(props: ListViewProps) {
208
213
  getPConnect().getListActions().setSelectedRows({});
209
214
  } else {
210
215
  getPConnect().getListActions().clearSelectedRows();
216
+ setSelectedRowSet(new Set());
211
217
  }
212
218
  }
213
219
  }
@@ -560,6 +566,7 @@ export default function ListView(props: ListViewProps) {
560
566
  const selectParams: any = [];
561
567
 
562
568
  myColumns.forEach(column => {
569
+ column.label = PCore.getLocaleUtils().getLocaleValue(column.label, localeReference);
563
570
  selectParams.push({
564
571
  field: column.id
565
572
  });
@@ -586,6 +593,17 @@ export default function ListView(props: ListViewProps) {
586
593
  if (bCallSetRowsColumns) {
587
594
  setRows(myRows);
588
595
  setColumns(myColumns);
596
+
597
+ if (selectionMode === SELECTION_MODE.MULTI && selectedValues?.length > 0) {
598
+ const readonlyIds = new Set<string>(selectedValues.map((element: any) => element[rowID]));
599
+ const initialSet = new Set<string>();
600
+ myRows?.forEach(row => {
601
+ if (readonlyIds.has(row[rowID])) {
602
+ initialSet.add(row[rowID]);
603
+ }
604
+ });
605
+ setSelectedRowSet(initialSet);
606
+ }
589
607
  }
590
608
 
591
609
  return () => {
@@ -1013,22 +1031,57 @@ export default function ListView(props: ListViewProps) {
1013
1031
  setSelectedValue(value);
1014
1032
  };
1015
1033
 
1016
- const onCheckboxClick = event => {
1017
- const value = event?.target?.value;
1018
- const checked = event?.target?.checked;
1034
+ const getSelectedValue = (row: any, checked: boolean) => {
1035
+ const rowValue = row[rowID];
1019
1036
  const reqObj: any = {};
1020
1037
  if (compositeKeys?.length > 1) {
1021
- const index = response.findIndex(element => element[rowID] === value);
1038
+ const index = response.findIndex(element => element[rowID] === rowValue);
1022
1039
  const selectedRow = response[index];
1023
1040
  compositeKeys.forEach(element => {
1024
1041
  reqObj[element] = selectedRow[element];
1025
1042
  });
1026
1043
  reqObj.$selected = checked;
1027
1044
  } else {
1028
- reqObj[rowID] = value;
1045
+ reqObj[rowID] = rowValue;
1029
1046
  reqObj.$selected = checked;
1030
1047
  }
1031
- getPConnect()?.getListActions()?.setSelectedRows([reqObj]);
1048
+ return reqObj;
1049
+ };
1050
+
1051
+ const onCheckboxClick = (row: any) => {
1052
+ const rowKey = row[rowID];
1053
+ const newSet = new Set(selectedRowSet);
1054
+ if (newSet.has(rowKey)) {
1055
+ newSet.delete(rowKey);
1056
+ } else {
1057
+ newSet.add(rowKey);
1058
+ }
1059
+ setSelectedRowSet(newSet);
1060
+ const checked = newSet.has(rowKey);
1061
+ const requiredValue = getSelectedValue(row, checked);
1062
+ getPConnect()?.getListActions()?.setSelectedRows([requiredValue]);
1063
+ };
1064
+
1065
+ const isAllSelected = (): boolean => {
1066
+ const numSelected = selectedRowSet.size;
1067
+ const numRows = arRows?.length || 0;
1068
+ return numRows > 0 && numSelected === numRows;
1069
+ };
1070
+
1071
+ const toggleAllRows = () => {
1072
+ if (isAllSelected()) {
1073
+ setSelectedRowSet(new Set());
1074
+ getPConnect()?.getListActions()?.clearSelectedRows();
1075
+ return;
1076
+ }
1077
+ if (selectedRowSet.size > 0 && !isAllSelected()) {
1078
+ getPConnect()?.getListActions()?.clearSelectedRows();
1079
+ }
1080
+ const newSet = new Set<string>();
1081
+ arRows.forEach(row => newSet.add(row[rowID]));
1082
+ setSelectedRowSet(newSet);
1083
+ const requiredValues = arRows.map(row => getSelectedValue(row, true));
1084
+ getPConnect()?.getListActions()?.setSelectedRows(requiredValues);
1032
1085
  };
1033
1086
 
1034
1087
  const processColumnValue = (column, value) => {
@@ -1151,7 +1204,16 @@ export default function ListView(props: ListViewProps) {
1151
1204
  <Table>
1152
1205
  <TableHead>
1153
1206
  <TableRow>
1154
- {(selectionMode === SELECTION_MODE.SINGLE || selectionMode === SELECTION_MODE.MULTI) && <TableCell />}
1207
+ {selectionMode === SELECTION_MODE.SINGLE && <TableCell padding='checkbox' />}
1208
+ {selectionMode === SELECTION_MODE.MULTI && (
1209
+ <TableCell padding='checkbox'>
1210
+ <Checkbox
1211
+ indeterminate={selectedRowSet.size > 0 && !isAllSelected()}
1212
+ checked={arRows?.length > 0 && isAllSelected()}
1213
+ onChange={toggleAllRows}
1214
+ />
1215
+ </TableCell>
1216
+ )}
1155
1217
  {arColumns.map(column => {
1156
1218
  return (
1157
1219
  <TableCell className={classes.cell} key={column.id} sortDirection={orderBy === column.id ? order : false}>
@@ -1179,7 +1241,7 @@ export default function ListView(props: ListViewProps) {
1179
1241
  return (
1180
1242
  <TableRow key={row[rowID]}>
1181
1243
  {selectionMode === SELECTION_MODE.SINGLE && (
1182
- <TableCell>
1244
+ <TableCell padding='checkbox'>
1183
1245
  <Radio
1184
1246
  onChange={handleChange}
1185
1247
  value={row[rowID]}
@@ -1190,12 +1252,8 @@ export default function ListView(props: ListViewProps) {
1190
1252
  </TableCell>
1191
1253
  )}
1192
1254
  {selectionMode === SELECTION_MODE.MULTI && (
1193
- <TableCell>
1194
- <Checkbox
1195
- onChange={onCheckboxClick}
1196
- checked={selectedValues.some(selectedValue => selectedValue[rowID] === row[rowID])}
1197
- value={row[rowID]}
1198
- />
1255
+ <TableCell padding='checkbox'>
1256
+ <Checkbox onChange={() => onCheckboxClick(row)} checked={selectedRowSet.has(row[rowID])} />
1199
1257
  </TableCell>
1200
1258
  )}
1201
1259
  {arColumns.map(column => {
@@ -4,12 +4,27 @@ interface MultiReferenceReadOnlyProps extends PConnProps {
4
4
  config: { referenceList: any; readonlyContextList: any };
5
5
  label: string;
6
6
  hideLabel: boolean;
7
+ displayMode?: any;
8
+ displayAs?: any;
7
9
  }
8
10
 
9
11
  export default function MultiReferenceReadOnly(props: MultiReferenceReadOnlyProps) {
10
- const { getPConnect, label = '', hideLabel = false, config } = props;
12
+ const { getPConnect, label = '', hideLabel = false, config, displayMode, displayAs } = props;
11
13
  const { referenceList, readonlyContextList } = config;
12
14
 
15
+ if (['readonlyMulti', 'combobox', 'checkboxgroup'].includes(displayAs)) {
16
+ return getPConnect().createComponent({
17
+ type: 'SimpleTableSelectReadonly',
18
+ config: {
19
+ ...config,
20
+ displayMode,
21
+ label,
22
+ hideLabel,
23
+ displayAs
24
+ }
25
+ } as any);
26
+ }
27
+
13
28
  // When referenceList does not contain selected values, it should be replaced with readonlyContextList while calling SimpleTableManual
14
29
  let readonlyContextObject;
15
30
  if (!PCore.getAnnotationUtils().isProperty(referenceList)) {
@@ -0,0 +1 @@
1
+ export { default } from '../CaseView';
@@ -1,6 +1,5 @@
1
1
  import { Avatar, Card, CardHeader, Divider, Typography } from '@mui/material';
2
2
  import makeStyles from '@mui/styles/makeStyles';
3
- import Grid2 from '@mui/material/Grid2';
4
3
  import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
5
4
  import { prepareCaseSummaryData, filterUtilities } from '@pega/react-sdk-components/lib/components/template/utils';
6
5
  import { Utils } from '@pega/react-sdk-components/lib/components/helpers/utils';
@@ -29,6 +28,16 @@ const useStyles = makeStyles(theme => ({
29
28
  },
30
29
  caseViewIconImage: {
31
30
  filter: 'var(--svg-color)'
31
+ },
32
+ selfServiceCaseViewHeader: {
33
+ margin: '10px 8px 0px 8px',
34
+ height: '50px',
35
+ display: 'flex',
36
+ justifyContent: 'space-between',
37
+ alignItems: 'center',
38
+ backgroundColor: theme.palette.primary.light,
39
+ color: theme.palette.getContrastText(theme.palette.primary.light),
40
+ padding: '0 8px'
32
41
  }
33
42
  }));
34
43
 
@@ -86,11 +95,14 @@ export default function SelfServiceCaseView(props) {
86
95
  return false;
87
96
  };
88
97
 
98
+ const showSummary = bShowSummaryRegion && (primarySummaryFields.length > 0 || secondarySummaryFields.length > 0);
99
+ const showUtilities = bShowUtilitiesRegion && isUtilitiesRegionNotEmpty();
100
+
89
101
  return (
90
102
  <div>
91
- {bShowCaseActions && (
92
- <div style={{ display: 'flex', justifyContent: 'space-around', alignItems: 'center', margin: '10px' }}>
93
- <div>{PCore.getLocaleUtils().getLocaleValue(header, '', localeKey)}</div>
103
+ <div className={classes.selfServiceCaseViewHeader}>
104
+ <div>{PCore.getLocaleUtils().getLocaleValue(header, '', localeKey)}</div>
105
+ {bShowCaseActions && (
94
106
  <CaseViewActionsMenu
95
107
  getPConnect={getPConnect}
96
108
  availableActions={availableActions}
@@ -98,47 +110,43 @@ export default function SelfServiceCaseView(props) {
98
110
  caseTypeName={caseTypeName}
99
111
  caseTypeID={caseTypeID}
100
112
  />
101
- </div>
102
- )}
103
- <div>
104
- <Grid2 container>
105
- <Grid2 size={{ xs: 3 }}>
106
- {bShowSummaryRegion && (primarySummaryFields.length > 0 || secondarySummaryFields.length > 0) && (
107
- <div>
108
- <Card className={classes.root}>
109
- <CardHeader
110
- className={classes.caseViewHeader}
111
- title={
112
- <Typography variant='h6' component='div' id='case-name'>
113
- {PCore.getLocaleUtils().getLocaleValue(header, '', localeKey)}
114
- </Typography>
115
- }
116
- subheader={
117
- <Typography variant='body1' component='div' id='caseId'>
118
- {subheader}
119
- </Typography>
120
- }
121
- avatar={
122
- <Avatar className={classes.caseViewIconBox} variant='square'>
123
- <img src={svgCase} className={classes.caseViewIconImage} />
124
- </Avatar>
125
- }
126
- />
127
- <Divider />
128
- <CaseSummary arPrimaryFields={primarySummaryFields} arSecondaryFields={secondarySummaryFields}></CaseSummary>
129
- <Divider />
130
- </Card>
131
- </div>
132
- )}
133
- </Grid2>
113
+ )}
114
+ </div>
115
+ <div style={{ display: 'flex', flexDirection: 'row' }}>
116
+ {showSummary && (
117
+ <div style={{ flex: '0 0 25%' }}>
118
+ <Card className={classes.root}>
119
+ <CardHeader
120
+ className={classes.caseViewHeader}
121
+ title={
122
+ <Typography variant='h6' component='div' id='case-name'>
123
+ {PCore.getLocaleUtils().getLocaleValue(header, '', localeKey)}
124
+ </Typography>
125
+ }
126
+ subheader={
127
+ <Typography variant='body1' component='div' id='caseId'>
128
+ {subheader}
129
+ </Typography>
130
+ }
131
+ avatar={
132
+ <Avatar className={classes.caseViewIconBox} variant='square'>
133
+ <img src={svgCase} className={classes.caseViewIconImage} />
134
+ </Avatar>
135
+ }
136
+ />
137
+ <Divider />
138
+ <CaseSummary arPrimaryFields={primarySummaryFields} arSecondaryFields={secondarySummaryFields}></CaseSummary>
139
+ <Divider />
140
+ </Card>
141
+ </div>
142
+ )}
134
143
 
135
- <Grid2 size={{ xs: 6 }}>
136
- {bShowCaseLifecycle && renderedRegions.stages}
137
- {renderedRegions.todo}
138
- </Grid2>
144
+ <div style={{ flex: 1 }}>
145
+ {bShowCaseLifecycle && renderedRegions.stages}
146
+ {renderedRegions.todo}
147
+ </div>
139
148
 
140
- {bShowUtilitiesRegion && isUtilitiesRegionNotEmpty() && <Grid2 size={{ xs: 3 }}>{renderedRegions.utilities}</Grid2>}
141
- </Grid2>
149
+ {showUtilities && <div style={{ flex: '0 0 25%' }}>{renderedRegions.utilities}</div>}
142
150
  </div>
143
151
  </div>
144
152
  );
@@ -1,4 +1,4 @@
1
- import React, { type PropsWithChildren, useEffect, useLayoutEffect, useRef, useState } from 'react';
1
+ import React, { type PropsWithChildren, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
2
2
  import Table from '@mui/material/Table';
3
3
  import TableBody from '@mui/material/TableBody';
4
4
  import TableCell from '@mui/material/TableCell';
@@ -28,9 +28,10 @@ import { Utils } from '@pega/react-sdk-components/lib/components/helpers/utils';
28
28
  import { getReferenceList } from '@pega/react-sdk-components/lib/components/helpers/field-group-utils';
29
29
  import { getDataPage } from '@pega/react-sdk-components/lib/components/helpers/data_page';
30
30
  import { getGenericFieldsLocalizedValue } from '@pega/react-sdk-components/lib/components/helpers/common-utils';
31
- import { buildFieldsForTable, filterData, getContext } from '@pega/react-sdk-components/lib/components/helpers/simpleTableHelpers';
31
+ import { buildFieldsForTable, filterData, getConfigFields, getContext } from '@pega/react-sdk-components/lib/components/helpers/simpleTableHelpers';
32
32
  import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps';
33
33
  import { format } from '@pega/react-sdk-components/lib/components/helpers/formatters';
34
+ import { initializeColumns } from '@pega/react-sdk-components/lib/components/template/ListView/utils';
34
35
 
35
36
  interface SimpleTableManualProps extends PConnProps {
36
37
  // If any, enter additional props that only exist on this component
@@ -190,6 +191,8 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
190
191
  const bUseSeparateViewForEdit = editModeConfig ? editModeConfig.useSeparateViewForEdit : useSeparateViewForEdit;
191
192
  const editView = editModeConfig ? editModeConfig.editView : viewForEditModal;
192
193
 
194
+ const configFields = getConfigFields(rawFields, contextClass, primaryFieldsViewIndex);
195
+
193
196
  const fieldsWithPropNames = rawFields.map((field, index) => {
194
197
  return { ...resolvedFields[index], propName: field.config.value.replace('@P .', '') };
195
198
  });
@@ -207,10 +210,15 @@ export default function SimpleTableManual(props: PropsWithChildren<SimpleTableMa
207
210
  // Constellation DX Components do). It will also have the "label", and "meta" contains the original,
208
211
  // unchanged config info. For now, much of the info here is carried over from
209
212
  // Constellation DX Components.
210
- const fieldDefs = buildFieldsForTable(rawFields, getPConnect(), showDeleteButton, {
211
- primaryFieldsViewIndex,
212
- fields: resolvedFields
213
- });
213
+
214
+ const fieldDefs = useMemo(
215
+ () =>
216
+ isDisplayModeEnabled || readOnlyMode
217
+ ? initializeColumns(configFields, undefined)
218
+ : // For inline edit table
219
+ buildFieldsForTable(rawFields, getPConnect(), showDeleteButton, { primaryFieldsViewIndex, fields: resolvedFields }),
220
+ []
221
+ );
214
222
 
215
223
  useLayoutEffect(() => {
216
224
  if (allowEditingInModal) {