import { of } from 'rxjs'; import { catchError, exhaustMap, map, withLatestFrom, concatMap, switchMap } from 'rxjs/operators'; import { Injectable, Inject } from '@angular/core'; import { Store, select } from '@ngrx/store'; import { Actions, ofType, createEffect } from '@ngrx/effects'; import { AddResponse as GroupAddResponse, UpdateResponse as GroupUpdateResponse, DelResponse as GroupDelResponse } from '@ucap/protocol-group'; import { GroupProtocolService } from '@ucap/ng-protocol-group'; import { SyncProtocolService } from '@ucap/ng-protocol-sync'; import { DepartmentSelector } from '@ucap/ng-store-organization'; import { LoginActions } from '@ucap/ng-store-authentication'; import { ModuleConfig } from '../../config/module-config'; import { _MODULE_CONFIG } from '../../config/token'; import * as buddyActions from '../buddy/actions'; import { GroupSelector } from '../state'; import { groups, groupsSuccess, groupsFailure, create, createSuccess, createFailure, update, updateFailure, updateMember, del, delFailure, delSuccess, moveMember, moveFromFailure, moveToFailure, updateMemberSuccess } from './actions'; @Injectable() export class Effects { sessionCreatedForGroups$ = createEffect(() => { return this.actions$.pipe( ofType(LoginActions.sessionCreated), map(action => groups()) ); }); groups$ = createEffect(() => { return this.actions$.pipe( ofType(groups), withLatestFrom(this.store.pipe(select(GroupSelector.groupSyncDate))), switchMap(([action, syncDate]) => { return this.syncProtocolService.group2({ syncDate }).pipe( map(res => groupsSuccess({ groupList: res.groupInfos, syncDate: res.res.syncDate }) ), catchError(error => of(groupsFailure({ error }))) ); }) ); }); create$ = createEffect(() => this.actions$.pipe( ofType(create), exhaustMap(action => { return this.groupProtocolService .add({ groupName: action.groupName }) .pipe( switchMap((res: GroupAddResponse) => { const actions: any[] = []; if (!!action.targetUserSeqs && 0 < action.targetUserSeqs.length) { actions.push( update({ req: { groupSeq: res.groupSeq, groupName: res.groupName, userSeqs: action.targetUserSeqs } }) ); } actions.push( createSuccess({ res, targetUserSeqs: action.targetUserSeqs }) ); return actions; }), catchError(error => of(createFailure({ error }))) ); }) ) ); updateMember$ = createEffect( () => { return this.actions$.pipe( ofType(updateMember), withLatestFrom( this.store.pipe(select(GroupSelector.groups)), this.store.pipe(select(DepartmentSelector.myDepartmentUserInfoList)) // 내 부서원 비교. ), switchMap(([action, groupList, myDeptUserList]) => { const targetGroup = action.targetGroup; const targetUserSeqs = action.targetUserSeqs; // Del Buddy let userSeqsForDelete: string[] = targetGroup.userSeqs.filter( v => targetUserSeqs.indexOf(v) < 0 ); // 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다. if ( !!this.moduleConfig.useMyDeptGroup && this.moduleConfig.useMyDeptGroup ) { userSeqsForDelete = userSeqsForDelete.filter( delbuddy => myDeptUserList.filter(deptUser => deptUser.seq === delbuddy) .length === 0 ); } userSeqsForDelete = userSeqsForDelete.filter(delbuddy => { let exist = false; for (const group of groupList) { if ( group.seq !== targetGroup.seq && group.userSeqs.filter(v => v === delbuddy).length > 0 ) { exist = true; break; } } return !exist; }); return [ update({ req: { groupSeq: targetGroup.seq, groupName: targetGroup.name, userSeqs: targetUserSeqs } }), updateMemberSuccess({ targetGroup, targetUserSeqs, userSeqsForDelete }) ]; }) ); }, { dispatch: false } ); moveMember$ = createEffect(() => this.actions$.pipe( ofType(moveMember), withLatestFrom(this.store.pipe(select(GroupSelector.groups))), exhaustMap(([action, groupList]) => { // copy to const toGroup = groupList.find(g => g.seq === action.toGroup.seq); let toTrgtUserSeqs = toGroup.userSeqs; action.targetUserSeq.forEach(trgtSeq => { if (toTrgtUserSeqs.indexOf(trgtSeq) > -1) { // ignore } else { toTrgtUserSeqs = toTrgtUserSeqs.concat(trgtSeq); } }); return this.groupProtocolService .update2({ groupSeq: action.toGroup.seq, groupName: action.toGroup.name, userSeqs: toTrgtUserSeqs }) .pipe( exhaustMap((resTo: GroupUpdateResponse) => { // del from const fromGroup = groupList.find( g => g.seq === action.fromGroup.seq ); const fromTrgtUserSeqs = fromGroup.userSeqs; return this.groupProtocolService .update2({ groupSeq: action.fromGroup.seq, groupName: action.fromGroup.name, userSeqs: fromTrgtUserSeqs.filter( trgtSeq => action.targetUserSeq.indexOf(trgtSeq) < 0 ) }) .pipe( map((resFrom: GroupUpdateResponse) => { return groups(); }), catchError(error => of(moveFromFailure({ error }))) ); }), catchError(error => of(moveToFailure({ error }))) ); }) ) ); del$ = createEffect(() => this.actions$.pipe( ofType(del), withLatestFrom( this.store.pipe(select(GroupSelector.groups)), this.store.pipe(select(DepartmentSelector.myDepartmentUserInfoList)) // 내 부서원 비교. ), exhaustMap(([action, groupList, myDeptUserList]) => { // Del Buddy const targetUserSeqs = action.group.userSeqs; let userSeqsForDelete: string[] = []; // 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다. if ( !!this.moduleConfig.useMyDeptGroup && this.moduleConfig.useMyDeptGroup ) { userSeqsForDelete = targetUserSeqs.filter( delbuddy => myDeptUserList.filter(deptUser => deptUser.seq === delbuddy) .length === 0 ); } userSeqsForDelete = targetUserSeqs.filter(delbuddy => { let exist = false; for (const group of groupList) { if ( group.seq !== action.group.seq && group.userSeqs.filter(v => v === delbuddy).length > 0 ) { exist = true; break; } } return !exist; }); if (userSeqsForDelete.length > 0) { // 즐겨찾기 해제. userSeqsForDelete.forEach(buddySeq => { this.store.dispatch( buddyActions.update({ req: { seq: Number(buddySeq), isFavorit: false } }) ); }); // 동료 삭제 this.store.dispatch( buddyActions.del({ req: { userSeqs: userSeqsForDelete } }) ); } return this.groupProtocolService .del({ groupSeq: action.group.seq }) .pipe( map((res: GroupDelResponse) => { return delSuccess({ res }); }), catchError(error => of(delFailure({ error }))) ); }) ) ); update$ = createEffect(() => this.actions$.pipe( ofType(update), map(action => action.req), concatMap(req => this.groupProtocolService.update2(req).pipe( map((res: GroupUpdateResponse) => { return groups(); }), catchError(error => of(updateFailure({ error }))) ) ) ) ); constructor( private actions$: Actions, private store: Store, @Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig, private syncProtocolService: SyncProtocolService, private groupProtocolService: GroupProtocolService ) {} }