This repository has been archived by the owner on May 6, 2019. It is now read-only.
/
books.ts
88 lines (73 loc) · 2.34 KB
/
books.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import '@ngrx/core/add/operator/select';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';
import { Action } from '@ngrx/store';
import { Book } from '../models';
import { BookActions } from '../actions';
export interface BooksState {
ids: string[];
entities: { [id: string]: Book };
};
const initialState: BooksState = {
ids: [],
entities: {}
};
export default function(state = initialState, action: Action): BooksState {
switch (action.type) {
case BookActions.SEARCH_COMPLETE:
case BookActions.LOAD_COLLECTION_SUCCESS: {
const books: Book[] = action.payload;
const newBooks = books.filter(book => !state.entities[book.id]);
const newBookIds = newBooks.map(book => book.id);
const newBookEntities = newBooks.reduce((entities: { [id: string]: Book }, book: Book) => {
return Object.assign(entities, {
[book.id]: book
});
}, {});
return {
ids: [ ...state.ids, ...newBookIds ],
entities: Object.assign({}, state.entities, newBookEntities)
};
}
case BookActions.LOAD_BOOK: {
const book: Book = action.payload;
if (state.ids.includes(book.id)) {
return state;
}
return {
ids: [ ...state.ids, book.id ],
entities: Object.assign({}, state.entities, {
[book.id]: book
})
};
}
default: {
return state;
}
}
}
/**
* Because the data structure is defined within the reducer it is optimal to
* locate our selector functions at this level. If store is to be thought of
* as a database, and reducers the tables, selectors can be considered the
* queries into said database. Remember to keep your selectors small and
* focused so they can be combined and composed to fit each particular
* use-case.
*/
export function getBookEntities() {
return (state$: Observable<BooksState>) => state$
.select(s => s.entities);
};
export function getBook(id: string) {
return (state$: Observable<BooksState>) => state$
.select(s => s.entities[id]);
}
export function getBooks(bookIds: string[]) {
return (state$: Observable<BooksState>) => state$
.let(getBookEntities())
.map(entities => bookIds.map(id => entities[id]));
}
export function hasBook(id: string) {
return (state$: Observable<BooksState>) => state$
.select(s => s.ids.includes(id));
}