From df590ccfef64b51107b89bec185c4f78495c53fa Mon Sep 17 00:00:00 2001 From: Ihor Tkachuk Date: Sun, 12 Feb 2017 21:56:32 +0200 Subject: [PATCH 1/2] added routing --- .../homework_10/package.json | 7 +- .../homework_10/public/css/styles.css | 129 ++++++++++++++++++ .../homework_10/src/app/app-routing.module.ts | 22 +++ .../homework_10/src/app/app.component.html | 18 +-- .../homework_10/src/app/app.component.scss | 76 ++++------- .../homework_10/src/app/app.component.ts | 40 +----- .../homework_10/src/app/app.module.ts | 28 ++-- .../dashboard/dashboard.component.html | 8 ++ .../dashboard/dashboard.component.scss | 76 +++++++++++ .../dashboard/dashboard.component.ts | 22 +++ .../hero-detail/hero-detail.component.html | 3 + .../hero-detail/hero-detail.component.scss | 31 +++++ .../hero-detail/hero-detail.component.ts | 33 ++++- .../hero-edit/hero-edit.component.html | 33 ++--- .../hero-edit/hero-edit.component.ts | 32 +++-- .../components/heroes/heroes.component.html | 15 ++ .../components/heroes/heroes.component.scss | 61 +++++++++ .../app/components/heroes/heroes.component.ts | 36 +++++ .../homework_10/src/app/data/mock-heroes.ts | 39 ------ .../src/app/in-memory-data.service.ts | 44 ++++++ .../src/app/services/hero.service.ts | 43 ++++-- .../homework_10/src/index.html | 3 +- 22 files changed, 608 insertions(+), 191 deletions(-) create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/public/css/styles.css create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app-routing.module.ts mode change 100755 => 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.ts create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.html create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.scss create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.ts create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.html create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.scss create mode 100755 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.ts delete mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/data/mock-heroes.ts create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/in-memory-data.service.ts diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/package.json b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/package.json index 17a82327..859d5f89 100755 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/package.json +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/package.json @@ -17,12 +17,13 @@ "@angular/platform-browser": "~2.4.0", "@angular/platform-browser-dynamic": "~2.4.0", "@angular/router": "~3.4.0", + "angular-in-memory-web-api": "^0.2.4", "core-js": "~2.4.1", + "ng2-toastr": "~1.3.6", + "primeng": "~1.0.1", "reflect-metadata": "~0.1.3", "rxjs": "5.0.1", - "zone.js": "~0.7.2", - "ng2-toastr": "~1.3.6", - "primeng": "~1.0.1" + "zone.js": "~0.7.2" }, "devDependencies": { "@angular/compiler-cli": "~2.4.0", diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/public/css/styles.css b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/public/css/styles.css new file mode 100644 index 00000000..536b27ff --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/public/css/styles.css @@ -0,0 +1,129 @@ +/* Master Styles */ +h1 { + color: #369; + font-family: Arial, Helvetica, sans-serif; + font-size: 250%; +} + +h2, h3 { + color: #444; + font-family: Arial, Helvetica, sans-serif; + font-weight: lighter; +} + +body { + margin: 2em; +} + +body, input[text], button { + color: #888; + font-family: Cambria, Georgia; +} + +a { + cursor: pointer; + cursor: hand; +} + +button { + font-family: Arial; + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + cursor: hand; +} + +button:hover { + background-color: #cfd8dc; +} + +button:disabled { + background-color: #eee; + color: #aaa; + cursor: auto; +} + +/* Navigation link styles */ +nav a { + padding: 5px 10px; + text-decoration: none; + margin-right: 10px; + margin-top: 10px; + display: inline-block; + background-color: #eee; + border-radius: 4px; +} + +nav a:visited, a:link { + color: #607D8B; +} + +nav a:hover { + color: #039be5; + background-color: #CFD8DC; +} + +nav a.active { + color: #039be5; +} + +/* items class */ +.items { + margin: 0 0 2em 0; + list-style-type: none; + padding: 0; + width: 24em; +} + +.items li { + cursor: pointer; + position: relative; + left: 0; + background-color: #EEE; + margin: .5em; + padding: .3em 0; + height: 1.6em; + border-radius: 4px; +} + +.items li:hover { + color: #607D8B; + background-color: #DDD; + left: .1em; +} + +.items li.selected { + background-color: #CFD8DC; + color: white; +} + +.items li.selected:hover { + background-color: #BBD8DC; +} + +.items .text { + position: relative; + top: -3px; +} + +.items .badge { + display: inline-block; + font-size: small; + color: white; + padding: 0.8em 0.7em 0 0.7em; + background-color: #607D8B; + line-height: 1em; + position: relative; + left: -1px; + top: -4px; + height: 1.8em; + margin-right: .8em; + border-radius: 4px 0 0 4px; +} + +/* everywhere else */ +* { + font-family: Arial, Helvetica, sans-serif; +} \ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app-routing.module.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app-routing.module.ts new file mode 100644 index 00000000..d311b057 --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app-routing.module.ts @@ -0,0 +1,22 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { DashboardComponent } from './components/dashboard/dashboard.component'; +import { HeroesComponent } from './components/heroes/heroes.component'; +import { HeroDetailComponent } from './components/hero-detail/hero-detail.component'; +import { HeroEditComponent } from './components/hero-edit/hero-edit.component'; + +const routes: Routes = [ + { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, + { path: 'dashboard', component: DashboardComponent }, + { path: 'detail/:id', component: HeroDetailComponent }, + { path: 'edit/:id', component: HeroEditComponent }, + { path: 'heroes', component: HeroesComponent } +]; + +@NgModule({ + imports: [ RouterModule.forRoot(routes) ], + exports: [ RouterModule ] +}) + +export class AppRoutingModule {} diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.html index 3d1db8f3..88d6c2d3 100755 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.html +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.html @@ -1,12 +1,6 @@ -

My Heroes

- - - - - +

{{title}}

+ + diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.scss b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.scss index 05c62b89..0ec3bd1d 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.scss +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.scss @@ -1,61 +1,33 @@ -.selected { - background-color: #CFD8DC !important; - color: white; +h1 { + font-size: 1.2em; + color: #999; + margin-bottom: 0; } -.heroes { - margin: 0 0 2em 0; - list-style-type: none; - padding: 0; - width: 15em; - - li { - cursor: pointer; - position: relative; - left: 0; - background-color: #EEE; - margin: .5em; - padding: .3em 0; - height: 1.6em; - border-radius: 4px; - - &.selected:hover { - background-color: #BBD8DC !important; - color: white; - } +h2 { + font-size: 2em; + margin-top: 0; + padding-top: 0; +} - &:hover { - color: #607D8B; - background-color: #DDD; - left: .1em; - } +nav a { + padding: 5px 10px; + text-decoration: none; + margin-top: 10px; + display: inline-block; + background-color: #eee; + border-radius: 4px; - i { - position: absolute; - right: 6px; - color: darkgrey; - border-left: 1px solid; - padding-left: 5px; - } + &:visited, &:link { + color: #607D8B; } - .text { - position: relative; - top: -3px; + &:hover { + color: #039be5; + background-color: #CFD8DC; } - .badge { - display: inline-block; - font-size: small; - color: white; - padding: 0.8em 0.7em 0 0.7em; - background-color: #607D8B; - line-height: 1em; - position: relative; - left: -1px; - top: -4px; - height: 1.8em; - margin-right: .8em; - border-radius: 4px 0 0 4px; + &.active { + color: #039be5; } -} +} \ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.ts old mode 100755 new mode 100644 index 58607b9b..f79306a8 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.ts +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.component.ts @@ -1,41 +1,11 @@ -import { Component, OnInit } from '@angular/core'; - -import { Hero } from './shared/hero'; -import { HeroService } from './services/hero.service'; +import { Component } from '@angular/core'; @Component({ - selector: 'hero-app', + selector: 'my-app', templateUrl: 'app.component.html', - styleUrls: ['app.component.scss'], + styleUrls: ['app.component.scss'] }) -export class AppComponent implements OnInit { - heroes: Hero[]; - selectedHero: Hero; - editHero: Hero; - - constructor(private heroService: HeroService) {} - - getHeroes(): void { - this.heroes = this.heroService.getHeroes(); - } - - ngOnInit(): void { - this.getHeroes(); - } - - onSelect(hero: Hero): void { - this.editHero = null; - this.selectedHero = hero; - } - - onEdit(hero: Hero): void { - this.selectedHero = null; - this.editHero = hero; - } - - clear() { - this.selectedHero = null; - this.editHero = null; - } +export class AppComponent { + title = 'Tour of Heroes'; } diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.module.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.module.ts index ac6c6d01..8fe7acda 100755 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.module.ts +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.module.ts @@ -1,22 +1,34 @@ -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { FormsModule } from '@angular/forms'; +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { FormsModule } from '@angular/forms'; +import { AppRoutingModule } from './app-routing.module'; +import { HttpModule } from '@angular/http'; -import { AppComponent } from './app.component'; -import { HeroDetailComponent } from './components/hero-detail/hero-detail.component'; -import { HeroEditComponent } from './components/hero-edit/hero-edit.component'; +import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; +import { InMemoryDataService } from './in-memory-data.service'; + +import { AppComponent } from './app.component'; +import { HeroesComponent } from './components/heroes/heroes.component'; +import { HeroDetailComponent } from './components/hero-detail/hero-detail.component'; +import { HeroEditComponent } from './components/hero-edit/hero-edit.component'; +import { DashboardComponent } from './components/dashboard/dashboard.component'; import { HeroService } from './services/hero.service'; @NgModule({ declarations: [ AppComponent, + HeroesComponent, HeroDetailComponent, - HeroEditComponent + HeroEditComponent, + DashboardComponent ], imports: [ BrowserModule, - FormsModule + FormsModule, + HttpModule, + InMemoryWebApiModule.forRoot(InMemoryDataService), + AppRoutingModule ], bootstrap: [ AppComponent diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.html new file mode 100644 index 00000000..f627812e --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.html @@ -0,0 +1,8 @@ +

Top Heroes

+
+ +
+

{{hero.name}}

+
+
+
\ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.scss b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.scss new file mode 100644 index 00000000..d8029a7c --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.scss @@ -0,0 +1,76 @@ +[class*='col-'] { + float: left; + padding-right: 20px; + padding-bottom: 20px; +} + +[class*='col-']:last-of-type { + padding-right: 0; +} + +a { + text-decoration: none; +} + +*, *:after, *:before { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +h3 { + text-align: center; + margin-bottom: 0; +} + +h4 { + position: relative; +} + +.grid { + margin: 0; +} + +.col-1-4 { + width: 25%; +} + +.module { + padding: 20px; + text-align: center; + color: #eee; + max-height: 120px; + min-width: 120px; + background-color: #607D8B; + border-radius: 2px; + + &:hover { + background-color: #EEE; + cursor: pointer; + color: #607d8b; + } +} + +.grid-pad { + padding: 10px 0; +} + +.grid-pad > [class*='col-']:last-of-type { + padding-right: 20px; +} + +@media (max-width: 600px) { + .module { + font-size: 10px; + max-height: 75px; + } +} + +@media (max-width: 1024px) { + .grid { + margin: 0; + } + .module { + min-width: 60px; + } +} \ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.ts new file mode 100644 index 00000000..b6fb4519 --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.ts @@ -0,0 +1,22 @@ +import { Component, OnInit } from '@angular/core'; + +import { Hero } from '../../shared/hero'; +import { HeroService } from '../../services/hero.service'; + +@Component({ + selector: 'my-dashboard', + templateUrl: 'dashboard.component.html', + styleUrls: ['dashboard.component.scss'] +}) + +export class DashboardComponent implements OnInit { + heroes: Hero[] = []; + + constructor(private heroService: HeroService) { + } + + ngOnInit(): void { + this.heroService.getHeroes() + .then(heroes => this.heroes = heroes.slice(1, 5)); + } +} diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.html index 4e2898de..b9f0338d 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.html +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.html @@ -3,4 +3,7 @@

{{hero.name}} details!

{{hero.id}}
{{hero.name}}
{{hero.name}} + + + \ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.scss b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.scss index 9e645ba2..25bcc263 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.scss +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.scss @@ -1,8 +1,39 @@ label { + display: inline-block; + width: 3em; + margin: .5em 0; + color: #607D8B; font-weight: bold; } +input { + height: 2em; + font-size: 1em; + padding-left: .4em; +} + +button { + margin-top: 20px; + font-family: Arial, sans-serif; + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + + &:hover { + background-color: #cfd8dc; + } + + &:disabled { + background-color: #eee; + color: #ccc; + cursor: auto; + } +} + img { + display: block; width: 100px; height: auto; } \ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.ts index 53b01eef..06a16169 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.ts +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-detail/hero-detail.component.ts @@ -1,6 +1,11 @@ -import { Component, Input } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRoute, Params } from '@angular/router'; +import { Location } from '@angular/common'; -import { Hero } from '../../shared/hero'; +import { Hero } from '../../shared/hero'; +import { HeroService } from '../../services/hero.service'; + +import 'rxjs/add/operator/switchMap'; @Component({ selector: 'hero-detail', @@ -8,6 +13,26 @@ import { Hero } from '../../shared/hero'; styleUrls: ['hero-detail.component.scss'] }) -export class HeroDetailComponent { - @Input() hero: Hero; +export class HeroDetailComponent implements OnInit { + hero: Hero; + + constructor(private router: Router, + private heroService: HeroService, + private route: ActivatedRoute, + private location: Location) { + } + + ngOnInit(): void { + this.route.params + .switchMap((params: Params) => this.heroService.getHero(+params['id'])) + .subscribe(hero => this.hero = hero); + } + + gotoEdit(): void { + this.router.navigate(['/edit', this.hero.id]); + } + + goBack(): void { + this.location.back(); + } } diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.html index a171e8f1..dd60fbf0 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.html +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.html @@ -1,16 +1,17 @@ -
-

{{hero.name}} Edit!

-
{{hero.id}}
- -
- - -
-
- - -
-
- -
-
\ No newline at end of file +

Edit!

+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.ts index 55fe3327..987a2ddd 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.ts +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.ts @@ -1,7 +1,11 @@ -import { Component, Input, Output, EventEmitter } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Params } from '@angular/router'; +import { Location } from '@angular/common'; -import { Hero } from '../../shared/hero'; -import { HeroService } from '../../services/hero.service'; +import { Hero } from '../../shared/hero'; +import { HeroService } from '../../services/hero.service'; + +import 'rxjs/add/operator/switchMap'; @Component({ selector: 'hero-edit', @@ -9,14 +13,22 @@ import { HeroService } from '../../services/hero.service'; styleUrls: ['hero-edit.component.scss'] }) -export class HeroEditComponent { - @Input() hero: Hero; - @Output() save = new EventEmitter(); +export class HeroEditComponent implements OnInit { + hero: Hero; + + constructor(private heroService: HeroService, + private route: ActivatedRoute, + private location: Location) { + } - constructor(private heroService: HeroService) {} + ngOnInit(): void { + this.route.params + .switchMap((params: Params) => this.heroService.getHero(+params['id'])) + .subscribe(hero => this.hero = hero); + console.log(this.hero); // returns undefined + } - onSubmit(formValue: Hero): void { - this.heroService.update(formValue); - this.save.emit(); + goBack(): void { + this.location.back(); } } \ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.html new file mode 100644 index 00000000..3a0c75f4 --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.html @@ -0,0 +1,15 @@ +

My Heroes

+ + + +
+

+ {{selectedHero.name | uppercase}} is my hero +

+ +
diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.scss b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.scss new file mode 100644 index 00000000..05c62b89 --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.scss @@ -0,0 +1,61 @@ +.selected { + background-color: #CFD8DC !important; + color: white; +} + +.heroes { + margin: 0 0 2em 0; + list-style-type: none; + padding: 0; + width: 15em; + + li { + cursor: pointer; + position: relative; + left: 0; + background-color: #EEE; + margin: .5em; + padding: .3em 0; + height: 1.6em; + border-radius: 4px; + + &.selected:hover { + background-color: #BBD8DC !important; + color: white; + } + + &:hover { + color: #607D8B; + background-color: #DDD; + left: .1em; + } + + i { + position: absolute; + right: 6px; + color: darkgrey; + border-left: 1px solid; + padding-left: 5px; + } + } + + .text { + position: relative; + top: -3px; + } + + .badge { + display: inline-block; + font-size: small; + color: white; + padding: 0.8em 0.7em 0 0.7em; + background-color: #607D8B; + line-height: 1em; + position: relative; + left: -1px; + top: -4px; + height: 1.8em; + margin-right: .8em; + border-radius: 4px 0 0 4px; + } +} diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.ts new file mode 100755 index 00000000..f54698f5 --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; + +import { Hero } from '../../shared/hero'; +import { HeroService } from '../../services/hero.service'; + +@Component({ + selector: 'my-heroes', + templateUrl: 'heroes.component.html', + styleUrls: ['heroes.component.scss'], +}) + +export class HeroesComponent implements OnInit { + heroes: Hero[]; + selectedHero: Hero; + + constructor(private router: Router, + private heroService: HeroService) { + } + + getHeroes(): void { + this.heroService.getHeroes().then(heroes => this.heroes = heroes); + } + + ngOnInit(): void { + this.getHeroes(); + } + + onSelect(hero: Hero): void { + this.selectedHero = hero; + } + + gotoDetail(): void { + this.router.navigate(['/detail', this.selectedHero.id]); + } +} diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/data/mock-heroes.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/data/mock-heroes.ts deleted file mode 100644 index bd2a69a1..00000000 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/data/mock-heroes.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Hero } from '../shared/hero'; - -export const HEROES: Hero[] = [ - { - id: 1, - name: 'Hulk', - image: 'https://upload.wikimedia.org/wikipedia/en/5/59/Hulk_(comics_character).png' - }, - { - id: 2, - name: 'Superman', - image: 'https://upload.wikimedia.org/wikipedia/en/e/eb/SupermanRoss.png' - }, - { - id: 3, - name: 'Batman', - image: 'https://upload.wikimedia.org/wikipedia/en/1/17/Batman-BenAffleck.jpg' - }, - { - id: 4, - name: 'Iron Man', - image: 'https://upload.wikimedia.org/wikipedia/en/e/e0/Iron_Man_bleeding_edge.jpg' - }, - { - id: 5, - name: 'Capitan America', - image: 'http://vignette3.wikia.nocookie.net/marveldatabase/images/f/f0/Steven_Rogers_(Earth-1610).png/revision/latest?cb=20100205184014' - }, - { - id: 6, - name: 'Green Lantern', - image: 'https://s-media-cache-ak0.pinimg.com/736x/f6/fd/e2/f6fde22f9571b81ac9d7ffcf580c2b87.jpg' - }, - { - id: 7, - name: 'Thor', - image: 'https://marvelheroes.com/sites/default/files/styles/character_profile_266x405/public/character/image/Store_Thor_Modern.png?itok=ky_Xd0nm' - } -]; diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/in-memory-data.service.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/in-memory-data.service.ts new file mode 100644 index 00000000..b1ef37c3 --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/in-memory-data.service.ts @@ -0,0 +1,44 @@ +import { InMemoryDbService } from 'angular-in-memory-web-api'; + +export class InMemoryDataService implements InMemoryDbService { + createDb() { + let heroes = [ + { + id: 1, + name: 'Hulk', + image: 'https://upload.wikimedia.org/wikipedia/en/5/59/Hulk_(comics_character).png' + }, + { + id: 2, + name: 'Superman', + image: 'https://upload.wikimedia.org/wikipedia/en/e/eb/SupermanRoss.png' + }, + { + id: 3, + name: 'Batman', + image: 'https://upload.wikimedia.org/wikipedia/en/1/17/Batman-BenAffleck.jpg' + }, + { + id: 4, + name: 'Iron Man', + image: 'https://upload.wikimedia.org/wikipedia/en/e/e0/Iron_Man_bleeding_edge.jpg' + }, + { + id: 5, + name: 'Capitan America', + image: 'http://vignette3.wikia.nocookie.net/marveldatabase/images/f/f0/Steven_Rogers_(Earth-1610).png/revision/latest?cb=20100205184014' + }, + { + id: 6, + name: 'Green Lantern', + image: 'https://s-media-cache-ak0.pinimg.com/736x/f6/fd/e2/f6fde22f9571b81ac9d7ffcf580c2b87.jpg' + }, + { + id: 7, + name: 'Thor', + image: 'https://marvelheroes.com/sites/default/files/styles/character_profile_266x405/public/character/image/Store_Thor_Modern.png?itok=ky_Xd0nm' + } + ]; + return { heroes }; + } +} diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero.service.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero.service.ts index 01b42236..170fb6ac 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero.service.ts +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero.service.ts @@ -1,24 +1,45 @@ import { Injectable } from '@angular/core'; +import { Headers, Http } from '@angular/http'; -import { Hero } from '../shared/hero'; -import { HEROES } from '../data/mock-heroes'; +import 'rxjs/add/operator/toPromise'; + +import { Hero } from '../shared/hero'; @Injectable() export class HeroService { - heroes = HEROES; + private heroesUrl = 'api/heroes'; + + constructor(private http: Http) { } - getHeroes() { - return this.heroes; + getHeroes(): Promise { + return this.http.get(this.heroesUrl) + .toPromise() + .then(response => response.json().data as Hero[]) + .catch(this.handleError); } - getHeroById(id: number) { - return this.heroes.filter((item) => item.id === id).pop(); + getHero(id: number): Promise { + const url = `${this.heroesUrl}/${id}`; + return this.http.get(url) + .toPromise() + .then(response => response.json().data as Hero) + .catch(this.handleError); } - update(obj: Hero) { - let hero = this.getHeroById(obj.id); - Object.assign(hero, obj); - return hero; + private handleError(error: any): Promise { + console.error('An error occurred', error); + return Promise.reject(error.message || error); } + + + // getHeroById(id: number) { + // return this.heroes.filter((item) => item.id === id).pop(); + // } + // + // update(obj: Hero) { + // let hero = this.getHeroById(obj.id); + // Object.assign(hero, obj); + // return hero; + // } } diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/index.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/index.html index 68ea1682..2c347cd7 100755 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/index.html +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/index.html @@ -8,10 +8,11 @@ + - Loading... + Loading... From 94df79a0ed49eeeb7671fc312408ca75a7a3600b Mon Sep 17 00:00:00 2001 From: Ihor Tkachuk Date: Mon, 13 Feb 2017 23:23:09 +0200 Subject: [PATCH 2/2] added reactive form --- .../homework_10/src/app/app.module.ts | 17 +++--- .../dashboard/dashboard.component.html | 4 +- .../hero-edit/hero-edit.component.html | 32 +++++------ .../hero-edit/hero-edit.component.scss | 16 +++++- .../hero-edit/hero-edit.component.ts | 35 ++++++++++-- .../hero-search/hero-search.component.html | 10 ++++ .../hero-search/hero-search.component.scss | 15 +++++ .../hero-search/hero-search.component.ts | 56 +++++++++++++++++++ .../components/heroes/heroes.component.html | 9 +++ .../components/heroes/heroes.component.scss | 8 +++ .../app/components/heroes/heroes.component.ts | 19 +++++++ .../src/app/services/hero-search.service.ts | 20 +++++++ .../src/app/services/hero.service.ts | 37 ++++++++---- 13 files changed, 235 insertions(+), 43 deletions(-) create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.html create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.scss create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.ts create mode 100644 homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero-search.service.ts diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.module.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.module.ts index 8fe7acda..60cbcc13 100755 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.module.ts +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/app.module.ts @@ -1,8 +1,8 @@ -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { FormsModule } from '@angular/forms'; -import { AppRoutingModule } from './app-routing.module'; -import { HttpModule } from '@angular/http'; +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { AppRoutingModule } from './app-routing.module'; +import { HttpModule } from '@angular/http'; import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; import { InMemoryDataService } from './in-memory-data.service'; @@ -12,6 +12,7 @@ import { HeroesComponent } from './components/heroes/heroes.component'; import { HeroDetailComponent } from './components/hero-detail/hero-detail.component'; import { HeroEditComponent } from './components/hero-edit/hero-edit.component'; import { DashboardComponent } from './components/dashboard/dashboard.component'; +import { HeroSearchComponent } from './components/hero-search/hero-search.component'; import { HeroService } from './services/hero.service'; @@ -21,14 +22,16 @@ import { HeroService } from './services/hero.service'; HeroesComponent, HeroDetailComponent, HeroEditComponent, - DashboardComponent + DashboardComponent, + HeroSearchComponent ], imports: [ BrowserModule, FormsModule, HttpModule, InMemoryWebApiModule.forRoot(InMemoryDataService), - AppRoutingModule + AppRoutingModule, + ReactiveFormsModule ], bootstrap: [ AppComponent diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.html index f627812e..56bf2804 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.html +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/dashboard/dashboard.component.html @@ -5,4 +5,6 @@

Top Heroes

{{hero.name}}

- \ No newline at end of file + + + \ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.html index dd60fbf0..bd8cb8a1 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.html +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.html @@ -1,17 +1,15 @@ -

Edit!

- - - - - - - - - - - - - - - - \ No newline at end of file +
+

{{hero.name}} Edit!

+
{{hero.id}}
+
+ + +
+
+ + +
+
+ +
+
\ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.scss b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.scss index eb813562..fad3e429 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.scss +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.scss @@ -1,3 +1,17 @@ input.ng-invalid { - border: 1px solid red; + border: 1px solid #F44336; + box-shadow: 0 0 5px #F44336; +} + +input { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 6px 12px; + background: none; + border: 1px solid #eee; +} + +.field { + margin-bottom: 10px; } \ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.ts index 987a2ddd..90802caf 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.ts +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-edit/hero-edit.component.ts @@ -1,6 +1,7 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Params } from '@angular/router'; -import { Location } from '@angular/common'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Params } from '@angular/router'; +import { Location } from '@angular/common'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { Hero } from '../../shared/hero'; import { HeroService } from '../../services/hero.service'; @@ -15,17 +16,39 @@ import 'rxjs/add/operator/switchMap'; export class HeroEditComponent implements OnInit { hero: Hero; + form: FormGroup; constructor(private heroService: HeroService, private route: ActivatedRoute, - private location: Location) { + private location: Location, + private fb: FormBuilder) { + this.createForm(); } ngOnInit(): void { this.route.params .switchMap((params: Params) => this.heroService.getHero(+params['id'])) - .subscribe(hero => this.hero = hero); - console.log(this.hero); // returns undefined + .subscribe(hero => { + this.hero = hero; + this.form.setValue({ + id: this.hero.id, + name: this.hero.name, + image: this.hero.image + }); + }); + } + + createForm() { + this.form = this.fb.group({ + id: [''], + name: ['', Validators.required], + image: ['', Validators.required] + }); + } + + save(): void { + this.heroService.update(this.form.value) + .then(() => this.goBack()); } goBack(): void { diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.html new file mode 100644 index 00000000..a971555a --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.html @@ -0,0 +1,10 @@ +
+

Hero Search

+ +
+
+ {{hero.name}} +
+
+
\ No newline at end of file diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.scss b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.scss new file mode 100644 index 00000000..d71389a3 --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.scss @@ -0,0 +1,15 @@ +.search-result { + border-bottom: 1px solid gray; + border-left: 1px solid gray; + border-right: 1px solid gray; + width: 195px; + height: 20px; + padding: 5px; + background-color: white; + cursor: pointer; +} + +#search-box { + width: 200px; + height: 20px; +} diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.ts new file mode 100644 index 00000000..6fb4551a --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/hero-search/hero-search.component.ts @@ -0,0 +1,56 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable } from 'rxjs/Observable'; +import { Subject } from 'rxjs/Subject'; + +// Observable class extensions +import 'rxjs/add/observable/of'; +// Observable operators +import 'rxjs/add/operator/catch'; +import 'rxjs/add/operator/debounceTime'; +import 'rxjs/add/operator/distinctUntilChanged'; + +import { HeroSearchService } from '../../services/hero-search.service'; +import { Hero } from '../../shared/hero'; + +@Component({ + selector: 'hero-search', + templateUrl: 'hero-search.component.html', + styleUrls: ['hero-search.component.scss'], + providers: [HeroSearchService] +}) + +export class HeroSearchComponent implements OnInit { + heroes: Observable; + private searchTerms = new Subject(); + + constructor(private heroSearchService: HeroSearchService, + private router: Router) { + } + + // Push a search term into the observable stream. + search(term: string): void { + this.searchTerms.next(term); + } + + ngOnInit(): void { + this.heroes = this.searchTerms + .debounceTime(300) // wait 300ms after each keystroke before considering the term + .distinctUntilChanged() // ignore if next search term is same as previous + .switchMap(term => term // switch to new observable each time the term changes + // return the http search observable + ? this.heroSearchService.search(term) + // or the observable of empty heroes if there was no search term + : Observable.of([])) + .catch(error => { + // TODO: add real error handling + console.log(error); + return Observable.of([]); + }); + } + + gotoDetail(hero: Hero): void { + let link = ['/detail', hero.id]; + this.router.navigate(link); + } +} diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.html b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.html index 3a0c75f4..99440ec8 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.html +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.html @@ -1,9 +1,18 @@

My Heroes

+
+ + +
+
  • {{hero.id}} {{hero.name}} +
diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.scss b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.scss index 05c62b89..4ee72cd5 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.scss +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.scss @@ -59,3 +59,11 @@ border-radius: 4px 0 0 4px; } } + +button.delete { + float:right; + margin-top: 2px; + margin-right: .8em; + background-color: gray !important; + color:white; +} diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.ts index f54698f5..857c4248 100755 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.ts +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/components/heroes/heroes.component.ts @@ -30,6 +30,25 @@ export class HeroesComponent implements OnInit { this.selectedHero = hero; } + add(name: string): void { + name = name.trim(); + if (!name) { return; } + this.heroService.create(name) + .then(hero => { + this.heroes.push(hero); + this.selectedHero = null; + }); + } + + delete(hero: Hero): void { + this.heroService + .delete(hero.id) + .then(() => { + this.heroes = this.heroes.filter(h => h !== hero); + if (this.selectedHero === hero) { this.selectedHero = null; } + }); + } + gotoDetail(): void { this.router.navigate(['/detail', this.selectedHero.id]); } diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero-search.service.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero-search.service.ts new file mode 100644 index 00000000..3df3d050 --- /dev/null +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero-search.service.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import { Http } from '@angular/http'; +import { Observable } from 'rxjs/Observable'; + +import 'rxjs/add/operator/map'; + +import { Hero } from '../shared/hero'; + +@Injectable() + +export class HeroSearchService { + constructor(private http: Http) { + } + + search(term: string): Observable { + return this.http + .get(`app/heroes/?name=${term}`) + .map(response => response.json().data as Hero[]); + } +} diff --git a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero.service.ts b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero.service.ts index 170fb6ac..e14ed384 100644 --- a/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero.service.ts +++ b/homeworks/ihor.tkachuk_ihortkachuk/homework_10/src/app/services/hero.service.ts @@ -9,6 +9,7 @@ import { Hero } from '../shared/hero'; export class HeroService { private heroesUrl = 'api/heroes'; + private headers = new Headers({'Content-Type': 'application/json'}); constructor(private http: Http) { } @@ -27,19 +28,33 @@ export class HeroService { .catch(this.handleError); } + update(hero: Hero): Promise { + const url = `${this.heroesUrl}/${hero.id}`; + return this.http + .put(url, JSON.stringify(hero), {headers: this.headers}) + .toPromise() + .then(() => hero) + .catch(this.handleError); + } + + create(name: string): Promise { + return this.http + .post(this.heroesUrl, JSON.stringify({name: name}), {headers: this.headers}) + .toPromise() + .then(res => res.json().data) + .catch(this.handleError); + } + + delete(id: number): Promise { + const url = `${this.heroesUrl}/${id}`; + return this.http.delete(url, {headers: this.headers}) + .toPromise() + .then(() => null) + .catch(this.handleError); + } + private handleError(error: any): Promise { console.error('An error occurred', error); return Promise.reject(error.message || error); } - - - // getHeroById(id: number) { - // return this.heroes.filter((item) => item.id === id).pop(); - // } - // - // update(obj: Hero) { - // let hero = this.getHeroById(obj.id); - // Object.assign(hero, obj); - // return hero; - // } }