@pega/angular-sdk-overrides 0.25.1 → 0.25.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/lib/designSystemExtension/alert/alert.component.scss +3 -3
  2. package/lib/designSystemExtension/banner/banner.component.scss +12 -2
  3. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.html +6 -3
  4. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.scss +5 -34
  5. package/lib/designSystemExtension/material-details/material-details.component.scss +0 -5
  6. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.html +2 -2
  7. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.scss +4 -3
  8. package/lib/designSystemExtension/material-summary-item/material-summary-item.component.scss +2 -17
  9. package/lib/designSystemExtension/material-utility/material-utility.component.scss +1 -2
  10. package/lib/designSystemExtension/material-vertical-tabs/material-vertical-tabs.component.scss +1 -1
  11. package/lib/designSystemExtension/operator/operator.component.html +1 -1
  12. package/lib/designSystemExtension/operator/operator.component.scss +3 -10
  13. package/lib/designSystemExtension/operator/operator.component.ts +0 -1
  14. package/lib/designSystemExtension/pulse/pulse.component.scss +2 -2
  15. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.scss +0 -1
  16. package/lib/designSystemExtension/wss-quick-create/wss-quick-create.component.scss +16 -8
  17. package/lib/field/auto-complete/auto-complete.component.html +0 -1
  18. package/lib/field/auto-complete/auto-complete.component.ts +35 -172
  19. package/lib/field/cancel-alert/cancel-alert.component.html +8 -12
  20. package/lib/field/cancel-alert/cancel-alert.component.scss +2 -3
  21. package/lib/field/cancel-alert/cancel-alert.component.ts +24 -36
  22. package/lib/field/check-box/check-box.component.html +0 -1
  23. package/lib/field/check-box/check-box.component.scss +0 -1
  24. package/lib/field/check-box/check-box.component.ts +19 -149
  25. package/lib/field/currency/currency.component.ts +36 -168
  26. package/lib/field/date/date.component.html +1 -1
  27. package/lib/field/date/date.component.ts +30 -150
  28. package/lib/field/date-time/date-time.component.ts +31 -149
  29. package/lib/field/decimal/decimal.component.ts +38 -163
  30. package/lib/field/dropdown/dropdown.component.ts +29 -151
  31. package/lib/field/email/email.component.ts +16 -155
  32. package/lib/field/field.base.ts +149 -0
  33. package/lib/field/group/group.component.ts +7 -4
  34. package/lib/field/integer/integer.component.ts +18 -157
  35. package/lib/field/location/location.component.ts +1 -1
  36. package/lib/field/multiselect/multiselect.component.ts +46 -148
  37. package/lib/field/multiselect/utils.ts +55 -47
  38. package/lib/field/object-reference/object-reference.component.html +17 -0
  39. package/lib/field/object-reference/object-reference.component.scss +0 -0
  40. package/lib/field/object-reference/object-reference.component.spec.ts +22 -0
  41. package/lib/field/object-reference/object-reference.component.ts +237 -0
  42. package/lib/field/percentage/percentage.component.ts +37 -154
  43. package/lib/field/phone/phone.component.ts +28 -142
  44. package/lib/field/radio-buttons/radio-buttons.component.scss +4 -2
  45. package/lib/field/radio-buttons/radio-buttons.component.ts +35 -161
  46. package/lib/field/rich-text/rich-text.component.ts +19 -90
  47. package/lib/field/scalar-list/scalar-list.component.ts +17 -72
  48. package/lib/field/selectable-card/selectable-card.component.html +54 -24
  49. package/lib/field/selectable-card/selectable-card.component.scss +11 -0
  50. package/lib/field/selectable-card/selectable-card.component.ts +16 -52
  51. package/lib/field/semantic-link/semantic-link.component.html +4 -8
  52. package/lib/field/semantic-link/semantic-link.component.scss +0 -13
  53. package/lib/field/semantic-link/semantic-link.component.ts +165 -5
  54. package/lib/field/text/text.component.scss +0 -1
  55. package/lib/field/text-area/text-area.component.ts +18 -152
  56. package/lib/field/text-input/text-input.component.ts +16 -155
  57. package/lib/field/time/time.component.ts +17 -151
  58. package/lib/field/url/url.component.ts +16 -154
  59. package/lib/field/user-reference/user-reference.component.scss +0 -1
  60. package/lib/field/user-reference/user-reference.component.ts +2 -3
  61. package/lib/infra/Containers/flow-container/flow-container.component.ts +5 -7
  62. package/lib/infra/Containers/modal-view-container/modal-view-container.component.ts +5 -10
  63. package/lib/infra/Containers/view-container/helper.ts +35 -2
  64. package/lib/infra/Containers/view-container/view-container.component.ts +1 -1
  65. package/lib/infra/action-buttons/action-buttons.component.html +13 -8
  66. package/lib/infra/action-buttons/action-buttons.component.scss +23 -0
  67. package/lib/infra/action-buttons/action-buttons.component.ts +1 -2
  68. package/lib/infra/assignment/assignment.component.ts +8 -6
  69. package/lib/infra/assignment-card/assignment-card.component.html +1 -2
  70. package/lib/infra/assignment-card/assignment-card.component.scss +0 -4
  71. package/lib/infra/assignment-card/assignment-card.component.ts +21 -4
  72. package/lib/infra/defer-load/defer-load.component.html +6 -2
  73. package/lib/infra/defer-load/defer-load.component.ts +16 -10
  74. package/lib/infra/multi-step/multi-step.component.scss +1 -21
  75. package/lib/infra/navbar/navbar.component.html +25 -28
  76. package/lib/infra/navbar/navbar.component.scss +16 -4
  77. package/lib/infra/navbar/navbar.component.ts +8 -3
  78. package/lib/infra/root-container/root-container.component.scss +0 -1
  79. package/lib/infra/root-container/root-container.component.ts +1 -2
  80. package/lib/infra/stages/stages.component.html +2 -2
  81. package/lib/infra/stages/stages.component.scss +7 -35
  82. package/lib/infra/stages/stages.component.ts +4 -2
  83. package/lib/infra/view/view.component.html +1 -1
  84. package/lib/infra/view/view.component.ts +0 -2
  85. package/lib/template/advanced-search/advanced-search.component.html +12 -0
  86. package/lib/template/advanced-search/advanced-search.component.scss +0 -0
  87. package/lib/template/advanced-search/advanced-search.component.spec.ts +0 -0
  88. package/lib/template/advanced-search/advanced-search.component.ts +112 -0
  89. package/lib/template/advanced-search/advanced-search.service.ts +27 -0
  90. package/lib/template/advanced-search/search-group/persist-utils.ts +56 -0
  91. package/lib/template/advanced-search/search-groups/search-groups.component.html +32 -0
  92. package/lib/template/advanced-search/search-groups/search-groups.component.scss +0 -0
  93. package/lib/template/advanced-search/search-groups/search-groups.component.spec.ts +0 -0
  94. package/lib/template/advanced-search/search-groups/search-groups.component.ts +294 -0
  95. package/lib/template/advanced-search/search-groups/utils.ts +29 -0
  96. package/lib/template/app-shell/app-shell.component.html +4 -1
  97. package/lib/template/app-shell/app-shell.component.scss +0 -3
  98. package/lib/template/app-shell/app-shell.component.ts +46 -7
  99. package/lib/template/case-summary/case-summary.component.scss +0 -2
  100. package/lib/template/case-view/case-view.component.html +3 -3
  101. package/lib/template/case-view/case-view.component.scss +18 -10
  102. package/lib/template/case-view/case-view.component.ts +1 -1
  103. package/lib/template/data-reference/data-reference-advanced-search.service.ts +16 -0
  104. package/lib/template/data-reference/data-reference.component.html +11 -8
  105. package/lib/template/data-reference/data-reference.component.ts +346 -112
  106. package/lib/template/data-reference/search-form/search-form.component.html +39 -0
  107. package/lib/template/data-reference/search-form/search-form.component.scss +11 -0
  108. package/lib/template/data-reference/search-form/search-form.component.spec.ts +0 -0
  109. package/lib/template/data-reference/search-form/search-form.component.ts +167 -0
  110. package/lib/template/data-reference/search-form/tabsData.ts +160 -0
  111. package/lib/template/data-reference/utils.ts +92 -0
  112. package/lib/template/default-form/default-form.component.ts +10 -2
  113. package/lib/template/default-page/default-page.component.html +34 -0
  114. package/lib/template/default-page/default-page.component.scss +31 -0
  115. package/lib/template/default-page/default-page.component.spec.ts +24 -0
  116. package/lib/template/default-page/default-page.component.ts +64 -0
  117. package/lib/template/field-group-list/field-group-list.component.scss +0 -1
  118. package/lib/template/inline-dashboard-page/inline-dashboard-page.component.ts +1 -1
  119. package/lib/template/list-view/list-view.component.html +9 -4
  120. package/lib/template/list-view/list-view.component.scss +21 -21
  121. package/lib/template/list-view/list-view.component.ts +154 -84
  122. package/lib/template/list-view/utils.ts +25 -2
  123. package/lib/template/object-page/object-page.component.html +1 -0
  124. package/lib/template/object-page/object-page.component.scss +0 -0
  125. package/lib/template/object-page/object-page.component.spec.ts +22 -0
  126. package/lib/template/object-page/object-page.component.ts +14 -0
  127. package/lib/template/one-column-tab/one-column-tab.component.scss +1 -1
  128. package/lib/template/repeating-structures/repeating-structures.component.ts +0 -1
  129. package/lib/template/self-service-case-view/self-service-case-view.component.html +80 -0
  130. package/lib/template/self-service-case-view/self-service-case-view.component.scss +124 -0
  131. package/lib/template/self-service-case-view/self-service-case-view.component.spec.ts +24 -0
  132. package/lib/template/self-service-case-view/self-service-case-view.component.ts +216 -0
  133. package/lib/template/simple-table/simple-table.component.ts +0 -1
  134. package/lib/template/simple-table-manual/helpers.ts +2 -2
  135. package/lib/template/simple-table-manual/simple-table-manual.component.html +4 -4
  136. package/lib/template/simple-table-manual/simple-table-manual.component.scss +4 -14
  137. package/lib/template/simple-table-manual/simple-table-manual.component.ts +8 -4
  138. package/lib/template/single-reference-readonly/single-reference-readonly.component.html +4 -1
  139. package/lib/template/single-reference-readonly/single-reference-readonly.component.scss +21 -0
  140. package/lib/template/single-reference-readonly/single-reference-readonly.component.ts +104 -3
  141. package/lib/template/utils.ts +42 -0
  142. package/lib/template/wss-nav-bar/wss-nav-bar.component.html +5 -4
  143. package/lib/template/wss-nav-bar/wss-nav-bar.component.scss +2 -8
  144. package/lib/template/wss-nav-bar/wss-nav-bar.component.ts +1 -8
  145. package/lib/widget/app-announcement/app-announcement.component.html +1 -2
  146. package/lib/widget/app-announcement/app-announcement.component.scss +2 -2
  147. package/lib/widget/attachment/Attachment.types.ts +92 -0
  148. package/lib/widget/attachment/AttachmentUtils.ts +287 -0
  149. package/lib/widget/attachment/attachment.component.html +3 -3
  150. package/lib/widget/attachment/attachment.component.scss +2 -5
  151. package/lib/widget/attachment/attachment.component.ts +255 -254
  152. package/lib/widget/feed-container/feed-container.component.scss +3 -9
  153. package/lib/widget/feed-container/feed-container.component.ts +2 -2
  154. package/lib/widget/file-utility/file-utility.component.html +3 -3
  155. package/lib/widget/file-utility/file-utility.component.scss +5 -16
  156. package/lib/widget/list-utility/list-utility.component.scss +3 -5
  157. package/lib/widget/todo/todo.component.html +8 -5
  158. package/lib/widget/todo/todo.component.scss +10 -11
  159. package/lib/widget/todo/todo.component.ts +6 -2
  160. package/package.json +1 -1
