Skip to content

Commit e8085d0

Browse files
committed
[GLAM-610] Refactoring of the open street map component in order to include the logic for retrieving the coordinates
1 parent d1d3a22 commit e8085d0

5 files changed

Lines changed: 143 additions & 107 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
<div *ngIf="(place | async )">
1+
<div *ngIf="coordinates">
22
<ds-open-street-map
3-
[coordinates]="(coordinates$ | async)"
4-
[pointers]="(pointers$ | async)"
3+
[coordinates]="coordinates"
54
[showControlsZoom]="true"
5+
[showDisplayName]="true"
66
></ds-open-street-map>
7-
<div class="my-1 text-muted">{{ displayName$ | async }}</div>
87
</div>
98

10-
<div *ngIf="(invalidLocationErrorCode | async) as errorCode" class="text-danger">{{ 'location.error.' + errorCode | translate }}</div>
9+
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
import { Component, Inject, OnInit } from '@angular/core';
22

3+
import { TranslateService } from '@ngx-translate/core';
4+
35
import { FieldRenderingType, MetadataBoxFieldRendering } from '../metadata-box.decorator';
46
import { RenderingTypeValueModelComponent } from '../rendering-type-value.model';
5-
import {
6-
LocationCoordinates, LocationErrorCodes,
7-
LocationPlace,
8-
LocationService,
9-
} from '../../../../../../../core/services/location.service';
10-
import { BehaviorSubject, Observable } from 'rxjs';
117
import { LayoutField } from '../../../../../../../core/layout/models/box.model';
128
import { Item } from '../../../../../../../core/shared/item.model';
139
import { MetadataValue } from '../../../../../../../core/shared/metadata.models';
14-
import { TranslateService } from '@ngx-translate/core';
15-
import { map } from 'rxjs/operators';
16-
import { OpenStreetMapPointer } from '../../../../../../../shared/open-street-map/open-street-map.component';
1710

