novo-elements 13.1.0-next.4 → 13.1.0-next.5
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.
- package/elements/places/index.d.ts +11 -2
- package/elements/query-builder/index.d.ts +66 -35
- package/fesm2022/novo-elements-elements-places.mjs +128 -31
- package/fesm2022/novo-elements-elements-places.mjs.map +1 -1
- package/fesm2022/novo-elements-elements-query-builder.mjs +61 -15
- package/fesm2022/novo-elements-elements-query-builder.mjs.map +1 -1
- package/fesm2022/novo-elements.mjs +14 -0
- package/fesm2022/novo-elements.mjs.map +1 -1
- package/index.d.ts +14 -0
- package/package.json +1 -1
|
@@ -14,7 +14,11 @@ declare class GooglePlacesService {
|
|
|
14
14
|
private platformId;
|
|
15
15
|
private _global;
|
|
16
16
|
private _localStorageService;
|
|
17
|
+
private mapsLoad?;
|
|
18
|
+
private mapsLoadKey?;
|
|
17
19
|
constructor(_http: HttpClient, platformId: Object, _global: GlobalRef, _localStorageService: LocalStorageService);
|
|
20
|
+
loadGoogleMaps(settings: PlacesSettings): Promise<void>;
|
|
21
|
+
private injectGoogleMapsScript;
|
|
18
22
|
getPredictions(url: string, query: string, sessionToken?: string): Promise<any>;
|
|
19
23
|
getLatLngDetail(url: string, lat: number, lng: number): Promise<any>;
|
|
20
24
|
getPlaceDetails(url: string, placeId: string, sessionToken?: string): Promise<any>;
|
|
@@ -55,6 +59,10 @@ interface PlacesSettings {
|
|
|
55
59
|
currentLocIconUrl?: string;
|
|
56
60
|
searchIconUrl?: string;
|
|
57
61
|
locationIconUrl?: string;
|
|
62
|
+
/** Bullhorn-managed key; when set, the library lazy-loads the Maps JS SDK with it instead of relying on a host script tag. */
|
|
63
|
+
googleApiKey?: string;
|
|
64
|
+
/** Extra Maps JS loader query params, merged over the defaults (libraries=places, loading=async). */
|
|
65
|
+
googleMapsLoaderParams?: Record<string, string>;
|
|
58
66
|
}
|
|
59
67
|
/** Normalized address prediction; raw provider records are mapped into this via normalizePrediction. */
|
|
60
68
|
interface AddressLookupPrediction {
|
|
@@ -72,6 +80,7 @@ declare class PlacesListComponent extends BasePickerResults implements OnInit, O
|
|
|
72
80
|
private _global;
|
|
73
81
|
private _googlePlacesService;
|
|
74
82
|
private cdr;
|
|
83
|
+
private addressConfig;
|
|
75
84
|
private static readonly SESSION_TOKEN_TIMEOUT_MS;
|
|
76
85
|
userSettings: PlacesSettings;
|
|
77
86
|
termChange: EventEmitter<any>;
|
|
@@ -94,7 +103,7 @@ declare class PlacesListComponent extends BasePickerResults implements OnInit, O
|
|
|
94
103
|
model: any;
|
|
95
104
|
onModelChange: Function;
|
|
96
105
|
onModelTouched: Function;
|
|
97
|
-
constructor(platformId: Object, _elmRef: ElementRef, _global: GlobalRef, _googlePlacesService: GooglePlacesService, cdr: ChangeDetectorRef);
|
|
106
|
+
constructor(platformId: Object, _elmRef: ElementRef, _global: GlobalRef, _googlePlacesService: GooglePlacesService, cdr: ChangeDetectorRef, addressConfig?: PlacesSettings);
|
|
98
107
|
ngOnInit(): any;
|
|
99
108
|
ngOnChanges(): any;
|
|
100
109
|
writeValue(model: any): void;
|
|
@@ -125,7 +134,7 @@ declare class PlacesListComponent extends BasePickerResults implements OnInit, O
|
|
|
125
134
|
private getPlaceLocationInfo;
|
|
126
135
|
private setRecentLocation;
|
|
127
136
|
private getRecentLocations;
|
|
128
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<PlacesListComponent,
|
|
137
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PlacesListComponent, [null, null, null, null, null, { optional: true; }]>;
|
|
129
138
|
static ɵcmp: i0.ɵɵComponentDeclaration<PlacesListComponent, "google-places-list", never, { "userSettings": { "alias": "userSettings"; "required": false; }; }, { "termChange": "termChange"; "select": "select"; "matchesUpdated": "matchesUpdated"; }, never, never, false, never>;
|
|
130
139
|
}
|
|
131
140
|
|
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { TemplateRef, ViewContainerRef, OnInit, OnChanges, AfterContentInit, AfterViewInit, OnDestroy, ElementRef, ChangeDetectorRef, SimpleChanges, QueryList, InputSignal, Signal, AfterContentChecked, InjectionToken } from '@angular/core';
|
|
3
|
-
import * as
|
|
2
|
+
import { TemplateRef, ViewContainerRef, OnInit, OnChanges, AfterContentInit, AfterViewInit, OnDestroy, ElementRef, ChangeDetectorRef, SimpleChanges, QueryList, InputSignal, Signal, AfterContentChecked, PipeTransform, InjectionToken } from '@angular/core';
|
|
3
|
+
import * as i16 from '@angular/forms';
|
|
4
4
|
import { FormGroup, FormControl, ControlContainer, FormControlName, UntypedFormGroup, AbstractControl, FormBuilder, FormArray } from '@angular/forms';
|
|
5
5
|
import { NovoLabelService } from 'novo-elements/services';
|
|
6
6
|
import { Subject, Subscription } from 'rxjs';
|
|
7
7
|
import { Day } from 'date-fns';
|
|
8
|
-
import * as
|
|
8
|
+
import * as i26 from 'novo-elements/elements/field';
|
|
9
9
|
import { NovoPickerToggleElement } from 'novo-elements/elements/field';
|
|
10
|
-
import * as
|
|
11
|
-
import { PlacesListComponent } from 'novo-elements/elements/places';
|
|
12
|
-
import * as
|
|
10
|
+
import * as i19 from 'novo-elements/elements/places';
|
|
11
|
+
import { PlacesListComponent, PlacesSettings } from 'novo-elements/elements/places';
|
|
12
|
+
import * as i24 from 'novo-elements/elements/select';
|
|
13
13
|
import { NovoSelectElement } from 'novo-elements/elements/select';
|
|
14
|
-
import * as
|
|
14
|
+
import * as i29 from 'novo-elements/elements/tabbed-group-picker';
|
|
15
15
|
import { NovoTabbedGroupPickerElement, TabbedGroupPickerTab, TabbedGroupPickerButtonConfig } from 'novo-elements/elements/tabbed-group-picker';
|
|
16
|
-
import * as
|
|
17
|
-
import * as
|
|
18
|
-
import * as
|
|
19
|
-
import * as
|
|
20
|
-
import * as
|
|
21
|
-
import * as
|
|
22
|
-
import * as
|
|
23
|
-
import * as
|
|
24
|
-
import * as
|
|
25
|
-
import * as
|
|
26
|
-
import * as
|
|
27
|
-
import * as
|
|
28
|
-
import * as
|
|
29
|
-
import * as
|
|
30
|
-
import * as
|
|
31
|
-
import * as
|
|
32
|
-
import * as
|
|
33
|
-
import * as
|
|
34
|
-
import * as
|
|
35
|
-
import * as
|
|
36
|
-
import * as
|
|
37
|
-
import * as
|
|
16
|
+
import * as i15 from '@angular/common';
|
|
17
|
+
import * as i17 from '@angular/cdk/drag-drop';
|
|
18
|
+
import * as i18 from '@angular/cdk/table';
|
|
19
|
+
import * as i20 from 'novo-elements/elements/autocomplete';
|
|
20
|
+
import * as i21 from 'novo-elements/elements/button';
|
|
21
|
+
import * as i22 from 'novo-elements/elements/common';
|
|
22
|
+
import * as i23 from 'novo-elements/elements/form';
|
|
23
|
+
import * as i25 from 'novo-elements/elements/non-ideal-state';
|
|
24
|
+
import * as i27 from 'novo-elements/elements/flex';
|
|
25
|
+
import * as i28 from 'novo-elements/elements/tabs';
|
|
26
|
+
import * as i30 from 'novo-elements/elements/loading';
|
|
27
|
+
import * as i31 from 'novo-elements/elements/card';
|
|
28
|
+
import * as i32 from 'novo-elements/elements/date-picker';
|
|
29
|
+
import * as i33 from 'novo-elements/elements/date-time-picker';
|
|
30
|
+
import * as i34 from 'novo-elements/elements/icon';
|
|
31
|
+
import * as i35 from 'novo-elements/elements/radio';
|
|
32
|
+
import * as i36 from 'novo-elements/elements/search';
|
|
33
|
+
import * as i37 from 'novo-elements/elements/switch';
|
|
34
|
+
import * as i38 from 'novo-elements/elements/chips';
|
|
35
|
+
import * as i39 from 'novo-elements/elements/select-search';
|
|
36
|
+
import * as i40 from 'novo-elements/elements/dropdown';
|
|
37
|
+
import * as i41 from 'novo-elements/elements/tooltip';
|
|
38
38
|
|
|
39
39
|
/** Base interface for a condidation template directives. */
|
|
40
40
|
interface ConditionDef {
|
|
@@ -176,15 +176,35 @@ interface FieldConfig<T extends BaseFieldDef> {
|
|
|
176
176
|
find: (name: string) => T;
|
|
177
177
|
}
|
|
178
178
|
interface AddressData {
|
|
179
|
-
address_components
|
|
180
|
-
formatted_address
|
|
181
|
-
geometry
|
|
179
|
+
address_components?: AddressComponent[];
|
|
180
|
+
formatted_address?: string;
|
|
181
|
+
geometry?: AddressGeometry;
|
|
182
182
|
name?: string;
|
|
183
|
-
place_id
|
|
183
|
+
place_id?: string;
|
|
184
|
+
address1?: string;
|
|
185
|
+
address2?: string;
|
|
186
|
+
city?: string;
|
|
187
|
+
state?: string;
|
|
188
|
+
zip?: string;
|
|
189
|
+
countryName?: string;
|
|
190
|
+
countryCode?: string;
|
|
191
|
+
formattedAddress?: string;
|
|
192
|
+
location?: AddressGeoPoint;
|
|
193
|
+
viewport?: AddressDetailViewport;
|
|
194
|
+
referenceId?: string;
|
|
195
|
+
postalCodes?: string[];
|
|
184
196
|
radius?: AddressRadius;
|
|
185
197
|
postal_codes?: string[];
|
|
186
198
|
types?: string[];
|
|
187
199
|
}
|
|
200
|
+
interface AddressGeoPoint {
|
|
201
|
+
latitude: number;
|
|
202
|
+
longitude: number;
|
|
203
|
+
}
|
|
204
|
+
interface AddressDetailViewport {
|
|
205
|
+
northeast: AddressGeoPoint;
|
|
206
|
+
southwest: AddressGeoPoint;
|
|
207
|
+
}
|
|
188
208
|
interface AddressRadius {
|
|
189
209
|
value: number;
|
|
190
210
|
units: AddressRadiusUnitsName;
|
|
@@ -431,6 +451,7 @@ declare class NovoDefaultAddressConditionDef extends AbstractConditionFieldDef i
|
|
|
431
451
|
term: string;
|
|
432
452
|
private _addressChangesSubscription;
|
|
433
453
|
element: ElementRef<any>;
|
|
454
|
+
protected readonly addressConfig: PlacesSettings;
|
|
434
455
|
constructor(labelService: NovoLabelService);
|
|
435
456
|
ngOnDestroy(): void;
|
|
436
457
|
onKeyup(event: any, viewIndex: any): void;
|
|
@@ -629,9 +650,19 @@ declare class CriteriaBuilderComponent implements OnInit, OnDestroy, AfterConten
|
|
|
629
650
|
static ɵcmp: i0.ɵɵComponentDeclaration<CriteriaBuilderComponent, "novo-criteria-builder", never, { "config": { "alias": "config"; "required": false; }; "controlName": { "alias": "controlName"; "required": false; }; "allowedGroupings": { "alias": "allowedGroupings"; "required": false; }; "editTypeFn": { "alias": "editTypeFn"; "required": false; }; "addressConfig": { "alias": "addressConfig"; "required": false; }; "dateConfig": { "alias": "dateConfig"; "required": false; }; "canBeEmpty": { "alias": "canBeEmpty"; "required": false; }; "HideFirstOperator": { "alias": "hideFirstOperator"; "required": false; }; }, {}, ["_contentFieldDefs"], never, false, never>;
|
|
630
651
|
}
|
|
631
652
|
|
|
653
|
+
/**
|
|
654
|
+
* Resolves a display label from an address value. Google client-SDK results use formatted_address;
|
|
655
|
+
* address-search-service results use formattedAddress.
|
|
656
|
+
*/
|
|
657
|
+
declare class AddressLabelPipe implements PipeTransform {
|
|
658
|
+
transform(item: AddressData): string;
|
|
659
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AddressLabelPipe, never>;
|
|
660
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<AddressLabelPipe, "addressLabel", false>;
|
|
661
|
+
}
|
|
662
|
+
|
|
632
663
|
declare class NovoQueryBuilderModule {
|
|
633
664
|
static ɵfac: i0.ɵɵFactoryDeclaration<NovoQueryBuilderModule, never>;
|
|
634
|
-
static ɵmod: i0.ɵɵNgModuleDeclaration<NovoQueryBuilderModule, [typeof CriteriaBuilderComponent, typeof ConditionBuilderComponent, typeof ConditionInputOutlet, typeof ConditionOperatorOutlet, typeof ConditionGroupComponent, typeof NovoDefaultAddressConditionDef, typeof NovoDefaultBooleanConditionDef, typeof NovoDefaultDateConditionDef, typeof NovoDefaultDateTimeConditionDef, typeof NovoConditionOperatorsDef, typeof NovoConditionInputDef, typeof NovoConditionFieldDef, typeof NovoDefaultStringConditionDef, typeof NovoDefaultNumberConditionDef, typeof NovoDefaultIdConditionDef, typeof NovoDefaultPickerConditionDef, typeof NovoConditionTemplatesComponent], [typeof
|
|
665
|
+
static ɵmod: i0.ɵɵNgModuleDeclaration<NovoQueryBuilderModule, [typeof AddressLabelPipe, typeof CriteriaBuilderComponent, typeof ConditionBuilderComponent, typeof ConditionInputOutlet, typeof ConditionOperatorOutlet, typeof ConditionGroupComponent, typeof NovoDefaultAddressConditionDef, typeof NovoDefaultBooleanConditionDef, typeof NovoDefaultDateConditionDef, typeof NovoDefaultDateTimeConditionDef, typeof NovoConditionOperatorsDef, typeof NovoConditionInputDef, typeof NovoConditionFieldDef, typeof NovoDefaultStringConditionDef, typeof NovoDefaultNumberConditionDef, typeof NovoDefaultIdConditionDef, typeof NovoDefaultPickerConditionDef, typeof NovoConditionTemplatesComponent], [typeof i15.CommonModule, typeof i16.FormsModule, typeof i16.ReactiveFormsModule, typeof i17.DragDropModule, typeof i18.CdkTableModule, typeof i19.GooglePlacesModule, typeof i20.NovoAutoCompleteModule, typeof i21.NovoButtonModule, typeof i22.NovoCommonModule, typeof i23.NovoFormModule, typeof i24.NovoSelectModule, typeof i25.NovoNonIdealStateModule, typeof i26.NovoFieldModule, typeof i22.NovoOptionModule, typeof i27.NovoFlexModule, typeof i28.NovoTabModule, typeof i29.NovoTabbedGroupPickerModule, typeof i30.NovoLoadingModule, typeof i31.NovoCardModule, typeof i32.NovoDatePickerModule, typeof i33.NovoDateTimePickerModule, typeof i34.NovoIconModule, typeof i22.NovoOverlayModule, typeof i35.NovoRadioModule, typeof i36.NovoSearchBoxModule, typeof i37.NovoSwitchModule, typeof i38.NovoChipsModule, typeof i39.NovoSelectSearchModule, typeof i40.NovoDropdownModule, typeof i23.NovoFormExtrasModule, typeof i41.NovoTooltipModule], [typeof CriteriaBuilderComponent, typeof ConditionBuilderComponent, typeof NovoDefaultAddressConditionDef, typeof NovoDefaultBooleanConditionDef, typeof NovoDefaultDateConditionDef, typeof NovoDefaultDateTimeConditionDef, typeof NovoConditionOperatorsDef, typeof NovoConditionInputDef, typeof NovoConditionFieldDef, typeof NovoDefaultStringConditionDef, typeof NovoDefaultNumberConditionDef, typeof NovoDefaultIdConditionDef, typeof NovoDefaultPickerConditionDef, typeof NovoConditionTemplatesComponent]>;
|
|
635
666
|
static ɵinj: i0.ɵɵInjectorDeclaration<NovoQueryBuilderModule>;
|
|
636
667
|
}
|
|
637
668
|
|
|
@@ -640,4 +671,4 @@ declare const NOVO_CRITERIA_BUILDER: InjectionToken<any>;
|
|
|
640
671
|
declare const NOVO_CONDITION_BUILDER: InjectionToken<any>;
|
|
641
672
|
|
|
642
673
|
export { AbstractConditionFieldDef, BaseConditionFieldDef, ConditionBuilderComponent, ConditionInputOutlet, ConditionOperatorOutlet, Conjunction, CriteriaBuilderComponent, NOVO_CONDITION_BUILDER, NOVO_CRITERIA_BUILDER, NOVO_QUERY_BUILDER, NovoConditionFieldDef, NovoConditionInputDef, NovoConditionOperatorsDef, NovoConditionTemplatesComponent, NovoDefaultAddressConditionDef, NovoDefaultBooleanConditionDef, NovoDefaultDateConditionDef, NovoDefaultDateTimeConditionDef, NovoDefaultIdConditionDef, NovoDefaultNumberConditionDef, NovoDefaultPickerConditionDef, NovoDefaultStringConditionDef, NovoQueryBuilderModule, Operator, RadiusUnits };
|
|
643
|
-
export type { AddressComponent, AddressCriteriaConfig, AddressData, AddressGeometry, AddressGeometryLocation, AddressGeometryViewport, AddressRadius, AddressRadiusUnitsName, BaseFieldDef, Condition, ConditionDef, ConditionGroup, ConditionOrConditionGroup, ConditionType, Criteria, DateCriteriaConfig, FieldConfig, NestedConditionGroup, NestedCriteria, OperatorName, QueryBuilderConfig, QueryFilterOutlet };
|
|
674
|
+
export type { AddressComponent, AddressCriteriaConfig, AddressData, AddressDetailViewport, AddressGeoPoint, AddressGeometry, AddressGeometryLocation, AddressGeometryViewport, AddressRadius, AddressRadiusUnitsName, BaseFieldDef, Condition, ConditionDef, ConditionGroup, ConditionOrConditionGroup, ConditionType, Criteria, DateCriteriaConfig, FieldConfig, NestedConditionGroup, NestedCriteria, OperatorName, QueryBuilderConfig, QueryFilterOutlet };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i3 from '@angular/common';
|
|
2
2
|
import { isPlatformBrowser, CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { PLATFORM_ID, Inject, Injectable, forwardRef, EventEmitter, Output, Input, Component, NgModule
|
|
4
|
+
import { PLATFORM_ID, Inject, Injectable, InjectionToken, forwardRef, EventEmitter, Output, Input, Optional, Component, NgModule } from '@angular/core';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
|
|
6
6
|
import { BasePickerResults } from 'novo-elements/elements/picker';
|
|
7
7
|
import * as i2 from 'novo-elements/services';
|
|
@@ -18,6 +18,53 @@ class GooglePlacesService {
|
|
|
18
18
|
this._global = _global;
|
|
19
19
|
this._localStorageService = _localStorageService;
|
|
20
20
|
}
|
|
21
|
+
// Ensure the Google Maps JS SDK is available before any window.google usage.
|
|
22
|
+
// No-ops when the SDK is already present (host script tag) or no key is configured (search-service path).
|
|
23
|
+
loadGoogleMaps(settings) {
|
|
24
|
+
const _window = this._global.nativeGlobal;
|
|
25
|
+
if (_window?.google?.maps?.places) {
|
|
26
|
+
return Promise.resolve();
|
|
27
|
+
}
|
|
28
|
+
if (!isPlatformBrowser(this.platformId) || !settings?.googleApiKey) {
|
|
29
|
+
return Promise.resolve();
|
|
30
|
+
}
|
|
31
|
+
if (!this.mapsLoad) {
|
|
32
|
+
this.mapsLoadKey = settings.googleApiKey;
|
|
33
|
+
this.mapsLoad = this.injectGoogleMapsScript(settings);
|
|
34
|
+
}
|
|
35
|
+
else if (this.mapsLoadKey && this.mapsLoadKey !== settings.googleApiKey) {
|
|
36
|
+
// The Maps JS API can only be loaded once per page; a second, different key is ignored.
|
|
37
|
+
console.warn('GooglePlacesService: the Google Maps SDK is already loading with a different key; ignoring the new googleApiKey.');
|
|
38
|
+
}
|
|
39
|
+
return this.mapsLoad;
|
|
40
|
+
}
|
|
41
|
+
injectGoogleMapsScript(settings) {
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
const _window = this._global.nativeGlobal;
|
|
44
|
+
// Build params one at a time so undefined override values are dropped instead of serialized as "undefined".
|
|
45
|
+
// The component uses the legacy Places API (AutocompleteService, PlacesService) which requires the
|
|
46
|
+
// synchronous library load — google.maps.places is fully populated when onload fires.
|
|
47
|
+
const params = new URLSearchParams();
|
|
48
|
+
params.set('key', settings.googleApiKey);
|
|
49
|
+
params.set('libraries', 'places');
|
|
50
|
+
for (const [key, value] of Object.entries(settings.googleMapsLoaderParams ?? {})) {
|
|
51
|
+
if (value !== undefined && value !== null) {
|
|
52
|
+
params.set(key, value);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const script = document.createElement('script');
|
|
56
|
+
script.src = `https://maps.googleapis.com/maps/api/js?${params.toString()}`;
|
|
57
|
+
script.async = true;
|
|
58
|
+
script.onload = () => resolve();
|
|
59
|
+
script.onerror = () => {
|
|
60
|
+
// Clear both cached fields so a later attempt can retry with any key.
|
|
61
|
+
this.mapsLoad = undefined;
|
|
62
|
+
this.mapsLoadKey = undefined;
|
|
63
|
+
reject(new Error('Failed to load the Google Maps JavaScript API.'));
|
|
64
|
+
};
|
|
65
|
+
document.head.appendChild(script);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
21
68
|
getPredictions(url, query, sessionToken) {
|
|
22
69
|
return new Promise((resolve) => {
|
|
23
70
|
const separator = url.includes('?') ? '&' : '?';
|
|
@@ -164,14 +211,12 @@ class GooglePlacesService {
|
|
|
164
211
|
const _window = this._global.nativeGlobal;
|
|
165
212
|
const placesService = new _window.google.maps.places.PlacesService(document.createElement('div'));
|
|
166
213
|
placesService.getDetails({ placeId }, (result) => {
|
|
167
|
-
if (result === null
|
|
214
|
+
if (result === null) {
|
|
215
|
+
resolve(false);
|
|
216
|
+
}
|
|
217
|
+
else if (result.length === 0) {
|
|
168
218
|
this.getGeoPaceDetailByReferance(result.referance).then((referanceData) => {
|
|
169
|
-
|
|
170
|
-
resolve(false);
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
resolve(referanceData);
|
|
174
|
-
}
|
|
219
|
+
resolve(referanceData || false);
|
|
175
220
|
});
|
|
176
221
|
}
|
|
177
222
|
else {
|
|
@@ -282,6 +327,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
282
327
|
args: [PLATFORM_ID]
|
|
283
328
|
}] }, { type: i2.GlobalRef }, { type: i2.LocalStorageService }] });
|
|
284
329
|
|
|
330
|
+
/** App-wide address-lookup config; when provided, every novo-address enables autocomplete on Address 1. */
|
|
331
|
+
const NOVO_ADDRESS_CONFIG = new InjectionToken('NOVO_ADDRESS_CONFIG');
|
|
332
|
+
|
|
285
333
|
// NG2
|
|
286
334
|
// Value accessor for the component (supports ngModel)
|
|
287
335
|
const PLACES_VALUE_ACCESSOR = {
|
|
@@ -291,13 +339,16 @@ const PLACES_VALUE_ACCESSOR = {
|
|
|
291
339
|
};
|
|
292
340
|
class PlacesListComponent extends BasePickerResults {
|
|
293
341
|
static { this.SESSION_TOKEN_TIMEOUT_MS = 3 * 60 * 1000; }
|
|
294
|
-
constructor(platformId, _elmRef, _global, _googlePlacesService, cdr
|
|
342
|
+
constructor(platformId, _elmRef, _global, _googlePlacesService, cdr,
|
|
343
|
+
// Fallback config from the app-wide token; used when [userSettings] does not provide a field.
|
|
344
|
+
addressConfig = null) {
|
|
295
345
|
super(_elmRef, cdr);
|
|
296
346
|
this.platformId = platformId;
|
|
297
347
|
this._elmRef = _elmRef;
|
|
298
348
|
this._global = _global;
|
|
299
349
|
this._googlePlacesService = _googlePlacesService;
|
|
300
350
|
this.cdr = cdr;
|
|
351
|
+
this.addressConfig = addressConfig;
|
|
301
352
|
this.termChange = new EventEmitter();
|
|
302
353
|
this.select = new EventEmitter();
|
|
303
354
|
this.matchesUpdated = new EventEmitter();
|
|
@@ -337,6 +388,8 @@ class PlacesListComponent extends BasePickerResults {
|
|
|
337
388
|
currentLocIconUrl: '',
|
|
338
389
|
searchIconUrl: '',
|
|
339
390
|
locationIconUrl: '',
|
|
391
|
+
googleApiKey: '',
|
|
392
|
+
googleMapsLoaderParams: {},
|
|
340
393
|
};
|
|
341
394
|
this.onModelChange = () => { };
|
|
342
395
|
this.onModelTouched = () => { };
|
|
@@ -498,6 +551,10 @@ class PlacesListComponent extends BasePickerResults {
|
|
|
498
551
|
if (this.settings.showRecentSearch) {
|
|
499
552
|
this.getRecentLocations();
|
|
500
553
|
}
|
|
554
|
+
if (this.settings.useGoogleGeoApi && !this.settings.googleApiKey) {
|
|
555
|
+
console.warn('google-places-list: No googleApiKey configured — Google Places autocomplete is disabled. ' +
|
|
556
|
+
'Pass address.googleApiKey to NovoElementProviders.forRoot() to enable it.');
|
|
557
|
+
}
|
|
501
558
|
if (!this.settings.useGoogleGeoApi) {
|
|
502
559
|
if (!this.settings.geoPredictionServerUrl) {
|
|
503
560
|
this.isSettingsError = true;
|
|
@@ -529,21 +586,25 @@ class PlacesListComponent extends BasePickerResults {
|
|
|
529
586
|
}
|
|
530
587
|
}
|
|
531
588
|
// function to set user settings if it is available.
|
|
589
|
+
// Priority: [userSettings] input > NOVO_ADDRESS_CONFIG token > defaultSettings.
|
|
532
590
|
setUserSettings() {
|
|
533
591
|
const _tempObj = {};
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
_tempObj[value] = this.userSettings[value]
|
|
592
|
+
const keys = Object.keys(this.defaultSettings);
|
|
593
|
+
for (const value of keys) {
|
|
594
|
+
if (this.userSettings?.[value] !== undefined) {
|
|
595
|
+
_tempObj[value] = this.userSettings[value];
|
|
596
|
+
}
|
|
597
|
+
else if (this.addressConfig?.[value] !== undefined) {
|
|
598
|
+
_tempObj[value] = this.addressConfig[value];
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
_tempObj[value] = this.defaultSettings[value];
|
|
538
602
|
}
|
|
539
|
-
return _tempObj;
|
|
540
|
-
}
|
|
541
|
-
else {
|
|
542
|
-
return this.defaultSettings;
|
|
543
603
|
}
|
|
604
|
+
return _tempObj;
|
|
544
605
|
}
|
|
545
606
|
// function to get the autocomplete list based on user input.
|
|
546
|
-
getListQuery(value) {
|
|
607
|
+
async getListQuery(value) {
|
|
547
608
|
this.recentDropdownOpen = false;
|
|
548
609
|
if (this.settings.useGoogleGeoApi) {
|
|
549
610
|
const _tempParams = {
|
|
@@ -555,14 +616,27 @@ class PlacesListComponent extends BasePickerResults {
|
|
|
555
616
|
_tempParams.geoLocation = this.settings.geoLocation;
|
|
556
617
|
_tempParams.radius = this.settings.geoRadius;
|
|
557
618
|
}
|
|
558
|
-
|
|
619
|
+
try {
|
|
620
|
+
await this._googlePlacesService.loadGoogleMaps(this.settings);
|
|
621
|
+
if (!this._global.nativeGlobal?.google?.maps?.places) {
|
|
622
|
+
this.updateListItem([]);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
const result = await this._googlePlacesService.getGeoPrediction(_tempParams);
|
|
559
626
|
this.updateListItem(result);
|
|
560
|
-
}
|
|
627
|
+
}
|
|
628
|
+
catch (err) {
|
|
629
|
+
console.error('Failed to load Google Maps for address predictions', err);
|
|
630
|
+
this.updateListItem([]);
|
|
631
|
+
}
|
|
561
632
|
}
|
|
562
633
|
else {
|
|
563
634
|
this._googlePlacesService.getPredictions(this.settings.geoPredictionServerUrl, value, this.ensureSessionToken()).then((result) => {
|
|
564
635
|
result = this.extractServerList(this.settings.serverResponseListHierarchy, result);
|
|
565
636
|
this.updateListItem(result);
|
|
637
|
+
}).catch((err) => {
|
|
638
|
+
console.error('Failed to load address predictions from server', err);
|
|
639
|
+
this.updateListItem([]);
|
|
566
640
|
});
|
|
567
641
|
}
|
|
568
642
|
}
|
|
@@ -626,14 +700,22 @@ class PlacesListComponent extends BasePickerResults {
|
|
|
626
700
|
});
|
|
627
701
|
}
|
|
628
702
|
// function to execute to get location detail based on latitude and longitude.
|
|
629
|
-
getCurrentLocationInfo(latlng) {
|
|
703
|
+
async getCurrentLocationInfo(latlng) {
|
|
630
704
|
if (this.settings.useGoogleGeoApi) {
|
|
631
|
-
|
|
705
|
+
try {
|
|
706
|
+
await this._googlePlacesService.loadGoogleMaps(this.settings);
|
|
707
|
+
const result = await this._googlePlacesService.getGeoLatLngDetail(latlng);
|
|
632
708
|
if (result) {
|
|
633
709
|
this.setRecentLocation(result);
|
|
634
710
|
}
|
|
711
|
+
}
|
|
712
|
+
catch (err) {
|
|
713
|
+
console.error('Failed to load Google Maps for current location', err);
|
|
714
|
+
}
|
|
715
|
+
finally {
|
|
716
|
+
// Always clear the spinner, even if the SDK never loaded.
|
|
635
717
|
this.gettingCurrentLocationFlag = false;
|
|
636
|
-
}
|
|
718
|
+
}
|
|
637
719
|
}
|
|
638
720
|
else {
|
|
639
721
|
this._googlePlacesService.getLatLngDetail(this.settings.geoLatLangServiceUrl, latlng.lat, latlng.lng).then((result) => {
|
|
@@ -642,6 +724,9 @@ class PlacesListComponent extends BasePickerResults {
|
|
|
642
724
|
this.setRecentLocation(result);
|
|
643
725
|
}
|
|
644
726
|
this.gettingCurrentLocationFlag = false;
|
|
727
|
+
}).catch((err) => {
|
|
728
|
+
console.error('Failed to get current location detail from server', err);
|
|
729
|
+
this.gettingCurrentLocationFlag = false;
|
|
645
730
|
});
|
|
646
731
|
}
|
|
647
732
|
}
|
|
@@ -649,9 +734,16 @@ class PlacesListComponent extends BasePickerResults {
|
|
|
649
734
|
async getPlaceLocationInfo(selectedData) {
|
|
650
735
|
const placeId = selectedData.placeId;
|
|
651
736
|
if (this.settings.useGoogleGeoApi) {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
this.
|
|
737
|
+
try {
|
|
738
|
+
// Ensure the SDK is loaded before getGeoPlaceDetail touches window.google.
|
|
739
|
+
await this._googlePlacesService.loadGoogleMaps(this.settings);
|
|
740
|
+
const data = await this._googlePlacesService.getGeoPlaceDetail(placeId);
|
|
741
|
+
if (data) {
|
|
742
|
+
this.setRecentLocation(data);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
catch (err) {
|
|
746
|
+
console.error('Failed to load Google Maps for place details', err);
|
|
655
747
|
}
|
|
656
748
|
}
|
|
657
749
|
else {
|
|
@@ -662,6 +754,9 @@ class PlacesListComponent extends BasePickerResults {
|
|
|
662
754
|
this.setRecentLocation(result);
|
|
663
755
|
}
|
|
664
756
|
}
|
|
757
|
+
catch (err) {
|
|
758
|
+
console.error('Failed to load place details from server', err);
|
|
759
|
+
}
|
|
665
760
|
finally {
|
|
666
761
|
// The details call ends the Google billing session; clear the token even if the request
|
|
667
762
|
// failed so the next interaction starts a fresh session.
|
|
@@ -693,7 +788,7 @@ class PlacesListComponent extends BasePickerResults {
|
|
|
693
788
|
this.recentSearchData = data && data.length ? data : [];
|
|
694
789
|
});
|
|
695
790
|
}
|
|
696
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PlacesListComponent, deps: [{ token: PLATFORM_ID }, { token: i0.ElementRef }, { token: i2.GlobalRef }, { token: GooglePlacesService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
791
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PlacesListComponent, deps: [{ token: PLATFORM_ID }, { token: i0.ElementRef }, { token: i2.GlobalRef }, { token: GooglePlacesService }, { token: i0.ChangeDetectorRef }, { token: NOVO_ADDRESS_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
697
792
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: PlacesListComponent, isStandalone: false, selector: "google-places-list", inputs: { userSettings: "userSettings" }, outputs: { termChange: "termChange", select: "select", matchesUpdated: "matchesUpdated" }, providers: [PLACES_VALUE_ACCESSOR], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<novo-list direction=\"vertical\">\n @for (data of matches; track $index) {\n <novo-list-item (click)=\"selectedListNode($event, $index)\" [ngClass]=\"{ active: data === activeMatch }\">\n <item-header>\n <item-avatar icon=\"location\"></item-avatar>\n <item-title>{{ data.primaryText }}</item-title>\n </item-header>\n <item-content>{{ data.secondaryText }}</item-content>\n </novo-list-item>\n }\n</novo-list>\n", styles: [":host{display:grid}:host novo-list{border:1px solid #4a89dc;background-color:#fff}:host novo-list novo-list-item{cursor:pointer;flex:0 0;transition:background-color .25s}:host novo-list novo-list-item>div{width:100%}:host novo-list novo-list-item.active{background-color:#e0ebf9}:host novo-list novo-list-item:hover{background-color:#f1f6fc}:host novo-list novo-list-item item-content{flex-flow:row wrap}:host novo-list novo-list-item item-content>*{flex:0 0 33%;white-space:nowrap}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i4.NovoListElement, selector: "novo-list", inputs: ["theme", "direction"] }, { kind: "component", type: i4.NovoListItemElement, selector: "novo-list-item, a[list-item], button[list-item]" }, { kind: "component", type: i4.NovoItemAvatarElement, selector: "item-avatar, novo-item-avatar", inputs: ["icon", "color"] }, { kind: "component", type: i4.NovoItemTitleElement, selector: "item-title, novo-item-title" }, { kind: "component", type: i4.NovoItemHeaderElement, selector: "item-header, novo-item-header" }, { kind: "component", type: i4.NovoItemContentElement, selector: "item-content, novo-item-content", inputs: ["direction"] }] }); }
|
|
698
793
|
}
|
|
699
794
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PlacesListComponent, decorators: [{
|
|
@@ -702,7 +797,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
702
797
|
}], ctorParameters: () => [{ type: Object, decorators: [{
|
|
703
798
|
type: Inject,
|
|
704
799
|
args: [PLATFORM_ID]
|
|
705
|
-
}] }, { type: i0.ElementRef }, { type: i2.GlobalRef }, { type: GooglePlacesService }, { type: i0.ChangeDetectorRef }
|
|
800
|
+
}] }, { type: i0.ElementRef }, { type: i2.GlobalRef }, { type: GooglePlacesService }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
|
|
801
|
+
type: Optional
|
|
802
|
+
}, {
|
|
803
|
+
type: Inject,
|
|
804
|
+
args: [NOVO_ADDRESS_CONFIG]
|
|
805
|
+
}] }], propDecorators: { userSettings: [{
|
|
706
806
|
type: Input
|
|
707
807
|
}], termChange: [{
|
|
708
808
|
type: Output
|
|
@@ -723,9 +823,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
723
823
|
exports: [PlacesListComponent], imports: [CommonModule, FormsModule, NovoListModule], providers: [GooglePlacesService, provideHttpClient(withInterceptorsFromDi())] }]
|
|
724
824
|
}] });
|
|
725
825
|
|
|
726
|
-
/** App-wide address-lookup config; when provided, every novo-address enables autocomplete on Address 1. */
|
|
727
|
-
const NOVO_ADDRESS_CONFIG = new InjectionToken('NOVO_ADDRESS_CONFIG');
|
|
728
|
-
|
|
729
826
|
/**
|
|
730
827
|
* Generated bundle index. Do not edit.
|
|
731
828
|
*/
|