import { Box, Grid2 as Grid, Typography, Theme, Divider } from "@mui/material"; 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 { Plenum } from "models/Plenum"; import { Pressure } from "models/Pressure"; import { GrainCable } from "models/GrainCable"; import { extension, Summary } from "pbHelpers/ComponentType"; import { makeStyles } from "@mui/styles"; interface Props { component: Component | Plenum | Pressure | GrainCable; reading?: convertedUnitMeasurement | null; tableCell?: boolean; centered?: boolean; dense?: boolean; omitTime?: boolean; onlyRecent?: boolean; largeText?: boolean; boldMeasurements?: boolean; } const useStyles = makeStyles((theme: Theme) => { return ({ "@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 } = props; const [summaries, setSummaries] = useState([]); 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 ) ); } }, [component, reading]); // eslint-disable-line react-hooks/exhaustive-deps const noSummary = () => { return ( No Data ); }; const noRecent = () => { return ( No Recent Data ); }; const getSummaryComponent = (summaries: Summary[]): any => { if (summaries.length < 1) { return noSummary(); } let overlays: JSX.Element[] = []; let grain = GrainDescriber(component.settings.grainType); return ( {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( {overlay.message} ); } } return ( {summary.label} {summary.error && {" [error(s)]"}} {": "} {sumVal} {" "}
); })}
{component.settings.grainType !== pond.Grain.GRAIN_NONE && component.settings.grainType !== pond.Grain.GRAIN_INVALID && ( Grain Type: {grain.name} )} {!props.omitTime && ( {moment(timestamp).fromNow()} )} {overlays.length > 0 && ( {overlays} )}
); }; const getTableCellSummaryComponent = (summaries: Summary[]): any => { if (summaries.length < 1 || summaries === undefined) { return Unknown; } const blacklist: Array = []; const filteredSummaries = summaries.filter((item: any) => !blacklist.includes(item.label)); return ( {filteredSummaries.map((summary: Summary, i: number) => { let sumVal = summary.value; return ( {summary.label} {summary.error && {" [error(s)]"}} {": "} {sumVal} {" "} {i + 1 !== filteredSummaries.length && ","} ); })} ); }; const getDenseSummary = (summaries: Summary[]): any => { if (summaries.length < 1) { return null; } const blacklist: Array = ["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 ( {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( {overlay.message} ); } } return ( {sumVal} {i + 1 !== filteredSummaries.length && ", "} ); })} {!props.omitTime && ( {" - "} {moment(timestamp).fromNow()} )} {overlays} ); }; if (!recent) return noRecent(); if (summaries.length <= 0) return noSummary(); if (dense) return getDenseSummary(summaries); if (tableCell) return getTableCellSummaryComponent(summaries); return getSummaryComponent(summaries); }