Merge branch 'dev_environment' of gitlab.com:brandx/bxt-app into dev_environment

This commit is contained in:
Carter 2025-03-11 13:35:43 -06:00
commit 8df5b5e602

View file

@ -125,6 +125,43 @@ interface GrainNodePoint {
y: number; y: number;
} }
interface EllipseData {
key: string | number;
xCenter: string | number;
yCenter: string | number;
xRadius: string | number;
yRadius: string | number;
fillColour: string;
}
interface NodeData { //this could be either a box or a circle depending
key: string | number
x: number;
y: number
width: string | number
height: string | number
borderRad: string | number
nodeNumber: number
nodeTemp: number
}
interface CircleData {
key: string | number
centerX: string | number
centerY: string | number
radius: string | number
onClick?: () => void
}
interface TextData {
key: number | string,
x: number,
y: number,
stroke: string,
filter?: string,
value: string
}
export default function BinSVGV2(props: Props) { export default function BinSVGV2(props: Props) {
const classes = useStyles(); const classes = useStyles();
const { const {
@ -399,6 +436,20 @@ export default function BinSVGV2(props: Props) {
return classes.cableNode; return classes.cableNode;
}; };
const renderText = (text: TextData[]) => {
return text.map(text => (
<text
key={text.key}
x={text.x}
y={text.y}
stroke={text.stroke}
filter={text.filter}
className={classes.tempHum}>
{text.value}
</text>
))
}
const multiCables = () => { const multiCables = () => {
if (!cables) return; if (!cables) return;
//sort the cables by node number so the one with the most nodes is in the middle //sort the cables by node number so the one with the most nodes is in the middle
@ -478,11 +529,17 @@ export default function BinSVGV2(props: Props) {
const filledToY = (fillPercentage * (minNodeY - maxNodeY)) / 100 + maxNodeY; const filledToY = (fillPercentage * (minNodeY - maxNodeY)) / 100 + maxNodeY;
const nodeSpacingY = (maxNodeY - minNodeY) / (cable.temperatures.length + 1); //removing the +1 here would place the nodes starting at the bottom of the cable line rather than from the center const nodeSpacingY = (maxNodeY - minNodeY) / (cable.temperatures.length + 1); //removing the +1 here would place the nodes starting at the bottom of the cable line rather than from the center
let nodeHeatMap: React.SVGProps<SVGEllipseElement>[] = []; //let nodeHeatMap: React.SVGProps<SVGEllipseElement>[] = [];
let nodes: React.SVGProps<SVGCircleElement | SVGRectElement | SVGElement>[] = []; let nodeHeatMapData: EllipseData[] = [];
let temps: React.SVGProps<SVGTextElement>[] = []; //let nodes: React.SVGProps<SVGCircleElement | SVGRectElement | SVGElement>[] = [];
let hums: React.SVGProps<SVGTextElement>[] = []; let nodesData: NodeData[] = [];
let nodeClickers: React.SVGProps<SVGCircleElement>[] = [];
//let temps: React.SVGProps<SVGTextElement>[] = [];
let tempData: TextData[] = []
//let hums: React.SVGProps<SVGTextElement>[] = [];
let humData: TextData[] = [];
//let nodeClickers: React.SVGProps<SVGCircleElement>[] = [];
let nodeClickData: CircleData[] = [];
cable.temperatures.forEach((temp, index) => { cable.temperatures.forEach((temp, index) => {
//since the array goes from the top down set the nodeNumber we are currently working with to be the number of nodes we have left //since the array goes from the top down set the nodeNumber we are currently working with to be the number of nodes we have left
@ -509,88 +566,141 @@ export default function BinSVGV2(props: Props) {
//if we are using the auto top nodes only show the heatmap for nodes at or below the top node //if we are using the auto top nodes only show the heatmap for nodes at or below the top node
if (cable.topNode > 0) { if (cable.topNode > 0) {
if (nodeNumber <= cable.topNode) { if (nodeNumber <= cable.topNode) {
nodeHeatMap.push( // nodeHeatMap.push(
<ellipse // <ellipse
key={index} // key={index}
cx={cablePos} // cx={cablePos}
cy={nodeY} // cy={nodeY}
rx="120" // rx="120"
ry="60" // ry="60"
fill={getGrainGradient(temp)} // fill={getGrainGradient(temp)}
/> // />
); // );
nodeHeatMapData.push({
key: index,
xCenter: cablePos,
yCenter: nodeY,
xRadius: "120",
yRadius: "60",
fillColour: getGrainGradient(temp)
})
} }
} else if (nodeY > filledToY) { } else if (nodeY > filledToY) {
//otherwise use the fill level of the bin //otherwise use the fill level of the bin
nodeHeatMap.push( // nodeHeatMap.push(
<ellipse // <ellipse
key={index} // key={index}
cx={cablePos} // cx={cablePos}
cy={nodeY} // cy={nodeY}
rx="120" // rx="120"
ry="60" // ry="60"
fill={getGrainGradient(temp)} // fill={getGrainGradient(temp)}
/> // />
); // );
nodeHeatMapData.push({
key: index,
xCenter: cablePos,
yCenter: nodeY,
xRadius: "120",
yRadius: "60",
fillColour: getGrainGradient(temp)
})
} }
const displayWidth = 90; const displayWidth = 90;
const displayHeight = 45; const displayHeight = 45;
const cornerRad = 10; const cornerRad = 10;
//add the boxes to display the temps in fulscreen view //add the boxes to display the temps in fulscreen view
nodes.push( // nodes.push(
showTempHum ? ( // showTempHum ? (
<rect // <rect
key={"node" + index} // key={"node" + index}
x={cablePos - displayWidth / 2} // x={cablePos - displayWidth / 2}
y={nodeY - displayHeight / 2} // y={nodeY - displayHeight / 2}
width={displayWidth} // width={displayWidth}
height={displayHeight} // height={displayHeight}
rx={cornerRad} // rx={cornerRad}
className={classes.cableNode}></rect> // className={classes.cableNode}></rect>
) : ( // ) : (
<g key={"node" + index}> // <g key={"node" + index}>
{nodeNumber === topNode && topNodeHat(cablePos, nodeY)} // {nodeNumber === topNode && topNodeHat(cablePos, nodeY)}
<circle cx={cablePos} cy={nodeY} className={nodeClass(temp)} r="16"></circle> // <circle cx={cablePos} cy={nodeY} className={nodeClass(temp)} r="16"></circle>
</g> // </g>
) // )
); // );
//if showTempHum is true will render as a box otherwise will render as a circle which is why the x,y, and radius values will be different
nodesData.push({
key: "node" + index,
x: showTempHum ? cablePos - displayWidth / 2 : cablePos,
y: showTempHum ? nodeY - displayHeight / 2 : nodeY,
height: displayHeight,
width: displayWidth,
borderRad: showTempHum ? cornerRad : "16",
nodeNumber: nodeNumber,
nodeTemp: temp
})
temps.push( // temps.push(
<text // <text
filter="drop-shadow( 4px 4px 10px rgba(0, 0, 0, .7))" // key={"node" + index + "temp"}
key={"node" + index + "temp"} // x={cablePos}
x={cablePos} // y={nodeY + 10}
y={nodeY + 10} // stroke="blue"
stroke="blue" // filter="drop-shadow( 4px 4px 10px rgba(0, 0, 0, .7))"
className={classes.tempHum}> // className={classes.tempHum}>
{displayTemp.toFixed(1)}° // {displayTemp.toFixed(1)}°
</text> // </text>
); // );
hums.push( tempData.push({
<text key: "node" + index + "temp",
key={"node" + index + "hum"} x: cablePos,
x={cablePos} y: nodeY + 10,
y={nodeY + 10} stroke: "blue",
stroke="green" value: displayTemp.toFixed(1) +"°",
className={classes.tempHum}> filter: "drop-shadow( 4px 4px 10px rgba(0, 0, 0, .7))"
{ExtractMoisture(props.grainType, temp, cable.humidities[index] ?? 0).toFixed(1)}% })
</text> // hums.push(
); // <text
// key={"node" + index + "hum"}
// x={cablePos}
// y={nodeY + 10}
// stroke="green"
// className={classes.tempHum}>
// {ExtractMoisture(props.grainType, temp, cable.humidities[index] ?? 0).toFixed(1)}%
// </text>
// );
humData.push({
key: "node" + index + "hum",
x: cablePos,
y: nodeY + 10,
stroke: "green",
value: ExtractMoisture(props.grainType, temp, cable.humidities[index] ?? 0).toFixed(1)+"%",
})
!showTempHum && !showTempHum &&
nodeClickers.push( // nodeClickers.push(
<circle // <circle
key={"node" + index} // key={"node" + index}
onClick={() => { // onClick={() => {
// if (cable.key() !== "" && cableNodeClicked) {
// cableNodeClicked(cable, nodeNumber);
// }
// }}
// cx={cablePos}
// cy={nodeY}
// className={classes.clickableArea}
// r="50"
// />
// );
nodeClickData.push({
key: "node"+index,
centerX: cablePos,
centerY: nodeY,
radius: "50",
onClick: () => {
if (cable.key() !== "" && cableNodeClicked) { if (cable.key() !== "" && cableNodeClicked) {
cableNodeClicked(cable, nodeNumber); cableNodeClicked(cable, nodeNumber);
} }
}} }
cx={cablePos} })
cy={nodeY}
className={classes.clickableArea}
r="50"
/>
);
//if the current node is the top node of the cable use its x and y to add to the cable grain path //if the current node is the top node of the cable use its x and y to add to the cable grain path
if (nodeNumber === topNode) { if (nodeNumber === topNode) {
@ -617,22 +727,60 @@ export default function BinSVGV2(props: Props) {
numNodes--; numNodes--;
}); });
// cableLines.push( cableLines.push(
// <g key={"cable" + cableIndex} id={"cable " + cableIndex} data-name={"cable " + cableIndex}> <g key={"cable" + cableIndex} id={"cable " + cableIndex} data-name={"cable " + cableIndex}>
// {nodeHeatMap} {nodeHeatMapData.map(e => (
// <line <ellipse
// stroke={cableCol} key={e.key}
// x1={cablePos} cx={e.xCenter}
// y1={topY} cy={e.yCenter}
// x2={cablePos} rx={e.xRadius}
// y2={bottomY} ry={e.yRadius}
// className={classes.cableLine} fill={e.fillColour}
// /> />
// {nodes} ))}
// {showTempHum && (extraDetails === "temps" ? temps : hums)} <line
// {nodeClickers} stroke={cableCol}
// </g> x1={cablePos}
// ); y1={topY}
x2={cablePos}
y2={bottomY}
className={classes.cableLine}
/>
{nodesData.map(e => {
if (showTempHum) {
return (
<rect
key={e.key}
x={e.x}
y={e.y}
width={e.width}
height={e.height}
rx={e.borderRad}
className={classes.cableNode}/>
)
} else {
return (
<g key={e.key}>
{e.nodeNumber === topNode && topNodeHat(cablePos, e.y)}
<circle cx={cablePos} cy={e.y} className={nodeClass(e.nodeTemp)} r="16"></circle>
</g>
)
}
})}
{showTempHum && (extraDetails === "temps" ? renderText(tempData) : renderText(humData))}
{nodeClickData.map((e) => (
<circle
key={e.key}
onClick={e.onClick}
cx={e.centerX}
cy={e.centerY}
className={classes.clickableArea}
r={e.radius}
/>
))}
</g>
);
}); });
//for single cable bins the endY would still be 0 so just make it the startY to draw a straight line across the bin //for single cable bins the endY would still be 0 so just make it the startY to draw a straight line across the bin
if (cableGrainEndY === 0) { if (cableGrainEndY === 0) {