fix backward compability
This commit is contained in:
parent
f705995311
commit
4727cae10e
7 changed files with 196 additions and 214 deletions
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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!),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
||||||
|
|
|
||||||
|
|
@ -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(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue