fix: Datenlücken in Charts korrekt darstellen, Version 1.5.1
- withGaps()-Hilfsfunktion: fügt null-Punkte bei Datenlücken ein - Betrifft: Temperatur, Luftdruck, Feuchte, Wind, Böen - restore-db.sh: mapfile durch while-read ersetzt (zsh-kompatibel)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wetterstation-frontend",
|
||||
"private": true,
|
||||
"version": "1.5.0",
|
||||
"version": "1.5.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useMemo, useState, useCallback } from 'react'
|
||||
import Highcharts from 'highcharts'
|
||||
import { HighchartsReact } from 'highcharts-react-official'
|
||||
import { format } from 'date-fns'
|
||||
@@ -24,6 +24,24 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
// State für Anleitung
|
||||
const [showAnleitung, setShowAnleitung] = useState(false)
|
||||
|
||||
// Schwellwert für Datenlücken (abhängig vom Zeitraum)
|
||||
const gapThresholdMs = useMemo(() => {
|
||||
if (timeRange === '24h') return 2 * 60 * 60 * 1000 // 2 Stunden
|
||||
return 1.5 * 24 * 3600 * 1000 // 1,5 Tage
|
||||
}, [timeRange])
|
||||
|
||||
// Fügt null-Einträge in Lücken ein, damit Highcharts die Linie unterbricht
|
||||
const withGaps = useCallback((pairs) => {
|
||||
const result = []
|
||||
for (let i = 0; i < pairs.length; i++) {
|
||||
result.push(pairs[i])
|
||||
if (i < pairs.length - 1 && pairs[i + 1][0] - pairs[i][0] > gapThresholdMs) {
|
||||
result.push([(pairs[i][0] + pairs[i + 1][0]) / 2, null])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}, [gapThresholdMs])
|
||||
|
||||
// State für benutzerdefinierten Zeitbereich
|
||||
const [showCustomRangeModal, setShowCustomRangeModal] = useState(false)
|
||||
const [customStartDate, setCustomStartDate] = useState('')
|
||||
@@ -405,7 +423,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
series: [
|
||||
{
|
||||
name: 'Maximaltemperatur',
|
||||
data: sortedData.filter(item => item.max_temperature != null).map(item => [new Date(item.datetime).getTime(), item.max_temperature]),
|
||||
data: withGaps(sortedData.filter(item => item.max_temperature != null).map(item => [new Date(item.datetime).getTime(), item.max_temperature])),
|
||||
color: 'rgb(255, 99, 132)',
|
||||
type: 'line',
|
||||
lineWidth: 2,
|
||||
@@ -419,7 +437,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
},
|
||||
{
|
||||
name: 'Minimaltemperatur',
|
||||
data: sortedData.filter(item => item.min_temperature != null).map(item => [new Date(item.datetime).getTime(), item.min_temperature]),
|
||||
data: withGaps(sortedData.filter(item => item.min_temperature != null).map(item => [new Date(item.datetime).getTime(), item.min_temperature])),
|
||||
color: 'rgb(54, 162, 235)',
|
||||
type: 'line',
|
||||
lineWidth: 2,
|
||||
@@ -461,7 +479,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
},
|
||||
series: [{
|
||||
name: 'Temperatur',
|
||||
data: sortedData.filter(item => item.temperature != null).map(item => [new Date(item.datetime).getTime(), item.temperature]),
|
||||
data: withGaps(sortedData.filter(item => item.temperature != null).map(item => [new Date(item.datetime).getTime(), item.temperature])),
|
||||
color: 'rgb(255, 99, 132)',
|
||||
fillColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
@@ -481,7 +499,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
}
|
||||
}]
|
||||
}
|
||||
}, [sortedData, temperatureSuffix, timeRange])
|
||||
}, [sortedData, temperatureSuffix, timeRange, withGaps])
|
||||
|
||||
// Luftfeuchtigkeit Chart
|
||||
const humidityOptions = useMemo(() => {
|
||||
@@ -497,7 +515,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
},
|
||||
series: [{
|
||||
name: 'Feuchte',
|
||||
data: sortedData.filter(item => item.humidity != null).map(item => [new Date(item.datetime).getTime(), item.humidity]),
|
||||
data: withGaps(sortedData.filter(item => item.humidity != null).map(item => [new Date(item.datetime).getTime(), item.humidity])),
|
||||
color: 'rgb(54, 162, 235)',
|
||||
fillColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
@@ -516,7 +534,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
}
|
||||
}]
|
||||
}
|
||||
}, [sortedData, timeRange])
|
||||
}, [sortedData, timeRange, withGaps])
|
||||
|
||||
// Luftdruck Chart
|
||||
const pressureOptions = useMemo(() => {
|
||||
@@ -545,7 +563,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
},
|
||||
series: [{
|
||||
name: 'Luftdruck',
|
||||
data: sortedData.filter(item => item.pressure != null).map(item => [new Date(item.datetime).getTime(), item.pressure]),
|
||||
data: withGaps(sortedData.filter(item => item.pressure != null).map(item => [new Date(item.datetime).getTime(), item.pressure])),
|
||||
color: 'rgb(75, 192, 192)',
|
||||
fillColor: {
|
||||
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
||||
@@ -564,7 +582,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
}
|
||||
}]
|
||||
}
|
||||
}, [sortedData, timeRange])
|
||||
}, [sortedData, timeRange, withGaps])
|
||||
|
||||
// Regen Chart (angepasst an Zeitraum)
|
||||
const rainOptions = useMemo(() => {
|
||||
@@ -645,7 +663,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
},
|
||||
series
|
||||
}
|
||||
}, [sortedData, rainData, timeRange])
|
||||
}, [sortedData, rainData, timeRange, withGaps])
|
||||
|
||||
// Windgeschwindigkeit Chart
|
||||
const windSpeedOptions = useMemo(() => {
|
||||
@@ -655,9 +673,9 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
const hideGusts = (timeRange === '365d') || (isCustomRange && customDays >= 365)
|
||||
const windSpeedSeries = {
|
||||
name: 'Windgeschwindigkeit',
|
||||
data: sortedData
|
||||
data: withGaps(sortedData
|
||||
.filter(item => item.wind_speed != null)
|
||||
.map(item => [new Date(item.datetime).getTime(), item.wind_speed]),
|
||||
.map(item => [new Date(item.datetime).getTime(), item.wind_speed])),
|
||||
color: 'rgb(153, 102, 255)',
|
||||
fillColor: 'rgba(153, 102, 255, 0.1)',
|
||||
type: 'area',
|
||||
@@ -674,9 +692,9 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
? [windSpeedSeries]
|
||||
: [windSpeedSeries, {
|
||||
name: 'Böe' + windGustSuffix,
|
||||
data: sortedData
|
||||
data: withGaps(sortedData
|
||||
.filter(item => item.wind_gust != null)
|
||||
.map(item => [new Date(item.datetime).getTime(), item.wind_gust]),
|
||||
.map(item => [new Date(item.datetime).getTime(), item.wind_gust])),
|
||||
color: 'rgb(255, 100, 0)',
|
||||
fillColor: 'rgba(255, 100, 0, 0.15)',
|
||||
type: 'area',
|
||||
@@ -716,7 +734,7 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '
|
||||
},
|
||||
series
|
||||
}
|
||||
}, [sortedData, timeRange, windGustSuffix])
|
||||
}, [sortedData, timeRange, windGustSuffix, withGaps])
|
||||
|
||||
// Windrichtung Chart
|
||||
const windDirOptions = useMemo(() => ({
|
||||
|
||||
Reference in New Issue
Block a user