mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Works much better
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user