| 作者 | SHA1 | 备注 | 提交日期 |
|---|---|---|---|
|
|
e3a46d8895 | 24-343 Cleaning up | 8 年前 |
|
|
66bb853828 | 24-342 Storing recipes via ngrx | 8 年前 |
| @@ -5,8 +5,6 @@ import { HeaderComponent } from "./header/header.component"; | |||||
| import { HomeComponent } from "./home/home.component"; | import { HomeComponent } from "./home/home.component"; | ||||
| import { SharedModule } from "../shared/shared.module"; | import { SharedModule } from "../shared/shared.module"; | ||||
| import { AppRoutingModule } from "../app-routing.module"; | import { AppRoutingModule } from "../app-routing.module"; | ||||
| import { RecipeService } from "../recipes/recipe.service"; | |||||
| import { DataStorageService } from "../shared/data-storage.service"; | |||||
| import { AuthInterceptor } from "../shared/auth.interceptor"; | import { AuthInterceptor } from "../shared/auth.interceptor"; | ||||
| import { LoggingInterceptor } from "../shared/logging.interceptor"; | import { LoggingInterceptor } from "../shared/logging.interceptor"; | ||||
| @@ -24,8 +22,6 @@ import { LoggingInterceptor } from "../shared/logging.interceptor"; | |||||
| HeaderComponent | HeaderComponent | ||||
| ], | ], | ||||
| providers: [ | providers: [ | ||||
| RecipeService, | |||||
| DataStorageService, | |||||
| {provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true}, | {provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true}, | ||||
| {provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true} | {provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true} | ||||
| ], | ], | ||||
| @@ -2,7 +2,6 @@ import { Component, OnInit } from "@angular/core"; | |||||
| import { Store } from "@ngrx/store"; | import { Store } from "@ngrx/store"; | ||||
| import { Observable } from "rxjs/Observable"; | import { Observable } from "rxjs/Observable"; | ||||
| import { DataStorageService } from "../../shared/data-storage.service"; | |||||
| import * as fromApp from '../../ngrx/app.reducers'; | import * as fromApp from '../../ngrx/app.reducers'; | ||||
| import * as fromAuth from '../../auth/ngrx/auth.reducers'; | import * as fromAuth from '../../auth/ngrx/auth.reducers'; | ||||
| import * as AuthActions from '../../auth/ngrx/auth.actions'; | import * as AuthActions from '../../auth/ngrx/auth.actions'; | ||||
| @@ -15,18 +14,14 @@ import * as RecipeActions from '../../recipes/ngrx/recipe.actions'; | |||||
| export class HeaderComponent implements OnInit { | export class HeaderComponent implements OnInit { | ||||
| authState: Observable<fromAuth.State>; | authState: Observable<fromAuth.State>; | ||||
| constructor(private dataStorageService: DataStorageService, private store: Store<fromApp.AppState>) {} | |||||
| constructor(private store: Store<fromApp.AppState>) {} | |||||
| ngOnInit() { | ngOnInit() { | ||||
| this.authState = this.store.select('auth') | this.authState = this.store.select('auth') | ||||
| } | } | ||||
| onSaveData() { | onSaveData() { | ||||
| this.dataStorageService.storeRecipes().subscribe( | |||||
| response => { | |||||
| // console.log(response); | |||||
| } | |||||
| ); | |||||
| this.store.dispatch(new RecipeActions.StoreRecipes()); | |||||
| } | } | ||||
| onFetchData() { | onFetchData() { | ||||
| @@ -2,15 +2,22 @@ import { Injectable } from "@angular/core"; | |||||
| import { Actions, Effect } from "@ngrx/effects"; | import { Actions, Effect } from "@ngrx/effects"; | ||||
| import 'rxjs/add/operator/map'; | import 'rxjs/add/operator/map'; | ||||
| import 'rxjs/add/operator/switchMap'; | import 'rxjs/add/operator/switchMap'; | ||||
| import 'rxjs/add/operator/withLatestFrom'; | |||||
| import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http'; | import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http'; | ||||
| import { Store } from "@ngrx/store"; | |||||
| import * as RecipeActions from '../ngrx/recipe.actions'; | import * as RecipeActions from '../ngrx/recipe.actions'; | ||||
| import { Recipe } from "../recipe.model"; | import { Recipe } from "../recipe.model"; | ||||
| import * as fromRecipe from './recipe.reducers'; | |||||
| @Injectable() | @Injectable() | ||||
| export class RecipeEffects { | export class RecipeEffects { | ||||
| readonly baseUrl: string = 'https://my-recipe-book-cb837.firebaseio.com/'; | readonly baseUrl: string = 'https://my-recipe-book-cb837.firebaseio.com/'; | ||||
| constructor(private actions$: Actions, | |||||
| private httpClient: HttpClient, | |||||
| private store: Store<fromRecipe.FeatureState>) {} | |||||
| @Effect() | @Effect() | ||||
| recipeFetch = this.actions$.ofType(RecipeActions.FETCH_RECIPES) | recipeFetch = this.actions$.ofType(RecipeActions.FETCH_RECIPES) | ||||
| .switchMap((action: RecipeActions.FetchRecipes) => { | .switchMap((action: RecipeActions.FetchRecipes) => { | ||||
| @@ -23,6 +30,10 @@ export class RecipeEffects { | |||||
| }; | }; | ||||
| }); | }); | ||||
| constructor(private actions$: Actions, | |||||
| private httpClient: HttpClient) {} | |||||
| @Effect({dispatch: false}) | |||||
| recipeStore = this.actions$.ofType(RecipeActions.STORE_RECIPES) | |||||
| .withLatestFrom(this.store.select('recipes')) | |||||
| .switchMap(([action, state]) => { | |||||
| return this.httpClient.put(this.baseUrl + 'recipes.json', state.recipes); | |||||
| }); | |||||
| } | } | ||||
| @@ -12,7 +12,7 @@ export interface State { | |||||
| } | } | ||||
| const initialState: State = { | const initialState: State = { | ||||
| recipes: [new Recipe("Foo", "Bar", "image.jpg", [])] | |||||
| recipes: [] | |||||
| }; | }; | ||||
| export function recipeReducer(state = initialState, action: RecipeActions.RecipeActions) { | export function recipeReducer(state = initialState, action: RecipeActions.RecipeActions) { | ||||
| @@ -35,7 +35,7 @@ | |||||
| <li | <li | ||||
| class="list-group-item" | class="list-group-item" | ||||
| *ngFor="let ingredient of (recipeState | async).recipes[id].ingredients"> | *ngFor="let ingredient of (recipeState | async).recipes[id].ingredients"> | ||||
| {{ (recipeState | async).recipes[id].name }} - {{ (recipeState | async).recipes[id].amount }} | |||||
| {{ ingredient.name }} - {{ ingredient.amount }} | |||||
| </li> | </li> | ||||
| </ul> | </ul> | ||||
| </div> | </div> | ||||
| @@ -7,7 +7,7 @@ import { Recipe } from '../recipe.model'; | |||||
| import * as ShoppingListActions from '../../shopping-list/ngrx/shopping-list.actions'; | import * as ShoppingListActions from '../../shopping-list/ngrx/shopping-list.actions'; | ||||
| import * as fromApp from '../../ngrx/app.reducers'; | import * as fromApp from '../../ngrx/app.reducers'; | ||||
| import * as fromRecipe from '../ngrx/recipe.reducers'; | import * as fromRecipe from '../ngrx/recipe.reducers'; | ||||
| import * as RecipeACtions from '../ngrx/recipe.actions'; | |||||
| import * as RecipeActions from '../ngrx/recipe.actions'; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-recipe-detail', | selector: 'app-recipe-detail', | ||||
| @@ -45,7 +45,7 @@ export class RecipeDetailComponent implements OnInit { | |||||
| } | } | ||||
| onDelete() { | onDelete() { | ||||
| this.store.dispatch(new RecipeACtions.DeleteRecipe(this.id)); | |||||
| this.store.dispatch(new RecipeActions.DeleteRecipe(this.id)); | |||||
| this.router.navigate(['/recipes']); | this.router.navigate(['/recipes']); | ||||
| } | } | ||||
| } | } | ||||
| @@ -3,9 +3,6 @@ import { Router, ActivatedRoute } from '@angular/router'; | |||||
| import { Store } from '@ngrx/store'; | import { Store } from '@ngrx/store'; | ||||
| import { Observable } from 'rxjs/Observable'; | import { Observable } from 'rxjs/Observable'; | ||||
| import { Recipe } from '../recipe.model'; | |||||
| import { RecipeService } from '../recipe.service'; | |||||
| import * as fromRecipe from '../ngrx/recipe.reducers'; | import * as fromRecipe from '../ngrx/recipe.reducers'; | ||||
| @Component({ | @Component({ | ||||
| @@ -1,19 +0,0 @@ | |||||
| import { EventEmitter } from "@angular/core"; | |||||
| import { Subject } from "rxjs/Subject"; | |||||
| import { Recipe } from "./recipe.model"; | |||||
| import { Ingredient } from "../shared/ingredient.model"; | |||||
| export class RecipeService { | |||||
| recipesChanged = new Subject<Recipe[]>(); | |||||
| private recipes: Recipe[] = []; | |||||
| replaceRecipes(recipes: Recipe[]) { | |||||
| this.recipes = recipes; | |||||
| this.recipesChanged.next(this.recipes.slice()); | |||||
| } | |||||
| getRecipes() { | |||||
| return this.recipes.slice(); | |||||
| } | |||||
| } | |||||
| @@ -1,7 +1,5 @@ | |||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||
| import { RecipeService } from './recipe.service'; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-recipes', | selector: 'app-recipes', | ||||
| templateUrl: './recipes.component.html', | templateUrl: './recipes.component.html', | ||||
| @@ -1,29 +0,0 @@ | |||||
| import { Injectable } from '@angular/core'; | |||||
| import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http'; | |||||
| import { RecipeService } from '../recipes/recipe.service'; | |||||
| import { Recipe } from '../recipes/recipe.model'; | |||||
| @Injectable() | |||||
| export class DataStorageService { | |||||
| readonly baseUrl: string = 'https://my-recipe-book-cb837.firebaseio.com/'; | |||||
| constructor(private httpClient: HttpClient, | |||||
| private recipeService: RecipeService) {} | |||||
| storeRecipes() { | |||||
| // const token = this.authService.getToken(); | |||||
| // return this.httpClient.put(this.baseUrl + 'recipes.json?auth=' + token, this.recipeService.getRecipes()); | |||||
| // const req = new HttpRequest('PUT', this.baseUrl, this.recipeService.getRecipes(), {reportProgress: true, params: new HttpParams().set('auth', token)}); | |||||
| // return this.httpClient.request(req); | |||||
| return this.httpClient.put(this.baseUrl + 'recipes.json', this.recipeService.getRecipes()); | |||||
| } | |||||
| fetchRecipes() { | |||||
| this.httpClient.get<Recipe[]>(this.baseUrl + 'recipes.json').subscribe( | |||||
| recipes => { | |||||
| this.recipeService.replaceRecipes(recipes); | |||||
| } | |||||
| ) | |||||
| } | |||||
| } | |||||
| @@ -4,10 +4,10 @@ import 'rxjs/add/operator/do'; | |||||
| export class LoggingInterceptor implements HttpInterceptor { | export class LoggingInterceptor implements HttpInterceptor { | ||||
| intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | ||||
| // do without consuming it! | |||||
| // do() without consuming it! | |||||
| return next.handle(req).do( | return next.handle(req).do( | ||||
| event => { | event => { | ||||
| console.log('Logging interceptor', event); | |||||
| // console.log('Logging interceptor', event); | |||||
| } | } | ||||
| ) | ) | ||||
| } | } | ||||