Merge pull request #2411 from automatisch/AUT-1481
feat: update react flow library and improve state management
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
"@xyflow/react": "^12.4.4",
|
||||
"axios": "^1.6.0",
|
||||
"clipboard-copy": "^4.0.1",
|
||||
"compare-versions": "^4.1.3",
|
||||
@@ -33,7 +34,6 @@
|
||||
"react-router-dom": "^6.0.2",
|
||||
"react-scripts": "5.0.0",
|
||||
"react-window": "^1.8.9",
|
||||
"reactflow": "^11.11.2",
|
||||
"slate": "^0.94.1",
|
||||
"slate-history": "^0.93.0",
|
||||
"slate-react": "^0.94.2",
|
||||
|
||||
@@ -18,6 +18,8 @@ import { StepPropType, SubstepPropType } from 'propTypes/propTypes';
|
||||
import useTriggers from 'hooks/useTriggers';
|
||||
import useActions from 'hooks/useActions';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
|
||||
const optionGenerator = (app) => ({
|
||||
label: app.name,
|
||||
value: app.key,
|
||||
@@ -145,7 +147,11 @@ function ChooseAppAndEventSubstep(props) {
|
||||
title={name}
|
||||
valid={valid}
|
||||
/>
|
||||
<Collapse in={expanded} timeout="auto" unmountOnExit>
|
||||
<Collapse
|
||||
in={expanded}
|
||||
timeout={useNewFlowEditor ? 0 : 'auto'}
|
||||
unmountOnExit
|
||||
>
|
||||
<ListItem
|
||||
sx={{
|
||||
pt: 2,
|
||||
|
||||
@@ -25,6 +25,8 @@ import useTestConnection from 'hooks/useTestConnection';
|
||||
import useOAuthClients from 'hooks/useOAuthClients';
|
||||
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
|
||||
const ADD_CONNECTION_VALUE = 'ADD_CONNECTION';
|
||||
const ADD_SHARED_CONNECTION_VALUE = 'ADD_SHARED_CONNECTION';
|
||||
|
||||
@@ -240,7 +242,11 @@ function ChooseConnectionSubstep(props) {
|
||||
title={name}
|
||||
valid={isTestConnectionPending ? null : stepConnection?.verified}
|
||||
/>
|
||||
<Collapse in={expanded} timeout="auto" unmountOnExit>
|
||||
<Collapse
|
||||
in={expanded}
|
||||
timeout={useNewFlowEditor ? 0 : 'auto'}
|
||||
unmountOnExit
|
||||
>
|
||||
<ListItem
|
||||
sx={{
|
||||
pt: 2,
|
||||
|
||||
@@ -9,7 +9,7 @@ import Stack from '@mui/material/Stack';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import * as React from 'react';
|
||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||
import { ReactFlowProvider } from 'reactflow';
|
||||
import { ReactFlowProvider } from '@xyflow/react';
|
||||
|
||||
import Can from 'components/Can';
|
||||
import Container from 'components/Container';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { EdgeLabelRenderer, getStraightPath } from 'reactflow';
|
||||
import { EdgeLabelRenderer, getStraightPath } from '@xyflow/react';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { EdgesContext } from '../EditorNew';
|
||||
|
||||
export default function Edge({
|
||||
@@ -14,7 +14,7 @@ export default function Edge({
|
||||
source,
|
||||
data: { laidOut },
|
||||
}) {
|
||||
const { stepCreationInProgress, flowActive, onAddStep } =
|
||||
const { flowActive, onStepAdd, isCreateStepPending } =
|
||||
useContext(EdgesContext);
|
||||
|
||||
const [edgePath, labelX, labelY] = getStraightPath({
|
||||
@@ -28,7 +28,7 @@ export default function Edge({
|
||||
<>
|
||||
<EdgeLabelRenderer>
|
||||
<IconButton
|
||||
onClick={() => onAddStep(source)}
|
||||
onClick={() => onStepAdd(source)}
|
||||
color="primary"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
@@ -36,7 +36,7 @@ export default function Edge({
|
||||
pointerEvents: 'all',
|
||||
visibility: laidOut ? 'visible' : 'hidden',
|
||||
}}
|
||||
disabled={stepCreationInProgress || flowActive}
|
||||
disabled={isCreateStepPending || flowActive}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
import { useEffect, useCallback, createContext, useRef, useState } from 'react';
|
||||
import {
|
||||
useEffect,
|
||||
useCallback,
|
||||
createContext,
|
||||
useRef,
|
||||
useState,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { FlowPropType } from 'propTypes/propTypes';
|
||||
import ReactFlow, { useNodesState, useEdgesState } from 'reactflow';
|
||||
import 'reactflow/dist/style.css';
|
||||
import { ReactFlow, useEdgesState, applyNodeChanges } from '@xyflow/react';
|
||||
import '@xyflow/react/dist/style.css';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
import useCreateStep from 'hooks/useCreateStep';
|
||||
import useUpdateStep from 'hooks/useUpdateStep';
|
||||
import useCreateStep from 'hooks/useCreateStep';
|
||||
import { FlowPropType } from 'propTypes/propTypes';
|
||||
|
||||
import { useAutoLayout } from './useAutoLayout';
|
||||
import { useScrollBoundaries } from './useScrollBoundaries';
|
||||
import FlowStepNode from './FlowStepNode/FlowStepNode';
|
||||
import Edge from './Edge/Edge';
|
||||
import InvisibleNode from './InvisibleNode/InvisibleNode';
|
||||
import { EditorWrapper } from './style';
|
||||
import {
|
||||
generateEdgeId,
|
||||
generateInitialEdges,
|
||||
generateInitialNodes,
|
||||
updatedCollapsedNodes,
|
||||
} from './utils';
|
||||
import { getLaidOutElements, updatedCollapsedNodes } from './utils';
|
||||
import { EDGE_TYPES, INVISIBLE_NODE_ID, NODE_TYPES } from './constants';
|
||||
import { EditorWrapper } from './style';
|
||||
|
||||
export const EdgesContext = createContext();
|
||||
export const NodesContext = createContext();
|
||||
@@ -38,22 +40,122 @@ const EditorNew = ({ flow }) => {
|
||||
const { mutateAsync: updateStep } = useUpdateStep();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const [nodes, setNodes] = useState([]);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState();
|
||||
const [containerHeight, setContainerHeight] = useState(null);
|
||||
const containerRef = useRef(null);
|
||||
const { mutateAsync: createStep, isPending: isCreateStepPending } =
|
||||
useCreateStep(flow?.id);
|
||||
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(
|
||||
generateInitialNodes(flow),
|
||||
);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(
|
||||
generateInitialEdges(flow),
|
||||
);
|
||||
const [containerHeight, setContainerHeight] = useState(null);
|
||||
|
||||
useAutoLayout();
|
||||
useScrollBoundaries(containerHeight);
|
||||
|
||||
const createdStepIdRef = useRef(null);
|
||||
const containerRef = useRef(null);
|
||||
const onStepDelete = useCallback(
|
||||
(nodeId) => {
|
||||
const prevEdge = edges.find((edge) => edge.target === nodeId);
|
||||
const edgeToDelete = edges.find((edge) => edge.source === nodeId);
|
||||
|
||||
const newEdges = edges
|
||||
.map((edge) => {
|
||||
if (
|
||||
edge.id === edgeToDelete?.id ||
|
||||
(edge.id === prevEdge?.id && !edgeToDelete)
|
||||
) {
|
||||
return null;
|
||||
} else if (edge.id === prevEdge?.id) {
|
||||
return {
|
||||
...prevEdge,
|
||||
target: edgeToDelete?.target,
|
||||
};
|
||||
}
|
||||
return edge;
|
||||
})
|
||||
.filter((edge) => !!edge);
|
||||
|
||||
setNodes((nodes) => {
|
||||
const newNodes = nodes.filter((node) => node.id !== nodeId);
|
||||
const laidOutElements = getLaidOutElements(newNodes, newEdges);
|
||||
setEdges([...laidOutElements.edges]);
|
||||
return [...laidOutElements.nodes];
|
||||
});
|
||||
},
|
||||
[edges, setEdges],
|
||||
);
|
||||
|
||||
const onStepAdd = useCallback(
|
||||
async (previousStepId) => {
|
||||
const { data: createdStep } = await createStep({ previousStepId });
|
||||
|
||||
setNodes((nodes) => {
|
||||
const newNode = {
|
||||
id: createdStep.id,
|
||||
type: NODE_TYPES.FLOW_STEP,
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
|
||||
const newNodes = nodes.flatMap((node) => {
|
||||
if (node.id === previousStepId) {
|
||||
return [node, newNode];
|
||||
}
|
||||
return node;
|
||||
});
|
||||
return updatedCollapsedNodes(newNodes, createdStep.id);
|
||||
});
|
||||
|
||||
setEdges((edges) => {
|
||||
const newEdges = edges
|
||||
.map((edge) => {
|
||||
if (edge.source === previousStepId) {
|
||||
const previousTarget = edge.target;
|
||||
return [
|
||||
{ ...edge, target: createdStep.id },
|
||||
{
|
||||
id: uuidv4(),
|
||||
source: createdStep.id,
|
||||
target: previousTarget,
|
||||
type: EDGE_TYPES.ADD_NODE_EDGE,
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
return edge;
|
||||
})
|
||||
.flat();
|
||||
|
||||
return newEdges;
|
||||
});
|
||||
},
|
||||
[createStep, setEdges],
|
||||
);
|
||||
|
||||
const onStepAddDebounced = useMemo(
|
||||
() => debounce(onStepAdd, 300),
|
||||
[onStepAdd],
|
||||
);
|
||||
|
||||
const onNodesChange = useCallback(
|
||||
(changes) => {
|
||||
setNodes((oldNodes) => {
|
||||
const newNodes = applyNodeChanges(changes, oldNodes);
|
||||
|
||||
if (changes?.some((change) => change.type === 'dimensions')) {
|
||||
const laidOutElements = getLaidOutElements(newNodes, edges);
|
||||
setEdges([...laidOutElements.edges]);
|
||||
return [...laidOutElements.nodes];
|
||||
} else {
|
||||
return newNodes;
|
||||
}
|
||||
});
|
||||
},
|
||||
[setNodes, setEdges, edges],
|
||||
);
|
||||
|
||||
const openNextStep = useCallback(
|
||||
(currentStepId) => {
|
||||
@@ -108,111 +210,54 @@ const EditorNew = ({ flow }) => {
|
||||
[updateStep, queryClient],
|
||||
);
|
||||
|
||||
const onAddStep = useCallback(
|
||||
debounce(async (previousStepId) => {
|
||||
const { data: createdStep } = await createStep({ previousStepId });
|
||||
createdStepIdRef.current = createdStep.id;
|
||||
}, 300),
|
||||
[createStep],
|
||||
);
|
||||
useEffect(function initiateNodesAndEdges() {
|
||||
const newNodes = flow?.steps.map((step, index) => {
|
||||
return {
|
||||
id: step.id,
|
||||
type: NODE_TYPES.FLOW_STEP,
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
zIndex: index !== 0 ? 0 : 1,
|
||||
data: {
|
||||
collapsed: index !== 0,
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (flow.steps.length + 1 !== nodes.length) {
|
||||
setNodes((nodes) => {
|
||||
const newNodes = flow.steps.map((step) => {
|
||||
const createdStepId = createdStepIdRef.current;
|
||||
const prevNode = nodes.find(({ id }) => id === step.id);
|
||||
if (prevNode) {
|
||||
return {
|
||||
...prevNode,
|
||||
zIndex: createdStepId ? 0 : prevNode.zIndex,
|
||||
data: {
|
||||
...prevNode.data,
|
||||
collapsed: createdStepId ? true : prevNode.data.collapsed,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
id: step.id,
|
||||
type: NODE_TYPES.FLOW_STEP,
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
zIndex: 1,
|
||||
data: {
|
||||
collapsed: false,
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
newNodes.push({
|
||||
id: INVISIBLE_NODE_ID,
|
||||
type: NODE_TYPES.INVISIBLE,
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const prevInvisible = nodes.find(({ id }) => id === INVISIBLE_NODE_ID);
|
||||
return [
|
||||
...newNodes,
|
||||
{
|
||||
id: INVISIBLE_NODE_ID,
|
||||
type: NODE_TYPES.INVISIBLE,
|
||||
position: {
|
||||
x: prevInvisible?.position.x || 0,
|
||||
y: prevInvisible?.position.y || 0,
|
||||
const newEdges = newNodes
|
||||
.map((node, i) => {
|
||||
const sourceId = node.id;
|
||||
const targetId = newNodes[i + 1]?.id;
|
||||
if (targetId) {
|
||||
return {
|
||||
id: uuidv4(),
|
||||
source: sourceId,
|
||||
target: targetId,
|
||||
type: 'addNodeEdge',
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
};
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((edge) => !!edge);
|
||||
|
||||
setEdges((edges) => {
|
||||
const newEdges = flow.steps
|
||||
.map((step, i) => {
|
||||
const sourceId = step.id;
|
||||
const targetId = flow.steps[i + 1]?.id;
|
||||
const edge = edges?.find(
|
||||
(edge) => edge.id === generateEdgeId(sourceId, targetId),
|
||||
);
|
||||
if (targetId) {
|
||||
return {
|
||||
id: generateEdgeId(sourceId, targetId),
|
||||
source: sourceId,
|
||||
target: targetId,
|
||||
type: 'addNodeEdge',
|
||||
data: {
|
||||
laidOut: edge ? edge?.data.laidOut : false,
|
||||
},
|
||||
};
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((edge) => !!edge);
|
||||
|
||||
const lastStep = flow.steps[flow.steps.length - 1];
|
||||
const lastEdge = edges[edges.length - 1];
|
||||
|
||||
return lastStep
|
||||
? [
|
||||
...newEdges,
|
||||
{
|
||||
id: generateEdgeId(lastStep.id, INVISIBLE_NODE_ID),
|
||||
source: lastStep.id,
|
||||
target: INVISIBLE_NODE_ID,
|
||||
type: 'addNodeEdge',
|
||||
data: {
|
||||
laidOut:
|
||||
lastEdge?.id ===
|
||||
generateEdgeId(lastStep.id, INVISIBLE_NODE_ID)
|
||||
? lastEdge?.data.laidOut
|
||||
: false,
|
||||
},
|
||||
},
|
||||
]
|
||||
: newEdges;
|
||||
});
|
||||
|
||||
if (createdStepIdRef.current) {
|
||||
createdStepIdRef.current = null;
|
||||
}
|
||||
}
|
||||
}, [flow.steps]);
|
||||
setNodes(newNodes);
|
||||
setEdges(newEdges);
|
||||
}, []);
|
||||
|
||||
useEffect(function updateContainerHeightOnResize() {
|
||||
const updateHeight = () => {
|
||||
@@ -237,15 +282,16 @@ const EditorNew = ({ flow }) => {
|
||||
onStepOpen,
|
||||
onStepClose,
|
||||
onStepChange,
|
||||
flowId: flow.id,
|
||||
steps: flow.steps,
|
||||
onStepDelete,
|
||||
flowId: flow?.id,
|
||||
steps: flow?.steps,
|
||||
}}
|
||||
>
|
||||
<EdgesContext.Provider
|
||||
value={{
|
||||
stepCreationInProgress: isCreateStepPending,
|
||||
onAddStep,
|
||||
flowActive: flow.active,
|
||||
flowActive: flow?.active,
|
||||
isCreateStepPending,
|
||||
onStepAdd: onStepAddDebounced,
|
||||
}}
|
||||
>
|
||||
<EditorWrapper direction="column" ref={containerRef}>
|
||||
@@ -264,6 +310,7 @@ const EditorNew = ({ flow }) => {
|
||||
zoomOnDoubleClick={false}
|
||||
panActivationKeyCode={null}
|
||||
proOptions={{ hideAttribution: true }}
|
||||
elementsSelectable={false}
|
||||
/>
|
||||
</EditorWrapper>
|
||||
</EdgesContext.Provider>
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import { Handle, Position } from 'reactflow';
|
||||
import { useContext } from 'react';
|
||||
import { Handle, Position } from '@xyflow/react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import FlowStep from 'components/FlowStep';
|
||||
|
||||
import { NodeWrapper, NodeInnerWrapper } from './style.js';
|
||||
import { useContext } from 'react';
|
||||
import { NodesContext } from '../EditorNew.jsx';
|
||||
import { NodeWrapper, NodeInnerWrapper } from './style.js';
|
||||
|
||||
function FlowStepNode({ data: { collapsed, laidOut }, id }) {
|
||||
const { openNextStep, onStepOpen, onStepClose, onStepChange, flowId, steps } =
|
||||
useContext(NodesContext);
|
||||
const {
|
||||
openNextStep,
|
||||
onStepOpen,
|
||||
onStepClose,
|
||||
onStepChange,
|
||||
onStepDelete,
|
||||
flowId,
|
||||
steps,
|
||||
} = useContext(NodesContext);
|
||||
|
||||
const step = steps.find(({ id: stepId }) => stepId === id);
|
||||
|
||||
@@ -36,6 +43,7 @@ function FlowStepNode({ data: { collapsed, laidOut }, id }) {
|
||||
onChange={onStepChange}
|
||||
flowId={flowId}
|
||||
onContinue={() => openNextStep(step.id)}
|
||||
onDelete={onStepDelete}
|
||||
/>
|
||||
)}
|
||||
<Handle
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Handle, Position } from 'reactflow';
|
||||
import { Handle, Position } from '@xyflow/react';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
// This node is used for adding an edge with add node button after the last flow step node
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import Dagre from '@dagrejs/dagre';
|
||||
import { usePrevious } from 'hooks/usePrevious';
|
||||
import { isEqual } from 'lodash';
|
||||
import { useNodesInitialized, useNodes, useReactFlow } from 'reactflow';
|
||||
|
||||
const getLaidOutElements = (nodes, edges) => {
|
||||
const graph = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
|
||||
graph.setGraph({
|
||||
rankdir: 'TB',
|
||||
marginy: 60,
|
||||
ranksep: 64,
|
||||
});
|
||||
edges.forEach((edge) => graph.setEdge(edge.source, edge.target));
|
||||
nodes.forEach((node) => graph.setNode(node.id, node));
|
||||
|
||||
Dagre.layout(graph);
|
||||
|
||||
return {
|
||||
nodes: nodes.map((node) => {
|
||||
const { x, y, width, height } = graph.node(node.id);
|
||||
return {
|
||||
...node,
|
||||
position: { x: x - width / 2, y: y - height / 2 },
|
||||
};
|
||||
}),
|
||||
edges,
|
||||
};
|
||||
};
|
||||
|
||||
export const useAutoLayout = () => {
|
||||
const nodes = useNodes();
|
||||
const prevNodes = usePrevious(nodes);
|
||||
const nodesInitialized = useNodesInitialized();
|
||||
const { getEdges, setNodes, setEdges } = useReactFlow();
|
||||
|
||||
const onLayout = useCallback(
|
||||
(nodes, edges) => {
|
||||
const laidOutElements = getLaidOutElements(nodes, edges);
|
||||
|
||||
setNodes([
|
||||
...laidOutElements.nodes.map((node) => ({
|
||||
...node,
|
||||
data: { ...node.data, laidOut: true },
|
||||
})),
|
||||
]);
|
||||
setEdges([
|
||||
...laidOutElements.edges.map((edge) => ({
|
||||
...edge,
|
||||
data: { ...edge.data, laidOut: true },
|
||||
})),
|
||||
]);
|
||||
},
|
||||
[setEdges, setNodes],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const shouldAutoLayout =
|
||||
nodesInitialized &&
|
||||
!isEqual(
|
||||
nodes.map(({ width, height }) => ({ width, height })),
|
||||
prevNodes.map(({ width, height }) => ({ width, height })),
|
||||
);
|
||||
|
||||
if (shouldAutoLayout) {
|
||||
onLayout(nodes, getEdges());
|
||||
}
|
||||
}, [nodes]);
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useViewport, useReactFlow, useNodes } from 'reactflow';
|
||||
import { useViewport, useReactFlow, useNodes } from '@xyflow/react';
|
||||
|
||||
const scrollYMargin = 100;
|
||||
|
||||
@@ -24,7 +24,7 @@ export const useScrollBoundaries = (containerHeight) => {
|
||||
function updateMaxYScroll() {
|
||||
if (nodes?.length && containerHeight) {
|
||||
const maxY =
|
||||
containerHeight - nodes[nodes.length - 1].y - scrollYMargin;
|
||||
containerHeight - nodes[nodes.length - 1].position.y - scrollYMargin;
|
||||
setMaxYScroll(maxY >= 0 ? 0 : maxY);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { INVISIBLE_NODE_ID, NODE_TYPES } from './constants';
|
||||
|
||||
export const generateEdgeId = (sourceId, targetId) => `${sourceId}-${targetId}`;
|
||||
import Dagre from '@dagrejs/dagre';
|
||||
import { NODE_TYPES } from './constants';
|
||||
|
||||
export const updatedCollapsedNodes = (nodes, openStepId) => {
|
||||
return nodes.map((node) => {
|
||||
@@ -17,72 +16,50 @@ export const updatedCollapsedNodes = (nodes, openStepId) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const generateInitialNodes = (flow) => {
|
||||
const newNodes = flow.steps.map((step, index) => {
|
||||
const collapsed = index !== 0;
|
||||
const edgeLaidOut = (edge, nodes) => {
|
||||
const sourceNode = nodes.find((node) => node.id === edge.source);
|
||||
const targetNodeNode = nodes.find((node) => node.id === edge.target);
|
||||
|
||||
return {
|
||||
id: step.id,
|
||||
type: NODE_TYPES.FLOW_STEP,
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
zIndex: collapsed ? 0 : 1,
|
||||
data: {
|
||||
collapsed,
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
return Boolean(sourceNode?.measured && targetNodeNode?.measured);
|
||||
};
|
||||
|
||||
export const getLaidOutElements = (nodes, edges) => {
|
||||
const graph = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
|
||||
graph.setGraph({
|
||||
rankdir: 'TB',
|
||||
marginy: 60,
|
||||
ranksep: 64,
|
||||
});
|
||||
edges.forEach((edge) => graph.setEdge(edge.source, edge.target));
|
||||
nodes.forEach((node) =>
|
||||
graph.setNode(node.id, {
|
||||
...node,
|
||||
width: node.measured?.width ?? 0,
|
||||
height: node.measured?.height ?? 0,
|
||||
}),
|
||||
);
|
||||
|
||||
return [
|
||||
...newNodes,
|
||||
{
|
||||
id: INVISIBLE_NODE_ID,
|
||||
type: NODE_TYPES.INVISIBLE,
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const generateInitialEdges = (flow) => {
|
||||
const newEdges = flow.steps
|
||||
.map((step, i) => {
|
||||
const sourceId = step.id;
|
||||
const targetId = flow.steps[i + 1]?.id;
|
||||
if (targetId) {
|
||||
return {
|
||||
id: generateEdgeId(sourceId, targetId),
|
||||
source: sourceId,
|
||||
target: targetId,
|
||||
type: 'addNodeEdge',
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((edge) => !!edge);
|
||||
|
||||
const lastStep = flow.steps[flow.steps.length - 1];
|
||||
|
||||
return lastStep
|
||||
? [
|
||||
...newEdges,
|
||||
{
|
||||
id: generateEdgeId(lastStep.id, INVISIBLE_NODE_ID),
|
||||
source: lastStep.id,
|
||||
target: INVISIBLE_NODE_ID,
|
||||
type: 'addNodeEdge',
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
},
|
||||
]
|
||||
: newEdges;
|
||||
Dagre.layout(graph);
|
||||
|
||||
return {
|
||||
nodes: nodes.map((node) => {
|
||||
const position = graph.node(node.id);
|
||||
// We are shifting the dagre node position (anchor=center center) to the top left
|
||||
// so it matches the React Flow node anchor point (top left).
|
||||
const x = position.x - (node.measured?.width ?? 0) / 2;
|
||||
const y = position.y - (node.measured?.height ?? 0) / 2;
|
||||
|
||||
return {
|
||||
...node,
|
||||
position: { x, y },
|
||||
...(node.type === NODE_TYPES.FLOW_STEP
|
||||
? { data: { ...node.data, laidOut: node.measured ? true : false } }
|
||||
: {}),
|
||||
};
|
||||
}),
|
||||
edges: edges.map((edge) => ({
|
||||
...edge,
|
||||
data: { ...edge.data, laidOut: edgeLaidOut(edge, nodes) },
|
||||
})),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,6 +44,8 @@ import useTriggerSubsteps from 'hooks/useTriggerSubsteps';
|
||||
import useActionSubsteps from 'hooks/useActionSubsteps';
|
||||
import useStepWithTestExecutions from 'hooks/useStepWithTestExecutions';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
|
||||
const validIcon = <CheckCircleIcon color="success" />;
|
||||
const errorIcon = <ErrorIcon color="error" />;
|
||||
|
||||
@@ -108,7 +110,7 @@ function generateValidationSchema(substeps) {
|
||||
}
|
||||
|
||||
function FlowStep(props) {
|
||||
const { collapsed, onChange, onContinue, flowId, step } = props;
|
||||
const { collapsed, onChange, onContinue, onDelete, flowId, step } = props;
|
||||
const editorContext = React.useContext(EditorContext);
|
||||
const contextButtonRef = React.useRef(null);
|
||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||
@@ -290,7 +292,11 @@ function FlowStep(props) {
|
||||
</Stack>
|
||||
</Header>
|
||||
|
||||
<Collapse in={!collapsed} unmountOnExit>
|
||||
<Collapse
|
||||
in={!collapsed}
|
||||
unmountOnExit
|
||||
timeout={useNewFlowEditor ? 0 : 'auto'}
|
||||
>
|
||||
<Content>
|
||||
<List>
|
||||
<StepExecutionsProvider value={stepWithTestExecutionsData}>
|
||||
@@ -378,6 +384,7 @@ function FlowStep(props) {
|
||||
stepId={step.id}
|
||||
deletable={!isTrigger}
|
||||
onClose={onContextMenuClose}
|
||||
onDelete={onDelete}
|
||||
anchorEl={anchorEl}
|
||||
flowId={flowId}
|
||||
/>
|
||||
@@ -393,6 +400,7 @@ FlowStep.propTypes = {
|
||||
onClose: PropTypes.func,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onContinue: PropTypes.func,
|
||||
onDelete: PropTypes.func,
|
||||
flowId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
function FlowStepContextMenu(props) {
|
||||
const { stepId, onClose, anchorEl, deletable, flowId } = props;
|
||||
const { stepId, onClose, onDelete, anchorEl, deletable, flowId } = props;
|
||||
const formatMessage = useFormatMessage();
|
||||
const queryClient = useQueryClient();
|
||||
const { mutateAsync: deleteStep } = useDeleteStep();
|
||||
@@ -21,8 +21,9 @@ function FlowStepContextMenu(props) {
|
||||
await deleteStep(stepId);
|
||||
|
||||
await queryClient.invalidateQueries({ queryKey: ['flows', flowId] });
|
||||
onDelete?.(stepId);
|
||||
},
|
||||
[deleteStep, stepId, queryClient, flowId],
|
||||
[deleteStep, onDelete, stepId, queryClient, flowId],
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -44,6 +45,7 @@ function FlowStepContextMenu(props) {
|
||||
FlowStepContextMenu.propTypes = {
|
||||
stepId: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func,
|
||||
anchorEl: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
|
||||
|
||||
@@ -11,6 +11,8 @@ import InputCreator from 'components/InputCreator';
|
||||
import FilterConditions from './FilterConditions';
|
||||
import { StepPropType, SubstepPropType } from 'propTypes/propTypes';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
|
||||
function FlowSubstep(props) {
|
||||
const {
|
||||
substep,
|
||||
@@ -34,7 +36,11 @@ function FlowSubstep(props) {
|
||||
title={name}
|
||||
valid={validationStatus}
|
||||
/>
|
||||
<Collapse in={expanded} timeout="auto" unmountOnExit>
|
||||
<Collapse
|
||||
in={expanded}
|
||||
timeout={useNewFlowEditor ? 0 : 'auto'}
|
||||
unmountOnExit
|
||||
>
|
||||
<ListItem
|
||||
sx={{
|
||||
pt: 2,
|
||||
|
||||
@@ -16,6 +16,8 @@ import FlowSubstepTitle from 'components/FlowSubstepTitle';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { StepPropType, SubstepPropType } from 'propTypes/propTypes';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
|
||||
function TestSubstep(props) {
|
||||
const {
|
||||
substep,
|
||||
@@ -74,7 +76,11 @@ function TestSubstep(props) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<FlowSubstepTitle expanded={expanded} onClick={onToggle} title={name} />
|
||||
<Collapse in={expanded} timeout="auto" unmountOnExit>
|
||||
<Collapse
|
||||
in={expanded}
|
||||
timeout={useNewFlowEditor ? 0 : 'auto'}
|
||||
unmountOnExit
|
||||
>
|
||||
<ListItem
|
||||
sx={{
|
||||
pt: 2,
|
||||
|
||||
@@ -2008,72 +2008,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
|
||||
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
|
||||
|
||||
"@reactflow/background@11.3.14":
|
||||
version "11.3.14"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/background/-/background-11.3.14.tgz#778ca30174f3de77fc321459ab3789e66e71a699"
|
||||
integrity sha512-Gewd7blEVT5Lh6jqrvOgd4G6Qk17eGKQfsDXgyRSqM+CTwDqRldG2LsWN4sNeno6sbqVIC2fZ+rAUBFA9ZEUDA==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/controls@11.2.14":
|
||||
version "11.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/controls/-/controls-11.2.14.tgz#508ed2c40d23341b3b0919dd11e76fd49cf850c7"
|
||||
integrity sha512-MiJp5VldFD7FrqaBNIrQ85dxChrG6ivuZ+dcFhPQUwOK3HfYgX2RHdBua+gx+40p5Vw5It3dVNp/my4Z3jF0dw==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/core@11.11.4":
|
||||
version "11.11.4"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/core/-/core-11.11.4.tgz#89bd86d1862aa1416f3f49926cede7e8c2aab6a7"
|
||||
integrity sha512-H4vODklsjAq3AMq6Np4LE12i1I4Ta9PrDHuBR9GmL8uzTt2l2jh4CiQbEMpvMDcp7xi4be0hgXj+Ysodde/i7Q==
|
||||
dependencies:
|
||||
"@types/d3" "^7.4.0"
|
||||
"@types/d3-drag" "^3.0.1"
|
||||
"@types/d3-selection" "^3.0.3"
|
||||
"@types/d3-zoom" "^3.0.1"
|
||||
classcat "^5.0.3"
|
||||
d3-drag "^3.0.0"
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/minimap@11.7.14":
|
||||
version "11.7.14"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/minimap/-/minimap-11.7.14.tgz#298d7a63cb1da06b2518c99744f716560c88ca73"
|
||||
integrity sha512-mpwLKKrEAofgFJdkhwR5UQ1JYWlcAAL/ZU/bctBkuNTT1yqV+y0buoNVImsRehVYhJwffSWeSHaBR5/GJjlCSQ==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
"@types/d3-selection" "^3.0.3"
|
||||
"@types/d3-zoom" "^3.0.1"
|
||||
classcat "^5.0.3"
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/node-resizer@2.2.14":
|
||||
version "2.2.14"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/node-resizer/-/node-resizer-2.2.14.tgz#1810c0ce51aeb936f179466a6660d1e02c7a77a8"
|
||||
integrity sha512-fwqnks83jUlYr6OHcdFEedumWKChTHRGw/kbCxj0oqBd+ekfs+SIp4ddyNU0pdx96JIm5iNFS0oNrmEiJbbSaA==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
classcat "^5.0.4"
|
||||
d3-drag "^3.0.0"
|
||||
d3-selection "^3.0.0"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/node-toolbar@1.3.14":
|
||||
version "1.3.14"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/node-toolbar/-/node-toolbar-1.3.14.tgz#c6ffc76f82acacdce654f2160dc9852162d6e7c9"
|
||||
integrity sha512-rbynXQnH/xFNu4P9H+hVqlEUafDCkEoCy0Dg9mG22Sg+rY/0ck6KkrAQrYrTgXusd+cEJOMK0uOOFCK2/5rSGQ==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.4"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@remix-run/router@1.21.0":
|
||||
version "1.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.21.0.tgz#c65ae4262bdcfe415dbd4f64ec87676e4a56e2b5"
|
||||
@@ -2421,99 +2355,18 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/d3-array@*":
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5"
|
||||
integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==
|
||||
|
||||
"@types/d3-axis@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.6.tgz#e760e5765b8188b1defa32bc8bb6062f81e4c795"
|
||||
integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-brush@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.6.tgz#c2f4362b045d472e1b186cdbec329ba52bdaee6c"
|
||||
integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-chord@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.6.tgz#1706ca40cf7ea59a0add8f4456efff8f8775793d"
|
||||
integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==
|
||||
|
||||
"@types/d3-color@*":
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2"
|
||||
integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==
|
||||
|
||||
"@types/d3-contour@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.6.tgz#9ada3fa9c4d00e3a5093fed0356c7ab929604231"
|
||||
integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==
|
||||
dependencies:
|
||||
"@types/d3-array" "*"
|
||||
"@types/geojson" "*"
|
||||
|
||||
"@types/d3-delaunay@*":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz#185c1a80cc807fdda2a3fe960f7c11c4a27952e1"
|
||||
integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==
|
||||
|
||||
"@types/d3-dispatch@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7"
|
||||
integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==
|
||||
|
||||
"@types/d3-drag@*", "@types/d3-drag@^3.0.1":
|
||||
"@types/d3-drag@^3.0.7":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02"
|
||||
integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-dsv@*":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17"
|
||||
integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==
|
||||
|
||||
"@types/d3-ease@*":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b"
|
||||
integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==
|
||||
|
||||
"@types/d3-fetch@*":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980"
|
||||
integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==
|
||||
dependencies:
|
||||
"@types/d3-dsv" "*"
|
||||
|
||||
"@types/d3-force@*":
|
||||
version "3.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.10.tgz#6dc8fc6e1f35704f3b057090beeeb7ac674bff1a"
|
||||
integrity sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==
|
||||
|
||||
"@types/d3-format@*":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90"
|
||||
integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==
|
||||
|
||||
"@types/d3-geo@*":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440"
|
||||
integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==
|
||||
dependencies:
|
||||
"@types/geojson" "*"
|
||||
|
||||
"@types/d3-hierarchy@*":
|
||||
version "3.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz#6023fb3b2d463229f2d680f9ac4b47466f71f17b"
|
||||
integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==
|
||||
|
||||
"@types/d3-interpolate@*":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c"
|
||||
@@ -2521,73 +2374,19 @@
|
||||
dependencies:
|
||||
"@types/d3-color" "*"
|
||||
|
||||
"@types/d3-path@*":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a"
|
||||
integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==
|
||||
|
||||
"@types/d3-polygon@*":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz#dfae54a6d35d19e76ac9565bcb32a8e54693189c"
|
||||
integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==
|
||||
|
||||
"@types/d3-quadtree@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f"
|
||||
integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==
|
||||
|
||||
"@types/d3-random@*":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb"
|
||||
integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==
|
||||
|
||||
"@types/d3-scale-chromatic@*":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644"
|
||||
integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==
|
||||
|
||||
"@types/d3-scale@*":
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb"
|
||||
integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==
|
||||
dependencies:
|
||||
"@types/d3-time" "*"
|
||||
|
||||
"@types/d3-selection@*", "@types/d3-selection@^3.0.3":
|
||||
"@types/d3-selection@*", "@types/d3-selection@^3.0.10":
|
||||
version "3.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.11.tgz#bd7a45fc0a8c3167a631675e61bc2ca2b058d4a3"
|
||||
integrity sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==
|
||||
|
||||
"@types/d3-shape@*":
|
||||
version "3.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.6.tgz#65d40d5a548f0a023821773e39012805e6e31a72"
|
||||
integrity sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==
|
||||
dependencies:
|
||||
"@types/d3-path" "*"
|
||||
|
||||
"@types/d3-time-format@*":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz#d6bc1e6b6a7db69cccfbbdd4c34b70632d9e9db2"
|
||||
integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==
|
||||
|
||||
"@types/d3-time@*":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be"
|
||||
integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==
|
||||
|
||||
"@types/d3-timer@*":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70"
|
||||
integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==
|
||||
|
||||
"@types/d3-transition@*":
|
||||
"@types/d3-transition@^3.0.8":
|
||||
version "3.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.9.tgz#1136bc57e9ddb3c390dccc9b5ff3b7d2b8d94706"
|
||||
integrity sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-zoom@*", "@types/d3-zoom@^3.0.1":
|
||||
"@types/d3-zoom@^3.0.8":
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b"
|
||||
integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==
|
||||
@@ -2595,42 +2394,6 @@
|
||||
"@types/d3-interpolate" "*"
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3@^7.4.0":
|
||||
version "7.4.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.3.tgz#d4550a85d08f4978faf0a4c36b848c61eaac07e2"
|
||||
integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==
|
||||
dependencies:
|
||||
"@types/d3-array" "*"
|
||||
"@types/d3-axis" "*"
|
||||
"@types/d3-brush" "*"
|
||||
"@types/d3-chord" "*"
|
||||
"@types/d3-color" "*"
|
||||
"@types/d3-contour" "*"
|
||||
"@types/d3-delaunay" "*"
|
||||
"@types/d3-dispatch" "*"
|
||||
"@types/d3-drag" "*"
|
||||
"@types/d3-dsv" "*"
|
||||
"@types/d3-ease" "*"
|
||||
"@types/d3-fetch" "*"
|
||||
"@types/d3-force" "*"
|
||||
"@types/d3-format" "*"
|
||||
"@types/d3-geo" "*"
|
||||
"@types/d3-hierarchy" "*"
|
||||
"@types/d3-interpolate" "*"
|
||||
"@types/d3-path" "*"
|
||||
"@types/d3-polygon" "*"
|
||||
"@types/d3-quadtree" "*"
|
||||
"@types/d3-random" "*"
|
||||
"@types/d3-scale" "*"
|
||||
"@types/d3-scale-chromatic" "*"
|
||||
"@types/d3-selection" "*"
|
||||
"@types/d3-shape" "*"
|
||||
"@types/d3-time" "*"
|
||||
"@types/d3-time-format" "*"
|
||||
"@types/d3-timer" "*"
|
||||
"@types/d3-transition" "*"
|
||||
"@types/d3-zoom" "*"
|
||||
|
||||
"@types/eslint-scope@^3.7.7":
|
||||
version "3.7.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5"
|
||||
@@ -2705,11 +2468,6 @@
|
||||
"@types/qs" "*"
|
||||
"@types/serve-static" "*"
|
||||
|
||||
"@types/geojson@*":
|
||||
version "7946.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613"
|
||||
integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==
|
||||
|
||||
"@types/graceful-fs@^4.1.2":
|
||||
version "4.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4"
|
||||
@@ -3251,6 +3009,28 @@
|
||||
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
|
||||
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
|
||||
|
||||
"@xyflow/react@^12.4.4":
|
||||
version "12.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@xyflow/react/-/react-12.4.4.tgz#3f1042fba8b3d6cb64cc76e3e1d1b7dd69a34448"
|
||||
integrity sha512-9RZ9dgKZNJOlbrXXST5HPb5TcXPOIDGondjwcjDro44OQRPl1E0ZRPTeWPGaQtVjbg4WpR4BUYwOeshNI2TuVg==
|
||||
dependencies:
|
||||
"@xyflow/system" "0.0.52"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.0"
|
||||
|
||||
"@xyflow/system@0.0.52":
|
||||
version "0.0.52"
|
||||
resolved "https://registry.yarnpkg.com/@xyflow/system/-/system-0.0.52.tgz#450ee5c62f5d7ac961ba4d14726737094ce07abf"
|
||||
integrity sha512-pJBMaoh/GEebIABWEIxAai0yf57dm+kH7J/Br+LnLFPuJL87Fhcmm4KFWd/bCUy/kCWUg+2/yFAGY0AUHRPOnQ==
|
||||
dependencies:
|
||||
"@types/d3-drag" "^3.0.7"
|
||||
"@types/d3-selection" "^3.0.10"
|
||||
"@types/d3-transition" "^3.0.8"
|
||||
"@types/d3-zoom" "^3.0.8"
|
||||
d3-drag "^3.0.0"
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
|
||||
abab@^2.0.3, abab@^2.0.5:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
|
||||
@@ -4019,7 +3799,7 @@ cjs-module-lexer@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170"
|
||||
integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==
|
||||
|
||||
classcat@^5.0.3, classcat@^5.0.4:
|
||||
classcat@^5.0.3:
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/classcat/-/classcat-5.0.5.tgz#8c209f359a93ac302404a10161b501eba9c09c77"
|
||||
integrity sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==
|
||||
@@ -9055,18 +8835,6 @@ react@^18.2.0:
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
reactflow@^11.11.2:
|
||||
version "11.11.4"
|
||||
resolved "https://registry.yarnpkg.com/reactflow/-/reactflow-11.11.4.tgz#e3593e313420542caed81aecbd73fb9bc6576653"
|
||||
integrity sha512-70FOtJkUWH3BAOsN+LU9lCrKoKbtOPnz2uq0CV2PLdNSwxTXOhCbsZr50GmZ+Rtw3jx8Uv7/vBFtCGixLfd4Og==
|
||||
dependencies:
|
||||
"@reactflow/background" "11.3.14"
|
||||
"@reactflow/controls" "11.2.14"
|
||||
"@reactflow/core" "11.11.4"
|
||||
"@reactflow/minimap" "11.7.14"
|
||||
"@reactflow/node-resizer" "2.2.14"
|
||||
"@reactflow/node-toolbar" "1.3.14"
|
||||
|
||||
read-cache@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
|
||||
@@ -10471,10 +10239,10 @@ url-parse@^1.5.3:
|
||||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
use-sync-external-store@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9"
|
||||
integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==
|
||||
use-sync-external-store@^1.2.2:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc"
|
||||
integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
@@ -11091,9 +10859,9 @@ yup@^0.32.11:
|
||||
property-expr "^2.0.4"
|
||||
toposort "^2.0.2"
|
||||
|
||||
zustand@^4.4.1:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.5.tgz#f8c713041543715ec81a2adda0610e1dc82d4ad1"
|
||||
integrity sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==
|
||||
zustand@^4.4.0:
|
||||
version "4.5.6"
|
||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.6.tgz#6857d52af44874a79fb3408c9473f78367255c96"
|
||||
integrity sha512-ibr/n1hBzLLj5Y+yUcU7dYw8p6WnIVzdJbnX+1YpaScvZVF2ziugqHs+LAmHw4lWO9c/zRj+K1ncgWDQuthEdQ==
|
||||
dependencies:
|
||||
use-sync-external-store "1.2.2"
|
||||
use-sync-external-store "^1.2.2"
|
||||
|
||||
Reference in New Issue
Block a user