From d03b4c6158d97048ac02252f1570749ea1a748d7 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Wed, 4 Mar 2026 13:26:52 -0600 Subject: [PATCH 01/12] hotfix for the delta temp to switch over from listing to sampling the measurements --- src/gate/GateDeltaTempGraph.tsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/gate/GateDeltaTempGraph.tsx b/src/gate/GateDeltaTempGraph.tsx index fc5b253..d547b1c 100644 --- a/src/gate/GateDeltaTempGraph.tsx +++ b/src/gate/GateDeltaTempGraph.tsx @@ -104,28 +104,25 @@ export default function GateDeltaTempGraph(props: Props){ */ useEffect(()=>{ //get the measurements for the temp component - componentAPI.listUnitMeasurements( + componentAPI.sampleUnitMeasurements( deviceID, tempComponent.key(), start.toISOString(), end.toISOString(), - 500, - 0, - "timestamp", + 500 ).then(resp => { + console.log(resp) if(resp.data.measurements){ let tempCompMeasurements = resp.data.measurements.map(um => UnitMeasurement.any(um, user)); //if there is an ambient component, then treat the temp component like a single sensor and not a chain, and use the ambient measurements as the inlet if(ambient){ //need to then load the measurements for the ambient component - componentAPI.listUnitMeasurements( + componentAPI.sampleUnitMeasurements( deviceID, ambient.key(), start.toISOString(), end.toISOString(), - 500, - 0, - "timestamp", + 500 ).then(resp => { let ambientMeasurements = resp.data.measurements.map(um => UnitMeasurement.any(um, user)); //now loop through each of them to 'combine' them into a single array From 5c4f19201019ba6ef78236f57178f6512e7f025f Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 5 Mar 2026 12:48:59 -0600 Subject: [PATCH 02/12] hotfix adding component path to the group router --- src/navigation/Router.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/navigation/Router.tsx b/src/navigation/Router.tsx index cb97f67..94ce101 100644 --- a/src/navigation/Router.tsx +++ b/src/navigation/Router.tsx @@ -278,6 +278,10 @@ export default function Router() { path="/:groupID/devices/:deviceID" element={} /> + } + /> } From d8512faa35ffd1c8b51b5e3c9082a05925f11de6 Mon Sep 17 00:00:00 2001 From: Carter Date: Tue, 10 Mar 2026 15:23:09 -0600 Subject: [PATCH 03/12] switched to master proto --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 90ac71b..7f5044c 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,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#master", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", From 5c9832b037ad8e90845e8a2c65115d14334afa6e Mon Sep 17 00:00:00 2001 From: csawatzky Date: Wed, 11 Mar 2026 11:22:35 -0600 Subject: [PATCH 04/12] hotfix to show the actual fan state on the bin page and not have it hardcoded to on --- src/bin/BinVisualizerV2.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/BinVisualizerV2.tsx b/src/bin/BinVisualizerV2.tsx index 37ed664..53ee866 100644 --- a/src/bin/BinVisualizerV2.tsx +++ b/src/bin/BinVisualizerV2.tsx @@ -1556,7 +1556,7 @@ export default function BinVisualizer(props: Props) { let device = componentDevices.get(fan.key) if(fanComp && device){ return ( - + ) } })} From 843e3a792ef7c909c5e116cbc290eef87cf30a2d Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 16 Mar 2026 11:30:29 -0600 Subject: [PATCH 05/12] fixed some placement stuff --- src/common/ResponsiveTable.tsx | 43 ++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/common/ResponsiveTable.tsx b/src/common/ResponsiveTable.tsx index 2a4cf1a..f55098b 100644 --- a/src/common/ResponsiveTable.tsx +++ b/src/common/ResponsiveTable.tsx @@ -28,13 +28,12 @@ const useStyles = makeStyles((theme: Theme) => { marginTop: theme.spacing(-2), }, titleComp: { - padding: theme.spacing(1), - marginLeft: theme.spacing(-1) + padding: theme.spacing(1, 1, 0, 1.5), }, subtitleComp: { - padding: theme.spacing(1), - marginTop: theme.spacing(-2), - marginLeft: theme.spacing(-1), + padding: theme.spacing(0, 1, 0.5, 1.5), + display: "flex", + alignItems: "center", }, titleContainer: { border: "none", @@ -42,6 +41,8 @@ const useStyles = makeStyles((theme: Theme) => { searchContainer: { border: "none", textAlign: "right", + display: "flex", + alignItems: "center", }, mobileTitleBox: { margin: theme.spacing(1), @@ -118,8 +119,9 @@ function ResizableHeaderTitle(props: { : {}), }} > - - {column.title} {showOrderIcon(column)} + + {column.title} + {showOrderIcon(column)} ); @@ -491,9 +493,17 @@ export default function ResponsiveTable(props: Props) { const sortKey = column.sortKey ? column.sortKey : column.title.toLowerCase() if (sortKey === orderBy) { if (order === "asc") { - return + return ( + + + + ) } else { - return + return ( + + + + ) } } return null; @@ -553,14 +563,17 @@ export default function ResponsiveTable(props: Props) { {(title || setSearchText) && ( - + - - {renderTitle()} - {renderSubtitle()} - + {renderTitle()} + {renderSubtitle()} - + {actions && actions} From 0ea05bdb725002272a475107a179b7ab6da63e85 Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 16 Mar 2026 12:30:18 -0600 Subject: [PATCH 06/12] table changes --- src/common/ResponsiveTable.tsx | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/common/ResponsiveTable.tsx b/src/common/ResponsiveTable.tsx index f55098b..b69589e 100644 --- a/src/common/ResponsiveTable.tsx +++ b/src/common/ResponsiveTable.tsx @@ -546,15 +546,19 @@ export default function ResponsiveTable(props: Props) { const clampedWidth = Math.max(MIN_COLUMN_WIDTH, newWidthForIndex) const actualDelta = newWidths[index] - clampedWidth newWidths[index] = clampedWidth - newWidths.every((width, j) => { - if (j <= index || width === 0) return true - else if (newWidths[j] !== undefined) { - newWidths[j] = newWidths[j] + actualDelta - return false - } - }) + + if (actualDelta > 0) { + // Shrinking current column – give space to next column + newWidths[index + 1] = (newWidths[index + 1] ?? 0) + actualDelta + } else if (actualDelta < 0) { + // Growing current column – take from next column only what it can give + const nextWidth = newWidths[index + 1] ?? 0 + const availableFromNext = Math.max(0, nextWidth - MIN_COLUMN_WIDTH) + const takeFromNext = Math.min(-actualDelta, availableFromNext) + newWidths[index + 1] = nextWidth - takeFromNext + // If we couldn't take enough, the table grows (clampedWidth already applied) + } setRowWidths(newWidths) - } const MIN_COLUMN_WIDTH = 24; From 4326ecbd0f62c8a868a77cea6344931d376c61eb Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 16 Mar 2026 12:40:10 -0600 Subject: [PATCH 07/12] deleted package-lock and ran npm install --- package-lock.json | 766 +--------------------------------------------- 1 file changed, 2 insertions(+), 764 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9b726d6..dfbde6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,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#master", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", @@ -1922,278 +1922,6 @@ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", "license": "MIT" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/linux-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", @@ -2211,159 +1939,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", @@ -3742,244 +3317,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.59.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", @@ -4008,90 +3345,6 @@ "linux" ] }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@sentry-internal/browser-utils": { "version": "8.55.0", "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.55.0.tgz", @@ -9370,21 +8623,6 @@ "integrity": "sha512-hlq4+BU0hlPmwsFjwGGzZ+OZ9N/wq9Ljg/sq3pX+2CD7hrJsX9tJgWWK/wiNTFM212CLHWhicOoqwXyZGGetJg==", "license": "MIT" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -11967,7 +11205,7 @@ }, "node_modules/protobuf-ts": { "version": "1.0.0", - "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#e4a1e598240d504e3ccfe09d6f023c5865ab2c71", + "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#40e15b5ed18b10c97125260a2d53a81d1eec398e", "dependencies": { "protobufjs": "^6.8.8" } From 0f87a0b840f8e042537713b6747372454b2f6351 Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 16 Mar 2026 14:10:47 -0600 Subject: [PATCH 08/12] adjusting column sizes will now make the table bigger or smaller if it has to --- src/common/ResponsiveTable.tsx | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/common/ResponsiveTable.tsx b/src/common/ResponsiveTable.tsx index b69589e..4c21901 100644 --- a/src/common/ResponsiveTable.tsx +++ b/src/common/ResponsiveTable.tsx @@ -16,8 +16,6 @@ const useStyles = makeStyles((theme: Theme) => { }, tableContainer: { width: "100%", - maxWidth: "100%", - overflow: "hidden", minWidth: 0, }, title: { @@ -550,14 +548,8 @@ export default function ResponsiveTable(props: Props) { if (actualDelta > 0) { // Shrinking current column – give space to next column newWidths[index + 1] = (newWidths[index + 1] ?? 0) + actualDelta - } else if (actualDelta < 0) { - // Growing current column – take from next column only what it can give - const nextWidth = newWidths[index + 1] ?? 0 - const availableFromNext = Math.max(0, nextWidth - MIN_COLUMN_WIDTH) - const takeFromNext = Math.min(-actualDelta, availableFromNext) - newWidths[index + 1] = nextWidth - takeFromNext - // If we couldn't take enough, the table grows (clampedWidth already applied) } + // When growing (actualDelta < 0): never shrink adjacent columns – table grows to accommodate setRowWidths(newWidths) } @@ -605,7 +597,20 @@ export default function ResponsiveTable(props: Props) { )} - +
0 + ? (() => { + const colsWidth = columns.reduce( + (sum, c, i) => sum + (filterList.includes(c.title) || c.hidden ? 0 : (rowWidths[i] ?? 0)), + 0 + ) + (rowSelect ? 48 : 0) + (renderGutter ? 48 : 0) + return colsWidth > 0 ? `max(${colsWidth}px, 100%)` : "100%" + })() + : "100%", + }} + > {customElement && From 141ece8a3efff31434058e84d60968c1566a2891 Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 16 Mar 2026 14:15:17 -0600 Subject: [PATCH 09/12] overlay overflow hidden so it stops affecting the scroll bar --- src/common/PulseBox.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/PulseBox.tsx b/src/common/PulseBox.tsx index 2cdc5ce..90c611c 100644 --- a/src/common/PulseBox.tsx +++ b/src/common/PulseBox.tsx @@ -8,6 +8,7 @@ const useStyles = makeStyles((_theme: Theme) => ({ position: 'relative', display: 'block', // Changed to block to respect Box margins width: 'fit-content', // Shrinks to child width + overflow: 'hidden', // Clip pulse animation so it doesn't affect parent layout '&::after': { content: '""', position: 'absolute', From 62763dd2914c05578baf9ca215ba349e4f4f71fb Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 16 Mar 2026 14:24:21 -0600 Subject: [PATCH 10/12] overlay overflow hidden so it stops affecting the scroll bar --- src/common/PulseBox.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/common/PulseBox.tsx b/src/common/PulseBox.tsx index 90c611c..f4ae696 100644 --- a/src/common/PulseBox.tsx +++ b/src/common/PulseBox.tsx @@ -8,7 +8,6 @@ const useStyles = makeStyles((_theme: Theme) => ({ position: 'relative', display: 'block', // Changed to block to respect Box margins width: 'fit-content', // Shrinks to child width - overflow: 'hidden', // Clip pulse animation so it doesn't affect parent layout '&::after': { content: '""', position: 'absolute', @@ -16,8 +15,7 @@ const useStyles = makeStyles((_theme: Theme) => ({ left: 0, width: '100%', height: '100%', - border: '2px solid var(--pulse-color)', - borderRadius: 'inherit', // Should inherit from Box + borderRadius: 'inherit', animation: '$pulse 1.75s infinite ease-in-out', pointerEvents: 'none', boxSizing: 'border-box', @@ -26,13 +24,13 @@ const useStyles = makeStyles((_theme: Theme) => ({ }, '@keyframes pulse': { from: { - transform: "scale(1)", - opacity: 1 + boxShadow: '0 0 0 2px var(--pulse-color)', + opacity: 1, }, to: { - transform: "scale(1.25)", - opacity: 0 - } + boxShadow: '0 0 0 14px var(--pulse-color)', + opacity: 0, + }, }, })); From 575c84246cb127da1bf06a1e78a8e88f11aaac8a Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 16 Mar 2026 14:41:18 -0600 Subject: [PATCH 11/12] gave the pulse box better animation pacing so the colors don't change in the middle of a pulse --- src/common/PulseBox.tsx | 72 +++++++++++++++++++++++-------------- src/common/StatusDust.tsx | 17 +-------- src/common/StatusGas.tsx | 17 +-------- src/common/StatusPlenum.tsx | 18 +--------- src/common/StatusSen5x.tsx | 17 +-------- 5 files changed, 50 insertions(+), 91 deletions(-) diff --git a/src/common/PulseBox.tsx b/src/common/PulseBox.tsx index f4ae696..eb5da3d 100644 --- a/src/common/PulseBox.tsx +++ b/src/common/PulseBox.tsx @@ -1,56 +1,76 @@ import { Box, BoxProps, Theme } from "@mui/material"; import { makeStyles } from "@mui/styles"; import classNames from "classnames"; -import { forwardRef, ReactNode } from "react"; +import { forwardRef, ReactNode, useCallback, useState } from "react"; const useStyles = makeStyles((_theme: Theme) => ({ pulseWrapper: { position: 'relative', - display: 'block', // Changed to block to respect Box margins - width: 'fit-content', // Shrinks to child width - '&::after': { - content: '""', - position: 'absolute', - top: 0, - left: 0, - width: '100%', - height: '100%', - borderRadius: 'inherit', - animation: '$pulse 1.75s infinite ease-in-out', - pointerEvents: 'none', - boxSizing: 'border-box', - transition: "border-color 0.35s ease-in-out", - }, + display: 'block', + width: 'fit-content', + }, + pulseRing: { + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + borderRadius: 'inherit', + pointerEvents: 'none', + boxSizing: 'border-box', + animation: '$pulse 4.4s infinite ease-in-out', }, '@keyframes pulse': { - from: { - boxShadow: '0 0 0 2px var(--pulse-color)', - opacity: 1, - }, - to: { - boxShadow: '0 0 0 14px var(--pulse-color)', - opacity: 0, - }, + /* pulse, pause, pulse, pause - CONSISTENT: both pauses equal, both pulses equal */ + /* Pulse 1 (0-42%) */ + '0%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, + '2%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 1 }, + '40%': { boxShadow: '0 0 0 14px var(--pulse-color)', opacity: 0 }, + '42%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, + /* Pause 1 (42-50%) */ + '50%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, + /* Pulse 2 (50-92%) */ + '52%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 1 }, + '90%': { boxShadow: '0 0 0 14px var(--pulse-color)', opacity: 0 }, + '92%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, + /* Pause 2 (92-100%) - same length as Pause 1, color change at iteration */ + '100%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, }, })); interface Props extends BoxProps { color: string; + colors?: string[]; children: ReactNode; className?: string; } const PulseBox = forwardRef((props, ref) => { - const { color, children, className, ...boxProps } = props; + const { color, colors: colorsProp, children, className, ...boxProps } = props; const classes = useStyles() + const colors = colorsProp && colorsProp.length > 0 ? colorsProp : [color]; + const [colorIndex, setColorIndex] = useState(0); + const displayColor = colors[colorIndex % colors.length] ?? color; + + const onAnimationIteration = useCallback(() => { + if (colors.length > 1) { + setColorIndex((i) => (i + 1) % colors.length); + } + }, [colors.length]); + return ( + {children} ); diff --git a/src/common/StatusDust.tsx b/src/common/StatusDust.tsx index 4963269..c157501 100644 --- a/src/common/StatusDust.tsx +++ b/src/common/StatusDust.tsx @@ -57,21 +57,6 @@ export default function StatusDust(props: Props) { const colors = or(device.status.sen5x?.overlays.map(overlay => overlay.color), []); const messages = or(device.status.sen5x?.overlays.map(overlay => overlay.message), []); - const [color, setColor] = useState(colors.length > 0 ? colors[0] : ""); - const [, setColorIndex] = useState(0) - - useEffect(() => { - const interval = setInterval(() => { - setColorIndex(prevIndex => { - const newIndex = prevIndex >= colors.length - 1 ? 0 : prevIndex + 1; - setColor(colors[newIndex]); // Use the new index here - return newIndex; - }); - }, 7500); - - return () => clearInterval(interval); - }, []); - // const [currentIndex, setCurrentIndex] = useState(0); // Auto-cycle through measurements every 3 seconds @@ -142,7 +127,7 @@ export default function StatusDust(props: Props) { return ( - + overlay.message), []); } - const [color, setColor] = useState(colors.length > 0 ? colors[0] : ""); - const [, setColorIndex] = useState(0) - const gasTypes: ("o2" | "no2" | "co2" | "co" | "lel" | "h2s")[] = ["o2", "no2", "co2", "co", "lel", "h2s"] - useEffect(() => { - const interval = setInterval(() => { - setColorIndex(prevIndex => { - const newIndex = prevIndex >= colors.length - 1 ? 0 : prevIndex + 1; - setColor(colors[newIndex]); // Use the new index here - return newIndex; - }); - }, 7500); - - return () => clearInterval(interval); - }, []); - const [currentIndex, setCurrentIndex] = useState(0); // Auto-cycle through measurements every 5 seconds @@ -183,7 +168,7 @@ export default function StatusGas(props: Props) { } return ( - + { gasType === "all" && diff --git a/src/common/StatusPlenum.tsx b/src/common/StatusPlenum.tsx index 250660a..c7efef0 100644 --- a/src/common/StatusPlenum.tsx +++ b/src/common/StatusPlenum.tsx @@ -5,7 +5,6 @@ import { Device } from "models"; import PulseBox from "./PulseBox"; import RelativeTimestamp from "./RelativeTimestamp"; import { or } from "utils"; -import { useEffect, useState } from "react"; interface Props { device: Device; @@ -33,21 +32,6 @@ export default function StatusPlenum(props: Props) { const colors = or(device.status.plenum?.overlays.map(overlay => overlay.color), []); const messages = or(device.status.plenum?.overlays.map(overlay => overlay.message), []); - const [color, setColor] = useState(colors.length > 0 ? colors[0] : ""); - const [, setColorIndex] = useState(0) - - useEffect(() => { - const interval = setInterval(() => { - setColorIndex(prevIndex => { - const newIndex = prevIndex >= colors.length - 1 ? 0 : prevIndex + 1; - setColor(colors[newIndex]); // Use the new index here - return newIndex; - }); - }, 5000); - - return () => clearInterval(interval); - }, []); - const tooltip = () => { if (messages.length === 0) return null if (messages.length < 2) return ( @@ -107,7 +91,7 @@ export default function StatusPlenum(props: Props) { return ( - + diff --git a/src/common/StatusSen5x.tsx b/src/common/StatusSen5x.tsx index 533fde2..4e3d316 100644 --- a/src/common/StatusSen5x.tsx +++ b/src/common/StatusSen5x.tsx @@ -58,21 +58,6 @@ export default function StatusSen5x(props: Props) { const colors = or(device.status.sen5x?.overlays.map(overlay => overlay.color), []); const messages = or(device.status.sen5x?.overlays.map(overlay => overlay.message), []); - const [color, setColor] = useState(colors.length > 0 ? colors[0] : ""); - const [, setColorIndex] = useState(0) - - useEffect(() => { - const interval = setInterval(() => { - setColorIndex(prevIndex => { - const newIndex = prevIndex >= colors.length - 1 ? 0 : prevIndex + 1; - setColor(colors[newIndex]); // Use the new index here - return newIndex; - }); - }, 7500); - - return () => clearInterval(interval); - }, []); - const [currentIndex, setCurrentIndex] = useState(0); // Auto-cycle through measurements every 5 seconds @@ -147,7 +132,7 @@ export default function StatusSen5x(props: Props) { return ( - + Date: Mon, 16 Mar 2026 14:49:28 -0600 Subject: [PATCH 12/12] made the pulse box animation look nice by starting the pulse from behind the box that it's pulsing --- src/common/PulseBox.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/common/PulseBox.tsx b/src/common/PulseBox.tsx index eb5da3d..37ae123 100644 --- a/src/common/PulseBox.tsx +++ b/src/common/PulseBox.tsx @@ -8,6 +8,8 @@ const useStyles = makeStyles((_theme: Theme) => ({ position: 'relative', display: 'block', width: 'fit-content', + isolation: 'isolate', + overflow: 'visible', }, pulseRing: { position: 'absolute', @@ -18,23 +20,24 @@ const useStyles = makeStyles((_theme: Theme) => ({ borderRadius: 'inherit', pointerEvents: 'none', boxSizing: 'border-box', + zIndex: -1, animation: '$pulse 4.4s infinite ease-in-out', }, '@keyframes pulse': { + /* Start behind box, then expand out and fade */ /* pulse, pause, pulse, pause - CONSISTENT: both pauses equal, both pulses equal */ - /* Pulse 1 (0-42%) */ - '0%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, - '2%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 1 }, + /* Pulse 1 (0-42%) - gradual fade in to soften the start */ + '0%': { boxShadow: '0 0 0 -2px var(--pulse-color)', opacity: 1 }, '40%': { boxShadow: '0 0 0 14px var(--pulse-color)', opacity: 0 }, - '42%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, + '42%': { boxShadow: '0 0 0 -2px var(--pulse-color)', opacity: 0 }, /* Pause 1 (42-50%) */ - '50%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, + '50%': { boxShadow: '0 0 0 -2px var(--pulse-color)', opacity: 0 }, /* Pulse 2 (50-92%) */ - '52%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 1 }, + '52%': { boxShadow: '0 0 0 -2px var(--pulse-color)', opacity: 1 }, '90%': { boxShadow: '0 0 0 14px var(--pulse-color)', opacity: 0 }, - '92%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, + '92%': { boxShadow: '0 0 0 -2px var(--pulse-color)', opacity: 0 }, /* Pause 2 (92-100%) - same length as Pause 1, color change at iteration */ - '100%': { boxShadow: '0 0 0 2px var(--pulse-color)', opacity: 0 }, + '100%': { boxShadow: '0 0 0 -2px var(--pulse-color)', opacity: 0 }, }, }));