From 7b393e3ab942bdf325f0d1de42a1539ead354021 Mon Sep 17 00:00:00 2001 From: Irv Lennert Date: Sun, 7 Jul 2019 20:58:12 -0400 Subject: [PATCH] upgrade to NgRx 8 with factory methods --- README.md | 5 - package-lock.json | 36 ++--- package.json | 12 +- src/app/app.component.ts | 17 +-- src/app/app.module.ts | 20 +-- src/app/auth/auth.actions.ts | 36 ++--- src/app/auth/auth.effects.spec.ts | 2 +- src/app/auth/auth.effects.ts | 61 ++++---- src/app/auth/auth.guard.ts | 14 +- src/app/auth/auth.module.ts | 22 +-- src/app/auth/auth.reducer.spec.ts | 4 +- src/app/auth/auth.reducer.ts | 41 +++-- src/app/auth/auth.selectors.ts | 4 +- src/app/auth/auth.service.ts | 16 +- src/app/auth/login/login.component.ts | 21 +-- .../course-dialog/course-dialog.component.ts | 27 ++-- src/app/courses/course.actions.ts | 144 ++++++------------ src/app/courses/course.effects.ts | 99 ++++++------ src/app/courses/course.reducers.ts | 61 +++----- src/app/courses/course.selectors.ts | 18 +-- src/app/courses/course/course.component.ts | 26 ++-- src/app/courses/courses.module.ts | 54 ++++--- src/app/courses/home/home.component.ts | 11 +- src/app/courses/lessons.reducers.ts | 69 +++------ src/app/courses/model/course.ts | 10 +- src/app/courses/services/course.resolver.ts | 25 ++- src/app/courses/services/courses.service.ts | 28 ++-- .../courses/services/lessons.datasource.ts | 20 ++- src/app/reducers/index.ts | 2 +- 29 files changed, 381 insertions(+), 524 deletions(-) diff --git a/README.md b/README.md index 94df6bf..0a9eaea 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ This course repository is updated to Angular v8, and there is a package-lock.js ![Angular Ngrx Course](https://s3-us-west-1.amazonaws.com/angular-university/course-images/angular-ngrx-course.png) - # Installation pre-requisites IMPORTANT: Please use NPM 5 or above, to make sure the package-lock.json is used. @@ -20,14 +19,12 @@ For running this project we need and npm installed on our machine. These are som - [Install Node and NPM on Linux](https://www.youtube.com/watch?v=yUdHk-Dk_BY) - [Install Node and NPM on Mac](https://www.youtube.com/watch?v=Imj8PgG3bZU) - # Installing the Angular CLI With the following command the angular-cli will be installed globally in your machine: npm install -g @angular/cli - # How To install this repository We can install the master branch using the following commands: @@ -63,8 +60,6 @@ To run the frontend part of our code, we will use the Angular CLI: The application is visible at port 4200: [http://localhost:4200](http://localhost:4200) - - # Important This repository has multiple branches, have a look at the beginning of each section to see the name of the branch. diff --git a/package-lock.json b/package-lock.json index 56f9624..f64e3f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -427,35 +427,35 @@ } }, "@ngrx/effects": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-7.4.0.tgz", - "integrity": "sha512-YjgB17WnLCBDPjAkHduKWsLFSGLZryPaTjY3EIvMF+WTRPDlgC5SAv2n7p3YIei6g6IYcEvOwLWBqZHFUXTgBw==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-8.0.1.tgz", + "integrity": "sha512-f15SjzZ670HdHVpu3byOiP5R6MOxh/DMQgP8PynKtmadmkKkM69imGsp+8qDEQNABw5O8oJGAn8aLm76QGPnjQ==" }, "@ngrx/entity": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@ngrx/entity/-/entity-7.4.0.tgz", - "integrity": "sha512-aFRDTNp6IFkYFlP9gV6hgNgtDYot9KYF8WVbaQTao9ihmdPumMBOCeRttPPiHS/cU41w9nW3xF53NgxQPnEiQA==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@ngrx/entity/-/entity-8.0.1.tgz", + "integrity": "sha512-mdsrKHxo/uYP+sIjgIWmVbIKrLpqvcUlUamV+QfMPTxQXN9nmFsvNsemcOHN1fCklaGWzLo0tfoF/NVwdhJb5w==" }, "@ngrx/router-store": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@ngrx/router-store/-/router-store-7.4.0.tgz", - "integrity": "sha512-ZpwTO1/ha3pxO7NV3jIfnwipBN1A719IjAOgrcmI8Ut06VH3HY/7JVFTkwLN/FyuHvl4EOlAVYmMAblmrymUWA==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@ngrx/router-store/-/router-store-8.0.1.tgz", + "integrity": "sha512-ItgyqjPtjpUmMRKe48pyBMzrntimJwImttxqRa0uMWooPGIJB6zAmbgjn2AtyUqX63IRl8BGT8V3pJ4FLrxIow==" }, "@ngrx/schematics": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@ngrx/schematics/-/schematics-7.4.0.tgz", - "integrity": "sha512-H0endOV7nYWDaFH7mOJAWFGVymlOYynwjEHZPWeLQFZIFUaekKOrgrHpc+rygu1Hov5ww8lNXHgAunm4vpvwMA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@ngrx/schematics/-/schematics-8.0.1.tgz", + "integrity": "sha512-BnHYRHkzAqXKDRQW5WZoSOwxJkHmwsd/bEJ5wRinplVRSUJY0BYgCVe1by1hj37/FAsRH5E6WBtoOgUyn0i/MQ==", "dev": true }, "@ngrx/store": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-7.4.0.tgz", - "integrity": "sha512-kwTUHgfgBeAL4RQBjZO46z9v4Xzg8PXAgY4WwXdt3zUk1tF4ZvijMleFvFRUoiJJfxF/UM6jgIZ/yGrX2dXQuA==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-8.0.1.tgz", + "integrity": "sha512-B6HY8TCFZ4+bUfJAJatF42+F33Qboo7zKc+gxTi6eEioKvNqWkb22K4De5HV2j/l/blXvMOPMSO1Rf/sGqID0w==" }, "@ngrx/store-devtools": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-7.4.0.tgz", - "integrity": "sha512-ZmPpquprBYUozbLuLMLZzUhI+LnMNGMNg8x1ij9yDxXWQADcJm1Zu7kouYE1r5SoCYxKfwJ3Ia1VQfS3A5S8dw==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-8.0.1.tgz", + "integrity": "sha512-TxOksSARaQ1hCZM0/qMCun6axbSFuhSEmuW9YLRhuU5m3gvJN4cr5tk960DDVGl8/06YX6Q2CQ7uIgx5qCwbsg==" }, "@ngtools/webpack": { "version": "8.0.1", diff --git a/package.json b/package.json index 58f4405..2f5e052 100644 --- a/package.json +++ b/package.json @@ -25,11 +25,11 @@ "@angular/platform-browser": "^8.0.0", "@angular/platform-browser-dynamic": "^8.0.0", "@angular/router": "^8.0.0", - "@ngrx/effects": "^7.0.0", - "@ngrx/entity": "^7.0.0", - "@ngrx/router-store": "^7.0.0", - "@ngrx/store": "^7.0.0", - "@ngrx/store-devtools": "^7.0.0", + "@ngrx/effects": "^8.0.0", + "@ngrx/entity": "^8.0.0", + "@ngrx/router-store": "^8.0.0", + "@ngrx/store": "^8.0.0", + "@ngrx/store-devtools": "^8.0.0", "body-parser": "^1.18.2", "core-js": "^2.4.1", "express": "^4.16.2", @@ -44,7 +44,7 @@ "@angular/cli": "^8.0.1", "@angular/compiler-cli": "^8.0.0", "@angular/language-service": "^8.0.0", - "@ngrx/schematics": "^7.0.0", + "@ngrx/schematics": "^8.0.0", "@types/express": "^4.0.39", "@types/jasmine": "~2.5.53", "@types/jasminewd2": "~2.0.2", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 673cd9e..ae5447c 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,11 +1,10 @@ -import {Component, OnInit} from '@angular/core'; -import {select, Store} from "@ngrx/store"; -import {Observable} from "rxjs"; -import {AppState} from './reducers'; -import {Logout} from './auth/auth.actions'; -import {map} from 'rxjs/operators'; -import {isLoggedIn, isLoggedOut} from './auth/auth.selectors'; -import {Router} from '@angular/router'; +import { Component, OnInit } from '@angular/core'; +import { select, Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; +import { AppState } from './reducers'; +import * as authApiActions from './auth/auth.actions'; +import { isLoggedIn, isLoggedOut } from './auth/auth.selectors'; +import { Router } from '@angular/router'; @Component({ selector: 'app-root', @@ -39,7 +38,7 @@ export class AppComponent implements OnInit { logout() { - this.store.dispatch(new Logout()); + this.store.dispatch(authApiActions.logout()); } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 1ac94fe..a70c37e 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -2,21 +2,21 @@ import {BrowserModule} from '@angular/platform-browser'; import {NgModule} from '@angular/core'; import {AppComponent} from './app.component'; -import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {MatMenuModule} from '@angular/material/menu'; import {MatIconModule} from '@angular/material/icon'; -import { MatListModule } from "@angular/material/list"; -import { MatSidenavModule } from "@angular/material/sidenav"; -import { MatToolbarModule } from "@angular/material/toolbar"; -import {HttpClientModule} from "@angular/common/http"; +import { MatListModule } from '@angular/material/list'; +import { MatSidenavModule } from '@angular/material/sidenav'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import {HttpClientModule} from '@angular/common/http'; -import {RouterModule, Routes} from "@angular/router"; -import {AuthModule} from "./auth/auth.module"; +import {RouterModule, Routes} from '@angular/router'; +import {AuthModule} from './auth/auth.module'; import { StoreModule } from '@ngrx/store'; import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { environment } from '../environments/environment'; -import {RouterStateSerializer, StoreRouterConnectingModule} from "@ngrx/router-store"; +import {RouterStateSerializer, StoreRouterConnectingModule} from '@ngrx/router-store'; import { EffectsModule } from '@ngrx/effects'; import { reducers, metaReducers } from './reducers'; @@ -31,7 +31,7 @@ const routes: Routes = [ canActivate: [AuthGuard], }, { - path: "**", + path: '**', redirectTo: '/' } ]; @@ -55,7 +55,7 @@ const routes: Routes = [ StoreModule.forRoot(reducers, { metaReducers }), !environment.production ? StoreDevtoolsModule.instrument() : [], EffectsModule.forRoot([]), - StoreRouterConnectingModule.forRoot({stateKey:'router'}) + StoreRouterConnectingModule.forRoot({stateKey: 'router'}) ], providers: [ { provide: RouterStateSerializer, useClass: CustomSerializer } diff --git a/src/app/auth/auth.actions.ts b/src/app/auth/auth.actions.ts index 04457fd..93085f5 100644 --- a/src/app/auth/auth.actions.ts +++ b/src/app/auth/auth.actions.ts @@ -1,30 +1,12 @@ -import { Action } from '@ngrx/store'; -import {User} from '../model/user.model'; +import { createAction } from '@ngrx/store'; +import { User } from '../model/user.model'; +export const login = createAction( + '[Auth/API] Login Success', + (user: User) => ({ user }) +); -export enum AuthActionTypes { - LoginAction = '[Login] Action', - LogoutAction = '[Logout] Action', -} - - -export class Login implements Action { - - readonly type = AuthActionTypes.LoginAction; - - constructor(public payload: {user: User}) { - - } -} - - -export class Logout implements Action { - - readonly type = AuthActionTypes.LogoutAction; - - -} - - -export type AuthActions = Login | Logout; +export const logout = createAction( + '[Auth/API] Logout Success' +); diff --git a/src/app/auth/auth.effects.spec.ts b/src/app/auth/auth.effects.spec.ts index 77902a0..690642c 100644 --- a/src/app/auth/auth.effects.spec.ts +++ b/src/app/auth/auth.effects.spec.ts @@ -1,6 +1,6 @@ import { TestBed, inject } from '@angular/core/testing'; import { provideMockActions } from '@ngrx/effects/testing'; -import { Observable } from 'rxjs/Observable'; +import { Observable } from 'rxjs'; import { AuthEffects } from './auth.effects'; diff --git a/src/app/auth/auth.effects.ts b/src/app/auth/auth.effects.ts index 8fd2000..296c7aa 100644 --- a/src/app/auth/auth.effects.ts +++ b/src/app/auth/auth.effects.ts @@ -1,49 +1,42 @@ import { Injectable } from '@angular/core'; -import {Actions, Effect, ofType} from '@ngrx/effects'; -import {AuthActionTypes, Login, Logout} from './auth.actions'; -import {tap} from 'rxjs/operators'; -import {Router} from '@angular/router'; -import {defer, of} from 'rxjs'; - +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import * as authApiActions from './auth.actions'; +import { tap } from 'rxjs/operators'; +import { Router } from '@angular/router'; +import { defer, of } from 'rxjs'; @Injectable() export class AuthEffects { - @Effect({dispatch:false}) - login$ = this.actions$.pipe( - ofType(AuthActionTypes.LoginAction), - tap(action => localStorage.setItem("user", JSON.stringify(action.payload.user))) + loginSuccess$ = createEffect(() => + this.actions$.pipe( + ofType(authApiActions.login), + tap(action => localStorage.setItem('user', JSON.stringify(action.user))) + ), + { dispatch: false } ); - @Effect({dispatch:false}) - logout$ = this.actions$.pipe( - ofType(AuthActionTypes.LogoutAction), - tap(() => { - - localStorage.removeItem("user"); - this.router.navigateByUrl('/login'); - - }) + logoutSuccess$ = createEffect(() => + this.actions$.pipe( + ofType(authApiActions.logout), + tap(() => { + localStorage.removeItem('user'); + this.router.navigateByUrl('./login'); + }) + ), + { dispatch: false } ); - @Effect() - init$ = defer(() => { - - const userData = localStorage.getItem("user"); + init$ = createEffect(() => defer(() => { + const userData = localStorage.getItem('user'); if (userData) { - return of(new Login({user:JSON.parse(userData)})); - } - else { - return of(new Logout()); + return of(authApiActions.login(JSON.parse(userData))); + } else { + return of(authApiActions.logout()); } + })); - }); - - constructor(private actions$: Actions, private router:Router) { - - + constructor(private actions$: Actions, private router: Router) { } - - } diff --git a/src/app/auth/auth.guard.ts b/src/app/auth/auth.guard.ts index 168810f..008464f 100644 --- a/src/app/auth/auth.guard.ts +++ b/src/app/auth/auth.guard.ts @@ -1,10 +1,10 @@ -import {Injectable} from '@angular/core'; -import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router'; -import {Observable} from 'rxjs'; -import {select, Store} from '@ngrx/store'; -import {AppState} from '../reducers'; -import {isLoggedIn} from './auth.selectors'; -import {tap} from 'rxjs/operators'; +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; +import { Observable } from 'rxjs'; +import { select, Store } from '@ngrx/store'; +import { AppState } from '../reducers'; +import { isLoggedIn } from './auth.selectors'; +import { tap } from 'rxjs/operators'; diff --git a/src/app/auth/auth.module.ts b/src/app/auth/auth.module.ts index 6dd59d9..a59f5e1 100644 --- a/src/app/auth/auth.module.ts +++ b/src/app/auth/auth.module.ts @@ -1,15 +1,15 @@ -import {ModuleWithProviders, NgModule} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {LoginComponent} from './login/login.component'; -import {MatCardModule} from "@angular/material/card"; -import { MatInputModule } from "@angular/material/input"; -import {RouterModule} from "@angular/router"; -import {ReactiveFormsModule} from "@angular/forms"; -import {MatButtonModule} from "@angular/material/button"; +import { ModuleWithProviders, NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { LoginComponent } from './login/login.component'; +import { MatCardModule } from '@angular/material/card'; +import { MatInputModule } from '@angular/material/input'; +import { RouterModule } from '@angular/router'; +import { ReactiveFormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; import { StoreModule } from '@ngrx/store'; -import {AuthService} from "./auth.service"; +import { AuthService } from './auth.service'; import * as fromAuth from './auth.reducer'; -import {AuthGuard} from './auth.guard'; +import { AuthGuard } from './auth.guard'; import { EffectsModule } from '@ngrx/effects'; import { AuthEffects } from './auth.effects'; @@ -37,6 +37,6 @@ export class AuthModule { AuthService, AuthGuard ] - } + }; } } diff --git a/src/app/auth/auth.reducer.spec.ts b/src/app/auth/auth.reducer.spec.ts index 3b6d436..6a140af 100644 --- a/src/app/auth/auth.reducer.spec.ts +++ b/src/app/auth/auth.reducer.spec.ts @@ -1,11 +1,11 @@ -import { authReducer, initialAuthState } from './auth.reducer'; +import { reducer, initialAuthState } from './auth.reducer'; describe('Auth Reducer', () => { describe('unknown action', () => { it('should return the initial state', () => { const action = {} as any; - const result = authReducer(initialAuthState, action); + const result = reducer(initialAuthState, action); expect(result).toBe(initialAuthState); }); diff --git a/src/app/auth/auth.reducer.ts b/src/app/auth/auth.reducer.ts index d670b51..4066b96 100644 --- a/src/app/auth/auth.reducer.ts +++ b/src/app/auth/auth.reducer.ts @@ -1,11 +1,12 @@ -import { Action } from '@ngrx/store'; -import {User} from '../model/user.model'; -import {AuthActions, AuthActionTypes} from './auth.actions'; +import { Action, createReducer, on } from '@ngrx/store'; +import { User } from '../model/user.model'; + +import * as authApiActions from './auth.actions'; export interface AuthState { - loggedIn: boolean, - user: User + loggedIn: boolean; + user: User; } export const initialAuthState: AuthState = { @@ -13,23 +14,17 @@ export const initialAuthState: AuthState = { user: undefined }; -export function authReducer(state = initialAuthState, - action: AuthActions): AuthState { - switch (action.type) { - - case AuthActionTypes.LoginAction: - return { - loggedIn: true, - user: action.payload.user - }; +export const reducer = createReducer( + initialAuthState, + on(authApiActions.login, (state, { user }) => ({ + ...state, + loggedIn: true, + user + })), + on(authApiActions.logout, () => initialAuthState) +); - case AuthActionTypes.LogoutAction: - return { - loggedIn: false, - user: undefined - }; - - default: - return state; - } +export function authReducer(state = initialAuthState, + action: Action): AuthState { + return reducer(state, action); } diff --git a/src/app/auth/auth.selectors.ts b/src/app/auth/auth.selectors.ts index dabfb48..59185d3 100644 --- a/src/app/auth/auth.selectors.ts +++ b/src/app/auth/auth.selectors.ts @@ -1,7 +1,9 @@ import {createSelector} from '@ngrx/store'; +import { AuthState } from './auth.reducer'; -export const selectAuthState = state => state.auth; + +export const selectAuthState = state => state.auth; export const isLoggedIn = createSelector( diff --git a/src/app/auth/auth.service.ts b/src/app/auth/auth.service.ts index abcf54c..a3260dd 100644 --- a/src/app/auth/auth.service.ts +++ b/src/app/auth/auth.service.ts @@ -1,7 +1,7 @@ -import {Injectable} from "@angular/core"; -import {HttpClient} from "@angular/common/http"; -import {Observable} from "rxjs"; -import {User} from "../model/user.model"; +import {Injectable} from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import {Observable} from 'rxjs'; +import {User} from '../model/user.model'; @@ -9,12 +9,10 @@ import {User} from "../model/user.model"; @Injectable() export class AuthService { - constructor(private http:HttpClient) { - + constructor(private http: HttpClient) { } - login(email:string, password:string): Observable { - return this.http.post('/api/login', {email,password}); + login(email: string, password: string): Observable { + return this.http.post('/api/login', {email, password}); } - } diff --git a/src/app/auth/login/login.component.ts b/src/app/auth/login/login.component.ts index ea4fe15..a34a504 100644 --- a/src/app/auth/login/login.component.ts +++ b/src/app/auth/login/login.component.ts @@ -1,16 +1,17 @@ import { Component, OnInit, ViewEncapsulation } from '@angular/core'; -import {FormBuilder, FormGroup, Validators} from "@angular/forms"; +import {FormBuilder, FormGroup, Validators} from '@angular/forms'; -import {Store} from "@ngrx/store"; +import {Store} from '@ngrx/store'; -import {AuthService} from "../auth.service"; -import {tap} from "rxjs/operators"; -import {noop} from "rxjs"; -import {Router} from "@angular/router"; +import {AuthService} from '../auth.service'; +import {tap} from 'rxjs/operators'; +import {noop} from 'rxjs'; +import {Router} from '@angular/router'; import {AppState} from '../../reducers'; -import {Login} from '../auth.actions'; +import * as authApiActions from '../auth.actions'; @Component({ +// tslint:disable-next-line: component-selector selector: 'login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] @@ -20,9 +21,9 @@ export class LoginComponent implements OnInit { form: FormGroup; constructor( - private fb:FormBuilder, + private fb: FormBuilder, private auth: AuthService, - private router:Router, + private router: Router, private store: Store) { this.form = fb.group({ @@ -44,7 +45,7 @@ export class LoginComponent implements OnInit { .pipe( tap(user => { - this.store.dispatch(new Login({user})); + this.store.dispatch(authApiActions.login(user)); this.router.navigateByUrl('/courses'); diff --git a/src/app/courses/course-dialog/course-dialog.component.ts b/src/app/courses/course-dialog/course-dialog.component.ts index 3e4fee7..d5b91d8 100644 --- a/src/app/courses/course-dialog/course-dialog.component.ts +++ b/src/app/courses/course-dialog/course-dialog.component.ts @@ -1,32 +1,33 @@ import {Component, Inject, OnInit, ViewEncapsulation} from '@angular/core'; -import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog"; -import {FormBuilder, Validators, FormGroup} from "@angular/forms"; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import {FormBuilder, Validators, FormGroup} from '@angular/forms'; import * as moment from 'moment'; -import {Course} from "../model/course"; -import {CoursesService} from "../services/courses.service"; -import {AppState} from "../../reducers"; -import {Store} from "@ngrx/store"; -import {Update} from "@ngrx/entity"; -import {CourseSaved} from '../course.actions'; +import {Course} from '../model/course'; +import {CoursesService} from '../services/courses.service'; +import {AppState} from '../../reducers'; +import {Store} from '@ngrx/store'; +import {Update} from '@ngrx/entity'; +import * as courseActions from '../course.actions'; @Component({ +// tslint:disable-next-line: component-selector selector: 'course-dialog', templateUrl: './course-dialog.component.html', styleUrls: ['./course-dialog.component.css'] }) export class CourseDialogComponent implements OnInit { - courseId:number; + courseId: number; form: FormGroup; - description:string; + description: string; constructor( private store: Store, private coursesService: CoursesService, private fb: FormBuilder, private dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) course:Course ) { + @Inject(MAT_DIALOG_DATA) course: Course ) { this.courseId = course.id; @@ -36,7 +37,7 @@ export class CourseDialogComponent implements OnInit { this.form = fb.group({ description: [course.description, Validators.required], category: [course.category, Validators.required], - longDescription: [course.longDescription,Validators.required], + longDescription: [course.longDescription, Validators.required], promo: [course.promo, []] }); @@ -61,7 +62,7 @@ export class CourseDialogComponent implements OnInit { changes }; - this.store.dispatch(new CourseSaved({course})); + this.store.dispatch(courseActions.courseSaved(course)); this.dialogRef.close(); } diff --git a/src/app/courses/course.actions.ts b/src/app/courses/course.actions.ts index bd9f842..f637774 100644 --- a/src/app/courses/course.actions.ts +++ b/src/app/courses/course.actions.ts @@ -1,103 +1,49 @@ -import {Action} from '@ngrx/store'; -import {Course} from './model/course'; -import {Update} from '@ngrx/entity'; -import {Lesson} from './model/lesson'; +import { createAction } from '@ngrx/store'; +import { Update } from '@ngrx/entity'; -export enum CourseActionTypes { - CourseRequested = '[View Course Page] Course Requested', - CourseLoaded = '[Courses API] Course Loaded', - AllCoursesRequested = '[Courses Home Page] All Courses Requested', - AllCoursesLoaded = '[Courses API] All Courses Loaded', - CourseSaved = '[Edit Course Dialog] Course Saved', - LessonsPageRequested = '[Course Landing Page] Lessons Page Requested', - LessonsPageLoaded = '[Courses API] Lessons Page Loaded', - LessonsPageCancelled = '[Courses API] Lessons Page Cancelled' -} +import { Course } from './model/course'; +import { Lesson } from './model/lesson'; export interface PageQuery { - pageIndex: number; - pageSize:number; -} - -export class LessonsPageRequested implements Action { - - readonly type = CourseActionTypes.LessonsPageRequested; - - constructor(public payload: {courseId:number, page:PageQuery}) {} - -} - -export class LessonsPageLoaded implements Action { - - readonly type = CourseActionTypes.LessonsPageLoaded; - - constructor(public payload:{lessons: Lesson[]}) {} - -} - -export class LessonsPageCancelled implements Action { - - readonly type = CourseActionTypes.LessonsPageCancelled; - -} - - -export class CourseRequested implements Action { - - readonly type = CourseActionTypes.CourseRequested; - - constructor(public payload: { courseId: number }) { - - } -} - - -export class CourseLoaded implements Action { - - readonly type = CourseActionTypes.CourseLoaded; - - constructor(public payload: { course: Course }) { - } -} - - -export class AllCoursesRequested implements Action { - - readonly type = CourseActionTypes.AllCoursesRequested; - -} - -export class AllCoursesLoaded implements Action { - - readonly type = CourseActionTypes.AllCoursesLoaded; - - constructor(public payload: { courses: Course[] }) { - - } - -} - -export class CourseSaved implements Action { - - readonly type = CourseActionTypes.CourseSaved; - - constructor(public payload: { course: Update }) {} -} - - - - -export type CourseActions = - CourseRequested - | CourseLoaded - | AllCoursesRequested - | AllCoursesLoaded - | CourseSaved - | LessonsPageRequested - | LessonsPageLoaded - | LessonsPageCancelled; - - - - +pageIndex: number; +pageSize: number; +} + +export const lessonsPageRequested = createAction( + '[Course Landing Page] Lessons Page Requested', + (payload: {courseId: number, page: PageQuery}) => ({ payload }) +); + +export const lessonsPageLoaded = createAction( + '[Courses API] Lessons Page Loaded', + (lessons: Lesson[]) => ({ lessons }) +); + +export const lessonsPageCancelled = createAction( + '[Courses API] Lessons Page Cancelled' +); + +export const courseRequested = createAction( + '[View Course Page] Course Requested', + (courseId: number) => ({ courseId }) +); + +export const courseLoaded = createAction( + '[Courses API] Course Loaded', + (course: Course) => ({ course }) +); + +export const allCoursesRequested = createAction( + '[Courses Home Page] All Courses Requested' +); + +export const allCoursesLoaded = createAction( + '[Courses API] All Courses Loaded', + (courses: Course[]) => ({ courses }) +); + +export const courseSaved = createAction( + '[Edit Course Dialog] Course Saved', + (course: Update) => ({ course }) +); diff --git a/src/app/courses/course.effects.ts b/src/app/courses/course.effects.ts index 82182d5..c01fd6a 100644 --- a/src/app/courses/course.effects.ts +++ b/src/app/courses/course.effects.ts @@ -1,66 +1,63 @@ -import {Injectable} from '@angular/core'; -import {Actions, Effect, ofType} from '@ngrx/effects'; -import { - AllCoursesLoaded, - AllCoursesRequested, - CourseActionTypes, - CourseLoaded, - CourseRequested, LessonsPageCancelled, LessonsPageLoaded, - LessonsPageRequested -} from './course.actions'; -import {throwError,of} from 'rxjs'; -import {catchError, concatMap, exhaustMap, filter, map, mergeMap, withLatestFrom} from "rxjs/operators"; -import {CoursesService} from './services/courses.service'; -import {AppState} from '../reducers'; -import {select, Store} from '@ngrx/store'; -import {allCoursesLoaded} from './course.selectors'; + +import { Injectable } from '@angular/core'; +import { of, throwError } from 'rxjs'; +import { catchError, concatMap, exhaustMap, filter, map, mergeMap, withLatestFrom } from 'rxjs/operators'; +import { select, Store } from '@ngrx/store'; +import { Actions, ofType, createEffect } from '@ngrx/effects'; + +import * as courseActions from './course.actions'; +import { CoursesService } from './services/courses.service'; +import { AppState } from '../reducers'; +import { allCoursesLoaded } from './course.selectors'; @Injectable() export class CourseEffects { - @Effect() - loadCourse$ = this.actions$ - .pipe( - ofType(CourseActionTypes.CourseRequested), - mergeMap(action => this.coursesService.findCourseById(action.payload.courseId)), - map(course => new CourseLoaded({course})) + loadCourse$ = createEffect(() => + this.actions$.pipe( + ofType(courseActions.courseRequested), + mergeMap(action => this.coursesService.findCourseById(action.courseId)), + map(course => courseActions.courseLoaded(course)), + catchError(err => { + console.log('error loading course ', err); + return throwError(err); + }) + ) ); - @Effect() - loadAllCourses$ = this.actions$ - .pipe( - ofType(CourseActionTypes.AllCoursesRequested), + loadAllCourses$ = createEffect(() => + this.actions$.pipe( + ofType(courseActions.allCoursesRequested), withLatestFrom(this.store.pipe(select(allCoursesLoaded))), - filter(([action, allCoursesLoaded]) => !allCoursesLoaded), + filter(([action, coursesLoaded]) => !coursesLoaded), mergeMap(() => this.coursesService.findAllCourses()), - map(courses => new AllCoursesLoaded({courses})) - ); - - - @Effect() - loadLessonsPage$ = this.actions$ - .pipe( - ofType(CourseActionTypes.LessonsPageRequested), - mergeMap(({payload}) => - this.coursesService.findLessons(payload.courseId, - payload.page.pageIndex, payload.page.pageSize) - .pipe( - catchError(err => { - console.log('error loading a lessons page ', err); - this.store.dispatch(new LessonsPageCancelled()); - return of([]); - }) - ) + map(courses => courseActions.allCoursesLoaded(courses)), + catchError(err => { + console.log('error loading all courses ', err); + return throwError(err); + }) + ) + ); + loadLessonsPage$ = createEffect(() => + this.actions$.pipe( + ofType(courseActions.lessonsPageRequested), + mergeMap(action => this.coursesService.findLessons(action.payload.courseId, + action.payload.page.pageIndex, action.payload.page.pageSize) + .pipe( + catchError(err => { + console.log('error loading a lessons page ', err); + this.store.dispatch(courseActions.lessonsPageCancelled()); + return of([]); + }) + ) ), - map(lessons => new LessonsPageLoaded({lessons})) - ); - - + map(lessons => courseActions.lessonsPageLoaded(lessons)) + ) + ); - constructor(private actions$ :Actions, private coursesService: CoursesService, + constructor(private actions$: Actions, private coursesService: CoursesService, private store: Store) { - } } diff --git a/src/app/courses/course.reducers.ts b/src/app/courses/course.reducers.ts index 5230beb..adf2824 100644 --- a/src/app/courses/course.reducers.ts +++ b/src/app/courses/course.reducers.ts @@ -1,17 +1,18 @@ -import {Course} from './model/course'; + +import { createReducer, on, Action } from '@ngrx/store'; import {createEntityAdapter, EntityAdapter, EntityState} from '@ngrx/entity'; -import {CourseActions, CourseActionTypes} from './course.actions'; +import {Course} from './model/course'; +import * as courseActions from './course.actions'; -export interface CoursesState extends EntityState { - - allCoursesLoaded:boolean; +export interface CoursesState extends EntityState { + allCoursesLoaded: boolean; } -export const adapter : EntityAdapter = +export const adapter: EntityAdapter = createEntityAdapter(); @@ -19,44 +20,26 @@ export const initialCoursesState: CoursesState = adapter.getInitialState({ allCoursesLoaded: false }); - -export function coursesReducer(state = initialCoursesState , action: CourseActions): CoursesState { - - switch(action.type) { - - case CourseActionTypes.CourseLoaded: - - return adapter.addOne(action.payload.course, state); - - case CourseActionTypes.AllCoursesLoaded: - - return adapter.addAll(action.payload.courses, {...state, allCoursesLoaded:true}); - - case CourseActionTypes.CourseSaved: - - return adapter.updateOne(action.payload.course,state); - - default: { - - return state; - } - - } +export const reducer = createReducer( + initialCoursesState, + on(courseActions.courseLoaded, (state, { course }) => { + return adapter.addOne(course, state); + }), + on(courseActions.allCoursesLoaded, (state, { courses }) => { + return adapter.addAll(courses, {...state, allCoursesLoaded: true}); + }), + on(courseActions.courseSaved, (state, { course }) => { + return adapter.updateOne(course, state); + }) +); + +export function coursesReducer(state = initialCoursesState , action: Action): CoursesState { + return reducer(state, action); } - export const { selectAll, selectEntities, selectIds, selectTotal - } = adapter.getSelectors(); - - - - - - - - diff --git a/src/app/courses/course.selectors.ts b/src/app/courses/course.selectors.ts index 1bdfc87..d380766 100644 --- a/src/app/courses/course.selectors.ts +++ b/src/app/courses/course.selectors.ts @@ -8,12 +8,11 @@ import * as fromLesson from './lessons.reducers'; import {PageQuery} from './course.actions'; import {LessonsState} from './lessons.reducers'; -export const selectCoursesState = createFeatureSelector("courses"); +export const selectCoursesState = createFeatureSelector('courses'); -export const selectLessonsState = createFeatureSelector("lessons"); +export const selectLessonsState = createFeatureSelector('lessons'); - -export const selectCourseById = (courseId:number) => createSelector( +export const selectCourseById = (courseId: number) => createSelector( selectCoursesState, coursesState => coursesState.entities[courseId] ); @@ -30,35 +29,28 @@ export const selectBeginnerCourses = createSelector( courses => courses.filter(course => course.category === 'BEGINNER') ); - export const selectAdvancedCourses = createSelector( selectAllCourses, courses => courses.filter(course => course.category === 'ADVANCED') ); - - export const selectPromoTotal = createSelector( selectAllCourses, courses => courses.filter(course => course.promo).length ); - export const allCoursesLoaded = createSelector( selectCoursesState, coursesState => coursesState.allCoursesLoaded ); - - export const selectAllLessons = createSelector( selectLessonsState, fromLesson.selectAll ); - -export const selectLessonsPage = (courseId:number, page:PageQuery) => createSelector( +export const selectLessonsPage = (courseId: number, page: PageQuery) => createSelector( selectAllLessons, allLessons => { @@ -66,7 +58,7 @@ export const selectLessonsPage = (courseId:number, page:PageQuery) => createSele end = start + page.pageSize; return allLessons - .filter(lesson => lesson.courseId == courseId) + .filter(lesson => lesson.courseId === courseId) .slice(start, end); } diff --git a/src/app/courses/course/course.component.ts b/src/app/courses/course/course.component.ts index 5af9f7e..4bffa70 100644 --- a/src/app/courses/course/course.component.ts +++ b/src/app/courses/course/course.component.ts @@ -1,14 +1,14 @@ import {AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, OnInit, ViewChild} from '@angular/core'; -import {ActivatedRoute} from "@angular/router"; -import { MatPaginator } from "@angular/material/paginator"; -import { MatSort } from "@angular/material/sort"; -import { MatTableDataSource } from "@angular/material/table"; -import {Course} from "../model/course"; -import {CoursesService} from "../services/courses.service"; +import {ActivatedRoute} from '@angular/router'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; +import {Course} from '../model/course'; +import {CoursesService} from '../services/courses.service'; import {debounceTime, distinctUntilChanged, startWith, tap, delay} from 'rxjs/operators'; -import {merge, fromEvent, Observable} from "rxjs"; -import {LessonsDataSource} from "../services/lessons.datasource"; +import {merge, fromEvent, Observable} from 'rxjs'; +import {LessonsDataSource} from '../services/lessons.datasource'; import {AppState} from '../../reducers'; import {select, Store} from '@ngrx/store'; import {PageQuery} from '../course.actions'; @@ -16,6 +16,7 @@ import {selectLessonsLoading} from '../course.selectors'; @Component({ +// tslint:disable-next-line: component-selector selector: 'course', templateUrl: './course.component.html', styleUrls: ['./course.component.css'], @@ -23,16 +24,15 @@ import {selectLessonsLoading} from '../course.selectors'; }) export class CourseComponent implements OnInit, AfterViewInit { - course:Course; + course: Course; dataSource: LessonsDataSource; - displayedColumns = ["seqNo", "description", "duration"]; + displayedColumns = ['seqNo', 'description', 'duration']; @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; - loading$ : Observable; - + loading$: Observable; constructor(private route: ActivatedRoute, private store: Store) { @@ -40,7 +40,7 @@ export class CourseComponent implements OnInit, AfterViewInit { ngOnInit() { - this.course = this.route.snapshot.data["course"]; + this.course = this.route.snapshot.data['course']; this.loading$ = this.store.pipe(select(selectLessonsLoading)); diff --git a/src/app/courses/courses.module.ts b/src/app/courses/courses.module.ts index 157c239..12bb9d8 100644 --- a/src/app/courses/courses.module.ts +++ b/src/app/courses/courses.module.ts @@ -1,28 +1,28 @@ -import {ModuleWithProviders, NgModule} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {HomeComponent} from "./home/home.component"; -import {CoursesCardListComponent} from "./courses-card-list/courses-card-list.component"; -import {CourseDialogComponent} from "./course-dialog/course-dialog.component"; -import {CourseResolver} from "./services/course.resolver"; -import {CoursesService} from "./services/courses.service"; -import {CourseComponent} from "./course/course.component"; -import { MatDatepickerModule } from "@angular/material/datepicker"; -import { MatDialogModule } from "@angular/material/dialog"; -import { MatInputModule } from "@angular/material/input"; -import { MatPaginatorModule } from "@angular/material/paginator"; -import { MatProgressSpinnerModule } from "@angular/material/progress-spinner"; -import { MatSelectModule } from "@angular/material/select"; -import { MatSlideToggleModule } from "@angular/material/slide-toggle"; -import { MatSortModule } from "@angular/material/sort"; -import { MatTableModule } from "@angular/material/table"; -import {MatTabsModule} from "@angular/material/tabs"; -import {ReactiveFormsModule} from "@angular/forms"; -import {MatMenuModule} from "@angular/material/menu"; -import {MatMomentDateModule} from "@angular/material-moment-adapter"; -import {MatCardModule} from "@angular/material/card"; -import {MatButtonModule} from "@angular/material/button"; -import {MatIconModule} from "@angular/material/icon"; -import {RouterModule, Routes} from "@angular/router"; + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { HomeComponent } from './home/home.component'; +import { CoursesCardListComponent } from './courses-card-list/courses-card-list.component'; +import { CourseDialogComponent } from './course-dialog/course-dialog.component'; +import { CourseResolver } from './services/course.resolver'; +import { CoursesService } from './services/courses.service'; +import { CourseComponent } from './course/course.component'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatInputModule } from '@angular/material/input'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatSelectModule } from '@angular/material/select'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatSortModule } from '@angular/material/sort'; +import { MatTableModule } from '@angular/material/table'; +import { MatTabsModule } from '@angular/material/tabs'; +import { ReactiveFormsModule } from '@angular/forms'; +import { MatMomentDateModule } from '@angular/material-moment-adapter'; +import { MatCardModule } from '@angular/material/card'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { RouterModule, Routes } from '@angular/router'; import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import {CourseEffects} from './course.effects'; @@ -32,7 +32,7 @@ import {lessonsReducer} from './lessons.reducers'; export const coursesRoutes: Routes = [ { - path: "", + path: '', component: HomeComponent }, @@ -79,6 +79,4 @@ export const coursesRoutes: Routes = [ ] }) export class CoursesModule { - - } diff --git a/src/app/courses/home/home.component.ts b/src/app/courses/home/home.component.ts index e0cd972..8f586d7 100644 --- a/src/app/courses/home/home.component.ts +++ b/src/app/courses/home/home.component.ts @@ -1,13 +1,12 @@ import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core'; -import {Course} from "../model/course"; -import {Observable} from "rxjs"; -import {filter, map, tap, withLatestFrom} from "rxjs/operators"; -import {CoursesService} from "../services/courses.service"; +import {Course} from '../model/course'; +import {Observable} from 'rxjs'; import {AppState} from '../../reducers'; import {select, Store} from '@ngrx/store'; import {selectAdvancedCourses, selectAllCourses, selectBeginnerCourses, selectPromoTotal} from '../course.selectors'; -import {AllCoursesRequested} from '../course.actions'; +import * as courseActions from '../course.actions'; @Component({ +// tslint:disable-next-line: component-selector selector: 'home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'] @@ -26,7 +25,7 @@ export class HomeComponent implements OnInit { ngOnInit() { - this.store.dispatch(new AllCoursesRequested()); + this.store.dispatch(courseActions.allCoursesRequested()); this.beginnerCourses$ = this.store.pipe(select(selectBeginnerCourses)); diff --git a/src/app/courses/lessons.reducers.ts b/src/app/courses/lessons.reducers.ts index 7a7a82d..462607b 100644 --- a/src/app/courses/lessons.reducers.ts +++ b/src/app/courses/lessons.reducers.ts @@ -1,75 +1,54 @@ +import { createReducer, on, Action } from '@ngrx/store'; import {createEntityAdapter, EntityAdapter, EntityState} from '@ngrx/entity'; -import {Lesson} from './model/lesson'; -import {Course} from './model/course'; -import {CourseActions, CourseActionTypes} from './course.actions'; - +import {Lesson} from './model/lesson'; +import * as courseActions from './course.actions'; export interface LessonsState extends EntityState { - loading:boolean; + loading: boolean; } -function sortByCourseAndSeqNo(l1: Lesson, l2:Lesson) { +function sortByCourseAndSeqNo(l1: Lesson, l2: Lesson) { const compare = l1.courseId - l2.courseId; - if (compare != 0) { + if (compare !== 0) { return compare; - } - else { + } else { return l1.seqNo - l2.seqNo; } } -export const adapter : EntityAdapter = +export const adapter: EntityAdapter = createEntityAdapter({ sortComparer: sortByCourseAndSeqNo }); - const initialLessonsState = adapter.getInitialState({ loading: false }); - +export const reducer = createReducer( + initialLessonsState, + on(courseActions.lessonsPageCancelled, (state) => ({ + ...state, + loading: false + })), + on(courseActions.lessonsPageRequested, (state) => ({ + ...state, + loading: true + })), + on(courseActions.lessonsPageLoaded, (state, { lessons }) => { + return adapter.addMany(lessons, {...state, loading: false}); + }) +); export function lessonsReducer(state = initialLessonsState, - action: CourseActions): LessonsState { - - switch(action.type) { - - case CourseActionTypes.LessonsPageCancelled: - - return { - ...state, - loading:false - }; - - case CourseActionTypes.LessonsPageRequested: - return { - ...state, - loading:true - }; - - case CourseActionTypes.LessonsPageLoaded: - - return adapter.addMany(action.payload.lessons, {...state, loading:false}); - - - default: - - return state; - - } - + action: Action): LessonsState { + return reducer(state, action); } - - export const { selectAll, selectEntities, selectIds, selectTotal - } = adapter.getSelectors(); - - diff --git a/src/app/courses/model/course.ts b/src/app/courses/model/course.ts index 79d4cf2..96d52ff 100644 --- a/src/app/courses/model/course.ts +++ b/src/app/courses/model/course.ts @@ -1,12 +1,12 @@ export interface Course { - id:number; - description:string; + id: number; + description: string; iconUrl: string; courseListIcon: string; longDescription: string; - category:string; - lessonsCount:number; - promo:boolean; + category: string; + lessonsCount: number; + promo: boolean; } diff --git a/src/app/courses/services/course.resolver.ts b/src/app/courses/services/course.resolver.ts index 9f1540c..5dd8707 100644 --- a/src/app/courses/services/course.resolver.ts +++ b/src/app/courses/services/course.resolver.ts @@ -1,16 +1,16 @@ -import {Injectable} from "@angular/core"; -import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from "@angular/router"; -import {Course} from "../model/course"; -import {Observable} from "rxjs"; -import {CoursesService} from "./courses.service"; -import {AppState} from "../../reducers"; -import {select, Store} from "@ngrx/store"; -import {filter, first, tap} from "rxjs/operators"; +import {Injectable} from '@angular/core'; +import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router'; +import {Course} from '../model/course'; +import {Observable} from 'rxjs'; +import {CoursesService} from './courses.service'; +import {AppState} from '../../reducers'; +import {select, Store} from '@ngrx/store'; +import {filter, first, tap} from 'rxjs/operators'; import {selectCourseById} from '../course.selectors'; -import {CourseRequested} from '../course.actions'; +import * as courseActions from '../course.actions'; @@ -18,7 +18,7 @@ import {CourseRequested} from '../course.actions'; export class CourseResolver implements Resolve { constructor( - private coursesService:CoursesService, + private coursesService: CoursesService, private store: Store) { } @@ -32,13 +32,12 @@ export class CourseResolver implements Resolve { select(selectCourseById(courseId)), tap(course => { if (!course) { - this.store.dispatch(new CourseRequested({courseId})); + this.store.dispatch(courseActions.courseRequested(courseId)); } }), filter(course => !!course), first() - ) - + ); } } diff --git a/src/app/courses/services/courses.service.ts b/src/app/courses/services/courses.service.ts index df4418a..80e4df6 100644 --- a/src/app/courses/services/courses.service.ts +++ b/src/app/courses/services/courses.service.ts @@ -1,17 +1,17 @@ -import {Injectable} from "@angular/core"; -import {HttpClient, HttpParams} from "@angular/common/http"; -import {Observable} from "rxjs"; -import {Course} from "../model/course"; -import {map} from "rxjs/operators"; -import {Lesson} from "../model/lesson"; +import {Injectable} from '@angular/core'; +import {HttpClient, HttpParams} from '@angular/common/http'; +import {Observable} from 'rxjs'; +import {Course} from '../model/course'; +import {map} from 'rxjs/operators'; +import {Lesson} from '../model/lesson'; @Injectable() export class CoursesService { - constructor(private http:HttpClient) { + constructor(private http: HttpClient) { } @@ -26,19 +26,19 @@ export class CoursesService { ); } - findAllCourseLessons(courseId:number): Observable { + findAllCourseLessons(courseId: number): Observable { return this.http.get('/api/lessons', { params: new HttpParams() .set('courseId', courseId.toString()) - .set('pageNumber', "0") - .set('pageSize', "1000") + .set('pageNumber', '0') + .set('pageSize', '1000') }).pipe( - map(res => res["payload"]) + map(res => res['payload']) ); } findLessons( - courseId:number, + courseId: number, pageNumber = 0, pageSize = 3): Observable { return this.http.get('/api/lessons', { @@ -48,7 +48,7 @@ export class CoursesService { .set('pageNumber', pageNumber.toString()) .set('pageSize', pageSize.toString()) }).pipe( - map(res => res["payload"]) + map(res => res['payload']) ); } @@ -58,4 +58,4 @@ export class CoursesService { } -} \ No newline at end of file +} diff --git a/src/app/courses/services/lessons.datasource.ts b/src/app/courses/services/lessons.datasource.ts index 9e9ee4c..ada394b 100644 --- a/src/app/courses/services/lessons.datasource.ts +++ b/src/app/courses/services/lessons.datasource.ts @@ -1,15 +1,14 @@ -import {CollectionViewer, DataSource} from "@angular/cdk/collections"; -import {Observable, BehaviorSubject, of} from "rxjs"; -import {Lesson} from "../model/lesson"; -import {CoursesService} from "./courses.service"; -import {catchError, finalize, tap} from 'rxjs/operators'; +import {CollectionViewer, DataSource} from '@angular/cdk/collections'; +import {Observable, BehaviorSubject, of} from 'rxjs'; +import {Lesson} from '../model/lesson'; +import {catchError, tap} from 'rxjs/operators'; import {AppState} from '../../reducers'; import {select, Store} from '@ngrx/store'; -import {LessonsPageRequested, PageQuery} from '../course.actions'; import {selectLessonsPage} from '../course.selectors'; +import * as courseActions from '../course.actions'; @@ -21,16 +20,15 @@ export class LessonsDataSource implements DataSource { } - loadLessons(courseId:number, page: PageQuery) { + loadLessons(courseId: number, page: courseActions.PageQuery) { this.store .pipe( select(selectLessonsPage(courseId, page)), tap(lessons => { if (lessons.length > 0) { this.lessonsSubject.next(lessons); - } - else { - this.store.dispatch(new LessonsPageRequested({courseId, page})); + } else { + this.store.dispatch(courseActions.lessonsPageRequested({courseId, page})); } }), catchError(() => of([])) @@ -40,7 +38,7 @@ export class LessonsDataSource implements DataSource { } connect(collectionViewer: CollectionViewer): Observable { - console.log("Connecting data source"); + console.log('Connecting data source'); return this.lessonsSubject.asObservable(); } diff --git a/src/app/reducers/index.ts b/src/app/reducers/index.ts index 60e9d3c..3f6d4e6 100644 --- a/src/app/reducers/index.ts +++ b/src/app/reducers/index.ts @@ -7,11 +7,11 @@ import { } from '@ngrx/store'; import { environment } from '../../environments/environment'; import {User} from '../model/user.model'; -import {AuthActions, AuthActionTypes} from '../auth/auth.actions'; import {storeFreeze} from 'ngrx-store-freeze'; import {routerReducer} from '@ngrx/router-store'; +// tslint:disable-next-line: no-empty-interface export interface AppState { }