Fixed flowsContext to work using useFlow zustand, removed unused functions
This commit is contained in:
parent
75326cad27
commit
3d720f7f79
5 changed files with 37 additions and 262 deletions
|
|
@ -46,9 +46,11 @@ import {
|
||||||
checkOldEdgesHandles,
|
checkOldEdgesHandles,
|
||||||
cleanEdges,
|
cleanEdges,
|
||||||
createFlowComponent,
|
createFlowComponent,
|
||||||
|
processFlowEdges,
|
||||||
removeFileNameFromComponents,
|
removeFileNameFromComponents,
|
||||||
scapeJSONParse,
|
scapeJSONParse,
|
||||||
scapedJSONStringfy,
|
scapedJSONStringfy,
|
||||||
|
updateEdges,
|
||||||
updateEdgesHandleIds,
|
updateEdgesHandleIds,
|
||||||
updateIds,
|
updateIds,
|
||||||
} from "../utils/reactflowUtils";
|
} from "../utils/reactflowUtils";
|
||||||
|
|
@ -60,6 +62,7 @@ import {
|
||||||
import { alertContext } from "./alertContext";
|
import { alertContext } from "./alertContext";
|
||||||
import { AuthContext } from "./authContext";
|
import { AuthContext } from "./authContext";
|
||||||
import { typesContext } from "./typesContext";
|
import { typesContext } from "./typesContext";
|
||||||
|
import useFlow from "../stores/flowManagerStore";
|
||||||
|
|
||||||
const uid = new ShortUniqueId({ length: 5 });
|
const uid = new ShortUniqueId({ length: 5 });
|
||||||
|
|
||||||
|
|
@ -98,98 +101,10 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
const [tabId, setTabId] = useState("");
|
const [tabId, setTabId] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [flows, setFlows] = useState<Array<FlowType>>([]);
|
const [flows, setFlows] = useState<Array<FlowType>>([]);
|
||||||
const { reactFlowInstance, setData } = useContext(typesContext);
|
const { setData } = useContext(typesContext);
|
||||||
const [lastCopiedSelection, setLastCopiedSelection] = useState<{
|
|
||||||
nodes: any;
|
|
||||||
edges: any;
|
|
||||||
} | null>(null);
|
|
||||||
const [tabsState, setTabsState] = useState<FlowsState>({});
|
const [tabsState, setTabsState] = useState<FlowsState>({});
|
||||||
const [getTweak, setTweak] = useState<tweakType>([]);
|
|
||||||
|
|
||||||
const [nodes, setNodesInternal, onNodesChangeInternal] = useNodesState([]);
|
const {nodes, edges, paste, setPending, reactFlowInstance} = useFlow();
|
||||||
|
|
||||||
const [edges, setEdgesInternal, onEdgesChangeInternal] = useEdgesState([]);
|
|
||||||
|
|
||||||
const setPending = (pending: boolean) => {
|
|
||||||
setTabsState((prev: FlowsState) => {
|
|
||||||
return {
|
|
||||||
...prev,
|
|
||||||
[tabId]: {
|
|
||||||
...prev[tabId],
|
|
||||||
isPending: pending,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const isPending = tabsState[tabId]?.isPending ?? false;
|
|
||||||
|
|
||||||
const onNodesChange = useCallback(
|
|
||||||
(change: NodeChange[]) => {
|
|
||||||
onNodesChangeInternal(change);
|
|
||||||
if (!isPending) setPending(true);
|
|
||||||
},
|
|
||||||
[onNodesChangeInternal, setPending, isPending]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEdgesChange = useCallback(
|
|
||||||
(edges: EdgeChange[]) => {
|
|
||||||
onEdgesChangeInternal(edges);
|
|
||||||
if (!isPending) setPending(true);
|
|
||||||
},
|
|
||||||
[onEdgesChangeInternal, setPending, isPending]
|
|
||||||
);
|
|
||||||
|
|
||||||
const setNodes = (change: Node[] | ((oldState: Node[]) => Node[])) => {
|
|
||||||
let newChange = typeof change === "function" ? change(nodes) : change;
|
|
||||||
let newEdges = cleanEdges(newChange, edges);
|
|
||||||
|
|
||||||
saveCurrentFlow(
|
|
||||||
newChange,
|
|
||||||
newEdges,
|
|
||||||
reactFlowInstance?.getViewport() ?? { zoom: 1, x: 0, y: 0 }
|
|
||||||
);
|
|
||||||
setEdgesInternal(newEdges);
|
|
||||||
setNodesInternal(newChange);
|
|
||||||
};
|
|
||||||
|
|
||||||
const setNode = (id: string, change: Node | ((oldState: Node) => Node)) => {
|
|
||||||
let newChange =
|
|
||||||
typeof change === "function"
|
|
||||||
? change(nodes.find((node) => node.id === id)!)
|
|
||||||
: change;
|
|
||||||
|
|
||||||
setNodes((oldNodes) =>
|
|
||||||
oldNodes.map((node) => {
|
|
||||||
if (node.id === id) {
|
|
||||||
return newChange;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getNode = (id: string) => {
|
|
||||||
return nodes.find((node) => node.id === id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const setEdges = (change: Edge[] | ((oldState: Edge[]) => Edge[])) => {
|
|
||||||
let newChange = typeof change === "function" ? change(edges) : change;
|
|
||||||
|
|
||||||
saveCurrentFlow(
|
|
||||||
nodes,
|
|
||||||
newChange,
|
|
||||||
reactFlowInstance?.getViewport() ?? { zoom: 1, x: 0, y: 0 }
|
|
||||||
);
|
|
||||||
setEdgesInternal(newChange);
|
|
||||||
};
|
|
||||||
|
|
||||||
const newNodeId = useRef(uid());
|
|
||||||
|
|
||||||
function incrementNodeId() {
|
|
||||||
newNodeId.current = uid();
|
|
||||||
return newNodeId.current;
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshFlows() {
|
function refreshFlows() {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
@ -197,7 +112,7 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
if (DbData) {
|
if (DbData) {
|
||||||
try {
|
try {
|
||||||
processFlows(DbData, false);
|
processFlows(DbData, false);
|
||||||
updateStateWithDbData(DbData);
|
setFlows(DbData);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
@ -247,23 +162,6 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function processFlowEdges(flow: FlowType) {
|
|
||||||
if (!flow.data || !flow.data.edges) return;
|
|
||||||
if (checkOldEdgesHandles(flow.data.edges)) {
|
|
||||||
const newEdges = updateEdgesHandleIds(flow.data);
|
|
||||||
flow.data.edges = newEdges;
|
|
||||||
}
|
|
||||||
//update edges colors
|
|
||||||
flow.data.edges.forEach((edge) => {
|
|
||||||
edge.className = "";
|
|
||||||
edge.style = { stroke: "#555" };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateStateWithDbData(tabsData: FlowType[]) {
|
|
||||||
setFlows(tabsData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads the current flow as a JSON file
|
* Downloads the current flow as a JSON file
|
||||||
*/
|
*/
|
||||||
|
|
@ -311,11 +209,6 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
link.click();
|
link.click();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeId(nodeType: string) {
|
|
||||||
return nodeType + "-" + incrementNodeId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a file input and listens to a change event to upload a JSON flow file.
|
* Creates a file input and listens to a change event to upload a JSON flow file.
|
||||||
* If the file type is application/json, the file is read and parsed into a JSON object.
|
* If the file type is application/json, the file is read and parsed into a JSON object.
|
||||||
|
|
@ -424,111 +317,6 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
processFlows(flows.filter((flow) => flow.id !== id));
|
processFlows(flows.filter((flow) => flow.id !== id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Add a new flow to the list of flows.
|
|
||||||
* @param flow Optional flow to add.
|
|
||||||
*/
|
|
||||||
function paste(
|
|
||||||
selectionInstance: { nodes: Node[]; edges: Edge[] },
|
|
||||||
position: { x: number; y: number; paneX?: number; paneY?: number }
|
|
||||||
) {
|
|
||||||
let minimumX = Infinity;
|
|
||||||
let minimumY = Infinity;
|
|
||||||
let idsMap = {};
|
|
||||||
let newNodes: Node<NodeDataType>[] = nodes;
|
|
||||||
let newEdges = edges;
|
|
||||||
selectionInstance.nodes.forEach((node: Node) => {
|
|
||||||
if (node.position.y < minimumY) {
|
|
||||||
minimumY = node.position.y;
|
|
||||||
}
|
|
||||||
if (node.position.x < minimumX) {
|
|
||||||
minimumX = node.position.x;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const insidePosition = position.paneX
|
|
||||||
? { x: position.paneX + position.x, y: position.paneY! + position.y }
|
|
||||||
: reactFlowInstance!.screenToFlowPosition({
|
|
||||||
x: position.x,
|
|
||||||
y: position.y,
|
|
||||||
});
|
|
||||||
|
|
||||||
selectionInstance.nodes.forEach((node: NodeType) => {
|
|
||||||
// Generate a unique node ID
|
|
||||||
let newId = getNodeId(node.data.type);
|
|
||||||
idsMap[node.id] = newId;
|
|
||||||
|
|
||||||
// Create a new node object
|
|
||||||
const newNode: NodeType = {
|
|
||||||
id: newId,
|
|
||||||
type: "genericNode",
|
|
||||||
position: {
|
|
||||||
x: insidePosition.x + node.position!.x - minimumX,
|
|
||||||
y: insidePosition.y + node.position!.y - minimumY,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
..._.cloneDeep(node.data),
|
|
||||||
id: newId,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add the new node to the list of nodes in state
|
|
||||||
newNodes = newNodes
|
|
||||||
.map((node) => ({ ...node, selected: false }))
|
|
||||||
.concat({ ...newNode, selected: false });
|
|
||||||
});
|
|
||||||
setNodes(newNodes);
|
|
||||||
|
|
||||||
selectionInstance.edges.forEach((edge: Edge) => {
|
|
||||||
let source = idsMap[edge.source];
|
|
||||||
let target = idsMap[edge.target];
|
|
||||||
const sourceHandleObject: sourceHandleType = scapeJSONParse(
|
|
||||||
edge.sourceHandle!
|
|
||||||
);
|
|
||||||
let sourceHandle = scapedJSONStringfy({
|
|
||||||
...sourceHandleObject,
|
|
||||||
id: source,
|
|
||||||
});
|
|
||||||
sourceHandleObject.id = source;
|
|
||||||
|
|
||||||
edge.data.sourceHandle = sourceHandleObject;
|
|
||||||
const targetHandleObject: targetHandleType = scapeJSONParse(
|
|
||||||
edge.targetHandle!
|
|
||||||
);
|
|
||||||
let targetHandle = scapedJSONStringfy({
|
|
||||||
...targetHandleObject,
|
|
||||||
id: target,
|
|
||||||
});
|
|
||||||
targetHandleObject.id = target;
|
|
||||||
edge.data.targetHandle = targetHandleObject;
|
|
||||||
let id =
|
|
||||||
"reactflow__edge-" +
|
|
||||||
source +
|
|
||||||
sourceHandle +
|
|
||||||
"-" +
|
|
||||||
target +
|
|
||||||
targetHandle;
|
|
||||||
newEdges = addEdge(
|
|
||||||
{
|
|
||||||
source,
|
|
||||||
target,
|
|
||||||
sourceHandle,
|
|
||||||
targetHandle,
|
|
||||||
id,
|
|
||||||
data: cloneDeep(edge.data),
|
|
||||||
style: { stroke: "#555" },
|
|
||||||
className:
|
|
||||||
targetHandleObject.type === "Text"
|
|
||||||
? "stroke-gray-800 "
|
|
||||||
: "stroke-gray-900 ",
|
|
||||||
animated: targetHandleObject.type === "Text",
|
|
||||||
selected: false,
|
|
||||||
},
|
|
||||||
newEdges.map((edge) => ({ ...edge, selected: false }))
|
|
||||||
);
|
|
||||||
});
|
|
||||||
setEdges(newEdges);
|
|
||||||
}
|
|
||||||
|
|
||||||
const addFlow = async (
|
const addFlow = async (
|
||||||
newProject: Boolean,
|
newProject: Boolean,
|
||||||
|
|
@ -592,26 +380,12 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
//add animation to text type edges
|
//add animation to text type edges
|
||||||
updateEdges(data.edges);
|
updateEdges(data.edges);
|
||||||
// updateNodes(data.nodes, data.edges);
|
// updateNodes(data.nodes, data.edges);
|
||||||
if (refreshIds) updateIds(data, getNodeId); // Assuming updateIds is defined elsewhere
|
if (refreshIds) updateIds(data); // Assuming updateIds is defined elsewhere
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateEdges = (edges: Edge[]) => {
|
|
||||||
if (edges)
|
|
||||||
edges.forEach((edge) => {
|
|
||||||
const targetHandleObject: targetHandleType = scapeJSONParse(
|
|
||||||
edge.targetHandle!
|
|
||||||
);
|
|
||||||
edge.className =
|
|
||||||
(targetHandleObject.type === "Text"
|
|
||||||
? "stroke-gray-800 "
|
|
||||||
: "stroke-gray-900 ") + " stroke-connection";
|
|
||||||
edge.animated = targetHandleObject.type === "Text";
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const createNewFlow = (
|
const createNewFlow = (
|
||||||
flowData: ReactFlowJsonObject | null,
|
flowData: ReactFlowJsonObject | null,
|
||||||
flow: FlowType
|
flow: FlowType
|
||||||
|
|
@ -726,7 +500,6 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [isBuilt, setIsBuilt] = useState(false);
|
|
||||||
// Initialize state variable for the version
|
// Initialize state variable for the version
|
||||||
const [version, setVersion] = useState("");
|
const [version, setVersion] = useState("");
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -735,21 +508,6 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
function deleteNode(idx: string | Array<string>) {
|
|
||||||
setNodes((oldNodes) =>
|
|
||||||
oldNodes.filter((node) =>
|
|
||||||
typeof idx === "string" ? node.id !== idx : !idx.includes(node.id)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteEdge(idx: string | Array<string>) {
|
|
||||||
setEdges((oldEdges) =>
|
|
||||||
oldEdges.filter((edge) =>
|
|
||||||
typeof idx === "string" ? edge.id !== idx : !idx.includes(edge.id)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlowsContext.Provider
|
<FlowsContext.Provider
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@ import { AuthContext } from "./authContext";
|
||||||
//context to share types adn functions from nodes to flow
|
//context to share types adn functions from nodes to flow
|
||||||
|
|
||||||
const initialValue: typesContextType = {
|
const initialValue: typesContextType = {
|
||||||
reactFlowInstance: null,
|
|
||||||
setReactFlowInstance: (newState: ReactFlowInstance) => {},
|
|
||||||
types: {},
|
types: {},
|
||||||
setTypes: () => {},
|
setTypes: () => {},
|
||||||
templates: {},
|
templates: {},
|
||||||
|
|
@ -34,8 +32,6 @@ export const typesContext = createContext<typesContextType>(initialValue);
|
||||||
|
|
||||||
export function TypesProvider({ children }: { children: ReactNode }) {
|
export function TypesProvider({ children }: { children: ReactNode }) {
|
||||||
const [types, setTypes] = useState({});
|
const [types, setTypes] = useState({});
|
||||||
const [reactFlowInstance, setReactFlowInstance] =
|
|
||||||
useState<ReactFlowInstance | null>(null);
|
|
||||||
const [templates, setTemplates] = useState({});
|
const [templates, setTemplates] = useState({});
|
||||||
const [data, setData] = useState({});
|
const [data, setData] = useState({});
|
||||||
const [fetchError, setFetchError] = useState(false);
|
const [fetchError, setFetchError] = useState(false);
|
||||||
|
|
@ -100,8 +96,6 @@ export function TypesProvider({ children }: { children: ReactNode }) {
|
||||||
value={{
|
value={{
|
||||||
types,
|
types,
|
||||||
setTypes,
|
setTypes,
|
||||||
reactFlowInstance,
|
|
||||||
setReactFlowInstance,
|
|
||||||
setTemplates,
|
setTemplates,
|
||||||
templates,
|
templates,
|
||||||
data,
|
data,
|
||||||
|
|
|
||||||
|
|
@ -290,10 +290,9 @@ export default function ExtraSidebar(): JSX.Element {
|
||||||
{flow && flow.data && (
|
{flow && flow.data && (
|
||||||
<ShadTooltip content="Save" side="top">
|
<ShadTooltip content="Save" side="top">
|
||||||
<button
|
<button
|
||||||
disabled={flow?.data?.nodes.length === 0}
|
|
||||||
className={
|
className={
|
||||||
"extra-side-bar-buttons " +
|
"extra-side-bar-buttons " +
|
||||||
(isPending && flow!.data!.nodes?.length > 0
|
(isPending
|
||||||
? ""
|
? ""
|
||||||
: "button-disable")
|
: "button-disable")
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +304,7 @@ export default function ExtraSidebar(): JSX.Element {
|
||||||
name="Save"
|
name="Save"
|
||||||
className={
|
className={
|
||||||
"side-bar-button-size" +
|
"side-bar-button-size" +
|
||||||
(isPending && flow!.data!.nodes?.length > 0
|
(isPending
|
||||||
? " "
|
? " "
|
||||||
: " extra-side-bar-save-disable")
|
: " extra-side-bar-save-disable")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ const template: { [char: string]: APIClassType } = {};
|
||||||
const data: { [char: string]: string } = {};
|
const data: { [char: string]: string } = {};
|
||||||
|
|
||||||
export type typesContextType = {
|
export type typesContextType = {
|
||||||
reactFlowInstance: ReactFlowInstance | null;
|
|
||||||
setReactFlowInstance: (newState: ReactFlowInstance) => void;
|
|
||||||
types: typeof types;
|
types: typeof types;
|
||||||
setTypes: (newState: {}) => void;
|
setTypes: (newState: {}) => void;
|
||||||
templates: typeof template;
|
templates: typeof template;
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,6 @@ export function updateTemplate(
|
||||||
|
|
||||||
export function updateIds(
|
export function updateIds(
|
||||||
newFlow: ReactFlowJsonObject,
|
newFlow: ReactFlowJsonObject,
|
||||||
getNodeId: (type: string) => string
|
|
||||||
) {
|
) {
|
||||||
let idsMap = {};
|
let idsMap = {};
|
||||||
|
|
||||||
|
|
@ -269,6 +268,20 @@ export function validateNodes(nodes: Node[], edges: Edge[]) {
|
||||||
return nodes.flatMap((n: NodeType) => validateNode(n, edges));
|
return nodes.flatMap((n: NodeType) => validateNode(n, edges));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function updateEdges(edges: Edge[]) {
|
||||||
|
if (edges)
|
||||||
|
edges.forEach((edge) => {
|
||||||
|
const targetHandleObject: targetHandleType = scapeJSONParse(
|
||||||
|
edge.targetHandle!
|
||||||
|
);
|
||||||
|
edge.className =
|
||||||
|
(targetHandleObject.type === "Text"
|
||||||
|
? "stroke-gray-800 "
|
||||||
|
: "stroke-gray-900 ") + " stroke-connection";
|
||||||
|
edge.animated = targetHandleObject.type === "Text";
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export function addVersionToDuplicates(flow: FlowType, flows: FlowType[]) {
|
export function addVersionToDuplicates(flow: FlowType, flows: FlowType[]) {
|
||||||
const existingNames = flows.map((item) => item.name);
|
const existingNames = flows.map((item) => item.name);
|
||||||
let newName = flow.name;
|
let newName = flow.name;
|
||||||
|
|
@ -922,6 +935,19 @@ function updateEdgesIds(edges: Edge[], idsMap: { [key: string]: string }) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function processFlowEdges(flow: FlowType) {
|
||||||
|
if (!flow.data || !flow.data.edges) return;
|
||||||
|
if (checkOldEdgesHandles(flow.data.edges)) {
|
||||||
|
const newEdges = updateEdgesHandleIds(flow.data);
|
||||||
|
flow.data.edges = newEdges;
|
||||||
|
}
|
||||||
|
//update edges colors
|
||||||
|
flow.data.edges.forEach((edge) => {
|
||||||
|
edge.className = "";
|
||||||
|
edge.style = { stroke: "#555" };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function expandGroupNode(
|
export function expandGroupNode(
|
||||||
groupNode: NodeDataType,
|
groupNode: NodeDataType,
|
||||||
nodes: Node[],
|
nodes: Node[],
|
||||||
|
|
@ -930,7 +956,7 @@ export function expandGroupNode(
|
||||||
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void
|
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void
|
||||||
) {
|
) {
|
||||||
const { template, flow } = _.cloneDeep(groupNode.node!);
|
const { template, flow } = _.cloneDeep(groupNode.node!);
|
||||||
const idsMap = updateIds(flow!.data!, getNodeId);
|
const idsMap = updateIds(flow!.data!);
|
||||||
updateProxyIdsOnTemplate(template, idsMap);
|
updateProxyIdsOnTemplate(template, idsMap);
|
||||||
let flowEdges = edges;
|
let flowEdges = edges;
|
||||||
updateEdgesIds(flowEdges, idsMap);
|
updateEdgesIds(flowEdges, idsMap);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue