129 lines
5.0 KiB
JavaScript
129 lines
5.0 KiB
JavaScript
import React, { Component } from 'react';
|
|
import { Grid, Typography, Button, ButtonGroup, Box, Alert } from '@mui/material';
|
|
import ControllerCard from './ControllerCard';
|
|
import OutputChart from './OutputChart';
|
|
import { withI18n } from './I18nContext';
|
|
import { withDevices } from './DevicesContext';
|
|
|
|
class Dashboard extends Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
range: 'day', // 'day', 'week', 'month'
|
|
offset: 0
|
|
};
|
|
}
|
|
|
|
setRange = (range) => {
|
|
this.setState({ range, offset: 0 });
|
|
};
|
|
|
|
setOffset = (offset) => {
|
|
if (offset < 0) offset = 0;
|
|
this.setState({ offset });
|
|
};
|
|
|
|
render() {
|
|
const { i18n: { t }, devicesCtx: { devices, groupedDevices, loading, error } } = this.props;
|
|
const { range, offset } = this.state;
|
|
|
|
const nowMs = Date.now();
|
|
let startMs, endMs;
|
|
|
|
if (range === 'today') {
|
|
const d = new Date(nowMs);
|
|
d.setHours(0, 0, 0, 0);
|
|
const midnightMs = d.getTime();
|
|
startMs = midnightMs - (offset * 24 * 3600 * 1000);
|
|
endMs = startMs + (24 * 3600 * 1000);
|
|
} else {
|
|
const durationSec = (range === 'week' ? 7 * 24 * 3600 : (range === 'month' ? 30 * 24 * 3600 : 24 * 3600));
|
|
endMs = nowMs - (offset * durationSec * 1000);
|
|
startMs = endMs - (durationSec * 1000);
|
|
}
|
|
|
|
const dateOpts = { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' };
|
|
const dateRangeLabel = `${new Date(startMs).toLocaleString([], dateOpts)} - ${new Date(endMs).toLocaleString([], dateOpts)}`;
|
|
|
|
if (loading) return <Typography>{t('dashboard.loading')}</Typography>;
|
|
if (error) return <Alert severity="error">{error}</Alert>;
|
|
|
|
return (
|
|
<Box>
|
|
<Box
|
|
display="flex"
|
|
justifyContent="space-between"
|
|
alignItems="center"
|
|
mb={3}
|
|
sx={{
|
|
position: 'sticky',
|
|
top: 0,
|
|
zIndex: 100,
|
|
backgroundColor: '#1d2021', // Dashboard background color to cover content
|
|
padding: '10px 20px', // Added horizontal padding
|
|
borderBottom: '1px solid #3c3836',
|
|
margin: '-16px -16px 16px -16px' // Negative margin to stretch full width if inside padding
|
|
}}
|
|
>
|
|
<Typography variant="h6" sx={{ color: '#ebdbb2' }}>
|
|
{dateRangeLabel}
|
|
</Typography>
|
|
<ButtonGroup variant="contained" aria-label="outlined primary button group">
|
|
<Button
|
|
onClick={() => this.setOffset(this.state.offset + 1)}
|
|
color="inherit"
|
|
>
|
|
<
|
|
</Button>
|
|
<Button
|
|
onClick={() => this.setRange('day')}
|
|
color={range === 'day' ? 'primary' : 'inherit'}
|
|
>
|
|
{t('dashboard.hours24')}
|
|
</Button>
|
|
<Button
|
|
onClick={() => this.setRange('today')}
|
|
color={range === 'today' ? 'primary' : 'inherit'}
|
|
>
|
|
1 Tag
|
|
</Button>
|
|
<Button
|
|
onClick={() => this.setRange('week')}
|
|
color={range === 'week' ? 'primary' : 'inherit'}
|
|
>
|
|
{t('dashboard.days7')}
|
|
</Button>
|
|
<Button
|
|
onClick={() => this.setRange('month')}
|
|
color={range === 'month' ? 'primary' : 'inherit'}
|
|
>
|
|
{t('dashboard.days30')}
|
|
</Button>
|
|
<Button
|
|
onClick={() => this.setOffset(this.state.offset - 1)}
|
|
disabled={this.state.offset <= 0}
|
|
color="inherit"
|
|
>
|
|
>
|
|
</Button>
|
|
</ButtonGroup>
|
|
</Box>
|
|
|
|
{Object.entries(groupedDevices).map(([controllerName, ports]) => (
|
|
<ControllerCard
|
|
key={controllerName}
|
|
controllerName={controllerName}
|
|
ports={ports}
|
|
range={range}
|
|
offset={this.state.offset}
|
|
/>
|
|
))}
|
|
|
|
<OutputChart range={range} offset={this.state.offset} devices={devices} />
|
|
</Box>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default withDevices(withI18n(Dashboard));
|