119 lines
4.4 KiB
JavaScript
119 lines
4.4 KiB
JavaScript
import React, { Component } from 'react';
|
|
import { Card, CardHeader, CardContent, Divider, Grid, Box, Typography } from '@mui/material';
|
|
import EnvChart from './EnvChart';
|
|
import LevelChart from './LevelChart';
|
|
import { withI18n } from './I18nContext';
|
|
|
|
class ControllerCard extends Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
envData: [],
|
|
portData: {}
|
|
};
|
|
this.interval = null;
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.fetchData();
|
|
this.interval = setInterval(() => this.fetchData(), 60000);
|
|
}
|
|
|
|
componentDidUpdate(prevProps) {
|
|
if (prevProps.controllerName !== this.props.controllerName ||
|
|
prevProps.range !== this.props.range) {
|
|
this.fetchData();
|
|
}
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
if (this.interval) {
|
|
clearInterval(this.interval);
|
|
}
|
|
}
|
|
|
|
fetchData = async () => {
|
|
const { controllerName, ports, range } = this.props;
|
|
try {
|
|
if (ports.length === 0) return;
|
|
|
|
// Fetch all ports concurrently
|
|
const promises = ports.map(port =>
|
|
fetch(`api/history?devName=${encodeURIComponent(controllerName)}&port=${port.port}&range=${range}`)
|
|
.then(res => res.json())
|
|
.then(data => ({ port: port.port, data }))
|
|
);
|
|
|
|
const results = await Promise.all(promises);
|
|
|
|
const newPortData = {};
|
|
results.forEach(item => {
|
|
newPortData[item.port] = item.data;
|
|
});
|
|
|
|
this.setState({ portData: newPortData });
|
|
|
|
// Use the data from the first port for the Environment Chart
|
|
// This avoids a redundant network request
|
|
if (results.length > 0) {
|
|
this.setState({ envData: results[0].data });
|
|
}
|
|
|
|
} catch (err) {
|
|
console.error("Fetch error", err);
|
|
}
|
|
};
|
|
|
|
render() {
|
|
const { controllerName, ports, range, i18n: { t } } = this.props;
|
|
const { envData, portData } = this.state;
|
|
|
|
return (
|
|
<Card sx={{ mb: 4, borderRadius: 2, boxShadow: 3 }}>
|
|
<CardHeader
|
|
title={controllerName}
|
|
titleTypographyProps={{ variant: 'h5', fontWeight: 'bold', color: 'primary.main' }}
|
|
sx={{ bgcolor: 'background.paper', borderLeft: '6px solid', borderLeftColor: 'primary.main' }}
|
|
/>
|
|
<CardContent>
|
|
{/* Environment Chart */}
|
|
<Box sx={{ height: 350, mb: 6 }}>
|
|
<Typography variant="h6" color="text.secondary" gutterBottom>
|
|
{t('controller.environment')}
|
|
</Typography>
|
|
<EnvChart data={envData} range={range} />
|
|
</Box>
|
|
|
|
<Divider sx={{ mt: 2, mb: 3 }} />
|
|
|
|
{/* Port Grid */}
|
|
<Grid container spacing={3}>
|
|
{ports.map((port) => {
|
|
const isLight = port.port_name && port.port_name.toLowerCase().includes('light');
|
|
const isCO2 = port.port_name && port.port_name.toLowerCase().includes('co2');
|
|
const pData = portData[port.port] || [];
|
|
|
|
return (
|
|
<Grid size={{ xs: 12, md: 6, lg: 4 }} key={port.port}>
|
|
<Card variant="outlined" sx={{ bgcolor: 'background.paper' }}>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
{port.port_name || `${t('controller.port')} ${port.port}`}
|
|
</Typography>
|
|
<Box sx={{ height: 250 }}>
|
|
<LevelChart data={pData} isLight={isLight} isCO2={isCO2} range={range} />
|
|
</Box>
|
|
</CardContent>
|
|
</Card>
|
|
</Grid>
|
|
);
|
|
})}
|
|
</Grid>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default withI18n(ControllerCard);
|