123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- import { useEffect, useState } from 'react';
- // material-ui
- import {
- Avatar,
- AvatarGroup,
- Box,
- Button,
- Grid,
- List,
- ListItemAvatar,
- ListItemButton,
- ListItemSecondaryAction,
- ListItemText,
- MenuItem,
- Stack,
- TextField,
- Typography,
- Alert,
- TableHead,
- TableRow,
- TableCell,
- TableContainer,
- Table,
- TableBody,
- Dialog,
- DialogTitle,
- DialogContent,
- DialogContentText,
- DialogActions
- } from '@mui/material';
- import MainCard from '../../../components/MainCard';
- // material-ui
- import { useTheme } from '@mui/material/styles';
- // third-party
- import ReactApexChart from 'react-apexcharts';
- import { object } from 'prop-types';
- import { FormaterForMetric } from './utils';
- import { set } from 'lodash';
- import { DownOutlined, UpOutlined } from '@ant-design/icons';
- import PlotComponent from './plot';
- function formatDate(now, time) {
- // use as UTC
- // now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
- const year = now.getFullYear();
- const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are 0-based
- const day = String(now.getDate()).padStart(2, '0');
- const hours = String(now.getHours()).padStart(2, '0');
- const minutes = String(now.getMinutes()).padStart(2, '0');
- const seconds = String(now.getSeconds()).padStart(2, '0');
- return time ? `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` : `${year}-${month}-${day}`;
- }
- function descendingComparator(a, b, orderBy) {
- let a1 = a[orderBy];
- let b1 = b[orderBy];
- if(orderBy != 'name') {
- a1 = parseFloat(a["__" + orderBy]);
- b1 = parseFloat(b["__" + orderBy]);
- } else {
- a1 = a1.toLowerCase();
- b1 = b1.toLowerCase();
- }
- if (b1 < a1) {
- return -1;
- }
- if (b1 > a1) {
- return 1;
- }
- return 0;
- }
- function getComparator(order, orderBy) {
- return order === 'desc' ? (a, b) => descendingComparator(a, b, orderBy) : (a, b) => -descendingComparator(a, b, orderBy);
- }
- function stableSort(array, comparator) {
- const stabilizedThis = array.map((el, index) => [el, index]);
- stabilizedThis.sort((a, b) => {
- const order = comparator(a[0], b[0]);
- if (order !== 0) {
- return order;
- }
- return a[1] - b[1];
- });
- return stabilizedThis.map((el) => el[0]);
- }
- function toUTC(date, time) {
- let now = new Date(date);
- now.setMinutes(now.getMinutes() + now.getTimezoneOffset());
- return formatDate(now, time);
- }
- function OrderTableHead({ order, orderBy, headCells, setOrderBy, setOrder }) {
- return (
- <TableHead>
- <TableRow>
- {headCells.map((headCell) => (
- <TableCell
- key={headCell.id}
- align={headCell.align}
- padding={headCell.disablePadding ? 'none' : 'normal'}
- sortDirection={orderBy === headCell.id ? order : false}
- sx={{
- '&:hover': {
- cursor: 'pointer',
- color: 'primary.main'
- }
- }}
- onClick={() => {
- console.log(headCell.id);
- if(orderBy === headCell.id) {
- setOrder(order === 'asc' ? 'desc' : 'asc');
- } else {
- setOrder('asc');
- setOrderBy(headCell.id);
- }
- }}
- >
- {headCell.label} {orderBy === headCell.id ? (
- <Box component="span" sx={{ ...(!headCell.disablePadding && { srOnly: true }) }}>
- {order === 'desc' ? <DownOutlined /> : <UpOutlined />}
- </Box>
- ) : null}
- </TableCell>
- ))}
- </TableRow>
- </TableHead>
- );
- }
- const TableComponent = ({ title, data, displayMax, render, xAxis, slot, zoom}) => {
- const theme = useTheme();
- const { primary, secondary } = theme.palette.text;
- const line = theme.palette.divider;
- const [series, setSeries] = useState([]);
- const [order, setOrder] = useState('asc');
- const [orderBy, setOrderBy] = useState('name');
- const [headCells, setHeadCells] = useState([]);
- const [rows, setRows] = useState([]);
- const [openModal, setOpenModal] = useState(false);
- useEffect(() => {
- let heads = {};
- let fnrows = [];
- data.forEach((item) => {
- let k = item.Key.split('.')
- let v = item.Values.length ? item.Values[item.Values.length - 1].Value : 0;
- let avgIndex = 0;
- v = xAxis
- .filter((date, index) => {
- if (zoom && zoom.xaxis && zoom.xaxis.min && zoom.xaxis.max) {
- return index >= zoom.xaxis.min && index <= zoom.xaxis.max;
- }
- return true;
- })
- .map((date) => {
- if (slot === 'hourly' || slot === 'daily') {
- let key = slot === 'hourly' ? "hour_" : "day_";
- let k = key + toUTC(date, slot === 'hourly');
- if (k in item.ValuesAggl) {
- return item.ValuesAggl[k].Value;
- } else {
- return 0;
- }
- } else {
- let realIndex = item.Values.length - 1 - parseInt(date / item.TimeScale)
- return item.Values[realIndex] ? item.Values[realIndex].Value : 0;
- }
- })
- .reduce((a, b) => {
- if (typeof b === "undefined" || b === null) {
- return a;
- }
- if (item.AggloType == "min") {
- return Math.min(a, b);
- } else if (item.AggloType == "max") {
- return Math.max(a, b);
- } else if (item.AggloType == "avg") {
- avgIndex++;
- return a + b;
- } else if (item.AggloType == "sum") {
- return a + b;
- } else {
- return b;
- }
- }, 0);
- if (item.AggloType == "avg" && avgIndex) {
- v = v / avgIndex;
- }
- let name = k[k.length - 1];
- let cat = k[k.length - 2];
- heads[cat] = true;
- let formatter = FormaterForMetric(item, displayMax);
- if(!fnrows.find((row) => row.name === name)) {
- fnrows.push({
- name,
- [cat]: render ? render(item, v, formatter(v)) : formatter(v),
- ["__" + cat]: v,
- "__key": [item.Key]
- });
- } else {
- fnrows.find((row) => row.name === name)[cat] = render ? render(item, v, formatter(v)) : formatter(v)
- fnrows.find((row) => row.name === name)["__" + cat] = v
- fnrows.find((row) => row.name === name)["__key"].push(item.Key)
- }
- });
- // remove from fnrows rows where all values are 0
- fnrows = fnrows.filter((row) => {
- let flag = false;
- Object.keys(row).forEach((key) => {
- if(key !== 'name' && row["__" + key]) {
- flag = true;
- }
- });
- return flag;
- }
- );
- let fnhc = [
- {
- id: 'name',
- align: 'left',
- disablePadding: false,
- label: 'Name'
- },
- ];
- Object.keys(heads).forEach((head) => {
- fnhc.push({
- id: head,
- align: 'right',
- disablePadding: false,
- label: head
- });
- });
- setHeadCells(fnhc);
- setRows(fnrows);
-
- }, [data, slot, xAxis, zoom]);
- return <>
- {openModal && <Dialog open={openModal} onClose={() => setOpenModal(false)} maxWidth="md" fullWidth={true}>
- <DialogTitle>Detailed History</DialogTitle>
- <DialogContent>
- <DialogContentText style={{
- }}>
- <PlotComponent
- data={data.filter((item) => {
- if (!openModal) {
- return false;
- }
- return openModal.includes(item.Key)
- })}
- xAxis={xAxis}
- slot={slot}
- zoom={zoom}
- zoomDisabled={true}
- />
- </DialogContentText>
- </DialogContent>
- <DialogActions>
- <Button onClick={() => {
- setOpenModal(false)
- }}>Close</Button>
- </DialogActions>
- </Dialog>}
-
- <Grid item xs={12} md={5} lg={4}>
- <Grid container alignItems="center" justifyContent="space-between">
- <Grid item>
- <Typography variant="h5">{title}</Typography>
- </Grid>
- </Grid>
- <MainCard content={false} sx={{ mt: 1.5 }}>
- <Box>
- <TableContainer
- sx={{
- width: '100%',
- overflowX: 'auto',
- position: 'relative',
- display: 'block',
- maxWidth: '100%',
- '& td, & th': { whiteSpace: 'nowrap' },
- maxHeight: '474px'
- }}
- >
- <Table
- aria-labelledby="tableTitle"
- sx={{
- '& .MuiTableCell-root:first-child': {
- pl: 2
- },
- '& .MuiTableCell-root:last-child': {
- pr: 3
- }
- }}
- >
- <OrderTableHead headCells={headCells} order={order} orderBy={orderBy} setOrderBy={setOrderBy} setOrder={setOrder} />
- <TableBody style={{height:'409px', overflow: 'auto'}}>
- {stableSort(rows, getComparator(order, orderBy)).map((row, index) => {
- const isItemSelected = false // isSelected(row.trackingNo);
- const labelId = `enhanced-table-checkbox-${index}`;
- return (
- <TableRow
- hover
- role="checkbox"
- sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
- aria-checked={isItemSelected}
- tabIndex={-1}
- key={row.trackingNo}
- selected={isItemSelected}
- onClick={() => {
- setOpenModal(row.__key);
- }}
- >
- {headCells.map((headCell) => {
- return <TableCell align={
- headCell.align
- }>{row[headCell.id]}</TableCell>
- })}
- </TableRow>
- );
- })}
- </TableBody>
- </Table>
- </TableContainer>
- </Box>
- </MainCard>
- </Grid>
- </>
- }
- export default TableComponent;
|