allow panels to hold commands
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import type { OptionalDynamicComponentData } from '@/composables/dynamic.ts';
|
||||
import { computed, defineAsyncComponent } from 'vue';
|
||||
import {
|
||||
AnyTypes,
|
||||
type CommandParameterData,
|
||||
type DynamicDataType,
|
||||
type OptionalDynamicComponentData,
|
||||
} from '@/composables/dynamic.ts';
|
||||
import { computed, defineAsyncComponent, inject, type Ref, ref } from 'vue';
|
||||
import CommandParameterListConfigurator from '@/components/CommandParameterListConfigurator.vue';
|
||||
|
||||
const TelemetryValue = defineAsyncComponent(
|
||||
() => import('@/components/TelemetryValue.vue'),
|
||||
@@ -8,6 +14,9 @@ const TelemetryValue = defineAsyncComponent(
|
||||
const GridLayout = defineAsyncComponent(
|
||||
() => import('@/components/layout/GridLayout.vue'),
|
||||
);
|
||||
const CommandInput = defineAsyncComponent(
|
||||
() => import('@/components/CommandInput.vue'),
|
||||
);
|
||||
|
||||
const model = defineModel<OptionalDynamicComponentData>('data', {
|
||||
required: true,
|
||||
@@ -19,13 +28,26 @@ const props = defineProps<{
|
||||
editable: boolean;
|
||||
}>();
|
||||
|
||||
const busy = ref(false);
|
||||
|
||||
// Provide a fallback option
|
||||
const inputs = inject<Ref<{ [id: string]: DynamicDataType }>>(
|
||||
'inputs',
|
||||
ref({}),
|
||||
);
|
||||
|
||||
const thisSymbol = Symbol();
|
||||
|
||||
const isSelected = computed(() => {
|
||||
return selection.value == thisSymbol && props.editable;
|
||||
});
|
||||
|
||||
function selectThis() {
|
||||
function selectThis(e: Event) {
|
||||
if (props.editable) {
|
||||
// Only do this when we are editable
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
selection.value = thisSymbol;
|
||||
}
|
||||
|
||||
@@ -100,6 +122,54 @@ function deleteColumn() {
|
||||
model.value = grid;
|
||||
}
|
||||
}
|
||||
|
||||
function makeInput() {
|
||||
model.value = {
|
||||
type: 'input',
|
||||
id: [...Array(32)]
|
||||
.map(() => Math.floor(Math.random() * 16).toString(16))
|
||||
.join(''),
|
||||
data_type: 'Float32',
|
||||
};
|
||||
}
|
||||
|
||||
function makeCommandButton() {
|
||||
model.value = {
|
||||
type: 'command_button',
|
||||
text: 'Button Text',
|
||||
command_name: '',
|
||||
parameters: {},
|
||||
};
|
||||
}
|
||||
|
||||
async function sendCommand(command: {
|
||||
command_name: string;
|
||||
parameters: { [key: string]: CommandParameterData };
|
||||
}) {
|
||||
busy.value = true;
|
||||
|
||||
const params: { [key: string]: DynamicDataType } = {};
|
||||
for (const param_name in command.parameters) {
|
||||
const parameter = command.parameters[param_name];
|
||||
switch (parameter.type) {
|
||||
case 'constant':
|
||||
params[param_name] = parameter.value;
|
||||
break;
|
||||
case 'input':
|
||||
params[param_name] = inputs.value[parameter.id];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await fetch(`/api/cmd/${command.command_name}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
busy.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -123,20 +193,30 @@ function deleteColumn() {
|
||||
<button v-if="model.type != 'grid'" @click.stop.prevent="makeGrid">
|
||||
Make Grid
|
||||
</button>
|
||||
<button
|
||||
v-if="model.type != 'input'"
|
||||
@click.stop.prevent="makeInput"
|
||||
>
|
||||
Make Input
|
||||
</button>
|
||||
<button
|
||||
v-if="model.type != 'command_button'"
|
||||
@click.stop.prevent="makeCommandButton"
|
||||
>
|
||||
Make Command Button
|
||||
</button>
|
||||
</div>
|
||||
</Teleport>
|
||||
<template v-if="model.type == 'none'">
|
||||
<!-- Intentionally Left Empty -->
|
||||
<span
|
||||
v-if="editable"
|
||||
:class="`${editable ? 'editable' : ''} ${isSelected ? 'selected' : ''}`"
|
||||
@click.stop.prevent="selectThis"
|
||||
@click="selectThis"
|
||||
></span>
|
||||
</template>
|
||||
<template v-else-if="model.type == 'text'">
|
||||
<span
|
||||
:class="`${model.justify_right ? 'justify-right' : ''} ${editable ? 'editable' : ''} ${isSelected ? 'selected' : ''}`"
|
||||
@click.stop.prevent="selectThis"
|
||||
@click="selectThis"
|
||||
>
|
||||
{{ model.text }}
|
||||
</span>
|
||||
@@ -155,7 +235,7 @@ function deleteColumn() {
|
||||
<span
|
||||
v-if="editable"
|
||||
:class="`${editable ? 'editable' : ''} ${isSelected ? 'selected' : ''}`"
|
||||
@click.stop.prevent="selectThis"
|
||||
@click="selectThis"
|
||||
>
|
||||
{{ '{' }} {{ model.data }} {{ '}' }}
|
||||
</span>
|
||||
@@ -163,7 +243,7 @@ function deleteColumn() {
|
||||
v-else
|
||||
:class="`${editable ? 'editable' : ''} ${isSelected ? 'selected' : ''}`"
|
||||
:data="model.data"
|
||||
@click.stop.prevent="selectThis"
|
||||
@click="selectThis"
|
||||
></TelemetryValue>
|
||||
<Teleport v-if="isSelected" to="#inspector">
|
||||
<label>Telemetry Item: </label>
|
||||
@@ -175,7 +255,7 @@ function deleteColumn() {
|
||||
:class="`${editable ? 'editable' : ''} ${isSelected ? 'selected' : ''}`"
|
||||
:cols="model.columns"
|
||||
:equal_col_width="model.equal_width"
|
||||
@click.stop.prevent="selectThis"
|
||||
@click="selectThis"
|
||||
>
|
||||
<template v-for="x in model.cells.length" :key="x">
|
||||
<template v-for="y in model.columns" :key="y">
|
||||
@@ -210,6 +290,60 @@ function deleteColumn() {
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
<template v-else-if="model.type == 'input'">
|
||||
<span
|
||||
v-if="editable"
|
||||
:class="`${editable ? 'editable' : ''} ${isSelected ? 'selected' : ''}`"
|
||||
@click="selectThis"
|
||||
>
|
||||
{{ '[' }} {{ model.id }} {{ ']' }}
|
||||
</span>
|
||||
<CommandInput
|
||||
v-else
|
||||
:type="model.data_type"
|
||||
v-model="inputs[model.id]"
|
||||
></CommandInput>
|
||||
<Teleport v-if="isSelected" to="#inspector">
|
||||
<div class="row">
|
||||
<label>Input ID: </label>
|
||||
<input v-model="model.id" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Data Type: </label>
|
||||
<select v-model="model.data_type">
|
||||
<option v-for="type in AnyTypes" :key="type" :value="type">
|
||||
{{ type }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
<template v-else-if="model.type == 'command_button'">
|
||||
<button
|
||||
:disabled="busy"
|
||||
:class="`${editable ? 'editable' : ''} ${isSelected ? 'selected' : ''}`"
|
||||
@click.stop.prevent="
|
||||
(e) => (editable ? selectThis(e) : sendCommand(model as any))
|
||||
"
|
||||
>
|
||||
{{ model.text }}
|
||||
</button>
|
||||
<Teleport v-if="isSelected" to="#inspector">
|
||||
<div class="row">
|
||||
<label>Button Text: </label>
|
||||
<input v-model="model.text" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Command: </label>
|
||||
<input v-model="model.command_name" />
|
||||
</div>
|
||||
<CommandParameterListConfigurator
|
||||
:key="model.command_name"
|
||||
:command_name="model.command_name"
|
||||
v-model="model.parameters"
|
||||
></CommandParameterListConfigurator>
|
||||
</Teleport>
|
||||
</template>
|
||||
<template v-else> ERROR: Unknown data: {{ model }} </template>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user