@pega/angular-sdk-overrides 0.26.1 → 0.26.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 (133) hide show
  1. package/lib/designSystemExtension/alert/alert.component.html +4 -1
  2. package/lib/designSystemExtension/alert/alert.component.scss +9 -10
  3. package/lib/designSystemExtension/alert/alert.component.ts +6 -2
  4. package/lib/designSystemExtension/field-group/field-group.component.ts +11 -3
  5. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.html +12 -3
  6. package/lib/designSystemExtension/operator/operator.component.ts +2 -1
  7. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.html +104 -10
  8. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.scss +141 -1
  9. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.ts +224 -72
  10. package/lib/field/auto-complete/auto-complete.component.html +46 -5
  11. package/lib/field/auto-complete/auto-complete.component.scss +92 -0
  12. package/lib/field/auto-complete/auto-complete.component.ts +349 -22
  13. package/lib/field/cancel-alert/cancel-alert.component.ts +38 -15
  14. package/lib/field/check-box/check-box.component.html +3 -1
  15. package/lib/field/check-box/check-box.component.ts +10 -1
  16. package/lib/field/currency/currency.component.html +2 -1
  17. package/lib/field/currency/currency.component.ts +10 -1
  18. package/lib/field/date/date.component.html +2 -1
  19. package/lib/field/date/date.component.ts +2 -0
  20. package/lib/field/date-time/date-time.component.html +2 -1
  21. package/lib/field/date-time/date-time.component.scss +46 -40
  22. package/lib/field/date-time/date-time.component.ts +2 -0
  23. package/lib/field/decimal/decimal.component.html +2 -1
  24. package/lib/field/decimal/decimal.component.ts +2 -0
  25. package/lib/field/dropdown/dropdown.component.html +2 -1
  26. package/lib/field/dropdown/dropdown.component.ts +10 -1
  27. package/lib/field/email/email.component.html +2 -1
  28. package/lib/field/email/email.component.ts +2 -2
  29. package/lib/field/field.base.ts +27 -1
  30. package/lib/field/group/group.component.html +1 -1
  31. package/lib/field/group/group.component.ts +1 -3
  32. package/lib/field/integer/integer.component.html +2 -1
  33. package/lib/field/integer/integer.component.ts +4 -2
  34. package/lib/field/location/location.component.html +2 -1
  35. package/lib/field/location/location.component.ts +3 -1
  36. package/lib/field/object-reference/object-reference.component.html +1 -1
  37. package/lib/field/object-reference/object-reference.component.ts +3 -0
  38. package/lib/field/percentage/percentage.component.html +2 -1
  39. package/lib/field/percentage/percentage.component.ts +10 -1
  40. package/lib/field/phone/phone.component.html +2 -1
  41. package/lib/field/phone/phone.component.ts +2 -1
  42. package/lib/field/radio-buttons/radio-buttons.component.html +2 -1
  43. package/lib/field/radio-buttons/radio-buttons.component.ts +10 -1
  44. package/lib/field/rich-text/rich-text.component.scss +1 -166
  45. package/lib/field/rich-text/rich-text.component.ts +1 -1
  46. package/lib/field/semantic-link/semantic-link.component.html +1 -1
  47. package/lib/field/semantic-link/semantic-link.component.scss +4 -0
  48. package/lib/field/semantic-link/semantic-link.component.ts +9 -5
  49. package/lib/field/text-area/text-area.component.html +2 -1
  50. package/lib/field/text-area/text-area.component.ts +2 -1
  51. package/lib/field/text-input/text-input.component.html +2 -1
  52. package/lib/field/text-input/text-input.component.ts +2 -1
  53. package/lib/field/time/time.component.html +2 -1
  54. package/lib/field/time/time.component.ts +2 -1
  55. package/lib/field/url/url.component.html +2 -1
  56. package/lib/field/url/url.component.ts +2 -1
  57. package/lib/field/user-reference/user-reference.component.html +4 -2
  58. package/lib/field/user-reference/user-reference.component.ts +10 -5
  59. package/lib/infra/Containers/flow-container/flow-container.component.html +1 -1
  60. package/lib/infra/Containers/flow-container/flow-container.component.ts +33 -40
  61. package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.html +12 -0
  62. package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.spec.ts +130 -0
  63. package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.ts +77 -0
  64. package/lib/infra/Containers/modal-view-container/modal-view-container.component.html +35 -8
  65. package/lib/infra/Containers/modal-view-container/modal-view-container.component.spec.ts +24 -11
  66. package/lib/infra/Containers/modal-view-container/modal-view-container.component.ts +185 -194
  67. package/lib/infra/Containers/view-container/view-container.component.ts +32 -31
  68. package/lib/infra/assignment/assignment.component.html +2 -1
  69. package/lib/infra/assignment/assignment.component.ts +30 -13
  70. package/lib/infra/defer-load/defer-load.component.ts +6 -3
  71. package/lib/infra/multi-step/multi-step.component.html +25 -33
  72. package/lib/infra/multi-step/multi-step.component.scss +48 -0
  73. package/lib/infra/multi-step/multi-step.component.ts +11 -0
  74. package/lib/infra/navbar/navbar.component.ts +33 -35
  75. package/lib/infra/root-container/root-container.component.ts +33 -38
  76. package/lib/infra/view/view.component.ts +17 -39
  77. package/lib/template/app-shell/app-shell.component.ts +12 -11
  78. package/lib/template/base/details-template-base.ts +35 -53
  79. package/lib/template/case-summary/case-summary.component.ts +15 -1
  80. package/lib/template/case-view/case-view.component.html +13 -1
  81. package/lib/template/case-view/case-view.component.spec.ts +119 -10
  82. package/lib/template/case-view/case-view.component.ts +52 -3
  83. package/lib/template/data-reference/data-reference.component.ts +27 -18
  84. package/lib/template/data-reference/search-form/search-form.component.html +1 -1
  85. package/lib/template/data-reference/search-form/search-form.component.ts +2 -0
  86. package/lib/template/default-form/default-form.component.html +19 -3
  87. package/lib/template/default-form/default-form.component.ts +13 -3
  88. package/lib/template/details/details.component.html +23 -3
  89. package/lib/template/details/details.component.scss +9 -2
  90. package/lib/template/details/details.component.ts +3 -32
  91. package/lib/template/details-narrow-wide/details-narrow-wide.component.html +21 -2
  92. package/lib/template/details-narrow-wide/details-narrow-wide.component.scss +8 -1
  93. package/lib/template/details-narrow-wide/details-narrow-wide.component.ts +3 -37
  94. package/lib/template/details-one-column/details-one-column.component.html +23 -1
  95. package/lib/template/details-one-column/details-one-column.component.scss +14 -0
  96. package/lib/template/details-one-column/details-one-column.component.ts +3 -38
  97. package/lib/template/details-three-column/details-three-column.component.html +21 -2
  98. package/lib/template/details-three-column/details-three-column.component.scss +8 -1
  99. package/lib/template/details-three-column/details-three-column.component.ts +3 -46
  100. package/lib/template/details-two-column/details-two-column.component.html +21 -2
  101. package/lib/template/details-two-column/details-two-column.component.scss +8 -1
  102. package/lib/template/details-two-column/details-two-column.component.ts +3 -44
  103. package/lib/template/details-wide-narrow/details-wide-narrow.component.html +21 -2
  104. package/lib/template/details-wide-narrow/details-wide-narrow.component.scss +8 -1
  105. package/lib/template/details-wide-narrow/details-wide-narrow.component.ts +3 -41
  106. package/lib/template/field-value-list/field-value-list.component.scss +17 -0
  107. package/lib/template/list-view/list-view.component.ts +39 -0
  108. package/lib/template/self-service-case-view/self-service-case-view.component.html +13 -1
  109. package/lib/template/self-service-case-view/self-service-case-view.component.spec.ts +96 -11
  110. package/lib/template/self-service-case-view/self-service-case-view.component.ts +52 -3
  111. package/lib/template/simple-table-manual/helpers.ts +30 -9
  112. package/lib/template/simple-table-manual/simple-table-manual.component.html +30 -14
  113. package/lib/template/simple-table-manual/simple-table-manual.component.scss +4 -0
  114. package/lib/template/simple-table-manual/simple-table-manual.component.ts +118 -29
  115. package/lib/template/single-reference-readonly/single-reference-readonly.component.html +1 -1
  116. package/lib/template/single-reference-readonly/single-reference-readonly.component.scss +2 -2
  117. package/lib/template/single-reference-readonly/single-reference-readonly.component.ts +4 -4
  118. package/lib/template/wss-nav-bar/wss-nav-bar.component.ts +18 -20
  119. package/lib/widget/attachment/AttachmentUtils.ts +18 -10
  120. package/lib/widget/attachment/attachment.component.html +16 -6
  121. package/lib/widget/attachment/attachment.component.ts +12 -2
  122. package/lib/widget/case-history/case-history.component.ts +6 -2
  123. package/lib/widget/file-utility/file-utility.component.ts +25 -29
  124. package/lib/widget/todo/todo.component.ts +7 -2
  125. package/package.json +1 -1
  126. package/lib/designSystemExtension/material-details/material-details.component.html +0 -40
  127. package/lib/designSystemExtension/material-details/material-details.component.scss +0 -116
  128. package/lib/designSystemExtension/material-details/material-details.component.spec.ts +0 -24
  129. package/lib/designSystemExtension/material-details/material-details.component.ts +0 -31
  130. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.html +0 -41
  131. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.scss +0 -34
  132. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.spec.ts +0 -22
  133. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.ts +0 -61
