diff --git a/projects/common-map/src/fm-map/effects/map.effects.ts b/projects/common-map/src/fm-map/effects/map.effects.ts index c635a83..3858d54 100644 --- a/projects/common-map/src/fm-map/effects/map.effects.ts +++ b/projects/common-map/src/fm-map/effects/map.effects.ts @@ -1,11 +1,12 @@ import { Injectable } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; -import { Store, Action } from '@ngrx/store'; -import { Effect, Actions,ofType } from '@ngrx/effects'; +import { Store, Action,createFeatureSelector } from '@ngrx/store'; +import { ROUTER_NAVIGATED, RouterReducerState } from '@ngrx/router-store'; +import * as fromRouter from '@ngrx/router-store'; +import { createEffect, Actions,ofType } from '@ngrx/effects'; -import { EMPTY, Observable , of,merge} from 'rxjs'; -import { withLatestFrom, switchMap, map, catchError, mergeMap,tap } from 'rxjs/operators'; +import { EMPTY, Observable , of} from 'rxjs'; +import { withLatestFrom, switchMap, map, catchError, mergeMap } from 'rxjs/operators'; import {GeoJSON,WKT} from 'ol/format'; import {Feature} from 'ol'; @@ -30,11 +31,24 @@ import * as style from 'ol/style'; import { ItemTypeService,IQueryState } from '@farmmaps/common'; import { TemporalItemLayer } from '../models/item.layer' +export const getRouterState = createFeatureSelector('router'); + +export const { + selectCurrentRoute, // select the current route + selectQueryParams, // select the current route query params + selectQueryParam, // factory function to select a query param + selectRouteParams, // select the current route params + selectRouteParam, // factory function to select a route param + selectRouteData, // select the current route data + selectUrl, // select the current url +} = fromRouter.getSelectors(getRouterState); + @Injectable() export class MapEffects { private _geojsonFormat: GeoJSON; private _wktFormat: WKT; + private overrideSelectedItemLayer private toPointFeature(updateEvent:commonActions.DeviceUpdateEvent): Feature { var f = this._wktFormat.readFeature(updateEvent.attributes["geometry"],{ @@ -47,8 +61,7 @@ export class MapEffects { return f; } - @Effect() - init$: Observable = this.actions$.pipe( + init$ = createEffect(() => this.actions$.pipe( ofType(mapActions.INIT), withLatestFrom(this.store$.select(commonReducers.selectGetRootItems)), switchMap(([action, rootItems]) => { @@ -88,25 +101,23 @@ export class MapEffects { return actions; } - )); + ))); - @Effect() - initBaseLayers$: Observable = this.actions$.pipe( + initBaseLayers$ = createEffect(() => this.actions$.pipe( ofType(mapActions.INIT), withLatestFrom(this.store$.select(mapReducers.selectGetProjection)), - map(([action, projection]) => new mapActions.LoadBaseLayers(projection))); + map(([action, projection]) => new mapActions.LoadBaseLayers(projection))) + ); - @Effect() - loadBaseLayers$: Observable = this.actions$.pipe( + loadBaseLayers$ = createEffect(() => this.actions$.pipe( ofType(mapActions.LOADBASELAYERS), switchMap((action: mapActions.LoadBaseLayers) => { return this.itemService$.getItemList("vnd.farmmaps.itemtype.layer", { "isBaseLayer": true }).pipe( map((items: IItem[]) => new mapActions.LoadBaseLayersSuccess(items)), catchError(error => of(new commonActions.Fail(error)))); - })); + }))); - @Effect() - startSearch$: Observable = this.actions$.pipe( + startSearch$ = createEffect(() => this.actions$.pipe( ofType(mapActions.STARTSEARCH), switchMap((action) => { let a = action as mapActions.StartSearch; @@ -129,11 +140,10 @@ export class MapEffects { return []; } return newAction; - })); + }))); - @Effect() - zoomToExtent$: Observable = this.actions$.pipe( + zoomToExtent$ = createEffect(() => this.actions$.pipe( ofType(mapActions.STARTSEARCHSUCCESS), mergeMap((action: mapActions.StartSearchSuccess) => { let actions =[]; @@ -150,10 +160,9 @@ export class MapEffects { } } return actions; - })); + }))); - @Effect() - zoomToExtent2$: Observable = this.actions$.pipe( + zoomToExtent2$ = createEffect(() => this.actions$.pipe( ofType(mapActions.SETFEATURES), switchMap((action: mapActions.SetFeatures) => { let extent = createEmpty(); @@ -164,17 +173,15 @@ export class MapEffects { if(action.features.length>0) return of(new mapActions.SetExtent(extent)); } return EMPTY; - })); + }))); - @Effect() - hideMenu$: Observable = this.actions$.pipe( + hideMenu$ = createEffect(() => this.actions$.pipe( ofType(mapActions.STARTSEARCHSUCCESS), mergeMap((action: mapActions.StartSearchSuccess) => { return of(new commonActions.SetMenuVisible(false)); - })); + }))); - @Effect() - selectItem$: Observable = this.actions$.pipe( + selectItem$ = createEffect(() => this.actions$.pipe( ofType(mapActions.SELECTITEM), withLatestFrom(this.store$.select(mapReducers.selectGetSelectedItem)), switchMap(([action, selectedItem]) => { @@ -195,26 +202,19 @@ export class MapEffects { return []; } } - )); + ))); - @Effect() - selectItemSuccessSetLayer$: Observable = this.actions$.pipe( + selectItemSuccessSetLayer$ = createEffect(() => this.actions$.pipe( ofType(mapActions.SELECTITEMSUCCESS), map((action:mapActions.SelectItemSuccess) => new mapActions.SetSelectedItemLayer(action.item) ) - ); + )); - @Effect() - selectItemSuccess$: Observable = this.actions$.pipe( + selectItemSuccess$ = createEffect(() => this.actions$.pipe( ofType(mapActions.SELECTITEMSUCCESS), - switchMap((action:mapActions.SelectItemSuccess) => { - let overrideSelectedItemLayer = false; - if(this.route$ && this.route$.snapshot && this.route$.snapshot.data && this.route$.snapshot.data["fm-map-map"]) { - let params = this.route$.snapshot.data["fm-map-map"]; - overrideSelectedItemLayer = params["overrideSelectedItemlayer"] ? params["overrideSelectedItemlayer"] : false; - } - if(!overrideSelectedItemLayer) { + switchMap((action:mapActions.SelectItemSuccess) => { + if(!this.overrideSelectedItemLayer) { return this.itemService$.getFeature(action.item.code, "EPSG:3857").pipe( map((feature: any) => { let f = this._geojsonFormat.readFeature(feature); @@ -226,10 +226,9 @@ export class MapEffects { return EMPTY; } } - )); + ))); - @Effect() - selectItemSuccessTemporal$: Observable = this.actions$.pipe( + selectItemSuccessTemporal$ = createEffect(() => this.actions$.pipe( ofType(mapActions.SELECTITEMSUCCESS), switchMap((action:mapActions.SelectItemSuccess) => { if(action.item.itemType == "vnd.farmmaps.itemtype.temporal") { @@ -244,16 +243,14 @@ export class MapEffects { return []; } } - )); + ))); - @Effect() - uploadedItemClick$: Observable = this.actions$.pipe( + uploadedItemClick$ = createEffect(() => this.actions$.pipe( ofType(commonActions.UPLOADEDFILECLICK), switchMap((action: commonActions.UploadedFileClick) => of(new mapActions.DoQuery(tassign(mapReducers.initialState.query, {itemCode:action.itemCode}))) - )); + ))); - @Effect() - featureUpdate$: Observable = this.actions$.pipe( + featureUpdate$ = createEffect(() => this.actions$.pipe( ofType(commonActions.DEVICEUPDATEEVENT), withLatestFrom(this.store$.select(mapReducers.selectGetFeatures)), mergeMap(([action, features]) => { @@ -270,10 +267,9 @@ export class MapEffects { } else { return []; } - })); + }))); - @Effect() - itemUpdate$: Observable = this.actions$.pipe( + itemUpdate$ = createEffect(() => this.actions$.pipe( ofType(commonActions.ITEMCHANGEDEVENT), withLatestFrom(this.store$.select(mapReducers.selectGetSelectedItem)), mergeMap(([action, selectedItem]) => { @@ -292,7 +288,7 @@ export class MapEffects { } else { return []; } - })); + }))); getActionFromQueryState(queryState:IQueryState, inSearch:boolean):Observable|[] { if(!inSearch && (queryState.itemType || queryState.parentCode || queryState.itemCode || queryState.query || queryState.tags)) { @@ -309,8 +305,7 @@ export class MapEffects { return of(newAction); } - @Effect() - getLayerValue$: Observable = this.actions$.pipe( + getLayerValue$ = createEffect(() => this.actions$.pipe( ofType(mapActions.GETLAYERVALUE), mergeMap((action:mapActions.GetLayerValue) => { var l = action.itemLayer.item.data["layers"][action.itemLayer.layerIndex]; @@ -334,19 +329,17 @@ export class MapEffects { return a; })) } - )); + ))); - @Effect() - updateLayerValuesOnLayerAddedOrRemoved$: Observable = this.actions$.pipe( + updateLayerValuesOnLayerAddedOrRemoved$ = createEffect(() => this.actions$.pipe( ofType(mapActions.ADDLAYER,mapActions.REMOVELAYER,mapActions.SELECTITEM,mapActions.NEXTTEMPORAL,mapActions.PREVIOUSTEMPORAL,mapActions.TOGGLELAYERVALUESENABLED), withLatestFrom(this.store$.select(mapReducers.selectGetLayerValuesX)), withLatestFrom(this.store$.select(mapReducers.selectGetLayerValuesY)), map(([[action,x],y]) => new mapActions.SetLayerValuesLocation(x,y)) - ); + )); - @Effect() - getLayerValues$: Observable = this.actions$.pipe( + getLayerValues$ = createEffect(() => this.actions$.pipe( ofType(mapActions.SETLAYERVALUESLOCATION), withLatestFrom(this.store$.select(mapReducers.selectGetSelectedItemLayer)), withLatestFrom(this.store$.select(mapReducers.selectGetLayerValuesEnabled)), @@ -372,20 +365,18 @@ export class MapEffects { }); } return actions; - })); + }))); - @Effect() - setState$: Observable = this.actions$.pipe( + setState$ = createEffect(() => this.actions$.pipe( ofType(mapActions.SETSTATE), withLatestFrom(this.store$.select(mapReducers.selectGetInSearch)), switchMap(([action,inSearch]) => { let a = action as mapActions.SetState; return this.getActionFromQueryState(a.queryState,inSearch); - })); + }))); - @Effect() - escape$:Observable = this.actions$.pipe( + escape$ = createEffect(() => this.actions$.pipe( ofType(commonActions.ESCAPE), switchMap((action) => { let a = action as commonActions.Escape; @@ -394,9 +385,21 @@ export class MapEffects { } else { return EMPTY; } - })); + }))); - constructor(private actions$: Actions, private store$: Store, private folderService$: FolderService, private itemService$: ItemService,private featureIconService$:FeatureIconService,private itemTypeService$:ItemTypeService, private route$: ActivatedRoute) { + setOverride$ = createEffect(() => this.actions$.pipe( + ofType(ROUTER_NAVIGATED), + switchMap(() => this.store$.select(selectRouteData as any)), + switchMap((data: any) => { + if(data && data["fm-map-map"]) { + let params = data["fm-map-map"]; + this.overrideSelectedItemLayer = params["overrideSelectedItemlayer"] ? params["overrideSelectedItemlayer"] : false; + } + return []; + }) + )); + + constructor(private actions$: Actions, private store$: Store, private folderService$: FolderService, private itemService$: ItemService,private featureIconService$:FeatureIconService,private itemTypeService$:ItemTypeService) { this._geojsonFormat = new GeoJSON(); this._wktFormat = new WKT(); } diff --git a/projects/common/src/fm/effects/app-common.effects.ts b/projects/common/src/fm/effects/app-common.effects.ts index 9daab8f..a3ae339 100644 --- a/projects/common/src/fm/effects/app-common.effects.ts +++ b/projects/common/src/fm/effects/app-common.effects.ts @@ -1,9 +1,9 @@ import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { OAuthService,UserInfo } from 'angular-oauth2-oidc'; -import { Store, Action } from '@ngrx/store'; -import { Effect, Actions,ofType } from '@ngrx/effects'; -import { Observable , defer , of,from,zip } from 'rxjs'; +import { Store } from '@ngrx/store'; +import { Actions,ofType,createEffect } from '@ngrx/effects'; +import { of,from,zip } from 'rxjs'; import { withLatestFrom,mergeMap,switchMap,map,catchError,first} from 'rxjs/operators'; import * as appCommonActions from '../actions/app-common.actions'; import * as appCommonReducers from '../reducers/app-common.reducer'; @@ -12,43 +12,37 @@ import { FolderService } from '../services/folder.service'; import { UserService } from '../services/user.service'; import { IItemTypes } from '../models/item.types'; import { IListItem } from '../models/list.item'; -import { IUser } from '../models/user'; -import {IQueryState} from '../models/query.state'; import {StateSerializerService} from '../services/state-serializer.service'; @Injectable() export class AppCommonEffects { - @Effect({ dispatch: false }) - login$: Observable = this.actions$.pipe( + login$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.LOGIN), withLatestFrom(this.store$.select(appCommonReducers.selectGetInitialized)), mergeMap(([action, initialized]) => { var a = (action as appCommonActions.Login); this.oauthService$.initCodeFlow(a.url,{"prompt":"login"}); return []; - })); + })),{dispatch:false}); - @Effect({ dispatch: false }) - logout$: Observable = this.actions$.pipe( + logout$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.LOGOUT), mergeMap((action) => { this.oauthService$.revokeTokenAndLogout(); return []; - })); + })),{dispatch:false}); - @Effect() - loadItemTypes$: Observable = this.actions$.pipe( + loadItemTypes$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.LOADITEMTYPES), switchMap((action) => { return this.itemService$.getItemTypes().pipe( map((itemTypes: IItemTypes) => new appCommonActions.LoadItemTypesSuccess(itemTypes)), catchError(error => of(new appCommonActions.Fail(error)))) } - )); + ))); - @Effect() - initUser$: Observable = this.actions$.pipe( + initUser$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.INITUSER), first(), switchMap((action) => { @@ -56,11 +50,10 @@ export class AppCommonEffects { switchMap(([user,userInfo]) => {return of(new appCommonActions.InitUserSuccess(user,userInfo as UserInfo))} ), catchError(error => of(new appCommonActions.Fail(error)))) } - )); + ))); - @Effect() - initUserPackages$:Observable = this.actions$.pipe( + initUserPackages$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.INITUSERPACKAGES), switchMap(() => { return this.itemService$.getItemList('vnd.farmmaps.itemtype.package').pipe( @@ -68,10 +61,9 @@ export class AppCommonEffects { catchError(error => of(new appCommonActions.Fail(error))) ) }) - ); + )); - @Effect() - userPackagesChanged$:Observable = this.actions$.pipe( + userPackagesChanged$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.ITEMCHANGEDEVENT), switchMap((action) => { let a = action as appCommonActions.ItemChangedEvent; @@ -80,10 +72,9 @@ export class AppCommonEffects { else return []; }) - ); + )); - @Effect() - initUserSettingsRoot$:Observable = this.actions$.pipe( + initUserSettingsRoot$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.INITUSERSETTINGSROOT), withLatestFrom(this.store$.select(appCommonReducers.SelectGetUser)), switchMap(([, user]) => { @@ -92,10 +83,9 @@ export class AppCommonEffects { catchError(error => of(new appCommonActions.Fail(error))) ) }) - ); + )); - @Effect() - initUserSettingsRootChanged$:Observable = this.actions$.pipe( + initUserSettingsRootChanged$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.ITEMCHANGEDEVENT), switchMap((action) => { let a = action as appCommonActions.ItemChangedEvent; @@ -104,38 +94,34 @@ export class AppCommonEffects { else return []; }) - ); + )); - @Effect() - initUserSuccess$: Observable = this.actions$.pipe( + initUserSuccess$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.INITUSERSUCCESS), switchMap(() => { return [new appCommonActions.InitRoot(),new appCommonActions.InitUserPackages(),new appCommonActions.InitUserSettingsRoot()]; } - )); + ))); - @Effect() - initRoot$: Observable = this.actions$.pipe( + initRoot$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.INITROOT), switchMap(() => { return this.folderService$.getMyRoots().pipe( map((folders: IListItem[]) => new appCommonActions.InitRootSuccess(folders)), catchError(error => of(new appCommonActions.Fail(error)))) } - )); + ))); - @Effect() - deleteItems$: Observable = this.actions$.pipe( + deleteItems$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.DELETEITEMS), switchMap((action:appCommonActions.DeleteItems) => { return this.itemService$.deleteItems(action.itemCodes).pipe( map((deletedItemCodes: string[]) => new appCommonActions.DeleteItemsSuccess(deletedItemCodes)), catchError(error => of(new appCommonActions.Fail(error)))) } - )); + ))); - @Effect() - editItem$: Observable = this.actions$.pipe( + editItem$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.EDITITEM), withLatestFrom(this.store$.select(appCommonReducers.selectGetItemTypes)), switchMap(([action, itemtypes]) => { @@ -148,10 +134,9 @@ export class AppCommonEffects { this.router$.navigate(['/editor',editor,'item', a.item.code]) return []; } - )); + ))); - @Effect() - viewItem$: Observable = this.actions$.pipe( + viewItem$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.VIEWITEM), withLatestFrom(this.store$.select(appCommonReducers.selectGetItemTypes)), switchMap(([action, itemtypes]) => { @@ -181,20 +166,18 @@ export class AppCommonEffects { } return []; } - )); + ))); - @Effect({ dispatch: false }) - fail$: Observable = this.actions$.pipe( + fail$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.FAIL), map((action) => { let failAction = action as appCommonActions.Fail; console.debug(failAction.payload) return null; - })); + })),{dispatch:false}); - @Effect({ dispatch: false }) - online$: Observable = this.actions$.pipe( + online$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.ONLINE), switchMap((action) => { console.debug("Online: Check token"); @@ -206,7 +189,7 @@ export class AppCommonEffects { } } return of(undefined); - })); + })),{dispatch:false}); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 354f3e5..55d62bb 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -13,7 +13,7 @@ import {AppRootComponent} from './app.component'; import {StoreModule, ActionReducer,MetaReducer} from '@ngrx/store'; import {EffectsModule, EffectSources} from '@ngrx/effects'; -import { StoreRouterConnectingModule} from '@ngrx/router-store'; +import { StoreRouterConnectingModule,routerReducer} from '@ngrx/router-store'; import {AppRoutingModule} from './app-routing.module'; import { LogoComponent } from './logo/logo.component'; @@ -76,13 +76,14 @@ export const metaReducers: MetaReducer[] = [debug]; AppCommonModule, AppCommonServiceModule.forRoot(), BrowserModule, - StoreModule.forRoot({},{metaReducers,runtimeChecks: { // TODO fix this should all be true + StoreModule.forRoot({router:routerReducer},{metaReducers,runtimeChecks: { // TODO fix this should all be true strictStateImmutability: false, strictActionImmutability: false, strictStateSerializability: false, strictActionSerializability: false - }}), - EffectsModule.forRoot([]) + }}), + StoreRouterConnectingModule.forRoot({stateKey:"router"}), + EffectsModule.forRoot([]), ], providers: [ AuthConfigFactory,