Merge remote-tracking branch 'origin/dev' into authentication
This commit is contained in:
commit
f065a46950
36 changed files with 865 additions and 564 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from langflow.utils.logger import logger
|
from langflow.utils.logger import logger
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from alembic.util.exc import CommandError
|
||||||
from sqlmodel import Session
|
from sqlmodel import Session
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
@ -13,7 +13,23 @@ def initialize_database():
|
||||||
from langflow.services import service_manager, ServiceType
|
from langflow.services import service_manager, ServiceType
|
||||||
|
|
||||||
database_manager = service_manager.get(ServiceType.DATABASE_MANAGER)
|
database_manager = service_manager.get(ServiceType.DATABASE_MANAGER)
|
||||||
database_manager.run_migrations()
|
try:
|
||||||
|
database_manager.run_migrations()
|
||||||
|
except CommandError as exc:
|
||||||
|
if "Can't locate revision identified by" not in str(exc):
|
||||||
|
raise exc
|
||||||
|
# This means there's wrong revision in the DB
|
||||||
|
# We need to delete the alembic_version table
|
||||||
|
# and run the migrations again
|
||||||
|
logger.warning(
|
||||||
|
"Wrong revision in DB, deleting alembic_version table and running migrations again"
|
||||||
|
)
|
||||||
|
with session_getter(database_manager) as session:
|
||||||
|
session.execute("DROP TABLE alembic_version")
|
||||||
|
database_manager.run_migrations()
|
||||||
|
except Exception as exc:
|
||||||
|
logger.error(f"Error running migrations: {exc}")
|
||||||
|
raise RuntimeError("Error running migrations") from exc
|
||||||
database_manager.create_db_and_tables()
|
database_manager.create_db_and_tables()
|
||||||
logger.debug("Database initialized")
|
logger.debug("Database initialized")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ class DocumentLoaderFrontNode(FrontendNode):
|
||||||
"UnstructuredEmailLoader": build_file_field(
|
"UnstructuredEmailLoader": build_file_field(
|
||||||
suffixes=[".eml"], fileTypes=["eml"]
|
suffixes=[".eml"], fileTypes=["eml"]
|
||||||
),
|
),
|
||||||
"SlackDirectoryLoader": build_file_field(suffixes=[".zip"], fileTypes=["zip"]),
|
|
||||||
"EverNoteLoader": build_file_field(suffixes=[".xml"], fileTypes=["xml"]),
|
"EverNoteLoader": build_file_field(suffixes=[".xml"], fileTypes=["xml"]),
|
||||||
"FacebookChatLoader": build_file_field(suffixes=[".json"], fileTypes=["json"]),
|
"FacebookChatLoader": build_file_field(suffixes=[".json"], fileTypes=["json"]),
|
||||||
"BSHTMLLoader": build_file_field(suffixes=[".html"], fileTypes=["html"]),
|
"BSHTMLLoader": build_file_field(suffixes=[".html"], fileTypes=["html"]),
|
||||||
|
|
@ -105,7 +104,30 @@ class DocumentLoaderFrontNode(FrontendNode):
|
||||||
advanced=False,
|
advanced=False,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
elif self.template.type_name in {"SlackDirectoryLoader"}:
|
||||||
|
self.template.add_field(
|
||||||
|
TemplateField(
|
||||||
|
field_type="file",
|
||||||
|
required=True,
|
||||||
|
show=True,
|
||||||
|
name="zip_path",
|
||||||
|
value="",
|
||||||
|
display_name="Path to zip file",
|
||||||
|
suffixes=[".zip"],
|
||||||
|
file_types=["zip"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.template.add_field(
|
||||||
|
TemplateField(
|
||||||
|
field_type="str",
|
||||||
|
required=False,
|
||||||
|
show=True,
|
||||||
|
name="workspace_url",
|
||||||
|
value="",
|
||||||
|
display_name="Workspace URL",
|
||||||
|
advanced=False,
|
||||||
|
)
|
||||||
|
)
|
||||||
elif self.template.type_name in self.file_path_templates:
|
elif self.template.type_name in self.file_path_templates:
|
||||||
self.template.add_field(self.file_path_templates[self.template.type_name])
|
self.template.add_field(self.file_path_templates[self.template.type_name])
|
||||||
elif self.template.type_name in {
|
elif self.template.type_name in {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
import React, {
|
||||||
|
ReactNode,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
||||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
||||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||||
|
|
@ -17,6 +23,7 @@ import { TOOLTIP_EMPTY } from "../../../../constants/constants";
|
||||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||||
import { typesContext } from "../../../../contexts/typesContext";
|
import { typesContext } from "../../../../contexts/typesContext";
|
||||||
import { ParameterComponentType } from "../../../../types/components";
|
import { ParameterComponentType } from "../../../../types/components";
|
||||||
|
import { TabsState } from "../../../../types/tabs";
|
||||||
import { isValidConnection } from "../../../../utils/reactflowUtils";
|
import { isValidConnection } from "../../../../utils/reactflowUtils";
|
||||||
import {
|
import {
|
||||||
nodeColors,
|
nodeColors,
|
||||||
|
|
@ -38,15 +45,15 @@ export default function ParameterComponent({
|
||||||
required = false,
|
required = false,
|
||||||
optionalHandle = null,
|
optionalHandle = null,
|
||||||
info = "",
|
info = "",
|
||||||
}: ParameterComponentType) {
|
}: ParameterComponentType): JSX.Element {
|
||||||
const ref = useRef(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const refHtml = useRef(null);
|
const refHtml = useRef<HTMLDivElement & ReactNode>(null);
|
||||||
const infoHtml = useRef(null);
|
const infoHtml = useRef<HTMLDivElement & ReactNode>(null);
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
const [position, setPosition] = useState(0);
|
const [position, setPosition] = useState(0);
|
||||||
const { setTabsState, tabId, save, flows } = useContext(TabsContext);
|
const { setTabsState, tabId, save, flows } = useContext(TabsContext);
|
||||||
|
|
||||||
const flow = flows.find((f) => f.id === tabId).data?.nodes ?? null;
|
const flow = flows.find((flow) => flow.id === tabId)?.data?.nodes ?? null;
|
||||||
|
|
||||||
// Update component position
|
// Update component position
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -62,16 +69,18 @@ export default function ParameterComponent({
|
||||||
|
|
||||||
const { reactFlowInstance } = useContext(typesContext);
|
const { reactFlowInstance } = useContext(typesContext);
|
||||||
let disabled =
|
let disabled =
|
||||||
reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false;
|
reactFlowInstance?.getEdges().some((edge) => edge.targetHandle === id) ??
|
||||||
|
false;
|
||||||
|
|
||||||
const { data: myData } = useContext(typesContext);
|
const { data: myData } = useContext(typesContext);
|
||||||
|
|
||||||
const handleOnNewValue = (newValue: any) => {
|
const handleOnNewValue = (newValue: string | string[] | boolean): void => {
|
||||||
let newData = cloneDeep(data);
|
let newData = cloneDeep(data);
|
||||||
newData.node.template[name].value = newValue;
|
newData.node!.template[name].value = newValue;
|
||||||
setData(newData);
|
setData(newData);
|
||||||
// Set state to pending
|
// Set state to pending
|
||||||
setTabsState((prev) => {
|
//@ts-ignore
|
||||||
|
setTabsState((prev: TabsState) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
[tabId]: {
|
[tabId]: {
|
||||||
|
|
@ -86,10 +95,11 @@ export default function ParameterComponent({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (name === "openai_api_base") console.log(info);
|
if (name === "openai_api_base") console.log(info);
|
||||||
|
// @ts-ignore
|
||||||
infoHtml.current = (
|
infoHtml.current = (
|
||||||
<div className="h-full w-full word-break-break-word">
|
<div className="h-full w-full break-words">
|
||||||
{info.split("\n").map((line, i) => (
|
{info.split("\n").map((line, index) => (
|
||||||
<p key={i} className="block">
|
<p key={index} className="block">
|
||||||
{line}
|
{line}
|
||||||
</p>
|
</p>
|
||||||
))}
|
))}
|
||||||
|
|
@ -98,18 +108,19 @@ export default function ParameterComponent({
|
||||||
}, [info]);
|
}, [info]);
|
||||||
|
|
||||||
function renderTooltips() {
|
function renderTooltips() {
|
||||||
let groupedObj = groupByFamily(myData, tooltipTitle, left, flow);
|
let groupedObj = groupByFamily(myData, tooltipTitle!, left, flow!);
|
||||||
|
|
||||||
if (groupedObj && groupedObj.length > 0) {
|
if (groupedObj && groupedObj.length > 0) {
|
||||||
refHtml.current = groupedObj.map((item, i) => {
|
//@ts-ignore
|
||||||
|
refHtml.current = groupedObj.map((item, index) => {
|
||||||
const Icon: any =
|
const Icon: any =
|
||||||
nodeIconsLucide[item.family] ?? nodeIconsLucide["unknown"];
|
nodeIconsLucide[item.family] ?? nodeIconsLucide["unknown"];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
key={i}
|
key={index}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
i > 0 ? "mt-2 flex items-center" : "flex items-center"
|
index > 0 ? "mt-2 flex items-center" : "flex items-center"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
@ -132,10 +143,10 @@ export default function ParameterComponent({
|
||||||
{" "}
|
{" "}
|
||||||
{item.type === "" ? "" : " - "}
|
{item.type === "" ? "" : " - "}
|
||||||
{item.type.split(", ").length > 2
|
{item.type.split(", ").length > 2
|
||||||
? item.type.split(", ").map((el, i) => (
|
? item.type.split(", ").map((el, index) => (
|
||||||
<React.Fragment key={el + i}>
|
<React.Fragment key={el + index}>
|
||||||
<span>
|
<span>
|
||||||
{i === item.type.split(", ").length - 1
|
{index === item.type.split(", ").length - 1
|
||||||
? el
|
? el
|
||||||
: (el += `, `)}
|
: (el += `, `)}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -148,6 +159,7 @@ export default function ParameterComponent({
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
//@ts-ignore
|
||||||
refHtml.current = <span>{TOOLTIP_EMPTY}</span>;
|
refHtml.current = <span>{TOOLTIP_EMPTY}</span>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +219,7 @@ export default function ParameterComponent({
|
||||||
position={left ? Position.Left : Position.Right}
|
position={left ? Position.Left : Position.Right}
|
||||||
id={id}
|
id={id}
|
||||||
isValidConnection={(connection) =>
|
isValidConnection={(connection) =>
|
||||||
isValidConnection(connection, reactFlowInstance)
|
isValidConnection(connection, reactFlowInstance!)
|
||||||
}
|
}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
left ? "-ml-0.5 " : "-mr-0.5 ",
|
left ? "-ml-0.5 " : "-mr-0.5 ",
|
||||||
|
|
@ -223,9 +235,9 @@ export default function ParameterComponent({
|
||||||
|
|
||||||
{left === true &&
|
{left === true &&
|
||||||
type === "str" &&
|
type === "str" &&
|
||||||
!data.node.template[name].options ? (
|
!data.node?.template[name].options ? (
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
{data.node.template[name].list ? (
|
{data.node?.template[name].list ? (
|
||||||
<InputListComponent
|
<InputListComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={
|
value={
|
||||||
|
|
@ -236,7 +248,7 @@ export default function ParameterComponent({
|
||||||
}
|
}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
/>
|
/>
|
||||||
) : data.node.template[name].multiline ? (
|
) : data.node?.template[name].multiline ? (
|
||||||
<TextAreaComponent
|
<TextAreaComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
|
|
@ -245,8 +257,8 @@ export default function ParameterComponent({
|
||||||
) : (
|
) : (
|
||||||
<InputComponent
|
<InputComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
password={data.node.template[name].password ?? false}
|
password={data.node?.template[name].password ?? false}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
@ -255,9 +267,9 @@ export default function ParameterComponent({
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
enabled={data.node.template[name].value ?? false}
|
enabled={data.node?.template[name].value ?? false}
|
||||||
setEnabled={(t) => {
|
setEnabled={(isEnabled) => {
|
||||||
handleOnNewValue(t);
|
handleOnNewValue(isEnabled);
|
||||||
}}
|
}}
|
||||||
size="large"
|
size="large"
|
||||||
/>
|
/>
|
||||||
|
|
@ -266,13 +278,13 @@ export default function ParameterComponent({
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<FloatComponent
|
<FloatComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : left === true &&
|
) : left === true &&
|
||||||
type === "str" &&
|
type === "str" &&
|
||||||
data.node.template[name].options ? (
|
data.node?.template[name].options ? (
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
options={data.node.template[name].options}
|
options={data.node.template[name].options}
|
||||||
|
|
@ -283,13 +295,13 @@ export default function ParameterComponent({
|
||||||
) : left === true && type === "code" ? (
|
) : left === true && type === "code" ? (
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<CodeAreaComponent
|
<CodeAreaComponent
|
||||||
dynamic={data.node.template[name].dynamic ?? false}
|
dynamic={data.node?.template[name].dynamic ?? false}
|
||||||
setNodeClass={(nodeClass) => {
|
setNodeClass={(nodeClass) => {
|
||||||
data.node = nodeClass;
|
data.node = nodeClass;
|
||||||
}}
|
}}
|
||||||
nodeClass={data.node}
|
nodeClass={data.node}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -297,12 +309,12 @@ export default function ParameterComponent({
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<InputFileComponent
|
<InputFileComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
fileTypes={data.node.template[name].fileTypes}
|
fileTypes={data.node?.template[name].fileTypes}
|
||||||
suffixes={data.node.template[name].suffixes}
|
suffixes={data.node?.template[name].suffixes}
|
||||||
onFileChange={(t: string) => {
|
onFileChange={(filePath: string) => {
|
||||||
data.node.template[name].file_path = t;
|
data.node!.template[name].file_path = filePath;
|
||||||
save();
|
save();
|
||||||
}}
|
}}
|
||||||
></InputFileComponent>
|
></InputFileComponent>
|
||||||
|
|
@ -311,7 +323,7 @@ export default function ParameterComponent({
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<IntComponent
|
<IntComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -324,7 +336,7 @@ export default function ParameterComponent({
|
||||||
}}
|
}}
|
||||||
nodeClass={data.node}
|
nodeClass={data.node}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -159,52 +159,59 @@ export default function GenericNode({
|
||||||
|
|
||||||
<>
|
<>
|
||||||
{Object.keys(data.node.template)
|
{Object.keys(data.node.template)
|
||||||
.filter((t) => t.charAt(0) !== "_")
|
.filter((templateField) => templateField.charAt(0) !== "_")
|
||||||
.map((t: string, idx) => (
|
.map((templateField: string, idx) => (
|
||||||
<div key={idx}>
|
<div key={idx}>
|
||||||
{data.node.template[t].show &&
|
{data.node.template[templateField].show &&
|
||||||
!data.node.template[t].advanced ? (
|
!data.node.template[templateField].advanced ? (
|
||||||
<ParameterComponent
|
<ParameterComponent
|
||||||
key={
|
key={
|
||||||
(data.node.template[t].input_types?.join(";") ??
|
(data.node.template[templateField].input_types?.join(
|
||||||
data.node.template[t].type) +
|
";"
|
||||||
|
) ?? data.node.template[templateField].type) +
|
||||||
"|" +
|
"|" +
|
||||||
t +
|
templateField +
|
||||||
"|" +
|
"|" +
|
||||||
data.id
|
data.id
|
||||||
}
|
}
|
||||||
data={data}
|
data={data}
|
||||||
setData={setData}
|
setData={setData}
|
||||||
color={
|
color={
|
||||||
nodeColors[types[data.node.template[t].type]] ??
|
nodeColors[
|
||||||
nodeColors[data.node.template[t].type] ??
|
types[data.node.template[templateField].type]
|
||||||
|
] ??
|
||||||
|
nodeColors[data.node.template[templateField].type] ??
|
||||||
nodeColors.unknown
|
nodeColors.unknown
|
||||||
}
|
}
|
||||||
title={
|
title={
|
||||||
data.node.template[t].display_name
|
data.node.template[templateField].display_name
|
||||||
? data.node.template[t].display_name
|
? data.node.template[templateField].display_name
|
||||||
: data.node.template[t].name
|
: data.node.template[templateField].name
|
||||||
? toTitleCase(data.node.template[t].name)
|
? toTitleCase(data.node.template[templateField].name)
|
||||||
: toTitleCase(t)
|
: toTitleCase(templateField)
|
||||||
}
|
}
|
||||||
info={data.node.template[t].info}
|
info={data.node.template[templateField].info}
|
||||||
name={t}
|
name={templateField}
|
||||||
tooltipTitle={
|
tooltipTitle={
|
||||||
data.node.template[t].input_types?.join("\n") ??
|
data.node.template[templateField].input_types?.join(
|
||||||
data.node.template[t].type
|
"\n"
|
||||||
|
) ?? data.node.template[templateField].type
|
||||||
}
|
}
|
||||||
required={data.node.template[t].required}
|
required={data.node.template[templateField].required}
|
||||||
id={
|
id={
|
||||||
(data.node.template[t].input_types?.join(";") ??
|
(data.node.template[templateField].input_types?.join(
|
||||||
data.node.template[t].type) +
|
";"
|
||||||
|
) ?? data.node.template[templateField].type) +
|
||||||
"|" +
|
"|" +
|
||||||
t +
|
templateField +
|
||||||
"|" +
|
"|" +
|
||||||
data.id
|
data.id
|
||||||
}
|
}
|
||||||
left={true}
|
left={true}
|
||||||
type={data.node.template[t].type}
|
type={data.node.template[templateField].type}
|
||||||
optionalHandle={data.node.template[t].input_types}
|
optionalHandle={
|
||||||
|
data.node.template[templateField].input_types
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,9 @@ export default function AlertDropdown({ children }: AlertDropdownType) {
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
open={open}
|
open={open}
|
||||||
onOpenChange={(k) => {
|
onOpenChange={(target) => {
|
||||||
setOpen(k);
|
setOpen(target);
|
||||||
if (k) setNotificationCenter(false);
|
if (target) setNotificationCenter(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PopoverTrigger>{children}</PopoverTrigger>
|
<PopoverTrigger>{children}</PopoverTrigger>
|
||||||
|
|
|
||||||
|
|
@ -55,12 +55,12 @@ export const EditFlowSettings: React.FC<InputProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const [desc, setDesc] = useState(
|
const [desc, setDesc] = useState(
|
||||||
flows.find((f) => f.id === tabId).description
|
flows.find((flow) => flow.id === tabId).description
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDescriptionChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
|
const handleDescriptionChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
flows.find((f) => f.id === tabId).description = event.target.value;
|
flows.find((flow) => flow.id === tabId).description = event.target.value;
|
||||||
setDesc(flows.find((f) => f.id === tabId).description);
|
setDesc(flows.find((flow) => flow.id === tabId).description);
|
||||||
setDescription(event.target.value);
|
setDescription(event.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,9 @@ export default function CodeAreaComponent({
|
||||||
value={myValue}
|
value={myValue}
|
||||||
nodeClass={nodeClass}
|
nodeClass={nodeClass}
|
||||||
setNodeClass={setNodeClass}
|
setNodeClass={setNodeClass}
|
||||||
setValue={(t: string) => {
|
setValue={(value: string) => {
|
||||||
setMyValue(t);
|
setMyValue(value);
|
||||||
onChange(t);
|
onChange(value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex w-full items-center">
|
<div className="flex w-full items-center">
|
||||||
|
|
|
||||||
|
|
@ -205,13 +205,15 @@ export default function CodeTabsComponent({
|
||||||
: "overflow-hidden"
|
: "overflow-hidden"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{data.map((t: any, index) => (
|
{data.map((node: any, index) => (
|
||||||
<div className="px-3" key={index}>
|
<div className="px-3" key={index}>
|
||||||
{tweaks.tweaksList.current.includes(t["data"]["id"]) && (
|
{tweaks.tweaksList.current.includes(
|
||||||
|
node["data"]["id"]
|
||||||
|
) && (
|
||||||
<AccordionComponent
|
<AccordionComponent
|
||||||
trigger={t["data"]["id"]}
|
trigger={node["data"]["id"]}
|
||||||
open={openAccordion}
|
open={openAccordion}
|
||||||
keyValue={t["data"]["id"]}
|
keyValue={node["data"]["id"]}
|
||||||
>
|
>
|
||||||
<div className="api-modal-table-arrangement">
|
<div className="api-modal-table-arrangement">
|
||||||
<Table className="table-fixed bg-muted outline-1">
|
<Table className="table-fixed bg-muted outline-1">
|
||||||
|
|
@ -226,78 +228,92 @@ export default function CodeTabsComponent({
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody className="p-0">
|
<TableBody className="p-0">
|
||||||
{Object.keys(t["data"]["node"]["template"])
|
{Object.keys(node["data"]["node"]["template"])
|
||||||
.filter(
|
.filter(
|
||||||
(n) =>
|
(templateField) =>
|
||||||
n.charAt(0) !== "_" &&
|
templateField.charAt(0) !== "_" &&
|
||||||
t.data.node.template[n].show &&
|
node.data.node.template[templateField]
|
||||||
(t.data.node.template[n].type === "str" ||
|
.show &&
|
||||||
t.data.node.template[n].type ===
|
(node.data.node.template[templateField]
|
||||||
"bool" ||
|
.type === "str" ||
|
||||||
t.data.node.template[n].type ===
|
node.data.node.template[templateField]
|
||||||
"float" ||
|
.type === "bool" ||
|
||||||
t.data.node.template[n].type ===
|
node.data.node.template[templateField]
|
||||||
"code" ||
|
.type === "float" ||
|
||||||
t.data.node.template[n].type ===
|
node.data.node.template[templateField]
|
||||||
"prompt" ||
|
.type === "code" ||
|
||||||
t.data.node.template[n].type ===
|
node.data.node.template[templateField]
|
||||||
"file" ||
|
.type === "prompt" ||
|
||||||
t.data.node.template[n].type === "int")
|
node.data.node.template[templateField]
|
||||||
|
.type === "file" ||
|
||||||
|
node.data.node.template[templateField]
|
||||||
|
.type === "int")
|
||||||
)
|
)
|
||||||
.map((n, i) => {
|
.map((templateField, index) => {
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
key={i}
|
key={index}
|
||||||
className="h-10 dark:border-b-muted"
|
className="h-10 dark:border-b-muted"
|
||||||
>
|
>
|
||||||
<TableCell className="p-0 text-center text-sm text-foreground">
|
<TableCell className="p-0 text-center text-sm text-foreground">
|
||||||
{n}
|
{templateField}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="p-0 text-xs text-foreground">
|
<TableCell className="p-0 text-xs text-foreground">
|
||||||
<div className="m-auto w-[250px]">
|
<div className="m-auto w-[250px]">
|
||||||
{t.data.node.template[n].type ===
|
{node.data.node.template[
|
||||||
"str" &&
|
templateField
|
||||||
!t.data.node.template[n].options ? (
|
].type === "str" &&
|
||||||
|
!node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].options ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
{t.data.node.template[n]
|
{node.data.node.template[
|
||||||
.list ? (
|
templateField
|
||||||
|
].list ? (
|
||||||
<InputListComponent
|
<InputListComponent
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
value={
|
value={
|
||||||
!t.data.node.template[n]
|
!node.data.node.template[
|
||||||
.value ||
|
templateField
|
||||||
t.data.node.template[n]
|
].value ||
|
||||||
.value === ""
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
? [""]
|
? [""]
|
||||||
: t.data.node.template[
|
: node.data.node
|
||||||
n
|
.template[
|
||||||
|
templateField
|
||||||
].value
|
].value
|
||||||
}
|
}
|
||||||
onChange={(k) => {
|
onChange={(target) => {
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
let newInputList =
|
let newInputList =
|
||||||
cloneDeep(old);
|
cloneDeep(old);
|
||||||
newInputList[
|
newInputList[
|
||||||
index
|
index
|
||||||
].data.node.template[
|
].data.node.template[
|
||||||
n
|
templateField
|
||||||
].value = k;
|
].value = target;
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
tweaks.buildTweakObject(
|
tweaks.buildTweakObject(
|
||||||
t["data"]["id"],
|
node["data"]["id"],
|
||||||
k,
|
target,
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : t.data.node.template[n]
|
) : node.data.node.template[
|
||||||
.multiline ? (
|
templateField
|
||||||
|
].multiline ? (
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={tweaks.buildContent(
|
content={tweaks.buildContent(
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
.value
|
templateField
|
||||||
|
].value
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -305,33 +321,38 @@ export default function CodeTabsComponent({
|
||||||
disabled={false}
|
disabled={false}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
!t.data.node.template[
|
!node.data.node
|
||||||
n
|
.template[
|
||||||
|
templateField
|
||||||
].value ||
|
].value ||
|
||||||
t.data.node.template[
|
node.data.node
|
||||||
n
|
.template[
|
||||||
|
templateField
|
||||||
].value === ""
|
].value === ""
|
||||||
? ""
|
? ""
|
||||||
: t.data.node
|
: node.data.node
|
||||||
.template[n]
|
.template[
|
||||||
.value
|
templateField
|
||||||
|
].value
|
||||||
}
|
}
|
||||||
onChange={(k) => {
|
onChange={(target) => {
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
let newInputList =
|
let newInputList =
|
||||||
cloneDeep(old);
|
cloneDeep(old);
|
||||||
newInputList[
|
newInputList[
|
||||||
index
|
index
|
||||||
].data.node.template[
|
].data.node.template[
|
||||||
n
|
templateField
|
||||||
].value = k;
|
].value = target;
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
tweaks.buildTweakObject(
|
tweaks.buildTweakObject(
|
||||||
t["data"]["id"],
|
node["data"]["id"],
|
||||||
k,
|
target,
|
||||||
t.data.node
|
node.data.node
|
||||||
.template[n]
|
.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -342,47 +363,55 @@ export default function CodeTabsComponent({
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
password={
|
password={
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
.password ?? false
|
templateField
|
||||||
|
].password ?? false
|
||||||
}
|
}
|
||||||
value={
|
value={
|
||||||
!t.data.node.template[n]
|
!node.data.node.template[
|
||||||
.value ||
|
templateField
|
||||||
t.data.node.template[n]
|
].value ||
|
||||||
.value === ""
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
? ""
|
? ""
|
||||||
: t.data.node.template[
|
: node.data.node
|
||||||
n
|
.template[
|
||||||
|
templateField
|
||||||
].value
|
].value
|
||||||
}
|
}
|
||||||
onChange={(k) => {
|
onChange={(target) => {
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
let newInputList =
|
let newInputList =
|
||||||
cloneDeep(old);
|
cloneDeep(old);
|
||||||
newInputList[
|
newInputList[
|
||||||
index
|
index
|
||||||
].data.node.template[
|
].data.node.template[
|
||||||
n
|
templateField
|
||||||
].value = k;
|
].value = target;
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
tweaks.buildTweakObject(
|
tweaks.buildTweakObject(
|
||||||
t["data"]["id"],
|
node["data"]["id"],
|
||||||
k,
|
target,
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : t.data.node.template[n].type ===
|
) : node.data.node.template[
|
||||||
"bool" ? (
|
templateField
|
||||||
|
].type === "bool" ? (
|
||||||
<div className="ml-auto">
|
<div className="ml-auto">
|
||||||
{" "}
|
{" "}
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
enabled={
|
enabled={
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
.value
|
templateField
|
||||||
|
].value
|
||||||
}
|
}
|
||||||
setEnabled={(e) => {
|
setEnabled={(e) => {
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
|
|
@ -391,31 +420,37 @@ export default function CodeTabsComponent({
|
||||||
newInputList[
|
newInputList[
|
||||||
index
|
index
|
||||||
].data.node.template[
|
].data.node.template[
|
||||||
n
|
templateField
|
||||||
].value = e;
|
].value = e;
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
tweaks.buildTweakObject(
|
tweaks.buildTweakObject(
|
||||||
t["data"]["id"],
|
node["data"]["id"],
|
||||||
e,
|
e,
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
disabled={false}
|
disabled={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : t.data.node.template[n].type ===
|
) : node.data.node.template[
|
||||||
"file" ? (
|
templateField
|
||||||
|
].type === "file" ? (
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={tweaks.buildContent(
|
content={tweaks.buildContent(
|
||||||
!t.data.node.template[n]
|
!node.data.node.template[
|
||||||
.value ||
|
templateField
|
||||||
t.data.node.template[n]
|
].value ||
|
||||||
.value === ""
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
? ""
|
? ""
|
||||||
: t.data.node.template[n]
|
: node.data.node.template[
|
||||||
.value
|
templateField
|
||||||
|
].value
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
|
|
@ -423,147 +458,176 @@ export default function CodeTabsComponent({
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
value={
|
value={
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
.value ?? ""
|
templateField
|
||||||
|
].value ?? ""
|
||||||
}
|
}
|
||||||
onChange={(k: any) => {}}
|
onChange={(
|
||||||
|
target: any
|
||||||
|
) => {}}
|
||||||
fileTypes={
|
fileTypes={
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
.fileTypes
|
templateField
|
||||||
|
].fileTypes
|
||||||
}
|
}
|
||||||
suffixes={
|
suffixes={
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
.suffixes
|
templateField
|
||||||
|
].suffixes
|
||||||
}
|
}
|
||||||
onFileChange={(
|
onFileChange={(
|
||||||
value: any
|
value: any
|
||||||
) => {
|
) => {
|
||||||
t.data.node.template[
|
node.data.node.template[
|
||||||
n
|
templateField
|
||||||
].file_path = value;
|
].file_path = value;
|
||||||
}}
|
}}
|
||||||
></InputFileComponent>
|
></InputFileComponent>
|
||||||
</div>
|
</div>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
) : t.data.node.template[n].type ===
|
) : node.data.node.template[
|
||||||
"float" ? (
|
templateField
|
||||||
|
].type === "float" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<FloatComponent
|
<FloatComponent
|
||||||
disabled={false}
|
disabled={false}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
!t.data.node.template[n]
|
!node.data.node.template[
|
||||||
.value ||
|
templateField
|
||||||
t.data.node.template[n]
|
].value ||
|
||||||
.value === ""
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
? ""
|
? ""
|
||||||
: t.data.node.template[n]
|
: node.data.node.template[
|
||||||
.value
|
templateField
|
||||||
|
].value
|
||||||
}
|
}
|
||||||
onChange={(k) => {
|
onChange={(target) => {
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
let newInputList =
|
let newInputList =
|
||||||
cloneDeep(old);
|
cloneDeep(old);
|
||||||
newInputList[
|
newInputList[
|
||||||
index
|
index
|
||||||
].data.node.template[
|
].data.node.template[
|
||||||
n
|
templateField
|
||||||
].value = k;
|
].value = target;
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
tweaks.buildTweakObject(
|
tweaks.buildTweakObject(
|
||||||
t["data"]["id"],
|
node["data"]["id"],
|
||||||
k,
|
target,
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : t.data.node.template[n].type ===
|
) : node.data.node.template[
|
||||||
"str" &&
|
templateField
|
||||||
t.data.node.template[n]
|
].type === "str" &&
|
||||||
.options ? (
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].options ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
editNode={true}
|
editNode={true}
|
||||||
apiModal={true}
|
apiModal={true}
|
||||||
options={
|
options={
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
.options
|
templateField
|
||||||
|
].options
|
||||||
}
|
}
|
||||||
onSelect={(k) => {
|
onSelect={(target) => {
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
let newInputList =
|
let newInputList =
|
||||||
cloneDeep(old);
|
cloneDeep(old);
|
||||||
newInputList[
|
newInputList[
|
||||||
index
|
index
|
||||||
].data.node.template[
|
].data.node.template[
|
||||||
n
|
templateField
|
||||||
].value = k;
|
].value = target;
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
tweaks.buildTweakObject(
|
tweaks.buildTweakObject(
|
||||||
t["data"]["id"],
|
node["data"]["id"],
|
||||||
k,
|
target,
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
value={
|
value={
|
||||||
!t.data.node.template[n]
|
!node.data.node.template[
|
||||||
.value ||
|
templateField
|
||||||
t.data.node.template[n]
|
].value ||
|
||||||
.value === ""
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
? ""
|
? ""
|
||||||
: t.data.node.template[n]
|
: node.data.node.template[
|
||||||
.value
|
templateField
|
||||||
|
].value
|
||||||
}
|
}
|
||||||
></Dropdown>
|
></Dropdown>
|
||||||
</div>
|
</div>
|
||||||
) : t.data.node.template[n].type ===
|
) : node.data.node.template[
|
||||||
"int" ? (
|
templateField
|
||||||
|
].type === "int" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<IntComponent
|
<IntComponent
|
||||||
disabled={false}
|
disabled={false}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
!t.data.node.template[n]
|
!node.data.node.template[
|
||||||
.value ||
|
templateField
|
||||||
t.data.node.template[n]
|
].value ||
|
||||||
.value === ""
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
? ""
|
? ""
|
||||||
: t.data.node.template[n]
|
: node.data.node.template[
|
||||||
.value
|
templateField
|
||||||
|
].value
|
||||||
}
|
}
|
||||||
onChange={(k) => {
|
onChange={(target) => {
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
let newInputList =
|
let newInputList =
|
||||||
cloneDeep(old);
|
cloneDeep(old);
|
||||||
newInputList[
|
newInputList[
|
||||||
index
|
index
|
||||||
].data.node.template[
|
].data.node.template[
|
||||||
n
|
templateField
|
||||||
].value = k;
|
].value = target;
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
tweaks.buildTweakObject(
|
tweaks.buildTweakObject(
|
||||||
t["data"]["id"],
|
node["data"]["id"],
|
||||||
k,
|
target,
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : t.data.node.template[n].type ===
|
) : node.data.node.template[
|
||||||
"prompt" ? (
|
templateField
|
||||||
|
].type === "prompt" ? (
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={tweaks.buildContent(
|
content={tweaks.buildContent(
|
||||||
!t.data.node.template[n]
|
!node.data.node.template[
|
||||||
.value ||
|
templateField
|
||||||
t.data.node.template[n]
|
].value ||
|
||||||
.value === ""
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
? ""
|
? ""
|
||||||
: t.data.node.template[n]
|
: node.data.node.template[
|
||||||
.value
|
templateField
|
||||||
|
].value
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
|
|
@ -571,44 +635,53 @@ export default function CodeTabsComponent({
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
value={
|
value={
|
||||||
!t.data.node.template[n]
|
!node.data.node.template[
|
||||||
.value ||
|
templateField
|
||||||
t.data.node.template[n]
|
].value ||
|
||||||
.value === ""
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
? ""
|
? ""
|
||||||
: t.data.node.template[
|
: node.data.node
|
||||||
n
|
.template[
|
||||||
|
templateField
|
||||||
].value
|
].value
|
||||||
}
|
}
|
||||||
onChange={(k) => {
|
onChange={(target) => {
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
let newInputList =
|
let newInputList =
|
||||||
cloneDeep(old);
|
cloneDeep(old);
|
||||||
newInputList[
|
newInputList[
|
||||||
index
|
index
|
||||||
].data.node.template[
|
].data.node.template[
|
||||||
n
|
templateField
|
||||||
].value = k;
|
].value = target;
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
tweaks.buildTweakObject(
|
tweaks.buildTweakObject(
|
||||||
t["data"]["id"],
|
node["data"]["id"],
|
||||||
k,
|
target,
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
) : t.data.node.template[n].type ===
|
) : node.data.node.template[
|
||||||
"code" ? (
|
templateField
|
||||||
|
].type === "code" ? (
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={tweaks.buildContent(
|
content={tweaks.buildContent(
|
||||||
tweaks.getValue(
|
tweaks.getValue(
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
.value,
|
templateField
|
||||||
t.data,
|
].value,
|
||||||
t.data.node.template[n]
|
node.data,
|
||||||
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -617,37 +690,43 @@ export default function CodeTabsComponent({
|
||||||
disabled={false}
|
disabled={false}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
!t.data.node.template[n]
|
!node.data.node.template[
|
||||||
.value ||
|
templateField
|
||||||
t.data.node.template[n]
|
].value ||
|
||||||
.value === ""
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
? ""
|
? ""
|
||||||
: t.data.node.template[
|
: node.data.node
|
||||||
n
|
.template[
|
||||||
|
templateField
|
||||||
].value
|
].value
|
||||||
}
|
}
|
||||||
onChange={(k) => {
|
onChange={(target) => {
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
let newInputList =
|
let newInputList =
|
||||||
cloneDeep(old);
|
cloneDeep(old);
|
||||||
newInputList[
|
newInputList[
|
||||||
index
|
index
|
||||||
].data.node.template[
|
].data.node.template[
|
||||||
n
|
templateField
|
||||||
].value = k;
|
].value = target;
|
||||||
return newInputList;
|
return newInputList;
|
||||||
});
|
});
|
||||||
tweaks.buildTweakObject(
|
tweaks.buildTweakObject(
|
||||||
t["data"]["id"],
|
node["data"]["id"],
|
||||||
k,
|
target,
|
||||||
t.data.node.template[n]
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
) : t.data.node.template[n].type ===
|
) : node.data.node.template[
|
||||||
"Any" ? (
|
templateField
|
||||||
|
].type === "Any" ? (
|
||||||
"-"
|
"-"
|
||||||
) : (
|
) : (
|
||||||
<div className="hidden"></div>
|
<div className="hidden"></div>
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@ export default function FloatComponent({
|
||||||
type="number"
|
type="number"
|
||||||
step={step}
|
step={step}
|
||||||
min={min}
|
min={min}
|
||||||
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
|
onInput={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
if (e.target.value < min.toString()) {
|
if (event.target.value < min.toString()) {
|
||||||
e.target.value = min.toString();
|
event.target.value = min.toString();
|
||||||
}
|
}
|
||||||
if (e.target.value > max.toString()) {
|
if (event.target.value > max.toString()) {
|
||||||
e.target.value = max.toString();
|
event.target.value = max.toString();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
max={max}
|
max={max}
|
||||||
|
|
@ -40,8 +40,8 @@ export default function FloatComponent({
|
||||||
placeholder={
|
placeholder={
|
||||||
editNode ? "Number 0 to 1" : "Type a number from zero to one"
|
editNode ? "Number 0 to 1" : "Type a number from zero to one"
|
||||||
}
|
}
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
onChange(e.target.value);
|
onChange(event.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,8 @@ export default function Header() {
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<span className="ml-4 text-2xl">⛓️</span>
|
<span className="ml-4 text-2xl">⛓️</span>
|
||||||
</Link>
|
</Link>
|
||||||
{flows.findIndex((f) => tabId === f.id) !== -1 && tabId !== "" && (
|
{flows.findIndex((flow) => tabId === flow.id) !== -1 &&
|
||||||
<MenuBar flows={flows} tabId={tabId} />
|
tabId !== "" && <MenuBar flows={flows} tabId={tabId} />}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="round-button-div">
|
<div className="round-button-div">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ export default function InputComponent({
|
||||||
password && !editNode ? "pr-10" : ""
|
password && !editNode ? "pr-10" : ""
|
||||||
)}
|
)}
|
||||||
placeholder={password && editNode ? "Key" : "Type something..."}
|
placeholder={password && editNode ? "Key" : "Type something..."}
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
onChange(e.target.value);
|
onChange(event.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{password && (
|
{password && (
|
||||||
|
|
|
||||||
|
|
@ -49,11 +49,11 @@ export default function InputFileComponent({
|
||||||
input.style.display = "none"; // Hidden from view
|
input.style.display = "none"; // Hidden from view
|
||||||
input.multiple = false; // Allow only one file selection
|
input.multiple = false; // Allow only one file selection
|
||||||
|
|
||||||
input.onchange = (e: Event) => {
|
input.onchange = (event: Event) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// Get the selected file
|
// Get the selected file
|
||||||
const file = (e.target as HTMLInputElement).files?.[0];
|
const file = (event.target as HTMLInputElement).files?.[0];
|
||||||
|
|
||||||
// Check if the file type is correct
|
// Check if the file type is correct
|
||||||
if (file && checkFileType(file.name)) {
|
if (file && checkFileType(file.name)) {
|
||||||
|
|
|
||||||
|
|
@ -25,18 +25,18 @@ export default function InputListComponent({
|
||||||
"flex flex-col gap-3"
|
"flex flex-col gap-3"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{value.map((i, idx) => {
|
{value.map((singleValue, idx) => {
|
||||||
return (
|
return (
|
||||||
<div key={idx} className="flex w-full gap-3">
|
<div key={idx} className="flex w-full gap-3">
|
||||||
<Input
|
<Input
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
type="text"
|
type="text"
|
||||||
value={i}
|
value={singleValue}
|
||||||
className={editNode ? "input-edit-node" : ""}
|
className={editNode ? "input-edit-node" : ""}
|
||||||
placeholder="Type something..."
|
placeholder="Type something..."
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
let newInputList = _.cloneDeep(value);
|
let newInputList = _.cloneDeep(value);
|
||||||
newInputList[idx] = e.target.value;
|
newInputList[idx] = event.target.value;
|
||||||
onChange(newInputList);
|
onChange(newInputList);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -41,17 +41,17 @@ export default function IntComponent({
|
||||||
type="number"
|
type="number"
|
||||||
step="1"
|
step="1"
|
||||||
min={min}
|
min={min}
|
||||||
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
|
onInput={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
if (e.target.value < min.toString()) {
|
if (event.target.value < min.toString()) {
|
||||||
e.target.value = min.toString();
|
event.target.value = min.toString();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
value={value ?? ""}
|
value={value ?? ""}
|
||||||
className={editNode ? "input-edit-node" : ""}
|
className={editNode ? "input-edit-node" : ""}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
placeholder={editNode ? "Integer number" : "Type an integer number"}
|
placeholder={editNode ? "Integer number" : "Type an integer number"}
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
onChange(e.target.value);
|
onChange(event.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@ export default function PromptAreaComponent({
|
||||||
value={value}
|
value={value}
|
||||||
buttonText="Check & Save"
|
buttonText="Check & Save"
|
||||||
modalTitle="Edit Prompt"
|
modalTitle="Edit Prompt"
|
||||||
setValue={(t: string) => {
|
setValue={(value: string) => {
|
||||||
onChange(t);
|
onChange(value);
|
||||||
}}
|
}}
|
||||||
nodeClass={nodeClass}
|
nodeClass={nodeClass}
|
||||||
setNodeClass={setNodeClass}
|
setNodeClass={setNodeClass}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ export default function TextAreaComponent({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className={editNode ? "input-edit-node" : ""}
|
className={editNode ? "input-edit-node" : ""}
|
||||||
placeholder={"Type something..."}
|
placeholder={"Type something..."}
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
onChange(e.target.value);
|
onChange(event.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -35,8 +35,8 @@ export default function TextAreaComponent({
|
||||||
buttonText="Finishing Editing"
|
buttonText="Finishing Editing"
|
||||||
modalTitle="Edit Text"
|
modalTitle="Edit Text"
|
||||||
value={value}
|
value={value}
|
||||||
setValue={(t: string) => {
|
setValue={(value: string) => {
|
||||||
onChange(t);
|
onChange(value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!editNode && (
|
{!editNode && (
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ export default function ToggleComponent({
|
||||||
<div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}>
|
<div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}>
|
||||||
<Switch
|
<Switch
|
||||||
checked={enabled}
|
checked={enabled}
|
||||||
onChange={(x: boolean) => {
|
onChange={(isEnabled: boolean) => {
|
||||||
setEnabled(x);
|
setEnabled(isEnabled);
|
||||||
}}
|
}}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
enabled ? "bg-primary" : "bg-input",
|
enabled ? "bg-primary" : "bg-input",
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ export default function ToggleShadComponent({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className=""
|
className=""
|
||||||
checked={enabled}
|
checked={enabled}
|
||||||
onCheckedChange={(x: boolean) => {
|
onCheckedChange={(isEnabled: boolean) => {
|
||||||
setEnabled(x);
|
setEnabled(isEnabled);
|
||||||
}}
|
}}
|
||||||
></Switch>
|
></Switch>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ export default function RenameLabel(props) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isRename) {
|
if (isRename) {
|
||||||
setMyValue(props.value);
|
setMyValue(props.value);
|
||||||
document.addEventListener("keydown", (e) => {
|
document.addEventListener("keydown", (event) => {
|
||||||
if (e.key === "Escape") {
|
if (event.key === "Escape") {
|
||||||
setIsRename(false);
|
setIsRename(false);
|
||||||
props.setValue("");
|
props.setValue("");
|
||||||
}
|
}
|
||||||
|
|
@ -67,8 +67,8 @@ export default function RenameLabel(props) {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
value={myValue}
|
value={myValue}
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
setMyValue(e.target.value);
|
setMyValue(event.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -508,3 +508,84 @@ export const URL_EXCLUDED_FROM_ERROR_RETRIES = [
|
||||||
"/api/v1/custom_component",
|
"/api/v1/custom_component",
|
||||||
"/api/v1/validate/prompt",
|
"/api/v1/validate/prompt",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const tabsCode = [];
|
||||||
|
|
||||||
|
export function tabsArray(codes: string[], method: number) {
|
||||||
|
if (!method) return;
|
||||||
|
if (method === 0) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: "cURL",
|
||||||
|
mode: "bash",
|
||||||
|
image: "https://curl.se/logo/curl-symbol-transparent.png",
|
||||||
|
language: "sh",
|
||||||
|
code: codes[0],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python API",
|
||||||
|
mode: "python",
|
||||||
|
image:
|
||||||
|
"https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w",
|
||||||
|
language: "py",
|
||||||
|
code: codes[1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python Code",
|
||||||
|
mode: "python",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
language: "py",
|
||||||
|
code: codes[2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Chat Widget HTML",
|
||||||
|
description:
|
||||||
|
"Insert this code anywhere in your <body> tag. To use with react and other libs, check our <a class='link-color' href='https://langflow.org/guidelines/widget'>documentation</a>.",
|
||||||
|
mode: "html",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
language: "py",
|
||||||
|
code: codes[3],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: "cURL",
|
||||||
|
mode: "bash",
|
||||||
|
image: "https://curl.se/logo/curl-symbol-transparent.png",
|
||||||
|
language: "sh",
|
||||||
|
code: codes[0],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python API",
|
||||||
|
mode: "python",
|
||||||
|
image:
|
||||||
|
"https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w",
|
||||||
|
language: "py",
|
||||||
|
code: codes[1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python Code",
|
||||||
|
mode: "python",
|
||||||
|
language: "py",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
code: codes[2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Chat Widget HTML",
|
||||||
|
description:
|
||||||
|
"Insert this code anywhere in your <body> tag. To use with react and other libs, check our <a class='link-color' href='https://langflow.org/guidelines/widget'>documentation</a>.",
|
||||||
|
mode: "html",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
language: "py",
|
||||||
|
code: codes[3],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Tweaks",
|
||||||
|
mode: "python",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
language: "py",
|
||||||
|
code: codes[4],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -316,11 +316,13 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
const input = document.createElement("input");
|
const input = document.createElement("input");
|
||||||
input.type = "file";
|
input.type = "file";
|
||||||
// add a change event listener to the file input
|
// add a change event listener to the file input
|
||||||
input.onchange = (e: Event) => {
|
input.onchange = (event: Event) => {
|
||||||
// check if the file type is application/json
|
// check if the file type is application/json
|
||||||
if ((e.target as HTMLInputElement).files[0].type === "application/json") {
|
if (
|
||||||
|
(event.target as HTMLInputElement).files[0].type === "application/json"
|
||||||
|
) {
|
||||||
// get the file from the file input
|
// get the file from the file input
|
||||||
const file = (e.target as HTMLInputElement).files[0];
|
const file = (event.target as HTMLInputElement).files[0];
|
||||||
// read the file as text
|
// read the file as text
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("file", file);
|
formData.append("file", file);
|
||||||
|
|
@ -359,12 +361,12 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
let idsMap = {};
|
let idsMap = {};
|
||||||
let nodes = reactFlowInstance.getNodes();
|
let nodes = reactFlowInstance.getNodes();
|
||||||
let edges = reactFlowInstance.getEdges();
|
let edges = reactFlowInstance.getEdges();
|
||||||
selectionInstance.nodes.forEach((n) => {
|
selectionInstance.nodes.forEach((node) => {
|
||||||
if (n.position.y < minimumY) {
|
if (node.position.y < minimumY) {
|
||||||
minimumY = n.position.y;
|
minimumY = node.position.y;
|
||||||
}
|
}
|
||||||
if (n.position.x < minimumX) {
|
if (node.position.x < minimumX) {
|
||||||
minimumX = n.position.x;
|
minimumX = node.position.x;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -372,43 +374,43 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
? { x: position.paneX + position.x, y: position.paneY + position.y }
|
? { x: position.paneX + position.x, y: position.paneY + position.y }
|
||||||
: reactFlowInstance.project({ x: position.x, y: position.y });
|
: reactFlowInstance.project({ x: position.x, y: position.y });
|
||||||
|
|
||||||
selectionInstance.nodes.forEach((n: NodeType) => {
|
selectionInstance.nodes.forEach((node: NodeType) => {
|
||||||
// Generate a unique node ID
|
// Generate a unique node ID
|
||||||
let newId = getNodeId(n.data.type);
|
let newId = getNodeId(node.data.type);
|
||||||
idsMap[n.id] = newId;
|
idsMap[node.id] = newId;
|
||||||
|
|
||||||
// Create a new node object
|
// Create a new node object
|
||||||
const newNode: NodeType = {
|
const newNode: NodeType = {
|
||||||
id: newId,
|
id: newId,
|
||||||
type: "genericNode",
|
type: "genericNode",
|
||||||
position: {
|
position: {
|
||||||
x: insidePosition.x + n.position.x - minimumX,
|
x: insidePosition.x + node.position.x - minimumX,
|
||||||
y: insidePosition.y + n.position.y - minimumY,
|
y: insidePosition.y + node.position.y - minimumY,
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
..._.cloneDeep(n.data),
|
..._.cloneDeep(node.data),
|
||||||
id: newId,
|
id: newId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add the new node to the list of nodes in state
|
// Add the new node to the list of nodes in state
|
||||||
nodes = nodes
|
nodes = nodes
|
||||||
.map((e) => ({ ...e, selected: false }))
|
.map((node) => ({ ...node, selected: false }))
|
||||||
.concat({ ...newNode, selected: false });
|
.concat({ ...newNode, selected: false });
|
||||||
});
|
});
|
||||||
reactFlowInstance.setNodes(nodes);
|
reactFlowInstance.setNodes(nodes);
|
||||||
|
|
||||||
selectionInstance.edges.forEach((e) => {
|
selectionInstance.edges.forEach((edge) => {
|
||||||
let source = idsMap[e.source];
|
let source = idsMap[edge.source];
|
||||||
let target = idsMap[e.target];
|
let target = idsMap[edge.target];
|
||||||
let sourceHandleSplitted = e.sourceHandle.split("|");
|
let sourceHandleSplitted = edge.sourceHandle.split("|");
|
||||||
let sourceHandle =
|
let sourceHandle =
|
||||||
sourceHandleSplitted[0] +
|
sourceHandleSplitted[0] +
|
||||||
"|" +
|
"|" +
|
||||||
source +
|
source +
|
||||||
"|" +
|
"|" +
|
||||||
sourceHandleSplitted.slice(2).join("|");
|
sourceHandleSplitted.slice(2).join("|");
|
||||||
let targetHandleSplitted = e.targetHandle.split("|");
|
let targetHandleSplitted = edge.targetHandle.split("|");
|
||||||
let targetHandle =
|
let targetHandle =
|
||||||
targetHandleSplitted.slice(0, -1).join("|") + "|" + target;
|
targetHandleSplitted.slice(0, -1).join("|") + "|" + target;
|
||||||
let id =
|
let id =
|
||||||
|
|
@ -433,7 +435,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
animated: targetHandle.split("|")[0] === "Text",
|
animated: targetHandle.split("|")[0] === "Text",
|
||||||
selected: false,
|
selected: false,
|
||||||
},
|
},
|
||||||
edges.map((e) => ({ ...e, selected: false }))
|
edges.map((edge) => ({ ...edge, selected: false }))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
reactFlowInstance.setEdges(edges);
|
reactFlowInstance.setEdges(edges);
|
||||||
|
|
|
||||||
|
|
@ -88,12 +88,12 @@ export function TypesProvider({ children }: { children: ReactNode }) {
|
||||||
|
|
||||||
function deleteNode(idx: string) {
|
function deleteNode(idx: string) {
|
||||||
reactFlowInstance.setNodes(
|
reactFlowInstance.setNodes(
|
||||||
reactFlowInstance.getNodes().filter((n: Node) => n.id !== idx)
|
reactFlowInstance.getNodes().filter((node: Node) => node.id !== idx)
|
||||||
);
|
);
|
||||||
reactFlowInstance.setEdges(
|
reactFlowInstance.setEdges(
|
||||||
reactFlowInstance
|
reactFlowInstance
|
||||||
.getEdges()
|
.getEdges()
|
||||||
.filter((ns) => ns.source !== idx && ns.target !== idx)
|
.filter((edge) => edge.source !== idx && edge.target !== idx)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,18 @@ export function UndoRedoProvider({ children }) {
|
||||||
const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => []));
|
const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => []));
|
||||||
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => []));
|
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => []));
|
||||||
const [tabIndex, setTabIndex] = useState(
|
const [tabIndex, setTabIndex] = useState(
|
||||||
flows.findIndex((f) => f.id === tabId)
|
flows.findIndex((flow) => flow.id === tabId)
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// whenever the flows variable changes, we need to add one array to the past and future states
|
// whenever the flows variable changes, we need to add one array to the past and future states
|
||||||
setPast((old) => flows.map((f, i) => (old[i] ? old[i] : [])));
|
setPast((old) =>
|
||||||
setFuture((old) => flows.map((f, i) => (old[i] ? old[i] : [])));
|
flows.map((flow, index) => (old[index] ? old[index] : []))
|
||||||
setTabIndex(flows.findIndex((f) => f.id === tabId));
|
);
|
||||||
|
setFuture((old) =>
|
||||||
|
flows.map((flow, index) => (old[index] ? old[index] : []))
|
||||||
|
);
|
||||||
|
setTabIndex(flows.findIndex((flow) => flow.id === tabId));
|
||||||
}, [flows, tabId]);
|
}, [flows, tabId]);
|
||||||
|
|
||||||
const { setNodes, setEdges, getNodes, getEdges } = useReactFlow();
|
const { setNodes, setEdges, getNodes, getEdges } = useReactFlow();
|
||||||
|
|
|
||||||
|
|
@ -181,22 +181,22 @@ const ApiModal = forwardRef(
|
||||||
function filterNodes() {
|
function filterNodes() {
|
||||||
let arrNodesWithValues = [];
|
let arrNodesWithValues = [];
|
||||||
|
|
||||||
flow["data"]["nodes"].forEach((t) => {
|
flow["data"]["nodes"].forEach((node) => {
|
||||||
Object.keys(t["data"]["node"]["template"])
|
Object.keys(node["data"]["node"]["template"])
|
||||||
.filter(
|
.filter(
|
||||||
(n) =>
|
(templateField) =>
|
||||||
n.charAt(0) !== "_" &&
|
templateField.charAt(0) !== "_" &&
|
||||||
t.data.node.template[n].show &&
|
node.data.node.template[templateField].show &&
|
||||||
(t.data.node.template[n].type === "str" ||
|
(node.data.node.template[templateField].type === "str" ||
|
||||||
t.data.node.template[n].type === "bool" ||
|
node.data.node.template[templateField].type === "bool" ||
|
||||||
t.data.node.template[n].type === "float" ||
|
node.data.node.template[templateField].type === "float" ||
|
||||||
t.data.node.template[n].type === "code" ||
|
node.data.node.template[templateField].type === "code" ||
|
||||||
t.data.node.template[n].type === "prompt" ||
|
node.data.node.template[templateField].type === "prompt" ||
|
||||||
t.data.node.template[n].type === "file" ||
|
node.data.node.template[templateField].type === "file" ||
|
||||||
t.data.node.template[n].type === "int")
|
node.data.node.template[templateField].type === "int")
|
||||||
)
|
)
|
||||||
.map((n, i) => {
|
.map((n, i) => {
|
||||||
arrNodesWithValues.push(t["id"]);
|
arrNodesWithValues.push(node["id"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,13 +49,15 @@ const EditNodeModal = forwardRef(
|
||||||
const { reactFlowInstance } = useContext(typesContext);
|
const { reactFlowInstance } = useContext(typesContext);
|
||||||
|
|
||||||
let disabled =
|
let disabled =
|
||||||
reactFlowInstance?.getEdges().some((e) => e.targetHandle === data.id) ??
|
reactFlowInstance
|
||||||
false;
|
?.getEdges()
|
||||||
|
.some((edge) => edge.targetHandle === data.id) ?? false;
|
||||||
|
|
||||||
function changeAdvanced(n) {
|
function changeAdvanced(templateParam) {
|
||||||
setMyData((old) => {
|
setMyData((old) => {
|
||||||
let newData = cloneDeep(old);
|
let newData = cloneDeep(old);
|
||||||
newData.node.template[n].advanced = !newData.node.template[n].advanced;
|
newData.node.template[templateParam].advanced =
|
||||||
|
!newData.node.template[templateParam].advanced;
|
||||||
return newData;
|
return newData;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -112,51 +114,65 @@ const EditNodeModal = forwardRef(
|
||||||
<TableBody className="p-0">
|
<TableBody className="p-0">
|
||||||
{Object.keys(myData.node.template)
|
{Object.keys(myData.node.template)
|
||||||
.filter(
|
.filter(
|
||||||
(t) =>
|
(templateParam) =>
|
||||||
t.charAt(0) !== "_" &&
|
templateParam.charAt(0) !== "_" &&
|
||||||
myData.node.template[t].show &&
|
myData.node.template[templateParam].show &&
|
||||||
(myData.node.template[t].type === "str" ||
|
(myData.node.template[templateParam].type ===
|
||||||
myData.node.template[t].type === "bool" ||
|
"str" ||
|
||||||
myData.node.template[t].type === "float" ||
|
myData.node.template[templateParam].type ===
|
||||||
myData.node.template[t].type === "code" ||
|
"bool" ||
|
||||||
myData.node.template[t].type === "prompt" ||
|
myData.node.template[templateParam].type ===
|
||||||
myData.node.template[t].type === "file" ||
|
"float" ||
|
||||||
myData.node.template[t].type === "int")
|
myData.node.template[templateParam].type ===
|
||||||
|
"code" ||
|
||||||
|
myData.node.template[templateParam].type ===
|
||||||
|
"prompt" ||
|
||||||
|
myData.node.template[templateParam].type ===
|
||||||
|
"file" ||
|
||||||
|
myData.node.template[templateParam].type ===
|
||||||
|
"int")
|
||||||
)
|
)
|
||||||
.map((n, i) => (
|
.map((templateParam, index) => (
|
||||||
<TableRow key={i} className="h-10">
|
<TableRow key={index} className="h-10">
|
||||||
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
||||||
{myData.node.template[n].name
|
{myData.node.template[templateParam].name
|
||||||
? myData.node.template[n].name
|
? myData.node.template[templateParam].name
|
||||||
: myData.node.template[n].display_name}
|
: myData.node.template[templateParam]
|
||||||
|
.display_name}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
||||||
{myData.node.template[n].type === "str" &&
|
{myData.node.template[templateParam].type ===
|
||||||
!myData.node.template[n].options ? (
|
"str" &&
|
||||||
|
!myData.node.template[templateParam].options ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
{myData.node.template[n].list ? (
|
{myData.node.template[templateParam].list ? (
|
||||||
<InputListComponent
|
<InputListComponent
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={
|
value={
|
||||||
!myData.node.template[n].value ||
|
!myData.node.template[templateParam]
|
||||||
myData.node.template[n].value === ""
|
.value ||
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value === ""
|
||||||
? [""]
|
? [""]
|
||||||
: myData.node.template[n].value
|
: myData.node.template[templateParam]
|
||||||
|
.value
|
||||||
}
|
}
|
||||||
onChange={(t: string[]) => {
|
onChange={(value: string[]) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : myData.node.template[n].multiline ? (
|
) : myData.node.template[templateParam]
|
||||||
|
.multiline ? (
|
||||||
<TextAreaComponent
|
<TextAreaComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
myData.node.template[n].value ?? ""
|
myData.node.template[templateParam]
|
||||||
|
.value ?? ""
|
||||||
}
|
}
|
||||||
onChange={(t: string) => {
|
onChange={(value: string) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -164,105 +180,142 @@ const EditNodeModal = forwardRef(
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
password={
|
password={
|
||||||
myData.node.template[n].password ??
|
myData.node.template[templateParam]
|
||||||
false
|
.password ?? false
|
||||||
}
|
}
|
||||||
value={
|
value={
|
||||||
myData.node.template[n].value ?? ""
|
myData.node.template[templateParam]
|
||||||
|
.value ?? ""
|
||||||
}
|
}
|
||||||
onChange={(t) => {
|
onChange={(value) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "bool" ? (
|
) : myData.node.template[templateParam].type ===
|
||||||
|
"bool" ? (
|
||||||
<div className="ml-auto">
|
<div className="ml-auto">
|
||||||
{" "}
|
{" "}
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
enabled={myData.node.template[n].value}
|
enabled={
|
||||||
setEnabled={(t) => {
|
myData.node.template[templateParam].value
|
||||||
handleOnNewValue(t, n);
|
}
|
||||||
|
setEnabled={(isEnabled) => {
|
||||||
|
handleOnNewValue(
|
||||||
|
isEnabled,
|
||||||
|
templateParam
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "float" ? (
|
) : myData.node.template[templateParam].type ===
|
||||||
|
"float" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<FloatComponent
|
<FloatComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
onChange={(t) => {
|
myData.node.template[templateParam]
|
||||||
handleOnNewValue(t, n);
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value) => {
|
||||||
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "str" &&
|
) : myData.node.template[templateParam].type ===
|
||||||
myData.node.template[n].options ? (
|
"str" &&
|
||||||
|
myData.node.template[templateParam].options ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
numberOfOptions={nodeLength}
|
numberOfOptions={nodeLength}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
options={myData.node.template[n].options}
|
options={
|
||||||
onSelect={(t) => handleOnNewValue(t, n)}
|
myData.node.template[templateParam]
|
||||||
|
.options
|
||||||
|
}
|
||||||
|
onSelect={(value) =>
|
||||||
|
handleOnNewValue(value, templateParam)
|
||||||
|
}
|
||||||
value={
|
value={
|
||||||
myData.node.template[n].value ??
|
myData.node.template[templateParam]
|
||||||
"Choose an option"
|
.value ?? "Choose an option"
|
||||||
}
|
}
|
||||||
></Dropdown>
|
></Dropdown>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "int" ? (
|
) : myData.node.template[templateParam].type ===
|
||||||
|
"int" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<IntComponent
|
<IntComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
onChange={(t) => {
|
myData.node.template[templateParam]
|
||||||
handleOnNewValue(t, n);
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value) => {
|
||||||
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "file" ? (
|
) : myData.node.template[templateParam].type ===
|
||||||
|
"file" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<InputFileComponent
|
<InputFileComponent
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
onChange={(t: string) => {
|
myData.node.template[templateParam]
|
||||||
handleOnNewValue(t, n);
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value: string) => {
|
||||||
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
fileTypes={
|
fileTypes={
|
||||||
myData.node.template[n].fileTypes
|
myData.node.template[templateParam]
|
||||||
|
.fileTypes
|
||||||
}
|
}
|
||||||
suffixes={myData.node.template[n].suffixes}
|
suffixes={
|
||||||
onFileChange={(t: string) => {
|
myData.node.template[templateParam]
|
||||||
data.node.template[n].file_path = t;
|
.suffixes
|
||||||
|
}
|
||||||
|
onFileChange={(filePath: string) => {
|
||||||
|
data.node.template[
|
||||||
|
templateParam
|
||||||
|
].file_path = filePath;
|
||||||
}}
|
}}
|
||||||
></InputFileComponent>
|
></InputFileComponent>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "prompt" ? (
|
) : myData.node.template[templateParam].type ===
|
||||||
|
"prompt" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<PromptAreaComponent
|
<PromptAreaComponent
|
||||||
field_name={n}
|
field_name={templateParam}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
nodeClass={myData.node}
|
nodeClass={myData.node}
|
||||||
setNodeClass={(nodeClass) => {
|
setNodeClass={(nodeClass) => {
|
||||||
myData.node = nodeClass;
|
myData.node = nodeClass;
|
||||||
}}
|
}}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
onChange={(t: string) => {
|
myData.node.template[templateParam]
|
||||||
handleOnNewValue(t, n);
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value: string) => {
|
||||||
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "code" ? (
|
) : myData.node.template[templateParam].type ===
|
||||||
|
"code" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<CodeAreaComponent
|
<CodeAreaComponent
|
||||||
dynamic={
|
dynamic={
|
||||||
data.node.template[n].dynamic ?? false
|
data.node.template[templateParam]
|
||||||
|
.dynamic ?? false
|
||||||
}
|
}
|
||||||
setNodeClass={(nodeClass) => {
|
setNodeClass={(nodeClass) => {
|
||||||
data.node = nodeClass;
|
data.node = nodeClass;
|
||||||
|
|
@ -270,13 +323,17 @@ const EditNodeModal = forwardRef(
|
||||||
nodeClass={data.node}
|
nodeClass={data.node}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
onChange={(t: string) => {
|
myData.node.template[templateParam]
|
||||||
handleOnNewValue(t, n);
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value: string) => {
|
||||||
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "Any" ? (
|
) : myData.node.template[templateParam].type ===
|
||||||
|
"Any" ? (
|
||||||
"-"
|
"-"
|
||||||
) : (
|
) : (
|
||||||
<div className="hidden"></div>
|
<div className="hidden"></div>
|
||||||
|
|
@ -285,8 +342,13 @@ const EditNodeModal = forwardRef(
|
||||||
<TableCell className="p-0 text-right">
|
<TableCell className="p-0 text-right">
|
||||||
<div className="items-center text-center">
|
<div className="items-center text-center">
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
enabled={!myData.node.template[n].advanced}
|
enabled={
|
||||||
setEnabled={(e) => changeAdvanced(n)}
|
!myData.node.template[templateParam]
|
||||||
|
.advanced
|
||||||
|
}
|
||||||
|
setEnabled={(e) =>
|
||||||
|
changeAdvanced(templateParam)
|
||||||
|
}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@ const ExportModal = forwardRef((props: { children: ReactNode }, ref) => {
|
||||||
const { flows, tabId, updateFlow, downloadFlow, saveFlow } =
|
const { flows, tabId, updateFlow, downloadFlow, saveFlow } =
|
||||||
useContext(TabsContext);
|
useContext(TabsContext);
|
||||||
const [checked, setChecked] = useState(false);
|
const [checked, setChecked] = useState(false);
|
||||||
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
|
const [name, setName] = useState(
|
||||||
|
flows.find((flow) => flow.id === tabId).name
|
||||||
|
);
|
||||||
const [invalidName, setInvalidName] = useState(false);
|
const [invalidName, setInvalidName] = useState(false);
|
||||||
const [description, setDescription] = useState(
|
const [description, setDescription] = useState(
|
||||||
flows.find((f) => f.id === tabId).description
|
flows.find((flow) => flow.id === tabId).description
|
||||||
);
|
);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
return (
|
return (
|
||||||
|
|
@ -59,13 +61,13 @@ const ExportModal = forwardRef((props: { children: ReactNode }, ref) => {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (checked)
|
if (checked)
|
||||||
downloadFlow(
|
downloadFlow(
|
||||||
flows.find((f) => f.id === tabId),
|
flows.find((flow) => flow.id === tabId),
|
||||||
name,
|
name,
|
||||||
description
|
description
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
downloadFlow(
|
downloadFlow(
|
||||||
removeApiKeys(flows.find((f) => f.id === tabId)),
|
removeApiKeys(flows.find((flow) => flow.id === tabId)),
|
||||||
name,
|
name,
|
||||||
description
|
description
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,16 @@ export default function FlowSettingsModal({
|
||||||
const { flows, tabId, updateFlow, setTabsState, saveFlow } =
|
const { flows, tabId, updateFlow, setTabsState, saveFlow } =
|
||||||
useContext(TabsContext);
|
useContext(TabsContext);
|
||||||
const maxLength = 50;
|
const maxLength = 50;
|
||||||
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
|
const [name, setName] = useState(
|
||||||
|
flows.find((flow) => flow.id === tabId).name
|
||||||
|
);
|
||||||
const [description, setDescription] = useState(
|
const [description, setDescription] = useState(
|
||||||
flows.find((f) => f.id === tabId).description
|
flows.find((flow) => flow.id === tabId).description
|
||||||
);
|
);
|
||||||
const [invalidName, setInvalidName] = useState(false);
|
const [invalidName, setInvalidName] = useState(false);
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
let savedFlow = flows.find((f) => f.id === tabId);
|
let savedFlow = flows.find((flow) => flow.id === tabId);
|
||||||
savedFlow.name = name;
|
savedFlow.name = name;
|
||||||
savedFlow.description = description;
|
savedFlow.description = description;
|
||||||
saveFlow(savedFlow);
|
saveFlow(savedFlow);
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ export default function ChatInput({
|
||||||
}`,
|
}`,
|
||||||
}}
|
}}
|
||||||
value={lockChat ? "Thinking..." : chatValue}
|
value={lockChat ? "Thinking..." : chatValue}
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
setChatValue(e.target.value);
|
setChatValue(event.target.value);
|
||||||
}}
|
}}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
lockChat
|
lockChat
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ export default function FormModal({
|
||||||
const handleKeys = formKeysData.handle_keys;
|
const handleKeys = formKeysData.handle_keys;
|
||||||
|
|
||||||
const keyToUse = Object.keys(inputKeys).find(
|
const keyToUse = Object.keys(inputKeys).find(
|
||||||
(k) => !handleKeys.some((j) => j === k) && inputKeys[k] === ""
|
(key) => !handleKeys.some((j) => j === key) && inputKeys[key] === ""
|
||||||
);
|
);
|
||||||
|
|
||||||
return inputKeys[keyToUse];
|
return inputKeys[keyToUse];
|
||||||
|
|
@ -70,9 +70,9 @@ export default function FormModal({
|
||||||
const [chatKey, setChatKey] = useState(() => {
|
const [chatKey, setChatKey] = useState(() => {
|
||||||
if (tabsState[flow.id]?.formKeysData?.input_keys) {
|
if (tabsState[flow.id]?.formKeysData?.input_keys) {
|
||||||
return Object.keys(tabsState[flow.id].formKeysData.input_keys).find(
|
return Object.keys(tabsState[flow.id].formKeysData.input_keys).find(
|
||||||
(k) =>
|
(key) =>
|
||||||
!tabsState[flow.id].formKeysData.handle_keys.some((j) => j === k) &&
|
!tabsState[flow.id].formKeysData.handle_keys.some((j) => j === key) &&
|
||||||
tabsState[flow.id].formKeysData.input_keys[k] === ""
|
tabsState[flow.id].formKeysData.input_keys[key] === ""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// TODO: return a sensible default
|
// TODO: return a sensible default
|
||||||
|
|
@ -425,13 +425,13 @@ export default function FormModal({
|
||||||
{tabsState[id.current]?.formKeysData?.input_keys
|
{tabsState[id.current]?.formKeysData?.input_keys
|
||||||
? Object.keys(
|
? Object.keys(
|
||||||
tabsState[id.current].formKeysData.input_keys
|
tabsState[id.current].formKeysData.input_keys
|
||||||
).map((i, k) => (
|
).map((key, index) => (
|
||||||
<div className="file-component-accordion-div" key={k}>
|
<div className="file-component-accordion-div" key={index}>
|
||||||
<AccordionComponent
|
<AccordionComponent
|
||||||
trigger={
|
trigger={
|
||||||
<div className="file-component-badge-div">
|
<div className="file-component-badge-div">
|
||||||
<Badge variant="gray" size="md">
|
<Badge variant="gray" size="md">
|
||||||
{i}
|
{key}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
@ -441,24 +441,26 @@ export default function FormModal({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
enabled={chatKey === i}
|
enabled={chatKey === key}
|
||||||
setEnabled={(value) =>
|
setEnabled={(value) =>
|
||||||
handleOnCheckedChange(value, i)
|
handleOnCheckedChange(value, key)
|
||||||
}
|
}
|
||||||
size="small"
|
size="small"
|
||||||
disabled={tabsState[
|
disabled={tabsState[
|
||||||
id.current
|
id.current
|
||||||
].formKeysData.handle_keys.some((t) => t === i)}
|
].formKeysData.handle_keys.some(
|
||||||
|
(t) => t === key
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
key={k}
|
key={index}
|
||||||
keyValue={i}
|
keyValue={key}
|
||||||
>
|
>
|
||||||
<div className="file-component-tab-column">
|
<div className="file-component-tab-column">
|
||||||
{tabsState[id.current].formKeysData.handle_keys.some(
|
{tabsState[id.current].formKeysData.handle_keys.some(
|
||||||
(t) => t === i
|
(t) => t === key
|
||||||
) && (
|
) && (
|
||||||
<div className="font-normal text-muted-foreground ">
|
<div className="font-normal text-muted-foreground ">
|
||||||
Source: Component
|
Source: Component
|
||||||
|
|
@ -467,18 +469,18 @@ export default function FormModal({
|
||||||
<Textarea
|
<Textarea
|
||||||
className="custom-scroll"
|
className="custom-scroll"
|
||||||
value={
|
value={
|
||||||
tabsState[id.current].formKeysData.input_keys[i]
|
tabsState[id.current].formKeysData.input_keys[key]
|
||||||
}
|
}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setTabsState((old) => {
|
setTabsState((old) => {
|
||||||
let newTabsState = _.cloneDeep(old);
|
let newTabsState = _.cloneDeep(old);
|
||||||
newTabsState[
|
newTabsState[
|
||||||
id.current
|
id.current
|
||||||
].formKeysData.input_keys[i] = e.target.value;
|
].formKeysData.input_keys[key] = e.target.value;
|
||||||
return newTabsState;
|
return newTabsState;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
disabled={chatKey === i}
|
disabled={chatKey === key}
|
||||||
placeholder="Enter text..."
|
placeholder="Enter text..."
|
||||||
></Textarea>
|
></Textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -486,35 +488,37 @@ export default function FormModal({
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
: null}
|
: null}
|
||||||
{tabsState[id.current].formKeysData.memory_keys.map((i, k) => (
|
{tabsState[id.current].formKeysData.memory_keys.map(
|
||||||
<div className="file-component-accordion-div" key={k}>
|
(key, index) => (
|
||||||
<AccordionComponent
|
<div className="file-component-accordion-div" key={index}>
|
||||||
trigger={
|
<AccordionComponent
|
||||||
<div className="file-component-badge-div">
|
trigger={
|
||||||
<Badge variant="gray" size="md">
|
<div className="file-component-badge-div">
|
||||||
{i}
|
<Badge variant="gray" size="md">
|
||||||
</Badge>
|
{key}
|
||||||
<div className="-mb-1">
|
</Badge>
|
||||||
<ToggleShadComponent
|
<div className="-mb-1">
|
||||||
enabled={chatKey === i}
|
<ToggleShadComponent
|
||||||
setEnabled={() => {}}
|
enabled={chatKey === key}
|
||||||
size="small"
|
setEnabled={() => {}}
|
||||||
disabled={true}
|
size="small"
|
||||||
/>
|
disabled={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
key={index}
|
||||||
|
keyValue={key}
|
||||||
|
>
|
||||||
|
<div className="file-component-tab-column">
|
||||||
|
<div className="font-normal text-muted-foreground ">
|
||||||
|
Source: Memory
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
</AccordionComponent>
|
||||||
key={k}
|
</div>
|
||||||
keyValue={i}
|
)
|
||||||
>
|
)}
|
||||||
<div className="file-component-tab-column">
|
|
||||||
<div className="font-normal text-muted-foreground ">
|
|
||||||
Source: Memory
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AccordionComponent>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="eraser-column-arrangement">
|
<div className="eraser-column-arrangement">
|
||||||
<div className="eraser-size">
|
<div className="eraser-size">
|
||||||
|
|
@ -534,14 +538,14 @@ export default function FormModal({
|
||||||
</div>
|
</div>
|
||||||
<div ref={messagesRef} className="chat-message-div">
|
<div ref={messagesRef} className="chat-message-div">
|
||||||
{chatHistory.length > 0 ? (
|
{chatHistory.length > 0 ? (
|
||||||
chatHistory.map((c, i) => (
|
chatHistory.map((chat, index) => (
|
||||||
<ChatMessage
|
<ChatMessage
|
||||||
lockChat={lockChat}
|
lockChat={lockChat}
|
||||||
chat={c}
|
chat={chat}
|
||||||
lastMessage={
|
lastMessage={
|
||||||
chatHistory.length - 1 === i ? true : false
|
chatHistory.length - 1 === index ? true : false
|
||||||
}
|
}
|
||||||
key={i}
|
key={index}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -208,9 +208,9 @@ export default function GenericModal({
|
||||||
setIsEdit(false);
|
setIsEdit(false);
|
||||||
}}
|
}}
|
||||||
autoFocus
|
autoFocus
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
setInputValue(e.target.value);
|
setInputValue(event.target.value);
|
||||||
checkVariables(e.target.value);
|
checkVariables(event.target.value);
|
||||||
}}
|
}}
|
||||||
placeholder="Type message here."
|
placeholder="Type message here."
|
||||||
/>
|
/>
|
||||||
|
|
@ -221,8 +221,8 @@ export default function GenericModal({
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className="form-input h-full w-full rounded-lg focus-visible:ring-1"
|
className="form-input h-full w-full rounded-lg focus-visible:ring-1"
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
setInputValue(e.target.value);
|
setInputValue(event.target.value);
|
||||||
}}
|
}}
|
||||||
placeholder="Type message here."
|
placeholder="Type message here."
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ export default function DisclosureComponent({
|
||||||
<span className="components-disclosure-title">{title}</span>
|
<span className="components-disclosure-title">{title}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="components-disclosure-div">
|
<div className="components-disclosure-div">
|
||||||
{buttons.map((x, index) => (
|
{buttons.map((btn, index) => (
|
||||||
<button key={index} onClick={x.onClick}>
|
<button key={index} onClick={btn.onClick}>
|
||||||
{x.Icon}
|
{btn.Icon}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -141,10 +141,10 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
}, [setExtraComponent, setExtraNavigation]);
|
}, [setExtraComponent, setExtraNavigation]);
|
||||||
|
|
||||||
const onEdgesChangeMod = useCallback(
|
const onEdgesChangeMod = useCallback(
|
||||||
(s: EdgeChange[]) => {
|
(change: EdgeChange[]) => {
|
||||||
onEdgesChange(s);
|
onEdgesChange(change);
|
||||||
setNodes((x) => {
|
setNodes((node) => {
|
||||||
let newX = _.cloneDeep(x);
|
let newX = _.cloneDeep(node);
|
||||||
return newX;
|
return newX;
|
||||||
});
|
});
|
||||||
setTabsState((prev) => {
|
setTabsState((prev) => {
|
||||||
|
|
@ -161,8 +161,8 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
);
|
);
|
||||||
|
|
||||||
const onNodesChangeMod = useCallback(
|
const onNodesChangeMod = useCallback(
|
||||||
(s: NodeChange[]) => {
|
(change: NodeChange[]) => {
|
||||||
onNodesChange(s);
|
onNodesChange(change);
|
||||||
setTabsState((prev) => {
|
setTabsState((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
|
|
@ -193,8 +193,8 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
eds
|
eds
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
setNodes((x) => {
|
setNodes((node) => {
|
||||||
let newX = _.cloneDeep(x);
|
let newX = _.cloneDeep(node);
|
||||||
return newX;
|
return newX;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -219,7 +219,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
|
|
||||||
const onDragOver = useCallback((event: React.DragEvent) => {
|
const onDragOver = useCallback((event: React.DragEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (event.dataTransfer.types.some((t) => t === "nodedata")) {
|
if (event.dataTransfer.types.some((types) => types === "nodedata")) {
|
||||||
event.dataTransfer.dropEffect = "move";
|
event.dataTransfer.dropEffect = "move";
|
||||||
} else {
|
} else {
|
||||||
event.dataTransfer.dropEffect = "copy";
|
event.dataTransfer.dropEffect = "copy";
|
||||||
|
|
@ -229,7 +229,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
const onDrop = useCallback(
|
const onDrop = useCallback(
|
||||||
(event: React.DragEvent) => {
|
(event: React.DragEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (event.dataTransfer.types.some((t) => t === "nodedata")) {
|
if (event.dataTransfer.types.some((types) => types === "nodedata")) {
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
|
|
||||||
// Get the current bounds of the ReactFlow wrapper element
|
// Get the current bounds of the ReactFlow wrapper element
|
||||||
|
|
@ -281,7 +281,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
// Add the new node to the list of nodes in state
|
// Add the new node to the list of nodes in state
|
||||||
}
|
}
|
||||||
setNodes((nds) => nds.concat(newNode));
|
setNodes((nds) => nds.concat(newNode));
|
||||||
} else if (event.dataTransfer.types.some((t) => t === "Files")) {
|
} else if (event.dataTransfer.types.some((types) => types === "Files")) {
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
uploadFlow(false, event.dataTransfer.files.item(0));
|
uploadFlow(false, event.dataTransfer.files.item(0));
|
||||||
}
|
}
|
||||||
|
|
@ -303,7 +303,10 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
setEdges(
|
setEdges(
|
||||||
edges.filter(
|
edges.filter(
|
||||||
(ns) => !mynodes.some((n) => ns.source === n.id || ns.target === n.id)
|
(edge) =>
|
||||||
|
!mynodes.some(
|
||||||
|
(node) => edge.source === node.id || edge.target === node.id
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -326,7 +329,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
|
|
||||||
const onEdgeUpdateEnd = useCallback((_, edge) => {
|
const onEdgeUpdateEnd = useCallback((_, edge) => {
|
||||||
if (!edgeUpdateSuccessful.current) {
|
if (!edgeUpdateSuccessful.current) {
|
||||||
setEdges((eds) => eds.filter((e) => e.id !== edge.id));
|
setEdges((eds) => eds.filter((edg) => edg.id !== edge.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
edgeUpdateSuccessful.current = true;
|
edgeUpdateSuccessful.current = true;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ export default function ExtraSidebar() {
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const flow = flows.find((f) => f.id === tabId);
|
const flow = flows.find((flow) => flow.id === tabId);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// show components with error on load
|
// show components with error on load
|
||||||
let errors = [];
|
let errors = [];
|
||||||
|
|
@ -143,10 +143,10 @@ export default function ExtraSidebar() {
|
||||||
id="search"
|
id="search"
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
className="nopan nodrag noundo nocopy input-search"
|
className="nopan nodrag noundo nocopy input-search"
|
||||||
onChange={(e) => {
|
onChange={(event) => {
|
||||||
handleSearchInput(e.target.value);
|
handleSearchInput(event.target.value);
|
||||||
// Set search input state
|
// Set search input state
|
||||||
setSearch(e.target.value);
|
setSearch(event.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="search-icon">
|
<div className="search-icon">
|
||||||
|
|
@ -161,42 +161,43 @@ export default function ExtraSidebar() {
|
||||||
<div className="side-bar-components-div-arrangement">
|
<div className="side-bar-components-div-arrangement">
|
||||||
{Object.keys(dataFilter)
|
{Object.keys(dataFilter)
|
||||||
.sort()
|
.sort()
|
||||||
.map((d: keyof APIObjectType, i) =>
|
.map((SBSectionName: keyof APIObjectType, index) =>
|
||||||
Object.keys(dataFilter[d]).length > 0 ? (
|
Object.keys(dataFilter[SBSectionName]).length > 0 ? (
|
||||||
<DisclosureComponent
|
<DisclosureComponent
|
||||||
openDisc={search.length == 0 ? false : true}
|
openDisc={search.length == 0 ? false : true}
|
||||||
key={i}
|
key={index}
|
||||||
button={{
|
button={{
|
||||||
title: nodeNames[d] ?? nodeNames.unknown,
|
title: nodeNames[SBSectionName] ?? nodeNames.unknown,
|
||||||
Icon: nodeIconsLucide[d] ?? nodeIconsLucide.unknown,
|
Icon:
|
||||||
|
nodeIconsLucide[SBSectionName] ?? nodeIconsLucide.unknown,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="side-bar-components-gap">
|
<div className="side-bar-components-gap">
|
||||||
{Object.keys(dataFilter[d])
|
{Object.keys(dataFilter[SBSectionName])
|
||||||
.sort()
|
.sort()
|
||||||
.map((t: string, k) => (
|
.map((SBItemName: string, index) => (
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={data[d][t].display_name}
|
content={data[SBSectionName][SBItemName].display_name}
|
||||||
side="right"
|
side="right"
|
||||||
key={k}
|
key={index}
|
||||||
>
|
>
|
||||||
<div key={k} data-tooltip-id={t}>
|
<div key={index} data-tooltip-id={SBItemName}>
|
||||||
<div
|
<div
|
||||||
draggable={!data[d][t].error}
|
draggable={!data[SBSectionName][SBItemName].error}
|
||||||
className={
|
className={
|
||||||
"side-bar-components-border bg-background" +
|
"side-bar-components-border bg-background" +
|
||||||
(data[d][t].error
|
(data[SBSectionName][SBItemName].error
|
||||||
? " cursor-not-allowed select-none"
|
? " cursor-not-allowed select-none"
|
||||||
: "")
|
: "")
|
||||||
}
|
}
|
||||||
style={{
|
style={{
|
||||||
borderLeftColor:
|
borderLeftColor:
|
||||||
nodeColors[d] ?? nodeColors.unknown,
|
nodeColors[SBSectionName] ?? nodeColors.unknown,
|
||||||
}}
|
}}
|
||||||
onDragStart={(event) =>
|
onDragStart={(event) =>
|
||||||
onDragStart(event, {
|
onDragStart(event, {
|
||||||
type: t,
|
type: SBItemName,
|
||||||
node: data[d][t],
|
node: data[SBSectionName][SBItemName],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onDragEnd={() => {
|
onDragEnd={() => {
|
||||||
|
|
@ -209,7 +210,7 @@ export default function ExtraSidebar() {
|
||||||
>
|
>
|
||||||
<div className="side-bar-components-div-form">
|
<div className="side-bar-components-div-form">
|
||||||
<span className="side-bar-components-text">
|
<span className="side-bar-components-text">
|
||||||
{data[d][t].display_name}
|
{data[SBSectionName][SBItemName].display_name}
|
||||||
</span>
|
</span>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
name="Menu"
|
name="Menu"
|
||||||
|
|
@ -223,7 +224,7 @@ export default function ExtraSidebar() {
|
||||||
</div>
|
</div>
|
||||||
</DisclosureComponent>
|
</DisclosureComponent>
|
||||||
) : (
|
) : (
|
||||||
<div key={i}></div>
|
<div key={index}></div>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,17 @@ import { classNames } from "../../../../utils/utils";
|
||||||
export default function NodeToolbarComponent({ data, setData, deleteNode }) {
|
export default function NodeToolbarComponent({ data, setData, deleteNode }) {
|
||||||
const [nodeLength, setNodeLength] = useState(
|
const [nodeLength, setNodeLength] = useState(
|
||||||
Object.keys(data.node.template).filter(
|
Object.keys(data.node.template).filter(
|
||||||
(t) =>
|
(templateField) =>
|
||||||
t.charAt(0) !== "_" &&
|
templateField.charAt(0) !== "_" &&
|
||||||
data.node.template[t].show &&
|
data.node.template[templateField].show &&
|
||||||
(data.node.template[t].type === "str" ||
|
(data.node.template[templateField].type === "str" ||
|
||||||
data.node.template[t].type === "bool" ||
|
data.node.template[templateField].type === "bool" ||
|
||||||
data.node.template[t].type === "float" ||
|
data.node.template[templateField].type === "float" ||
|
||||||
data.node.template[t].type === "code" ||
|
data.node.template[templateField].type === "code" ||
|
||||||
data.node.template[t].type === "prompt" ||
|
data.node.template[templateField].type === "prompt" ||
|
||||||
data.node.template[t].type === "file" ||
|
data.node.template[templateField].type === "file" ||
|
||||||
data.node.template[t].type === "Any" ||
|
data.node.template[templateField].type === "Any" ||
|
||||||
data.node.template[t].type === "int")
|
data.node.template[templateField].type === "int")
|
||||||
).length
|
).length
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export function cleanEdges({
|
||||||
const sourceNode = nodes.find((node) => node.id === edge.source);
|
const sourceNode = nodes.find((node) => node.id === edge.source);
|
||||||
const targetNode = nodes.find((node) => node.id === edge.target);
|
const targetNode = nodes.find((node) => node.id === edge.target);
|
||||||
if (!sourceNode || !targetNode) {
|
if (!sourceNode || !targetNode) {
|
||||||
newEdges = newEdges.filter((e) => e.id !== edge.id);
|
newEdges = newEdges.filter((edg) => edg.id !== edge.id);
|
||||||
}
|
}
|
||||||
// check if the source and target handle still exists
|
// check if the source and target handle still exists
|
||||||
if (sourceNode && targetNode) {
|
if (sourceNode && targetNode) {
|
||||||
|
|
@ -41,7 +41,7 @@ export function cleanEdges({
|
||||||
...sourceNode.data.node.base_classes,
|
...sourceNode.data.node.base_classes,
|
||||||
].join("|");
|
].join("|");
|
||||||
if (id !== sourceHandle) {
|
if (id !== sourceHandle) {
|
||||||
newEdges = newEdges.filter((e) => e.id !== edge.id);
|
newEdges = newEdges.filter((edg) => edg.id !== edge.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -57,15 +57,15 @@ export function isValidConnection(
|
||||||
targetHandle
|
targetHandle
|
||||||
.split("|")[0]
|
.split("|")[0]
|
||||||
.split(";")
|
.split(";")
|
||||||
.some((n) => n === sourceHandle.split("|")[0]) ||
|
.some((target) => target === sourceHandle.split("|")[0]) ||
|
||||||
sourceHandle
|
sourceHandle
|
||||||
.split("|")
|
.split("|")
|
||||||
.slice(2)
|
.slice(2)
|
||||||
.some((t) =>
|
.some((target) =>
|
||||||
targetHandle
|
targetHandle
|
||||||
.split("|")[0]
|
.split("|")[0]
|
||||||
.split(";")
|
.split(";")
|
||||||
.some((n) => n === t)
|
.some((n) => n === target)
|
||||||
) ||
|
) ||
|
||||||
targetHandle.split("|")[0] === "str"
|
targetHandle.split("|")[0] === "str"
|
||||||
) {
|
) {
|
||||||
|
|
@ -129,35 +129,35 @@ export function updateTemplate(
|
||||||
export function updateIds(newFlow, getNodeId) {
|
export function updateIds(newFlow, getNodeId) {
|
||||||
let idsMap = {};
|
let idsMap = {};
|
||||||
|
|
||||||
newFlow.nodes.forEach((n: NodeType) => {
|
newFlow.nodes.forEach((node: NodeType) => {
|
||||||
// Generate a unique node ID
|
// Generate a unique node ID
|
||||||
let newId = getNodeId(n.data.type);
|
let newId = getNodeId(node.data.type);
|
||||||
idsMap[n.id] = newId;
|
idsMap[node.id] = newId;
|
||||||
n.id = newId;
|
node.id = newId;
|
||||||
n.data.id = newId;
|
node.data.id = newId;
|
||||||
// Add the new node to the list of nodes in state
|
// Add the new node to the list of nodes in state
|
||||||
});
|
});
|
||||||
|
|
||||||
newFlow.edges.forEach((e) => {
|
newFlow.edges.forEach((edge) => {
|
||||||
e.source = idsMap[e.source];
|
edge.source = idsMap[edge.source];
|
||||||
e.target = idsMap[e.target];
|
edge.target = idsMap[edge.target];
|
||||||
let sourceHandleSplitted = e.sourceHandle.split("|");
|
let sourceHandleSplitted = edge.sourceHandle.split("|");
|
||||||
e.sourceHandle =
|
edge.sourceHandle =
|
||||||
sourceHandleSplitted[0] +
|
sourceHandleSplitted[0] +
|
||||||
"|" +
|
"|" +
|
||||||
e.source +
|
edge.source +
|
||||||
"|" +
|
"|" +
|
||||||
sourceHandleSplitted.slice(2).join("|");
|
sourceHandleSplitted.slice(2).join("|");
|
||||||
let targetHandleSplitted = e.targetHandle.split("|");
|
let targetHandleSplitted = edge.targetHandle.split("|");
|
||||||
e.targetHandle =
|
edge.targetHandle =
|
||||||
targetHandleSplitted.slice(0, -1).join("|") + "|" + e.target;
|
targetHandleSplitted.slice(0, -1).join("|") + "|" + edge.target;
|
||||||
e.id =
|
edge.id =
|
||||||
"reactflow__edge-" +
|
"reactflow__edge-" +
|
||||||
e.source +
|
edge.source +
|
||||||
e.sourceHandle +
|
edge.sourceHandle +
|
||||||
"-" +
|
"-" +
|
||||||
e.target +
|
edge.target +
|
||||||
e.targetHandle;
|
edge.targetHandle;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,10 +169,10 @@ export function buildTweaks(flow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateNode(
|
export function validateNode(
|
||||||
n: NodeType,
|
node: NodeType,
|
||||||
reactFlowInstance: ReactFlowInstance
|
reactFlowInstance: ReactFlowInstance
|
||||||
): Array<string> {
|
): Array<string> {
|
||||||
if (!n.data?.node?.template || !Object.keys(n.data.node.template)) {
|
if (!node.data?.node?.template || !Object.keys(node.data.node.template)) {
|
||||||
return [
|
return [
|
||||||
"We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!",
|
"We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!",
|
||||||
];
|
];
|
||||||
|
|
@ -181,7 +181,7 @@ export function validateNode(
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
node: { template },
|
node: { template },
|
||||||
} = n.data;
|
} = node.data;
|
||||||
|
|
||||||
return Object.keys(template).reduce(
|
return Object.keys(template).reduce(
|
||||||
(errors: Array<string>, t) =>
|
(errors: Array<string>, t) =>
|
||||||
|
|
@ -194,9 +194,9 @@ export function validateNode(
|
||||||
!reactFlowInstance
|
!reactFlowInstance
|
||||||
.getEdges()
|
.getEdges()
|
||||||
.some(
|
.some(
|
||||||
(e) =>
|
(edge) =>
|
||||||
e.targetHandle.split("|")[1] === t &&
|
edge.targetHandle.split("|")[1] === t &&
|
||||||
e.targetHandle.split("|")[2] === n.id
|
edge.targetHandle.split("|")[2] === node.id
|
||||||
)
|
)
|
||||||
? [
|
? [
|
||||||
`${type} is missing ${
|
`${type} is missing ${
|
||||||
|
|
|
||||||
|
|
@ -103,11 +103,14 @@ export function groupByFamily(data, baseClasses, left, flow?: NodeType[]) {
|
||||||
"int",
|
"int",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const checkBaseClass = (t: any) =>
|
const checkBaseClass = (template: any) =>
|
||||||
t.type &&
|
template.type &&
|
||||||
t.show &&
|
template.show &&
|
||||||
((!excludeTypes.has(t.type) && baseClassesSet.has(t.type)) ||
|
((!excludeTypes.has(template.type) && baseClassesSet.has(template.type)) ||
|
||||||
(t.input_types && t.input_types.some((x) => baseClassesSet.has(x))));
|
(template.input_types &&
|
||||||
|
template.input_types.some((inputType) =>
|
||||||
|
baseClassesSet.has(inputType)
|
||||||
|
)));
|
||||||
|
|
||||||
if (flow) {
|
if (flow) {
|
||||||
for (const node of flow) {
|
for (const node of flow) {
|
||||||
|
|
@ -119,7 +122,9 @@ export function groupByFamily(data, baseClasses, left, flow?: NodeType[]) {
|
||||||
Object.values(nodeData.node.template).some(checkBaseClass),
|
Object.values(nodeData.node.template).some(checkBaseClass),
|
||||||
hasBaseClassInBaseClasses:
|
hasBaseClassInBaseClasses:
|
||||||
foundNode?.hasBaseClassInBaseClasses ||
|
foundNode?.hasBaseClassInBaseClasses ||
|
||||||
nodeData.node.base_classes.some((t) => baseClassesSet.has(t)),
|
nodeData.node.base_classes.some((baseClass) =>
|
||||||
|
baseClassesSet.has(baseClass)
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -135,8 +140,8 @@ export function groupByFamily(data, baseClasses, left, flow?: NodeType[]) {
|
||||||
hasBaseClassInTemplate: Object.values(node.template).some(
|
hasBaseClassInTemplate: Object.values(node.template).some(
|
||||||
checkBaseClass
|
checkBaseClass
|
||||||
),
|
),
|
||||||
hasBaseClassInBaseClasses: node.base_classes.some((t) =>
|
hasBaseClassInBaseClasses: node.base_classes.some((baseClass) =>
|
||||||
baseClassesSet.has(t)
|
baseClassesSet.has(baseClass)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
checkedNodes.set(n, foundNode);
|
checkedNodes.set(n, foundNode);
|
||||||
|
|
@ -162,13 +167,13 @@ export function groupByFamily(data, baseClasses, left, flow?: NodeType[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return left
|
return left
|
||||||
? arrOfPossibleOutputs.map((t) => ({
|
? arrOfPossibleOutputs.map((output) => ({
|
||||||
family: t.category,
|
family: output.category,
|
||||||
type: t.full ? "" : t.nodes.join(", "),
|
type: output.full ? "" : output.nodes.join(", "),
|
||||||
}))
|
}))
|
||||||
: arrOfPossibleInputs.map((t) => ({
|
: arrOfPossibleInputs.map((input) => ({
|
||||||
family: t.category,
|
family: input.category,
|
||||||
type: t.full ? "" : t.nodes.join(", "),
|
type: input.full ? "" : input.nodes.join(", "),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue