diff --git a/frontend/src/components/BaseButton.vue b/frontend/src/components/BaseButton.vue
index 762205216..f19685f00 100644
--- a/frontend/src/components/BaseButton.vue
+++ b/frontend/src/components/BaseButton.vue
@@ -4,7 +4,7 @@ import type { RouteLocationRaw } from "vue-router";
export interface Props {
to?: RouteLocationRaw;
href?: string;
- type: "primary" | "secondary" | "brand" | "danger";
+ type: "primary" | "secondary" | "brand" | "danger" | "retry";
disabled?: boolean;
htmlType?: HTMLButtonElement["type"];
}
@@ -109,6 +109,25 @@ defineEmits<{
}
}
+ &.retry {
+ background-color: $actris-violetlight;
+ margin: 0;
+ padding: 0 5px;
+ font-size: 0.8rem;
+ cursor: pointer;
+ display: flex;
+
+ &:hover,
+ &:focus-visible {
+ text-decoration: none;
+ background-color: darken($actris-violetlight, 10%);
+ }
+
+ &:focus-visible {
+ box-shadow: 0 0 0 3px rgba($red1, 0.5);
+ }
+ }
+
&:disabled {
pointer-events: none;
opacity: 0.5;
diff --git a/frontend/src/views/QueueView.vue b/frontend/src/views/QueueView.vue
index cdbf34f13..63c63cb9e 100644
--- a/frontend/src/views/QueueView.vue
+++ b/frontend/src/views/QueueView.vue
@@ -43,7 +43,7 @@
Date |
Product |
Instrument / model |
- Due in |
+ Due in |
@@ -64,6 +64,9 @@
{{ task.status === "created" ? timeDifference(task.scheduledAt) : "" }}
|
+
+ Retry
+ |
@@ -139,6 +142,41 @@ async function updateQueueData() {
lastUpdate = new Date();
}
+interface TaskPayload {
+ type: string;
+ siteId: string;
+ measurementDate: string;
+ productId: string;
+ instrumentInfoUuid?: string;
+ modelId?: string;
+}
+
+async function retryTask(task: AugmentedTask) {
+ const newTask: TaskPayload = {
+ type: task.type,
+ siteId: task.siteId,
+ productId: task.productId,
+ measurementDate: task.measurementDate,
+ };
+
+ if (task.instrumentInfo) {
+ newTask.instrumentInfoUuid = task.instrumentInfo.uuid;
+ } else if (task.model) {
+ newTask.modelId = task.model.id;
+ }
+
+ try {
+ await axios.post(`${backendUrl}queue/publish`, newTask, {
+ auth: { username: loginStore.username, password: loginStore.password },
+ });
+ if (updateTimeout) clearTimeout(updateTimeout);
+ await updateQueueData();
+ } catch (err) {
+ alert(`Failed to retry task: ${err}`);
+ console.error(err);
+ }
+}
+
async function cancelBatch() {
if (!confirm(`Cancel batch ${route.query.batch}?`)) return;
try {
@@ -238,6 +276,10 @@ function generateLink(task: AugmentedTask) {
padding-right: 20px;
padding-left: 20px;
}
+
+ .retry-button {
+ vertical-align: middle;
+ }
}
.list-enter-active {