Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Changed
- [BREAKING] Use of Location Picker API V3

## [5.5.0] - 2022-10-10

### Added
Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ The BFF should function solely as a pass-through layer where the API KEY gets ad

> We're using axios for handling requests in the example below. Feel free to use any other library.

Step 1: Create a contract with the "LOCATIONPICKER" on the api-store.
![screenshot](api-store.png)
Step 1: Create a contract with the "LOCATIONPICKER" on the marketplace.
![screenshot](marketplace.png)

Step 2: Copy the api key and api url

Step 3: In your BFF create a .env file and add:
```
API_KEY=00000000-0000-0000-0000-000000000000
LOCATION_PICKER_URL=https://api-gw-o.antwerpen.be/gis/locationpicker/v1
LOCATION_PICKER_URL=https://api-gw-o.antwerpen.be/gis/locationpicker/v3
```

Step 4: Create a new file **locations.routes.js** in **/routes** and add the following contents:
Expand Down Expand Up @@ -94,7 +94,7 @@ const locationModel = require('../models/location.model');
* @param res {Response}
*/
exports.proxyLocationRequest = (req, res) => {
const requestPath = req.originalUrl.replace('/api/v1/locations', '');
const requestPath = req.originalUrl.replace('/api/v3/locations', '');

locationModel.handleLocationRequest(requestPath)
.then((response) => {
Expand Down Expand Up @@ -140,7 +140,7 @@ Step 7: Add your newly created route to **app.js**
const locationProxy = require('./routes/location.routes');

// Add this after const app = express(); and before any error handler routes
app.use('/api/v1/locations', locationProxy);
app.use('/api/v3/locations', locationProxy);
```

**That's it!** 🎉
Expand Down Expand Up @@ -223,6 +223,8 @@ selectedLocation: InitialLocationModel = {
[prioritizeLayers]="prioritizeLayer"
[showClearInputButton]="showClearInputButton"
[sortBy]="sortBy"
[onlyAntwerp]="onlyAntwerp"
[countryCodes]="countryCodes"
[coordinateErrorNotification]="coordinateErrorNotification"
[locateMeNotAllowedNotification]="locateMeNotAllowedNotification"
[locateMeNotSupportedNotification]="locateMeNotSupportedNotification"
Expand Down Expand Up @@ -325,6 +327,10 @@ class ExampleComponent {
@Input() prioritizeLayers = ['straatnaam'];
/* Sort locations by certain key. */
@Input() sortBy = '';
/* Search locations and addresses inside Antwerp otherwise will search in provided countries ==> countryCodes */
@Input() onlyAntwerp = true;
/* Search locations and addresses in provided country codes if 'onlyAntwerp' is false*/
@Input() countryCodes = ['be','nl','lu'];
/* Use geolocation when the component finished loading */
@Input() locateUserOnInit = false;
/* Set time to wait after user stops typing before triggering a search */
Expand Down
Binary file removed api-store.png
Binary file not shown.
Binary file modified desktop-view.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added marketplace.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ export class NgxLocationPickerComponent implements OnInit, OnDestroy, ControlVal
@Input() prioritizeLayers = ['straatnaam'];
/* Sort locations by certain key. */
@Input() sortBy = '';
/* Search locations and addresses inside Antwerp otherwise will search in provided countries ==> countryCodes */
@Input() onlyAntwerp = true;
/* Search locations and addresses in provided country codes if 'onlyAntwerp' is false*/
@Input() countryCodes = ['be','nl','lu'];
/* Use geolocation when the component finished loading */
@Input() locateUserOnInit = false;
/* Set time to wait after user stops typing before triggering a search */
Expand Down Expand Up @@ -509,8 +513,10 @@ export class NgxLocationPickerComponent implements OnInit, OnDestroy, ControlVal
cascadingCoordinateRules: this.cascadingCoordinateRules,
selectedLocation: this.previousLocation,
locationKeywords: this.locationKeywords,
searchStreetNameForAddress: this.searchStreetNameForAddress
};
searchStreetNameForAddress: this.searchStreetNameForAddress,
onlyAntwerp: this.onlyAntwerp,
countryCodes: this.countryCodes
}

this.locationServiceSubscription = this.locationPickerService.delegateSearch(
delegateSearch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,13 @@ export class NgxLocationPickerHelper {
*
* @return streetAndNumber
*/
buildAddressQuery(query: string, selectedLocation: LocationModel | AddressModel | CoordinateModel): AddressQueryModel {
buildAddressQuery(query: string, selectedLocation: LocationModel | AddressModel | CoordinateModel, onlyAntwerp: boolean, countryCodes: string[]): AddressQueryModel {
const streetAndNumber: AddressQueryModel = {
streetname: '',
streetids: [],
housenumber: ''
housenumber: '',
onlyAntwerp: onlyAntwerp,
countries: countryCodes
};

const addressParts: Array<string> = (query && query.trim().length > 0) ? query.split(' ') : null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { NgxLocationPickerHelper } from './ngx-location-picker.helper';
import { LambertModel, LocationModel } from '../types/location.model';
import { AddressQueryModel } from '../types/address-query.model';
import { LocationQueryModel } from '../types/location-query.model';
import { LayerQueryModel } from '../types/layer-query.model';
import { LayerModel } from '../types/layer.model';
import { AddressIdQueryModel } from '../types/address-id-query.model';
import { CoordinateQueryModel } from '../types/coordinate-query.model';
import { AddressModel } from '../types/address.model';
import { CoordinateModel } from '../types/coordinate.model';
import { CascadingCoordinateRulesModel } from '../types/cascading-rules.model';
import { CoordinateModel, CoordinateSearchResponse } from '../types/coordinate.model';
import { DelegateSearchModel } from '../types/delegate-search.model';
import { PagedResult } from '../types/pagedresult.model'

@Injectable({
providedIn: 'root'
Expand Down Expand Up @@ -57,22 +56,27 @@ export class NgxLocationPickerService {
xcoord: coordinate.x,
ycoord: coordinate.y,
returnsingle: delegateSearch.cascadingCoordinateReturnSingle,
totalresults: delegateSearch.cascadingCoordinateLimit
totalresults: delegateSearch.cascadingCoordinateLimit,
cascadingRules: delegateSearch.cascadingCoordinateRules
};

return this.searchLocationsByCoordinates(requestQuery, delegateSearch.cascadingCoordinateRules);
return this.searchLocationsByCoordinates(requestQuery);
} else if (this.locationPickerHelper.isAddress(delegateSearch.search, delegateSearch.locationKeywords)) {
const addressQuery: AddressQueryModel = this.locationPickerHelper.buildAddressQuery(
delegateSearch.search,
delegateSearch.selectedLocation
delegateSearch.selectedLocation,
delegateSearch.onlyAntwerp,
delegateSearch.countryCodes
);
if (delegateSearch.searchStreetNameForAddress) {
const locationQuery: LocationQueryModel = {
layers: ['straatnaam'],
limit: delegateSearch.limit,
pagesize: delegateSearch.limit,
search: addressQuery.streetname,
prioritizelayer: delegateSearch.prioritizelayer,
sort: delegateSearch.sort
sort: delegateSearch.sort,
onlyAntwerp: delegateSearch.onlyAntwerp,
countries: delegateSearch.countryCodes
};

return this.searchLocations(locationQuery);
Expand All @@ -82,27 +86,27 @@ export class NgxLocationPickerService {
} else {
const locationQuery: LocationQueryModel = {
layers: delegateSearch.layers,
limit: delegateSearch.limit,
pagesize: delegateSearch.limit,
search: delegateSearch.search,
prioritizelayer: delegateSearch.prioritizelayer,
sort: delegateSearch.sort
sort: delegateSearch.sort,
onlyAntwerp: delegateSearch.onlyAntwerp,
countries: delegateSearch.countryCodes
};

return this.searchLocations(locationQuery);
}
}

/**
* Returns a list of layers based on the provided map service.
*
* @param query (the map service to load layers from)
* Returns a list of layers present in elastic.
*
* @return Observable<LayerModel[]>
*/
getMapLayers(query: LayerQueryModel): Observable<LayerModel[]> {
const parameters = this.locationPickerHelper.toHttpParams(query);

return this.httpClient.get<LayerModel[]>(`${this.locationPickerApi}/layers`, { params: parameters });
getLayers(): Observable<string[]> {
return this.httpClient
.get<PagedResult<'layers', string>>(`${this.locationPickerApi}/layers`)
.pipe(map((pagedResult: PagedResult<'layers', string>) => pagedResult._embedded.layers));
}

/**
Expand All @@ -115,7 +119,9 @@ export class NgxLocationPickerService {
private searchLocations(query: LocationQueryModel): Observable<LocationModel[]> {
const parameters = this.locationPickerHelper.toHttpParams(query);

return this.httpClient.get<LocationModel[]>(`${this.locationPickerApi}/locations`, { params: parameters });
return this.httpClient
.get<PagedResult<'locations', LocationModel>>(`${this.locationPickerApi}/locations`, { params: parameters })
.pipe(map((pagedResult: PagedResult<'locations', LocationModel>) => pagedResult._embedded.locations));
}

/**
Expand All @@ -128,7 +134,9 @@ export class NgxLocationPickerService {
private searchAddresses(query: AddressQueryModel): Observable<AddressModel[]> {
const parameters = this.locationPickerHelper.toHttpParams(query);

return this.httpClient.get<AddressModel[]>(`${this.locationPickerApi}/addresses`, { params: parameters });
return this.httpClient
.get<PagedResult<'addresses', AddressModel>>(`${this.locationPickerApi}/addresses`, { params: parameters })
.pipe(map((pagedResult: PagedResult<'addresses', AddressModel>) => pagedResult._embedded.addresses));
}

/**
Expand All @@ -152,12 +160,11 @@ export class NgxLocationPickerService {
* @return Observable<CoordinateModel[]>
*/
private searchLocationsByCoordinates(
query: CoordinateQueryModel,
cascadingCoordinateRules: Array<CascadingCoordinateRulesModel>
query: CoordinateQueryModel
): Observable<CoordinateModel[]> {
const parameters = this.locationPickerHelper.toHttpParams(query);

return this.httpClient.post<CoordinateModel[]>(`${this.locationPickerApi}/coordinates`,
cascadingCoordinateRules, { params: parameters });
return this.httpClient
.post<CoordinateSearchResponse>(`${this.locationPickerApi}/coordinates/search`,
query)
.pipe(map((result: CoordinateSearchResponse) => result.results));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ export interface AddressQueryModel {
streetname: string;
streetids: number[];
housenumber: string;
onlyAntwerp: boolean;
countries: string[];
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { CascadingCoordinateRulesModel } from './cascading-rules.model';

export interface CoordinateQueryModel {
xcoord: number;
ycoord: number;
returnsingle?: boolean;
totalresults?: number;
cascadingRules: Array<CascadingCoordinateRulesModel>
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ export interface CoordinateModel {
*/
actualLocation?: LatLngModel;
}

export interface CoordinateSearchResponse {
results: Array<CoordinateModel>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ export interface DelegateSearchModel {
selectedLocation: LocationModel | AddressModel | CoordinateModel;
locationKeywords: string[];
searchStreetNameForAddress: boolean;
onlyAntwerp: boolean;
countryCodes: string[];
}

This file was deleted.

4 changes: 0 additions & 4 deletions projects/ngx-location-picker/src/lib/types/layer.model.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export interface LocationQueryModel {
search: string;
sort: string;
prioritizelayer: Array<string>;
limit: number;
pagesize: number;
layers: Array<string>;
onlyAntwerp: boolean;
countries: Array<string>;
}
29 changes: 29 additions & 0 deletions projects/ngx-location-picker/src/lib/types/pagedresult.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export interface Page {
number: number;
size: number;
totalElements: number;
totalPages: number;
}

type Resource<T, PropertyName extends string> = {
[P in PropertyName]: T[];
}

interface Links {
first: Link;
prev: Link;
self: Link;
next: Link;
last: Link;
}

interface Link {
href: string;
}

// export expose the interface for other components
export interface PagedResult<PropertyName extends string, T = any> {
_links?: Links;
_embedded: Resource<T, PropertyName>;
_page: Page;
}