fix(graph): adding new button for dht graph

This commit is contained in:
Desy Ayurianti 2024-11-29 12:08:46 +07:00
parent cfbc25fd66
commit ae43ca880c
5 changed files with 176 additions and 48 deletions

View File

@ -62,7 +62,7 @@
</div> </div>
</div> </div>
<div class="text-center-copyright"> <div class="text-center-copyright">
<div>&copy;2024</div> <div>&copy;2024 Agrilink</div>
<div>Powered by <strong>Politeknik Negeri Malang</strong></div> <div>Powered by <strong>Politeknik Negeri Malang</strong></div>
</div> </div>
</div> </div>

View File

@ -17,7 +17,24 @@
</mat-form-field> </mat-form-field>
</div> </div>
<div class="sensor-wrapper"> <div class="sensor-wrapper">
<div class="title">Sensor DHT</div> <div class="title">Sensor DHT</div>
<div class="button-param">
<button
[ngClass]="{'active': activeButton === 'vicitemperature'}"
(click)="filterData('vicitemperature')">
Temperatur Udara
</button>
<button
[ngClass]="{'active': activeButton === 'vicihumidity'}"
(click)="filterData('vicihumidity')">
Kelembaban Udara
</button>
<button
[ngClass]="{'active': activeButton === 'viciluminosity'}"
(click)="filterData('viciluminosity')">
Intensitas Cahaya
</button>
</div>
<ng-container *ngIf="isLoadingDHT; else dhtData"> <ng-container *ngIf="isLoadingDHT; else dhtData">
<div class="d-flex align-items-center" style="padding: 50px 0px 50px 0px"> <div class="d-flex align-items-center" style="padding: 50px 0px 50px 0px">
<i class="fa fa-spinner fa-spin"></i> <i class="fa fa-spinner fa-spin"></i>

View File

@ -70,7 +70,7 @@
.title { .title {
text-align: center; text-align: center;
font-size: 20px; font-size: 20px;
margin: 18px 0px 0px 0px; margin: 18px 0px 18px 0px;
} }
@media (max-width: 768px) { @media (max-width: 768px) {
@ -90,6 +90,18 @@
font-size: 10px; font-size: 10px;
align-items: center; align-items: center;
} }
.button-param {
flex-direction: column;
align-items: center;
}
button {
width: 80%;
max-width: 300px;
text-align: center;
}
} }
@media (max-width: 344px) { @media (max-width: 344px) {
@ -109,6 +121,17 @@
font-size: 10px; font-size: 10px;
align-items: center; align-items: center;
} }
.button-param {
flex-direction: column;
align-items: center;
}
button {
width: 80%;
max-width: 300px;
text-align: center;
}
} }
.loading { .loading {
@ -128,4 +151,28 @@
font-size: 18px; font-size: 18px;
} }
.button-param {
display: flex;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
gap: 10px;
margin: 10px 0 10px 0px;
}
button {
font-family: 'Onest', sans-serif;
margin: 0;
padding: 5px 10px;
background-color: #E5E5E5;
color: #16423C;
border: none;
border-radius: 10px;
transition: all 0.3s ease;
}
button.active {
background-color: #16423C;
color: white;
}

View File

