@pega/angular-sdk-overrides 0.26.2 → 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.
- package/lib/designSystemExtension/field-group/field-group.component.ts +11 -3
- package/lib/designSystemExtension/material-case-summary/material-case-summary.component.html +12 -3
- package/lib/field/auto-complete/auto-complete.component.html +44 -4
- package/lib/field/auto-complete/auto-complete.component.scss +92 -0
- package/lib/field/auto-complete/auto-complete.component.ts +341 -16
- package/lib/field/cancel-alert/cancel-alert.component.ts +38 -15
- package/lib/field/group/group.component.html +1 -1
- package/lib/field/group/group.component.ts +1 -3
- package/lib/field/semantic-link/semantic-link.component.html +1 -1
- package/lib/field/semantic-link/semantic-link.component.scss +4 -0
- package/lib/infra/Containers/flow-container/flow-container.component.html +1 -1
- package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.html +12 -0
- package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.spec.ts +130 -0
- package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.ts +77 -0
- package/lib/infra/Containers/modal-view-container/modal-view-container.component.html +35 -8
- package/lib/infra/Containers/modal-view-container/modal-view-container.component.spec.ts +24 -11
- package/lib/infra/Containers/modal-view-container/modal-view-container.component.ts +179 -184
- package/lib/infra/assignment/assignment.component.html +2 -1
- package/lib/infra/assignment/assignment.component.ts +30 -13
- package/lib/infra/defer-load/defer-load.component.ts +6 -3
- package/lib/infra/multi-step/multi-step.component.html +25 -33
- package/lib/infra/multi-step/multi-step.component.scss +48 -0
- package/lib/infra/multi-step/multi-step.component.ts +11 -0
- package/lib/infra/view/view.component.ts +17 -39
- package/lib/template/base/details-template-base.ts +35 -54
- package/lib/template/case-summary/case-summary.component.ts +15 -1
- package/lib/template/case-view/case-view.component.html +13 -1
- package/lib/template/case-view/case-view.component.spec.ts +119 -10
- package/lib/template/case-view/case-view.component.ts +52 -3
- package/lib/template/data-reference/data-reference.component.ts +27 -18
- package/lib/template/data-reference/search-form/search-form.component.html +1 -1
- package/lib/template/data-reference/search-form/search-form.component.ts +2 -0
- package/lib/template/details/details.component.html +23 -3
- package/lib/template/details/details.component.scss +9 -2
- package/lib/template/details/details.component.ts +3 -32
- package/lib/template/details-narrow-wide/details-narrow-wide.component.html +21 -2
- package/lib/template/details-narrow-wide/details-narrow-wide.component.scss +8 -1
- package/lib/template/details-narrow-wide/details-narrow-wide.component.ts +3 -37
- package/lib/template/details-one-column/details-one-column.component.html +23 -1
- package/lib/template/details-one-column/details-one-column.component.scss +14 -0
- package/lib/template/details-one-column/details-one-column.component.ts +3 -38
- package/lib/template/details-three-column/details-three-column.component.html +21 -2
- package/lib/template/details-three-column/details-three-column.component.scss +8 -1
- package/lib/template/details-three-column/details-three-column.component.ts +3 -46
- package/lib/template/details-two-column/details-two-column.component.html +21 -2
- package/lib/template/details-two-column/details-two-column.component.scss +8 -1
- package/lib/template/details-two-column/details-two-column.component.ts +3 -44
- package/lib/template/details-wide-narrow/details-wide-narrow.component.html +21 -2
- package/lib/template/details-wide-narrow/details-wide-narrow.component.scss +8 -1
- package/lib/template/details-wide-narrow/details-wide-narrow.component.ts +3 -41
- package/lib/template/field-value-list/field-value-list.component.scss +17 -0
- package/lib/template/list-view/list-view.component.ts +39 -0
- package/lib/template/self-service-case-view/self-service-case-view.component.html +13 -1
- package/lib/template/self-service-case-view/self-service-case-view.component.spec.ts +96 -11
- package/lib/template/self-service-case-view/self-service-case-view.component.ts +52 -3
- package/lib/template/simple-table-manual/helpers.ts +27 -6
- package/lib/template/simple-table-manual/simple-table-manual.component.html +1 -3
- package/lib/template/simple-table-manual/simple-table-manual.component.scss +4 -0
- package/lib/template/simple-table-manual/simple-table-manual.component.ts +51 -20
- package/lib/template/single-reference-readonly/single-reference-readonly.component.scss +0 -4
- package/package.json +1 -1
- package/lib/designSystemExtension/material-details/material-details.component.html +0 -40
- package/lib/designSystemExtension/material-details/material-details.component.scss +0 -116
- package/lib/designSystemExtension/material-details/material-details.component.spec.ts +0 -24
- package/lib/designSystemExtension/material-details/material-details.component.ts +0 -31
- package/lib/designSystemExtension/material-details-fields/material-details-fields.component.html +0 -50
- package/lib/designSystemExtension/material-details-fields/material-details-fields.component.scss +0 -34
- package/lib/designSystemExtension/material-details-fields/material-details-fields.component.spec.ts +0 -22
- package/lib/designSystemExtension/material-details-fields/material-details-fields.component.ts +0 -61
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Component, forwardRef } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
2
3
|
import { ComponentMapperComponent } from '@pega/angular-sdk-components';
|
|
3
4
|
import { DetailsTemplateBase } from '@pega/angular-sdk-components';
|
|
4
5
|
|
|
@@ -6,45 +7,6 @@ import { DetailsTemplateBase } from '@pega/angular-sdk-components';
|
|
|
6
7
|
selector: 'app-details-wide-narrow',
|
|
7
8
|
templateUrl: './details-wide-narrow.component.html',
|
|
8
9
|
styleUrls: ['./details-wide-narrow.component.scss'],
|
|
9
|
-
imports: [forwardRef(() => ComponentMapperComponent)]
|
|
10
|
+
imports: [CommonModule, forwardRef(() => ComponentMapperComponent)]
|
|
10
11
|
})
|
|
11
|
-
export class DetailsWideNarrowComponent extends DetailsTemplateBase {
|
|
12
|
-
override pConn$: typeof PConnect;
|
|
13
|
-
|
|
14
|
-
highlightedDataArr: any[] = [];
|
|
15
|
-
showHighlightedData: boolean;
|
|
16
|
-
arFields$: any[] = [];
|
|
17
|
-
arFields2$: any[] = [];
|
|
18
|
-
propsToUse: any = {};
|
|
19
|
-
|
|
20
|
-
override updateSelf() {
|
|
21
|
-
const rawMetaData: any = this.pConn$.resolveConfigProps(this.pConn$.getRawMetadata()?.config);
|
|
22
|
-
this.showHighlightedData = rawMetaData?.showHighlightedData;
|
|
23
|
-
|
|
24
|
-
if (this.showHighlightedData) {
|
|
25
|
-
const highlightedData = rawMetaData?.highlightedData;
|
|
26
|
-
this.highlightedDataArr = highlightedData.map(field => {
|
|
27
|
-
field.config.displayMode = 'STACKED_LARGE_VAL';
|
|
28
|
-
|
|
29
|
-
if (field.config.value === '@P .pyStatusWork') {
|
|
30
|
-
field.type = 'TextInput';
|
|
31
|
-
field.config.displayAsStatus = true;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return field;
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
this.pConn$.setInheritedProp('displayMode', 'DISPLAY_ONLY');
|
|
39
|
-
this.pConn$.setInheritedProp('readOnly', true);
|
|
40
|
-
|
|
41
|
-
const kids = this.pConn$.getChildren() as any[];
|
|
42
|
-
for (const kid of kids) {
|
|
43
|
-
if (kids.indexOf(kid) == 0) {
|
|
44
|
-
this.arFields$ = this.processDetailFields(kid);
|
|
45
|
-
} else {
|
|
46
|
-
this.arFields2$ = this.processDetailFields(kid);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
12
|
+
export class DetailsWideNarrowComponent extends DetailsTemplateBase {}
|
|
@@ -21,3 +21,20 @@
|
|
|
21
21
|
.psdk-val-labels-left {
|
|
22
22
|
white-space: break-spaces;
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
.psdk-container-stacked-large-val {
|
|
26
|
+
margin: 8px 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.psdk-container-stacked-large-val .psdk-grid-label {
|
|
30
|
+
color: rgba(0, 0, 0, 0.6);
|
|
31
|
+
font-size: 0.875rem;
|
|
32
|
+
font-weight: 400;
|
|
33
|
+
line-height: 1.5;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.psdk-val-stacked {
|
|
37
|
+
color: rgba(0, 0, 0, 0.87);
|
|
38
|
+
font-size: 1.25rem;
|
|
39
|
+
line-height: 1.5;
|
|
40
|
+
}
|
|
@@ -18,6 +18,7 @@ import { DragDropModule, CdkDragDrop, moveItemInArray, CdkDropList, CdkDrag } fr
|
|
|
18
18
|
import { ProgressSpinnerService } from '@pega/angular-sdk-components';
|
|
19
19
|
import { Utils } from '@pega/angular-sdk-components';
|
|
20
20
|
import { ComponentMapperComponent } from '@pega/angular-sdk-components';
|
|
21
|
+
import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
|
|
21
22
|
import { getCurrencyOptions } from '@pega/angular-sdk-components';
|
|
22
23
|
import { getLocale, getSeconds } from '@pega/angular-sdk-components';
|
|
23
24
|
import { formatters } from '@pega/angular-sdk-components';
|
|
@@ -162,18 +163,28 @@ export class ListViewComponent implements OnInit, OnDestroy {
|
|
|
162
163
|
paging: any;
|
|
163
164
|
fieldDefs: any;
|
|
164
165
|
checkBoxValue: string;
|
|
166
|
+
// Last value seen on the bound property, used to detect external changes.
|
|
167
|
+
lastSelectedPropValue: any;
|
|
165
168
|
label?: string = '';
|
|
166
169
|
uniqueId = crypto.randomUUID();
|
|
167
170
|
displayAs: any;
|
|
168
171
|
showRecords: any;
|
|
169
172
|
identifier: string;
|
|
170
173
|
promotedFiltersId: string;
|
|
174
|
+
|
|
175
|
+
// Used with AngularPConnect
|
|
176
|
+
angularPConnectData: AngularPConnectData = {};
|
|
177
|
+
|
|
171
178
|
constructor(
|
|
179
|
+
private angularPConnect: AngularPConnectService,
|
|
172
180
|
private psService: ProgressSpinnerService,
|
|
173
181
|
public utils: Utils
|
|
174
182
|
) {}
|
|
175
183
|
|
|
176
184
|
ngOnInit(): void {
|
|
185
|
+
// First thing in initialization is registering and subscribing to the AngularPConnect service
|
|
186
|
+
this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
|
|
187
|
+
|
|
177
188
|
this.configProps$ = this.pConn$.getConfigProps() as ListViewProps;
|
|
178
189
|
/** By default, pyGUID is used for Data classes and pyID is for Work classes as row-id/key */
|
|
179
190
|
const defRowID = this.configProps$?.referenceType === 'Case' ? 'pyID' : 'pyGUID';
|
|
@@ -197,6 +208,7 @@ export class ListViewComponent implements OnInit, OnDestroy {
|
|
|
197
208
|
this.selectionMode = this.configProps$.selectionMode;
|
|
198
209
|
|
|
199
210
|
this.checkBoxValue = this.configProps$.value;
|
|
211
|
+
this.lastSelectedPropValue = this.configProps$.value;
|
|
200
212
|
|
|
201
213
|
this.arFilterMainButtons$.push({ actionID: 'submit', jsAction: 'submit', name: 'Submit' });
|
|
202
214
|
this.arFilterSecondaryButtons$.push({ actionID: 'cancel', jsAction: 'cancel', name: 'Cancel' });
|
|
@@ -266,6 +278,29 @@ export class ListViewComponent implements OnInit, OnDestroy {
|
|
|
266
278
|
this.clearSelectionsAndUpdateTable(this.pConn$, this.uniqueId, this.configProps$?.viewName);
|
|
267
279
|
}
|
|
268
280
|
|
|
281
|
+
onStateChange() {
|
|
282
|
+
// Should always check the bridge to see if the component should
|
|
283
|
+
// update itself (re-render)
|
|
284
|
+
const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this);
|
|
285
|
+
|
|
286
|
+
// ONLY call updateSelf when the component should update
|
|
287
|
+
if (bUpdateSelf) {
|
|
288
|
+
this.updateSelf();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
updateSelf(): void {
|
|
293
|
+
// The selected row is driven by the bound property, which another field on the screen may change.
|
|
294
|
+
const latestConfigProps = this.pConn$.getConfigProps() as ListViewProps;
|
|
295
|
+
const latestValue = latestConfigProps?.value;
|
|
296
|
+
|
|
297
|
+
// Only re-sync on an actual property change, so a row the user just picked is not reverted.
|
|
298
|
+
if (this.selectionMode === SELECTION_MODE.SINGLE && latestValue !== this.lastSelectedPropValue) {
|
|
299
|
+
this.lastSelectedPropValue = latestValue;
|
|
300
|
+
this.checkBoxValue = latestValue;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
269
304
|
clearSelectionsAndUpdateTable(getPConnect: any, uniqueId: string, viewName): void {
|
|
270
305
|
const clearSelectionsAndRefreshList = ({ viewName: name, clearSelections }: any) => {
|
|
271
306
|
if (name === viewName) {
|
|
@@ -487,6 +522,10 @@ export class ListViewComponent implements OnInit, OnDestroy {
|
|
|
487
522
|
// }
|
|
488
523
|
|
|
489
524
|
ngOnDestroy() {
|
|
525
|
+
if (this.angularPConnectData.unsubscribeFn) {
|
|
526
|
+
this.angularPConnectData.unsubscribeFn();
|
|
527
|
+
}
|
|
528
|
+
|
|
490
529
|
PCore.getPubSubUtils().unsubscribe(
|
|
491
530
|
PCore.getConstants().PUB_SUB_EVENTS.EVENT_DASHBOARD_FILTER_CHANGE,
|
|
492
531
|
`dashboard-component-${'id'}`,
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
<div class="psdk-self-service-case-view-header">
|
|
3
3
|
<div class="heading">{{ this.heading$ }}</div>
|
|
4
4
|
<div *ngIf="showCaseActions" class="psdk-case-view-buttons">
|
|
5
|
-
<button mat-raised-button color="secondary" [matMenuTriggerFor]="actionMenu"
|
|
5
|
+
<button mat-raised-button color="secondary" [matMenuTriggerFor]="actionMenu" [disabled]="bActionsMenuDisabled$">
|
|
6
|
+
{{ localizedVal('Actions...', localeCategory) }}
|
|
7
|
+
</button>
|
|
6
8
|
<mat-menu #actionMenu="matMenu" overlapTrigger="false">
|
|
7
9
|
<ng-container *ngFor="let action of arAvailableActions$">
|
|
8
10
|
<button mat-menu-item (click)="_menuActionClick(action)">
|
|
@@ -14,6 +16,16 @@
|
|
|
14
16
|
{{ process.name }}
|
|
15
17
|
</button>
|
|
16
18
|
</ng-container>
|
|
19
|
+
<ng-container *ngFor="let action of arDataObjectActions$">
|
|
20
|
+
<button mat-menu-item (click)="_menuDataObjectActionClick(action)">
|
|
21
|
+
{{ localizedVal(action.name, '', localeKey) }}
|
|
22
|
+
</button>
|
|
23
|
+
</ng-container>
|
|
24
|
+
<ng-container *ngFor="let action of arCreateCaseActions$">
|
|
25
|
+
<button mat-menu-item (click)="_menuCreateCaseActionClick(action)">
|
|
26
|
+
{{ localizedVal(action.name, '', localeKey) }}
|
|
27
|
+
</button>
|
|
28
|
+
</ng-container>
|
|
17
29
|
</mat-menu>
|
|
18
30
|
</div>
|
|
19
31
|
</div>
|
|
@@ -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
|
|
5
|
+
let actionsApi: { openDataObjectAction: jasmine.Spy; createWork: jasmine.Spy };
|
|
6
|
+
let dataInfoActions: any;
|
|
7
|
+
let configProps: any;
|
|
8
|
+
let dataRecord: any;
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}).compileComponents();
|
|
13
|
-
}));
|
|
10
|
+
const utilityChild = {
|
|
11
|
+
getPConnect: () => ({ getRawMetadata: () => ({ type: 'region', name: 'Utilities', children: [] }) })
|
|
12
|
+
};
|
|
14
13
|
|
|
15
14
|
beforeEach(() => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
148
|
-
this.
|
|
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(
|
|
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 = [...
|
|
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
|
|
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
|
|
241
|
+
} else if (label?.startsWith('@')) {
|
|
221
242
|
label = label.substring(3);
|
|
222
243
|
}
|
|
223
244
|
if (pConnect) {
|
|
@@ -247,7 +268,7 @@ export const buildFieldsForTable = (configFields, pConnect, showActionColumn, op
|
|
|
247
268
|
label: fieldsLabels[index],
|
|
248
269
|
fillAvailableSpace: !!field.config.fillAvailableSpace,
|
|
249
270
|
id: `${index}`,
|
|
250
|
-
name: field.config.value
|
|
271
|
+
name: getPropertyNameFromConfigValue(field.config.value),
|
|
251
272
|
cellRenderer: TABLE_CELL,
|
|
252
273
|
sort: false,
|
|
253
274
|
noContextMenu: true,
|
|
@@ -256,7 +277,7 @@ export const buildFieldsForTable = (configFields, pConnect, showActionColumn, op
|
|
|
256
277
|
...field
|
|
257
278
|
},
|
|
258
279
|
// BUG-615253: Workaround for autosize in table with lazy loading components
|
|
259
|
-
width: getFieldWidth(field,
|
|
280
|
+
width: getFieldWidth(field, fieldsLabels[index])
|
|
260
281
|
};
|
|
261
282
|
});
|
|
262
283
|
|
|
@@ -113,9 +113,7 @@
|
|
|
113
113
|
</tr>
|
|
114
114
|
</table>
|
|
115
115
|
</div>
|
|
116
|
-
<button *ngIf="showAddRowButton" mat-button color="primary" style="font-size: 16px" (click)="addRecord()">
|
|
117
|
-
+ {{ localizedVal('Add', localeCategory) }}
|
|
118
|
-
</button>
|
|
116
|
+
<button *ngIf="showAddRowButton" mat-button color="primary" style="font-size: 16px" (click)="addRecord()">+ {{ addButtonLabel$ }}</button>
|
|
119
117
|
</ng-container>
|
|
120
118
|
|
|
121
119
|
<!-- pop overs for filters-->
|