mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
Split up workflow output control and output visible controls
This commit is contained in:
@@ -18,7 +18,7 @@ describe("FormOutputLabel", () => {
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
const stepOne = { id: 0, workflow_outputs: outputs };
|
||||
const stepOne = { id: 0, outputs: [{ name: "output-name" }], workflow_outputs: outputs };
|
||||
const pinia = createPinia();
|
||||
setActivePinia(pinia);
|
||||
wrapper = mount(FormOutputLabel, {
|
||||
@@ -29,7 +29,7 @@ describe("FormOutputLabel", () => {
|
||||
localVue,
|
||||
pinia,
|
||||
});
|
||||
const stepTwo = { id: 1, workflow_outputs: outputs };
|
||||
const stepTwo = { id: 1, outputs: [{ name: "other-name" }], workflow_outputs: outputs };
|
||||
wrapperOther = mount(FormOutputLabel, {
|
||||
propsData: {
|
||||
name: "other-name",
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue, { computed } from "vue";
|
||||
import Vue from "vue";
|
||||
import BootstrapVue from "bootstrap-vue";
|
||||
import { UntypedParameters } from "components/Workflow/Editor/modules/parameters";
|
||||
import LintSection from "components/Workflow/Editor/LintSection";
|
||||
@@ -94,6 +94,7 @@ import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { faMagic, faExclamationTriangle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { useWorkflowStepStore } from "@/stores/workflowStepStore";
|
||||
import { DatatypesMapperModel } from "@/components/Datatypes/model";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
Vue.use(BootstrapVue);
|
||||
|
||||
@@ -131,9 +132,8 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const stepStore = useWorkflowStepStore();
|
||||
const hasActiveOutputs = computed(() => Object.keys(stepStore.workflowOutputs).length > 0);
|
||||
setup() {
|
||||
const { hasActiveOutputs } = storeToRefs(useWorkflowStepStore());
|
||||
return { hasActiveOutputs };
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
:datatypes-mapper="datatypesMapper"
|
||||
v-on="$listeners"
|
||||
@stopDragging="onStopDragging"
|
||||
@onToggle="onToggleOutput"
|
||||
@onChange="onChange" />
|
||||
</div>
|
||||
</draggable-wrapper>
|
||||
@@ -109,7 +108,6 @@ import Recommendations from "@/components/Workflow/Editor/Recommendations.vue";
|
||||
import NodeInput from "@/components/Workflow/Editor/NodeInput.vue";
|
||||
import NodeOutput from "@/components/Workflow/Editor/NodeOutput.vue";
|
||||
import DraggableWrapper from "@/components/Workflow/Editor/DraggablePan.vue";
|
||||
import { ActiveOutputs } from "./modules/outputs";
|
||||
import { computed, ref } from "vue";
|
||||
import { useNodePosition } from "@/components/Workflow/Editor/composables/useNodePosition";
|
||||
import { useWorkflowStateStore, type XYPosition } from "@/stores/workflowEditorStateStore";
|
||||
@@ -163,7 +161,7 @@ const isLoading = computed(() => Boolean(stateStore.getStepLoadingState(props.id
|
||||
const position = useNodePosition(el, props.id, stateStore);
|
||||
const title = computed(() => props.step.label || props.step.name);
|
||||
const idString = computed(() => `wf-node-step-${props.id}`);
|
||||
const showRule = computed(() => props.step.inputs.length > 0 && props.step.outputs.length > 0);
|
||||
const showRule = computed(() => props.step.inputs?.length > 0 && props.step.outputs?.length > 0);
|
||||
const iconClass = computed(() => `icon fa fa-fw ${WorkflowIcons[props.step.type]}`);
|
||||
const canClone = computed(() => props.step.type !== "subworkflow"); // Why ?
|
||||
const isEnabled = getGalaxyInstance().config.enable_tool_recommendations; // getGalaxyInstance is not reactive
|
||||
@@ -180,7 +178,6 @@ const classes = computed(() => {
|
||||
const style = computed(() => {
|
||||
return { top: props.step.position!.top + "px", left: props.step.position!.left + "px" };
|
||||
});
|
||||
const activeOutputs = new ActiveOutputs();
|
||||
const errors = computed(() => props.step.errors || stateStore.getStepLoadingState(props.id)?.error);
|
||||
const inputs = computed(() => props.step.inputs);
|
||||
const outputs = computed(() => props.step.outputs);
|
||||
@@ -213,10 +210,6 @@ function onClone() {
|
||||
emit("onClone", props.id);
|
||||
}
|
||||
|
||||
function onToggleOutput(name: string) {
|
||||
activeOutputs.toggle(name);
|
||||
}
|
||||
|
||||
function makeActive() {
|
||||
emit("onActivate", props.id);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
<template>
|
||||
<div class="form-row dataRow output-data-row">
|
||||
<div
|
||||
v-if="showCallout"
|
||||
v-if="showCalloutActiveOutput"
|
||||
v-b-tooltip
|
||||
:class="['callout-terminal', output.name]"
|
||||
title="Unchecked outputs will be hidden and are not available as subworkflow outputs."
|
||||
@keyup="onToggle"
|
||||
@click="onToggle">
|
||||
@keyup="onToggleActive"
|
||||
@click="onToggleActive">
|
||||
<i :class="['mark-terminal', activeClass]" />
|
||||
</div>
|
||||
<div
|
||||
v-if="showCalloutVisible"
|
||||
v-b-tooltip
|
||||
:class="['callout-terminal', output.name]"
|
||||
:title="visibleHint"
|
||||
@keyup="onToggleVisible"
|
||||
@click="onToggleVisible">
|
||||
<i :class="['mark-terminal', visibleClass]" />
|
||||
</div>
|
||||
{{ label }}
|
||||
<draggable-wrapper
|
||||
:id="id"
|
||||
@@ -49,6 +58,7 @@ import { ref, computed, watch, nextTick, toRefs } from "vue";
|
||||
import { DatatypesMapperModel } from "@/components/Datatypes/model";
|
||||
import { useWorkflowStateStore } from "@/stores/workflowEditorStateStore";
|
||||
import ConnectionMenu from "@/components/Workflow/Editor/ConnectionMenu";
|
||||
import { useWorkflowStepStore } from "@/stores/workflowStepStore";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -94,6 +104,8 @@ export default {
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const stateStore = useWorkflowStateStore();
|
||||
const stepStore = useWorkflowStepStore();
|
||||
const el = ref(null);
|
||||
const { rootOffset, parentOffset, stepPosition, output, stepId, datatypesMapper } = toRefs(props);
|
||||
const position = useCoordinatePosition(el, rootOffset, parentOffset, stepPosition);
|
||||
@@ -117,11 +129,24 @@ export default {
|
||||
});
|
||||
const { terminal, isMappedOver: isMultiple } = useTerminal(stepId, effectiveOutput, datatypesMapper);
|
||||
|
||||
const workflowOutput = computed(() =>
|
||||
props.workflowOutputs.find((workflowOutput) => workflowOutput.output_name == props.output.name)
|
||||
);
|
||||
const activeClass = computed(() => workflowOutput.value && "mark-terminal-active");
|
||||
const isVisible = computed(() => {
|
||||
const isHidden = `HideDatasetAction${props.output.name}` in props.postJobActions;
|
||||
return !isHidden;
|
||||
});
|
||||
const visibleClass = computed(() => (isVisible.value ? "mark-terminal-visible" : "mark-terminal-hidden"));
|
||||
const visibleHint = computed(() => {
|
||||
if (isVisible.value) {
|
||||
return `Output will be visible in history. Click to hide output.`;
|
||||
} else {
|
||||
return `Output will be hidden in history. Click to make output visible.`;
|
||||
}
|
||||
});
|
||||
const label = computed(() => {
|
||||
const workflowOutput = props.workflowOutputs.find(
|
||||
(workflowOutput) => workflowOutput.output_name == props.output.name
|
||||
);
|
||||
const activeLabel = workflowOutput?.label || props.output.name;
|
||||
const activeLabel = workflowOutput.value?.label || props.output.name;
|
||||
return `${activeLabel} (${extensions.value.join(", ")})`;
|
||||
});
|
||||
|
||||
@@ -140,10 +165,45 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
const stateStore = useWorkflowStateStore();
|
||||
function onToggleActive() {
|
||||
const step = stepStore.getStep(stepId.value);
|
||||
if (workflowOutput.value) {
|
||||
console.log("wfo", workflowOutput.value);
|
||||
step.workflow_outputs = step.workflow_outputs.filter(
|
||||
(workflowOutput) => workflowOutput.output_name !== output.value.name
|
||||
);
|
||||
} else {
|
||||
step.workflow_outputs.push({ output_name: output.value.name });
|
||||
}
|
||||
stepStore.updateStep(step);
|
||||
}
|
||||
|
||||
function onToggleVisible() {
|
||||
const actionKey = `HideDatasetAction${props.output.name}`;
|
||||
const step = stepStore.getStep(stepId.value);
|
||||
if (isVisible.value) {
|
||||
step.post_job_actions = {
|
||||
...step.post_job_actions,
|
||||
[actionKey]: {
|
||||
action_type: "HideDatasetAction",
|
||||
output_name: props.output.name,
|
||||
action_arguments: {},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
const { [actionKey]: ignoreUnused, ...newPostJobActions } = step.post_job_actions;
|
||||
step.post_job_actions = newPostJobActions;
|
||||
}
|
||||
stepStore.updateStep(step);
|
||||
}
|
||||
|
||||
return {
|
||||
el,
|
||||
position,
|
||||
activeClass,
|
||||
visibleClass,
|
||||
visibleHint,
|
||||
isVisible,
|
||||
terminal,
|
||||
isMultiple,
|
||||
label,
|
||||
@@ -153,6 +213,8 @@ export default {
|
||||
toggleChildComponent,
|
||||
closeMenu,
|
||||
effectiveOutput,
|
||||
onToggleActive,
|
||||
onToggleVisible,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
@@ -189,12 +251,11 @@ export default {
|
||||
id() {
|
||||
return `node-${this.stepId}-output-${this.output.name}`;
|
||||
},
|
||||
|
||||
activeClass() {
|
||||
return this.output.activeOutput && "mark-terminal-active";
|
||||
showCalloutActiveOutput() {
|
||||
return this.stepType === "tool" || this.stepType === "subworkflow";
|
||||
},
|
||||
showCallout() {
|
||||
return this.stepType == "tool";
|
||||
showCalloutVisible() {
|
||||
return this.stepType === "tool";
|
||||
},
|
||||
terminalClass() {
|
||||
const cls = "terminal output-terminal";
|
||||
@@ -234,9 +295,6 @@ export default {
|
||||
this.dragY = 0;
|
||||
this.$emit("stopDragging");
|
||||
},
|
||||
onToggle() {
|
||||
this.$emit("onToggle", this.output.name);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
import Vue from "vue";
|
||||
|
||||
export const allLabels = {};
|
||||
|
||||
export class ActiveOutputs {
|
||||
constructor() {
|
||||
this.entries = {};
|
||||
}
|
||||
|
||||
/** Initialize list of active outputs from server response */
|
||||
initialize(outputs, incoming) {
|
||||
this.outputs = outputs;
|
||||
this._refreshIndex();
|
||||
incoming &&
|
||||
incoming.forEach((entry) => {
|
||||
if (entry.label && allLabels[entry.label]) {
|
||||
entry.label = null;
|
||||
}
|
||||
this.add(entry.output_name, entry.label);
|
||||
if (entry.label) {
|
||||
allLabels[entry.label] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Adds a new record to the value stack **/
|
||||
add(name, label) {
|
||||
if (!this.exists(name)) {
|
||||
this.update(name, label);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Toggle an entry */
|
||||
toggle(name) {
|
||||
if (this.exists(name)) {
|
||||
this.remove(name);
|
||||
} else {
|
||||
this.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
/** Change label for an output */
|
||||
labelOutput(outputName, newLabel) {
|
||||
const activeOutput = this.get(outputName);
|
||||
const oldLabel = activeOutput && activeOutput.label;
|
||||
if (newLabel == oldLabel) {
|
||||
return true;
|
||||
}
|
||||
if (this.outputsIndex[outputName] && !allLabels[newLabel]) {
|
||||
const oldLabel = this.update(outputName, newLabel);
|
||||
if (oldLabel && allLabels[oldLabel]) {
|
||||
delete allLabels[oldLabel];
|
||||
}
|
||||
if (newLabel) {
|
||||
allLabels[newLabel] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns the number of added records **/
|
||||
count() {
|
||||
return Object.keys(this.entries).length;
|
||||
}
|
||||
|
||||
/** Return label */
|
||||
get(name) {
|
||||
return this.entries[name];
|
||||
}
|
||||
|
||||
/** Returns true if a record is available for a given key **/
|
||||
exists(name) {
|
||||
return !!this.entries[name];
|
||||
}
|
||||
|
||||
/** Remove an entry given its name */
|
||||
remove(name) {
|
||||
const activeOutput = this.get(name);
|
||||
const activeLabel = activeOutput && activeOutput.label;
|
||||
if (activeLabel && allLabels[activeLabel]) {
|
||||
delete allLabels[activeLabel];
|
||||
}
|
||||
delete this.entries[name];
|
||||
this._updateOutput(name);
|
||||
}
|
||||
|
||||
/** Returns list of all values */
|
||||
getAll() {
|
||||
return Object.values(this.entries);
|
||||
}
|
||||
|
||||
/** Update an active outputs label */
|
||||
update(name, label) {
|
||||
const activeOutput = this.get(name);
|
||||
const oldLabel = activeOutput && activeOutput.label;
|
||||
this.entries[name] = {
|
||||
output_name: name,
|
||||
label: label || null,
|
||||
};
|
||||
this._updateOutput(name);
|
||||
return oldLabel;
|
||||
}
|
||||
|
||||
/** Removes all entries which are not in the parsed dictionary of names */
|
||||
filterOutputs(names) {
|
||||
this.getAll().forEach((wf_output) => {
|
||||
if (!names.includes(wf_output.output_name)) {
|
||||
this.remove(wf_output.output_name);
|
||||
}
|
||||
});
|
||||
this._refreshIndex();
|
||||
}
|
||||
|
||||
/** Update an output */
|
||||
_updateOutput(name) {
|
||||
const output = this.outputsIndex[name];
|
||||
if (output) {
|
||||
const activeOutput = this.get(output.name);
|
||||
Vue.set(output, "activeOutput", !!activeOutput);
|
||||
Vue.set(output, "activeLabel", activeOutput && activeOutput.label);
|
||||
}
|
||||
}
|
||||
|
||||
/** Refreshes dictionary of outputs */
|
||||
_refreshIndex() {
|
||||
this.outputsIndex = {};
|
||||
this.outputs &&
|
||||
this.outputs.forEach((o) => {
|
||||
this.outputsIndex[o.name] = o;
|
||||
this._updateOutput(o.name);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
import { allLabels, ActiveOutputs } from "./outputs";
|
||||
|
||||
describe("Workflow Outputs", () => {
|
||||
it("test output label handling", () => {
|
||||
// Test adding initial node
|
||||
const activeOutputs = new ActiveOutputs();
|
||||
const outputs = [{ name: "output_0" }, { name: "output_1" }, { name: "output_2" }];
|
||||
const incoming = [
|
||||
{ output_name: "output_0", label: "label_0" },
|
||||
{ output_name: "output_1", label: "label_0" },
|
||||
{ output_name: "output_2", label: "label_1" },
|
||||
];
|
||||
activeOutputs.initialize(outputs, incoming);
|
||||
expect(Object.keys(allLabels).length).toBe(2);
|
||||
expect(allLabels["label_0"]).toBe(true);
|
||||
expect(allLabels["label_1"]).toBe(true);
|
||||
expect(activeOutputs.count()).toBe(3);
|
||||
expect(activeOutputs.entries["output_0"].label).toBe("label_0");
|
||||
expect(activeOutputs.entries["output_1"].label).toBe(null);
|
||||
expect(activeOutputs.entries["output_2"].label).toBe("label_1");
|
||||
|
||||
// Test adding additional node
|
||||
const activeOutputs_1 = new ActiveOutputs();
|
||||
const outputs_1 = [{ name: "output_0" }, { name: "output_1" }, { name: "output_2" }];
|
||||
const incoming_1 = [
|
||||
{ output_name: "output_0", label: "label_0" },
|
||||
{ output_name: "output_1", label: "label_0" },
|
||||
{ output_name: "output_2", label: "label_2" },
|
||||
];
|
||||
activeOutputs_1.initialize(outputs_1, incoming_1);
|
||||
expect(Object.keys(allLabels).length).toBe(3);
|
||||
expect(allLabels["label_0"]).toBe(true);
|
||||
expect(allLabels["label_1"]).toBe(true);
|
||||
expect(allLabels["label_2"]).toBe(true);
|
||||
expect(activeOutputs_1.count()).toBe(3);
|
||||
expect(activeOutputs_1.entries["output_0"].label).toBe(null);
|
||||
expect(activeOutputs_1.entries["output_1"].label).toBe(null);
|
||||
expect(activeOutputs_1.entries["output_2"].label).toBe("label_2");
|
||||
|
||||
// Test toggle / removal
|
||||
activeOutputs_1.toggle("output_0");
|
||||
expect(activeOutputs_1.count()).toBe(2);
|
||||
activeOutputs_1.toggle("output_1");
|
||||
expect(activeOutputs_1.count()).toBe(1);
|
||||
activeOutputs_1.toggle("output_0");
|
||||
expect(activeOutputs_1.count()).toBe(2);
|
||||
activeOutputs_1.toggle("output_1");
|
||||
expect(activeOutputs_1.count()).toBe(3);
|
||||
|
||||
// Test output filtering
|
||||
activeOutputs.filterOutputs(["output_0", "output_2"]);
|
||||
expect(activeOutputs.count()).toBe(2);
|
||||
expect(activeOutputs.entries["output_0"].label).toBe("label_0");
|
||||
expect(activeOutputs.entries["output_1"]).toBe(undefined);
|
||||
expect(activeOutputs.entries["output_2"].label).toBe("label_1");
|
||||
|
||||
// Update output label
|
||||
const response = activeOutputs.labelOutput("output_0", "label_3");
|
||||
expect(response).toBe(true);
|
||||
expect(activeOutputs.entries["output_0"].label).toBe("label_3");
|
||||
const response_1 = activeOutputs.labelOutput("output_0", "label_1");
|
||||
expect(response_1).toBe(false);
|
||||
expect(activeOutputs.entries["output_0"].label).toBe("label_3");
|
||||
|
||||
// Test output removal
|
||||
activeOutputs.filterOutputs([]);
|
||||
expect(Object.keys(allLabels).length).toBe(1);
|
||||
});
|
||||
});
|
||||
@@ -19,8 +19,7 @@
|
||||
"extensions": [
|
||||
"input"
|
||||
],
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -66,8 +65,7 @@
|
||||
"tabular"
|
||||
],
|
||||
"type": "data",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -109,8 +107,7 @@
|
||||
],
|
||||
"collection": true,
|
||||
"collection_type": "list",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -146,8 +143,7 @@
|
||||
],
|
||||
"collection": true,
|
||||
"collection_type": "list:list",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -183,8 +179,7 @@
|
||||
],
|
||||
"collection": true,
|
||||
"collection_type": "paired",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -216,8 +211,7 @@
|
||||
"label": "integer parameter input",
|
||||
"type": "integer",
|
||||
"optional": false,
|
||||
"parameter": true,
|
||||
"activeOutput": false
|
||||
"parameter": true
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -263,8 +257,7 @@
|
||||
"tabular"
|
||||
],
|
||||
"type": "data",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -319,8 +312,7 @@
|
||||
"optional": false,
|
||||
"collection": true,
|
||||
"collection_type": null,
|
||||
"collection_type_source": null,
|
||||
"activeOutput": false
|
||||
"collection_type_source": null
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -376,8 +368,7 @@
|
||||
],
|
||||
"type": "data",
|
||||
"optional": false,
|
||||
"label": "input dataset(s) (extracted element)",
|
||||
"activeOutput": false
|
||||
"label": "input dataset(s) (extracted element)"
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -416,8 +407,7 @@
|
||||
"extensions": [
|
||||
"input"
|
||||
],
|
||||
"optional": true,
|
||||
"activeOutput": false
|
||||
"optional": true
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -449,8 +439,7 @@
|
||||
"label": "text parameter input",
|
||||
"type": "text",
|
||||
"optional": false,
|
||||
"parameter": true,
|
||||
"activeOutput": false
|
||||
"parameter": true
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -497,8 +486,7 @@
|
||||
"txt"
|
||||
],
|
||||
"type": "data",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -564,8 +552,7 @@
|
||||
"txt"
|
||||
],
|
||||
"type": "data",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -618,8 +605,7 @@
|
||||
"txt"
|
||||
],
|
||||
"type": "data",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -680,8 +666,7 @@
|
||||
"input"
|
||||
],
|
||||
"type": "data",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -761,8 +746,7 @@
|
||||
"txt"
|
||||
],
|
||||
"type": "data",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
},
|
||||
{
|
||||
"name": "out2",
|
||||
@@ -770,8 +754,7 @@
|
||||
"txt"
|
||||
],
|
||||
"type": "data",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
@@ -818,8 +801,7 @@
|
||||
],
|
||||
"collection": true,
|
||||
"collection_type": "list:list:list",
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
"extensions": [
|
||||
"input"
|
||||
],
|
||||
"optional": false,
|
||||
"activeOutput": false
|
||||
"optional": false
|
||||
}
|
||||
],
|
||||
"annotation": "",
|
||||
|
||||
@@ -41,7 +41,6 @@ export interface DataOutput {
|
||||
extensions: string[];
|
||||
name: string;
|
||||
optional: boolean;
|
||||
activeOutput?: boolean;
|
||||
}
|
||||
|
||||
export interface CollectionOutput extends Omit<DataOutput, "type"> {
|
||||
@@ -148,15 +147,20 @@ export const useWorkflowStepStore = defineStore("workflowStepStore", {
|
||||
getStepIndex(state: State) {
|
||||
return Math.max(...Object.values(state.steps).map((step) => step.id), state.stepIndex);
|
||||
},
|
||||
hasActiveOutputs(state: State) {
|
||||
return Boolean(Object.values(state.steps).find((step) => step.workflow_outputs?.length));
|
||||
},
|
||||
workflowOutputs(state: State) {
|
||||
const workflowOutputs: WorkflowOutputs = {};
|
||||
Object.values(state.steps).forEach((step) => {
|
||||
if (step.workflow_outputs?.length) {
|
||||
step.workflow_outputs.forEach((workflowOutput) => {
|
||||
workflowOutputs[workflowOutput.label || workflowOutput.output_name] = {
|
||||
outputName: workflowOutput.output_name,
|
||||
stepId: step.id,
|
||||
};
|
||||
if (workflowOutput.label) {
|
||||
workflowOutputs[workflowOutput.label] = {
|
||||
outputName: workflowOutput.output_name,
|
||||
stepId: step.id,
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -174,6 +178,9 @@ export const useWorkflowStepStore = defineStore("workflowStepStore", {
|
||||
return step;
|
||||
},
|
||||
updateStep(this: State, step: Step) {
|
||||
step.workflow_outputs = step.workflow_outputs?.filter((workflowOutput) =>
|
||||
step.outputs.find((output) => workflowOutput.output_name == output.name)
|
||||
);
|
||||
this.steps[step.id.toString()] = step;
|
||||
},
|
||||
changeStepMapOver(stepId: number, mapOver: CollectionTypeDescriptor) {
|
||||
|
||||
@@ -163,6 +163,14 @@
|
||||
@extend .fa;
|
||||
@extend .fa-check-square;
|
||||
}
|
||||
&.mark-terminal-visible {
|
||||
@extend .fa;
|
||||
@extend .fa-eye;
|
||||
}
|
||||
&.mark-terminal-hidden {
|
||||
@extend .fa;
|
||||
@extend .fa-eye-slash;
|
||||
}
|
||||
}
|
||||
.delete-terminal {
|
||||
@extend .btn;
|
||||
|
||||
Reference in New Issue
Block a user