mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-20 19:32:15 +00:00
refactor(editor): Upgrade to jsPlumb 5 (#4989)
* WIP: Nodeview * Replace types * Finish N8nPlus endpoint type * Working on connector * Apply prettier * Fixed prettier issues * Debugging rendering * Fixed connectorrs position recalc * Fix snapping and output labels, WIP dragging * Fix N8nPlus endpoint rendering issues * Cleanup * Fix undo/redo and canvas add button position, cleanup * Cleanup * Revert accidental CLI changes * Fix pnpm-lock * Address bugs that came up during review * Reset CLI package from master * Various fixes * Fix run items label toggling * Linter fixes * Fix stalk size for larger run items label * Remove comment * Correctly reset workspace after renaming the node * Fix canvas e2e tests * Fix undo/redo tests * Fix stalk positioning and triggering of endpoint overlays * Repaint connections on pin removal * Limit repaintings * Unbind jsPlumb events on deactivation * Fix jsPlumb managment of Sticky and minor memort managment improvments * Address rest of PR points * Lint fix * Copy patches folder to docker * Fix e2e tests * set allowNonAppliedPatches to allow build * fix(editor): Handling router errors when navigation is canceled by user (#5271) * 🔨 Handling router errors in main sidebar, removing unused code * 🔨 Handling router errors in modals * ci(core): Fix docker nightly/custom image build (no-changelog) (#5284) * ci(core): Copy patches dir to Docker (no-changelog) * Update patch * Update package-lock * reapply the patch * skip patchedDependencies after the frontend is built --------- Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in> * Fix connector hover state on success * Remove allowNonAppliedPatches from package.json --------- Co-authored-by: Milorad FIlipović <milorad@n8n.io> Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
import { closestNumberDivisibleBy, getStyleTokenValue, isNumber } from '@/utils';
|
||||
import { getStyleTokenValue } from '@/utils/htmlUtils';
|
||||
import { isNumber } from '@/utils';
|
||||
import { NODE_OUTPUT_DEFAULT_KEY, STICKY_NODE_TYPE, QUICKSTART_NOTE_NAME } from '@/constants';
|
||||
import { EndpointStyle, IBounds, INodeUi, XYPosition } from '@/Interface';
|
||||
import { AnchorArraySpec, Connection, Endpoint, Overlay, OverlaySpec, PaintStyle } from 'jsplumb';
|
||||
import { ArrayAnchorSpec, ConnectorSpec, OverlaySpec, PaintStyle } from '@jsplumb/common';
|
||||
import { Endpoint, Connection } from '@jsplumb/core';
|
||||
import { N8nConnector } from '@/plugins/connectors/N8nCustomConnector';
|
||||
import { closestNumberDivisibleBy } from '@/utils';
|
||||
import {
|
||||
IConnection,
|
||||
INode,
|
||||
@@ -10,6 +14,7 @@ import {
|
||||
NodeInputConnections,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { EVENT_CONNECTION_MOUSEOUT, EVENT_CONNECTION_MOUSEOVER } from '@jsplumb/browser-ui';
|
||||
|
||||
/*
|
||||
Canvas constants and functions.
|
||||
@@ -24,8 +29,7 @@ export const OVERLAY_RUN_ITEMS_ID = 'run-items-label';
|
||||
export const OVERLAY_CONNECTION_ACTIONS_ID = 'connection-actions';
|
||||
export const JSPLUMB_FLOWCHART_STUB = 26;
|
||||
export const OVERLAY_INPUT_NAME_LABEL = 'input-name-label';
|
||||
export const OVERLAY_INPUT_NAME_LABEL_POSITION = [-3, 0.5];
|
||||
export const OVERLAY_INPUT_NAME_LABEL_POSITION_MOVED = [-4.5, 0.5];
|
||||
export const OVERLAY_INPUT_NAME_MOVED_CLASS = 'node-input-endpoint-label--moved';
|
||||
export const OVERLAY_OUTPUT_NAME_LABEL = 'output-name-label';
|
||||
export const GRID_SIZE = 20;
|
||||
|
||||
@@ -69,9 +73,9 @@ export const WELCOME_STICKY_NODE = {
|
||||
},
|
||||
};
|
||||
|
||||
export const CONNECTOR_FLOWCHART_TYPE = [
|
||||
'N8nCustom',
|
||||
{
|
||||
export const CONNECTOR_FLOWCHART_TYPE: ConnectorSpec = {
|
||||
type: N8nConnector.type,
|
||||
options: {
|
||||
cornerRadius: 12,
|
||||
stub: JSPLUMB_FLOWCHART_STUB + 10,
|
||||
targetGap: 4,
|
||||
@@ -91,7 +95,7 @@ export const CONNECTOR_FLOWCHART_TYPE = [
|
||||
return index * indexOffset + labelOffset + outputsOffset;
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const CONNECTOR_PAINT_STYLE_DEFAULT: PaintStyle = {
|
||||
stroke: getStyleTokenValue('--color-foreground-dark'),
|
||||
@@ -110,15 +114,10 @@ export const CONNECTOR_PAINT_STYLE_PRIMARY = {
|
||||
stroke: getStyleTokenValue('--color-primary'),
|
||||
};
|
||||
|
||||
export const CONNECTOR_PAINT_STYLE_SUCCESS = {
|
||||
...CONNECTOR_PAINT_STYLE_DEFAULT,
|
||||
stroke: getStyleTokenValue('--color-success-light'),
|
||||
};
|
||||
|
||||
export const CONNECTOR_ARROW_OVERLAYS: OverlaySpec[] = [
|
||||
[
|
||||
'Arrow',
|
||||
{
|
||||
{
|
||||
type: 'Arrow',
|
||||
options: {
|
||||
id: OVERLAY_ENDPOINT_ARROW_ID,
|
||||
location: 1,
|
||||
width: 12,
|
||||
@@ -126,10 +125,10 @@ export const CONNECTOR_ARROW_OVERLAYS: OverlaySpec[] = [
|
||||
length: 10,
|
||||
visible: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Arrow',
|
||||
{
|
||||
},
|
||||
{
|
||||
type: 'Arrow',
|
||||
options: {
|
||||
id: OVERLAY_MIDPOINT_ARROW_ID,
|
||||
location: 0.5,
|
||||
width: 12,
|
||||
@@ -137,12 +136,12 @@ export const CONNECTOR_ARROW_OVERLAYS: OverlaySpec[] = [
|
||||
length: 10,
|
||||
visible: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const ANCHOR_POSITIONS: {
|
||||
[key: string]: {
|
||||
[key: number]: AnchorArraySpec[];
|
||||
[key: number]: ArrayAnchorSpec[];
|
||||
};
|
||||
} = {
|
||||
input: {
|
||||
@@ -194,33 +193,42 @@ export const getInputEndpointStyle = (
|
||||
lineWidth: 0,
|
||||
});
|
||||
|
||||
export const getInputNameOverlay = (label: string): OverlaySpec => [
|
||||
'Label',
|
||||
{
|
||||
export const getInputNameOverlay = (labelText: string): OverlaySpec => ({
|
||||
type: 'Custom',
|
||||
options: {
|
||||
id: OVERLAY_INPUT_NAME_LABEL,
|
||||
location: OVERLAY_INPUT_NAME_LABEL_POSITION,
|
||||
label,
|
||||
cssClass: 'node-input-endpoint-label',
|
||||
visible: true,
|
||||
create: (component: Endpoint) => {
|
||||
const label = document.createElement('div');
|
||||
label.innerHTML = labelText;
|
||||
label.classList.add('node-input-endpoint-label');
|
||||
return label;
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
export const getOutputEndpointStyle = (nodeTypeData: INodeTypeDescription, color: string) => ({
|
||||
radius: nodeTypeData && nodeTypeData.outputs.length > 2 ? 7 : 9,
|
||||
export const getOutputEndpointStyle = (
|
||||
nodeTypeData: INodeTypeDescription,
|
||||
color: string,
|
||||
): PaintStyle => ({
|
||||
strokeWidth: nodeTypeData && nodeTypeData.outputs.length > 2 ? 7 : 9,
|
||||
fill: getStyleTokenValue(color),
|
||||
outlineStroke: 'none',
|
||||
});
|
||||
|
||||
export const getOutputNameOverlay = (label: string): OverlaySpec => [
|
||||
'Label',
|
||||
{
|
||||
export const getOutputNameOverlay = (labelText: string): OverlaySpec => ({
|
||||
type: 'Custom',
|
||||
options: {
|
||||
id: OVERLAY_OUTPUT_NAME_LABEL,
|
||||
location: [1.9, 0.5],
|
||||
label,
|
||||
cssClass: 'node-output-endpoint-label',
|
||||
visible: true,
|
||||
create: (component: Endpoint) => {
|
||||
const label = document.createElement('div');
|
||||
label.innerHTML = labelText;
|
||||
label.classList.add('node-output-endpoint-label');
|
||||
return label;
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
export const addOverlays = (connection: Connection, overlays: OverlaySpec[]) => {
|
||||
overlays.forEach((overlay: OverlaySpec) => {
|
||||
@@ -302,25 +310,34 @@ export const showOrHideMidpointArrow = (connection: Connection) => {
|
||||
if (!connection || !connection.endpoints || connection.endpoints.length !== 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasItemsLabel = !!getOverlay(connection, OVERLAY_RUN_ITEMS_ID);
|
||||
|
||||
const sourceEndpoint = connection.endpoints[0];
|
||||
const targetEndpoint = connection.endpoints[1];
|
||||
|
||||
const sourcePosition = sourceEndpoint.anchor.lastReturnValue[0];
|
||||
const targetPosition = targetEndpoint.anchor.lastReturnValue
|
||||
? targetEndpoint.anchor.lastReturnValue[0]
|
||||
: sourcePosition + 1; // lastReturnValue is null when moving connections from node to another
|
||||
const sourcePosition = sourceEndpoint._anchor.computedPosition?.curX ?? 0;
|
||||
const targetPosition = targetEndpoint._anchor.computedPosition?.curX ?? sourcePosition + 1;
|
||||
|
||||
const minimum = hasItemsLabel ? 150 : 0;
|
||||
const isBackwards = sourcePosition >= targetPosition;
|
||||
const isTooLong = Math.abs(sourcePosition - targetPosition) >= minimum;
|
||||
const isActionsOverlayHovered = getOverlay(
|
||||
connection,
|
||||
OVERLAY_CONNECTION_ACTIONS_ID,
|
||||
)?.component.isHover();
|
||||
const isConnectionHovered = connection.isHover();
|
||||
|
||||
const arrow = getOverlay(connection, OVERLAY_MIDPOINT_ARROW_ID);
|
||||
const isArrowVisible =
|
||||
isBackwards &&
|
||||
isTooLong &&
|
||||
!isActionsOverlayHovered &&
|
||||
!isConnectionHovered &&
|
||||
!connection.instance.isConnectionBeingDragged;
|
||||
|
||||
if (arrow) {
|
||||
arrow.setVisible(isBackwards && isTooLong);
|
||||
arrow.setVisible(isArrowVisible);
|
||||
arrow.setLocation(hasItemsLabel ? 0.6 : 0.5);
|
||||
connection.instance.repaint(arrow.canvas);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -329,8 +346,8 @@ export const getConnectorLengths = (connection: Connection): [number, number] =>
|
||||
return [0, 0];
|
||||
}
|
||||
const bounds = connection.connector.bounds;
|
||||
const diffX = Math.abs(bounds.maxX - bounds.minX);
|
||||
const diffY = Math.abs(bounds.maxY - bounds.minY);
|
||||
const diffX = Math.abs(bounds.xmax - bounds.xmin);
|
||||
const diffY = Math.abs(bounds.ymax - bounds.ymin);
|
||||
|
||||
return [diffX, diffY];
|
||||
};
|
||||
@@ -339,36 +356,30 @@ const isLoopingBackwards = (connection: Connection) => {
|
||||
const sourceEndpoint = connection.endpoints[0];
|
||||
const targetEndpoint = connection.endpoints[1];
|
||||
|
||||
const sourcePosition = sourceEndpoint.anchor.lastReturnValue[0];
|
||||
const targetPosition = targetEndpoint.anchor.lastReturnValue[0];
|
||||
const sourcePosition = sourceEndpoint._anchor.computedPosition?.curX ?? 0;
|
||||
const targetPosition = targetEndpoint._anchor.computedPosition?.curX ?? 0;
|
||||
|
||||
return targetPosition - sourcePosition < -1 * LOOPBACK_MINIMUM;
|
||||
};
|
||||
|
||||
export const showOrHideItemsLabel = (connection: Connection) => {
|
||||
if (!connection || !connection.connector) {
|
||||
return;
|
||||
}
|
||||
if (!connection?.connector) return;
|
||||
|
||||
const overlay = getOverlay(connection, OVERLAY_RUN_ITEMS_ID);
|
||||
if (!overlay) {
|
||||
return;
|
||||
}
|
||||
if (!overlay) return;
|
||||
|
||||
const actionsOverlay = getOverlay(connection, OVERLAY_CONNECTION_ACTIONS_ID);
|
||||
if (actionsOverlay && actionsOverlay.visible) {
|
||||
const isActionsOverlayHovered = actionsOverlay?.component.isHover();
|
||||
|
||||
if (isActionsOverlayHovered) {
|
||||
overlay.setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const [diffX, diffY] = getConnectorLengths(connection);
|
||||
const isHidden = diffX < MIN_X_TO_SHOW_OUTPUT_LABEL && diffY < MIN_Y_TO_SHOW_OUTPUT_LABEL;
|
||||
|
||||
if (diffX < MIN_X_TO_SHOW_OUTPUT_LABEL && diffY < MIN_Y_TO_SHOW_OUTPUT_LABEL) {
|
||||
overlay.setVisible(false);
|
||||
} else {
|
||||
overlay.setVisible(true);
|
||||
}
|
||||
|
||||
overlay.setVisible(!isHidden);
|
||||
const innerElement = overlay.canvas && overlay.canvas.querySelector('span');
|
||||
if (innerElement) {
|
||||
if (diffY === 0 || isLoopingBackwards(connection)) {
|
||||
@@ -503,22 +514,27 @@ export const getBackgroundStyles = (
|
||||
return styles;
|
||||
};
|
||||
|
||||
export const hideConnectionActions = (connection: Connection | null) => {
|
||||
if (connection && connection.connector) {
|
||||
hideOverlay(connection, OVERLAY_CONNECTION_ACTIONS_ID);
|
||||
showOrHideItemsLabel(connection);
|
||||
showOrHideMidpointArrow(connection);
|
||||
}
|
||||
export const hideConnectionActions = (connection: Connection) => {
|
||||
connection.instance.setSuspendDrawing(true);
|
||||
hideOverlay(connection, OVERLAY_CONNECTION_ACTIONS_ID);
|
||||
showOrHideMidpointArrow(connection);
|
||||
showOrHideItemsLabel(connection);
|
||||
connection.instance.setSuspendDrawing(false);
|
||||
(connection.endpoints || []).forEach((endpoint) => {
|
||||
connection.instance.repaint(endpoint.element);
|
||||
});
|
||||
};
|
||||
|
||||
export const showConnectionActions = (connection: Connection | null) => {
|
||||
if (connection && connection.connector) {
|
||||
showOverlay(connection, OVERLAY_CONNECTION_ACTIONS_ID);
|
||||
hideOverlay(connection, OVERLAY_RUN_ITEMS_ID);
|
||||
if (!getOverlay(connection, OVERLAY_RUN_ITEMS_ID)) {
|
||||
hideOverlay(connection, OVERLAY_MIDPOINT_ARROW_ID);
|
||||
}
|
||||
export const showConnectionActions = (connection: Connection) => {
|
||||
showOverlay(connection, OVERLAY_CONNECTION_ACTIONS_ID);
|
||||
hideOverlay(connection, OVERLAY_RUN_ITEMS_ID);
|
||||
if (!getOverlay(connection, OVERLAY_RUN_ITEMS_ID)) {
|
||||
hideOverlay(connection, OVERLAY_MIDPOINT_ARROW_ID);
|
||||
}
|
||||
|
||||
(connection.endpoints || []).forEach((endpoint) => {
|
||||
connection.instance.repaint(endpoint.element);
|
||||
});
|
||||
};
|
||||
|
||||
export const getOutputSummary = (data: ITaskData[], nodeConnections: NodeInputConnections) => {
|
||||
@@ -586,11 +602,9 @@ export const getOutputSummary = (data: ITaskData[], nodeConnections: NodeInputCo
|
||||
|
||||
export const resetConnection = (connection: Connection) => {
|
||||
connection.removeOverlay(OVERLAY_RUN_ITEMS_ID);
|
||||
connection.setPaintStyle(CONNECTOR_PAINT_STYLE_DEFAULT);
|
||||
connection.removeClass('success');
|
||||
showOrHideMidpointArrow(connection);
|
||||
if (connection.canvas) {
|
||||
connection.canvas.classList.remove('success');
|
||||
}
|
||||
connection.setPaintStyle(CONNECTOR_PAINT_STYLE_DEFAULT);
|
||||
};
|
||||
|
||||
export const getRunItemsLabel = (output: { total: number; iterations: number }): string => {
|
||||
@@ -604,27 +618,36 @@ export const addConnectionOutputSuccess = (
|
||||
connection: Connection,
|
||||
output: { total: number; iterations: number },
|
||||
) => {
|
||||
connection.setPaintStyle(CONNECTOR_PAINT_STYLE_SUCCESS);
|
||||
if (connection.canvas) {
|
||||
connection.canvas.classList.add('success');
|
||||
}
|
||||
|
||||
connection.addClass('success');
|
||||
if (getOverlay(connection, OVERLAY_RUN_ITEMS_ID)) {
|
||||
connection.removeOverlay(OVERLAY_RUN_ITEMS_ID);
|
||||
}
|
||||
|
||||
connection.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
const overlay = connection.addOverlay({
|
||||
type: 'Custom',
|
||||
options: {
|
||||
id: OVERLAY_RUN_ITEMS_ID,
|
||||
label: `<span>${getRunItemsLabel(output)}</span>`,
|
||||
cssClass: 'connection-run-items-label',
|
||||
create() {
|
||||
const container = document.createElement('div');
|
||||
const span = document.createElement('span');
|
||||
|
||||
container.classList.add('connection-run-items-label');
|
||||
span.classList.add('floating');
|
||||
span.innerHTML = getRunItemsLabel(output);
|
||||
container.appendChild(span);
|
||||
return container;
|
||||
},
|
||||
location: 0.5,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
overlay.setVisible(true);
|
||||
showOrHideItemsLabel(connection);
|
||||
showOrHideMidpointArrow(connection);
|
||||
|
||||
(connection.endpoints || []).forEach((endpoint) => {
|
||||
connection.instance.repaint(endpoint.element);
|
||||
});
|
||||
};
|
||||
|
||||
const getContentDimensions = (): { editorWidth: number; editorHeight: number } => {
|
||||
@@ -677,9 +700,10 @@ export const getZoomToFit = (
|
||||
};
|
||||
|
||||
export const showDropConnectionState = (connection: Connection, targetEndpoint?: Endpoint) => {
|
||||
if (connection && connection.connector) {
|
||||
if (connection?.connector) {
|
||||
const connector = connection.connector as N8nConnector;
|
||||
if (targetEndpoint) {
|
||||
connection.connector.setTargetEndpoint(targetEndpoint);
|
||||
connector.setTargetEndpoint(targetEndpoint);
|
||||
}
|
||||
connection.setPaintStyle(CONNECTOR_PAINT_STYLE_PRIMARY);
|
||||
hideOverlay(connection, OVERLAY_DROP_NODE_ID);
|
||||
@@ -687,31 +711,33 @@ export const showDropConnectionState = (connection: Connection, targetEndpoint?:
|
||||
};
|
||||
|
||||
export const showPullConnectionState = (connection: Connection) => {
|
||||
if (connection && connection.connector) {
|
||||
connection.connector.resetTargetEndpoint();
|
||||
if (connection?.connector) {
|
||||
const connector = connection.connector as N8nConnector;
|
||||
connector.resetTargetEndpoint();
|
||||
connection.setPaintStyle(CONNECTOR_PAINT_STYLE_PULL);
|
||||
showOverlay(connection, OVERLAY_DROP_NODE_ID);
|
||||
}
|
||||
};
|
||||
|
||||
export const resetConnectionAfterPull = (connection: Connection) => {
|
||||
if (connection && connection.connector) {
|
||||
connection.connector.resetTargetEndpoint();
|
||||
if (connection?.connector) {
|
||||
const connector = connection.connector as N8nConnector;
|
||||
connector.resetTargetEndpoint();
|
||||
connection.setPaintStyle(CONNECTOR_PAINT_STYLE_DEFAULT);
|
||||
}
|
||||
};
|
||||
|
||||
export const resetInputLabelPosition = (targetEndpoint: Endpoint) => {
|
||||
export const resetInputLabelPosition = (targetEndpoint: Connection | Endpoint) => {
|
||||
const inputNameOverlay = getOverlay(targetEndpoint, OVERLAY_INPUT_NAME_LABEL);
|
||||
if (inputNameOverlay) {
|
||||
inputNameOverlay.setLocation(OVERLAY_INPUT_NAME_LABEL_POSITION);
|
||||
targetEndpoint.instance.removeOverlayClass(inputNameOverlay, OVERLAY_INPUT_NAME_MOVED_CLASS);
|
||||
}
|
||||
};
|
||||
|
||||
export const moveBackInputLabelPosition = (targetEndpoint: Endpoint) => {
|
||||
const inputNameOverlay = getOverlay(targetEndpoint, OVERLAY_INPUT_NAME_LABEL);
|
||||
if (inputNameOverlay) {
|
||||
inputNameOverlay.setLocation(OVERLAY_INPUT_NAME_LABEL_POSITION_MOVED);
|
||||
targetEndpoint.instance.addOverlayClass(inputNameOverlay, OVERLAY_INPUT_NAME_MOVED_CLASS);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -720,36 +746,42 @@ export const addConnectionActionsOverlay = (
|
||||
onDelete: Function,
|
||||
onAdd: Function,
|
||||
) => {
|
||||
if (getOverlay(connection, OVERLAY_CONNECTION_ACTIONS_ID)) {
|
||||
return; // avoid free floating actions when moving connection from one node to another
|
||||
}
|
||||
connection.addOverlay([
|
||||
'Label',
|
||||
{
|
||||
const overlay = connection.addOverlay({
|
||||
type: 'Custom',
|
||||
options: {
|
||||
id: OVERLAY_CONNECTION_ACTIONS_ID,
|
||||
label: `<div class="add">${getIcon('plus')}</div> <div class="delete">${getIcon(
|
||||
'trash',
|
||||
)}</div>`,
|
||||
cssClass: OVERLAY_CONNECTION_ACTIONS_ID,
|
||||
visible: false,
|
||||
events: {
|
||||
mousedown: (overlay: Overlay, event: MouseEvent) => {
|
||||
const element = event.target as HTMLElement;
|
||||
if (
|
||||
element.classList.contains('delete') ||
|
||||
(element.parentElement && element.parentElement.classList.contains('delete'))
|
||||
) {
|
||||
onDelete();
|
||||
} else if (
|
||||
element.classList.contains('add') ||
|
||||
(element.parentElement && element.parentElement.classList.contains('add'))
|
||||
) {
|
||||
onAdd();
|
||||
}
|
||||
},
|
||||
create: (component: Connection) => {
|
||||
const div = document.createElement('div');
|
||||
const addButton = document.createElement('button');
|
||||
const deleteButton = document.createElement('button');
|
||||
|
||||
div.classList.add(OVERLAY_CONNECTION_ACTIONS_ID);
|
||||
addButton.classList.add('add');
|
||||
deleteButton.classList.add('delete');
|
||||
|
||||
addButton.innerHTML = getIcon('plus');
|
||||
deleteButton.innerHTML = getIcon('trash');
|
||||
|
||||
addButton.addEventListener('click', () => onAdd());
|
||||
deleteButton.addEventListener('click', () => onDelete());
|
||||
|
||||
// We have to manually trigger connection mouse events because the overlay
|
||||
// is not part of the connection element
|
||||
div.addEventListener('mouseout', () =>
|
||||
connection.instance.fire(EVENT_CONNECTION_MOUSEOUT, component),
|
||||
);
|
||||
div.addEventListener('mouseover', () =>
|
||||
connection.instance.fire(EVENT_CONNECTION_MOUSEOVER, component),
|
||||
);
|
||||
|
||||
div.appendChild(addButton);
|
||||
div.appendChild(deleteButton);
|
||||
return div;
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
overlay.setVisible(false);
|
||||
};
|
||||
|
||||
export const getOutputEndpointUUID = (nodeId: string, outputIndex: number) => {
|
||||
|
||||
Reference in New Issue
Block a user