diff --git a/src/openflexure_microscope_server/things/scan_workflows.py b/src/openflexure_microscope_server/things/scan_workflows.py
index 13b6dba3..9d80390d 100644
--- a/src/openflexure_microscope_server/things/scan_workflows.py
+++ b/src/openflexure_microscope_server/things/scan_workflows.py
@@ -625,12 +625,14 @@ class HistoScanWorkflow(RectGridWorkflow[HistoScanSettingsModel]):
can_terminate=False,
notify_on_success=True,
success_message="Background image has been updated",
+ update_interface_on_response=True,
)
check_bg_button = action_button_for(
self,
"check_background",
poll_interval=0.1,
submit_label="Check Current Image",
+ disabled=not self._background_detector.ready,
can_terminate=False,
notify_on_success=True,
response_is_success_message=True,
diff --git a/src/openflexure_microscope_server/ui.py b/src/openflexure_microscope_server/ui.py
index 9df04f5d..771dccc7 100644
--- a/src/openflexure_microscope_server/ui.py
+++ b/src/openflexure_microscope_server/ui.py
@@ -158,6 +158,9 @@ class ActionButton(BaseModel):
button_primary: bool = True
"""Specify whether the button is styled as a primary button."""
+ disabled: bool = False
+ """Specify whether the button is disabled."""
+
modal_progress: bool = False
"""Specify whether to show a progress modal."""
@@ -180,6 +183,12 @@ class ActionButton(BaseModel):
success_message: str = "Success!"
"""The message to show on successful completion."""
+ update_interface_on_response: bool = False
+ """If True the action button emits a requestUpdate signal when completed.
+
+ Downstream components can subscribe to this and request an update.
+ """
+
def action_button_for(thing: lt.Thing, action_name: str, **kwargs: Any) -> ActionButton:
"""Create a ActionButton data for the specified Thing Action.
diff --git a/webapp/src/components/labThingsComponents/actionButton.vue b/webapp/src/components/labThingsComponents/actionButton.vue
index e5bfda75..eaaaf115 100644
--- a/webapp/src/components/labThingsComponents/actionButton.vue
+++ b/webapp/src/components/labThingsComponents/actionButton.vue
@@ -322,6 +322,9 @@ export default {
} else if (response.data.status == "cancelled") {
this.$emit("cancelled", response.data);
this.modalNotify(`The action '${this.submitLabel}' was cancelled.`);
+ } else if (response.data.status == "error") {
+ const err_msg = this.log?.[0]?.message ?? "Unknown error";
+ this.$emit("error", err_msg);
}
}
this.taskUrl = null;
diff --git a/webapp/src/components/labThingsComponents/serverSpecifiedActionButton.vue b/webapp/src/components/labThingsComponents/serverSpecifiedActionButton.vue
index df1afd23..44b129fe 100644
--- a/webapp/src/components/labThingsComponents/serverSpecifiedActionButton.vue
+++ b/webapp/src/components/labThingsComponents/serverSpecifiedActionButton.vue
@@ -8,6 +8,7 @@
:requires-confirmation="actionData.requires_confirmation"
:confirmation-message="actionData.confirmation_message"
:button-primary="actionData.button_primary"
+ :is-disabled="actionData.disabled"
:modal-progress="actionData.modal_progress"
:stream-with-modal="actionData.stream_with_modal"
@response="actionResponse"
@@ -34,7 +35,7 @@ export default {
},
},
- emits: ["response", "finished"],
+ emits: ["response", "finished", "requestUpdate"],
methods: {
/**
@@ -50,6 +51,9 @@ export default {
} else {
this.modalNotify(this.actionData.success_message);
}
+ if (this.actionData.update_interface_on_response) {
+ this.$emit("requestUpdate");
+ }
this.$emit("response", response);
}
},
diff --git a/webapp/src/components/labThingsComponents/serverSpecifiedInterface.vue b/webapp/src/components/labThingsComponents/serverSpecifiedInterface.vue
index 8c47c622..10aa5636 100644
--- a/webapp/src/components/labThingsComponents/serverSpecifiedInterface.vue
+++ b/webapp/src/components/labThingsComponents/serverSpecifiedInterface.vue
@@ -10,12 +10,19 @@