@pega/angular-sdk-overrides 24.2.12 → 25.1.11

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 (237) hide show
  1. package/lib/designSystemExtension/alert/alert.component.scss +3 -3
  2. package/lib/designSystemExtension/alert/alert.component.ts +0 -1
  3. package/lib/designSystemExtension/alert-banner/alert-banner.component.ts +0 -1
  4. package/lib/designSystemExtension/banner/banner.component.html +1 -1
  5. package/lib/designSystemExtension/banner/banner.component.scss +17 -3
  6. package/lib/designSystemExtension/banner/banner.component.ts +0 -1
  7. package/lib/designSystemExtension/case-create-stage/case-create-stage.component.ts +0 -1
  8. package/lib/designSystemExtension/field-group/field-group.component.ts +0 -1
  9. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.html +6 -3
  10. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.scss +5 -34
  11. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.ts +0 -1
  12. package/lib/designSystemExtension/material-details/material-details.component.scss +0 -5
  13. package/lib/designSystemExtension/material-details/material-details.component.ts +0 -1
  14. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.html +2 -2
  15. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.scss +4 -3
  16. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.ts +0 -1
  17. package/lib/designSystemExtension/material-summary-item/material-summary-item.component.scss +4 -17
  18. package/lib/designSystemExtension/material-summary-item/material-summary-item.component.ts +0 -1
  19. package/lib/designSystemExtension/material-summary-list/material-summary-list.component.ts +0 -1
  20. package/lib/designSystemExtension/material-utility/material-utility.component.scss +1 -2
  21. package/lib/designSystemExtension/material-vertical-tabs/material-vertical-tabs.component.scss +1 -1
  22. package/lib/designSystemExtension/material-vertical-tabs/material-vertical-tabs.component.ts +0 -1
  23. package/lib/designSystemExtension/operator/operator.component.html +1 -1
  24. package/lib/designSystemExtension/operator/operator.component.scss +3 -10
  25. package/lib/designSystemExtension/operator/operator.component.ts +0 -2
  26. package/lib/designSystemExtension/pulse/pulse.component.scss +2 -2
  27. package/lib/designSystemExtension/pulse/pulse.component.ts +0 -1
  28. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.html +4 -17
  29. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.scss +0 -1
  30. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.ts +30 -1
  31. package/lib/designSystemExtension/wss-quick-create/wss-quick-create.component.scss +16 -9
  32. package/lib/designSystemExtension/wss-quick-create/wss-quick-create.component.ts +0 -1
  33. package/lib/field/auto-complete/auto-complete.component.html +0 -1
  34. package/lib/field/auto-complete/auto-complete.component.ts +35 -173
  35. package/lib/field/cancel-alert/cancel-alert.component.html +8 -12
  36. package/lib/field/cancel-alert/cancel-alert.component.scss +2 -3
  37. package/lib/field/cancel-alert/cancel-alert.component.ts +24 -37
  38. package/lib/field/check-box/check-box.component.html +19 -10
  39. package/lib/field/check-box/check-box.component.scss +6 -1
  40. package/lib/field/check-box/check-box.component.ts +25 -151
  41. package/lib/field/currency/currency.component.ts +36 -169
  42. package/lib/field/date/date.component.html +2 -2
  43. package/lib/field/date/date.component.ts +30 -151
  44. package/lib/field/date-time/date-time.component.html +1 -1
  45. package/lib/field/date-time/date-time.component.ts +34 -149
  46. package/lib/field/decimal/decimal.component.ts +38 -164
  47. package/lib/field/dropdown/dropdown.component.ts +29 -152
  48. package/lib/field/email/email.component.ts +16 -156
  49. package/lib/field/field.base.ts +149 -0
  50. package/lib/field/group/group.component.ts +7 -5
  51. package/lib/field/integer/integer.component.ts +18 -158
  52. package/lib/field/list-view-action-buttons/list-view-action-buttons.component.ts +0 -1
  53. package/lib/field/location/config-ext.json +8 -0
  54. package/lib/field/location/location.component.html +46 -0
  55. package/lib/field/location/location.component.scss +18 -0
  56. package/lib/field/location/location.component.spec.ts +22 -0
  57. package/lib/field/location/location.component.ts +280 -0
  58. package/lib/field/multiselect/multiselect.component.ts +47 -152
  59. package/lib/field/multiselect/utils.ts +55 -47
  60. package/lib/field/object-reference/object-reference.component.html +17 -0
  61. package/lib/field/object-reference/object-reference.component.scss +0 -0
  62. package/lib/field/object-reference/object-reference.component.spec.ts +22 -0
  63. package/lib/field/object-reference/object-reference.component.ts +237 -0
  64. package/lib/field/percentage/percentage.component.ts +37 -155
  65. package/lib/field/phone/phone.component.html +18 -19
  66. package/lib/field/phone/phone.component.scss +4 -0
  67. package/lib/field/phone/phone.component.ts +43 -145
  68. package/lib/field/radio-buttons/radio-buttons.component.html +14 -6
  69. package/lib/field/radio-buttons/radio-buttons.component.scss +4 -2
  70. package/lib/field/radio-buttons/radio-buttons.component.ts +37 -160
  71. package/lib/field/rich-text/rich-text.component.html +2 -0
  72. package/lib/field/rich-text/rich-text.component.scss +172 -0
  73. package/lib/field/rich-text/rich-text.component.ts +21 -91
  74. package/lib/field/scalar-list/scalar-list.component.ts +17 -73
  75. package/lib/field/selectable-card/selectable-card.component.html +70 -0
  76. package/lib/field/selectable-card/selectable-card.component.scss +11 -0
  77. package/lib/field/selectable-card/selectable-card.component.spec.ts +22 -0
  78. package/lib/field/selectable-card/selectable-card.component.ts +219 -0
  79. package/lib/field/semantic-link/semantic-link.component.html +4 -8
  80. package/lib/field/semantic-link/semantic-link.component.scss +0 -13
  81. package/lib/field/semantic-link/semantic-link.component.ts +165 -6
  82. package/lib/field/text/text.component.scss +0 -1
  83. package/lib/field/text/text.component.ts +0 -1
  84. package/lib/field/text-area/text-area.component.ts +18 -153
  85. package/lib/field/text-content/text-content.component.ts +0 -1
  86. package/lib/field/text-input/text-input.component.ts +16 -156
  87. package/lib/field/time/time.component.ts +17 -152
  88. package/lib/field/url/url.component.ts +16 -155
  89. package/lib/field/user-reference/user-reference.component.scss +0 -1
  90. package/lib/field/user-reference/user-reference.component.ts +2 -4
  91. package/lib/infra/Containers/flow-container/flow-container.component.html +2 -2
  92. package/lib/infra/Containers/flow-container/flow-container.component.ts +8 -9
  93. package/lib/infra/Containers/hybrid-view-container/hybrid-view-container.component.ts +0 -1
  94. package/lib/infra/Containers/modal-view-container/modal-view-container.component.ts +5 -11
  95. package/lib/infra/Containers/view-container/helper.ts +35 -2
  96. package/lib/infra/Containers/view-container/view-container.component.ts +1 -2
  97. package/lib/infra/action-buttons/action-buttons.component.html +13 -8
  98. package/lib/infra/action-buttons/action-buttons.component.scss +23 -0
  99. package/lib/infra/action-buttons/action-buttons.component.ts +1 -3
  100. package/lib/infra/assignment/assignment.component.ts +21 -10
  101. package/lib/infra/assignment-card/assignment-card.component.html +1 -2
  102. package/lib/infra/assignment-card/assignment-card.component.scss +0 -4
  103. package/lib/infra/assignment-card/assignment-card.component.ts +21 -5
  104. package/lib/infra/dashboard-filter/dashboard-filter.component.ts +0 -1
  105. package/lib/infra/defer-load/defer-load.component.html +6 -2
  106. package/lib/infra/defer-load/defer-load.component.ts +22 -12
  107. package/lib/infra/error-boundary/error-boundary.component.ts +0 -1
  108. package/lib/infra/multi-step/multi-step.component.html +22 -38
  109. package/lib/infra/multi-step/multi-step.component.scss +14 -27
  110. package/lib/infra/multi-step/multi-step.component.ts +0 -1
  111. package/lib/infra/navbar/navbar.component.html +36 -41
  112. package/lib/infra/navbar/navbar.component.scss +22 -4
  113. package/lib/infra/navbar/navbar.component.ts +8 -4
  114. package/lib/infra/reference/reference.component.ts +5 -0
  115. package/lib/infra/region/region.component.ts +0 -1
  116. package/lib/infra/root-container/root-container.component.scss +0 -1
  117. package/lib/infra/root-container/root-container.component.ts +1 -5
  118. package/lib/infra/stages/stages.component.html +4 -3
  119. package/lib/infra/stages/stages.component.scss +12 -36
  120. package/lib/infra/stages/stages.component.ts +4 -3
  121. package/lib/infra/view/view.component.html +1 -1
  122. package/lib/infra/view/view.component.ts +3 -7
  123. package/lib/template/advanced-search/advanced-search.component.html +12 -0
  124. package/lib/template/advanced-search/advanced-search.component.scss +0 -0
  125. package/lib/template/advanced-search/advanced-search.component.spec.ts +0 -0
  126. package/lib/template/advanced-search/advanced-search.component.ts +112 -0
  127. package/lib/template/advanced-search/advanced-search.service.ts +27 -0
  128. package/lib/template/advanced-search/search-group/persist-utils.ts +56 -0
  129. package/lib/template/advanced-search/search-groups/search-groups.component.html +32 -0
  130. package/lib/template/advanced-search/search-groups/search-groups.component.scss +0 -0
  131. package/lib/template/advanced-search/search-groups/search-groups.component.spec.ts +0 -0
  132. package/lib/template/advanced-search/search-groups/search-groups.component.ts +294 -0
  133. package/lib/template/advanced-search/search-groups/utils.ts +29 -0
  134. package/lib/template/app-shell/app-shell.component.html +4 -1
  135. package/lib/template/app-shell/app-shell.component.scss +0 -3
  136. package/lib/template/app-shell/app-shell.component.ts +46 -8
  137. package/lib/template/banner-page/banner-page.component.ts +0 -1
  138. package/lib/template/case-summary/case-summary.component.scss +0 -2
  139. package/lib/template/case-summary/case-summary.component.ts +6 -22
  140. package/lib/template/case-view/case-view.component.html +4 -4
  141. package/lib/template/case-view/case-view.component.scss +18 -10
  142. package/lib/template/case-view/case-view.component.ts +1 -11
  143. package/lib/template/confirmation/confirmation.component.html +1 -1
  144. package/lib/template/confirmation/confirmation.component.ts +0 -1
  145. package/lib/template/data-reference/data-reference.component.html +11 -8
  146. package/lib/template/data-reference/data-reference.component.ts +346 -113
  147. package/lib/template/data-reference/search-form/search-form.component.html +39 -0
  148. package/lib/template/data-reference/search-form/search-form.component.scss +11 -0
  149. package/lib/template/data-reference/search-form/search-form.component.spec.ts +0 -0
  150. package/lib/template/data-reference/search-form/search-form.component.ts +167 -0
  151. package/lib/template/data-reference/search-form/tabsData.ts +160 -0
  152. package/lib/template/data-reference/utils.ts +92 -0
  153. package/lib/template/default-form/default-form.component.ts +10 -3
  154. package/lib/template/default-page/default-page.component.html +34 -0
  155. package/lib/template/default-page/default-page.component.scss +31 -0
  156. package/lib/template/default-page/default-page.component.spec.ts +24 -0
  157. package/lib/template/default-page/default-page.component.ts +64 -0
  158. package/lib/template/details/details.component.ts +0 -1
  159. package/lib/template/details-narrow-wide/details-narrow-wide.component.ts +0 -1
  160. package/lib/template/details-one-column/details-one-column.component.ts +0 -1
  161. package/lib/template/details-sub-tabs/details-sub-tabs.component.ts +0 -1
  162. package/lib/template/details-three-column/details-three-column.component.ts +0 -1
  163. package/lib/template/details-two-column/details-two-column.component.ts +0 -1
  164. package/lib/template/details-wide-narrow/details-wide-narrow.component.ts +0 -1
  165. package/lib/template/dynamic-tabs/dynamic-tabs.component.ts +0 -1
  166. package/lib/template/field-group-list/field-group-list.component.scss +0 -1
  167. package/lib/template/field-group-list/field-group-list.component.ts +0 -1
  168. package/lib/template/field-group-template/field-group-template.component.ts +14 -28
  169. package/lib/template/field-value-list/field-value-list.component.ts +0 -1
  170. package/lib/template/inline-dashboard/inline-dashboard.component.ts +0 -1
  171. package/lib/template/inline-dashboard-page/inline-dashboard-page.component.ts +1 -2
  172. package/lib/template/list-page/list-page.component.ts +0 -1
  173. package/lib/template/list-view/list-view.component.html +170 -162
  174. package/lib/template/list-view/list-view.component.scss +25 -21
  175. package/lib/template/list-view/list-view.component.ts +207 -119
  176. package/lib/template/list-view/listViewHelpers.ts +1 -4
  177. package/lib/template/list-view/utils.ts +25 -2
  178. package/lib/template/multi-reference-readonly/multi-reference-readonly.component.ts +0 -1
  179. package/lib/template/narrow-wide-form/narrow-wide-form.component.ts +0 -1
  180. package/lib/template/object-page/object-page.component.html +1 -0
  181. package/lib/template/object-page/object-page.component.scss +0 -0
  182. package/lib/template/object-page/object-page.component.spec.ts +22 -0
  183. package/lib/template/object-page/object-page.component.ts +14 -0
  184. package/lib/template/one-column/one-column.component.ts +0 -1
  185. package/lib/template/one-column-page/one-column-page.component.ts +0 -1
  186. package/lib/template/one-column-tab/one-column-tab.component.scss +1 -1
  187. package/lib/template/one-column-tab/one-column-tab.component.ts +0 -1
  188. package/lib/template/page/page.component.ts +0 -1
  189. package/lib/template/promoted-filters/promoted-filters.component.ts +0 -1
  190. package/lib/template/repeating-structures/repeating-structures.component.ts +0 -2
  191. package/lib/template/self-service-case-view/self-service-case-view.component.html +78 -0
  192. package/lib/template/self-service-case-view/self-service-case-view.component.scss +132 -0
  193. package/lib/template/self-service-case-view/self-service-case-view.component.spec.ts +24 -0
  194. package/lib/template/self-service-case-view/self-service-case-view.component.ts +207 -0
  195. package/lib/template/simple-table/simple-table.component.ts +0 -2
  196. package/lib/template/simple-table-manual/helpers.ts +117 -3
  197. package/lib/template/simple-table-manual/simple-table-manual.component.html +4 -4
  198. package/lib/template/simple-table-manual/simple-table-manual.component.scss +4 -14
  199. package/lib/template/simple-table-manual/simple-table-manual.component.ts +45 -25
  200. package/lib/template/simple-table-select/simple-table-select.component.ts +0 -1
  201. package/lib/template/single-reference-readonly/single-reference-readonly.component.html +4 -1
  202. package/lib/template/single-reference-readonly/single-reference-readonly.component.scss +21 -0
  203. package/lib/template/single-reference-readonly/single-reference-readonly.component.ts +104 -4
  204. package/lib/template/sub-tabs/sub-tabs.component.ts +0 -1
  205. package/lib/template/three-column/three-column.component.ts +0 -1
  206. package/lib/template/three-column-page/three-column-page.component.ts +0 -1
  207. package/lib/template/two-column/two-column.component.ts +0 -1
  208. package/lib/template/two-column-page/two-column-page.component.ts +0 -1
  209. package/lib/template/two-column-tab/two-column-tab.component.ts +0 -1
  210. package/lib/template/utils.ts +42 -0
  211. package/lib/template/wide-narrow-form/wide-narrow-form.component.ts +0 -1
  212. package/lib/template/wide-narrow-page/wide-narrow-page.component.ts +0 -1
  213. package/lib/template/wss-nav-bar/wss-nav-bar.component.html +6 -5
  214. package/lib/template/wss-nav-bar/wss-nav-bar.component.scss +8 -17
  215. package/lib/template/wss-nav-bar/wss-nav-bar.component.ts +1 -9
  216. package/lib/widget/app-announcement/app-announcement.component.html +1 -2
  217. package/lib/widget/app-announcement/app-announcement.component.scss +2 -2
  218. package/lib/widget/app-announcement/app-announcement.component.ts +0 -1
  219. package/lib/widget/attachment/Attachment.types.ts +92 -0
  220. package/lib/widget/attachment/AttachmentUtils.ts +287 -0
  221. package/lib/widget/attachment/attachment.component.html +3 -3
  222. package/lib/widget/attachment/attachment.component.scss +9 -12
  223. package/lib/widget/attachment/attachment.component.ts +267 -254
  224. package/lib/widget/case-history/case-history.component.ts +0 -1
  225. package/lib/widget/feed-container/feed-container.component.scss +3 -9
  226. package/lib/widget/feed-container/feed-container.component.ts +2 -3
  227. package/lib/widget/file-utility/file-utility.component.html +3 -3
  228. package/lib/widget/file-utility/file-utility.component.scss +6 -17
  229. package/lib/widget/file-utility/file-utility.component.ts +24 -9
  230. package/lib/widget/list-utility/list-utility.component.scss +4 -5
  231. package/lib/widget/list-utility/list-utility.component.ts +0 -1
  232. package/lib/widget/quick-create/quick-create.component.ts +41 -23
  233. package/lib/widget/todo/todo.component.html +8 -5
  234. package/lib/widget/todo/todo.component.scss +11 -10
  235. package/lib/widget/todo/todo.component.ts +7 -4
  236. package/lib/widget/utility/utility.component.ts +0 -1
  237. package/package.json +1 -1
