import { UpdateUserPreferences } from './../../core/actions'; import { GlobalState } from '@app/core/state'; import { Store } from '@ngrx/store'; import { forkJoinWithKeys } from '@app/degree-planner/shared/utils'; import { Injectable } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; import { DarsActionTypes } from '@app/dars/store/actions'; import * as darsActions from '@app/dars/store/actions'; import { flatMap, map, catchError, withLatestFrom, tap } from 'rxjs/operators'; import { DarsApiService } from '../services/api.service'; import { Alert, DarsDisclaimerAlert } from '@app/core/models/alert'; import { DegreePlannerApiService } from '@app/degree-planner/services/api.service'; import { of } from 'rxjs'; import * as selectors from '@app/dars/store/selectors'; import { groupAuditMetadata } from './utils'; import { MatSnackBar } from '@angular/material'; import { TermCodeFactory } from '@app/degree-planner/services/termcode.factory'; @Injectable() export class DARSEffects { constructor( private actions$: Actions, private api: DarsApiService, private degreeAPI: DegreePlannerApiService, private store$: Store<GlobalState>, private snackBar: MatSnackBar, private termCodeService: TermCodeFactory, ) {} @Effect() load$ = this.actions$.pipe( ofType(DarsActionTypes.StartLoadingDARSView), withLatestFrom(this.store$.select(selectors.getDARSState)), flatMap(([_, state]) => { if (state.hasLoaded) { return of(new darsActions.DoneLoadingDARSView(state)); } return forkJoinWithKeys({ degreePlans: this.degreeAPI.getAllDegreePlans(), degreePrograms: this.api.getStudentDegreePrograms(), metadata: this.api.getAudits(), userPreferences: this.degreeAPI.getUserPreferences(), activeTermCodes: this.degreeAPI.getActiveTermCodes(), }).pipe( map(tuple => { if (this.termCodeService.isNotInitialized()) { this.termCodeService.setActiveTermCodes(tuple.activeTermCodes); } const alerts: Alert[] = []; if (tuple.userPreferences.darsHasDismissedDisclaimer !== true) { alerts.push( new DarsDisclaimerAlert(() => { this.store$.dispatch( new UpdateUserPreferences({ darsHasDismissedDisclaimer: true, }), ); }), ); } return new darsActions.DoneLoadingDARSView({ hasLoaded: true, degreePlans: tuple.degreePlans, degreePrograms: tuple.degreePrograms, metadata: { status: 'Loaded', outstanding: { program: 0, whatIf: 0 }, pending: { program: 0, whatIf: 0 }, ...groupAuditMetadata(tuple.metadata, tuple.degreePrograms), }, audits: {}, alerts, }); }), ); }), catchError(() => { return of( new darsActions.ErrorLoadingDARSView({ message: 'Error loading DARS information. Please try again', }), ); }), ); @Effect() refreshMetadata$ = this.actions$.pipe( ofType<darsActions.RefreshMetadata>(DarsActionTypes.RefreshMetadata), flatMap(action => this.api.getAudits().pipe( map(metadata => new darsActions.DoneRefreshingMetadata(metadata)), tap(() => action.payload && action.payload.callback()), catchError(() => { return of( new darsActions.ErrorRefreshingMetadata({ message: 'Error loading metadata. Please try again', }), ); }), ), ), ); @Effect() getAudit$ = this.actions$.pipe( ofType<darsActions.StartLoadingAudit>(DarsActionTypes.StartLoadingAudit), withLatestFrom(this.store$.select(selectors.getAudits)), flatMap(([action, audits]) => { const metadata = action.payload; const darsDegreeAuditReportId = metadata.darsDegreeAuditReportId; const info = audits[darsDegreeAuditReportId]; if (info !== undefined && info.status === 'Loaded') { return of( new darsActions.DoneLoadingAudit({ metadata, audit: info.audit }), ); } else { return this.api.getAudit(darsDegreeAuditReportId).pipe( map(audit => { return new darsActions.DoneLoadingAudit({ metadata, audit }); }), ); } }), ); @Effect() newAudit$ = this.actions$.pipe( ofType(DarsActionTypes.StartSendingAudit), flatMap((action: darsActions.StartSendingAudit) => { const auditType = action.payload.auditType; return this.api.newAudit({ ...action.payload }).pipe( map(({ darsJobId }) => { return new darsActions.DoneSendingAudit({ auditType, darsJobId }); }), catchError(_err => { this.snackBar.open('Unable to generate audit'); return of( new darsActions.ErrorSendingAudit({ auditType, message: 'Unable to generate audit', }), ); }), ); }), ); @Effect() updateAudits$ = this.actions$.pipe( ofType(DarsActionTypes.DoneSendingAudit), map(() => new darsActions.RefreshMetadata()), ); }