@ -1,5 +1,5 @@
import { Component, OnInit, ElementRef, ViewChild, AfterViewInit, OnDestroy, OnChanges, Input, SimpleChanges, ChangeDetectorRef } from '@angular/core'; import { Component, OnInit, ElementRef, ViewChild, AfterViewInit, OnDestroy, OnChanges, Input, SimpleChanges, ChangeDetectorRef } from '@angular/core';
import { Chart, registerables } from 'chart.js'; import { Chart, registerables, Tooltip } from 'chart.js';
import { SensorService } from '../../../../cores/services/sensor.service'; import { SensorService } from '../../../../cores/services/sensor.service';
import { ApiResponse, ParameterSensor } from '../../../../cores/interface/sensor-data'; import { ApiResponse, ParameterSensor } from '../../../../cores/interface/sensor-data';
import { CommonModule, formatDate } from '@angular/common'; import { CommonModule, formatDate } from '@angular/common';
@ -52,6 +52,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
isNoDataNPK2: boolean = false; isNoDataNPK2: boolean = false;
allNoData: boolean = false; allNoData: boolean = false;
activeButton: string = 'vicitemperature';
sensorParameters: { [key: string]: string[] } = { sensorParameters: { [key: string]: string[] } = {
dht: ['vicitemperature', 'vicihumidity', 'viciluminosity'], dht: ['vicitemperature', 'vicihumidity', 'viciluminosity'],
@ -162,7 +163,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
const dEnd = endDate ? this.formatDate(endDate) : this.getDate(); const dEnd = endDate ? this.formatDate(endDate) : this.getDate();
if (timeRange === 'HOURLY') { if (timeRange === 'HOURLY') {
this.sensorService.getSensorDataHourly('dht', 'npk', hStart, hEnd, timeRange).subscribe({ this.sensorService.getSensorDataHourly('dht', '', hStart, hEnd, timeRange).subscribe({
next: (response) => { next: (response) => {
this.isLoadingDHT = false; this.isLoadingDHT = false;
if (response.statusCode === 200 && response.data.dht?.length > 0) { if (response.statusCode === 200 && response.data.dht?.length > 0) {
@ -280,7 +281,6 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
updateCharts(): void { updateCharts(): void {
const interval = this.selectedInterval; const interval = this.selectedInterval;
Object.keys(this.charts).forEach(key => { Object.keys(this.charts).forEach(key => {
if (this.charts[key]) { if (this.charts[key]) {
this.charts[key]?.destroy(); this.charts[key]?.destroy();
@ -298,8 +298,25 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
this.fetchNPK1Data(interval); this.fetchNPK1Data(interval);
this.fetchNPK2Data(interval); this.fetchNPK2Data(interval);
} }
if (this.charts['dht']) {
this.filterData(this.activeButton);
}
} }
filterData(parameter: string): void {
this.activeButton = parameter;
const chart = this.charts['dht'];
if (chart) {
chart.data.datasets.forEach((dataset: any) => {
dataset.hidden = dataset.label !== this.parameterDisplayNames[parameter];
});
chart.update();
}
}
createChart(canvas: HTMLCanvasElement, response: ApiResponse, sensor: string, selectedOption: string): void { createChart(canvas: HTMLCanvasElement, response: ApiResponse, sensor: string, selectedOption: string): void {
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
@ -327,6 +344,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
const pointRadius = data.length === 1 ? 5 : 0; const pointRadius = data.length === 1 ? 5 : 0;
const pointHoverRadius = data.length === 1 ? 7 : 0; const pointHoverRadius = data.length === 1 ? 7 : 0;
const isHidden = parameter !== this.activeButton;
return { return {
label: displayName, label: displayName,
@ -338,6 +356,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
tension: 0.5, tension: 0.5,
pointRadius, pointRadius,
pointHoverRadius, pointHoverRadius,
hidden : isHidden
}; };
}).filter(dataset => dataset !== null); }).filter(dataset => dataset !== null);
} else { } else {
@ -372,7 +391,6 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
const pointRadius = data.length === 1 ? 5 : 0; const pointRadius = data.length === 1 ? 5 : 0;
const pointHoverRadius = data.length === 1 ? 7 : 0; const pointHoverRadius = data.length === 1 ? 7 : 0;
return { return {
label: displayName, label: displayName,
data, data,
@ -397,48 +415,94 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
this.charts[sensor]?.destroy(); this.charts[sensor]?.destroy();
} }
if(sensor === 'dht'){
this.charts[sensor] = new Chart(ctx, { this.charts[sensor] = new Chart(ctx, {
type: 'line', type: 'line',
data: { data: {
labels: this.getLabels(response, sensor), labels: this.getLabels(response, sensor),
datasets, datasets,
}, },
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
aspectRatio: 2, aspectRatio: 2,
plugins: { plugins: {
tooltip: { tooltip: {
enabled: true, enabled: true,
mode: 'nearest', mode: 'nearest',
intersect: false, intersect: false,
callbacks: { callbacks: {
label: (tooltipItem: any) => { label: (tooltipItem: any) => {
const paramLabel = tooltipItem.dataset.label; const paramLabel = tooltipItem.dataset.label;
const value = tooltipItem.formattedValue; const value = tooltipItem.formattedValue;
return `${paramLabel}: ${value}`; return `${paramLabel}: ${value}`;
} }
} }
},
legend: {
display: false,
}, },
legend: { display: true } },
}, scales: {
scales: { x: {
x: { grid: { display: false },
grid: { display: false }, beginAtZero: true,
beginAtZero: true, ticks: {
ticks: { callback: (value: string | number, index: number, values: any) => {
callback: (value: string | number, index: number, values: any) => { const labels = this.getLabels(response, sensor);
const labels = this.getLabels(response, sensor); return labels[index] || value;
return labels[index] || value; }
} }
} },
y: { grid: { display: false }, beginAtZero: true }
}
}
});
}else if(sensor === 'npk1' || sensor === 'npk2'){
this.charts[sensor] = new Chart(ctx, {
type: 'line',
data: {
labels: this.getLabels(response, sensor),
datasets,
},
options: {
responsive: true,
maintainAspectRatio: false,
aspectRatio: 2,
plugins: {
tooltip: {
enabled: true,
mode: 'nearest',
intersect: false,
callbacks: {
label: (tooltipItem: any) => {
const paramLabel = tooltipItem.dataset.label;
const value = tooltipItem.formattedValue;
return `${paramLabel}: ${value}`;
}
}
},
legend: {
display: true,
}, },
y: { grid: { display: false }, beginAtZero: true } },
} scales: {
} x: {
}); grid: { display: false },
beginAtZero: true,
ticks: {
callback: (value: string | number, index: number, values: any) => {
const labels = this.getLabels(response, sensor);
return labels[index] || value;
}
}
},
y: { grid: { display: false }, beginAtZero: true }
}
}
});
}
} }
getDataFromResponse(response: ApiResponse, sensor: string, parameter: string): { data: number[], labels: string[] } { getDataFromResponse(response: ApiResponse, sensor: string, parameter: string): { data: number[], labels: string[] } {

View File

@ -55,7 +55,7 @@
</div> </div>
</div> </div>
<div class="text-center-copyright"> <div class="text-center-copyright">
<div>&copy;2024</div> <div>&copy;2024 Agrilink</div>
<div>Powered by <strong>Politeknik Negeri Malang</strong></div> <div>Powered by <strong>Politeknik Negeri Malang</strong></div>
</div> </div>
</div> </div>