@@ -0,0 +1,22 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { LocationComponent } from './location.component';
4
+
5
+ describe('LocationComponent', () => {
6
+ let component: LocationComponent;
7
+ let fixture: ComponentFixture<LocationComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [LocationComponent]
12
+ }).compileComponents();
13
+
14
+ fixture = TestBed.createComponent(LocationComponent);
15
+ component = fixture.componentInstance;
16
+ fixture.detectChanges();
17
+ });
18
+
19
+ it('should create', () => {
20
+ expect(component).toBeTruthy();
21
+ });
22
+ });
@@ -0,0 +1,280 @@
1
+ import { Component, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { ReactiveFormsModule } from '@angular/forms';
4
+ import { MatFormFieldModule } from '@angular/material/form-field';
5
+ import { MatInputModule } from '@angular/material/input';
6
+ import { MatAutocompleteModule } from '@angular/material/autocomplete';
7
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
8
+ import { MatIconModule } from '@angular/material/icon';
9
+ import { MatButtonModule } from '@angular/material/button';
10
+ import { GoogleMapsModule } from '@angular/google-maps';
11
+ import { debounceTime, from, of, switchMap } from 'rxjs';
12
+
13
+ import { FieldBase } from '@pega/angular-sdk-components';
14
+ import { GoogleMapsLoaderService } from '@pega/angular-sdk-components';
15
+ import { handleEvent } from '@pega/angular-sdk-components';
16
+
17
+ import { PConnFieldProps } from '@pega/angular-sdk-components';
18
+
19
+ interface LocationProps extends PConnFieldProps {
20
+ coordinates: string;
21
+ showMap: boolean;
22
+ onlyCoordinates: boolean;
23
+ showMapReadOnly: boolean;
24
+ }
25
+
26
+ @Component({
27
+ selector: 'app-location',
28
+ imports: [
29
+ CommonModule,
30
+ GoogleMapsModule,
31
+ MatAutocompleteModule,
32
+ MatButtonModule,
33
+ MatFormFieldModule,
34
+ MatIconModule,
35
+ MatInputModule,
36
+ MatProgressSpinnerModule,
37
+ ReactiveFormsModule
38
+ ],
39
+ templateUrl: './location.component.html',
40
+ styleUrl: './location.component.scss'
41
+ })
42
+ export class LocationComponent extends FieldBase {
43
+ private loader = inject(GoogleMapsLoaderService);
44
+
45
+ private autocompleteService!: google.maps.places.AutocompleteService;
46
+ private geocoder!: google.maps.Geocoder;
47
+
48
+ // Dom variables
49
+ mapReady = false;
50
+ isLocating = false;
51
+ showMap = true;
52
+ filteredOptions: string[] = [];
53
+ center: google.maps.LatLngLiteral;
54
+ markerPosition: google.maps.LatLngLiteral | null = null;
55
+
56
+ configProps$: LocationProps;
57
+ onlyCoordinates: boolean;
58
+ coordinates: string;
59
+ showMapReadOnly$: boolean;
60
+ valueProp: string;
61
+ coordinatesProp: string;
62
+
63
+ override async ngOnInit() {
64
+ super.ngOnInit();
65
+
66
+ // Loading map
67
+ const apiKey = this.pConn$.getGoogleMapsAPIKey();
68
+ await this.loader.load(apiKey);
69
+ this.mapReady = true;
70
+ this.initializeGoogleServices();
71
+ this.getPlacePredictions();
72
+ }
73
+
74
+ /**
75
+ * Updates the component when there are changes in the state.
76
+ */
77
+ override updateSelf(): void {
78
+ // Resolve configuration properties
79
+ this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as LocationProps;
80
+
81
+ // Update component common properties
82
+ this.updateComponentCommonProperties(this.configProps$);
83
+
84
+ this.onlyCoordinates = !!this.configProps$.onlyCoordinates;
85
+ this.showMapReadOnly$ = !!this.configProps$.showMapReadOnly;
86
+ this.showMap = this.bReadonly$ ? this.showMapReadOnly$ : !!this.configProps$.showMap;
87
+
88
+ if (this.configProps$.coordinates) {
89
+ const latAndLong: number[] = this.configProps$.coordinates.split(',').map(Number);
90
+ const latitude = Number(latAndLong[0]);
91
+ const longitude = Number(latAndLong[1]);
92
+ this.updateMap(latitude, longitude, this.configProps$.value);
93
+ }
94
+
95
+ this.valueProp = this.pConn$.getStateProps().value;
96
+ this.coordinatesProp = this.pConn$.getStateProps().coordinates;
97
+ }
98
+
99
+ onOptionSelected(event: any) {
100
+ const value = event.option.value;
101
+ if (this.isCoordinateString(value)) {
102
+ const [lat, lng] = value.split(',').map(Number);
103
+ this.updateMap(lat, lng, value);
104
+ this.updateProps();
105
+ } else {
106
+ this.geocoder.geocode({ address: value }, (res, status) => {
107
+ if (status === google.maps.GeocoderStatus.OK && res && res[0]) {
108
+ const loc = res[0].geometry.location;
109
+ this.updateMap(loc.lat(), loc.lng(), value);
110
+ this.updateProps();
111
+ }
112
+ });
113
+ }
114
+ }
115
+
116
+ fieldOnBlur() {
117
+ this.updateProps();
118
+ }
119
+
120
+ locateMe() {
121
+ if (!navigator.geolocation) {
122
+ alert('Geolocation not supported by this browser.');
123
+ return;
124
+ }
125
+
126
+ this.isLocating = true;
127
+ this.tryGetLocation(0);
128
+ }
129
+
130
+ onMapClick(event: google.maps.MapMouseEvent) {
131
+ if (!event.latLng) return;
132
+
133
+ const lat = event.latLng.lat();
134
+ const lng = event.latLng.lng();
135
+
136
+ if (this.onlyCoordinates) {
137
+ this.updateMap(lat, lng);
138
+ this.updateProps();
139
+ } else {
140
+ this.geocoder.geocode({ location: { lat, lng } }, (res, status) => {
141
+ if (status === google.maps.GeocoderStatus.OK && res && res[0]) {
142
+ this.updateMap(lat, lng, res[0].formatted_address);
143
+ } else {
144
+ this.updateMap(lat, lng);
145
+ }
146
+ this.updateProps();
147
+ });
148
+ }
149
+ }
150
+
151
+ private tryGetLocation(retryCount: number) {
152
+ navigator.geolocation.getCurrentPosition(
153
+ position => {
154
+ const lat = position.coords.latitude;
155
+ const lng = position.coords.longitude;
156
+ if (this.onlyCoordinates) {
157
+ this.updateMap(lat, lng);
158
+ this.updateProps();
159
+ this.isLocating = false;
160
+ } else {
161
+ this.geocoder.geocode({ location: { lat, lng } }, (res, status) => {
162
+ this.isLocating = false;
163
+ if (status === google.maps.GeocoderStatus.OK && res && res[0]) {
164
+ this.updateMap(lat, lng, res[0].formatted_address);
165
+ } else {
166
+ this.updateMap(lat, lng);
167
+ }
168
+ this.updateProps();
169
+ });
170
+ }
171
+ },
172
+ err => {
173
+ console.error('Geolocation error', err);
174
+
175
+ if (err.code === err.POSITION_UNAVAILABLE && retryCount < 2) {
176
+ console.warn('Retrying location fetch...');
177
+ setTimeout(() => this.tryGetLocation(retryCount + 1), 2000);
178
+ } else {
179
+ this.isLocating = false;
180
+
181
+ switch (err.code) {
182
+ case err.PERMISSION_DENIED:
183
+ alert('Location permission denied. Please allow access in your browser settings.');
184
+ break;
185
+ case err.POSITION_UNAVAILABLE:
186
+ alert('Location unavailable. Please check your internet or GPS.');
187
+ break;
188
+ case err.TIMEOUT:
189
+ alert('Timed out while trying to get your location. Try again.');
190
+ break;
191
+ default:
192
+ alert('Could not get your location. Please try again.');
193
+ }
194
+ }
195
+ },
196
+ {
197
+ enableHighAccuracy: true,
198
+ timeout: 10000,
199
+ maximumAge: 0
200
+ }
201
+ );
202
+ }
203
+
204
+ private initializeGoogleServices() {
205
+ this.autocompleteService = new google.maps.places.AutocompleteService();
206
+ this.geocoder = new google.maps.Geocoder();
207
+ }
208
+
209
+ private getPlacePredictions() {
210
+ this.fieldControl.valueChanges
211
+ .pipe(
212
+ debounceTime(300),
213
+ switchMap(value => this.getSuggestions(value || ''))
214
+ )
215
+ .subscribe(predictions => {
216
+ this.filteredOptions = predictions;
217
+ });
218
+ }
219
+
220
+ private isCoordinateString(value: string): boolean {
221
+ const regex = /^-?\d+(\.\d+)?\s*,\s*-?\d+(\.\d+)?$/;
222
+ return regex.test(value.trim());
223
+ }
224
+
225
+ private getSuggestions(input: string) {
226
+ if (!input.trim()) return of([]);
227
+
228
+ if (this.isCoordinateString(input)) {
229
+ return of([input]);
230
+ }
231
+
232
+ return from(
233
+ new Promise<string[]>(resolve => {
234
+ this.autocompleteService.getPlacePredictions({ input }, (preds, status) => {
235
+ if (status === google.maps.places.PlacesServiceStatus.OK && preds) {
236
+ if (this.onlyCoordinates) {
237
+ // only first exact match as coordinates
238
+ this.geocoder.geocode({ placeId: preds[0].place_id }, (response, geocoderStatus) => {
239
+ if (geocoderStatus === google.maps.GeocoderStatus.OK && response && response[0]) {
240
+ const loc = response[0].geometry.location;
241
+ resolve([`${loc.lat()}, ${loc.lng()}`]);
242
+ } else {
243
+ resolve([]);
244
+ }
245
+ });
246
+ } else {
247
+ resolve(preds.map(p => p.description));
248
+ }
249
+ } else {
250
+ resolve([]);
251
+ }
252
+ });
253
+ })
254
+ );
255
+ }
256
+
257
+ private updateMap(lat: number, lng: number, value?: string) {
258
+ this.center = { lat, lng };
259
+ this.markerPosition = { lat, lng };
260
+ this.setCoordinates(lat, lng);
261
+ if (this.onlyCoordinates) {
262
+ this.setLocationValue(this.coordinates);
263
+ } else {
264
+ this.setLocationValue(value || '');
265
+ }
266
+ }
267
+
268
+ private updateProps() {
269
+ handleEvent(this.actionsApi, 'change', this.valueProp, this.fieldControl.value);
270
+ handleEvent(this.actionsApi, 'change', this.coordinatesProp, this.coordinates);
271
+ }
272
+
273
+ private setCoordinates(latitude: number, longitude: number) {
274
+ this.coordinates = `${latitude}, ${longitude}`;
275
+ }
276
+
277
+ private setLocationValue(value: string) {
278
+ this.fieldControl.setValue(value, { emitEvent: false });
279
+ }
280
+ }
@@ -1,6 +1,6 @@
1
1
  import { CommonModule } from '@angular/common';
2
- import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
3
- import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
2
+ import { Component } from '@angular/core';
3
+ import { ReactiveFormsModule } from '@angular/forms';
4
4
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
5
5
  import { MatChipsModule } from '@angular/material/chips';
6
6
  import { MatCheckboxModule } from '@angular/material/checkbox';
@@ -8,9 +8,8 @@ import { MatOptionModule } from '@angular/material/core';
8
8
  import { MatFormFieldModule } from '@angular/material/form-field';
9
9
  import { MatInputModule } from '@angular/material/input';
10
10
  import { MatIconModule } from '@angular/material/icon';
11
- import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
12
- import { ComponentMapperComponent } from '@pega/angular-sdk-components';
13
- import { Utils } from '@pega/angular-sdk-components';
11
+
12
+ import { FieldBase } from '@pega/angular-sdk-components';
14
13
  import { doSearch, getDisplayFieldsMetaData, getGroupDataForItemsTree, preProcessColumns } from './utils';
15
14
  import { deleteInstruction, insertInstruction } from '@pega/angular-sdk-components';
16
15
  import { handleEvent } from '@pega/angular-sdk-components';
@@ -19,7 +18,6 @@ import { handleEvent } from '@pega/angular-sdk-components';
19
18
  selector: 'app-multiselect',
20
19
  templateUrl: './multiselect.component.html',
21
20
  styleUrls: ['./multiselect.component.scss'],
22
- standalone: true,
23
21
  imports: [
24
22
  CommonModule,
25
23
  ReactiveFormsModule,
@@ -29,43 +27,19 @@ import { handleEvent } from '@pega/angular-sdk-components';
29
27
  MatOptionModule,
30
28
  MatCheckboxModule,
31
29
  MatIconModule,
32
- MatChipsModule,
33
- forwardRef(() => ComponentMapperComponent)
30
+ MatChipsModule
34
31
  ]
35
32
  })
