mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
refactor(editor): Migrate mouseSelect & deviceSupportHelpers mixins to composables (no-changelog) (#5775)
* refactor(editor): Migrate mouseSelect & deviceSupportHelpers mixins to composables (no-changelog) * Fix node drop position and correct event listeners
This commit is contained in:
parent
c9d9069c0e
commit
78c9707fa7
234
packages/editor-ui/src/composables/useCanvasMouseSelect.ts
Normal file
234
packages/editor-ui/src/composables/useCanvasMouseSelect.ts
Normal file
|
@ -0,0 +1,234 @@
|
|||
import { INodeUi, XYPosition } from '@/Interface';
|
||||
|
||||
import useDeviceSupport from './useDeviceSupport';
|
||||
import { useUIStore } from '@/stores/ui';
|
||||
import { useWorkflowsStore } from '@/stores/workflows';
|
||||
import {
|
||||
getMousePosition,
|
||||
getRelativePosition,
|
||||
HEADER_HEIGHT,
|
||||
SIDEBAR_WIDTH,
|
||||
SIDEBAR_WIDTH_EXPANDED,
|
||||
} from '@/utils/nodeViewUtils';
|
||||
import { ref, watchEffect, onMounted, computed, onUnmounted } from 'vue';
|
||||
import { useCanvasStore } from '@/stores/canvas';
|
||||
|
||||
interface ExtendedHTMLSpanElement extends HTMLSpanElement {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export default function useCanvasMouseSelect() {
|
||||
const selectActive = ref(false);
|
||||
const selectBox = ref(document.createElement('span') as ExtendedHTMLSpanElement);
|
||||
|
||||
const { isTouchDevice, isCtrlKeyPressed } = useDeviceSupport();
|
||||
const uiStore = useUIStore();
|
||||
const canvasStore = useCanvasStore();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
|
||||
function _setSelectBoxStyle(styles: Record<string, string>) {
|
||||
Object.assign(selectBox.value.style, styles);
|
||||
}
|
||||
|
||||
function _showSelectBox(event: MouseEvent) {
|
||||
const [x, y] = getMousePositionWithinNodeView(event);
|
||||
selectBox.value = Object.assign(selectBox.value, { x, y });
|
||||
|
||||
_setSelectBoxStyle({
|
||||
left: selectBox.value.x + 'px',
|
||||
top: selectBox.value.y + 'px',
|
||||
visibility: 'visible',
|
||||
});
|
||||
selectActive.value = true;
|
||||
}
|
||||
|
||||
function _updateSelectBox(event: MouseEvent) {
|
||||
const selectionBox = _getSelectionBox(event);
|
||||
|
||||
_setSelectBoxStyle({
|
||||
left: selectionBox.x + 'px',
|
||||
top: selectionBox.y + 'px',
|
||||
width: selectionBox.width + 'px',
|
||||
height: selectionBox.height + 'px',
|
||||
});
|
||||
}
|
||||
|
||||
function _hideSelectBox() {
|
||||
selectBox.value.x = 0;
|
||||
selectBox.value.y = 0;
|
||||
|
||||
_setSelectBoxStyle({
|
||||
visibility: 'hidden',
|
||||
left: '0px',
|
||||
top: '0px',
|
||||
width: '0px',
|
||||
height: '0px',
|
||||
});
|
||||
selectActive.value = false;
|
||||
}
|
||||
|
||||
function _getSelectionBox(event: MouseEvent) {
|
||||
const [x, y] = getMousePositionWithinNodeView(event);
|
||||
return {
|
||||
x: Math.min(x, selectBox.value.x),
|
||||
y: Math.min(y, selectBox.value.y),
|
||||
width: Math.abs(x - selectBox.value.x),
|
||||
height: Math.abs(y - selectBox.value.y),
|
||||
};
|
||||
}
|
||||
|
||||
function _getNodesInSelection(event: MouseEvent): INodeUi[] {
|
||||
const returnNodes: INodeUi[] = [];
|
||||
const selectionBox = _getSelectionBox(event);
|
||||
|
||||
// Go through all nodes and check if they are selected
|
||||
workflowsStore.allNodes.forEach((node: INodeUi) => {
|
||||
// TODO: Currently always uses the top left corner for checking. Should probably use the center instead
|
||||
if (
|
||||
node.position[0] < selectionBox.x ||
|
||||
node.position[0] > selectionBox.x + selectionBox.width
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
node.position[1] < selectionBox.y ||
|
||||
node.position[1] > selectionBox.y + selectionBox.height
|
||||
) {
|
||||
return;
|
||||
}
|
||||
returnNodes.push(node);
|
||||
});
|
||||
|
||||
return returnNodes;
|
||||
}
|
||||
|
||||
function _createSelectBox() {
|
||||
selectBox.value.id = 'select-box';
|
||||
_setSelectBoxStyle({
|
||||
margin: '0px auto',
|
||||
border: '2px dotted #FF0000',
|
||||
// Positioned absolutely within #node-view. This is consistent with how nodes are positioned.
|
||||
position: 'absolute',
|
||||
zIndex: '100',
|
||||
visibility: 'hidden',
|
||||
});
|
||||
|
||||
selectBox.value.addEventListener('mouseup', mouseUpMouseSelect);
|
||||
|
||||
const nodeViewEl = document.querySelector('#node-view') as HTMLDivElement;
|
||||
nodeViewEl.appendChild(selectBox.value);
|
||||
}
|
||||
|
||||
function _mouseMoveSelect(e: MouseEvent) {
|
||||
if (e.buttons === 0) {
|
||||
// Mouse button is not pressed anymore so stop selection mode
|
||||
// Happens normally when mouse leave the view pressed and then
|
||||
// comes back unpressed.
|
||||
mouseUpMouseSelect(e);
|
||||
return;
|
||||
}
|
||||
|
||||
_updateSelectBox(e);
|
||||
}
|
||||
|
||||
function mouseUpMouseSelect(e: MouseEvent) {
|
||||
if (selectActive.value === false) {
|
||||
if (isTouchDevice === true && e.target instanceof HTMLElement) {
|
||||
if (e.target && e.target.id.includes('node-view')) {
|
||||
// Deselect all nodes
|
||||
deselectAllNodes();
|
||||
}
|
||||
}
|
||||
// If it is not active return directly.
|
||||
// Else normal node dragging will not work.
|
||||
return;
|
||||
}
|
||||
document.removeEventListener('mousemove', _mouseMoveSelect);
|
||||
|
||||
// Deselect all nodes
|
||||
deselectAllNodes();
|
||||
|
||||
// Select the nodes which are in the selection box
|
||||
const selectedNodes = _getNodesInSelection(e);
|
||||
selectedNodes.forEach((node) => {
|
||||
nodeSelected(node);
|
||||
});
|
||||
|
||||
if (selectedNodes.length === 1) {
|
||||
uiStore.lastSelectedNode = selectedNodes[0].name;
|
||||
}
|
||||
|
||||
_hideSelectBox();
|
||||
}
|
||||
function mouseDownMouseSelect(e: MouseEvent, moveButtonPressed: boolean) {
|
||||
if (isCtrlKeyPressed(e) === true || moveButtonPressed) {
|
||||
// We only care about it when the ctrl key is not pressed at the same time.
|
||||
// So we exit when it is pressed.
|
||||
return;
|
||||
}
|
||||
|
||||
if (uiStore.isActionActive('dragActive')) {
|
||||
// If a node does currently get dragged we do not activate the selection
|
||||
return;
|
||||
}
|
||||
_showSelectBox(e);
|
||||
|
||||
// Leave like this.
|
||||
// Do not add an anonymous function because then remove would not work anymore
|
||||
document.addEventListener('mousemove', _mouseMoveSelect);
|
||||
}
|
||||
|
||||
function getMousePositionWithinNodeView(event: MouseEvent | TouchEvent): XYPosition {
|
||||
const [mouseX, mouseY] = getMousePosition(event);
|
||||
|
||||
const sidebarWidth = canvasStore.isDemo
|
||||
? 0
|
||||
: uiStore.sidebarMenuCollapsed
|
||||
? SIDEBAR_WIDTH
|
||||
: SIDEBAR_WIDTH_EXPANDED;
|
||||
const headerHeight = canvasStore.isDemo ? 0 : HEADER_HEIGHT;
|
||||
|
||||
const relativeX = mouseX - sidebarWidth;
|
||||
const relativeY = mouseY - headerHeight;
|
||||
const nodeViewScale = canvasStore.nodeViewScale;
|
||||
const nodeViewOffsetPosition = uiStore.nodeViewOffsetPosition;
|
||||
|
||||
return getRelativePosition(relativeX, relativeY, nodeViewScale, nodeViewOffsetPosition);
|
||||
}
|
||||
|
||||
function nodeDeselected(node: INodeUi) {
|
||||
uiStore.removeNodeFromSelection(node);
|
||||
instance.value.removeFromDragSelection(instance.value.getManagedElement(node?.id));
|
||||
}
|
||||
|
||||
function nodeSelected(node: INodeUi) {
|
||||
uiStore.addSelectedNode(node);
|
||||
instance.value.addToDragSelection(instance.value.getManagedElement(node?.id));
|
||||
}
|
||||
|
||||
function deselectAllNodes() {
|
||||
instance.value.clearDragSelection();
|
||||
uiStore.resetSelectedNodes();
|
||||
uiStore.lastSelectedNode = null;
|
||||
uiStore.lastSelectedNodeOutputIndex = null;
|
||||
|
||||
canvasStore.lastSelectedConnection = null;
|
||||
canvasStore.newNodeInsertPosition = null;
|
||||
}
|
||||
|
||||
const instance = computed(() => canvasStore.jsPlumbInstance);
|
||||
|
||||
onMounted(() => {
|
||||
_createSelectBox();
|
||||
});
|
||||
|
||||
return {
|
||||
getMousePositionWithinNodeView,
|
||||
mouseUpMouseSelect,
|
||||
mouseDownMouseSelect,
|
||||
nodeDeselected,
|
||||
nodeSelected,
|
||||
deselectAllNodes,
|
||||
};
|
||||
}
|
37
packages/editor-ui/src/composables/useDeviceSupport.ts
Normal file
37
packages/editor-ui/src/composables/useDeviceSupport.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import { ref } from 'vue';
|
||||
|
||||
interface DeviceSupportHelpers {
|
||||
isTouchDevice: boolean;
|
||||
isMacOs: boolean;
|
||||
controlKeyCode: string;
|
||||
isCtrlKeyPressed: (e: MouseEvent | KeyboardEvent) => boolean;
|
||||
}
|
||||
|
||||
export default function useDeviceSupportHelpers(): DeviceSupportHelpers {
|
||||
const isTouchDevice = ref('ontouchstart' in window || navigator.maxTouchPoints > 0);
|
||||
const userAgent = ref(navigator.userAgent.toLowerCase());
|
||||
const isMacOs = ref(
|
||||
userAgent.value.includes('macintosh') ||
|
||||
userAgent.value.includes('ipad') ||
|
||||
userAgent.value.includes('iphone') ||
|
||||
userAgent.value.includes('ipod'),
|
||||
);
|
||||
const controlKeyCode = ref(isMacOs.value ? 'Meta' : 'Control');
|
||||
|
||||
function isCtrlKeyPressed(e: MouseEvent | KeyboardEvent): boolean {
|
||||
if (isTouchDevice.value === true) {
|
||||
return true;
|
||||
}
|
||||
if (isMacOs.value) {
|
||||
return (e as KeyboardEvent).metaKey;
|
||||
}
|
||||
return (e as KeyboardEvent).ctrlKey;
|
||||
}
|
||||
|
||||
return {
|
||||
isTouchDevice: isTouchDevice.value,
|
||||
isMacOs: isMacOs.value,
|
||||
controlKeyCode: controlKeyCode.value,
|
||||
isCtrlKeyPressed,
|
||||
};
|
||||
}
|
|
@ -1,225 +0,0 @@
|
|||
import { INodeUi, XYPosition } from '@/Interface';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
|
||||
import { deviceSupportHelpers } from '@/mixins/deviceSupportHelpers';
|
||||
import { VIEWS } from '@/constants';
|
||||
import { mapStores } from 'pinia';
|
||||
import { useUIStore } from '@/stores/ui';
|
||||
import { useWorkflowsStore } from '@/stores/workflows';
|
||||
import {
|
||||
getMousePosition,
|
||||
getRelativePosition,
|
||||
HEADER_HEIGHT,
|
||||
SIDEBAR_WIDTH,
|
||||
SIDEBAR_WIDTH_EXPANDED,
|
||||
} from '@/utils/nodeViewUtils';
|
||||
|
||||
export const mouseSelect = mixins(deviceSupportHelpers).extend({
|
||||
data() {
|
||||
return {
|
||||
selectActive: false,
|
||||
selectBox: document.createElement('span'),
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.createSelectBox();
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useUIStore, useWorkflowsStore),
|
||||
isDemo(): boolean {
|
||||
return this.$route.name === VIEWS.DEMO;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
createSelectBox() {
|
||||
this.selectBox.id = 'select-box';
|
||||
this.selectBox.style.margin = '0px auto';
|
||||
this.selectBox.style.border = '2px dotted #FF0000';
|
||||
// Positioned absolutely within #node-view. This is consistent with how nodes are positioned.
|
||||
this.selectBox.style.position = 'absolute';
|
||||
this.selectBox.style.zIndex = '100';
|
||||
this.selectBox.style.visibility = 'hidden';
|
||||
|
||||
this.selectBox.addEventListener('mouseup', this.mouseUpMouseSelect);
|
||||
|
||||
const nodeViewEl = this.$el.querySelector('#node-view') as HTMLDivElement;
|
||||
nodeViewEl.appendChild(this.selectBox);
|
||||
},
|
||||
isCtrlKeyPressed(e: MouseEvent | KeyboardEvent): boolean {
|
||||
if (this.isTouchDevice === true) {
|
||||
return true;
|
||||
}
|
||||
if (this.isMacOs) {
|
||||
return e.metaKey;
|
||||
}
|
||||
return e.ctrlKey;
|
||||
},
|
||||
getMousePositionWithinNodeView(event: MouseEvent | TouchEvent): XYPosition {
|
||||
const [x, y] = getMousePosition(event);
|
||||
const sidebarOffset = this.isDemo
|
||||
? 0
|
||||
: this.uiStore.sidebarMenuCollapsed
|
||||
? SIDEBAR_WIDTH
|
||||
: SIDEBAR_WIDTH_EXPANDED;
|
||||
const headerOffset = this.isDemo ? 0 : HEADER_HEIGHT;
|
||||
// @ts-ignore
|
||||
return getRelativePosition(
|
||||
x - sidebarOffset,
|
||||
y - headerOffset,
|
||||
this.nodeViewScale,
|
||||
this.uiStore.nodeViewOffsetPosition,
|
||||
);
|
||||
},
|
||||
showSelectBox(event: MouseEvent) {
|
||||
const [x, y] = this.getMousePositionWithinNodeView(event);
|
||||
this.selectBox = Object.assign(this.selectBox, { x, y });
|
||||
|
||||
// @ts-ignore
|
||||
this.selectBox.style.left = this.selectBox.x + 'px';
|
||||
// @ts-ignore
|
||||
this.selectBox.style.top = this.selectBox.y + 'px';
|
||||
this.selectBox.style.visibility = 'visible';
|
||||
|
||||
this.selectActive = true;
|
||||
},
|
||||
updateSelectBox(event: MouseEvent) {
|
||||
const selectionBox = this.getSelectionBox(event);
|
||||
this.selectBox.style.left = selectionBox.x + 'px';
|
||||
this.selectBox.style.top = selectionBox.y + 'px';
|
||||
|
||||
this.selectBox.style.width = selectionBox.width + 'px';
|
||||
this.selectBox.style.height = selectionBox.height + 'px';
|
||||
},
|
||||
hideSelectBox() {
|
||||
this.selectBox.style.visibility = 'hidden';
|
||||
// @ts-ignore
|
||||
this.selectBox.x = 0;
|
||||
// @ts-ignore
|
||||
this.selectBox.y = 0;
|
||||
this.selectBox.style.left = '0px';
|
||||
this.selectBox.style.top = '0px';
|
||||
this.selectBox.style.width = '0px';
|
||||
this.selectBox.style.height = '0px';
|
||||
|
||||
this.selectActive = false;
|
||||
},
|
||||
getSelectionBox(event: MouseEvent) {
|
||||
const [x, y] = this.getMousePositionWithinNodeView(event);
|
||||
return {
|
||||
// @ts-ignore
|
||||
x: Math.min(x, this.selectBox.x),
|
||||
// @ts-ignore
|
||||
y: Math.min(y, this.selectBox.y),
|
||||
// @ts-ignore
|
||||
width: Math.abs(x - this.selectBox.x),
|
||||
// @ts-ignore
|
||||
height: Math.abs(y - this.selectBox.y),
|
||||
};
|
||||
},
|
||||
getNodesInSelection(event: MouseEvent): INodeUi[] {
|
||||
const returnNodes: INodeUi[] = [];
|
||||
const selectionBox = this.getSelectionBox(event);
|
||||
|
||||
// Go through all nodes and check if they are selected
|
||||
this.workflowsStore.allNodes.forEach((node: INodeUi) => {
|
||||
// TODO: Currently always uses the top left corner for checking. Should probably use the center instead
|
||||
if (
|
||||
node.position[0] < selectionBox.x ||
|
||||
node.position[0] > selectionBox.x + selectionBox.width
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
node.position[1] < selectionBox.y ||
|
||||
node.position[1] > selectionBox.y + selectionBox.height
|
||||
) {
|
||||
return;
|
||||
}
|
||||
returnNodes.push(node);
|
||||
});
|
||||
|
||||
return returnNodes;
|
||||
},
|
||||
mouseDownMouseSelect(e: MouseEvent, moveButtonPressed: boolean) {
|
||||
if (this.isCtrlKeyPressed(e) === true || moveButtonPressed) {
|
||||
// We only care about it when the ctrl key is not pressed at the same time.
|
||||
// So we exit when it is pressed.
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.uiStore.isActionActive('dragActive')) {
|
||||
// If a node does currently get dragged we do not activate the selection
|
||||
return;
|
||||
}
|
||||
this.showSelectBox(e);
|
||||
|
||||
// @ts-ignore // Leave like this. Do not add a anonymous function because then remove would not work anymore
|
||||
this.$el.addEventListener('mousemove', this.mouseMoveSelect);
|
||||
},
|
||||
mouseUpMouseSelect(e: MouseEvent) {
|
||||
if (this.selectActive === false) {
|
||||
if (this.isTouchDevice === true) {
|
||||
// @ts-ignore
|
||||
if (e.target && e.target.id.includes('node-view')) {
|
||||
// Deselect all nodes
|
||||
this.deselectAllNodes();
|
||||
}
|
||||
}
|
||||
// If it is not active return directly.
|
||||
// Else normal node dragging will not work.
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
this.$el.removeEventListener('mousemove', this.mouseMoveSelect);
|
||||
|
||||
// Deselect all nodes
|
||||
this.deselectAllNodes();
|
||||
|
||||
// Select the nodes which are in the selection box
|
||||
const selectedNodes = this.getNodesInSelection(e);
|
||||
selectedNodes.forEach((node) => {
|
||||
this.nodeSelected(node);
|
||||
});
|
||||
|
||||
if (selectedNodes.length === 1) {
|
||||
this.uiStore.lastSelectedNode = selectedNodes[0].name;
|
||||
}
|
||||
|
||||
this.hideSelectBox();
|
||||
},
|
||||
mouseMoveSelect(e: MouseEvent) {
|
||||
if (e.buttons === 0) {
|
||||
// Mouse button is not pressed anymore so stop selection mode
|
||||
// Happens normally when mouse leave the view pressed and then
|
||||
// comes back unpressed.
|
||||
this.mouseUpMouseSelect(e);
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateSelectBox(e);
|
||||
},
|
||||
nodeDeselected(node: INodeUi) {
|
||||
this.uiStore.removeNodeFromSelection(node);
|
||||
// @ts-ignore
|
||||
this.instance.removeFromDragSelection(this.instance.getManagedElement(node?.id));
|
||||
},
|
||||
nodeSelected(node: INodeUi) {
|
||||
this.uiStore.addSelectedNode(node);
|
||||
// @ts-ignore
|
||||
this.instance.addToDragSelection(this.instance.getManagedElement(node?.id));
|
||||
},
|
||||
deselectAllNodes() {
|
||||
// @ts-ignore
|
||||
this.instance.clearDragSelection();
|
||||
this.uiStore.resetSelectedNodes();
|
||||
this.uiStore.lastSelectedNode = null;
|
||||
this.uiStore.lastSelectedNodeOutputIndex = null;
|
||||
// @ts-ignore
|
||||
this.lastSelectedConnection = null;
|
||||
// @ts-ignore
|
||||
this.newNodeInsertPosition = null;
|
||||
},
|
||||
},
|
||||
});
|
|
@ -18,7 +18,7 @@ import { newInstance } from '@jsplumb/browser-ui';
|
|||
import { N8nPlusEndpointHandler } from '@/plugins/endpoints/N8nPlusEndpointType';
|
||||
import * as N8nPlusEndpointRenderer from '@/plugins/endpoints/N8nPlusEndpointRenderer';
|
||||
import { N8nConnector } from '@/plugins/connectors/N8nCustomConnector';
|
||||
import { EndpointFactory, Connectors } from '@jsplumb/core';
|
||||
import { EndpointFactory, Connectors, Connection } from '@jsplumb/core';
|
||||
import { MoveNodeCommand } from '@/models/history';
|
||||
import {
|
||||
DEFAULT_PLACEHOLDER_TRIGGER_BUTTON,
|
||||
|
@ -42,6 +42,8 @@ export const useCanvasStore = defineStore('canvas', () => {
|
|||
|
||||
const jsPlumbInstanceRef = ref<BrowserJsPlumbInstance>();
|
||||
const isDragging = ref<boolean>(false);
|
||||
const lastSelectedConnection = ref<Connection | null>(null);
|
||||
const newNodeInsertPosition = ref<XYPosition | null>(null);
|
||||
|
||||
const nodes = computed<INodeUi[]>(() => workflowStore.allNodes);
|
||||
const triggerNodes = computed<INodeUi[]>(() =>
|
||||
|
@ -256,6 +258,9 @@ export const useCanvasStore = defineStore('canvas', () => {
|
|||
isDemo,
|
||||
nodeViewScale,
|
||||
canvasAddButtonPosition,
|
||||
lastSelectedConnection,
|
||||
newNodeInsertPosition,
|
||||
jsPlumbInstance,
|
||||
setRecenteredCanvasAddButtonPosition,
|
||||
getNodesWithPlaceholderNode,
|
||||
setZoomLevel,
|
||||
|
@ -265,6 +270,5 @@ export const useCanvasStore = defineStore('canvas', () => {
|
|||
zoomToFit,
|
||||
wheelScroll,
|
||||
initInstance,
|
||||
jsPlumbInstance,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -203,10 +203,10 @@ import {
|
|||
import { copyPaste } from '@/mixins/copyPaste';
|
||||
import { externalHooks } from '@/mixins/externalHooks';
|
||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
||||
import { mouseSelect } from '@/mixins/mouseSelect';
|
||||
import { moveNodeWorkflow } from '@/mixins/moveNodeWorkflow';
|
||||
import { restApi } from '@/mixins/restApi';
|
||||
import useGlobalLinkActions from '@/composables/useGlobalLinkActions';
|
||||
import useCanvasMouseSelect from '@/composables/useCanvasMouseSelect';
|
||||
import { showMessage } from '@/mixins/showMessage';
|
||||
import { titleChange } from '@/mixins/titleChange';
|
||||
|
||||
|
@ -321,7 +321,6 @@ export default mixins(
|
|||
copyPaste,
|
||||
externalHooks,
|
||||
genericHelpers,
|
||||
mouseSelect,
|
||||
moveNodeWorkflow,
|
||||
restApi,
|
||||
showMessage,
|
||||
|
@ -342,10 +341,9 @@ export default mixins(
|
|||
CanvasControls,
|
||||
},
|
||||
setup() {
|
||||
const { registerCustomAction, unregisterCustomAction } = useGlobalLinkActions();
|
||||
return {
|
||||
registerCustomAction,
|
||||
unregisterCustomAction,
|
||||
...useCanvasMouseSelect(),
|
||||
...useGlobalLinkActions(),
|
||||
};
|
||||
},
|
||||
errorCaptured: (err, vm, info) => {
|
||||
|
@ -592,14 +590,12 @@ export default mixins(
|
|||
GRID_SIZE: NodeViewUtils.GRID_SIZE,
|
||||
STICKY_NODE_TYPE,
|
||||
createNodeActive: false,
|
||||
lastSelectedConnection: null as null | Connection,
|
||||
lastClickPosition: [450, 450] as XYPosition,
|
||||
ctrlKeyPressed: false,
|
||||
moveCanvasKeyPressed: false,
|
||||
stopExecutionInProgress: false,
|
||||
blankRedirect: false,
|
||||
credentialsUpdated: false,
|
||||
newNodeInsertPosition: null as XYPosition | null,
|
||||
pullConnActiveNodeName: null as string | null,
|
||||
pullConnActive: false,
|
||||
dropPrevented: false,
|
||||
|
@ -1682,7 +1678,8 @@ export default mixins(
|
|||
// If adding more than one node, offset the X position
|
||||
mousePosition[0] -
|
||||
NodeViewUtils.NODE_SIZE / 2 +
|
||||
NodeViewUtils.NODE_SIZE * (index * 2 + NodeViewUtils.GRID_SIZE),
|
||||
NodeViewUtils.NODE_SIZE * index * 2 +
|
||||
NodeViewUtils.GRID_SIZE,
|
||||
mousePosition[1] - NodeViewUtils.NODE_SIZE / 2,
|
||||
] as XYPosition,
|
||||
dragAndDrop: true,
|
||||
|
@ -1711,8 +1708,8 @@ export default mixins(
|
|||
this.nodeSelected(node);
|
||||
this.uiStore.lastSelectedNode = node.name;
|
||||
this.uiStore.lastSelectedNodeOutputIndex = null;
|
||||
this.lastSelectedConnection = null;
|
||||
this.newNodeInsertPosition = null;
|
||||
this.canvasStore.lastSelectedConnection = null;
|
||||
this.canvasStore.newNodeInsertPosition = null;
|
||||
|
||||
if (setActive) {
|
||||
this.ndvStore.activeNodeName = node.name;
|
||||
|
@ -1854,7 +1851,7 @@ export default mixins(
|
|||
options.position,
|
||||
);
|
||||
} else if (lastSelectedNode) {
|
||||
const lastSelectedConnection = this.lastSelectedConnection;
|
||||
const lastSelectedConnection = this.canvasStore.lastSelectedConnection;
|
||||
if (lastSelectedConnection) {
|
||||
// set when injecting into a connection
|
||||
const [diffX] = NodeViewUtils.getConnectorLengths(lastSelectedConnection);
|
||||
|
@ -1868,12 +1865,12 @@ export default mixins(
|
|||
}
|
||||
|
||||
// set when pulling connections
|
||||
if (this.newNodeInsertPosition) {
|
||||
if (this.canvasStore.newNodeInsertPosition) {
|
||||
newNodeData.position = NodeViewUtils.getNewNodePosition(this.nodes, [
|
||||
this.newNodeInsertPosition[0] + NodeViewUtils.GRID_SIZE,
|
||||
this.newNodeInsertPosition[1] - NodeViewUtils.NODE_SIZE / 2,
|
||||
this.canvasStore.newNodeInsertPosition[0] + NodeViewUtils.GRID_SIZE,
|
||||
this.canvasStore.newNodeInsertPosition[1] - NodeViewUtils.NODE_SIZE / 2,
|
||||
]);
|
||||
this.newNodeInsertPosition = null;
|
||||
this.canvasStore.newNodeInsertPosition = null;
|
||||
} else {
|
||||
let yOffset = 0;
|
||||
|
||||
|
@ -2035,7 +2032,7 @@ export default mixins(
|
|||
return;
|
||||
}
|
||||
|
||||
const lastSelectedConnection = this.lastSelectedConnection;
|
||||
const lastSelectedConnection = this.canvasStore.lastSelectedConnection;
|
||||
const lastSelectedNode = this.lastSelectedNode;
|
||||
const lastSelectedNodeOutputIndex = this.uiStore.lastSelectedNodeOutputIndex;
|
||||
|
||||
|
@ -2087,10 +2084,10 @@ export default mixins(
|
|||
|
||||
this.uiStore.lastSelectedNode = sourceNode.name;
|
||||
this.uiStore.lastSelectedNodeOutputIndex = info.index;
|
||||
this.newNodeInsertPosition = null;
|
||||
this.canvasStore.newNodeInsertPosition = null;
|
||||
|
||||
if (info.connection) {
|
||||
this.lastSelectedConnection = info.connection;
|
||||
this.canvasStore.lastSelectedConnection = info.connection;
|
||||
}
|
||||
|
||||
this.onToggleNodeCreator({
|
||||
|
@ -2363,7 +2360,7 @@ export default mixins(
|
|||
try {
|
||||
this.pullConnActiveNodeName = null;
|
||||
this.pullConnActive = true;
|
||||
this.newNodeInsertPosition = null;
|
||||
this.canvasStore.newNodeInsertPosition = null;
|
||||
NodeViewUtils.resetConnection(connection);
|
||||
|
||||
const nodes = [...document.querySelectorAll('.node-wrapper')];
|
||||
|
@ -2414,7 +2411,7 @@ export default mixins(
|
|||
|
||||
const onMouseUp = (e: MouseEvent | TouchEvent) => {
|
||||
this.pullConnActive = false;
|
||||
this.newNodeInsertPosition = this.getMousePositionWithinNodeView(e);
|
||||
this.canvasStore.newNodeInsertPosition = this.getMousePositionWithinNodeView(e);
|
||||
NodeViewUtils.resetConnectionAfterPull(connection);
|
||||
window.removeEventListener('mousemove', onMouseMove);
|
||||
window.removeEventListener('mouseup', onMouseUp);
|
||||
|
|
Loading…
Reference in a new issue