Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
phillipzada authored Oct 23, 2017
2 parents dae762f + 4db7d61 commit 3e5ff01
Show file tree
Hide file tree
Showing 17 changed files with 71 additions and 63 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Reactive libraries for Angular
- [@ngrx/router-store](./docs/router-store/README.md) - Bindings to connect the Angular Router to @ngrx/store
- [@ngrx/store-devtools](./docs/store-devtools/README.md) - Store instrumentation that enables a
[powerful time-travelling debugger](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en).
- [@ngrx/entity](./docs/entity/README.md) - Entity State adapter for managing record collections.

## Examples
- [example-app](./example-app/README.md) - Example application utilizing @ngrx libraries, showcasing common patterns and best practices.
Expand Down
4 changes: 2 additions & 2 deletions example-app/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterModule } from '@angular/router';
import { HttpModule } from '@angular/http';

import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
Expand All @@ -30,7 +30,7 @@ import { environment } from '../environments/environment';
CommonModule,
BrowserModule,
BrowserAnimationsModule,
HttpModule,
HttpClientModule,
RouterModule.forRoot(routes, { useHash: true }),

/**
Expand Down
9 changes: 8 additions & 1 deletion example-app/app/books/actions/book.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Book } from '../models/book';

export const SEARCH = '[Book] Search';
export const SEARCH_COMPLETE = '[Book] Search Complete';
export const SEARCH_ERROR = '[Book] Search Error';
export const LOAD = '[Book] Load';
export const SELECT = '[Book] Select';

Expand All @@ -25,6 +26,12 @@ export class SearchComplete implements Action {
constructor(public payload: Book[]) {}
}

export class SearchError implements Action {
readonly type = SEARCH_ERROR;

constructor(public payload: string) {}
}

export class Load implements Action {
readonly type = LOAD;

Expand All @@ -41,4 +48,4 @@ export class Select implements Action {
* Export a type alias of all actions in this action group
* so that reducers can easily compose action types
*/
export type Actions = Search | SearchComplete | Load | Select;
export type Actions = Search | SearchComplete | SearchError | Load | Select;
10 changes: 9 additions & 1 deletion example-app/app/books/components/book-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,23 @@ import { Component, Output, Input, EventEmitter } from '@angular/core';
</md-input-container>
<md-spinner [class.show]="searching"></md-spinner>
</md-card-content>
<md-card-footer><span *ngIf="error">{{error}}</span></md-card-footer>
</md-card>
`,
styles: [
`
md-card-title,
md-card-content {
md-card-content,
md-card-footer {
display: flex;
justify-content: center;
}
md-card-footer {
color: #FF0000;
padding: 5px 0;
}
input {
width: 300px;
}
Expand All @@ -50,5 +57,6 @@ import { Component, Output, Input, EventEmitter } from '@angular/core';
export class BookSearchComponent {
@Input() query = '';
@Input() searching = false;
@Input() error = '';
@Output() search = new EventEmitter<string>();
}
4 changes: 3 additions & 1 deletion example-app/app/books/containers/find-book-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,21 @@ import { Book } from '../models/book';
selector: 'bc-find-book-page',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<bc-book-search [query]="searchQuery$ | async" [searching]="loading$ | async" (search)="search($event)"></bc-book-search>
<bc-book-search [query]="searchQuery$ | async" [searching]="loading$ | async" [error]="error$ | async" (search)="search($event)"></bc-book-search>
<bc-book-preview-list [books]="books$ | async"></bc-book-preview-list>
`,
})
export class FindBookPageComponent {
searchQuery$: Observable<string>;
books$: Observable<Book[]>;
loading$: Observable<boolean>;
error$: Observable<string>;

constructor(private store: Store<fromBooks.State>) {
this.searchQuery$ = store.select(fromBooks.getSearchQuery).take(1);
this.books$ = store.select(fromBooks.getSearchResults);
this.loading$ = store.select(fromBooks.getSearchLoading);
this.error$ = store.select(fromBooks.getSearchError);
}

search(query: string) {
Expand Down
8 changes: 4 additions & 4 deletions example-app/app/books/effects/book.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { empty } from 'rxjs/observable/empty';
import { BookEffects, SEARCH_SCHEDULER, SEARCH_DEBOUNCE } from './book';
import { GoogleBooksService } from '../../core/services/google-books';
import { Observable } from 'rxjs/Observable';
import { Search, SearchComplete } from '../actions/book';
import { Search, SearchComplete, SearchError } from '../actions/book';
import { Book } from '../models/book';

export class TestActions extends Actions {
Expand Down Expand Up @@ -62,10 +62,10 @@ describe('BookEffects', () => {
expect(effects.search$).toBeObservable(expected);
});

it('should return a new book.SearchComplete, with an empty array, if the books service throws', () => {
it('should return a new book.SearchError if the books service throws', () => {
const action = new Search('query');
const completion = new SearchComplete([]);
const error = 'Error!';
const completion = new SearchError('Unexpected Error. Try again later.');
const error = 'Unexpected Error. Try again later.';

actions$.stream = hot('-a---', { a: action });
const response = cold('-#|', {}, error);
Expand Down
2 changes: 1 addition & 1 deletion example-app/app/books/effects/book.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class BookEffects {
.searchBooks(query)
.takeUntil(nextSearch$)
.map((books: Book[]) => new book.SearchComplete(books))
.catch(() => of(new book.SearchComplete([])));
.catch(err => of(new book.SearchError(err)));
});

constructor(
Expand Down
4 changes: 4 additions & 0 deletions example-app/app/books/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ export const getSearchLoading = createSelector(
getSearchState,
fromSearch.getLoading
);
export const getSearchError = createSelector(
getSearchState,
fromSearch.getError
);

/**
* Some selector functions create joins across parts of state. This selector
Expand Down
17 changes: 16 additions & 1 deletion example-app/app/books/reducers/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import * as book from '../actions/book';
export interface State {
ids: string[];
loading: boolean;
error: string;
query: string;
}

const initialState: State = {
ids: [],
loading: false,
error: '',
query: '',
};

Expand All @@ -21,25 +23,36 @@ export function reducer(state = initialState, action: book.Actions): State {
return {
ids: [],
loading: false,
error: '',
query,
};
}

return {
...state,
query,
loading: true,
error: '',
query,
};
}

case book.SEARCH_COMPLETE: {
return {
ids: action.payload.map(book => book.id),
loading: false,
error: '',
query: state.query,
};
}

case book.SEARCH_ERROR: {
return {
...state,
loading: false,
error: action.payload,
};
}

default: {
return state;
}
Expand All @@ -51,3 +64,5 @@ export const getIds = (state: State) => state.ids;
export const getQuery = (state: State) => state.query;

export const getLoading = (state: State) => state.loading;

export const getError = (state: State) => state.error;
20 changes: 6 additions & 14 deletions example-app/app/core/services/google-books.spec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { TestBed } from '@angular/core/testing';
import { Http } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { cold } from 'jasmine-marbles';
import { GoogleBooksService } from './google-books';

describe('Service: GoogleBooks', () => {
let service: GoogleBooksService;
let http: any;
let http: HttpClient;

beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{ provide: Http, useValue: { get: jest.fn() } },
{ provide: HttpClient, useValue: { get: jest.fn() } },
GoogleBooksService,
],
});

service = TestBed.get(GoogleBooksService);
http = TestBed.get(Http);
http = TestBed.get(HttpClient);
});

const data = {
Expand All @@ -35,11 +35,7 @@ describe('Service: GoogleBooks', () => {
const queryTitle = 'Book Title';

it('should call the search api and return the search results', () => {
const httpResponse = {
json: () => books,
};

const response = cold('-a|', { a: httpResponse });
const response = cold('-a|', { a: books });
const expected = cold('-b|', { b: books.items });
http.get = jest.fn(() => response);

Expand All @@ -50,11 +46,7 @@ describe('Service: GoogleBooks', () => {
});

it('should retrieve the book from the volumeId', () => {
const httpResponse = {
json: () => data,
};

const response = cold('-a|', { a: httpResponse });
const response = cold('-a|', { a: data });
const expected = cold('-b|', { b: data });
http.get = jest.fn(() => response);

Expand Down
10 changes: 5 additions & 5 deletions example-app/app/core/services/google-books.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import 'rxjs/add/operator/map';
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Book } from '../../books/models/book';

@Injectable()
export class GoogleBooksService {
private API_PATH = 'https://www.googleapis.com/books/v1/volumes';

constructor(private http: Http) {}
constructor(private http: HttpClient) {}

searchBooks(queryTitle: string): Observable<Book[]> {
return this.http
.get(`${this.API_PATH}?q=${queryTitle}`)
.map(res => res.json().items || []);
.get<{ items: Book[] }>(`${this.API_PATH}?q=${queryTitle}`)
.map(books => books.items || []);
}

retrieveBook(volumeId: string): Observable<Book> {
return this.http.get(`${this.API_PATH}/${volumeId}`).map(res => res.json());
return this.http.get<Book>(`${this.API_PATH}/${volumeId}`);
}
}
6 changes: 2 additions & 4 deletions modules/effects/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@
"type": "git",
"url": "https://github.com/ngrx/platform.git"
},
"authors": [
"Mike Ryan"
],
"authors": ["Mike Ryan"],
"license": "MIT",
"peerDependencies": {
"@angular/core": "^4.0.0",
"@angular/core": "^4.0.0 || ^5.0.0-rc.2",
"@ngrx/store": "^4.0.0",
"rxjs": "^5.0.0"
}
Expand Down
6 changes: 2 additions & 4 deletions modules/entity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@
"type": "git",
"url": "https://github.com/ngrx/platform.git"
},
"authors": [
"Mike Ryan"
],
"authors": ["Mike Ryan"],
"license": "MIT",
"peerDependencies": {
"@angular/core": "^4.0.0",
"@angular/core": "^4.0.0 || ^5.0.0-rc.2",
"@ngrx/store": "^4.0.0",
"rxjs": "^5.0.0"
}
Expand Down
16 changes: 5 additions & 11 deletions modules/router-store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,13 @@
"type": "git",
"url": "git+https://github.com/ngrx/platform.git"
},
"keywords": [
"RxJS",
"Angular",
"Redux"
],
"authors": [
"Victor Savkin <[email protected]>"
],
"keywords": ["RxJS", "Angular", "Redux"],
"authors": ["Victor Savkin <[email protected]>"],
"license": "MIT",
"peerDependencies": {
"@angular/common": "^4.0.0",
"@angular/core": "^4.0.0",
"@angular/router": "^4.0.0",
"@angular/common": "^4.0.0 || ^5.0.0-rc.2",
"@angular/core": "^4.0.0 || ^5.0.0-rc.2",
"@angular/router": "^4.0.0 || ^5.0.0-rc.2",
"@ngrx/store": "^4.0.0",
"rxjs": "^5.0.0"
}
Expand Down
1 change: 0 additions & 1 deletion modules/router-store/spec/integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,6 @@ describe('integration spec', () => {
{ type: 'router', event: 'GuardsCheckEnd', url: '/next' },
{ type: 'router', event: 'ResolveStart', url: '/next' },
{ type: 'router', event: 'ResolveEnd', url: '/next' },

{ type: 'router', event: 'NavigationEnd', url: '/next' },
]);

Expand Down
8 changes: 1 addition & 7 deletions modules/store-devtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,7 @@
"type": "git",
"url": "git+https://github.com/ngrx/platform.git"
},
"keywords": [
"RxJS",
"Angular",
"Redux",
"Store",
"@ngrx/store"
],
"keywords": ["RxJS", "Angular", "Redux", "Store", "@ngrx/store"],
"contributors": [
{
"name": "Rob Wormald",
Expand Down
8 changes: 2 additions & 6 deletions modules/store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,15 @@
"type": "git",
"url": "git+https://github.com/ngrx/platform.git"
},
"keywords": [
"RxJS",
"Angular",
"Redux"
],
"keywords": ["RxJS", "Angular", "Redux"],
"author": "Rob Wormald <[email protected]>",
"license": "MIT",
"bugs": {
"url": "https://github.com/ngrx/platform/issues"
},
"homepage": "https://github.com/ngrx/platform#readme",
"peerDependencies": {
"@angular/core": "^4.0.0",
"@angular/core": "^4.0.0 || ^5.0.0-rc.2",
"rxjs": "^5.0.0"
}
}

0 comments on commit 3e5ff01

Please sign in to comment.