From 3c93e247f8e177951783136bd1acee4a703f9107 Mon Sep 17 00:00:00 2001 From: ievavold <ievavold@wisc.edu> Date: Mon, 10 Jun 2019 09:57:31 -0500 Subject: [PATCH] move user preferences to core module --- src/app/app.component.ts | 6 ++++ src/app/app.module.ts | 10 ------- src/app/core/actions.ts | 20 +++++++++---- src/app/core/core.module.ts | 6 ++++ src/app/core/effects.ts | 19 +++++++++---- src/app/core/reducer.ts | 14 ++++++++-- src/app/dars/dars.module.ts | 3 ++ src/app/dars/store/effects.ts | 28 ++----------------- .../degree-planner/degree-planner.module.ts | 3 ++ .../store/effects/plan.effects.ts | 16 ++++------- src/app/degree-planner/store/reducer.ts | 2 +- src/app/degree-planner/store/selectors.ts | 1 - 12 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 3c9473c..e47a23e 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -9,6 +9,9 @@ import { } from '@angular/forms'; import { Course } from '@app/core/models/course'; import { DegreePlannerApiService } from '@app/degree-planner/services/api.service'; +import { Store } from '@ngrx/store'; +import { GlobalState } from './core/state'; +import { Initialize } from './core/actions'; @Component({ selector: 'cse-root', @@ -28,6 +31,7 @@ export class AppComponent implements OnInit { public dialog: MatDialog, private fb: FormBuilder, private api: DegreePlannerApiService, + private store: Store<GlobalState>, ) { this.subjectCode = new FormControl('', [Validators.required]); this.coursesForm = this.fb.group({ @@ -36,6 +40,8 @@ export class AppComponent implements OnInit { } ngOnInit() { + this.store.dispatch(new Initialize()); + this.api.getUserProfile().subscribe(profile => { const customEvent = new CustomEvent('myuw-login', { detail: { diff --git a/src/app/app.module.ts b/src/app/app.module.ts index eb358f3..32d6cb3 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -18,23 +18,13 @@ import { FeedbackDialogComponent } from './degree-planner/dialogs/feedback-dialo import { CreditOverloadDialogComponent } from './degree-planner/dialogs/credit-overload-dialog/credit-overload-dialog.component'; import { GoogleAnalyticsService } from './shared/services/google-analytics.service'; import { IE11WarningDialogComponent } from './degree-planner/dialogs/ie11-warning-dialog/ie11-warning-dialog.component'; -import { darsReducer } from './dars/store/reducer'; import { DARSModule } from './dars/dars.module'; import { DegreePlannerModule } from './degree-planner/degree-planner.module'; -import { preferencesReducer } from './core/reducer'; -import { UserPreferencesEffects } from './core/effects'; -import { EffectsModule } from '@ngrx/effects'; @NgModule({ imports: [ DARSModule, DegreePlannerModule, - StoreModule.forRoot({ - preferences: preferencesReducer, - degreePlanner: degreePlannerReducer, - dars: darsReducer, - }), - EffectsModule.forFeature([UserPreferencesEffects]), BrowserModule, BrowserAnimationsModule, HttpClientModule, diff --git a/src/app/core/actions.ts b/src/app/core/actions.ts index 0b224cb..44d6a52 100644 --- a/src/app/core/actions.ts +++ b/src/app/core/actions.ts @@ -1,20 +1,30 @@ import { Action } from '@ngrx/store'; import { UserPreferences } from '@app/core/models/user-preferences'; -export enum UserPreferencesActionTypes { +export enum CoreActionTypes { + Initialize = '[Core] Initialize', + + PopulateUserPreferences = '[User Preferences] Populate', UpdateUserPreferences = '[User Preferences] Update', + + DismissAlert = '[UI] Dismiss Alert', +} + +export class Initialize implements Action { + public readonly type = CoreActionTypes.Initialize; } -export enum NotificationActionTypes { - DismissAlert = '[UI] Dismiss alert', +export class InitializeUserPreferences implements Action { + public readonly type = CoreActionTypes.PopulateUserPreferences; + constructor(public payload: { preferences: UserPreferences }) {} } export class UpdateUserPreferences implements Action { - public readonly type = UserPreferencesActionTypes.UpdateUserPreferences; + public readonly type = CoreActionTypes.UpdateUserPreferences; constructor(public payload: Partial<UserPreferences>) {} } export class DismissAlert implements Action { - public readonly type = NotificationActionTypes.DismissAlert; + public readonly type = CoreActionTypes.DismissAlert; constructor(public payload: { key: string }) {} } diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 628a950..96a2b0f 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -7,12 +7,18 @@ import { environment } from './../../environments/environment'; import { SharedModule } from '../shared/shared.module'; import { NavigationComponent } from './navigation/navigation.component'; import { throwIfAlreadyLoaded } from './module-import-check'; +import { EffectsModule } from '@ngrx/effects'; +import { CoreEffects } from './effects'; +import { StoreModule } from '@ngrx/store'; +import { preferencesReducer } from './reducer'; @NgModule({ imports: [ CommonModule, // we use *ngFor RouterModule, // we use router-outlet and routerLink SharedModule, + StoreModule.forRoot({ preferences: preferencesReducer }), + EffectsModule.forFeature([CoreEffects]), ], exports: [NavigationComponent], declarations: [NavigationComponent], diff --git a/src/app/core/effects.ts b/src/app/core/effects.ts index 5a29880..bc43990 100644 --- a/src/app/core/effects.ts +++ b/src/app/core/effects.ts @@ -1,23 +1,32 @@ import { Injectable } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects'; -import { tap, withLatestFrom } from 'rxjs/operators'; +import { tap, withLatestFrom, flatMap, map } from 'rxjs/operators'; import { GlobalState } from '@app/core/state'; import { Store } from '@ngrx/store'; import { DegreePlannerApiService } from '@app/degree-planner/services/api.service'; -import { UpdateUserPreferences, UserPreferencesActionTypes } from './actions'; +import * as actions from './actions'; +import { CoreActionTypes } from './actions'; import { UserPreferences } from './models/user-preferences'; @Injectable() -export class UserPreferencesEffects { +export class CoreEffects { constructor( private actions$: Actions, private api: DegreePlannerApiService, private store$: Store<GlobalState>, ) {} + + @Effect() + initializeUserPreferences$ = this.actions$.pipe( + ofType(CoreActionTypes.Initialize), + flatMap(() => this.api.getUserPreferences()), + map(preferences => new actions.InitializeUserPreferences({ preferences })), + ); + @Effect({ dispatch: false }) updateUserPreferences$ = this.actions$.pipe( - ofType<UpdateUserPreferences>( - UserPreferencesActionTypes.UpdateUserPreferences, + ofType<actions.UpdateUserPreferences>( + CoreActionTypes.UpdateUserPreferences, ), withLatestFrom(this.store$), tap(([update, state]) => { diff --git a/src/app/core/reducer.ts b/src/app/core/reducer.ts index 0069409..2d69b13 100644 --- a/src/app/core/reducer.ts +++ b/src/app/core/reducer.ts @@ -1,13 +1,21 @@ -import { UserPreferencesActionTypes, UpdateUserPreferences } from './actions'; +import { CoreActionTypes, UpdateUserPreferences } from './actions'; +import * as actions from './actions'; import { INITIAL_PREFERENCES_STATE } from './state'; import { UserPreferences } from './models/user-preferences'; +type SupportedActions = + | actions.InitializeUserPreferences + | actions.UpdateUserPreferences; + export function preferencesReducer( state = INITIAL_PREFERENCES_STATE, - action: UpdateUserPreferences, + action: SupportedActions, ): UserPreferences { switch (action.type) { - case UserPreferencesActionTypes.UpdateUserPreferences: { + case CoreActionTypes.PopulateUserPreferences: { + return action.payload.preferences; + } + case CoreActionTypes.UpdateUserPreferences: { const update: UserPreferences = { ...state }; // Remove properties who's value is undefined diff --git a/src/app/dars/dars.module.ts b/src/app/dars/dars.module.ts index 1a2b72c..87605b0 100644 --- a/src/app/dars/dars.module.ts +++ b/src/app/dars/dars.module.ts @@ -8,9 +8,12 @@ import { DarsMetadataTableComponent } from './metadata-table/metadata-table.comp import { NewAuditOptionsComponent } from './dars-view/new-audit-options/new-audit-options.component'; import { MatStepperModule } from '@angular/material'; import { AlertContainerComponent } from '../shared/components/alert-container/alert-container.component'; +import { StoreModule } from '@ngrx/store'; +import { darsReducer } from './store/reducer'; @NgModule({ imports: [ + StoreModule.forFeature('dars', darsReducer), EffectsModule.forFeature([DARSEffects]), SharedModule, MatStepperModule, diff --git a/src/app/dars/store/effects.ts b/src/app/dars/store/effects.ts index 82b4b08..b8804d6 100644 --- a/src/app/dars/store/effects.ts +++ b/src/app/dars/store/effects.ts @@ -1,4 +1,3 @@ -import { visibleAudit } from './selectors'; import { UpdateUserPreferences } from './../../core/actions'; import { GlobalState } from '@app/core/state'; import { Store } from '@ngrx/store'; @@ -7,12 +6,10 @@ 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, switchMap, mergeMap } from 'rxjs/operators'; +import { flatMap, map } from 'rxjs/operators'; import { DarsApiService } from '../services/api.service'; -import { of } from 'rxjs'; import { Alert, DarsDisclaimerAlert } from '@app/core/models/alert'; import { DegreePlannerApiService } from '@app/degree-planner/services/api.service'; -import { INITIAL_DARS_STATE } from './state'; @Injectable() export class DARSEffects { @@ -34,7 +31,7 @@ export class DARSEffects { }); }), - flatMap(({ metadata, userPreferences }) => { + map(({ metadata, userPreferences }) => { const alerts: Alert[] = []; if (userPreferences.darsHasDismissedDisclaimer !== true) { alerts.push( @@ -48,27 +45,8 @@ export class DARSEffects { ); } - return forkJoinWithKeys({ - metadata: of(metadata), - visibleAudit: of({}), - alerts: of(alerts), - }).pipe( - switchMap(payload => { - return [ - new darsActions.AddAuditMetadata({ metadata }), - new UpdateUserPreferences(userPreferences), - ]; - }), - ); + return new darsActions.AddAuditMetadata({ metadata }); }), - - // catchError(() => { - // return of( - // new darsActions.ErrorLoadingMetadata({ - // message: 'Unable to load audit metadata. Please try again', - // }), - // ); - // }), ); @Effect() diff --git a/src/app/degree-planner/degree-planner.module.ts b/src/app/degree-planner/degree-planner.module.ts index 1a58879..827396c 100644 --- a/src/app/degree-planner/degree-planner.module.ts +++ b/src/app/degree-planner/degree-planner.module.ts @@ -16,11 +16,14 @@ import { DegreePlanEffects } from './store/effects/plan.effects'; import { NoteEffects } from './store/effects/note.effects'; import { CourseEffects } from './store/effects/course.effects'; import { ErrorEffects } from './store/effects/error.effects'; +import { StoreModule } from '@ngrx/store'; +import { degreePlannerReducer } from './store/reducer'; @NgModule({ imports: [ SharedModule, DragDropModule, + StoreModule.forFeature('degreePlanner', degreePlannerReducer), EffectsModule.forRoot([ DegreePlanEffects, NoteEffects, diff --git a/src/app/degree-planner/store/effects/plan.effects.ts b/src/app/degree-planner/store/effects/plan.effects.ts index 9301e8d..fec0b33 100644 --- a/src/app/degree-planner/store/effects/plan.effects.ts +++ b/src/app/degree-planner/store/effects/plan.effects.ts @@ -9,7 +9,6 @@ import { withLatestFrom, catchError, filter, - switchMap, } from 'rxjs/operators'; import { GlobalState } from '@app/core/state'; import { Store } from '@ngrx/store'; @@ -112,15 +111,12 @@ export class DegreePlanEffects { allDegreePlans: of(allDegreePlans), alerts: of(alerts), }).pipe( - switchMap(payload => { - return [ - new InitialLoadSuccess({ - ...INITIAL_DEGREE_PLANNER_STATE, - ...payload, - isLoadingPlan: false, - }), - new UpdateUserPreferences(userPreferences), - ]; + map(payload => { + return new InitialLoadSuccess({ + ...INITIAL_DEGREE_PLANNER_STATE, + ...payload, + isLoadingPlan: false, + }); }), ); }), diff --git a/src/app/degree-planner/store/reducer.ts b/src/app/degree-planner/store/reducer.ts index 1770f8f..1f16a12 100644 --- a/src/app/degree-planner/store/reducer.ts +++ b/src/app/degree-planner/store/reducer.ts @@ -144,7 +144,7 @@ export function degreePlannerReducer( return newState; } - case globalActions.NotificationActionTypes.DismissAlert: { + case globalActions.CoreActionTypes.DismissAlert: { const keyToRemove = action.payload.key; const newAlerts = state.alerts.filter(({ key }) => key !== keyToRemove); return { ...state, alerts: newAlerts }; diff --git a/src/app/degree-planner/store/selectors.ts b/src/app/degree-planner/store/selectors.ts index a7677dc..677134e 100644 --- a/src/app/degree-planner/store/selectors.ts +++ b/src/app/degree-planner/store/selectors.ts @@ -4,7 +4,6 @@ import { DegreePlannerState } from './state'; import { TermCode } from '@app/degree-planner/shared/term-codes/termcode'; import { YearCode } from '@app/degree-planner/shared/term-codes/yearcode'; import { YearMapping, Year } from '@app/core/models/year'; -import { UserPreferences } from '@app/core/models/user-preferences'; export const getDegreePlannerState = ({ degreePlanner }: GlobalState) => { return degreePlanner; -- GitLab