@@ -1,24 +1,109 @@
1
- import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2
-
3
1
  import { SelfServiceCaseViewComponent } from './self-service-case-view.component';
4
2
 
5
3
  describe('SelfServiceCaseViewComponent', () => {
6
4
  let component: SelfServiceCaseViewComponent;
7
- let fixture: ComponentFixture<SelfServiceCaseViewComponent>;
5
+ let actionsApi: { openDataObjectAction: jasmine.Spy; createWork: jasmine.Spy };
6
+ let dataInfoActions: any;
7
+ let configProps: any;
8
+ let dataRecord: any;
8
9
 
9
- beforeEach(waitForAsync(() => {
10
- TestBed.configureTestingModule({
11
- declarations: [SelfServiceCaseViewComponent]
12
- }).compileComponents();
13
- }));
10
+ const utilityChild = {
11
+ getPConnect: () => ({ getRawMetadata: () => ({ type: 'region', name: 'Utilities', children: [] }) })
12
+ };
14
13
 
15
14
  beforeEach(() => {
16
- fixture = TestBed.createComponent(SelfServiceCaseViewComponent);
17
- component = fixture.componentInstance;
18
- fixture.detectChanges();
15
+ (globalThis as any).PCore = {
16
+ getLocaleUtils: () => ({ getLocaleValue: (value: string) => value }),
17
+ getCaseUtils: () => ({ isObjectCaseType: () => false })
18
+ };
19
+
20
+ actionsApi = {
21
+ openDataObjectAction: jasmine.createSpy('openDataObjectAction'),
22
+ createWork: jasmine.createSpy('createWork')
23
+ };
24
+ dataInfoActions = undefined;
25
+ dataRecord = { PlanID: 'P-1' };
26
+ // Summary region is switched off so the test does not depend on case summary metadata.
27
+ configProps = { icon: 'case', header: 'Header', subheader: 'ID-1', showSummaryRegion: false, showCaseActions: true };
28
+
29
+ const utils = {
30
+ getImageSrc: () => '',
31
+ getSDKStaticContentUrl: () => '',
32
+ getBooleanValue: (value: any) => value === true || value === 'true'
33
+ } as any;
34
+
35
+ component = new SelfServiceCaseViewComponent({} as any, utils);
36
+ component.pConn$ = {
37
+ resolveConfigProps: () => configProps,
38
+ getConfigProps: () => configProps,
39
+ getCaseLocaleReference: () => 'MY-CLASS!CASE!MY-CASE',
40
+ getChildren: () => [utilityChild, utilityChild, utilityChild, utilityChild, utilityChild],
41
+ getLocalizationService: () => ({ getLocalizedText: (value: string) => value }),
42
+ getDataObject: () => ({ caseInfo: { ID: 'C-1', availableActions: [], availableProcesses: [] } }),
43
+ getValue: (prop: string, context?: string) => {
44
+ if (prop === '.actions' && context === 'dataInfo') return dataInfoActions;
45
+ if (prop === '.content' && context === 'dataInfo') return dataRecord;
46
+ if (prop === '.classID' && context === 'dataInfo.content') return 'My-Data-Class';
47
+ if (context === '') return dataRecord[prop.slice(1)];
48
+ return undefined;
49
+ },
50
+ getActionsApi: () => actionsApi
51
+ } as any;
52
+ component.localizedVal = (value: string) => value;
19
53
  });
20
54
 
21
55
  it('should create', () => {
22
56
  expect(component).toBeTruthy();
23
57
  });
58
+
59
+ it('lists data object actions published under dataInfo', () => {
60
+ dataInfoActions = {
61
+ availableActions: [{ ID: 'Edit', name: 'Edit' }],
62
+ availableCreateCaseActions: [{ ID: 'My-Work-Class', name: 'Request Plan Change' }]
63
+ };
64
+
65
+ component.fullUpdate();
66
+
67
+ expect(component.arDataObjectActions$.length).toBe(1);
68
+ expect(component.arCreateCaseActions$.length).toBe(1);
69
+ expect(component.bActionsMenuDisabled$).toBeFalse();
70
+ });
71
+
72
+ it('falls back to empty arrays and disables the menu when nothing is available', () => {
73
+ component.fullUpdate();
74
+
75
+ expect(component.arDataObjectActions$).toEqual([]);
76
+ expect(component.arCreateCaseActions$).toEqual([]);
77
+ expect(component.bActionsMenuDisabled$).toBeTrue();
78
+ });
79
+
80
+ it('keeps honouring the showCaseActions configuration flag', () => {
81
+ configProps = { ...configProps, showCaseActions: false };
82
+
83
+ component.fullUpdate();
84
+
85
+ expect(component.showCaseActions).toBeFalse();
86
+ });
87
+
88
+ it('preserves the case locale reference used for action labels', () => {
89
+ component.fullUpdate();
90
+
91
+ expect(component.localeKey).toBe('MY-CLASS!CASE!MY-CASE');
92
+ });
93
+
94
+ it('opens a data object action with the record class and content', () => {
95
+ component._menuDataObjectActionClick({ ID: 'updateCVV', name: 'Update CVV' });
96
+
97
+ expect(actionsApi.openDataObjectAction).toHaveBeenCalledWith('My-Data-Class', dataRecord, 'updateCVV', 'Update CVV');
98
+ });
99
+
100
+ it('starts a new case with starting fields nested under the target reference field', () => {
101
+ component._menuCreateCaseActionClick({
102
+ ID: 'My-Work-Class',
103
+ name: 'Request Plan Change',
104
+ targetDataReferenceField: { field: 'PlanRef', inputs: [{ linkedField: 'PlanID' }] }
105
+ });
106
+
107
+ expect(actionsApi.createWork).toHaveBeenCalledWith('My-Work-Class', { startingFields: { PlanRef: { PlanID: 'P-1' } } });
108
+ });
24
109
  });
