From 991eb9eb518b78fdb9172168ca3dfb089523eb85 Mon Sep 17 00:00:00 2001 From: Ahmed Awan Date: Thu, 22 Aug 2024 15:31:01 -0500 Subject: [PATCH] [24.1] Handle error when workflow is unowned in Invocation view Found this when investigating https://github.com/galaxyproject/galaxy/issues/18697; that if (in this case) I run another user's shared workflow with a subworkflow, the invocation view for the parent renders everything fine, but there is an unhandled error caused by the subworkflow not being shared. Now this fix handles that error and shows it on hover on the `WorkflowStepTitle` --- .../WorkflowInvocationOverview.vue | 5 +- .../WorkflowInvocationState.vue | 47 ++++++++----------- .../WorkflowStepTitle.vue | 28 ++++++++--- client/src/stores/workflowStore.ts | 1 + 4 files changed, 45 insertions(+), 36 deletions(-) diff --git a/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.vue b/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.vue index ae69835b6479..9e8fb40cce09 100644 --- a/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.vue +++ b/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.vue @@ -3,8 +3,8 @@ import { BAlert, BButton } from "bootstrap-vue"; import { computed } from "vue"; import { InvocationJobsSummary, InvocationStep, WorkflowInvocationElementView } from "@/api/invocations"; -import { useWorkflowInstance } from "@/composables/useWorkflowInstance"; import { getRootFromIndexLink } from "@/onload"; +import { type Workflow } from "@/stores/workflowStore"; import { withPrefix } from "@/utils/redirect"; import { @@ -28,6 +28,7 @@ function getUrl(path: string): string { interface Props { invocation?: WorkflowInvocationElementView; + workflow?: Workflow; invocationAndJobTerminal: boolean; invocationSchedulingTerminal: boolean; isFullPage?: boolean; @@ -40,8 +41,6 @@ const props = defineProps(); const generatePdfTooltip = "Generate PDF report for this workflow invocation"; -const { workflow } = useWorkflowInstance(props.invocation?.workflow_id ?? ""); - const invocationId = computed(() => props.invocation?.id); const indexStr = computed(() => { diff --git a/client/src/components/WorkflowInvocationState/WorkflowInvocationState.vue b/client/src/components/WorkflowInvocationState/WorkflowInvocationState.vue index b1e590cd203d..85968bb08c85 100644 --- a/client/src/components/WorkflowInvocationState/WorkflowInvocationState.vue +++ b/client/src/components/WorkflowInvocationState/WorkflowInvocationState.vue @@ -6,10 +6,9 @@ import { BAlert, BButton, BButtonGroup, BTab, BTabs } from "bootstrap-vue"; import { computed, onMounted, onUnmounted, ref, watch } from "vue"; import { type InvocationJobsSummary, type WorkflowInvocationElementView } from "@/api/invocations"; -import type { StoredWorkflowDetailed } from "@/api/workflows"; import { useAnimationFrameResizeObserver } from "@/composables/sensors/animationFrameResizeObserver"; import { useInvocationStore } from "@/stores/invocationStore"; -import { useWorkflowStore } from "@/stores/workflowStore"; +import { useWorkflowStore, type Workflow } from "@/stores/workflowStore"; import localize from "@/utils/localization"; import { errorMessageAsString } from "@/utils/simple-error"; @@ -51,6 +50,7 @@ const invocationStore = useInvocationStore(); const stepStatesInterval = ref(undefined); const jobStatesInterval = ref(undefined); const initialLoading = ref(true); +const invocationLoaded = ref(false); const errorMessage = ref(null); // after the report tab is first activated, no longer lazy-render it from then on @@ -73,7 +73,7 @@ useAnimationFrameResizeObserver(scrollableDiv, ({ clientSize, scrollSize }) => { }); const invocation = computed(() => - !initialLoading.value && !errorMessage.value + invocationLoaded.value ? (invocationStore.getInvocationById(props.invocationId) as WorkflowInvocationElementView) : null ); @@ -107,14 +107,17 @@ const invocationStateSuccess = computed(() => { const workflowStore = useWorkflowStore(); -const isDeletedWorkflow = computed(() => getWorkflow()?.deleted === true); -const workflowVersion = computed(() => getWorkflow()?.version); +const workflow = ref(undefined); +const isDeletedWorkflow = computed(() => workflow.value?.deleted === true); +const workflowVersion = computed(() => workflow.value?.version); onMounted(async () => { try { await invocationStore.fetchInvocationForId({ id: props.invocationId }); - initialLoading.value = false; + invocationLoaded.value = true; if (invocation.value) { + await workflowStore.fetchWorkflowForInstanceId(invocation.value.workflow_id); + workflow.value = workflowStore.getStoredWorkflowByInstanceId(invocation.value.workflow_id); await pollStepStatesUntilTerminal(); await pollJobStatesUntilTerminal(); } @@ -151,23 +154,8 @@ function onCancel() { function cancelWorkflowSchedulingLocal() { cancelWorkflowScheduling(props.invocationId).then(onCancel).catch(onError); } - -function getWorkflow() { - return invocation.value?.workflow_id - ? (workflowStore.getStoredWorkflowByInstanceId( - invocation.value?.workflow_id - ) as unknown as StoredWorkflowDetailed) - : undefined; -} - -function getWorkflowId() { - return invocation.value?.workflow_id - ? workflowStore.getStoredWorkflowIdByInstanceId(invocation.value?.workflow_id) - : undefined; -} - function getWorkflowName() { - return workflowStore.getStoredWorkflowNameByInstanceId(invocation.value?.workflow_id || ""); + return workflow.value?.name || "..."; } @@ -202,13 +190,13 @@ function getWorkflowName() { -
+
Workflow Version: {{ workflowVersion + 1 }} - +
+ :to="`/workflows/edit?id=${workflow.id}&version=${workflowVersion}`"> Edit + + + diff --git a/client/src/components/WorkflowInvocationState/WorkflowStepTitle.vue b/client/src/components/WorkflowInvocationState/WorkflowStepTitle.vue index 1253d73e3e40..0a8d5963580b 100644 --- a/client/src/components/WorkflowInvocationState/WorkflowStepTitle.vue +++ b/client/src/components/WorkflowInvocationState/WorkflowStepTitle.vue @@ -1,8 +1,11 @@ diff --git a/client/src/stores/workflowStore.ts b/client/src/stores/workflowStore.ts index b757fe868b20..2cd194a093c1 100644 --- a/client/src/stores/workflowStore.ts +++ b/client/src/stores/workflowStore.ts @@ -12,6 +12,7 @@ export interface Workflow { step_count?: number; latest_id?: string; version: number; + deleted?: boolean; } export const useWorkflowStore = defineStore("workflowStore", () => {