V 1.2.0 diverse Anpassungen, so dass es ähnlich der alten Anwenung ist. Ist nun mal gut zu benutzen
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wetterstation-frontend",
|
||||
"private": true,
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -4,6 +4,7 @@ import './App.css'
|
||||
|
||||
function App() {
|
||||
const [weatherData, setWeatherData] = useState([])
|
||||
const [currentWeatherData, setCurrentWeatherData] = useState([]) // Immer die aktuellen 24h-Werte
|
||||
const [rainData, setRainData] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
@@ -18,6 +19,7 @@ function App() {
|
||||
// Prüfe ob eingebettete Daten vorhanden sind (statischer Build)
|
||||
if (window.__WEATHER_DATA__ && timeRange === '24h') {
|
||||
setWeatherData(window.__WEATHER_DATA__)
|
||||
setCurrentWeatherData(window.__WEATHER_DATA__)
|
||||
setRainData([])
|
||||
setLastUpdate(new Date())
|
||||
setLoading(false)
|
||||
@@ -58,6 +60,18 @@ function App() {
|
||||
const weatherDataResult = await weatherResponse.json()
|
||||
setWeatherData(weatherDataResult)
|
||||
|
||||
// Immer die aktuellen 24h-Daten für "Aktuell"-Anzeige laden
|
||||
if (timeRange !== '24h') {
|
||||
const currentUrl = `${baseUrl}/weather/history?hours=24`
|
||||
const currentResponse = await fetch(currentUrl)
|
||||
if (currentResponse.ok) {
|
||||
const currentDataResult = await currentResponse.json()
|
||||
setCurrentWeatherData(currentDataResult)
|
||||
}
|
||||
} else {
|
||||
setCurrentWeatherData(weatherDataResult)
|
||||
}
|
||||
|
||||
// Regendaten laden (falls separater Endpunkt)
|
||||
if (rainUrl) {
|
||||
const rainResponse = await fetch(rainUrl)
|
||||
@@ -138,6 +152,7 @@ function App() {
|
||||
<main className="app-main">
|
||||
<WeatherDashboard
|
||||
data={weatherData}
|
||||
currentData={currentWeatherData}
|
||||
rainData={rainData}
|
||||
timeRange={timeRange}
|
||||
onTimeRangeChange={setTimeRange}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.dashboard {
|
||||
width: 100%;
|
||||
/* max-width: 1900px; */
|
||||
/* max-width: 1900px; */
|
||||
max-width: 795px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
@@ -51,7 +51,7 @@
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.value-card {
|
||||
@@ -82,17 +82,43 @@
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.chart-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
background: white;
|
||||
padding: 1rem;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.chart-container h3 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 0.75rem;
|
||||
color: #333;
|
||||
font-size: 1rem;
|
||||
background: #e0e0e0;
|
||||
padding: 0.5rem;
|
||||
border-radius: 4px;
|
||||
margin: -0.5rem -0.5rem 0.5rem -0.5rem;
|
||||
}
|
||||
|
||||
.chart-container h3 .unit {
|
||||
font-weight: normal;
|
||||
color: #666;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.current-value {
|
||||
text-align: left;
|
||||
font-size: 0.9rem;
|
||||
color: #0066cc;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.chart-wrapper {
|
||||
@@ -102,11 +128,15 @@
|
||||
}
|
||||
|
||||
.chart-stats {
|
||||
margin-top: 0.5rem;
|
||||
/* margin-top: 0.5rem; */
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.7rem;
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
background: #e0e0e0;
|
||||
padding: 0.5rem;
|
||||
border-radius: 4px;
|
||||
margin: 0.2rem -0.5rem -0.5rem -0.5rem;
|
||||
}
|
||||
|
||||
.dashboard-footer {
|
||||
@@ -117,7 +147,7 @@
|
||||
.footer-divider {
|
||||
border: none;
|
||||
border-top: 1px solid #ccc;
|
||||
margin: 0 0 1rem 0;
|
||||
margin: 0 0 0.5rem 0;
|
||||
}
|
||||
|
||||
.footer-credits {
|
||||
@@ -155,7 +185,8 @@
|
||||
.version-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.version-short {
|
||||
@@ -164,6 +195,15 @@
|
||||
|
||||
.version-full {
|
||||
display: inline;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.time-range-short {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.time-range-full {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* Responsive Design für schmale Bildschirme (Smartphones) */
|
||||
@@ -185,12 +225,21 @@
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.time-range-short {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.time-range-full {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.time-range-label {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.version-short {
|
||||
display: inline;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.version-full {
|
||||
|
||||
@@ -20,12 +20,17 @@ Highcharts.setOptions({
|
||||
}
|
||||
})
|
||||
|
||||
const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeChange }) => {
|
||||
const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '24h', onTimeRangeChange }) => {
|
||||
// Daten vorbereiten und nach Zeit sortieren (älteste zuerst)
|
||||
const sortedData = useMemo(() => {
|
||||
return [...data].sort((a, b) => new Date(a.datetime) - new Date(b.datetime))
|
||||
}, [data])
|
||||
|
||||
// Aktuelle Werte aus separaten currentData (immer 24h)
|
||||
const sortedCurrentData = useMemo(() => {
|
||||
return [...currentData].sort((a, b) => new Date(a.datetime) - new Date(b.datetime))
|
||||
}, [currentData])
|
||||
|
||||
// Zeitraum-Label
|
||||
const timeRangeLabel = useMemo(() => {
|
||||
switch (timeRange) {
|
||||
@@ -118,7 +123,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
tooltip: {
|
||||
shared: true,
|
||||
crosshairs: true,
|
||||
xDateFormat: timeRange === '24h' ? '%d.%m.%Y %H:%M' : '%d.%m.%Y'
|
||||
xDateFormat: timeRange === '24h' ? '%d.%m.%Y %H:%M' : (timeRange === '7d' || timeRange === '30d' ? '%d.%m.%Y - %Hh' : '%d.%m.%Y')
|
||||
},
|
||||
plotOptions: {
|
||||
series: {
|
||||
@@ -160,7 +165,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
...getCommonOptions(),
|
||||
yAxis: {
|
||||
...getCommonOptions().yAxis,
|
||||
title: { text: 'Temperatur (°C)' },
|
||||
title: { text: null },
|
||||
min: yMin,
|
||||
max: yMax
|
||||
},
|
||||
@@ -181,6 +186,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
gapSize: 2 * 24 * 3600 * 1000,
|
||||
gapUnit: 'value',
|
||||
tooltip: {
|
||||
valueDecimals: 1,
|
||||
valueSuffix: ' °C'
|
||||
}
|
||||
}]
|
||||
@@ -192,7 +198,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
...getCommonOptions(),
|
||||
yAxis: {
|
||||
...getCommonOptions().yAxis,
|
||||
title: { text: 'Feuchte (%)' },
|
||||
title: { text: null },
|
||||
min: 40,
|
||||
max: 100
|
||||
},
|
||||
@@ -212,6 +218,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
gapSize: 2 * 24 * 3600 * 1000,
|
||||
gapUnit: 'value',
|
||||
tooltip: {
|
||||
valueDecimals: 0,
|
||||
valueSuffix: ' %'
|
||||
}
|
||||
}]
|
||||
@@ -237,7 +244,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
...getCommonOptions(),
|
||||
yAxis: {
|
||||
...getCommonOptions().yAxis,
|
||||
title: { text: 'Luftdruck (hPa)' },
|
||||
title: { text: null },
|
||||
min: yMin,
|
||||
max: yMax
|
||||
},
|
||||
@@ -257,6 +264,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
gapSize: 2 * 24 * 3600 * 1000,
|
||||
gapUnit: 'value',
|
||||
tooltip: {
|
||||
valueDecimals: 0,
|
||||
valueSuffix: ' hPa'
|
||||
}
|
||||
}]
|
||||
@@ -320,7 +328,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
...getCommonOptions(),
|
||||
yAxis: {
|
||||
...getCommonOptions().yAxis,
|
||||
title: { text: yAxisTitle }
|
||||
title: { text: null }
|
||||
},
|
||||
series
|
||||
}
|
||||
@@ -342,6 +350,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
gapSize: 2 * 24 * 3600 * 1000,
|
||||
gapUnit: 'value',
|
||||
tooltip: {
|
||||
valueDecimals: 1,
|
||||
valueSuffix: ' km/h'
|
||||
}
|
||||
}]
|
||||
@@ -357,6 +366,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
gapSize: 2 * 24 * 3600 * 1000,
|
||||
gapUnit: 'value',
|
||||
tooltip: {
|
||||
valueDecimals: 1,
|
||||
valueSuffix: ' km/h'
|
||||
}
|
||||
}, {
|
||||
@@ -371,6 +381,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
gapSize: 2 * 24 * 3600 * 1000,
|
||||
gapUnit: 'value',
|
||||
tooltip: {
|
||||
valueDecimals: 1,
|
||||
valueSuffix: ' km/h'
|
||||
}
|
||||
}]
|
||||
@@ -390,12 +401,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
},
|
||||
yAxis: {
|
||||
...getCommonOptions().yAxis,
|
||||
title: {
|
||||
text: 'Windspeed (km/h)',
|
||||
style: {
|
||||
whiteSpace: 'nowrap'
|
||||
}
|
||||
}
|
||||
title: { text: null }
|
||||
},
|
||||
series
|
||||
}
|
||||
@@ -404,6 +410,13 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
// Windrichtung Chart
|
||||
const windDirOptions = useMemo(() => ({
|
||||
...getCommonOptions(),
|
||||
tooltip: {
|
||||
formatter: function() {
|
||||
const dateFormat = timeRange === '24h' ? '%d.%m.%Y %H:%M' : (timeRange === '7d' || timeRange === '30d' ? '%d.%m.%Y - %Hh' : '%d.%m.%Y')
|
||||
const dateStr = Highcharts.dateFormat(dateFormat, this.x)
|
||||
return `${dateStr}<br/><span style="color:${this.color}">\u25CF</span> ${this.series.name}: <b>${this.y.toFixed(0)}°</b>`
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
scatter: {
|
||||
marker: {
|
||||
@@ -420,7 +433,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
},
|
||||
yAxis: {
|
||||
...getCommonOptions().yAxis,
|
||||
title: { text: 'Windrichtung' },
|
||||
title: { text: null },
|
||||
min: 0,
|
||||
max: 360,
|
||||
tickInterval: 45,
|
||||
@@ -438,15 +451,12 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
name: 'Windrichtung',
|
||||
data: sortedData.filter(item => item.wind_dir != null).map(item => [new Date(item.datetime).getTime(), item.wind_dir]),
|
||||
color: 'rgb(54, 162, 235)',
|
||||
type: 'scatter',
|
||||
tooltip: {
|
||||
valueSuffix: ' °'
|
||||
}
|
||||
type: 'scatter'
|
||||
}]
|
||||
}), [sortedData])
|
||||
}), [sortedData, timeRange])
|
||||
|
||||
// Aktuellste Werte für Übersicht
|
||||
const current = sortedData[sortedData.length - 1] || {}
|
||||
// Aktuellste Werte für Übersicht (immer aus den 24h-Daten, Fallback auf sortedData)
|
||||
const current = (sortedCurrentData.length > 0 ? sortedCurrentData[sortedCurrentData.length - 1] : sortedData[sortedData.length - 1]) || {}
|
||||
|
||||
// Berechne Min/Max für den gewählten Zeitraum
|
||||
const periodStats = useMemo(() => {
|
||||
@@ -512,25 +522,29 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
className={timeRange === '24h' ? 'active' : ''}
|
||||
onClick={() => onTimeRangeChange('24h')}
|
||||
>
|
||||
24 Stunden
|
||||
<span className="time-range-full">24 Stunden</span>
|
||||
<span className="time-range-short">24h</span>
|
||||
</button>
|
||||
<button
|
||||
className={timeRange === '7d' ? 'active' : ''}
|
||||
onClick={() => onTimeRangeChange('7d')}
|
||||
>
|
||||
7 Tage
|
||||
<span className="time-range-full">7 Tage</span>
|
||||
<span className="time-range-short">7d</span>
|
||||
</button>
|
||||
<button
|
||||
className={timeRange === '30d' ? 'active' : ''}
|
||||
onClick={() => onTimeRangeChange('30d')}
|
||||
>
|
||||
30 Tage
|
||||
<span className="time-range-full">30 Tage</span>
|
||||
<span className="time-range-short">30d</span>
|
||||
</button>
|
||||
<button
|
||||
className={timeRange === '365d' ? 'active' : ''}
|
||||
onClick={() => onTimeRangeChange('365d')}
|
||||
>
|
||||
365 Tage
|
||||
<span className="time-range-full">365 Tage</span>
|
||||
<span className="time-range-short">365d</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -541,57 +555,77 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
|
||||
{/* Charts Grid */}
|
||||
<div className="charts-grid">
|
||||
<div className="chart-container">
|
||||
<h3>🌡️ Temperatur{aggregationSuffix} - Aktuell: {current.temperature?.toFixed(1) || '-'}°C</h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={temperatureOptions} />
|
||||
</div>
|
||||
<div className="chart-stats">
|
||||
Min: {periodStats.minTemp?.toFixed(1) || '-'}°C ({periodStats.minTempTime || '-'}) | Max: {periodStats.maxTemp?.toFixed(1) || '-'}°C ({periodStats.maxTempTime || '-'})
|
||||
<div className="chart-item">
|
||||
<div className="current-value">Aktuell: {current.temperature?.toFixed(1) || '-'}°C</div>
|
||||
<div className="chart-container">
|
||||
<h3><span>🌡️ Temperatur{aggregationSuffix}</span><span className="unit">[°C]</span></h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={temperatureOptions} />
|
||||
</div>
|
||||
<div className="chart-stats">
|
||||
Min: {periodStats.minTemp?.toFixed(1) || '-'}°C ({periodStats.minTempTime || '-'}) | Max: {periodStats.maxTemp?.toFixed(1) || '-'}°C ({periodStats.maxTempTime || '-'})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="chart-container">
|
||||
<h3>🌐 Luftdruck{aggregationSuffix} - Aktuell: {current.pressure?.toFixed(1) || '-'} hPa</h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={pressureOptions} />
|
||||
</div>
|
||||
<div className="chart-stats">
|
||||
Min: {periodStats.minPressure?.toFixed(1) || '-'} hPa ({periodStats.minPressureTime || '-'}) | Max: {periodStats.maxPressure?.toFixed(1) || '-'} hPa ({periodStats.maxPressureTime || '-'})
|
||||
<div className="chart-item">
|
||||
<div className="current-value">Aktuell: {current.pressure?.toFixed(0) || '-'} hPa</div>
|
||||
<div className="chart-container">
|
||||
<h3><span>🌐 Luftdruck{aggregationSuffix}</span><span className="unit">[hPa]</span></h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={pressureOptions} />
|
||||
</div>
|
||||
<div className="chart-stats">
|
||||
Min: {periodStats.minPressure?.toFixed(0) || '-'} hPa ({periodStats.minPressureTime || '-'}) | Max: {periodStats.maxPressure?.toFixed(0) || '-'} hPa ({periodStats.maxPressureTime || '-'})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="chart-container">
|
||||
<h3>💧 Luftfeuchtigkeit{aggregationSuffix} - Aktuell: {current.humidity || '-'}%</h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={humidityOptions} />
|
||||
</div>
|
||||
<div className="chart-stats">
|
||||
Min: {periodStats.minHumidity || '-'}% ({periodStats.minHumidityTime || '-'}) | Max: {periodStats.maxHumidity || '-'}% ({periodStats.maxHumidityTime || '-'})
|
||||
<div className="chart-item">
|
||||
<div className="current-value">Aktuell: {current.humidity || '-'}%</div>
|
||||
<div className="chart-container">
|
||||
<h3><span>💧 Luftfeuchtigkeit{aggregationSuffix}</span><span className="unit">[%]</span></h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={humidityOptions} />
|
||||
</div>
|
||||
<div className="chart-stats">
|
||||
Min: {periodStats.minHumidity || '-'}% ({periodStats.minHumidityTime || '-'}) | Max: {periodStats.maxHumidity || '-'}% ({periodStats.maxHumidityTime || '-'})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="chart-container">
|
||||
<h3>🌧️ Regen{aggregationSuffix} - Aktuell: {current.rain?.toFixed(1) || '-'} mm</h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={rainOptions} />
|
||||
<div className="chart-item">
|
||||
<div className="current-value">Aktuell: {current.rain?.toFixed(1) || '-'} mm</div>
|
||||
<div className="chart-container">
|
||||
<h3><span>🌧️ Regen{aggregationSuffix}</span><span className="unit">[mm]</span></h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={rainOptions} />
|
||||
</div>
|
||||
<div className="chart-stats"> </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="chart-container">
|
||||
<h3>🧭 Windrichtung{aggregationSuffix} - Aktuell: {current.wind_dir ?? '-'}°</h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={windDirOptions} />
|
||||
<div className="chart-item">
|
||||
<div className="current-value">Aktuell: {current.wind_dir ?? '-'}°</div>
|
||||
<div className="chart-container">
|
||||
<h3><span>🧭 Windrichtung{aggregationSuffix}</span><span className="unit">[°]</span></h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={windDirOptions} />
|
||||
</div>
|
||||
<div className="chart-stats"> </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="chart-container">
|
||||
<h3>💨 Windspeed{aggregationSuffix} - Aktuell: {current.wind_speed?.toFixed(1) || '-'} km/h</h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={windSpeedOptions} />
|
||||
</div>
|
||||
<div className="chart-stats">
|
||||
Max: {periodStats.maxWindGust?.toFixed(1) || '-'} km/h ({periodStats.maxWindGustTime || '-'})
|
||||
<div className="chart-item">
|
||||
<div className="current-value">Aktuell: {current.wind_speed?.toFixed(1) || '-'} km/h</div>
|
||||
<div className="chart-container">
|
||||
<h3><span>💨 Windspeed{aggregationSuffix}</span><span className="unit">[km/h]</span></h3>
|
||||
<div className="chart-wrapper">
|
||||
<HighchartsReact highcharts={Highcharts} options={windSpeedOptions} />
|
||||
</div>
|
||||
<div className="chart-stats">
|
||||
Max: {periodStats.maxWindGust?.toFixed(1) || '-'} km/h ({periodStats.maxWindGustTime || '-'})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -610,7 +644,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC
|
||||
{' '}{version} – {buildDate}
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<hr className="footer-divider" />
|
||||
<div className="footer-credits">
|
||||
<div className="footer-left">Daten-Erfassung mit einer Davis VantagePro.</div>
|
||||
<div className="footer-right">Grafiken erzeugt mit HighCharts</div>
|
||||
|
||||
Reference in New Issue
Block a user