@pega/angular-sdk-overrides 24.1.10 → 24.2.12

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 (125) hide show
  1. package/lib/designSystemExtension/alert-banner/alert-banner.component.ts +1 -1
  2. package/lib/designSystemExtension/case-create-stage/case-create-stage.component.ts +1 -1
  3. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.scss +2 -1
  4. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.ts +0 -1
  5. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.html +2 -2
  6. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.ts +10 -1
  7. package/lib/designSystemExtension/operator/operator.component.html +1 -1
  8. package/lib/designSystemExtension/operator/operator.component.scss +10 -2
  9. package/lib/designSystemExtension/operator/operator.component.ts +5 -4
  10. package/lib/designSystemExtension/pulse/pulse.component.ts +7 -7
  11. package/lib/field/auto-complete/auto-complete.component.html +0 -1
  12. package/lib/field/auto-complete/auto-complete.component.ts +31 -15
  13. package/lib/field/check-box/check-box.component.html +4 -0
  14. package/lib/field/check-box/check-box.component.ts +11 -10
  15. package/lib/field/currency/currency.component.html +4 -4
  16. package/lib/field/currency/currency.component.ts +42 -19
  17. package/lib/field/date/date.component.html +3 -7
  18. package/lib/field/date/date.component.ts +22 -39
  19. package/lib/field/date-time/date-time.component.html +3 -4
  20. package/lib/field/date-time/date-time.component.ts +35 -16
  21. package/lib/field/decimal/decimal.component.html +4 -3
  22. package/lib/field/decimal/decimal.component.ts +47 -21
  23. package/lib/field/dropdown/dropdown.component.html +1 -0
  24. package/lib/field/dropdown/dropdown.component.ts +146 -18
  25. package/lib/field/email/email.component.ts +24 -4
  26. package/lib/field/group/group.component.ts +2 -2
  27. package/lib/field/integer/integer.component.ts +22 -4
  28. package/lib/field/list-view-action-buttons/list-view-action-buttons.component.html +1 -1
  29. package/lib/field/list-view-action-buttons/list-view-action-buttons.component.ts +3 -2
  30. package/lib/field/multiselect/multiselect.component.ts +15 -5
  31. package/lib/field/percentage/percentage.component.html +3 -3
  32. package/lib/field/percentage/percentage.component.ts +45 -20
  33. package/lib/field/phone/config-ext.json +1 -1
  34. package/lib/field/phone/phone.component.html +4 -2
  35. package/lib/field/phone/phone.component.ts +16 -26
  36. package/lib/field/radio-buttons/radio-buttons.component.html +3 -6
  37. package/lib/field/radio-buttons/radio-buttons.component.ts +9 -9
  38. package/lib/field/rich-text/rich-text.component.ts +19 -8
  39. package/lib/field/scalar-list/scalar-list.component.ts +3 -4
  40. package/lib/field/text/text.component.ts +8 -4
  41. package/lib/field/text-area/text-area.component.html +4 -1
  42. package/lib/field/text-area/text-area.component.ts +22 -5
  43. package/lib/field/text-input/text-input.component.ts +22 -4
  44. package/lib/field/time/time.component.html +2 -2
  45. package/lib/field/time/time.component.ts +35 -6
  46. package/lib/field/url/url.component.ts +22 -4
  47. package/lib/field/user-reference/user-reference.component.html +40 -46
  48. package/lib/field/user-reference/user-reference.component.ts +111 -20
  49. package/lib/infra/Containers/flow-container/flow-container.component.html +1 -1
  50. package/lib/infra/Containers/flow-container/flow-container.component.ts +25 -47
  51. package/lib/infra/Containers/flow-container/helpers.ts +2 -2
  52. package/lib/infra/Containers/modal-view-container/modal-view-container.component.html +1 -11
  53. package/lib/infra/Containers/modal-view-container/modal-view-container.component.ts +1 -8
  54. package/lib/infra/Containers/preview-view-container/preview-view-container.component.ts +1 -1
  55. package/lib/infra/Containers/view-container/helper.ts +22 -0
  56. package/lib/infra/Containers/view-container/view-container.component.ts +5 -17
  57. package/lib/infra/action-buttons/action-buttons.component.html +1 -1
  58. package/lib/infra/assignment/assignment.component.html +1 -1
  59. package/lib/infra/assignment/assignment.component.ts +82 -40
  60. package/lib/infra/assignment-card/assignment-card.component.html +1 -0
  61. package/lib/infra/defer-load/defer-load.component.ts +8 -5
  62. package/lib/infra/navbar/navbar.component.ts +3 -5
  63. package/lib/infra/reference/reference.component.ts +77 -90
  64. package/lib/infra/root-container/root-container.component.html +2 -15
  65. package/lib/infra/root-container/root-container.component.ts +27 -30
  66. package/lib/infra/stages/stages.component.scss +2 -2
  67. package/lib/infra/view/view.component.html +7 -20
  68. package/lib/infra/view/view.component.ts +20 -2
  69. package/lib/template/app-shell/app-shell.component.ts +20 -2
  70. package/lib/template/base/details-template-base.ts +67 -0
  71. package/lib/template/base/form-template-base.ts +16 -0
  72. package/lib/template/case-summary/case-summary.component.ts +1 -1
  73. package/lib/template/case-view/case-view.component.html +4 -4
  74. package/lib/template/case-view/case-view.component.ts +8 -13
  75. package/lib/template/confirmation/confirmation.component.html +1 -1
  76. package/lib/template/confirmation/confirmation.component.ts +1 -1
  77. package/lib/template/data-reference/data-reference.component.ts +36 -40
  78. package/lib/template/default-form/default-form.component.html +0 -4
  79. package/lib/template/default-form/default-form.component.ts +41 -24
  80. package/lib/template/details/details.component.ts +7 -41
  81. package/lib/template/details-narrow-wide/details-narrow-wide.component.ts +6 -39
  82. package/lib/template/details-one-column/details-one-column.component.ts +7 -42
  83. package/lib/template/details-sub-tabs/details-sub-tabs.component.html +1 -2
  84. package/lib/template/details-sub-tabs/details-sub-tabs.component.ts +5 -37
  85. package/lib/template/details-three-column/details-three-column.component.ts +7 -43
  86. package/lib/template/details-two-column/details-two-column.component.ts +8 -44
  87. package/lib/template/details-wide-narrow/details-wide-narrow.component.ts +7 -42
  88. package/lib/template/dynamic-tabs/dynamic-tabs.component.html +3 -0
  89. package/lib/template/dynamic-tabs/dynamic-tabs.component.ts +8 -3
  90. package/lib/template/field-group-template/field-group-template.component.html +7 -7
  91. package/lib/template/field-group-template/field-group-template.component.scss +8 -0
  92. package/lib/template/field-group-template/field-group-template.component.ts +68 -47
  93. package/lib/template/field-value-list/field-value-list.component.html +2 -2
  94. package/lib/template/field-value-list/field-value-list.component.scss +6 -1
  95. package/lib/template/inline-dashboard-page/inline-dashboard-page.component.ts +2 -2
  96. package/lib/template/list-view/list-view.component.html +6 -1
  97. package/lib/template/list-view/list-view.component.scss +11 -0
  98. package/lib/template/list-view/list-view.component.ts +25 -7
  99. package/lib/template/list-view/listViewHelpers.ts +3 -6
  100. package/lib/template/list-view/utils.ts +2 -5
  101. package/lib/template/narrow-wide-form/narrow-wide-form.component.ts +1 -1
  102. package/lib/template/one-column/one-column.component.ts +4 -3
  103. package/lib/template/one-column-tab/one-column-tab.component.ts +1 -1
  104. package/lib/template/page/page.component.ts +1 -1
  105. package/lib/template/promoted-filters/promoted-filters.component.ts +1 -1
  106. package/lib/template/repeating-structures/repeating-structures.component.ts +1 -1
  107. package/lib/template/simple-table-manual/helpers.ts +10 -8
  108. package/lib/template/simple-table-manual/simple-table-manual.component.html +25 -6
  109. package/lib/template/simple-table-manual/simple-table-manual.component.scss +12 -3
  110. package/lib/template/simple-table-manual/simple-table-manual.component.ts +77 -37
  111. package/lib/template/simple-table-select/simple-table-select.component.ts +3 -3
  112. package/lib/template/three-column/three-column.component.ts +4 -3
  113. package/lib/template/two-column/two-column.component.ts +4 -3
  114. package/lib/template/two-column-tab/two-column-tab.component.ts +1 -1
  115. package/lib/template/utils.ts +16 -0
  116. package/lib/template/wide-narrow-form/wide-narrow-form.component.ts +4 -3
  117. package/lib/template/wide-narrow-page/wide-narrow-page.component.ts +1 -1
  118. package/lib/template/wss-nav-bar/wss-nav-bar.component.ts +3 -3
  119. package/lib/widget/attachment/attachment.component.ts +7 -9
  120. package/lib/widget/feed-container/feed-container.component.ts +7 -9
  121. package/lib/widget/file-utility/file-utility.component.ts +2 -5
  122. package/lib/widget/todo/todo.component.html +5 -6
  123. package/lib/widget/todo/todo.component.scss +9 -0
  124. package/lib/widget/todo/todo.component.ts +95 -84
  125. package/package.json +1 -1
