fix backward compability

This commit is contained in:
anovazzi1 2024-05-31 16:09:41 -03:00
commit 4727cae10e
7 changed files with 196 additions and 214 deletions

View file

@ -18,6 +18,7 @@ export default function OutputComponent({
frozen = false, frozen = false,
nodeId, nodeId,
idx, idx,
name,
}: outputComponentType) { }: outputComponentType) {
const setNode = useFlowStore((state) => state.setNode); const setNode = useFlowStore((state) => state.setNode);
const updateNodeInternals = useUpdateNodeInternals(); const updateNodeInternals = useUpdateNodeInternals();
@ -27,33 +28,36 @@ export default function OutputComponent({
} }
return ( return (
<DropdownMenu> <div className="flex gap-2">
<DropdownMenuTrigger> <span>{name}</span>
<span <DropdownMenu>
className={cn(frozen ? " text-ice" : "", "flex items-center gap-1")} <DropdownMenuTrigger>
> <span
{selected} className={cn(frozen ? " text-ice" : "", "flex items-center gap-1")}
<ForwardedIconComponent name="ChevronDown" className="h-4 w-4" />
</span>
</DropdownMenuTrigger>
<DropdownMenuContent>
{types.map((type) => (
<DropdownMenuItem
onSelect={() => {
// TODO: UDPDATE SET NODE TO NEW NODE FORM
setNode(nodeId, (node) => {
const newNode = cloneDeep(node);
(newNode.data as NodeDataType).node!.outputs![idx].selected =
type;
return newNode;
});
updateNodeInternals(nodeId);
}}
> >
{type} {selected}
</DropdownMenuItem> <ForwardedIconComponent name="ChevronDown" className="h-4 w-4" />
))} </span>
</DropdownMenuContent> </DropdownMenuTrigger>
</DropdownMenu> <DropdownMenuContent>
{types.map((type) => (
<DropdownMenuItem
onSelect={() => {
// TODO: UDPDATE SET NODE TO NEW NODE FORM
setNode(nodeId, (node) => {
const newNode = cloneDeep(node);
(newNode.data as NodeDataType).node!.outputs![idx].selected =
type;
return newNode;
});
updateNodeInternals(nodeId);
}}
>
{type}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
); );
} }

View file

@ -59,6 +59,7 @@ export default function ParameterComponent({
proxy, proxy,
showNode, showNode,
index, index,
outputName,
}: ParameterComponentType): JSX.Element { }: ParameterComponentType): JSX.Element {
const infoHtml = useRef<HTMLDivElement & ReactNode>(null); const infoHtml = useRef<HTMLDivElement & ReactNode>(null);
const nodes = useFlowStore((state) => state.nodes); const nodes = useFlowStore((state) => state.nodes);
@ -79,7 +80,7 @@ export default function ParameterComponent({
debouncedHandleUpdateValues, debouncedHandleUpdateValues,
setNode, setNode,
isLoading, isLoading,
setIsLoading setIsLoading,
); );
const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass( const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
@ -87,7 +88,7 @@ export default function ParameterComponent({
name, name,
takeSnapshot, takeSnapshot,
setNode, setNode,
updateNodeInternals updateNodeInternals,
); );
const { handleRefreshButtonPress: handleRefreshButtonPressHook } = const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
@ -96,7 +97,7 @@ export default function ParameterComponent({
let disabled = let disabled =
edges.some( edges.some(
(edge) => (edge) =>
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id) edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
) ?? false; ) ?? false;
const handleRefreshButtonPress = async (name, data) => { const handleRefreshButtonPress = async (name, data) => {
@ -107,7 +108,7 @@ export default function ParameterComponent({
const handleOnNewValue = async ( const handleOnNewValue = async (
newValue: string | string[] | boolean | Object[], newValue: string | string[] | boolean | Object[],
skipSnapshot: boolean | undefined = false skipSnapshot: boolean | undefined = false,
): Promise<void> => { ): Promise<void> => {
handleOnNewValueHook(newValue, skipSnapshot); handleOnNewValueHook(newValue, skipSnapshot);
}; };
@ -137,6 +138,7 @@ export default function ParameterComponent({
selected={title} selected={title}
nodeId={data.id} nodeId={data.id}
frozen={data.node?.frozen} frozen={data.node?.frozen}
name={outputName ?? type ?? title}
/> />
) : ( ) : (
<span>{title}</span> <span>{title}</span>
@ -188,14 +190,14 @@ export default function ParameterComponent({
className={classNames( className={classNames(
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ", left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
"h-3 w-3 rounded-full border-2 bg-background", "h-3 w-3 rounded-full border-2 bg-background",
!showNode ? "mt-0" : "" !showNode ? "mt-0" : "",
)} )}
style={{ style={{
borderColor: color ?? nodeColors.unknown, borderColor: color ?? nodeColors.unknown,
}} }}
onClick={() => { onClick={() => {
setFilterEdge( setFilterEdge(
groupByFamily(myData, tooltipTitle!, left, nodes!) groupByFamily(myData, tooltipTitle!, left, nodes!),
); );
}} }}
></Handle> ></Handle>
@ -280,12 +282,12 @@ export default function ParameterComponent({
} }
className={classNames( className={classNames(
left ? "-ml-0.5" : "-mr-0.5", left ? "-ml-0.5" : "-mr-0.5",
"h-3 w-3 rounded-full border-2 bg-background" "h-3 w-3 rounded-full border-2 bg-background",
)} )}
style={{ borderColor: color ?? nodeColors.unknown }} style={{ borderColor: color ?? nodeColors.unknown }}
onClick={() => { onClick={() => {
setFilterEdge( setFilterEdge(
groupByFamily(myData, tooltipTitle!, left, nodes!) groupByFamily(myData, tooltipTitle!, left, nodes!),
); );
}} }}
/> />

View file

@ -55,14 +55,14 @@ export default function GenericNode({
const [nodeName, setNodeName] = useState(data.node!.display_name); const [nodeName, setNodeName] = useState(data.node!.display_name);
const [inputDescription, setInputDescription] = useState(false); const [inputDescription, setInputDescription] = useState(false);
const [nodeDescription, setNodeDescription] = useState( const [nodeDescription, setNodeDescription] = useState(
data.node?.description! data.node?.description!,
); );
const [isOutdated, setIsOutdated] = useState(false); const [isOutdated, setIsOutdated] = useState(false);
const buildStatus = useFlowStore( const buildStatus = useFlowStore(
(state) => state.flowBuildStatus[data.id]?.status (state) => state.flowBuildStatus[data.id]?.status,
); );
const lastRunTime = useFlowStore( const lastRunTime = useFlowStore(
(state) => state.flowBuildStatus[data.id]?.timestamp (state) => state.flowBuildStatus[data.id]?.timestamp,
); );
const [validationStatus, setValidationStatus] = const [validationStatus, setValidationStatus] =
useState<validationStatusType | null>(null); useState<validationStatusType | null>(null);
@ -115,7 +115,7 @@ export default function GenericNode({
updateNodeInternals(data.id); updateNodeInternals(data.id);
}, },
[data.id, data.node, setNode, setIsOutdated] [data.id, data.node, setNode, setIsOutdated],
); );
if (!data.node!.template) { if (!data.node!.template) {
@ -252,60 +252,10 @@ export default function GenericNode({
); );
}; };
const buildParameterComponent = ({
data,
conditionalPath,
showNode,
left,
}: {
data: NodeDataType;
conditionalPath: string | null;
showNode: boolean;
left: boolean;
}) => {
return (
<ParameterComponent
key={scapedJSONStringfy({
baseClasses: data.node!.base_classes,
id: data.id,
dataType: data.type,
conditionalPath: conditionalPath,
})}
data={data}
color={
(data.node?.output_types && data.node.output_types.length > 0
? nodeColors[data.node.output_types[0]] ??
nodeColors[types[data.node.output_types[0]]]
: nodeColors[types[data.type]]) ?? nodeColors.unknown
}
title={
data.node?.output_types && data.node.output_types.length > 0
? data.node.output_types.join(" | ")
: data.type
}
conditionPath={conditionalPath}
tooltipTitle={data.node?.base_classes.join("\n")}
id={{
baseClasses: data.node!.base_classes,
id: data.id,
dataType: data.type,
// First parameter component should be true
// Second should be false
conditionalPath: conditionalPath,
}}
// Type should be base_classes if it's not a conditional node
// else it should be true in the first parameter component
type={data.node?.base_classes.join("|")}
left={left}
showNode={showNode}
/>
);
};
const isDark = useDarkStore((state) => state.dark); const isDark = useDarkStore((state) => state.dark);
const renderIconStatus = ( const renderIconStatus = (
buildStatus: BuildStatus | undefined, buildStatus: BuildStatus | undefined,
validationStatus: validationStatusType | null validationStatus: validationStatusType | null,
) => { ) => {
if (buildStatus === BuildStatus.BUILDING) { if (buildStatus === BuildStatus.BUILDING) {
return <Loading className="text-medium-indigo" />; return <Loading className="text-medium-indigo" />;
@ -346,7 +296,7 @@ export default function GenericNode({
}; };
const getSpecificClassFromBuildStatus = ( const getSpecificClassFromBuildStatus = (
buildStatus: BuildStatus | undefined, buildStatus: BuildStatus | undefined,
validationStatus: validationStatusType | null validationStatus: validationStatusType | null,
) => { ) => {
let isInvalid = validationStatus && !validationStatus.valid; let isInvalid = validationStatus && !validationStatus.valid;
@ -370,11 +320,11 @@ export default function GenericNode({
selected: boolean, selected: boolean,
showNode: boolean, showNode: boolean,
buildStatus: BuildStatus | undefined, buildStatus: BuildStatus | undefined,
validationStatus: validationStatusType | null validationStatus: validationStatusType | null,
) => { ) => {
const specificClassFromBuildStatus = getSpecificClassFromBuildStatus( const specificClassFromBuildStatus = getSpecificClassFromBuildStatus(
buildStatus, buildStatus,
validationStatus validationStatus,
); );
const baseBorderClass = getBaseBorderClass(selected); const baseBorderClass = getBaseBorderClass(selected);
@ -383,7 +333,7 @@ export default function GenericNode({
baseBorderClass, baseBorderClass,
nodeSizeClass, nodeSizeClass,
"generic-node-div", "generic-node-div",
specificClassFromBuildStatus specificClassFromBuildStatus,
); );
return names; return names;
}; };
@ -443,7 +393,7 @@ export default function GenericNode({
selected, selected,
showNode, showNode,
buildStatus, buildStatus,
validationStatus validationStatus,
)} )}
> >
{data.node?.beta && showNode && ( {data.node?.beta && showNode && (
@ -588,7 +538,7 @@ export default function GenericNode({
} }
title={getFieldTitle( title={getFieldTitle(
data.node?.template!, data.node?.template!,
templateField templateField,
)} )}
info={data.node?.template[templateField].info} info={data.node?.template[templateField].info}
name={templateField} name={templateField}
@ -616,9 +566,9 @@ export default function GenericNode({
proxy={data.node?.template[templateField].proxy} proxy={data.node?.template[templateField].proxy}
showNode={showNode} showNode={showNode}
/> />
) ),
)} )}
<ParameterComponent {/* <ParameterComponent
index={0} index={0}
key={scapedJSONStringfy({ key={scapedJSONStringfy({
baseClasses: data.node!.base_classes, baseClasses: data.node!.base_classes,
@ -643,7 +593,7 @@ export default function GenericNode({
type={data.node?.base_classes.join("|")} type={data.node?.base_classes.join("|")}
left={false} left={false}
showNode={showNode} showNode={showNode}
/> /> */}
</> </>
)} )}
</div> </div>
@ -775,7 +725,7 @@ export default function GenericNode({
!data.node?.description) && !data.node?.description) &&
nameEditable nameEditable
? "font-light italic" ? "font-light italic"
: "" : "",
)} )}
onDoubleClick={(e) => { onDoubleClick={(e) => {
setInputDescription(true); setInputDescription(true);
@ -837,13 +787,13 @@ export default function GenericNode({
} }
title={getFieldTitle( title={getFieldTitle(
data.node?.template!, data.node?.template!,
templateField templateField,
)} )}
info={data.node?.template[templateField].info} info={data.node?.template[templateField].info}
name={templateField} name={templateField}
tooltipTitle={ tooltipTitle={
data.node?.template[templateField].input_types?.join( data.node?.template[templateField].input_types?.join(
"\n" "\n",
) ?? data.node?.template[templateField].type ) ?? data.node?.template[templateField].type
} }
required={data.node!.template[templateField].required} required={data.node!.template[templateField].required}
@ -870,7 +820,7 @@ export default function GenericNode({
<div <div
className={classNames( className={classNames(
Object.keys(data.node!.template).length < 1 ? "hidden" : "", Object.keys(data.node!.template).length < 1 ? "hidden" : "",
"flex-max-width justify-center" "flex-max-width justify-center",
)} )}
> >
{" "} {" "}
@ -881,7 +831,7 @@ export default function GenericNode({
<ParameterComponent <ParameterComponent
index={idx} index={idx}
key={scapedJSONStringfy({ key={scapedJSONStringfy({
baseClasses: [output.selected ?? output.types[0]], output_types: [output.selected ?? output.types[0]],
id: data.id, id: data.id,
dataType: data.type, dataType: data.type,
})} })}
@ -892,17 +842,18 @@ export default function GenericNode({
nodeColors[types[data.type]] ?? nodeColors[types[data.type]] ??
nodeColors.unknown nodeColors.unknown
} }
title={output.name} title={output.selected ?? output.types[0]}
tooltipTitle={output.selected ?? output.types[0]} tooltipTitle={output.selected ?? output.types[0]}
id={{ id={{
baseClasses: [output.selected ?? output.types[0]], output_types: [output.selected ?? output.types[0]],
id: data.id, id: data.id,
dataType: data.type, dataType: data.type,
idx: idx, name: output.name,
}} }}
type={output.types.join("|")} type={output.types.join("|")}
left={false} left={false}
showNode={showNode} showNode={showNode}
outputName={output.name}
/> />
))} ))}
</> </>

View file

@ -84,14 +84,14 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
readFlowsFromDatabase() readFlowsFromDatabase()
.then((dbData) => { .then((dbData) => {
if (dbData) { if (dbData) {
const { data, flows } = processFlows(dbData, false); const { data, flows } = processFlows(dbData);
const examples = flows.filter( const examples = flows.filter(
(flow) => flow.folder_id === starterFolderId (flow) => flow.folder_id === starterFolderId,
); );
get().setExamples(examples); get().setExamples(examples);
const flowsWithoutStarterFolder = flows.filter( const flowsWithoutStarterFolder = flows.filter(
(flow) => flow.folder_id !== starterFolderId (flow) => flow.folder_id !== starterFolderId,
); );
get().setFlows(flowsWithoutStarterFolder); get().setFlows(flowsWithoutStarterFolder);
@ -119,7 +119,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
if (get().currentFlow) { if (get().currentFlow) {
get().saveFlow( get().saveFlow(
{ ...get().currentFlow!, data: { nodes, edges, viewport } }, { ...get().currentFlow!, data: { nodes, edges, viewport } },
true true,
); );
} }
}, },
@ -145,7 +145,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
return updatedFlow; return updatedFlow;
} }
return flow; return flow;
}) }),
); );
//update tabs state //update tabs state
@ -194,7 +194,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
flow?: FlowType, flow?: FlowType,
override?: boolean, override?: boolean,
position?: XYPosition, position?: XYPosition,
fromDragAndDrop?: boolean fromDragAndDrop?: boolean,
): Promise<string | undefined> => { ): Promise<string | undefined> => {
let flowData = flow let flowData = flow
? processDataFromFlow(flow) ? processDataFromFlow(flow)
@ -209,7 +209,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
const newFlow = createNewFlow( const newFlow = createNewFlow(
flowData!, flowData!,
flow!, flow!,
folder_id || my_collection_id! folder_id || my_collection_id!,
); );
const { id } = await saveFlowToDatabase(newFlow); const { id } = await saveFlowToDatabase(newFlow);
newFlow.id = id; newFlow.id = id;
@ -232,7 +232,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
const newFlow = createNewFlow( const newFlow = createNewFlow(
flowData!, flowData!,
flow!, flow!,
folder_id || my_collection_id! folder_id || my_collection_id!,
); );
const newName = addVersionToDuplicates(newFlow, get().flows); const newName = addVersionToDuplicates(newFlow, get().flows);
@ -268,7 +268,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
.getState() .getState()
.paste( .paste(
{ nodes: flow!.data!.nodes, edges: flow!.data!.edges }, { nodes: flow!.data!.nodes, edges: flow!.data!.edges },
position ?? { x: 10, y: 10 } position ?? { x: 10, y: 10 },
); );
} }
}, },
@ -278,7 +278,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
multipleDeleteFlowsComponents(id) multipleDeleteFlowsComponents(id)
.then(() => { .then(() => {
const { data, flows } = processFlows( const { data, flows } = processFlows(
get().flows.filter((flow) => !id.includes(flow.id)) get().flows.filter((flow) => !id.includes(flow.id)),
); );
get().setFlows(flows); get().setFlows(flows);
set({ isLoading: false }); set({ isLoading: false });
@ -298,7 +298,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
deleteFlowFromDatabase(id) deleteFlowFromDatabase(id)
.then(() => { .then(() => {
const { data, flows } = processFlows( const { data, flows } = processFlows(
get().flows.filter((flow) => flow.id !== id) get().flows.filter((flow) => flow.id !== id),
); );
get().setFlows(flows); get().setFlows(flows);
set({ isLoading: false }); set({ isLoading: false });
@ -320,7 +320,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
let componentFlow = get().flows.find( let componentFlow = get().flows.find(
(componentFlow) => (componentFlow) =>
componentFlow.is_component && componentFlow.name === key componentFlow.is_component && componentFlow.name === key,
); );
if (componentFlow) { if (componentFlow) {
@ -368,7 +368,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
fileData, fileData,
undefined, undefined,
position, position,
true true,
); );
resolve(id); resolve(id);
} }
@ -409,7 +409,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
return get().addFlow( return get().addFlow(
true, true,
createFlowComponent(component, useDarkStore.getState().version), createFlowComponent(component, useDarkStore.getState().version),
override override,
); );
}, },
takeSnapshot: () => { takeSnapshot: () => {
@ -430,7 +430,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
if (pastLength > 0) { if (pastLength > 0) {
past[currentFlowId] = past[currentFlowId].slice( past[currentFlowId] = past[currentFlowId].slice(
pastLength - defaultOptions.maxHistorySize + 1, pastLength - defaultOptions.maxHistorySize + 1,
pastLength pastLength,
); );
past[currentFlowId].push(newState); past[currentFlowId].push(newState);

View file

@ -70,6 +70,7 @@ export type ParameterComponentType = {
showNode?: boolean; showNode?: boolean;
index: number; index: number;
onCloseModal?: (close: boolean) => void; onCloseModal?: (close: boolean) => void;
outputName?: string;
}; };
export type InputListComponentType = { export type InputListComponentType = {
value: string[]; value: string[];
@ -118,6 +119,7 @@ export type outputComponentType = {
nodeId: string; nodeId: string;
frozen?: boolean; frozen?: boolean;
idx: number; idx: number;
name: string;
}; };
export type PromptAreaComponentType = { export type PromptAreaComponentType = {
@ -528,7 +530,7 @@ export type nodeToolbarPropsType = {
updateNodeCode?: ( updateNodeCode?: (
newNodeClass: APIClassType, newNodeClass: APIClassType,
code: string, code: string,
name: string name: string,
) => void; ) => void;
setShowState: (show: boolean | SetStateAction<boolean>) => void; setShowState: (show: boolean | SetStateAction<boolean>) => void;
isOutdated?: boolean; isOutdated?: boolean;
@ -578,7 +580,7 @@ export type chatMessagePropsType = {
updateChat: ( updateChat: (
chat: ChatMessageType, chat: ChatMessageType,
message: string, message: string,
stream_url?: string stream_url?: string,
) => void; ) => void;
}; };
@ -670,12 +672,12 @@ export type codeTabsPropsType = {
value: string, value: string,
node: NodeType, node: NodeType,
template: InputFieldType, template: InputFieldType,
tweak: tweakType tweak: tweakType,
) => string; ) => string;
buildTweakObject?: ( buildTweakObject?: (
tw: string, tw: string,
changes: string | string[] | boolean | number | Object[] | Object, changes: string | string[] | boolean | number | Object[] | Object,
template: InputFieldType template: InputFieldType,
) => Promise<string | void>; ) => Promise<string | void>;
}; };
activeTweaks?: boolean; activeTweaks?: boolean;

View file

@ -58,9 +58,9 @@ export type TweaksType = Array<
export type sourceHandleType = { export type sourceHandleType = {
dataType: string; dataType: string;
id: string; id: string;
baseClasses: string[]; output_types: string[];
conditionalPath?: string | null; conditionalPath?: string | null;
idx: number; name: string;
}; };
//left side //left side
export type targetHandleType = { export type targetHandleType = {

View file

@ -45,8 +45,7 @@ export function checkChatInput(nodes: Node[]) {
return nodes.some((node) => node.data.type === "ChatInput"); return nodes.some((node) => node.data.type === "ChatInput");
} }
export function cleanEdges(nodes: Node[], edges: Edge[]) { export function cleanEdges(nodes: NodeType[], edges: Edge[]) {
console.log("cleanEdges");
let newEdges = cloneDeep(edges); let newEdges = cloneDeep(edges);
edges.forEach((edge) => { edges.forEach((edge) => {
// check if the source and target node still exists // check if the source and target node still exists
@ -76,12 +75,16 @@ export function cleanEdges(nodes: Node[], edges: Edge[]) {
} }
} }
if (sourceHandle) { if (sourceHandle) {
const index = scapeJSONParse(sourceHandle).idx ?? 0; const name = scapeJSONParse(sourceHandle).name;
const output = sourceNode.data.node!.outputs?.find(
(output) => output.name === name,
);
const outputTypes = [output?.selected ?? ""];
const id: sourceHandleType = { const id: sourceHandleType = {
id: sourceNode.data.id, id: sourceNode.data.id,
baseClasses: [sourceNode.data.node.outputs[index].selected], name: name,
output_types: outputTypes,
dataType: sourceNode.data.type, dataType: sourceNode.data.type,
idx: index,
}; };
if (scapedJSONStringfy(id) !== sourceHandle) { if (scapedJSONStringfy(id) !== sourceHandle) {
newEdges = newEdges.filter((e) => e.id !== edge.id); newEdges = newEdges.filter((e) => e.id !== edge.id);
@ -102,18 +105,18 @@ export function unselectAllNodes({ updateNodes, data }: unselectAllNodesType) {
export function isValidConnection( export function isValidConnection(
{ source, target, sourceHandle, targetHandle }: Connection, { source, target, sourceHandle, targetHandle }: Connection,
nodes: Node[], nodes: Node[],
edges: Edge[] edges: Edge[],
) { ) {
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!); const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!); const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
if ( if (
targetHandleObject.inputTypes?.some( targetHandleObject.inputTypes?.some(
(n) => n === sourceHandleObject.dataType (n) => n === sourceHandleObject.dataType,
) || ) ||
sourceHandleObject.baseClasses.some( sourceHandleObject.output_types.some(
(t) => (t) =>
targetHandleObject.inputTypes?.some((n) => n === t) || targetHandleObject.inputTypes?.some((n) => n === t) ||
t === targetHandleObject.type t === targetHandleObject.type,
) )
) { ) {
let targetNode = nodes.find((node) => node.id === target!)?.data?.node; let targetNode = nodes.find((node) => node.id === target!)?.data?.node;
@ -146,7 +149,7 @@ export function removeApiKeys(flow: FlowType): FlowType {
export function updateTemplate( export function updateTemplate(
reference: APITemplateType, reference: APITemplateType,
objectToUpdate: APITemplateType objectToUpdate: APITemplateType,
): APITemplateType { ): APITemplateType {
let clonedObject: APITemplateType = cloneDeep(reference); let clonedObject: APITemplateType = cloneDeep(reference);
@ -206,7 +209,7 @@ export const processDataFromFlow = (flow: FlowType, refreshIds = true) => {
export function updateIds( export function updateIds(
{ edges, nodes }: { edges: Edge[]; nodes: Node[] }, { edges, nodes }: { edges: Edge[]; nodes: Node[] },
selection?: { edges: Edge[]; nodes: Node[] } selection?: { edges: Edge[]; nodes: Node[] },
) { ) {
let idsMap = {}; let idsMap = {};
const selectionIds = selection?.nodes.map((n) => n.id); const selectionIds = selection?.nodes.map((n) => n.id);
@ -234,7 +237,7 @@ export function updateIds(
edge.source = idsMap[edge.source]; edge.source = idsMap[edge.source];
edge.target = idsMap[edge.target]; edge.target = idsMap[edge.target];
const sourceHandleObject: sourceHandleType = scapeJSONParse( const sourceHandleObject: sourceHandleType = scapeJSONParse(
edge.sourceHandle! edge.sourceHandle!,
); );
edge.sourceHandle = scapedJSONStringfy({ edge.sourceHandle = scapedJSONStringfy({
...sourceHandleObject, ...sourceHandleObject,
@ -244,7 +247,7 @@ export function updateIds(
edge.data.sourceHandle.id = edge.source; edge.data.sourceHandle.id = edge.source;
} }
const targetHandleObject: targetHandleType = scapeJSONParse( const targetHandleObject: targetHandleType = scapeJSONParse(
edge.targetHandle! edge.targetHandle!,
); );
edge.targetHandle = scapedJSONStringfy({ edge.targetHandle = scapedJSONStringfy({
...targetHandleObject, ...targetHandleObject,
@ -290,11 +293,11 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
(scapeJSONParse(edge.targetHandle!) as targetHandleType).fieldName === (scapeJSONParse(edge.targetHandle!) as targetHandleType).fieldName ===
t && t &&
(scapeJSONParse(edge.targetHandle!) as targetHandleType).id === (scapeJSONParse(edge.targetHandle!) as targetHandleType).id ===
node.id node.id,
) )
) { ) {
errors.push( errors.push(
`${displayName || type} is missing ${getFieldTitle(template, t)}.` `${displayName || type} is missing ${getFieldTitle(template, t)}.`,
); );
} else if ( } else if (
template[t].type === "dict" && template[t].type === "dict" &&
@ -308,15 +311,15 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
errors.push( errors.push(
`${displayName || type} (${getFieldTitle( `${displayName || type} (${getFieldTitle(
template, template,
t t,
)}) contains duplicate keys with the same values.` )}) contains duplicate keys with the same values.`,
); );
if (hasEmptyKey(template[t].value)) if (hasEmptyKey(template[t].value))
errors.push( errors.push(
`${displayName || type} (${getFieldTitle( `${displayName || type} (${getFieldTitle(
template, template,
t t,
)}) field must not be empty.` )}) field must not be empty.`,
); );
} }
return errors; return errors;
@ -325,7 +328,7 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
export function validateNodes( export function validateNodes(
nodes: Node[], nodes: Node[],
edges: Edge[] edges: Edge[],
): // this returns an array of tuples with the node id and the errors ): // this returns an array of tuples with the node id and the errors
Array<{ id: string; errors: Array<string> }> { Array<{ id: string; errors: Array<string> }> {
if (nodes.length === 0) { if (nodes.length === 0) {
@ -346,19 +349,16 @@ export function updateEdges(edges: Edge[]) {
if (edges) if (edges)
edges.forEach((edge) => { edges.forEach((edge) => {
const targetHandleObject: targetHandleType = scapeJSONParse( const targetHandleObject: targetHandleType = scapeJSONParse(
edge.targetHandle! edge.targetHandle!,
); );
edge.className = "stroke-gray-900 stroke-connection"; edge.className = "stroke-gray-900 stroke-connection";
}); });
} }
export function addVersionToDuplicates(flow: FlowType, flows: FlowType[]) { export function addVersionToDuplicates(flow: FlowType, flows: FlowType[]) {
console.log("flow", flow);
console.log("flows", flows);
const existingNames = flows const existingNames = flows
.filter((f) => f.folder_id === flow.folder_id) .filter((f) => f.folder_id === flow.folder_id)
.map((item) => item.name); .map((item) => item.name);
console.log("existingNames", existingNames);
let newName = flow.name; let newName = flow.name;
let count = 1; let count = 1;
@ -374,6 +374,7 @@ export function updateEdgesHandleIds({
edges, edges,
nodes, nodes,
}: updateEdgesHandleIdsType): Edge[] { }: updateEdgesHandleIdsType): Edge[] {
console.log("updateEdgesHandleIds");
let newEdges = cloneDeep(edges); let newEdges = cloneDeep(edges);
newEdges.forEach((edge) => { newEdges.forEach((edge) => {
const sourceNodeId = edge.source; const sourceNodeId = edge.source;
@ -396,11 +397,14 @@ export function updateEdgesHandleIds({
}; };
} }
if (source && sourceNode) { if (source && sourceNode) {
const output_types =
sourceNode.data.node!.output_types ??
sourceNode.data.node!.base_classes;
newSource = { newSource = {
id: sourceNode.data.id, id: sourceNode.data.id,
baseClasses: sourceNode.data.node!.base_classes, output_types,
dataType: sourceNode.data.type, dataType: sourceNode.data.type,
idx: 0, name: output_types.join(" | "),
}; };
} }
edge.sourceHandle = scapedJSONStringfy(newSource!); edge.sourceHandle = scapedJSONStringfy(newSource!);
@ -415,51 +419,70 @@ export function updateEdgesHandleIds({
} }
export function updateNewOutput({ nodes, edges }: updateEdgesHandleIdsType) { export function updateNewOutput({ nodes, edges }: updateEdgesHandleIdsType) {
console.log("updateNewOutput");
let newEdges = cloneDeep(edges); let newEdges = cloneDeep(edges);
let newNodes = cloneDeep(nodes); let newNodes = cloneDeep(nodes);
newEdges.forEach((edge) => { newEdges.forEach((edge) => {
if (edge.sourceHandle && edge.targetHandle) { if (edge.sourceHandle && edge.targetHandle) {
let newSourceHandle: sourceHandleType = scapeJSONParse(edge.sourceHandle); let newSourceHandle: sourceHandleType = scapeJSONParse(edge.sourceHandle);
let newTargetHandle: targetHandleType = scapeJSONParse(edge.targetHandle); let newTargetHandle: targetHandleType = scapeJSONParse(edge.targetHandle);
const id = newSourceHandle.id;
const sourceNodeIndex = newNodes.findIndex((node) => node.id === id);
let sourceNode: NodeType | undefined = undefined;
if (sourceNodeIndex !== -1) {
sourceNode = newNodes[sourceNodeIndex];
}
let intersection; let intersection;
//@ts-ignore
if (newSourceHandle.baseClasses) {
if (!newSourceHandle.output_types) {
if (sourceNode?.data.node!.output_types) {
newSourceHandle.output_types = sourceNode?.data.node!.output_types;
} else {
//@ts-ignore
newSourceHandle.output_types = newSourceHandle.baseClasses;
}
}
//@ts-ignore
delete newSourceHandle.baseClasses;
}
if (newTargetHandle.inputTypes && newTargetHandle.inputTypes.length > 0) { if (newTargetHandle.inputTypes && newTargetHandle.inputTypes.length > 0) {
//conjuction subtraction //conjuction subtraction
intersection = newSourceHandle.baseClasses.filter((type) => intersection = newSourceHandle.output_types.filter((type) =>
newTargetHandle.inputTypes!.includes(type) newTargetHandle.inputTypes!.includes(type),
); );
} else { } else {
intersection = newSourceHandle.baseClasses.filter( intersection = newSourceHandle.output_types.filter(
(type) => type === newTargetHandle.type (type) => type === newTargetHandle.type,
); );
} }
const selected = intersection[0]; const selected = intersection[0];
newSourceHandle.baseClasses = [selected]; newSourceHandle.name = newSourceHandle.output_types.join(" | ");
const id = newSourceHandle.id; newSourceHandle.output_types = [selected];
newSourceHandle.idx = 0; if (sourceNode) {
const sourceNodeIndex = newNodes.findIndex((node) => node.id === id); if (!sourceNode.data.node?.outputs) {
if (sourceNodeIndex > -1) { sourceNode.data.node!.outputs = [];
const sourceNode = newNodes[sourceNodeIndex]; }
const types =
sourceNode.data.node!.output_types ??
sourceNode.data.node!.base_classes;
if ( if (
!sourceNode.data.node?.outputs || !sourceNode.data.node!.outputs.some(
sourceNode.data.node!.outputs!.length === 0 (output) => output.selected === selected,
)
) { ) {
const outputTypes = sourceNode.data.node!.output_types; sourceNode.data.node!.outputs.push({
// create a new output field for each output type types,
sourceNode.data.node!.outputs = [ selected: selected,
{ name: types.join(" | "),
types: outputTypes ?? [], });
selected: selected,
name: outputTypes?.join(" | ") ?? "",
},
];
} }
} }
edge.sourceHandle = scapedJSONStringfy(newSourceHandle); edge.sourceHandle = scapedJSONStringfy(newSourceHandle);
edge.data.sourceHandle = newSourceHandle; edge.data.sourceHandle = newSourceHandle;
} }
}); });
return { nodes: newNodes, edges: newEdges }; return { nodes: newNodes, edges: newEdges };
} }
@ -468,7 +491,7 @@ export function handleKeyDown(
| React.KeyboardEvent<HTMLInputElement> | React.KeyboardEvent<HTMLInputElement>
| React.KeyboardEvent<HTMLTextAreaElement>, | React.KeyboardEvent<HTMLTextAreaElement>,
inputValue: string | string[] | null, inputValue: string | string[] | null,
block: string block: string,
) { ) {
//condition to fix bug control+backspace on Windows/Linux //condition to fix bug control+backspace on Windows/Linux
if ( if (
@ -493,7 +516,7 @@ export function handleKeyDown(
} }
export function handleOnlyIntegerInput( export function handleOnlyIntegerInput(
event: React.KeyboardEvent<HTMLInputElement> event: React.KeyboardEvent<HTMLInputElement>,
) { ) {
if ( if (
event.key === "." || event.key === "." ||
@ -509,7 +532,7 @@ export function handleOnlyIntegerInput(
export function getConnectedNodes( export function getConnectedNodes(
edge: Edge, edge: Edge,
nodes: Array<NodeType> nodes: Array<NodeType>,
): Array<NodeType> { ): Array<NodeType> {
const sourceId = edge.source; const sourceId = edge.source;
const targetId = edge.target; const targetId = edge.target;
@ -610,7 +633,7 @@ export function checkOldEdgesHandles(edges: Edge[]): boolean {
!edge.sourceHandle || !edge.sourceHandle ||
!edge.targetHandle || !edge.targetHandle ||
!edge.sourceHandle.includes("{") || !edge.sourceHandle.includes("{") ||
!edge.targetHandle.includes("{") !edge.targetHandle.includes("{"),
); );
} }
@ -637,7 +660,7 @@ export function customStringify(obj: any): string {
const keys = Object.keys(obj).sort(); const keys = Object.keys(obj).sort();
const keyValuePairs = keys.map( const keyValuePairs = keys.map(
(key) => `"${key}":${customStringify(obj[key])}` (key) => `"${key}":${customStringify(obj[key])}`,
); );
return `{${keyValuePairs.join(",")}}`; return `{${keyValuePairs.join(",")}}`;
} }
@ -666,7 +689,7 @@ export function getHandleId(
source: string, source: string,
sourceHandle: string, sourceHandle: string,
target: string, target: string,
targetHandle: string targetHandle: string,
) { ) {
return ( return (
"reactflow__edge-" + source + sourceHandle + "-" + target + targetHandle "reactflow__edge-" + source + sourceHandle + "-" + target + targetHandle
@ -677,7 +700,7 @@ export function generateFlow(
selection: OnSelectionChangeParams, selection: OnSelectionChangeParams,
nodes: Node[], nodes: Node[],
edges: Edge[], edges: Edge[],
name: string name: string,
): generateFlowType { ): generateFlowType {
const newFlowData = { nodes, edges, viewport: { zoom: 1, x: 0, y: 0 } }; const newFlowData = { nodes, edges, viewport: { zoom: 1, x: 0, y: 0 } };
const uid = new ShortUniqueId({ length: 5 }); const uid = new ShortUniqueId({ length: 5 });
@ -686,7 +709,7 @@ export function generateFlow(
newFlowData.edges = selection.edges.filter( newFlowData.edges = selection.edges.filter(
(edge) => (edge) =>
selection.nodes.some((node) => node.id === edge.target) && selection.nodes.some((node) => node.id === edge.target) &&
selection.nodes.some((node) => node.id === edge.source) selection.nodes.some((node) => node.id === edge.source),
); );
newFlowData.nodes = selection.nodes; newFlowData.nodes = selection.nodes;
@ -707,7 +730,7 @@ export function generateFlow(
(edge) => (edge) =>
(selection.nodes.some((node) => node.id === edge.target) || (selection.nodes.some((node) => node.id === edge.target) ||
selection.nodes.some((node) => node.id === edge.source)) && selection.nodes.some((node) => node.id === edge.source)) &&
newFlowData.edges.every((e) => e.id !== edge.id) newFlowData.edges.every((e) => e.id !== edge.id),
), ),
}; };
} }
@ -718,13 +741,13 @@ export function reconnectEdges(groupNode: NodeType, excludedEdges: Edge[]) {
const { nodes, edges } = groupNode.data.node!.flow!.data!; const { nodes, edges } = groupNode.data.node!.flow!.data!;
const lastNode = findLastNode(groupNode.data.node!.flow!.data!); const lastNode = findLastNode(groupNode.data.node!.flow!.data!);
newEdges = newEdges.filter( newEdges = newEdges.filter(
(e) => !(nodes.some((n) => n.id === e.source) && e.source !== lastNode?.id) (e) => !(nodes.some((n) => n.id === e.source) && e.source !== lastNode?.id),
); );
newEdges.forEach((edge) => { newEdges.forEach((edge) => {
if (lastNode && edge.source === lastNode.id) { if (lastNode && edge.source === lastNode.id) {
edge.source = groupNode.id; edge.source = groupNode.id;
let newSourceHandle: sourceHandleType = scapeJSONParse( let newSourceHandle: sourceHandleType = scapeJSONParse(
edge.sourceHandle! edge.sourceHandle!,
); );
newSourceHandle.id = groupNode.id; newSourceHandle.id = groupNode.id;
edge.sourceHandle = scapedJSONStringfy(newSourceHandle); edge.sourceHandle = scapedJSONStringfy(newSourceHandle);
@ -751,7 +774,7 @@ export function reconnectEdges(groupNode: NodeType, excludedEdges: Edge[]) {
export function filterFlow( export function filterFlow(
selection: OnSelectionChangeParams, selection: OnSelectionChangeParams,
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void, setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
) { ) {
setNodes((nodes) => nodes.filter((node) => !selection.nodes.includes(node))); setNodes((nodes) => nodes.filter((node) => !selection.nodes.includes(node)));
setEdges((edges) => edges.filter((edge) => !selection.edges.includes(edge))); setEdges((edges) => edges.filter((edge) => !selection.edges.includes(edge)));
@ -789,7 +812,7 @@ export function updateFlowPosition(NewPosition: XYPosition, flow: FlowType) {
export function concatFlows( export function concatFlows(
flow: FlowType, flow: FlowType,
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void, setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
) { ) {
const { nodes, edges } = flow.data!; const { nodes, edges } = flow.data!;
setNodes((old) => [...old, ...nodes]); setNodes((old) => [...old, ...nodes]);
@ -798,7 +821,7 @@ export function concatFlows(
export function validateSelection( export function validateSelection(
selection: OnSelectionChangeParams, selection: OnSelectionChangeParams,
edges: Edge[] edges: Edge[],
): Array<string> { ): Array<string> {
const clonedSelection = cloneDeep(selection); const clonedSelection = cloneDeep(selection);
const clonedEdges = cloneDeep(edges); const clonedEdges = cloneDeep(edges);
@ -812,7 +835,7 @@ export function validateSelection(
let nodesSet = new Set(clonedSelection.nodes.map((n) => n.id)); let nodesSet = new Set(clonedSelection.nodes.map((n) => n.id));
// then filter the edges that are connected to the nodes in the set // then filter the edges that are connected to the nodes in the set
let connectedEdges = clonedSelection.edges.filter( let connectedEdges = clonedSelection.edges.filter(
(e) => nodesSet.has(e.source) && nodesSet.has(e.target) (e) => nodesSet.has(e.source) && nodesSet.has(e.target),
); );
// add the edges to the selection // add the edges to the selection
clonedSelection.edges = connectedEdges; clonedSelection.edges = connectedEdges;
@ -826,17 +849,17 @@ export function validateSelection(
clonedSelection.nodes.some( clonedSelection.nodes.some(
(node) => (node) =>
isInputNode(node.data as NodeDataType) || isInputNode(node.data as NodeDataType) ||
isOutputNode(node.data as NodeDataType) isOutputNode(node.data as NodeDataType),
) )
) { ) {
errorsArray.push( errorsArray.push(
"Please select only nodes that are not input or output nodes" "Please select only nodes that are not input or output nodes",
); );
} }
//check if there are two or more nodes with free outputs //check if there are two or more nodes with free outputs
if ( if (
clonedSelection.nodes.filter( clonedSelection.nodes.filter(
(n) => !clonedSelection.edges.some((e) => e.source === n.id) (n) => !clonedSelection.edges.some((e) => e.source === n.id),
).length > 1 ).length > 1
) { ) {
errorsArray.push("Please select only one node with free outputs"); errorsArray.push("Please select only one node with free outputs");
@ -847,7 +870,7 @@ export function validateSelection(
clonedSelection.nodes.some( clonedSelection.nodes.some(
(node) => (node) =>
!clonedSelection.edges.some((edge) => edge.target === node.id) && !clonedSelection.edges.some((edge) => edge.target === node.id) &&
!clonedSelection.edges.some((edge) => edge.source === node.id) !clonedSelection.edges.some((edge) => edge.source === node.id),
) )
) { ) {
errorsArray.push("Please select only nodes that are connected"); errorsArray.push("Please select only nodes that are connected");
@ -904,8 +927,8 @@ export function mergeNodeTemplates({
nodeTemplate[key].display_name nodeTemplate[key].display_name
? nodeTemplate[key].display_name ? nodeTemplate[key].display_name
: nodeTemplate[key].name : nodeTemplate[key].name
? toTitleCase(nodeTemplate[key].name) ? toTitleCase(nodeTemplate[key].name)
: toTitleCase(key); : toTitleCase(key);
} }
} }
}); });
@ -916,7 +939,7 @@ function isHandleConnected(
edges: Edge[], edges: Edge[],
key: string, key: string,
field: InputFieldType, field: InputFieldType,
nodeId: string nodeId: string,
) { ) {
/* /*
this function receives a flow and a handleId and check if there is a connection with this handle this function receives a flow and a handleId and check if there is a connection with this handle
@ -932,7 +955,7 @@ function isHandleConnected(
id: nodeId, id: nodeId,
proxy: { id: field.proxy!.id, field: field.proxy!.field }, proxy: { id: field.proxy!.id, field: field.proxy!.field },
inputTypes: field.input_types, inputTypes: field.input_types,
} as targetHandleType) } as targetHandleType),
) )
) { ) {
return true; return true;
@ -947,7 +970,7 @@ function isHandleConnected(
fieldName: key, fieldName: key,
id: nodeId, id: nodeId,
inputTypes: field.input_types, inputTypes: field.input_types,
} as targetHandleType) } as targetHandleType),
) )
) { ) {
return true; return true;
@ -970,7 +993,7 @@ export function generateNodeTemplate(Flow: FlowType) {
export function generateNodeFromFlow( export function generateNodeFromFlow(
flow: FlowType, flow: FlowType,
getNodeId: (type: string) => string getNodeId: (type: string) => string,
): NodeType { ): NodeType {
const { nodes } = flow.data!; const { nodes } = flow.data!;
const outputNode = cloneDeep(findLastNode(flow.data!)); const outputNode = cloneDeep(findLastNode(flow.data!));
@ -1001,7 +1024,7 @@ export function generateNodeFromFlow(
export function connectedInputNodesOnHandle( export function connectedInputNodesOnHandle(
nodeId: string, nodeId: string,
handleId: string, handleId: string,
{ nodes, edges }: { nodes: NodeType[]; edges: Edge[] } { nodes, edges }: { nodes: NodeType[]; edges: Edge[] },
) { ) {
const connectedNodes: Array<{ name: string; id: string; isGroup: boolean }> = const connectedNodes: Array<{ name: string; id: string; isGroup: boolean }> =
[]; [];
@ -1038,7 +1061,7 @@ export function connectedInputNodesOnHandle(
export function updateProxyIdsOnTemplate( export function updateProxyIdsOnTemplate(
template: APITemplateType, template: APITemplateType,
idsMap: { [key: string]: string } idsMap: { [key: string]: string },
) { ) {
Object.keys(template).forEach((key) => { Object.keys(template).forEach((key) => {
if (template[key].proxy && idsMap[template[key].proxy!.id]) { if (template[key].proxy && idsMap[template[key].proxy!.id]) {
@ -1049,7 +1072,7 @@ export function updateProxyIdsOnTemplate(
export function updateEdgesIds( export function updateEdgesIds(
edges: Edge[], edges: Edge[],
idsMap: { [key: string]: string } idsMap: { [key: string]: string },
) { ) {
edges.forEach((edge) => { edges.forEach((edge) => {
let targetHandle: targetHandleType = edge.data.targetHandle; let targetHandle: targetHandleType = edge.data.targetHandle;
@ -1090,7 +1113,7 @@ export function expandGroupNode(
nodes: Node[], nodes: Node[],
edges: Edge[], edges: Edge[],
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void, setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
) { ) {
const idsMap = updateIds(flow!.data!); const idsMap = updateIds(flow!.data!);
updateProxyIdsOnTemplate(template, idsMap); updateProxyIdsOnTemplate(template, idsMap);
@ -1133,7 +1156,7 @@ export function expandGroupNode(
const lastNode = cloneDeep(findLastNode(flow!.data!)); const lastNode = cloneDeep(findLastNode(flow!.data!));
newEdge.source = lastNode!.id; newEdge.source = lastNode!.id;
let newSourceHandle: sourceHandleType = scapeJSONParse( let newSourceHandle: sourceHandleType = scapeJSONParse(
newEdge.sourceHandle! newEdge.sourceHandle!,
); );
newSourceHandle.id = lastNode!.id; newSourceHandle.id = lastNode!.id;
newEdge.data.sourceHandle = newSourceHandle; newEdge.data.sourceHandle = newSourceHandle;
@ -1190,7 +1213,7 @@ export function expandGroupNode(
export function getGroupStatus( export function getGroupStatus(
flow: FlowType, flow: FlowType,
ssData: { [key: string]: { valid: boolean; params: string } } ssData: { [key: string]: { valid: boolean; params: string } },
) { ) {
let status = { valid: true, params: SUCCESS_BUILD }; let status = { valid: true, params: SUCCESS_BUILD };
const { nodes } = flow.data!; const { nodes } = flow.data!;
@ -1209,7 +1232,7 @@ export function getGroupStatus(
export function createFlowComponent( export function createFlowComponent(
nodeData: NodeDataType, nodeData: NodeDataType,
version: string version: string,
): FlowType { ): FlowType {
const flowNode: FlowType = { const flowNode: FlowType = {
data: { data: {
@ -1245,7 +1268,7 @@ export function downloadNode(NodeFLow: FlowType) {
export function updateComponentNameAndType( export function updateComponentNameAndType(
data: any, data: any,
component: NodeDataType component: NodeDataType,
) {} ) {}
export function removeFileNameFromComponents(flow: FlowType) { export function removeFileNameFromComponents(flow: FlowType) {
@ -1319,7 +1342,7 @@ export function extractFieldsFromComponenents(data: APIObjectType) {
export function downloadFlow( export function downloadFlow(
flow: FlowType, flow: FlowType,
flowName: string, flowName: string,
flowDescription?: string flowDescription?: string,
) { ) {
let clonedFlow = cloneDeep(flow); let clonedFlow = cloneDeep(flow);
removeFileNameFromComponents(clonedFlow); removeFileNameFromComponents(clonedFlow);
@ -1329,7 +1352,7 @@ export function downloadFlow(
...clonedFlow, ...clonedFlow,
name: flowName, name: flowName,
description: flowDescription, description: flowDescription,
}) }),
)}`; )}`;
// create a link element and set its properties // create a link element and set its properties
@ -1344,7 +1367,7 @@ export function downloadFlow(
export function downloadFlows() { export function downloadFlows() {
downloadFlowsFromDatabase().then((flows) => { downloadFlowsFromDatabase().then((flows) => {
const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent( const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
JSON.stringify(flows) JSON.stringify(flows),
)}`; )}`;
// create a link element and set its properties // create a link element and set its properties
@ -1368,7 +1391,7 @@ export function getRandomDescription(): string {
export const createNewFlow = ( export const createNewFlow = (
flowData: ReactFlowJsonObject, flowData: ReactFlowJsonObject,
flow: FlowType, flow: FlowType,
folderId: string folderId: string,
) => { ) => {
return { return {
description: flow?.description ?? getRandomDescription(), description: flow?.description ?? getRandomDescription(),