diff --git a/src/app/app.html b/src/app/app.html
index 390d15d..05085a5 100644
--- a/src/app/app.html
+++ b/src/app/app.html
@@ -27,7 +27,7 @@
-
+
diff --git a/src/app/app.ts b/src/app/app.ts
index f03e610..e82070b 100644
--- a/src/app/app.ts
+++ b/src/app/app.ts
@@ -7,10 +7,11 @@ import {MatDrawer, MatDrawerContainer, MatDrawerContent} from '@angular/material
import {StationList} from './station-list/station-list';
import {WettterOverview} from './components/wettter-overview/wettter-overview';
import {TemperatureComponent} from './components/diagrams/temperature/temperature';
+import {Diagrams} from './components/diagrams/diagrams';
@Component({
selector: 'app-root',
- imports: [RouterOutlet, MatToolbar, MatIcon, MatIconButton, RouterLink, MatButton, MatDrawerContainer, MatDrawer, MatDrawerContent, StationList, WettterOverview, TemperatureComponent],
+ imports: [RouterOutlet, MatToolbar, MatIcon, MatIconButton, RouterLink, MatButton, MatDrawerContainer, MatDrawer, MatDrawerContent, StationList, WettterOverview, TemperatureComponent, Diagrams],
templateUrl: './app.html',
styleUrl: './app.css'
})
diff --git a/src/app/components/diagrams/diagrams.css b/src/app/components/diagrams/diagrams.css
new file mode 100644
index 0000000..37b3da8
--- /dev/null
+++ b/src/app/components/diagrams/diagrams.css
@@ -0,0 +1,3 @@
+.diagrams-container {
+ margin: 2em;
+}
diff --git a/src/app/components/diagrams/diagrams.html b/src/app/components/diagrams/diagrams.html
new file mode 100644
index 0000000..6861fe7
--- /dev/null
+++ b/src/app/components/diagrams/diagrams.html
@@ -0,0 +1,3 @@
+
diff --git a/src/app/components/diagrams/diagrams.spec.ts b/src/app/components/diagrams/diagrams.spec.ts
new file mode 100644
index 0000000..1d2d162
--- /dev/null
+++ b/src/app/components/diagrams/diagrams.spec.ts
@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { Diagrams } from './diagrams';
+
+describe('Diagrams', () => {
+ let component: Diagrams;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [Diagrams],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(Diagrams);
+ component = fixture.componentInstance;
+ await fixture.whenStable();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/diagrams/diagrams.ts b/src/app/components/diagrams/diagrams.ts
new file mode 100644
index 0000000..33fb4b6
--- /dev/null
+++ b/src/app/components/diagrams/diagrams.ts
@@ -0,0 +1,65 @@
+import {ChangeDetectorRef, Component, Input, ViewChild} from '@angular/core';
+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';
+
+@Component({
+ selector: 'app-diagrams',
+ imports: [
+ TemperatureComponent
+ ],
+ templateUrl: './diagrams.html',
+ styleUrl: './diagrams.css',
+})
+export class Diagrams {
+ timeResolution: TimeResolution = '7d';
+ @Input() activeStations: StationListResponse[] = [];
+ @ViewChild('temperature') temperatureDiagram?: TemperatureComponent
+ resolution: MeasurementResolution = MeasurementResolution.Daily;
+ measurements: MeasurementListResponse | undefined;
+
+ constructor(private api: DefaultService) {
+ }
+
+ ngOnInit() {
+ if (this.activeStations.length === 0) {
+ this.api.listStationsStationsListGet().subscribe(stations => {
+ this.activeStations = stations;
+ this.fetchMeasurements();
+ });
+ } else {
+ this.fetchMeasurements();
+ }
+ }
+
+
+
+ get timeIntervalStart(): string | undefined {
+ const now = new Date();
+ const map: Record = {
+ '24h': addHours(now, -24),
+ '7d': startOfDay(addDays(now, -7)),
+ '30d': startOfDay(addMonths(now, -1)),
+ '1Y': startOfDay(addYears(now, -1)),
+ 'All': undefined
+ };
+ return map[this.timeResolution]?.toISOString();
+ }
+
+ fetchMeasurements() {
+ const stationIds = this.activeStations.map(s => s.id);
+ const now = new Date().toISOString();
+
+ this.api.getMeasurementsMeasurementsGet(
+ stationIds, undefined, this.timeIntervalStart, now, this.resolution
+ ).subscribe(data => {
+ this.measurements = data;
+ this.buildCharts();
+ });
+ }
+
+ buildCharts() {
+ this.temperatureDiagram?.buildChart(this.measurements!)
+ }
+}
diff --git a/src/app/components/diagrams/temperature/temperature.html b/src/app/components/diagrams/temperature/temperature.html
index 6da1947..513bdae 100644
--- a/src/app/components/diagrams/temperature/temperature.html
+++ b/src/app/components/diagrams/temperature/temperature.html
@@ -1,7 +1,22 @@
@if(measurements) {
- Temperaturverlauf
+ Temperaturverlauf
+
+
+ line_axis
+ Line
+
+
+ bar_chart
+ Balken
+
+
+ area_chart
+ Fläche
+
+
+
{
- this.activeStations = stations;
- this.fetchMeasurements();
- });
- } else {
- this.fetchMeasurements();
- }
+ switchChartType(type: 'bar' | 'area' | 'line') {
+ this.chartType = type;
+ this.buildChart(this.measurements!)
}
-
- get timeIntervalStart(): string | undefined {
- const now = new Date();
- const map: Record = {
- '24h': addHours(now, -24),
- '7d': startOfDay(addDays(now, -7)),
- '30d': startOfDay(addMonths(now, -1)),
- '1Y': startOfDay(addYears(now, -1)),
- 'All': undefined
- };
- return map[this.timeResolution]?.toISOString();
- }
-
- fetchMeasurements() {
- const stationIds = this.activeStations.map(s => s.id);
- const now = new Date().toISOString();
-
- this.api.getMeasurementsMeasurementsGet(
- stationIds, undefined, this.timeIntervalStart, now, this.resolution
- ).subscribe(data => {
- this.measurements = data;
- this.buildChart();
- });
- }
-
- buildChart() {
+ 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: 'line',
+ 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: 2,
+ 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)'}`,
@@ -108,13 +105,15 @@ export class TemperatureComponent implements OnInit {
},
tooltip: {
theme: 'dark',
+ shared: true,
+ intersect: false,
x: { format: 'dd.MM.yyyy HH:mm' },
- y: { formatter: (val: number) => `${val.toFixed(1)} °C` }
+ y: { formatter: (val: number) => `${val?.toFixed(1)} °C` }
},
legend: {
labels: { colors: '#9e9e9e' }
},
};
- this.cdr.detectChanges()
+ this.cdr.detectChanges();
}
}