Skip to content

Commit

Permalink
Expose more tool information / navigability in UI.
Browse files Browse the repository at this point in the history
We had a specific request that job parameter displays that "For: Job parameters as table. The output doesn't show what tool was used, it would be good if it did." I don't want to populate the widget directly with information because it might disrupt the flow of the report but I agree it should be navigable.

So I have augmented the widget such that is a title is added - a little info icon will appear in the title span that will show a link to the tool and render the name as it would appear in the tool form. This information should be available in other places for the same reason IMO. So this popover is now used in the job metrics table the same way as well as in the workflow step display Markdown component and in the invocation step display component.
  • Loading branch information
jmchilton committed Dec 22, 2023
1 parent 9952f15 commit 05c0cc1
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 8 deletions.
30 changes: 27 additions & 3 deletions client/src/components/Markdown/Elements/JobMetrics.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
<script setup lang="ts">
import { computed, watch } from "vue";
import { useJobStore } from "@/stores/jobStore";
import JobMetrics from "@/components/JobMetrics/JobMetrics.vue";
import ToolLinkPopover from "@/components/Tool/ToolLinkPopover.vue";
interface JobMetricsProps {
jobId: string;
title?: string;
footer?: string;
}
withDefaults(defineProps<JobMetricsProps>(), {
title: null,
footer: null,
const props = withDefaults(defineProps<JobMetricsProps>(), {
title: undefined,
footer: undefined,
});
const jobStore = useJobStore();
const toolId = computed(() => {
return jobStore.getJob(props.jobId)?.tool_id;
});
const toolVersion = computed(() => {
return jobStore.getJob(props.jobId)?.tool_version;
});
watch(
props,
() => {
jobStore.fetchJob(props.jobId);
},
{ immediate: true }
);
</script>

<template>
<b-card nobody>
<b-card-title v-if="title">
<b>{{ title }}</b>
<icon ref="info" icon="info-circle" size="sm" />
<ToolLinkPopover :target="() => $refs.info" :tool-id="toolId" :tool-version="toolVersion" />
</b-card-title>
<JobMetrics
class="job-metrics"
Expand Down
30 changes: 27 additions & 3 deletions client/src/components/Markdown/Elements/JobParameters.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<script setup lang="ts">
import { computed, watch } from "vue";
import { useJobStore } from "@/stores/jobStore";
import JobParameters from "@/components/JobParameters/JobParameters.vue";
import ToolLinkPopover from "@/components/Tool/ToolLinkPopover.vue";
interface JobParametersProps {
jobId: string;
Expand All @@ -8,17 +13,36 @@ interface JobParametersProps {
footer?: string;
}
withDefaults(defineProps<JobParametersProps>(), {
const props = withDefaults(defineProps<JobParametersProps>(), {
param: undefined,
title: null,
footer: null,
title: undefined,
footer: undefined,
});
const jobStore = useJobStore();
const toolId = computed(() => {
return jobStore.getJob(props.jobId)?.tool_id;
});
const toolVersion = computed(() => {
return jobStore.getJob(props.jobId)?.tool_version;
});
watch(
props,
() => {
jobStore.fetchJob(props.jobId);
},
{ immediate: true }
);
</script>

<template>
<b-card nobody>
<b-card-title v-if="title">
<b>{{ title }}</b>
<icon ref="info" icon="info-circle" size="sm" />
<ToolLinkPopover :target="() => $refs.info" :tool-id="toolId" :tool-version="toolVersion" />
</b-card-title>
<JobParameters class="job-parameters" :job-id="jobId" :param="param" :include-title="false" />
<b-card-footer v-if="footer">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { isEmpty } from "@/utils/utils";
import WorkflowTree from "./WorkflowTree.vue";
import LoadingSpan from "@/components/LoadingSpan.vue";
import ToolLinkPopover from "@/components/Tool/ToolLinkPopover.vue";
import WorkflowStepIcon from "@/components/WorkflowInvocationState/WorkflowStepIcon.vue";
import WorkflowStepTitle from "@/components/WorkflowInvocationState/WorkflowStepTitle.vue";
Expand Down Expand Up @@ -104,7 +105,14 @@ onMounted(async () => {
</b-alert>
<div v-if="itemContent !== null">
<div v-for="step in itemContent?.steps" :key="step.order_index" class="mb-2">
<WorkflowStepIcon v-if="step.type" :step-type="step.type" />
<span :id="`step-icon-${step.order_index}`">
<WorkflowStepIcon v-if="step.type" :step-type="step.type" />
</span>
<ToolLinkPopover
v-if="step.type == 'tool'"
:target="`step-icon-${step.order_index}`"
:tool-id="step.tool_id"
:tool-version="step.tool_version" />
<WorkflowStepTitle
:step-tool-id="step.tool_id"
:step-subworkflow-id="step.subworkflow_id"
Expand Down
41 changes: 41 additions & 0 deletions client/src/components/Tool/ToolLink.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<script setup lang="ts">
import { computed, watch } from "vue";
import { useToolStore } from "@/stores/toolStore";
const toolStore = useToolStore();
interface ToolLinkProps {
toolId: string;
toolVersion: string;
}
const props = defineProps<ToolLinkProps>();
const toolName = computed(() => {
if (props.toolId) {
return toolStore.getToolNameById(props.toolId);
}
return "";
});
const toolLink = computed(() => {
return `/root?tool_id=${props.toolId}&tool_version=${props.toolVersion}`;
});
watch(
props,
() => {
if (props.toolId && !toolStore.getToolForId(props.toolId)) {
toolStore.fetchToolForId(props.toolId);
}
},
{ immediate: true }
);
</script>

<template>
<router-link :to="toolLink">
<b>{{ toolName || toolId }}</b> (Galaxy Version {{ toolVersion }})
</router-link>
</template>
24 changes: 24 additions & 0 deletions client/src/components/Tool/ToolLinkPopover.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
import ToolLink from "./ToolLink.vue";
interface ToolLinkPopoverProps {
target: string | Function;
toolId?: string;
toolVersion?: string;
}
withDefaults(defineProps<ToolLinkPopoverProps>(), {
toolId: null,
toolVersion: null,
});
// default boundary of scrollParent doesn't work well at all in the workflow display list
const boundary = "window";
</script>

<template>
<b-popover v-if="toolId" :boundary="boundary" :target="target" triggers="hover">
Tool:
<ToolLink :tool-id="toolId" :tool-version="toolVersion || 'latest'" />
</b-popover>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
<div class="d-flex" :data-step="workflowStep.id">
<div class="ui-portlet-section" style="width: 100%">
<div class="portlet-header portlet-title portlet-operations cursor-pointer" @click="toggleStep">
<WorkflowStepIcon class="portlet-title-icon" :step-type="workflowStepType" />
<span :id="`step-icon-${workflowStep.id}`">
<WorkflowStepIcon class="portlet-title-icon" :step-type="workflowStepType" />
</span>
<ToolLinkPopover :target="`step-icon-${workflowStep.id}`" v-bind="toolProps(workflowStep.id)" />
<span class="portlet-title-text">
<u class="step-title">
<WorkflowStepTitle v-bind="titleProps(workflowStep.id)" />
Expand Down Expand Up @@ -93,6 +96,7 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import GenericHistoryItem from "components/History/Content/GenericItem";
import LoadingSpan from "components/LoadingSpan";
import { InvocationStepProvider } from "components/providers";
import ToolLinkPopover from "components/Tool/ToolLinkPopover";
import { mapActions as vuexMapActions, mapGetters } from "vuex";
import JobStep from "./JobStep";
Expand All @@ -110,6 +114,7 @@ export default {
ParameterStep,
InvocationStepProvider,
GenericHistoryItem,
ToolLinkPopover,
WorkflowStepIcon,
WorkflowStepTitle,
WorkflowInvocationState: () => import("components/WorkflowInvocationState/WorkflowInvocationState"),
Expand Down Expand Up @@ -148,6 +153,13 @@ export default {
toggleStep() {
this.expanded = !this.expanded;
},
toolProps(stepIndex) {
const workflowStep = this.workflow.steps[stepIndex];
return {
toolId: workflowStep.tool_id,
toolVersion: workflowStep.tool_version,
};
},
titleProps(stepIndex) {
const invocationStep = this.invocation.steps[stepIndex];
const workflowStep = this.workflow.steps[stepIndex];
Expand Down
2 changes: 2 additions & 0 deletions client/src/stores/jobStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { getAppRoot } from "@/onload/loadConfig";
/* interfaces */
interface Job {
id: string;
tool_id: string;
tool_version: string;
}
interface JobDef {
tool_id: string;
Expand Down
2 changes: 2 additions & 0 deletions lib/galaxy/managers/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,8 @@ def do_inputs(inputs, values, prefix, step, other_values=None):
continue
if step.type == "tool":
tool = trans.app.toolbox.get_tool(step.tool_id, step.tool_version)
step_dict["tool_id"] = step.tool_id
step_dict["tool_version"] = step.tool_version
step_dict["label"] = step.label or tool.name
step_dict["inputs"] = do_inputs(tool.inputs, step.state.inputs, "", step)
elif step.type == "subworkflow":
Expand Down
1 change: 1 addition & 0 deletions lib/galaxy/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1822,6 +1822,7 @@ def to_dict(self, view="collection", system_details=False):
else:
rval = super().to_dict(view=view)
rval["tool_id"] = self.tool_id
rval["tool_version"] = self.tool_version
rval["history_id"] = self.history_id
if system_details or view == "admin_job_list":
# System level details that only admins should have.
Expand Down

0 comments on commit 05c0cc1

Please sign in to comment.