From 050c2b76725770ef504f1db5d691d61faa9578b2 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Wed, 25 Mar 2026 18:19:52 +0000 Subject: [PATCH 1/2] Verify properties and actions exist before making controls and buttons. --- src/openflexure_microscope_server/ui.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/openflexure_microscope_server/ui.py b/src/openflexure_microscope_server/ui.py index 4620cab2..33134247 100644 --- a/src/openflexure_microscope_server/ui.py +++ b/src/openflexure_microscope_server/ui.py @@ -224,6 +224,8 @@ def action_button_for(thing: lt.Thing, action_name: str, **kwargs: Any) -> Actio :return: An ActionButton (Pydantic Model) object with all the information the webapp needs to create the action button. """ + if action_name not in thing.actions: + raise AttributeError(f"{thing.name} has no action {action_name}") return ActionButton(thing=thing.name, action=action_name, **kwargs) @@ -283,6 +285,8 @@ def property_control_for( """ if "label" not in kwargs: kwargs["label"] = property_name + if property_name not in thing.properties: + raise AttributeError(f"{thing.name} has no property {property_name}") return PropertyControl(thing=thing.name, property_name=property_name, **kwargs) From c0158a7a6c4d16a1e7fa9d38e8fa53d65f9425e6 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Fri, 15 May 2026 14:30:14 +0100 Subject: [PATCH 2/2] Provide feeback to user on broken UI components. --- src/openflexure_microscope_server/ui.py | 12 +++++++++-- webapp/src/App.vue | 12 +++++++++++ .../labThingsComponents/actionButton.vue | 20 ++++++++++++++++--- .../labThingsComponents/propertyControl.vue | 14 +++++++++++++ .../serverSpecifiedActionButton.vue | 1 + .../serverSpecifiedPropertyControl.vue | 1 + 6 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/openflexure_microscope_server/ui.py b/src/openflexure_microscope_server/ui.py index 33134247..420a7b9e 100644 --- a/src/openflexure_microscope_server/ui.py +++ b/src/openflexure_microscope_server/ui.py @@ -214,6 +214,9 @@ class ActionButton(BaseModel): Downstream components can subscribe to this and request an update. """ + broken: bool = False + """If True the action button is broken. There is no corresponding action.""" + def action_button_for(thing: lt.Thing, action_name: str, **kwargs: Any) -> ActionButton: """Create a ActionButton data for the specified Thing Action. @@ -225,7 +228,8 @@ def action_button_for(thing: lt.Thing, action_name: str, **kwargs: Any) -> Actio webapp needs to create the action button. """ if action_name not in thing.actions: - raise AttributeError(f"{thing.name} has no action {action_name}") + thing.logger.error(f"{thing.name} has no action {action_name}") + kwargs["broken"] = True return ActionButton(thing=thing.name, action=action_name, **kwargs) @@ -272,6 +276,9 @@ class PropertyControl(BaseModel): used. """ + broken: bool = False + """If True the property control is broken. There is no corresponding property.""" + def property_control_for( thing: lt.Thing, property_name: str, **kwargs: Any @@ -286,7 +293,8 @@ def property_control_for( if "label" not in kwargs: kwargs["label"] = property_name if property_name not in thing.properties: - raise AttributeError(f"{thing.name} has no property {property_name}") + thing.logger.error(f"{thing.name} has no property {property_name}") + kwargs["broken"] = True return PropertyControl(thing=thing.name, property_name=property_name, **kwargs) diff --git a/webapp/src/App.vue b/webapp/src/App.vue index c603d280..c8f0e830 100644 --- a/webapp/src/App.vue +++ b/webapp/src/App.vue @@ -387,4 +387,16 @@ html { padding: 0; height: 100%; } + +.ui-element-error-icon { + vertical-align: middle; + padding-right: 10px; + color: #a00; +} + +.ui-element-broken { + border-color: #a00 !important; + color: #a00 !important; + cursor: not-allowed; +} diff --git a/webapp/src/components/labThingsComponents/actionButton.vue b/webapp/src/components/labThingsComponents/actionButton.vue index 6b173d62..6f1df1a9 100644 --- a/webapp/src/components/labThingsComponents/actionButton.vue +++ b/webapp/src/components/labThingsComponents/actionButton.vue @@ -3,13 +3,15 @@ +
+ error {{ label }} +