import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { OAuthService,UserInfo } from 'angular-oauth2-oidc'; 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'; 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 {StateSerializerService} from '../services/state-serializer.service'; @Injectable() export class AppCommonEffects { login$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.LOGIN), withLatestFrom(this.store$.select(appCommonReducers.selectGetInitialized)), mergeMap(([action, initialized]) => { const a = (action as appCommonActions.Login); this.oauthService$.initCodeFlow(a.url,{"prompt":"login"}); return []; })),{dispatch:false}); logout$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.LOGOUT), mergeMap((action) => { this.oauthService$.revokeTokenAndLogout(); return []; })),{dispatch:false}); 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)))) } ))); initUser$ = createEffect(() => 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)))) } ))); initUserPackages$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.INITUSERPACKAGES), switchMap(() => { return this.itemService$.getItemList('vnd.farmmaps.itemtype.package').pipe( switchMap((items) => of(new appCommonActions.InitUserPackagesSuccess(items))), catchError(error => of(new appCommonActions.Fail(error))) ) }) )); initPackages$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.INITPACKAGES), switchMap(() => { return this.itemService$.getItemList('vnd.farmmaps.itemtype.package.template').pipe( switchMap((items) => of(new appCommonActions.InitPackagesSuccess(items))), catchError(error => of(new appCommonActions.Fail(error))) ) }) )); userPackagesChanged$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.ITEMCHANGEDEVENT), switchMap((action) => { const a = action as appCommonActions.ItemChangedEvent; if(a.itemCode.endsWith(":USER_PACKAGES")) return of(new appCommonActions.InitUserPackages()); else return []; }) )); initUserSettingsRoot$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.INITUSERSETTINGSROOT), withLatestFrom(this.store$.select(appCommonReducers.SelectGetUser)), switchMap(([, user]) => { return this.itemService$.getItem(user.code + ':USER_SETTINGS').pipe( switchMap((item) => of(new appCommonActions.InitUserSettingsRootSuccess(item))), catchError(error => of(new appCommonActions.Fail(error))) ) }) )); initUserSettingsRootChanged$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.ITEMCHANGEDEVENT), switchMap((action) => { const a = action as appCommonActions.ItemChangedEvent; if(a.itemCode.endsWith(":USER_SETTINGS")) return of(new appCommonActions.InitUserSettingsRoot()); else return []; }) )); initUserSuccess$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.INITUSERSUCCESS), switchMap(() => { return [new appCommonActions.InitRoot(),new appCommonActions.InitUserPackages(),new appCommonActions.InitPackages(),new appCommonActions.InitUserSettingsRoot()]; } ))); 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)))) } ))); 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)))) } ))); editItem$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.EDITITEM), withLatestFrom(this.store$.select(appCommonReducers.selectGetItemTypes)), switchMap(([action, itemtypes]) => { const a = action as appCommonActions.EditItem; var editor = "property"; if(a.item.itemType) { const itemType = itemtypes[a.item.itemType]; var editor = itemType && itemType.editor ? itemType.editor : editor; } this.router$.navigate(['/editor',editor,'item', a.item.code]) return []; } ))); viewItem$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.VIEWITEM), withLatestFrom(this.store$.select(appCommonReducers.selectGetItemTypes)), switchMap(([action, itemtypes]) => { const a = action as appCommonActions.EditItem; const itemType = itemtypes[a.item.itemType]; const viewer = itemType.viewer; const editor = itemType.editor; if(viewer == 'select_as_mapitem') { const queryState = { itemCode: a.item.code, parentCode: null, level: 1, itemType: null, bboxFilter: false, query: null, tags: null, endDate: null, startDate: null, bbox: [] }; const 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 []; } ))); fail$ = createEffect(() => this.actions$.pipe( ofType(appCommonActions.FAIL), map((action) => { const failAction = action as appCommonActions.Fail; console.debug(failAction.payload) return null; })),{dispatch:false}); online$ = createEffect(() => 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(); } } return of(undefined); })),{dispatch:false}); 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()); } }