Add weather

This commit is contained in:
pgrondek 2020-05-02 15:07:01 +02:00
parent 186a3fe1a3
commit b5d7e9e482
16 changed files with 246 additions and 11 deletions

View file

@ -7,7 +7,3 @@ mat-sidenav-container {
mat-card-content { mat-card-content {
text-align: center; text-align: center;
} }
.mat-card {
background-color: pink;
}

View file

@ -1,4 +1,4 @@
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule, DomSanitizer} from '@angular/platform-browser';
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {AppComponent} from './app.component'; import {AppComponent} from './app.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
@ -10,14 +10,17 @@ import {MatCardModule} from '@angular/material/card';
import {DashboardComponent} from './dashboard/dashboard.component'; import {DashboardComponent} from './dashboard/dashboard.component';
import {MatGridListModule} from '@angular/material/grid-list'; import {MatGridListModule} from '@angular/material/grid-list';
import {MatMenuModule} from '@angular/material/menu'; import {MatMenuModule} from '@angular/material/menu';
import {MatIconModule} from '@angular/material/icon'; import {MatIconModule, MatIconRegistry} from '@angular/material/icon';
import {MatButtonModule} from '@angular/material/button'; import {WeatherComponent} from './weather/weather.component';
import {HttpClientModule} from '@angular/common/http';
import { MatButtonModule } from '@angular/material/button';
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
ClockComponent, ClockComponent,
DashboardComponent DashboardComponent,
WeatherComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
@ -29,10 +32,14 @@ import {MatButtonModule} from '@angular/material/button';
MatGridListModule, MatGridListModule,
MatMenuModule, MatMenuModule,
MatIconModule, MatIconModule,
HttpClientModule,
MatButtonModule MatButtonModule
], ],
providers: [], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { export class AppModule {
constructor(matIconRegistry: MatIconRegistry, domSanitizer: DomSanitizer) {
matIconRegistry.addSvgIconSet(domSanitizer.bypassSecurityTrustResourceUrl('./assets/mdi.svg'));
}
} }

3
src/app/core/adapter.ts Normal file
View file

@ -0,0 +1,3 @@
export interface Adapter<T> {
adapt(item: any): T;
}

View file

@ -3,6 +3,8 @@
<mat-grid-tile> <mat-grid-tile>
<app-clock></app-clock> <app-clock></app-clock>
</mat-grid-tile> </mat-grid-tile>
<mat-grid-tile>
<app-weather></app-weather>
</mat-grid-tile>
</mat-grid-list> </mat-grid-list>
</div> </div>

View file

@ -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
) {
}
}

View file

@ -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<Weather> {
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
);
}
}

View file

@ -0,0 +1,37 @@
import {Adapter} from '../../core/adapter';
import {Injectable} from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class WeatherIconAdapter implements Adapter<string> {
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;
}
}

View file

@ -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();
});
});

View file

@ -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<Weather> {
return this.http.get<any>(this.apiUrl)
.pipe(map((data) => this.adapter.adapt(data)))
;
}
}

View file

@ -0,0 +1,10 @@
@import "../dashboard/card.css";
.mat-grid-tile {
font-size: 1.5rem;
}
.weather-icon {
height: 100px;
width: 100px;
}

View file

@ -0,0 +1,24 @@
<mat-card class="dashboard-card">
<mat-card-title>
{{weather?.name}}
</mat-card-title>
<mat-card-content class="dashboard-card-content">
<div>
<mat-icon svgIcon="{{weather?.icon}}"
class="weather-icon"></mat-icon><br/>
{{weather?.description}}
</div>
<mat-grid-list cols="2" rowHeight="30px">
<mat-grid-tile>Temperature</mat-grid-tile>
<mat-grid-tile>
{{weather?.temperature.temperature}} °C
</mat-grid-tile>
<mat-grid-tile>Humidity</mat-grid-tile>
<mat-grid-tile>{{weather?.humidity}}%</mat-grid-tile>
<mat-grid-tile>Pressure</mat-grid-tile>
<mat-grid-tile> {{weather?.pressure}} hPa</mat-grid-tile>
<mat-grid-tile>Wind</mat-grid-tile>
<mat-grid-tile>{{weather?.windSpeed}} kmph</mat-grid-tile>
</mat-grid-list>
</mat-card-content>
</mat-card>

View file

@ -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<WeatherComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ WeatherComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(WeatherComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -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);
}
}

1
src/assets/mdi.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.9 MiB

View file

@ -1,3 +1,9 @@
export const environment = { export const environment = {
production: true production: true,
weather: {
url: 'https://api.openweathermap.org/data/2.5/weather',
cityId: '756135',
units: 'metric',
apiKey: ''
}
}; };

View file

@ -3,7 +3,13 @@
// The list of file replacements can be found in `angular.json`. // The list of file replacements can be found in `angular.json`.
export const environment = { export const environment = {
production: false production: false,
weather: {
url: 'https://api.openweathermap.org/data/2.5/weather',
cityId: '756135',
units: 'metric',
apiKey: ''
}
}; };
/* /*