fix: Add factor to prevent overlap (#5426)

* fix: add random factor to prevent overlap

* update package.lock

* feat: Add positionDictionary and related functions to FlowStoreType

* feat: Add buildPositionDictionary function to reactflowUtils.ts

* feat: Add buildPositionDictionary function to reactflowUtils.ts

This commit adds the buildPositionDictionary function to reactflowUtils.ts. This function is used to build a dictionary of positions for nodes in the flow. It is necessary for managing the positions of nodes and preventing overlap.

* fix: Remove random factor from paste function in PageComponent

* [autofix.ci] apply automated fixes

* feat: Add setPositionDictionary function to PageComponent

This commit adds the setPositionDictionary function to the PageComponent in order to set the position dictionary for the flow. This function is used to update the position dictionary when the canvas is moved or resized.

Co-authored-by: [Author Name]

* [autofix.ci] apply automated fixes

* Refactor position calculation in useFlowStore

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
anovazzi1 2025-01-09 10:55:59 -03:00 committed by GitHub
commit 1f614ccca6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 52 additions and 1 deletions

View file

@ -86,6 +86,9 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
const templates = useTypesStore((state) => state.templates);
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
const reactFlowWrapper = useRef<HTMLDivElement>(null);
const setPositionDictionary = useFlowStore(
(state) => state.setPositionDictionary,
);
const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance);
const setReactFlowInstance = useFlowStore(
@ -338,7 +341,15 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
// 👇 make moving the canvas undoable
autoSaveFlow();
updateCurrentFlow({ nodes });
}, [takeSnapshot, autoSaveFlow, nodes, edges, reactFlowInstance]);
setPositionDictionary({});
}, [
takeSnapshot,
autoSaveFlow,
nodes,
edges,
reactFlowInstance,
setPositionDictionary,
]);
const onSelectionDragStart: SelectionDragHandler = useCallback(() => {
// 👇 make dragging a selection undoable

View file

@ -31,6 +31,7 @@ import {
import { FlowStoreType, VertexLayerElementType } from "../types/zustand/flow";
import { buildFlowVerticesWithFallback } from "../utils/buildUtils";
import {
buildPositionDictionary,
checkChatInput,
cleanEdges,
detectBrokenEdgesEdges,
@ -52,6 +53,19 @@ import { useTypesStore } from "./typesStore";
// this is our useStore hook that we can use in our components to get parts of the store and call actions
const useFlowStore = create<FlowStoreType>((set, get) => ({
positionDictionary: {},
setPositionDictionary: (positionDictionary) => {
set({ positionDictionary });
},
isPositionAvailable: (position: { x: number; y: number }) => {
if (
get().positionDictionary[position.x] &&
get().positionDictionary[position.x] === position.y
) {
return false;
}
return true;
},
fitViewNode: (nodeId) => {
if (get().reactFlowInstance && get().nodes.find((n) => n.id === nodeId)) {
get().reactFlowInstance?.fitView({ nodes: [{ id: nodeId }] });
@ -211,6 +225,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
hasIO: inputs.length > 0 || outputs.length > 0,
flowPool: {},
currentFlow: flow,
positionDictionary: {},
});
},
setIsBuilding: (isBuilding) => {
@ -386,6 +401,17 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
y: position.y,
});
let internalPostionDictionary = get().positionDictionary;
if (Object.keys(internalPostionDictionary).length === 0) {
internalPostionDictionary = buildPositionDictionary(get().nodes);
}
while (!get().isPositionAvailable(insidePosition)) {
insidePosition.x += 10;
insidePosition.y += 10;
}
internalPostionDictionary[insidePosition.x] = insidePosition.y;
get().setPositionDictionary(internalPostionDictionary);
selection.nodes.forEach((node: AllNodeType) => {
// Generate a unique node ID
let newId = getNodeId(node.data.type);

View file

@ -53,6 +53,12 @@ export type FlowPoolType = {
};
export type FlowStoreType = {
//key x, y
positionDictionary: { [key: number]: number };
isPositionAvailable: (position: { x: number; y: number }) => boolean;
setPositionDictionary: (positionDictionary: {
[key: number]: number;
}) => void;
fitViewNode: (nodeId: string) => void;
autoSaveFlow: (() => void) | undefined;
componentsToUpdate: string[];

View file

@ -1746,3 +1746,11 @@ export function someFlowTemplateFields(
export function checkHasToolMode(template: APITemplateType) {
return template && Object.values(template).some((field) => field.tool_mode);
}
export function buildPositionDictionary(nodes: AllNodeType[]) {
const positionDictionary = {};
nodes.forEach((node) => {
positionDictionary[node.position.x] = node.position.y;
});
return positionDictionary;
}