Add data_visualization/js/ui.js
This commit is contained in:
parent
e77e3f1a54
commit
8f80a64b21
1 changed files with 111 additions and 0 deletions
111
data_visualization/js/ui.js
Normal file
111
data_visualization/js/ui.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* UI Logic for Data Visualization
|
||||
* Handles rendering charts, updating stats, and applying filters.
|
||||
*/
|
||||
|
||||
import { fetchData } from './api.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} SensorData
|
||||
* @property {string} timestamp - ISO time string
|
||||
* @property {number} intensity - Measured light intensity
|
||||
* @property {number} wavelength - Light wavelength in nm
|
||||
* @property {string} sensor_id - Identifier of the sensor
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders chart visualization inside the DOM element with id 'chart-container'.
|
||||
* @param {SensorData[]} dataArray
|
||||
*/
|
||||
export function renderChart(dataArray) {
|
||||
const container = document.getElementById('chart-container');
|
||||
if (!container) return;
|
||||
|
||||
container.innerHTML = '';
|
||||
|
||||
// Create canvas for chart
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.setAttribute('role', 'img');
|
||||
canvas.setAttribute('aria-label', 'Diagramm der Intensitätswerte über Zeit');
|
||||
container.appendChild(canvas);
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
const timestamps = dataArray.map(d => new Date(d.timestamp).toLocaleTimeString());
|
||||
const intensities = dataArray.map(d => d.intensity);
|
||||
|
||||
// Chart.js-like pseudo implementation (no external lib)
|
||||
ctx.beginPath();
|
||||
const maxIntensity = Math.max(...intensities, 1);
|
||||
const minIntensity = Math.min(...intensities, 0);
|
||||
const width = canvas.width = container.offsetWidth;
|
||||
const height = canvas.height = Math.min(400, container.offsetHeight || 300);
|
||||
|
||||
ctx.strokeStyle = '#007acc';
|
||||
ctx.lineWidth = 2;
|
||||
|
||||
intensities.forEach((value, i) => {
|
||||
const x = (i / (intensities.length - 1)) * width;
|
||||
const y = height - ((value - minIntensity) / (maxIntensity - minIntensity)) * height;
|
||||
if (i === 0) ctx.moveTo(x, y);
|
||||
else ctx.lineTo(x, y);
|
||||
});
|
||||
ctx.stroke();
|
||||
|
||||
updateSummary(dataArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates statistics panel with calculated summary data.
|
||||
* @param {SensorData[]} dataArray
|
||||
*/
|
||||
export function updateSummary(dataArray) {
|
||||
const avg = dataArray.length ? dataArray.reduce((acc, d) => acc + d.intensity, 0) / dataArray.length : 0;
|
||||
const max = dataArray.length ? Math.max(...dataArray.map(d => d.intensity)) : 0;
|
||||
const min = dataArray.length ? Math.min(...dataArray.map(d => d.intensity)) : 0;
|
||||
|
||||
const summaryEl = document.getElementById('summary-panel');
|
||||
if (!summaryEl) return;
|
||||
|
||||
summaryEl.innerHTML = `
|
||||
<div class="summary__item"><strong>Durchschnitt:</strong> ${avg.toFixed(2)}</div>
|
||||
<div class="summary__item"><strong>Max:</strong> ${max.toFixed(2)}</div>
|
||||
<div class="summary__item"><strong>Min:</strong> ${min.toFixed(2)}</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads filter form values and triggers data reload.
|
||||
*/
|
||||
export async function applyFilters() {
|
||||
const sensorSelect = document.getElementById('filter-sensor');
|
||||
const timeStart = document.getElementById('filter-start');
|
||||
const timeEnd = document.getElementById('filter-end');
|
||||
|
||||
const params = {};
|
||||
if (sensorSelect?.value) params.sensor = sensorSelect.value;
|
||||
if (timeStart?.value) params.start = timeStart.value;
|
||||
if (timeEnd?.value) params.end = timeEnd.value;
|
||||
|
||||
const data = await fetchData(params).catch(() => []);
|
||||
renderChart(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds UI event handlers.
|
||||
*/
|
||||
export function bindUIEvents() {
|
||||
const form = document.getElementById('filter-form');
|
||||
if (form) {
|
||||
form.addEventListener('submit', e => {
|
||||
e.preventDefault();
|
||||
applyFilters();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-bind when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
bindUIEvents();
|
||||
});
|
||||
Loading…
Reference in a new issue