diff --git a/CHANGELOG.md b/CHANGELOG.md index da9b169..03f023c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index f4a1b71..a76b3da 100644 --- a/README.md +++ b/README.md @@ -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: @@ -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) => { @@ -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!** 🎉 @@ -223,6 +223,8 @@ selectedLocation: InitialLocationModel = { [prioritizeLayers]="prioritizeLayer" [showClearInputButton]="showClearInputButton" [sortBy]="sortBy" + [onlyAntwerp]="onlyAntwerp" + [countryCodes]="countryCodes" [coordinateErrorNotification]="coordinateErrorNotification" [locateMeNotAllowedNotification]="locateMeNotAllowedNotification" [locateMeNotSupportedNotification]="locateMeNotSupportedNotification" @@ -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 */ diff --git a/api-store.png b/api-store.png deleted file mode 100644 index b9d394f..0000000 Binary files a/api-store.png and /dev/null differ diff --git a/desktop-view.png b/desktop-view.png index 3f4e3ed..4c01700 100644 Binary files a/desktop-view.png and b/desktop-view.png differ diff --git a/marketplace.png b/marketplace.png new file mode 100644 index 0000000..8412b7d Binary files /dev/null and b/marketplace.png differ diff --git a/projects/ngx-location-picker/src/lib/components/ngx-location-picker.component.ts b/projects/ngx-location-picker/src/lib/components/ngx-location-picker.component.ts index 795c0e2..28e2023 100644 --- a/projects/ngx-location-picker/src/lib/components/ngx-location-picker.component.ts +++ b/projects/ngx-location-picker/src/lib/components/ngx-location-picker.component.ts @@ -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 */ @@ -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 diff --git a/projects/ngx-location-picker/src/lib/services/ngx-location-picker.helper.ts b/projects/ngx-location-picker/src/lib/services/ngx-location-picker.helper.ts index 5adb27e..d1f39f8 100644 --- a/projects/ngx-location-picker/src/lib/services/ngx-location-picker.helper.ts +++ b/projects/ngx-location-picker/src/lib/services/ngx-location-picker.helper.ts @@ -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 = (query && query.trim().length > 0) ? query.split(' ') : null; diff --git a/projects/ngx-location-picker/src/lib/services/ngx-location-picker.service.ts b/projects/ngx-location-picker/src/lib/services/ngx-location-picker.service.ts index eb63431..083b298 100644 --- a/projects/ngx-location-picker/src/lib/services/ngx-location-picker.service.ts +++ b/projects/ngx-location-picker/src/lib/services/ngx-location-picker.service.ts @@ -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' @@ -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); @@ -82,10 +86,12 @@ 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); @@ -93,16 +99,14 @@ export class NgxLocationPickerService { } /** - * 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 */ - getMapLayers(query: LayerQueryModel): Observable { - const parameters = this.locationPickerHelper.toHttpParams(query); - - return this.httpClient.get(`${this.locationPickerApi}/layers`, { params: parameters }); + getLayers(): Observable { + return this.httpClient + .get>(`${this.locationPickerApi}/layers`) + .pipe(map((pagedResult: PagedResult<'layers', string>) => pagedResult._embedded.layers)); } /** @@ -115,7 +119,9 @@ export class NgxLocationPickerService { private searchLocations(query: LocationQueryModel): Observable { const parameters = this.locationPickerHelper.toHttpParams(query); - return this.httpClient.get(`${this.locationPickerApi}/locations`, { params: parameters }); + return this.httpClient + .get>(`${this.locationPickerApi}/locations`, { params: parameters }) + .pipe(map((pagedResult: PagedResult<'locations', LocationModel>) => pagedResult._embedded.locations)); } /** @@ -128,7 +134,9 @@ export class NgxLocationPickerService { private searchAddresses(query: AddressQueryModel): Observable { const parameters = this.locationPickerHelper.toHttpParams(query); - return this.httpClient.get(`${this.locationPickerApi}/addresses`, { params: parameters }); + return this.httpClient + .get>(`${this.locationPickerApi}/addresses`, { params: parameters }) + .pipe(map((pagedResult: PagedResult<'addresses', AddressModel>) => pagedResult._embedded.addresses)); } /** @@ -152,12 +160,11 @@ export class NgxLocationPickerService { * @return Observable */ private searchLocationsByCoordinates( - query: CoordinateQueryModel, - cascadingCoordinateRules: Array + query: CoordinateQueryModel ): Observable { - const parameters = this.locationPickerHelper.toHttpParams(query); - - return this.httpClient.post(`${this.locationPickerApi}/coordinates`, - cascadingCoordinateRules, { params: parameters }); + return this.httpClient + .post(`${this.locationPickerApi}/coordinates/search`, + query) + .pipe(map((result: CoordinateSearchResponse) => result.results)); } } diff --git a/projects/ngx-location-picker/src/lib/types/address-query.model.ts b/projects/ngx-location-picker/src/lib/types/address-query.model.ts index a701c7c..03f2ba7 100644 --- a/projects/ngx-location-picker/src/lib/types/address-query.model.ts +++ b/projects/ngx-location-picker/src/lib/types/address-query.model.ts @@ -2,4 +2,6 @@ export interface AddressQueryModel { streetname: string; streetids: number[]; housenumber: string; + onlyAntwerp: boolean; + countries: string[]; } diff --git a/projects/ngx-location-picker/src/lib/types/coordinate-query.model.ts b/projects/ngx-location-picker/src/lib/types/coordinate-query.model.ts index bb35441..7e99b11 100644 --- a/projects/ngx-location-picker/src/lib/types/coordinate-query.model.ts +++ b/projects/ngx-location-picker/src/lib/types/coordinate-query.model.ts @@ -1,6 +1,9 @@ +import { CascadingCoordinateRulesModel } from './cascading-rules.model'; + export interface CoordinateQueryModel { xcoord: number; ycoord: number; returnsingle?: boolean; totalresults?: number; + cascadingRules: Array } diff --git a/projects/ngx-location-picker/src/lib/types/coordinate.model.ts b/projects/ngx-location-picker/src/lib/types/coordinate.model.ts index d196e62..176f727 100644 --- a/projects/ngx-location-picker/src/lib/types/coordinate.model.ts +++ b/projects/ngx-location-picker/src/lib/types/coordinate.model.ts @@ -16,3 +16,7 @@ export interface CoordinateModel { */ actualLocation?: LatLngModel; } + +export interface CoordinateSearchResponse { + results: Array; +} diff --git a/projects/ngx-location-picker/src/lib/types/delegate-search.model.ts b/projects/ngx-location-picker/src/lib/types/delegate-search.model.ts index 78828dc..02ba479 100644 --- a/projects/ngx-location-picker/src/lib/types/delegate-search.model.ts +++ b/projects/ngx-location-picker/src/lib/types/delegate-search.model.ts @@ -16,4 +16,6 @@ export interface DelegateSearchModel { selectedLocation: LocationModel | AddressModel | CoordinateModel; locationKeywords: string[]; searchStreetNameForAddress: boolean; + onlyAntwerp: boolean; + countryCodes: string[]; } diff --git a/projects/ngx-location-picker/src/lib/types/layer-query.model.ts b/projects/ngx-location-picker/src/lib/types/layer-query.model.ts deleted file mode 100644 index 60688fd..0000000 --- a/projects/ngx-location-picker/src/lib/types/layer-query.model.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface LayerQueryModel { - mapservice?: string; -} diff --git a/projects/ngx-location-picker/src/lib/types/layer.model.ts b/projects/ngx-location-picker/src/lib/types/layer.model.ts deleted file mode 100644 index 72e93d9..0000000 --- a/projects/ngx-location-picker/src/lib/types/layer.model.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface LayerModel { - id: number; - name: string; -} diff --git a/projects/ngx-location-picker/src/lib/types/location-query.model.ts b/projects/ngx-location-picker/src/lib/types/location-query.model.ts index 9d876c3..d0ad13d 100644 --- a/projects/ngx-location-picker/src/lib/types/location-query.model.ts +++ b/projects/ngx-location-picker/src/lib/types/location-query.model.ts @@ -2,6 +2,8 @@ export interface LocationQueryModel { search: string; sort: string; prioritizelayer: Array; - limit: number; + pagesize: number; layers: Array; + onlyAntwerp: boolean; + countries: Array; } diff --git a/projects/ngx-location-picker/src/lib/types/pagedresult.model.ts b/projects/ngx-location-picker/src/lib/types/pagedresult.model.ts new file mode 100644 index 0000000..bbfd475 --- /dev/null +++ b/projects/ngx-location-picker/src/lib/types/pagedresult.model.ts @@ -0,0 +1,29 @@ +export interface Page { + number: number; + size: number; + totalElements: number; + totalPages: number; +} + +type Resource = { + [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 { + _links?: Links; + _embedded: Resource; + _page: Page; +} \ No newline at end of file