Skip to content

Commit

Permalink
Refactor workflow step toward TS & reuse.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmchilton committed Nov 21, 2023
1 parent 3a143d6 commit 5291b69
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { isEmpty } from "@/utils/utils";
import WorkflowTree from "./WorkflowTree.vue";
import LoadingSpan from "@/components/LoadingSpan.vue";
import WorkflowStepIcon from "@/components/WorkflowInvocationState/WorkflowStepIcon.vue";
import WorkflowStepTitle from "@/components/WorkflowInvocationState/WorkflowStepTitle.vue";
interface WorkflowDisplayProps {
workflowId: string;
Expand Down Expand Up @@ -102,7 +104,13 @@ onMounted(async () => {
</b-alert>
<div v-if="itemContent !== null">
<div v-for="step in itemContent?.steps" :key="step.order_index" class="mb-2">
<div>Step {{ step.order_index + 1 }}: {{ step.label }}</div>
<WorkflowStepIcon v-if="step.type" :step-type="step.type" />
<WorkflowStepTitle
:step-tool-id="step.tool_id"
:step-subworkflow-id="step.subworkflow_id"
:step-label="step.label"
:step-type="step.type"
:step-index="step.order_index" />
<WorkflowTree :input="step" :skip-head="true" />
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
<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">
<i :class="'portlet-title-icon fa mr-1 ' + stepIcon"></i>
<WorkflowStepIcon :class="portlet - title - icon" :step-type="workflowStepType" />
<span class="portlet-title-text">
<u class="step-title">{{ stepLabel }}</u>
<u class="step-title">
<WorkflowStepTitle v-bind="titleProps(workflowStep.id)" />
</u>
</span>
<FontAwesomeIcon class="float-right" :icon="expanded ? 'fa-chevron-up' : 'fa-chevron-down'" />
</div>
Expand Down Expand Up @@ -61,7 +63,7 @@
<li
v-for="stepInput in Object.values(workflowStep.input_steps)"
:key="stepInput.source_step">
{{ labelForWorkflowStep(stepInput.source_step) }}
<WorkflowStepTitle v-bind="titleProps(stepInput.source_step)" />
</li>
</ul>
</div>
Expand Down Expand Up @@ -91,14 +93,12 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import GenericHistoryItem from "components/History/Content/GenericItem";
import LoadingSpan from "components/LoadingSpan";
import { InvocationStepProvider } from "components/providers";
import WorkflowIcons from "components/Workflow/icons";
import { mapActions, mapState } from "pinia";
import { useToolStore } from "stores/toolStore";
import { useWorkflowStore } from "stores/workflowStore";
import { mapActions as vuexMapActions, mapGetters } from "vuex";
import JobStep from "./JobStep";
import ParameterStep from "./ParameterStep";
import WorkflowStepIcon from "./WorkflowStepIcon";
import WorkflowStepTitle from "./WorkflowStepTitle";
library.add(faChevronUp, faChevronDown);
Expand All @@ -110,6 +110,8 @@ export default {
ParameterStep,
InvocationStepProvider,
GenericHistoryItem,
WorkflowStepIcon,
WorkflowStepTitle,
WorkflowInvocationState: () => import("components/WorkflowInvocationState/WorkflowInvocationState"),
},
props: {
Expand All @@ -124,8 +126,6 @@ export default {
};
},
computed: {
...mapState(useWorkflowStore, ["getStoredWorkflowByInstanceId"]),
...mapState(useToolStore, ["getToolForId", "getToolNameById"]),
...mapGetters(["getInvocationStepById"]),
isReady() {
return this.invocation.steps.length > 0;
Expand All @@ -142,59 +142,23 @@ export default {
isDataStep() {
return ["data_input", "data_collection_input"].includes(this.workflowStepType);
},
stepIcon() {
return WorkflowIcons[this.workflowStepType];
},
stepLabel() {
return this.labelForWorkflowStep(this.workflowStep.id);
},
},
created() {
this.fetchTool();
this.fetchSubworkflow();
},
methods: {
...mapActions(useWorkflowStore, ["fetchWorkflowForInstanceId"]),
...mapActions(useToolStore, ["fetchToolForId"]),
...vuexMapActions(["fetchInvocationStepById"]),
fetchTool() {
if (this.workflowStep.tool_id && !this.getToolForId(this.workflowStep.tool_id)) {
this.fetchToolForId(this.workflowStep.tool_id);
}
},
fetchSubworkflow() {
if (this.workflowStep.workflow_id) {
this.fetchWorkflowForInstanceId(this.workflowStep.workflow_id);
}
},
toggleStep() {
this.expanded = !this.expanded;
},
labelForWorkflowStep(stepIndex) {
titleProps(stepIndex) {
const invocationStep = this.invocation.steps[stepIndex];
const workflowStep = this.workflow.steps[stepIndex];
const oneBasedStepIndex = stepIndex + 1;
if (invocationStep && invocationStep.workflow_step_label) {
return `Step ${oneBasedStepIndex}: ${invocationStep.workflow_step_label}`;
}
const workflowStepType = workflowStep.type;
switch (workflowStepType) {
case "tool":
return `Step ${oneBasedStepIndex}: ${this.getToolNameById(workflowStep.tool_id)}`;
case "subworkflow": {
const subworkflow = this.getStoredWorkflowByInstanceId(workflowStep.workflow_id);
const label = subworkflow ? subworkflow.name : "Subworkflow";
return `Step ${oneBasedStepIndex}: ${label}`;
}
case "parameter_input":
return `Step ${oneBasedStepIndex}: Parameter input`;
case "data_input":
return `Step ${oneBasedStepIndex}: Data input`;
case "data_collection_input":
return `Step ${oneBasedStepIndex}: Data collection input`;
default:
return `Step ${oneBasedStepIndex}: Unknown step type '${workflowStepType}'`;
}
const rval = {
stepIndex: stepIndex,
stepLabel: invocationStep && invocationStep.workflow_step_label,
stepType: workflowStep.type,
stepToolId: workflowStep.tool_id,
stepSubworkflowId: workflowStep.workflow_id,
};
return rval;
},
},
};
Expand Down
22 changes: 22 additions & 0 deletions client/src/components/WorkflowInvocationState/WorkflowStepIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts" setup>
import { computed } from "vue";
import WorkflowIcons from "@/components/Workflow/icons";
interface WorkflowStepIconProps {
stepType: "tool" | "data_input" | "data_collection_input" | "subworkflow" | "parameter_input" | "pause";
}
const props = defineProps<WorkflowStepIconProps>();
const stepIcon = computed(() => {
return WorkflowIcons[props.stepType];
});
const cssClasses = computed(() => {
return ["fa", "mr-1", stepIcon.value];
});
</script>

<template>
<i :class="cssClasses"></i>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<script setup lang="ts">
import { computed, watch } from "vue";
import { useToolStore } from "@/stores/toolStore";
import { useWorkflowStore } from "@/stores/workflowStore";
interface WorkflowInvocationStepTitleProps {
stepIndex: number;
stepLabel?: string;
stepType: string;
stepToolId?: string;
stepSubworkflowId?: string;
}
const props = defineProps<WorkflowInvocationStepTitleProps>();
const workflowStore = useWorkflowStore();
const toolStore = useToolStore();
const subWorkflow = computed(() => {
if (props.stepSubworkflowId) {
return workflowStore.getStoredWorkflowByInstanceId(props.stepSubworkflowId);
}
return null;
});
const toolName = computed(() => {
if (props.stepToolId) {
return toolStore.getToolNameById(props.stepToolId);
}
return "";
});
const title = computed(() => {
const oneBasedStepIndex = props.stepIndex + 1;
if (props.stepLabel) {
return `Step ${oneBasedStepIndex}: ${props.stepLabel}`;
}
const workflowStepType = props.stepType;
switch (workflowStepType) {
case "tool":
return `Step ${oneBasedStepIndex}: ${toolName.value}`;
case "subworkflow": {
const subworkflow = subWorkflow.value;
const label = subworkflow ? subworkflow.name : "Subworkflow";
return `Step ${oneBasedStepIndex}: ${label}`;
}
case "parameter_input":
return `Step ${oneBasedStepIndex}: Parameter input`;
case "data_input":
return `Step ${oneBasedStepIndex}: Data input`;
case "data_collection_input":
return `Step ${oneBasedStepIndex}: Data collection input`;
default:
return `Step ${oneBasedStepIndex}: Unknown step type '${workflowStepType}'`;
}
});
function initStores() {
if (props.stepToolId && !toolStore.getToolForId(props.stepToolId)) {
toolStore.fetchToolForId(props.stepToolId);
}
if (props.stepSubworkflowId) {
workflowStore.fetchWorkflowForInstanceId(props.stepSubworkflowId);
}
}
watch(props, () => {
initStores();
});
initStores();
</script>

<template>
<span>{{ title }}</span>
</template>
1 change: 1 addition & 0 deletions lib/galaxy/managers/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,7 @@ def do_inputs(inputs, values, prefix, step, other_values=None):
for step in workflow.steps:
step_dict = {}
step_dict["order_index"] = step.order_index
step_dict["type"] = step.type
if step.annotations:
step_dict["annotation"] = step.annotations[0].annotation
try:
Expand Down

0 comments on commit 5291b69

Please sign in to comment.