From 1b6bd0b4e880c3aecc83cf459ea180c0c06c0e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petro=CC=81=20Tama=CC=81s?= Date: Fri, 13 Apr 2018 15:44:14 +0200 Subject: [PATCH] fix: optimize observable subscribtions --- .../hike-edit-pois-external.component.ts | 38 ++++++++----- .../hike-edit-pois-gtrack.component.ts | 53 ++++++++++++------- .../hike-edit-pois-hike.component.ts | 43 ++++++++------- .../hike-edit-route-planner.component.ts | 40 +++++++++----- .../hike-edit-gtrack-poi-info.component.ts | 1 - .../pages/hike-edit/hike-edit.component.ts | 53 +++++++++++++------ .../pages/hike-list/hike-list.component.ts | 18 +++++-- .../shared/services/poi/poi-editor.service.ts | 2 +- src/app/store/effects/hike-edit.ts | 19 +++++-- 9 files changed, 177 insertions(+), 90 deletions(-) diff --git a/src/app/pages/hike-edit/components/hike-edit-pois-external/hike-edit-pois-external.component.ts b/src/app/pages/hike-edit/components/hike-edit-pois-external/hike-edit-pois-external.component.ts index 0ab292cd..0faddeec 100644 --- a/src/app/pages/hike-edit/components/hike-edit-pois-external/hike-edit-pois-external.component.ts +++ b/src/app/pages/hike-edit/components/hike-edit-pois-external/hike-edit-pois-external.component.ts @@ -45,8 +45,8 @@ export class HikeEditPoisExternalComponent implements OnInit, OnDestroy { ngOnInit() { this._store .select(this._hikeEditMapSelectors.getMapId) - .takeUntil(this._destroy$) .filter(id => id !== '') + .takeUntil(this._destroy$) .subscribe((mapId: string) => { this._map = this._adminMapService.getMapById(mapId); }); @@ -55,12 +55,13 @@ export class HikeEditPoisExternalComponent implements OnInit, OnDestroy { this.pois$ = this._getSubdomainSelector(this.poiType.subdomain); // Route info from the store (for disabling GET buttons) - this.routeInfoData$ = this._store.select(this._hikeEditRoutePlannerSelectors.getRoutePlanner); + this.routeInfoData$ = this._store + .select(this._hikeEditRoutePlannerSelectors.getRoutePlanner) + .takeUntil(this._destroy$); // Update poi properties after poi list loaded this._store .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector(this.poiType.subdomain, 'loaded')) - .takeUntil(this._destroy$) .filter(loaded => !!loaded) .switchMap(() => Observable.combineLatest( this._getSubdomainSelector(this.poiType.subdomain).take(1), @@ -72,6 +73,7 @@ export class HikeEditPoisExternalComponent implements OnInit, OnDestroy { }) .switchMap((pois: IExternalPoi[]) => this._poiEditorService.assignOnOffRoutePois(pois)) .switchMap((pois: IExternalPoi[]) => this._poiEditorService.handleElevation(pois)) + .takeUntil(this._destroy$) .subscribe((pois) => { // Refresh poi list on the store this._updateSubdomainPois(pois); @@ -88,12 +90,12 @@ export class HikeEditPoisExternalComponent implements OnInit, OnDestroy { // Update inGtrackDb properties after common poi list has been refreshed this._store .select(this._poiSelectors.getAllPois) - .takeUntil(this._destroy$) .filter((gTrackPois: IGTrackPoi[]) => gTrackPois.length > 0) + .takeUntil(this._destroy$) .subscribe((gTrackPois: IGTrackPoi[]) => { this._getSubdomainSelector(this.poiType.subdomain) - .take(1) .filter((externalPois: IExternalPoi[]) => externalPois.length > 0) + .take(1) .subscribe((externalPois: IExternalPoi[]) => { // TODO Refresh commonPoiList after poi save this._setSubdomainPoisInGtrackDb(this._poiEditorService.handleGTrackPois(externalPois, gTrackPois)); @@ -105,24 +107,32 @@ export class HikeEditPoisExternalComponent implements OnInit, OnDestroy { // this.loading$ = this._store - .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector(this.poiType.subdomain, 'loading')); + .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector(this.poiType.subdomain, 'loading')) + .takeUntil(this._destroy$); this.showOnrouteMarkers$ = this._store - .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector(this.poiType.subdomain, 'showOnrouteMarkers')); + .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector(this.poiType.subdomain, 'showOnrouteMarkers')) + .takeUntil(this._destroy$); this.showOffrouteMarkers$ = this._store - .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector(this.poiType.subdomain, 'showOffrouteMarkers')); + .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector(this.poiType.subdomain, 'showOffrouteMarkers')) + .takeUntil(this._destroy$); // // Refresh markers // - this.showOnrouteMarkers$.takeUntil(this._destroy$).subscribe(() => { - this._poiEditorService.refreshPoiMarkers(this._map); - }); - this.showOffrouteMarkers$.takeUntil(this._destroy$).subscribe(() => { - this._poiEditorService.refreshPoiMarkers(this._map); - }); + this.showOnrouteMarkers$ + .takeUntil(this._destroy$) + .subscribe(() => { + this._poiEditorService.refreshPoiMarkers(this._map); + }); + + this.showOffrouteMarkers$ + .takeUntil(this._destroy$) + .subscribe(() => { + this._poiEditorService.refreshPoiMarkers(this._map); + }); } ngOnDestroy() { diff --git a/src/app/pages/hike-edit/components/hike-edit-pois-gtrack/hike-edit-pois-gtrack.component.ts b/src/app/pages/hike-edit/components/hike-edit-pois-gtrack/hike-edit-pois-gtrack.component.ts index 4eb3484e..2ea0cf46 100644 --- a/src/app/pages/hike-edit/components/hike-edit-pois-gtrack/hike-edit-pois-gtrack.component.ts +++ b/src/app/pages/hike-edit/components/hike-edit-pois-gtrack/hike-edit-pois-gtrack.component.ts @@ -58,17 +58,21 @@ export class HikeEditPoisGTrackComponent implements OnInit, OnDestroy { // Get pois by id from geoSearch result Observable .combineLatest( - this._store.select(this._geoSearchSelectors.getGeoSearch('gTrackPois')), - this._store.select(this._poiSelectors.getPoiIds) + this._store + .select(this._geoSearchSelectors.getGeoSearch('gTrackPois')) + .takeUntil(this._destroy$), + this._store + .select(this._poiSelectors.getPoiIds) + .takeUntil(this._destroy$) ) .takeUntil(this._destroy$) .subscribe(([searchData, inStorePoiIds]: [IGeoSearchResponseItem, string[]]) => { if (searchData) { - const poiIds = _.difference((searchData).results, _.intersection((searchData).results, inStorePoiIds)) + const missingPoiIds = _.difference((searchData).results, _.intersection((searchData).results, inStorePoiIds)) // Get only the not-loaded pois - if (poiIds && poiIds.length > 0) { - this._store.dispatch(new commonPoiActions.LoadPois(poiIds)); + if (missingPoiIds && missingPoiIds.length > 0) { + this._store.dispatch(new commonPoiActions.LoadPois(missingPoiIds)); } } }); @@ -77,14 +81,18 @@ export class HikeEditPoisGTrackComponent implements OnInit, OnDestroy { // dirty flag will change on add/remove gTrackPoi to/from the hike this.pois$ = Observable .combineLatest( - this._store.select(this._geoSearchSelectors.getGeoSearchResults<(IPoi)>('gTrackPois', this._poiSelectors.getAllPois)), - this._store.select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('gTrack', 'dirty')) + this._store + .select(this._geoSearchSelectors.getGeoSearchResults<(IPoi)>('gTrackPois', this._poiSelectors.getAllPois)) + .takeUntil(this._destroy$), + this._store + .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('gTrack', 'dirty')) + .takeUntil(this._destroy$) ) .debounceTime(150) - .takeUntil(this._destroy$) .filter(([pois, dirty]: [IGTrackPoi[], boolean]) => typeof pois !== 'undefined') .switchMap(([pois, dirty]: [IGTrackPoi[], boolean]) => this._store .select(this._hikeEditRoutePlannerSelectors.getPath) + .takeUntil(this._destroy$) .switchMap((path: any) => { return Observable.of([this._poiEditorService.organizePois(_.cloneDeep(pois), path), dirty]) }) @@ -98,7 +106,8 @@ export class HikeEditPoisGTrackComponent implements OnInit, OnDestroy { } return Observable.of(this._poiEditorService.handleHikeInclusion(pois)); - }); + }) + .takeUntil(this._destroy$); this.pois$ .debounceTime(150) @@ -116,24 +125,32 @@ export class HikeEditPoisGTrackComponent implements OnInit, OnDestroy { // this.searchContext$ = this._store - .select(this._geoSearchSelectors.getGeoSearchContext('gTrackPois')); + .select(this._geoSearchSelectors.getGeoSearchContext('gTrackPois')) + .takeUntil(this._destroy$); this.showOnrouteMarkers$ = this._store - .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('gTrack', 'showOnrouteMarkers')); + .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('gTrack', 'showOnrouteMarkers')) + .takeUntil(this._destroy$); this.showOffrouteMarkers$ = this._store - .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('gTrack', 'showOffrouteMarkers')); + .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('gTrack', 'showOffrouteMarkers')) + .takeUntil(this._destroy$); // // Refresh markers // - this.showOnrouteMarkers$.takeUntil(this._destroy$).subscribe(() => { - this._poiEditorService.refreshPoiMarkers(this._map); - }); - this.showOffrouteMarkers$.takeUntil(this._destroy$).subscribe(() => { - this._poiEditorService.refreshPoiMarkers(this._map); - }); + this.showOnrouteMarkers$ + .takeUntil(this._destroy$) + .subscribe(() => { + this._poiEditorService.refreshPoiMarkers(this._map); + }); + + this.showOffrouteMarkers$ + .takeUntil(this._destroy$) + .subscribe(() => { + this._poiEditorService.refreshPoiMarkers(this._map); + }); } ngOnDestroy() { diff --git a/src/app/pages/hike-edit/components/hike-edit-pois-hike/hike-edit-pois-hike.component.ts b/src/app/pages/hike-edit/components/hike-edit-pois-hike/hike-edit-pois-hike.component.ts index afbe8ccd..8824b2d8 100644 --- a/src/app/pages/hike-edit/components/hike-edit-pois-hike/hike-edit-pois-hike.component.ts +++ b/src/app/pages/hike-edit/components/hike-edit-pois-hike/hike-edit-pois-hike.component.ts @@ -35,7 +35,6 @@ export class HikeEditPoisHikeComponent implements OnInit, OnDestroy { private _store: Store, private _adminMapService: AdminMapService, private _poiEditorService: PoiEditorService, - private _hikeEditMapSelectors: HikeEditMapSelectors, private _hikeEditPoiSelectors: HikeEditPoiSelectors, private _hikeEditGeneralInfoSelectors: HikeEditGeneralInfoSelectors, @@ -48,8 +47,8 @@ export class HikeEditPoisHikeComponent implements OnInit, OnDestroy { ngOnInit() { this._store .select(this._hikeEditMapSelectors.getMapId) - .takeUntil(this._destroy$) .filter(id => id !== '') + .takeUntil(this._destroy$) .subscribe((mapId: string) => { this._map = this._adminMapService.getMapById(mapId); }); @@ -57,37 +56,38 @@ export class HikeEditPoisHikeComponent implements OnInit, OnDestroy { // Get pois by id Observable .combineLatest( - this._store.select(this._hikeEditGeneralInfoSelectors.getPois), - this._store.select(this._poiSelectors.getPoiIds) + this._store.select(this._hikeEditGeneralInfoSelectors.getPois).takeUntil(this._destroy$), + this._store.select(this._poiSelectors.getPoiIds).takeUntil(this._destroy$) ) .debounceTime(150) .takeUntil(this._destroy$) .subscribe(([inHikePoiIds, inStorePoiIds]: [string[], string[]]) => { - const poiIds = _.difference(inHikePoiIds, _.intersection(inHikePoiIds, inStorePoiIds)) + const missingPoiIds = _.difference(inHikePoiIds, _.intersection(inHikePoiIds, inStorePoiIds)) // Get only the not-loaded pois - if (poiIds && poiIds.length > 0) { - this._store.dispatch(new commonPoiActions.LoadPois(poiIds)); + if (missingPoiIds && missingPoiIds.length > 0) { + this._store.dispatch(new commonPoiActions.LoadPois(missingPoiIds)); } }); // Poi list this.pois$ = this._store .select(this._hikeEditGeneralInfoSelectors.getHikePois<(IPoi)>(this._poiSelectors.getAllPois)) - .takeUntil(this._destroy$) .filter((pois: IPoi[]) => typeof pois !== 'undefined') + .takeUntil(this._destroy$) .switchMap((pois: IPoi[]) => { return this._store .select(this._hikeEditRoutePlannerSelectors.getPath) - .take(1) + .filter((path: any) => path && path.geometry.coordinates.length > 0) + .takeUntil(this._destroy$) .map((path: any) => { return this._poiEditorService.organizePois(_.cloneDeep(pois), path); }); }); this.pois$ - .takeUntil(this._destroy$) .debounceTime(150) + .takeUntil(this._destroy$) .subscribe((pois: Poi[]) => { // Refresh markers this._poiEditorService.refreshPoiMarkers(this._map); @@ -98,21 +98,28 @@ export class HikeEditPoisHikeComponent implements OnInit, OnDestroy { // this.showOnrouteMarkers$ = this._store - .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('hike', 'showOnrouteMarkers')); + .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('hike', 'showOnrouteMarkers')) + .takeUntil(this._destroy$); this.showOffrouteMarkers$ = this._store - .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('hike', 'showOffrouteMarkers')); + .select(this._hikeEditPoiSelectors.getHikeEditPoiContextPropertySelector('hike', 'showOffrouteMarkers')) + .takeUntil(this._destroy$); // // Refresh markers // - this.showOnrouteMarkers$.takeUntil(this._destroy$).subscribe(() => { - this._poiEditorService.refreshPoiMarkers(this._map); - }); - this.showOffrouteMarkers$.takeUntil(this._destroy$).subscribe(() => { - this._poiEditorService.refreshPoiMarkers(this._map); - }); + this.showOnrouteMarkers$ + .takeUntil(this._destroy$) + .subscribe(() => { + this._poiEditorService.refreshPoiMarkers(this._map); + }); + + this.showOffrouteMarkers$ + .takeUntil(this._destroy$) + .subscribe(() => { + this._poiEditorService.refreshPoiMarkers(this._map); + }); } ngOnDestroy() { diff --git a/src/app/pages/hike-edit/components/hike-edit-route-planner/hike-edit-route-planner.component.ts b/src/app/pages/hike-edit/components/hike-edit-route-planner/hike-edit-route-planner.component.ts index 7b11746d..cba31f57 100644 --- a/src/app/pages/hike-edit/components/hike-edit-route-planner/hike-edit-route-planner.component.ts +++ b/src/app/pages/hike-edit/components/hike-edit-route-planner/hike-edit-route-planner.component.ts @@ -42,27 +42,38 @@ export class HikeEditRoutePlannerComponent implements OnInit, OnDestroy { this.routeInfoData$ = this._store.select(this._hikeEditRoutePlannerSelectors.getRoutePlanner); this._store.select(this._hikeEditMapSelectors.getMapId) - .takeUntil(this._destroy$) .filter(id => id !== '') + .takeUntil(this._destroy$) .subscribe((mapId: string) => { this._map = this._adminMapService.getMapById(mapId); }); // Show toaster when the route has been saved this._store.select(this._hikeEditGeneralInfoSelectors.getRouteId) - .takeUntil(this._destroy$) - .switchMap((routeId: string) => this._store.select(this._routeSelectors.getRouteContext(routeId))) + .switchMap((routeId: string) => { + return this._store + .select(this._routeSelectors.getRouteContext(routeId)) + .takeUntil(this._destroy$); + }) .filter(routeContext => !!(routeContext && routeContext.saved)) + .takeUntil(this._destroy$) .subscribe((routeContext) => { this._toasterService.pop('success', 'Success!', 'Route saved!'); }); // Handling route load this._store.select(this._hikeEditGeneralInfoSelectors.getRouteId) - .takeUntil(this._destroy$) - .switchMap((routeId: string) => this._store.select(this._routeSelectors.getRouteContext(routeId))) + .switchMap((routeId: string) => { + return this._store + .select(this._routeSelectors.getRouteContext(routeId)) + .takeUntil(this._destroy$); + }) .filter(routeContext => !!(routeContext && routeContext.loaded)) - .switchMap((routeContext) => this._store.select(this._routeSelectors.getRoute((routeContext).id))) + .switchMap((routeContext) => { + return this._store + .select(this._routeSelectors.getRoute((routeContext).id)) + .takeUntil(this._destroy$); + }) .take(1) .subscribe((route) => { setTimeout(() => { @@ -98,16 +109,17 @@ export class HikeEditRoutePlannerComponent implements OnInit, OnDestroy { private _loadRoute(routeData: Route) { if (this._map && this._waypointMarkerService) { - this._waypointMarkerService.reset(); - + const coords: L.LatLng[] = []; for (let feature of routeData.route.features) { - let latlng = L.latLng( - feature.geometry.coordinates[1], - feature.geometry.coordinates[0] - ); - - this._waypointMarkerService.addWaypoint(latlng); + if (feature.geometry.type === 'Point') { + coords.push(L.latLng( + feature.geometry.coordinates[1], + feature.geometry.coordinates[0] + )); + } } + + this._waypointMarkerService.addWaypointList(coords); } } } diff --git a/src/app/pages/hike-edit/components/modals/hike-edit-gtrack-poi-info/hike-edit-gtrack-poi-info.component.ts b/src/app/pages/hike-edit/components/modals/hike-edit-gtrack-poi-info/hike-edit-gtrack-poi-info.component.ts index 87b8420a..4383db5c 100644 --- a/src/app/pages/hike-edit/components/modals/hike-edit-gtrack-poi-info/hike-edit-gtrack-poi-info.component.ts +++ b/src/app/pages/hike-edit/components/modals/hike-edit-gtrack-poi-info/hike-edit-gtrack-poi-info.component.ts @@ -45,7 +45,6 @@ export class HikeEditGTrackPoiInfoComponent implements OnInit, OnDestroy { .take(1) .subscribe((poi: Poi) => { this._gTrackPoi = _.cloneDeep(poi); - console.log('this._gTrackPoi', this._gTrackPoi); this._initFormSubscriptions(); }); diff --git a/src/app/pages/hike-edit/hike-edit.component.ts b/src/app/pages/hike-edit/hike-edit.component.ts index e9d76288..bf5a33d3 100644 --- a/src/app/pages/hike-edit/hike-edit.component.ts +++ b/src/app/pages/hike-edit/hike-edit.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Component, OnInit, OnDestroy, NgZone } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { ActivatedRoute, Router } from '@angular/router'; import { Observable } from 'rxjs/Observable'; @@ -16,6 +16,7 @@ import { ToasterService } from 'angular2-toaster'; import * as uuid from 'uuid/v1'; import * as _ from 'lodash'; import { RoutingControlService, WaypointMarkerService } from '../../shared/services/admin-map'; +import { IGeneralInfoState } from '../../store/state'; @Component({ selector: 'gt-hike-edit', @@ -39,7 +40,8 @@ export class HikeEditComponent implements OnInit, OnDestroy { private _hikeEditRoutePlannerSelectors: HikeEditRoutePlannerSelectors, private _toasterService: ToasterService, private _router: Router, - private _title: Title + private _title: Title, + private _zone: NgZone ) {} ngOnInit() { @@ -69,12 +71,12 @@ export class HikeEditComponent implements OnInit, OnDestroy { // Generate initial hike id and load the empty hikeProgram (for save toaster handling) const _hikeId = uuid(); this._store.dispatch(new hikeEditGeneralInfoActions.SetHikeId({ hikeId: _hikeId })); - this._store.dispatch(new commonHikeActions.HikeProgramUnsaved(_hikeId)); + this._store.dispatch(new commonHikeActions.HikeProgramModified(_hikeId)); // Generate initial route id and load the empty route (for save toaster handling) const _routeId = uuid(); this._store.dispatch(new hikeEditGeneralInfoActions.SetRouteId({ routeId: _routeId })); - this._store.dispatch(new commonRouteActions.RouteUnsaved(_routeId)); + this._store.dispatch(new commonRouteActions.RouteModified(_routeId)); // Create initial language block this._store.dispatch(new hikeEditGeneralInfoActions.SetDescriptions({ @@ -91,30 +93,48 @@ export class HikeEditComponent implements OnInit, OnDestroy { } }); - this.routeInfoData$ = this._store.select(this._hikeEditRoutePlannerSelectors.getRoutePlanner); + this.routeInfoData$ = this._store + .select(this._hikeEditRoutePlannerSelectors.getRoutePlanner) + .takeUntil(this._destroy$); - this.allowSave$ = Observable.combineLatest( - this._store.select(this._hikeEditGeneralInfoSelectors.getPois), - this.routeInfoData$ - ).map(([inHikePois, routeInfoData]: [any[], any]) => { - return inHikePois.length > 0 && (routeInfoData.segments && routeInfoData.segments.length > 0); - }) + this.allowSave$ = Observable + .combineLatest( + this._store.select(this._hikeEditGeneralInfoSelectors.getPois).takeUntil(this._destroy$), + this.routeInfoData$ + ) + .takeUntil(this._destroy$) + .map(([inHikePois, routeInfoData]: [any[], any]) => { + return inHikePois.length > 0 && (routeInfoData.segments && routeInfoData.segments.length > 0); + }) // Handling hike save - this._store.select(this._hikeEditGeneralInfoSelectors.getHikeId) - .takeUntil(this._destroy$) + this._store + .select(this._hikeEditGeneralInfoSelectors.getHikeId) .switchMap((hikeId: string) => this._store.select(this._hikeSelectors.getHikeContext(hikeId))) .filter(hikeContext => !!(hikeContext && hikeContext.saved)) + .takeUntil(this._destroy$) .subscribe((hikeContext) => { this._toasterService.pop('success', 'Success!', 'Hike saved!'); + + this._store.dispatch(new commonHikeActions.HikeProgramModified((hikeContext).id)); + this._router.navigate([`/admin/hike/${(hikeContext).id}`]); }); // Handling hike load - this._store.select(this._hikeEditGeneralInfoSelectors.getHikeId) - .switchMap((hikeId: string) => this._store.select(this._hikeSelectors.getHikeContext(hikeId))) + this._store + .select(this._hikeEditGeneralInfoSelectors.getHikeId) + .switchMap((hikeId: string) => { + return this._store + .select(this._hikeSelectors.getHikeContext(hikeId)) + .takeUntil(this._destroy$) + }) .filter(hikeContext => !!(hikeContext && hikeContext.loaded)) - .switchMap((hikeContext) => this._store.select(this._hikeSelectors.getHike((hikeContext).id))) + .switchMap((hikeContext) => { + return this._store + .select(this._hikeSelectors.getHike((hikeContext).id)) + .takeUntil(this._destroy$) + }) .take(1) .subscribe((hike) => { this._hikeDataService.splitHikeDataToStore(hike); @@ -137,6 +157,7 @@ export class HikeEditComponent implements OnInit, OnDestroy { this._store.select(this._hikeEditRoutePlannerSelectors.getRoutePlanner).take(1), this._store.select(this._hikeEditGeneralInfoSelectors.getRouteId).take(1) ) + .takeUntil(this._destroy$) .subscribe(([routePlannerState, routeId]: [IHikeEditRoutePlannerState, string]) => { if (routePlannerState && routeId) { let _route: IRoute = { diff --git a/src/app/pages/hike-list/hike-list.component.ts b/src/app/pages/hike-list/hike-list.component.ts index c765f7c1..d81dd76c 100644 --- a/src/app/pages/hike-list/hike-list.component.ts +++ b/src/app/pages/hike-list/hike-list.component.ts @@ -1,6 +1,7 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { Store } from '@ngrx/store'; +import { Subject } from 'rxjs/Subject'; import { Observable } from 'rxjs/Observable'; import { State, commonHikeActions @@ -9,13 +10,16 @@ import { IHikeProgram } from 'subrepos/provider-client'; import { HikeSelectors } from 'subrepos/gtrack-common-ngx'; import { LanguageService } from 'app/shared/services'; +import * as _ from 'lodash'; + @Component({ selector: 'gt-hike-list', templateUrl: './hike-list.component.html', styleUrls: ['./hike-list.component.scss'] }) -export class HikeListComponent implements OnInit { +export class HikeListComponent implements OnInit, OnDestroy { public hikeList$: Observable; + private _destroy$: Subject = new Subject(); constructor( private _store: Store, @@ -26,11 +30,19 @@ export class HikeListComponent implements OnInit { ngOnInit() { this._title.setTitle('Hikes'); - this.hikeList$ = this._store.select(this._hikeSelectors.getAllHikes); + this.hikeList$ = this._store + .select(this._hikeSelectors.getAllHikes) + .takeUntil(this._destroy$) + .map((hikes) => _.orderBy(hikes, ['timestamp'], ['desc'])); this._store.dispatch(new commonHikeActions.LoadHikePrograms()); } + ngOnDestroy( ) { + this._destroy$.next(true); + this._destroy$.unsubscribe(); + } + deleteHike(hikeId) { // this._store.dispatch(this._actions.deleteHike(hikeId)); } diff --git a/src/app/shared/services/poi/poi-editor.service.ts b/src/app/shared/services/poi/poi-editor.service.ts index 60191511..16af9cd0 100644 --- a/src/app/shared/services/poi/poi-editor.service.ts +++ b/src/app/shared/services/poi/poi-editor.service.ts @@ -130,7 +130,7 @@ export class PoiEditorService { ) { let _pois: any[] = []; - if (path) { + if (pois && path) { const _smallBuffer = >turf.buffer(path, 50, {units: 'meters'}); const _bigBuffer = >turf.buffer(path, 1000, {units: 'meters'}); diff --git a/src/app/store/effects/hike-edit.ts b/src/app/store/effects/hike-edit.ts index 0d042ce5..6baff1cf 100644 --- a/src/app/store/effects/hike-edit.ts +++ b/src/app/store/effects/hike-edit.ts @@ -20,11 +20,13 @@ export class HikeEditEffects { collectHikeData$: Observable = this._actions$ .ofType(hikeEditActions.COLLECT_HIKE_DATA) .switchMap(data => { - return this._hikeDataService.collectHikeGeneralInfo() + return this._hikeDataService + .collectHikeGeneralInfo() .map((generalInfo) => _.extend(_.cloneDeep(data), generalInfo)); }) .switchMap(data => { - return this._hikeDataService.collectHikeDescriptions() + return this._hikeDataService + .collectHikeDescriptions() .map((descriptions) => { const descriptionObj = {}; descriptions.map(desc => { @@ -34,16 +36,23 @@ export class HikeEditEffects { }); }) .switchMap(data => { - return this._hikeDataService.collectHikeRouteInfo() + return this._hikeDataService + .collectHikeRouteInfo() .map((routeInfoObj) => _.extend(_.cloneDeep(data), routeInfoObj)); }) .switchMap(data => { - return this._hikeDataService.collectHikeLocation(data) + return this._hikeDataService + .collectHikeStops() + .map((stopsObj) => _.extend(_.cloneDeep(data), stopsObj)); + }) + .switchMap(data => { + return this._hikeDataService + .collectHikeLocation(data) .then((locationObj) => _.extend(_.cloneDeep(data), locationObj)); }) .map(data => { return new commonHikeActions.SaveHikeProgram( - _.extend(_.cloneDeep(data), { + _.extend(data, { routeIcon: 'fake', elevationIcon: 'fake' // todo from service })