Fixed not being able to throw nodes at screen

This commit is contained in:
Lucas Oliveira 2024-06-17 10:53:11 -03:00
commit a3821f4367
2 changed files with 70 additions and 69 deletions

View file

@ -24,7 +24,6 @@ export default function InputComponent({
blurOnEnter = false,
optionsIcon = "ChevronsUpDown",
selectedOption,
setSelectedOption,
selectedOptions = [],
setSelectedOptions,
@ -72,7 +71,7 @@ export default function InputComponent({
editNode ? "input-edit-node" : "",
password && editNode ? "pr-8" : "",
password && !editNode ? "pr-10" : "",
className!
className!,
)}
placeholder={password && editNode ? "Key" : placeholder}
onChange={(e) => {
@ -155,7 +154,7 @@ export default function InputComponent({
<span
className={cn(
password && selectedOption === "" ? "right-8" : "right-0",
"absolute inset-y-0 flex items-center pr-2.5"
"absolute inset-y-0 flex items-center pr-2.5",
)}
>
<button
@ -168,7 +167,7 @@ export default function InputComponent({
onChange && setSelectedOption && selectedOption !== ""
? "text-medium-indigo"
: "text-muted-foreground",
"hover:text-accent-foreground"
"hover:text-accent-foreground",
)}
>
<ForwardedIconComponent
@ -188,7 +187,7 @@ export default function InputComponent({
"mb-px",
editNode
? "input-component-true-button"
: "input-component-false-button"
: "input-component-false-button",
)}
onClick={(event) => {
event.preventDefault();
@ -205,7 +204,7 @@ export default function InputComponent({
className={classNames(
editNode
? "input-component-true-svg"
: "input-component-false-svg"
: "input-component-false-svg",
)}
>
<path
@ -224,7 +223,7 @@ export default function InputComponent({
className={classNames(
editNode
? "input-component-true-svg"
: "input-component-false-svg"
: "input-component-false-svg",
)}
>
<path

View file

@ -80,7 +80,7 @@ export function cleanEdges(nodes: NodeType[], edges: Edge[]) {
const parsedSourceHandle = scapeJSONParse(sourceHandle);
const name = parsedSourceHandle.name;
const output = sourceNode.data.node!.outputs?.find(
(output) => output.name === name
(output) => output.name === name,
);
if (output) {
const outputTypes =
@ -114,18 +114,18 @@ export function unselectAllNodes({ updateNodes, data }: unselectAllNodesType) {
export function isValidConnection(
{ source, target, sourceHandle, targetHandle }: Connection,
nodes: Node[],
edges: Edge[]
edges: Edge[],
) {
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
if (
targetHandleObject.inputTypes?.some(
(n) => n === sourceHandleObject.dataType
(n) => n === sourceHandleObject.dataType,
) ||
sourceHandleObject.output_types.some(
(t) =>
targetHandleObject.inputTypes?.some((n) => n === t) ||
t === targetHandleObject.type
t === targetHandleObject.type,
)
) {
let targetNode = nodes.find((node) => node.id === target!)?.data?.node;
@ -158,7 +158,7 @@ export function removeApiKeys(flow: FlowType): FlowType {
export function updateTemplate(
reference: APITemplateType,
objectToUpdate: APITemplateType
objectToUpdate: APITemplateType,
): APITemplateType {
let clonedObject: APITemplateType = cloneDeep(reference);
@ -190,7 +190,10 @@ export const processFlows = (DbData: FlowType[], skipUpdate = true) => {
(flow.data.nodes[0].data as NodeDataType).node!.display_name =
flow.name;
savedComponents[
createRandomKey((flow.data.nodes[0].data as NodeDataType).type, uid())
createRandomKey(
(flow.data.nodes[0].data as NodeDataType).type,
uid.rnd(),
)
] = cloneDeep((flow.data.nodes[0].data as NodeDataType).node!);
return;
}
@ -218,7 +221,7 @@ export const processDataFromFlow = (flow: FlowType, refreshIds = true) => {
export function updateIds(
{ edges, nodes }: { edges: Edge[]; nodes: Node[] },
selection?: { edges: Edge[]; nodes: Node[] }
selection?: { edges: Edge[]; nodes: Node[] },
) {
let idsMap = {};
const selectionIds = selection?.nodes.map((n) => n.id);
@ -246,7 +249,7 @@ export function updateIds(
edge.source = idsMap[edge.source];
edge.target = idsMap[edge.target];
const sourceHandleObject: sourceHandleType = scapeJSONParse(
edge.sourceHandle!
edge.sourceHandle!,
);
edge.sourceHandle = scapedJSONStringfy({
...sourceHandleObject,
@ -256,7 +259,7 @@ export function updateIds(
edge.data.sourceHandle.id = edge.source;
}
const targetHandleObject: targetHandleType = scapeJSONParse(
edge.targetHandle!
edge.targetHandle!,
);
edge.targetHandle = scapedJSONStringfy({
...targetHandleObject,
@ -302,11 +305,11 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
(scapeJSONParse(edge.targetHandle!) as targetHandleType).fieldName ===
t &&
(scapeJSONParse(edge.targetHandle!) as targetHandleType).id ===
node.id
node.id,
)
) {
errors.push(
`${displayName || type} is missing ${getFieldTitle(template, t)}.`
`${displayName || type} is missing ${getFieldTitle(template, t)}.`,
);
} else if (
template[t].type === "dict" &&
@ -320,15 +323,15 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
errors.push(
`${displayName || type} (${getFieldTitle(
template,
t
)}) contains duplicate keys with the same values.`
t,
)}) contains duplicate keys with the same values.`,
);
if (hasEmptyKey(template[t].value))
errors.push(
`${displayName || type} (${getFieldTitle(
template,
t
)}) field must not be empty.`
t,
)}) field must not be empty.`,
);
}
return errors;
@ -337,7 +340,7 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
export function validateNodes(
nodes: Node[],
edges: Edge[]
edges: Edge[],
): // this returns an array of tuples with the node id and the errors
Array<{ id: string; errors: Array<string> }> {
if (nodes.length === 0) {
@ -358,7 +361,7 @@ export function updateEdges(edges: Edge[]) {
if (edges)
edges.forEach((edge) => {
const targetHandleObject: targetHandleType = scapeJSONParse(
edge.targetHandle!
edge.targetHandle!,
);
edge.className = "";
});
@ -456,11 +459,11 @@ export function updateNewOutput({ nodes, edges }: updateEdgesHandleIdsType) {
if (newTargetHandle.inputTypes && newTargetHandle.inputTypes.length > 0) {
//conjuction subtraction
intersection = newSourceHandle.output_types.filter((type) =>
newTargetHandle.inputTypes!.includes(type)
newTargetHandle.inputTypes!.includes(type),
);
} else {
intersection = newSourceHandle.output_types.filter(
(type) => type === newTargetHandle.type
(type) => type === newTargetHandle.type,
);
}
const selected = intersection[0];
@ -475,7 +478,7 @@ export function updateNewOutput({ nodes, edges }: updateEdgesHandleIdsType) {
sourceNode.data.node!.base_classes!;
if (
!sourceNode.data.node!.outputs.some(
(output) => output.selected === selected
(output) => output.selected === selected,
)
) {
sourceNode.data.node!.outputs.push({
@ -499,7 +502,7 @@ export function handleKeyDown(
| React.KeyboardEvent<HTMLInputElement>
| React.KeyboardEvent<HTMLTextAreaElement>,
inputValue: string | string[] | null,
block: string
block: string,
) {
//condition to fix bug control+backspace on Windows/Linux
if (
@ -522,7 +525,7 @@ export function handleKeyDown(
}
export function handleOnlyIntegerInput(
event: React.KeyboardEvent<HTMLInputElement>
event: React.KeyboardEvent<HTMLInputElement>,
) {
if (
event.key === "." ||
@ -538,7 +541,7 @@ export function handleOnlyIntegerInput(
export function getConnectedNodes(
edge: Edge,
nodes: Array<NodeType>
nodes: Array<NodeType>,
): Array<NodeType> {
const sourceId = edge.source;
const targetId = edge.target;
@ -639,7 +642,7 @@ export function checkOldEdgesHandles(edges: Edge[]): boolean {
!edge.sourceHandle ||
!edge.targetHandle ||
!edge.sourceHandle.includes("{") ||
!edge.targetHandle.includes("{")
!edge.targetHandle.includes("{"),
);
}
@ -666,7 +669,7 @@ export function customStringify(obj: any): string {
const keys = Object.keys(obj).sort();
const keyValuePairs = keys.map(
(key) => `"${key}":${customStringify(obj[key])}`
(key) => `"${key}":${customStringify(obj[key])}`,
);
return `{${keyValuePairs.join(",")}}`;
}
@ -688,14 +691,14 @@ export function getMiddlePoint(nodes: Node[]) {
}
export function getNodeId(nodeType: string) {
return nodeType + "-" + uid();
return nodeType + "-" + uid.rnd();
}
export function getHandleId(
source: string,
sourceHandle: string,
target: string,
targetHandle: string
targetHandle: string,
) {
return (
"reactflow__edge-" + source + sourceHandle + "-" + target + targetHandle
@ -706,16 +709,15 @@ export function generateFlow(
selection: OnSelectionChangeParams,
nodes: Node[],
edges: Edge[],
name: string
name: string,
): generateFlowType {
const newFlowData = { nodes, edges, viewport: { zoom: 1, x: 0, y: 0 } };
const uid = new ShortUniqueId({ length: 5 });
/* remove edges that are not connected to selected nodes on both ends
*/
newFlowData.edges = edges.filter(
(edge) =>
selection.nodes.some((node) => node.id === edge.target) &&
selection.nodes.some((node) => node.id === edge.source)
selection.nodes.some((node) => node.id === edge.source),
);
newFlowData.nodes = selection.nodes;
@ -725,7 +727,7 @@ export function generateFlow(
name: name,
description: "",
//generating local id instead of using the id from the server, can change in the future
id: uid(),
id: uid.rnd(),
};
// filter edges that are not connected to selected nodes on both ends
// using O(n²) aproach because the number of edges is small
@ -736,7 +738,7 @@ export function generateFlow(
(edge) =>
(selection.nodes.some((node) => node.id === edge.target) ||
selection.nodes.some((node) => node.id === edge.source)) &&
newFlowData.edges.every((e) => e.id !== edge.id)
newFlowData.edges.every((e) => e.id !== edge.id),
),
};
}
@ -747,13 +749,13 @@ export function reconnectEdges(groupNode: NodeType, excludedEdges: Edge[]) {
const { nodes, edges } = groupNode.data.node!.flow!.data!;
const lastNode = findLastNode(groupNode.data.node!.flow!.data!);
newEdges = newEdges.filter(
(e) => !(nodes.some((n) => n.id === e.source) && e.source !== lastNode?.id)
(e) => !(nodes.some((n) => n.id === e.source) && e.source !== lastNode?.id),
);
newEdges.forEach((edge) => {
if (lastNode && edge.source === lastNode.id) {
edge.source = groupNode.id;
let newSourceHandle: sourceHandleType = scapeJSONParse(
edge.sourceHandle!
edge.sourceHandle!,
);
newSourceHandle.id = groupNode.id;
edge.sourceHandle = scapedJSONStringfy(newSourceHandle);
@ -780,7 +782,7 @@ export function reconnectEdges(groupNode: NodeType, excludedEdges: Edge[]) {
export function filterFlow(
selection: OnSelectionChangeParams,
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
) {
setNodes((nodes) => nodes.filter((node) => !selection.nodes.includes(node)));
setEdges((edges) => edges.filter((edge) => !selection.edges.includes(edge)));
@ -818,7 +820,7 @@ export function updateFlowPosition(NewPosition: XYPosition, flow: FlowType) {
export function concatFlows(
flow: FlowType,
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
) {
const { nodes, edges } = flow.data!;
setNodes((old) => [...old, ...nodes]);
@ -827,7 +829,7 @@ export function concatFlows(
export function validateSelection(
selection: OnSelectionChangeParams,
edges: Edge[]
edges: Edge[],
): Array<string> {
const clonedSelection = cloneDeep(selection);
const clonedEdges = cloneDeep(edges);
@ -841,7 +843,7 @@ export function validateSelection(
let nodesSet = new Set(clonedSelection.nodes.map((n) => n.id));
// then filter the edges that are connected to the nodes in the set
let connectedEdges = clonedSelection.edges.filter(
(e) => nodesSet.has(e.source) && nodesSet.has(e.target)
(e) => nodesSet.has(e.source) && nodesSet.has(e.target),
);
// add the edges to the selection
clonedSelection.edges = connectedEdges;
@ -855,17 +857,17 @@ export function validateSelection(
clonedSelection.nodes.some(
(node) =>
isInputNode(node.data as NodeDataType) ||
isOutputNode(node.data as NodeDataType)
isOutputNode(node.data as NodeDataType),
)
) {
errorsArray.push(
"Please select only nodes that are not input or output nodes"
"Please select only nodes that are not input or output nodes",
);
}
//check if there are two or more nodes with free outputs
if (
clonedSelection.nodes.filter(
(n) => !clonedSelection.edges.some((e) => e.source === n.id)
(n) => !clonedSelection.edges.some((e) => e.source === n.id),
).length > 1
) {
errorsArray.push("Please select only one node with free outputs");
@ -876,7 +878,7 @@ export function validateSelection(
clonedSelection.nodes.some(
(node) =>
!clonedSelection.edges.some((edge) => edge.target === node.id) &&
!clonedSelection.edges.some((edge) => edge.source === node.id)
!clonedSelection.edges.some((edge) => edge.source === node.id),
)
) {
errorsArray.push("Please select only nodes that are connected");
@ -933,8 +935,8 @@ export function mergeNodeTemplates({
nodeTemplate[key].display_name
? nodeTemplate[key].display_name
: nodeTemplate[key].name
? toTitleCase(nodeTemplate[key].name)
: toTitleCase(key);
? toTitleCase(nodeTemplate[key].name)
: toTitleCase(key);
}
}
});
@ -945,7 +947,7 @@ function isTargetHandleConnected(
edges: Edge[],
key: string,
field: InputFieldType,
nodeId: string
nodeId: string,
) {
/*
this function receives a flow and a handleId and check if there is a connection with this handle
@ -961,7 +963,7 @@ function isTargetHandleConnected(
id: nodeId,
proxy: { id: field.proxy!.id, field: field.proxy!.field },
inputTypes: field.input_types,
} as targetHandleType)
} as targetHandleType),
)
) {
return true;
@ -976,7 +978,7 @@ function isTargetHandleConnected(
fieldName: key,
id: nodeId,
inputTypes: field.input_types,
} as targetHandleType)
} as targetHandleType),
)
) {
return true;
@ -999,7 +1001,7 @@ export function generateNodeTemplate(Flow: FlowType) {
export function generateNodeFromFlow(
flow: FlowType,
getNodeId: (type: string) => string
getNodeId: (type: string) => string,
): NodeType {
const { nodes } = flow.data!;
const outputNode = cloneDeep(findLastNode(flow.data!));
@ -1040,7 +1042,7 @@ function generateNodeOutputs(flow: FlowType) {
!edges.some(
(edge) =>
edge.source === node.id &&
(edge.data.sourceHandle as sourceHandleType).name === output.name
(edge.data.sourceHandle as sourceHandleType).name === output.name,
)
) {
outputs.push(
@ -1054,7 +1056,7 @@ function generateNodeOutputs(flow: FlowType) {
},
name: node.id + "_" + output.name,
display_name: output.display_name,
})
}),
);
}
});
@ -1066,7 +1068,7 @@ function generateNodeOutputs(flow: FlowType) {
export function connectedInputNodesOnHandle(
nodeId: string,
handleId: string,
{ nodes, edges }: { nodes: NodeType[]; edges: Edge[] }
{ nodes, edges }: { nodes: NodeType[]; edges: Edge[] },
) {
const connectedNodes: Array<{ name: string; id: string; isGroup: boolean }> =
[];
@ -1103,7 +1105,7 @@ export function connectedInputNodesOnHandle(
export function updateProxyIdsOnTemplate(
template: APITemplateType,
idsMap: { [key: string]: string }
idsMap: { [key: string]: string },
) {
Object.keys(template).forEach((key) => {
if (template[key].proxy && idsMap[template[key].proxy!.id]) {
@ -1114,7 +1116,7 @@ export function updateProxyIdsOnTemplate(
export function updateEdgesIds(
edges: Edge[],
idsMap: { [key: string]: string }
idsMap: { [key: string]: string },
) {
edges.forEach((edge) => {
let targetHandle: targetHandleType = edge.data.targetHandle;
@ -1151,7 +1153,7 @@ export function expandGroupNode(
edges: Edge[],
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
outputs?: OutputFieldType[]
outputs?: OutputFieldType[],
) {
const idsMap = updateIds(flow!.data!);
updateProxyIdsOnTemplate(template, idsMap);
@ -1243,7 +1245,7 @@ export function expandGroupNode(
if (nodeIndex !== -1) {
if (gNodes[nodeIndex].data.node?.outputs) {
const nodeOutputIndex = gNodes[nodeIndex].data.node!.outputs!.findIndex(
(o) => o.name === output.proxy?.name
(o) => o.name === output.proxy?.name,
);
if (nodeOutputIndex !== -1 && output.selected) {
gNodes[nodeIndex].data.node!.outputs![nodeOutputIndex].selected =
@ -1263,7 +1265,7 @@ export function expandGroupNode(
export function getGroupStatus(
flow: FlowType,
ssData: { [key: string]: { valid: boolean; params: string } }
ssData: { [key: string]: { valid: boolean; params: string } },
) {
let status = { valid: true, params: SUCCESS_BUILD };
const { nodes } = flow.data!;
@ -1282,7 +1284,7 @@ export function getGroupStatus(
export function createFlowComponent(
nodeData: NodeDataType,
version: string
version: string,
): FlowType {
const flowNode: FlowType = {
data: {
@ -1318,7 +1320,7 @@ export function downloadNode(NodeFLow: FlowType) {
export function updateComponentNameAndType(
data: any,
component: NodeDataType
component: NodeDataType,
) {}
export function removeFileNameFromComponents(flow: FlowType) {
@ -1392,7 +1394,7 @@ export function extractFieldsFromComponenents(data: APIObjectType) {
export function downloadFlow(
flow: FlowType,
flowName: string,
flowDescription?: string
flowDescription?: string,
) {
let clonedFlow = cloneDeep(flow);
removeFileNameFromComponents(clonedFlow);
@ -1402,7 +1404,7 @@ export function downloadFlow(
...clonedFlow,
name: flowName,
description: flowDescription,
})
}),
)}`;
// create a link element and set its properties
@ -1417,7 +1419,7 @@ export function downloadFlow(
export function downloadFlows() {
downloadFlowsFromDatabase().then((flows) => {
const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
JSON.stringify(flows)
JSON.stringify(flows),
)}`;
// create a link element and set its properties
@ -1441,7 +1443,7 @@ export function getRandomDescription(): string {
export const createNewFlow = (
flowData: ReactFlowJsonObject,
flow: FlowType,
folderId: string
folderId: string,
) => {
return {
description: flow?.description ?? getRandomDescription(),