Compare commits

...
7 Commits
Author SHA1 Message Date
Tannerandaider 4e24836aec fix: filter out null values in lastFormatter
Co-authored-by: aider (gemini/gemini-3.1-pro-preview) <aider@aider.chat>
2026-08-25 20:51:25 +00:00
Tanner 88b830973a Rename Soil Moisture 2026-08-25 19:54:36 +00:00
Tannerandaider d499eedb70 refactor: stack soil moisture charts with MultiLineChart
Co-authored-by: aider (gemini/gemini-3.1-pro-preview) <aider@aider.chat>
2026-08-25 19:52:59 +00:00
Tanner 44b33cea75 fix: format tooltip values to one decimal place 2026-08-25 19:52:57 +00:00
Tanner 87c62ca860 Adjust interval settings, use avg air data 2026-08-25 19:36:22 +00:00
Tanner d6c5226e44 Remove trailing whitespace 2026-08-25 19:10:31 +00:00
Tanner d1d6812863 Adjust pressure chart labels 2026-08-25 19:07:49 +00:00
+24 -21
View File
@@ -9,14 +9,10 @@ import './App.css';
let tzcache = {};
const durations = [
{id: 0, len: 'Day', win: '10m', full: '10 min', delta: [1, 'days'], format: 'HH'},
{id: 1, len: 'Day', win: '1h', full: '1 hour', delta: [1, 'days'], format: 'HH'},
{id: 2, len: 'Week', win: '1h', full: '1 hour', delta: [7, 'days'], format: 'HH'},
{id: 3, len: 'Week', win: '1d', full: '1 day', delta: [7, 'days'], format: 'D'},
{id: 4, len: 'Month', win: '1d', full: '1 day', delta: [1, 'months'], format: 'D'},
{id: 5, len: 'Month', win: '7d', full: '7 day', delta: [1, 'months'], format: 'D'},
{id: 6, len: 'Year', win: '1d', full: '1 day', delta: [1, 'years'], format: 'M/D'},
{id: 7, len: 'Year', win: '30d', full: '30 day', delta: [1, 'years'], format: 'M'},
{id: 0, len: 'Day', win: '5m', full: '5 min', delta: [1, 'days'], format: 'HH'},
{id: 1, len: 'Week', win: '30m', full: '30 min', delta: [7, 'days'], format: 'HH'},
{id: 2, len: 'Month', win: '2h', full: '2 hour', delta: [1, 'months'], format: 'D'},
{id: 3, len: 'Year', win: '1d', full: '1 day', delta: [1, 'years'], format: 'M/D'},
];
const units = {
@@ -501,7 +497,7 @@ function Air({name, sensorName, end, duration}) {
<ChartContainer
name={name}
data={data}
lastFormatter={(x) => x.max_p10?.toFixed(1) + ' ug/m³'}
lastFormatter={(x) => x.p10?.toFixed(1) + ' ug/m³'}
loading={loading}
>
<XAxis
@@ -529,7 +525,7 @@ function Air({name, sensorName, end, duration}) {
<CartesianGrid strokeDasharray='3 3'/>
<Tooltip
formatter={(v, name) => v + units[name]}
formatter={(v, name) => v.toFixed(1) + units[name]}
labelFormatter={timeStr => moment(timeStr).tz('America/Edmonton').format('ddd MMM DD h:mm A')}
separator=': '
/>
@@ -539,7 +535,7 @@ function Air({name, sensorName, end, duration}) {
<Line
yAxisId='pm'
type='monotone'
dataKey='max_p10'
dataKey='p10'
name='PM10'
stroke='black'
strokeWidth={2}
@@ -550,7 +546,7 @@ function Air({name, sensorName, end, duration}) {
<Line
yAxisId='pm'
type='monotone'
dataKey='max_p25'
dataKey='p25'
name='PM2.5'
stroke='red'
strokeWidth={2}
@@ -561,7 +557,7 @@ function Air({name, sensorName, end, duration}) {
<Line
yAxisId='co2'
type='monotone'
dataKey='max_co2'
dataKey='co2'
name='CO2'
stroke='blue'
strokeWidth={2}
@@ -572,7 +568,7 @@ function Air({name, sensorName, end, duration}) {
<Line
yAxisId='voc'
type='monotone'
dataKey='max_voc'
dataKey='voc'
name='VOC'
stroke='green'
strokeWidth={2}
@@ -723,7 +719,7 @@ function MultiLineChart({title, measurement, dataKey, sensors, colors, end, dura
name={title}
data={data}
lastFormatter={(x) => {
const vals = sensors.map(s => x[s]).filter(v => v !== undefined);
const vals = sensors.map(s => x[s]).filter(v => v !== undefined && v !== null);
return vals.length ? vals[0].toFixed(1) + (units[unitKey] || '') : 'No data';
}}
loading={loading}
@@ -737,7 +733,6 @@ function MultiLineChart({title, measurement, dataKey, sensors, colors, end, dura
separator=': '
/>
<ReferenceLine x={moment().tz('America/Edmonton').startOf('day').toISOString().replace('.000', '')} stroke='blue' />
<Legend />
{sensors.map((sensor, i) => (
<Line
key={sensor}
@@ -877,20 +872,28 @@ function Graphs({end, duration}) {
<Lux name='Bedroom Lux' sensorName='Bedroom' end={end} duration={duration} />
<Lux name='Laundry Room Lux' sensorName='Laundry Room' end={end} duration={duration} />
<MultiLineChart
title='Pressure'
title='Absolute Pressure'
measurement='hpa'
dataKey='hpa'
sensors={['Kitchen', 'Bedroom', 'Laundry Room']}
colors={['black', 'red', 'blue']}
end={end}
duration={duration}
yDomain={[850, 915]}
yDomain={[870, 915]}
unitKey='Hpa'
/>
<WH51Soil name='Side Garden Soil Moisture' sensorName='Side Garden' end={end} duration={duration} />
<Soil name='Dumb Cane Soil Moisture' sensorName='Dumb Cane' end={end} duration={duration} />
<Soil name='Kitchen Pothos Soil Moisture' sensorName='Kitchen Pothos' end={end} duration={duration} />
<Soil name='Dracaena Soil Moisture' sensorName='Dracaena' end={end} duration={duration} />
<MultiLineChart
title='House Plant Soil Moisture'
measurement='soil'
dataKey='soil'
sensors={['Dumb Cane', 'Kitchen Pothos', 'Dracaena']}
colors={['black', 'red', 'blue']}
end={end}
duration={duration}
yDomain={[0, 1000]}
unitKey='Soil'
/>
{!!api_key ||
<div>