Merge branch 'object_status' into staging_environment

This commit is contained in:
csawatzky 2026-01-19 13:18:14 -06:00
commit 3f186f7a45
9 changed files with 78 additions and 18 deletions

View file

@ -11,8 +11,10 @@ import ResponsiveTable, { Column } from "common/ResponsiveTable";
import AddGateFab from "./AddGateFab";
import GateSettings from "./GateSettings";
import { useGateAPI, useGlobalState } from "providers";
import { Settings } from "@mui/icons-material";
import { CheckCircleOutline, DoNotDisturb, ErrorOutline, RemoveCircleOutline, Settings } from "@mui/icons-material";
import { cloneDeep } from "lodash";
import moment from "moment";
import { pond } from "protobuf-ts/pond";
interface Props {
//gates: Gate[];
@ -89,6 +91,19 @@ export default function GateList(props: Props) {
setPageSize(event.target.value);
};
const displayPCAStatus = (state: pond.PCAState) => {
switch(state){
case pond.PCAState.PCA_STATE_IN_BOUNDS:
return <CheckCircleOutline sx={{color: "green"}}/>
case pond.PCAState.PCA_STATE_OUT_BOUNDS:
return <ErrorOutline sx={{color: "red"}} />
case pond.PCAState.PCA_STATE_OFF:
return <RemoveCircleOutline />
default:
return <DoNotDisturb />
}
}
const desktopCols = (): Column<Gate>[] => {
return [
{
@ -151,6 +166,29 @@ export default function GateList(props: Props) {
</Box>
)
},
{
title: "PCA Status",
render: gate => (
<Box padding={2}>
{displayPCAStatus(gate.status.pcaState)}
</Box>
)
},
{
title: "Last FLow",
render: gate => (
<Box padding={2}>
<Box display="flex" justifyContent="space-between">
<Typography>Last Flow:</Typography>
<Typography>{gate.status.lastMassAirflow.toFixed(2)}</Typography>
</Box>
<Box display="flex" justifyContent="space-between">
<Typography>Last Reading:</Typography>
<Typography>{gate.status.lastUpdate !== "" ? moment(gate.status.lastUpdate).fromNow() : "No Reading Yet"}</Typography>
</Box>
</Box>
)
}
]
}
const mobileCols = (): Column<Gate>[] => {
@ -162,13 +200,16 @@ export default function GateList(props: Props) {
<Typography margin="auto" marginLeft={0} fontWeight={650} fontSize={20}>
{gate.name}
</Typography>
<IconButton onClick={(event) => {
event.stopPropagation()
setSelectedGate(gate)
setGateDialog(true)
}}>
<Settings />
</IconButton>
<Box display="flex" alignItems="center" gap={1}>
{displayPCAStatus(gate.status.pcaState)}
<IconButton onClick={(event) => {
event.stopPropagation()
setSelectedGate(gate)
setGateDialog(true)
}}>
<Settings />
</IconButton>
</Box>
</Box>
)
}
@ -198,6 +239,14 @@ export default function GateList(props: Props) {
<Typography>PCA Unit:</Typography>
<Typography>{gate.settings.pcaType !== "" ? gate.settings.pcaType : "None"}</Typography>
</Box>
<Box padding={2} display="flex" flexDirection="row" justifyContent="space-between">
<Typography>Last Flow:</Typography>
<Typography>{gate.status.lastMassAirflow}</Typography>
</Box>
<Box padding={2} display="flex" flexDirection="row" justifyContent="space-between">
<Typography>Last Reading:</Typography>
<Typography>{gate.status.lastUpdate !== "" ? moment(gate.status.lastUpdate).fromNow() : "No PCA reading yet"}</Typography>
</Box>
</Box>
// <Typography variant="body2" color="textSecondary" sx={{ padding: 1 }}>

View file

@ -176,12 +176,23 @@ export class Device {
case pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE:
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE:
case pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE:
max = this.status.firmwareVersion >= "2.1.9" ? 4 : 2;
max = this.versionComparison(this.status.firmwareVersion, "2.1.9") ? 4 : 2;
}
return max
}
private versionComparison(deviceVersion: string, requiredVersion: string): boolean {
// Feature explicitly not supported on this platform
if (!requiredVersion || requiredVersion === "N/A") {
return false;
}
// Device firmware missing / unset
if (!deviceVersion || deviceVersion.trim() === "") {
return false;
}
//compare the versions
const parse = (v: string) => {
const [core, pre] = v.split("-");
const parts = core.split(".").map(n => parseInt(n, 10));

View file

@ -5,22 +5,24 @@ import { or } from "utils/types";
export class Gate {
public settings: pond.GateSettings = pond.GateSettings.create();
public status: pond.GateStatus = pond.GateStatus.create();
public name: string = "Gate";
public key: string = "";
public preferences: any = {};
public gateMutations: any = {};
public pcaState: pond.PCAState = pond.PCAState.PCA_STATE_UNKNOWN;
// public pcaState: pond.PCAState = pond.PCAState.PCA_STATE_UNKNOWN;
public static create(pb?: pond.Gate): Gate {
let my = new Gate();
if (pb) {
let g = pond.Gate.fromObject(pb);
my.settings = pond.GateSettings.fromObject(cloneDeep(or(g.settings, {})));
my.status = pond.GateStatus.fromObject(cloneDeep(or(g.status, {})));
my.name = g.name;
my.key = g.key;
my.preferences = g.componentPreferences;
my.gateMutations = g.gateMutations;
my.pcaState = g.pcaState;
// my.pcaState = g.pcaState;
}
return my;
}
@ -77,7 +79,7 @@ export class Gate {
}
public gateMarkerColour(): string {
switch (this.pcaState) {
switch (this.status.pcaState) {
case pond.PCAState.PCA_STATE_OFF:
return "grey";
case pond.PCAState.PCA_STATE_IN_BOUNDS:

View file

@ -179,7 +179,6 @@ export default function NewObjectInteraction(props: Props){
setNewAlertComponentType(quack.ComponentType.COMPONENT_TYPE_INVALID);
setConditions([]);
setSelectedAlertComponents([]);
setValidOptions([])
setValidComponents([])
setValStrings(["0", "0"]);
setNumConditions(0)

View file

@ -128,9 +128,8 @@ export default function DevicePage() {
interaction.settings.nodeOne > interaction.settings.nodeTwo &&
interaction.settings.nodeTwo !== 0
) {
//flip operator and send negative comparitor to save
//flip operator to display what is actually happening
interaction.settings.conditions.forEach(condition => {
//coming back from the backend as a string for some reason
if (condition.comparison === quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN) {
condition.comparison = quack.RelationalOperator.RELATIONAL_OPERATOR_LESS_THAN;
} else {

View file

@ -182,7 +182,6 @@ export default function Terminals(props: Props) {
if(loading) return
setLoading(true)
terminalAPI.listTerminals(200, 0, "asc", "name", undefined, as).then(resp => {
console.log(resp.data)
if(resp.data.terminals){
setTerminals(resp.data.terminals.map(a => Terminal.any(a)));
}

View file

@ -138,6 +138,7 @@ export default function GateProvider(props: PropsWithChildren<Props>) {
return new Promise<AxiosResponse<pond.ListGatesResponse>>((resolve, reject) => {
get<pond.ListGatesResponse>(url).then(resp => {
resp.data = pond.ListGatesResponse.fromObject(resp.data)
console.log(resp)
return resolve(resp)
}).catch(err => {
return reject(err)