Works much better

This commit is contained in:
mvdbeek
2023-01-09 17:15:42 +01:00
parent 7852cf3e67
commit 6cec979f87
12 changed files with 109 additions and 257 deletions
@@ -13,17 +13,9 @@ export default {
type: String,
required: false,
},
startX: {
type: Number,
},
startY: {
type: Number,
},
endX: {
type: Number,
},
endY: {
type: Number,
position: {
type: Object,
required: true,
},
},
data() {
@@ -36,12 +28,6 @@ export default {
// this.terminal.destroy();
},
computed: {
left() {
return Math.min(this.startX, this.endX);
},
top() {
return Math.max(this.startY, this.endY);
},
offsetStart() {
return 0;
},
@@ -50,10 +36,10 @@ export default {
},
lineData() {
const data = [
{ x: this.startX, y: this.startY + this.offsetStart },
{ x: this.startX + this.lineShift, y: this.startY + this.offsetStart },
{ x: this.endX - this.lineShift, y: this.endY + this.offsetEnd },
{ x: this.endX, y: this.endY + this.offsetEnd },
{ x: this.position.startX, y: this.position.startY + this.offsetStart },
{ x: this.position.startX + this.lineShift, y: this.position.startY + this.offsetStart },
{ x: this.position.endX - this.lineShift, y: this.position.endY + this.offsetEnd },
{ x: this.position.endX, y: this.position.endY + this.offsetEnd },
];
return data;
},
@@ -3,7 +3,7 @@
:draggable-options="draggableOptions"
@start="onDragStart"
@move="move"
:stop="stopPropagation"
:stop="onStopDragging"
:start="stopPropagation"
:drag="stopPropagation"
v-on="$listeners">
@@ -55,6 +55,11 @@ export default {
console.log("mousedown", e);
this.$emit("mousedown", e);
},
onStopDragging(e) {
console.log("stopDragging");
e.stopPropagation();
this.$emit("stopDragging");
},
stopPropagation(e) {
e.stopPropagation();
},
@@ -62,22 +67,6 @@ export default {
console.log("moveEvent", e);
e.event.stopPropagation();
},
// onMouseDown(e) {
// this.mouseDown = { offsetX: e.offsetX, offsetY: e.offsetY };
// if (!this.position) {
// const { top, left } = this.$refs.drag.getBoundingClientRect();
// this._localPosition = { top: top + window.scrollY, left: left + window.scrollX };
// }
// },
// onDrag(e) {
// const left = this.localPosition.left + (e.offsetX - this.mouseDown.offsetX) / this.zoom;
// const top = this.localPosition.top + (e.offsetY - this.mouseDown.offsetY) / this.zoom;
// this.$emit("updatePosition", { left, top });
// },
// onDragEnd(e) {
// // this.onDrag(e);
// this.$emit("dragEnd");
// },
},
};
</script>
@@ -341,7 +341,8 @@ export default {
}
},
steps(newSteps, oldSteps) {
this.hasChanges = true;
console.log("steps watch triggered");
// this.hasChanges = true;
this.nodeIndex = Math.max(...Object.keys(newSteps).map((k) => parseInt(k))) + 1;
},
nodes(newNodes, oldNodes) {
@@ -368,7 +369,7 @@ export default {
},
onUpdateStepPosition(stepId, position) {
console.log("updating step position");
// this.steps[stepId].position = position;
this.steps[stepId].position = position;
},
onDisconnect(nodeId, inputName) {
delete this.steps[nodeId].input_connections[inputName];
@@ -541,7 +542,7 @@ export default {
},
onAttributes() {
this._ensureParametersSet();
this.onDeactivate();
this.$store.commit("workflowState/setActiveNode", null);
this.showInPanel = "attributes";
},
onAnnotation(nodeId, newAnnotation) {
@@ -86,7 +86,7 @@
:offset-x="offset.x"
:offset-y="offset.y"
v-on="$listeners"
@stop="onStop"
@stopDragging="onStopDragging"
@onAdd="onAddOutput"
@onRemove="onRemoveOutput"
@onToggle="onToggleOutput"
@@ -268,8 +268,9 @@ export default {
left: this.step.position.left + deltaX,
});
},
onStop() {
console.log("onStop called");
onStopDragging() {
console.log("onStopDragging called");
this.$emit("stopDragging");
},
onUpdatePosition(position) {
this.$emit("onUpdateStepPosition", this.step.id, position);
@@ -46,8 +46,12 @@ export default {
isMultiple: false,
initX: 0,
initY: 0,
nodeId: null,
};
},
created() {
this.nodeId = this.getNode().id;
},
mounted() {
const rect = this.$refs.terminal.getBoundingClientRect();
this.initX = rect.left + rect.width / 2 - this.rootOffset.left;
@@ -75,7 +79,7 @@ export default {
return this.initY + this.offsetY;
},
position() {
return { endX: this.startX, endY: this.startY };
return Object.freeze({ endX: this.startX, endY: this.startY });
},
},
beforeDestroy() {
@@ -84,9 +88,13 @@ export default {
},
watch: {
position(position) {
console.log(position);
console.log({
stepId: this.nodeId,
inputName: this.input.name,
position,
});
this.$store.commit("workflowState/setInputTerminalPosition", {
stepId: this.getNode().id,
stepId: this.nodeId,
inputName: this.input.name,
position,
});
@@ -102,6 +110,7 @@ export default {
},
mouseOver(e) {
console.log("mousOver");
// }
},
mouseLeave() {
this.showRemove = false;
@@ -14,9 +14,8 @@
:class="terminalClass"
:output-name="output.name"
@start="isDragging = true"
@stop="onStopDragging"
@move="onMove"
v-on="$listeners">
@stopDragging="onStopDragging"
@move="onMove">
<div class="icon" ref="terminal"></div>
</draggable-wrapper>
</div>
@@ -79,7 +78,7 @@ export default {
},
computed: {
position() {
return { startX: this.startX, startY: this.startY };
return Object.freeze({ startX: this.startX, startY: this.startY });
},
startX() {
const newX = this.initX + this.offsetX;
@@ -156,6 +155,7 @@ export default {
console.log("is dragging ?", this.isDragging);
},
dragPosition() {
console.log("dragPosition", this.endX);
if (this.isDragging) {
this.$emit("onDragConnector", this.dragPosition);
}
@@ -180,6 +180,7 @@ export default {
this.isDragging = false;
this.deltaX = 0;
this.deltaY = 0;
this.$emit("stopDragging");
},
inputDragStart(e) {
console.log("inputDragStart", e);
@@ -195,7 +196,8 @@ export default {
},
onChange() {
// this.isMultiple = this.terminal.isMappedOver();
this.$emit("onChange");
console.log("onChange");
// this.$emit("onChange");
},
onToggle() {
this.$emit("onToggle", this.output.name);
@@ -0,0 +1,38 @@
<template>
<raw-connector v-if="position" :position="position"></raw-connector>
</template>
<script>
import RawConnector from "./Connector";
export default {
components: {
RawConnector,
},
props: {
connection: {
type: Object,
},
},
computed: {
position() {
const outputPos = this.$store.getters["workflowState/getOutputTerminalPosition"](
this.connection.outputStepId,
this.connection.outputName
);
const inputPos = this.$store.getters["workflowState/getInputTerminalPosition"](
this.connection.inputStepId,
this.connection.inputName
);
if (inputPos && outputPos) {
return {
...inputPos,
...outputPos,
};
}
},
},
};
</script>
<style></style>
@@ -1,117 +0,0 @@
<template>
<div>
<node-connector
:startX="connection.startX"
:endX="connection.endX"
:startY="connection.startY"
:endY="connection.endY"
:cpShift="connection.cpShift"
:width="connection.width"
:height="connection.height"
:left="connection.left"
:top="connection.top"
v-for="connection in connections"
:key="connection.key" />
</div>
</template>
<script>
import $ from "jquery";
// import Connector from "./modules/connector";
import NodeConnector from "./Connector.vue";
export default {
components: {
NodeConnector,
},
props: {
canvasManager: {
type: Object,
required: true,
},
step: {
type: Object,
required: true,
},
getManager: {
type: Function,
required: true,
},
},
data() {
return {
handleMarginX: 8,
canvasExtra: 100,
zIndex: 1000,
cpFactor: 10,
};
},
methods: {
getCoordinates(outputTerminal, inputTerminal) {
// Find the position of each handle
const canvasContainer = $("#canvas-container");
const relativeLeft = (e) =>
($(e).offset().left - canvasContainer.offset().left) / this.canvasManager.canvasZoom +
this.handleMarginX;
const relativeTop = (e) =>
($(e).offset().top - canvasContainer.offset().top) / this.canvasManager.canvasZoom +
0.5 * $(e).height();
let startX = relativeLeft(outputTerminal.element);
let startY = relativeTop(outputTerminal.element);
let endX = relativeLeft(inputTerminal.element);
let endY = relativeTop(inputTerminal.element);
// Calculate canvas area
const canvas_min_x = Math.min(startX, endX);
const canvas_max_x = Math.max(startX, endX);
const canvas_min_y = Math.min(startY, endY);
const canvas_max_y = Math.max(startY, endY);
const canvas_left = canvas_min_x - this.canvasExtra;
const canvas_top = canvas_min_y - this.canvasExtra;
const width = canvas_max_x - canvas_min_x + 2 * this.canvasExtra;
const height = canvas_max_y - canvas_min_y + 2 * this.canvasExtra;
const cpShift = Math.min(
Math.max(Math.abs(canvas_max_y - canvas_min_y) / 2, this.cpFactor),
3 * this.cpFactor
);
// Adjust points to be relative to the canvas
startX -= canvas_left;
startY -= canvas_top;
endX -= canvas_left;
endY -= canvas_top;
return { startX, startY, endX, endY, cpShift, width, height, left: canvas_left, top: canvas_top };
},
},
computed: {
connections() {
const rval = [];
if (!this.step.input_connections) {
return rval;
}
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 coordinates = this.getCoordinates(outputTerminal, inputTerminal);
console.log(coordinates);
coordinates.key = `${source}-${target}`;
rval.push(coordinates);
}
});
}
});
return rval;
},
},
};
</script>
@@ -9,20 +9,12 @@
@mouseup="handleUp"
@mousedown.prevent.stop="handleDown">
<div id="canvas-container" ref="canvas">
<svg width="100%" height="100%">
<connector
v-if="draggingConnection"
:startX="draggingConnection.startX"
:endX="draggingConnection.endX"
:startY="draggingConnection.startY"
:endY="draggingConnection.endY"></connector>
<connector
<svg class="canvas-svg">
<raw-connector v-if="draggingConnection" :position="draggingConnection"></raw-connector>
<terminal-connector
v-for="connection in connections"
:key="connection.id"
:startX="connection.startX"
:endX="connection.endX"
:startY="connection.startY"
:endY="connection.endY"></connector>
:connection="connection"></terminal-connector>
</svg>
<WorkflowNode
v-for="(step, key) in steps"
@@ -36,7 +28,7 @@
:get-manager="getManager"
:activeNodeId="activeNodeId"
:root-offset="rootOffset"
@stop="onStop"
@stopDragging="onStopDragging"
@onDragConnector="onDragConnector"
@onActivate="onActivate"
@onRemove="onRemove"
@@ -56,15 +48,15 @@
<script>
import ZoomControl from "./ZoomControl";
import WorkflowNode from "./Node";
import WorkflowConnection from "./WorkflowConnection";
import Connector from "./Connector.vue";
import RawConnector from "./Connector";
import TerminalConnector from "./TerminalConnector";
export default {
components: {
Connector,
RawConnector,
TerminalConnector,
WorkflowNode,
ZoomControl,
WorkflowConnection,
},
data() {
return {
@@ -99,7 +91,7 @@ export default {
// this.canvasManager.scrollToNodes();
},
methods: {
onStop() {
onStopDragging() {
console.log("onStop");
this.draggingConnection = null;
},
@@ -137,6 +129,7 @@ export default {
return this.$store.getters["workflowState/getActiveNode"]();
},
connections() {
console.log("connection fired");
const connections = [];
Object.entries(this.steps).forEach(([stepId, step]) => {
Object.entries(step.input_connections).forEach(([input_name, outputArray]) => {
@@ -144,21 +137,14 @@ export default {
outputArray = [outputArray];
}
outputArray.forEach((output) => {
const outputPos = this.$store.getters["workflowState/getOutputTerminalPosition"](
output.id,
output.output_name
);
const inputPos = this.$store.getters["workflowState/getInputTerminalPosition"](
step.id,
input_name
);
if (inputPos && outputPos) {
connections.push({
id: `${step.id}-${input_name}-${output.id}-${output.output_name}`,
...inputPos,
...outputPos,
});
}
const connection = {
id: `${step.id}-${input_name}-${output.id}-${output.output_name}`,
inputStepId: step.id,
inputName: input_name,
outputStepId: output.id,
outputName: output.output_name,
};
connections.push(connection);
});
});
});
@@ -23,66 +23,18 @@ export async function fromSimple(workflow, data, appendData = false) {
}
export function toSimple(workflow) {
const nodes = {};
const canvasZoom = workflow.canvasManager.canvasZoom;
console.log("to Simple");
const steps = {};
_rectifyOutputs(workflow);
Object.values(workflow.nodes).forEach((node) => {
const input_connections = {};
Object.values(node.inputTerminals).forEach((t) => {
input_connections[t.name] = null;
// There should only be 0 or 1 connectors, so this is
// really a sneaky if statement
const cons = [];
t.connectors.forEach((c, i) => {
if (c.outputHandle) {
const con_dict = {
id: c.outputHandle.node.id,
output_name: c.outputHandle.name,
};
const input_subworkflow_step_id = t.attributes.input.input_subworkflow_step_id;
if (input_subworkflow_step_id !== undefined) {
con_dict.input_subworkflow_step_id = input_subworkflow_step_id;
}
cons[i] = con_dict;
input_connections[t.name] = cons;
}
});
});
const postJobActions = {};
if (node.postJobActions) {
Object.values(node.postJobActions).forEach((act) => {
const pja = {
action_type: act.action_type,
output_name: act.output_name,
action_arguments: act.action_arguments,
};
postJobActions[act.action_type + act.output_name] = null;
postJobActions[act.action_type + act.output_name] = pja;
});
}
const node_data = {
id: node.id,
type: node.type,
content_id: node.content_id,
tool_version: node.config_form ? node.config_form.version : null,
tool_state: node.tool_state,
errors: node.errors,
input_connections: input_connections,
position: _scaledNodePosition(node.element, canvasZoom),
annotation: node.annotation,
post_job_actions: node.postJobActions,
uuid: node.uuid,
label: node.label,
workflow_outputs: node.activeOutputs.getAll(),
};
nodes[node.id] = node_data;
steps[node.id] = node.step;
});
const report = workflow.report;
const license = workflow.license;
const creator = workflow.creator;
const annotation = workflow.annotation;
const name = workflow.name;
return { steps: nodes, report, license, creator, annotation, name };
return { steps, report, license, creator, annotation, name };
}
function _scaledNodePosition(element, canvasZoom) {
+2 -1
View File
@@ -39,6 +39,7 @@ galaxyStorage.config({
storeName: "galaxyStore",
});
// smh vuex-persistence incurs a 100ms penalty on commit (at least for the workflowState store)
const panelsPersistence = new VuexPersistence({
storage: galaxyStorage,
asyncStorage: true,
@@ -53,7 +54,7 @@ const panelsPersistence = new VuexPersistence({
export function createStore() {
const storeConfig = {
plugins: [createCache(), panelsPersistence.plugin],
plugins: [createCache()],
modules: {
collectionAttributesStore: collectionAttributesStore,
collectionElements: collectionElementsStore,
+6 -2
View File
@@ -1,3 +1,7 @@
.canvas-svg {
// not sure if hack or not ...
overflow: visible;
}
.workflow-client {
.workflow-panel {
background: $white;
@@ -218,11 +222,11 @@
z-index: 10;
}
canvas {
position: absolute;
position: relative;
z-index: 10;
}
canvas.dragging {
position: absolute;
position: relative;
z-index: 1000;
}
}