diff --git a/package.json b/package.json index a75cb191..9dbf151c 100644 --- a/package.json +++ b/package.json @@ -37,20 +37,21 @@ "node": ">=8" }, "devDependencies": { - "@angular/animations": "7.2.0", - "@angular/cli": "7.2.1", - "@angular/common": "7.2.0", - "@angular/compiler": "7.2.0", - "@angular/compiler-cli": "7.2.0", - "@angular/core": "7.2.0", - "@angular/forms": "7.2.0", - "@angular/platform-browser": "7.2.0", - "@angular/platform-browser-dynamic": "7.2.0", - "@angular/router": "7.2.0", + "@angular/animations": "7.2.1", + "@angular/cli": "7.2.2", + "@angular/common": "7.2.1", + "@angular/compiler": "7.2.1", + "@angular/compiler-cli": "7.2.1", + "@angular/core": "7.2.1", + "@angular/forms": "7.2.1", + "@angular/platform-browser": "7.2.1", + "@angular/platform-browser-dynamic": "7.2.1", + "@angular/router": "7.2.1", "@commitlint/cli": "7.0.0", "@commitlint/config-conventional": "7.0.1", "@commitlint/prompt-cli": "7.0.0", "@types/jest": "23.1.6", + "@types/webpack-env": "1.13.6", "babel-core": "6.26.3", "babel-jest": "23.4.2", "codelyzer": "4.5.0", diff --git a/packages/example-app/package.json b/packages/example-app/package.json index 334c7490..ce4679e7 100644 --- a/packages/example-app/package.json +++ b/packages/example-app/package.json @@ -26,6 +26,7 @@ "@angular/platform-browser": "^7.2.0", "@angular/platform-browser-dynamic": "^7.2.0", "@angular/router": "^7.2.0", + "@types/webpack-env": "1.13.6", "core-js": "^2.6.2", "flux-standard-action": "^2.0.3", "ramda": "^0.23.0", diff --git a/packages/example-app/src/app/animals/animal-list/component.ts b/packages/example-app/src/app/animals/animal-list/component.ts index 94c01a7f..b16e4383 100644 --- a/packages/example-app/src/app/animals/animal-list/component.ts +++ b/packages/example-app/src/app/animals/animal-list/component.ts @@ -13,12 +13,12 @@ export class AnimalListComponent { @Input() animalType!: string; @Input() animals!: Observable; @Input() loading!: Observable; - @Input() error!: Observable; + @Input() error!: Observable; // Since we're observing an array of items, we need to set up a 'trackBy' // parameter so Angular doesn't tear down and rebuild the list's DOM every // time there's an update. - getKey(_: any, animal: Animal) { + getKey(_: unknown, animal: Animal) { return animal.id; } } diff --git a/packages/example-app/src/app/animals/animal/reducers.ts b/packages/example-app/src/app/animals/animal/reducers.ts index 28319cb4..142eadd2 100644 --- a/packages/example-app/src/app/animals/animal/reducers.ts +++ b/packages/example-app/src/app/animals/animal/reducers.ts @@ -1,4 +1,6 @@ import { Action, Reducer } from 'redux'; + +import { Animal } from '../model'; import { ADD_TICKET, REMOVE_TICKET } from './actions'; export const ticketsReducer: Reducer = ( @@ -15,10 +17,13 @@ export const ticketsReducer: Reducer = ( }; // Basic reducer logic. -export const animalComponentReducer: Reducer = ( - state: any = {}, +export const animalComponentReducer = ( + state: Animal | undefined, action: Action, -): {} => ({ - ...state, - tickets: ticketsReducer(state.tickets, action), -}); +) => + state + ? { + ...state, + tickets: ticketsReducer(state.tickets, action), + } + : {}; diff --git a/packages/example-app/src/app/animals/api/actions.ts b/packages/example-app/src/app/animals/api/actions.ts index 8a5074f7..241f75fe 100644 --- a/packages/example-app/src/app/animals/api/actions.ts +++ b/packages/example-app/src/app/animals/api/actions.ts @@ -1,10 +1,11 @@ import { dispatch } from '@angular-redux/store'; import { Injectable } from '@angular/core'; import { FluxStandardAction } from 'flux-standard-action'; -import { Animal, AnimalType, LoadError } from '../model'; + +import { Animal, AnimalError, AnimalType } from '../model'; // Flux-standard-action gives us stronger typing of our actions. -export type Payload = Animal[] | LoadError; +export type Payload = Animal[] | AnimalError; export interface MetaData { animalType: AnimalType; @@ -44,8 +45,8 @@ export class AnimalAPIActions { loadFailed = ( animalType: AnimalType, - error: LoadError, - ): AnimalAPIAction => ({ + error: AnimalError, + ): AnimalAPIAction => ({ type: AnimalAPIActions.LOAD_FAILED, meta: { animalType }, payload: error, diff --git a/packages/example-app/src/app/animals/api/epics.ts b/packages/example-app/src/app/animals/api/epics.ts index 5846e587..d488af31 100644 --- a/packages/example-app/src/app/animals/api/epics.ts +++ b/packages/example-app/src/app/animals/api/epics.ts @@ -5,7 +5,7 @@ import { of } from 'rxjs'; import { catchError, filter, map, startWith, switchMap } from 'rxjs/operators'; import { AppState } from '../../store/model'; -import { Animal, AnimalType, LoadError } from '../model'; +import { Animal, AnimalError, AnimalType } from '../model'; import { AnimalAPIAction, AnimalAPIActions } from './actions'; import { AnimalAPIService } from './service'; @@ -37,8 +37,8 @@ export class AnimalAPIEpics { private createLoadAnimalEpic( animalType: AnimalType, ): Epic< - AnimalAPIAction, - AnimalAPIAction, + AnimalAPIAction, + AnimalAPIAction, AppState > { return (action$, state$) => diff --git a/packages/example-app/src/app/animals/api/reducer.ts b/packages/example-app/src/app/animals/api/reducer.ts index a7573b29..23457833 100644 --- a/packages/example-app/src/app/animals/api/reducer.ts +++ b/packages/example-app/src/app/animals/api/reducer.ts @@ -7,7 +7,7 @@ import { AnimalAPIAction, AnimalAPIActions } from './actions'; const INITIAL_STATE: AnimalList = { items: {}, loading: false, - error: null, + error: undefined, }; // A higher-order reducer: accepts an animal type and returns a reducer @@ -28,14 +28,14 @@ export function createAnimalAPIReducer(animalType: AnimalType) { ...state, items: {}, loading: true, - error: null, + error: undefined, }; case AnimalAPIActions.LOAD_SUCCEEDED: return { ...state, items: indexBy(prop('id'), action.payload as Animal[]), loading: false, - error: null, + error: undefined, }; case AnimalAPIActions.LOAD_FAILED: return { diff --git a/packages/example-app/src/app/animals/model.ts b/packages/example-app/src/app/animals/model.ts index 88bc85a5..587a4763 100644 --- a/packages/example-app/src/app/animals/model.ts +++ b/packages/example-app/src/app/animals/model.ts @@ -13,13 +13,19 @@ export interface Animal { tickets: number; } +export interface AnimalResponse { + name: string; + type: AnimalType; + ticketPrice: number; +} + export interface AnimalList { items: {}; loading: boolean; - error: any; + error: boolean | undefined; } -export interface LoadError { +export interface AnimalError { status: string; } @@ -31,10 +37,10 @@ export function initialAnimalList(): AnimalList { }; } -export const fromServer = (record: any): Animal => ({ +export const fromServer = (record: AnimalResponse): Animal => ({ id: record.name.toLowerCase(), - animalType: record.animalType, + animalType: record.type, name: record.name, ticketPrice: record.ticketPrice || 0, - tickets: record.tickets || 0, + tickets: 0, }); diff --git a/packages/example-app/src/app/elephants/page.spec.ts b/packages/example-app/src/app/elephants/page.spec.ts index 4133d50d..4966d58b 100644 --- a/packages/example-app/src/app/elephants/page.spec.ts +++ b/packages/example-app/src/app/elephants/page.spec.ts @@ -10,7 +10,7 @@ import { Observable } from 'rxjs'; import { toArray } from 'rxjs/operators'; import { AnimalAPIActions } from '../animals/api/actions'; -import { ANIMAL_TYPES } from '../animals/model'; +import { Animal, ANIMAL_TYPES } from '../animals/model'; import { ElephantPageComponent } from './page'; @Component({ @@ -19,9 +19,9 @@ import { ElephantPageComponent } from './page'; }) class MockAnimalListComponent { @Input() animalsName!: string; - @Input() animals!: Observable; + @Input() animals!: Observable; @Input() loading!: Observable; - @Input() error!: Observable; + @Input() error!: Observable; } describe('Elephant Page Container', () => { diff --git a/packages/example-app/src/app/elephants/page.ts b/packages/example-app/src/app/elephants/page.ts index 87d50437..6986f66f 100644 --- a/packages/example-app/src/app/elephants/page.ts +++ b/packages/example-app/src/app/elephants/page.ts @@ -8,8 +8,8 @@ import { map } from 'rxjs/operators'; import { AnimalAPIActions } from '../animals/api/actions'; import { Animal, ANIMAL_TYPES } from '../animals/model'; -export const sortAnimals = (animalDictionary$: Observable<{}>) => - animalDictionary$.pipe( +export function sortAnimals(animalDictionary$: Observable<{}>) { + return animalDictionary$.pipe( map( pipe( values, @@ -17,6 +17,7 @@ export const sortAnimals = (animalDictionary$: Observable<{}>) => ), ), ); +} @Component({ templateUrl: './page.html', @@ -31,7 +32,7 @@ export class ElephantPageComponent { readonly loading!: Observable; @select(['elephant', 'error']) - readonly error!: Observable; + readonly error!: Observable; constructor(actions: AnimalAPIActions) { actions.loadAnimals(ANIMAL_TYPES.ELEPHANT); diff --git a/packages/example-app/src/app/feedback/page.html b/packages/example-app/src/app/feedback/page.html index f3aed0bb..aba190f8 100644 --- a/packages/example-app/src/app/feedback/page.html +++ b/packages/example-app/src/app/feedback/page.html @@ -24,14 +24,14 @@

Feedback Form

ngControl ngModel /> - +