Skip to content

Commit

Permalink
Merge branch 'master' into devtool-sanitizers
Browse files Browse the repository at this point in the history
  • Loading branch information
rupeshtiwari authored Nov 3, 2017
2 parents 10ddaaa + 2a22211 commit 99333d6
Show file tree
Hide file tree
Showing 48 changed files with 763 additions and 102 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: 4 additions & 0 deletions build/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ export const packages: PackageDescription[] = [
name: 'entity',
hasTestingModule: false,
},
{
name: 'codegen',
hasTestingModule: false,
},
];
2 changes: 1 addition & 1 deletion docs/entity/adapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export interface User {
`user.actions.ts`

```ts
import { Action } from '@ngrx/action';
import { Action } from '@ngrx/store';
import { User } from './user.model';

export const LOAD_USERS = '[User] Load Users';
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: 6 additions & 0 deletions modules/codegen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@ngrx/codegen
=======

The sources for this package are in the main [ngrx/platform](https://github.com/ngrx/platform) repo. Please file issues and pull requests against that repo.

License: MIT
7 changes: 7 additions & 0 deletions modules/codegen/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* DO NOT EDIT
*
* This file is automatically generated at build
*/

export * from './public_api';
21 changes: 21 additions & 0 deletions modules/codegen/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@ngrx/codegen",
"version": "4.1.0",
"description": "Codegen for Ngrx and Redux actions",
"module": "@ngrx/codegen.es5.js",
"es2015": "@ngrx/codegen.js",
"main": "bundles/codegen.umd.js",
"typings": "codegen.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/ngrx/platform.git"
},
"authors": ["Mike Ryan"],
"license": "MIT",
"dependencies": {
"glob": "^7.1.2",
"lodash": "^4.17.4",
"ora": "^1.3.0",
"typescript": "^2.4.0"
}
}
1 change: 1 addition & 0 deletions modules/codegen/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src/index';
10 changes: 10 additions & 0 deletions modules/codegen/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default {
entry: './dist/codegen/@ngrx/codegen.es5.js',
dest: './dist/codegen/bundles/codegen.umd.js',
format: 'umd',
exports: 'named',
moduleName: 'ngrx.codegen',
globals: {

}
}
Loading

0 comments on commit 99333d6

Please sign in to comment.