diff --git a/src/app/alert.model.ts b/src/app/alert.model.ts new file mode 100644 index 0000000..7155150 --- /dev/null +++ b/src/app/alert.model.ts @@ -0,0 +1,11 @@ +export enum AlertType { + success = 'success', + info = 'info', + warning = 'warning', + danger = 'danger', +} + +export interface Alert { + type: AlertType; + message: string; +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 11c5132..eaf21ea 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -2,9 +2,9 @@ import { HttpClientModule } from '@angular/common/http'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; -import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgbAlertModule, NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api'; -import { environment } from 'src/environments/environment'; +import { environment } from '../environments/environment'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { DashboardComponent } from './dashboard/dashboard.component'; @@ -36,6 +36,7 @@ import { SearchInputComponent } from './search-input/search-input.component'; FormsModule, AppRoutingModule, NgbCollapseModule, + NgbAlertModule, HttpClientModule, environment.production ? [] diff --git a/src/app/hero.service.ts b/src/app/hero.service.ts index 3384009..c92bbd4 100644 --- a/src/app/hero.service.ts +++ b/src/app/hero.service.ts @@ -2,7 +2,8 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; -import { environment } from '../environments/environment'; +import { environment } from 'src/environments/environment'; +import { AlertType } from './alert.model'; import { Hero } from './hero.model'; import { MessageService } from './message.service'; @@ -20,79 +21,92 @@ export class HeroService { }; constructor( - private http: HttpClient, - private messageService: MessageService + private messageService: MessageService, + private http: HttpClient ) {} + // GET /heroes getHeroes(): Observable { return this.http.get(this.heroesUrl, this.httpOptions).pipe( - tap(() => this.log('fetched heroes')), + tap((heroes) => { + this.log(`fetched ${heroes.length} heroes`); + }), catchError(this.handleError('getHeroes', [])) ); } + // GET /heroes/id getHero(id: number): Observable { - const url = `${this.heroesUrl}/${id}`; - - return this.http.get(url, this.httpOptions).pipe( - tap(() => this.log(`fetched hero id=${id}`)), - catchError(this.handleError('getHeroes')) - ); + return this.http + .get(`${this.heroesUrl}/${id}`, this.httpOptions) + .pipe( + tap(() => this.log(`fetched hero id=${id}.`)), + catchError(this.handleError('getHero')) + ); } + // PUT /heroes/id updateHero(hero: Hero): Observable { const url = `${this.heroesUrl}/${hero.id}`; return this.http.put(url, hero, this.httpOptions).pipe( - tap(() => this.log(`updated hero id=${hero.id}`)), - catchError(this.handleError('updateHeroes')) + tap(() => this.log(`updated hero id=${hero.id}.`, AlertType.success)), + catchError(this.handleError('updateHero')) ); } + // POST /heroes addHero(hero: Hero): Observable { - return this.http.post(this.heroesUrl, hero, this.httpOptions).pipe( - tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)), + return this.http.post(this.heroesUrl, hero, this.httpOptions).pipe( + tap((newHero) => + this.log(`added hero w/ id=${newHero.id}.`, AlertType.success) + ), catchError(this.handleError('addHero')) ); } + // DELETE /heroes/id deleteHero(hero: Hero): Observable { const url = `${this.heroesUrl}/${hero.id}`; - return this.http.delete(url, this.httpOptions).pipe( - tap(() => this.log(`deleted hero id=${hero.id}`)), + return this.http.delete(url, this.httpOptions).pipe( + tap(() => this.log(`deleted hero id=${hero.id}.`, AlertType.success)), catchError(this.handleError('deleteHero')) ); } + // GET /heroes/?name=term searchHeroes(term: string): Observable { - if (!term.trim()) { + if (!(term && term.trim())) { return of([]); } return this.http .get(`${this.heroesUrl}/?name=${term}`, this.httpOptions) .pipe( - tap((heroes) => + tap((heroes) => { heroes && heroes.length - ? this.log(`found heroes matching "${term}"`) - : this.log(`no heroes matching "${term}"`) - ), + ? this.log(`found ${heroes.length} heroes matching term=${term}`) + : this.log(`no heroes matching term=${term}`, AlertType.warning); + }), catchError(this.handleError('searchHeroes', [])) ); } + private log(message: string, type = AlertType.info) { + this.messageService.add({ + message: `HeroService: ${message}`, + type, + }); + } + private handleError(operation = 'operation', result?: T) { return (error: any): Observable => { console.log(error); - this.log(`${operation} failed: ${error.message}`); + this.log(`${operation} failed: ${error.message}`, AlertType.danger); - return of(result as T); + return of(result); }; } - - private log(message: string) { - this.messageService.add(`HeroService: ${message}`); - } } diff --git a/src/app/heroes/heroes.component.html b/src/app/heroes/heroes.component.html index 67bf863..a9a7997 100644 --- a/src/app/heroes/heroes.component.html +++ b/src/app/heroes/heroes.component.html @@ -6,7 +6,10 @@

My Heroes

- +
diff --git a/src/app/message.service.ts b/src/app/message.service.ts index d72412e..8188ac3 100644 --- a/src/app/message.service.ts +++ b/src/app/message.service.ts @@ -1,16 +1,25 @@ import { Injectable } from '@angular/core'; +import { Alert } from './alert.model'; @Injectable({ providedIn: 'root', }) export class MessageService { - messages: string[] = []; + private alerts: Alert[] = []; - add(message: string) { - this.messages.push(message); + getMessages(): Alert[] { + return this.alerts; + } + + add(alert: Alert) { + this.alerts.push(alert); } clear() { - this.messages = []; + this.alerts = []; + } + + close(alert: Alert) { + this.alerts.splice(this.alerts.indexOf(alert), 1); } } diff --git a/src/app/messages/messages.component.html b/src/app/messages/messages.component.html index 89f32d6..5163cf2 100644 --- a/src/app/messages/messages.component.html +++ b/src/app/messages/messages.component.html @@ -1,4 +1,4 @@ -
+

Messages

-
- +
+ + {{ alert.message }} +
diff --git a/src/app/messages/messages.component.ts b/src/app/messages/messages.component.ts index 71a8ef8..94606ac 100644 --- a/src/app/messages/messages.component.ts +++ b/src/app/messages/messages.component.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core'; +import { Alert } from '../alert.model'; import { MessageService } from '../message.service'; @Component({ @@ -8,4 +9,8 @@ import { MessageService } from '../message.service'; }) export class MessagesComponent { constructor(public messageService: MessageService) {} + + close(alert: Alert) { + this.messageService.close(alert); + } }