Skip to content

Commit

Permalink
Merge pull request #19298 from ahmedhamidawan/consistent_tabs_invocat…
Browse files Browse the repository at this point in the history
…ion_view

[24.2] Fix inconsistent tab handling in invocation view
  • Loading branch information
davelopez authored Dec 11, 2024
2 parents 9e266d4 + eade161 commit 85d3631
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { BButtonGroup, BCol, BContainer, BRow } from "bootstrap-vue";
import { BAlert, BButtonGroup, BCol, BContainer, BRow } from "bootstrap-vue";
import type { VisualizationSpec } from "vega-embed";
import { computed, ref, watch } from "vue";
import { type ComputedRef } from "vue";
Expand All @@ -8,16 +8,16 @@ import { type components, GalaxyApi } from "@/api";
import { getAppRoot } from "@/onload/loadConfig";
import { errorMessageAsString } from "@/utils/simple-error";
import LoadingSpan from "../LoadingSpan.vue";
import HelpText from "@/components/Help/HelpText.vue";
const VegaWrapper = () => import("./VegaWrapper.vue");
const props = defineProps({
invocationId: {
type: String,
required: true,
},
});
interface Props {
invocationId: string;
notTerminal?: boolean;
}
const props = defineProps<Props>();
const groupBy = ref<"tool_id" | "step_id">("tool_id");
const timing = ref<"seconds" | "minutes" | "hours">("seconds");
Expand All @@ -44,7 +44,11 @@ async function fetchMetrics() {
}
}
watch(props, () => fetchMetrics(), { immediate: true });
watch(
() => props.invocationId,
() => fetchMetrics(),
{ immediate: true }
);
function itemToX(item: components["schemas"]["WorkflowJobMetric"]) {
if (groupBy.value === "tool_id") {
Expand Down Expand Up @@ -380,6 +384,9 @@ const groupByInTitles = computed(() => {

<template>
<div>
<BAlert v-if="props.notTerminal" variant="warning" show>
<LoadingSpan message="Metrics will update and change as the workflow progresses." />
</BAlert>
<BContainer>
<BRow align-h="end" class="mb-2">
<BButtonGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const selectors = {
bAlertStub: "balert-stub",
spanElement: "span",
invocationReportTab: '[titleitemclass="invocation-report-tab"]',
invocationExportTab: '[titleitemclass="invocation-export-tab"]',
fullPageHeading: "anonymous-stub[h1='true']",
};

Expand Down Expand Up @@ -177,16 +178,20 @@ describe("WorkflowInvocationState check invocation and job terminal states", ()
});
});

describe("WorkflowInvocationState check 'Report' tab disabled state and header", () => {
it("determines that 'Report' tab is disabled for non-terminal invocation", async () => {
describe("WorkflowInvocationState check 'Report' and 'Export' tab disabled state and header", () => {
it("for non-terminal invocation", async () => {
const wrapper = await mountWorkflowInvocationState("non-terminal-id");
const reportTab = wrapper.find(selectors.invocationReportTab);
expect(reportTab.attributes("disabled")).toBe("true");
const exportTab = wrapper.find(selectors.invocationExportTab);
expect(exportTab.attributes("disabled")).toBe("true");
});
it("determines that 'Report' tab is not disabled for terminal invocation", async () => {
it("for terminal invocation", async () => {
const wrapper = await mountWorkflowInvocationState(invocationData.id);
const reportTab = wrapper.find(selectors.invocationReportTab);
expect(reportTab.attributes("disabled")).toBeUndefined();
const exportTab = wrapper.find(selectors.invocationExportTab);
expect(exportTab.attributes("disabled")).toBeUndefined();
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,22 @@ watch(
);
const workflowStore = useWorkflowStore();
const reportTabDisabled = computed(
const tabsDisabled = computed(
() =>
!invocationStateSuccess.value ||
!invocation.value ||
!workflowStore.getStoredWorkflowByInstanceId(invocation.value.workflow_id)
);
/** Tooltip message for the report tab when it is disabled */
const disabledReportTooltip = computed(() => {
/** Tooltip message for the a tab when it is disabled */
const disabledTabTooltip = computed(() => {
const state = invocationState.value;
if (state != "scheduled") {
return `This workflow is not currently scheduled. The current state is ${state}. Once the workflow is fully scheduled and jobs have complete this option will become available.`;
return `This workflow is not currently scheduled. The current state is ${state}. Once the workflow is fully scheduled and jobs have complete any disabled tabs will become available.`;
} else if (runningCount.value != 0) {
return `The workflow invocation still contains ${runningCount.value} running job(s). Once these jobs have completed this option will become available.`;
return `The workflow invocation still contains ${runningCount.value} running job(s). Once these jobs have completed any disabled tabs will become available.`;
} else {
return "Steps for this workflow are still running. A report will be available once complete.";
return "Steps for this workflow are still running. Any disabled tabs will be available once complete.";
}
});
Expand Down Expand Up @@ -332,45 +332,43 @@ async function onCancel() {
</BTab> -->
<BTab
v-if="!props.isSubworkflow"
title="Report"
title-item-class="invocation-report-tab"
:disabled="reportTabDisabled"
:disabled="tabsDisabled"
:lazy="reportLazy"
:active.sync="reportActive">
<template v-slot:title>
<span>Report</span>
<BBadge
v-if="reportTabDisabled"
v-b-tooltip.hover.noninteractive
:title="disabledReportTooltip"
variant="warning">
<FontAwesomeIcon :icon="faExclamation" />
</BBadge>
</template>
<InvocationReport v-if="invocationStateSuccess" :invocation-id="invocation.id" />
</BTab>
<BTab title="Export" title-item-class="invocation-export-tab" lazy>
<BTab title="Export" title-item-class="invocation-export-tab" :disabled="tabsDisabled" lazy>
<div v-if="invocationAndJobTerminal">
<WorkflowInvocationExportOptions :invocation-id="invocation.id" />
</div>
<BAlert v-else variant="info" show>
<LoadingSpan message="Waiting to complete invocation" />
</BAlert>
</BTab>
<BTab title="Metrics" :lazy="true">
<WorkflowInvocationMetrics :invocation-id="invocation.id"></WorkflowInvocationMetrics>
<WorkflowInvocationMetrics :invocation-id="invocation.id" :not-terminal="!invocationAndJobTerminal" />
</BTab>
<template v-slot:tabs-end>
<BButton
v-if="!props.isFullPage && !invocationAndJobTerminal"
v-b-tooltip.noninteractive.hover
class="ml-auto my-1"
title="Cancel scheduling of workflow invocation"
data-description="cancel invocation button"
size="sm"
@click="onCancel">
<FontAwesomeIcon :icon="faTimes" fixed-width />
Cancel Workflow
</BButton>
<div class="ml-auto d-flex align-items-center">
<BBadge
v-if="tabsDisabled"
v-b-tooltip.hover.noninteractive
class="mr-1"
:title="disabledTabTooltip"
variant="primary">
<FontAwesomeIcon :icon="faExclamation" />
</BBadge>
<BButton
v-if="!props.isFullPage && !invocationAndJobTerminal"
v-b-tooltip.noninteractive.hover
class="my-1"
title="Cancel scheduling of workflow invocation"
data-description="cancel invocation button"
size="sm"
@click="onCancel">
<FontAwesomeIcon :icon="faTimes" fixed-width />
Cancel Workflow
</BButton>
</div>
</template>
</BTabs>
</div>
Expand All @@ -387,9 +385,10 @@ async function onCancel() {

<style lang="scss">
// To show the tooltip on the disabled report tab badge
.invocation-report-tab {
.invocation-report-tab,
.invocation-export-tab {
.nav-link.disabled {
pointer-events: auto !important;
background-color: #e9edf0;
}
}
</style>
Expand Down
2 changes: 2 additions & 0 deletions lib/galaxy_test/selenium/test_workflow_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class TestWorkflowRun(SeleniumTestCase, UsesHistoryItemAssertions, RunsWorkflows
def test_workflow_export_file_rocrate(self):
self._setup_simple_invocation_for_export_testing()
invocations = self.components.invocations
self.workflow_run_wait_for_ok(hid=2)
invocations.export_tab.wait_for_and_click()
self.screenshot("invocation_export_formats")
invocations.export_output_format(type="ro-crate").wait_for_and_click()
Expand All @@ -60,6 +61,7 @@ def test_workflow_export_file_rocrate(self):
def test_workflow_export_file_native(self):
self._setup_simple_invocation_for_export_testing()
invocations = self.components.invocations
self.workflow_run_wait_for_ok(hid=2)
invocations.export_tab.wait_for_and_click()
self.screenshot("invocation_export_formats")
invocations.export_output_format(type="default-file").wait_for_and_click()
Expand Down

0 comments on commit 85d3631

Please sign in to comment.