From 65e70265fbd267953a380171504a4c2b566a9849 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 15 Jan 2026 14:32:39 -0600 Subject: [PATCH 1/5] displaying status information on the gates dashboard now --- package-lock.json | 4 +-- package.json | 2 +- src/gate/GateList.tsx | 65 +++++++++++++++++++++++++++++----- src/models/Gate.ts | 8 +++-- src/pages/Terminals.tsx | 1 - src/providers/pond/gateAPI.tsx | 1 + 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0e25c26..367ad08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,7 @@ "mui-tel-input": "^7.0.0", "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", - "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#staging", + "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#object_status", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", @@ -10953,7 +10953,7 @@ }, "node_modules/protobuf-ts": { "version": "1.0.0", - "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#3f647071f211c4552c2acc23a8ecabb6904a4156", + "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#580cb59c08f9895384b5adc4853c480bf3bf3165", "dependencies": { "protobufjs": "^6.8.8" } diff --git a/package.json b/package.json index fc7a1ac..3cf9d54 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "mui-tel-input": "^7.0.0", "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", - "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#staging", + "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#object_status", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", diff --git a/src/gate/GateList.tsx b/src/gate/GateList.tsx index 5c548e2..bdf58c2 100644 --- a/src/gate/GateList.tsx +++ b/src/gate/GateList.tsx @@ -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 + case pond.PCAState.PCA_STATE_OUT_BOUNDS: + return + case pond.PCAState.PCA_STATE_OFF: + return + default: + return + } + } + const desktopCols = (): Column[] => { return [ { @@ -151,6 +166,29 @@ export default function GateList(props: Props) { ) }, + { + title: "PCA Status", + render: gate => ( + + {displayPCAStatus(gate.status.pcaState)} + + ) + }, + { + title: "Last FLow", + render: gate => ( + + + Last Flow: + {gate.status.lastMassAirflow.toFixed(2)} + + + Last Reading: + {gate.status.lastUpdate !== "" ? moment(gate.status.lastUpdate).fromNow() : "No Reading Yet"} + + + ) + } ] } const mobileCols = (): Column[] => { @@ -162,13 +200,16 @@ export default function GateList(props: Props) { {gate.name} - { - event.stopPropagation() - setSelectedGate(gate) - setGateDialog(true) - }}> - - + + {displayPCAStatus(gate.status.pcaState)} + { + event.stopPropagation() + setSelectedGate(gate) + setGateDialog(true) + }}> + + + ) } @@ -198,6 +239,14 @@ export default function GateList(props: Props) { PCA Unit: {gate.settings.pcaType !== "" ? gate.settings.pcaType : "None"} + + Last Flow: + {gate.status.lastMassAirflow} + + + Last Reading: + {gate.status.lastUpdate !== "" ? moment(gate.status.lastUpdate).fromNow() : "No PCA reading yet"} + // diff --git a/src/models/Gate.ts b/src/models/Gate.ts index 8842e68..ccd0e77 100644 --- a/src/models/Gate.ts +++ b/src/models/Gate.ts @@ -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: diff --git a/src/pages/Terminals.tsx b/src/pages/Terminals.tsx index dd90aac..94464d5 100644 --- a/src/pages/Terminals.tsx +++ b/src/pages/Terminals.tsx @@ -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))); } diff --git a/src/providers/pond/gateAPI.tsx b/src/providers/pond/gateAPI.tsx index 5b07606..ac63bb0 100644 --- a/src/providers/pond/gateAPI.tsx +++ b/src/providers/pond/gateAPI.tsx @@ -138,6 +138,7 @@ export default function GateProvider(props: PropsWithChildren) { return new Promise>((resolve, reject) => { get(url).then(resp => { resp.data = pond.ListGatesResponse.fromObject(resp.data) + console.log(resp) return resolve(resp) }).catch(err => { return reject(err) From d23d1d6ed3e64210448f6b6b3c5a4950b25f7af6 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Fri, 16 Jan 2026 10:11:59 -0600 Subject: [PATCH 2/5] fixed the options disappearing for alert after closing the dialog box --- src/objects/objectInteractions/NewObjectInteraction.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/objects/objectInteractions/NewObjectInteraction.tsx b/src/objects/objectInteractions/NewObjectInteraction.tsx index 8e76c25..64a63b0 100644 --- a/src/objects/objectInteractions/NewObjectInteraction.tsx +++ b/src/objects/objectInteractions/NewObjectInteraction.tsx @@ -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) From 89d5e40d4555838b41c62efd95c5f934637e60a3 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Mon, 19 Jan 2026 09:49:12 -0600 Subject: [PATCH 3/5] fix bug where the operator wasn't being flipped where it was supposed to --- src/pages/Device.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/Device.tsx b/src/pages/Device.tsx index ee4ae56..0a47a05 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -128,10 +128,9 @@ 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.toString() === "RELATIONAL_OPERATOR_GREATER_THAN") { + if (condition.comparison === quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN) { condition.comparison = quack.RelationalOperator.RELATIONAL_OPERATOR_LESS_THAN; } else { condition.comparison = quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN; From 9f3b48c27793531d114781c71949b9a13457515a Mon Sep 17 00:00:00 2001 From: csawatzky Date: Mon, 19 Jan 2026 12:06:11 -0600 Subject: [PATCH 4/5] make sure to use the new version comparison for the max conditions as well --- src/models/Device.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/Device.ts b/src/models/Device.ts index f4ea4ee..ae03634 100644 --- a/src/models/Device.ts +++ b/src/models/Device.ts @@ -176,7 +176,7 @@ 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 } From 76774b4692e2d81fbeb2a2b077b7fe774c3f405c Mon Sep 17 00:00:00 2001 From: csawatzky Date: Mon, 19 Jan 2026 12:31:51 -0600 Subject: [PATCH 5/5] fix bug where the version check was not functioning as expected when the version in the device status was empty or the requiredVersion was N/A --- src/models/Device.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/models/Device.ts b/src/models/Device.ts index ae03634..7b25c13 100644 --- a/src/models/Device.ts +++ b/src/models/Device.ts @@ -182,6 +182,17 @@ export class Device { } 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));