Move draggable logic into own component

This commit is contained in:
mvdbeek
2023-01-09 17:15:41 +01:00
parent 78337a4a0f
commit edba5a2683
2 changed files with 148 additions and 109 deletions
@@ -0,0 +1,52 @@
<template>
<div draggable="true" @drag="onDrag" @dragend="onDragEnd" @mousedown="onMouseDown" :style="style">
<slot></slot>
</div>
</template>
<script>
export default {
props: {
position: {
top: {
type: Number,
default: 0,
},
left: {
type: Number,
default: 0,
},
},
zoom: {
type: Number,
default: 1,
required: false,
},
},
data() {
return {
mouseDown: {},
localPosition: {},
};
},
computed: {
style() {
return { top: this.position.top + "px", left: this.position.left + "px" };
},
},
methods: {
onMouseDown(e) {
this.mouseDown = { offsetX: e.offsetX, offsetY: e.offsetY };
},
onDrag(e) {
const left = this.position.left + (e.offsetX - this.mouseDown.offsetX) / this.zoom;
const top = this.position.top + (e.offsetY - this.mouseDown.offsetY) / this.zoom;
this.$emit("updatePosition", { left, top });
},
onDragEnd(e) {
// this.onDrag(e);
this.$emit("dragEnd");
},
},
};
</script>
+96 -109
View File
@@ -1,94 +1,88 @@
<template>
<div
@click="makeActive()"
:id="idString"
:name="name"
:node-label="label"
:class="classes"
:style="style"
draggable="true"
@mousedown="onMouseDown"
@dragstart="makeActive"
@drag="onDrag"
@dragend="onDragEnd">
<div class="node-header unselectable clearfix">
<b-button
v-b-tooltip.hover
class="node-destroy py-0 float-right"
variant="primary"
size="sm"
aria-label="destroy node"
title="Remove"
@click="onRemove">
<i class="fa fa-times" />
</b-button>
<b-button
v-if="isEnabled"
:id="popoverId"
class="node-recommendations py-0 float-right"
variant="primary"
size="sm"
aria-label="tool recommendations">
<i class="fa fa-arrow-right" />
</b-button>
<b-popover :target="popoverId" triggers="hover" placement="bottom" :show.sync="popoverShow">
<Recommendations
<draggable-wrapper
:position="step.position || defaultPosition"
:zoom="canvasManager.zoomLevel"
@updatePosition="onUpdatePosition">
<div @click="makeActive()" :id="idString" :name="name" :node-label="label" :class="classes" draggable="true">
<div class="node-header unselectable clearfix">
<b-button
v-b-tooltip.hover
class="node-destroy py-0 float-right"
variant="primary"
size="sm"
aria-label="destroy node"
title="Remove"
@click="onRemove">
<i class="fa fa-times" />
</b-button>
<b-button
v-if="isEnabled"
:id="popoverId"
class="node-recommendations py-0 float-right"
variant="primary"
size="sm"
aria-label="tool recommendations">
<i class="fa fa-arrow-right" />
</b-button>
<b-popover :target="popoverId" triggers="hover" placement="bottom" :show.sync="popoverShow">
<Recommendations
:get-node="getNode"
:get-manager="getManager"
:datatypes-mapper="datatypesMapper"
@onCreate="onCreate" />
</b-popover>
<b-button
v-if="canClone"
v-b-tooltip.hover
class="node-clone py-0 float-right"
variant="primary"
size="sm"
aria-label="clone node"
title="Duplicate"
@click="onClone">
<i class="fa fa-files-o" />
</b-button>
<i :class="iconClass" />
<span
v-b-tooltip.hover
title="Index of the step in the workflow run form. Steps are ordered by distance to the upper-left corner of the window; inputs are listed first."
>{{ stepIndex }}:
</span>
<span class="node-title">{{ title }}</span>
</div>
<b-alert v-if="!!errors" variant="danger" show class="node-error">
{{ errors }}
</b-alert>
<div v-else class="node-body">
<loading-span v-if="showLoading" message="Loading details" />
<node-input
v-for="input in inputs"
:key="input.name"
:input="input"
:get-node="getNode"
:get-manager="getManager"
:datatypes-mapper="datatypesMapper"
@onCreate="onCreate" />
</b-popover>
<b-button
v-if="canClone"
v-b-tooltip.hover
class="node-clone py-0 float-right"
variant="primary"
size="sm"
aria-label="clone node"
title="Duplicate"
@click="onClone">
<i class="fa fa-files-o" />
</b-button>
<i :class="iconClass" />
<span
v-b-tooltip.hover
title="Index of the step in the workflow run form. Steps are ordered by distance to the upper-left corner of the window; inputs are listed first."
>{{ stepIndex }}:
</span>
<span class="node-title">{{ title }}</span>
:canvas-manager="canvasManager"
@onAdd="onAddInput"
@onRemove="onRemoveInput"
@onDisconnect="onDisconnect"
@onChange="onChange" />
<div v-if="showRule" class="rule" />
<node-output
v-for="output in outputs"
:key="output.name"
:output="output"
:post-job-actions="postJobActions"
:get-node="getNode"
:get-manager="getManager"
:canvas-manager="canvasManager"
@onAdd="onAddOutput"
@onRemove="onRemoveOutput"
@onToggle="onToggleOutput"
@onChange="onChange" />
</div>
</div>
<b-alert v-if="!!errors" variant="danger" show class="node-error">
{{ errors }}
</b-alert>
<div v-else class="node-body">
<loading-span v-if="showLoading" message="Loading details" />
<node-input
v-for="input in inputs"
:key="input.name"
:input="input"
: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
v-for="output in outputs"
:key="output.name"
:output="output"
:post-job-actions="postJobActions"
:get-node="getNode"
:get-manager="getManager"
:canvas-manager="canvasManager"
@onAdd="onAddOutput"
@onRemove="onRemoveOutput"
@onToggle="onToggleOutput"
@onChange="onChange" />
</div>
</div>
</draggable-wrapper>
</template>
<script>
@@ -100,6 +94,7 @@ import { getGalaxyInstance } from "app";
import Recommendations from "components/Workflow/Editor/Recommendations";
import NodeInput from "./NodeInput";
import NodeOutput from "./NodeOutput";
import DraggableWrapper from "./Draggable";
import { ActiveOutputs } from "./modules/outputs";
Vue.use(BootstrapVue);
@@ -107,6 +102,7 @@ const OFFSET_RANGE = 100;
export default {
components: {
DraggableWrapper,
LoadingSpan,
Recommendations,
NodeInput,
@@ -216,35 +212,22 @@ export default {
}
return cssObj;
},
style() {
const step = this.step;
const styleObj = {};
if (step.position) {
styleObj.top = step.position.top + "px";
styleObj.left = step.position.left + "px";
} else {
// Set initial scroll position
// TODO: should just be in template
const p = document.getElementById("canvas-viewport");
const o = document.getElementById("canvas-container");
if (p && o) {
const el = this.$el;
const left =
-o.offsetLeft + (p.offsetWidth - el.offsetWidth) / 2 + this.offsetVaryPosition(OFFSET_RANGE);
const top =
-o.offsetTop + (p.offsetHeight - el.offsetHeight) / 2 + this.offsetVaryPosition(OFFSET_RANGE);
styleObj.top = `${top}px`;
styleObj.left = `${left}px`;
}
defaultPosition() {
const p = document.getElementById("canvas-viewport");
const o = document.getElementById("canvas-container");
if (p && o) {
const el = this.$el;
const left =
-o.offsetLeft + (p.offsetWidth - el.offsetWidth) / 2 + this.offsetVaryPosition(OFFSET_RANGE);
const top =
-o.offsetTop + (p.offsetHeight - el.offsetHeight) / 2 + this.offsetVaryPosition(OFFSET_RANGE);
return { left, top };
}
return styleObj;
},
},
mounted() {
this.canvasManager = this.getCanvasManager();
this.activeOutputs = new ActiveOutputs();
this.element = this.$el;
this.content_id = this.contentId;
// initialize node data
this.$emit("onAdd", this);
if (this.step.config_form) {
@@ -255,6 +238,10 @@ export default {
},
methods: {
onUpdatePosition(position) {
const newStep = { ...this.step, position };
this.$emit("onUpdateStep", newStep.id, newStep);
},
onMouseDown(e) {
this.mouseDown = { offsetX: e.offsetX, offsetY: e.offsetY };
console.log("mouseDownOffset", this.mouseDown);