Added accordion panels for commands

This commit is contained in:
Jono Targett 2026-03-16 23:27:27 +10:30
parent 97870827e7
commit 300b1de7de
2 changed files with 75 additions and 31 deletions

View File

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

View File

@ -2,6 +2,11 @@
import { ref, reactive, watch, onMounted } from 'vue' import { ref, reactive, watch, onMounted } from 'vue'
import MQTTService from '../../services/mqtt.js' import MQTTService from '../../services/mqtt.js'
import Accordion from 'primevue/accordion';
import AccordionPanel from 'primevue/accordionpanel';
import AccordionHeader from 'primevue/accordionheader';
import AccordionContent from 'primevue/accordioncontent';
const props = defineProps({ const props = defineProps({
deviceId: String deviceId: String
}) })
@ -21,11 +26,12 @@ function rebuildList() {
function updateCommand(device, name, field, value) { function updateCommand(device, name, field, value) {
if (!commandMap[name]) { if (!commandMap[name]) {
commandMap[name] = { commandMap[name] = {
name, name,
description: '', description: '',
input: '' schema: '',
} input: ''
}
} }
commandMap[name][field] = value commandMap[name][field] = value
@ -36,7 +42,7 @@ function sendCommand(cmd) {
const topic = `device/${props.deviceId}/command/${cmd.name}` const topic = `device/${props.deviceId}/command/${cmd.name}`
mqtt2.publish(topic, JSON.stringify(cmd.input)) mqtt2.publish(topic, cmd.input || '{}')
} }
watch(() => props.deviceId, () => { watch(() => props.deviceId, () => {
@ -61,6 +67,9 @@ onMounted(() => {
if (field === 'description') { if (field === 'description') {
updateCommand(device, command, 'description', payload) updateCommand(device, command, 'description', payload)
} }
if (field === 'schema') {
updateCommand(device, command, 'schema', payload)
}
}) })
@ -81,34 +90,67 @@ onMounted(() => {
</template> </template>
<template #empty> No commands available.</template> <template #empty> No commands available.</template>
<template #list="slotProps"> <template #list="slotProps">
<div <Accordion>
v-for="cmd in slotProps.items"
:key="cmd.name"
class="p-card p-mb-3"
style="padding:1rem"
>
<h3>{{ cmd.name }}</h3> <AccordionPanel
v-for="cmd in slotProps.items"
:key="cmd.name"
:value="cmd.name"
>
<p>{{ cmd.description }}</p> <AccordionHeader>
<div class="command-header">
<span class="command-name">{{ cmd.name }}</span>
<span class="command-desc">{{ cmd.description }}</span>
</div>
</AccordionHeader>
<AccordionContent>
<div class="command-body">
<Textarea <Textarea
v-model="cmd.input" v-model="cmd.input"
rows="3" rows="4"
style="width:100%" style="width:100%"
placeholder="JSON arguments..." :placeholder="cmd.schema || 'JSON arguments...'"
/> />
<Button <Button
label="Send Command" label="Send Command"
icon="pi pi-send" icon="pi pi-send"
class="p-mt-2" class="p-mt-2"
@click="sendCommand(cmd)" @click="sendCommand(cmd)"
/> />
</div> </div>
</AccordionContent>
</template> </AccordionPanel>
</Accordion>
</template>
</DataView> </DataView>
</div> </div>
</template> </template>
<style scoped>
.command-header {
display: flex;
gap: 10px;
align-items: center;
}
.command-name {
font-weight: 600;
}
.command-desc {
color: #666;
font-size: 0.9rem;
}
.command-body {
padding-top: 0.5rem;
}
</style>