From 3803756be9d99d81fa4fda98d19015efd6db0b91 Mon Sep 17 00:00:00 2001 From: Andrew Berry Date: Sat, 14 Dec 2024 14:11:49 -0500 Subject: [PATCH] feat(ui): show source routes on device pages --- src/components/device-page/info.tsx | 44 ++++++++++++++++++++++++++--- src/i18n/locales/en.json | 4 ++- src/types.ts | 1 + 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/components/device-page/info.tsx b/src/components/device-page/info.tsx index 4df5b666f..d19e0cf20 100644 --- a/src/components/device-page/info.tsx +++ b/src/components/device-page/info.tsx @@ -6,7 +6,7 @@ import DeviceControlGroup from '../device-control/DeviceControlGroup'; import cx from 'classnames'; import style from './style.module.css'; import { connect } from 'unistore/react'; -import { AvailabilityState, GlobalState } from '../../store'; +import { AvailabilityState, Devices, GlobalState } from '../../store'; import get from 'lodash/get'; import { DeviceImage } from '../device-image/DeviceImage'; import { ModelLink, VendorLink } from '../vendor-links/vendor-links'; @@ -23,7 +23,7 @@ import { DeviceControlUpdateDesc } from '../device-control/DeviceControlUpdateDe type DeviceInfoProps = { device: Device; }; -type PropsFromStore = Pick; +type PropsFromStore = Pick; // [Flower sensor](https://modkam.ru/?p=1700) const markdownLinkRegex = /\[(.*?)]\((.*?)\)/; @@ -31,13 +31,14 @@ const markdownLinkRegex = /\[(.*?)]\((.*?)\)/; // eslint-disable-next-line react/prefer-stateless-function export class DeviceInfo extends Component< Pick & + Devices & DeviceInfoProps & PropsFromStore & WithTranslation<'zigbee'>, unknown > { render(): JSX.Element { - const { device, deviceStates, bridgeInfo, availability, t } = this.props; + const { device, deviceStates, bridgeInfo, availability, t, devices } = this.props; const { configureDevice, renameDevice, removeDevice, setDeviceDescription, interviewDevice } = this.props; const homeassistantEnabled = !!bridgeInfo.config?.homeassistant; const deviceState: DeviceState = deviceStates[device.friendly_name] ?? ({} as DeviceState); @@ -177,6 +178,40 @@ export class DeviceInfo extends Component< ), }, + { + key: 'source_route', + translationKey: 'source_route', + render: ( + device: Device, + deviceStatus: DeviceState, + bridgeInfo: BridgeInfo, + availability: AvailabilityState, + t: TFunction, + devices: Devices, + ) => { + return ( +
+ {deviceStatus.source_route instanceof Array && deviceStatus.source_route.length > 0 + ? deviceStatus.source_route + .map((addr: number) => { + const device = Object.values(devices).find((d) => d.network_address === addr); + if (device) { + return ( + {device.friendly_name} + ); + } + return {toHex(addr, 4)}; + }) + .reduce((prev, curr) => ( + <> + {prev} → {curr} + + )) + : t('Direct to coordinator')} +
+ ); + }, + }, { key: 'date_code', translationKey: 'firmware_build_date', @@ -250,6 +285,7 @@ export class DeviceInfo extends Component< bridgeInfo, availability[device.friendly_name] ?? 'offline', t, + devices, ) ) : (
{get(device, prop.key)}
@@ -268,7 +304,7 @@ export class DeviceInfo extends Component< } } -const mappedProps = ['deviceStates', 'bridgeInfo', 'availability']; +const mappedProps = ['deviceStates', 'bridgeInfo', 'availability', 'devices']; const ConnectedDeviceInfoPage = withTranslation('zigbee')( connect(mappedProps, actions)(DeviceInfo), diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index fe84363a3..5797cf04b 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -2699,7 +2699,9 @@ "command": "Command", "payload": "Payload", "save_description": "Save description", - "update_description": "Update description" + "update_description": "Update description", + "source_route": "Source route", + "direct_to_coordinator": "Direct to coordinator" }, "scene": { "manage_scenes_header": "Manage scenes", diff --git a/src/types.ts b/src/types.ts index 3abca493b..b6e656451 100644 --- a/src/types.ts +++ b/src/types.ts @@ -271,6 +271,7 @@ export interface Device extends WithFriendlyName, WithDescription { ieee_address: IEEEEAddress; type: DeviceType; network_address: number; + source_route: number[]; power_source?: PowerSource; model_id: string; manufacturer: string;