Skip to content

Commit

Permalink
Fix hard failure on google maps error (#2184)
Browse files Browse the repository at this point in the history
* Fixes a bug where if Google Maps failed to embed, the entire site would hard-fail
* Move the embedGoogleMaps.ts helper scripts into a DI service
* Lazy load google maps to only embed when we need it for the current page (improving performance)
* Asyncronously embed google maps (embedding google maps is no longer a blocking operating, improving performance and reducing the scope for bugs)
* Adds loading spinner when Google maps is loading
* Adds failure state when Google maps fails to load
* Re-enables map component tests

Fixes: #2175
  • Loading branch information
hudson-newey committed Dec 11, 2024
1 parent 90f66c3 commit d65f6a0
Show file tree
Hide file tree
Showing 25 changed files with 520 additions and 269 deletions.
15 changes: 0 additions & 15 deletions .vscode/settings.json

This file was deleted.

4 changes: 2 additions & 2 deletions src/app/components/data-request/data-request.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import schema from "./data-request.schema.json";
<p>To download a standard CSV of annotations</p>
<ol>
<li>Open the site or point page you're interested in</li>
<li>Open the project, site, or point page you're interested in</li>
<li>
Use the <i>Download Annotations</i> button to download annotations
</li>
Expand Down Expand Up @@ -54,7 +54,7 @@ class DataRequestComponent extends FormTemplate<DataRequest> implements OnInit {
private api: DataRequestService,
notifications: ToastrService,
route: ActivatedRoute,
router: Router
router: Router,
) {
super(notifications, route, router, {
successMsg: () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import { withUnsubscribe } from "@helpers/unsubscribe/unsubscribe";
import { Project } from "@models/Project";
import { Region } from "@models/Region";
import { ISite, Site } from "@models/Site";
import {
MapMarkerOptions,
sanitizeMapMarkers,
} from "@shared/map/map.component";
import { MapMarkerOptions } from "@services/maps/maps.service";
import { sanitizeMapMarkers } from "@shared/map/map.component";
import { List } from "immutable";
import { merge, Observable } from "rxjs";
import { switchMap, takeUntil } from "rxjs/operators";
Expand Down Expand Up @@ -42,11 +40,11 @@ export class SiteMapComponent extends withUnsubscribe() implements OnChanges {
if ((this.project || this.region) && !this.sitesSubset?.length) {
this.getFilter(filters, this.project, this.region)
.pipe(
switchMap((models) => this.getMarkers(models)),
takeUntil(this.unsubscribe)
switchMap((models: Site[]) => this.getMarkers(models)),
takeUntil(this.unsubscribe),
)
.subscribe({
next: (sites) => this.pushMarkers(sites),
next: (sites: Site[]) => this.pushMarkers(sites),
error: () => this.pushMarkers([]),
});
}
Expand All @@ -57,8 +55,8 @@ export class SiteMapComponent extends withUnsubscribe() implements OnChanges {
private getFilter(
filters: Filters<ISite>,
project: Project,
region?: Region
) {
region?: Region,
): Observable<Site[]> {
return this.region
? this.sitesApi.filterByRegion(filters, project, region)
: this.sitesApi.filter(filters, project);
Expand All @@ -67,14 +65,14 @@ export class SiteMapComponent extends withUnsubscribe() implements OnChanges {
/**
* Retrieve map markers from api
*/
private getMarkers(sites: Site[]) {
private getMarkers(sites: Site[]): Observable<Site[]> {
const numPages = sites?.[0]?.getMetadata()?.paging?.maxPage || 1;
const observables: Observable<Site[]>[] = [];

// Can skip first page because initial filter produces the results
for (let page = 2; page <= numPages; page++) {
observables.push(
this.getFilter({ paging: { page } }, this.project, this.region)
this.getFilter({ paging: { page } }, this.project, this.region),
);
}

Expand All @@ -85,9 +83,9 @@ export class SiteMapComponent extends withUnsubscribe() implements OnChanges {
/**
* Push new sites to markers list
*/
private pushMarkers(sites: Site[]) {
private pushMarkers(sites: Site[]): void {
this.markers = this.markers.concat(
sanitizeMapMarkers(sites.map((site) => site.getMapMarker()))
sanitizeMapMarkers(sites.map((site) => site.getMapMarker())),
);
}
}
3 changes: 1 addition & 2 deletions src/app/components/projects/projects.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { getRouteConfigForPage } from "@helpers/page/pageRouting";
import { MapModule } from "@shared/map/map.module";
import { SharedModule } from "@shared/shared.module";
import { SiteCardComponent } from "./components/site-card/site-card.component";
import { SiteMapComponent } from "./components/site-map/site-map.component";
Expand Down Expand Up @@ -30,7 +29,7 @@ const routes = projectsRoute.compileRoutes(getRouteConfigForPage);

@NgModule({
declarations: components,
imports: [MapModule, SharedModule, RouterModule.forChild(routes)],
imports: [SharedModule, RouterModule.forChild(routes)],
exports: [RouterModule, ...components],
})
export class ProjectsModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
ReactiveFormsModule,
} from "@angular/forms";
import { GoogleMapsModule } from "@angular/google-maps";
import { embedGoogleMaps } from "@helpers/embedScript/embedGoogleMaps";
import { createHostFactory, SpectatorHost } from "@ngneat/spectator";
import { FormlyBootstrapModule } from "@ngx-formly/bootstrap";
import { FormlyFieldProps, FormlyModule } from "@ngx-formly/core";
Expand Down Expand Up @@ -62,8 +61,6 @@ describe("FormlyLocationInput", () => {
return spectator;
}

beforeAll(async () => await embedGoogleMaps());

beforeEach(() => setup());

const getLatitudeInput = () =>
Expand Down
8 changes: 3 additions & 5 deletions src/app/components/shared/formly/location-input.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { Component, OnInit } from "@angular/core";
import { isInstantiated } from "@helpers/isInstantiated/isInstantiated";
import { FieldType } from "@ngx-formly/core";
import {
MapMarkerOptions,
sanitizeMapMarkers,
} from "@shared/map/map.component";
import { sanitizeMapMarkers } from "@shared/map/map.component";
import { List } from "immutable";
import { MapMarkerOptions } from "@services/maps/maps.service";
import { asFormControl } from "./helper";

/**
Expand Down Expand Up @@ -131,7 +129,7 @@ export class LocationInputComponent extends FieldType implements OnInit {
position: { lat: latitude, lng: longitude },
label: `Position (${latitude},${longitude})`,
}
: null
: null,
);
}

Expand Down
33 changes: 33 additions & 0 deletions src/app/components/shared/map/map.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@if (hasMarkers && googleMapsLoaded === true) {
<google-map
height="100%"
width="100%"
[options]="mapOptions"
(mapClick)="markerOptions?.draggable && newLocation.emit($event)"
>
<map-marker
#markerRef="mapMarker"
*ngFor="let individualMarkerOptions of validMarkersOptions"
[options]="markerOptions"
[position]="individualMarkerOptions.position"
(mapDragend)="newLocation.emit($event)"
(mapMouseover)="addMapMarkerInfo(individualMarkerOptions, markerRef)"
(positionChanged)="focusMarkers()"
(markerInitialized)="focusMarkers()"
></map-marker>
<map-info-window>{{ infoContent }}</map-info-window>
</google-map>
} @else {
<div class="map-placeholder">
@if (googleMapsLoaded === false) {
<p class="text-danger">Failure loading map</p>
<p class="error-hint">
Please ensure your ad-block is not blocking Google Maps
</p>
} @else if (googleMapsLoaded === null) {
<baw-loading></baw-loading>
} @else if (!hasMarkers) {
<p>No locations specified</p>
}
</div>
}
12 changes: 9 additions & 3 deletions src/app/components/shared/map/map.component.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
.map-placeholder {
border: 1px solid black;
display: flex;
height: 100%;
min-height: 400px;
flex-direction: column;
justify-content: center;
align-items: center;

border: 1px solid black;
height: 100%;
min-height: 400px;
}

.error-hint {
text-align: center;
}
Loading

0 comments on commit d65f6a0

Please sign in to comment.