@@ -9,6 +9,7 @@ import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-c
9
9
  import { Utils } from '@pega/angular-sdk-components';
10
10
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
11
11
  import { prepareCaseSummaryData } from '@pega/angular-sdk-components';
12
+ import { CreateCaseAction, DataObjectAction, DataObjectActions } from '@pega/angular-sdk-components';
12
13
 
13
14
  interface SelfServiceCaseViewProps {
14
15
  // If any, enter additional props that only exist on this component
@@ -45,6 +46,9 @@ export class SelfServiceCaseViewComponent implements OnInit, OnDestroy {
45
46
 
46
47
  arAvailableActions$: any[] = [];
47
48
  arAvailabeProcesses$: any[] = [];
49
+ arDataObjectActions$: DataObjectAction[] = [];
50
+ arCreateCaseActions$: CreateCaseAction[] = [];
51
+ bActionsMenuDisabled$ = true;
48
52
 
49
53
  caseSummaryPConn$: any;
50
54
  currentCaseID = '';
@@ -102,10 +106,31 @@ export class SelfServiceCaseViewComponent implements OnInit, OnDestroy {
102
106
  sessionStorage.setItem('okToInitFlowContainer', 'true');
103
107
  } else {
104
108
  this.updateHeaderAndSummary();
109
+ this.updateCaseActions();
105
110
  }
106
111
  }
107
112
  }
