import { Injectable } from '@angular/core'; import { map, tap, switchMap, withLatestFrom, filter, startWith, catchError, } from 'rxjs/operators'; import { Actions, ofType, createEffect, OnInitEffects } from '@ngrx/effects'; import { ActivationStart, NavigationStart, Router } from '@angular/router'; // App import * as userActions from './user.actions'; import * as oidcActions from './oidc.actions'; import { MwUserApiService } from '../services/user-api.service'; import { mwCreateApiEffect } from 'projects/core/src//store/effect.utils'; import { MwUserEffectsService } from './user.effects.service'; import { Action } from '@ngrx/store'; import { OidcSecurityService } from 'angular-auth-oidc-client'; import { MwUserService } from '../services/user.service'; import { MwAuthService } from '../services/auth.service'; import { of } from 'rxjs'; @Injectable() export class UserEffects implements OnInitEffects { init$ = createEffect( () => this.actions$.pipe( ofType(userActions.init), tap(() => { this.userEffectsService.registerFcmToken(); }) ), { dispatch: false } ); requestUserProfile$ = mwCreateApiEffect( this.actions$, userActions.requestUserProfile, (action) => this.userApiService.getProfile(action.companyId), (profile, action) => { return userActions.setUserProfile({ userApiProfile: profile, forceLanguage: action.language, }); }, () => userActions.setUserProfile({ userApiProfile: null, forceLanguage: undefined, }) ); setActiveCompany$ = createEffect(() => this.actions$.pipe( ofType(userActions.setActiveCompany), map((action) => userActions.requestUserProfile({ companyId: action.company?.companyId, language: action.language, }) ) ) ); oidcUserDataReceived$ = createEffect(() => this.actions$.pipe( ofType(oidcActions.userDataReceived), withLatestFrom(this.authService.loggedIn$), withLatestFrom(this.userService.userProfile$.pipe(startWith(null))), filter(([[action, isLoggedIn], userProfile]) => isLoggedIn), map(([[action, isLoggedIn], userProfile]) => ({ ...action, companyId: action.companyId, companyNotRequired: action.companyNotRequired, })), map((action) => userActions.trySetActiveCompany({ selectedCompanyId: action.companyId, selectedLanguage: action.language, companyNotRequired: action.companyNotRequired, }) ) ) ); trySetActiveCompany = createEffect(() => this.actions$.pipe( ofType(userActions.trySetActiveCompany), switchMap((action) => this.userApiService.getCompanies().pipe( map((companies) => { const company = companies.find((t) => t.companyId === action.selectedCompanyId) || null; const hasManyCompanies = companies.length > 1; if (company || action.companyNotRequired) { return userActions.setActiveCompany({ company, language: action.selectedLanguage, hasManyCompanies, }); } else { return userActions.changeCompany({ selectedCompanyId: undefined, }); } }) ) ) ) ); logout$ = createEffect( () => this.actions$.pipe( ofType(userActions.logOut), tap(() => { this.oidcSecurityService.logoff(); }) ), { dispatch: false } ); registerFcmToken$ = createEffect( () => this.actions$.pipe( ofType(userActions.registerFcmToken), tap((action) => { this.userApiService.registerFcmToken(action.token).subscribe(); }) ), { dispatch: false } ); changeCompany = createEffect( () => this.actions$.pipe( ofType(userActions.changeCompany), tap((action) => { this.authService.changeCompany(action.selectedCompanyId); }) ), { dispatch: false } ); changeLanguage = createEffect(() => this.actions$.pipe( ofType(userActions.changeLanguage), switchMap((action) => this.userApiService.changeLanguage(action.userLanguage).pipe( map(() => userActions.userProfileLanguageChanged({ userLanguage: action.userLanguage, }) ), catchError((err) => of(userActions.userProfileLanguageChangeFailed({ err })) ) ) ) ) ); constructor( private readonly actions$: Actions, private readonly userApiService: MwUserApiService, private readonly userEffectsService: MwUserEffectsService, private readonly oidcSecurityService: OidcSecurityService, private readonly userService: MwUserService, private readonly router: Router, private readonly authService: MwAuthService ) {} ngrxOnInitEffects(): Action { this.subscribeToAutoLoginRoute(); return userActions.init(); } private subscribeToAutoLoginRoute(): void { this.router.events .pipe( filter( (event) => event instanceof NavigationStart && event.url.indexOf('?autologin=') !== -1 ) ) .subscribe(() => { const guid = this.getAutoLoginGuid(); if (guid) { this.authService.authorizeByGuid(guid); } }); } private getAutoLoginGuid(): string | null { return new URLSearchParams('?' + window.location.href.split('?')[1]).get( 'autologin' ); } }