From f4ba89920cf50ba4ab229f5678e5e06a5160eabe Mon Sep 17 00:00:00 2001 From: Willem Dantuma Date: Fri, 4 Feb 2022 16:21:26 +0100 Subject: [PATCH] AW-3096 Zoeken op locatie (geocoding) mogelijk maken --- .../map-search/map-search.component.html | 2 +- .../map-search/map-search.component.ts | 65 +++++++++++++------ .../fm-map/components/map/map.component.html | 2 +- .../fm-map/components/map/map.component.ts | 17 ++++- .../src/fm/services/typeahead.service.ts | 4 ++ 5 files changed, 66 insertions(+), 24 deletions(-) diff --git a/projects/common-map/src/fm-map/components/map-search/map-search.component.html b/projects/common-map/src/fm-map/components/map-search/map-search.component.html index c78dc6b..e853376 100644 --- a/projects/common-map/src/fm-map/components/map-search/map-search.component.html +++ b/projects/common-map/src/fm-map/components/map-search/map-search.component.html @@ -1,5 +1,5 @@ - + diff --git a/projects/common-map/src/fm-map/components/map-search/map-search.component.ts b/projects/common-map/src/fm-map/components/map-search/map-search.component.ts index 5cd587b..4222aff 100644 --- a/projects/common-map/src/fm-map/components/map-search/map-search.component.ts +++ b/projects/common-map/src/fm-map/components/map-search/map-search.component.ts @@ -1,6 +1,6 @@ import { Component, Input, Output, OnInit, EventEmitter, SimpleChanges, OnChanges, ViewChild } from '@angular/core'; -import { Observable , of } from 'rxjs'; -import { debounceTime,distinctUntilChanged,tap,switchMap,merge,catchError} from 'rxjs/operators'; +import { Observable , of,merge,forkJoin } from 'rxjs'; +import { debounceTime,distinctUntilChanged,tap,switchMap,catchError,map} from 'rxjs/operators'; import { TypeaheadService, TimespanService } from '@farmmaps/common'; import { IQueryState } from '@farmmaps/common'; import { IPeriodState } from '../../models/period.state'; @@ -26,7 +26,8 @@ export class MapSearchComponent { this.periodLocal = tassign(this.periodLocal,{startDate: period.startDate,endDate:period.endDate}); this.startEndCaption = this.timespanService.getCaption(period.startDate, period.endDate, 4) } - @Output() onSearch = new EventEmitter(); + @Output() onSearch = new EventEmitter() + @Output() onCitySearch = new EventEmitter() @Output() onClear = new EventEmitter(); @Output() onSearchCollapse = new EventEmitter(); @Output() onSearchExpand = new EventEmitter(); @@ -69,20 +70,27 @@ export class MapSearchComponent { this.filterOptionsLocal = { query: "", tags: "", startDate: null, endDate: null, bboxFilter: false, itemType: null, itemCode:null,level:0,parentCode:null,bbox:[] }; } - search = (text$: Observable) => + search = (text$: Observable) => text$.pipe( debounceTime(300), distinctUntilChanged(), - tap(() => this.searching = true), - switchMap(term => term.length < 1 ? of([]) : - this.typeaheadService.getSearchTypeaheadItems(term).pipe( - tap(() => this.searchFailed = false), + tap(() => {this.searching = true;this.searchFailed=false;}), + switchMap(term => term.length < 1 ? of([]) : + forkJoin( + this.typeaheadService.getTagTypeaheadItems(term).pipe( catchError(() => { this.searchFailed = true; return of([]); - })) ), + }),map( (sa:string[]) => sa.map((s,i) => ({"name":s,"type":"tag"})))), + this.typeaheadService.getCityTypeaheadItems(term).pipe( + catchError(() => { + this.searchFailed = true; + return of([]); + }),map( (sa:string[]) => sa.map((s,i) => ({"name":s,"type":"city"})))), + ).pipe(map(([a1,a2]) => [...a1, ...a2] ),map(a => a.sort((a, b) => (a.name.toUpperCase() > b.name.toUpperCase()) ? 1 : -1))) + ), tap(() => this.searching = false), - merge(this.hideSearchingWhenUnsubscribed)); + ); formatter = (x: { name: string }) => x.name; @@ -109,18 +117,23 @@ export class MapSearchComponent { } handleSelect(event) { - event.preventDefault(); - this.filterOptionsLocal.query = null; - this.filterOptionsLocal.itemType = null; - this.filterOptionsLocal.itemCode = null; - this.filterOptionsLocal.parentCode = null; - this.filterOptionsLocal.tags = event.item.name; - if (this.dateFilter) { - this.filterOptionsLocal.startDate = this.periodLocal.startDate; - this.filterOptionsLocal.endDate = this.periodLocal.endDate; + if(event.item.type == "tag") { + event.preventDefault(); + this.filterOptionsLocal.query = null; + this.filterOptionsLocal.itemType = null; + this.filterOptionsLocal.itemCode = null; + this.filterOptionsLocal.parentCode = null; + this.filterOptionsLocal.tags = event.item.name; + if (this.dateFilter) { + this.filterOptionsLocal.startDate = this.periodLocal.startDate; + this.filterOptionsLocal.endDate = this.periodLocal.endDate; + } + this.onSearch.emit(this.filterOptionsLocal); + this.searchTextLocal = { name: this.filterOptionsLocal.tags }; + } else if (event.item.type == "city") { + this.clearEnabled = true; + this.onCitySearch.emit(event.item.name); } - this.onSearch.emit(this.filterOptionsLocal); - this.searchTextLocal = { name: this.filterOptionsLocal.tags }; } handleSelectPeriod(event: { startDate: Date, endDate: Date }) { @@ -177,5 +190,15 @@ export class MapSearchComponent { handleClearClick(event) { this.onClear.emit({}); } + + getIcon(type):string { + if(type == "tag") + return "fal fa-tag"; + else if(type == "city") + return "fal fa-map-marker-alt"; + else if(type == "search") + return "fal fa-search"; + + } } diff --git a/projects/common-map/src/fm-map/components/map/map.component.html b/projects/common-map/src/fm-map/components/map/map.component.html index 79c1542..5bbde45 100644 --- a/projects/common-map/src/fm-map/components/map/map.component.html +++ b/projects/common-map/src/fm-map/components/map/map.component.html @@ -50,7 +50,7 @@
- +
diff --git a/projects/common-map/src/fm-map/components/map/map.component.ts b/projects/common-map/src/fm-map/components/map/map.component.ts index a8f32d6..4d2d66a 100644 --- a/projects/common-map/src/fm-map/components/map/map.component.ts +++ b/projects/common-map/src/fm-map/components/map/map.component.ts @@ -21,6 +21,7 @@ import {IStyles} from '../../models/style.cache'; import { IDroppedFile } from '../aol/file-drop-target/file-drop-target.component'; import { StateSerializerService } from '@farmmaps/common'; import { GeolocationService} from '../../services/geolocation.service'; +import { GeolocatorService } from '@farmmaps/common'; import {DeviceOrientationService} from '../../services/device-orientation.service'; // AppCommon @@ -30,7 +31,7 @@ import {commonReducers} from '@farmmaps/common'; import {commonActions} from '@farmmaps/common'; import {Feature} from 'ol'; -import {Geometry} from 'ol/geom'; +import {Geometry,Point,Circle} from 'ol/geom'; import {Extent,createEmpty,extend } from 'ol/extent'; import {transform} from 'ol/proj'; import { tassign } from 'tassign'; @@ -101,6 +102,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { public itemTypeService: ItemTypeService, private location: Location, private geolocationService: GeolocationService, + private geolocaterService: GeolocatorService, private zone: NgZone, private deviceorientationService:DeviceOrientationService, public devicesService:DeviceService) { @@ -452,6 +454,19 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { this.store.dispatch(new mapActions.SetPeriod(period)); } + handleCitySearch(location:string) { + this.geolocaterService.geocode(location).subscribe(locations => { + if( locations.length > 0) { + let point = new Point([locations[0].coordinates.lon,locations[0].coordinates.lat]); + point.transform('EPSG:4326', 'EPSG:3857'); + let circle = new Circle(point.getCoordinates(),5000);// + let extent = createEmpty(); + extend(extent, circle.getExtent()); + this.store.dispatch(new mapActions.SetExtent(extent)) + } + }); + } + ngOnDestroy() { if (this.paramSub) this.paramSub.unsubscribe(); if (this.itemTypeSub) this.itemTypeSub.unsubscribe(); diff --git a/projects/common/src/fm/services/typeahead.service.ts b/projects/common/src/fm/services/typeahead.service.ts index a4e7495..3829aec 100644 --- a/projects/common/src/fm/services/typeahead.service.ts +++ b/projects/common/src/fm/services/typeahead.service.ts @@ -22,4 +22,8 @@ export class TypeaheadService { getTagTypeaheadItems(searchText: string, skip: number = 0, take: number = 10): Observable { return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/typeahead/tag/?q=${searchText}&skip=${skip}&take=${take}`); } + + getCityTypeaheadItems(searchText: string, skip: number = 0, take: number = 10): Observable { + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/typeahead/city/?q=${searchText}&skip=${skip}&take=${take}`); + } }