@pega/sdk 0.0.13 → 0.0.14
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/package.json +1 -1
- package/templates/angular-sdk-reference/angular.json +2 -1
- package/templates/angular-sdk-reference/package.json +1 -0
- package/templates/angular-sdk-reference/pega-constellationjs-0.26.3-local.tgz +0 -0
- package/templates/angular-sdk-reference/src/app/app.component.ts +232 -15
- package/templates/angular-sdk-reference/src/components/component-map.ts +90 -0
- package/templates/angular-sdk-reference/src/components/fields/auto-complete/auto-complete.component.ts +267 -0
- package/templates/angular-sdk-reference/src/components/fields/checkbox/checkbox.component.ts +84 -0
- package/templates/angular-sdk-reference/src/components/fields/currency/currency.component.ts +97 -0
- package/templates/angular-sdk-reference/src/components/fields/date-input/date-input.component.ts +88 -0
- package/templates/angular-sdk-reference/src/components/fields/dropdown/dropdown.component.ts +101 -0
- package/templates/angular-sdk-reference/src/components/fields/email/email.component.ts +91 -0
- package/templates/angular-sdk-reference/src/components/fields/integer/integer.component.ts +93 -0
- package/templates/angular-sdk-reference/src/components/fields/phone/phone.component.ts +91 -0
- package/templates/angular-sdk-reference/src/components/fields/radio-buttons/radio-buttons.component.ts +102 -0
- package/templates/angular-sdk-reference/src/components/fields/text-area/text-area.component.ts +98 -0
- package/templates/angular-sdk-reference/src/components/fields/text-input/text-input.component.ts +97 -0
- package/templates/angular-sdk-reference/src/components/fields/url-input/url-input.component.ts +94 -0
- package/templates/angular-sdk-reference/src/components/infra/assignment/assignment.component.ts +206 -0
- package/templates/angular-sdk-reference/src/components/infra/case-summary/case-summary.component.ts +76 -0
- package/templates/angular-sdk-reference/src/components/infra/case-view/case-view.component.ts +114 -0
- package/templates/angular-sdk-reference/src/components/infra/flow-container/flow-container.component.ts +411 -0
- package/templates/angular-sdk-reference/src/components/infra/reference/reference.component.ts +158 -0
- package/templates/angular-sdk-reference/src/components/infra/region/region.component.ts +39 -0
- package/templates/angular-sdk-reference/src/components/infra/root-container/root-container.component.ts +193 -0
- package/templates/angular-sdk-reference/src/components/infra/stages/stages.component.ts +78 -0
- package/templates/angular-sdk-reference/src/components/infra/view/view.component.ts +139 -0
- package/templates/angular-sdk-reference/src/components/infra/view-container/view-container.component.ts +191 -0
- package/templates/angular-sdk-reference/src/components/templates/default-form/default-form.component.ts +101 -0
- package/templates/angular-sdk-reference/src/components/templates/narrow-wide/narrow-wide.component.ts +37 -0
- package/templates/angular-sdk-reference/src/components/templates/one-column/one-column.component.ts +37 -0
- package/templates/angular-sdk-reference/src/components/templates/two-column/two-column.component.ts +37 -0
- package/templates/angular-sdk-reference/src/components/templates/wide-narrow/wide-narrow.component.ts +37 -0
- package/templates/angular-sdk-reference/src/helpers/event-utils.ts +18 -0
- package/templates/angular-sdk-reference/src/helpers/utils.ts +38 -0
- package/templates/angular-sdk-reference/src/helpers/versionHelpers.ts +14 -0
- package/templates/angular-sdk-reference/tsconfig.json +5 -2
- package/templates/react-sdk-reference/.ai-common/agents/embedded-flow-expert.md +11 -4
- package/templates/react-sdk-reference/.ai-common/prompts/component-manifest.json +7 -0
- package/templates/react-sdk-reference/.ai-common/prompts/generate-all-components.md +3 -1
- package/templates/react-sdk-reference/.ai-common/skills/field-components.md +75 -29
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/AutoComplete.md +133 -101
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/EmbeddedData.md +385 -0
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/EmbeddedDataMulti.md +506 -0
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/ObjectReference.md +549 -86
- package/templates/react-sdk-reference/.ai-common/skills/field-skills/UserReference.md +181 -83
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/ListView.md +125 -153
- package/templates/react-sdk-reference/.ai-common/skills/template-skills/SimpleTable.md +90 -81
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CaseView — renders the full case view with header, actions menu, and tabs/content.
|
|
3
|
+
*
|
|
4
|
+
* Simplified version that shows heading, status, and renders children.
|
|
5
|
+
*
|
|
6
|
+
* Pattern reference: angular-sdk-components CaseViewComponent + sdk-react CaseView
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
10
|
+
import { Component, Input, ChangeDetectorRef, NgZone } from '@angular/core';
|
|
11
|
+
import type { OnInit, OnDestroy } from '@angular/core';
|
|
12
|
+
import { CommonModule } from '@angular/common';
|
|
13
|
+
import type { Unsubscribe } from '@pega/sdk-angular';
|
|
14
|
+
import { PConnectBridgeComponent } from '@pega/sdk-angular';
|
|
15
|
+
|
|
16
|
+
@Component({
|
|
17
|
+
selector: 'pega-case-view',
|
|
18
|
+
standalone: true,
|
|
19
|
+
imports: [CommonModule, PConnectBridgeComponent],
|
|
20
|
+
template: `
|
|
21
|
+
<div>
|
|
22
|
+
<div *ngIf="heading" style="font-size: 1.25rem; font-weight: 600; margin-bottom: 0.5rem;">
|
|
23
|
+
{{ heading }}
|
|
24
|
+
</div>
|
|
25
|
+
<div *ngIf="id" style="font-size: 0.75rem; color: #6b7280; margin-bottom: 1rem;">
|
|
26
|
+
{{ id }}
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<!-- Case summary -->
|
|
30
|
+
<div *ngIf="caseSummaryGetPConnect">
|
|
31
|
+
<pconnect-bridge [getPConnect]="caseSummaryGetPConnect"></pconnect-bridge>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- Children (tabs, stages, etc.) -->
|
|
35
|
+
<div *ngFor="let getter of childGetters">
|
|
36
|
+
<pconnect-bridge [getPConnect]="getter"></pconnect-bridge>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
`,
|
|
40
|
+
})
|
|
41
|
+
export class CaseViewComponent implements OnInit, OnDestroy {
|
|
42
|
+
@Input() props: any;
|
|
43
|
+
|
|
44
|
+
heading = '';
|
|
45
|
+
id = '';
|
|
46
|
+
status = '';
|
|
47
|
+
caseSummaryGetPConnect: (() => typeof PConnect) | null = null;
|
|
48
|
+
childGetters: Array<() => typeof PConnect> = [];
|
|
49
|
+
|
|
50
|
+
private pConn: any;
|
|
51
|
+
private observable: any;
|
|
52
|
+
private storeUnsub: Unsubscribe | undefined;
|
|
53
|
+
|
|
54
|
+
constructor(
|
|
55
|
+
private ngZone: NgZone,
|
|
56
|
+
private cdr: ChangeDetectorRef,
|
|
57
|
+
) {}
|
|
58
|
+
|
|
59
|
+
ngOnInit(): void {
|
|
60
|
+
this.pConn = this.props.getPConnect();
|
|
61
|
+
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
const { PConnectObservable } = PCore.getInitialiser().getSdkCore() as any;
|
|
64
|
+
this.observable = new PConnectObservable(this.pConn);
|
|
65
|
+
this.updateSelf();
|
|
66
|
+
|
|
67
|
+
this.storeUnsub = this.observable.subscribe(() => {
|
|
68
|
+
this.updateSelf();
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ngOnDestroy(): void {
|
|
73
|
+
this.storeUnsub?.();
|
|
74
|
+
this.observable?.destroy();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private updateSelf(): void {
|
|
78
|
+
const configProps = this.pConn.resolveConfigProps(this.pConn.getConfigProps());
|
|
79
|
+
|
|
80
|
+
this.heading = configProps.header ?? '';
|
|
81
|
+
this.id = configProps.subheader ?? '';
|
|
82
|
+
|
|
83
|
+
const children = this.pConn.getChildren?.() ?? [];
|
|
84
|
+
|
|
85
|
+
// First child is typically the case summary (if applicable)
|
|
86
|
+
if (children.length > 0) {
|
|
87
|
+
const firstChild = children[0];
|
|
88
|
+
const firstPConn = firstChild.getPConnect?.() ?? firstChild;
|
|
89
|
+
const firstCompName = firstPConn.getComponentName?.() ?? '';
|
|
90
|
+
|
|
91
|
+
if (firstCompName === 'CaseSummary' || firstCompName === 'CaseSummaryFields') {
|
|
92
|
+
this.caseSummaryGetPConnect = firstChild.getPConnect ?? (() => firstChild);
|
|
93
|
+
this.childGetters = children.slice(1).map((child: any) => {
|
|
94
|
+
return child.getPConnect ?? (() => child);
|
|
95
|
+
});
|
|
96
|
+
} else {
|
|
97
|
+
this.caseSummaryGetPConnect = null;
|
|
98
|
+
this.childGetters = children.map((child: any) => {
|
|
99
|
+
return child.getPConnect ?? (() => child);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
this.childGetters = [];
|
|
104
|
+
this.caseSummaryGetPConnect = null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Update okToInitFlowContainer
|
|
108
|
+
sessionStorage.setItem('okToInitFlowContainer', 'true');
|
|
109
|
+
|
|
110
|
+
this.ngZone.run(() => {
|
|
111
|
+
this.cdr.detectChanges();
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowContainer — manages the case execution lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* Key flow:
|
|
5
|
+
* 1. initContainer: checks getActiveContainerItemName, calls initializeContainers + addContainerItem
|
|
6
|
+
* 2. Store subscription drives updateSelf on every Redux change
|
|
7
|
+
* 3. updateSelf reads routingInfo from populateAdditionalProps, creates PConnect for active item
|
|
8
|
+
* 4. Renders the assignment form via PConnectBridgeComponent
|
|
9
|
+
* 5. sessionStorage('okToInitFlowContainer') gate for re-init on cancel
|
|
10
|
+
*
|
|
11
|
+
* Pattern reference: angular-sdk-components FlowContainerComponent
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
15
|
+
import { Component, Input, ChangeDetectorRef, NgZone } from '@angular/core';
|
|
16
|
+
import type { OnInit, OnDestroy } from '@angular/core';
|
|
17
|
+
import { CommonModule } from '@angular/common';
|
|
18
|
+
import { AssignmentComponent } from '../assignment/assignment.component';
|
|
19
|
+
|
|
20
|
+
@Component({
|
|
21
|
+
selector: 'pega-flow-container',
|
|
22
|
+
standalone: true,
|
|
23
|
+
imports: [CommonModule, AssignmentComponent],
|
|
24
|
+
template: `
|
|
25
|
+
<div [id]="buildName" style="text-align: left;">
|
|
26
|
+
<!-- Confirmation banner -->
|
|
27
|
+
<div
|
|
28
|
+
*ngIf="bShowConfirm"
|
|
29
|
+
style="padding: 1rem; background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 0.5rem; margin-bottom: 1rem;"
|
|
30
|
+
>
|
|
31
|
+
<p style="color: #166534;">{{ caseMessages }}</p>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- Assignment view (perform mode) -->
|
|
35
|
+
<div *ngIf="!bShowConfirm && !showTodo && arChildren.length > 0">
|
|
36
|
+
<div
|
|
37
|
+
*ngIf="containerName"
|
|
38
|
+
style="font-size: 0.875rem; font-weight: 500; margin-bottom: 0.5rem; padding: 0 0.5rem;"
|
|
39
|
+
>
|
|
40
|
+
{{ containerName }}
|
|
41
|
+
</div>
|
|
42
|
+
<!-- Render Assignment explicitly — it wraps children with action buttons.
|
|
43
|
+
Matches reference pattern: FlowContainer -> Assignment -> view children -->
|
|
44
|
+
<pega-assignment [props]="assignmentProps"></pega-assignment>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<!-- Todo/review mode placeholder -->
|
|
48
|
+
<div
|
|
49
|
+
*ngIf="!bShowConfirm && showTodo"
|
|
50
|
+
style="padding: 1rem; text-align: center; color: #64748b;"
|
|
51
|
+
>
|
|
52
|
+
Case is in review mode
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
`,
|
|
56
|
+
})
|
|
57
|
+
export class FlowContainerComponent implements OnInit, OnDestroy {
|
|
58
|
+
@Input() props: any;
|
|
59
|
+
|
|
60
|
+
buildName = '';
|
|
61
|
+
containerName = '';
|
|
62
|
+
showTodo = false;
|
|
63
|
+
bShowConfirm = false;
|
|
64
|
+
caseMessages = '';
|
|
65
|
+
itemKey = '';
|
|
66
|
+
arChildren: Array<{ getPConnect: () => typeof PConnect }> = [];
|
|
67
|
+
assignmentProps: Record<string, unknown> = {};
|
|
68
|
+
|
|
69
|
+
private pConn: any;
|
|
70
|
+
private storeUnsub: (() => void) | undefined;
|
|
71
|
+
private localizedVal: any;
|
|
72
|
+
private bReInit = false;
|
|
73
|
+
|
|
74
|
+
constructor(
|
|
75
|
+
private cdr: ChangeDetectorRef,
|
|
76
|
+
private ngZone: NgZone,
|
|
77
|
+
) {}
|
|
78
|
+
|
|
79
|
+
ngOnInit(): void {
|
|
80
|
+
this.pConn = this.props.getPConnect();
|
|
81
|
+
this.localizedVal = PCore.getLocaleUtils().getLocaleValue;
|
|
82
|
+
|
|
83
|
+
// Load children from pConn
|
|
84
|
+
this.arChildren = (this.pConn.getChildren?.() ?? []).map((child: any) => ({
|
|
85
|
+
getPConnect: child.getPConnect ?? (() => child),
|
|
86
|
+
}));
|
|
87
|
+
|
|
88
|
+
this.initComponent();
|
|
89
|
+
|
|
90
|
+
// Build initial assignment props for the Assignment component
|
|
91
|
+
this.updateAssignmentProps();
|
|
92
|
+
|
|
93
|
+
// Initialize the container (matching withSimpleViewContainerRenderer pattern from sdk-react)
|
|
94
|
+
this.ensureContainerInitialized();
|
|
95
|
+
|
|
96
|
+
// Add container item if initialized but no items yet (matching sdk-react useEffect pattern)
|
|
97
|
+
this.ensureContainerItem();
|
|
98
|
+
|
|
99
|
+
// Subscribe to store for routing changes
|
|
100
|
+
this.storeUnsub = PCore.getStore().subscribe(() => {
|
|
101
|
+
// Re-check container initialization on every store change
|
|
102
|
+
this.ensureContainerInitialized();
|
|
103
|
+
this.ensureContainerItem();
|
|
104
|
+
this.updateSelf();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Subscribe to cancel events
|
|
108
|
+
PCore.getPubSubUtils().subscribe(
|
|
109
|
+
(PCore.getConstants() as any).PUB_SUB_EVENTS.EVENT_CANCEL,
|
|
110
|
+
() => {
|
|
111
|
+
// cancel happened — allow re-init of flow container
|
|
112
|
+
this.bReInit = true;
|
|
113
|
+
},
|
|
114
|
+
'cancelAssignment',
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
ngOnDestroy(): void {
|
|
119
|
+
this.storeUnsub?.();
|
|
120
|
+
|
|
121
|
+
PCore.getPubSubUtils().unsubscribe(
|
|
122
|
+
(PCore.getConstants() as any).PUB_SUB_EVENTS.EVENT_CANCEL,
|
|
123
|
+
'cancelAssignment',
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Ensure the container is initialized.
|
|
129
|
+
* Matches the useContainerInitializer pattern from sdk-react's
|
|
130
|
+
* withSimpleViewContainerRenderer HOC.
|
|
131
|
+
*/
|
|
132
|
+
private ensureContainerInitialized(): void {
|
|
133
|
+
const context = this.pConn.getContextName();
|
|
134
|
+
const containerName = this.pConn.getContainerName();
|
|
135
|
+
const containerMgr = this.pConn.getContainerManager();
|
|
136
|
+
|
|
137
|
+
const isInitialized = (
|
|
138
|
+
PCore.getContainerUtils() as any
|
|
139
|
+
).isContainerInitialized(context, containerName);
|
|
140
|
+
|
|
141
|
+
if (!isInitialized) {
|
|
142
|
+
containerMgr.initializeContainers({
|
|
143
|
+
type: 'single',
|
|
144
|
+
name: containerName,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Add a container item if the container is initialized but has no items.
|
|
151
|
+
* Matches the sdk-react FlowContainer's useEffect + addContainerItem helper.
|
|
152
|
+
*/
|
|
153
|
+
private ensureContainerItem(): void {
|
|
154
|
+
const context = this.pConn.getContextName();
|
|
155
|
+
const containerName = this.pConn.getContainerName();
|
|
156
|
+
const containerPath = `${context}/${containerName}`;
|
|
157
|
+
|
|
158
|
+
const isInitialized = (
|
|
159
|
+
PCore.getContainerUtils() as any
|
|
160
|
+
).isContainerInitialized(context, containerName);
|
|
161
|
+
const hasItems = (PCore.getContainerUtils() as any).hasContainerItems(
|
|
162
|
+
containerPath,
|
|
163
|
+
);
|
|
164
|
+
const hasMetadataChildren = !!this.pConn.getMetadata?.()?.children;
|
|
165
|
+
|
|
166
|
+
if (isInitialized && hasMetadataChildren && !hasItems) {
|
|
167
|
+
this.addContainerItemWithContext();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Adds a container item with full context — matches sdk-react's addContainerItem helper.
|
|
173
|
+
* Passes key, flowName, caseViewMode, resourceType, and data so PCore can properly
|
|
174
|
+
* populate the workarea container.
|
|
175
|
+
*/
|
|
176
|
+
private addContainerItemWithContext(): void {
|
|
177
|
+
const containerMgr = this.pConn.getContainerManager();
|
|
178
|
+
const contextName = this.pConn.getContextName();
|
|
179
|
+
const caseViewMode = this.pConn.getValue('context_data.caseViewMode');
|
|
180
|
+
|
|
181
|
+
let key: string | undefined;
|
|
182
|
+
let flowName: string | undefined;
|
|
183
|
+
|
|
184
|
+
if (caseViewMode !== 'review') {
|
|
185
|
+
const target = contextName.substring(0, contextName.lastIndexOf('_'));
|
|
186
|
+
const activeContainerItemID = (
|
|
187
|
+
PCore.getContainerUtils() as any
|
|
188
|
+
).getActiveContainerItemName(target);
|
|
189
|
+
const containerItemData = (
|
|
190
|
+
PCore.getContainerUtils() as any
|
|
191
|
+
).getContainerItemData(target, activeContainerItemID);
|
|
192
|
+
|
|
193
|
+
if (containerItemData) {
|
|
194
|
+
({ key, flowName } = containerItemData);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
containerMgr.addContainerItem({
|
|
199
|
+
semanticURL: '',
|
|
200
|
+
key,
|
|
201
|
+
flowName,
|
|
202
|
+
caseViewMode: 'perform',
|
|
203
|
+
resourceType: 'ASSIGNMENT',
|
|
204
|
+
data: this.pConn.getDataObject(contextName),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Initialize component state from pConn — name, children, todo visibility.
|
|
210
|
+
*/
|
|
211
|
+
private initComponent(): void {
|
|
212
|
+
const baseContext = this.pConn.getContextName();
|
|
213
|
+
const acName = this.pConn.getContainerName();
|
|
214
|
+
|
|
215
|
+
if (this.itemKey === '') {
|
|
216
|
+
this.itemKey = `${baseContext}/${acName}`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
this.pConn.isBoundToState();
|
|
220
|
+
this.buildName = this.getBuildName();
|
|
221
|
+
this.showTodo = this.getTodoVisibility();
|
|
222
|
+
|
|
223
|
+
// Get container/assignment name
|
|
224
|
+
if (this.arChildren.length > 0) {
|
|
225
|
+
const oWorkItem = this.arChildren[0].getPConnect() as any;
|
|
226
|
+
const oWorkData = oWorkItem.getDataObject?.();
|
|
227
|
+
if (oWorkData) {
|
|
228
|
+
this.containerName = this.localizedVal(
|
|
229
|
+
oWorkData.caseInfo?.assignments?.[0]?.name,
|
|
230
|
+
undefined,
|
|
231
|
+
this.pConn.getCaseLocaleReference?.(),
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private getTodoVisibility(): boolean {
|
|
238
|
+
const caseViewMode = this.pConn.getValue('context_data.caseViewMode');
|
|
239
|
+
if (caseViewMode && caseViewMode === 'review') {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
return !(caseViewMode && caseViewMode === 'perform');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Called on every store change — reads routingInfo, creates new PConnect,
|
|
247
|
+
* and updates arChildren to render the assignment form.
|
|
248
|
+
*/
|
|
249
|
+
private updateSelf(): void {
|
|
250
|
+
const caseViewMode = this.pConn.getValue('context_data.caseViewMode');
|
|
251
|
+
|
|
252
|
+
if (caseViewMode === 'review') {
|
|
253
|
+
this.showTodo = true;
|
|
254
|
+
if (this.bReInit) {
|
|
255
|
+
this.bReInit = false;
|
|
256
|
+
this.ensureContainerInitialized();
|
|
257
|
+
this.ensureContainerItem();
|
|
258
|
+
}
|
|
259
|
+
this.cdr.detectChanges();
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (caseViewMode === 'perform') {
|
|
264
|
+
this.showTodo = false;
|
|
265
|
+
if (this.bReInit) {
|
|
266
|
+
this.bReInit = false;
|
|
267
|
+
this.ensureContainerInitialized();
|
|
268
|
+
this.ensureContainerItem();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Check for case completion messages
|
|
273
|
+
this.showCaseMessages();
|
|
274
|
+
|
|
275
|
+
// Update children from routingInfo
|
|
276
|
+
this.updateFlowContainerChildren();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
private showCaseMessages(): void {
|
|
280
|
+
const theCaseMessages = this.pConn.getValue('caseMessages');
|
|
281
|
+
const hasAssignments = this.checkHasAssignments();
|
|
282
|
+
|
|
283
|
+
if (!hasAssignments) {
|
|
284
|
+
this.bShowConfirm = true;
|
|
285
|
+
this.caseMessages =
|
|
286
|
+
this.localizedVal(theCaseMessages, 'Messages') ||
|
|
287
|
+
this.localizedVal(
|
|
288
|
+
'Thank you! The next step in this case has been routed appropriately.',
|
|
289
|
+
'Messages',
|
|
290
|
+
);
|
|
291
|
+
} else {
|
|
292
|
+
this.bShowConfirm = false;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private checkHasAssignments(): boolean {
|
|
297
|
+
const { CASE_INFO } = PCore.getConstants() as any;
|
|
298
|
+
const assignments = this.pConn.getValue(
|
|
299
|
+
CASE_INFO.D_CASE_ASSIGNMENTS_RESULTS,
|
|
300
|
+
);
|
|
301
|
+
const childCases = this.pConn.getValue(CASE_INFO.CHILD_ASSIGNMENTS);
|
|
302
|
+
|
|
303
|
+
return (
|
|
304
|
+
(assignments && assignments.length > 0) ||
|
|
305
|
+
(childCases && childCases.length > 0)
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Reads routingInfo from Redux props, creates PConnect for active container item,
|
|
311
|
+
* and updates arChildren to render the assignment form components.
|
|
312
|
+
*/
|
|
313
|
+
private updateFlowContainerChildren(): void {
|
|
314
|
+
// routingInfo is populated by PConnectObservable.resolveState() which calls
|
|
315
|
+
// populateAdditionalProps — it arrives via this.props (set by the bridge),
|
|
316
|
+
// NOT from pConn.getComponentProps() which skips populateAdditionalProps.
|
|
317
|
+
const routingInfo = this.props?.routingInfo;
|
|
318
|
+
if (!routingInfo) return;
|
|
319
|
+
|
|
320
|
+
const { accessedOrder, items, type } = routingInfo;
|
|
321
|
+
if (!accessedOrder || !items) return;
|
|
322
|
+
|
|
323
|
+
const key = accessedOrder[accessedOrder.length - 1];
|
|
324
|
+
if (key && key !== '') {
|
|
325
|
+
this.itemKey = key;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (
|
|
329
|
+
accessedOrder.length > 0 &&
|
|
330
|
+
items[key]?.view &&
|
|
331
|
+
type === 'single' &&
|
|
332
|
+
Object.keys(items[key].view).length > 0
|
|
333
|
+
) {
|
|
334
|
+
this.addPConnectAndUpdateChildren(items[key], key);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Creates a new PConnect from the routing item's view metadata,
|
|
340
|
+
* and replaces arChildren so the template renders the new assignment form.
|
|
341
|
+
*/
|
|
342
|
+
private addPConnectAndUpdateChildren(currentItem: any, key: string): void {
|
|
343
|
+
const localPConn =
|
|
344
|
+
this.arChildren.length > 0
|
|
345
|
+
? (this.arChildren[0].getPConnect() as any)
|
|
346
|
+
: this.pConn;
|
|
347
|
+
|
|
348
|
+
const rootView = currentItem.view;
|
|
349
|
+
const { context, name: viewName } = rootView.config;
|
|
350
|
+
|
|
351
|
+
// Don't proceed if View doesn't exist
|
|
352
|
+
if (!viewName) return;
|
|
353
|
+
|
|
354
|
+
const config: any = { meta: rootView };
|
|
355
|
+
config.options = {
|
|
356
|
+
context: currentItem.context,
|
|
357
|
+
pageReference: context || localPConn.getPageReference(),
|
|
358
|
+
hasForm: true,
|
|
359
|
+
isFlowContainer: true,
|
|
360
|
+
containerName: localPConn.getContainerName(),
|
|
361
|
+
containerItemName: key,
|
|
362
|
+
parentPageReference: localPConn.getPageReference(),
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
const configObject = PCore.createPConnect(config) as any;
|
|
366
|
+
|
|
367
|
+
this.ngZone.run(() => {
|
|
368
|
+
this.buildName = this.getBuildName();
|
|
369
|
+
this.arChildren = [
|
|
370
|
+
{
|
|
371
|
+
getPConnect:
|
|
372
|
+
configObject.getPConnect ?? (() => configObject.getPConnect()),
|
|
373
|
+
},
|
|
374
|
+
];
|
|
375
|
+
|
|
376
|
+
// Update container/assignment name
|
|
377
|
+
const oWorkItem = configObject.getPConnect();
|
|
378
|
+
const oWorkData = oWorkItem.getDataObject?.();
|
|
379
|
+
if (oWorkData) {
|
|
380
|
+
this.containerName = this.localizedVal(
|
|
381
|
+
oWorkData.caseInfo?.assignments?.[0]?.name,
|
|
382
|
+
undefined,
|
|
383
|
+
this.pConn.getCaseLocaleReference?.(),
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Update assignment props so Assignment component gets new children + itemKey
|
|
388
|
+
this.updateAssignmentProps();
|
|
389
|
+
|
|
390
|
+
this.cdr.detectChanges();
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
private getBuildName(): string {
|
|
395
|
+
const sContext = this.pConn.getContextName?.() ?? '';
|
|
396
|
+
const sName = this.pConn.getContainerName?.() ?? '';
|
|
397
|
+
return `${sContext.toUpperCase()}/${sName.toUpperCase()}`;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Update assignmentProps passed to the Assignment component.
|
|
402
|
+
* Must be called whenever arChildren, itemKey, or pConn changes.
|
|
403
|
+
*/
|
|
404
|
+
private updateAssignmentProps(): void {
|
|
405
|
+
this.assignmentProps = {
|
|
406
|
+
getPConnect: () => this.pConn,
|
|
407
|
+
arChildren: this.arChildren,
|
|
408
|
+
itemKey: this.itemKey,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reference — resolves a 'reference' PConnect to its actual referenced view
|
|
3
|
+
* and renders it via PConnectBridge.
|
|
4
|
+
*
|
|
5
|
+
* Pattern reference: angular-sdk-components ReferenceComponent + sdk-react Reference
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
9
|
+
import { Component, Input } from '@angular/core';
|
|
10
|
+
import type { OnInit } from '@angular/core';
|
|
11
|
+
import { CommonModule } from '@angular/common';
|
|
12
|
+
import { PConnectBridgeComponent } from '@pega/sdk-angular';
|
|
13
|
+
|
|
14
|
+
@Component({
|
|
15
|
+
selector: 'pega-reference',
|
|
16
|
+
standalone: true,
|
|
17
|
+
imports: [CommonModule, PConnectBridgeComponent],
|
|
18
|
+
template: `
|
|
19
|
+
<div *ngIf="viewGetPConnect">
|
|
20
|
+
<pconnect-bridge [getPConnect]="viewGetPConnect"></pconnect-bridge>
|
|
21
|
+
</div>
|
|
22
|
+
`,
|
|
23
|
+
})
|
|
24
|
+
export class ReferenceComponent implements OnInit {
|
|
25
|
+
@Input() props: any;
|
|
26
|
+
|
|
27
|
+
viewGetPConnect: (() => typeof PConnect) | null = null;
|
|
28
|
+
|
|
29
|
+
ngOnInit(): void {
|
|
30
|
+
const pConn = this.props.getPConnect();
|
|
31
|
+
const {
|
|
32
|
+
visibility = true,
|
|
33
|
+
context = '',
|
|
34
|
+
readOnly = false,
|
|
35
|
+
displayMode = '',
|
|
36
|
+
} = this.props;
|
|
37
|
+
|
|
38
|
+
const referenceConfig: any = { ...pConn.getComponentConfig() };
|
|
39
|
+
delete referenceConfig?.name;
|
|
40
|
+
delete referenceConfig?.type;
|
|
41
|
+
delete referenceConfig?.visibility;
|
|
42
|
+
|
|
43
|
+
const viewMetadata = pConn.getReferencedView();
|
|
44
|
+
if (!viewMetadata) return;
|
|
45
|
+
|
|
46
|
+
const viewObject = {
|
|
47
|
+
...viewMetadata,
|
|
48
|
+
config: {
|
|
49
|
+
...viewMetadata.config,
|
|
50
|
+
...referenceConfig,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const viewComponent = pConn.createComponent(viewObject, null, null, {
|
|
55
|
+
pageReference: context && context.startsWith('@CLASS') ? '' : context,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (referenceConfig.inheritedProps?.length > 0) {
|
|
59
|
+
const inheritedProps = pConn.getInheritedProps();
|
|
60
|
+
referenceConfig.inheritedProps = Object.keys(inheritedProps).map(
|
|
61
|
+
(prop) => ({ prop, value: inheritedProps[prop] }),
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const newPConnect =
|
|
66
|
+
viewComponent.getPConnect?.() ?? viewComponent.props?.getPConnect?.();
|
|
67
|
+
if (newPConnect) {
|
|
68
|
+
newPConnect.setInheritedConfig({
|
|
69
|
+
...referenceConfig,
|
|
70
|
+
readOnly,
|
|
71
|
+
displayMode,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (visibility !== false) {
|
|
76
|
+
const getter =
|
|
77
|
+
viewComponent.getPConnect ?? (() => newPConnect ?? viewComponent);
|
|
78
|
+
this.viewGetPConnect = getter;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Static utility: normalizes a PConnect that might be a 'reference' into
|
|
84
|
+
* its dereferenced view. Returns the input unchanged if not a reference.
|
|
85
|
+
*/
|
|
86
|
+
static normalizePConn(inPConn: any): any {
|
|
87
|
+
if (!inPConn) return inPConn;
|
|
88
|
+
|
|
89
|
+
const hasGetPConnect = !!inPConn.getPConnect;
|
|
90
|
+
const componentName = hasGetPConnect
|
|
91
|
+
? inPConn.getPConnect().getComponentName()
|
|
92
|
+
: inPConn.getComponentName?.();
|
|
93
|
+
|
|
94
|
+
if (componentName === 'reference') {
|
|
95
|
+
const pConn = hasGetPConnect ? inPConn.getPConnect() : inPConn;
|
|
96
|
+
const referenceConfig: any = { ...pConn.getComponentConfig() };
|
|
97
|
+
delete referenceConfig?.name;
|
|
98
|
+
delete referenceConfig?.type;
|
|
99
|
+
delete referenceConfig?.visibility;
|
|
100
|
+
|
|
101
|
+
const viewMetadata = pConn.getReferencedView();
|
|
102
|
+
if (!viewMetadata) return null;
|
|
103
|
+
|
|
104
|
+
const viewObject = {
|
|
105
|
+
...viewMetadata,
|
|
106
|
+
config: { ...viewMetadata.config, ...referenceConfig },
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const resolvedConfigProps = pConn.resolveConfigProps(
|
|
110
|
+
pConn.getConfigProps(),
|
|
111
|
+
);
|
|
112
|
+
const {
|
|
113
|
+
visibility = true,
|
|
114
|
+
context,
|
|
115
|
+
readOnly = false,
|
|
116
|
+
displayMode = '',
|
|
117
|
+
} = resolvedConfigProps;
|
|
118
|
+
|
|
119
|
+
const viewComponent = pConn.createComponent(viewObject, null, null, {
|
|
120
|
+
pageReference: context && context.startsWith('@CLASS') ? '' : context,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (referenceConfig.inheritedProps?.length > 0) {
|
|
124
|
+
const inheritedProps = pConn.getInheritedProps();
|
|
125
|
+
referenceConfig.inheritedProps = Object.keys(inheritedProps).map(
|
|
126
|
+
(prop: string) => ({ prop, value: inheritedProps[prop] }),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const newPConnect = viewComponent.getPConnect?.();
|
|
131
|
+
if (newPConnect) {
|
|
132
|
+
newPConnect.setInheritedConfig({
|
|
133
|
+
...referenceConfig,
|
|
134
|
+
readOnly,
|
|
135
|
+
displayMode,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (visibility !== false) {
|
|
140
|
+
return hasGetPConnect ? viewComponent : newPConnect;
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return inPConn;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Static utility: normalizes an array of PConnect objects, replacing any
|
|
150
|
+
* 'reference' components with their resolved views.
|
|
151
|
+
*/
|
|
152
|
+
static normalizePConnArray(inArray: any[]): any[] {
|
|
153
|
+
if (!inArray?.length) return inArray ?? [];
|
|
154
|
+
return inArray
|
|
155
|
+
.map((child) => ReferenceComponent.normalizePConn(child))
|
|
156
|
+
.filter(Boolean);
|
|
157
|
+
}
|
|
158
|
+
}
|