@@ -0,0 +1,237 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, Input, OnInit, forwardRef, OnDestroy } from '@angular/core';
3
+ import { FormGroup } from '@angular/forms';
4
+ import { ComponentMetadataConfig } from '@pega/pcore-pconnect-typedefs/interpreter/types';
5
+ import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
6
+ import { ComponentMapperComponent } from '@pega/angular-sdk-components';
7
+ import { generateColumns, getDataRelationshipContextFromKey } from '@pega/angular-sdk-components';
8
+ import { PConnFieldProps } from '@pega/angular-sdk-components';
9
+
10
+ interface ObjectReferenceProps extends PConnFieldProps {
11
+ showPromotedFilters: boolean;
12
+ inline: boolean;
13
+ parameters: object;
14
+ mode: string;
15
+ targetObjectType: any;
16
+ allowAndPersistChangesInReviewMode: boolean;
17
+ }
18
+
19
+ @Component({
20
+ selector: 'app-object-reference',
21
+ imports: [CommonModule, forwardRef(() => ComponentMapperComponent)],
22
+ templateUrl: './object-reference.component.html',
23
+ styleUrl: './object-reference.component.scss'
24
+ })
25
+ export class ObjectReferenceComponent implements OnInit, OnDestroy {
26
+ @Input() pConn$: typeof PConnect;
27
+ @Input() formGroup$: FormGroup;
28
+
29
+ angularPConnectData: AngularPConnectData = {};
30
+ configProps: ObjectReferenceProps;
31
+ value: { [key: string]: any };
32
+ readOnly: boolean;
33
+ isForm: boolean;
34
+ type: string;
35
+ isDisplayModeEnabled: boolean;
36
+ canBeChangedInReviewMode: boolean;
37
+ newComponentName: string;
38
+ newPconn: typeof PConnect;
39
+ rawViewMetadata: ComponentMetadataConfig | undefined;
40
+
41
+ constructor(private angularPConnect: AngularPConnectService) {}
42
+
43
+ ngOnInit() {
44
+ this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
45
+ this.checkAndUpdate();
46
+ }
47
+
48
+ onStateChange() {
49
+ this.checkAndUpdate();
50
+ }
51
+
52
+ ngOnDestroy() {
53
+ if (this.angularPConnectData.unsubscribeFn) {
54
+ this.angularPConnectData.unsubscribeFn();
55
+ }
56
+ }
57
+
58
+ checkAndUpdate() {
59
+ const shouldUpdate = this.angularPConnect.shouldComponentUpdate(this);
60
+ if (shouldUpdate) {
61
+ this.updateSelf();
62
+ }
63
+ }
64
+
65
+ updateSelf() {
66
+ this.configProps = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as ObjectReferenceProps;
67
+ const {
68
+ displayMode,
69
+ allowAndPersistChangesInReviewMode: editableInReview = false,
70
+ targetObjectType,
71
+ mode,
72
+ parameters,
73
+ hideLabel,
74
+ inline,
75
+ showPromotedFilters
76
+ } = this.configProps;
77
+
78
+ const referenceType: string = targetObjectType === 'case' ? 'Case' : 'Data';
79
+ this.rawViewMetadata = this.pConn$.getRawMetadata();
80
+ const refFieldMetadata = this.pConn$.getFieldMetadata(this.rawViewMetadata?.config?.value?.split('.', 2)[1] ?? '');
81
+ const propsToUse = { ...this.pConn$.getInheritedProps(), ...this.configProps };
82
+
83
+ this.isDisplayModeEnabled = displayMode === 'DISPLAY_ONLY';
84
+ this.type = this.getComponentType();
85
+ this.canBeChangedInReviewMode = editableInReview && ['Autocomplete', 'Dropdown'].includes(this.type);
86
+
87
+ if (this.type === 'SemanticLink' && !this.canBeChangedInReviewMode) {
88
+ const config: any = {
89
+ ...this.rawViewMetadata?.config,
90
+ primaryField: (this.rawViewMetadata?.config as any).displayField,
91
+ caseClass: (this.rawViewMetadata?.config as any).targetObjectClass,
92
+ text: (this.rawViewMetadata?.config as any).displayField,
93
+ caseID: (this.rawViewMetadata?.config as any).value,
94
+ contextPage: `@P .${(this.rawViewMetadata?.config as any).displayField ? getDataRelationshipContextFromKey((this.rawViewMetadata?.config as any).displayField) : null}`,
95
+ resourceParams: { workID: (this.rawViewMetadata?.config as any).value },
96
+ resourcePayload: { caseClassName: (this.rawViewMetadata?.config as any).targetObjectClass }
97
+ };
98
+ this.createSemanticLinkPConnect(config, displayMode ?? '', referenceType, hideLabel);
99
+ return;
100
+ }
101
+
102
+ if (this.type !== 'SemanticLink' && !this.isDisplayModeEnabled) {
103
+ const config: any = { ...this.rawViewMetadata?.config };
104
+ generateColumns(config, this.pConn$, referenceType);
105
+ config.deferDatasource = true;
106
+ config.listType = 'datapage';
107
+ if (['Dropdown', 'AutoComplete'].includes(this.type) && !config.placeholder) {
108
+ config.placeholder = '@L Select...';
109
+ }
110
+ config.showPromotedFilters = showPromotedFilters;
111
+ if (!this.canBeChangedInReviewMode) {
112
+ config.displayMode = displayMode;
113
+ }
114
+ config.parameters = parameters;
115
+
116
+ this.createOtherComponentPConnect(config, propsToUse, mode, refFieldMetadata, referenceType, hideLabel, inline);
117
+ }
118
+ }
119
+
120
+ onRecordChange(value) {
121
+ const caseKey = this.pConn$.getCaseInfo().getKey() ?? '';
122
+ const refreshOptions = { autoDetectRefresh: true, propertyName: '' };
123
+ refreshOptions.propertyName = this.rawViewMetadata?.config?.value ?? '';
124
+
125
+ if (!this.canBeChangedInReviewMode || !this.pConn$.getValue('__currentPageTabViewName')) {
126
+ const pgRef = this.pConn$.getPageReference().replace('caseInfo.content', '') ?? '';
127
+ const viewName = this.rawViewMetadata?.name;
128
+ if (viewName && viewName.length > 0) {
129
+ getPConnect().getActionsApi().refreshCaseView(caseKey, viewName, pgRef, refreshOptions);
130
+ }
131
+ }
132
+
133
+ const propValue = value;
134
+ const propName =
135
+ this.rawViewMetadata?.type === 'SimpleTableSelect' && this.configProps.mode === 'multi'
136
+ ? PCore.getAnnotationUtils().getPropertyName(this.rawViewMetadata?.config?.selectionList ?? '')
137
+ : PCore.getAnnotationUtils().getPropertyName(this.rawViewMetadata?.config?.value ?? '');
138
+
139
+ if (propValue && this.canBeChangedInReviewMode && this.isDisplayModeEnabled) {
140
+ PCore.getCaseUtils()
141
+ .getCaseEditLock(caseKey, '')
142
+ .then(caseResponse => {
143
+ const pageTokens = this.pConn$.getPageReference().replace('caseInfo.content', '').split('.');
144
+ let curr = {};
145
+ const commitData = curr;
146
+
147
+ pageTokens?.forEach(el => {
148
+ if (el !== '') {
149
+ curr[el] = {};
150
+ curr = curr[el];
151
+ }
152
+ });
153
+
154
+ // expecting format like {Customer: {pyID:"C-100"}}
155
+ const propArr = propName.split('.');
156
+ propArr.forEach((element, idx) => {
157
+ if (idx + 1 === propArr.length) {
158
+ curr[element] = propValue;
159
+ } else {
160
+ curr[element] = {};
161
+ curr = curr[element];
162
+ }
163
+ });
164
+
165
+ PCore.getCaseUtils()
166
+ .updateCaseEditFieldsData(caseKey, { [caseKey]: commitData }, caseResponse.headers.etag, this.pConn$?.getContextName() ?? '')
167
+ .then(response => {
168
+ PCore.getContainerUtils().updateParentLastUpdateTime(this.pConn$.getContextName() ?? '', response.data.data.caseInfo.lastUpdateTime);
169
+ PCore.getContainerUtils().updateRelatedContextEtag(this.pConn$.getContextName() ?? '', response.headers.etag);
170
+ });
171
+ });
172
+ }
173
+ }
174
+
175
+ private getComponentType(): string {
176
+ // componentType is not defined in ComponentMetadataConfig type so using any
177
+ return (this.rawViewMetadata?.config as any)?.componentType;
178
+ }
179
+
180
+ private createSemanticLinkPConnect(config: any, displayMode: string, referenceType: string, hideLabel: boolean) {
181
+ const semanticLinkConfig = {
182
+ ...config,
183
+ displayMode,
184
+ referenceType,
185
+ hideLabel,
186
+ dataRelationshipContext: config.displayField ? getDataRelationshipContextFromKey(config.displayField) : null
187
+ };
188
+
189
+ const component = this.pConn$.createComponent({ type: 'SemanticLink', config: semanticLinkConfig }, '', 0, {});
190
+ this.newPconn = component?.getPConnect();
191
+ }
192
+
193
+ private createOtherComponentPConnect(
194
+ config: any,
195
+ propsToUse: any,
196
+ mode: string,
197
+ refFieldMetadata: any,
198
+ referenceType: string,
199
+ hideLabel: boolean,
200
+ inline: boolean
201
+ ) {
202
+ const fieldMetaData = {
203
+ datasourceMetadata: {
204
+ datasource: {
205
+ parameters: config.parameters ?? {},
206
+ propertyForDisplayText: config.datasource?.fields?.text?.substring(3) ?? config.datasource?.fields?.text,
207
+ propertyForValue: config.datasource?.fields?.value?.substring(3) ?? config.datasource?.fields?.value,
208
+ name: config.referenceList ?? ''
209
+ }
210
+ }
211
+ };
212
+
213
+ const componentConfig = {
214
+ ...config,
215
+ descriptors: mode === 'single' ? refFieldMetadata?.descriptors : null,
216
+ datasourceMetadata: fieldMetaData.datasourceMetadata,
217
+ required: propsToUse.required,
218
+ visibility: propsToUse.visibility,
219
+ disabled: propsToUse.disabled,
220
+ label: propsToUse.label,
221
+ readOnly: false,
222
+ ...(mode === 'single' && { referenceType }),
223
+ contextClass: config.targetObjectClass,
224
+ primaryField: config.displayField,
225
+ dataRelationshipContext: config.displayField ? getDataRelationshipContextFromKey(config.displayField) : null,
226
+ hideLabel,
227
+ inline
228
+ };
229
+
230
+ const component = this.pConn$.createComponent({ type: this.type, config: componentConfig }, '', 0, {});
231
+ this.newComponentName = component?.getPConnect().getComponentName();
232
+ this.newPconn = component?.getPConnect();
233
+ if (this.rawViewMetadata?.config) {
234
+ this.rawViewMetadata.config = { ...config };
235
+ }
236
+ }
237
+ }
@@ -1,19 +1,19 @@
1
- import { Component, OnInit, Input, ChangeDetectorRef, forwardRef, OnDestroy } from '@angular/core';
1
+ import { Component, forwardRef } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
- import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
3
+ import { FormControl, ReactiveFormsModule } from '@angular/forms';
4
4
  import { MatInputModule } from '@angular/material/input';
