Merge branch 'timestamped_status' into staging_environment

This commit is contained in:
Carter 2025-10-15 12:41:01 -06:00
commit 63e4a12cff
7 changed files with 363 additions and 121 deletions

View file

@ -114,6 +114,29 @@ export default function StatusDust(props: Props) {
)
}
function compareTimestamps(timestamp1: string, timestamp2: string): number {
const date1 = new Date(timestamp1);
const date2 = new Date(timestamp2);
// Check if dates are valid
if (isNaN(date1.getTime()) || isNaN(date2.getTime())) {
throw new Error("Invalid RFC3339 timestamp format");
}
// Compare using getTime() for millisecond precision
return date1.getTime() - date2.getTime();
}
if (device.status.sen5x?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status.sen5x?.timestamp, oneDayAgo.toISOString()) < 0) {
return null
}
} else {
return null
}
return (
<Tooltip title={tooltip()}>
<PulseBox color={color} className={classes.box} >

View file

@ -152,9 +152,31 @@ export default function StatusGas(props: Props) {
)
}
function compareTimestamps(timestamp1: string, timestamp2: string): number {
const date1 = new Date(timestamp1);
const date2 = new Date(timestamp2);
// Check if dates are valid
if (isNaN(date1.getTime()) || isNaN(date2.getTime())) {
throw new Error("Invalid RFC3339 timestamp format");
}
// Compare using getTime() for millisecond precision
return date1.getTime() - date2.getTime();
}
const gasDisplay = () => {
const gas = gasType === "all" ? gasTypes[currentIndex] : gasType
// if (gasType !== "all") {
if (device.status[gas]?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status[gas]?.timestamp, oneDayAgo.toISOString()) < 0) {
return null
}
} else {
return null
}
return (
<Tooltip title={tooltip()}>
<PulseBox color={color} className={gasType === "all" ? classes.boxTall : classes.box}>

View file

@ -80,6 +80,29 @@ export default function StatusPlenum(props: Props) {
)
}
function compareTimestamps(timestamp1: string, timestamp2: string): number {
const date1 = new Date(timestamp1);
const date2 = new Date(timestamp2);
// Check if dates are valid
if (isNaN(date1.getTime()) || isNaN(date2.getTime())) {
throw new Error("Invalid RFC3339 timestamp format");
}
// Compare using getTime() for millisecond precision
return date1.getTime() - date2.getTime();
}
if (device.status.plenum?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status.plenum?.timestamp, oneDayAgo.toISOString()) < 0) {
return null
}
} else {
return null
}
return (
<Tooltip title={tooltip()}>
<PulseBox color={color} className={classes.box} >

View file

@ -120,6 +120,29 @@ export default function StatusSen5x(props: Props) {
)
}
function compareTimestamps(timestamp1: string, timestamp2: string): number {
const date1 = new Date(timestamp1);
const date2 = new Date(timestamp2);
// Check if dates are valid
if (isNaN(date1.getTime()) || isNaN(date2.getTime())) {
throw new Error("Invalid RFC3339 timestamp format");
}
// Compare using getTime() for millisecond precision
return date1.getTime() - date2.getTime();
}
if (device.status.sen5x?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status.sen5x?.timestamp, oneDayAgo.toISOString()) < 0) {
return null
}
} else {
return null
}
return (
<Tooltip title={tooltip()}>
<PulseBox color={color} className={classes.box} >

View file

@ -208,6 +208,118 @@ export default function Devices() {
})
}, [tab])
function compareTimestamps(timestamp1: string, timestamp2: string): number {
const date1 = new Date(timestamp1);
const date2 = new Date(timestamp2);
// Check if dates are valid
if (isNaN(date1.getTime()) || isNaN(date2.getTime())) {
throw new Error("Invalid RFC3339 timestamp format");
}
// Compare using getTime() for millisecond precision
return date1.getTime() - date2.getTime();
}
const doesDeviceHavePlenum = (device: pond.Device) => {
if (device.status?.plenum?.temperature && device.status?.plenum?.timestamp) {
if (device.status.plenum?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status.plenum?.timestamp, oneDayAgo.toISOString()) < 0) {
return true
}
} else {
return false
}
}
return false
}
const doesDeviceHaveSen5x = (device: pond.Device) => {
if (device.status?.sen5x?.temperature && device.status?.sen5x?.timestamp) {
if (device.status.sen5x?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status.sen5x?.timestamp, oneDayAgo.toISOString()) < 0) {
return true
}
} else {
return false
}
}
return false
}
// if (device.status?.o2) setHasO2(true)
// if (device.status?.co) setHasCo(true)
// if (device.status?.co2) setHasCo2(true)
// if (device.status?.no2) setHasNo2(true)
const doesDeviceHaveO2 = (device: pond.Device) => {
if (device.status?.o2?.ppm && device.status?.o2?.timestamp) {
if (device.status.sen5x?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status.o2?.timestamp, oneDayAgo.toISOString()) < 0) {
return true
}
} else {
return false
}
}
return false
}
const doesDeviceHaveCo = (device: pond.Device) => {
if (device.status?.co?.ppm && device.status?.co?.timestamp) {
if (device.status.co?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status.co?.timestamp, oneDayAgo.toISOString()) < 0) {
return true
}
} else {
return false
}
}
return false
}
const doesDeviceHaveCo2 = (device: pond.Device) => {
if (device.status?.co2?.ppm && device.status?.co2?.timestamp) {
if (device.status.co2?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status.co2?.timestamp, oneDayAgo.toISOString()) < 0) {
return true
}
} else {
return false
}
}
return false
}
const doesDeviceHaveNo2 = (device: pond.Device) => {
if (device.status?.no2?.ppm && device.status?.no2?.timestamp) {
if (device.status.no2?.timestamp) {
const now = new Date();
const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
if (compareTimestamps(device.status.no2?.timestamp, oneDayAgo.toISOString()) < 0) {
return true
}
} else {
return false
}
}
return false
}
useEffect(() => {
console.log(hasPlenums)
}, [hasPlenums])
const openProvisionDialog = () => {
setIsProvisionDialogOpen(true);
};
@ -319,12 +431,13 @@ export default function Devices() {
).then(resp => {
let newDevices: Device[] = []
resp.data.devices.forEach(device => {
if (device.status?.plenum?.temperature) setHasPlenums(true)
if (device.status?.sen5x?.temperature) setHasSen5x(true)
if (device.status?.o2) setHasO2(true)
if (device.status?.co) setHasCo(true)
if (device.status?.co2) setHasCo2(true)
if (device.status?.no2) setHasNo2(true)
setHasPlenums(doesDeviceHavePlenum(device))
setHasPlenums(true)
setHasSen5x(doesDeviceHaveSen5x(device))
setHasO2(doesDeviceHaveO2(device))
setHasCo(doesDeviceHaveCo(device))
setHasCo2(doesDeviceHaveCo2(device))
setHasNo2(doesDeviceHaveNo2(device))
newDevices.push(Device.create(device))
})
setDevices(newDevices)
@ -809,12 +922,12 @@ export default function Devices() {
).then(resp => {
let newDevices: Device[] = []
resp.data.devices.forEach(device => {
if (device.status?.plenum?.temperature) setHasPlenums(true)
if (device.status?.sen5x?.temperature) setHasSen5x(true)
if (device.status?.o2) setHasO2(true)
if (device.status?.co) setHasCo(true)
if (device.status?.co2) setHasCo2(true)
if (device.status?.no2) setHasNo2(true)
setHasPlenums(doesDeviceHavePlenum(device))
setHasSen5x(doesDeviceHaveSen5x(device))
setHasO2(doesDeviceHaveO2(device))
setHasCo(doesDeviceHaveCo(device))
setHasCo2(doesDeviceHaveCo2(device))
setHasNo2(doesDeviceHaveNo2(device))
newDevices.push(Device.create(device))
})
setDevices(currentRows.concat(newDevices))

View file

@ -119,7 +119,7 @@ export default function TeamProvider(props: PropsWithChildren<Props>) {
prefixSearch?: string,
) => {
//let asText = team ? "&as=" + team.key() : "";
const view = otherTeam ? otherTeam : as
const view = otherTeam ? otherTeam : (as.length > 0 ? as : undefined)
let url = pondURL(
"/teams" +
"?limit=" +