@pega/angular-sdk-overrides 0.242.6 → 0.242.8

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 (59) 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/currency/currency.component.ts +19 -13
  8. package/lib/field/date-time/date-time.component.html +0 -1
  9. package/lib/field/date-time/date-time.component.ts +17 -3
  10. package/lib/field/decimal/decimal.component.html +1 -0
  11. package/lib/field/decimal/decimal.component.ts +38 -15
  12. package/lib/field/dropdown/dropdown.component.ts +18 -3
  13. package/lib/field/email/email.component.ts +17 -7
  14. package/lib/field/integer/integer.component.html +1 -1
  15. package/lib/field/integer/integer.component.ts +16 -6
  16. package/lib/field/list-view-action-buttons/list-view-action-buttons.component.html +1 -1
  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/phone.component.ts +6 -13
  20. package/lib/field/rich-text/rich-text.component.ts +12 -3
  21. package/lib/field/text/text.component.ts +2 -2
  22. package/lib/field/text-area/text-area.component.html +1 -1
  23. package/lib/field/text-area/text-area.component.ts +16 -6
  24. package/lib/field/text-input/text-input.component.html +1 -1
  25. package/lib/field/text-input/text-input.component.ts +16 -6
  26. package/lib/field/time/time.component.html +1 -1
  27. package/lib/field/time/time.component.ts +21 -6
  28. package/lib/field/url/url.component.html +1 -1
  29. package/lib/field/url/url.component.ts +16 -6
  30. package/lib/field/user-reference/user-reference.component.html +40 -38
  31. package/lib/field/user-reference/user-reference.component.ts +66 -7
  32. package/lib/infra/Containers/flow-container/flow-container.component.ts +2 -5
  33. package/lib/infra/Containers/flow-container/helpers.ts +1 -1
  34. package/lib/infra/Containers/modal-view-container/modal-view-container.component.html +1 -11
  35. package/lib/infra/Containers/modal-view-container/modal-view-container.component.ts +0 -1
  36. package/lib/infra/action-buttons/action-buttons.component.html +1 -1
  37. package/lib/infra/assignment/assignment.component.ts +3 -5
  38. package/lib/infra/assignment-card/assignment-card.component.ts +4 -32
  39. package/lib/infra/defer-load/defer-load.component.ts +4 -1
  40. package/lib/infra/reference/reference.component.ts +77 -90
  41. package/lib/infra/root-container/root-container.component.ts +24 -17
  42. package/lib/template/base/form-template-base.ts +2 -2
  43. package/lib/template/default-form/default-form.component.ts +5 -7
  44. package/lib/template/field-group-template/field-group-template.component.html +7 -7
  45. package/lib/template/field-group-template/field-group-template.component.scss +8 -0
  46. package/lib/template/field-group-template/field-group-template.component.ts +64 -41
  47. package/lib/template/field-group-template/utils.ts +9 -0
  48. package/lib/template/field-value-list/field-value-list.component.html +2 -2
  49. package/lib/template/field-value-list/field-value-list.component.scss +4 -0
  50. package/lib/template/list-view/list-view.component.html +3 -1
  51. package/lib/template/list-view/list-view.component.ts +1 -1
  52. package/lib/template/simple-table-manual/helpers.ts +18 -2
  53. package/lib/template/simple-table-manual/simple-table-manual.component.html +25 -6
  54. package/lib/template/simple-table-manual/simple-table-manual.component.scss +7 -3
  55. package/lib/template/simple-table-manual/simple-table-manual.component.ts +62 -23
  56. package/lib/widget/todo/todo.component.html +1 -2
  57. package/lib/widget/todo/todo.component.scss +2 -0
  58. package/lib/widget/todo/todo.component.ts +4 -3
  59. package/package.json +1 -1
@@ -13,53 +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
- // debugger;
37
-
38
29
  console.error(`Reference component: createFullReferencedViewFromRef inPConn is NOT a reference! ${inPConn.getComponentName()}`);
30
+ return null;
39
31
  }
40
32
 
41
- const theResolvedConfigProps = inPConn.resolveConfigProps(inPConn.getConfigProps());
42
-
43
- const referenceConfig = { ...inPConn.getComponentConfig() } || {};
33
+ // Get reference configuration and make a copy
34
+ const referenceConfig = { ...inPConn.getComponentConfig() };
44
35
 
