Merge branch 'dropdown-gui' into 'v3'
Optional options in UI property control become dropdown See merge request openflexure/openflexure-microscope-server!477
This commit is contained in:
commit
a6b95f0948
4 changed files with 55 additions and 7 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
"""Functionality for communicating the required user interface for a thing."""
|
"""Functionality for communicating the required user interface for a thing."""
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any, Optional
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
@ -90,6 +90,13 @@ class PropertyControl(BaseModel):
|
||||||
read_back_delay: int = 1000
|
read_back_delay: int = 1000
|
||||||
"""The delay in ms before reading back the property."""
|
"""The delay in ms before reading back the property."""
|
||||||
|
|
||||||
|
options: Optional[dict[str, str | int | float | bool]] = None
|
||||||
|
"""A mapping of UI display name to value, used for creating a dropdown.
|
||||||
|
|
||||||
|
These options aren't validated here in any way. Any invalid values will be rejected
|
||||||
|
when selected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def property_control_for(
|
def property_control_for(
|
||||||
thing: lt.Thing, property_name: str, **kwargs: Any
|
thing: lt.Thing, property_name: str, **kwargs: Any
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<label v-if="dataType == 'number'" class="uk-form-label"
|
<label v-if="useDropdown" class="uk-form-label">
|
||||||
|
{{ label }}
|
||||||
|
<div class="input-and-buttons-container">
|
||||||
|
<select
|
||||||
|
v-model="internalValue"
|
||||||
|
class="uk-form-small numeric-setting-line-input dropdown"
|
||||||
|
@change="sendValue"
|
||||||
|
>
|
||||||
|
<option v-for="(value, display) in options" :key="value" :value="value">
|
||||||
|
{{ display }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<sync-property-button @click="requestUpdate" />
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<label v-if="!useDropdown && dataType == 'number'" class="uk-form-label"
|
||||||
>{{ label }}
|
>{{ label }}
|
||||||
<div class="input-and-buttons-container">
|
<div class="input-and-buttons-container">
|
||||||
<input
|
<input
|
||||||
|
|
@ -18,7 +33,7 @@
|
||||||
<sync-property-button @click="requestUpdate" />
|
<sync-property-button @click="requestUpdate" />
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<div v-if="dataType == 'boolean'" class="input-and-buttons-container">
|
<div v-if="!useDropdown && dataType == 'boolean'" class="input-and-buttons-container">
|
||||||
<label class="uk-form-label numeric-setting-line-input">
|
<label class="uk-form-label numeric-setting-line-input">
|
||||||
<input
|
<input
|
||||||
ref="checkbox"
|
ref="checkbox"
|
||||||
|
|
@ -32,7 +47,7 @@
|
||||||
</label>
|
</label>
|
||||||
<sync-property-button @click="requestUpdate" />
|
<sync-property-button @click="requestUpdate" />
|
||||||
</div>
|
</div>
|
||||||
<label v-if="dataType == 'number_array'" class="uk-form-label"
|
<label v-if="!useDropdown && dataType == 'number_array'" class="uk-form-label"
|
||||||
>{{ label }}
|
>{{ label }}
|
||||||
<div class="input-and-buttons-container">
|
<div class="input-and-buttons-container">
|
||||||
<input
|
<input
|
||||||
|
|
@ -51,7 +66,7 @@
|
||||||
<sync-property-button @click="requestUpdate" />
|
<sync-property-button @click="requestUpdate" />
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<label v-if="dataType == 'number_object'" class="uk-form-label"
|
<label v-if="!useDropdown && dataType == 'number_object'" class="uk-form-label"
|
||||||
>{{ label }}
|
>{{ label }}
|
||||||
<div v-for="(val, key) in modelValue" :key="key">
|
<div v-for="(val, key) in modelValue" :key="key">
|
||||||
<label>{{ internalLabels[key] }}</label>
|
<label>{{ internalLabels[key] }}</label>
|
||||||
|
|
@ -71,7 +86,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<label v-if="dataType == 'string'" class="uk-form-label"
|
<label v-if="!useDropdown && dataType == 'string'" class="uk-form-label"
|
||||||
>{{ label }}
|
>{{ label }}
|
||||||
<div class="input-and-buttons-container">
|
<div class="input-and-buttons-container">
|
||||||
<input
|
<input
|
||||||
|
|
@ -87,7 +102,7 @@
|
||||||
<sync-property-button @click="requestUpdate" />
|
<sync-property-button @click="requestUpdate" />
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<label v-if="dataType == 'other'" class="uk-form-label"
|
<label v-if="!useDropdown && dataType == 'other'" class="uk-form-label"
|
||||||
>{{ label }}
|
>{{ label }}
|
||||||
<div class="input-and-buttons-container">
|
<div class="input-and-buttons-container">
|
||||||
<input
|
<input
|
||||||
|
|
@ -128,6 +143,12 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
// Default is Null as None is passed from the server.
|
||||||
|
default: null,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ["requestUpdate", "sendValue", "animationShown"],
|
emits: ["requestUpdate", "sendValue", "animationShown"],
|
||||||
|
|
@ -176,6 +197,14 @@ export default {
|
||||||
form.op?.includes('writeproperty')
|
form.op?.includes('writeproperty')
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
useDropdown: function () {
|
||||||
|
if (this.options === null) return false;
|
||||||
|
if (["number", "string", "boolean"].includes(this.dataType)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
console.warn(`Cannot support dropdown for datatype of ${this.dataType}`);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
dataType: function () {
|
dataType: function () {
|
||||||
let prop = this.dataSchema;
|
let prop = this.dataSchema;
|
||||||
if (prop == undefined) {
|
if (prop == undefined) {
|
||||||
|
|
@ -328,6 +357,11 @@ export default {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
width: 6em;
|
width: 6em;
|
||||||
}
|
}
|
||||||
|
.dropdown {
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
.edited {
|
.edited {
|
||||||
background-color: #fff3cd;
|
background-color: #fff3cd;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
:data-schema="propertyDescription"
|
:data-schema="propertyDescription"
|
||||||
:label="label"
|
:label="label"
|
||||||
:animate="animate"
|
:animate="animate"
|
||||||
|
:options="options"
|
||||||
@request-update="readProperty"
|
@request-update="readProperty"
|
||||||
@send-value="writeProperty"
|
@send-value="writeProperty"
|
||||||
@animation-shown="resetAnimate"
|
@animation-shown="resetAnimate"
|
||||||
|
|
@ -44,6 +45,11 @@ export default {
|
||||||
default: 1000,
|
default: 1000,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
:label="propertyData.label"
|
:label="propertyData.label"
|
||||||
:read-back="propertyData.read_back"
|
:read-back="propertyData.read_back"
|
||||||
:read-back-delay="propertyData.read_back_delay"
|
:read-back-delay="propertyData.read_back_delay"
|
||||||
|
:options="propertyData.options"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue