ADD: Humidity and Air Pressure Diagrams
This commit is contained in:
parent
fe3e7334ce
commit
f8e59e3649
@ -1,3 +1,7 @@
|
||||
<div class="diagrams-container">
|
||||
<app-temperature #temperature [measurements]="measurements"></app-temperature>
|
||||
<div style="display: flex">
|
||||
<app-humidity style="width: 50%" #humidity [measurements]="measurements"></app-humidity>
|
||||
<app-pressure style="width: 50%;" #pressure [measurements]="measurements"></app-pressure>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -3,11 +3,15 @@ import {TemperatureComponent, TimeResolution} from './temperature/temperature';
|
||||
import {DefaultService, MeasurementListResponse, MeasurementResolution, StationListResponse} from '../../api';
|
||||
import {ApexOptions} from 'ng-apexcharts';
|
||||
import {addDays, addHours, addMonths, addYears, startOfDay} from 'date-fns';
|
||||
import {Humidity} from './humidity/humidity';
|
||||
import {Pressure} from './pressure/pressure';
|
||||
|
||||
@Component({
|
||||
selector: 'app-diagrams',
|
||||
imports: [
|
||||
TemperatureComponent
|
||||
TemperatureComponent,
|
||||
Humidity,
|
||||
Pressure
|
||||
],
|
||||
templateUrl: './diagrams.html',
|
||||
styleUrl: './diagrams.css',
|
||||
@ -16,6 +20,8 @@ export class Diagrams {
|
||||
timeResolution: TimeResolution = '7d';
|
||||
@Input() activeStations: StationListResponse[] = [];
|
||||
@ViewChild('temperature') temperatureDiagram?: TemperatureComponent
|
||||
@ViewChild('humidity') humidityDiagram?: TemperatureComponent
|
||||
@ViewChild('pressure') pressureDiagram?: TemperatureComponent
|
||||
resolution: MeasurementResolution = MeasurementResolution.Daily;
|
||||
measurements: MeasurementListResponse | undefined;
|
||||
|
||||
@ -77,5 +83,7 @@ export class Diagrams {
|
||||
|
||||
buildCharts() {
|
||||
this.temperatureDiagram?.buildChart(this.measurements!)
|
||||
this.humidityDiagram?.buildChart(this.measurements!)
|
||||
this.pressureDiagram?.buildChart(this.measurements!)
|
||||
}
|
||||
}
|
||||
|
||||
0
src/app/components/diagrams/humidity/humidity.css
Normal file
0
src/app/components/diagrams/humidity/humidity.css
Normal file
37
src/app/components/diagrams/humidity/humidity.html
Normal file
37
src/app/components/diagrams/humidity/humidity.html
Normal file
@ -0,0 +1,37 @@
|
||||
@if(measurements) {
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
<mat-card-title>Luftfeuchtigkeit
|
||||
<mat-button-toggle-group name="fontStyle" aria-label="Font Style" (valueChange)="switchChartType($event)" [value]="'bar'">
|
||||
<mat-button-toggle value="line">
|
||||
<mat-icon>line_axis</mat-icon>
|
||||
Line
|
||||
</mat-button-toggle>
|
||||
<mat-button-toggle value="bar">
|
||||
<mat-icon>bar_chart</mat-icon>
|
||||
Balken
|
||||
</mat-button-toggle>
|
||||
<mat-button-toggle value="area">
|
||||
<mat-icon>area_chart</mat-icon>
|
||||
Fläche
|
||||
</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<apx-chart
|
||||
[series]="chartOptions.series!"
|
||||
[chart]="chartOptions.chart!"
|
||||
[xaxis]="chartOptions.xaxis!"
|
||||
[yaxis]="chartOptions.yaxis!"
|
||||
[stroke]="chartOptions.stroke!"
|
||||
[grid]="chartOptions.grid!"
|
||||
[dataLabels]="chartOptions.dataLabels!"
|
||||
[tooltip]="chartOptions.tooltip!"
|
||||
[legend]="chartOptions.legend!"
|
||||
[theme]="chartOptions.theme!"
|
||||
/>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
}
|
||||
22
src/app/components/diagrams/humidity/humidity.spec.ts
Normal file
22
src/app/components/diagrams/humidity/humidity.spec.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { Humidity } from './humidity';
|
||||
|
||||
describe('Humidity', () => {
|
||||
let component: Humidity;
|
||||
let fixture: ComponentFixture<Humidity>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [Humidity],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(Humidity);
|
||||
component = fixture.componentInstance;
|
||||
await fixture.whenStable();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
114
src/app/components/diagrams/humidity/humidity.ts
Normal file
114
src/app/components/diagrams/humidity/humidity.ts
Normal file
@ -0,0 +1,114 @@
|
||||
import {ChangeDetectorRef, Component, Input} from '@angular/core';
|
||||
import {DefaultService, MeasurementListResponse} from '../../../api';
|
||||
import {ApexOptions, ChartComponent, ChartType} from 'ng-apexcharts';
|
||||
import {MatButtonToggle, MatButtonToggleGroup} from '@angular/material/button-toggle';
|
||||
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from '@angular/material/card';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
|
||||
@Component({
|
||||
selector: 'app-humidity',
|
||||
imports: [
|
||||
ChartComponent,
|
||||
MatButtonToggle,
|
||||
MatButtonToggleGroup,
|
||||
MatCard,
|
||||
MatCardContent,
|
||||
MatCardHeader,
|
||||
MatCardTitle,
|
||||
MatIcon
|
||||
],
|
||||
templateUrl: './humidity.html',
|
||||
styleUrl: './humidity.css',
|
||||
})
|
||||
export class Humidity {
|
||||
|
||||
@Input() measurements: MeasurementListResponse | undefined;
|
||||
chartOptions: ApexOptions = {};
|
||||
chartType: ChartType = 'bar';
|
||||
|
||||
constructor(private api: DefaultService, private cdr: ChangeDetectorRef) {}
|
||||
|
||||
switchChartType(type: 'bar' | 'area' | 'line') {
|
||||
this.chartType = type;
|
||||
this.buildChart(this.measurements!)
|
||||
}
|
||||
public buildChart(measurements: MeasurementListResponse) {
|
||||
this.measurements = measurements;
|
||||
if (!this.measurements) return;
|
||||
|
||||
const isBar = this.chartType === 'bar';
|
||||
const isArea = this.chartType === 'area';
|
||||
|
||||
this.chartOptions = {
|
||||
chart: {
|
||||
type: this.chartType,
|
||||
height: 280,
|
||||
toolbar: { show: false },
|
||||
animations: { enabled: true },
|
||||
background: 'transparent',
|
||||
stacked: false,
|
||||
},
|
||||
theme: { mode: 'dark' },
|
||||
dataLabels: {
|
||||
enabled: false, // <- das hat gefehlt
|
||||
},
|
||||
stroke: {
|
||||
curve: 'smooth',
|
||||
width: isBar ? 0 : 2,
|
||||
},
|
||||
fill: {
|
||||
type: isArea ? 'gradient' : 'solid',
|
||||
opacity: isArea ? 0.3 : (isBar ? 0.85 : 1),
|
||||
gradient: isArea ? {
|
||||
shadeIntensity: 1,
|
||||
opacityFrom: 0.4,
|
||||
opacityTo: 0.05,
|
||||
stops: [0, 100]
|
||||
} : undefined,
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '70%',
|
||||
borderRadius: 3,
|
||||
}
|
||||
},
|
||||
series: this.measurements.stations.map(s => ({
|
||||
name: `${s.station.name} ${s.indoor ? '(innen)' : '(außen)'}`,
|
||||
data: s.measurements.map(m => ({
|
||||
x: new Date(m.timestamp).getTime(),
|
||||
y: m.humidity
|
||||
}))
|
||||
})),
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
labels: {
|
||||
datetimeUTC: false,
|
||||
style: { colors: '#9e9e9e', fontSize: '11px' }
|
||||
},
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
style: { colors: '#9e9e9e', fontSize: '11px' },
|
||||
formatter: (val: number) => `${val.toFixed(1)}%`
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
borderColor: 'rgba(255,255,255,0.06)',
|
||||
strokeDashArray: 4,
|
||||
},
|
||||
tooltip: {
|
||||
theme: 'dark',
|
||||
shared: true,
|
||||
intersect: false,
|
||||
x: { format: 'dd.MM.yyyy HH:mm' },
|
||||
y: { formatter: (val: number) => `${val?.toFixed(1)} %` }
|
||||
},
|
||||
legend: {
|
||||
labels: { colors: '#9e9e9e' }
|
||||
},
|
||||
};
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
}
|
||||
0
src/app/components/diagrams/pressure/pressure.css
Normal file
0
src/app/components/diagrams/pressure/pressure.css
Normal file
37
src/app/components/diagrams/pressure/pressure.html
Normal file
37
src/app/components/diagrams/pressure/pressure.html
Normal file
@ -0,0 +1,37 @@
|
||||
@if(measurements) {
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
<mat-card-title>Luftdruck
|
||||
<mat-button-toggle-group name="fontStyle" aria-label="Font Style" (valueChange)="switchChartType($event)" [value]="'bar'">
|
||||
<mat-button-toggle value="line">
|
||||
<mat-icon>line_axis</mat-icon>
|
||||
Line
|
||||
</mat-button-toggle>
|
||||
<mat-button-toggle value="bar">
|
||||
<mat-icon>bar_chart</mat-icon>
|
||||
Balken
|
||||
</mat-button-toggle>
|
||||
<mat-button-toggle value="area">
|
||||
<mat-icon>area_chart</mat-icon>
|
||||
Fläche
|
||||
</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<apx-chart
|
||||
[series]="chartOptions.series!"
|
||||
[chart]="chartOptions.chart!"
|
||||
[xaxis]="chartOptions.xaxis!"
|
||||
[yaxis]="chartOptions.yaxis!"
|
||||
[stroke]="chartOptions.stroke!"
|
||||
[grid]="chartOptions.grid!"
|
||||
[dataLabels]="chartOptions.dataLabels!"
|
||||
[tooltip]="chartOptions.tooltip!"
|
||||
[legend]="chartOptions.legend!"
|
||||
[theme]="chartOptions.theme!"
|
||||
/>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
}
|
||||
22
src/app/components/diagrams/pressure/pressure.spec.ts
Normal file
22
src/app/components/diagrams/pressure/pressure.spec.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { Pressure } from './pressure';
|
||||
|
||||
describe('Pressure', () => {
|
||||
let component: Pressure;
|
||||
let fixture: ComponentFixture<Pressure>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [Pressure],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(Pressure);
|
||||
component = fixture.componentInstance;
|
||||
await fixture.whenStable();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
113
src/app/components/diagrams/pressure/pressure.ts
Normal file
113
src/app/components/diagrams/pressure/pressure.ts
Normal file
@ -0,0 +1,113 @@
|
||||
import {ChangeDetectorRef, Component, Input} from '@angular/core';
|
||||
import {ApexOptions, ChartComponent, ChartType} from "ng-apexcharts";
|
||||
import {MatButtonToggle, MatButtonToggleGroup} from "@angular/material/button-toggle";
|
||||
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from "@angular/material/card";
|
||||
import {MatIcon} from "@angular/material/icon";
|
||||
import {DefaultService, MeasurementListResponse} from '../../../api';
|
||||
|
||||
@Component({
|
||||
selector: 'app-pressure',
|
||||
imports: [
|
||||
ChartComponent,
|
||||
MatButtonToggle,
|
||||
MatButtonToggleGroup,
|
||||
MatCard,
|
||||
MatCardContent,
|
||||
MatCardHeader,
|
||||
MatCardTitle,
|
||||
MatIcon
|
||||
],
|
||||
templateUrl: './pressure.html',
|
||||
styleUrl: './pressure.css',
|
||||
})
|
||||
export class Pressure {
|
||||
@Input() measurements: MeasurementListResponse | undefined;
|
||||
chartOptions: ApexOptions = {};
|
||||
chartType: ChartType = 'bar';
|
||||
|
||||
constructor(private api: DefaultService, private cdr: ChangeDetectorRef) {}
|
||||
|
||||
switchChartType(type: 'bar' | 'area' | 'line') {
|
||||
this.chartType = type;
|
||||
this.buildChart(this.measurements!)
|
||||
}
|
||||
public buildChart(measurements: MeasurementListResponse) {
|
||||
this.measurements = measurements;
|
||||
if (!this.measurements) return;
|
||||
|
||||
const isBar = this.chartType === 'bar';
|
||||
const isArea = this.chartType === 'area';
|
||||
|
||||
this.chartOptions = {
|
||||
chart: {
|
||||
type: this.chartType,
|
||||
height: 280,
|
||||
toolbar: { show: false },
|
||||
animations: { enabled: true },
|
||||
background: 'transparent',
|
||||
stacked: false,
|
||||
},
|
||||
theme: { mode: 'dark' },
|
||||
dataLabels: {
|
||||
enabled: false, // <- das hat gefehlt
|
||||
},
|
||||
stroke: {
|
||||
curve: 'smooth',
|
||||
width: isBar ? 0 : 2,
|
||||
},
|
||||
fill: {
|
||||
type: isArea ? 'gradient' : 'solid',
|
||||
opacity: isArea ? 0.3 : (isBar ? 0.85 : 1),
|
||||
gradient: isArea ? {
|
||||
shadeIntensity: 1,
|
||||
opacityFrom: 0.4,
|
||||
opacityTo: 0.05,
|
||||
stops: [0, 100]
|
||||
} : undefined,
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '70%',
|
||||
borderRadius: 3,
|
||||
}
|
||||
},
|
||||
series: this.measurements.stations.map(s => ({
|
||||
name: `${s.station.name} ${s.indoor ? '(innen)' : '(außen)'}`,
|
||||
data: s.measurements.map(m => ({
|
||||
x: new Date(m.timestamp).getTime(),
|
||||
y: m.pressure
|
||||
}))
|
||||
})),
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
labels: {
|
||||
datetimeUTC: false,
|
||||
style: { colors: '#9e9e9e', fontSize: '11px' }
|
||||
},
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
style: { colors: '#9e9e9e', fontSize: '11px' },
|
||||
formatter: (val: number) => `${val.toFixed(1)}hPa`
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
borderColor: 'rgba(255,255,255,0.06)',
|
||||
strokeDashArray: 4,
|
||||
},
|
||||
tooltip: {
|
||||
theme: 'dark',
|
||||
shared: true,
|
||||
intersect: false,
|
||||
x: { format: 'dd.MM.yyyy HH:mm' },
|
||||
y: { formatter: (val: number) => `${val?.toFixed(1)} hPa` }
|
||||
},
|
||||
legend: {
|
||||
labels: { colors: '#9e9e9e' }
|
||||
},
|
||||
};
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user