ADD: Humidity and Air Pressure Diagrams
This commit is contained in:
parent
fe3e7334ce
commit
f8e59e3649
@ -1,3 +1,7 @@
|
|||||||
<div class="diagrams-container">
|
<div class="diagrams-container">
|
||||||
<app-temperature #temperature [measurements]="measurements"></app-temperature>
|
<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>
|
</div>
|
||||||
|
|||||||
@ -3,11 +3,15 @@ import {TemperatureComponent, TimeResolution} from './temperature/temperature';
|
|||||||
import {DefaultService, MeasurementListResponse, MeasurementResolution, StationListResponse} from '../../api';
|
import {DefaultService, MeasurementListResponse, MeasurementResolution, StationListResponse} from '../../api';
|
||||||
import {ApexOptions} from 'ng-apexcharts';
|
import {ApexOptions} from 'ng-apexcharts';
|
||||||
import {addDays, addHours, addMonths, addYears, startOfDay} from 'date-fns';
|
import {addDays, addHours, addMonths, addYears, startOfDay} from 'date-fns';
|
||||||
|
import {Humidity} from './humidity/humidity';
|
||||||
|
import {Pressure} from './pressure/pressure';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-diagrams',
|
selector: 'app-diagrams',
|
||||||
imports: [
|
imports: [
|
||||||
TemperatureComponent
|
TemperatureComponent,
|
||||||
|
Humidity,
|
||||||
|
Pressure
|
||||||
],
|
],
|
||||||
templateUrl: './diagrams.html',
|
templateUrl: './diagrams.html',
|
||||||
styleUrl: './diagrams.css',
|
styleUrl: './diagrams.css',
|
||||||
@ -16,6 +20,8 @@ export class Diagrams {
|
|||||||
timeResolution: TimeResolution = '7d';
|
timeResolution: TimeResolution = '7d';
|
||||||
@Input() activeStations: StationListResponse[] = [];
|
@Input() activeStations: StationListResponse[] = [];
|
||||||
@ViewChild('temperature') temperatureDiagram?: TemperatureComponent
|
@ViewChild('temperature') temperatureDiagram?: TemperatureComponent
|
||||||
|
@ViewChild('humidity') humidityDiagram?: TemperatureComponent
|
||||||
|
@ViewChild('pressure') pressureDiagram?: TemperatureComponent
|
||||||
resolution: MeasurementResolution = MeasurementResolution.Daily;
|
resolution: MeasurementResolution = MeasurementResolution.Daily;
|
||||||
measurements: MeasurementListResponse | undefined;
|
measurements: MeasurementListResponse | undefined;
|
||||||
|
|
||||||
@ -77,5 +83,7 @@ export class Diagrams {
|
|||||||
|
|
||||||
buildCharts() {
|
buildCharts() {
|
||||||
this.temperatureDiagram?.buildChart(this.measurements!)
|
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