diff --git a/webapp/src/assets/less/theme.less b/webapp/src/assets/less/theme.less index c3c89bf6..237f0649 100644 --- a/webapp/src/assets/less/theme.less +++ b/webapp/src/assets/less/theme.less @@ -343,7 +343,7 @@ a:hover { border-radius: @button-border-radius; padding: 0 8px; border-color: @global-border; - margin-bottom: 2px; + margin-bottom: 4px; text-transform:none !important; } @@ -356,7 +356,6 @@ a:hover { background-color: rgba(180, 180, 180, 0.10); border-color: @global-primary-background; color: @button-text-color; - margin-bottom: 4px; } .uk-button-danger { diff --git a/webapp/src/components/labThingsComponents/actionButton.vue b/webapp/src/components/labThingsComponents/actionButton.vue index aa4d2265..b8ec4969 100644 --- a/webapp/src/components/labThingsComponents/actionButton.vue +++ b/webapp/src/components/labThingsComponents/actionButton.vue @@ -1,83 +1,37 @@ - - diff --git a/webapp/src/components/labThingsComponents/actionLogDisplay.vue b/webapp/src/components/labThingsComponents/actionLogDisplay.vue index 3602baa4..9fc8680e 100644 --- a/webapp/src/components/labThingsComponents/actionLogDisplay.vue +++ b/webapp/src/components/labThingsComponents/actionLogDisplay.vue @@ -7,7 +7,8 @@
- The task failed due to an error. There may be more information in the log. +

The task failed due to an error:

+

{{ errorMessage }}

The task was cancelled. @@ -43,6 +44,21 @@ export default { }; }, + computed: { + errorMessage() { + let logLength = this.log.length; + var defaultMessage = "Unexpected error, please check the logs"; + if (logLength == 0) { + return defaultMessage; + } + // Cannot use .at until we update OpenFlexure Connect + if (this.log[logLength - 1].levelname != "ERROR") { + return defaultMessage; + } + return this.log[logLength - 1].message || defaultMessage; + }, + }, + watch: { log: function () { this.scrollToBottom(); diff --git a/webapp/src/components/labThingsComponents/actionProgressBar.vue b/webapp/src/components/labThingsComponents/actionProgressBar.vue index 00afc787..d997b5d7 100644 --- a/webapp/src/components/labThingsComponents/actionProgressBar.vue +++ b/webapp/src/components/labThingsComponents/actionProgressBar.vue @@ -1,5 +1,5 @@ diff --git a/webapp/src/components/tabContentComponents/controlComponents/autofocusControl.vue b/webapp/src/components/tabContentComponents/controlComponents/autofocusControl.vue index c2e5256e..ef70d6c6 100644 --- a/webapp/src/components/tabContentComponents/controlComponents/autofocusControl.vue +++ b/webapp/src/components/tabContentComponents/controlComponents/autofocusControl.vue @@ -9,7 +9,6 @@ :submit-label="'Autofocus'" :button-primary="true" :submit-on-event="'globalFastAutofocusEvent'" - :is-disabled="isAutofocusing" @taskStarted="onAutofocus" @finished="afterAutofocus" @error="modalError" diff --git a/webapp/src/mixins/labThingsMixins.js b/webapp/src/mixins/labThingsMixins.js index b6ae7aa4..41f0bad1 100644 --- a/webapp/src/mixins/labThingsMixins.js +++ b/webapp/src/mixins/labThingsMixins.js @@ -64,19 +64,31 @@ export default { } await axios.put(url, value); }, - async invokeAction(thing, action, data) { - let url = this.$store.getters["wot/thingActionUrl"](thing, action, "invokeaction", false); + async invokeAction(thing, action, data, handleErrors = true) { + let url = this.thingActionUrl(thing, action); try { let response = await axios.post(url, data); return response; } catch (error) { - this.modalError(error); - return undefined; + if (handleErrors) { + this.modalError(error); + return undefined; + } else { + throw error; + } } }, - async pollUntilComplete(taskUrl, ongoingMethod, finalMethod, interval = 500) { + async pollUntilComplete( + taskUrl, + ongoingMethod, + finalMethod, + interval = 500, + modalErrors = true, + ) { + let response; + let finalMethodCalled = false; try { - const response = await axios.get(taskUrl, { baseURL: this.$store.getters.baseUri }); + response = await axios.get(taskUrl, { baseURL: this.$store.getters.baseUri }); const result = response.data.status; if ((result == "running") | (result == "pending")) { @@ -87,15 +99,33 @@ export default { } else { clearTimeout(this.pollTimers[taskUrl]); delete this.pollTimers[taskUrl]; + finalMethodCalled = true; finalMethod?.(response); } } catch (error) { + this.$emit("error", error); + if (modalErrors) { + this.modalError(error); + } clearTimeout(this.pollTimers[taskUrl]); delete this.pollTimers[taskUrl]; - this.modalError(error); + if (!finalMethodCalled) { + finalMethod?.(response); + } + } + }, + terminateAction(taskUrl) { + axios.delete(taskUrl, { baseURL: this.$store.getters.baseUri }); + }, + async findOngoingActions(thing, action) { + let url = this.thingActionUrl(thing, action); + try { + return await axios.get(url); + } catch (error) { + console.warn("checkExistingTasks: request failed", error); + return null; } }, - thingActionUrl(thing, action, allowUndefined = false) { let url = this.$store.getters["wot/thingActionUrl"]( thing,