mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
WIP store state in store / eliminate vue instance passing
This commit is contained in:
@@ -65,50 +65,19 @@
|
||||
{{ name }}
|
||||
</div>
|
||||
</div>
|
||||
<div id="workflow-canvas" class="unified-panel-body workflow-canvas">
|
||||
<ZoomControl v-if="!checkWheeled" :zoom-level="zoomLevel" @onZoom="onZoom" />
|
||||
<b-button
|
||||
v-else
|
||||
v-b-tooltip.hover
|
||||
class="reset-wheel"
|
||||
variant="light"
|
||||
title="Show Zoom Buttons"
|
||||
size="sm"
|
||||
aria-label="Show Zoom Buttons"
|
||||
@click="resetWheel">
|
||||
Zoom Controls
|
||||
</b-button>
|
||||
<div id="canvas-viewport">
|
||||
<div id="canvas-container" ref="canvas">
|
||||
<WorkflowNode
|
||||
v-for="(step, key) in steps"
|
||||
:id="key"
|
||||
:key="key"
|
||||
:name="step.name"
|
||||
:type="step.type"
|
||||
:content-id="step.content_id"
|
||||
:step="step"
|
||||
:datatypes-mapper="datatypesMapper"
|
||||
:get-manager="getManager"
|
||||
:get-canvas-manager="getCanvasManager"
|
||||
@onAdd="onAdd"
|
||||
@onUpdate="onUpdate"
|
||||
@onClone="onClone"
|
||||
@onCreate="onInsertTool"
|
||||
@onChange="onChange"
|
||||
@onActivate="onActivate"
|
||||
@onRemove="onRemove" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="workflow-overview" aria-hidden="true">
|
||||
<div class="workflow-overview-body">
|
||||
<div id="overview-container">
|
||||
<canvas id="overview-canvas" width="0" height="0" />
|
||||
<div id="overview-viewport" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<workflow-graph
|
||||
:steps="steps"
|
||||
:datatypes-mapper="datatypesMapper"
|
||||
:get-manager="getManager"
|
||||
@onActiveNode="onActiveNode"
|
||||
@onAdd="onAdd"
|
||||
@onUpdate="onUpdate"
|
||||
@onClone="onClone"
|
||||
@onCreate="onInsertTool"
|
||||
@onChange="onChange"
|
||||
@onDisconnect="onDisconnect"
|
||||
@onRemove="onRemove">
|
||||
</workflow-graph>
|
||||
</div>
|
||||
<SidePanel id="right" side="right">
|
||||
<template v-slot:panel>
|
||||
@@ -211,7 +180,6 @@ import { fromSimple, toSimple } from "./modules/model";
|
||||
import { getModule, getVersions, saveWorkflow, loadWorkflow } from "./modules/services";
|
||||
import { getUntypedWorkflowParameters } from "./modules/parameters";
|
||||
import { getStateUpgradeMessages } from "./modules/utilities";
|
||||
import WorkflowCanvas from "./modules/canvas";
|
||||
import WorkflowOptions from "./Options";
|
||||
import FormDefault from "./Forms/FormDefault";
|
||||
import FormTool from "./Forms/FormTool";
|
||||
@@ -226,8 +194,8 @@ import RefactorConfirmationModal from "./RefactorConfirmationModal";
|
||||
import MessagesModal from "./MessagesModal";
|
||||
import { hide_modal } from "layout/modal";
|
||||
import WorkflowAttributes from "./Attributes";
|
||||
import ZoomControl from "./ZoomControl";
|
||||
import WorkflowNode from "./Node";
|
||||
import WorkflowGraph from "./WorkflowGraph.vue";
|
||||
|
||||
import Vue from "vue";
|
||||
import { ConfirmDialog } from "composables/confirmDialog";
|
||||
|
||||
@@ -241,11 +209,10 @@ export default {
|
||||
FormTool,
|
||||
WorkflowOptions,
|
||||
WorkflowAttributes,
|
||||
ZoomControl,
|
||||
WorkflowNode,
|
||||
WorkflowLint,
|
||||
RefactorConfirmationModal,
|
||||
MessagesModal,
|
||||
WorkflowGraph,
|
||||
},
|
||||
props: {
|
||||
id: {
|
||||
@@ -280,7 +247,6 @@ export default {
|
||||
markdownText: null,
|
||||
versions: [],
|
||||
parameters: null,
|
||||
zoomLevel: 7,
|
||||
steps: {},
|
||||
hasChanges: false,
|
||||
nodeIndex: 0,
|
||||
@@ -302,8 +268,6 @@ export default {
|
||||
messageIsError: false,
|
||||
version: this.initialVersion,
|
||||
showInPanel: "attributes",
|
||||
isWheeled: false,
|
||||
canvasManager: null,
|
||||
saveAsName: null,
|
||||
saveAsAnnotation: null,
|
||||
showSaveAsModal: false,
|
||||
@@ -355,12 +319,6 @@ export default {
|
||||
hasActiveNodeTool() {
|
||||
return this.activeNode && this.activeNode.type == "tool";
|
||||
},
|
||||
checkWheeled() {
|
||||
if (this.canvasManager != null) {
|
||||
return this.canvasManager.isWheeled;
|
||||
}
|
||||
return this.isWheeled;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
id(newId, oldId) {
|
||||
@@ -394,27 +352,13 @@ export default {
|
||||
this.datatypesMapper = mapper;
|
||||
this.datatypes = mapper.datatypes;
|
||||
|
||||
// canvas overview management
|
||||
this.canvasManager = new WorkflowCanvas(this, this.$refs.canvas);
|
||||
this._loadCurrent(this.id, this.version);
|
||||
});
|
||||
hide_modal();
|
||||
},
|
||||
methods: {
|
||||
onActivate(node) {
|
||||
if (this.activeNode != node) {
|
||||
this.onDeactivate();
|
||||
node.makeActive();
|
||||
this.activeNode = node;
|
||||
this.canvasManager.drawOverview();
|
||||
this.$refs["right-panel"].scrollTop = 0;
|
||||
}
|
||||
},
|
||||
onDeactivate() {
|
||||
if (this.activeNode) {
|
||||
this.activeNode.makeInactive();
|
||||
this.activeNode = null;
|
||||
}
|
||||
onDisconnect(nodeId, inputName) {
|
||||
delete this.steps[nodeId].input_connections[inputName];
|
||||
},
|
||||
onAttemptRefactor(actions) {
|
||||
if (this.hasChanges) {
|
||||
@@ -463,6 +407,7 @@ export default {
|
||||
this._loadEditorData(response.workflow);
|
||||
},
|
||||
onAdd(node) {
|
||||
console.log("onAdd", node);
|
||||
this.nodes[node.id] = node;
|
||||
},
|
||||
onUpdate(node) {
|
||||
@@ -488,11 +433,9 @@ export default {
|
||||
Vue.set(this.nodes[nodeId], "postJobActions", postJobActions);
|
||||
this.onChange();
|
||||
},
|
||||
onRemove(node) {
|
||||
delete this.nodes[node.id];
|
||||
Vue.delete(this.steps, node.id);
|
||||
this.canvasManager.drawOverview();
|
||||
this.onDeactivate();
|
||||
onRemove(nodeId) {
|
||||
delete this.nodes[nodeId];
|
||||
Vue.delete(this.steps, nodeId);
|
||||
this.showInPanel = "attributes";
|
||||
},
|
||||
onEditSubworkflow(contentId) {
|
||||
@@ -646,13 +589,6 @@ export default {
|
||||
this.$router.push(url);
|
||||
});
|
||||
},
|
||||
onZoom(zoomLevel) {
|
||||
this.zoomLevel = this.canvasManager.setZoom(zoomLevel);
|
||||
},
|
||||
resetWheel() {
|
||||
this.zoomLevel = this.canvasManager.zoomLevel;
|
||||
this.canvasManager.isWheeled = false;
|
||||
},
|
||||
onSave(hideProgress = false) {
|
||||
!hideProgress && this.onWorkflowMessage("Saving workflow...", "progress");
|
||||
return saveWorkflow(this)
|
||||
@@ -712,8 +648,6 @@ export default {
|
||||
this.versions = versions;
|
||||
});
|
||||
await Vue.nextTick();
|
||||
this.canvasManager.drawOverview();
|
||||
this.canvasManager.scrollToNodes();
|
||||
this.hasChanges = has_changes;
|
||||
},
|
||||
_loadCurrent(id, version) {
|
||||
@@ -739,13 +673,16 @@ export default {
|
||||
this.creator = creator;
|
||||
}
|
||||
},
|
||||
onActiveNode(nodeId) {
|
||||
this.activeNode = this.nodes[nodeId];
|
||||
console.log("active node");
|
||||
this.$refs["right-panel"].scrollTop = 0;
|
||||
},
|
||||
getManager() {
|
||||
return this;
|
||||
},
|
||||
getCanvasManager() {
|
||||
return this.canvasManager;
|
||||
},
|
||||
getNode() {
|
||||
console.log("getting node");
|
||||
return this.activeNode;
|
||||
},
|
||||
onInsertedStateMessages(insertedStateMessages) {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
<template>
|
||||
<div
|
||||
:id="idString"
|
||||
:name="name"
|
||||
:node-label="label"
|
||||
:class="{ 'workflow-node': true, 'node-on-scroll-to': scrolledTo, 'node-highlight': highlight }">
|
||||
<div @click="makeActive()" :id="idString" :name="name" :node-label="label" :class="classes">
|
||||
<div class="node-header unselectable clearfix">
|
||||
<b-button
|
||||
v-b-tooltip.hover
|
||||
@@ -62,8 +58,10 @@
|
||||
:get-node="getNode"
|
||||
:get-manager="getManager"
|
||||
:datatypes-mapper="datatypesMapper"
|
||||
:canvas-manager="canvasManager"
|
||||
@onAdd="onAddInput"
|
||||
@onRemove="onRemoveInput"
|
||||
@onDisconnect="onDisconnect"
|
||||
@onChange="onChange" />
|
||||
<div v-if="showRule" class="rule" />
|
||||
<node-output
|
||||
@@ -73,6 +71,7 @@
|
||||
:post-job-actions="postJobActions"
|
||||
:get-node="getNode"
|
||||
:get-manager="getManager"
|
||||
:canvas-manager="canvasManager"
|
||||
@onAdd="onAddOutput"
|
||||
@onRemove="onRemoveOutput"
|
||||
@onToggle="onToggleOutput"
|
||||
@@ -136,9 +135,14 @@ export default {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
activeNodeId: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
canvasManager: null,
|
||||
popoverShow: false,
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
@@ -187,6 +191,20 @@ export default {
|
||||
stepIndex() {
|
||||
return parseInt(this.id) + 1;
|
||||
},
|
||||
isActive() {
|
||||
return this.id == this.activeNodeId;
|
||||
},
|
||||
classes() {
|
||||
const cssObj = {
|
||||
"workflow-node": true,
|
||||
"node-on-scroll-to": this.scrolledTo,
|
||||
"node-highlight": this.highlight || this.isActive,
|
||||
};
|
||||
if (this.isActive) {
|
||||
return { ...cssObj, "is-active": true };
|
||||
}
|
||||
return cssObj;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.canvasManager = this.getCanvasManager();
|
||||
@@ -216,7 +234,7 @@ export default {
|
||||
// Attach node dragging events
|
||||
attachDragging(this.$el, {
|
||||
dragstart: () => {
|
||||
this.$emit("onActivate", this);
|
||||
this.$emit("onActivate", this.id);
|
||||
},
|
||||
dragend: () => {
|
||||
this.$emit("onChange");
|
||||
@@ -233,7 +251,7 @@ export default {
|
||||
this.onRedraw();
|
||||
},
|
||||
dragclickonly: () => {
|
||||
this.$emit("onActivate", this);
|
||||
this.$emit("onActivate", this.id);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -248,7 +266,6 @@ export default {
|
||||
|
||||
methods: {
|
||||
onChange() {
|
||||
this.onRedraw();
|
||||
this.$emit("onChange");
|
||||
},
|
||||
onAddInput(input, terminal) {
|
||||
@@ -259,6 +276,9 @@ export default {
|
||||
delete this.inputTerminals[input.name];
|
||||
this.onRedraw();
|
||||
},
|
||||
onDisconnect(inputName) {
|
||||
this.$emit("onDisconnect", this.id, inputName);
|
||||
},
|
||||
onAddOutput(output, terminal) {
|
||||
this.outputTerminals[output.name] = terminal;
|
||||
this.onRedraw();
|
||||
@@ -286,7 +306,7 @@ export default {
|
||||
t.destroy();
|
||||
});
|
||||
this.activeOutputs.filterOutputs([]);
|
||||
this.$emit("onRemove", this);
|
||||
this.$emit("onRemove", this.id);
|
||||
},
|
||||
onRedraw() {
|
||||
Object.values(this.inputTerminals).forEach((t) => {
|
||||
@@ -302,7 +322,7 @@ export default {
|
||||
setNode(data) {
|
||||
this.initData(data);
|
||||
this.$emit("onChange");
|
||||
this.$emit("onActivate", this);
|
||||
this.$emit("onActivate", this.id);
|
||||
},
|
||||
setAnnotation(annotation) {
|
||||
this.annotation = annotation;
|
||||
@@ -347,19 +367,7 @@ export default {
|
||||
this.highlight = false;
|
||||
},
|
||||
makeActive() {
|
||||
this.element.classList.add("node-active");
|
||||
},
|
||||
makeInactive() {
|
||||
// Keep inactive nodes stacked from most to least recently active
|
||||
// by moving element to the end of parent's node list
|
||||
document.activeElement.blur();
|
||||
const element = this.element;
|
||||
((p) => {
|
||||
p.removeChild(element);
|
||||
p.appendChild(element);
|
||||
})(element.parentNode);
|
||||
// Remove active class
|
||||
element.classList.remove("node-active");
|
||||
this.$emit("onActivate", this.id);
|
||||
},
|
||||
offsetVaryPosition(offsetRange) {
|
||||
return Math.floor(Math.random() * offsetRange);
|
||||
|
||||
@@ -30,6 +30,10 @@ export default {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
canvasManager: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -100,11 +104,12 @@ export default {
|
||||
element: this.$refs.terminal,
|
||||
});
|
||||
terminal.on("change", this.onChange.bind(this));
|
||||
new InputDragging(this.getManager(), {
|
||||
new InputDragging(this.getManager(), this.canvasManager, {
|
||||
el: this.$refs.terminal,
|
||||
terminal: terminal,
|
||||
});
|
||||
this.$emit("onAdd", this.input, terminal);
|
||||
this.$store.commit("setInputTerminal", { inputTerminalId: terminal.element.id, inputTerminal: terminal });
|
||||
return terminal;
|
||||
},
|
||||
onChange() {
|
||||
@@ -112,6 +117,7 @@ export default {
|
||||
this.$emit("onChange");
|
||||
},
|
||||
onRemove() {
|
||||
this.$emit("onDisconnect", this.input.name);
|
||||
this.terminal.destroy();
|
||||
},
|
||||
mouseOver(e) {
|
||||
|
||||
@@ -26,6 +26,10 @@ export default {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
canvasManager: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
getNode: {
|
||||
type: Function,
|
||||
required: true,
|
||||
@@ -154,13 +158,17 @@ export default {
|
||||
datatypes: this.extensions,
|
||||
});
|
||||
}
|
||||
new OutputDragging(this.getManager(), {
|
||||
new OutputDragging(this.getManager(), this.canvasManager, {
|
||||
el: this.$refs.terminal,
|
||||
terminal: this.terminal,
|
||||
});
|
||||
this.terminal.on("change", this.onChange.bind(this));
|
||||
this.terminal.emit("change");
|
||||
this.$emit("onAdd", this.output, this.terminal);
|
||||
this.$store.commit("setOutputTerminal", {
|
||||
outputTerminalId: this.terminal.element.id,
|
||||
outputTerminal: this.terminal,
|
||||
});
|
||||
},
|
||||
onChange() {
|
||||
this.isMultiple = this.terminal.isMappedOver();
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div v-if="canvasManager">{{ connections }}</div>
|
||||
</template>
|
||||
<script>
|
||||
import Connector from "./modules/connector";
|
||||
|
||||
export default {
|
||||
// components: {
|
||||
// WorkflowConnection
|
||||
// },
|
||||
props: {
|
||||
canvasManager: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
step: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
getManager: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
connections() {
|
||||
Object.entries(this.step.input_connections).forEach(([k, v]) => {
|
||||
if (v) {
|
||||
const source = `node-${this.step.id}-input-${k}`;
|
||||
const inputTerminal = this.$store.getters.getInputTerminal(source);
|
||||
if (!Array.isArray(v)) {
|
||||
v = [v];
|
||||
}
|
||||
v.forEach((x) => {
|
||||
const target = `node-${x.id}-output-${x.output_name}`;
|
||||
let outputTerminal = this.$store.getters.getOutputTerminal(target);
|
||||
console.log(outputTerminal);
|
||||
if (inputTerminal && outputTerminal) {
|
||||
const c = new Connector(this.canvasManager, outputTerminal, inputTerminal);
|
||||
c.connect(outputTerminal, inputTerminal);
|
||||
this.$store.commit("setConnection", source, target, c);
|
||||
c.redraw();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<div id="workflow-canvas" class="unified-panel-body workflow-canvas">
|
||||
<ZoomControl v-if="!checkWheeled" :zoom-level="zoomLevel" @onZoom="onZoom" />
|
||||
<b-button
|
||||
v-else
|
||||
v-b-tooltip.hover
|
||||
class="reset-wheel"
|
||||
variant="light"
|
||||
title="Show Zoom Buttons"
|
||||
size="sm"
|
||||
aria-label="Show Zoom Buttons"
|
||||
@click="resetWheel">
|
||||
Zoom Controls
|
||||
</b-button>
|
||||
<div id="canvas-viewport">
|
||||
<div id="canvas-container" ref="canvas">
|
||||
<WorkflowNode
|
||||
v-for="(step, key) in steps"
|
||||
:id="key"
|
||||
:key="key"
|
||||
:name="step.name"
|
||||
:type="step.type"
|
||||
:content-id="step.content_id"
|
||||
:step="step"
|
||||
:datatypes-mapper="datatypesMapper"
|
||||
:get-manager="getManager"
|
||||
:get-canvas-manager="getCanvasManager"
|
||||
:activeNodeId="activeNodeId"
|
||||
@onActivate="onActivate"
|
||||
@onRemove="onRemove"
|
||||
v-on="$listeners" />
|
||||
<workflow-connection
|
||||
v-for="(step, key) in steps"
|
||||
:key="`${key}-c`"
|
||||
:step="step"
|
||||
:canvas-manager="canvasManager"
|
||||
:get-manager="getManager" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="workflow-overview" aria-hidden="true">
|
||||
<div class="workflow-overview-body">
|
||||
<div id="overview-container">
|
||||
<canvas id="overview-canvas" width="0" height="0" />
|
||||
<div id="overview-viewport" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import WorkflowCanvas from "./modules/canvas";
|
||||
import ZoomControl from "./ZoomControl";
|
||||
import WorkflowNode from "./Node";
|
||||
import WorkflowConnection from "./WorkflowConnection";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WorkflowNode,
|
||||
ZoomControl,
|
||||
WorkflowConnection,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isWheeled: false,
|
||||
canvasManager: null,
|
||||
zoomLevel: 7,
|
||||
activeNodeId: null,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
steps: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
getManager: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
datatypesMapper: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// canvas overview management
|
||||
this.canvasManager = new WorkflowCanvas(this.getManager(), this.$refs.canvas);
|
||||
this.canvasManager.drawOverview();
|
||||
this.canvasManager.scrollToNodes();
|
||||
},
|
||||
methods: {
|
||||
getCanvasManager() {
|
||||
return this.canvasManager;
|
||||
},
|
||||
onZoom(zoomLevel) {
|
||||
this.zoomLevel = this.canvasManager.setZoom(zoomLevel);
|
||||
},
|
||||
resetWheel() {
|
||||
this.zoomLevel = this.canvasManager.zoomLevel;
|
||||
this.canvasManager.isWheeled = false;
|
||||
},
|
||||
onActivate(nodeId) {
|
||||
console.log("onNodeId", nodeId);
|
||||
if (this.activeNodeId != nodeId) {
|
||||
this.activeNodeId = nodeId;
|
||||
this.canvasManager.drawOverview();
|
||||
this.$emit("onActiveNode", nodeId);
|
||||
}
|
||||
},
|
||||
onDeactivate() {
|
||||
this.activeNodeId = null;
|
||||
},
|
||||
onRemove(nodeId) {
|
||||
this.$emit("onRemove", nodeId);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
checkWheeled() {
|
||||
if (this.canvasManager != null) {
|
||||
return this.canvasManager.isWheeled;
|
||||
}
|
||||
return this.isWheeled;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -29,8 +29,6 @@ class Connector {
|
||||
this.canvas.style.position = "absolute";
|
||||
const container = document.getElementById("canvas-container");
|
||||
container.appendChild(this.canvas);
|
||||
this.svg = d3.select(this.canvas).append("svg");
|
||||
this.svg.attr("class", "ribbon");
|
||||
if (outputHandle && inputHandle) {
|
||||
this.connect(outputHandle, inputHandle);
|
||||
}
|
||||
@@ -109,8 +107,11 @@ class Connector {
|
||||
this.canvas.style.top = `${canvas_top}px`;
|
||||
|
||||
// Resize the svg
|
||||
this.svg.style("width", `${canvas_width}px`);
|
||||
this.svg.style("height", `${canvas_height}px`);
|
||||
const svg = d3.select(this.canvas).append("svg");
|
||||
svg.attr("class", "ribbon");
|
||||
console.log(svg);
|
||||
svg.style("width", `${canvas_width}px`);
|
||||
svg.style("height", `${canvas_height}px`);
|
||||
|
||||
// Adjust points to be relative to the canvas
|
||||
start_x -= canvas_left;
|
||||
@@ -122,9 +123,9 @@ class Connector {
|
||||
const cp_shift = Math.min(Math.max(Math.abs(canvas_max_y - canvas_min_y) / 2, cpFactor), 3 * cpFactor);
|
||||
|
||||
// Draw ribbons
|
||||
this.drawRibbon(outputHandle, inputHandle, cp_shift, start_x, start_y, end_x, end_y);
|
||||
this.drawRibbon(svg, outputHandle, inputHandle, cp_shift, start_x, start_y, end_x, end_y);
|
||||
}
|
||||
drawRibbon(outputHandle, inputHandle, cp_shift, start_x, start_y, end_x, end_y) {
|
||||
drawRibbon(svg, outputHandle, inputHandle, cp_shift, start_x, start_y, end_x, end_y) {
|
||||
// Check ribbon type
|
||||
const startRibbon = outputHandle && outputHandle.isMappedOver();
|
||||
const endRibbon = inputHandle && inputHandle.isMappedOver();
|
||||
@@ -142,7 +143,7 @@ class Connector {
|
||||
end_offsets = offsets;
|
||||
num_offsets = offsets.length;
|
||||
}
|
||||
this.svg.selectAll("*").remove();
|
||||
svg.selectAll("*").remove();
|
||||
for (let i = 0; i < num_offsets; i++) {
|
||||
let inner_width = ribbonInnerSingle;
|
||||
let outer_width = ribbonOuterSingle;
|
||||
@@ -151,6 +152,7 @@ class Connector {
|
||||
outer_width = ribbonOuterMultiple;
|
||||
}
|
||||
this.drawCurve(
|
||||
svg,
|
||||
start_x,
|
||||
start_y,
|
||||
end_x,
|
||||
@@ -163,7 +165,7 @@ class Connector {
|
||||
);
|
||||
}
|
||||
}
|
||||
drawCurve(start_x, start_y, end_x, end_y, cp_shift, inner_width, outer_width, offset_start, offset_end) {
|
||||
drawCurve(svg, start_x, start_y, end_x, end_y, cp_shift, inner_width, outer_width, offset_start, offset_end) {
|
||||
offset_start = offset_start || 0;
|
||||
offset_end = offset_end || 0;
|
||||
const lineData = [
|
||||
@@ -172,6 +174,7 @@ class Connector {
|
||||
{ x: end_x - cp_shift, y: end_y + offset_end },
|
||||
{ x: end_x, y: end_y + offset_end },
|
||||
];
|
||||
console.log("lineData", lineData);
|
||||
const lineFunction = d3.svg
|
||||
.line()
|
||||
.x(function (d) {
|
||||
@@ -181,14 +184,12 @@ class Connector {
|
||||
return d.y;
|
||||
})
|
||||
.interpolate("basis");
|
||||
this.svg
|
||||
.append("path")
|
||||
svg.append("path")
|
||||
.attr("class", "ribbon-outer")
|
||||
.attr("d", lineFunction(lineData))
|
||||
.attr("stroke-width", outer_width)
|
||||
.attr("fill", "none");
|
||||
this.svg
|
||||
.append("path")
|
||||
svg.append("path")
|
||||
.attr("class", this.innerClass)
|
||||
.attr("d", lineFunction(lineData))
|
||||
.attr("stroke-width", inner_width)
|
||||
|
||||
@@ -11,8 +11,9 @@ export function attachDragging(el, callbacks) {
|
||||
}
|
||||
|
||||
export class InputDragging {
|
||||
constructor(app, options = {}) {
|
||||
constructor(app, canvasManager, options = {}) {
|
||||
this.app = app;
|
||||
this.canvasManager = canvasManager;
|
||||
this.el = options.el;
|
||||
this.terminal = options.terminal;
|
||||
this.el.terminal = this.terminal;
|
||||
@@ -64,15 +65,16 @@ export class InputDragging {
|
||||
d.proxy.dropTooltip = "";
|
||||
if (this.$el.hasClass("can-accept")) {
|
||||
const terminal = this.terminal;
|
||||
const c = new Connector(this.app.canvasManager, d.drag.terminal, terminal);
|
||||
const c = new Connector(this.canvasManager, d.drag.terminal, terminal);
|
||||
c.redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class OutputDragging {
|
||||
constructor(app, options) {
|
||||
constructor(app, canvasManager, options) {
|
||||
this.app = app;
|
||||
this.canvasManager = canvasManager;
|
||||
this.el = options.el;
|
||||
this.terminal = options.terminal;
|
||||
this.el.terminal = this.terminal;
|
||||
@@ -97,16 +99,16 @@ export class OutputDragging {
|
||||
}
|
||||
onDrag(e, d = {}) {
|
||||
var onmove = () => {
|
||||
var canvasZoom = this.app.canvasManager.canvasZoom;
|
||||
var canvasZoom = this.canvasManager.canvasZoom;
|
||||
var po = $(d.proxy).offsetParent().offset();
|
||||
var x = d.offsetX - po.left;
|
||||
var y = d.offsetY - po.top;
|
||||
$(d.proxy).css({ left: x / canvasZoom, top: y / canvasZoom });
|
||||
d.proxy.terminal.redraw();
|
||||
this.app.canvasManager.updateViewportOverlay();
|
||||
this.canvasManager.updateViewportOverlay();
|
||||
};
|
||||
onmove();
|
||||
this.app.canvasManager.scrollPanel.test(e, onmove);
|
||||
this.canvasManager.scrollPanel.test(e, onmove);
|
||||
}
|
||||
onDragStart(e, d = {}) {
|
||||
$(d.available).addClass("input-terminal-active");
|
||||
@@ -120,7 +122,7 @@ export class OutputDragging {
|
||||
},
|
||||
});
|
||||
h.terminal = new Terminals.Terminal({ element: h, node: {} });
|
||||
const c = new Connector(this.app.canvasManager);
|
||||
const c = new Connector(this.canvasManager);
|
||||
c.dragging = true;
|
||||
c.connect(this.terminal, h.terminal);
|
||||
return h;
|
||||
@@ -133,6 +135,6 @@ export class OutputDragging {
|
||||
$(d.proxy).tooltip("dispose");
|
||||
$(d.proxy).remove();
|
||||
$(d.available).removeClass("input-terminal-active");
|
||||
this.app.canvasManager.scrollPanel.stop();
|
||||
this.canvasManager.scrollPanel.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import Connector from "./connector";
|
||||
import Vue from "vue";
|
||||
|
||||
export async function fromSimple(workflow, data, appendData = false) {
|
||||
let offset = 0;
|
||||
if (appendData) {
|
||||
@@ -11,11 +8,7 @@ export async function fromSimple(workflow, data, appendData = false) {
|
||||
workflow.annotation = data.annotation;
|
||||
workflow.license = data.license;
|
||||
workflow.creator = data.creator;
|
||||
Object.values(workflow.nodes).forEach((node) => {
|
||||
node.onRemove();
|
||||
});
|
||||
}
|
||||
await Vue.nextTick();
|
||||
workflow.version = data.version;
|
||||
workflow.report = data.report || {};
|
||||
Object.values(data.steps).forEach((step) => {
|
||||
@@ -24,46 +17,9 @@ export async function fromSimple(workflow, data, appendData = false) {
|
||||
if (appendData) {
|
||||
step.uuid = null;
|
||||
}
|
||||
Vue.set(workflow.steps, workflow.nodeIndex++, {
|
||||
...step,
|
||||
});
|
||||
});
|
||||
await Vue.nextTick();
|
||||
// Second pass, connections
|
||||
let using_workflow_outputs = false;
|
||||
Object.entries(data.steps).forEach(([id, step]) => {
|
||||
if (step.workflow_outputs && step.workflow_outputs.length > 0) {
|
||||
using_workflow_outputs = true;
|
||||
}
|
||||
});
|
||||
|
||||
Object.entries(data.steps).forEach(([id, step]) => {
|
||||
const nodeIndex = parseInt(id) + offset;
|
||||
const node = workflow.nodes[nodeIndex];
|
||||
Object.entries(step.input_connections).forEach(([k, v]) => {
|
||||
if (v) {
|
||||
if (!Array.isArray(v)) {
|
||||
v = [v];
|
||||
}
|
||||
v.forEach((x) => {
|
||||
const otherNodeIndex = parseInt(x.id) + offset;
|
||||
const otherNode = workflow.nodes[otherNodeIndex];
|
||||
const c = new Connector(workflow.canvasManager);
|
||||
c.connect(otherNode.outputTerminals[x.output_name], node.inputTerminals[k]);
|
||||
c.redraw();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (!using_workflow_outputs) {
|
||||
// Older workflows contain HideDatasetActions only, but no active outputs yet.
|
||||
Object.values(node.outputs).forEach((ot) => {
|
||||
if (!node.postJobActions[`HideDatasetAction${ot.name}`]) {
|
||||
node.activeOutputs.add(ot.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
console.log("setting workflow steps");
|
||||
workflow.steps = data.steps;
|
||||
}
|
||||
|
||||
export function toSimple(workflow) {
|
||||
|
||||
@@ -126,6 +126,7 @@ class Terminal extends EventEmitter {
|
||||
this.emit("change");
|
||||
}
|
||||
redraw() {
|
||||
console.log("redraw");
|
||||
this.connectors.forEach((c) => {
|
||||
c.redraw();
|
||||
});
|
||||
|
||||
@@ -18,6 +18,8 @@ import { invocationStore } from "./invocationStore";
|
||||
import { collectionElementsStore, datasetStore, historyStore } from "./historyStore";
|
||||
import { userStore, userFlagsStore } from "./userStore";
|
||||
import { configStore } from "./configStore";
|
||||
import { workflowStateStore } from "./workflowEditorStateStore";
|
||||
import { workflowStore } from "./workflowStore";
|
||||
import { toolStore } from "./toolStore";
|
||||
import { datasetPathDestinationStore } from "./datasetPathDestinationStore";
|
||||
import { datasetExtFilesStore } from "./datasetExtFilesStore";
|
||||
@@ -71,6 +73,8 @@ export function createStore() {
|
||||
tools: toolStore,
|
||||
user: userStore,
|
||||
userFlags: userFlagsStore,
|
||||
workflows: workflowStore,
|
||||
workflowState: workflowStateStore,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
export const state = {
|
||||
inputTerminals: {},
|
||||
outputTerminals: {},
|
||||
connections: {},
|
||||
};
|
||||
|
||||
import Vue from "vue";
|
||||
const getters = {
|
||||
getInputTerminal: (state) => (inputTerminalId) => {
|
||||
return state.inputTerminals[inputTerminalId];
|
||||
},
|
||||
getOutputTerminal: (state) => (outputTerminalId) => {
|
||||
return state.outputTerminals[outputTerminalId];
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {};
|
||||
|
||||
const mutations = {
|
||||
setInputTerminal: (state, { inputTerminalId, inputTerminal }) => {
|
||||
// TODO: Need to find a better inputTerminalId, terminal.id is just undefined
|
||||
console.log(inputTerminalId);
|
||||
Vue.set(state.inputTerminals, inputTerminalId, inputTerminal);
|
||||
},
|
||||
setOutputTerminal: (state, { outputTerminalId, outputTerminal }) => {
|
||||
console.log(outputTerminal);
|
||||
Vue.set(state.outputTerminals, outputTerminalId, outputTerminal);
|
||||
},
|
||||
setConnection: (state, { source, target, connection }) => {
|
||||
if (!state.connections[source]) {
|
||||
state.connections[source] = { target: connection };
|
||||
} else {
|
||||
state.connections[source][target] = connection;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const workflowStateStore = {
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
||||
Reference in New Issue
Block a user