diff --git a/apps/ngrx-1/src/app/app.component.ts b/apps/ngrx-1/src/app/app.component.ts index 924d07838..d60727550 100644 --- a/apps/ngrx-1/src/app/app.component.ts +++ b/apps/ngrx-1/src/app/app.component.ts @@ -9,6 +9,7 @@ import { Store } from '@ngrx/store'; import { loadActivities } from './store/activity/activity.actions'; import { ActivityType } from './store/activity/activity.model'; import { selectActivities } from './store/activity/activity.selectors'; +import { initApp } from './store/app/app.actions'; import { loadStatuses } from './store/status/status.actions'; import { selectAllTeachersByActivityType } from './store/status/status.selectors'; import { loadUsers } from './store/user/user.actions'; @@ -29,8 +30,7 @@ import { loadUsers } from './store/user/user.actions'; *ngFor=" let teacher of getAllTeachersForActivityType$(activity.type) | async - " - > + "> {{ teacher.name }} @@ -63,9 +63,7 @@ export class AppComponent implements OnInit { activities$ = this.store.select(selectActivities); ngOnInit(): void { - this.store.dispatch(loadActivities()); - this.store.dispatch(loadUsers()); - this.store.dispatch(loadStatuses()); + this.store.dispatch(initApp()); } getAllTeachersForActivityType$ = (type: ActivityType) => diff --git a/apps/ngrx-1/src/app/store/app/app.actions.ts b/apps/ngrx-1/src/app/store/app/app.actions.ts new file mode 100644 index 000000000..2538f285f --- /dev/null +++ b/apps/ngrx-1/src/app/store/app/app.actions.ts @@ -0,0 +1,3 @@ +import { createAction } from '@ngrx/store'; + +export const initApp = createAction('[AppComponent] initialize Application'); diff --git a/apps/ngrx-1/src/app/store/app/app.effects.ts b/apps/ngrx-1/src/app/store/app/app.effects.ts new file mode 100644 index 000000000..9fb01f3e0 --- /dev/null +++ b/apps/ngrx-1/src/app/store/app/app.effects.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { flatMap, mergeMap } from 'rxjs/operators'; +import * as AppActions from './app.actions'; +import * as ActivityActions from '../activity/activity.actions'; +import * as UserActions from '../user/user.actions'; + +@Injectable() +export class AppEffects { + initialiseApp$ = createEffect(() => + this.actions$.pipe( + ofType(AppActions.initApp), + mergeMap(() => [ + ActivityActions.loadActivities(), + UserActions.loadUsers(), + ]) + ) + ); + + constructor(private actions$: Actions) {} +} diff --git a/apps/ngrx-1/src/app/store/status/status.effects.ts b/apps/ngrx-1/src/app/store/status/status.effects.ts deleted file mode 100644 index 3459a5901..000000000 --- a/apps/ngrx-1/src/app/store/status/status.effects.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { Store } from '@ngrx/store'; -import { combineLatest, concatMap, map } from 'rxjs'; -import { selectActivities } from '../activity/activity.selectors'; -import { selectUser } from '../user/user.selectors'; -import * as StatusActions from './status.actions'; -import { Status } from './status.model'; - -@Injectable() -export class StatusEffects { - loadStatuses$ = createEffect(() => { - return this.actions$.pipe( - ofType(StatusActions.loadStatuses), - concatMap(() => - combineLatest([ - this.store.select(selectUser), - this.store.select(selectActivities), - ]).pipe( - map(([user, activities]): Status[] => { - if (user?.isAdmin) { - return activities.reduce( - (status: Status[], activity): Status[] => { - const index = status.findIndex( - (s) => s.name === activity.type - ); - if (index === -1) { - return [ - ...status, - { name: activity.type, teachers: [activity.teacher] }, - ]; - } else { - status[index].teachers.push(activity.teacher); - return status; - } - }, - [] - ); - } - return []; - }), - map((statuses) => StatusActions.loadStatusesSuccess({ statuses })) - ) - ) - ); - }); - - constructor(private actions$: Actions, private store: Store) {} -} diff --git a/apps/ngrx-1/src/app/store/status/status.reducer.ts b/apps/ngrx-1/src/app/store/status/status.reducer.ts deleted file mode 100644 index 1dd8ece05..000000000 --- a/apps/ngrx-1/src/app/store/status/status.reducer.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { createReducer, on } from '@ngrx/store'; -import { ActivityType, Person } from '../activity/activity.model'; -import * as StatusActions from './status.actions'; -import { Status } from './status.model'; - -export const statusFeatureKey = 'status'; - -export interface StatusState { - statuses: Status[]; - teachersMap: Map; -} - -export const initialState: StatusState = { - statuses: [], - teachersMap: new Map(), -}; - -export const statusReducer = createReducer( - initialState, - on(StatusActions.loadStatusesSuccess, (state, { statuses }): StatusState => { - const map = new Map(); - statuses.forEach((s) => map.set(s.name, s.teachers)); - return { - ...state, - statuses, - teachersMap: map, - }; - }) -); diff --git a/apps/ngrx-1/src/app/store/status/status.selectors.ts b/apps/ngrx-1/src/app/store/status/status.selectors.ts index 85b72f885..12fe69360 100644 --- a/apps/ngrx-1/src/app/store/status/status.selectors.ts +++ b/apps/ngrx-1/src/app/store/status/status.selectors.ts @@ -1,17 +1,39 @@ -import { createFeatureSelector, createSelector } from '@ngrx/store'; +import { createSelector } from '@ngrx/store'; import { ActivityType } from '../activity/activity.model'; -import { statusFeatureKey, StatusState } from './status.reducer'; - -export const selectStatusState = - createFeatureSelector(statusFeatureKey); +import { selectActivities } from '../activity/activity.selectors'; +import { selectUser } from '../user/user.selectors'; +import { Status } from './status.model'; export const selectStatuses = createSelector( - selectStatusState, - (state) => state.statuses + selectUser, + selectActivities, + (user, activities): Status[] => { + if (user?.isAdmin) { + return activities.reduce((status: Status[], activity): Status[] => { + const index = status.findIndex((s) => s.name === activity.type); + if (index === -1) { + return [ + ...status, + { name: activity.type, teachers: [activity.teacher] }, + ]; + } else { + status[index].teachers.push(activity.teacher); + return status; + } + }, []); + } + return []; + } ); +export const selectTeachersMap = createSelector(selectStatuses, (statuses) => { + const map = new Map(); + statuses.forEach((s) => map.set(s.name, s.teachers)); + return map; +}); + export const selectAllTeachersByActivityType = (name: ActivityType) => createSelector( - selectStatusState, - (state) => state.teachersMap.get(name) ?? [] + selectTeachersMap, + (teachersMap) => teachersMap.get(name) ?? [] ); diff --git a/apps/ngrx-1/src/main.ts b/apps/ngrx-1/src/main.ts index 343da9b64..a395c0729 100644 --- a/apps/ngrx-1/src/main.ts +++ b/apps/ngrx-1/src/main.ts @@ -8,11 +8,8 @@ import { activityFeatureKey, activityReducer, } from './app/store/activity/activity.reducer'; -import { StatusEffects } from './app/store/status/status.effects'; -import { - statusFeatureKey, - statusReducer, -} from './app/store/status/status.reducer'; +import { AppEffects } from './app/store/app/app.effects'; + import { UserEffects } from './app/store/user/user.effects'; import { userFeatureKey, userReducer } from './app/store/user/user.reducer'; import { environment } from './environments/environment'; @@ -22,7 +19,6 @@ if (environment.production) { } const reducers = { - [statusFeatureKey]: statusReducer, [activityFeatureKey]: activityReducer, [userFeatureKey]: userReducer, }; @@ -30,6 +26,6 @@ const reducers = { bootstrapApplication(AppComponent, { providers: [ provideStore(reducers), - provideEffects([ActivityEffects, UserEffects, StatusEffects]), + provideEffects([AppEffects, ActivityEffects, UserEffects]), ], });