36
- export class MultiselectComponent implements OnInit, OnDestroy {
37
- @Input() pConn$: typeof PConnect;
38
- @Input() formGroup$: FormGroup;
39
-
40
- // Used with AngularPConnect
41
- angularPConnectData: AngularPConnectData = {};
33
+ export class MultiselectComponent extends FieldBase {
34
+ configProps$: any;
42
35
 
43
- label$ = '';
44
- value$ = '';
45
- bRequired$ = false;
46
- bDisabled$ = false;
47
- bVisible$ = true;
48
- controlName$: string;
49
- bHasForm$ = true;
50
36
  listType: string;
51
- placeholder: string;
52
- fieldControl = new FormControl('', null);
53
37
  parameters: {};
54
- hideLabel: boolean;
55
- configProps$: any;
56
38
 
57
39
  referenceList: any;
58
40
  selectionKey: string;
59
41
  primaryField: string;
60
- initialCaseClass: any;
61
42
  showSecondaryInSearchOnly = false;
62
- isGroupData = false;
63
- referenceType;
64
- secondaryFields;
65
- groupDataSource = [];
66
- matchPosition = 'contains';
67
- maxResultsDisplay;
68
- groupColumnsConfig = [{}];
69
43
  selectionList;
70
44
  listActions: any;
71
45
  selectedItems: any[] = [];
@@ -74,64 +48,32 @@ export class MultiselectComponent implements OnInit, OnDestroy {
74
48
  dataApiObj: any;
75
49
  itemsTree: any[] = [];
76
50
  trigger: any;
77
- actionsApi: Object;
78
- propName: string;
79
-
80
- constructor(
81
- private angularPConnect: AngularPConnectService,
82
- private utils: Utils
83
- ) {}
84
-
85
- ngOnInit(): void {
86
- // First thing in initialization is registering and subscribing to the AngularPConnect service
87
- this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
88
- this.controlName$ = this.angularPConnect.getComponentID(this);
89
-
90
- // Then, continue on with other initialization
91
- this.checkAndUpdate();
92
-
93
- if (this.formGroup$) {
94
- // add control to formGroup
95
- this.formGroup$.addControl(this.controlName$, this.fieldControl);
96
- this.fieldControl.setValue(this.value$);
97
- this.bHasForm$ = true;
98
- } else {
99
- this.bHasForm$ = false;
100
- }
101
- }
102
-
103
- ngOnDestroy(): void {
104
- if (this.formGroup$) {
105
- this.formGroup$.removeControl(this.controlName$);
106
- }
107
-
108
- if (this.angularPConnectData.unsubscribeFn) {
109
- this.angularPConnectData.unsubscribeFn();
110
- }
111
- }
112
51
 
113
- // Callback passed when subscribing to store change
114
- onStateChange() {
115
- this.checkAndUpdate();
116
- }
52
+ /**
53
+ * Updates the component when there are changes in the state.
54
+ */
55
+ override updateSelf() {
56
+ // Resolve configuration properties
57
+ this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps());
117
58
 
118
- checkAndUpdate() {
119
- // Should always check the bridge to see if the component should
120
- // update itself (re-render)
121
- const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this);
59
+ // Update component common properties
60
+ this.updateComponentCommonProperties(this.configProps$);
122
61
 
123
- // ONLY call updateSelf when the component should update
124
- if (bUpdateSelf) {
125
- this.updateSelf();
126
- }
127
- }
128
-
129
- // updateSelf
130
- updateSelf() {
131
- this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps());
62
+ this.setPropertyValuesFromProps();
132
63
 
64
+ const {
65
+ groupDataSource = [],
66
+ parameters = {},
67
+ listType = '',
68
+ showSecondaryInSearchOnly = false,
69
+ isGroupData = false,
70
+ referenceType,
71
+ secondaryFields,
72
+ matchPosition = 'contains',
73
+ maxResultsDisplay,
74
+ groupColumnsConfig = [{}]
75
+ } = this.configProps$;
133
76
  let { datasource = [], columns = [{}] } = this.configProps$;
134
- this.setPropertyValuesFromProps();
135
77
 
136
78
  if (this.referenceList.length > 0) {
137
79
  datasource = this.referenceList;
@@ -149,8 +91,8 @@ export class MultiselectComponent implements OnInit, OnDestroy {
149
91
  }
150
92
  ];
151
93
  let secondaryColumns: any = [];
152
- if (this.secondaryFields) {
153
- secondaryColumns = this.secondaryFields.map(secondaryField => ({
94
+ if (secondaryFields) {
95
+ secondaryColumns = secondaryFields.map(secondaryField => ({
154
96
  value: secondaryField,
155
97
  display: 'true',
156
98
  secondary: 'true',
@@ -166,7 +108,7 @@ export class MultiselectComponent implements OnInit, OnDestroy {
166
108
  }
167
109
  ];
168
110
  }
169
- if (this.referenceType === 'Case') {
111
+ if (referenceType === 'Case') {
170
112
  columns = [...columns, ...secondaryColumns];
171
113
  }
172
114
  }
@@ -176,54 +118,36 @@ export class MultiselectComponent implements OnInit, OnDestroy {
176
118
 
177
119
  const dataConfig = {
178
120
  dataSource: datasource,
179
- groupDataSource: this.groupDataSource,
180
- isGroupData: this.isGroupData,
181
- showSecondaryInSearchOnly: this.showSecondaryInSearchOnly,
182
- parameters: this.parameters,
183
- matchPosition: this.matchPosition,
184
- listType: this.listType,
185
- maxResultsDisplay: this.maxResultsDisplay || '100',
121
+ groupDataSource,
122
+ isGroupData,
123
+ showSecondaryInSearchOnly,
124
+ parameters,
125
+ matchPosition,
126
+ listType,
127
+ maxResultsDisplay: maxResultsDisplay || '100',
186
128
  columns: preProcessColumns(columns),
187
- groupColumnsConfig: preProcessColumns(this.groupColumnsConfig),
129
+ groupColumnsConfig: preProcessColumns(groupColumnsConfig),
188
130
  associationFilter: undefined,
189
131
  ignoreCase: undefined
190
132
  };
191
133
 
192
134
  const groupsDisplayFieldMeta = this.listType !== 'associated' ? getDisplayFieldsMetaData(dataConfig.groupColumnsConfig) : null;
193
135
 
194
- this.itemsTreeBaseData = getGroupDataForItemsTree(this.groupDataSource, groupsDisplayFieldMeta, this.showSecondaryInSearchOnly) || [];
136
+ this.itemsTreeBaseData = getGroupDataForItemsTree(groupDataSource, groupsDisplayFieldMeta, this.showSecondaryInSearchOnly) || [];
195
137
 
196
- this.itemsTree = this.isGroupData ? getGroupDataForItemsTree(this.groupDataSource, groupsDisplayFieldMeta, this.showSecondaryInSearchOnly) : [];
138
+ this.itemsTree = isGroupData ? getGroupDataForItemsTree(groupDataSource, groupsDisplayFieldMeta, this.showSecondaryInSearchOnly) : [];
197
139
 
198
140
  this.displayFieldMeta = this.listType !== 'associated' ? getDisplayFieldsMetaData(dataConfig.columns) : null;
199
141
 
200
142
  this.listActions = this.pConn$.getListActions();
201
143
  this.pConn$.setReferenceList(this.selectionList);
202
144
 
203
- if (this.configProps$.visibility != null) {
204
- this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
205
- }
206
-
207
- // disabled
208
- if (this.configProps$.disabled != undefined) {
209
- this.bDisabled$ = this.utils.getBooleanValue(this.configProps$.disabled);
210
- }
211
-
212
- if (this.bDisabled$) {
213
- this.fieldControl.disable();
214
- } else {
215
- this.fieldControl.enable();
216
- }
217
-
218
- this.actionsApi = this.pConn$.getActionsApi();
219
- this.propName = this.pConn$.getStateProps().value;
220
-
221
145
  if (this.listType !== 'associated') {
222
146
  PCore.getDataApi()
223
147
  ?.init(dataConfig, contextName)
224
148
  .then(async dataObj => {
225
149
  this.dataApiObj = dataObj;
226
- if (!this.isGroupData) {
150
+ if (!isGroupData) {
227
151
  this.getCaseListBasedOnParams(this.value$ ?? '', '', [...this.selectedItems], [...this.itemsTree]);
228
152
  }
229
153
  });
@@ -231,23 +155,9 @@ export class MultiselectComponent implements OnInit, OnDestroy {
231
155
  }
232
156
 
233
157
  setPropertyValuesFromProps() {
234
- this.label$ = this.configProps$.label;
235
- this.placeholder = this.configProps$.placeholder || '';
236
- this.listType = this.configProps$.listType ? this.configProps$.listType : '';
237
- this.hideLabel = this.configProps$.hideLabel;
238
- this.parameters = this.configProps$?.parameters ? this.configProps$?.parameters : {};
239
158
  this.referenceList = this.configProps$?.referenceList;
240
159
  this.selectionKey = this.configProps$?.selectionKey;
241
160
  this.primaryField = this.configProps$?.primaryField;
242
- this.initialCaseClass = this.configProps$?.initialCaseClass;
243
- this.showSecondaryInSearchOnly = this.configProps$?.showSecondaryInSearchOnly ? this.configProps$?.showSecondaryInSearchOnly : false;
244
- this.isGroupData = this.configProps$?.isGroupData ? this.configProps$.isGroupData : false;
245
- this.referenceType = this.configProps$?.referenceType;
246
- this.secondaryFields = this.configProps$?.secondaryFields;
247
- this.groupDataSource = this.configProps$?.groupDataSource ? this.configProps$?.groupDataSource : [];
248
- this.matchPosition = this.configProps$?.matchPosition ? this.configProps$?.matchPosition : 'contains';
249
- this.maxResultsDisplay = this.configProps$?.maxResultsDisplay;
250
- this.groupColumnsConfig = this.configProps$?.groupColumnsConfig ? this.configProps$?.groupColumnsConfig : [{}];
251
161
  this.selectionList = this.configProps$?.selectionList;
252
162
  this.value$ = this.configProps$?.value;
253
163
  }
@@ -269,15 +179,17 @@ export class MultiselectComponent implements OnInit, OnDestroy {
269
179
 
270
180
  const initalItemsTree = isTriggeredFromSearch || !currentItemsTree ? [...this.itemsTreeBaseData] : [...currentItemsTree];
271
181
 
182
+ const { initialCaseClass, isGroupData, showSecondaryInSearchOnly } = this.configProps$;
183
+
272
184
  doSearch(
273
185
  searchText,
274
186
  group,
275
- this.initialCaseClass,
187
+ initialCaseClass,
276
188
  this.displayFieldMeta,
277
189
  this.dataApiObj,
278
190
  initalItemsTree,
279
- this.isGroupData,
280
- this.showSecondaryInSearchOnly,
191
+ isGroupData,
192
+ showSecondaryInSearchOnly,
281
193
  selectedRows || []
282
194
  ).then(res => {
283
195
  this.itemsTree = res || [];
@@ -349,21 +261,4 @@ export class MultiselectComponent implements OnInit, OnDestroy {
349
261
  deleteInstruction(this.pConn$, this.selectionList, this.selectionKey, data);
350
262
  }
351
263
  }
352
-
353
- getErrorMessage() {
354
- let errMessage = '';
355
-
356
- // look for validation messages for json, pre-defined or just an error pushed from workitem (400)
357
- if (this.fieldControl.hasError('message')) {
358
- errMessage = this.angularPConnectData.validateMessage ?? '';
359
- return errMessage;
360
- }
361
- if (this.fieldControl.hasError('required')) {
362
- errMessage = 'You must enter a value';
363
- } else if (this.fieldControl.errors) {
364
- errMessage = this.fieldControl.errors.toString();
365
- }
366
-
367
- return errMessage;
368
- }
369
264
  }