@pega/angular-sdk-overrides 0.242.7 → 0.242.9

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 (53) hide show
  1. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.ts +0 -1
  2. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.html +1 -1
  3. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.ts +6 -0
  4. package/lib/designSystemExtension/operator/operator.component.html +1 -1
  5. package/lib/designSystemExtension/operator/operator.component.scss +10 -2
  6. package/lib/designSystemExtension/operator/operator.component.ts +4 -3
  7. package/lib/field/auto-complete/auto-complete.component.html +0 -1
  8. package/lib/field/auto-complete/auto-complete.component.ts +15 -2
  9. package/lib/field/currency/currency.component.ts +19 -13
  10. package/lib/field/date-time/date-time.component.html +0 -1
  11. package/lib/field/date-time/date-time.component.ts +17 -3
  12. package/lib/field/decimal/decimal.component.html +1 -0
  13. package/lib/field/decimal/decimal.component.ts +38 -15
  14. package/lib/field/dropdown/dropdown.component.ts +18 -4
  15. package/lib/field/list-view-action-buttons/list-view-action-buttons.component.html +1 -1
  16. package/lib/field/list-view-action-buttons/list-view-action-buttons.component.ts +3 -2
  17. package/lib/field/percentage/percentage.component.html +1 -1
  18. package/lib/field/percentage/percentage.component.ts +27 -17
  19. package/lib/field/phone/config-ext.json +1 -1
  20. package/lib/field/phone/phone.component.ts +6 -13
  21. package/lib/field/rich-text/rich-text.component.ts +12 -3
  22. package/lib/field/text/text.component.ts +2 -2
  23. package/lib/field/text-input/text-input.component.ts +1 -1
  24. package/lib/field/time/time.component.html +1 -1
  25. package/lib/field/time/time.component.ts +21 -6
  26. package/lib/field/user-reference/user-reference.component.html +40 -38
  27. package/lib/field/user-reference/user-reference.component.ts +70 -7
  28. package/lib/infra/Containers/flow-container/flow-container.component.ts +7 -2
  29. package/lib/infra/Containers/flow-container/helpers.ts +1 -1
  30. package/lib/infra/Containers/modal-view-container/modal-view-container.component.html +1 -11
  31. package/lib/infra/Containers/modal-view-container/modal-view-container.component.ts +0 -1
  32. package/lib/infra/action-buttons/action-buttons.component.html +1 -1
  33. package/lib/infra/assignment/assignment.component.ts +2 -4
  34. package/lib/infra/assignment-card/assignment-card.component.ts +4 -32
  35. package/lib/infra/defer-load/defer-load.component.ts +4 -1
  36. package/lib/infra/reference/reference.component.ts +70 -86
  37. package/lib/infra/root-container/root-container.component.ts +24 -17
  38. package/lib/template/default-form/default-form.component.ts +5 -7
  39. package/lib/template/field-group-template/field-group-template.component.html +7 -7
  40. package/lib/template/field-group-template/field-group-template.component.scss +8 -0
  41. package/lib/template/field-group-template/field-group-template.component.ts +64 -41
  42. package/lib/template/field-group-template/utils.ts +9 -0
  43. package/lib/template/field-value-list/field-value-list.component.html +2 -2
  44. package/lib/template/field-value-list/field-value-list.component.scss +4 -0
  45. package/lib/template/list-view/list-view.component.html +3 -1
  46. package/lib/template/list-view/list-view.component.ts +1 -1
  47. package/lib/template/simple-table-manual/helpers.ts +18 -2
  48. package/lib/template/simple-table-manual/simple-table-manual.component.html +25 -6
  49. package/lib/template/simple-table-manual/simple-table-manual.component.scss +11 -3
  50. package/lib/template/simple-table-manual/simple-table-manual.component.ts +62 -22
  51. package/lib/widget/todo/todo.component.html +0 -1
  52. package/lib/widget/todo/todo.component.scss +2 -0
  53. package/package.json +1 -1
@@ -165,15 +165,30 @@ export class TimeComponent implements OnInit, OnDestroy {
165
165
  }
166
166
  }
167
167
 
