src/weather.container.ts
changeDetection | ChangeDetectionStrategy.Default |
selector | weather-widget |
styles |
:host {
display: flex;
position: relative;
padding: 1em;
box-sizing: border-box;
}
.info {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
}
.info.wide {
flex-direction: row;
}
.wide .current {
flex-grow: 0;
}
.wide .forecast {
flex-grow: 1;
overflow-y: auto;
height: 100%;
}
.current {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-width: 140px;
}
.forecast {
min-width: 200px;
width: 100%;
overflow-y: auto;
}
.current, .forecast {
padding: 0.5em;
}
weather-actions {
display: block;
position: absolute;
top: 10px;
right: 10px;
}
weather-current-temperature.big {
font-size: 3em;
}
weather-icon.big {
font-size: 6em;
padding: 0.15em;
}
.empty {
flex-direction: row;
}
.empty i {
font-size: 3em;
margin-right: 0.3em;
}
|
template |
|
currentWeather
|
|
Defined in src/weather.container.ts:143
|
forecast
|
|
Defined in src/weather.container.ts:142
|
settings
|
|
Defined in src/weather.container.ts:145
|
constructor(weatherApi: WeatherApiService, changeDetectorRef: ChangeDetectorRef, renderer: Renderer2, element: ElementRef)
|
Defined in src/weather.container.ts:173
|
background |
background: |
Type : string
|
Decorators : HostBinding
|
Defined in src/weather.container.ts:137
|
color |
color: |
Type : string
|
Decorators : HostBinding
|
Defined in src/weather.container.ts:138
|
currentWeather$ |
currentWeather$: |
Type : Observable<CurrentWeather>
|
Defined in src/weather.container.ts:169
|
forecast$ |
forecast$: |
Type : Observable<[]>
|
Defined in src/weather.container.ts:170
|
height |
height: |
Default value : auto
|
Decorators : HostBinding
|
Defined in src/weather.container.ts:140
|
isMouseOn |
isMouseOn: |
Type : boolean
|
Defined in src/weather.container.ts:171
|
isWideLayout |
isWideLayout: |
Default value : false
|
Defined in src/weather.container.ts:166
|
settings |
settings: |
Type : WeatherSettings
|
Defined in src/weather.container.ts:162
|
subscriptionCurrentWeather |
subscriptionCurrentWeather: |
Type : Subscription
|
Defined in src/weather.container.ts:167
|
subscriptionForecast |
subscriptionForecast: |
Type : Subscription
|
Defined in src/weather.container.ts:168
|
width |
width: |
Default value : auto
|
Decorators : HostBinding
|
Defined in src/weather.container.ts:139
|
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
HostBinding,
HostListener,
Input,
OnDestroy,
Renderer2
} from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import {
CurrentWeather,
Forecast,
WeatherApiService
} from './services/api/weather.api.service';
import {
WeatherLayout,
WeatherQueryParams,
WeatherSettings
} from './weather.interfaces';
@Component({
selector: 'weather-widget',
changeDetection: ChangeDetectionStrategy.Default,
styles: [
`
:host {
display: flex;
position: relative;
padding: 1em;
box-sizing: border-box;
}
.info {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
}
.info.wide {
flex-direction: row;
}
.wide .current {
flex-grow: 0;
}
.wide .forecast {
flex-grow: 1;
overflow-y: auto;
height: 100%;
}
.current {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-width: 140px;
}
.forecast {
min-width: 200px;
width: 100%;
overflow-y: auto;
}
.current, .forecast {
padding: 0.5em;
}
weather-actions {
display: block;
position: absolute;
top: 10px;
right: 10px;
}
weather-current-temperature.big {
font-size: 3em;
}
weather-icon.big {
font-size: 6em;
padding: 0.15em;
}
.empty {
flex-direction: row;
}
.empty i {
font-size: 3em;
margin-right: 0.3em;
}
`
],
template: `
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.10/css/weather-icons.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.10/css/weather-icons-wind.min.css">
<div *ngIf="currentWeather" class="info" [class.wide]="isWideLayout">
<div class="current">
<weather-icon
class="big"
[iconImageUrl]="currentWeather?.iconUrl"
[iconClass]="currentWeather?.iconClass"></weather-icon>
<weather-current-description
[descripion]="currentWeather?.description"></weather-current-description>
<weather-current-wind
*ngIf="settings.showWind"
[scale]="settings.scale"
[deg]="currentWeather?.wind.deg"
[speed]="currentWeather?.wind.speed"></weather-current-wind>
<weather-location [place]="currentWeather?.location"></weather-location>
<weather-current-temperature
class="big"
[temp]="currentWeather?.temp"
[deg]="settings.scale"></weather-current-temperature>
<weather-current-details
*ngIf="settings.showDetails"
[maxTemp]="currentWeather?.maxTemp"
[minTemp]="currentWeather?.minTemp"
[pressure]="currentWeather?.pressure"
[humidity]="currentWeather?.humidity"></weather-current-details>
</div>
<div class="forecast" *ngIf="settings.showForecast">
<weather-forecast
[forecast]="forecast"
[settings]="settings"
[mode]="settings.forecastMode"></weather-forecast>
</div>
</div>
<div *ngIf="!currentWeather" class="info empty">
<i class="wi wi-sunrise"></i>
No weather data...
</div>
<weather-actions *ngIf="isMouseOn" (update)="getWeather()"></weather-actions>
`
})
export // tslint:disable-next-line:component-class-suffix
class WeatherContainer implements OnDestroy {
@HostBinding('style.background') background: string;
@HostBinding('style.color') color: string;
@HostBinding('style.width') width = 'auto';
@HostBinding('style.height') height = 'auto';
@Input() forecast: Forecast[] | null;
@Input() currentWeather: CurrentWeather | null;
@Input()
set settings(value: WeatherSettings) {
if (!value) {
return;
}
this._settings = value;
this.background = this._settings.backgroundColor || 'white';
this.color = this._settings.color || 'black';
this.width = this._settings.width;
this.height = this._settings.height;
if (this.weatherApi.apiConfig.name && this.weatherApi.apiConfig.key) {
this.getWeather();
}
if (this._settings.layout) {
this.isWideLayout = this._settings.layout === WeatherLayout.WIDE;
}
}
get settings(): WeatherSettings {
return this._settings;
}
isWideLayout = false;
subscriptionCurrentWeather: Subscription;
subscriptionForecast: Subscription;
currentWeather$: Observable<CurrentWeather>;
forecast$: Observable<Forecast[]>;
isMouseOn: boolean;
private _settings: WeatherSettings;
constructor(
private weatherApi: WeatherApiService,
private changeDetectorRef: ChangeDetectorRef,
private renderer: Renderer2,
private element: ElementRef
) {}
ngOnDestroy() {
if (this.subscriptionCurrentWeather) {
this.subscriptionCurrentWeather.unsubscribe();
}
if (this.subscriptionForecast) {
this.subscriptionForecast.unsubscribe();
}
}
@HostListener('mouseenter')
private onMouseEnter() {
this.renderer.addClass(this.element.nativeElement, 'active');
this.isMouseOn = true;
}
@HostListener('mouseleave')
private onMouseLeave() {
this.renderer.removeClass(this.element.nativeElement, 'active');
this.isMouseOn = false;
}
getWeather(): void {
if (this.subscriptionCurrentWeather) {
this.subscriptionCurrentWeather.unsubscribe();
}
if (this.subscriptionForecast) {
this.subscriptionForecast.unsubscribe();
}
this.currentWeather$ = this.currentWeatherCall();
this.forecast$ = this.forecastCall();
this.subscriptionCurrentWeather = this.currentWeather$.subscribe(data => {
this.currentWeather = data;
this.changeDetectorRef.markForCheck();
});
this.subscriptionForecast = this.forecast$.subscribe(data => {
this.forecast = data;
this.changeDetectorRef.markForCheck();
});
}
currentWeatherCall(): Observable<CurrentWeather> {
const params: WeatherQueryParams = Object.assign(
{},
this.settings.location,
{ units: this.settings.scale },
{ lang: this.settings.language }
);
return this.weatherApi.currentWeather(params);
}
forecastCall(): Observable<Forecast[]> {
const params: WeatherQueryParams = Object.assign(
{},
this.settings.location,
{ units: this.settings.scale },
{ lang: this.settings.language }
);
return this.weatherApi.forecast(params);
}
}