diff --git a/src/src/app/app.module.ts b/src/src/app/app.module.ts index df5ab97..c3781de 100644 --- a/src/src/app/app.module.ts +++ b/src/src/app/app.module.ts @@ -13,6 +13,8 @@ import { MatIconModule } from '@angular/material/icon'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatMenuModule } from '@angular/material/menu'; +import { environment } from 'src/environments/environment'; +import { GoogleMapsConfigModule } from 'src/app/google-maps'; @NgModule({ declarations: [ @@ -31,6 +33,7 @@ import { MatMenuModule } from '@angular/material/menu'; MatFormFieldModule, MatInputModule, MatMenuModule, + GoogleMapsConfigModule.forRoot(environment.googleMapApiKey), ], providers: [], bootstrap: [AppComponent] diff --git a/src/src/app/google-maps/api-key.token.ts b/src/src/app/google-maps/api-key.token.ts new file mode 100644 index 0000000..46e4e5d --- /dev/null +++ b/src/src/app/google-maps/api-key.token.ts @@ -0,0 +1,3 @@ +import { InjectionToken } from '@angular/core'; + +export const GOOGLE_MAPS_API_KEY = new InjectionToken('Google Maps API key'); diff --git a/src/src/app/google-maps/config.module.ts b/src/src/app/google-maps/config.module.ts new file mode 100644 index 0000000..bb13e2c --- /dev/null +++ b/src/src/app/google-maps/config.module.ts @@ -0,0 +1,20 @@ +import { HttpClientJsonpModule, HttpClientModule } from '@angular/common/http'; +import { ModuleWithProviders, NgModule } from '@angular/core'; +import { GOOGLE_MAPS_API_KEY } from 'src/app/google-maps/api-key.token'; + +@NgModule({ + imports: [ + HttpClientModule, + HttpClientJsonpModule, + ], +}) +export class GoogleMapsConfigModule { + static forRoot(googleMapsApiKey: string): ModuleWithProviders { + return > { + ngModule: GoogleMapsConfigModule, + providers: [ + { provide: GOOGLE_MAPS_API_KEY, useValue: googleMapsApiKey, }, + ], + }; + } +} diff --git a/src/src/app/google-maps/index.ts b/src/src/app/google-maps/index.ts new file mode 100644 index 0000000..c02b34f --- /dev/null +++ b/src/src/app/google-maps/index.ts @@ -0,0 +1,2 @@ +export * from './config.module'; +export * from './script-loader'; diff --git a/src/src/app/google-maps/script-loader.ts b/src/src/app/google-maps/script-loader.ts new file mode 100644 index 0000000..e6de8d9 --- /dev/null +++ b/src/src/app/google-maps/script-loader.ts @@ -0,0 +1,40 @@ +import { HttpClient, HttpParams } from '@angular/common/http'; +import { Inject, Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; +import { Observable, of } from 'rxjs'; +import { catchError, map, publishReplay, refCount } from 'rxjs/operators'; +import { GOOGLE_MAPS_API_KEY } from './api-key.token'; + +const SCRIPT_URL = 'https://maps.googleapis.com/maps/api/js'; + +@Injectable({ + providedIn: 'root', +}) +export class GoogleMapsScriptLoader implements Resolve { + readonly scriptLoaded$: Observable; + + constructor( + @Inject(GOOGLE_MAPS_API_KEY) apiKey: string, + httpClient: HttpClient, + ) { + this.scriptLoaded$ = this._loadScript(httpClient, apiKey) + .pipe( + publishReplay(1), + refCount(), + ); + } + + resolve(_route: ActivatedRouteSnapshot, _state: RouterStateSnapshot): Observable { + return this.scriptLoaded$; + } + + _loadScript(httpClient: HttpClient, apiKey: string): Observable { + const queryParams = new HttpParams().append('key', apiKey); + const url = `${SCRIPT_URL}?${queryParams.toString()}`; + + return httpClient.jsonp(url, 'callback').pipe( + map(() => true), + catchError(() => of(false)), + ); + } +} diff --git a/src/src/app/main/components/google-map/google-map.component.html b/src/src/app/main/components/google-map/google-map.component.html index d410d88..97c774c 100644 --- a/src/src/app/main/components/google-map/google-map.component.html +++ b/src/src/app/main/components/google-map/google-map.component.html @@ -1,17 +1,15 @@ - - - - - + + + + - - - - - + + + + diff --git a/src/src/app/main/components/google-map/google-map.component.ts b/src/src/app/main/components/google-map/google-map.component.ts index acaab66..3c53ce6 100644 --- a/src/src/app/main/components/google-map/google-map.component.ts +++ b/src/src/app/main/components/google-map/google-map.component.ts @@ -4,7 +4,6 @@ import { map, scan, shareReplay, tap } from 'rxjs/operators'; import { GoogleMapViewConfig } from '../../models/google-map-view-config'; import { Marker } from '../../models/marker'; -import { GoogleMapScriptLoaderService } from '../../services/google-map-script-loader.service'; import { GoogleMapViewConfigService } from '../../services/google-map-view-config.service'; import { MarkerStorageService } from '../../services/marker-storage.service'; @@ -15,7 +14,6 @@ import { MarkerStorageService } from '../../services/marker-storage.service'; styleUrls: ['./google-map.component.css'], }) export class GoogleMapComponent { - readonly loaded$ = this._loader.loadScript().pipe(shareReplay()); readonly options = this._config.options; private readonly _addedMarker$ = new ReplaySubject(1); @@ -38,7 +36,6 @@ export class GoogleMapComponent { constructor( @Inject(GoogleMapViewConfigService) private readonly _config: GoogleMapViewConfig, - private readonly _loader: GoogleMapScriptLoaderService, private readonly _markerStorage: MarkerStorageService ) {} diff --git a/src/src/app/main/main.routes.ts b/src/src/app/main/main.routes.ts index cadf71a..1df3075 100644 --- a/src/src/app/main/main.routes.ts +++ b/src/src/app/main/main.routes.ts @@ -1,10 +1,13 @@ import { Routes } from '@angular/router'; - +import { GoogleMapsScriptLoader } from 'src/app/google-maps'; import { MainComponent } from './main.component'; export const routes: Routes = [ { path: '', component: MainComponent, + resolve: { + googleMapsScriptLoaded: GoogleMapsScriptLoader, + }, }, ]; diff --git a/src/src/app/main/maps.module.ts b/src/src/app/main/maps.module.ts index ddebad3..813c553 100644 --- a/src/src/app/main/maps.module.ts +++ b/src/src/app/main/maps.module.ts @@ -1,22 +1,11 @@ import { CommonModule } from '@angular/common'; -import { HttpClientJsonpModule, HttpClientModule } from '@angular/common/http'; import { NgModule } from '@angular/core'; - -import { environment } from '../../environments/environment'; -import { GoogleMapApiConfig } from './models/google-map-api-config'; import { GoogleMapViewConfig } from './models/google-map-view-config'; -import { GoogleMapApiConfigService } from './services/google-map-api-config.service'; import { GoogleMapViewConfigService } from './services/google-map-view-config.service'; @NgModule({ - imports: [CommonModule, HttpClientModule, HttpClientJsonpModule], + imports: [CommonModule], providers: [ - { - provide: GoogleMapApiConfigService, - useValue: { - googleMapApiKey: environment.googleMapApiKey, - }, - }, { provide: GoogleMapViewConfigService, useValue: { diff --git a/src/src/app/main/models/google-map-api-config.ts b/src/src/app/main/models/google-map-api-config.ts deleted file mode 100644 index 9431b92..0000000 --- a/src/src/app/main/models/google-map-api-config.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface GoogleMapApiConfig { - googleMapApiKey: string; -} diff --git a/src/src/app/main/services/google-map-api-config.service.ts b/src/src/app/main/services/google-map-api-config.service.ts deleted file mode 100644 index c3f70ea..0000000 --- a/src/src/app/main/services/google-map-api-config.service.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { InjectionToken } from '@angular/core'; - -import { GoogleMapApiConfig } from '../models/google-map-api-config'; - -export const GoogleMapApiConfigService = new InjectionToken( - 'GoogleMapApiConfig' -); diff --git a/src/src/app/main/services/google-map-script-loader.service.ts b/src/src/app/main/services/google-map-script-loader.service.ts deleted file mode 100644 index 141ed0a..0000000 --- a/src/src/app/main/services/google-map-script-loader.service.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { HttpClient } from '@angular/common/http'; -import { Inject, Injectable } from '@angular/core'; -import { Observable, of } from 'rxjs'; -import { catchError, map } from 'rxjs/operators'; - -import { GoogleMapApiConfig } from '../models/google-map-api-config'; -import { GoogleMapApiConfigService } from './google-map-api-config.service'; - -@Injectable({ - providedIn: 'root', -}) -export class GoogleMapScriptLoaderService { - private readonly _url = - 'https://maps.googleapis.com/maps/api/js' + - `?key=${this._config.googleMapApiKey}`; - - constructor( - @Inject(GoogleMapApiConfigService) - private readonly _config: GoogleMapApiConfig, - private readonly _httpClient: HttpClient - ) {} - - loadScript(): Observable { - return this._httpClient.jsonp(this._url, 'callback').pipe( - map(() => true), - catchError(() => of(false)) - ); - } -}