Readded the flash effect on property change

This commit is contained in:
Jono Targett 2026-03-17 20:57:51 +10:30
parent 6f075fd49a
commit a3c9d053aa
4 changed files with 45 additions and 28 deletions

3
console/.gitignore vendored
View File

@ -32,3 +32,6 @@ dist-ssr
.env .env
.env.local .env.local
.env.*.local .env.*.local
.vite

View File

@ -18,7 +18,7 @@ import CommandsWidget from "./components/dashboard/CommandsWidget.vue";
<PropertiesWidget device-id="example-gps-fedora" /> <PropertiesWidget device-id="example-gps-fedora" />
<CommandsWidget device-id="example-gps-fedora" /> <CommandsWidget device-id="example-gps-fedora" />
</div> </div>
<StatsWidget /> <!-- <StatsWidget /> -->
<!-- <div class="layout-grid-row"> <!-- <div class="layout-grid-row">
<SalesTrendWidget /> <SalesTrendWidget />
<RecentActivityWidget /> <RecentActivityWidget />

View File

@ -102,7 +102,7 @@ const jsonFormsConfig = {
header="Command Schema" header="Command Schema"
:modal="true" :modal="true"
:closable="true" :closable="true"
:style="{width: '400px'}" :style="{width: '700px'}"
> >
<pre>{{ schemaDialog.content }}</pre> <pre>{{ schemaDialog.content }}</pre>
</Dialog> </Dialog>
@ -185,8 +185,7 @@ const jsonFormsConfig = {
} }
.command-desc { .command-desc {
color: #666; font-size: 0.8rem;
font-size: 0.9rem;
} }

View File

@ -12,29 +12,12 @@ const filterMode = ref({ label: 'Lenient', value: 'lenient' });
const mqtt = new MQTTService() const mqtt = new MQTTService()
/* const changedKeys = ref({})
Internal storage
device -> property tree
*/
const devices = {}
// /*
// Convert nested object -> PrimeVue TreeTable format
// */
// function buildNodes() {
// nodes.value = Object.entries(devices).map(([deviceId, tree]) => ({
// key: deviceId,
// data: { name: deviceId },
// children: buildTree(tree, deviceId)
// }))
// }
let propertyTree = {} let propertyTree = {}
// function buildTree(obj, path) {
function buildNodes(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 ? `${path}/${key}` : key const fullKey = path ? `${path}/${key}` : key
if (val && typeof val === 'object' && !('value' in val)) { if (val && typeof val === 'object' && !('value' in val)) {
@ -55,12 +38,11 @@ function buildNodes(obj, path='') {
}) })
} }
/*
Insert MQTT property into nested tree
*/
function insertProperty(pathParts, value) { function insertProperty(pathParts, value) {
let node = propertyTree let node = propertyTree
const fullKey = pathParts.join('/')
pathParts.forEach((part, i) => { pathParts.forEach((part, i) => {
if (i === pathParts.length - 1) { if (i === pathParts.length - 1) {
node[part] = { value } node[part] = { value }
@ -70,16 +52,26 @@ function insertProperty(pathParts, value) {
} }
}) })
// 🔥 always flash on update
changedKeys.value[fullKey] = true
setTimeout(() => {
delete changedKeys.value[fullKey]
}, 600)
nodes.value = buildNodes(propertyTree) nodes.value = buildNodes(propertyTree)
} }
function rowClass(node) {
return changedKeys.value.has(node.key) ? 'flash-row' : ''
}
watch(() => props.deviceId, () => { watch(() => props.deviceId, () => {
propertyTree = {} propertyTree = {}
nodes.value = [] nodes.value = []
}) })
onMounted(() => { onMounted(() => {
mqtt.subscribe('device/+/property/#', (payload, topic) => { mqtt.subscribe('device/+/property/#', (payload, topic) => {
const parts = topic.split('/') const parts = topic.split('/')
@ -117,7 +109,30 @@ onMounted(() => {
<template #filter> <template #filter>
<InputText v-model="filters['value']" type="text" placeholder="Filter by value" /> <InputText v-model="filters['value']" type="text" placeholder="Filter by value" />
</template> </template>
<template #body="{ node }">
<span :class="{ 'flash-cell': changedKeys[node.key] }">
{{ node.data.value }}
</span>
</template>
</Column> </Column>
</TreeTable> </TreeTable>
</div> </div>
</template> </template>
<style scoped>
.flash-cell {
animation: flash-bg 0.6s ease;
border-radius: 6px;
}
@keyframes flash-bg {
0% {
background-color: var(--p-primary-color);
color: var(--p-primary-color-text);
}
100% {
background-color: transparent;
color: inherit;
}
}
</style>