From 26d9ce745b164d2a577bf34ae6fefd4fde7f2b48 Mon Sep 17 00:00:00 2001 From: PhilippeL Date: Tue, 7 Jul 2020 15:20:18 -0400 Subject: [PATCH 1/8] feat(feature-details): add routing directive to access route from directions tool --- .../feature-details.component.html | 2 +- .../feature-details.component.ts | 11 ++- .../feature-details.directive.ts | 86 +++++++++++++++++++ .../feature-details/feature-details.module.ts | 9 +- .../src/lib/search/shared/sources/icherche.ts | 12 ++- packages/geo/src/locale/en.geo.json | 1 + packages/geo/src/locale/fr.geo.json | 1 + .../search-results-tool.component.html | 4 +- .../search-results-tool.component.ts | 2 + 9 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 packages/geo/src/lib/feature/feature-details/feature-details.directive.ts diff --git a/packages/geo/src/lib/feature/feature-details/feature-details.component.html b/packages/geo/src/lib/feature/feature-details/feature-details.component.html index aa73dd6f30..3c7a5cbbdd 100644 --- a/packages/geo/src/lib/feature/feature-details/feature-details.component.html +++ b/packages/geo/src/lib/feature/feature-details/feature-details.component.html @@ -14,7 +14,7 @@ {{property.key }} - + diff --git a/packages/geo/src/lib/feature/feature-details/feature-details.component.ts b/packages/geo/src/lib/feature/feature-details/feature-details.component.ts index 2db6f40b44..6bd5ff55ea 100644 --- a/packages/geo/src/lib/feature/feature-details/feature-details.component.ts +++ b/packages/geo/src/lib/feature/feature-details/feature-details.component.ts @@ -2,12 +2,14 @@ import { Component, Input, ChangeDetectionStrategy, - ChangeDetectorRef + ChangeDetectorRef, + Output, + EventEmitter } from '@angular/core'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { NetworkService, ConnectionState } from '@igo2/core'; -import { getEntityTitle, getEntityIcon } from '@igo2/common'; +import { getEntityTitle, getEntityIcon, Toolbox } from '@igo2/common'; import { Feature } from '../shared'; import { SearchSource } from '../../search/shared/sources/source'; @@ -34,6 +36,8 @@ export class FeatureDetailsComponent { @Input() map: IgoMap; + @Input() toolbox: Toolbox; + @Input() get feature(): Feature { return this._feature; @@ -46,6 +50,8 @@ export class FeatureDetailsComponent { private _feature: Feature; private _source: SearchSource; + @Output() routeEvent = new EventEmitter(); + /** * @internal */ @@ -139,6 +145,7 @@ export class FeatureDetailsComponent { } } + console.log(feature.properties); return feature.properties; } } diff --git a/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts b/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts new file mode 100644 index 0000000000..b9360786f1 --- /dev/null +++ b/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts @@ -0,0 +1,86 @@ +import { OnInit, OnDestroy, Directive, Self, HostListener, ElementRef, Renderer2 } from '@angular/core'; +import { FeatureDetailsComponent } from './feature-details.component'; + +import olGeolocation from 'ol/Geolocation'; +import * as olProj from 'ol/proj'; + +import { BehaviorSubject } from 'rxjs'; + +import pointOnFeature from '@turf/point-on-feature'; + + +@Directive({ + selector: '[igoFeatureDetailsDirective]' +}) +export class FeatureDetailsDirective implements OnInit { + private component: FeatureDetailsComponent; + public geolocation$ = new BehaviorSubject(undefined); + private geolocation: olGeolocation; + + get map() { + return this.component.map; + } + + get feature() { + return this.component.feature; + } + + @HostListener('routeEvent') + activateRouting() { + console.log('ici') + this.component.toolbox.activateTool('directions'); + } + + constructor( + @Self() component: FeatureDetailsComponent, + private el: ElementRef, + private renderer: Renderer2 + ) { + this.component = component; + } + + ngOnInit() { + this.geolocation = new olGeolocation({ + trackingOptions: { + enableHighAccuracy: true + }, + projection: this.map.projection, + tracking: true + }); + + this.geolocation.on('change', evt => { + this.geolocation$.next(this.geolocation); + }); + + this.geolocation$.subscribe(geolocation => { + if (this.map.geolocation$.getValue().getTracking() === false) { + geolocation.setTracking(false); + } + + if (geolocation.getTracking() === true) { + let userCoord = geolocation.getPosition(); + userCoord = olProj.transform(userCoord, this.map.projection, 'EPSG:4326'); + } + + let destCoord; + if (this.feature.geometry.type === 'Point') { + destCoord = this.feature.geometry.coordinates[0] + ',' + this.feature.geometry.coordinates[1]; + } else { + const point = pointOnFeature(this.feature.geometry); + destCoord = point[0] + ',' + point[1]; + } + console.log(destCoord); + }) + } + + ngAfterViewInit() { + const routeElement = (this.el.nativeElement) + .querySelector('routing'); + + console.log(routeElement); + + this.renderer.listen(routeElement, 'click', () => { + alert('Buton was clicked'); + }); + } +} diff --git a/packages/geo/src/lib/feature/feature-details/feature-details.module.ts b/packages/geo/src/lib/feature/feature-details/feature-details.module.ts index 52e28dd0f7..6e0e26e53e 100644 --- a/packages/geo/src/lib/feature/feature-details/feature-details.module.ts +++ b/packages/geo/src/lib/feature/feature-details/feature-details.module.ts @@ -6,6 +6,7 @@ import { IgoLanguageModule } from '@igo2/core'; import { IgoKeyValueModule } from '@igo2/common'; import { FeatureDetailsComponent } from './feature-details.component'; +import { FeatureDetailsDirective } from './feature-details.directive'; /** * @ignore @@ -17,7 +18,11 @@ import { FeatureDetailsComponent } from './feature-details.component'; IgoLanguageModule, IgoKeyValueModule ], - exports: [FeatureDetailsComponent], - declarations: [FeatureDetailsComponent] + exports: [ + FeatureDetailsComponent, + FeatureDetailsDirective], + declarations: [ + FeatureDetailsComponent, + FeatureDetailsDirective] }) export class IgoFeatureDetailsModule {} diff --git a/packages/geo/src/lib/search/shared/sources/icherche.ts b/packages/geo/src/lib/search/shared/sources/icherche.ts index b5408cee69..5644ee50a5 100644 --- a/packages/geo/src/lib/search/shared/sources/icherche.ts +++ b/packages/geo/src/lib/search/shared/sources/icherche.ts @@ -417,7 +417,7 @@ export class IChercheSearchSource extends SearchSource implements TextSearch { private computeProperties(data: IChercheData): { [key: string]: any } { const properties = ObjectUtils.removeKeys( data.properties, - IChercheSearchSource.propertiesBlacklist + IChercheSearchSource.propertiesBlacklist, ); if (data.geometry === undefined) { @@ -478,10 +478,18 @@ export class IChercheSearchSource extends SearchSource implements TextSearch { ); } + const routing: { + Route: string + } = { + Route: '' + this.languageService.translate.instant('igo.geo.seeRouting') + '' + } + console.log(routing); + return Object.assign( { type: data.index }, properties, - googleLinksProperties + googleLinksProperties, + routing ); } diff --git a/packages/geo/src/locale/en.geo.json b/packages/geo/src/locale/en.geo.json index 391e1636c3..e4705d5c17 100644 --- a/packages/geo/src/locale/en.geo.json +++ b/packages/geo/src/locale/en.geo.json @@ -382,6 +382,7 @@ "targetHtmlUrl": "Open the external link", "searchByCoord": "Search by coordinates", "searchByName": "Search by name", + "seeRouting": "See routing", "timeFilter": { "date": "Date", "endDate": "End Date", diff --git a/packages/geo/src/locale/fr.geo.json b/packages/geo/src/locale/fr.geo.json index b21e4637cc..580c91c806 100644 --- a/packages/geo/src/locale/fr.geo.json +++ b/packages/geo/src/locale/fr.geo.json @@ -382,6 +382,7 @@ "targetHtmlUrl": "Ouvrir le lien externe", "searchByCoord": "Rechercher par coordonnées", "searchByName": "Rechercher par nom", + "seeRouting": "Voir l'itinéraire", "timeFilter": { "date": "Date", "endDate": "Date de fin", diff --git a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.html b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.html index 9e99f84915..63187cc0bf 100644 --- a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.html +++ b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.html @@ -59,7 +59,9 @@

{{ 'igo.integration.searchResultsTool.noResults' | translate }}

+ [feature]="feature$ | async" + [map]="map" + [toolbox]="toolState.toolbox"> diff --git a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts index 6a83ca5f42..7533ea193b 100644 --- a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts +++ b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts @@ -28,6 +28,7 @@ import { import { MapState } from '../../map/map.state'; import { SearchState } from '../search.state'; +import { ToolState } from '../../tool/tool.state'; /** * Tool to browse the search results @@ -106,6 +107,7 @@ export class SearchResultsToolComponent implements OnInit, OnDestroy { private layerService: LayerService, private searchState: SearchState, private elRef: ElementRef, + public toolState: ToolState ) {} ngOnInit() { From 801fde7bee3636cb51b618d700b4403571d7e381 Mon Sep 17 00:00:00 2001 From: PhilippeL Date: Fri, 10 Jul 2020 14:51:02 -0400 Subject: [PATCH 2/8] feat(feature-details): add routing option for feature-details --- .../directions-form.component.ts | 97 ++++++++++++------ .../feature-details.component.scss | 4 + .../feature-details.component.ts | 12 ++- .../feature-details.directive.ts | 99 +++++++++++++------ .../src/lib/search/shared/sources/icherche.ts | 3 +- .../search-results-tool.component.html | 4 +- .../search-results-tool.component.ts | 11 ++- 7 files changed, 161 insertions(+), 69 deletions(-) diff --git a/packages/geo/src/lib/directions/directions-form/directions-form.component.ts b/packages/geo/src/lib/directions/directions-form/directions-form.component.ts index f03a2e0227..be4ffd0006 100644 --- a/packages/geo/src/lib/directions/directions-form/directions-form.component.ts +++ b/packages/geo/src/lib/directions/directions-form/directions-form.component.ts @@ -9,14 +9,8 @@ import { ChangeDetectorRef } from '@angular/core'; import { FormGroup, FormBuilder, Validators, FormArray } from '@angular/forms'; -import { Subscription, Subject } from 'rxjs'; -import { - debounceTime, - distinctUntilChanged, - map, - take, - skipWhile -} from 'rxjs/operators'; +import { Subscription, Subject, BehaviorSubject } from 'rxjs'; +import { debounceTime, distinctUntilChanged, map, take, skipWhile } from 'rxjs/operators'; import olFeature from 'ol/Feature'; import OlGeoJSON from 'ol/format/GeoJSON'; @@ -93,7 +87,17 @@ export class DirectionsFormComponent implements OnInit, OnDestroy { /** * The stops store */ - @Input() stopsStore: FeatureStore; + @Input() + get stopsStore(): FeatureStore { + return this._stopsStore; + } + set stopsStore(value: FeatureStore) { + this._stopsStore = value; + this.stopsStore$.next(value); + } + private _stopsStore: FeatureStore; + + private stopsStore$: BehaviorSubject = new BehaviorSubject(undefined); /** * The route and vertex store @@ -150,6 +154,33 @@ export class DirectionsFormComponent implements OnInit, OnDestroy { ) .subscribe((term: string) => this.handleTermChanged(term)) ); + + this.stopsStore$.subscribe(stopsStore => { + const stops = stopsStore.all(); + console.log(stops); + if (stops.length > 1) { + const coords = []; + for (const feature of stops) { + this.chooseProposal(feature, stops.findIndex(f => f.geometry.coordinates === feature.geometry.coordinates)) + coords.push(feature.geometry.coordinates); + } + const routeResponse = this.directionsService.route(coords, {}); + if (routeResponse) { + routeResponse.map(res => + this.routesQueries$$.push( + res.subscribe(route => { + this.routesResults = route; + this.activeRoute = this.routesResults[0] as Directions; + this.showRouteGeometry(true); + this.changeDetectorRefs.detectChanges(); + }) + ) + ); + } + } else if (stops.length === 1) { + this.chooseProposal(stops[0], 1); + } + }) } ngOnDestroy(): void { @@ -1071,31 +1102,31 @@ export class DirectionsFormComponent implements OnInit, OnDestroy { if (this.search$$) { this.search$$.unsubscribe(); } - const researches = this.searchService.search(term, { - searchType: 'Feature' - }); - researches.map( - res => - (this.search$$ = res.request.subscribe(results => { - results - .filter(r => r.data.geometry) - .forEach(element => { - if ( - searchProposals.filter(r => r.source === element.source) - .length === 0 - ) { - searchProposals.push({ - source: element.source, - meta: element.meta, - results: results.map(r => r.data) - }); - } - }); + const researches = this.searchService.search(term, {searchType: 'Feature'}); + researches.map(res => + this.search$$ = + res.request.subscribe(results => { + results + .filter(r => r.data.geometry) + .forEach(element => { + if ( + searchProposals.filter(r => r.source === element.source) + .length === 0 + ) { + searchProposals.push({ + source: element.source, + meta: element.meta, + results: results.map(r => r.data) + }); + } + }); + if (this.stops) { this.stops .at(this.currentStopIndex) .patchValue({ stopProposals: searchProposals }); - this.changeDetectorRefs.detectChanges(); - })) + } + this.changeDetectorRefs.detectChanges(); + }) ); } } @@ -1157,7 +1188,9 @@ export class DirectionsFormComponent implements OnInit, OnDestroy { } if (geomCoord !== undefined) { - this.stops.at(i).patchValue({ stopCoordinates: geomCoord }); + if (this.stops) { + this.stops.at(i).patchValue({ stopCoordinates: geomCoord }); + } this.addStopOverlay(geomCoord, i); /* const proposalExtent = this.directionsStopsOverlayDataSource.ol .getFeatureById(this.getStopOverlayID(i)) diff --git a/packages/geo/src/lib/feature/feature-details/feature-details.component.scss b/packages/geo/src/lib/feature/feature-details/feature-details.component.scss index f53d8962bd..49a4a56d64 100644 --- a/packages/geo/src/lib/feature/feature-details/feature-details.component.scss +++ b/packages/geo/src/lib/feature/feature-details/feature-details.component.scss @@ -12,6 +12,10 @@ table td { width: 30%; } +table ::ng-deep .routing { + cursor: pointer; +} + iframe { height: calc(100% - 4px); width: 100%; diff --git a/packages/geo/src/lib/feature/feature-details/feature-details.component.ts b/packages/geo/src/lib/feature/feature-details/feature-details.component.ts index 6bd5ff55ea..109a1b4658 100644 --- a/packages/geo/src/lib/feature/feature-details/feature-details.component.ts +++ b/packages/geo/src/lib/feature/feature-details/feature-details.component.ts @@ -15,6 +15,8 @@ import { Feature } from '../shared'; import { SearchSource } from '../../search/shared/sources/source'; import { IgoMap } from '../../map/shared/map'; +import olGeolocation from 'ol/Geolocation'; + @Component({ selector: 'igo-feature-details', templateUrl: './feature-details.component.html', @@ -45,12 +47,14 @@ export class FeatureDetailsComponent { set feature(value: Feature) { this._feature = value; this.cdRef.detectChanges(); + this.selectFeature.emit(); } private _feature: Feature; private _source: SearchSource; @Output() routeEvent = new EventEmitter(); + @Output() selectFeature = new EventEmitter(); /** * @internal @@ -66,6 +70,13 @@ export class FeatureDetailsComponent { return getEntityIcon(this.feature) || 'link'; } + public geolocation: olGeolocation = new olGeolocation({ + trackingOptions: { + enableHighAccuracy: true + }, + tracking: true + }); + constructor( private cdRef: ChangeDetectorRef, private sanitizer: DomSanitizer, @@ -145,7 +156,6 @@ export class FeatureDetailsComponent { } } - console.log(feature.properties); return feature.properties; } } diff --git a/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts b/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts index b9360786f1..180ffc3472 100644 --- a/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts +++ b/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts @@ -1,4 +1,4 @@ -import { OnInit, OnDestroy, Directive, Self, HostListener, ElementRef, Renderer2 } from '@angular/core'; +import { OnInit, Directive, Self, HostListener, ElementRef, Output, EventEmitter } from '@angular/core'; import { FeatureDetailsComponent } from './feature-details.component'; import olGeolocation from 'ol/Geolocation'; @@ -7,15 +7,32 @@ import * as olProj from 'ol/proj'; import { BehaviorSubject } from 'rxjs'; import pointOnFeature from '@turf/point-on-feature'; - +import { Feature, FEATURE } from '../shared'; @Directive({ + // This directive allow to view the route between the user coordinates and the feature selector: '[igoFeatureDetailsDirective]' }) + export class FeatureDetailsDirective implements OnInit { private component: FeatureDetailsComponent; public geolocation$ = new BehaviorSubject(undefined); - private geolocation: olGeolocation; + + public start: Feature = { + meta: { id: 1 }, + type: FEATURE, + geometry: { + type: 'Point', + coordinates: undefined + }, + projection: 'EPSG:4326', + properties: { + id: 1, + name: 'User coordinates', + } + }; + + public end: Feature; get map() { return this.component.map; @@ -24,63 +41,81 @@ export class FeatureDetailsDirective implements OnInit { get feature() { return this.component.feature; } + feature$ = new BehaviorSubject(undefined); - @HostListener('routeEvent') - activateRouting() { - console.log('ici') - this.component.toolbox.activateTool('directions'); + get geolocation() { + return this.component.geolocation; + } + + @Output() routingEvent = new EventEmitter() + + @HostListener('selectFeature') + setFeature() { + this.feature$.next(this.feature); } constructor( @Self() component: FeatureDetailsComponent, - private el: ElementRef, - private renderer: Renderer2 + private el: ElementRef ) { this.component = component; } ngOnInit() { - this.geolocation = new olGeolocation({ - trackingOptions: { - enableHighAccuracy: true - }, - projection: this.map.projection, - tracking: true - }); - this.geolocation.on('change', evt => { this.geolocation$.next(this.geolocation); }); this.geolocation$.subscribe(geolocation => { - if (this.map.geolocation$.getValue().getTracking() === false) { - geolocation.setTracking(false); + console.log(geolocation); + if (!geolocation) { + return; } + geolocation.setProjection(this.map.projection); + if (this.map.geolocation$.getValue() && this.map.geolocation$.getValue().getTracking() === false) { + geolocation.setTracking(false); + } + console.log(geolocation.getTracking()); if (geolocation.getTracking() === true) { let userCoord = geolocation.getPosition(); + console.log(userCoord); userCoord = olProj.transform(userCoord, this.map.projection, 'EPSG:4326'); + console.log(userCoord); + this.start.geometry.coordinates = userCoord; } + }) - let destCoord; + this.feature$.subscribe(() => { if (this.feature.geometry.type === 'Point') { - destCoord = this.feature.geometry.coordinates[0] + ',' + this.feature.geometry.coordinates[1]; + this.end = this.feature; } else { - const point = pointOnFeature(this.feature.geometry); - destCoord = point[0] + ',' + point[1]; + this.end = pointOnFeature(this.feature.geometry); } - console.log(destCoord); + this.bindClicking(); }) } - ngAfterViewInit() { - const routeElement = (this.el.nativeElement) - .querySelector('routing'); - - console.log(routeElement); + bindClicking() { + const routeElement = (this.el.nativeElement).querySelector('span.routing'); + routeElement.addEventListener('click', this.activateRouting.bind(this)); + } - this.renderer.listen(routeElement, 'click', () => { - alert('Buton was clicked'); - }); + activateRouting() { + if (!this.geolocation) { + const geolocation = new olGeolocation({ + trackingOptions: { + enableHighAccuracy: true + }, + projection: this.map.projection, + tracking: true + }); + + geolocation.on('change', evt => { + this.geolocation$.next(geolocation); + }); + } + console.log(this.start, this.end); + this.start.geometry.coordinates ? this.routingEvent.emit([this.start, this.end]) : this.routingEvent.emit([this.end]); } } diff --git a/packages/geo/src/lib/search/shared/sources/icherche.ts b/packages/geo/src/lib/search/shared/sources/icherche.ts index 5644ee50a5..35fc3a9a8b 100644 --- a/packages/geo/src/lib/search/shared/sources/icherche.ts +++ b/packages/geo/src/lib/search/shared/sources/icherche.ts @@ -481,9 +481,8 @@ export class IChercheSearchSource extends SearchSource implements TextSearch { const routing: { Route: string } = { - Route: '' + this.languageService.translate.instant('igo.geo.seeRouting') + '' + Route: '' + this.languageService.translate.instant('igo.geo.seeRouting') + '' } - console.log(routing); return Object.assign( { type: data.index }, diff --git a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.html b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.html index 63187cc0bf..9f8b18fd6b 100644 --- a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.html +++ b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.html @@ -59,9 +59,11 @@

{{ 'igo.integration.searchResultsTool.noResults' | translate }}

+ [toolbox]="toolState.toolbox" + (routingEvent)="getRoute($event)"> diff --git a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts index 7533ea193b..bf50da801b 100644 --- a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts +++ b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts @@ -29,6 +29,7 @@ import { MapState } from '../../map/map.state'; import { SearchState } from '../search.state'; import { ToolState } from '../../tool/tool.state'; +import { DirectionState } from '../../directions/directions.state'; /** * Tool to browse the search results @@ -107,7 +108,8 @@ export class SearchResultsToolComponent implements OnInit, OnDestroy { private layerService: LayerService, private searchState: SearchState, private elRef: ElementRef, - public toolState: ToolState + public toolState: ToolState, + private directionState: DirectionState ) {} ngOnInit() { @@ -298,4 +300,11 @@ export class SearchResultsToolComponent implements OnInit, OnDestroy { const elemBottom = elemTop + elem.clientHeight + padding; return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); } + + getRoute(features: Feature[]) { + this.toolState.toolbox.activateTool('directions'); + this.directionState.stopsStore.clear(); + this.directionState.routeStore.clear(); + this.directionState.stopsStore.insertMany(features); + } } From faaed4c54727886e6c360756c0d1ebdd130274a1 Mon Sep 17 00:00:00 2001 From: PhilippeL Date: Wed, 22 Jul 2020 09:46:28 -0400 Subject: [PATCH 3/8] WIP --- .../directions-form.component.ts | 139 ++++++++++++------ .../feature-details.component.ts | 8 - .../feature-details.directive.ts | 35 ++--- .../directions-tool.component.html | 8 +- .../directions-tool.component.ts | 5 + .../src/lib/directions/directions.state.ts | 8 +- .../search-results-tool.component.ts | 2 +- 7 files changed, 123 insertions(+), 82 deletions(-) diff --git a/packages/geo/src/lib/directions/directions-form/directions-form.component.ts b/packages/geo/src/lib/directions/directions-form/directions-form.component.ts index be4ffd0006..5bd33a8c89 100644 --- a/packages/geo/src/lib/directions/directions-form/directions-form.component.ts +++ b/packages/geo/src/lib/directions/directions-form/directions-form.component.ts @@ -10,7 +10,7 @@ import { } from '@angular/core'; import { FormGroup, FormBuilder, Validators, FormArray } from '@angular/forms'; import { Subscription, Subject, BehaviorSubject } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, take, skipWhile } from 'rxjs/operators'; +import { debounceTime, distinctUntilChanged, map, take, skipWhile, startWith } from 'rxjs/operators'; import olFeature from 'ol/Feature'; import OlGeoJSON from 'ol/format/GeoJSON'; @@ -41,7 +41,7 @@ import { } from '../../feature/shared/feature.utils'; import { tryAddLoadingStrategy } from '../../feature/shared/strategies.utils'; -import { Directions, DirectionsOptions } from '../shared/directions.interface'; +import { Directions, DirectionsOptions, Stop } from '../shared/directions.interface'; import { DirectionsService } from '../shared/directions.service'; import { DirectionsFormService } from './directions-form.service'; @@ -87,17 +87,75 @@ export class DirectionsFormComponent implements OnInit, OnDestroy { /** * The stops store */ + @Input() stopsStore: FeatureStore + @Input() - get stopsStore(): FeatureStore { - return this._stopsStore; - } - set stopsStore(value: FeatureStore) { - this._stopsStore = value; - this.stopsStore$.next(value); + get routeFromFeatureDetail(): boolean { + return this._routeFromFeatureDetail; } - private _stopsStore: FeatureStore; + set routeFromFeatureDetail(value: boolean) { + this._routeFromFeatureDetail = value; + + if (value === true) { + this.ngOnInit(); + + setTimeout(() => { + this.routesResults = undefined; + + const nbStops = this.stops.length; + for (let i = 0; i < nbStops; i++) { + this.stops.removeAt(0); + } + this.stops.insert(0, this.createStop('start')); + this.stops.insert(1, this.createStop('end')); + + this.routeStore.clear(); + for (const feature of this.stopsStore.all()) { + if (feature.properties.id && feature.properties.id.toString().startsWith('directionsStop')) { + this.stopsStore.delete(feature); + } + } + + console.log(this.stops); + console.log('if true', this.stopsStore.all()); + if (this.stopsStore.all().length === 2) { + let i = 0; + const coordinates = []; + + for (const feature of this.stopsStore.all()) { + let directionsText; + i === 0 ? directionsText = 'start' : directionsText = 'end'; + coordinates.push(feature.geometry.coordinates); + this.handleLocationProposals(feature.geometry.coordinates, i); + this.addStopOverlay(feature.geometry.coordinates, i); + i++; + } + this.writeStopsToFormService(coordinates); + + const routeResponse = this.directionsService.route(coordinates, {}); + if (routeResponse) { + routeResponse.map(res => + this.routesQueries$$.push( + res.subscribe(route => { + this.routesResults = route; + this.activeRoute = this.routesResults[0] as Directions; + this.showRouteGeometry(true); + this.changeDetectorRefs.detectChanges(); + }) + ) + ); + } - private stopsStore$: BehaviorSubject = new BehaviorSubject(undefined); + } else if (this.stopsStore.all().length === 1) { + this.handleLocationProposals(this.stopsStore.all()[0].geometry.coordinates, 1); + this.addStopOverlay(this.stopsStore.all()[0].geometry.coordinates, 1); + this.writeStopsToFormService(this.stopsStore.all()[0].geometry.coordinates); + } + }, 1); + this.routeFromFeatureDetail = false; + } + } + private _routeFromFeatureDetail: boolean; /** * The route and vertex store @@ -154,33 +212,6 @@ export class DirectionsFormComponent implements OnInit, OnDestroy { ) .subscribe((term: string) => this.handleTermChanged(term)) ); - - this.stopsStore$.subscribe(stopsStore => { - const stops = stopsStore.all(); - console.log(stops); - if (stops.length > 1) { - const coords = []; - for (const feature of stops) { - this.chooseProposal(feature, stops.findIndex(f => f.geometry.coordinates === feature.geometry.coordinates)) - coords.push(feature.geometry.coordinates); - } - const routeResponse = this.directionsService.route(coords, {}); - if (routeResponse) { - routeResponse.map(res => - this.routesQueries$$.push( - res.subscribe(route => { - this.routesResults = route; - this.activeRoute = this.routesResults[0] as Directions; - this.showRouteGeometry(true); - this.changeDetectorRefs.detectChanges(); - }) - ) - ); - } - } else if (stops.length === 1) { - this.chooseProposal(stops[0], 1); - } - }) } ngOnDestroy(): void { @@ -507,14 +538,18 @@ export class DirectionsFormComponent implements OnInit, OnDestroy { return this.stopsForm.get('stops') as FormArray; } - public writeStopsToFormService() { - const stops = []; - this.stops.value.forEach(stop => { - if (stop.stopCoordinates instanceof Array) { - stops.push(stop); - } - }); - this.directionsFormService.setStops(stops); + public writeStopsToFormService(stopsArray?) { + if (stopsArray) { + this.directionsFormService.setStops(stopsArray); + } else { + const stops = []; + this.stops.value.forEach(stop => { + if (stop.stopCoordinates instanceof Array) { + stops.push(stop); + } + }); + this.directionsFormService.setStops(stops); + } } addStop(): void { @@ -531,6 +566,16 @@ export class DirectionsFormComponent implements OnInit, OnDestroy { }); } + createStopFromFeature(feature: Feature, directionsText?: string): Stop { + const stop: Stop = ({ + stopPoint: feature.properties.nom, + stopProposals: [], + directionsText: directionsText, + stopCoordinates: feature.geometry.coordinates + }); + return stop; + } + removeStop(index: number): void { const id = this.getStopOverlayID(index); this.deleteStoreFeatureByID(this.stopsStore, id); @@ -1188,9 +1233,7 @@ export class DirectionsFormComponent implements OnInit, OnDestroy { } if (geomCoord !== undefined) { - if (this.stops) { - this.stops.at(i).patchValue({ stopCoordinates: geomCoord }); - } + this.stops.at(i).patchValue({ stopCoordinates: geomCoord }); this.addStopOverlay(geomCoord, i); /* const proposalExtent = this.directionsStopsOverlayDataSource.ol .getFeatureById(this.getStopOverlayID(i)) diff --git a/packages/geo/src/lib/feature/feature-details/feature-details.component.ts b/packages/geo/src/lib/feature/feature-details/feature-details.component.ts index 109a1b4658..e50481a2f0 100644 --- a/packages/geo/src/lib/feature/feature-details/feature-details.component.ts +++ b/packages/geo/src/lib/feature/feature-details/feature-details.component.ts @@ -70,13 +70,6 @@ export class FeatureDetailsComponent { return getEntityIcon(this.feature) || 'link'; } - public geolocation: olGeolocation = new olGeolocation({ - trackingOptions: { - enableHighAccuracy: true - }, - tracking: true - }); - constructor( private cdRef: ChangeDetectorRef, private sanitizer: DomSanitizer, @@ -155,7 +148,6 @@ export class FeatureDetailsComponent { }); } } - return feature.properties; } } diff --git a/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts b/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts index 180ffc3472..bc6158ad6d 100644 --- a/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts +++ b/packages/geo/src/lib/feature/feature-details/feature-details.directive.ts @@ -44,7 +44,15 @@ export class FeatureDetailsDirective implements OnInit { feature$ = new BehaviorSubject(undefined); get geolocation() { - return this.component.geolocation; + return this.component.map.geolocation$.getValue(); + } + set geolocation(value) { + if (value) { + this.geolocation = value; + this.geolocation.on('change', evt => { + this.geolocation$.next(this.geolocation); + }); + } } @Output() routingEvent = new EventEmitter() @@ -62,12 +70,7 @@ export class FeatureDetailsDirective implements OnInit { } ngOnInit() { - this.geolocation.on('change', evt => { - this.geolocation$.next(this.geolocation); - }); - this.geolocation$.subscribe(geolocation => { - console.log(geolocation); if (!geolocation) { return; } @@ -75,13 +78,12 @@ export class FeatureDetailsDirective implements OnInit { if (this.map.geolocation$.getValue() && this.map.geolocation$.getValue().getTracking() === false) { geolocation.setTracking(false); + this.start = undefined; } - console.log(geolocation.getTracking()); + if (geolocation.getTracking() === true) { let userCoord = geolocation.getPosition(); - console.log(userCoord); userCoord = olProj.transform(userCoord, this.map.projection, 'EPSG:4326'); - console.log(userCoord); this.start.geometry.coordinates = userCoord; } }) @@ -92,6 +94,7 @@ export class FeatureDetailsDirective implements OnInit { } else { this.end = pointOnFeature(this.feature.geometry); } + this.geolocation$.next(this.geolocation); this.bindClicking(); }) } @@ -102,20 +105,6 @@ export class FeatureDetailsDirective implements OnInit { } activateRouting() { - if (!this.geolocation) { - const geolocation = new olGeolocation({ - trackingOptions: { - enableHighAccuracy: true - }, - projection: this.map.projection, - tracking: true - }); - - geolocation.on('change', evt => { - this.geolocation$.next(geolocation); - }); - } - console.log(this.start, this.end); this.start.geometry.coordinates ? this.routingEvent.emit([this.start, this.end]) : this.routingEvent.emit([this.end]); } } diff --git a/packages/integration/src/lib/directions/directions-tool/directions-tool.component.html b/packages/integration/src/lib/directions/directions-tool/directions-tool.component.html index 081a236ad8..ace098cd41 100644 --- a/packages/integration/src/lib/directions/directions-tool/directions-tool.component.html +++ b/packages/integration/src/lib/directions/directions-tool/directions-tool.component.html @@ -1 +1,7 @@ - + + diff --git a/packages/integration/src/lib/directions/directions-tool/directions-tool.component.ts b/packages/integration/src/lib/directions/directions-tool/directions-tool.component.ts index 7102d37a62..d3f27bbad5 100644 --- a/packages/integration/src/lib/directions/directions-tool/directions-tool.component.ts +++ b/packages/integration/src/lib/directions/directions-tool/directions-tool.component.ts @@ -34,6 +34,11 @@ export class DirectionsToolComponent { */ get map(): IgoMap { return this.mapState.map; } + + get routeFromFeatureDetail() { + return this.directionState.routeFromFeatureDetail; + } + constructor( private directionState: DirectionState, private mapState: MapState diff --git a/packages/integration/src/lib/directions/directions.state.ts b/packages/integration/src/lib/directions/directions.state.ts index 91d988d288..d98287f102 100644 --- a/packages/integration/src/lib/directions/directions.state.ts +++ b/packages/integration/src/lib/directions/directions.state.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, EventEmitter, Output } from '@angular/core'; import { FeatureStore } from '@igo2/geo'; import { MapState } from '../map/map.state'; @@ -25,6 +25,12 @@ export class DirectionState { map: this.mapState.map }); + public routeFromFeatureDetail = false; + constructor(private mapState: MapState) {} + setRouteFromFeatureDetail(value: boolean) { + this.routeFromFeatureDetail = value; + } + } diff --git a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts index bf50da801b..5f9b58c675 100644 --- a/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts +++ b/packages/integration/src/lib/search/search-results-tool/search-results-tool.component.ts @@ -304,7 +304,7 @@ export class SearchResultsToolComponent implements OnInit, OnDestroy { getRoute(features: Feature[]) { this.toolState.toolbox.activateTool('directions'); this.directionState.stopsStore.clear(); - this.directionState.routeStore.clear(); this.directionState.stopsStore.insertMany(features); + this.directionState.setRouteFromFeatureDetail(true); } } From 0dfb17c1dd2c71c2ff2ae2372b607d19ffdefcd1 Mon Sep 17 00:00:00 2001 From: PhilippeL Date: Thu, 6 Aug 2020 09:53:14 -0400 Subject: [PATCH 4/8] WIP --- .../directions-form.component.html | 2 +- .../directions-form.component.ts | 138 ++++++++++-------- .../feature-details.directive.ts | 9 +- packages/geo/src/public_api.ts | 1 + .../search-results-tool.component.ts | 1 + 5 files changed, 84 insertions(+), 67 deletions(-) diff --git a/packages/geo/src/lib/directions/directions-form/directions-form.component.html b/packages/geo/src/lib/directions/directions-form/directions-form.component.html index acc2235860..713d59a5c8 100644 --- a/packages/geo/src/lib/directions/directions-form/directions-form.component.html +++ b/packages/geo/src/lib/directions/directions-form/directions-form.component.html @@ -64,7 +64,7 @@