Enhance ModelHistoryDisplay with History Mode Toggle and Chart Data Calculation
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

- Added a switch to toggle between absolute and relative value modes for chart data in ModelHistoryDisplay, improving data analysis flexibility.
- Refactored chart data calculation to support relative values based on the selected history mode, enhancing user experience and data interpretation.
- Updated component layout for better alignment and usability of the new features.
This commit is contained in:
Tom Butcher 2026-08-24 23:14:22 +01:00
parent 71f5e10e5f
commit f0e93b0519

View File

@ -1,5 +1,14 @@
import { useEffect, useState, useContext, useMemo } from 'react' import { useEffect, useState, useContext, useMemo } from 'react'
import { Card, Segmented, Flex, Popover, DatePicker, Button, Space } from 'antd' import {
Card,
Segmented,
Flex,
Popover,
DatePicker,
Button,
Space,
Switch
} from 'antd'
import { import {
ResponsiveContainer, ResponsiveContainer,
BarChart, BarChart,
@ -37,6 +46,7 @@ const ModelHistoryDisplay = ({
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
const [error, setError] = useState(null) const [error, setError] = useState(null)
const [timeRange, setTimeRange] = useState('4hrs') const [timeRange, setTimeRange] = useState('4hrs')
const [historyMode, setHistoryMode] = useState('absolute')
const [startCustomDate, setStartCustomDate] = useState(null) const [startCustomDate, setStartCustomDate] = useState(null)
const [endCustomDate, setEndCustomDate] = useState(null) const [endCustomDate, setEndCustomDate] = useState(null)
const { isDarkMode, getColors } = useThemeContext() const { isDarkMode, getColors } = useThemeContext()
@ -287,7 +297,7 @@ const ModelHistoryDisplay = ({
return colors.default return colors.default
}) })
const chartRows = Array.from( const absoluteRows = Array.from(
chartData chartData
.reduce((acc, item) => { .reduce((acc, item) => {
const existing = acc.get(item.date) || { const existing = acc.get(item.date) || {
@ -301,6 +311,22 @@ const ModelHistoryDisplay = ({
.values() .values()
).sort((a, b) => new Date(a.date) - new Date(b.date)) ).sort((a, b) => new Date(a.date) - new Date(b.date))
const chartRows =
historyMode === 'relative' && absoluteRows.length > 0
? absoluteRows.map((row) => {
const next = {
date: row.date,
dateFormatted: row.dateFormatted
}
for (const statDef of modelStats) {
const category = statDef.label || statDef.name
next[category] =
(row[category] || 0) - (absoluteRows[0][category] || 0)
}
return next
})
: absoluteRows
const customTimeRangeContent = ( const customTimeRangeContent = (
<Space.Compact> <Space.Compact>
<DatePicker.RangePicker <DatePicker.RangePicker
@ -398,9 +424,9 @@ const ModelHistoryDisplay = ({
styles={{ body: { padding: '12px', ...styles } }} styles={{ body: { padding: '12px', ...styles } }}
> >
<Flex gap='small' vertical> <Flex gap='small' vertical>
{!startDate && !endDate && ( <Flex justify='space-between' align='center'>
<Flex justify='space-between'> <Flex align='center' gap='small'>
<Flex align='center' gap='5px'> {!startDate && !endDate && (
<Popover <Popover
content={customTimeRangeContent} content={customTimeRangeContent}
trigger='hover' trigger='hover'
@ -416,9 +442,21 @@ const ModelHistoryDisplay = ({
disabled={loading} disabled={loading}
/> />
</Popover> </Popover>
</Flex> )}
<Switch
size='small'
checked={historyMode === 'absolute'}
checkedChildren='Abs'
unCheckedChildren='Rel'
title='Absolute or relative values'
onChange={(checked) =>
setHistoryMode(checked ? 'absolute' : 'relative')
}
/>
</Flex>
<Flex gap='middle'> {!startDate && !endDate && (
<Flex gap='middle' align='center'>
{loading == true && <LoadingOutlined />} {loading == true && <LoadingOutlined />}
<Segmented <Segmented
size='small' size='small'
@ -434,8 +472,8 @@ const ModelHistoryDisplay = ({
disabled={loading} disabled={loading}
/> />
</Flex> </Flex>
</Flex> )}
)} </Flex>
{chartRows.length > 0 && ( {chartRows.length > 0 && (
<div style={{ width: '100%', height: `${height}px` }}> <div style={{ width: '100%', height: `${height}px` }}>
<ResponsiveContainer width='100%' height='100%'> <ResponsiveContainer width='100%' height='100%'>