@@ -1,4 +1,3 @@
1
- /* eslint-disable max-classes-per-file */
2
1
  import { Component, OnInit, Input, ChangeDetectorRef, forwardRef, Inject, OnDestroy } from '@angular/core';
3
2
  import { CommonModule } from '@angular/common';
4
3
  import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
@@ -15,13 +14,14 @@ import { ComponentMapperComponent } from '@pega/angular-sdk-components';
15
14
  import { dateFormatInfoDefault, getDateFormatInfo } from '@pega/angular-sdk-components';
16
15
  import { PConnFieldProps } from '@pega/angular-sdk-components';
17
16
  import { format } from '@pega/angular-sdk-components';
17
+ import { handleEvent } from '@pega/angular-sdk-components';
18
18
 
19
19
  interface DateProps extends PConnFieldProps {
20
20
  // If any, enter additional props that only exist on Date here
21
21
  }
22
22
 
23
23
  class MyFormat {
24
- theDateFormat: any = getDateFormatInfo();
24
+ theDateFormat = getDateFormatInfo();
25
25
 
26
26
  get display() {
27
27
  return {
@@ -83,7 +83,10 @@ export class DateComponent implements OnInit, OnDestroy {
83
83
  // Start with default dateFormatInfo
84
84
  dateFormatInfo = dateFormatInfoDefault;
85
85
  // and then update, as needed, based on locale, etc.
86
- theDateFormat: any = getDateFormatInfo();
86
+ theDateFormat = getDateFormatInfo();
87
+ actionsApi: Object;
88
+ propName: string;
89
+ formattedValue$: any;
87
90
 
88
91
  constructor(
89
92
  private angularPConnect: AngularPConnectService,
@@ -146,27 +149,16 @@ export class DateComponent implements OnInit, OnDestroy {
146
149
  // moved this from ngOnInit() and call this from there instead...
147
150
  this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as DateProps;
148
151
 
149
- if (this.configProps$.value != undefined) {
150
- let sDateValue: any = '';
151
- sDateValue = this.configProps$.value;
152
-
153
- if (sDateValue != '') {
154
- if (typeof sDateValue === 'object') {
155
- sDateValue = sDateValue.toISOString();
156
- } else if (sDateValue.indexOf('/') < 0) {
157
- // if we have the "pega" format, then for display, convert to standard format (US)
158
- // sDateValue = this.formatDate(sDateValue);
159
- sDateValue = this.utils.generateDate(sDateValue, 'Date-Long-Custom-YYYY');
160
- }
161
- this.value$ = new Date(sDateValue);
162
- }
163
- }
152
+ this.value$ = this.configProps$.value;
164
153
  this.testId = this.configProps$.testId;
165
154
  this.label$ = this.configProps$.label;
166
155
  this.displayMode$ = this.configProps$.displayMode;
167
156
  this.helperText = this.configProps$.helperText;
168
157
  this.placeholder = this.configProps$.placeholder || '';
169
158
 
159
+ this.actionsApi = this.pConn$.getActionsApi();
160
+ this.propName = this.pConn$.getStateProps().value;
161
+
170
162
  // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
171
163
  setTimeout(() => {
172
164
  if (this.configProps$.required != null) {
@@ -175,6 +167,12 @@ export class DateComponent implements OnInit, OnDestroy {
175
167
  this.cdRef.detectChanges();
176
168
  });
177
169
 
170
+ if (this.displayMode$ === 'DISPLAY_ONLY' || this.displayMode$ === 'STACKED_LARGE_VAL') {
171
+ this.formattedValue$ = format(this.value$, 'date', {
172
+ format: this.theDateFormat.dateFormatString
173
+ });
174
+ }
175
+
178
176
  if (this.configProps$.visibility != null) {
179
177
  this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
180
178
  }
@@ -194,7 +192,7 @@ export class DateComponent implements OnInit, OnDestroy {
194
192
  this.bReadonly$ = this.utils.getBooleanValue(this.configProps$.readOnly);
195
193
  }
196
194
 
197
- this.componentReference = (this.pConn$.getStateProps() as any).value;
195
+ this.componentReference = this.pConn$.getStateProps().value;
198
196
 
199
197
  // trigger display of error message with field control
200
198
  if (this.angularPConnectData.validateMessage != null && this.angularPConnectData.validateMessage != '') {
@@ -209,20 +207,11 @@ export class DateComponent implements OnInit, OnDestroy {
209
207
 
210
208
  fieldOnDateChange(event: any) {
211
209
  // this comes from the date pop up
212
- if (typeof event.value === 'object') {
213
- // convert date to pega "date" format
214
- event.value = event.value?.toISOString();
215
- }
216
- this.angularPConnectData.actions?.onChange(this, { value: event.value });
217
- }
218
-
219
- fieldOnBlur(event: any) {
220
- // PConnect wants to use eventHandler for onBlur
221
- if (typeof event.value === 'object') {
222
- // convert date to pega "date" format
223
- event.value = event.value?.toISOString();
224
- }
225
- this.angularPConnectData.actions?.onBlur(this, { value: event.value });
210
+ const value = event?.target?.value.format('YYYY-MM-DD');
211
+ handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
212
+ this.pConn$.clearErrorMessages({
213
+ property: this.propName
214
+ });
226
215
  }
227
216
 
228
217
  hasErrors() {
@@ -243,10 +232,4 @@ export class DateComponent implements OnInit, OnDestroy {
243
232
  }
244
233
  return errMessage;
245
234
  }
246
-
247
- getFormattedValue() {
248
- return format(this.value$, 'date', {
249
- format: this.theDateFormat.dateFormatString
250
- });
251
- }
252
235
  }
@@ -1,5 +1,5 @@
1
1
  <div *ngIf="displayMode$; else noDisplayMode">
2
- <component-mapper *ngIf="bVisible$ !== false" name="FieldValueList" [props]="{ label$, value$, displayMode$ }"></component-mapper>
2
+ <component-mapper *ngIf="bVisible$ !== false" name="FieldValueList" [props]="{ label$, value$: formattedValue$, displayMode$ }"></component-mapper>
3
3
  </div>
4
4
  <ng-template #noDisplayMode>
5
5
  <div *ngIf="!bReadonly$ && bHasForm$; else noEdit">
@@ -12,13 +12,12 @@
12
12
  [attr.data-test-id]="testId"
13
13
  [placeholder]="placeholder"
14
14
  [formControl]="fieldControl"
15
- (blur)="fieldOnBlur($event)"
16
15
  (dateTimeChange)="fieldOnDateChange($event)"
17
- [value]="value$"
18
16
  [required]="bRequired$"
17
+ [readonly]="bDisabled$"
19
18
  />
20
19
  <mat-datepicker-toggle matSuffix [owlDateTimeTrigger]="dtPicker"></mat-datepicker-toggle>
21
- <owl-date-time #dtPicker></owl-date-time>
20
+ <owl-date-time #dtPicker [disabled]="bDisabled$"></owl-date-time>
22
21
  <mat-error *ngIf="fieldControl?.invalid">{{ getErrorMessage() }}</mat-error>
23
22
  </mat-form-field>
24
23
  </div>
@@ -6,11 +6,15 @@ import { MatInputModule } from '@angular/material/input';
6
6
  import { MatFormFieldModule } from '@angular/material/form-field';
7
7
  import { OwlDateTimeModule, OwlNativeDateTimeModule } from '@danielmoncada/angular-datetime-picker';
8
8
  import { interval } from 'rxjs';
9
+ import dayjs from 'dayjs';
9
10
  import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
10
11
  import { Utils } from '@pega/angular-sdk-components';
11
12
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
12
13
  import { dateFormatInfoDefault, getDateFormatInfo } from '@pega/angular-sdk-components';
13
14
  import { PConnFieldProps } from '@pega/angular-sdk-components';
15
+ import { handleEvent } from '@pega/angular-sdk-components';
16
+ import { format } from '@pega/angular-sdk-components';
17
+ import { DateFormatters } from '@pega/angular-sdk-components';
14
18
 
15
19
  interface DateTimeProps extends PConnFieldProps {
16
20
  // If any, enter additional props that only exist on DateTime here
@@ -61,8 +65,12 @@ export class DateTimeComponent implements OnInit, OnDestroy {
61
65
  // Start with default dateFormatInfo
62
66
  dateFormatInfo = dateFormatInfoDefault;
63
67
  // and then update, as needed, based on locale, etc.
64
- theDateFormat: any = getDateFormatInfo();
68
+ theDateFormat = getDateFormatInfo();
65
69
  placeholder: string;
70
+ actionsApi: Object;
71
+ propName: string;
72
+ formattedValue$: any;
73
+ timezone = PCore.getEnvironmentInfo()?.getTimeZone();
66
74
 
67
75
  constructor(
68
76
  private angularPConnect: AngularPConnectService,
@@ -71,7 +79,7 @@ export class DateTimeComponent implements OnInit, OnDestroy {
71
79
  ) {}
72
80
 
73
81
  ngOnInit(): void {
74
- this.placeholder = `${this.theDateFormat.dateFormatStringLC}, hh:mm a`;
82
+ this.placeholder = `${this.theDateFormat.dateFormatStringLC}, hh:mm A`;
75
83
  // First thing in initialization is registering and subscribing to the AngularPConnect service
76
84
  this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
77
85
  this.controlName$ = this.angularPConnect.getComponentID(this);
@@ -83,7 +91,12 @@ export class DateTimeComponent implements OnInit, OnDestroy {
83
91
  if (this.formGroup$) {
84
92
  // add control to formGroup
85
93
  this.formGroup$.addControl(this.controlName$, this.fieldControl);
86
- this.fieldControl.setValue(this.value$);
94
+ let dateTimeValue = this.value$ ?? '';
95
+
96
+ if (this.value$) {
97
+ dateTimeValue = dayjs(DateFormatters?.convertToTimezone(this.value$, { timezone: this.timezone }))?.toISOString();
98
+ }
99
+ this.fieldControl.setValue(dateTimeValue);
87
100
  this.bHasForm$ = true;
88
101
  } else {
89
102
  this.bReadonly$ = true;
@@ -127,7 +140,11 @@ export class DateTimeComponent implements OnInit, OnDestroy {
127
140
  this.testId = this.configProps$.testId;
128
141
  this.helperText = this.configProps$.helperText;
129
142
  this.value$ = this.configProps$?.value;
130
- this.fieldControl.setValue(this.value$);
143
+ let dateTimeValue = this.configProps$?.value ?? '';
144
+ if (this.value$) {
145
+ dateTimeValue = dayjs(DateFormatters?.convertToTimezone(this.value$, { timezone: this.timezone }))?.toISOString();
146
+ }
147
+ this.fieldControl.setValue(dateTimeValue);
131
148
  // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
132
149
  setTimeout(() => {
133
150
  if (this.configProps$.required != null) {
@@ -136,6 +153,12 @@ export class DateTimeComponent implements OnInit, OnDestroy {
136
153
  this.cdRef.detectChanges();
137
154
  });
138
155
 
156
+ if (this.displayMode$ === 'DISPLAY_ONLY' || this.displayMode$ === 'STACKED_LARGE_VAL') {
157
+ this.formattedValue$ = format(this.value$, 'datetime', {
158
+ format: `${this.theDateFormat.dateFormatString} hh:mm A`
159
+ });
160
+ }
161
+
139
162
  if (this.configProps$.visibility != null) {
140
163
  this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
141
164
  }
@@ -155,7 +178,10 @@ export class DateTimeComponent implements OnInit, OnDestroy {
155
178
  this.bReadonly$ = this.utils.getBooleanValue(this.configProps$.readOnly);
156
179
  }
157
180
 
158
- this.componentReference = (this.pConn$.getStateProps() as any).value;
181
+ this.componentReference = this.pConn$.getStateProps().value;
182
+
183
+ this.actionsApi = this.pConn$.getActionsApi();
184
+ this.propName = this.pConn$.getStateProps().value;
159
185
 
160
186
  // trigger display of error message with field control
161
187
  if (this.angularPConnectData.validateMessage != null && this.angularPConnectData.validateMessage != '') {
@@ -172,18 +198,11 @@ export class DateTimeComponent implements OnInit, OnDestroy {
172
198
  // this comes from the date pop up
173
199
  if (typeof event.value === 'object') {
174
200
  // convert date to pega "date" format
175
- event.value = event.value?.toISOString();
201
+ const dateTime = dayjs(event.value?.toISOString());
202
+ const timeZoneDateTime = (dayjs as any).tz(dateTime.format('YYYY-MM-DDTHH:mm:ss'), this.timezone);
203
+ event.value = timeZoneDateTime && timeZoneDateTime.isValid() ? timeZoneDateTime.toISOString() : '';
176
204
  }
177
- this.angularPConnectData.actions?.onChange(this, { value: event.value });
178
- }
179
-
180
- fieldOnBlur(event: any) {
181
- if (typeof event.value === 'object') {
182
- // convert date to pega "date" format
183
- event.value = event.value?.toISOString();
184
- }
185
-
186
- this.angularPConnectData.actions?.onBlur(this, event);
205
+ handleEvent(this.actionsApi, 'changeNblur', this.propName, event.value);
187
206
  }
188
207
 
189
208
  getErrorMessage() {
@@ -11,9 +11,10 @@
11
11
  matInput
12
12
  currencyMask
13
13
  [options]="{
14
- prefix: bReadonly$ && formatter === 'Currency' ? currSym : '',
15
- thousands: currSep,
16
- decimal: currDec,
14
+ prefix: currencySymbol,
15
+ suffix: suffix,
16
+ thousands: thousandSeparator,
17
+ decimal: decimalSeparator,
17
18
  align: 'left',
18
19
  nullable: true,
19
20
  precision: decimalPrecision,
@@ -4,6 +4,7 @@ import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angul
4
4
  import { MatInputModule } from '@angular/material/input';
5
5
  import { MatFormFieldModule } from '@angular/material/form-field';
6
6
  import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
7
+ import { interval } from 'rxjs';
7
8
  import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
8
9
  import { Utils } from '@pega/angular-sdk-components';
9
10
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
@@ -58,13 +59,14 @@ export class DecimalComponent implements OnInit, OnDestroy {
58
59
  placeholder: string;
59
60
 
60
61
  fieldControl = new FormControl<number | null>(null, null);
61
- currDec: string;
62
- currSep: string;
63
- currSym: string;
62
+ decimalSeparator: string;
63
+ thousandSeparator: string;
64
+ currencySymbol = '';
64
65
  decimalPrecision: number | undefined;
65
66
  formatter;
66
67
  formattedValue: any;
67
68
  inputMode: any;
69
+ suffix = '';
68
70
 
69
71
  constructor(
70
72
  private angularPConnect: AngularPConnectService,
@@ -136,23 +138,24 @@ export class DecimalComponent implements OnInit, OnDestroy {
136
138
  nValue = parseFloat(nValue);
137
139
  }
138
140
  this.value$ = nValue;
141
+ this.fieldControl.setValue(this.value$);
139
142
  }
140
143
  this.helperText = this.configProps$.helperText;
141
144
  this.placeholder = this.configProps$.placeholder || '';
142
145
  const showGroupSeparators = this.configProps$.showGroupSeparators;
143
- const currencyISOCode: any = this.configProps$?.currencyISOCode;
146
+ const currencyISOCode = this.configProps$?.currencyISOCode ?? '';
144
147
 
145
148
  const theSymbols = getCurrencyCharacters(currencyISOCode);
146
- this.currDec = theSymbols.theDecimalIndicator;
147
- this.currSep = showGroupSeparators ? theSymbols.theDigitGroupSeparator : '';
149
+ this.decimalSeparator = theSymbols.theDecimalIndicator;
150
+ this.thousandSeparator = showGroupSeparators ? theSymbols.theDigitGroupSeparator : '';
148
151
 
149
152
  const theCurrencyOptions = getCurrencyOptions(currencyISOCode);
150
153
  this.formatter = this.configProps$.formatter;
151
154
 
152
- if (this.formatter === 'Currency') {
155
+ if (this.formatter) {
153
156
  this.formattedValue = format(this.value$, this.formatter.toLowerCase(), theCurrencyOptions);
154
157
  } else {
155
- this.formattedValue = format(this.value$, this.pConn$.getComponentName().toLowerCase(), theCurrencyOptions);
158
+ this.formattedValue = format(this.value$, 'decimal', theCurrencyOptions);
156
159
  }
157
160
 
158
161
  // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
@@ -183,26 +186,49 @@ export class DecimalComponent implements OnInit, OnDestroy {
183
186
  }
184
187
 
185
188
  if (this.bReadonly$ && this.formatter === 'Currency') {
186
- this.currSym = theSymbols.theCurrencySymbol;
187
- } else {
188
- this.currSym = '';
189
+ this.currencySymbol = theSymbols.theCurrencySymbol;
190
+ }
191
+
192
+ if (this.bReadonly$ && this.formatter === 'Percentage') {
193
+ this.suffix = '%';
189
194
  }
195
+
190
196
  this.decimalPrecision = this.configProps$?.decimalPrecision ?? 2;
191
197
 
192
- this.componentReference = (this.pConn$.getStateProps() as any).value;
198
+ this.componentReference = this.pConn$.getStateProps().value;
199
+
200
+ // trigger display of error message with field control
201
+ if (this.angularPConnectData.validateMessage != null && this.angularPConnectData.validateMessage != '') {
202
+ const timer = interval(100).subscribe(() => {
203
+ this.fieldControl.setErrors({ message: true });
204
+ this.fieldControl.markAsTouched();
205
+
206
+ timer.unsubscribe();
207
+ });
208
+ }
193
209
  }
194
210
 
195
211
  fieldOnBlur(event: any) {
196
- const actionsApi = this.pConn$?.getActionsApi();
197
- const propName = (this.pConn$?.getStateProps() as any).value;
198
- let value = event?.target?.value;
199
- if (this.currSep === ',') {
200
- value = value.replace(/,/g, '');
201
- } else {
202
- value = value?.replace(/\./g, '');
203
- value = value?.replace(/,/g, '.');
212
+ const oldVal = this.value$ ?? '';
213
+ const isValueChanged = event.target.value.toString() !== oldVal.toString();
214
+
215
+ if (isValueChanged) {
216
+ const actionsApi = this.pConn$?.getActionsApi();
217
+ const propName = this.pConn$?.getStateProps().value;
218
+ let value = event?.target?.value;
219
+ // replacing thousand separator with empty string as not required in api call
220
+ if (this.configProps$.showGroupSeparators) {
221
+ const thousandSep = this.thousandSeparator === '.' ? '\\.' : this.thousandSeparator;
222
+ const regExp = new RegExp(String.raw`${thousandSep}`, 'g');
223
+ value = value?.replace(regExp, '');
224
+ }
225
+ // replacing decimal separator with '.'
226
+ if (this.decimalSeparator !== '.') {
227
+ const regExp = new RegExp(String.raw`${this.decimalSeparator}`, 'g');
228
+ value = value.replace(regExp, '.');
229
+ }
230
+ handleEvent(actionsApi, 'changeNblur', propName, value);
204
231
  }
205
- handleEvent(actionsApi, 'changeNblur', propName, value);
206
232
  }
207
233
 
208
234
  getErrorMessage() {
@@ -12,6 +12,7 @@
12
12
  <mat-select
13
13
  [value]="value$"
14
14
  [required]="bRequired$"
15
+ [disabled]="bDisabled$"
15
16
  [attr.data-test-id]="testId"
16
17
  (selectionChange)="fieldOnChange($event)"
17
18
  [formControl]="fieldControl"
@@ -5,12 +5,47 @@ import { MatOptionModule } from '@angular/material/core';
5
5
  import { MatSelectModule } from '@angular/material/select';
6
6
  import { MatFormFieldModule } from '@angular/material/form-field';
7
7
  import { interval } from 'rxjs';
8
+ import isEqual from 'fast-deep-equal';
8
9
  import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
10
+ import { DatapageService } from '@pega/angular-sdk-components';
9
11
  import { Utils } from '@pega/angular-sdk-components';
10
12
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
11
13
  import { handleEvent } from '@pega/angular-sdk-components';
12
14
  import { PConnFieldProps } from '@pega/angular-sdk-components';
13
15
 
16
+ function flattenParameters(params = {}) {
17
+ const flatParams = {};
18
+ Object.keys(params).forEach(key => {
19
+ const { name, value: theVal } = params[key];
20
+ flatParams[name] = theVal;
21
+ });
22
+
23
+ return flatParams;
24
+ }
25
+
26
+ function preProcessColumns(columnList) {
27
+ return columnList.map(col => {
28
+ const tempColObj = { ...col };
29
+ tempColObj.value = col.value && col.value.startsWith('.') ? col.value.substring(1) : col.value;
30
+ return tempColObj;
31
+ });
32
+ }
33
+
34
+ function getDisplayFieldsMetaData(columnList) {
35
+ const displayColumns = columnList.filter(col => col.display === 'true');
36
+ const metaDataObj: any = { key: '', primary: '', secondary: [] };
37
+ const keyCol = columnList.filter(col => col.key === 'true');
38
+ metaDataObj.key = keyCol.length > 0 ? keyCol[0].value : 'auto';
39
+ for (let index = 0; index < displayColumns.length; index += 1) {
40
+ if (displayColumns[index].primary === 'true') {
41
+ metaDataObj.primary = displayColumns[index].value;
42
+ } else {
43
+ metaDataObj.secondary.push(displayColumns[index].value);
44
+ }
45
+ }
46
+ return metaDataObj;
47
+ }
48
+
14
49
  interface IOption {
15
50
  key: string;
16
51
  value: string;
@@ -22,6 +57,11 @@ interface DropdownProps extends PConnFieldProps {
22
57
  datasource?: any[];
23
58
  onRecordChange?: any;
24
59
  fieldMetadata?: any;
60
+ listType?: string;
61
+ columns?: any[];
62
+ deferDatasource?: boolean;
63
+ datasourceMetadata?: any;
64
+ parameters?: any;
25
65
  }
26
66
 
27
67
  @Component({
@@ -53,7 +93,7 @@ export class DropdownComponent implements OnInit, OnDestroy {
53
93
  testId = '';
54
94
  helperText: string;
55
95
  hideLabel: any;
56
-
96
+ theDatasource: any[] | null;
57
97
  fieldControl = new FormControl('', null);
58
98
  fieldMetadata: any[];
59
99
  localeContext = '';
@@ -61,11 +101,14 @@ export class DropdownComponent implements OnInit, OnDestroy {
61
101
  localeName = '';
62
102
  localePath = '';
63
103
  localizedValue = '';
104
+ actionsApi: Object;
105
+ propName: string;
64
106
 
65
107
  constructor(
66
108
  private angularPConnect: AngularPConnectService,
67
109
  private cdRef: ChangeDetectorRef,
68
- private utils: Utils
110
+ private utils: Utils,
111
+ private dataPageService: DatapageService
69
112
  ) {}
70
113
 
71
114
  ngOnInit(): void {
@@ -76,8 +119,8 @@ export class DropdownComponent implements OnInit, OnDestroy {
76
119
  // Then, continue on with other initialization
77
120
 
78
121
  // call updateSelf when initializing
79
- // this.updateSelf();
80
122
  this.checkAndUpdate();
123
+ // this should get called afer checkAndUpdate
81
124
 
82
125
  if (this.formGroup$) {
83
126
  // add control to formGroup
@@ -90,6 +133,18 @@ export class DropdownComponent implements OnInit, OnDestroy {
90
133
  }
91
134
  }
92
135
 
136
+ set options(options: IOption[]) {
137
+ this.options$ = options;
138
+ if (this.displayMode$) {
139
+ this.value$ = this.options$?.find(option => option.key === this.value$)?.value || this.value$;
140
+ this.localizedValue = this.pConn$.getLocalizedValue(
141
+ this.value$ === 'Select...' ? '' : this.value$,
142
+ this.localePath,
143
+ this.pConn$.getLocaleRuleNameFromKeys(this.localeClass, this.localeContext, this.localeName)
144
+ );
145
+ }
146
+ }
147
+
93
148
  ngOnDestroy(): void {
94
149
  if (this.formGroup$) {
95
150
  this.formGroup$.removeControl(this.controlName$);
@@ -120,7 +175,6 @@ export class DropdownComponent implements OnInit, OnDestroy {
120
175
  updateSelf(): void {
121
176
  // moved this from ngOnInit() and call this from there instead...
122
177
  this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as DropdownProps;
123
-
124
178
  if (this.configProps$.value != undefined) {
125
179
  this.value$ = this.configProps$.value;
126
180
  }
@@ -130,6 +184,7 @@ export class DropdownComponent implements OnInit, OnDestroy {
130
184
  this.label$ = this.configProps$.label;
131
185
  this.helperText = this.configProps$.helperText;
132
186
  this.hideLabel = this.configProps$.hideLabel;
187
+ const datasource = this.configProps$.datasource;
133
188
  // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
134
189
  setTimeout(() => {
135
190
  if (this.configProps$.required != null) {
@@ -138,6 +193,11 @@ export class DropdownComponent implements OnInit, OnDestroy {
138
193
  this.cdRef.detectChanges();
139
194
  });
140
195
 
196
+ if (!isEqual(datasource, this.theDatasource)) {
197
+ // inbound datasource is different, so update theDatasource
198
+ this.theDatasource = datasource || null;
199
+ }
200
+
141
201
  if (this.configProps$.visibility != null) {
142
202
  this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
143
203
  }
@@ -157,18 +217,23 @@ export class DropdownComponent implements OnInit, OnDestroy {
157
217
  this.bReadonly$ = this.utils.getBooleanValue(this.configProps$.readOnly);
158
218
  }
159
219
 
160
- this.componentReference = (this.pConn$.getStateProps() as any).value;
220
+ this.componentReference = this.pConn$.getStateProps().value;
161
221
 
162
- const optionsList = [...this.utils.getOptionList(this.configProps$, this.pConn$.getDataObject())];
163
- optionsList?.unshift({ key: 'Select', value: this.pConn$.getLocalizedValue('Select...', '', '') });
164
- this.options$ = optionsList;
165
222
  if (this.value$ === '' && !this.bReadonly$) {
166
223
  this.value$ = 'Select';
167
224
  }
168
225
 
169
- const propName = (this.pConn$.getStateProps() as any).value;
226
+ if (this.theDatasource) {
227
+ const optionsList = [...this.utils.getOptionList(this.configProps$, this.pConn$.getDataObject())];
228
+ optionsList?.unshift({ key: 'Select', value: this.pConn$.getLocalizedValue('Select...', '', '') });
229
+ this.options = optionsList;
230
+ }
231
+
232
+ this.actionsApi = this.pConn$.getActionsApi();
233
+
234
+ this.propName = this.pConn$.getStateProps().value;
170
235
  const className = this.pConn$.getCaseInfo().getClassName();
171
- const refName = propName?.slice(propName.lastIndexOf('.') + 1);
236
+ const refName = this.propName?.slice(this.propName.lastIndexOf('.') + 1);
172
237
 
173
238
  this.fieldMetadata = this.configProps$.fieldMetadata;
174
239
  const metaData = Array.isArray(this.fieldMetadata) ? this.fieldMetadata.filter(field => field?.classID === className)[0] : this.fieldMetadata;
@@ -185,6 +250,9 @@ export class DropdownComponent implements OnInit, OnDestroy {
185
250
  this.localePath,
186
251
  this.pConn$.getLocaleRuleNameFromKeys(this.localeClass, this.localeContext, this.localeName)
187
252
  );
253
+
254
+ this.localizedValue = this.options$?.find(opt => opt.key === this.value$)?.value || this.localizedValue;
255
+ this.getDatapageData();
188
256
  // trigger display of error message with field control
189
257
  if (this.angularPConnectData.validateMessage != null && this.angularPConnectData.validateMessage != '') {
190
258
  const timer = interval(100).subscribe(() => {
@@ -196,6 +264,70 @@ export class DropdownComponent implements OnInit, OnDestroy {
196
264
  }
197
265
  }
198
266
 
267
+ getDatapageData() {
268
+ const configProps = this.pConn$.getConfigProps() as DropdownProps;
269
+ let { listType, parameters, datasource = [], columns = [] } = configProps;
270
+ const { deferDatasource, datasourceMetadata } = configProps;
271
+ const context = this.pConn$.getContextName();
272
+ if (deferDatasource && datasourceMetadata?.datasource?.name) {
273
+ listType = 'datapage';
274
+ datasource = datasourceMetadata.datasource.name;
275
+ const { parameters: dataSourceParameters, propertyForDisplayText, propertyForValue } = datasourceMetadata.datasource;
276
+ parameters = flattenParameters(dataSourceParameters);
277
+ const displayProp = propertyForDisplayText?.startsWith('@P') ? propertyForDisplayText.substring(3) : propertyForDisplayText;
278
+ const valueProp = propertyForValue?.startsWith('@P') ? propertyForValue.substring(3) : propertyForValue;
279
+ columns = [
280
+ {
281
+ key: 'true',
282
+ setProperty: 'Associated property',
283
+ value: valueProp
284
+ },
285
+ {
286
+ display: 'true',
287
+ primary: 'true',
288
+ useForSearch: true,
289
+ value: displayProp
290
+ }
291
+ ];
292
+ }
293
+
294
+ columns = preProcessColumns(columns) || [];
295
+ if (listType !== 'associated' && typeof datasource === 'string') {
296
+ this.getData(datasource, parameters, columns, context, listType);
297
+ }
298
+ }
299
+
300
+ getData(dataSource, parameters, columns, context, listType) {
301
+ const dataConfig: any = {
302
+ columns,
303
+ dataSource,
304
+ deferDatasource: true,
305
+ listType,
306
+ parameters,
307
+ matchPosition: 'contains',
308
+ maxResultsDisplay: '5000',
309
+ cacheLifeSpan: 'form'
310
+ };
311
+ PCore.getDataApi()
312
+ .init(dataConfig, context)
313
+ .then((dataApiObj: any) => {
314
+ const optionsData: any[] = [];
315
+ const displayColumn = getDisplayFieldsMetaData(columns);
316
+ dataApiObj?.fetchData('').then(response => {
317
+ response.data?.forEach(element => {
318
+ const val = element[displayColumn.primary]?.toString();
319
+ const obj = {
320
+ key: element[displayColumn.key] || element.pyGUID,
321
+ value: val
322
+ };
323
+ optionsData.push(obj);
324
+ });
325
+ optionsData?.unshift({ key: 'Select', value: this.pConn$.getLocalizedValue('Select...', '', '') });
326
+ this.options = optionsData;
327
+ });
328
+ });
329
+ }
330
+
199
331
  isSelected(buttonValue: string): boolean {
200
332
  return this.value$ === buttonValue;
201
333
  }
@@ -204,17 +336,13 @@ export class DropdownComponent implements OnInit, OnDestroy {
204
336
  if (event?.value === 'Select') {
205
337
  event.value = '';
206
338
  }
207
- const actionsApi = this.pConn$?.getActionsApi();
208
- const propName = (this.pConn$?.getStateProps() as any).value;
209
- handleEvent(actionsApi, 'changeNblur', propName, event.value);
339
+ handleEvent(this.actionsApi, 'changeNblur', this.propName, event.value);
210
340
  if (this.configProps$?.onRecordChange) {
211
341
  this.configProps$.onRecordChange(event);
212
342
  }
213
- }
214
-
215
- fieldOnBlur(event: any) {
216
- // PConnect wants to use eventHandler for onBlur
217
- this.angularPConnectData.actions?.onBlur(this, event);
343
+ this.pConn$.clearErrorMessages({
344
+ property: this.propName
345
+ });
218
346
  }
219
347
 
220
348
  getLocalizedOptionValue(opt: IOption) {