168
- fieldOnChange() {
169
- this.pConn$.clearErrorMessages({
170
- property: this.propName
171
- });
168
+ fieldOnChange(event: any) {
169
+ const oldVal = this.value$ ?? '';
170
+ const isValueChanged = event.target.value.toString() !== oldVal.toString();
171
+
172
+ if (isValueChanged) {
173
+ this.pConn$.clearErrorMessages({
174
+ property: this.propName
175
+ });
176
+ }
172
177
  }
173
178
 
174
179
  fieldOnBlur(event: any) {
175
- const value = event?.target?.value;
176
- handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
180
+ const oldVal = this.value$ ?? '';
181
+ const isValueChanged = event?.target?.value.toString() !== oldVal.toString();
182
+
183
+ if (isValueChanged) {
184
+ let value = event?.target?.value;
185
+ const hhmmPattern = /^\d{2}:\d{2}$/;
186
+ if (hhmmPattern.test(value)) {
187
+ value = `${value}:00`; // append ":00"
188
+ }
189
+
190
+ handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
191
+ }
177
192
  }
178
193
 
179
194
  getErrorMessage() {
@@ -1,45 +1,47 @@
1
- <div class="psdk-user-reference">
1
+ <div>
2
2
  <div *ngIf="displayMode$; else noDisplayMode">
3
3
  <component-mapper name="FieldValueList" [props]="{ label$, value$, displayMode$ }"></component-mapper>
4
4
  </div>
5
5
  <ng-template #noDisplayMode>
6
- <div *ngIf="type === 'operator'">
7
- <component-mapper name="Operator" [props]="{ pConn$ }"></component-mapper>
8
- </div>
9
- <div [formGroup]="formGroup$" *ngIf="type === 'dropdown'">
10
- <mat-form-field class="psdk-full-width" subscriptSizing="dynamic" [hintLabel]="helperText">
11
- <mat-select [required]="bRequired$" [formControl]="fieldControl" [attr.data-test-id]="testId" (selectionChange)="fieldOnChange($event)">
12
- <mat-option *ngFor="let opt of options$" [value]="opt.key">
13
- {{ opt.value }}
14
- </mat-option>
15
- </mat-select>
16
- <mat-label>{{ label$ }}</mat-label>
17
- <mat-error *ngIf="fieldControl.invalid">
18
- {{ getErrorMessage() }}
19
- </mat-error>
20
- </mat-form-field>
21
- </div>
22
- <div [formGroup]="formGroup$" *ngIf="type === 'searchbox'">
23
- <mat-form-field class="psdk-full-width" subscriptSizing="dynamic" [hintLabel]="helperText">
24
- <mat-label>{{ label$ }}</mat-label>
25
- <input
26
- matInput
27
- [placeholder]="placeholder"
28
- [formControl]="fieldControl"
29
- [required]="bRequired$"
30
- [matAutocomplete]="auto"
31
- [attr.data-test-id]="testId"
32
- (blur)="fieldOnBlur($event)"
33
- />
34
- <mat-autocomplete #auto="matAutocomplete" autoActiveFirstOption (optionSelected)="optionChanged($event)">
35
- <mat-option *ngFor="let opt of filteredOptions | async" [value]="opt.value">
36
- <span>{{ opt.value }}</span>
37
- </mat-option>
38
- </mat-autocomplete>
39
- <mat-error *ngIf="fieldControl.invalid">
40
- {{ getErrorMessage() }}
41
- </mat-error>
42
- </mat-form-field>
6
+ <div class="psdk-user-reference">
7
+ <div *ngIf="this.userID$ && type === 'operator'">
8
+ <component-mapper name="Operator" [props]="{ pConn$, name$: userName$ }"></component-mapper>
9
+ </div>
10
+ <div [formGroup]="formGroup$" *ngIf="type === 'dropdown'">
11
+ <mat-form-field class="psdk-full-width" subscriptSizing="dynamic" [hintLabel]="helperText">
12
+ <mat-select [required]="bRequired$" [formControl]="fieldControl" [attr.data-test-id]="testId" (selectionChange)="fieldOnChange($event)">
13
+ <mat-option *ngFor="let opt of options$" [value]="opt.key">
14
+ {{ opt.value }}
15
+ </mat-option>
16
+ </mat-select>
17
+ <mat-label>{{ label$ }}</mat-label>
18
+ <mat-error *ngIf="fieldControl.invalid">
19
+ {{ getErrorMessage() }}
20
+ </mat-error>
21
+ </mat-form-field>
22
+ </div>
23
+ <div [formGroup]="formGroup$" *ngIf="type === 'searchbox'">
24
+ <mat-form-field class="psdk-full-width" subscriptSizing="dynamic" [hintLabel]="helperText">
25
+ <mat-label>{{ label$ }}</mat-label>
26
+ <input
27
+ matInput
28
+ [placeholder]="placeholder"
29
+ [formControl]="fieldControl"
30
+ [required]="bRequired$"
31
+ [matAutocomplete]="auto"
32
+ [attr.data-test-id]="testId"
33
+ (blur)="fieldOnBlur($event)"
34
+ />
35
+ <mat-autocomplete #auto="matAutocomplete" autoActiveFirstOption (optionSelected)="optionChanged($event)">
36
+ <mat-option *ngFor="let opt of filteredOptions | async" [value]="opt.value">
37
+ <span>{{ opt.value }}</span>
38
+ </mat-option>
39
+ </mat-autocomplete>
40
+ <mat-error *ngIf="fieldControl.invalid">
41
+ {{ getErrorMessage() }}
42
+ </mat-error>
43
+ </mat-form-field>
44
+ </div>
43
45
  </div>
44
46
  </ng-template>
45
47
  </div>
@@ -168,7 +168,11 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
168
168
  this.placeholder = placeholder || '';
169
169
  this.displayMode$ = displayMode;
170
170
 
171
- this.value$ = this.pConn$.getConfigProps()?.value;
171
+ if (value && typeof value === 'object') {
172
+ this.value$ = value.userName ? value.userName : '';
173
+ } else {
174
+ this.value$ = value || '';
175
+ }
172
176
 
173
177
  const { readOnly, required } = props;
174
178
  [this.bReadonly$, this.bRequired$] = [readOnly, required].map(prop => prop === true || (typeof prop === 'string' && prop === 'true'));
@@ -184,12 +188,8 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
184
188
  } else {
185
189
  // if same user ref field is referred in view as editable & readonly formatted text
186
190
  // referenced users won't be available, so get user details from dx api
187
- const { getOperatorDetails } = PCore.getUserApi();
188
- getOperatorDetails(this.userID$).then((resp: any) => {
189
- if (resp.data && resp.data.pyOperatorInfo && resp.data.pyOperatorInfo.pyUserName) {
190
- this.userName$ = resp.data.pyOperatorInfo.pyUserName;
191
- }
192
- });
191
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
192
+ this.userName$ = await getUserName(this.pConn$, this.userID$);
193
193
  }
194
194
  } else if (displayAs === DROPDOWN_LIST || displayAs === SEARCH_BOX) {
195
195
  const queryPayload = {
@@ -257,3 +257,66 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
257
257
  return errMessage;
258
258
  }
259
259
  }