5
5
  import { MatFormFieldModule } from '@angular/material/form-field';
6
- import { interval } from 'rxjs';
7
6
  import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
8
- import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
9
- import { Utils } from '@pega/angular-sdk-components';
7
+
8
+ import { FieldBase } from '@pega/angular-sdk-components';
10
9
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
11
10
  import { handleEvent } from '@pega/angular-sdk-components';
12
11
  import { getCurrencyCharacters } from '@pega/angular-sdk-components';
13
- import { PConnFieldProps } from '@pega/angular-sdk-components';
14
12
  import { format } from '@pega/angular-sdk-components';
13
+ import { PConnFieldProps } from '@pega/angular-sdk-components';
15
14
 
16
- interface PercentageProps extends PConnFieldProps {
15
+ interface PercentageProps extends Omit<PConnFieldProps, 'value'> {
16
+ value?: number;
17
17
  showGroupSeparators?: string;
18
18
  decimalPrecision?: number;
19
19
  currencyISOCode?: string;
@@ -26,155 +26,54 @@ interface PercentageProps extends PConnFieldProps {
26
26
  styleUrls: ['./percentage.component.scss'],
27
27
  imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, NgxCurrencyDirective, forwardRef(() => ComponentMapperComponent)]
28
28
  })
29
- export class PercentageComponent implements OnInit, OnDestroy {
30
- @Input() pConn$: typeof PConnect;
31
- @Input() formGroup$: FormGroup;
32
-
33
- // Used with AngularPConnect
34
- angularPConnectData: AngularPConnectData = {};
29
+ export class PercentageComponent extends FieldBase {
35
30
  configProps$: PercentageProps;
31
+ override fieldControl = new FormControl<number | null>(null, null);
36
32
 
37
- label$ = '';
38
- value$: number;
39
- bRequired$ = false;
40
- bReadonly$ = false;
41
- bDisabled$ = false;
42
- bVisible$ = true;
43
- displayMode$?: string = '';
44
- controlName$: string;
45
- bHasForm$ = true;
46
- componentReference = '';
47
- testId: string;
48
- helperText: string;
49
- placeholder: string;
50
33
  decimalSeparator: string;
51
34
  thousandSeparator: string;
52
- inputMode: any;
35
+ inputMode: any = NgxCurrencyInputMode.Natural;
53
36
  decimalPrecision: number | undefined;
54
- fieldControl = new FormControl<number | null>(null, null);
55
- actionsApi: Object;
56
- propName: string;
57
37
  formattedValue: string;
58
38
 
59
- constructor(
60
- private angularPConnect: AngularPConnectService,
61
- private cdRef: ChangeDetectorRef,
62
- private utils: Utils
63
- ) {}
64
-
65
- ngOnInit(): void {
66
- // First thing in initialization is registering and subscribing to the AngularPConnect service
67
- this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
68
- this.controlName$ = this.angularPConnect.getComponentID(this);
39
+ /**
40
+ * Updates the component when there are changes in the state.
41
+ */
42
+ override updateSelf(): void {
43
+ // Resolve configuration properties
44
+ this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as PercentageProps;
69
45
 
70
- // Then, continue on with other initialization
71
- // call updateSelf when initializing
72
- // this.updateSelf();
73
- this.checkAndUpdate();
46
+ // Update component common properties
47
+ this.updateComponentCommonProperties(this.configProps$);
74
48
 
75
- if (this.formGroup$) {
76
- // add control to formGroup
77
- this.formGroup$.addControl(this.controlName$, this.fieldControl);
78
- this.fieldControl.setValue(this.value$);
79
- this.bHasForm$ = true;
80
- } else {
81
- this.bReadonly$ = true;
82
- this.bHasForm$ = false;
49
+ // Set component specific properties
50
+ const { value } = this.configProps$;
51
+ if (value) {
52
+ this.value$ = value;
53
+ this.fieldControl.setValue(value);
83
54
  }
84
- }
85
55
 
86
- ngOnDestroy(): void {
87
- if (this.formGroup$) {
88
- this.formGroup$.removeControl(this.controlName$);
89
- }
90
-
91
- if (this.angularPConnectData.unsubscribeFn) {
92
- this.angularPConnectData.unsubscribeFn();
93
- }
56
+ // update percentage properties
57
+ this.updatePercentageProperties(this.configProps$);
94
58
  }
95
59
 
96
- // Callback passed when subscribing to store change
97
- onStateChange() {
98
- this.checkAndUpdate();
99
- }
100
-
101
- checkAndUpdate() {
102
- // Should always check the bridge to see if the component should
103
- // update itself (re-render)
104
- const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this);
105
-
106
- // ONLY call updateSelf when the component should update
107
- if (bUpdateSelf) {
108
- this.updateSelf();
109
- }
110
- }
111
-
112
- // updateSelf
113
- updateSelf(): void {
114
- // moved this from ngOnInit() and call this from there instead...
115
- this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as PercentageProps;
116
- this.testId = this.configProps$.testId;
117
- this.label$ = this.configProps$.label;
118
- this.displayMode$ = this.configProps$.displayMode;
119
- this.inputMode = NgxCurrencyInputMode.Natural;
120
- const nValue: any = this.configProps$.value;
121
- if (nValue) {
122
- this.value$ = nValue;
123
- this.fieldControl.setValue(nValue);
124
- }
125
- this.helperText = this.configProps$.helperText;
126
- this.placeholder = this.configProps$.placeholder || '';
127
- const showGroupSeparators = this.configProps$.showGroupSeparators;
60
+ /**
61
+ * Updates the percentage properties
62
+ *
63
+ * @param {Object} configProps - Configuration properties.
64
+ * @param {boolean} configProps.showGroupSeparators - Whether to show group separators.
65
+ * @param {number} configProps.decimalPrecision - The number of decimal places to display.
66
+ */
67
+ updatePercentageProperties(configProps): void {
68
+ const { showGroupSeparators, decimalPrecision } = configProps;
128
69
 
129
70
  const theSymbols = getCurrencyCharacters('');
130
71
  this.decimalSeparator = theSymbols.theDecimalIndicator;
131
72
  this.thousandSeparator = showGroupSeparators ? theSymbols.theDigitGroupSeparator : '';
73
+ this.decimalPrecision = decimalPrecision ?? 2;
132
74
 
133
- this.actionsApi = this.pConn$.getActionsApi();
134
- this.propName = this.pConn$.getStateProps().value;
135
-
136
- if (this.displayMode$ === 'DISPLAY_ONLY' || this.displayMode$ === 'STACKED_LARGE_VAL') {
137
- this.formattedValue = nValue ? format(nValue, 'percentage') : '';
138
- }
139
-
140
- // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
141
- setTimeout(() => {
142
- if (this.configProps$.required != null) {
143
- this.bRequired$ = this.utils.getBooleanValue(this.configProps$.required);
144
- }
145
- this.cdRef.detectChanges();
146
- });
147
-
148
- if (this.configProps$.visibility != null) {
149
- this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
150
- }
151
-
152
- // disabled
153
- if (this.configProps$.disabled != undefined) {
154
- this.bDisabled$ = this.utils.getBooleanValue(this.configProps$.disabled);
155
- }
156
-
157
- if (this.bDisabled$) {
158
- this.fieldControl.disable();
159
- } else {
160
- this.fieldControl.enable();
161
- }
162
-
163
- if (this.configProps$.readOnly != null) {
164
- this.bReadonly$ = this.utils.getBooleanValue(this.configProps$.readOnly);
165
- }
166
-
167
- this.decimalPrecision = this.configProps$?.decimalPrecision ?? 2;
168
-
169
- this.componentReference = this.pConn$.getStateProps().value;
170
-
171
- // trigger display of error message with field control
172
- if (this.angularPConnectData.validateMessage != null && this.angularPConnectData.validateMessage != '') {
173
- const timer = interval(100).subscribe(() => {
174
- this.fieldControl.setErrors({ message: true });
175
- this.fieldControl.markAsTouched();
176
- timer.unsubscribe();
177
- });
75
+ if (['DISPLAY_ONLY', 'STACKED_LARGE_VAL'].includes(this.displayMode$)) {
76
+ this.formattedValue = this.value$ ? format(this.value$, 'percentage') : '';
178
77
  }
179
78
  }
180
79
 
@@ -210,20 +109,4 @@ export class PercentageComponent implements OnInit, OnDestroy {
210
109
  handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
211
110
  }
212
111
  }
213
-
214
- getErrorMessage() {
215
- // field control gets error message from here
216
- let errMessage = '';
217
- // look for validation messages for json, pre-defined or just an error pushed from workitem (400)
218
- if (this.fieldControl.hasError('message')) {
219
- errMessage = this.angularPConnectData.validateMessage ?? '';
220
- return errMessage;
221
- }
222
- if (this.fieldControl.hasError('required')) {
223
- errMessage = 'You must enter a value';
224
- } else if (this.fieldControl.errors) {
225
- errMessage = this.fieldControl.errors.toString();
226
- }
227
- return errMessage;
228
- }
229
112
  }
@@ -1,14 +1,13 @@
1
- import { Component, OnInit, Input, ChangeDetectorRef, forwardRef, OnDestroy } from '@angular/core';
1
+ import { Component, forwardRef } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
- import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
3
+ import { ReactiveFormsModule } from '@angular/forms';
4
4
  import { MatFormFieldModule } from '@angular/material/form-field';
5
- import { interval } from 'rxjs';
6
5
  import { MatTelInput } from 'mat-tel-input';
7
6
  import { parsePhoneNumberFromString } from 'libphonenumber-js';
8
- import { Utils } from '@pega/angular-sdk-components';
9
- import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
10
- import { handleEvent } from '@pega/angular-sdk-components';
7
+
8
+ import { FieldBase } from '@pega/angular-sdk-components';
11
9
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
10
+ import { handleEvent } from '@pega/angular-sdk-components';
12
11
  import { PConnFieldProps } from '@pega/angular-sdk-components';
13
12
 
14
13
  interface PhoneProps extends PConnFieldProps {
@@ -21,141 +20,28 @@ interface PhoneProps extends PConnFieldProps {
21
20
  styleUrls: ['./phone.component.scss'],
22
21
  imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatTelInput, forwardRef(() => ComponentMapperComponent)]
23
22
  })
24
- export class PhoneComponent implements OnInit, OnDestroy {
25
- @Input() pConn$: typeof PConnect;
26
- @Input() formGroup$: FormGroup;
27
-
28
- // Used with AngularPConnect
29
- angularPConnectData: AngularPConnectData = {};
23
+ export class PhoneComponent extends FieldBase {
30
24
  configProps$: PhoneProps;
31
25
 
32
- label$ = '';
33
- value$: string;
34
- bRequired$ = false;
35
- bReadonly$ = false;
36
- bDisabled$ = false;
37
- bVisible$ = true;
38
- displayMode$?: string = '';
39
- controlName$: string;
40
- bHasForm$ = true;
41
- testId: string;
42
- helperText: string;
43
- placeholder: string;
44
-
45
- fieldControl = new FormControl('', null);
46
-
47
- actionsApi: Object;
48
- propName: string;
49
26
  preferredCountries: string[] = ['us'];
50
27
 
51
- constructor(
52
- private angularPConnect: AngularPConnectService,
53
- private cdRef: ChangeDetectorRef,
54
- private utils: Utils
55
- ) {}
56
-
57
- ngOnInit(): void {
58
- // First thing in initialization is registering and subscribing to the AngularPConnect service
59
- this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
60
- this.controlName$ = this.angularPConnect.getComponentID(this);
61
-
62
- // Then, continue on with other initialization
63
-
64
- // call updateSelf when initializing
65
- // this.updateSelf();
66
- this.checkAndUpdate();
67
-
68
- if (this.formGroup$) {
69
- // add control to formGroup
70
- this.formGroup$.addControl(this.controlName$, this.fieldControl);
71
- this.fieldControl.setValue(this.value$);
72
- this.bHasForm$ = true;
73
- } else {
74
- this.bReadonly$ = true;
75
- this.bHasForm$ = false;
76
- }
77
- }
78
-
79
- ngOnDestroy(): void {
80
- if (this.formGroup$) {
81
- this.formGroup$.removeControl(this.controlName$);
82
- }
83
-
84
- if (this.angularPConnectData.unsubscribeFn) {
85
- this.angularPConnectData.unsubscribeFn();
86
- }
87
- }
88
-
89
- // Callback passed when subscribing to store change
90
- onStateChange() {
91
- this.checkAndUpdate();
92
- }
93
-
94
- checkAndUpdate() {
95
- // Should always check the bridge to see if the component should
96
- // update itself (re-render)
97
- const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this);
98
-
99
- // ONLY call updateSelf when the component should update
100
- if (bUpdateSelf) {
101
- this.updateSelf();
102
- }
103
- }
104
-
105
- // updateSelf
106
- updateSelf(): void {
107
- // moved this from ngOnInit() and call this from there instead...
28
+ /**
29
+ * Updates the component when there are changes in the state.
30
+ */
31
+ override updateSelf(): void {
32
+ // Resolve config properties
108
33
  this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as PhoneProps;
109
34
 
110
- this.label$ = this.configProps$.label;
111
- this.displayMode$ = this.configProps$.displayMode;
112
- this.testId = this.configProps$.testId;
113
- if (this.configProps$.value != undefined) {
114
- this.value$ = this.configProps$.value;
35
+ // Update component common properties
36
+ this.updateComponentCommonProperties(this.configProps$);
37
+
38
+ // Extract and normalize the value property
39
+ const { value } = this.configProps$;
40
+ if (value) {
41
+ this.value$ = value;
115
42
  this.fieldControl.setValue(this.value$);
116
43
  this.updatePreferredCountries();
117
44
  }
118
- this.helperText = this.configProps$.helperText;
119
- this.placeholder = this.configProps$.placeholder || '';
120
- this.actionsApi = this.pConn$.getActionsApi();
121
- this.propName = this.pConn$.getStateProps().value;
122
-
123
- // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
124
- setTimeout(() => {
125
- if (this.configProps$.required != null) {
126
- this.bRequired$ = this.utils.getBooleanValue(this.configProps$.required);
127
- }
128
- this.cdRef.detectChanges();
129
- });
130
-
131
- if (this.configProps$.visibility != null) {
132
- this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
133
- }
134
-
135
- // disabled
136
- if (this.configProps$.disabled != undefined) {
137
- this.bDisabled$ = this.utils.getBooleanValue(this.configProps$.disabled);
138
- }
139
-
140
- if (this.bDisabled$) {
141
- this.fieldControl.disable();
142
- } else {
143
- this.fieldControl.enable();
144
- }
145
-
146
- if (this.configProps$.readOnly != null) {
147
- this.bReadonly$ = this.utils.getBooleanValue(this.configProps$.readOnly);
148
- }
149
-
150
- // trigger display of error message with field control
151
- if (this.angularPConnectData.validateMessage != null && this.angularPConnectData.validateMessage != '') {
152
- const timer = interval(100).subscribe(() => {
153
- this.fieldControl.setErrors({ message: true });
154
- this.fieldControl.markAsTouched();
155
-
156
- timer.unsubscribe();
157
- });
158
- }
159
45
  }
160
46
 
161
47
  fieldOnBlur() {
@@ -167,7 +53,7 @@ export class PhoneComponent implements OnInit, OnDestroy {
167
53
  const newVal = this.formGroup$.controls[this.controlName$].value;
168
54
  const isValueChanged = newVal?.toString() !== oldVal.toString();
169
55
 
170
- if (isValueChanged && newVal) {
56
+ if (isValueChanged) {
171
57
  const value = this.formGroup$.controls[this.controlName$].value;
172
58
  handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
173
59
  }
@@ -183,20 +69,20 @@ export class PhoneComponent implements OnInit, OnDestroy {
183
69
  }
184
70
  }
185
71
 
186
- getErrorMessage() {
187
- let errMessage = '';
188
-
72
+ override getErrorMessage() {
189
73
  // look for validation messages for json, pre-defined or just an error pushed from workitem (400)
190
74
  if (this.fieldControl.hasError('message')) {
191
- errMessage = this.angularPConnectData.validateMessage ?? '';
192
- return errMessage;
75
+ return this.angularPConnectData.validateMessage ?? '';
193
76
  }
77
+
194
78
  if (this.fieldControl.hasError('required')) {
195
- errMessage = 'You must enter a value';
196
- } else if (this.fieldControl.errors) {
197
- errMessage = 'Invalid Phone';
79
+ return 'You must enter a value';
80
+ }
81
+
82
+ if (this.fieldControl.errors) {
83
+ return 'Invalid Phone';
198
84
  }
199
85
 
200
- return errMessage;
86
+ return '';
201
87
  }
202
88
  }