108
113
 
114
+ // React re-reads every action source on each render. Here fullUpdate is gated on a case ID
115
+ // change and so runs once, while actions (and a data object's `dataInfo.actions`) arrive
116
+ // later, so they are all refreshed on every store update instead.
117
+ updateCaseActions() {
118
+ const caseInfo = this.pConn$.getDataObject()?.caseInfo ?? {};
119
+ this.arAvailableActions$ = caseInfo.availableActions ?? [];
120
+ this.arAvailabeProcesses$ = caseInfo.availableProcesses ?? [];
121
+ this.editAction = this.arAvailableActions$.find(action => action.ID === 'pyUpdateCaseDetails');
122
+
123
+ const dataInfoActions: DataObjectActions = this.pConn$.getValue('.actions', 'dataInfo') ?? {};
124
+ this.arDataObjectActions$ = dataInfoActions.availableActions ?? [];
125
+ this.arCreateCaseActions$ = dataInfoActions.availableCreateCaseActions ?? [];
126
+
127
+ this.bActionsMenuDisabled$ =
128
+ this.arAvailableActions$.length === 0 &&
129
+ this.arAvailabeProcesses$.length === 0 &&
130
+ this.arDataObjectActions$.length === 0 &&
131
+ this.arCreateCaseActions$.length === 0;
132
+ }
133
+
109
134
  hasCaseIDChanged(): boolean {
110
135
  if (this.currentCaseID !== this.pConn$.getDataObject().caseInfo.ID) {
111
136
  this.currentCaseID = this.pConn$.getDataObject().caseInfo.ID;
@@ -144,9 +169,8 @@ export class SelfServiceCaseViewComponent implements OnInit, OnDestroy {
144
169
 
145
170
  const caseInfo = this.pConn$.getDataObject().caseInfo;
146
171
  this.currentCaseID = caseInfo.ID;
147
- this.arAvailableActions$ = caseInfo?.availableActions ? caseInfo.availableActions : [];
148
- this.editAction = this.arAvailableActions$.find(action => action.ID === 'pyUpdateCaseDetails');
149
- this.arAvailabeProcesses$ = caseInfo?.availableProcesses ? caseInfo.availableProcesses : [];
172
+
173
+ this.updateCaseActions();
150
174
 
151
175
  const { showCaseLifecycle = true, showSummaryRegion = true, showUtilitiesRegion = true, showCaseActions = true, caseClass } = this.configProps$;
152
176
  this.showCaseLifecycle = this.utils.getBooleanValue(showCaseLifecycle);
@@ -204,4 +228,29 @@ export class SelfServiceCaseViewComponent implements OnInit, OnDestroy {
204
228
 
205
229
  openProcessAction(data.ID, { ...data });
206
230
  }
231
+
232
+ _menuDataObjectActionClick(action: DataObjectAction) {
233
+ const actionsAPI = this.pConn$.getActionsApi();
234
+ const openDataObjectAction = actionsAPI.openDataObjectAction.bind(actionsAPI);
235
+ const classID = this.pConn$.getValue('.classID', 'dataInfo.content');
236
+ const dataRecord = this.pConn$.getValue('.content', 'dataInfo');
237
+
238
+ openDataObjectAction(classID, dataRecord, action.ID, this.localizedVal(action.name, '', this.localeKey));
239
+ }
240
+
241
+ _menuCreateCaseActionClick(action: CreateCaseAction) {
242
+ const actionsAPI = this.pConn$.getActionsApi();
243
+ const createWork = actionsAPI.createWork.bind(actionsAPI);
244
+ const { field, inputs } = action.targetDataReferenceField ?? {};
245
+ const startingFields: Record<string, any> = {};
246
+
247
+ // The engine expects the linked values nested under the target reference field.
248
+ if (field) {
249
+ inputs?.forEach(input => {
250
+ startingFields[field] = { ...startingFields[field], [input.linkedField]: this.pConn$.getValue(`.${input.linkedField}`, '') };
251
+ });
252
+ }
253
+
254
+ createWork(action.ID, { startingFields });
255
+ }
207
256
  }
@@ -148,12 +148,33 @@ const SUPPORTED_FIELD_TYPES = [
148
148
  'RichText'
149
149
  ];
150
150
 
151
+ // PCore.getNameSpaceUtils() exists at runtime but is missing from the pcore typedefs.
152
+ export const getQualifiedPrimaryFieldsName = (): string =>
153
+ (PCore as any).getNameSpaceUtils?.()?.getDefaultQualifiedName(PRIMARY_FIELDS) ?? PRIMARY_FIELDS;
154
+
155
+ export const isPrimaryFieldsValue = (value): boolean => value === PRIMARY_FIELDS || value === getQualifiedPrimaryFieldsName();
156
+
157
+ /**
158
+ * Strips annotation prefixes (ex: "@P .FirstName") and the leading dot from a raw config value.
159
+ */
160
+ export const getPropertyNameFromConfigValue = (configValue): string => {
161
+ let name = configValue ?? '';
162
+ if (name.startsWith('@')) {
163
+ name = name.substring(name.indexOf(' ') + 1);
164
+ }
165
+ if (name.startsWith('.')) {
166
+ name = name.substring(1);
167
+ }
168
+ return name;
169
+ };
170
+
151
171
  export const getConfigFields = (rawFields, contextClass, primaryFieldsViewIndex) => {
152
172
  let primaryFields: any = [];
153
173
  let configFields: any = [];
174
+ const safeRawFields = rawFields || [];
154
175
 
155
176
  if (primaryFieldsViewIndex > -1) {
156
- let primaryFieldVMD: any = PCore.getMetadataUtils().resolveView(PRIMARY_FIELDS);
177
+ let primaryFieldVMD: any = PCore.getMetadataUtils().resolveView(getQualifiedPrimaryFieldsName());
157
178
  if (Array.isArray(primaryFieldVMD)) {
158
179
  primaryFieldVMD = primaryFieldVMD.find(primaryFieldView => primaryFieldView.classID === contextClass);
159
180
  primaryFields = primaryFieldVMD?.children?.[0]?.children || [];
@@ -166,7 +187,7 @@ export const getConfigFields = (rawFields, contextClass, primaryFieldsViewIndex)
166
187
  }
167
188
  }
168
189
 
169
- configFields = [...rawFields.slice(0, primaryFieldsViewIndex), ...primaryFields, ...rawFields.slice(primaryFieldsViewIndex + 1)];
190
+ configFields = [...safeRawFields.slice(0, primaryFieldsViewIndex), ...primaryFields, ...safeRawFields.slice(primaryFieldsViewIndex + 1)];
170
191
  // filter duplicate fields after combining raw fields and primary fields
171
192
  return configFields.filter((field, index) => configFields.findIndex(_field => field.config?.value === _field.config?.value) === index);
172
193
  };
@@ -200,7 +221,7 @@ export const updateFieldLabels = (fields, configFields, primaryFieldsViewIndex,
200
221
  const { columnsRawConfig = [] } = options;
201
222
  fields.forEach((field, idx) => {
202
223
  const rawColumnConfig = columnsRawConfig[idx]?.config;
203
- if (field.config.value === PRIMARY_FIELDS) {
224
+ if (isPrimaryFieldsValue(field.config.value)) {
204
225
  labelsOfFields.push('');
205
226
  } else if (isFLProperty(rawColumnConfig?.label ?? rawColumnConfig?.caption)) {
206
227
  labelsOfFields.push(getFieldLabel(rawColumnConfig) || field.config.label || field.config.caption);
@@ -217,7 +238,7 @@ export const updateFieldLabels = (fields, configFields, primaryFieldsViewIndex,
217
238
  let label = configFields[i].config?.label;
218
239
  if (isFLProperty(label)) {
219
240
  label = getFieldLabel(configFields[i].config);
220
- } else if (label.startsWith('@')) {
241
+ } else if (label?.startsWith('@')) {
221
242
  label = label.substring(3);
222
243
  }
223
244
  if (pConnect) {
@@ -233,7 +254,7 @@ export const updateFieldLabels = (fields, configFields, primaryFieldsViewIndex,
233
254
  return labelsOfFields;
234
255
  };
235
256
 
236
- export const buildFieldsForTable = (configFields, pConnect, showDeleteButton, options) => {
257
+ export const buildFieldsForTable = (configFields, pConnect, showActionColumn, options) => {
237
258
  const { primaryFieldsViewIndex, fields } = options;
238
259
 
239
260
  // get resolved field labels for primary fields raw config included in configFields
@@ -247,7 +268,7 @@ export const buildFieldsForTable = (configFields, pConnect, showDeleteButton, op
247
268
  label: fieldsLabels[index],
248
269
  fillAvailableSpace: !!field.config.fillAvailableSpace,
249
270
  id: `${index}`,
250
- name: field.config.value.substr(4),
271
+ name: getPropertyNameFromConfigValue(field.config.value),
251
272
  cellRenderer: TABLE_CELL,
252
273
  sort: false,
253
274
  noContextMenu: true,
@@ -256,12 +277,12 @@ export const buildFieldsForTable = (configFields, pConnect, showDeleteButton, op
256
277
  ...field
257
278
  },
258
279
  // BUG-615253: Workaround for autosize in table with lazy loading components
259
- width: getFieldWidth(field, fields[index].config.label)
280
+ width: getFieldWidth(field, fieldsLabels[index])
260
281
  };
261
282
  });
262
283
 
263
- // ONLY add DELETE_ICON to fields when the table is requested as EDITABLE
264
- if (showDeleteButton) {
284
+ // Add the action column when either edit or delete is available.
285
+ if (showActionColumn) {
265
286
  fieldDefs.push({
266
287
  type: 'text',
267
288
  label: '',
@@ -3,7 +3,14 @@
3
3
  <h3 *ngIf="label" className="label" style="font-weight: bold">
4
4
  {{ label }} <span class="results-count">{{ getResultsText() }}</span>
5
5
  </h3>
6
- <table *ngIf="readOnlyMode || allowEditingInModal" mat-table [dataSource]="elementsData" class="mat-elevation-z8" id="readonly-table" matSort>
6
+ <table
7
+ *ngIf="readOnlyMode || allowEditingInModal || hideEditRow"
8
+ mat-table
9
+ [dataSource]="elementsData"
10
+ class="mat-elevation-z8"
11
+ id="readonly-table"
12
+ matSort
13
+ >
7
14
  <ng-container *ngFor="let dCol of processedFields; let i = index" [matColumnDef]="dCol.config.name">
8
15
  <th mat-header-cell *matHeaderCellDef mat-sort-header (click)="_headerSortClick($event, dCol)" arrowPosition="before">
9
16
  <div>{{ dCol.config.label }}</div>
@@ -39,20 +46,25 @@
39
46
  </td>
40
47
  </ng-container>
41
48
  <ng-container matColumnDef="DeleteIcon">
42
- <div *ngIf="allowEditingInModal">
43
- <th mat-header-cell *matHeaderCellDef></th>
44
- <td mat-cell *matCellDef="let element; index as j">
45
- <div class="header-icon">
49
+ <th mat-header-cell *matHeaderCellDef></th>
50
+ <td mat-cell *matCellDef="let element; index as j">
51
+ <ng-container *ngIf="allowEditingInModal; else deleteOnly">
52
+ <div *ngIf="rowActions[j]?.hasAnyAction" class="header-icon">
46
53
  <button mat-icon-button [matMenuTriggerFor]="utilityMenu">
47
54
  <mat-icon>more_vert</mat-icon>
48
55
  </button>
49
56
  <mat-menu #utilityMenu="matMenu" overlapTrigger="false">
50
- <button mat-menu-item (click)="editRecord(element, j)">Edit</button>
51
- <button mat-menu-item (click)="deleteRecord(j)">Delete</button>
57
+ <button *ngIf="rowActions[j]?.canEdit" mat-menu-item (click)="editRecord(element, element.__originalIndex)">Edit</button>
58
+ <button *ngIf="rowActions[j]?.canDelete" mat-menu-item (click)="deleteRecord(element.__originalIndex)">Delete</button>
52
59
  </mat-menu>
53
60
  </div>
54
- </td>
55
- </div>
61
+ </ng-container>
62
+ <ng-template #deleteOnly>
63
+ <button *ngIf="rowActions[j]?.canDelete" id="delete-button" mat-icon-button (click)="deleteRecord(j)">
64
+ <mat-icon>delete</mat-icon>
65
+ </button>
66
+ </ng-template>
67
+ </td>
56
68
  </ng-container>
57
69
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
58
70
  <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
@@ -62,7 +74,13 @@
62
74
  </td>
63
75
  </tr>
64
76
  </table>
65
- <table *ngIf="editableMode && !allowEditingInModal" mat-table [dataSource]="elementsData" class="mat-elevation-z8" id="editable-table">
77
+ <table
78
+ *ngIf="editableMode && !allowEditingInModal && !hideEditRow"
79
+ mat-table
80
+ [dataSource]="elementsData"
81
+ class="mat-elevation-z8"
82
+ id="editable-table"
83
+ >
66
84
  <ng-container *ngFor="let dCol of fieldDefs; let i = index">
67
85
  <ng-container *ngIf="dCol.name != 'DeleteIcon'" [matColumnDef]="dCol.name">
68
86
  <th mat-header-cell *matHeaderCellDef class="psdk-mat-header">{{ dCol.label }}</th>
@@ -81,7 +99,7 @@
81
99
  <ng-container matColumnDef="DeleteIcon">
82
100
  <th mat-header-cell *matHeaderCellDef></th>
83
101
  <td mat-cell *matCellDef="let element; index as j">
84
- <button id="delete-button" mat-icon-button (click)="deleteRecord(j)">
102
+ <button *ngIf="rowActions[j]?.canDelete" id="delete-button" mat-icon-button (click)="deleteRecord(j)">
85
103
  <mat-icon>delete</mat-icon>
86
104
  </button>
87
105
  </td>
@@ -95,9 +113,7 @@
95
113
  </tr>
96
114
  </table>
97
115
  </div>
98
- <button *ngIf="showAddRowButton" mat-button color="primary" style="font-size: 16px" (click)="addRecord()">
99
- + {{ localizedVal('Add', localeCategory) }}
100
- </button>
116
+ <button *ngIf="showAddRowButton" mat-button color="primary" style="font-size: 16px" (click)="addRecord()">+ {{ addButtonLabel$ }}</button>
101
117
  </ng-container>
102
118
 
103
119
  <!-- pop overs for filters-->
@@ -165,6 +165,10 @@ tr.mat-mdc-header-row {
165
165
  text-align: center;
166
166
  border: 1px solid var(--mat-sys-outline-variant);
167
167
  border-top: none;
168
+
169
+ td.mat-cell {
170
+ text-align: center;
171
+ }
168
172
  }
169
173
 
170
174
  .psdk-utility-card-action-svg-icon {