diff --git a/.angular-cli.json b/.angular-cli.json index fd1dc1a..1684599 100644 --- a/.angular-cli.json +++ b/.angular-cli.json @@ -1,60 +1,65 @@ { - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "project": { - "name": "gen" - }, - "apps": [ - { - "root": "src", - "outDir": "dist", - "assets": [ - "assets", - "favicon.ico" - ], - "index": "index.html", - "main": "main.ts", - "polyfills": "polyfills.ts", - "test": "test.ts", - "tsconfig": "tsconfig.app.json", - "testTsconfig": "tsconfig.spec.json", - "prefix": "app", - "styles": [ - "styles.css" - ], - "scripts": [], - "environmentSource": "environments/environment.ts", - "environments": { - "dev": "environments/environment.ts", - "prod": "environments/environment.prod.ts" - } - } - ], - "e2e": { - "protractor": { - "config": "./protractor.conf.js" - } - }, - "lint": [ - { - "project": "src/tsconfig.app.json", - "exclude": "**/node_modules/**" + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "project": { + "name": "gen" }, - { - "project": "src/tsconfig.spec.json", - "exclude": "**/node_modules/**" + "apps": [ + { + "root": "src", + "outDir": "dist", + "assets": [ + "assets", + "favicon.ico" + ], + "index": "index.html", + "main": "main.ts", + "polyfills": "polyfills.ts", + "test": "test.ts", + "tsconfig": "tsconfig.app.json", + "testTsconfig": "tsconfig.spec.json", + "prefix": "app", + "styles": [ + "styles.css" + ], + "scripts": [], + "environmentSource": "environments/environment.ts", + "environments": { + "dev": "environments/environment.ts", + "prod": "environments/environment.prod.ts" + } + } + ], + "e2e": { + "protractor": { + "config": "./protractor.conf.js" + } }, - { - "project": "e2e/tsconfig.e2e.json", - "exclude": "**/node_modules/**" + "lint": [ + { + "project": "src/tsconfig.app.json", + "exclude": "**/node_modules/**" + }, + { + "project": "src/tsconfig.spec.json", + "exclude": "**/node_modules/**" + }, + { + "project": "e2e/tsconfig.e2e.json", + "exclude": "**/node_modules/**" + } + ], + "test": { + "karma": { + "config": "./karma.conf.js" + } + }, + "defaults": { + "styleExt": "css", + "component": {}, + "serve": { + "port": 4200, + "host": "0.0.0.0", + "public-host": "dev.bitchmints.com:4200" + } } - ], - "test": { - "karma": { - "config": "./karma.conf.js" - } - }, - "defaults": { - "styleExt": "css", - "component": {} - } } diff --git a/package.json b/package.json index ea60fa4..c955bf1 100644 --- a/package.json +++ b/package.json @@ -1,49 +1,58 @@ { - "name": "gen", - "version": "0.0.0", - "license": "MIT", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build", - "test": "ng test", - "lint": "ng lint", - "e2e": "ng e2e" - }, - "private": true, - "dependencies": { - "@angular/animations": "^4.2.4", - "@angular/common": "^4.2.4", - "@angular/compiler": "^4.2.4", - "@angular/core": "^4.2.4", - "@angular/forms": "^4.2.4", - "@angular/http": "^4.2.4", - "@angular/platform-browser": "^4.2.4", - "@angular/platform-browser-dynamic": "^4.2.4", - "@angular/router": "^4.2.4", - "core-js": "^2.4.1", - "rxjs": "^5.4.2", - "zone.js": "^0.8.14" - }, - "devDependencies": { - "@angular/cli": "1.4.3", - "@angular/compiler-cli": "^4.2.4", - "@angular/language-service": "^4.2.4", - "@types/jasmine": "~2.5.53", - "@types/jasminewd2": "~2.0.2", - "@types/node": "~6.0.60", - "codelyzer": "~3.1.1", - "jasmine-core": "~2.6.2", - "jasmine-spec-reporter": "~4.1.0", - "karma": "~1.7.0", - "karma-chrome-launcher": "~2.1.1", - "karma-cli": "~1.0.1", - "karma-coverage-istanbul-reporter": "^1.2.1", - "karma-jasmine": "~1.1.0", - "karma-jasmine-html-reporter": "^0.2.2", - "protractor": "~5.1.2", - "ts-node": "~3.2.0", - "tslint": "~5.3.2", - "typescript": "~2.3.3" - } + "name": "gen", + "version": "0.0.0", + "license": "MIT", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e" + }, + "ngrxGen": { + "basePath": "./src/app", + "seperateDirectory": "true" + }, + "private": true, + "dependencies": { + "@angular/animations": "^4.2.4", + "@angular/common": "^4.2.4", + "@angular/compiler": "^4.2.4", + "@angular/core": "^4.2.4", + "@angular/forms": "^4.2.4", + "@angular/http": "^4.2.4", + "@angular/platform-browser": "^4.2.4", + "@angular/platform-browser-dynamic": "^4.2.4", + "@angular/router": "^4.2.4", + "@ngrx/effects": "^4.0.5", + "@ngrx/store": "^4.0.3", + "@ngrx/store-devtools": "^4.0.0", + "bootstrap": "^3.3.7", + "core-js": "^2.4.1", + "font-awesome": "^4.7.0", + "rxjs": "^5.4.2", + "zone.js": "^0.8.14" + }, + "devDependencies": { + "@angular/cli": "1.4.3", + "@angular/compiler-cli": "^4.2.4", + "@angular/language-service": "^4.2.4", + "@types/jasmine": "~2.5.53", + "@types/jasminewd2": "~2.0.2", + "@types/node": "~6.0.60", + "codelyzer": "~3.1.1", + "jasmine-core": "~2.6.2", + "jasmine-spec-reporter": "~4.1.0", + "karma": "~1.7.0", + "karma-chrome-launcher": "~2.1.1", + "karma-cli": "~1.0.1", + "karma-coverage-istanbul-reporter": "^1.2.1", + "karma-jasmine": "~1.1.0", + "karma-jasmine-html-reporter": "^0.2.2", + "protractor": "~5.1.2", + "ts-node": "~3.2.0", + "tslint": "~5.3.2", + "typescript": "~2.3.3" + } } diff --git a/serve.sh b/serve.sh new file mode 100755 index 0000000..d6d231d --- /dev/null +++ b/serve.sh @@ -0,0 +1 @@ +clear && ng serve --public-host=dev.bitchmints.com:4200 diff --git a/src/app/actions/podcasts.actions.ts b/src/app/actions/podcasts.actions.ts new file mode 100644 index 0000000..ff59909 --- /dev/null +++ b/src/app/actions/podcasts.actions.ts @@ -0,0 +1,26 @@ +import { Action } from '@ngrx/store'; + +export const LOAD = '[Podcasts] Load'; +export const LOAD_SUCCESS = '[Podcasts] Load Success'; +export const LOAD_FAIL = '[Podcasts] Load Fail'; + +export class LoadAction implements Action { + readonly type = LOAD; +} + +export class LoadSuccessAction implements Action { + readonly type = LOAD_SUCCESS; + + constructor(public payload: any) { } +} + +export class LoadFailAction implements Action { + readonly type = LOAD_FAIL; + + constructor(public payload: any) { } +} + +export type Actions = + | LoadAction + | LoadSuccessAction + | LoadFailAction; diff --git a/src/app/app.component.html b/src/app/app.component.html index 46d517b..d7782d8 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,20 +1,10 @@

- Welcome to {{title}}! + Hello, {{title}}!

- +
+
-

Here are some links to help you start:

- - diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts deleted file mode 100644 index bcbdf36..0000000 --- a/src/app/app.component.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { TestBed, async } from '@angular/core/testing'; -import { AppComponent } from './app.component'; -describe('AppComponent', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ - AppComponent - ], - }).compileComponents(); - })); - it('should create the app', async(() => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.debugElement.componentInstance; - expect(app).toBeTruthy(); - })); - it(`should have as title 'app'`, async(() => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.debugElement.componentInstance; - expect(app.title).toEqual('app'); - })); - it('should render title in a h1 tag', async(() => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.debugElement.nativeElement; - expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); - })); -}); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 7b0f672..7ea7bf7 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,10 +1,22 @@ import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs/Observable'; +import { LoadAction } from 'app/actions/podcasts.actions'; +import { State } from 'app/reducers'; + @Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.css'] + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] }) export class AppComponent { - title = 'app'; + title = 'Sailor'; + podcasts$: Observable; + + constructor(private store: Store){ + console.log('AppComponent', 'ctor', store); + this.podcasts$ = this.store.select(p => p.podcasts.result); + this.store.dispatch(new LoadAction()); + } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index f657163..f7fddef 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,16 +1,31 @@ import { BrowserModule } from '@angular/platform-browser'; +import { HttpModule } from '@angular/http'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; +import { StoreModule } from '@ngrx/store'; +import { EffectsModule } from '@ngrx/effects'; +import { StoreDevtoolsModule } from '@ngrx/store-devtools'; + +import { reducers } from './reducers'; +import { PodcastsEffects } from './effects/podcasts.effects'; +import { PodcastsService } from './services/podcasts.service'; + @NgModule({ - declarations: [ - AppComponent - ], - imports: [ - BrowserModule - ], - providers: [], - bootstrap: [AppComponent] + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, HttpModule, + + StoreModule.forRoot(reducers), + EffectsModule.forRoot([PodcastsEffects]), + StoreDevtoolsModule.instrument({maxAge: 25}) + ], + providers: [ + PodcastsService + ], + bootstrap: [AppComponent] }) export class AppModule { } diff --git a/src/app/effects/podcasts.effects.ts b/src/app/effects/podcasts.effects.ts new file mode 100644 index 0000000..57f2410 --- /dev/null +++ b/src/app/effects/podcasts.effects.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@angular/core'; +import { Actions, Effect } from '@ngrx/effects'; +import { Observable } from 'rxjs/Observable'; +import { PodcastsService } from '../services/podcasts.service'; +import * as podcasts from '../actions/podcasts.actions'; +import 'rxjs/add/operator/switchMap'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/catch'; +import 'rxjs/add/observable/of'; + +@Injectable() +export class PodcastsEffects { + constructor( + private podcastsService: PodcastsService, + private actions$: Actions + ) { } + + @Effect() get$ = this.actions$ + .ofType(podcasts.LOAD) + .switchMap(payload => this.podcastsService.get() + // If successful, dispatch success action with result + .map(res => ({ type: podcasts.LOAD_SUCCESS, payload: res.json() })) + // If request fails, dispatch failed action + .catch(() => Observable.of({ type: podcasts.LOAD_FAIL})) + ); +} diff --git a/src/app/reducers/index.ts b/src/app/reducers/index.ts new file mode 100644 index 0000000..7c5c5c4 --- /dev/null +++ b/src/app/reducers/index.ts @@ -0,0 +1,10 @@ +import * as fromPodcasts from './podcasts.reducer'; +import { ActionReducerMap } from '@ngrx/store'; + +export interface State { + podcasts: fromPodcasts.State; +} + +export const reducers: ActionReducerMap = { + podcasts: fromPodcasts.reducer +} diff --git a/src/app/reducers/podcasts.reducer.ts b/src/app/reducers/podcasts.reducer.ts new file mode 100644 index 0000000..abe2d9f --- /dev/null +++ b/src/app/reducers/podcasts.reducer.ts @@ -0,0 +1,46 @@ +import * as podcasts from '../actions/podcasts.actions'; + +export interface State { + loading: boolean; + entities: { [id: string]: any }; + result: string[]; +} + +export const initialState: State = { + loading: false, + entities: {}, + result: [] +} + +export function reducer(state = initialState, action: podcasts.Actions): State { + switch (action.type) { + case podcasts.LOAD: { + return { + ...state, + result: [], + loading: true + } + } + + case podcasts.LOAD_SUCCESS: { + + return { + ...state, + result: action.payload, + loading: false, + }; + } + + case podcasts.LOAD_FAIL: { + + return { + ...state, + loading: false, + }; + } + + default: { + return state; + } + } +} diff --git a/src/app/services/podcasts.service.ts b/src/app/services/podcasts.service.ts new file mode 100644 index 0000000..37d7dbf --- /dev/null +++ b/src/app/services/podcasts.service.ts @@ -0,0 +1,13 @@ +import { Injectable } from '@angular/core'; +import { Http } from '@angular/http'; +import { Observable } from 'rxjs/Observable'; + +@Injectable() +export class PodcastsService { + + constructor(private http: Http) { } + get() : Observable { + console.log('PodcastsService', 'get'); + return this.http.get('https://jsonplaceholder.typicode.com/posts'); + } +} diff --git a/src/styles.css b/src/styles.css index 90d4ee0..40e7da6 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1 +1,3 @@ /* You can add global styles to this file, and also import other style files */ +@import "~bootstrap/dist/css/bootstrap.min.css"; +@import "~font-awesome/css/font-awesome.css"; diff --git a/yarn.lock b/yarn.lock index 83e3e19..9a0e4f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -159,6 +159,18 @@ dependencies: tsickle "^0.21.0" +"@ngrx/effects@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-4.0.5.tgz#1224763800621b7305f9b18bc17ee09b25c861d1" + +"@ngrx/store-devtools@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-4.0.0.tgz#b79c24773217df7fd9735ad21f9cbf2533c96e04" + +"@ngrx/store@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-4.0.3.tgz#36abacdfa19bfb8506e40de80bae06050a1e15e9" + "@ngtools/json-schema@1.1.0", "@ngtools/json-schema@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@ngtools/json-schema/-/json-schema-1.1.0.tgz#c3a0c544d62392acc2813a42c8a0dc6f58f86922" @@ -671,6 +683,10 @@ boom@5.x.x: dependencies: hoek "4.x.x" +bootstrap@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-3.3.7.tgz#5a389394549f23330875a3b150656574f8a9eb71" + brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -1968,6 +1984,10 @@ flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" +font-awesome@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" + for-in@^0.1.3: version "0.1.8" resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1"