Eigenständige Chart-Komponente
This commit is contained in:
parent
9d790cf286
commit
780f3cb6a5
@ -1,14 +1,32 @@
|
|||||||
<main class="main">
|
<main class="main">
|
||||||
|
<div ngbDropdown class="d-inline-block" #houseDrop="ngbDropdown">
|
||||||
|
Haushalt:
|
||||||
|
<button type="button" class="btn btn-outline-primary" id="dropdownBasic1" ngbDropdownToggle>
|
||||||
|
{{getHouseName()}}
|
||||||
|
</button>
|
||||||
|
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
|
||||||
|
<button ngbDropdownItem (click)="$event.stopPropagation(); houseId=1;">Kerpen</button>
|
||||||
|
<button ngbDropdownItem (click)="$event.stopPropagation(); houseId=2;">Rommerskirchen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ngbDropdown class="d-inline-block">
|
||||||
|
<button type="button" class="btn btn-outline-primary" id="dropdownBasic2" ngbDropdownToggle>
|
||||||
|
Zeitraum
|
||||||
|
</button>
|
||||||
|
<div ngbDropdownMenu aria-labelledby="dropdownBasic2">
|
||||||
|
<button ngbDropdownItem (click)="$event.stopPropagation(); duration=120;">letzte 2 Stunden</button>
|
||||||
|
<button ngbDropdownItem (click)="$event.stopPropagation(); duration=360;">letzte 6 Stunden</button>
|
||||||
|
<button ngbDropdownItem (click)="$event.stopPropagation(); duration=1440;">letzte 24 Stunden</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div ngbAccordion>
|
<div ngbAccordion>
|
||||||
<div ngbAccordionItem>
|
<div ngbAccordionItem>
|
||||||
<h2 ngbAccordionHeader>
|
<h2 ngbAccordionHeader>
|
||||||
<button ngbAccordionButton>Diagramm der letzten 24h</button>
|
<button ngbAccordionButton>Diagramm</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div ngbAccordionCollapse>
|
<div ngbAccordionCollapse>
|
||||||
<div ngbAccordionBody>
|
<div ngbAccordionBody>
|
||||||
<div style="border: 1px solid blueviolet;width: 100%; height: 100%;">
|
<app-chart houseId="{{houseId}}" duration="{{duration}}"></app-chart>
|
||||||
<canvas id="canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -18,7 +36,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<div ngbAccordionCollapse>
|
<div ngbAccordionCollapse>
|
||||||
<div ngbAccordionBody>
|
<div ngbAccordionBody>
|
||||||
<ng-template><app-test duration="P1D"></app-test></ng-template>
|
<ng-template><app-test duration="P1D" houseId="{{houseId}}"></app-test></ng-template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,77 +1,44 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core';
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
import { TestComponent } from "./test/test.component";
|
import { TestComponent } from "./test/test.component";
|
||||||
|
import { ChartComponent } from './chart/chart.component';
|
||||||
import { RestService } from './rest.service';
|
import { RestService } from './rest.service';
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { Chart } from 'chart.js/auto';
|
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import 'chartjs-adapter-date-fns';
|
|
||||||
import { de } from 'date-fns/locale';
|
|
||||||
import { Aggregate } from './aggregate';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [RouterOutlet, TestComponent, NgbModule,],
|
imports: [RouterOutlet, TestComponent, ChartComponent, NgbModule,NgbDropdownModule,],
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrl: './app.component.css'
|
styleUrl: './app.component.css'
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
constructor(private rest: RestService) {
|
constructor(private rest: RestService) {
|
||||||
}
|
}
|
||||||
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.rest.getLatestData().subscribe((data: Aggregate[]) => {
|
this.houseId = 1;
|
||||||
this.chart = new Chart('canvas', {
|
this.duration = 120;
|
||||||
type: 'line',
|
|
||||||
options: {
|
|
||||||
scales: {
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
tooltipFormat: 'HH:mm',
|
|
||||||
displayFormats: {
|
|
||||||
hour: 'HH:mm',
|
|
||||||
minute: 'HH:mm'
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
title: {
|
getHouseName(): string {
|
||||||
display: true,
|
if (this.houseId) {
|
||||||
text: 'Zeitpunkt'
|
if (this.houseId === 1) {
|
||||||
},
|
return 'Kerpen';
|
||||||
adapters: {
|
} else if (this.houseId === 2) {
|
||||||
date: {
|
return 'Rommerskirchen';
|
||||||
locale: de
|
} else {
|
||||||
|
return 'Unbekannt';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 'Unbekannt';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
y: {
|
houseId: number | undefined = undefined;
|
||||||
type: 'linear'
|
duration: number | undefined = undefined;
|
||||||
//stacked: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
labels: data.map(row => row.timestampStart),
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: 'Bezug',
|
|
||||||
pointRadius: 0,
|
|
||||||
data: data.map(row => row.obtainedEnergy/60000)
|
|
||||||
}, {
|
|
||||||
label: 'Erzeugt',
|
|
||||||
pointRadius: 0,
|
|
||||||
data: data.map(row => row.producedEnergy/60000)
|
|
||||||
}, {
|
|
||||||
label: 'Eingespeist',
|
|
||||||
pointRadius: 0,
|
|
||||||
data: data.map(row => row.injectedEnergy/60000)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
title = 'test1';
|
|
||||||
chart: Chart | null = null;
|
|
||||||
}
|
}
|
||||||
|
|||||||
0
src/app/chart/chart.component.css
Normal file
0
src/app/chart/chart.component.css
Normal file
3
src/app/chart/chart.component.html
Normal file
3
src/app/chart/chart.component.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div style="border: 1px solid blueviolet;width: 50%; height: 50%;">
|
||||||
|
<canvas id="canvas"></canvas>
|
||||||
|
</div>
|
||||||
23
src/app/chart/chart.component.spec.ts
Normal file
23
src/app/chart/chart.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ChartComponent } from './chart.component';
|
||||||
|
|
||||||
|
describe('ChartComponent', () => {
|
||||||
|
let component: ChartComponent;
|
||||||
|
let fixture: ComponentFixture<ChartComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [ChartComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ChartComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
93
src/app/chart/chart.component.ts
Normal file
93
src/app/chart/chart.component.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import { Component, OnInit, OnChanges, SimpleChanges, numberAttribute, Input } from '@angular/core';
|
||||||
|
import { Chart } from 'chart.js/auto';
|
||||||
|
import 'chartjs-adapter-date-fns';
|
||||||
|
import { de } from 'date-fns/locale';
|
||||||
|
import { RestService } from '../rest.service';
|
||||||
|
import { Aggregate } from '../aggregate';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-chart',
|
||||||
|
standalone: true,
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './chart.component.html',
|
||||||
|
styleUrl: './chart.component.css'
|
||||||
|
})
|
||||||
|
export class ChartComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
|
@Input({ transform: numberAttribute }) houseId!: number;
|
||||||
|
@Input({ transform: numberAttribute }) duration!: number;
|
||||||
|
chart: Chart | null = null;
|
||||||
|
|
||||||
|
constructor(private rest: RestService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
console.log('Nothing yet on chart.ngOnInit()');
|
||||||
|
}
|
||||||
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
this.rest.getLatestData(this.houseId, this.duration).subscribe((data: Aggregate[]) => {
|
||||||
|
console.log('Change chart');
|
||||||
|
if (this.chart) {
|
||||||
|
this.chart.clear();
|
||||||
|
this.chart.destroy();
|
||||||
|
}
|
||||||
|
this.chart = new Chart('canvas', {
|
||||||
|
type: 'line',
|
||||||
|
options: {
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
type: 'time',
|
||||||
|
time: {
|
||||||
|
tooltipFormat: 'HH:mm',
|
||||||
|
displayFormats: {
|
||||||
|
hour: 'HH:mm',
|
||||||
|
minute: 'HH:mm'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Zeitpunkt'
|
||||||
|
},
|
||||||
|
adapters: {
|
||||||
|
date: {
|
||||||
|
locale: de
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
type: 'linear',
|
||||||
|
//stacked: true,
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Leistung [Watt]'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
labels: data.map(row => row.timestampStart),
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Bezug (Stromnetz)',
|
||||||
|
borderColor: '#ff0000',
|
||||||
|
pointRadius: 1,
|
||||||
|
data: data.map(row => row.obtainedEnergy/60000)
|
||||||
|
}, {
|
||||||
|
label: 'Erzeugt (Solar)',
|
||||||
|
borderColor: '#ffa500',
|
||||||
|
pointRadius: 1,
|
||||||
|
data: data.map(row => row.producedEnergy/60000)
|
||||||
|
}, {
|
||||||
|
label: 'Eingespeist (Stromnetz)',
|
||||||
|
borderColor: '#006400',
|
||||||
|
pointRadius: 1,
|
||||||
|
data: data.map(row => row.injectedEnergy/60000)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -16,15 +16,15 @@ export class RestService {
|
|||||||
return this.http.get<Statistics>('https://vz.home.peper.info/rest-vz/stats?houseId=1&duration=P7D');
|
return this.http.get<Statistics>('https://vz.home.peper.info/rest-vz/stats?houseId=1&duration=P7D');
|
||||||
}
|
}
|
||||||
|
|
||||||
getLatestData(): Observable<Aggregate[]> {
|
getLatestData(houseId: Number, duration: Number): Observable<Aggregate[]> {
|
||||||
return this.http.get<Aggregate[]>('https://vz.home.peper.info/rest-vz/latest-data?houseId=2&timeWindow=1440');
|
return this.http.get<Aggregate[]>('https://vz.home.peper.info/rest-vz/latest-data?houseId=' + houseId + '&timeWindow=' + duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
getStatisticsWithDuration(duration: string | undefined): Observable<Statistics> {
|
getStatisticsWithDuration(duration: string | undefined, houseId: Number): Observable<Statistics> {
|
||||||
if (duration) {
|
if (duration) {
|
||||||
return this.http.get<Statistics>('https://vz.home.peper.info/rest-vz/stats?houseId=1&duration=' + duration);
|
return this.http.get<Statistics>('https://vz.home.peper.info/rest-vz/stats?houseId=' + houseId + '&duration=' + duration);
|
||||||
} else {
|
} else {
|
||||||
return this.http.get<Statistics>('https://vz.home.peper.info/rest-vz/stats?houseId=1');
|
return this.http.get<Statistics>('https://vz.home.peper.info/rest-vz/stats?houseId=' + houseId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
|
||||||
import { Statistics } from '../statistics';
|
import { Statistics } from '../statistics';
|
||||||
import { RestService } from '../rest.service';
|
import { RestService } from '../rest.service';
|
||||||
import { formatDate, formatNumber } from '@angular/common';
|
import { formatDate, formatNumber } from '@angular/common';
|
||||||
import { NgIf } from '@angular/common';
|
import { NgIf } from '@angular/common';
|
||||||
|
import { numberAttribute } from '@angular/core';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -12,15 +13,22 @@ import * as _ from 'lodash';
|
|||||||
templateUrl: './test.component.html',
|
templateUrl: './test.component.html',
|
||||||
styleUrl: './test.component.css'
|
styleUrl: './test.component.css'
|
||||||
})
|
})
|
||||||
export class TestComponent implements OnInit {
|
export class TestComponent implements OnInit, OnChanges {
|
||||||
statistics!: Statistics;
|
statistics!: Statistics;
|
||||||
@Input() duration!: string;
|
@Input() duration!: string;
|
||||||
|
@Input({ transform: numberAttribute }) houseId!: Number;
|
||||||
|
|
||||||
constructor(private rest: RestService) {
|
constructor(private rest: RestService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
this.rest.getStatisticsWithDuration(this.duration, this.houseId).subscribe((data: Statistics) => {
|
||||||
|
this.statistics = data;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.rest.getStatisticsWithDuration(this.duration).subscribe((data: Statistics) => {
|
this.rest.getStatisticsWithDuration(this.duration, this.houseId).subscribe((data: Statistics) => {
|
||||||
this.statistics = data;
|
this.statistics = data;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user