mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-23 18:41:48 -08:00
fix(editor): Update new canvas connection checks (no-changelog) (#11019)
This commit is contained in:
parent
b5f4afe12e
commit
805a1140c9
|
@ -38,7 +38,7 @@ const runDataLabel = computed(() =>
|
|||
|
||||
const isHandlePlusVisible = computed(() => !isConnecting.value || isHovered.value);
|
||||
|
||||
const plusStatus = computed(() => (runData.value ? 'success' : 'default'));
|
||||
const plusType = computed(() => (runData.value ? 'success' : 'default'));
|
||||
|
||||
const plusLineSize = computed(
|
||||
() =>
|
||||
|
@ -73,7 +73,7 @@ function onClickAdd() {
|
|||
data-test-id="canvas-handle-plus"
|
||||
:line-size="plusLineSize"
|
||||
:handle-classes="handleClasses"
|
||||
:status="plusStatus"
|
||||
:type="plusType"
|
||||
@mouseenter="onMouseEnter"
|
||||
@mouseleave="onMouseLeave"
|
||||
@click:plus="onClickAdd"
|
||||
|
|
|
@ -30,7 +30,7 @@ const isHandlePlusVisible = computed(
|
|||
() => !isConnecting.value || isHovered.value || supportsMultipleConnections.value,
|
||||
);
|
||||
|
||||
const plusStatus = computed(() => (runData.value ? 'success' : 'ai'));
|
||||
const plusType = computed(() => (runData.value ? 'success' : 'ai'));
|
||||
|
||||
const isHovered = ref(false);
|
||||
|
||||
|
@ -55,7 +55,7 @@ function onClickAdd() {
|
|||
v-if="isHandlePlusAvailable"
|
||||
v-show="isHandlePlusVisible"
|
||||
:handle-classes="handleClasses"
|
||||
:status="plusStatus"
|
||||
:type="plusType"
|
||||
position="bottom"
|
||||
@mouseenter="onMouseEnter"
|
||||
@mouseleave="onMouseLeave"
|
||||
|
|
|
@ -42,7 +42,7 @@ describe('CanvasHandlePlus', () => {
|
|||
|
||||
it('should apply correct classes based on status', () => {
|
||||
const { container } = renderComponent({
|
||||
props: { status: 'success' },
|
||||
props: { type: 'success' },
|
||||
});
|
||||
|
||||
expect(container.firstChild).toHaveClass('success');
|
||||
|
|
|
@ -7,14 +7,14 @@ const props = withDefaults(
|
|||
handleClasses?: string;
|
||||
plusSize?: number;
|
||||
lineSize?: number;
|
||||
status?: 'success' | 'ai' | 'default';
|
||||
type?: 'success' | 'ai' | 'default';
|
||||
}>(),
|
||||
{
|
||||
position: 'right',
|
||||
handleClasses: undefined,
|
||||
plusSize: 24,
|
||||
lineSize: 46,
|
||||
status: 'default',
|
||||
type: 'default',
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -27,7 +27,7 @@ const style = useCssModule();
|
|||
const classes = computed(() => [
|
||||
style.wrapper,
|
||||
style[props.position],
|
||||
style[props.status],
|
||||
style[props.type],
|
||||
props.handleClasses,
|
||||
]);
|
||||
|
||||
|
|
|
@ -81,10 +81,11 @@ describe('useCanvasOperations', () => {
|
|||
},
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
const pinia = createTestingPinia({ initialState });
|
||||
setActivePinia(pinia);
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('requireNodeTypeDescription', () => {
|
||||
|
@ -323,10 +324,12 @@ describe('useCanvasOperations', () => {
|
|||
createTestWorkflowObject(workflowsStore.workflow),
|
||||
);
|
||||
|
||||
vi.spyOn(NodeHelpers, 'getNodeOutputs').mockReturnValue([
|
||||
vi.spyOn(NodeHelpers, 'getNodeOutputs').mockReturnValueOnce([
|
||||
{ type: NodeConnectionType.AiTool },
|
||||
]);
|
||||
vi.spyOn(NodeHelpers, 'getConnectionTypes').mockReturnValue([NodeConnectionType.AiTool]);
|
||||
vi.spyOn(NodeHelpers, 'getConnectionTypes')
|
||||
.mockReturnValueOnce([NodeConnectionType.AiTool])
|
||||
.mockReturnValueOnce([NodeConnectionType.AiTool]);
|
||||
|
||||
const { resolveNodePosition } = useCanvasOperations({ router });
|
||||
const position = resolveNodePosition({ ...node, position: undefined }, nodeTypeDescription);
|
||||
|
@ -1075,29 +1078,53 @@ describe('useCanvasOperations', () => {
|
|||
it('should return false if source and target nodes are the same', () => {
|
||||
const node = mockNode({ id: '1', type: 'testType', name: 'Test Node' });
|
||||
const { isConnectionAllowed } = useCanvasOperations({ router });
|
||||
expect(isConnectionAllowed(node, node, NodeConnectionType.Main)).toBe(false);
|
||||
expect(
|
||||
isConnectionAllowed(node, node, NodeConnectionType.Main, NodeConnectionType.Main),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if target node type does not have inputs', () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
const nodeTypesStore = mockedStore(useNodeTypesStore);
|
||||
const sourceNode = mockNode({
|
||||
id: '1',
|
||||
type: 'sourceType',
|
||||
name: 'Source Node',
|
||||
});
|
||||
const sourceNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: sourceNode.type,
|
||||
outputs: [],
|
||||
});
|
||||
const targetNode = mockNode({
|
||||
id: '2',
|
||||
type: 'targetType',
|
||||
name: 'Target Node',
|
||||
});
|
||||
const nodeTypeDescription = mockNodeTypeDescription({
|
||||
name: 'targetType',
|
||||
const targetNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: targetNode.type,
|
||||
inputs: [],
|
||||
});
|
||||
nodeTypesStore.getNodeType = vi.fn().mockReturnValue(nodeTypeDescription);
|
||||
|
||||
const workflowObject = createTestWorkflowObject(workflowsStore.workflow);
|
||||
workflowsStore.getCurrentWorkflow.mockReturnValue(workflowObject);
|
||||
|
||||
nodeTypesStore.getNodeType = vi.fn(
|
||||
(nodeTypeName: string) =>
|
||||
({
|
||||
[sourceNode.type]: sourceNodeTypeDescription,
|
||||
[targetNode.type]: targetNodeTypeDescription,
|
||||
})[nodeTypeName],
|
||||
);
|
||||
|
||||
const { isConnectionAllowed } = useCanvasOperations({ router });
|
||||
expect(isConnectionAllowed(sourceNode, targetNode, NodeConnectionType.Main)).toBe(false);
|
||||
expect(
|
||||
isConnectionAllowed(
|
||||
sourceNode,
|
||||
targetNode,
|
||||
NodeConnectionType.Main,
|
||||
NodeConnectionType.Main,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if target node does not exist in the workflow', () => {
|
||||
|
@ -1109,25 +1136,42 @@ describe('useCanvasOperations', () => {
|
|||
type: 'sourceType',
|
||||
name: 'Source Node',
|
||||
});
|
||||
const sourceNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: sourceNode.type,
|
||||
outputs: [],
|
||||
});
|
||||
const targetNode = mockNode({
|
||||
id: '2',
|
||||
type: 'targetType',
|
||||
name: 'Target Node',
|
||||
});
|
||||
const nodeTypeDescription = mockNodeTypeDescription({
|
||||
name: 'targetType',
|
||||
const targetNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: targetNode.type,
|
||||
inputs: [NodeConnectionType.Main],
|
||||
});
|
||||
|
||||
const workflowObject = createTestWorkflowObject(workflowsStore.workflow);
|
||||
workflowsStore.getCurrentWorkflow.mockReturnValue(workflowObject);
|
||||
nodeTypesStore.getNodeType = vi.fn().mockReturnValue(nodeTypeDescription);
|
||||
nodeTypesStore.getNodeType = vi.fn(
|
||||
(nodeTypeName: string) =>
|
||||
({
|
||||
[sourceNode.type]: sourceNodeTypeDescription,
|
||||
[targetNode.type]: targetNodeTypeDescription,
|
||||
})[nodeTypeName],
|
||||
);
|
||||
|
||||
const { isConnectionAllowed } = useCanvasOperations({ router });
|
||||
expect(isConnectionAllowed(sourceNode, targetNode, NodeConnectionType.Main)).toBe(false);
|
||||
expect(
|
||||
isConnectionAllowed(
|
||||
sourceNode,
|
||||
targetNode,
|
||||
NodeConnectionType.Main,
|
||||
NodeConnectionType.Main,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if input type does not match connection type', () => {
|
||||
it('should return false if source node does not have connection type', () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
const nodeTypesStore = mockedStore(useNodeTypesStore);
|
||||
const sourceNode = mockNode({
|
||||
|
@ -1135,14 +1179,17 @@ describe('useCanvasOperations', () => {
|
|||
type: 'sourceType',
|
||||
name: 'Source Node',
|
||||
});
|
||||
const sourceNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: sourceNode.type,
|
||||
outputs: [NodeConnectionType.Main],
|
||||
});
|
||||
|
||||
const targetNode = mockNode({
|
||||
id: '2',
|
||||
type: 'targetType',
|
||||
name: 'Target Node',
|
||||
});
|
||||
|
||||
const nodeTypeDescription = mockNodeTypeDescription({
|
||||
const targetNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: 'targetType',
|
||||
inputs: [NodeConnectionType.AiTool],
|
||||
});
|
||||
|
@ -1154,9 +1201,70 @@ describe('useCanvasOperations', () => {
|
|||
|
||||
editableWorkflowObject.value.nodes[sourceNode.name] = sourceNode;
|
||||
editableWorkflowObject.value.nodes[targetNode.name] = targetNode;
|
||||
nodeTypesStore.getNodeType = vi.fn().mockReturnValue(nodeTypeDescription);
|
||||
nodeTypesStore.getNodeType = vi.fn(
|
||||
(nodeTypeName: string) =>
|
||||
({
|
||||
[sourceNode.type]: sourceNodeTypeDescription,
|
||||
[targetNode.type]: targetNodeTypeDescription,
|
||||
})[nodeTypeName],
|
||||
);
|
||||
|
||||
expect(isConnectionAllowed(sourceNode, targetNode, NodeConnectionType.Main)).toBe(false);
|
||||
expect(
|
||||
isConnectionAllowed(
|
||||
sourceNode,
|
||||
targetNode,
|
||||
NodeConnectionType.AiTool,
|
||||
NodeConnectionType.AiTool,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if target node does not have connection type', () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
const nodeTypesStore = mockedStore(useNodeTypesStore);
|
||||
const sourceNode = mockNode({
|
||||
id: '1',
|
||||
type: 'sourceType',
|
||||
name: 'Source Node',
|
||||
});
|
||||
const sourceNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: sourceNode.type,
|
||||
outputs: [NodeConnectionType.Main],
|
||||
});
|
||||
|
||||
const targetNode = mockNode({
|
||||
id: '2',
|
||||
type: 'targetType',
|
||||
name: 'Target Node',
|
||||
});
|
||||
const targetNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: 'targetType',
|
||||
inputs: [NodeConnectionType.AiTool],
|
||||
});
|
||||
|
||||
const workflowObject = createTestWorkflowObject(workflowsStore.workflow);
|
||||
workflowsStore.getCurrentWorkflow.mockReturnValue(workflowObject);
|
||||
|
||||
const { isConnectionAllowed, editableWorkflowObject } = useCanvasOperations({ router });
|
||||
|
||||
editableWorkflowObject.value.nodes[sourceNode.name] = sourceNode;
|
||||
editableWorkflowObject.value.nodes[targetNode.name] = targetNode;
|
||||
nodeTypesStore.getNodeType = vi.fn(
|
||||
(nodeTypeName: string) =>
|
||||
({
|
||||
[sourceNode.type]: sourceNodeTypeDescription,
|
||||
[targetNode.type]: targetNodeTypeDescription,
|
||||
})[nodeTypeName],
|
||||
);
|
||||
|
||||
expect(
|
||||
isConnectionAllowed(
|
||||
sourceNode,
|
||||
targetNode,
|
||||
NodeConnectionType.Main,
|
||||
NodeConnectionType.AiTool,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if source node type is not allowed by target node input filter', () => {
|
||||
|
@ -1168,6 +1276,10 @@ describe('useCanvasOperations', () => {
|
|||
name: 'Source Node',
|
||||
typeVersion: 1,
|
||||
});
|
||||
const sourceNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: sourceNode.type,
|
||||
outputs: [NodeConnectionType.Main],
|
||||
});
|
||||
|
||||
const targetNode = mockNode({
|
||||
id: '2',
|
||||
|
@ -1175,8 +1287,7 @@ describe('useCanvasOperations', () => {
|
|||
name: 'Target Node',
|
||||
typeVersion: 1,
|
||||
});
|
||||
|
||||
const nodeTypeDescription = mockNodeTypeDescription({
|
||||
const targetNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: 'targetType',
|
||||
inputs: [
|
||||
{
|
||||
|
@ -1195,52 +1306,81 @@ describe('useCanvasOperations', () => {
|
|||
|
||||
editableWorkflowObject.value.nodes[sourceNode.name] = sourceNode;
|
||||
editableWorkflowObject.value.nodes[targetNode.name] = targetNode;
|
||||
nodeTypesStore.getNodeType = vi.fn().mockReturnValue(nodeTypeDescription);
|
||||
nodeTypesStore.getNodeType = vi.fn(
|
||||
(nodeTypeName: string) =>
|
||||
({
|
||||
[sourceNode.type]: sourceNodeTypeDescription,
|
||||
[targetNode.type]: targetNodeTypeDescription,
|
||||
})[nodeTypeName],
|
||||
);
|
||||
|
||||
expect(isConnectionAllowed(sourceNode, targetNode, NodeConnectionType.Main)).toBe(false);
|
||||
expect(
|
||||
isConnectionAllowed(
|
||||
sourceNode,
|
||||
targetNode,
|
||||
NodeConnectionType.Main,
|
||||
NodeConnectionType.Main,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if all conditions including filter are met', () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
const nodeTypesStore = mockedStore(useNodeTypesStore);
|
||||
|
||||
const sourceNode = mockNode({
|
||||
id: '1',
|
||||
type: 'sourceType',
|
||||
name: 'Source Node',
|
||||
typeVersion: 1,
|
||||
});
|
||||
|
||||
const targetNode = mockNode({
|
||||
id: '2',
|
||||
type: 'targetType',
|
||||
name: 'Target Node',
|
||||
typeVersion: 1,
|
||||
});
|
||||
|
||||
const nodeTypeDescription = mockNodeTypeDescription({
|
||||
name: 'targetType',
|
||||
inputs: [
|
||||
{
|
||||
type: NodeConnectionType.Main,
|
||||
filter: {
|
||||
nodes: ['sourceType'],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const workflowObject = createTestWorkflowObject(workflowsStore.workflow);
|
||||
workflowsStore.getCurrentWorkflow.mockReturnValue(workflowObject);
|
||||
|
||||
const { isConnectionAllowed, editableWorkflowObject } = useCanvasOperations({ router });
|
||||
|
||||
editableWorkflowObject.value.nodes[sourceNode.name] = sourceNode;
|
||||
editableWorkflowObject.value.nodes[targetNode.name] = targetNode;
|
||||
nodeTypesStore.getNodeType = vi.fn().mockReturnValue(nodeTypeDescription);
|
||||
|
||||
expect(isConnectionAllowed(sourceNode, targetNode, NodeConnectionType.Main)).toBe(true);
|
||||
});
|
||||
// it('should return true if all conditions including filter are met', () => {
|
||||
// const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
// const nodeTypesStore = mockedStore(useNodeTypesStore);
|
||||
//
|
||||
// const sourceNode = mockNode({
|
||||
// id: '1',
|
||||
// type: 'sourceType',
|
||||
// name: 'Source Node',
|
||||
// typeVersion: 1,
|
||||
// });
|
||||
// const sourceNodeTypeDescription = mockNodeTypeDescription({
|
||||
// name: sourceNode.type,
|
||||
// outputs: [NodeConnectionType.Main],
|
||||
// });
|
||||
//
|
||||
// const targetNode = mockNode({
|
||||
// id: '2',
|
||||
// type: 'targetType',
|
||||
// name: 'Target Node',
|
||||
// typeVersion: 1,
|
||||
// });
|
||||
// const targetNodeTypeDescription = mockNodeTypeDescription({
|
||||
// name: targetNode.type,
|
||||
// inputs: [
|
||||
// {
|
||||
// type: NodeConnectionType.Main,
|
||||
// filter: {
|
||||
// nodes: [sourceNode.type],
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
//
|
||||
// const workflowObject = createTestWorkflowObject(workflowsStore.workflow);
|
||||
// workflowsStore.getCurrentWorkflow.mockReturnValue(workflowObject);
|
||||
//
|
||||
// const { isConnectionAllowed, editableWorkflowObject } = useCanvasOperations({ router });
|
||||
//
|
||||
// editableWorkflowObject.value.nodes[sourceNode.name] = sourceNode;
|
||||
// editableWorkflowObject.value.nodes[targetNode.name] = targetNode;
|
||||
// nodeTypesStore.getNodeType = vi.fn(
|
||||
// (nodeTypeName: string) =>
|
||||
// ({
|
||||
// [sourceNode.type]: sourceNodeTypeDescription,
|
||||
// [targetNode.type]: targetNodeTypeDescription,
|
||||
// })[nodeTypeName],
|
||||
// );
|
||||
//
|
||||
// expect(
|
||||
// isConnectionAllowed(
|
||||
// sourceNode,
|
||||
// targetNode,
|
||||
// NodeConnectionType.Main,
|
||||
// NodeConnectionType.Main,
|
||||
// ),
|
||||
// ).toBe(true);
|
||||
// });
|
||||
|
||||
it('should return true if all conditions are met and no filter is set', () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
|
@ -1252,6 +1392,10 @@ describe('useCanvasOperations', () => {
|
|||
name: 'Source Node',
|
||||
typeVersion: 1,
|
||||
});
|
||||
const sourceNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: sourceNode.type,
|
||||
outputs: [NodeConnectionType.Main],
|
||||
});
|
||||
|
||||
const targetNode = mockNode({
|
||||
id: '2',
|
||||
|
@ -1259,9 +1403,8 @@ describe('useCanvasOperations', () => {
|
|||
name: 'Target Node',
|
||||
typeVersion: 1,
|
||||
});
|
||||
|
||||
const nodeTypeDescription = mockNodeTypeDescription({
|
||||
name: 'targetType',
|
||||
const targetNodeTypeDescription = mockNodeTypeDescription({
|
||||
name: targetNode.type,
|
||||
inputs: [
|
||||
{
|
||||
type: NodeConnectionType.Main,
|
||||
|
@ -1276,9 +1419,22 @@ describe('useCanvasOperations', () => {
|
|||
|
||||
editableWorkflowObject.value.nodes[sourceNode.name] = sourceNode;
|
||||
editableWorkflowObject.value.nodes[targetNode.name] = targetNode;
|
||||
nodeTypesStore.getNodeType = vi.fn().mockReturnValue(nodeTypeDescription);
|
||||
nodeTypesStore.getNodeType = vi.fn(
|
||||
(nodeTypeName: string) =>
|
||||
({
|
||||
[sourceNode.type]: sourceNodeTypeDescription,
|
||||
[targetNode.type]: targetNodeTypeDescription,
|
||||
})[nodeTypeName],
|
||||
);
|
||||
|
||||
expect(isConnectionAllowed(sourceNode, targetNode, NodeConnectionType.Main)).toBe(true);
|
||||
expect(
|
||||
isConnectionAllowed(
|
||||
sourceNode,
|
||||
targetNode,
|
||||
NodeConnectionType.Main,
|
||||
NodeConnectionType.Main,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1141,7 +1141,14 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
|||
connection,
|
||||
);
|
||||
|
||||
if (!isConnectionAllowed(sourceNode, targetNode, mappedConnection[1].type)) {
|
||||
if (
|
||||
!isConnectionAllowed(
|
||||
sourceNode,
|
||||
targetNode,
|
||||
mappedConnection[0].type,
|
||||
mappedConnection[1].type,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1278,7 +1285,8 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
|||
function isConnectionAllowed(
|
||||
sourceNode: INodeUi,
|
||||
targetNode: INodeUi,
|
||||
connectionType: NodeConnectionType,
|
||||
sourceConnectionType: NodeConnectionType,
|
||||
targetConnectionType: NodeConnectionType,
|
||||
): boolean {
|
||||
const blocklist = [STICKY_NODE_TYPE];
|
||||
|
||||
|
@ -1286,52 +1294,77 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
|||
return false;
|
||||
}
|
||||
|
||||
if (sourceConnectionType !== targetConnectionType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blocklist.includes(sourceNode.type) || blocklist.includes(targetNode.type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const sourceNodeType = nodeTypesStore.getNodeType(sourceNode.type, sourceNode.typeVersion);
|
||||
const sourceWorkflowNode = editableWorkflowObject.value.getNode(sourceNode.name);
|
||||
if (!sourceWorkflowNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let sourceNodeOutputs: Array<NodeConnectionType | INodeOutputConfiguration> = [];
|
||||
if (sourceNodeType) {
|
||||
sourceNodeOutputs =
|
||||
NodeHelpers.getNodeOutputs(
|
||||
editableWorkflowObject.value,
|
||||
sourceWorkflowNode,
|
||||
sourceNodeType,
|
||||
) || [];
|
||||
}
|
||||
|
||||
const sourceNodeHasOutputConnectionOfType = !!sourceNodeOutputs.find((output) => {
|
||||
const outputType = typeof output === 'string' ? output : output.type;
|
||||
return outputType === sourceConnectionType;
|
||||
});
|
||||
|
||||
if (!sourceNodeHasOutputConnectionOfType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const targetNodeType = nodeTypesStore.getNodeType(targetNode.type, targetNode.typeVersion);
|
||||
if (targetNodeType?.inputs?.length) {
|
||||
const workflowNode = editableWorkflowObject.value.getNode(targetNode.name);
|
||||
if (!workflowNode) {
|
||||
const targetWorkflowNode = editableWorkflowObject.value.getNode(targetNode.name);
|
||||
if (!targetWorkflowNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let targetNodeInputs: Array<NodeConnectionType | INodeInputConfiguration> = [];
|
||||
if (targetNodeType) {
|
||||
targetNodeInputs =
|
||||
NodeHelpers.getNodeInputs(
|
||||
editableWorkflowObject.value,
|
||||
targetWorkflowNode,
|
||||
targetNodeType,
|
||||
) || [];
|
||||
}
|
||||
|
||||
const targetNodeHasInputConnectionOfType = !!targetNodeInputs.find((input) => {
|
||||
const inputType = typeof input === 'string' ? input : input.type;
|
||||
if (inputType !== targetConnectionType) return false;
|
||||
|
||||
const filter = typeof input === 'object' && 'filter' in input ? input.filter : undefined;
|
||||
if (filter?.nodes.length && !filter.nodes.includes(sourceNode.type)) {
|
||||
toast.showToast({
|
||||
title: i18n.baseText('nodeView.showError.nodeNodeCompatible.title'),
|
||||
message: i18n.baseText('nodeView.showError.nodeNodeCompatible.message', {
|
||||
interpolate: { sourceNodeName: sourceNode.name, targetNodeName: targetNode.name },
|
||||
}),
|
||||
type: 'error',
|
||||
duration: 5000,
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
let inputs: Array<NodeConnectionType | INodeInputConfiguration> = [];
|
||||
if (targetNodeType) {
|
||||
inputs =
|
||||
NodeHelpers.getNodeInputs(editableWorkflowObject.value, workflowNode, targetNodeType) ||
|
||||
[];
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
let targetHasConnectionTypeAsInput = false;
|
||||
for (const input of inputs) {
|
||||
const inputType = typeof input === 'string' ? input : input.type;
|
||||
if (inputType === connectionType) {
|
||||
if (typeof input === 'object' && 'filter' in input && input.filter?.nodes.length) {
|
||||
if (!input.filter.nodes.includes(sourceNode.type)) {
|
||||
// this.dropPrevented = true;
|
||||
toast.showToast({
|
||||
title: i18n.baseText('nodeView.showError.nodeNodeCompatible.title'),
|
||||
message: i18n.baseText('nodeView.showError.nodeNodeCompatible.message', {
|
||||
interpolate: { sourceNodeName: sourceNode.name, targetNodeName: targetNode.name },
|
||||
}),
|
||||
type: 'error',
|
||||
duration: 5000,
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
targetHasConnectionTypeAsInput = true;
|
||||
}
|
||||
}
|
||||
|
||||
return targetHasConnectionTypeAsInput;
|
||||
}
|
||||
|
||||
return false;
|
||||
return targetNodeHasInputConnectionOfType;
|
||||
}
|
||||
|
||||
function addConnections(connections: CanvasConnectionCreateData[] | CanvasConnection[]) {
|
||||
|
|
Loading…
Reference in a new issue