Skip to content

Commit

Permalink
feat(books): use new ngrx features
Browse files Browse the repository at this point in the history
  • Loading branch information
abedzantout committed Jul 3, 2019
1 parent a5edcb3 commit 0fc5dc4
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 55 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {
BookActionTypes,
ActionBooksUpsertOne,
ActionBooksDeleteOne
actionBooksDeleteOne,
actionBooksUpsertOne,
BookActionTypes
} from './books.actions';

describe('Books Actions', () => {
it('should create ActionBooksUpsertOne action', () => {
const action = new ActionBooksUpsertOne({
const action = actionBooksUpsertOne({
book: {
id: '1',
title: 'test',
Expand All @@ -15,7 +15,7 @@ describe('Books Actions', () => {
}
});
expect(action.type).toEqual(BookActionTypes.UPSERT_ONE);
expect(action.payload.book).toEqual(
expect(action.book).toEqual(
jasmine.objectContaining({
id: '1',
title: 'test',
Expand All @@ -26,8 +26,8 @@ describe('Books Actions', () => {
});

it('should create ActionBooksDeleteOne action', () => {
const action = new ActionBooksDeleteOne({ id: '1' });
const action = actionBooksDeleteOne({ id: '1' });
expect(action.type).toEqual(BookActionTypes.DELETE_ONE);
expect(action.payload.id).toEqual('1');
expect(action.id).toEqual('1');
});
});
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { Action } from '@ngrx/store';
import { createAction, props } from '@ngrx/store';
import { Book } from './books.model';

export enum BookActionTypes {
UPSERT_ONE = '[Books] Upsert One',
DELETE_ONE = '[Books] Delete One'
}

export class ActionBooksUpsertOne implements Action {
readonly type = BookActionTypes.UPSERT_ONE;
constructor(readonly payload: { book: Book }) {}
}

export class ActionBooksDeleteOne implements Action {
readonly type = BookActionTypes.DELETE_ONE;
constructor(readonly payload: { id: string }) {}
}
export const actionBooksUpsertOne = createAction(
BookActionTypes.UPSERT_ONE,
props<{ book: Book }>()
);

export type BookActions = ActionBooksUpsertOne | ActionBooksDeleteOne;
export const actionBooksDeleteOne = createAction(
BookActionTypes.DELETE_ONE,
props<{ id: string }>()
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { TestScheduler } from 'rxjs/testing';

import { LocalStorageService } from '../../../core/core.module';

import { ActionBooksDeleteOne, ActionBooksUpsertOne } from './books.actions';
import { BookState } from './books.model';
import { Actions, getEffectsMetadata } from '@ngrx/effects';
import { BooksEffects, BOOKS_KEY } from './books.effects';
import { actionBooksDeleteOne, actionBooksUpsertOne } from './books.actions';

const scheduler = new TestScheduler((actual, expected) =>
assert.deepStrictEqual(actual, expected)
Expand Down Expand Up @@ -50,7 +50,7 @@ describe('BooksEffects', () => {
it('should call setItem on LocalStorageService for delete one action', () => {
scheduler.run(helpers => {
const { cold } = helpers;
const action = new ActionBooksDeleteOne({ id: '1' });
const action = actionBooksDeleteOne({ id: '1' });
const source = cold('a', { a: action });
const actions = new Actions(source);
const effects = new BooksEffects(actions, store, localStorage);
Expand All @@ -67,7 +67,7 @@ describe('BooksEffects', () => {
it('should call setItem on LocalStorageService for upsert one action', () => {
scheduler.run(helpers => {
const { cold } = helpers;
const action = new ActionBooksUpsertOne({ book: {} as any });
const action = actionBooksUpsertOne({ book: {} as any });
const source = cold('a', { a: action });
const actions = new Actions(source);
const effects = new BooksEffects(actions, store, localStorage);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import { Injectable } from '@angular/core';
import { Action, select, Store } from '@ngrx/store';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { select, Store } from '@ngrx/store';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { tap, withLatestFrom } from 'rxjs/operators';

import { LocalStorageService } from '../../../core/core.module';

import { State } from '../examples.state';
import { BookActionTypes } from './books.actions';
import { actionBooksDeleteOne, actionBooksUpsertOne } from './books.actions';
import { selectBooks } from './books.selectors';

export const BOOKS_KEY = 'EXAMPLES.BOOKS';

@Injectable()
export class BooksEffects {
constructor(
private actions$: Actions<Action>,
private actions$: Actions,
private store: Store<State>,
private localStorageService: LocalStorageService
) {}

@Effect({ dispatch: false })
persistBooks = this.actions$.pipe(
ofType(BookActionTypes.UPSERT_ONE, BookActionTypes.DELETE_ONE),
withLatestFrom(this.store.pipe(select(selectBooks))),
tap(([actions, booksState]) =>
this.localStorageService.setItem(BOOKS_KEY, booksState)
)
persistBooks = createEffect(
() =>
this.actions$.pipe(
ofType(actionBooksUpsertOne.type, actionBooksDeleteOne.type),
withLatestFrom(this.store.pipe(select(selectBooks))),
tap(([actions, booksState]) =>
this.localStorageService.setItem(BOOKS_KEY, booksState)
)
),
{ dispatch: false }
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BookState } from './books.model';
import { bookReducer, initialState } from './books.reducer';
import { ActionBooksUpsertOne, ActionBooksDeleteOne } from './books.actions';
import { actionBooksDeleteOne, actionBooksUpsertOne } from './books.actions';

describe('BookReducer', () => {
const TEST_INITIAL_STATE: BookState = {
Expand All @@ -24,7 +24,7 @@ describe('BookReducer', () => {
});

it('should add a book', () => {
const action = new ActionBooksUpsertOne({
const action = actionBooksUpsertOne({
book: {
id: '1234',
title: 'test',
Expand All @@ -40,7 +40,7 @@ describe('BookReducer', () => {

it('should update a book', () => {
const id = TEST_INITIAL_STATE.ids[0] as string;
const action = new ActionBooksUpsertOne({
const action = actionBooksUpsertOne({
book: {
id: id,
title: 'updated',
Expand All @@ -61,7 +61,7 @@ describe('BookReducer', () => {

it('should remove a book', () => {
const id = TEST_INITIAL_STATE.ids[0] as string;
const action = new ActionBooksDeleteOne({ id });
const action = actionBooksDeleteOne({ id });
const state = bookReducer(TEST_INITIAL_STATE, action);
expect(state.entities[id]).toBe(undefined);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { createEntityAdapter, EntityAdapter } from '@ngrx/entity';

import { Book, BookState } from './books.model';
import { BookActionTypes, BookActions } from './books.actions';
import { actionBooksDeleteOne, actionBooksUpsertOne } from './books.actions';
import { Action, createReducer, on } from '@ngrx/store';

export function sortByTitle(a: Book, b: Book): number {
return a.title.localeCompare(b.title);
Expand All @@ -24,18 +25,14 @@ export const initialState: BookState = bookAdapter.getInitialState({
}
});

export function bookReducer(
state: BookState = initialState,
action: BookActions
): BookState {
switch (action.type) {
case BookActionTypes.UPSERT_ONE:
return bookAdapter.upsertOne(action.payload.book, state);
const reducer = createReducer(
initialState,
on(actionBooksUpsertOne, (state, { book }) =>
bookAdapter.upsertOne(book, state)
),
on(actionBooksDeleteOne, (state, { id }) => bookAdapter.removeOne(id, state))
);

case BookActionTypes.DELETE_ONE:
return bookAdapter.removeOne(action.payload.id, state);

default:
return state;
}
export function bookReducer(state: BookState | undefined, action: Action) {
return reducer(state, action);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ROUTE_ANIMATIONS_ELEMENTS } from '../../../../core/core.module';

import { State } from '../../examples.state';
import { Book } from '../books.model';
import { ActionBooksUpsertOne, ActionBooksDeleteOne } from '../books.actions';
import { actionBooksDeleteOne, actionBooksUpsertOne } from '../books.actions';
import { selectSelectedBook, selectAllBooks } from '../books.selectors';

@Component({
Expand Down Expand Up @@ -69,15 +69,15 @@ export class CrudComponent {
}

delete(book: Book) {
this.store.dispatch(new ActionBooksDeleteOne({ id: book.id }));
this.store.dispatch(actionBooksDeleteOne({ id: book.id }));
this.isEditing = false;
this.router.navigate(['examples/crud']);
}

save() {
if (this.bookFormGroup.valid) {
const book = this.bookFormGroup.value;
this.store.dispatch(new ActionBooksUpsertOne({ book }));
this.store.dispatch(actionBooksUpsertOne({ book }));
this.isEditing = false;
this.router.navigate(['examples/crud', book.id]);
}
Expand Down

0 comments on commit 0fc5dc4

Please sign in to comment.