From b5d7e9e482ad107bdecd7b4ab0878bbe50063ab9 Mon Sep 17 00:00:00 2001 From: pgrondek Date: Sat, 2 May 2020 15:07:01 +0200 Subject: [PATCH] Add weather --- src/app/app.component.css | 4 -- src/app/app.module.ts | 15 ++++++-- src/app/core/adapter.ts | 3 ++ src/app/dashboard/dashboard.component.html | 4 +- src/app/weather/model/weather.ts | 23 ++++++++++++ src/app/weather/service/weather-adapter.ts | 30 +++++++++++++++ .../weather/service/weather-icon-adapter.ts | 37 +++++++++++++++++++ .../weather/service/weather.service.spec.ts | 16 ++++++++ src/app/weather/service/weather.service.ts | 26 +++++++++++++ src/app/weather/weather.component.css | 10 +++++ src/app/weather/weather.component.html | 24 ++++++++++++ src/app/weather/weather.component.spec.ts | 25 +++++++++++++ src/app/weather/weather.component.ts | 23 ++++++++++++ src/assets/mdi.svg | 1 + src/environments/environment.prod.ts | 8 +++- src/environments/environment.ts | 8 +++- 16 files changed, 246 insertions(+), 11 deletions(-) create mode 100644 src/app/core/adapter.ts create mode 100644 src/app/weather/model/weather.ts create mode 100644 src/app/weather/service/weather-adapter.ts create mode 100644 src/app/weather/service/weather-icon-adapter.ts create mode 100644 src/app/weather/service/weather.service.spec.ts create mode 100644 src/app/weather/service/weather.service.ts create mode 100644 src/app/weather/weather.component.css create mode 100644 src/app/weather/weather.component.html create mode 100644 src/app/weather/weather.component.spec.ts create mode 100644 src/app/weather/weather.component.ts create mode 100644 src/assets/mdi.svg diff --git a/src/app/app.component.css b/src/app/app.component.css index c64ade8..e1d93ca 100644 --- a/src/app/app.component.css +++ b/src/app/app.component.css @@ -7,7 +7,3 @@ mat-sidenav-container { mat-card-content { text-align: center; } - -.mat-card { - background-color: pink; -} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3fa0c33..a502af6 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,4 +1,4 @@ -import {BrowserModule} from '@angular/platform-browser'; +import {BrowserModule, DomSanitizer} from '@angular/platform-browser'; import {NgModule} from '@angular/core'; import {AppComponent} from './app.component'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; @@ -10,14 +10,17 @@ import {MatCardModule} from '@angular/material/card'; import {DashboardComponent} from './dashboard/dashboard.component'; import {MatGridListModule} from '@angular/material/grid-list'; import {MatMenuModule} from '@angular/material/menu'; -import {MatIconModule} from '@angular/material/icon'; -import {MatButtonModule} from '@angular/material/button'; +import {MatIconModule, MatIconRegistry} from '@angular/material/icon'; +import {WeatherComponent} from './weather/weather.component'; +import {HttpClientModule} from '@angular/common/http'; +import { MatButtonModule } from '@angular/material/button'; @NgModule({ declarations: [ AppComponent, ClockComponent, - DashboardComponent + DashboardComponent, + WeatherComponent ], imports: [ BrowserModule, @@ -29,10 +32,14 @@ import {MatButtonModule} from '@angular/material/button'; MatGridListModule, MatMenuModule, MatIconModule, + HttpClientModule, MatButtonModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { + constructor(matIconRegistry: MatIconRegistry, domSanitizer: DomSanitizer) { + matIconRegistry.addSvgIconSet(domSanitizer.bypassSecurityTrustResourceUrl('./assets/mdi.svg')); + } } diff --git a/src/app/core/adapter.ts b/src/app/core/adapter.ts new file mode 100644 index 0000000..098f0f9 --- /dev/null +++ b/src/app/core/adapter.ts @@ -0,0 +1,3 @@ +export interface Adapter { + adapt(item: any): T; +} diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html index 6a5391f..cd0db4c 100644 --- a/src/app/dashboard/dashboard.component.html +++ b/src/app/dashboard/dashboard.component.html @@ -3,6 +3,8 @@ - + + + diff --git a/src/app/weather/model/weather.ts b/src/app/weather/model/weather.ts new file mode 100644 index 0000000..04450ba --- /dev/null +++ b/src/app/weather/model/weather.ts @@ -0,0 +1,23 @@ +export class Weather { + constructor( + public name: string, + public description: string, + public icon: string, + public temperature: WeatherTemperature, + public pressure: number, + public humidity: number, + public windSpeed: number + ) { + } + +} + +export class WeatherTemperature { + constructor( + public temperature: number, + public min: number, + public max: number + ) { + } + +} diff --git a/src/app/weather/service/weather-adapter.ts b/src/app/weather/service/weather-adapter.ts new file mode 100644 index 0000000..b44383e --- /dev/null +++ b/src/app/weather/service/weather-adapter.ts @@ -0,0 +1,30 @@ +import {Weather, WeatherTemperature} from '../model/weather'; +import {Adapter} from '../../core/adapter'; +import {Injectable} from '@angular/core'; +import {WeatherIconAdapter} from './weather-icon-adapter'; + +@Injectable({ + providedIn: 'root' +}) +export class WeatherAdapter implements Adapter { + constructor(private iconAdapter: WeatherIconAdapter) { + } + + adapt(item: any): Weather { + + return new Weather( + item.name, + item.weather[0].main, + this.iconAdapter.adapt(item.weather[0].icon), + new WeatherTemperature( + item.main.temp, + item.main.temp_min, + item.main.temp_max + ), + item.main.pressure, + item.main.humidity, + item.wind.speed + ); + } + +} diff --git a/src/app/weather/service/weather-icon-adapter.ts b/src/app/weather/service/weather-icon-adapter.ts new file mode 100644 index 0000000..d1d369a --- /dev/null +++ b/src/app/weather/service/weather-icon-adapter.ts @@ -0,0 +1,37 @@ +import {Adapter} from '../../core/adapter'; +import {Injectable} from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class WeatherIconAdapter implements Adapter { + map = { + '01d': 'weather-sunny', + '02d': 'weather-partly-cloudy', + '03d': 'weather-cloudy', + '04d': 'weather-cloudy', + '09d': 'weather-pouring', + '10d': 'weather-rainy', + '11d': 'weather-lightning', + '13d': 'weather-snow', + '50d': 'weather-fog', + + '01n': 'weather-night', + '02n': 'weather-night-partly-cloudy', + '03n': 'weather-night-cloudy', + '04n': 'weather-night-cloudy', + '09n': 'weather-pouring', + '10n': 'weather-rainy', + '11n': 'weather-lightning', + '13n': 'weather-snow', + '50n': 'weather-fog' + }; + + adapt(item: any): string { + let icon = this.map[item]; + if (icon == null) { + icon = 'alert'; + } + return icon; + } +} diff --git a/src/app/weather/service/weather.service.spec.ts b/src/app/weather/service/weather.service.spec.ts new file mode 100644 index 0000000..7cb8941 --- /dev/null +++ b/src/app/weather/service/weather.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { WeatherService } from './weather.service'; + +describe('WeatherService', () => { + let service: WeatherService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(WeatherService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/weather/service/weather.service.ts b/src/app/weather/service/weather.service.ts new file mode 100644 index 0000000..912cd85 --- /dev/null +++ b/src/app/weather/service/weather.service.ts @@ -0,0 +1,26 @@ +import {Injectable} from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import {Observable} from 'rxjs'; +import {Weather} from '../model/weather'; +import {map} from 'rxjs/operators'; +import {WeatherAdapter} from './weather-adapter'; +import {environment} from '../../../environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class WeatherService { + apiUrl = environment.weather.url + + '?id=' + environment.weather.cityId + + '&units=' + environment.weather.units + + '&appid=' + environment.weather.apiKey; + + constructor(private http: HttpClient, private adapter: WeatherAdapter) { + } + + getWeather(): Observable { + return this.http.get(this.apiUrl) + .pipe(map((data) => this.adapter.adapt(data))) + ; + } +} diff --git a/src/app/weather/weather.component.css b/src/app/weather/weather.component.css new file mode 100644 index 0000000..13e71fa --- /dev/null +++ b/src/app/weather/weather.component.css @@ -0,0 +1,10 @@ +@import "../dashboard/card.css"; + +.mat-grid-tile { + font-size: 1.5rem; +} + +.weather-icon { + height: 100px; + width: 100px; +} diff --git a/src/app/weather/weather.component.html b/src/app/weather/weather.component.html new file mode 100644 index 0000000..4722179 --- /dev/null +++ b/src/app/weather/weather.component.html @@ -0,0 +1,24 @@ + + + {{weather?.name}} + + +
+
+ {{weather?.description}} +
+ + Temperature + + {{weather?.temperature.temperature}} °C + + Humidity + {{weather?.humidity}}% + Pressure + {{weather?.pressure}} hPa + Wind + {{weather?.windSpeed}} kmph + +
+
diff --git a/src/app/weather/weather.component.spec.ts b/src/app/weather/weather.component.spec.ts new file mode 100644 index 0000000..927c663 --- /dev/null +++ b/src/app/weather/weather.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { WeatherComponent } from './weather.component'; + +describe('WeatherComponent', () => { + let component: WeatherComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ WeatherComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(WeatherComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/weather/weather.component.ts b/src/app/weather/weather.component.ts new file mode 100644 index 0000000..fdac957 --- /dev/null +++ b/src/app/weather/weather.component.ts @@ -0,0 +1,23 @@ +import {Component, OnInit} from '@angular/core'; +import {WeatherService} from './service/weather.service'; +import {Weather} from './model/weather'; + +@Component({ + selector: 'app-weather', + templateUrl: './weather.component.html', + styleUrls: ['./weather.component.css'] +}) +export class WeatherComponent implements OnInit { + public weather: Weather = null; + + constructor( + private service: WeatherService + ) { + } + + ngOnInit(): void { + this.service.getWeather() + .subscribe(weather => this.weather = weather); + } + +} diff --git a/src/assets/mdi.svg b/src/assets/mdi.svg new file mode 100644 index 0000000..47f5a67 --- /dev/null +++ b/src/assets/mdi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 3612073..89ce0da 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,3 +1,9 @@ export const environment = { - production: true + production: true, + weather: { + url: 'https://api.openweathermap.org/data/2.5/weather', + cityId: '756135', + units: 'metric', + apiKey: '' + } }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 7b4f817..9d3ca51 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -3,7 +3,13 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false + production: false, + weather: { + url: 'https://api.openweathermap.org/data/2.5/weather', + cityId: '756135', + units: 'metric', + apiKey: '' + } }; /*