properties widget somewhat working

This commit is contained in:
Jono Targett 2026-03-16 07:22:42 +10:30
parent c33245c317
commit 566f02ede4
2 changed files with 49 additions and 27 deletions

View File

@ -13,13 +13,13 @@ import PropertiesWidget from "./components/dashboard/PropertiesWidget.vue";
<div class="layout-container"> <div class="layout-container">
<AppTopbar /> <AppTopbar />
<div class="layout-grid"> <div class="layout-grid">
<PropertiesWidget /> <PropertiesWidget device-id="example-gps-fedora" />
<StatsWidget /> <StatsWidget />
<div class="layout-grid-row"> <!-- <div class="layout-grid-row">
<SalesTrendWidget /> <SalesTrendWidget />
<RecentActivityWidget /> <RecentActivityWidget />
</div> </div>
<ProductOverviewWidget /> <ProductOverviewWidget /> -->
</div> </div>
<AppFooter /> <AppFooter />
</div> </div>

View File

@ -1,9 +1,14 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, watch, onMounted } from 'vue'
import MQTTService from '../../services/mqtt.js' import MQTTService from '../../services/mqtt.js'
const props = defineProps({
deviceId: String
})
const nodes = ref([]) const nodes = ref([])
const filters = ref({}) const filters = ref({})
const filterMode = ref({ label: 'Lenient', value: 'lenient' });
const mqtt = new MQTTService() const mqtt = new MQTTService()
@ -13,26 +18,30 @@ device -> property tree
*/ */
const devices = {} const devices = {}
/* // /*
Convert nested object -> PrimeVue TreeTable format // Convert nested object -> PrimeVue TreeTable format
*/ // */
function buildNodes() { // function buildNodes() {
nodes.value = Object.entries(devices).map(([deviceId, tree]) => ({ // nodes.value = Object.entries(devices).map(([deviceId, tree]) => ({
key: deviceId, // key: deviceId,
data: { name: deviceId }, // data: { name: deviceId },
children: buildTree(tree, deviceId) // children: buildTree(tree, deviceId)
})) // }))
} // }
function buildTree(obj, path) { let propertyTree = {}
// function buildTree(obj, path) {
function buildNodes(obj, path='') {
return Object.entries(obj).map(([key, val]) => { return Object.entries(obj).map(([key, val]) => {
const fullKey = `${path}/${key}` // const fullKey = `${path}/${key}`
const fullKey = path ? `${path}/${key}` : key
if (val && typeof val === 'object' && !('value' in val)) { if (val && typeof val === 'object' && !('value' in val)) {
return { return {
key: fullKey, key: fullKey,
data: { name: key }, data: { name: key },
children: buildTree(val, fullKey) children: buildNodes(val, fullKey)
} }
} }
@ -49,13 +58,11 @@ function buildTree(obj, path) {
/* /*
Insert MQTT property into nested tree Insert MQTT property into nested tree
*/ */
function insertProperty(deviceId, propertyPath, value) { function insertProperty(pathParts, value) {
if (!devices[deviceId]) devices[deviceId] = {} let node = propertyTree
let node = devices[deviceId] pathParts.forEach((part, i) => {
if (i === pathParts.length - 1) {
propertyPath.forEach((part, i) => {
if (i === propertyPath.length - 1) {
node[part] = { value } node[part] = { value }
} else { } else {
if (!node[part]) node[part] = {} if (!node[part]) node[part] = {}
@ -63,19 +70,25 @@ function insertProperty(deviceId, propertyPath, value) {
} }
}) })
buildNodes() nodes.value = buildNodes(propertyTree)
} }
watch(() => props.deviceId, () => {
propertyTree = {}
nodes.value = []
})
onMounted(() => { onMounted(() => {
mqtt.subscribe('device/+/property/#', (payload, topic) => { mqtt.subscribe('device/+/property/#', (payload, topic) => {
const parts = topic.split('/') const parts = topic.split('/')
const deviceId = parts[1] const device = parts[1]
const propertyPath = parts.slice(3) const propertyPath = parts.slice(3)
insertProperty(deviceId, propertyPath, payload) if (device !== props.deviceId) return
insertProperty(propertyPath, payload)
}) })
}) })
@ -84,7 +97,16 @@ onMounted(() => {
<template> <template>
<div class="card"> <div class="card">
<TreeTable :value="nodes" :filters="filters" filterMode="lenient"> <TreeTable :value="nodes" :filters="filters" :filterMode="filterMode.value">
<template #header>
<div class="flex products-header">
<span class="products-title">Properties</span>
<IconField class="search-field">
<InputIcon class="pi pi-search" />
<InputText v-model="filters['global']" placeholder="Filter by..." />
</IconField>
</div>
</template>
<template #empty> No properties available.</template> <template #empty> No properties available.</template>
<Column field="name" header="Name" expander style="min-width: 12rem"> <Column field="name" header="Name" expander style="min-width: 12rem">
<template #filter> <template #filter>