added tons of files for component functionality; manual component adding added temporarily
This commit is contained in:
parent
58830d480e
commit
45ff49bcea
121 changed files with 25883 additions and 65 deletions
311
src/component/UnitMeasurementSummary.tsx
Normal file
311
src/component/UnitMeasurementSummary.tsx
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue