Merge branch 'consolidate-action-button' into 'v3'
Consolidate action buton to just a button Closes #535 See merge request openflexure/openflexure-microscope-server!437
This commit is contained in:
commit
11e9374dfa
8 changed files with 282 additions and 239 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,83 +1,37 @@
|
|||
<template>
|
||||
<div v-observe-visibility="visibilityChanged" class="uk-margin-remove uk-padding-remove">
|
||||
<div v-if="taskStarted" ref="isPollingElement">
|
||||
<action-progress-bar
|
||||
v-if="taskStarted && hideOnRun"
|
||||
:progress="progress"
|
||||
:task-status="taskStatus"
|
||||
/>
|
||||
<!-- hideOnRun selects if the button hides, don't show progress bar if button doesn't hide. -->
|
||||
<button
|
||||
v-if="canTerminate && taskRunning"
|
||||
type="button"
|
||||
class="uk-button uk-button-danger uk-margin-remove uk-float-right uk-width-1-1"
|
||||
@click="terminateTask()"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
:disabled="isDisabled"
|
||||
:hidden="taskStarted && hideOnRun"
|
||||
class="uk-button uk-width-1-1"
|
||||
:class="[
|
||||
isDisabled ? 'uk-button-disabled' : '',
|
||||
buttonPrimary ? 'uk-button-primary' : 'uk-button-default',
|
||||
]"
|
||||
@click="bootstrapTask()"
|
||||
>
|
||||
{{ submitLabel }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="modal-center"
|
||||
ref="statusModal"
|
||||
class=""
|
||||
uk-modal="bg-close: false; esc-close: false; stack: true;"
|
||||
<button
|
||||
type="button"
|
||||
:disabled="buttonDisabled"
|
||||
class="uk-button uk-width-1-1 uk-position-relative"
|
||||
:class="buttonClasses"
|
||||
@click="handleClick"
|
||||
>
|
||||
<div id="status-modal" class="uk-modal-dialog uk-modal-body uk-margin-auto-vertical">
|
||||
<h2>{{ submitLabel }}</h2>
|
||||
<action-log-display :log="log" :task-status="taskStatus" />
|
||||
<div id="progress-and-cancel-row">
|
||||
<div class="stretchy">
|
||||
<action-progress-bar :progress="progress" :task-status="taskStatus" />
|
||||
</div>
|
||||
<action-progress-bar :progress="progress" :task-status="taskStatus" :in-button="true" />
|
||||
{{ buttonLabel }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
v-if="canTerminate && taskRunning"
|
||||
type="button"
|
||||
class="uk-button uk-button-danger not-stretchy"
|
||||
@click="terminateTask()"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
v-if="!taskStarted"
|
||||
type="button"
|
||||
class="uk-button not-stretchy"
|
||||
@click="hideModal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<action-status-modal
|
||||
ref="statusModal"
|
||||
:title="submitLabel"
|
||||
:log="log"
|
||||
:progress="progress"
|
||||
:can-terminate="canTerminate"
|
||||
:task-running="taskRunning"
|
||||
:task-started="taskStarted"
|
||||
:task-status="taskStatus"
|
||||
@terminateTask="terminateTask"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import UIkit from "uikit";
|
||||
import ActionProgressBar from "./actionProgressBar.vue";
|
||||
import ActionLogDisplay from "./actionLogDisplay.vue";
|
||||
import ActionStatusModal from "./actionStatusModal.vue";
|
||||
|
||||
export default {
|
||||
name: "ActionButton",
|
||||
components: { ActionProgressBar, ActionLogDisplay },
|
||||
components: { ActionProgressBar, ActionStatusModal },
|
||||
|
||||
props: {
|
||||
action: {
|
||||
|
|
@ -138,11 +92,6 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
hideOnRun: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
|
||||
data: function () {
|
||||
|
|
@ -157,8 +106,25 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
submitUrl() {
|
||||
return this.thingActionUrl(this.thing, this.action);
|
||||
buttonDisabled() {
|
||||
return this.isDisabled || (this.taskRunning && !this.canTerminate);
|
||||
},
|
||||
buttonLabel() {
|
||||
return this.taskRunning && this.canTerminate ? "Cancel" : this.submitLabel;
|
||||
},
|
||||
buttonClasses() {
|
||||
const classes = [];
|
||||
if (this.buttonDisabled) {
|
||||
classes.push("uk-button-disabled");
|
||||
}
|
||||
if (this.taskRunning && this.canTerminate) {
|
||||
classes.push("uk-button-danger");
|
||||
} else if (this.buttonPrimary) {
|
||||
classes.push("uk-button-primary");
|
||||
} else {
|
||||
classes.push("uk-button-default");
|
||||
}
|
||||
return classes.join(" ");
|
||||
},
|
||||
},
|
||||
|
||||
|
|
@ -181,27 +147,6 @@ export default {
|
|||
},
|
||||
|
||||
mounted() {
|
||||
//Define .from_index() as a custom function, working similar to .at()
|
||||
//For backwards compatibility, not using in-built .at() until updates to Connect
|
||||
function from_index(n) {
|
||||
// ToInteger() abstract op
|
||||
n = Math.trunc(n) || 0;
|
||||
// Allow negative indexing from the end
|
||||
if (n < 0) n += this.length;
|
||||
// OOB access is guaranteed to return undefined
|
||||
if (n < 0 || n >= this.length) return undefined;
|
||||
// Otherwise, this is just normal property access
|
||||
return this[n];
|
||||
}
|
||||
const TypedArray = Reflect.getPrototypeOf(Int8Array);
|
||||
for (const C of [Array, String, TypedArray]) {
|
||||
Object.defineProperty(C.prototype, "from_index", {
|
||||
value: from_index,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
// Check for already running tasks
|
||||
if (this.taskStarted != true) {
|
||||
this.checkExistingTasks();
|
||||
|
|
@ -223,6 +168,13 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
handleClick() {
|
||||
if (this.taskStarted) {
|
||||
this.terminateTask();
|
||||
} else {
|
||||
this.bootstrapTask();
|
||||
}
|
||||
},
|
||||
visibilityChanged(isVisible) {
|
||||
if (isVisible && this.taskStarted != true) {
|
||||
this.checkExistingTasks();
|
||||
|
|
@ -238,13 +190,9 @@ export default {
|
|||
*
|
||||
*/
|
||||
async checkExistingTasks() {
|
||||
let response;
|
||||
try {
|
||||
response = await axios.get(this.submitUrl);
|
||||
} catch (error) {
|
||||
console.warn("checkExistingTasks: request failed", error);
|
||||
return;
|
||||
}
|
||||
let response = await this.findOngoingActions(this.thing, this.action);
|
||||
// Exit if response is null, due to an error.
|
||||
if (response == null) return;
|
||||
// Check for a task that is ongoing.
|
||||
// We can't handle multiple tasks ongoing, so this picks the first.
|
||||
const ongoingTask = response.data.find((t) => ["pending", "running"].includes(t.status));
|
||||
|
|
@ -254,13 +202,7 @@ export default {
|
|||
this.$emit("taskStarted");
|
||||
// Find its URL
|
||||
const taskUrl = ongoingTask.links.find((t) => t.rel == "self").href;
|
||||
try {
|
||||
await this.pollOngoingTask(ongoingTask.id, taskUrl);
|
||||
} catch (error) {
|
||||
this.$emit("error", error);
|
||||
} finally {
|
||||
this.onTaskEnd();
|
||||
}
|
||||
this.startPollingTask(ongoingTask.id, taskUrl);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -280,142 +222,78 @@ export default {
|
|||
|
||||
async startTask() {
|
||||
// Starts a new Action task
|
||||
|
||||
this.$emit("submit", this.submitData);
|
||||
// Send a request to start a task
|
||||
|
||||
this.taskStarted = true;
|
||||
this.$emit("taskStarted");
|
||||
let response;
|
||||
try {
|
||||
let response = await axios.post(this.submitUrl, this.submitData);
|
||||
if (this.modalProgress) {
|
||||
UIkit.modal(this.$refs.statusModal).show();
|
||||
}
|
||||
await this.pollOngoingTask(response.data.id, response.data.href);
|
||||
response = await this.invokeAction(
|
||||
this.thing,
|
||||
this.action,
|
||||
this.submitData,
|
||||
false, // Stop invokeAction handling the error.
|
||||
);
|
||||
} catch (error) {
|
||||
this.$emit("error", error);
|
||||
} finally {
|
||||
this.onTaskEnd();
|
||||
return;
|
||||
}
|
||||
if (this.modalProgress) {
|
||||
this.$refs.statusModal.show();
|
||||
}
|
||||
// This just starts the polling. No need to await it.
|
||||
this.startPollingTask(response.data.id, response.data.href);
|
||||
},
|
||||
|
||||
async pollOngoingTask(taskId, taskUrl) {
|
||||
async startPollingTask(taskId, taskUrl) {
|
||||
// Return if taskRunning already set.
|
||||
if (this.taskRunning) return;
|
||||
// Starts polling an existing Action task
|
||||
this.taskUrl = taskUrl;
|
||||
// Start the store polling TaskId for success
|
||||
const response = await this.startPolling(taskId, taskUrl);
|
||||
if (response.status == "completed") {
|
||||
this.$emit("response", response);
|
||||
this.$emit("completed", response.output);
|
||||
} else if (response.status == "cancelled") {
|
||||
this.$emit("cancelled", response);
|
||||
this.modalNotify(`The action '${this.submitLabel}' was cancelled.`);
|
||||
}
|
||||
this.taskRunning = true;
|
||||
this.$emit("taskRunning", taskId);
|
||||
this.pollUntilComplete(
|
||||
taskUrl,
|
||||
this.onPollingResponse,
|
||||
this.onTaskEnd, // Method to run after task (even if error)
|
||||
500, // Interval
|
||||
);
|
||||
},
|
||||
|
||||
onTaskEnd: function () {
|
||||
// Reset taskRunning and taskId
|
||||
onTaskEnd: function (response) {
|
||||
if (response) {
|
||||
this.taskStatus = response.data.status;
|
||||
this.log = response.data.log;
|
||||
if (response.data.status == "completed") {
|
||||
this.$emit("response", response.data);
|
||||
this.$emit("completed", response.data.output);
|
||||
} else if (response.data.status == "cancelled") {
|
||||
this.$emit("cancelled", response.data);
|
||||
this.modalNotify(`The action '${this.submitLabel}' was cancelled.`);
|
||||
}
|
||||
}
|
||||
this.taskUrl = null;
|
||||
this.taskRunning = false;
|
||||
this.taskStarted = false;
|
||||
this.$emit("finished");
|
||||
},
|
||||
|
||||
startPolling: function (taskId, taskUrl) {
|
||||
if (this.taskRunning != true) {
|
||||
// Starts polling an existing Action task
|
||||
this.taskUrl = taskUrl;
|
||||
// Start the store polling TaskId for success
|
||||
this.taskRunning = true;
|
||||
this.$emit("taskRunning", taskId);
|
||||
return this.pollTask(taskId, this.pollInterval);
|
||||
}
|
||||
},
|
||||
|
||||
pollTask: function (taskId, interval) {
|
||||
interval = interval * 1000 || 500;
|
||||
|
||||
var checkCondition = (resolve, reject) => {
|
||||
// If the condition is met, we're done!
|
||||
axios.get(this.taskUrl, { baseURL: this.$store.getters.baseUri }).then((response) => {
|
||||
var result = response.data.status;
|
||||
this.taskStatus = result;
|
||||
if ((result == "running") | (result == "pending")) {
|
||||
// If the task is still running, we update progress/log,
|
||||
// and schedule another poll
|
||||
this.progress = response.data.progress;
|
||||
this.log = response.data.log;
|
||||
// Check again after timeout
|
||||
setTimeout(checkCondition, interval, resolve, reject);
|
||||
}
|
||||
// If task ends with an error
|
||||
else if (result == "error") {
|
||||
// Pass the error string back with reject
|
||||
if (!this.progress) this.progress = 1;
|
||||
// Test whether the log is empty or the most recent message is not from an error
|
||||
// If so, return a default message
|
||||
if (
|
||||
(response.data.log.length == 0) |
|
||||
(response.data.log.from_index(-1).levelname != "ERROR")
|
||||
) {
|
||||
var message = "Unexpected error, please check the logs";
|
||||
}
|
||||
// As LabThings Actions add the message from any raised exception to the log, the
|
||||
// last message in the log is the message from the Exception.
|
||||
// If the Exception was raised with no message, use a default.
|
||||
else {
|
||||
message =
|
||||
response.data.log.from_index(-1).message ||
|
||||
"Unexpected error, please check the logs";
|
||||
}
|
||||
// Raise an Error with the chosen message
|
||||
reject(new Error(message));
|
||||
}
|
||||
// If task ends without reporting an error
|
||||
// (Note: this includes cancellation)
|
||||
else {
|
||||
resolve(response.data);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(checkCondition);
|
||||
},
|
||||
|
||||
hideModal() {
|
||||
UIkit.modal(this.$refs.statusModal).hide();
|
||||
this.$root.$emit("modalClosed");
|
||||
onPollingResponse(response) {
|
||||
// While the task is still running, we update progress/log,
|
||||
// and schedule another poll
|
||||
var result = response.data.status;
|
||||
this.taskStatus = result;
|
||||
this.progress = response.data.progress;
|
||||
this.log = response.data.log;
|
||||
},
|
||||
|
||||
terminateTask: function () {
|
||||
axios.delete(this.taskUrl, { baseURL: this.$store.getters.baseUri });
|
||||
this.$root.$emit("modalClosed");
|
||||
if (this.taskUrl) {
|
||||
this.terminateAction(this.taskUrl);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import "../../assets/less/theme.less";
|
||||
|
||||
#progress-and-cancel-row {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: flex-start;
|
||||
align-content: stretch;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#progress-and-cancel-row .stretchy {
|
||||
flex-grow: 1;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
#progress-and-cancel-row .not-stretchy {
|
||||
flex-grow: 0;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#status-modal .log-container {
|
||||
height: 10em;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-if="taskStatus == 'error'" class="uk-alert uk-alert-danger">
|
||||
The task failed due to an error. There may be more information in the log.
|
||||
<p><b>The task failed due to an error:</b></p>
|
||||
<p>{{ errorMessage }}</p>
|
||||
</div>
|
||||
<div v-if="taskStatus == 'cancelled'" class="uk-alert uk-alert-warning">
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="progress uk-margin-small">
|
||||
<div class="progress uk-margin-small" :class="inButton ? 'in-button' : 'stand-alone'">
|
||||
<div v-if="indeterminateProgressBar" class="indeterminate"></div>
|
||||
<div v-else class="determinate" :style="barWidthFromProgress"></div>
|
||||
</div>
|
||||
|
|
@ -19,6 +19,11 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
inButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -41,7 +46,20 @@ export default {
|
|||
<style lang="less" scoped>
|
||||
@import "../../assets/less/theme.less";
|
||||
|
||||
.progress {
|
||||
.in-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background-color: transparent;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.stand-alone {
|
||||
position: relative;
|
||||
height: 5px;
|
||||
display: block;
|
||||
|
|
|
|||
105
webapp/src/components/labThingsComponents/actionStatusModal.vue
Normal file
105
webapp/src/components/labThingsComponents/actionStatusModal.vue
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<div ref="modal" class="" uk-modal="bg-close: false; esc-close: false; stack: true;">
|
||||
<div id="status-modal" class="uk-modal-dialog uk-modal-body uk-margin-auto-vertical">
|
||||
<h2>{{ title }}</h2>
|
||||
<action-log-display :log="log" :task-status="taskStatus" />
|
||||
<div id="progress-and-cancel-row">
|
||||
<div class="stretchy">
|
||||
<action-progress-bar :progress="progress" :task-status="taskStatus" />
|
||||
</div>
|
||||
|
||||
<button
|
||||
v-if="canTerminate && taskRunning"
|
||||
type="button"
|
||||
class="uk-button uk-button-danger not-stretchy"
|
||||
@click="$emit('terminateTask')"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button v-if="!taskStarted" type="button" class="uk-button not-stretchy" @click="hide">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UIkit from "uikit";
|
||||
import ActionProgressBar from "./actionProgressBar.vue";
|
||||
import ActionLogDisplay from "./actionLogDisplay.vue";
|
||||
|
||||
export default {
|
||||
name: "ActionStatusModal",
|
||||
components: { ActionProgressBar, ActionLogDisplay },
|
||||
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
log: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
progress: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
canTerminate: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
taskRunning: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
taskStarted: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
taskStatus: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
show() {
|
||||
UIkit.modal(this.$refs.modal).show();
|
||||
},
|
||||
hide() {
|
||||
UIkit.modal(this.$refs.modal).hide();
|
||||
this.$root.$emit("modalClosed");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import "../../assets/less/theme.less";
|
||||
|
||||
#progress-and-cancel-row {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: flex-start;
|
||||
align-content: stretch;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#progress-and-cancel-row .stretchy {
|
||||
flex-grow: 1;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
#progress-and-cancel-row .not-stretchy {
|
||||
flex-grow: 0;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#status-modal .log-container {
|
||||
height: 10em;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -11,7 +11,6 @@
|
|||
:button-primary="false"
|
||||
:submit-data="{ x: 0, y: 0, z: -100 }"
|
||||
:submit-label="' - '"
|
||||
:hide-on-run="false"
|
||||
:can-terminate="false"
|
||||
/>
|
||||
<action-button
|
||||
|
|
@ -22,7 +21,6 @@
|
|||
:submit-data="{ x: 0, y: 0, z: 100 }"
|
||||
:submit-label="'+'"
|
||||
:can-terminate="false"
|
||||
:hide-on-run="false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
:submit-label="'Autofocus'"
|
||||
:button-primary="true"
|
||||
:submit-on-event="'globalFastAutofocusEvent'"
|
||||
:is-disabled="isAutofocusing"
|
||||
@taskStarted="onAutofocus"
|
||||
@finished="afterAutofocus"
|
||||
@error="modalError"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue