123 lines
4 KiB
Python
123 lines
4 KiB
Python
"""Functionality for communicating the required user interface for a thing."""
|
|
|
|
from typing import Any, Optional
|
|
|
|
from pydantic import BaseModel
|
|
|
|
import labthings_fastapi as lt
|
|
|
|
|
|
class ActionButton(BaseModel):
|
|
"""The data required for creating an actionButton in Vue.
|
|
|
|
Currently this cannot be used to submitData, or to submitOnEvent.
|
|
"""
|
|
|
|
thing: str
|
|
"""The Thing "path" for the Thing instance."""
|
|
|
|
action: str
|
|
"""The name of the action to be triggered."""
|
|
|
|
poll_interval: int = 1
|
|
"""The interval for polling in seconds."""
|
|
|
|
submit_label: str = "Submit"
|
|
"""The label for the action button."""
|
|
|
|
can_terminate: bool = True
|
|
"""Specify whether the action can be terminated."""
|
|
|
|
requires_confirmation: bool = False
|
|
"""Specify whether a confirmation modal is needed."""
|
|
|
|
confirmation_message: str = "Start task?"
|
|
"""The message for the confirmation modal."""
|
|
|
|
button_primary: bool = True
|
|
"""Specify whether the button is styled as a primary button."""
|
|
|
|
modal_progress: bool = False
|
|
"""Specify whether to show a progress modal."""
|
|
|
|
stream_with_modal: bool = False
|
|
"""Specify whether to show a mini stream preview in the progress modal.
|
|
|
|
This option only has an effect if `modal_progress` is True.
|
|
If `modal_progress` is False, no modal (and therefore no stream preview) is shown.
|
|
"""
|
|
|
|
notify_on_success: bool = False
|
|
"""Specify whether to a notification on successful completion."""
|
|
|
|
success_message: str = "Success!"
|
|
"""The message to show on successful completion."""
|
|
|
|
|
|
def action_button_for(thing: lt.Thing, action_name: str, **kwargs: Any) -> ActionButton:
|
|
"""Create a ActionButton data for the specified Thing Action.
|
|
|
|
:param thing: The instance of the thing that has the action.
|
|
:param action_name: The name of the action to create a button for.
|
|
:param kwargs: Any attribute of `ActionButton` except for ``thing`` or ``action``.
|
|
:return: An ActionButton (Pydantic Model) object with all the information the
|
|
webapp needs to create the action button.
|
|
"""
|
|
return ActionButton(thing=thing.name, action=action_name, **kwargs)
|
|
|
|
|
|
class PropertyControl(BaseModel):
|
|
"""The data required for creating an actionButton in Vue.
|
|
|
|
Currently this cannot be used to submitData, or to submitOnEvent.
|
|
"""
|
|
|
|
thing: str
|
|
"""The Thing "path" for the Thing instance."""
|
|
|
|
property_name: str
|
|
"""The name of the property (or setting)."""
|
|
|
|
label: str
|
|
"""The label to show in the UI"""
|
|
|
|
read_back: bool = False
|
|
"""Whether or not to read back the property after setting.
|
|
|
|
This is useful for hardware settings that may be coerced to the closest value.
|
|
"""
|
|
|
|
read_back_delay: int = 1000
|
|
"""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.
|
|
"""
|
|
|
|
step: Optional[int | float] = None
|
|
"""The step size for a numerical input.
|
|
|
|
If the property is not numeric this will be ignored.
|
|
|
|
If this is left as None, then the UI will try to use the ``multipleOf`` field in
|
|
the property dataSchema. If ``multipleOf`` is not set then the browser default is
|
|
used.
|
|
"""
|
|
|
|
|
|
def property_control_for(
|
|
thing: lt.Thing, property_name: str, **kwargs: Any
|
|
) -> PropertyControl:
|
|
"""Create an PropertyControl data for the specified Thing Property.
|
|
|
|
:param thing: The instance of the thing that has the property to be controlled.
|
|
:param property_name: The name of the property to create a control for.
|
|
:param kwargs: Any attribute of `PropertyControl` except for ``thing`` or
|
|
``property_name``. If label is not set here it will be the property name.
|
|
"""
|
|
if "label" not in kwargs:
|
|
kwargs["label"] = property_name
|
|
return PropertyControl(thing=thing.name, property_name=property_name, **kwargs)
|