refactor: Optimize GenericNode and other nearby components to improve performance especially on larger flows (#8053)
* Improve render preformance for nodes * update component optimization * [autofix.ci] apply automated fixes * shard increase * nodeoutput check * restore --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com>
This commit is contained in:
parent
fe9aa9ecb3
commit
4b580d1569
8 changed files with 245 additions and 243 deletions
|
|
@ -9,6 +9,7 @@ import {
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import { cn } from "@/utils/utils";
|
import { cn } from "@/utils/utils";
|
||||||
import { useEffect, useMemo, useRef } from "react";
|
import { useEffect, useMemo, useRef } from "react";
|
||||||
|
import { useShallow } from "zustand/react/shallow";
|
||||||
import { default as IconComponent } from "../../../../components/common/genericIconComponent";
|
import { default as IconComponent } from "../../../../components/common/genericIconComponent";
|
||||||
import ShadTooltip from "../../../../components/common/shadTooltipComponent";
|
import ShadTooltip from "../../../../components/common/shadTooltipComponent";
|
||||||
import {
|
import {
|
||||||
|
|
@ -20,7 +21,6 @@ import {
|
||||||
import useFlowStore from "../../../../stores/flowStore";
|
import useFlowStore from "../../../../stores/flowStore";
|
||||||
import { useTypesStore } from "../../../../stores/typesStore";
|
import { useTypesStore } from "../../../../stores/typesStore";
|
||||||
import { NodeInputFieldComponentType } from "../../../../types/components";
|
import { NodeInputFieldComponentType } from "../../../../types/components";
|
||||||
import { scapedJSONStringfy } from "../../../../utils/reactflowUtils";
|
|
||||||
import useFetchDataOnMount from "../../../hooks/use-fetch-data-on-mount";
|
import useFetchDataOnMount from "../../../hooks/use-fetch-data-on-mount";
|
||||||
import useHandleOnNewValue from "../../../hooks/use-handle-new-value";
|
import useHandleOnNewValue from "../../../hooks/use-handle-new-value";
|
||||||
import NodeInputInfo from "../NodeInputInfo";
|
import NodeInputInfo from "../NodeInputInfo";
|
||||||
|
|
@ -44,10 +44,13 @@ export default function NodeInputField({
|
||||||
isToolMode = false,
|
isToolMode = false,
|
||||||
}: NodeInputFieldComponentType): JSX.Element {
|
}: NodeInputFieldComponentType): JSX.Element {
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const nodes = useFlowStore((state) => state.nodes);
|
|
||||||
const edges = useFlowStore((state) => state.edges);
|
|
||||||
const isAuth = useAuthStore((state) => state.isAuthenticated);
|
const isAuth = useAuthStore((state) => state.isAuthenticated);
|
||||||
const currentFlow = useFlowStore((state) => state.currentFlow);
|
const { currentFlowId, currentFlowName } = useFlowStore(
|
||||||
|
useShallow((state) => ({
|
||||||
|
currentFlowId: state.currentFlow?.id,
|
||||||
|
currentFlowName: state.currentFlow?.name,
|
||||||
|
})),
|
||||||
|
);
|
||||||
const myData = useTypesStore((state) => state.data);
|
const myData = useTypesStore((state) => state.data);
|
||||||
const postTemplateValue = usePostTemplateValue({
|
const postTemplateValue = usePostTemplateValue({
|
||||||
node: data.node!,
|
node: data.node!,
|
||||||
|
|
@ -56,11 +59,6 @@ export default function NodeInputField({
|
||||||
});
|
});
|
||||||
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
||||||
const { handleNodeClass } = useHandleNodeClass(data.id);
|
const { handleNodeClass } = useHandleNodeClass(data.id);
|
||||||
let disabled =
|
|
||||||
edges.some(
|
|
||||||
(edge) =>
|
|
||||||
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
|
|
||||||
) || isToolMode;
|
|
||||||
|
|
||||||
const { handleOnNewValue } = useHandleOnNewValue({
|
const { handleOnNewValue } = useHandleOnNewValue({
|
||||||
node: data.node!,
|
node: data.node!,
|
||||||
|
|
@ -74,9 +72,9 @@ export default function NodeInputField({
|
||||||
|
|
||||||
const nodeInformationMetadata: NodeInfoType = useMemo(() => {
|
const nodeInformationMetadata: NodeInfoType = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
flowId: currentFlow?.id ?? "",
|
flowId: currentFlowId ?? "",
|
||||||
nodeType: data?.type?.toLowerCase() ?? "",
|
nodeType: data?.type?.toLowerCase() ?? "",
|
||||||
flowName: currentFlow?.name ?? "",
|
flowName: currentFlowName ?? "",
|
||||||
isAuth,
|
isAuth,
|
||||||
variableName: name,
|
variableName: name,
|
||||||
};
|
};
|
||||||
|
|
@ -107,12 +105,10 @@ export default function NodeInputField({
|
||||||
const Handle = (
|
const Handle = (
|
||||||
<HandleRenderComponent
|
<HandleRenderComponent
|
||||||
left={true}
|
left={true}
|
||||||
nodes={nodes}
|
|
||||||
tooltipTitle={tooltipTitle}
|
tooltipTitle={tooltipTitle}
|
||||||
proxy={proxy}
|
proxy={proxy}
|
||||||
id={id}
|
id={id}
|
||||||
title={title}
|
title={title}
|
||||||
edges={edges}
|
|
||||||
myData={myData}
|
myData={myData}
|
||||||
colors={colors}
|
colors={colors}
|
||||||
setFilterEdge={setFilterEdge}
|
setFilterEdge={setFilterEdge}
|
||||||
|
|
@ -207,12 +203,12 @@ export default function NodeInputField({
|
||||||
handleOnNewValue={handleOnNewValue}
|
handleOnNewValue={handleOnNewValue}
|
||||||
name={name}
|
name={name}
|
||||||
nodeId={data.id}
|
nodeId={data.id}
|
||||||
|
inputId={id}
|
||||||
templateData={data.node?.template[name]!}
|
templateData={data.node?.template[name]!}
|
||||||
templateValue={data.node?.template[name].value ?? ""}
|
templateValue={data.node?.template[name].value ?? ""}
|
||||||
editNode={false}
|
editNode={false}
|
||||||
handleNodeClass={handleNodeClass}
|
handleNodeClass={handleNodeClass}
|
||||||
nodeClass={data.node!}
|
nodeClass={data.node!}
|
||||||
disabled={disabled}
|
|
||||||
placeholder={
|
placeholder={
|
||||||
isToolMode
|
isToolMode
|
||||||
? DEFAULT_TOOLSET_PLACEHOLDER
|
? DEFAULT_TOOLSET_PLACEHOLDER
|
||||||
|
|
@ -220,6 +216,7 @@ export default function NodeInputField({
|
||||||
}
|
}
|
||||||
isToolMode={isToolMode}
|
isToolMode={isToolMode}
|
||||||
nodeInformationMetadata={nodeInformationMetadata}
|
nodeInformationMetadata={nodeInformationMetadata}
|
||||||
|
proxy={proxy}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// NodeOutputs.tsx
|
||||||
|
import { OutputParameter } from ".";
|
||||||
|
|
||||||
|
export default function NodeOutputs({
|
||||||
|
outputs,
|
||||||
|
keyPrefix,
|
||||||
|
data,
|
||||||
|
types,
|
||||||
|
selected,
|
||||||
|
showNode,
|
||||||
|
isToolMode,
|
||||||
|
showHiddenOutputs,
|
||||||
|
}) {
|
||||||
|
if (!outputs?.length) return null;
|
||||||
|
|
||||||
|
return outputs?.map((output, idx) => (
|
||||||
|
<OutputParameter
|
||||||
|
key={`${keyPrefix}-${output.name}-${idx}`}
|
||||||
|
output={output}
|
||||||
|
idx={
|
||||||
|
data.node!.outputs?.findIndex((out) => out.name === output.name) ?? idx
|
||||||
|
}
|
||||||
|
lastOutput={idx === outputs.length - 1}
|
||||||
|
data={data}
|
||||||
|
types={types}
|
||||||
|
selected={selected}
|
||||||
|
showNode={showNode}
|
||||||
|
isToolMode={isToolMode}
|
||||||
|
showHiddenOutputs={showHiddenOutputs}
|
||||||
|
hidden={
|
||||||
|
keyPrefix === "hidden"
|
||||||
|
? showHiddenOutputs
|
||||||
|
? output.hidden
|
||||||
|
: true
|
||||||
|
: false
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
@ -177,7 +177,6 @@ function NodeOutputField({
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
|
|
||||||
// Use selective store subscriptions
|
// Use selective store subscriptions
|
||||||
const nodes = useFlowStore((state) => state.nodes);
|
|
||||||
const edges = useFlowStore((state) => state.edges);
|
const edges = useFlowStore((state) => state.edges);
|
||||||
const setNode = useFlowStore((state) => state.setNode);
|
const setNode = useFlowStore((state) => state.setNode);
|
||||||
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
||||||
|
|
@ -316,11 +315,9 @@ function NodeOutputField({
|
||||||
return (
|
return (
|
||||||
<HandleRenderComponent
|
<HandleRenderComponent
|
||||||
left={true}
|
left={true}
|
||||||
nodes={nodes}
|
|
||||||
tooltipTitle={tooltipTitle}
|
tooltipTitle={tooltipTitle}
|
||||||
id={id}
|
id={id}
|
||||||
title={title}
|
title={title}
|
||||||
edges={edges}
|
|
||||||
nodeId={data.id}
|
nodeId={data.id}
|
||||||
myData={myData}
|
myData={myData}
|
||||||
colors={colors}
|
colors={colors}
|
||||||
|
|
@ -332,11 +329,9 @@ function NodeOutputField({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
nodes,
|
|
||||||
tooltipTitle,
|
tooltipTitle,
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
edges,
|
|
||||||
data.id,
|
data.id,
|
||||||
myData,
|
myData,
|
||||||
colors,
|
colors,
|
||||||
|
|
@ -350,11 +345,9 @@ function NodeOutputField({
|
||||||
() => (
|
() => (
|
||||||
<HandleRenderComponent
|
<HandleRenderComponent
|
||||||
left={false}
|
left={false}
|
||||||
nodes={nodes}
|
|
||||||
tooltipTitle={tooltipTitle}
|
tooltipTitle={tooltipTitle}
|
||||||
id={id}
|
id={id}
|
||||||
title={title}
|
title={title}
|
||||||
edges={edges}
|
|
||||||
nodeId={data.id}
|
nodeId={data.id}
|
||||||
myData={myData}
|
myData={myData}
|
||||||
colors={colors}
|
colors={colors}
|
||||||
|
|
@ -365,11 +358,9 @@ function NodeOutputField({
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
nodes,
|
|
||||||
tooltipTitle,
|
tooltipTitle,
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
edges,
|
|
||||||
data.id,
|
data.id,
|
||||||
myData,
|
myData,
|
||||||
colors,
|
colors,
|
||||||
|
|
|
||||||
|
|
@ -151,12 +151,10 @@ const HandleContent = memo(function HandleContent({
|
||||||
|
|
||||||
const HandleRenderComponent = memo(function HandleRenderComponent({
|
const HandleRenderComponent = memo(function HandleRenderComponent({
|
||||||
left,
|
left,
|
||||||
nodes,
|
|
||||||
tooltipTitle = "",
|
tooltipTitle = "",
|
||||||
proxy,
|
proxy,
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
edges,
|
|
||||||
myData,
|
myData,
|
||||||
colors,
|
colors,
|
||||||
setFilterEdge,
|
setFilterEdge,
|
||||||
|
|
@ -166,12 +164,10 @@ const HandleRenderComponent = memo(function HandleRenderComponent({
|
||||||
colorName,
|
colorName,
|
||||||
}: {
|
}: {
|
||||||
left: boolean;
|
left: boolean;
|
||||||
nodes: any;
|
|
||||||
tooltipTitle?: string;
|
tooltipTitle?: string;
|
||||||
proxy?: any;
|
proxy?: any;
|
||||||
id: any;
|
id: any;
|
||||||
title: string;
|
title: string;
|
||||||
edges: any;
|
|
||||||
myData: any;
|
myData: any;
|
||||||
colors: string[];
|
colors: string[];
|
||||||
setFilterEdge: (edges: any) => void;
|
setFilterEdge: (edges: any) => void;
|
||||||
|
|
@ -209,20 +205,17 @@ const HandleRenderComponent = memo(function HandleRenderComponent({
|
||||||
[id, proxy],
|
[id, proxy],
|
||||||
);
|
);
|
||||||
|
|
||||||
const getConnection = useCallback(
|
const getConnection = (semiConnection: {
|
||||||
(semiConnection: {
|
source?: string;
|
||||||
source?: string;
|
sourceHandle?: string;
|
||||||
sourceHandle?: string;
|
target?: string;
|
||||||
target?: string;
|
targetHandle?: string;
|
||||||
targetHandle?: string;
|
}) => ({
|
||||||
}) => ({
|
source: semiConnection.source ?? nodeId,
|
||||||
source: semiConnection.source ?? nodeId,
|
sourceHandle: semiConnection.sourceHandle ?? myId,
|
||||||
sourceHandle: semiConnection.sourceHandle ?? myId,
|
target: semiConnection.target ?? nodeId,
|
||||||
target: semiConnection.target ?? nodeId,
|
targetHandle: semiConnection.targetHandle ?? myId,
|
||||||
targetHandle: semiConnection.targetHandle ?? myId,
|
});
|
||||||
}),
|
|
||||||
[nodeId, myId],
|
|
||||||
);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
sameNode,
|
sameNode,
|
||||||
|
|
@ -255,25 +248,26 @@ const HandleRenderComponent = memo(function HandleRenderComponent({
|
||||||
handleDragging &&
|
handleDragging &&
|
||||||
(left ? handleDragging.source : handleDragging.target) &&
|
(left ? handleDragging.source : handleDragging.target) &&
|
||||||
!ownDraggingHandle
|
!ownDraggingHandle
|
||||||
? isValidConnection(getConnection(handleDragging), nodes, edges)
|
? isValidConnection(getConnection(handleDragging))
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
const filterOpenHandle =
|
const filterOpenHandle =
|
||||||
filterType &&
|
filterType &&
|
||||||
(left ? filterType.source : filterType.target) &&
|
(left ? filterType.source : filterType.target) &&
|
||||||
!ownFilterHandle
|
!ownFilterHandle
|
||||||
? isValidConnection(getConnection(filterType), nodes, edges)
|
? isValidConnection(getConnection(filterType))
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
const openHandle = filterOpenHandle || draggingOpenHandle;
|
const openHandle = filterOpenHandle || draggingOpenHandle;
|
||||||
const filterPresent = handleDragging || filterType;
|
const filterPresent = handleDragging || filterType;
|
||||||
|
|
||||||
const connectedEdge = edges.find(
|
const connectedEdge = useFlowStore
|
||||||
(edge) => edge.target === nodeId && edge.targetHandle === myId,
|
.getState()
|
||||||
);
|
.edges.find(
|
||||||
const connectedColor =
|
(edge) => edge.target === nodeId && edge.targetHandle === myId,
|
||||||
nodeColorsName[connectedEdge?.data?.sourceHandle?.output_types[0]] ||
|
);
|
||||||
"gray";
|
const outputType = connectedEdge?.data?.sourceHandle?.output_types?.[0];
|
||||||
|
const connectedColor = outputType ? nodeColorsName[outputType] : "gray";
|
||||||
|
|
||||||
const isNullHandle =
|
const isNullHandle =
|
||||||
filterPresent && !(openHandle || ownDraggingHandle || ownFilterHandle);
|
filterPresent && !(openHandle || ownDraggingHandle || ownFilterHandle);
|
||||||
|
|
@ -341,9 +335,6 @@ const HandleRenderComponent = memo(function HandleRenderComponent({
|
||||||
filterType,
|
filterType,
|
||||||
nodeId,
|
nodeId,
|
||||||
myId,
|
myId,
|
||||||
nodes,
|
|
||||||
edges,
|
|
||||||
getConnection,
|
|
||||||
dark,
|
dark,
|
||||||
colors,
|
colors,
|
||||||
colorName,
|
colorName,
|
||||||
|
|
@ -365,6 +356,7 @@ const HandleRenderComponent = memo(function HandleRenderComponent({
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
|
const nodes = useFlowStore.getState().nodes;
|
||||||
setFilterEdge(groupByFamily(myData, tooltipTitle!, left, nodes!));
|
setFilterEdge(groupByFamily(myData, tooltipTitle!, left, nodes!));
|
||||||
setFilterType(currentFilter);
|
setFilterType(currentFilter);
|
||||||
if (filterOpenHandle && filterType) {
|
if (filterOpenHandle && filterType) {
|
||||||
|
|
@ -376,14 +368,12 @@ const HandleRenderComponent = memo(function HandleRenderComponent({
|
||||||
myData,
|
myData,
|
||||||
tooltipTitle,
|
tooltipTitle,
|
||||||
left,
|
left,
|
||||||
nodes,
|
|
||||||
setFilterEdge,
|
setFilterEdge,
|
||||||
setFilterType,
|
setFilterType,
|
||||||
currentFilter,
|
currentFilter,
|
||||||
filterOpenHandle,
|
filterOpenHandle,
|
||||||
filterType,
|
filterType,
|
||||||
onConnect,
|
onConnect,
|
||||||
getConnection,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const handleMouseEnter = useCallback(() => setIsHovered(true), []);
|
const handleMouseEnter = useCallback(() => setIsHovered(true), []);
|
||||||
|
|
@ -396,8 +386,8 @@ const HandleRenderComponent = memo(function HandleRenderComponent({
|
||||||
|
|
||||||
// Memoize the validation function
|
// Memoize the validation function
|
||||||
const validateConnection = useCallback(
|
const validateConnection = useCallback(
|
||||||
(connection: any) => isValidConnection(connection, nodes, edges),
|
(connection: any) => isValidConnection(connection),
|
||||||
[nodes, edges],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -424,7 +414,7 @@ const HandleRenderComponent = memo(function HandleRenderComponent({
|
||||||
position={left ? Position.Left : Position.Right}
|
position={left ? Position.Left : Position.Right}
|
||||||
id={myId}
|
id={myId}
|
||||||
isValidConnection={(connection) =>
|
isValidConnection={(connection) =>
|
||||||
isValidConnection(connection as Connection, nodes, edges)
|
isValidConnection(connection as Connection)
|
||||||
}
|
}
|
||||||
className={cn(
|
className={cn(
|
||||||
`group/handle z-50 transition-all`,
|
`group/handle z-50 transition-all`,
|
||||||
|
|
|
||||||
|
|
@ -24,25 +24,24 @@ import { useShortcutsStore } from "../../stores/shortcuts";
|
||||||
import { useTypesStore } from "../../stores/typesStore";
|
import { useTypesStore } from "../../stores/typesStore";
|
||||||
import { VertexBuildTypeAPI } from "../../types/api";
|
import { VertexBuildTypeAPI } from "../../types/api";
|
||||||
import { NodeDataType } from "../../types/flow";
|
import { NodeDataType } from "../../types/flow";
|
||||||
import { checkHasToolMode } from "../../utils/reactflowUtils";
|
|
||||||
import { classNames, cn } from "../../utils/utils";
|
import { classNames, cn } from "../../utils/utils";
|
||||||
import { processNodeAdvancedFields } from "../helpers/process-node-advanced-fields";
|
import { processNodeAdvancedFields } from "../helpers/process-node-advanced-fields";
|
||||||
import useUpdateNodeCode from "../hooks/use-update-node-code";
|
import useUpdateNodeCode from "../hooks/use-update-node-code";
|
||||||
import NodeDescription from "./components/NodeDescription";
|
import NodeDescription from "./components/NodeDescription";
|
||||||
import NodeName from "./components/NodeName";
|
import NodeName from "./components/NodeName";
|
||||||
import { OutputParameter } from "./components/NodeOutputParameter";
|
import NodeOutputs from "./components/NodeOutputParameter/NodeOutputs";
|
||||||
import NodeStatus from "./components/NodeStatus";
|
import NodeStatus from "./components/NodeStatus";
|
||||||
import NodeUpdateComponent from "./components/NodeUpdateComponent";
|
import NodeUpdateComponent from "./components/NodeUpdateComponent";
|
||||||
import RenderInputParameters from "./components/RenderInputParameters";
|
import RenderInputParameters from "./components/RenderInputParameters";
|
||||||
import { NodeIcon } from "./components/nodeIcon";
|
import { NodeIcon } from "./components/nodeIcon";
|
||||||
import { useBuildStatus } from "./hooks/use-get-build-status";
|
import { useBuildStatus } from "./hooks/use-get-build-status";
|
||||||
|
|
||||||
const MemoizedOutputParameter = memo(OutputParameter);
|
|
||||||
const MemoizedRenderInputParameters = memo(RenderInputParameters);
|
const MemoizedRenderInputParameters = memo(RenderInputParameters);
|
||||||
const MemoizedNodeIcon = memo(NodeIcon);
|
const MemoizedNodeIcon = memo(NodeIcon);
|
||||||
const MemoizedNodeName = memo(NodeName);
|
const MemoizedNodeName = memo(NodeName);
|
||||||
const MemoizedNodeStatus = memo(CustomNodeStatus);
|
const MemoizedNodeStatus = memo(CustomNodeStatus);
|
||||||
const MemoizedNodeDescription = memo(NodeDescription);
|
const MemoizedNodeDescription = memo(NodeDescription);
|
||||||
|
const MemoizedNodeOutputs = memo(NodeOutputs);
|
||||||
|
|
||||||
const HiddenOutputsButton = memo(
|
const HiddenOutputsButton = memo(
|
||||||
({
|
({
|
||||||
|
|
@ -104,10 +103,10 @@ function GenericNode({
|
||||||
|
|
||||||
const showNode = data.showNode ?? true;
|
const showNode = data.showNode ?? true;
|
||||||
|
|
||||||
const getValidationStatus = (data) => {
|
const getValidationStatus = useCallback((data) => {
|
||||||
setValidationStatus(data);
|
setValidationStatus(data);
|
||||||
return null;
|
return null;
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const { mutate: validateComponentCode } = usePostValidateComponentCode();
|
const { mutate: validateComponentCode } = usePostValidateComponentCode();
|
||||||
|
|
||||||
|
|
@ -246,45 +245,18 @@ function GenericNode({
|
||||||
callback: toggleEditNameDescription,
|
callback: toggleEditNameDescription,
|
||||||
});
|
});
|
||||||
|
|
||||||
const renderOutputs = useCallback(
|
const { shownOutputs, hiddenOutputs } = useMemo(() => {
|
||||||
(outputs, key?: string) => {
|
const shownOutputs: typeof data.node.outputs = [];
|
||||||
return outputs?.map((output, idx) => (
|
const hiddenOutputs: typeof data.node.outputs = [];
|
||||||
<MemoizedOutputParameter
|
(data.node?.outputs ?? []).forEach((output) => {
|
||||||
key={`${key}-${output.name}-${idx}`}
|
if (output.hidden) {
|
||||||
output={output}
|
hiddenOutputs.push(output);
|
||||||
idx={
|
} else {
|
||||||
data.node!.outputs?.findIndex((out) => out.name === output.name) ??
|
shownOutputs.push(output);
|
||||||
idx
|
}
|
||||||
}
|
});
|
||||||
lastOutput={idx === outputs.length - 1}
|
return { shownOutputs, hiddenOutputs };
|
||||||
data={data}
|
}, [data.node?.outputs]);
|
||||||
types={types}
|
|
||||||
selected={selected}
|
|
||||||
showNode={showNode}
|
|
||||||
isToolMode={isToolMode}
|
|
||||||
showHiddenOutputs={showHiddenOutputs}
|
|
||||||
hidden={
|
|
||||||
key === "hidden"
|
|
||||||
? showHiddenOutputs
|
|
||||||
? output.hidden
|
|
||||||
: true
|
|
||||||
: false
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
},
|
|
||||||
[data, types, selected, showNode, isToolMode, showHiddenOutputs],
|
|
||||||
);
|
|
||||||
|
|
||||||
const { shownOutputs, hiddenOutputs } = useMemo(
|
|
||||||
() => ({
|
|
||||||
shownOutputs:
|
|
||||||
data.node?.outputs?.filter((output) => !output.hidden) ?? [],
|
|
||||||
hiddenOutputs:
|
|
||||||
data.node?.outputs?.filter((output) => output.hidden) ?? [],
|
|
||||||
}),
|
|
||||||
[data.node?.outputs],
|
|
||||||
);
|
|
||||||
|
|
||||||
const [hasChangedNodeDescription, setHasChangedNodeDescription] =
|
const [hasChangedNodeDescription, setHasChangedNodeDescription] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
|
@ -391,114 +363,26 @@ function GenericNode({
|
||||||
toggleEditNameDescription,
|
toggleEditNameDescription,
|
||||||
selectedNodesCount,
|
selectedNodesCount,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hiddenOutputs && hiddenOutputs.length === 0) {
|
if (hiddenOutputs && hiddenOutputs.length === 0) {
|
||||||
setShowHiddenOutputs(false);
|
setShowHiddenOutputs(false);
|
||||||
}
|
}
|
||||||
}, [hiddenOutputs]);
|
}, [hiddenOutputs]);
|
||||||
|
|
||||||
const renderNodeIcon = useCallback(() => {
|
const handleToggleHiddenOutputs = useCallback(
|
||||||
return (
|
() => setShowHiddenOutputs((prev) => !prev),
|
||||||
<MemoizedNodeIcon
|
[],
|
||||||
dataType={data.type}
|
);
|
||||||
showNode={showNode}
|
|
||||||
icon={data.node?.icon}
|
|
||||||
isGroup={!!data.node?.flow}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}, [data.type, showNode, data.node?.icon, data.node?.flow]);
|
|
||||||
|
|
||||||
const renderNodeName = useCallback(() => {
|
const memoizedOnUpdateNode = useCallback(
|
||||||
return (
|
() => handleUpdateCode(true),
|
||||||
<MemoizedNodeName
|
[handleUpdateCode],
|
||||||
display_name={data.node?.display_name}
|
);
|
||||||
nodeId={data.id}
|
const memoizedSetDismissAll = useCallback(
|
||||||
selected={selected}
|
() => addDismissedNodes([data.id]),
|
||||||
showNode={showNode}
|
[addDismissedNodes, data.id],
|
||||||
validationStatus={validationStatus}
|
);
|
||||||
isOutdated={isOutdated}
|
|
||||||
beta={data.node?.beta || false}
|
|
||||||
editNameDescription={editNameDescription}
|
|
||||||
toggleEditNameDescription={toggleEditNameDescription}
|
|
||||||
setHasChangedNodeDescription={setHasChangedNodeDescription}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}, [
|
|
||||||
data.node?.display_name,
|
|
||||||
data.id,
|
|
||||||
selected,
|
|
||||||
showNode,
|
|
||||||
validationStatus,
|
|
||||||
isOutdated,
|
|
||||||
data.node?.beta,
|
|
||||||
editNameDescription,
|
|
||||||
toggleEditNameDescription,
|
|
||||||
setHasChangedNodeDescription,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const renderNodeStatus = useCallback(() => {
|
|
||||||
return (
|
|
||||||
<MemoizedNodeStatus
|
|
||||||
data={data}
|
|
||||||
frozen={data.node?.frozen}
|
|
||||||
showNode={showNode}
|
|
||||||
display_name={data.node?.display_name!}
|
|
||||||
nodeId={data.id}
|
|
||||||
selected={selected}
|
|
||||||
setBorderColor={setBorderColor}
|
|
||||||
buildStatus={buildStatus}
|
|
||||||
dismissAll={dismissAll}
|
|
||||||
isOutdated={isOutdated}
|
|
||||||
isUserEdited={isUserEdited}
|
|
||||||
isBreakingChange={hasBreakingChange}
|
|
||||||
getValidationStatus={getValidationStatus}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}, [
|
|
||||||
data,
|
|
||||||
showNode,
|
|
||||||
selected,
|
|
||||||
buildStatus,
|
|
||||||
isOutdated,
|
|
||||||
isUserEdited,
|
|
||||||
getValidationStatus,
|
|
||||||
dismissAll,
|
|
||||||
handleUpdateCode,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const renderDescription = useCallback(() => {
|
|
||||||
return (
|
|
||||||
<MemoizedNodeDescription
|
|
||||||
description={data.node?.description}
|
|
||||||
mdClassName={"dark:prose-invert"}
|
|
||||||
nodeId={data.id}
|
|
||||||
selected={selected}
|
|
||||||
editNameDescription={editNameDescription}
|
|
||||||
setEditNameDescription={set}
|
|
||||||
setHasChangedNodeDescription={setHasChangedNodeDescription}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}, [
|
|
||||||
data.node?.description,
|
|
||||||
data.id,
|
|
||||||
selected,
|
|
||||||
editNameDescription,
|
|
||||||
toggleEditNameDescription,
|
|
||||||
setHasChangedNodeDescription,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const renderInputParameters = useCallback(() => {
|
|
||||||
return (
|
|
||||||
<MemoizedRenderInputParameters
|
|
||||||
data={data}
|
|
||||||
types={types}
|
|
||||||
isToolMode={isToolMode}
|
|
||||||
showNode={showNode}
|
|
||||||
shownOutputs={shownOutputs}
|
|
||||||
showHiddenOutputs={showHiddenOutputs}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}, [data, types, isToolMode, showNode, shownOutputs, showHiddenOutputs]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn(shouldShowUpdateComponent ? "relative -mt-10" : "")}>
|
<div className={cn(shouldShowUpdateComponent ? "relative -mt-10" : "")}>
|
||||||
|
|
@ -510,20 +394,22 @@ function GenericNode({
|
||||||
!hasOutputs && "pb-4",
|
!hasOutputs && "pb-4",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<UpdateComponentModal
|
{openUpdateModal && (
|
||||||
open={openUpdateModal}
|
<UpdateComponentModal
|
||||||
setOpen={setOpenUpdateModal}
|
open={openUpdateModal}
|
||||||
onUpdateNode={() => handleUpdateCode(true)}
|
setOpen={setOpenUpdateModal}
|
||||||
components={componentUpdate ? [componentUpdate] : []}
|
onUpdateNode={memoizedOnUpdateNode}
|
||||||
/>
|
components={componentUpdate ? [componentUpdate] : []}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{memoizedNodeToolbarComponent}
|
{memoizedNodeToolbarComponent}
|
||||||
{shouldShowUpdateComponent && (
|
{shouldShowUpdateComponent && (
|
||||||
<NodeUpdateComponent
|
<NodeUpdateComponent
|
||||||
hasBreakingChange={hasBreakingChange}
|
hasBreakingChange={hasBreakingChange}
|
||||||
showNode={showNode}
|
showNode={showNode}
|
||||||
handleUpdateCode={() => handleUpdateCode()}
|
handleUpdateCode={handleUpdateCode}
|
||||||
loadingUpdate={loadingUpdate}
|
loadingUpdate={loadingUpdate}
|
||||||
setDismissAll={() => addDismissedNodes([data.id])}
|
setDismissAll={memoizedSetDismissAll}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
|
|
@ -546,28 +432,92 @@ function GenericNode({
|
||||||
className={"generic-node-title-arrangement"}
|
className={"generic-node-title-arrangement"}
|
||||||
data-testid="generic-node-title-arrangement"
|
data-testid="generic-node-title-arrangement"
|
||||||
>
|
>
|
||||||
{renderNodeIcon()}
|
<MemoizedNodeIcon
|
||||||
|
dataType={data.type}
|
||||||
|
showNode={showNode}
|
||||||
|
icon={data.node?.icon}
|
||||||
|
isGroup={!!data.node?.flow}
|
||||||
|
/>
|
||||||
<div className="generic-node-tooltip-div truncate">
|
<div className="generic-node-tooltip-div truncate">
|
||||||
{renderNodeName()}
|
<MemoizedNodeName
|
||||||
|
display_name={data.node?.display_name}
|
||||||
|
nodeId={data.id}
|
||||||
|
selected={selected}
|
||||||
|
showNode={showNode}
|
||||||
|
validationStatus={validationStatus}
|
||||||
|
isOutdated={isOutdated}
|
||||||
|
beta={data.node?.beta || false}
|
||||||
|
editNameDescription={editNameDescription}
|
||||||
|
toggleEditNameDescription={toggleEditNameDescription}
|
||||||
|
setHasChangedNodeDescription={setHasChangedNodeDescription}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-testid={`${showNode ? "show" : "hide"}-node-content`}>
|
<div data-testid={`${showNode ? "show" : "hide"}-node-content`}>
|
||||||
{!showNode && (
|
{!showNode && (
|
||||||
<>
|
<>
|
||||||
{renderInputParameters()}
|
<MemoizedRenderInputParameters
|
||||||
{shownOutputs.length > 0 &&
|
data={data}
|
||||||
renderOutputs(shownOutputs, "render-outputs")}
|
types={types}
|
||||||
|
isToolMode={isToolMode}
|
||||||
|
showNode={showNode}
|
||||||
|
shownOutputs={shownOutputs}
|
||||||
|
showHiddenOutputs={showHiddenOutputs}
|
||||||
|
/>
|
||||||
|
<MemoizedNodeOutputs
|
||||||
|
outputs={shownOutputs}
|
||||||
|
keyPrefix="render-outputs"
|
||||||
|
data={data}
|
||||||
|
types={types}
|
||||||
|
selected={selected}
|
||||||
|
showNode={showNode}
|
||||||
|
isToolMode={isToolMode}
|
||||||
|
showHiddenOutputs={showHiddenOutputs}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{renderNodeStatus()}
|
<MemoizedNodeStatus
|
||||||
|
data={data}
|
||||||
|
frozen={data.node?.frozen}
|
||||||
|
showNode={showNode}
|
||||||
|
display_name={data.node?.display_name!}
|
||||||
|
nodeId={data.id}
|
||||||
|
selected={selected}
|
||||||
|
setBorderColor={setBorderColor}
|
||||||
|
buildStatus={buildStatus}
|
||||||
|
dismissAll={dismissAll}
|
||||||
|
isOutdated={isOutdated}
|
||||||
|
isUserEdited={isUserEdited}
|
||||||
|
isBreakingChange={hasBreakingChange}
|
||||||
|
getValidationStatus={getValidationStatus}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{showNode && <div>{renderDescription()}</div>}
|
{showNode && (
|
||||||
|
<div>
|
||||||
|
<MemoizedNodeDescription
|
||||||
|
description={data.node?.description}
|
||||||
|
mdClassName={"dark:prose-invert"}
|
||||||
|
nodeId={data.id}
|
||||||
|
selected={selected}
|
||||||
|
editNameDescription={editNameDescription}
|
||||||
|
setEditNameDescription={set}
|
||||||
|
setHasChangedNodeDescription={setHasChangedNodeDescription}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{showNode && (
|
{showNode && (
|
||||||
<div className="nopan nodelete nodrag noflow relative cursor-auto">
|
<div className="nopan nodelete nodrag noflow relative cursor-auto">
|
||||||
<>
|
<>
|
||||||
{renderInputParameters()}
|
<MemoizedRenderInputParameters
|
||||||
|
data={data}
|
||||||
|
types={types}
|
||||||
|
isToolMode={isToolMode}
|
||||||
|
showNode={showNode}
|
||||||
|
shownOutputs={shownOutputs}
|
||||||
|
showHiddenOutputs={showHiddenOutputs}
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
Object.keys(data.node!.template).length < 1 ? "hidden" : "",
|
Object.keys(data.node!.template).length < 1 ? "hidden" : "",
|
||||||
|
|
@ -576,15 +526,33 @@ function GenericNode({
|
||||||
>
|
>
|
||||||
{" "}
|
{" "}
|
||||||
</div>
|
</div>
|
||||||
{!showHiddenOutputs &&
|
{!showHiddenOutputs && shownOutputs && (
|
||||||
shownOutputs &&
|
<MemoizedNodeOutputs
|
||||||
renderOutputs(shownOutputs, "shown")}
|
outputs={shownOutputs}
|
||||||
|
keyPrefix="shown"
|
||||||
|
data={data}
|
||||||
|
types={types}
|
||||||
|
selected={selected}
|
||||||
|
showNode={showNode}
|
||||||
|
isToolMode={isToolMode}
|
||||||
|
showHiddenOutputs={showHiddenOutputs}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={cn(showHiddenOutputs ? "" : "h-0 overflow-hidden")}
|
className={cn(showHiddenOutputs ? "" : "h-0 overflow-hidden")}
|
||||||
>
|
>
|
||||||
<div className="block">
|
<div className="block">
|
||||||
{renderOutputs(data.node!.outputs, "hidden")}
|
<MemoizedNodeOutputs
|
||||||
|
outputs={data.node!.outputs}
|
||||||
|
keyPrefix="hidden"
|
||||||
|
data={data}
|
||||||
|
types={types}
|
||||||
|
selected={selected}
|
||||||
|
showNode={showNode}
|
||||||
|
isToolMode={isToolMode}
|
||||||
|
showHiddenOutputs={showHiddenOutputs}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{hiddenOutputs && hiddenOutputs.length > 0 && (
|
{hiddenOutputs && hiddenOutputs.length > 0 && (
|
||||||
|
|
@ -606,7 +574,7 @@ function GenericNode({
|
||||||
>
|
>
|
||||||
<HiddenOutputsButton
|
<HiddenOutputsButton
|
||||||
showHiddenOutputs={showHiddenOutputs}
|
showHiddenOutputs={showHiddenOutputs}
|
||||||
onClick={() => setShowHiddenOutputs(!showHiddenOutputs)}
|
onClick={handleToggleHiddenOutputs}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,50 @@
|
||||||
import { ParameterRenderComponent } from "@/components/core/parameterRenderComponent";
|
import { ParameterRenderComponent } from "@/components/core/parameterRenderComponent";
|
||||||
import { NodeInfoType } from "@/components/core/parameterRenderComponent/types";
|
import { NodeInfoType } from "@/components/core/parameterRenderComponent/types";
|
||||||
import { handleOnNewValueType } from "@/CustomNodes/hooks/use-handle-new-value";
|
import { handleOnNewValueType } from "@/CustomNodes/hooks/use-handle-new-value";
|
||||||
|
import useFlowStore from "@/stores/flowStore";
|
||||||
import { APIClassType, InputFieldType } from "@/types/api";
|
import { APIClassType, InputFieldType } from "@/types/api";
|
||||||
|
import { targetHandleType } from "@/types/flow";
|
||||||
|
import { scapedJSONStringfy } from "@/utils/reactflowUtils";
|
||||||
import { cn } from "@/utils/utils";
|
import { cn } from "@/utils/utils";
|
||||||
|
|
||||||
export function CustomParameterComponent({
|
export function CustomParameterComponent({
|
||||||
handleOnNewValue,
|
handleOnNewValue,
|
||||||
name,
|
name,
|
||||||
nodeId,
|
nodeId,
|
||||||
|
inputId,
|
||||||
templateData,
|
templateData,
|
||||||
templateValue,
|
templateValue,
|
||||||
editNode,
|
editNode,
|
||||||
handleNodeClass,
|
handleNodeClass,
|
||||||
nodeClass,
|
nodeClass,
|
||||||
disabled,
|
|
||||||
placeholder,
|
placeholder,
|
||||||
isToolMode,
|
isToolMode = false,
|
||||||
nodeInformationMetadata,
|
nodeInformationMetadata,
|
||||||
|
proxy,
|
||||||
}: {
|
}: {
|
||||||
handleOnNewValue: handleOnNewValueType;
|
handleOnNewValue: handleOnNewValueType;
|
||||||
name: string;
|
name: string;
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
|
inputId: targetHandleType;
|
||||||
templateData: Partial<InputFieldType>;
|
templateData: Partial<InputFieldType>;
|
||||||
templateValue: any;
|
templateValue: any;
|
||||||
editNode: boolean;
|
editNode: boolean;
|
||||||
handleNodeClass: (value: any, code?: string, type?: string) => void;
|
handleNodeClass: (value: any, code?: string, type?: string) => void;
|
||||||
nodeClass: APIClassType;
|
nodeClass: APIClassType;
|
||||||
disabled: boolean;
|
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
isToolMode?: boolean;
|
isToolMode?: boolean;
|
||||||
nodeInformationMetadata?: NodeInfoType;
|
nodeInformationMetadata?: NodeInfoType;
|
||||||
|
proxy: { field: string; id: string } | undefined;
|
||||||
}) {
|
}) {
|
||||||
|
const edges = useFlowStore((state) => state.edges);
|
||||||
|
|
||||||
|
let disabled =
|
||||||
|
edges.some(
|
||||||
|
(edge) =>
|
||||||
|
edge.targetHandle ===
|
||||||
|
scapedJSONStringfy(proxy ? { ...inputId, proxy } : inputId),
|
||||||
|
) || isToolMode;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ParameterRenderComponent
|
<ParameterRenderComponent
|
||||||
handleOnNewValue={handleOnNewValue}
|
handleOnNewValue={handleOnNewValue}
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,6 @@ const NodeToolbarComponent = memo(
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
|
|
||||||
const paste = useFlowStore((state) => state.paste);
|
const paste = useFlowStore((state) => state.paste);
|
||||||
const nodes = useFlowStore((state) => state.nodes);
|
|
||||||
const edges = useFlowStore((state) => state.edges);
|
|
||||||
const setNodes = useFlowStore((state) => state.setNodes);
|
const setNodes = useFlowStore((state) => state.setNodes);
|
||||||
const setEdges = useFlowStore((state) => state.setEdges);
|
const setEdges = useFlowStore((state) => state.setEdges);
|
||||||
const getNodePosition = useFlowStore((state) => state.getNodePosition);
|
const getNodePosition = useFlowStore((state) => state.getNodePosition);
|
||||||
|
|
@ -200,8 +198,6 @@ const NodeToolbarComponent = memo(
|
||||||
data.id,
|
data.id,
|
||||||
updateFlowPosition(getNodePosition(data.id), data.node?.flow!),
|
updateFlowPosition(getNodePosition(data.id), data.node?.flow!),
|
||||||
data.node!.template,
|
data.node!.template,
|
||||||
nodes,
|
|
||||||
edges,
|
|
||||||
setNodes,
|
setNodes,
|
||||||
setEdges,
|
setEdges,
|
||||||
data.node?.outputs,
|
data.node?.outputs,
|
||||||
|
|
@ -213,8 +209,6 @@ const NodeToolbarComponent = memo(
|
||||||
data.node?.flow,
|
data.node?.flow,
|
||||||
data.node?.template,
|
data.node?.template,
|
||||||
data.node?.outputs,
|
data.node?.outputs,
|
||||||
nodes,
|
|
||||||
edges,
|
|
||||||
setNodes,
|
setNodes,
|
||||||
setEdges,
|
setEdges,
|
||||||
takeSnapshot,
|
takeSnapshot,
|
||||||
|
|
@ -307,6 +301,7 @@ const NodeToolbarComponent = memo(
|
||||||
|
|
||||||
const handleSelectChange = useCallback(
|
const handleSelectChange = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
|
let nodes;
|
||||||
setSelectedValue(event);
|
setSelectedValue(event);
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
|
|
@ -356,10 +351,12 @@ const NodeToolbarComponent = memo(
|
||||||
updateNode();
|
updateNode();
|
||||||
break;
|
break;
|
||||||
case "copy":
|
case "copy":
|
||||||
|
nodes = useFlowStore.getState().nodes;
|
||||||
const node = nodes.filter((node) => node.id === data.id);
|
const node = nodes.filter((node) => node.id === data.id);
|
||||||
setLastCopiedSelection({ nodes: _.cloneDeep(node), edges: [] });
|
setLastCopiedSelection({ nodes: _.cloneDeep(node), edges: [] });
|
||||||
break;
|
break;
|
||||||
case "duplicate":
|
case "duplicate":
|
||||||
|
nodes = useFlowStore.getState().nodes;
|
||||||
paste(
|
paste(
|
||||||
{
|
{
|
||||||
nodes: [nodes.find((node) => node.id === data.id)!],
|
nodes: [nodes.find((node) => node.id === data.id)!],
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import {
|
||||||
} from "@/CustomNodes/utils/get-handle-id";
|
} from "@/CustomNodes/utils/get-handle-id";
|
||||||
import { INCOMPLETE_LOOP_ERROR_ALERT } from "@/constants/alerts_constants";
|
import { INCOMPLETE_LOOP_ERROR_ALERT } from "@/constants/alerts_constants";
|
||||||
import { customDownloadFlow } from "@/customization/utils/custom-reactFlowUtils";
|
import { customDownloadFlow } from "@/customization/utils/custom-reactFlowUtils";
|
||||||
|
import useFlowStore from "@/stores/flowStore";
|
||||||
import {
|
import {
|
||||||
Connection,
|
Connection,
|
||||||
Edge,
|
Edge,
|
||||||
|
|
@ -320,12 +321,16 @@ export function unselectAllNodesEdges(nodes: Node[], edges: Edge[]) {
|
||||||
|
|
||||||
export function isValidConnection(
|
export function isValidConnection(
|
||||||
{ source, target, sourceHandle, targetHandle }: Connection,
|
{ source, target, sourceHandle, targetHandle }: Connection,
|
||||||
nodes: AllNodeType[],
|
nodes?: AllNodeType[],
|
||||||
edges: EdgeType[],
|
edges?: EdgeType[],
|
||||||
): boolean {
|
): boolean {
|
||||||
if (source === target) {
|
if (source === target) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nodesArray = nodes || useFlowStore.getState().nodes;
|
||||||
|
const edgesArray = edges || useFlowStore.getState().edges;
|
||||||
|
|
||||||
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
|
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
|
||||||
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
|
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
|
||||||
if (
|
if (
|
||||||
|
|
@ -345,20 +350,20 @@ export function isValidConnection(
|
||||||
t === targetHandleObject.type,
|
t === targetHandleObject.type,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
let targetNode = nodes.find((node) => node.id === target!)?.data?.node;
|
let targetNode = nodesArray.find((node) => node.id === target!)?.data?.node;
|
||||||
if (!targetNode) {
|
if (!targetNode) {
|
||||||
if (!edges.find((e) => e.targetHandle === targetHandle)) {
|
if (!edgesArray.find((e) => e.targetHandle === targetHandle)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
targetHandleObject.output_types &&
|
targetHandleObject.output_types &&
|
||||||
!edges.find((e) => e.targetHandle === targetHandle)
|
!edgesArray.find((e) => e.targetHandle === targetHandle)
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
} else if (
|
} else if (
|
||||||
!targetHandleObject.output_types &&
|
!targetHandleObject.output_types &&
|
||||||
((!targetNode.template[targetHandleObject.fieldName].list &&
|
((!targetNode.template[targetHandleObject.fieldName].list &&
|
||||||
!edges.find((e) => e.targetHandle === targetHandle)) ||
|
!edgesArray.find((e) => e.targetHandle === targetHandle)) ||
|
||||||
targetNode.template[targetHandleObject.fieldName].list)
|
targetNode.template[targetHandleObject.fieldName].list)
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1476,8 +1481,6 @@ export function expandGroupNode(
|
||||||
id: string,
|
id: string,
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
template: APITemplateType,
|
template: APITemplateType,
|
||||||
nodes: AllNodeType[],
|
|
||||||
edges: EdgeType[],
|
|
||||||
setNodes: (
|
setNodes: (
|
||||||
update: AllNodeType[] | ((oldState: AllNodeType[]) => AllNodeType[]),
|
update: AllNodeType[] | ((oldState: AllNodeType[]) => AllNodeType[]),
|
||||||
) => void,
|
) => void,
|
||||||
|
|
@ -1488,7 +1491,7 @@ export function expandGroupNode(
|
||||||
) {
|
) {
|
||||||
const idsMap = updateIds(flow!.data!);
|
const idsMap = updateIds(flow!.data!);
|
||||||
updateProxyIdsOnTemplate(template, idsMap);
|
updateProxyIdsOnTemplate(template, idsMap);
|
||||||
let flowEdges = edges;
|
let flowEdges = useFlowStore.getState().edges;
|
||||||
updateEdgesIds(flowEdges, idsMap);
|
updateEdgesIds(flowEdges, idsMap);
|
||||||
const gNodes: AllNodeType[] = cloneDeep(flow?.data?.nodes!);
|
const gNodes: AllNodeType[] = cloneDeep(flow?.data?.nodes!);
|
||||||
const gEdges = cloneDeep(flow!.data!.edges);
|
const gEdges = cloneDeep(flow!.data!.edges);
|
||||||
|
|
@ -1588,9 +1591,12 @@ export function expandGroupNode(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const filteredNodes = [...nodes.filter((n) => n.id !== id), ...gNodes];
|
const filteredNodes = [
|
||||||
|
...useFlowStore.getState().nodes.filter((n) => n.id !== id),
|
||||||
|
...gNodes,
|
||||||
|
];
|
||||||
const filteredEdges = [
|
const filteredEdges = [
|
||||||
...edges.filter((e) => e.target !== id && e.source !== id),
|
...flowEdges.filter((e) => e.target !== id && e.source !== id),
|
||||||
...gEdges,
|
...gEdges,
|
||||||
];
|
];
|
||||||
setNodes(filteredNodes);
|
setNodes(filteredNodes);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue