refactor helpers

This commit is contained in:
Mutasem 2021-11-01 15:38:24 +01:00
parent 71b50aeaf6
commit 0015cb4f34
5 changed files with 190 additions and 191 deletions

View file

@ -681,3 +681,11 @@ export interface IZoomConfig {
scale: number;
offset: XYPosition;
}
export interface IBounds {
minX: number;
minY: number;
maxX: number;
maxY: number;
}

View file

@ -6,7 +6,7 @@ import { deviceSupportHelpers } from '@/components/mixins/deviceSupportHelpers';
import { nodeIndex } from '@/components/mixins/nodeIndex';
import { NODE_NAME_PREFIX, NO_OP_NODE_TYPE } from '@/constants';
import { getStyleTokenValue } from '../helpers';
import { OVERLAY_INPUT_NAME_LABEL } from '@/views/canvasHelpers';
import * as CanvasHelpers from '@/views/canvasHelpers';
export const nodeBase = mixins(
deviceSupportHelpers,
@ -200,7 +200,7 @@ export const nodeBase = mixins(
newEndpointData.overlays = [
['Label',
{
id: OVERLAY_INPUT_NAME_LABEL,
id: CanvasHelpers.OVERLAY_INPUT_NAME_LABEL,
location: [-3, 0.5],
label: nodeTypeData.inputNames[index],
cssClass: 'node-input-endpoint-label',

View file

@ -110,7 +110,8 @@ export const showMessage = mixins(externalHooks).extend({
return errorMessage;
},
$showError(error: Error, title: string, message?: string) {
$showError(e: Error | unknown, title: string, message?: string) {
const error = e as Error;
const messageLine = message ? `${message}<br/>` : '';
this.$showMessage({
title,

View file

@ -135,7 +135,7 @@ import NodeCreator from '@/components/NodeCreator/NodeCreator.vue';
import NodeSettings from '@/components/NodeSettings.vue';
import RunData from '@/components/RunData.vue';
import { OVERLAY_INPUT_NAME_LABEL, JSPLUMB_FLOWCHART_STUB, getLeftmostTopNode, getWorkflowCorners, scaleSmaller, scaleBigger, scaleReset, showOrHideMidpointArrow, getIcon, getNewNodePosition, hideOverlay, showOrHideItemsLabel, showOverlay, OVERLAY_ENDPOINT_ARROW_ID, OVERLAY_MIDPOINT_ARROW_ID, OVERLAY_DROP_NODE_ID, OVERLAY_RUN_ITEMS_ID, OVERLAY_CONNECTION_ACTIONS_ID, getConnectorLengths, getRelativePosition, getMousePosition } from './canvasHelpers';
import * as CanvasHelpers from './canvasHelpers';
import mixins from 'vue-typed-mixins';
import { v4 as uuidv4} from 'uuid';
@ -158,7 +158,6 @@ import {
import {
ICredentialsResponse,
IExecutionResponse,
IN8nUISettings,
IWorkflowDb,
IWorkflowData,
INodeUi,
@ -174,113 +173,6 @@ import { mapGetters } from 'vuex';
import { getStyleTokenValue } from '@/components/helpers';
import '../plugins/N8nFlowchartType';
const NODE_SIZE = 100;
const DEFAULT_START_POSITION_X = 240;
const DEFAULT_START_POSITION_Y = 300;
const HEADER_HEIGHT = 65;
const SIDEBAR_WIDTH = 65;
const MAX_X_TO_PUSH_DOWNSTREAM_NODES = 300;
const DEFAULT_START_NODE = {
name: 'Start',
type: START_NODE_TYPE,
typeVersion: 1,
position: [
DEFAULT_START_POSITION_X,
DEFAULT_START_POSITION_Y,
] as XYPosition,
parameters: {},
};
const _OUTLINE_STROKE_COLOR = 'transparent';
const _OUTLINE_STROKE_WIDTH = 12;
const _ALWAYS_RESPECT_STUB = true;
const _PUSH_NODES_LENGTH = 200;
const CONNECTOR_PAINT_STYLE_DEFAULT: PaintStyle = {
stroke: getStyleTokenValue('--color-foreground-dark'),
strokeWidth: 2,
outlineWidth: _OUTLINE_STROKE_WIDTH,
outlineStroke: _OUTLINE_STROKE_COLOR,
};
const CONNECTOR_PAINT_STYLE_PRIMARY = {
...CONNECTOR_PAINT_STYLE_DEFAULT,
stroke: getStyleTokenValue('--color-primary'),
};
const CONNECTOR_PAINT_STYLE_SUCCESS = {
...CONNECTOR_PAINT_STYLE_DEFAULT,
stroke: getStyleTokenValue('--color-success'),
};
const CONNECTOR_TYPE_STRIGHT = ['Straight'];
const getFlowChartType = (connection: Connection) => {
const inputIndex = connection.__meta ? connection.__meta.targetOutputIndex : 0;
const outputIndex = connection.__meta ? connection.__meta.sourceOutputIndex : 0;
const outputEndpoint = connection.endpoints[0];
const outputOverlay = outputEndpoint.getOverlay('output-name-label');
let labelOffset = 0;
if (outputOverlay && outputOverlay.label && outputOverlay.label.length > 1) {
labelOffset = 16;
}
return ['N8nFlowchart', {
cornerRadius: 4,
stub: JSPLUMB_FLOWCHART_STUB + 10 * outputIndex + 10 * inputIndex + labelOffset,
gap: 5,
alwaysRespectStubs: _ALWAYS_RESPECT_STUB,
yOffset: NODE_SIZE,
loopbackMinimum: 140,
}];
};
const CONNECTOR_ARROW_OVERLAYS: OverlaySpec[] = [
[
'Arrow',
{
id: OVERLAY_ENDPOINT_ARROW_ID,
location: 1,
width: 12,
foldback: 1,
length: 10,
visible: true,
},
],
[
'Arrow',
{
id: OVERLAY_MIDPOINT_ARROW_ID,
location: 0.5,
width: 12,
foldback: 1,
length: 10,
visible: false,
},
],
];
const CONNECTOR_DROP_NODE_OVERLAY: OverlaySpec[] = [
[
'Label',
{
id: OVERLAY_DROP_NODE_ID,
label: 'Drop connection<br />to create node',
cssClass: 'drop-add-node-label',
location: 0.5,
visible: true,
},
],
];
const addOverlays = (connection: Connection, overlays: OverlaySpec[]) => {
overlays.forEach((overlay: OverlaySpec) => {
connection.addOverlay(overlay);
});
};
export default mixins(
copyPaste,
externalHooks,
@ -557,18 +449,18 @@ export default mixins(
const nodes = data.workflow.nodes;
const hasStartNode = !!nodes.find(node => node.type === START_NODE_TYPE);
const leftmostTop = getLeftmostTopNode(nodes);
const leftmostTop = CanvasHelpers.getLeftmostTopNode(nodes);
const diffX = DEFAULT_START_POSITION_X - leftmostTop.position[0];
const diffY = DEFAULT_START_POSITION_Y - leftmostTop.position[1];
const diffX = CanvasHelpers.DEFAULT_START_POSITION_X - leftmostTop.position[0];
const diffY = CanvasHelpers.DEFAULT_START_POSITION_Y - leftmostTop.position[1];
data.workflow.nodes.map((node) => {
node.position[0] += diffX + (hasStartNode? 0 : NODE_SIZE * 2);
node.position[0] += diffX + (hasStartNode? 0 : CanvasHelpers.NODE_SIZE * 2);
node.position[1] += diffY;
});
if (!hasStartNode) {
data.workflow.nodes.push(DEFAULT_START_NODE);
data.workflow.nodes.push(CanvasHelpers.DEFAULT_START_NODE);
}
this.blankRedirect = true;
@ -976,21 +868,21 @@ export default mixins(
},
resetZoom () {
const { scale, offset } = scaleReset({scale: this.nodeViewScale, offset: this.$store.getters.getNodeViewOffsetPosition});
const { scale, offset } = CanvasHelpers.scaleReset({scale: this.nodeViewScale, offset: this.$store.getters.getNodeViewOffsetPosition});
this.setZoomLevel(scale);
this.$store.commit('setNodeViewOffsetPosition', {newOffset: offset});
},
zoomIn() {
const { scale, offset: [xOffset, yOffset] } = scaleBigger({scale: this.nodeViewScale, offset: this.$store.getters.getNodeViewOffsetPosition});
const { scale, offset: [xOffset, yOffset] } = CanvasHelpers.scaleBigger({scale: this.nodeViewScale, offset: this.$store.getters.getNodeViewOffsetPosition});
this.setZoomLevel(scale);
this.$store.commit('setNodeViewOffsetPosition', {newOffset: [xOffset, yOffset]});
},
zoomOut() {
const { scale, offset: [xOffset, yOffset] } = scaleSmaller({scale: this.nodeViewScale, offset: this.$store.getters.getNodeViewOffsetPosition});
const { scale, offset: [xOffset, yOffset] } = CanvasHelpers.scaleSmaller({scale: this.nodeViewScale, offset: this.$store.getters.getNodeViewOffsetPosition});
this.setZoomLevel(scale);
this.$store.commit('setNodeViewOffsetPosition', {newOffset: [xOffset, yOffset]});
@ -1021,24 +913,24 @@ export default mixins(
return;
}
const {minX, minY, maxX, maxY} = getWorkflowCorners(nodes);
const {minX, minY, maxX, maxY} = CanvasHelpers.getWorkflowCorners(nodes);
const PADDING = NODE_SIZE * 4;
const PADDING = CanvasHelpers.NODE_SIZE * 4;
const editorWidth = window.innerWidth;
const diffX = maxX - minX + SIDEBAR_WIDTH + PADDING;
const diffX = maxX - minX + CanvasHelpers.SIDEBAR_WIDTH + PADDING;
const scaleX = editorWidth / diffX;
const editorHeight = window.innerHeight;
const diffY = maxY - minY + HEADER_HEIGHT + PADDING;
const diffY = maxY - minY + CanvasHelpers.HEADER_HEIGHT + PADDING;
const scaleY = editorHeight / diffY;
const zoomLevel = Math.min(scaleX, scaleY, 1);
let xOffset = (minX * -1) * zoomLevel + SIDEBAR_WIDTH; // find top right corner
xOffset += (editorWidth - SIDEBAR_WIDTH - (maxX - minX + NODE_SIZE) * zoomLevel) / 2; // add padding to center workflow
let xOffset = (minX * -1) * zoomLevel + CanvasHelpers.SIDEBAR_WIDTH; // find top right corner
xOffset += (editorWidth - CanvasHelpers.SIDEBAR_WIDTH - (maxX - minX + CanvasHelpers.NODE_SIZE) * zoomLevel) / 2; // add padding to center workflow
let yOffset = (minY * -1) * zoomLevel + HEADER_HEIGHT; // find top right corner
yOffset += (editorHeight - HEADER_HEIGHT - (maxY - minY + NODE_SIZE * 2) * zoomLevel) / 2; // add padding to center workflow
let yOffset = (minY * -1) * zoomLevel + CanvasHelpers.HEADER_HEIGHT; // find top right corner
yOffset += (editorHeight - CanvasHelpers.HEADER_HEIGHT - (maxY - minY + CanvasHelpers.NODE_SIZE * 2) * zoomLevel) / 2; // add padding to center workflow
this.setZoomLevel(zoomLevel);
this.$store.commit('setNodeViewOffsetPosition', {newOffset: [xOffset, yOffset]});
@ -1190,7 +1082,7 @@ export default mixins(
// Fix the node position as it could be totally offscreen
// and the pasted nodes would so not be directly visible to
// the user
this.updateNodePositions(workflowData, getNewNodePosition(this.nodes, this.lastClickPosition));
this.updateNodePositions(workflowData, CanvasHelpers.getNewNodePosition(this.nodes, this.lastClickPosition));
const data = await this.addNodesToWorkflow(workflowData);
@ -1319,14 +1211,14 @@ export default mixins(
if (lastSelectedNode) {
const lastSelectedConnection = this.lastSelectedConnection;
if (lastSelectedConnection) {
const [diffX] = getConnectorLengths(lastSelectedConnection);
if (diffX <= MAX_X_TO_PUSH_DOWNSTREAM_NODES) {
this.pushDownstreamNodes(lastSelectedNode.name, _PUSH_NODES_LENGTH);
const [diffX] = CanvasHelpers.getConnectorLengths(lastSelectedConnection);
if (diffX <= CanvasHelpers.MAX_X_TO_PUSH_DOWNSTREAM_NODES) {
this.pushDownstreamNodes(lastSelectedNode.name, CanvasHelpers.PUSH_NODES_OFFSET);
}
}
if (this.newNodeInsertPosition) {
newNodeData.position = getNewNodePosition(this.nodes, [this.newNodeInsertPosition[0], this.newNodeInsertPosition[1] - NODE_SIZE / 2]);
newNodeData.position = CanvasHelpers.getNewNodePosition(this.nodes, [this.newNodeInsertPosition[0], this.newNodeInsertPosition[1] - CanvasHelpers.NODE_SIZE / 2]);
this.newNodeInsertPosition = null;
}
else {
@ -1343,7 +1235,7 @@ export default mixins(
// If a node is active then add the new node directly after the current one
// newNodeData.position = [activeNode.position[0], activeNode.position[1] + 60];
newNodeData.position = getNewNodePosition(
newNodeData.position = CanvasHelpers.getNewNodePosition(
this.nodes,
[lastSelectedNode.position[0] + 200, lastSelectedNode.position[1] + yOffset],
[100, 0],
@ -1351,7 +1243,7 @@ export default mixins(
}
} else {
// If no node is active find a free spot
newNodeData.position = getNewNodePosition(this.nodes, this.lastClickPosition);
newNodeData.position = CanvasHelpers.getNewNodePosition(this.nodes, this.lastClickPosition);
}
// Check if node-name is unique else find one that is
@ -1427,12 +1319,12 @@ export default mixins(
},
initNodeView () {
this.instance.importDefaults({
Connector: CONNECTOR_TYPE_STRIGHT ,
Connector: CanvasHelpers.CONNECTOR_TYPE_STRIGHT,
Endpoint: ['Dot', { radius: 5 }],
DragOptions: { cursor: 'pointer', zIndex: 5000 },
PaintStyle: { strokeWidth: 2, stroke: getStyleTokenValue('--color-foreground-dark')},
HoverPaintStyle: { stroke: getStyleTokenValue('--color-primary'), lineWidth: 4 },
ConnectionOverlays: CONNECTOR_ARROW_OVERLAYS,
ConnectionOverlays: CanvasHelpers.CONNECTOR_ARROW_OVERLAYS,
Container: '#node-view',
});
@ -1489,18 +1381,18 @@ export default mixins(
const hideActions = (connection: Connection | null) => {
if (connection) {
hideOverlay(connection, OVERLAY_CONNECTION_ACTIONS_ID);
showOrHideItemsLabel(connection);
showOrHideMidpointArrow(connection);
CanvasHelpers.hideOverlay(connection, CanvasHelpers.OVERLAY_CONNECTION_ACTIONS_ID);
CanvasHelpers.showOrHideItemsLabel(connection);
CanvasHelpers.showOrHideMidpointArrow(connection);
}
};
const showActions = (connection: Connection | null) => {
if (connection) {
showOverlay(connection, OVERLAY_CONNECTION_ACTIONS_ID);
hideOverlay(connection, OVERLAY_RUN_ITEMS_ID);
if (!connection.getOverlay(OVERLAY_RUN_ITEMS_ID)) {
hideOverlay(connection, OVERLAY_MIDPOINT_ARROW_ID);
CanvasHelpers.showOverlay(connection, CanvasHelpers.OVERLAY_CONNECTION_ACTIONS_ID);
CanvasHelpers.hideOverlay(connection, CanvasHelpers.OVERLAY_RUN_ITEMS_ID);
if (!connection.getOverlay(CanvasHelpers.OVERLAY_RUN_ITEMS_ID)) {
CanvasHelpers.hideOverlay(connection, CanvasHelpers.OVERLAY_MIDPOINT_ARROW_ID);
}
}
};
@ -1519,15 +1411,15 @@ export default mixins(
targetOutputIndex: targetInfo.index,
};
const connectorType = getFlowChartType(info.connection);
const connectorType = CanvasHelpers.getFlowChartType(info.connection);
info.connection.setConnector(connectorType);
info.connection.setPaintStyle(CONNECTOR_PAINT_STYLE_DEFAULT);
addOverlays(info.connection, CONNECTOR_ARROW_OVERLAYS);
info.connection.setPaintStyle(CanvasHelpers.CONNECTOR_PAINT_STYLE_DEFAULT);
CanvasHelpers.addOverlays(info.connection, CanvasHelpers.CONNECTOR_ARROW_OVERLAYS);
showOrHideMidpointArrow(info.connection);
CanvasHelpers.showOrHideMidpointArrow(info.connection);
info.connection.removeOverlay(OVERLAY_DROP_NODE_ID);
info.connection.removeOverlay(CanvasHelpers.OVERLAY_DROP_NODE_ID);
if (this.isReadOnly === false) {
let exitTimer: NodeJS.Timeout | undefined;
@ -1583,9 +1475,9 @@ export default mixins(
info.connection.addOverlay([
'Label',
{
id: OVERLAY_CONNECTION_ACTIONS_ID,
label: `<div class="add">${getIcon('plus')}</div> <div class="delete">${getIcon('trash')}</div>`,
cssClass: OVERLAY_CONNECTION_ACTIONS_ID,
id: CanvasHelpers.OVERLAY_CONNECTION_ACTIONS_ID,
label: `<div class="add">${CanvasHelpers.getIcon('plus')}</div> <div class="delete">${CanvasHelpers.getIcon('trash')}</div>`,
cssClass: CanvasHelpers.OVERLAY_CONNECTION_ACTIONS_ID,
visible: false,
events: {
mousedown: (overlay: Overlay, event: MouseEvent) => {
@ -1610,7 +1502,7 @@ export default mixins(
]);
}
const inputNameOverlay = info.targetEndpoint.getOverlay(OVERLAY_INPUT_NAME_LABEL);
const inputNameOverlay = info.targetEndpoint.getOverlay(CanvasHelpers.OVERLAY_INPUT_NAME_LABEL);
if (inputNameOverlay) {
inputNameOverlay.setLocation([-4.5, .5]);
}
@ -1642,7 +1534,7 @@ export default mixins(
}
}
if (targetEndpoint !== undefined && targetEndpoint.connections!.length === maxConnections) {
const inputNameOverlay = targetEndpoint.getOverlay(OVERLAY_INPUT_NAME_LABEL);
const inputNameOverlay = targetEndpoint.getOverlay(CanvasHelpers.OVERLAY_INPUT_NAME_LABEL);
if (![null, undefined].includes(inputNameOverlay)) {
inputNameOverlay.setVisible(true);
}
@ -1682,7 +1574,7 @@ export default mixins(
});
this.instance.bind('connectionDetached', (info) => {
const inputNameOverlay = info.targetEndpoint.getOverlay(OVERLAY_INPUT_NAME_LABEL);
const inputNameOverlay = info.targetEndpoint.getOverlay(CanvasHelpers.OVERLAY_INPUT_NAME_LABEL);
if (inputNameOverlay) {
// todo
inputNameOverlay.setLocation([-3, .5]);
@ -1696,7 +1588,7 @@ export default mixins(
// @ts-ignore
this.instance.bind('connectionDrag', (connection: Connection) => {
this.newNodeInsertPosition = null;
addOverlays(connection, CONNECTOR_DROP_NODE_OVERLAY);
CanvasHelpers.addOverlays(connection, CanvasHelpers.CONNECTOR_DROP_NODE_OVERLAY);
let droppable = false;
const onMouseMove = () => {
@ -1707,17 +1599,17 @@ export default mixins(
const elements = document.querySelector('div.jtk-endpoint.dropHover');
if (elements && !droppable) {
droppable = true;
connection.setConnector(getFlowChartType(connection));
connection.setPaintStyle(CONNECTOR_PAINT_STYLE_PRIMARY);
addOverlays(connection, CONNECTOR_ARROW_OVERLAYS);
hideOverlay(connection, OVERLAY_DROP_NODE_ID);
connection.setConnector(CanvasHelpers.getFlowChartType(connection));
connection.setPaintStyle(CanvasHelpers.CONNECTOR_PAINT_STYLE_PRIMARY);
CanvasHelpers.addOverlays(connection, CanvasHelpers.CONNECTOR_ARROW_OVERLAYS);
CanvasHelpers.hideOverlay(connection, CanvasHelpers.OVERLAY_DROP_NODE_ID);
}
else if (!elements && droppable) {
droppable = false;
connection.setConnector(CONNECTOR_TYPE_STRIGHT );
connection.setPaintStyle(CONNECTOR_PAINT_STYLE_DEFAULT);
addOverlays(connection, CONNECTOR_ARROW_OVERLAYS);
showOverlay(connection, OVERLAY_DROP_NODE_ID);
connection.setConnector(CanvasHelpers.CONNECTOR_TYPE_STRIGHT);
connection.setPaintStyle(CanvasHelpers.CONNECTOR_PAINT_STYLE_DEFAULT);
CanvasHelpers.addOverlays(connection, CanvasHelpers.CONNECTOR_ARROW_OVERLAYS);
CanvasHelpers.showOverlay(connection, CanvasHelpers.OVERLAY_DROP_NODE_ID);
}
};
@ -1736,9 +1628,9 @@ export default mixins(
await this.$store.dispatch('workflows/setNewWorkflowName');
this.$store.commit('setStateDirty', false);
await this.addNodes([DEFAULT_START_NODE]);
await this.addNodes([CanvasHelpers.DEFAULT_START_NODE]);
this.nodeSelectedByName(DEFAULT_START_NODE.name, false);
this.nodeSelectedByName(CanvasHelpers.DEFAULT_START_NODE.name, false);
this.$store.commit('setStateDirty', false);
@ -1889,7 +1781,7 @@ export default mixins(
// Check if node-name is unique else find one that is
newNodeData.name = this.getUniqueNodeName(newNodeData.name);
newNodeData.position = getNewNodePosition(
newNodeData.position = CanvasHelpers.getNewNodePosition(
this.nodes,
[node.position[0], node.position[1] + 140],
[0, 140],
@ -1947,8 +1839,8 @@ export default mixins(
}) as Connection[];
[...incoming, ...outgoing].forEach((connection: Connection) => {
showOrHideMidpointArrow(connection);
showOrHideItemsLabel(connection);
CanvasHelpers.showOrHideMidpointArrow(connection);
CanvasHelpers.showOrHideItemsLabel(connection);
});
},
onNodeRun ({name, data}: {name: string, data: ITaskData[] | null}) {
@ -1957,9 +1849,9 @@ export default mixins(
const sourceId = `${NODE_NAME_PREFIX}${sourceIndex}`;
const resetConnection = (connection: Connection) => {
connection.removeOverlay(OVERLAY_RUN_ITEMS_ID);
connection.setPaintStyle(CONNECTOR_PAINT_STYLE_DEFAULT);
showOrHideMidpointArrow(connection);
connection.removeOverlay(CanvasHelpers.OVERLAY_RUN_ITEMS_ID);
connection.setPaintStyle(CanvasHelpers.CONNECTOR_PAINT_STYLE_DEFAULT);
CanvasHelpers.showOrHideMidpointArrow(connection);
// @ts-ignore
if (connection.canvas) {
// @ts-ignore
@ -2039,15 +1931,15 @@ export default mixins(
return;
}
conn.setPaintStyle(CONNECTOR_PAINT_STYLE_SUCCESS);
conn.setPaintStyle(CanvasHelpers.CONNECTOR_PAINT_STYLE_SUCCESS);
// @ts-ignore
if (conn.canvas) {
// @ts-ignore
(conn.canvas as Element).classList.add('success');
}
if (conn.getOverlay(OVERLAY_RUN_ITEMS_ID)) {
conn.removeOverlay(OVERLAY_RUN_ITEMS_ID);
if (conn.getOverlay(CanvasHelpers.OVERLAY_RUN_ITEMS_ID)) {
conn.removeOverlay(CanvasHelpers.OVERLAY_RUN_ITEMS_ID);
}
let label = `${output.total}`;
@ -2057,15 +1949,15 @@ export default mixins(
conn.addOverlay([
'Label',
{
id: OVERLAY_RUN_ITEMS_ID,
id: CanvasHelpers.OVERLAY_RUN_ITEMS_ID,
label,
cssClass: 'connection-output-items-label',
location: .5,
},
]);
showOrHideItemsLabel(conn);
showOrHideMidpointArrow(conn);
CanvasHelpers.showOrHideItemsLabel(conn);
CanvasHelpers.showOrHideMidpointArrow(conn);
});
});
});

View file

@ -1,5 +1,7 @@
import { INodeUi, IZoomConfig, XYPosition } from "@/Interface";
import { Connection } from "jsplumb";
import { getStyleTokenValue } from "@/components/helpers";
import { START_NODE_TYPE } from "@/constants";
import { IBounds, INodeUi, IZoomConfig, XYPosition } from "@/Interface";
import { Connection, OverlaySpec, PaintStyle } from "jsplumb";
export const OVERLAY_DROP_NODE_ID = 'drop-add-node';
export const OVERLAY_MIDPOINT_ARROW_ID = 'midpoint-arrow';
@ -9,15 +11,111 @@ export const OVERLAY_CONNECTION_ACTIONS_ID = 'connection-actions';
export const JSPLUMB_FLOWCHART_STUB = 26;
export const OVERLAY_INPUT_NAME_LABEL = 'input-name-label';
const _MIN_X_TO_SHOW_OUTPUT_LABEL = 90;
const _MIN_Y_TO_SHOW_OUTPUT_LABEL = 100;
const MIN_X_TO_SHOW_OUTPUT_LABEL = 90;
const MIN_Y_TO_SHOW_OUTPUT_LABEL = 100;
interface ICorners {
minX: number;
minY: number;
maxX: number;
maxY: number;
}
export const NODE_SIZE = 100;
export const DEFAULT_START_POSITION_X = 240;
export const DEFAULT_START_POSITION_Y = 300;
export const HEADER_HEIGHT = 65;
export const SIDEBAR_WIDTH = 65;
export const MAX_X_TO_PUSH_DOWNSTREAM_NODES = 300;
export const PUSH_NODES_OFFSET = 200;
export const DEFAULT_START_NODE = {
name: 'Start',
type: START_NODE_TYPE,
typeVersion: 1,
position: [
DEFAULT_START_POSITION_X,
DEFAULT_START_POSITION_Y,
] as XYPosition,
parameters: {},
};
export const CONNECTOR_PAINT_STYLE_DEFAULT: PaintStyle = {
stroke: getStyleTokenValue('--color-foreground-dark'),
strokeWidth: 2,
outlineWidth: 12,
outlineStroke: 'transparent',
};
export const CONNECTOR_PAINT_STYLE_PRIMARY = {
...CONNECTOR_PAINT_STYLE_DEFAULT,
stroke: getStyleTokenValue('--color-primary'),
};
export const CONNECTOR_PAINT_STYLE_SUCCESS = {
...CONNECTOR_PAINT_STYLE_DEFAULT,
stroke: getStyleTokenValue('--color-success'),
};
export const CONNECTOR_TYPE_STRIGHT = ['Straight'];
export const getFlowChartType = (connection: Connection) => {
const inputIndex = connection.__meta ? connection.__meta.targetOutputIndex : 0;
const outputIndex = connection.__meta ? connection.__meta.sourceOutputIndex : 0;
const outputEndpoint = connection.endpoints[0];
const outputOverlay = outputEndpoint.getOverlay('output-name-label');
let labelOffset = 0;
if (outputOverlay && outputOverlay.label && outputOverlay.label.length > 1) {
labelOffset = 16;
}
return ['N8nFlowchart', {
cornerRadius: 4,
stub: JSPLUMB_FLOWCHART_STUB + 10 * outputIndex + 10 * inputIndex + labelOffset,
gap: 5,
alwaysRespectStubs: true,
yOffset: NODE_SIZE,
loopbackMinimum: 140,
}];
};
export const CONNECTOR_ARROW_OVERLAYS: OverlaySpec[] = [
[
'Arrow',
{
id: OVERLAY_ENDPOINT_ARROW_ID,
location: 1,
width: 12,
foldback: 1,
length: 10,
visible: true,
},
],
[
'Arrow',
{
id: OVERLAY_MIDPOINT_ARROW_ID,
location: 0.5,
width: 12,
foldback: 1,
length: 10,
visible: false,
},
],
];
export const CONNECTOR_DROP_NODE_OVERLAY: OverlaySpec[] = [
[
'Label',
{
id: OVERLAY_DROP_NODE_ID,
label: 'Drop connection<br />to create node',
cssClass: 'drop-add-node-label',
location: 0.5,
visible: true,
},
],
];
export const addOverlays = (connection: Connection, overlays: OverlaySpec[]) => {
overlays.forEach((overlay: OverlaySpec) => {
connection.addOverlay(overlay);
});
};
export const getLeftmostTopNode = (nodes: INodeUi[]): INodeUi => {
return nodes.reduce((leftmostTop, node) => {
@ -29,8 +127,8 @@ export const getLeftmostTopNode = (nodes: INodeUi[]): INodeUi => {
});
};
export const getWorkflowCorners = (nodes: INodeUi[]): ICorners => {
return nodes.reduce((accu: ICorners, node: INodeUi) => {
export const getWorkflowCorners = (nodes: INodeUi[]): IBounds => {
return nodes.reduce((accu: IBounds, node: INodeUi) => {
if (node.position[0] < accu.minX) {
accu.minX = node.position[0];
}
@ -147,7 +245,7 @@ export const showOrHideItemsLabel = (connection: Connection) => {
const [diffX, diffY] = getConnectorLengths(connection);
if (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 {