added tons of files for component functionality; manual component adding added temporarily

This commit is contained in:
Carter 2025-02-11 16:31:03 -06:00
parent 58830d480e
commit 45ff49bcea
121 changed files with 25883 additions and 65 deletions

View file

@ -0,0 +1,311 @@
import { Box, Grid, Typography, makeStyles, createStyles, Theme } from "@material-ui/core";
import GrainDescriber from "grain/GrainDescriber";
import { Component } from "models";
import { convertedUnitMeasurement } from "models/UnitMeasurement";
import moment from "moment";
import { pond } from "protobuf-ts/pond";
import React, { useEffect, useState } from "react";
import Divider from "@material-ui/core/Divider";
import { Plenum } from "models/Plenum";
import { Pressure } from "models/Pressure";
import { GrainCable } from "models/GrainCable";
import { extension, Summary } from "pbHelpers/ComponentType";
interface Props {
component: Component | Plenum | Pressure | GrainCable;
reading?: convertedUnitMeasurement | null;
tableCell?: boolean;
centered?: boolean;
dense?: boolean;
omitTime?: boolean;
onlyRecent?: boolean;
largeText?: boolean;
boldMeasurements?: boolean;
excludedNodes?: number[];
}
const useStyles = makeStyles((theme: Theme) =>
createStyles({
"@keyframes ripple": {
from: {
transform: "scale(.8)",
opacity: 1
},
to: {
transform: "scale(1.4)",
opacity: 0
}
},
on: {
boxShadow: `0 0 0 2px ${theme.palette.background.paper}`,
animationName: "$ripple",
animationDuration: "1.2s",
animationTimingFunction: "ease-in-out",
animationIterationCount: "infinite"
},
off: {
backgroundColor: "transparent"
},
divider: {
margin: theme.spacing(1)
}
})
);
export default function UnitMeasurementSummary(props: Props) {
const {
component,
reading,
tableCell,
centered,
dense,
onlyRecent,
largeText,
boldMeasurements,
excludedNodes
} = props;
const [summaries, setSummaries] = useState<Summary[]>([]);
const [timestamp, setTimestamp] = useState("");
const [recent, setRecent] = useState(true);
const classes = useStyles();
useEffect(() => {
if (reading) {
if (onlyRecent) {
setRecent(
moment().diff(moment(reading.timestamp), "milliseconds") <=
component.settings.reportPeriodMs
);
}
setTimestamp(reading.timestamp);
setSummaries(
extension(component.type(), component.subType()).unitMeasurementSummary(
reading,
excludedNodes
)
);
}
}, [component, reading, excludedNodes]); // eslint-disable-line react-hooks/exhaustive-deps
const noSummary = () => {
return (
<Typography variant="body1" color="textPrimary">
No Data
</Typography>
);
};
const noRecent = () => {
return (
<Typography variant="body1" color="textPrimary">
No Recent Data
</Typography>
);
};
const getSummaryComponent = (summaries: Summary[]): any => {
if (summaries.length < 1) {
return noSummary();
}
let overlays: JSX.Element[] = [];
let grain = GrainDescriber(component.settings.grainType);
return (
<Grid container>
<Grid item xs={12}>
<Typography variant={largeText ? "body1" : "caption"} color="textPrimary">
{summaries.map((summary: Summary, index: number) => {
let sumVal = summary.value;
if (component.settings.hasOverlays) {
let overlay: pond.ComponentOverlays = pond.ComponentOverlays.create();
let found = false;
component.settings.overlays.forEach(ov => {
if (ov.measurementType === summary.type) {
//check if the sum value is within the overlay min-max, currently only checks based off the first node
//TODO-CS: possibly consider having more overlays by checking all nodes
let numVal = parseFloat(sumVal);
if (numVal >= ov.min && numVal <= ov.max) {
overlay = ov;
found = true;
}
}
});
if (found) {
overlays.push(
<React.Fragment key={"overlay" + index}>
<Grid item>
<Box
width="20px"
height="20px"
borderRadius="50%"
className={classes.on}
style={{ background: overlay.colour }}
/>
</Grid>
<Grid item>
<Typography
variant={largeText ? "body1" : "caption"}
component="span"
style={{ marginLeft: 5, marginRight: 5 }}>
{overlay.message}
</Typography>
</Grid>
</React.Fragment>
);
}
}
return (
<span key={index}>
{summary.label}
{summary.error && <span style={{ color: "red" }}>{" [error(s)]"}</span>}
{": "}
<span style={{ color: summary.colour, fontWeight: boldMeasurements ? 650 : 500 }}>
{sumVal}
</span>{" "}
<br />
</span>
);
})}
</Typography>
</Grid>
{component.settings.grainType !== pond.Grain.GRAIN_NONE &&
component.settings.grainType !== pond.Grain.GRAIN_INVALID && (
<Typography variant={largeText ? "body1" : "caption"} color="textPrimary">
<span key={"grainType"}>
Grain Type: <span style={{ color: grain.colour }}>{grain.name}</span>
</span>
</Typography>
)}
{!props.omitTime && (
<Grid item xs={12}>
<Typography color="textSecondary" variant={largeText ? "body1" : "caption"}>
{moment(timestamp).fromNow()}
</Typography>
</Grid>
)}
{overlays.length > 0 && (
<React.Fragment>
<Grid item xs={12}>
<Divider variant="middle" className={classes.divider} />
</Grid>
<Grid container direction="row">
{overlays}
</Grid>
</React.Fragment>
)}
</Grid>
);
};
const getTableCellSummaryComponent = (summaries: Summary[]): any => {
if (summaries.length < 1 || summaries === undefined) {
return <span>Unknown</span>;
}
const blacklist: Array<any> = [];
const filteredSummaries = summaries.filter((item: any) => !blacklist.includes(item.label));
return (
<Grid container direction="row" justify={centered ? "center" : "flex-start"} spacing={1}>
{filteredSummaries.map((summary: Summary, i: number) => {
let sumVal = summary.value;
return (
<Grid item key={"summary-" + i}>
{summary.label}
{summary.error && <span style={{ color: "red" }}>{" [error(s)]"}</span>}
{": "}
<span style={{ color: summary.colour, fontWeight: boldMeasurements ? 650 : 500 }}>
{sumVal}
</span>{" "}
{i + 1 !== filteredSummaries.length && ","}
</Grid>
);
})}
</Grid>
);
};
const getDenseSummary = (summaries: Summary[]): any => {
if (summaries.length < 1) {
return null;
}
const blacklist: Array<any> = ["Temperature (Air)", "Moisture (Air)"];
const filteredSummaries = summaries.filter(
(item: any) =>
!blacklist.includes(item.label) && (item.label !== "Grain Type" || item.value !== "None")
);
let overlays: any = [];
return (
<Box width={"100%"} component="div" key={Math.random()}>
{filteredSummaries.map((summary: Summary, i: number) => {
let sumVal = summary.value;
if (component.settings.hasOverlays) {
let overlay: pond.ComponentOverlays = pond.ComponentOverlays.create();
let found = false;
component.settings.overlays.forEach(ov => {
if (ov.measurementType === summary.type) {
//check if the sum value is within the overlay min-max
let numVal = parseFloat(sumVal);
if (numVal >= ov.min && numVal <= ov.max) {
overlay = ov;
found = true;
}
}
});
if (found) {
overlays.push(
<React.Fragment key={"overlay" + i}>
<Grid item>
<Box
width="20px"
height="20px"
borderRadius="50%"
className={classes.on}
style={{ background: overlay.colour }}
/>
</Grid>
<Grid item>
<Typography
variant={largeText ? "body1" : "caption"}
component="span"
style={{ marginLeft: 5, marginRight: 5 }}>
{overlay.message}
</Typography>
</Grid>
</React.Fragment>
);
}
}
return (
<Typography
key={"summary-" + i}
variant={largeText ? "body1" : "caption"}
component="span">
<span style={{ color: summary.colour }}>{sumVal}</span>
{i + 1 !== filteredSummaries.length && ", "}
</Typography>
);
})}
{!props.omitTime && (
<Box component="span">
{" - "}
<Typography color="textSecondary" variant={largeText ? "body1" : "caption"}>
{moment(timestamp).fromNow()}
</Typography>
</Box>
)}
<Grid container direction="row">
{overlays}
</Grid>
</Box>
);
};
if (!recent) return noRecent();
if (summaries.length <= 0) return noSummary();
if (dense) return getDenseSummary(summaries);
if (tableCell) return getTableCellSummaryComponent(summaries);
return getSummaryComponent(summaries);
}