45
- // Since SDK-A implements Reference as static methods and we don't rely on
46
- // the Reference component's handling of the visibility prop, we leave it in
47
- // (and also leaving the others in for now) so the referenced View can act on
48
- // 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)
49
38
  delete referenceConfig?.name;
50
- // delete referenceConfig?.type;
51
- // delete referenceConfig?.visibility;
39
+ delete referenceConfig?.type;
40
+ delete referenceConfig?.visibility;
52
41
 
42
+ // Get the metadata for the referenced view
53
43
  const viewMetadata = inPConn.getReferencedView();
54
44
 
45
+ // Return null if view metadata is not found
55
46
  if (!viewMetadata) {
56
47
  console.log('View not found ', inPConn.getComponentConfig());
57
48
  return null;
58
49
  }
59
50
 
60
- // If we get here, we have metadata for a View component...
61
- // const referencedComponentName = viewMetadata.type;
62
-
51
+ // Create the view object by merging metadata with reference config
63
52
  const viewObject = {
64
53
  ...viewMetadata,
65
54
  config: {
@@ -68,23 +57,31 @@ export class ReferenceComponent {
68
57
  }
69
58
  };
70
59
 
60
+ // Resolve configuration properties
61
+ const resolvedConfigProps = inPConn.resolveConfigProps(inPConn.getConfigProps());
62
+ const { visibility = true, context, readOnly = false, displayMode = '' } = resolvedConfigProps;
63
+
64
+ // Log debug information if logging is enabled
71
65
  if (ReferenceComponent.bLogging) {
72
- console.log(`Reference: about to call createComponent with pageReference: context: ${theResolvedConfigProps.context}`);
66
+ console.log(`Reference: about to call createComponent with pageReference: context: ${inPConn.getContextName()}`);
73
67
  }
74
68
 
69
+ // Create the component with the right context
75
70
  const viewComponent = inPConn.createComponent(viewObject, null, null, {
76
- pageReference: theResolvedConfigProps.context
71
+ pageReference: context && context.startsWith('@CLASS') ? '' : context
77
72
  });
78
73
 
79
- // updating the referencedComponent should trigger a render
74
+ // Get the PConnect object from the created component
80
75
  const newCompPConnect = viewComponent.getPConnect();
81
76
 
77
+ // Set inherited configuration on the new component
82
78
  newCompPConnect.setInheritedConfig({
83
79
  ...referenceConfig,
84
- readOnly: theResolvedConfigProps.readOnly ? theResolvedConfigProps.readOnly : false,
85
- displayMode: theResolvedConfigProps.displayMode ? theResolvedConfigProps.displayMode : null
80
+ readOnly,
81
+ displayMode
86
82
  });
87
83
 
84
+ // Log debug information if logging is enabled
88
85
  if (ReferenceComponent.bLogging) {
89
86
  console.log(
90
87
  `Angular Reference component: createFullReferencedViewFromRef -> newCompPConnect configProps: ${JSON.stringify(
@@ -93,73 +90,63 @@ export class ReferenceComponent {
93
90
  );
94
91
  }
95
92
 
96
- return newCompPConnect;
93
+ // Return the component if it should be visible, otherwise null
94
+ return visibility !== false ? newCompPConnect : null;
97
95
  }
98
96
 
99
- // STATIC method that other components can call to normalize
100
- // a pConn object that might be a 'reference'. If the incoming
101
- // pConn is a reference, return its dereferenced View PConnect's
102
- // getPConnect. Otherwise, return the passed in pConn unchanged
103
- // inPConn = a PConn object (ex: { getPConnect()} )
104
- static normalizePConn(inPConn: any) {
105
- // debugger;
106
-
107
- let returnObj = false;
108
- let thePConnType = '';
109
-
110
- if (inPConn.getPConnect) {
111
- // inPConn is an object (ex: { getPConnect()} ), so we want to return
112
- // any referenced view as the object containing the
113
- // the getPConnect function
114
- returnObj = true;
115
- thePConnType = inPConn.getPConnect().getComponentName();
116
- } else {
117
- // inPConn is an object with the PConnect function, so we want
118
- // to return any referenced view as the object containing the
119
- // the c11n function
120
- returnObj = false;
121
- 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;
122
109
  }
123
110
 
124
- if (thePConnType === 'reference') {
125
- if (returnObj) {
126
- // WAS...
127
- // const theRefViewPConn = inPConn.getPConnect().getReferencedViewPConnect(true);
128
- // Now: ALWAYS calling createFullReferencedViewFromRef to have options, PageReference, etc.
129
- // set correctly in the C11nEnv (PConnect) object
130
- // debugger;
131
- let theRefViewPConn = this.createFullReferencedViewFromRef(inPConn.getPConnect());
132
- // now return its PConnect
133
- theRefViewPConn = theRefViewPConn.getComponent();
134
-
135
- // const theFullReference = theRefViewPConn.getPConnect().getFullReference();
136
- // console.log(`theFullReference: ${theFullReference}`);
137
-
138
- 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();
139
123
  }
140
- // console.log(`created theFullRefView full reference: ${theFullRefView.getFullReference()}`);
141
- // debugger;
142
124
 
125
+ // For direct PConnect objects, just create the referenced view
143
126
  return this.createFullReferencedViewFromRef(inPConn);
144
127
  }
128
+
129
+ // Not a reference component, return unchanged
145
130
  return inPConn;
146
131
  }
147
132
 
148
- // STATIC method that other components can call to normalize
149
- // an array of pConn objects where any of the children might
150
- // be a 'reference'. The array returns an array of children
151
- // where any 'reference' is replaced with its ReferencedView
152
- // inPConnArray is an array of PConn objects or functions.
153
- // Its value is passed to normalizePConn
154
-
155
- static normalizePConnArray(inPConnArray: any) {
156
- if (!(inPConnArray?.length > 0)) {
157
- // null or empty array, return what was passed in
158
- 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 || [];
159
144
  }
160
145
 
161
- return inPConnArray.map(child => {
162
- return ReferenceComponent.normalizePConn(child);
163
- });
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 || [];
164
151
  }
165
152
  }
@@ -1,8 +1,9 @@
1
- import { Component, OnInit, Input, NgZone, forwardRef, OnDestroy } from '@angular/core';
1
+ import { Component, OnInit, Input, NgZone, forwardRef, OnDestroy, inject } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
4
4
  import { interval, Subscription } from 'rxjs';
5
5
  import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
6
+ import { ServerConfigService } from '@pega/angular-sdk-components';
6
7
  import { ProgressSpinnerService } from '@pega/angular-sdk-components';
7
8
  import { ReferenceComponent } from '@pega/angular-sdk-components';
8
9
  import { PreviewViewContainerComponent } from '@pega/angular-sdk-components';
@@ -37,6 +38,8 @@ export class RootContainerComponent implements OnInit, OnDestroy {
37
38
  @Input() displayOnlyFA$: boolean;
38
39
  @Input() isMashup$: boolean;
39
40
 
41
+ scService = inject(ServerConfigService);
42
+
40
43
  // For interaction with AngularPConnect
41
44
  angularPConnectData: AngularPConnectData = {};
42
45
 
@@ -62,8 +65,6 @@ export class RootContainerComponent implements OnInit, OnDestroy {
62
65
  ) {}
63
66
 
64
67
  ngOnInit(): void {
65
- const myContext = 'app';
66
-
67
68
  const { containers } = PCore.getStore().getState();
68
69
  const items = Object.keys(containers).filter(item => item.includes('root'));
69
70
 
@@ -84,24 +85,11 @@ export class RootContainerComponent implements OnInit, OnDestroy {
84
85
 
85
86
  this.pvConn$ = configObjPreview.getPConnect();
86
87
 
87
- const configObjModal = PCore.createPConnect({
88
- meta: {
89
- type: 'ModalViewContainer',
90
- config: {
91
- name: 'modal'
92
- }
93
- },
94
- options: {
95
- pageReference: 'pyPortal',
96
- context: myContext
97
- }
98
- });
88
+ this.configureModalContainer();
99
89
 
100
90
  // clear out hasViewContainer
101
91
  sessionStorage.setItem('hasViewContainer', 'false');
102
92
 
103
- this.mConn$ = configObjModal.getPConnect();
104
-
105
93
  // First thing in initialization is registering and subscribing to the AngularPConnect service
106
94
  this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
107
95
 
@@ -181,6 +169,25 @@ export class RootContainerComponent implements OnInit, OnDestroy {
181
169
  }
182
170
  }
183
171
 
172
+ async configureModalContainer() {
173
+ const sdkConfig = await this.scService.getSdkConfig();
174
+ const showModalsInEmbedMode = sdkConfig.serverConfig.showModalsInEmbedMode;
175
+
176
+ if (!this.displayOnlyFA$ || showModalsInEmbedMode) {
177
+ const configObjModal = PCore.createPConnect({
178
+ meta: {
179
+ type: 'ModalViewContainer',
180
+ config: {
181
+ name: 'modal'
182
+ }
183
+ },
184
+ options
185
+ });
186
+
187
+ this.mConn$ = configObjModal.getPConnect();
188
+ }
189
+ }
190
+
184
191
  generateViewContainerForNoPortal() {
185
192
  // bootstrap loadMashup resolves to here
186
193
  const arChildren = this.pConn$.getChildren() as any[];
@@ -1,5 +1,5 @@
1
1
  import { Directive, OnDestroy } from '@angular/core';
2
- import { AngularPConnectData } from 'packages/angular-sdk-components/src/public-api';
2
+ import { AngularPConnectData } from '@pega/angular-sdk-components';
3
3
 
4
4
  @Directive()
5
5
  export class FormTemplateBase implements OnDestroy {
@@ -9,7 +9,7 @@ export class FormTemplateBase implements OnDestroy {
9
9
  ngOnDestroy(): void {
10
10
  PCore.getContextTreeManager().removeContextTreeNode(this.pConn$.getContextName());
11
11
 
12
- if (this.angularPConnectData.unsubscribeFn) {
12
+ if (this.angularPConnectData?.unsubscribeFn) {
13
13
  this.angularPConnectData.unsubscribeFn();
14
14
  }
15
15
  }
@@ -1,8 +1,8 @@
1
- import { Component, OnInit, Input, forwardRef, OnDestroy } from '@angular/core';
1
+ import { Component, OnInit, Input, forwardRef } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { FormGroup } from '@angular/forms';
4
- import { ReferenceComponent } from '@pega/angular-sdk-components';
5
4
  import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
5
+ import { ReferenceComponent } from '@pega/angular-sdk-components';
6
6
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
7
7
  import { TemplateUtils } from '@pega/angular-sdk-components';
8
8
  import { FormTemplateBase } from '@pega/angular-sdk-components';
@@ -31,7 +31,7 @@ interface DefaultFormProps {
31
31
  standalone: true,
32
32
  imports: [CommonModule, forwardRef(() => ComponentMapperComponent)]
33
33
  })
34
- export class DefaultFormComponent extends FormTemplateBase implements OnInit, OnDestroy {
34
+ export class DefaultFormComponent extends FormTemplateBase implements OnInit {
35
35
  @Input() override pConn$: typeof PConnect;
36
36
  @Input() formGroup$: FormGroup;
37
37
 
@@ -86,10 +86,8 @@ export class DefaultFormComponent extends FormTemplateBase implements OnInit, On
86
86
  // normalize them
87
87
  const children = ReferenceComponent.normalizePConnArray(kids[0].getPConnect().getChildren());
88
88
 
89
- const visibleChildren = children?.filter(child => child !== undefined) || [];
90
-
91
- if (areViewsChanged(this.arChildren$, visibleChildren)) {
92
- this.arChildren$ = visibleChildren;
89
+ if (areViewsChanged(this.arChildren$, children)) {
90
+ this.arChildren$ = children;
93
91
  }
94
92
  }
95
93
  }
@@ -1,5 +1,5 @@
1
1
  <div id="field-group">
2
- <h3 *ngIf="showLabel$" className="label" style="font-weight: bold">
2
+ <h3 *ngIf="showLabel$" class="field-group-template-header" style="font-weight: bold">
3
3
  {{ label$ }}
4
4
  </h3>
5
5
  <div *ngIf="readonlyMode; else editable">
@@ -11,23 +11,23 @@
11
11
  </div>
12
12
  <ng-template #editable>
13
13
  <div *ngIf="children && children.length > 0">
14
- <div *ngFor="let kid of children; let i = index">
14
+ <div class="field-group-template-item" *ngFor="let child of children; let i = index">
15
15
  <div class="header-div">
16
16
  <div style="width: 80%">
17
- <b>{{ kid.name }}</b>
17
+ <b>{{ child.name }}</b>
18
18
  </div>
19
- <div *ngIf="allowAddEdit !== false" style="width: 20%; text-align: right">
19
+ <div *ngIf="allowDelete && child.allowRowDelete" style="width: 20%; text-align: right">
20
20
  <button id="delete-button" mat-icon-button (click)="deleteFieldGroupItem(i)">
21
21
  <img class="psdk-utility-card-action-svg-icon" src="{{ menuIconOverride$ }}" />
22
22
  </button>
23
23
  </div>
24
24
  </div>
25
25
 
26
- <div *ngIf="kid.children.getPConnect().getRawMetadata().type.toLowerCase() == 'region'">
27
- <component-mapper name="Region" [props]="{ pConn$: kid.children.getPConnect(), formGroup$ }"></component-mapper>
26
+ <div *ngIf="child.children.getPConnect().getRawMetadata().type.toLowerCase() == 'region'">
27
+ <component-mapper name="Region" [props]="{ pConn$: child.children.getPConnect(), formGroup$ }"></component-mapper>
28
28
  </div>
29
29
  </div>
30
- <button *ngIf="allowAddEdit !== false" mat-button color="primary" style="font-size: 16px" (click)="addFieldGroupItem()">+ Add</button>
31
30
  </div>
31
+ <button *ngIf="allowAdd" mat-button color="primary" style="font-size: 16px" (click)="addFieldGroupItem()">{{ getAddBtnLabel() }}</button>
32
32
  </ng-template>
33
33
  </div>
@@ -6,3 +6,11 @@
6
6
  display: flex;
7
7
  align-items: center;
8
8
  }
9
+
10
+ .field-group-template-header {
11
+ margin-left: 0;
12
+ }
13
+
14
+ .field-group-template-item {
15
+ padding-block: 1rem;
16
+ }
@@ -1,4 +1,4 @@
1
- import { Component, OnInit, Input, forwardRef, OnDestroy, OnChanges } from '@angular/core';
1
+ import { Component, OnInit, Input, forwardRef, OnDestroy, OnChanges, AfterViewInit } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { FormGroup } from '@angular/forms';
4
4
  import { MatButtonModule } from '@angular/material/button';
@@ -6,11 +6,14 @@ import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-c
6
6
  import { buildView, getReferenceList } from '@pega/angular-sdk-components';
7
7
  import { Utils } from '@pega/angular-sdk-components';
8
8
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
9
+ import { evaluateAllowRowAction } from './utils';
9
10
 
10
11
  interface FieldGroupTemplateProps {
11
12
  // If any, enter additional props that only exist on this component
12
13
  label?: string;
13
- showLabel?: boolean;
14
+ hideLabel?: boolean;
15
+ allowActions?: any;
16
+ allowRowDelete?: any;
14
17
  referenceList?: any[];
15
18
  contextClass: string;
16
19
  renderMode?: string;
@@ -19,6 +22,7 @@ interface FieldGroupTemplateProps {
19
22
  displayMode?: string;
20
23
  fieldHeader?: string;
21
24
  allowTableEdit: boolean;
25
+ targetClassLabel?: string;
22
26
  }
23
27
 
24
28
  @Component({
@@ -28,26 +32,27 @@ interface FieldGroupTemplateProps {
28
32
  standalone: true,
29
33
  imports: [CommonModule, MatButtonModule, forwardRef(() => ComponentMapperComponent)]
30
34
  })
31
- export class FieldGroupTemplateComponent implements OnInit, OnDestroy, OnChanges {
35
+ export class FieldGroupTemplateComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
32
36
  @Input() configProps$: FieldGroupTemplateProps;
33
37
  @Input() pConn$: typeof PConnect;
34
38
  @Input() formGroup$: FormGroup;
35
39
 
36
40
  angularPConnectData: AngularPConnectData = {};
37
- inheritedProps$: object;
41
+
38
42
  showLabel$?: boolean = true;
39
43
  label$?: string;
40
44
  readonlyMode: boolean;
41
45
  contextClass: any;
42
- referenceList: any;
43
- pageReference: any;
44
46
  heading: any;
45
47
  children: any;
46
48
  menuIconOverride$: any;
47
- prevRefLength: number;
48
- allowAddEdit: boolean;
49
+ referenceListLength: number;
49
50
  fieldHeader: any;
50
51
 
52
+ allowAdd = true;
53
+ allowEdit = true;
54
+ allowDelete = true;
55
+
51
56
  constructor(
52
57
  private angularPConnect: AngularPConnectService,
53
58
  private utils: Utils
@@ -58,9 +63,21 @@ export class FieldGroupTemplateComponent implements OnInit, OnDestroy, OnChanges
58
63
  this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
59
64
  this.updateSelf();
60
65
 
61
- const menuIconOverride$ = 'trash';
62
- if (menuIconOverride$) {
63
- this.menuIconOverride$ = this.utils.getImageSrc(menuIconOverride$, this.utils.getSDKStaticContentUrl());
66
+ this.menuIconOverride$ = this.utils.getImageSrc('trash', this.utils.getSDKStaticContentUrl());
67
+
68
+ const { allowActions, allowTableEdit, referenceList } = this.configProps$;
69
+
70
+ if (allowActions && Object.keys(allowActions).length > 0) {
71
+ this.allowAdd = allowActions.allowAdd ?? allowTableEdit ?? true;
72
+ this.allowEdit = allowActions.allowEdit ?? true;
73
+ this.allowDelete = allowActions.allowDelete ?? allowTableEdit ?? true;
74
+ } else {
75
+ this.allowAdd = allowTableEdit ?? true;
76
+ this.allowDelete = allowTableEdit ?? true;
77
+ }
78
+
79
+ if (referenceList?.length === 0 && (this.allowAdd || this.allowEdit)) {
80
+ this.pConn$.getListActions().insert({ classID: this.contextClass }, referenceList.length);
64
81
  }
65
82
  }
66
83
 
@@ -85,56 +102,57 @@ export class FieldGroupTemplateComponent implements OnInit, OnDestroy, OnChanges
85
102
  const props = changes.configProps$;
86
103
  if (props.currentValue !== props.previousValue) {
87
104
  this.configProps$ = props.currentValue;
105
+
88
106
  if (changes?.pConn$?.currentValue) {
89
107
  this.pConn$ = changes?.pConn$?.currentValue;
90
108
  }
109
+
91
110
  this.updateSelf();
92
111
  }
93
112
  }
94
113
  }
95
114
 
115
+ ngAfterViewInit() {
116
+ const resolvedList = getReferenceList(this.pConn$);
117
+ // @ts-ignore - Expected 3 arguments, but got 1
118
+ this.pConn$.getListActions().initDefaultPageInstructions(resolvedList);
119
+ }
120
+
96
121
  updateSelf() {
97
- this.inheritedProps$ = this.pConn$.getInheritedProps();
98
- this.label$ = this.configProps$.label;
99
- this.showLabel$ = this.configProps$.showLabel;
100
- // label & showLabel within inheritedProps takes precedence over configProps
101
- this.label$ = (this.inheritedProps$ as any).label || this.label$;
102
- this.showLabel$ = (this.inheritedProps$ as any).showLabel || this.showLabel$;
122
+ const inheritedProps: any = this.pConn$.getInheritedProps();
103
123
 
104
- this.allowAddEdit = this.configProps$.allowTableEdit;
124
+ const { label, hideLabel, allowRowDelete, referenceList, fieldHeader, renderMode, displayMode, heading, contextClass, lookForChildInConfig } =
125
+ this.configProps$;
126
+
127
+ // label within inheritedProps takes precedence over configProps
128
+ this.label$ = inheritedProps.label || label;
129
+
130
+ this.showLabel$ = referenceList?.length === 0 || !hideLabel;
105
131
 
106
- const renderMode = this.configProps$.renderMode;
107
- const displayMode = this.configProps$.displayMode;
108
132
  this.readonlyMode = renderMode === 'ReadOnly' || displayMode === 'DISPLAY_ONLY';
109
- this.contextClass = this.configProps$.contextClass;
110
- const lookForChildInConfig = this.configProps$.lookForChildInConfig;
111
- this.heading = this.configProps$.heading ?? 'Row';
112
- this.fieldHeader = this.configProps$.fieldHeader;
133
+
134
+ this.contextClass = contextClass;
135
+ this.heading = heading ?? 'Row';
136
+ this.fieldHeader = fieldHeader;
137
+
113
138
  const resolvedList = getReferenceList(this.pConn$);
114
- this.pageReference = `${this.pConn$.getPageReference()}${resolvedList}`;
115
139
  this.pConn$.setReferenceList(resolvedList);
140
+
116
141
  if (this.readonlyMode) {
117
142
  this.pConn$.setInheritedProp('displayMode', 'DISPLAY_ONLY');
118
143
  }
119
- this.referenceList = this.configProps$.referenceList;
120
- if (this.prevRefLength != this.referenceList.length) {
121
- // eslint-disable-next-line sonarjs/no-collapsible-if
122
- if (!this.readonlyMode) {
123
- if (this.referenceList?.length === 0 && this.allowAddEdit !== false) {
124
- this.addFieldGroupItem();
125
- }
126
- }
127
- const children: any = [];
128
- this.referenceList?.forEach((item, index) => {
129
- children.push({
144
+
145
+ if (this.referenceListLength != referenceList?.length) {
146
+ this.children = referenceList?.map((item, index) => {
147
+ return {
130
148
  id: index,
131
149
  name: this.fieldHeader === 'propertyRef' ? this.getDynamicHeader(item, index) : this.getStaticHeader(this.heading, index),
132
- children: buildView(this.pConn$, index, lookForChildInConfig)
133
- });
150
+ children: buildView(this.pConn$, index, lookForChildInConfig),
151
+ allowRowDelete: evaluateAllowRowAction(allowRowDelete, item)
152
+ };
134
153
  });
135
- this.children = children;
136
154
  }
137
- this.prevRefLength = this.referenceList.length;
155
+ this.referenceListLength = referenceList?.length || 0;
138
156
  }
139
157
 
140
158
  getStaticHeader = (heading, index) => {
@@ -149,10 +167,15 @@ export class FieldGroupTemplateComponent implements OnInit, OnDestroy, OnChanges
149
167
  };
150
168
 
151
169
  addFieldGroupItem() {
152
- this.pConn$.getListActions().insert({ classID: this.contextClass }, this.referenceList.length);
170
+ this.pConn$.getListActions().insert({ classID: this.contextClass }, this.referenceListLength);
153
171
  }
154
172
 
155
173
  deleteFieldGroupItem(index) {
156
174
  this.pConn$.getListActions().deleteEntry(index);
157
175
  }
176
+
177
+ getAddBtnLabel() {
178
+ const { targetClassLabel } = this.configProps$;
179
+ return targetClassLabel ? `+ Add ${targetClassLabel}` : '+ Add';
180
+ }
158
181
  }
@@ -0,0 +1,9 @@
1
+ export const evaluateAllowRowAction = (allowRowDelete, rowData) => {
2
+ if (allowRowDelete === undefined || allowRowDelete === true) return true;
3
+ if (allowRowDelete.startsWith?.('@E ')) {
4
+ const expression = allowRowDelete.replace('@E ', '');
5
+ // @ts-ignore
6
+ return PCore.getExpressionEngine().evaluate(expression, rowData);
7
+ }
8
+ return false;
9
+ };
@@ -1,5 +1,5 @@
1
- <div *ngIf="displayMode$ === 'DISPLAY_ONLY'; else STACKED_LARGE_VAL" class="psdk-container-labels-left">
2
- <div class="psdk-grid-label">{{ label$ }}</div>
1
+ <div *ngIf="displayMode$ === 'DISPLAY_ONLY'; else STACKED_LARGE_VAL" [ngClass]="label$ ? 'psdk-container-labels-left' : 'psdk-container-nolabels'">
2
+ <div *ngIf="label$" class="psdk-grid-label">{{ label$ }}</div>
3
3
  <div class="psdk-val-labels-left">
4
4
  <ng-container *ngTemplateOutlet="valueTemplate"></ng-container>
5
5
  </div>
@@ -6,6 +6,10 @@
6
6
  align-items: start;
7
7
  padding-block: 8px;
8
8
  }
9
+ .psdk-container-nolabels {
10
+ align-items: start;
11
+ padding-block: 8px;
12
+ }
9
13
  .psdk-value {
10
14
  margin: 8px 0px;
11
15
  }
@@ -180,7 +180,9 @@
180
180
  <tr mat-header-row *matHeaderRowDef="displayedColumns$"></tr>
181
181
  </table>
182
182
  </div>
183
- <div class="psdk-no-records" *ngIf="repeatListData?.length === 0">No Records Found.</div>
183
+ <div class="psdk-no-records" *ngIf="repeatListData?.length === 0">
184
+ {{ utils.getGenericFieldsLocalizedValue('CosmosFields.fields.lists', 'No records found.') }}
185
+ </div>
184
186
  </div>
185
187
  </div>
186
188
  </div>
@@ -165,7 +165,7 @@ export class ListViewComponent implements OnInit, OnDestroy {
165
165
 
166
166
  constructor(
167
167
  private psService: ProgressSpinnerService,
168
- private utils: Utils
168
+ public utils: Utils
169
169
  ) {}
170
170
 
171
171
  ngOnInit(): void {