260
+
261
+ const buildColumnForDisplayValue = dataObj => {
262
+ if (dataObj.columns) {
263
+ dataObj.columns = dataObj.columns.map(column => {
264
+ const tempColObj = { ...column };
265
+ if (tempColObj.key === 'true') {
266
+ tempColObj.useForSearch = true;
267
+ } else {
268
+ tempColObj.useForSearch = false;
269
+ }
270
+ return tempColObj;
271
+ });
272
+ }
273
+ };
274
+
275
+ function getUserName(pConn, userId = ''): Promise<string> {
276
+ return new Promise(resolve => {
277
+ const { parameters = {}, referenceList } = pConn.getConfigProps();
278
+ const contextName = pConn.getContextName();
279
+
280
+ // eslint-disable-next-line @typescript-eslint/no-shadow
281
+ const OPERATORS_DP = referenceList || PCore.getEnvironmentInfo().getDefaultOperatorDP() || '';
282
+
283
+ const columns = [
284
+ {
285
+ value: 'pyUserName',
286
+ display: 'true',
287
+ useForSearch: true,
288
+ primary: 'true'
289
+ },
290
+ {
291
+ value: 'pyUserIdentifier',
292
+ setProperty: 'Associated property',
293
+ key: 'true',
294
+ display: 'true',
295
+ secondary: 'true',
296
+ useForSearch: true
297
+ }
298
+ ];
299
+
300
+ const dataConfig: any = {
301
+ dataSource: OPERATORS_DP,
302
+ parameters,
303
+ matchPosition: 'equals',
304
+ listType: 'datapage',
305
+ columns,
306
+ cacheLifeSpan: 'form',
307
+ deferDatasource: false,
308
+ maxResultsDisplay: '1',
309
+ ignoreCase: true
310
+ };
311
+
312
+ PCore.getDataApi()
313
+ .init(dataConfig, contextName)
314
+ .then(dataApiObj => {
315
+ buildColumnForDisplayValue(dataApiObj);
316
+ dataApiObj.registerForBufferedCall({ waitTime: 50 });
317
+ dataApiObj.fetchData(userId).then((response: any) => {
318
+ resolve(response.data?.[0]?.pyUserName || userId);
319
+ });
320
+ });
321
+ });
322
+ }
@@ -127,7 +127,7 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
127
127
  () => {
128
128
  this.banners = [];
129
129
  },