1811
@Component({
1912
selector: 'ds-open-street-map-rendering',
@@ -23,13 +16,10 @@ import { OpenStreetMapPointer } from '../../../../../../../shared/open-street-ma
2316
@MetadataBoxFieldRendering(FieldRenderingType.OSMAP)
2417
export class OpenStreetMapRenderingComponent extends RenderingTypeValueModelComponent implements OnInit {
2518

26-
place = new BehaviorSubject<LocationPlace>(undefined);
27-
28-
coordinates$: Observable<LocationCoordinates>;
29-
pointers$: Observable<OpenStreetMapPointer[]>;
30-
displayName$: Observable<string>;
31-
32-
invalidLocationErrorCode: BehaviorSubject<string> = new BehaviorSubject(undefined);
19+
/**
20+
* The coordinates retrieved from the metadata, this may contain a pair or coordinate, a POI, or an address
21+
*/
22+
coordinates: string;
3323

3424
constructor(
3525
@Inject('fieldProvider') public fieldProvider: LayoutField,
@@ -38,85 +28,12 @@ export class OpenStreetMapRenderingComponent extends RenderingTypeValueModelComp
3828
@Inject('renderingSubTypeProvider') public renderingSubTypeProvider: string,
3929
@Inject('tabNameProvider') public tabNameProvider: string,
4030
protected translateService: TranslateService,
41-
private locationService: LocationService,
4231
) {
4332
super(fieldProvider, itemProvider, metadataValueProvider, tabNameProvider, renderingSubTypeProvider, translateService);
4433
}
4534

4635
ngOnInit(): void {
47-
48-
this.coordinates$ = this.place.asObservable().pipe(
49-
map((place) => place.coordinates),
50-
);
51-
52-
this.pointers$ = this.place.asObservable().pipe(
53-
map((place) => {
54-
const pointer: OpenStreetMapPointer = {
55-
coordinates: place.coordinates,
56-
color: 'green',
57-
};
58-
return [pointer];
59-
}),
60-
);
61-
62-
this.displayName$ = this.place.asObservable().pipe(
63-
map((place) => place.displayName),
64-
);
65-
66-
const position = this.metadataValue.value; // this may contain a pair or coordinate, a POI, or an address
67-
68-
if (this.locationService.isCoordinateString(position)) {
69-
70-
// Validate the coordinates, then retrieve the location name
71-
72-
if (this.locationService.isValidCoordinateString(position)) {
73-
const coordinates = this.locationService.parseCoordinates(position);
74-
this.locationService.searchCoordinates(coordinates).subscribe({
75-
next: (displayName) => {
76-
const place: LocationPlace = {
77-
coordinates: coordinates,
78-
displayName: displayName, // Show the name retrieved from Nominatim
79-
};
80-
this.place.next(place);
81-
},
82-
error: (err) => {
83-
// show the map centered on provided coordinates despite the possibility to retrieve a description for the place
84-
const place: LocationPlace = {
85-
coordinates: coordinates,
86-
};
87-
this.place.next(place);
88-
if (err.message === LocationErrorCodes.API_ERROR) {
89-
console.error(err.message);
90-
} else {
91-
console.warn(err.message);
92-
}
93-
},
94-
});
95-
} else {
96-
console.error(`Invalid coordinates: "${position}"`);
97-
this.invalidLocationErrorCode.next(LocationErrorCodes.INVALID_COORDINATES);
98-
}
99-
100-
} else {
101-
102-
// Retrieve the coordinates for the provided POI or address
103-
104-
this.locationService.searchPlace(position).subscribe({
105-
next: (place) => {
106-
place.displayName = position; // Show the name stored in metadata (comment out to show name retrieved from Nominatim)
107-
this.place.next(place);
108-
},
109-
error: (err) => {
110-
this.invalidLocationErrorCode.next(err.message); // either LOCATION_NOT_FOUND or API_ERROR
111-
if (err.message === LocationErrorCodes.API_ERROR) {
112-
console.error(err.message);
113-
} else {
114-
console.warn(err.message);
115-
}
116-
},
117-
});
118-
}
119-
36+
this.coordinates = this.metadataValue.value;
12037
}
12138

12239
}

src/app/shared/open-street-map/open-street-map.component.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
<div id="osm-wrapper" *ngIf="coordinates">
1+
<div id="osm-wrapper" *ngIf="(coordinates$ | async) !== null">
22
<aol-map [logo]="true" [width]="width" [height]="height">
33
<aol-interaction-default></aol-interaction-default>
44
<aol-view [zoom]="zoom">
5-
<aol-coordinate [x]="coordinates.longitude" [y]="coordinates.latitude" [srid]="SRID"></aol-coordinate>
5+
<aol-coordinate [x]="(coordinates$ | async)?.longitude" [y]="(coordinates$ | async)?.latitude" [srid]="SRID"></aol-coordinate>
66
</aol-view>
77
<aol-layer-tile>
88
<aol-source-osm></aol-source-osm>
99
</aol-layer-tile>
1010
<aol-layer-vector>
1111
<aol-source-vector>
12-
<aol-feature *ngFor="let pointer of pointers">
12+
<aol-feature *ngFor="let pointer of (pointers$ | async)">
1313
<aol-geometry-point>
1414
<aol-coordinate [x]="pointer.coordinates.longitude" [y]="pointer.coordinates.latitude" [srid]="SRID"></aol-coordinate>
1515
</aol-geometry-point>
@@ -45,3 +45,5 @@
4545
</aol-control>
4646
</aol-map>
4747
</div>
48+
<div *ngIf="showDisplayName" class="my-1 text-muted">{{ displayName$ | async }}</div>
49+
<div *ngIf="(invalidLocationErrorCode | async) as errorCode" class="text-danger">{{ 'location.error.' + errorCode | translate }}</div>

src/app/shared/open-street-map/open-street-map.component.ts

Lines changed: 125 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1-
import { Component, Input } from '@angular/core';
2-
import { LocationCoordinates } from '../../core/services/location.service';
1+
import { Component, Input, OnInit } from '@angular/core';
2+
import {
3+
LocationCoordinates,
4+
LocationErrorCodes,
5+
LocationPlace,
6+
LocationService
7+
} from '../../core/services/location.service';
8+
import { filter, map } from 'rxjs/operators';
9+
import { BehaviorSubject, Observable } from 'rxjs';
10+
import { TranslateService } from '@ngx-translate/core';
11+
import { isNotEmpty } from '../empty.util';
312

413
export interface OpenStreetMapPointer {
514
coordinates: LocationCoordinates,
@@ -11,7 +20,7 @@ export interface OpenStreetMapPointer {
1120
templateUrl: './open-street-map.component.html',
1221
styleUrls: ['./open-street-map.component.scss'],
1322
})
14-
export class OpenStreetMapComponent {
23+
export class OpenStreetMapComponent implements OnInit {
1524

1625
// Spacial reference identifier
1726
SRID = 'EPSG:4326'; // World Geodetic System 1984
@@ -31,12 +40,7 @@ export class OpenStreetMapComponent {
3140
/**
3241
* The map coordinates
3342
*/
34-
@Input() coordinates: LocationCoordinates;
35-
36-
/**
37-
* The pointers to be shown on the map
38-
*/
39-
@Input() pointers: OpenStreetMapPointer[];
43+
@Input() coordinates: string;
4044

4145
/**
4246
* The name of the location
@@ -53,6 +57,118 @@ export class OpenStreetMapComponent {
5357
*/
5458
@Input() showControlsZoom = true;
5559

60+
/**
61+
* The name of the location
62+
*/
63+
@Input() showDisplayName = false;
64+
65+
/**
66+
* The coordinates of the place once retrieved by the location service
67+
*/
68+
coordinates$: Observable<LocationCoordinates>;
69+
70+
/**
71+
* The name of the address to display
72+
*/
73+
displayName$: Observable<string>;
74+
75+
/**
76+
* Contains error codes from the location service
77+
*/
78+
invalidLocationErrorCode: BehaviorSubject<string> = new BehaviorSubject(undefined);
79+
80+
/**
81+
* The place to be shown in the map
82+
*/
83+
place = new BehaviorSubject<LocationPlace>(undefined);
84+
85+
/**
86+
* The pointers to be shown on the map
87+
*/
88+
pointers$: Observable<OpenStreetMapPointer[]>;
89+
90+
constructor(
91+
protected translateService: TranslateService,
92+
private locationService: LocationService) {
93+
}
94+
95+
ngOnInit(): void {
96+
97+
this.coordinates$ = this.place.asObservable().pipe(
98+
filter((place) => isNotEmpty(place)),
99+
map((place) => place.coordinates),
100+
);
101+
102+
this.pointers$ = this.place.asObservable().pipe(
103+
filter((place) => isNotEmpty(place)),
104+
map((place) => {
105+
const pointer: OpenStreetMapPointer = {
106+
coordinates: place.coordinates,
107+
color: 'green',
108+
};
109+
return [pointer];
110+
}),
111+
);
112+
113+
this.displayName$ = this.place.asObservable().pipe(
114+
filter((place) => isNotEmpty(place)),
115+
map((place) => place.displayName),
116+
);
117+
118+
if (this.locationService.isCoordinateString(this.coordinates)) {
119+
120+
// Validate the coordinates, then retrieve the location name
121+
122+
if (this.locationService.isValidCoordinateString(this.coordinates)) {
123+
const coordinates = this.locationService.parseCoordinates(this.coordinates);
124+
this.locationService.searchCoordinates(coordinates).subscribe({
125+
next: (displayName) => {
126+
const place: LocationPlace = {
127+
coordinates: coordinates,
128+
displayName: displayName, // Show the name retrieved from Nominatim
129+
};
130+
this.place.next(place);
131+
},
132+
error: (err) => {
133+
// show the map centered on provided coordinates despite the possibility to retrieve a description for the place
134+
const place: LocationPlace = {
135+
coordinates: coordinates,
136+
};
137+
this.place.next(place);
138+
if (err.message === LocationErrorCodes.API_ERROR) {
139+
console.error(err.message);
140+
} else {
141+
console.warn(err.message);
142+
}
143+
},
144+
});
145+
} else {
146+
console.error(`Invalid coordinates: "${this.coordinates}"`);
147+
this.invalidLocationErrorCode.next(LocationErrorCodes.INVALID_COORDINATES);
148+
}
149+
150+
} else {
151+
152+
// Retrieve the coordinates for the provided POI or address
153+
154+
this.locationService.searchPlace(this.coordinates).subscribe({
155+
next: (place) => {
156+
place.displayName = this.coordinates; // Show the name stored in metadata (comment out to show name retrieved from Nominatim)
157+
this.place.next(place);
158+
},
159+
error: (err) => {
160+
this.invalidLocationErrorCode.next(err.message); // either LOCATION_NOT_FOUND or API_ERROR
161+
if (err.message === LocationErrorCodes.API_ERROR) {
162+
console.error(err.message);
163+
} else {
164+
console.warn(err.message);
165+
}
166+
},
167+
});
168+
}
169+
170+
}
171+
56172
increaseZoom() {
57173
this.zoom++;
58174
}

src/app/shared/open-street-map/open-street-map.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { NgModule } from '@angular/core';
2+
import { CommonModule } from '@angular/common';
23

34
import { SharedModule } from '../shared.module';
45
import { OpenStreetMapComponent } from './open-street-map.component';
@@ -10,6 +11,7 @@ const COMPONENTS = [
1011

1112
@NgModule({
1213
imports: [
14+
CommonModule,
1315
SharedModule,
1416
AngularOpenlayersModule,
1517
],

0 commit comments

Comments
 (0)