frontend/src/pbHelpers/Device.ts
2024-12-13 13:27:16 -06:00

149 lines
5.5 KiB
TypeScript

import { Device, Tag } from "models";
import moment from "moment";
import { filterByTags } from "pbHelpers/Tag";
import { GetDeviceProductLabel } from "products/DeviceProduct";
import { pond } from "protobuf-ts/pond";
import { quack } from "protobuf-ts/quack";
import { capitalize } from "utils/strings";
import { getDevicePlatformLabel } from "./DevicePlatform";
import { filterByDeviceState } from "./DeviceState";
import { filterByPower } from "./Power";
import { getUpgradeChannelLabel } from "./UpgradeChannel";
//complex filter algorithm for searching a list of devices
export function filterDevices(searchValue: string, devices: Device[], tags: Tag[]): Device[] {
return devices.filter(device =>
filterDevice(searchValue.toLowerCase(), device, deviceTags(device, tags))
);
}
//helper function for filterDevices
export function filterDevice(searchValue: string, device: Device, tags: Tag[]): boolean {
const idMatch: boolean = filterByDeviceID(searchValue, device.settings.deviceId.toString());
const nameMatch: boolean = filterByDeviceName(searchValue, device.name());
const tagsMatch: boolean = filterByTags(searchValue, tags);
const deviceStateMatch: boolean = filterByDeviceState(searchValue, device.status.state);
const powerMatch: boolean = filterByPower(
searchValue,
device.status.power ? pond.DevicePower.create(device.status.power) : undefined
);
const lastActiveMatch: boolean = filterByLastActive(searchValue, device.status.lastActive);
return idMatch || nameMatch || tagsMatch || powerMatch || deviceStateMatch || lastActiveMatch;
}
export function filterByDeviceID(searchValue: string, deviceIDString: string): boolean {
return searchValue.replace("id:", "").trim() === deviceIDString;
}
export function filterByDeviceName(searchValue: string, deviceName: string): boolean {
return (
deviceName.toLowerCase().indexOf(
searchValue
.replace("name:", "")
.trim()
.toLowerCase()
) > -1
);
}
export function filterByDeviceDescription(searchValue: string, deviceDescription: string): boolean {
return (
deviceDescription.toLowerCase().indexOf(
searchValue
.replace("description:", "")
.trim()
.toLowerCase()
) > -1
);
}
export function filterByLastActive(searchValue: string, lastActive: string): boolean {
return (
moment(lastActive)
.fromNow()
.indexOf(searchValue.replace("last active:", "")) > -1
);
}
export function deviceTags(device: Device, tags: Tag[]): Tag[] {
return tags.filter(tag => device.status.tagKeys.some(key => key === tag.settings.key));
}
const keyTranslator = new Map<keyof pond.DeviceSettings, string>([
["deviceId", "Device ID"],
["name", "Name"],
["description", "Description"],
["sleepType", "Sleep Type"],
["sleepDurationS", "Sleep Duration"],
["sleepDelayMs", "Sleep Delay"],
["pondCheckPeriodS", "Check Period"],
["removed", "Removed"],
["platform", "Platform"],
["wakePin", "Wake Pin"],
["platform", "Platform"],
["automaticallyUpgrade", "Upgrades Automatically"],
["product", "Product"],
["upgradeChannel", "Upgrade Channel"],
["latitude", "Latitude"],
["longitude", "Longitude"],
["theme", "Marker Theme"],
["extensionComponents", "Extension Components"],
["mutations", "Device Mutations"]
]);
// Keys will be stringified by default if not found in the keyTranslator
export function TranslateKey(key: keyof pond.DeviceSettings): string {
let translatedKey = keyTranslator.get(key);
return translatedKey ? translatedKey : capitalize(key.toString());
}
const valueTranslator = new Map<keyof pond.DeviceSettings, (device: pond.DeviceSettings) => string>(
[
["name", device => device.name],
["description", device => device.description],
[
"sleepType",
device => {
switch (device.sleepType) {
case quack.SleepType.SLEEP_TYPE_DEEP:
return "Deep Sleep";
case quack.SleepType.SLEEP_TYPE_HIBERNATE:
return "Hibernate";
case quack.SleepType.SLEEP_TYPE_NAP:
return "Nap";
default:
return "None";
}
}
],
["sleepDurationS", device => device.sleepDurationS.toString() + "s"],
["sleepDelayMs", device => (device.sleepDelayMs / 1000).toString() + "s"],
["pondCheckPeriodS", device => device.pondCheckPeriodS.toString() + "s"],
["platform", device => getDevicePlatformLabel(device.platform)],
["product", device => GetDeviceProductLabel(device.product)],
["upgradeChannel", device => getUpgradeChannelLabel(device.upgradeChannel)],
["automaticallyUpgrade", device => device.automaticallyUpgrade.toString()],
["latitude", device => device.latitude.toString()],
["longitude", device => device.longitude.toString()],
["theme", device => "Colour: " + device.theme?.color + "Size: " + device.theme?.height],
["extensionComponents", device => device.extensionComponents.toString()],
["mutations", device => device.mutations.toString()]
]
);
// Values will be stringified by default if its key is not found in the valueTranslator
export function TranslateValue(key: keyof pond.DeviceSettings, device: pond.DeviceSettings) {
//console.log(device)
//console.log(key)
let translatorFunc = valueTranslator.get(key);
let dKey = device[key];
return translatorFunc ? translatorFunc(device) : capitalize(dKey ? dKey.toString() : "");
}
//checks the user's path to determine if they are on a shared url
export function isShareableLink(rawDeviceID: string): boolean {
if (!rawDeviceID) {
return false;
}
return isNaN(Number(rawDeviceID));
}