130
- 'CLEAR_BANNER_MESSAGES'
130
+ 'clearBannerMessages'
131
131
  );
132
132
  }
133
133
 
@@ -140,7 +140,7 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
140
140
 
141
141
  PCore.getPubSubUtils().unsubscribe('cancelPressed', 'cancelPressed');
142
142
 
143
- PCore.getPubSubUtils().unsubscribe('clearBannerMessages', 'CLEAR_BANNER_MESSAGES');
143
+ PCore.getPubSubUtils().unsubscribe('clearBannerMessages', 'clearBannerMessages');
144
144
  }
145
145
 
146
146
  handleCancel() {
@@ -442,6 +442,11 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
442
442
  this.bHasCaseMessages$ = true;
443
443
  this.bShowConfirm = true;
444
444
  this.checkSvg$ = this.utils.getImageSrc('check', this.utils.getSDKStaticContentUrl());
445
+ // Temp fix for 8.7 change: confirmationNote no longer coming through in caseMessages$.
446
+ // So, if we get here and caseMessages$ is empty, use default value in DX API response
447
+ if (!this.caseMessages$) {
448
+ this.caseMessages$ = this.localizedVal('Thank you! The next step in this case has been routed appropriately.', this.localeCategory);
449
+ }
445
450
 
446
451
  this.psService.sendMessage(false);
447
452
  } else {
@@ -33,7 +33,7 @@ export function hasAssignments(pConnect) {
33
33
  const assignments = pConnect.getValue(CASE_INFO.D_CASE_ASSIGNMENTS_RESULTS);
34
34
  const childCasesAssignments = getChildCaseAssignments(pConnect);
35
35
 
36
- return assignments || childCasesAssignments || isCaseWideLocalAction(pConnect);
36
+ return assignments || childCasesAssignments?.length || isCaseWideLocalAction(pConnect);
37
37
  }
38
38
 
39
39
  export const showBanner = getPConnect => {
@@ -1,4 +1,4 @@
1
- <div id="dialog" *ngIf="bShowModal$ && bShowAsModal$" class="psdk-dialog-background">
1
+ <div id="dialog" *ngIf="bShowModal$" class="psdk-dialog-background">
2
2
  <div class="psdk-modal-view-container-top" id="{{ buildName$ }}">
3
3
  <h3 *ngIf="title$ != ''">{{ title$ }}</h3>
4
4
  <component-mapper
@@ -15,16 +15,6 @@
15
15
  </div>
16
16
  </div>
17
17
 
18
- <div *ngIf="bShowModal$ && !bShowAsModal$">
19
- <div id="{{ buildName$ }}">
20
- <h3 *ngIf="title$ != ''">{{ title$ }}</h3>
21
- <component-mapper
22
- name="Assignment"
23
- [props]="{ pConn$: createdViewPConn$, formGroup$, arChildren$, itemKey$, isCreateStage$: true, updateToken$ }"
24
- ></component-mapper>
25
- </div>
26
- </div>
27
-
28
18
  <div *ngIf="bShowCancelAlert$">
29
19
  <component-mapper
30
20
  name="CancelAlert"
@@ -38,7 +38,6 @@ export class ModalViewContainerComponent implements OnInit, OnDestroy {
38
38
  context$: string;
39
39
  title$ = '';
40
40
  bShowModal$ = false;
41
- bShowAsModal$ = true;
42
41
  itemKey$: string;
43
42
  formGroup$: FormGroup;
44
43
  oCaseInfo: Object = {};
@@ -1,4 +1,4 @@
1
- <mat-grid-list cols="2" rowHeight="6.25rem">
1
+ <mat-grid-list *ngIf="arMainButtons$ && arSecondaryButtons$" cols="2" rowHeight="6.25rem">
2
2
  <mat-grid-tile>
3
3
  <button *ngFor="let aButton of arSecondaryButtons$" mat-raised-button color="secondary" (click)="buttonClick(aButton.jsAction, 'secondary')">
4
4
  {{ localizedVal(aButton.name, localeCategory) }}
@@ -326,7 +326,7 @@ export class AssignmentComponent implements OnInit, OnDestroy, OnChanges {
326
326
  switch (sAction) {
327
327
  case 'navigateToStep':
328
328
  this.erService.sendMessage('publish', '');
329
- // if (this.formValid()) {
329
+
330
330
  this.bReInit = true;
331
331
  this.psService.sendMessage(true);
332
332
 
@@ -340,7 +340,7 @@ export class AssignmentComponent implements OnInit, OnDestroy, OnChanges {
340
340
  this.psService.sendMessage(false);
341
341
  this.snackBarRef = this.snackBar.open(`${this.localizedVal('Navigation failed!', this.localeCategory)}`, 'Ok');
342
342
  });
343
- // }
343
+
344
344
  break;
345
345
 
346
346
  case 'saveAssignment': {
@@ -434,7 +434,6 @@ export class AssignmentComponent implements OnInit, OnDestroy, OnChanges {
434
434
  this.psService.sendMessage(false);
435
435
  this.snackBarRef = this.snackBar.open(`${this.localizedVal('Submit failed!', this.localeCategory)}`, 'Ok');
436
436
  });
437
-
438
437
  break;
439
438
 
440
439
  case 'approveCase': {
@@ -473,7 +472,6 @@ export class AssignmentComponent implements OnInit, OnDestroy, OnChanges {
473
472
  }
474
473
 
475
474
  registerForRefresh() {
476
- // @ts-ignore - Property 'getActionRefreshConditions' is private and only accessible within class 'CaseInfo'
477
475
  const refreshConditions = this.pConn$.getCaseInfo()?.getActionRefreshConditions();
478
476
  const pageReference = this.pConn$.getPageReference();
479
477
  const context = this.pConn$.getContextName();
@@ -1,10 +1,8 @@
1
- import { Component, OnInit, Input, Output, EventEmitter, forwardRef, OnChanges, OnDestroy } from '@angular/core';
1
+ import { Component, OnInit, Input, Output, EventEmitter, forwardRef, OnChanges } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { FormGroup, ReactiveFormsModule } from '@angular/forms';
4
4
  import { ReferenceComponent } from '@pega/angular-sdk-components';
5
5
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
6
- import { IdleDetectionService } from '@pega/angular-sdk-components';
7
- import { ServerConfigService } from '@pega/angular-sdk-components';
8
6
 
9
7
  @Component({
10
8
  selector: 'app-assignment-card',
@@ -13,7 +11,7 @@ import { ServerConfigService } from '@pega/angular-sdk-components';
13
11
  standalone: true,
14
12
  imports: [CommonModule, ReactiveFormsModule, forwardRef(() => ComponentMapperComponent)]
15
13
  })
16
- export class AssignmentCardComponent implements OnInit, OnChanges, OnDestroy {
14
+ export class AssignmentCardComponent implements OnInit, OnChanges {
17
15
  @Input() pConn$: typeof PConnect;
18
16
  @Input() formGroup$: FormGroup;
19
17
  @Input() arMainButtons$: any[];
@@ -23,16 +21,10 @@ export class AssignmentCardComponent implements OnInit, OnChanges, OnDestroy {
23
21
 
24
22
  @Output() actionButtonClick: EventEmitter<any> = new EventEmitter();
25
23
 
26
- constructor(
27
- private idleService: IdleDetectionService,
28
- private scservice: ServerConfigService
29
- ) {}
30
-
31
24
  ngOnInit(): void {
32
- // Children may contain 'reference' component, so we need to normalize them
25
+ // Children may contain 'reference' component, so we need to
26
+ // normalize them
33
27
  this.arChildren$ = ReferenceComponent.normalizePConnArray(this.arChildren$);
34
-
35
- this.checkAndEnableAutoSave();
36
28
  }
37
29
 
38
30
  ngOnChanges() {
@@ -41,27 +33,7 @@ export class AssignmentCardComponent implements OnInit, OnChanges, OnDestroy {
41
33
  this.arChildren$ = ReferenceComponent.normalizePConnArray(this.arChildren$);
42
34
  }
43
35
 
44
- ngOnDestroy() {
45
- this.idleService.stopWatching();
46
- }
47
-
48
- async checkAndEnableAutoSave() {
49
- const sdkConfig = await this.scservice.getSdkConfig();
50
- const autoSave = sdkConfig.serverConfig.autoSave;
51
-
52
- if (autoSave) {
53
- this.idleService.startWatching(() => this.autoSave(), autoSave);
54
- }
55
- }
56
-
57
36
  onActionButtonClick(oData: any) {
58
37
  this.actionButtonClick.emit(oData);
59
38
  }
60
-
61
- autoSave() {
62
- const context = this.pConn$.getContextName();
63
- if (PCore.getFormUtils().isStateModified(context)) {
64
- this.pConn$.getActionsApi().saveAssignment(context);
65
- }
66
- }
67
39
  }
@@ -38,6 +38,7 @@ export class DeferLoadComponent implements OnInit, OnDestroy, OnChanges {
38
38
  CASE: any;
39
39
  PAGE: any;
40
40
  DATA: any;
41
+ lastUpdateCaseTime;
41
42
  constructor(private angularPConnect: AngularPConnectService) {
42
43
  this.constants = PCore.getConstants();
43
44
  }
@@ -58,8 +59,10 @@ export class DeferLoadComponent implements OnInit, OnDestroy, OnChanges {
58
59
  // Should always check the bridge to see if the component should
59
60
  // update itself (re-render)
60
61
  const theRequestedAssignment = this.pConn$.getValue(PCore.getConstants().CASE_INFO.ASSIGNMENT_LABEL);
61
- if (theRequestedAssignment !== this.currentLoadedAssignment) {
62
+ const lastUpdateCaseTime = this.pConn$.getValue('caseInfo.lastUpdateTime');
63
+ if (theRequestedAssignment !== this.currentLoadedAssignment || (lastUpdateCaseTime && lastUpdateCaseTime !== this.lastUpdateCaseTime)) {
62
64
  this.currentLoadedAssignment = theRequestedAssignment;
65
+ this.lastUpdateCaseTime = lastUpdateCaseTime;
63
66
  this.loadActiveTab();
64
67
  }
65
68
  }
@@ -13,49 +13,42 @@ import { Component } from '@angular/core';
13
13
  standalone: true
14
14
  })
15
15
  export class ReferenceComponent {
16
- referencedComponent: any = null;
17
-
18
16
  /* Used to toggle some class-wide logging */
19
17
  private static bLogging = false;
20
18
 
21
- constructor() {
22
- // With new static method approach, this shouldn't be called any more
23
- window.alert(`in ReferenceComponent constructor!`);
24
-
25
- console.error(`in ReferenceComponent constructor!`);
26
- }
27
-
28
- // onStateChange and updateSelf methods removed from original implementation
29
- // when we moved to the static method implementation.
30
-
31
- // STATIC method to create a normalized PConn (a fully realized View that the 'reference'
32
- // component refers to) from the given pConn. Has to add in some stuff as in the constructor
33
- static createFullReferencedViewFromRef(inPConn: any) {
34
- // BAIL and ERROR if inPConn is NOT a reference!
19
+ /**
20
+ * Creates a normalized PConn from a reference component.
21
+ * Resolves the reference to its fully realized View with proper configuration.
22
+ *
23
+ * @param inPConn - The PConn object that represents a reference component
24
+ * @returns The dereferenced PConnect object, or null if reference can't be resolved
25
+ */
26
+ static createFullReferencedViewFromRef(inPConn: any): any {
27
+ // Validate that inPConn is a reference component
35
28
  if (inPConn.getComponentName() !== 'reference') {
36
29
  console.error(`Reference component: createFullReferencedViewFromRef inPConn is NOT a reference! ${inPConn.getComponentName()}`);
30
+ return null;
37
31
  }
38
32
 
39
- const referenceConfig = { ...inPConn.getComponentConfig() } || {};
33
+ // Get reference configuration and make a copy
34
+ const referenceConfig = { ...inPConn.getComponentConfig() };
40
35
 
41
- // Since SDK-A implements Reference as static methods and we don't rely on
42
- // the Reference component's handling of the visibility prop, we leave it in
43
- // (and also leaving the others in for now) so the referenced View can act on
44
- // the visibility prop. (The following 3 lines were carried over from React SDK)
36
+ // Remove properties that should not be inherited by the referenced view
37
+ // (Maintained from React SDK implementation)
45
38
  delete referenceConfig?.name;
46
39
  delete referenceConfig?.type;
47
40
  delete referenceConfig?.visibility;
48
41
 
42
+ // Get the metadata for the referenced view
49
43
  const viewMetadata = inPConn.getReferencedView();
50
44
 
45
+ // Return null if view metadata is not found
51
46
  if (!viewMetadata) {
52
47
  console.log('View not found ', inPConn.getComponentConfig());
53
48
  return null;
54
49
  }
55
50
 
56
- // If we get here, we have metadata for a View component...
57
- // const referencedComponentName = viewMetadata.type;
58
-
51
+ // Create the view object by merging metadata with reference config
59
52
  const viewObject = {
60
53
  ...viewMetadata,
61
54
  config: {
@@ -64,26 +57,31 @@ export class ReferenceComponent {
64
57
  }
65
58
  };
66
59
 
67
- const theResolvedConfigProps = inPConn.resolveConfigProps(inPConn.getConfigProps());
68
- const { visibility = true, context, readOnly = false, displayMode = '' } = theResolvedConfigProps;
60
+ // Resolve configuration properties
61
+ const resolvedConfigProps = inPConn.resolveConfigProps(inPConn.getConfigProps());
62
+ const { visibility = true, context, readOnly = false, displayMode = '' } = resolvedConfigProps;
69
63
 
64
+ // Log debug information if logging is enabled
70
65
  if (ReferenceComponent.bLogging) {
71
66
  console.log(`Reference: about to call createComponent with pageReference: context: ${inPConn.getContextName()}`);
72
67
  }
73
68
 
69
+ // Create the component with the right context
74
70
  const viewComponent = inPConn.createComponent(viewObject, null, null, {
75
71
  pageReference: context && context.startsWith('@CLASS') ? '' : context
76
72
  });
77
73
 
78
- // updating the referencedComponent should trigger a render
74
+ // Get the PConnect object from the created component
79
75
  const newCompPConnect = viewComponent.getPConnect();
80
76
 
77
+ // Set inherited configuration on the new component
81
78
  newCompPConnect.setInheritedConfig({
82
79
  ...referenceConfig,
83
80
  readOnly,
84
81
  displayMode
85
82
  });
86
83
 
84
+ // Log debug information if logging is enabled
87
85
  if (ReferenceComponent.bLogging) {
88
86
  console.log(
89
87
  `Angular Reference component: createFullReferencedViewFromRef -> newCompPConnect configProps: ${JSON.stringify(
@@ -92,77 +90,63 @@ export class ReferenceComponent {
92
90
  );
93
91
  }
94
92
 
95
- if (visibility !== false) {
96
- return newCompPConnect;
97
- }
98
-
99
- return null;
93
+ // Return the component if it should be visible, otherwise null
94
+ return visibility !== false ? newCompPConnect : null;
100
95
  }
101
96
 
102
- // STATIC method that other components can call to normalize
103
- // a pConn object that might be a 'reference'. If the incoming
104
- // pConn is a reference, return its dereferenced View PConnect's
105
- // getPConnect. Otherwise, return the passed in pConn unchanged
106
- // inPConn = a PConn object (ex: { getPConnect()} )
107
- static normalizePConn(inPConn: any) {
108
- // debugger;
109
-
110
- let returnObj = false;
111
- let thePConnType = '';
112
-
113
- if (inPConn.getPConnect) {
114
- // inPConn is an object (ex: { getPConnect()} ), so we want to return
115
- // any referenced view as the object containing the
116
- // the getPConnect function
117
- returnObj = true;
118
- thePConnType = inPConn.getPConnect().getComponentName();
119
- } else {
120
- // inPConn is an object with the PConnect function, so we want
121
- // to return any referenced view as the object containing the
122
- // the c11n function
123
- returnObj = false;
124
- thePConnType = inPConn.getComponentName();
97
+ /**
98
+ * Normalizes a PConn object that might be a 'reference'.
99
+ * If the incoming PConn is a reference, returns its dereferenced View.
100
+ * Otherwise, returns the passed in PConn unchanged.
101
+ *
102
+ * @param inPConn - A PConn object (ex: { getPConnect() } or direct PConnect)
103
+ * @returns The normalized PConn object with references resolved
104
+ */
105
+ static normalizePConn(inPConn: any): any {
106
+ // Early return for null or undefined input
107
+ if (!inPConn) {
108
+ return inPConn;
125
109
  }
126
110
 
127
- if (thePConnType === 'reference') {
128
- if (returnObj) {
129
- // WAS...
130
- // const theRefViewPConn = inPConn.getPConnect().getReferencedViewPConnect(true);
131
- // Now: ALWAYS calling createFullReferencedViewFromRef to have options, PageReference, etc.
132
- // set correctly in the C11nEnv (PConnect) object
133
- // debugger;
134
- let theRefViewPConn = this.createFullReferencedViewFromRef(inPConn.getPConnect());
135
- // now return its PConnect
136
- theRefViewPConn = theRefViewPConn?.getComponent();
137
-
138
- // const theFullReference = theRefViewPConn.getPConnect().getFullReference();
139
- // console.log(`theFullReference: ${theFullReference}`);
140
-
141
- return theRefViewPConn;
111
+ // Determine if we have an object with getPConnect method or direct PConnect
112
+ const hasGetPConnectMethod = !!inPConn.getPConnect;
113
+
114
+ // Get the component name in the appropriate way based on the object type
115
+ const componentName = hasGetPConnectMethod ? inPConn.getPConnect().getComponentName() : inPConn.getComponentName();
116
+
117
+ // Only process if this is a reference component
118
+ if (componentName === 'reference') {
119
+ if (hasGetPConnectMethod) {
120
+ // For objects with getPConnect method, get the referenced view and its component
121
+ const refViewPConn = this.createFullReferencedViewFromRef(inPConn.getPConnect());
122
+ return refViewPConn?.getComponent();
142
123
  }
143
- // console.log(`created theFullRefView full reference: ${theFullRefView.getFullReference()}`);
144
- // debugger;
145
124
 
125
+ // For direct PConnect objects, just create the referenced view
146
126
  return this.createFullReferencedViewFromRef(inPConn);
147
127
  }
128
+
129
+ // Not a reference component, return unchanged
148
130
  return inPConn;
149
131
  }
150
132
 
151
- // STATIC method that other components can call to normalize
152
- // an array of pConn objects where any of the children might
153
- // be a 'reference'. The array returns an array of children
154
- // where any 'reference' is replaced with its ReferencedView
155
- // inPConnArray is an array of PConn objects or functions.
156
- // Its value is passed to normalizePConn
157
-
158
- static normalizePConnArray(inPConnArray: any) {
159
- if (!(inPConnArray?.length > 0)) {
160
- // null or empty array, return what was passed in
161
- return inPConnArray;
133
+ /**
134
+ * Normalizes an array of PConn objects by replacing any 'reference' components
135
+ * with their referenced views.
136
+ *
137
+ * @param inPConnArray - Array of PConn objects to normalize
138
+ * @returns Normalized array with references resolved, or empty array if input is invalid
139
+ */
140
+ static normalizePConnArray(inPConnArray: any[]): any[] {
141
+ // Handle null, undefined, or empty array case
142
+ if (!inPConnArray?.length) {
143
+ return inPConnArray || [];
162
144
  }
163
145
 
164
- return inPConnArray.map(child => {
165
- return ReferenceComponent.normalizePConn(child);
166
- });
146
+ // Process array: normalize each item and filter out any null/undefined results
147
+ const normalizedArray = inPConnArray.map(child => ReferenceComponent.normalizePConn(child)).filter(Boolean);
148
+
149
+ // Ensure we always return an array (even if filter removes all items)
150
+ return normalizedArray || [];
167
151
  }
168
152
  }