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 { 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'; import { ItemService } from '../services/item.service'; 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( 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 []; })); @Effect({ dispatch: false }) logout$: Observable = this.actions$.pipe( ofType(appCommonActions.LOGOUT), mergeMap((action) => { this.oauthService$.logOut(true); return []; })); @Effect() loadItemTypes$: Observable = 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( ofType(appCommonActions.INITUSER), first(), switchMap((action) => { return zip(this.userService$.getCurrentUser(),from(this.oauthService$.loadUserProfile())).pipe( 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( ofType(appCommonActions.INITUSERPACKAGES), withLatestFrom(this.store$.select(appCommonReducers.SelectGetUser)), switchMap(([action,user]) => { return this.itemService$.getChildItemList(user.code+":USER_PACKAGES","vnd.farmmaps.itemtype.package").pipe( switchMap((items) => of(new appCommonActions.InitUserPackagesSuccess(items))), catchError(error => of(new appCommonActions.Fail(error))) ) }) ); @Effect() userPackagesChanged$:Observable = this.actions$.pipe( ofType(appCommonActions.ITEMCHANGEDEVENT), switchMap((action) => { let a = action as appCommonActions.ItemChangedEvent; if(a.itemCode.endsWith(":USER_PACKAGES")) return of(new appCommonActions.InitUserPackages()); else return of(undefined); }) ); @Effect() initUserSuccess$: Observable = this.actions$.pipe( ofType(appCommonActions.INITUSERSUCCESS), switchMap(() => { return [new appCommonActions.InitRoot(),new appCommonActions.InitUserPackages()]; } )); @Effect() initRoot$: Observable = 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( 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( ofType(appCommonActions.EDITITEM), withLatestFrom(this.store$.select(appCommonReducers.selectGetItemTypes)), switchMap(([action, itemtypes]) => { var a = action as appCommonActions.EditItem; var editor = "property"; if(a.item.itemType) { var itemType = itemtypes[a.item.itemType]; var editor = itemType && itemType.editor ? itemType.editor : editor; } this.router$.navigate(['/editor',editor,'item', a.item.code]) return []; } )); @Effect() viewItem$: Observable = this.actions$.pipe( ofType(appCommonActions.VIEWITEM), withLatestFrom(this.store$.select(appCommonReducers.selectGetItemTypes)), switchMap(([action, itemtypes]) => { var a = action as appCommonActions.EditItem; var itemType = itemtypes[a.item.itemType]; var viewer = itemType.viewer; var editor = itemType.editor; if(viewer == 'select_as_mapitem') { let queryState = { itemCode: a.item.code, parentCode: null, level: 1, itemType: null, bboxFilter: false, query: null, tags: null, endDate: null, startDate: null, bbox: [] }; let query = this.stateSerializerService$.serialize(queryState); this.router$.navigate(['/map', query ]) }else if(viewer == 'edit_in_editor') { this.router$.navigate(['/editor', editor, 'item', a.item.code]) } else { this.router$.navigate(['/viewer', viewer, 'item', a.item.code]) } return []; } )); @Effect({ dispatch: false }) fail$: Observable = this.actions$.pipe( ofType(appCommonActions.FAIL), map((action) => { let failAction = action as appCommonActions.Fail; console.debug(failAction.payload) return null; })); @Effect({ dispatch: false }) online$: Observable = this.actions$.pipe( ofType(appCommonActions.ONLINE), switchMap((action) => { console.debug("Online: Check token"); if(!this.oauthService$.hasValidAccessToken()) { console.debug("No valid token, try to refresh"); if(this.oauthService$.getRefreshToken() != null ) { console.debug("We have a refresh token"); this.oauthService$.refreshToken().then(() => { this.store$.dispatch(new appCommonActions.InitUser()); }); } } return of(undefined); })); constructor(private actions$: Actions, private store$: Store, private oauthService$: OAuthService, private itemService$: ItemService, private folderService$:FolderService, private userService$: UserService, private router$: Router, private stateSerializerService$:StateSerializerService) { store$.dispatch(new appCommonActions.LoadItemTypes()); } }