Merge remote-tracking branch 'origin/dev' into v2

This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-11-02 17:09:04 -03:00
commit 15e244f17a
46 changed files with 1663 additions and 1024 deletions

View file

@ -12,6 +12,22 @@ Embeddings are vector representations of text that capture the semantic meaning
--- ---
### BedrockEmbeddings
Used to load [Amazon Bedrocks’s](https://aws.amazon.com/bedrock/) embedding models.
**Params**
- **credentials_profile_name:** The name of the profile in the ~/.aws/credentials or ~/.aws/config files, which has either access keys or role information specified. If not specified, the default credential profile or, if on an EC2 instance, credentials from IMDS will be used. See [the AWS documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html) for more details.
- **model_id:** Id of the model to call, e.g., amazon.titan-embed-text-v1, this is equivalent to the modelId property in the list-foundation-models api.
- **endpoint_url:** Needed if you don’t want to default to us-east-1 endpoint.
- **region_name:** The aws region e.g., us-west-2. Fallsback to AWS_DEFAULT_REGION env variable or region specified in ~/.aws/config in case it is not provided here.
---
### CohereEmbeddings ### CohereEmbeddings
Used to load [Cohere’s](https://cohere.com/) embedding models. Used to load [Cohere’s](https://cohere.com/) embedding models.

1499
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "langflow" name = "langflow"
version = "0.5.0a1" version = "0.5.5"
description = "A Python package with a built-in web application" description = "A Python package with a built-in web application"
authors = ["Logspace <contact@logspace.ai>"] authors = ["Logspace <contact@logspace.ai>"]
maintainers = [ maintainers = [
@ -94,7 +94,9 @@ langfuse = "^1.1.1"
pillow = "^10.0.0" pillow = "^10.0.0"
metal-sdk = "^2.4.0" metal-sdk = "^2.4.0"
markupsafe = "^2.1.3" markupsafe = "^2.1.3"
boto3 = "^1.28.63"
numexpr = "^2.8.6"
qianfan = "0.0.5"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
types-redis = "^4.6.0.5" types-redis = "^4.6.0.5"

View file

@ -0,0 +1,46 @@
from typing import Optional
from langflow import CustomComponent
from langchain.embeddings import BedrockEmbeddings
from langchain.embeddings.base import Embeddings
class AmazonBedrockEmeddingsComponent(CustomComponent):
"""
A custom component for implementing an Embeddings Model using Amazon Bedrock.
"""
display_name: str = "Amazon Bedrock Embeddings"
description: str = "Embeddings model from Amazon Bedrock."
documentation = "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock"
beta = True
def build_config(self):
return {
"model_id": {
"display_name": "Model Id",
"options": ["amazon.titan-embed-text-v1"],
},
"credentials_profile_name": {"display_name": "Credentials Profile Name"},
"endpoint_url": {"display_name": "Bedrock Endpoint URL"},
"region_name": {"display_name": "AWS Region"},
"code": {"show": False},
}
def build(
self,
model_id: str = "amazon.titan-embed-text-v1",
credentials_profile_name: Optional[str] = None,
endpoint_url: Optional[str] = None,
region_name: Optional[str] = None,
) -> Embeddings:
try:
output = BedrockEmbeddings(
credentials_profile_name=credentials_profile_name,
model_id=model_id,
endpoint_url=endpoint_url,
region_name=region_name,
) # type: ignore
except Exception as e:
raise ValueError("Could not connect to AmazonBedrock API.") from e
return output

View file

@ -0,0 +1,45 @@
from typing import Optional
from langflow import CustomComponent
from langchain.llms.bedrock import Bedrock
from langchain.llms.base import BaseLLM
class AmazonBedrockComponent(CustomComponent):
display_name: str = "Amazon Bedrock"
description: str = "LLM model from Amazon Bedrock."
def build_config(self):
return {
"model_id": {
"display_name": "Model Id",
"options": [
"ai21.j2-grande-instruct",
"ai21.j2-jumbo-instruct",
"ai21.j2-mid",
"ai21.j2-mid-v1",
"ai21.j2-ultra",
"ai21.j2-ultra-v1",
"anthropic.claude-instant-v1",
"anthropic.claude-v1",
"anthropic.claude-v2",
"cohere.command-text-v14",
],
},
"credentials_profile_name": {"display_name": "Credentials Profile Name"},
"streaming": {"display_name": "Streaming", "field_type": "bool"},
"code": {"show": False},
}
def build(
self,
model_id: str = "anthropic.claude-instant-v1",
credentials_profile_name: Optional[str] = None,
) -> BaseLLM:
try:
output = Bedrock(
credentials_profile_name=credentials_profile_name,
model_id=model_id,
) # type: ignore
except Exception as e:
raise ValueError("Could not connect to AmazonBedrock API.") from e
return output

View file

@ -0,0 +1,48 @@
from typing import Optional
from langflow import CustomComponent
from langchain.retrievers import AmazonKendraRetriever
from langchain.schema import BaseRetriever
class AmazonKendraRetrieverComponent(CustomComponent):
display_name: str = "Amazon Kendra Retriever"
description: str = "Retriever that uses the Amazon Kendra API."
def build_config(self):
return {
"index_id": {"display_name": "Index ID"},
"region_name": {"display_name": "Region Name"},
"credentials_profile_name": {"display_name": "Credentials Profile Name"},
"attribute_filter": {
"display_name": "Attribute Filter",
"field_type": "code",
},
"top_k": {"display_name": "Top K", "field_type": "int"},
"user_context": {
"display_name": "User Context",
"field_type": "code",
},
"code": {"show": False},
}
def build(
self,
index_id: str,
top_k: int = 3,
region_name: Optional[str] = None,
credentials_profile_name: Optional[str] = None,
attribute_filter: Optional[dict] = None,
user_context: Optional[dict] = None,
) -> BaseRetriever:
try:
output = AmazonKendraRetriever(
index_id=index_id,
top_k=top_k,
region_name=region_name,
credentials_profile_name=credentials_profile_name,
attribute_filter=attribute_filter,
user_context=user_context,
) # type: ignore
except Exception as e:
raise ValueError("Could not connect to AmazonKendra API.") from e
return output

View file

@ -14,7 +14,7 @@ class ChromaComponent(CustomComponent):
A custom component for implementing a Vector Store using Chroma. A custom component for implementing a Vector Store using Chroma.
""" """
display_name: str = "Chroma (Custom Component)" display_name: str = "Chroma"
description: str = "Implementation of Vector Store using Chroma" description: str = "Implementation of Vector Store using Chroma"
documentation = "https://python.langchain.com/docs/integrations/vectorstores/chroma" documentation = "https://python.langchain.com/docs/integrations/vectorstores/chroma"
beta: str = True beta: str = True

View file

@ -106,6 +106,9 @@ embeddings:
documentation: "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/cohere" documentation: "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/cohere"
VertexAIEmbeddings: VertexAIEmbeddings:
documentation: "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/google_vertex_ai_palm" documentation: "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/google_vertex_ai_palm"
AmazonBedrockEmbeddings:
documentation: "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock"
llms: llms:
OpenAI: OpenAI:
documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai" documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai"
@ -265,8 +268,8 @@ retrievers:
# ZepRetriever: # ZepRetriever:
# documentation: "https://python.langchain.com/docs/modules/data_connection/retrievers/integrations/zep_memorystore" # documentation: "https://python.langchain.com/docs/modules/data_connection/retrievers/integrations/zep_memorystore"
vectorstores: vectorstores:
Chroma: # Chroma:
documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/chroma" # documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/chroma"
Qdrant: Qdrant:
documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/qdrant" documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/qdrant"
Weaviate: Weaviate:

View file

@ -106,9 +106,9 @@ class CSVAgent(CustomAgentExecutor):
tools, tools,
prefix=PANDAS_PREFIX, prefix=PANDAS_PREFIX,
suffix=PANDAS_SUFFIX, suffix=PANDAS_SUFFIX,
input_variables=["df", "input", "agent_scratchpad"], input_variables=["df_head", "input", "agent_scratchpad"],
) )
partial_prompt = prompt.partial(df=str(df.head())) partial_prompt = prompt.partial(df_head=str(df.head()))
llm_chain = LLMChain( llm_chain = LLMChain(
llm=llm, llm=llm,
prompt=partial_prompt, prompt=partial_prompt,

View file

@ -300,6 +300,8 @@ def instantiate_embedding(node_type, class_object, params: Dict):
def instantiate_vectorstore(class_object: Type[VectorStore], params: Dict): def instantiate_vectorstore(class_object: Type[VectorStore], params: Dict):
search_kwargs = params.pop("search_kwargs", {}) search_kwargs = params.pop("search_kwargs", {})
if search_kwargs == {"yourkey": "value"}:
search_kwargs = {}
# clean up docs or texts to have only documents # clean up docs or texts to have only documents
if "texts" in params: if "texts" in params:
params["documents"] = params.pop("texts") params["documents"] = params.pop("texts")

File diff suppressed because it is too large Load diff

View file

@ -16,8 +16,8 @@ import {
FETCH_ERROR_MESSAGE, FETCH_ERROR_MESSAGE,
} from "./constants/constants"; } from "./constants/constants";
import { alertContext } from "./contexts/alertContext"; import { alertContext } from "./contexts/alertContext";
import { FlowsContext } from "./contexts/flowsContext";
import { locationContext } from "./contexts/locationContext"; import { locationContext } from "./contexts/locationContext";
import { TabsContext } from "./contexts/tabsContext";
import { typesContext } from "./contexts/typesContext"; import { typesContext } from "./contexts/typesContext";
import Router from "./routes"; import Router from "./routes";
@ -30,7 +30,7 @@ export default function App() {
setShowSideBar(true); setShowSideBar(true);
setIsStackedOpen(true); setIsStackedOpen(true);
}, [location.pathname, setCurrent, setIsStackedOpen, setShowSideBar]); }, [location.pathname, setCurrent, setIsStackedOpen, setShowSideBar]);
const { hardReset } = useContext(TabsContext); const { hardReset } = useContext(FlowsContext);
const { const {
errorData, errorData,

View file

@ -23,10 +23,9 @@ import TextAreaComponent from "../../../../components/textAreaComponent";
import ToggleShadComponent from "../../../../components/toggleShadComponent"; import ToggleShadComponent from "../../../../components/toggleShadComponent";
import { Button } from "../../../../components/ui/button"; import { Button } from "../../../../components/ui/button";
import { TOOLTIP_EMPTY } from "../../../../constants/constants"; import { TOOLTIP_EMPTY } from "../../../../constants/constants";
import { TabsContext } from "../../../../contexts/tabsContext"; import { FlowsContext } from "../../../../contexts/flowsContext";
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 { import {
convertObjToArray, convertObjToArray,
convertValuesToNumbers, convertValuesToNumbers,
@ -63,7 +62,7 @@ export default function ParameterComponent({
const infoHtml = useRef<HTMLDivElement & ReactNode>(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, flows } = useContext(TabsContext); const { setTabsState, tabId, flows } = useContext(FlowsContext);
const flow = flows.find((flow) => flow.id === tabId)?.data?.nodes ?? null; const flow = flows.find((flow) => flow.id === tabId)?.data?.nodes ?? null;

View file

@ -7,7 +7,7 @@ import IconComponent from "../../components/genericIconComponent";
import InputComponent from "../../components/inputComponent"; import InputComponent from "../../components/inputComponent";
import { Textarea } from "../../components/ui/textarea"; import { Textarea } from "../../components/ui/textarea";
import { useSSE } from "../../contexts/SSEContext"; import { useSSE } from "../../contexts/SSEContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { typesContext } from "../../contexts/typesContext"; import { typesContext } from "../../contexts/typesContext";
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent"; import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
import { validationStatusType } from "../../types/components"; import { validationStatusType } from "../../types/components";
@ -18,7 +18,7 @@ import {
scapedJSONStringfy, scapedJSONStringfy,
} from "../../utils/reactflowUtils"; } from "../../utils/reactflowUtils";
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils"; import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
import { classNames, toTitleCase } from "../../utils/utils"; import { classNames, getFieldTitle } from "../../utils/utils";
import ParameterComponent from "./components/parameterComponent"; import ParameterComponent from "./components/parameterComponent";
export default function GenericNode({ export default function GenericNode({
@ -33,7 +33,7 @@ export default function GenericNode({
yPos: number; yPos: number;
}): JSX.Element { }): JSX.Element {
const [data, setData] = useState(olddata); const [data, setData] = useState(olddata);
const { updateFlow, flows, tabId } = useContext(TabsContext); const { updateFlow, flows, tabId } = useContext(FlowsContext);
const updateNodeInternals = useUpdateNodeInternals(); const updateNodeInternals = useUpdateNodeInternals();
const { types, deleteNode, reactFlowInstance, setFilterEdge, getFilterEdge } = const { types, deleteNode, reactFlowInstance, setFilterEdge, getFilterEdge } =
useContext(typesContext); useContext(typesContext);
@ -239,15 +239,10 @@ export default function GenericNode({
] ?? ] ??
nodeColors.unknown nodeColors.unknown
} }
title={ title={getFieldTitle(
data.node?.template[templateField].display_name data.node?.template!,
? data.node.template[templateField].display_name templateField
: data.node?.template[templateField].name )}
? toTitleCase(
data.node.template[templateField].name
)
: toTitleCase(templateField)
}
info={data.node?.template[templateField].info} info={data.node?.template[templateField].info}
name={templateField} name={templateField}
tooltipTitle={ tooltipTitle={
@ -448,15 +443,10 @@ export default function GenericNode({
] ?? ] ??
nodeColors.unknown nodeColors.unknown
} }
title={ title={getFieldTitle(
data.node?.template[templateField].display_name data.node?.template!,
? data.node.template[templateField].display_name templateField
: data.node?.template[templateField].name )}
? toTitleCase(
data.node.template[templateField].name
)
: toTitleCase(templateField)
}
info={data.node?.template[templateField].info} info={data.node?.template[templateField].info}
name={templateField} name={templateField}
tooltipTitle={ tooltipTitle={

View file

@ -1,5 +1,5 @@
import { useContext } from "react"; import { useContext } from "react";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { cardComponentPropsType } from "../../types/components"; import { cardComponentPropsType } from "../../types/components";
import { gradients } from "../../utils/styleUtils"; import { gradients } from "../../utils/styleUtils";
import IconComponent from "../genericIconComponent"; import IconComponent from "../genericIconComponent";
@ -17,7 +17,7 @@ export const CardComponent = ({
onDelete, onDelete,
button, button,
}: cardComponentPropsType): JSX.Element => { }: cardComponentPropsType): JSX.Element => {
const { removeFlow } = useContext(TabsContext); const { removeFlow } = useContext(FlowsContext);
return ( return (
<Card className="group"> <Card className="group">

View file

@ -7,9 +7,9 @@ import { typesContext } from "../../../contexts/typesContext";
import { postBuildInit } from "../../../controllers/API"; import { postBuildInit } from "../../../controllers/API";
import { FlowType } from "../../../types/flow"; import { FlowType } from "../../../types/flow";
import { TabsContext } from "../../../contexts/tabsContext"; import { FlowsContext } from "../../../contexts/flowsContext";
import { parsedDataType } from "../../../types/components"; import { parsedDataType } from "../../../types/components";
import { TabsState } from "../../../types/tabs"; import { FlowsState } from "../../../types/tabs";
import { validateNodes } from "../../../utils/reactflowUtils"; import { validateNodes } from "../../../utils/reactflowUtils";
import RadialProgressComponent from "../../RadialProgress"; import RadialProgressComponent from "../../RadialProgress";
import IconComponent from "../../genericIconComponent"; import IconComponent from "../../genericIconComponent";
@ -26,7 +26,7 @@ export default function BuildTrigger({
}): JSX.Element { }): JSX.Element {
const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE(); const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE();
const { reactFlowInstance } = useContext(typesContext); const { reactFlowInstance } = useContext(typesContext);
const { setTabsState } = useContext(TabsContext); const { setTabsState } = useContext(FlowsContext);
const { setErrorData, setSuccessData } = useContext(alertContext); const { setErrorData, setSuccessData } = useContext(alertContext);
const [isIconTouched, setIsIconTouched] = useState(false); const [isIconTouched, setIsIconTouched] = useState(false);
const eventClick = isBuilding ? "pointer-events-none" : ""; const eventClick = isBuilding ? "pointer-events-none" : "";
@ -99,7 +99,7 @@ export default function BuildTrigger({
setSuccessData({ title: parsedData.log }); setSuccessData({ title: parsedData.log });
} else if (parsedData.input_keys !== undefined) { } else if (parsedData.input_keys !== undefined) {
//@ts-ignore //@ts-ignore
setTabsState((old: TabsState) => { setTabsState((old: FlowsState) => {
return { return {
...old, ...old,
[flowId]: { [flowId]: {

View file

@ -5,7 +5,7 @@ import BuildTrigger from "./buildTrigger";
import ChatTrigger from "./chatTrigger"; import ChatTrigger from "./chatTrigger";
import * as _ from "lodash"; import * as _ from "lodash";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { getBuildStatus } from "../../controllers/API"; import { getBuildStatus } from "../../controllers/API";
import FormModal from "../../modals/formModal"; import FormModal from "../../modals/formModal";
import { NodeType } from "../../types/flow"; import { NodeType } from "../../types/flow";
@ -13,7 +13,7 @@ import { NodeType } from "../../types/flow";
export default function Chat({ flow }: ChatType): JSX.Element { export default function Chat({ flow }: ChatType): JSX.Element {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [canOpen, setCanOpen] = useState(false); const [canOpen, setCanOpen] = useState(false);
const { tabsState, isBuilt, setIsBuilt } = useContext(TabsContext); const { tabsState, isBuilt, setIsBuilt } = useContext(FlowsContext);
useEffect(() => { useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => { const handleKeyDown = (event: KeyboardEvent) => {

View file

@ -1,5 +1,5 @@
import { useContext, useState } from "react"; import { useContext, useState } from "react";
import { TabsContext } from "../../../../contexts/tabsContext"; import { FlowsContext } from "../../../../contexts/flowsContext";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@ -17,7 +17,7 @@ import IconComponent from "../../../genericIconComponent";
import { Button } from "../../../ui/button"; import { Button } from "../../../ui/button";
export const MenuBar = ({ flows, tabId }: menuBarPropsType): JSX.Element => { export const MenuBar = ({ flows, tabId }: menuBarPropsType): JSX.Element => {
const { addFlow } = useContext(TabsContext); const { addFlow } = useContext(FlowsContext);
const { setErrorData } = useContext(alertContext); const { setErrorData } = useContext(alertContext);
const { undo, redo } = useContext(undoRedoContext); const { undo, redo } = useContext(undoRedoContext);
const [openSettings, setOpenSettings] = useState(false); const [openSettings, setOpenSettings] = useState(false);

View file

@ -6,7 +6,7 @@ import { USER_PROJECTS_HEADER } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { darkContext } from "../../contexts/darkContext"; import { darkContext } from "../../contexts/darkContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { gradients } from "../../utils/styleUtils"; import { gradients } from "../../utils/styleUtils";
import IconComponent from "../genericIconComponent"; import IconComponent from "../genericIconComponent";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
@ -22,7 +22,7 @@ import { Separator } from "../ui/separator";
import MenuBar from "./components/menuBar"; import MenuBar from "./components/menuBar";
export default function Header(): JSX.Element { export default function Header(): JSX.Element {
const { flows, tabId } = useContext(TabsContext); const { flows, tabId } = useContext(FlowsContext);
const { dark, setDark } = useContext(darkContext); const { dark, setDark } = useContext(darkContext);
const { notificationCenter } = useContext(alertContext); const { notificationCenter } = useContext(alertContext);
const location = useLocation(); const location = useLocation();

View file

@ -1,6 +1,6 @@
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { uploadFile } from "../../controllers/API"; import { uploadFile } from "../../controllers/API";
import { FileComponentType } from "../../types/components"; import { FileComponentType } from "../../types/components";
import IconComponent from "../genericIconComponent"; import IconComponent from "../genericIconComponent";
@ -17,7 +17,7 @@ export default function InputFileComponent({
const [myValue, setMyValue] = useState(value); const [myValue, setMyValue] = useState(value);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const { setErrorData } = useContext(alertContext); const { setErrorData } = useContext(alertContext);
const { tabId } = useContext(TabsContext); const { tabId } = useContext(FlowsContext);
// Clear component state // Clear component state
useEffect(() => { useEffect(() => {

View file

@ -1,5 +1,5 @@
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import _ from "lodash"; import _, { cloneDeep } from "lodash";
import { import {
ReactNode, ReactNode,
createContext, createContext,
@ -28,7 +28,7 @@ import {
sourceHandleType, sourceHandleType,
targetHandleType, targetHandleType,
} from "../types/flow"; } from "../types/flow";
import { TabsContextType, TabsState } from "../types/tabs"; import { FlowsContextType, TabsState } from "../types/tabs";
import { import {
addVersionToDuplicates, addVersionToDuplicates,
checkOldEdgesHandles, checkOldEdgesHandles,
@ -45,7 +45,7 @@ import { typesContext } from "./typesContext";
const uid = new ShortUniqueId({ length: 5 }); const uid = new ShortUniqueId({ length: 5 });
const TabsContextInitialValue: TabsContextType = { const FlowsContextInitialValue: FlowsContextType = {
tabId: "", tabId: "",
setTabId: (index: string) => {}, setTabId: (index: string) => {},
isLoading: true, isLoading: true,
@ -75,8 +75,8 @@ const TabsContextInitialValue: TabsContextType = {
) => {}, ) => {},
}; };
export const TabsContext = createContext<TabsContextType>( export const FlowsContext = createContext<FlowsContextType>(
TabsContextInitialValue FlowsContextInitialValue
); );
export function TabsProvider({ children }: { children: ReactNode }) { export function TabsProvider({ children }: { children: ReactNode }) {
@ -428,6 +428,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
id: source, id: source,
}); });
sourceHandleObject.id = source; sourceHandleObject.id = source;
edge.data.sourceHandle = sourceHandleObject; edge.data.sourceHandle = sourceHandleObject;
const targetHandleObject: targetHandleType = scapeJSONParse( const targetHandleObject: targetHandleType = scapeJSONParse(
edge.targetHandle! edge.targetHandle!
@ -452,6 +453,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
sourceHandle, sourceHandle,
targetHandle, targetHandle,
id, id,
data: cloneDeep(edge.data),
style: { stroke: "#555" }, style: { stroke: "#555" },
className: className:
targetHandleObject.type === "Text" targetHandleObject.type === "Text"
@ -508,7 +510,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
let data = flow?.data ? flow.data : null; let data = flow?.data ? flow.data : null;
if (data) { if (data) {
processFlowEdges(flow); processFlowEdges(flow);
processFlowNodes(flow); //prevent node update for now
// processFlowNodes(flow);
//add animation to text type edges //add animation to text type edges
updateEdges(data.edges); updateEdges(data.edges);
// updateNodes(data.nodes, data.edges); // updateNodes(data.nodes, data.edges);
@ -635,7 +638,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
const [isBuilt, setIsBuilt] = useState(false); const [isBuilt, setIsBuilt] = useState(false);
return ( return (
<TabsContext.Provider <FlowsContext.Provider
value={{ value={{
saveFlow, saveFlow,
isBuilt, isBuilt,
@ -664,6 +667,6 @@ export function TabsProvider({ children }: { children: ReactNode }) {
}} }}
> >
{children} {children}
</TabsContext.Provider> </FlowsContext.Provider>
); );
} }

View file

@ -7,8 +7,8 @@ import { SSEProvider } from "./SSEContext";
import { AlertProvider } from "./alertContext"; import { AlertProvider } from "./alertContext";
import { AuthProvider } from "./authContext"; import { AuthProvider } from "./authContext";
import { DarkProvider } from "./darkContext"; import { DarkProvider } from "./darkContext";
import { TabsProvider } from "./flowsContext";
import { LocationProvider } from "./locationContext"; import { LocationProvider } from "./locationContext";
import { TabsProvider } from "./tabsContext";
import { TypesProvider } from "./typesContext"; import { TypesProvider } from "./typesContext";
import { UndoRedoProvider } from "./undoRedoContext"; import { UndoRedoProvider } from "./undoRedoContext";

View file

@ -13,7 +13,7 @@ import {
undoRedoContextType, undoRedoContextType,
} from "../types/typesContext"; } from "../types/typesContext";
import { isWrappedWithClass } from "../utils/utils"; import { isWrappedWithClass } from "../utils/utils";
import { TabsContext } from "./tabsContext"; import { FlowsContext } from "./flowsContext";
const initialValue = { const initialValue = {
undo: () => {}, undo: () => {},
@ -29,7 +29,7 @@ const defaultOptions: UseUndoRedoOptions = {
export const undoRedoContext = createContext<undoRedoContextType>(initialValue); export const undoRedoContext = createContext<undoRedoContextType>(initialValue);
export function UndoRedoProvider({ children }) { export function UndoRedoProvider({ children }) {
const { tabId, flows } = useContext(TabsContext); const { tabId, flows } = useContext(FlowsContext);
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(() => []));

View file

@ -0,0 +1,31 @@
const SvgAWS = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
xmlSpace="preserve"
id="Layer_1"
x={0}
y={0}
style={{
enableBackground: "new 0 0 304 182",
}}
viewBox="0 0 304 182"
{...props}
>
<style>{".st1{fill-rule:evenodd;clip-rule:evenodd;fill:#f90}"}</style>
<path
d="M86.4 66.4c0 3.7.4 6.7 1.1 8.9.8 2.2 1.8 4.6 3.2 7.2.5.8.7 1.6.7 2.3 0 1-.6 2-1.9 3L83.2 92c-.9.6-1.8.9-2.6.9-1 0-2-.5-3-1.4-1.4-1.5-2.6-3.1-3.6-4.7-1-1.7-2-3.6-3.1-5.9-7.8 9.2-17.6 13.8-29.4 13.8-8.4 0-15.1-2.4-20-7.2-4.9-4.8-7.4-11.2-7.4-19.2 0-8.5 3-15.4 9.1-20.6 6.1-5.2 14.2-7.8 24.5-7.8 3.4 0 6.9.3 10.6.8 3.7.5 7.5 1.3 11.5 2.2v-7.3c0-7.6-1.6-12.9-4.7-16-3.2-3.1-8.6-4.6-16.3-4.6-3.5 0-7.1.4-10.8 1.3-3.7.9-7.3 2-10.8 3.4-1.6.7-2.8 1.1-3.5 1.3-.7.2-1.2.3-1.6.3-1.4 0-2.1-1-2.1-3.1v-4.9c0-1.6.2-2.8.7-3.5.5-.7 1.4-1.4 2.8-2.1 3.5-1.8 7.7-3.3 12.6-4.5C41 1.9 46.2 1.3 51.7 1.3c11.9 0 20.6 2.7 26.2 8.1 5.5 5.4 8.3 13.6 8.3 24.6v32.4zM45.8 81.6c3.3 0 6.7-.6 10.3-1.8 3.6-1.2 6.8-3.4 9.5-6.4 1.6-1.9 2.8-4 3.4-6.4.6-2.4 1-5.3 1-8.7v-4.2c-2.9-.7-6-1.3-9.2-1.7-3.2-.4-6.3-.6-9.4-.6-6.7 0-11.6 1.3-14.9 4-3.3 2.7-4.9 6.5-4.9 11.5 0 4.7 1.2 8.2 3.7 10.6 2.4 2.5 5.9 3.7 10.5 3.7zm80.3 10.8c-1.8 0-3-.3-3.8-1-.8-.6-1.5-2-2.1-3.9L96.7 10.2c-.6-2-.9-3.3-.9-4 0-1.6.8-2.5 2.4-2.5h9.8c1.9 0 3.2.3 3.9 1 .8.6 1.4 2 2 3.9l16.8 66.2 15.6-66.2c.5-2 1.1-3.3 1.9-3.9.8-.6 2.2-1 4-1h8c1.9 0 3.2.3 4 1 .8.6 1.5 2 1.9 3.9l15.8 67 17.3-67c.6-2 1.3-3.3 2-3.9.8-.6 2.1-1 3.9-1h9.3c1.6 0 2.5.8 2.5 2.5 0 .5-.1 1-.2 1.6-.1.6-.3 1.4-.7 2.5l-24.1 77.3c-.6 2-1.3 3.3-2.1 3.9-.8.6-2.1 1-3.8 1h-8.6c-1.9 0-3.2-.3-4-1-.8-.7-1.5-2-1.9-4L156 23l-15.4 64.4c-.5 2-1.1 3.3-1.9 4-.8.7-2.2 1-4 1h-8.6zm128.5 2.7c-5.2 0-10.4-.6-15.4-1.8-5-1.2-8.9-2.5-11.5-4-1.6-.9-2.7-1.9-3.1-2.8-.4-.9-.6-1.9-.6-2.8v-5.1c0-2.1.8-3.1 2.3-3.1.6 0 1.2.1 1.8.3.6.2 1.5.6 2.5 1 3.4 1.5 7.1 2.7 11 3.5 4 .8 7.9 1.2 11.9 1.2 6.3 0 11.2-1.1 14.6-3.3 3.4-2.2 5.2-5.4 5.2-9.5 0-2.8-.9-5.1-2.7-7-1.8-1.9-5.2-3.6-10.1-5.2L246 52c-7.3-2.3-12.7-5.7-16-10.2-3.3-4.4-5-9.3-5-14.5 0-4.2.9-7.9 2.7-11.1 1.8-3.2 4.2-6 7.2-8.2 3-2.3 6.4-4 10.4-5.2 4-1.2 8.2-1.7 12.6-1.7 2.2 0 4.5.1 6.7.4 2.3.3 4.4.7 6.5 1.1 2 .5 3.9 1 5.7 1.6 1.8.6 3.2 1.2 4.2 1.8 1.4.8 2.4 1.6 3 2.5.6.8.9 1.9.9 3.3v4.7c0 2.1-.8 3.2-2.3 3.2-.8 0-2.1-.4-3.8-1.2-5.7-2.6-12.1-3.9-19.2-3.9-5.7 0-10.2.9-13.3 2.8-3.1 1.9-4.7 4.8-4.7 8.9 0 2.8 1 5.2 3 7.1 2 1.9 5.7 3.8 11 5.5l14.2 4.5c7.2 2.3 12.4 5.5 15.5 9.6 3.1 4.1 4.6 8.8 4.6 14 0 4.3-.9 8.2-2.6 11.6-1.8 3.4-4.2 6.4-7.3 8.8-3.1 2.5-6.8 4.3-11.1 5.6-4.5 1.4-9.2 2.1-14.3 2.1z"
style={{
fill: "#252f3e",
}}
/>
<path
d="M273.5 143.7c-32.9 24.3-80.7 37.2-121.8 37.2-57.6 0-109.5-21.3-148.7-56.7-3.1-2.8-.3-6.6 3.4-4.4 42.4 24.6 94.7 39.5 148.8 39.5 36.5 0 76.6-7.6 113.5-23.2 5.5-2.5 10.2 3.6 4.8 7.6z"
className="st1"
/>
<path
d="M287.2 128.1c-4.2-5.4-27.8-2.6-38.5-1.3-3.2.4-3.7-2.4-.8-4.5 18.8-13.2 49.7-9.4 53.3-5 3.6 4.5-1 35.4-18.6 50.2-2.7 2.3-5.3 1.1-4.1-1.9 4-9.9 12.9-32.2 8.7-37.5z"
className="st1"
/>
</svg>
);
export default SvgAWS;

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 304 182" style="enable-background:new 0 0 304 182;" xml:space="preserve">
<style type="text/css">
.st0{fill:#252F3E;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#FF9900;}
</style>
<g>
<path class="st0" d="M86.4,66.4c0,3.7,0.4,6.7,1.1,8.9c0.8,2.2,1.8,4.6,3.2,7.2c0.5,0.8,0.7,1.6,0.7,2.3c0,1-0.6,2-1.9,3l-6.3,4.2
c-0.9,0.6-1.8,0.9-2.6,0.9c-1,0-2-0.5-3-1.4C76.2,90,75,88.4,74,86.8c-1-1.7-2-3.6-3.1-5.9c-7.8,9.2-17.6,13.8-29.4,13.8
c-8.4,0-15.1-2.4-20-7.2c-4.9-4.8-7.4-11.2-7.4-19.2c0-8.5,3-15.4,9.1-20.6c6.1-5.2,14.2-7.8,24.5-7.8c3.4,0,6.9,0.3,10.6,0.8
c3.7,0.5,7.5,1.3,11.5,2.2v-7.3c0-7.6-1.6-12.9-4.7-16c-3.2-3.1-8.6-4.6-16.3-4.6c-3.5,0-7.1,0.4-10.8,1.3c-3.7,0.9-7.3,2-10.8,3.4
c-1.6,0.7-2.8,1.1-3.5,1.3c-0.7,0.2-1.2,0.3-1.6,0.3c-1.4,0-2.1-1-2.1-3.1v-4.9c0-1.6,0.2-2.8,0.7-3.5c0.5-0.7,1.4-1.4,2.8-2.1
c3.5-1.8,7.7-3.3,12.6-4.5c4.9-1.3,10.1-1.9,15.6-1.9c11.9,0,20.6,2.7,26.2,8.1c5.5,5.4,8.3,13.6,8.3,24.6V66.4z M45.8,81.6
c3.3,0,6.7-0.6,10.3-1.8c3.6-1.2,6.8-3.4,9.5-6.4c1.6-1.9,2.8-4,3.4-6.4c0.6-2.4,1-5.3,1-8.7v-4.2c-2.9-0.7-6-1.3-9.2-1.7
c-3.2-0.4-6.3-0.6-9.4-0.6c-6.7,0-11.6,1.3-14.9,4c-3.3,2.7-4.9,6.5-4.9,11.5c0,4.7,1.2,8.2,3.7,10.6
C37.7,80.4,41.2,81.6,45.8,81.6z M126.1,92.4c-1.8,0-3-0.3-3.8-1c-0.8-0.6-1.5-2-2.1-3.9L96.7,10.2c-0.6-2-0.9-3.3-0.9-4
c0-1.6,0.8-2.5,2.4-2.5h9.8c1.9,0,3.2,0.3,3.9,1c0.8,0.6,1.4,2,2,3.9l16.8,66.2l15.6-66.2c0.5-2,1.1-3.3,1.9-3.9c0.8-0.6,2.2-1,4-1
h8c1.9,0,3.2,0.3,4,1c0.8,0.6,1.5,2,1.9,3.9l15.8,67l17.3-67c0.6-2,1.3-3.3,2-3.9c0.8-0.6,2.1-1,3.9-1h9.3c1.6,0,2.5,0.8,2.5,2.5
c0,0.5-0.1,1-0.2,1.6c-0.1,0.6-0.3,1.4-0.7,2.5l-24.1,77.3c-0.6,2-1.3,3.3-2.1,3.9c-0.8,0.6-2.1,1-3.8,1h-8.6c-1.9,0-3.2-0.3-4-1
c-0.8-0.7-1.5-2-1.9-4L156,23l-15.4,64.4c-0.5,2-1.1,3.3-1.9,4c-0.8,0.7-2.2,1-4,1H126.1z M254.6,95.1c-5.2,0-10.4-0.6-15.4-1.8
c-5-1.2-8.9-2.5-11.5-4c-1.6-0.9-2.7-1.9-3.1-2.8c-0.4-0.9-0.6-1.9-0.6-2.8v-5.1c0-2.1,0.8-3.1,2.3-3.1c0.6,0,1.2,0.1,1.8,0.3
c0.6,0.2,1.5,0.6,2.5,1c3.4,1.5,7.1,2.7,11,3.5c4,0.8,7.9,1.2,11.9,1.2c6.3,0,11.2-1.1,14.6-3.3c3.4-2.2,5.2-5.4,5.2-9.5
c0-2.8-0.9-5.1-2.7-7c-1.8-1.9-5.2-3.6-10.1-5.2L246,52c-7.3-2.3-12.7-5.7-16-10.2c-3.3-4.4-5-9.3-5-14.5c0-4.2,0.9-7.9,2.7-11.1
c1.8-3.2,4.2-6,7.2-8.2c3-2.3,6.4-4,10.4-5.2c4-1.2,8.2-1.7,12.6-1.7c2.2,0,4.5,0.1,6.7,0.4c2.3,0.3,4.4,0.7,6.5,1.1
c2,0.5,3.9,1,5.7,1.6c1.8,0.6,3.2,1.2,4.2,1.8c1.4,0.8,2.4,1.6,3,2.5c0.6,0.8,0.9,1.9,0.9,3.3v4.7c0,2.1-0.8,3.2-2.3,3.2
c-0.8,0-2.1-0.4-3.8-1.2c-5.7-2.6-12.1-3.9-19.2-3.9c-5.7,0-10.2,0.9-13.3,2.8c-3.1,1.9-4.7,4.8-4.7,8.9c0,2.8,1,5.2,3,7.1
c2,1.9,5.7,3.8,11,5.5l14.2,4.5c7.2,2.3,12.4,5.5,15.5,9.6c3.1,4.1,4.6,8.8,4.6,14c0,4.3-0.9,8.2-2.6,11.6
c-1.8,3.4-4.2,6.4-7.3,8.8c-3.1,2.5-6.8,4.3-11.1,5.6C264.4,94.4,259.7,95.1,254.6,95.1z"/>
<g>
<path class="st1" d="M273.5,143.7c-32.9,24.3-80.7,37.2-121.8,37.2c-57.6,0-109.5-21.3-148.7-56.7c-3.1-2.8-0.3-6.6,3.4-4.4
c42.4,24.6,94.7,39.5,148.8,39.5c36.5,0,76.6-7.6,113.5-23.2C274.2,133.6,278.9,139.7,273.5,143.7z"/>
<path class="st1" d="M287.2,128.1c-4.2-5.4-27.8-2.6-38.5-1.3c-3.2,0.4-3.7-2.4-0.8-4.5c18.8-13.2,49.7-9.4,53.3-5
c3.6,4.5-1,35.4-18.6,50.2c-2.7,2.3-5.3,1.1-4.1-1.9C282.5,155.7,291.4,133.4,287.2,128.1z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -0,0 +1,8 @@
import React, { forwardRef } from "react";
import SvgAWS from "./AWS";
export const AWSIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
(props, ref) => {
return <SvgAWS ref={ref} {...props} />;
}
);

View file

@ -15,7 +15,7 @@ import CodeTabsComponent from "../../components/codeTabsComponent";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import { EXPORT_CODE_DIALOG } from "../../constants/constants"; import { EXPORT_CODE_DIALOG } from "../../constants/constants";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { TemplateVariableType } from "../../types/api"; import { TemplateVariableType } from "../../types/api";
import { tweakType, uniqueTweakType } from "../../types/components"; import { tweakType, uniqueTweakType } from "../../types/components";
import { FlowType, NodeType } from "../../types/flow/index"; import { FlowType, NodeType } from "../../types/flow/index";
@ -45,7 +45,7 @@ const ApiModal = forwardRef(
const [activeTab, setActiveTab] = useState("0"); const [activeTab, setActiveTab] = useState("0");
const tweak = useRef<tweakType>([]); const tweak = useRef<tweakType>([]);
const tweaksList = useRef<string[]>([]); const tweaksList = useRef<string[]>([]);
const { setTweak, getTweak, tabsState } = useContext(TabsContext); const { setTweak, getTweak, tabsState } = useContext(FlowsContext);
const pythonApiCode = getPythonApiCode( const pythonApiCode = getPythonApiCode(
flow, flow,
autoLogin, autoLogin,

View file

@ -33,10 +33,10 @@ import {
TableRow, TableRow,
} from "../../components/ui/table"; } from "../../components/ui/table";
import { limitScrollFieldsModal } from "../../constants/constants"; import { limitScrollFieldsModal } from "../../constants/constants";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { typesContext } from "../../contexts/typesContext"; import { typesContext } from "../../contexts/typesContext";
import { NodeDataType } from "../../types/flow"; import { NodeDataType } from "../../types/flow";
import { TabsState } from "../../types/tabs"; import { FlowsState } from "../../types/tabs";
import { import {
convertObjToArray, convertObjToArray,
convertValuesToNumbers, convertValuesToNumbers,
@ -69,7 +69,7 @@ const EditNodeModal = forwardRef(
const myData = useRef(data); const myData = useRef(data);
const { setTabsState, tabId } = useContext(TabsContext); const { setTabsState, tabId } = useContext(FlowsContext);
const { reactFlowInstance } = useContext(typesContext); const { reactFlowInstance } = useContext(typesContext);
let disabled = let disabled =
reactFlowInstance reactFlowInstance
@ -542,7 +542,7 @@ const EditNodeModal = forwardRef(
const newData = cloneDeep(myData.current); const newData = cloneDeep(myData.current);
myData.current = newData; myData.current = newData;
//@ts-ignore //@ts-ignore
setTabsState((prev: TabsState) => { setTabsState((prev: FlowsState) => {
return { return {
...prev, ...prev,
[tabId]: { [tabId]: {

View file

@ -5,13 +5,15 @@ import { Button } from "../../components/ui/button";
import { Checkbox } from "../../components/ui/checkbox"; import { Checkbox } from "../../components/ui/checkbox";
import { EXPORT_DIALOG_SUBTITLE } from "../../constants/constants"; import { EXPORT_DIALOG_SUBTITLE } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { typesContext } from "../../contexts/typesContext";
import { removeApiKeys } from "../../utils/reactflowUtils"; import { removeApiKeys } from "../../utils/reactflowUtils";
import BaseModal from "../baseModal"; import BaseModal from "../baseModal";
const ExportModal = forwardRef( const ExportModal = forwardRef(
(props: { children: ReactNode }, ref): JSX.Element => { (props: { children: ReactNode }, ref): JSX.Element => {
const { flows, tabId, downloadFlow } = useContext(TabsContext); const { flows, tabId, downloadFlow } = useContext(FlowsContext);
const { reactFlowInstance } = useContext(typesContext);
const { setNoticeData } = useContext(alertContext); const { setNoticeData } = useContext(alertContext);
const [checked, setChecked] = useState(true); const [checked, setChecked] = useState(true);
const flow = flows.find((f) => f.id === tabId); const flow = flows.find((f) => f.id === tabId);
@ -66,7 +68,12 @@ const ExportModal = forwardRef(
onClick={() => { onClick={() => {
if (checked) { if (checked) {
downloadFlow( downloadFlow(
flows.find((flow) => flow.id === tabId)!, {
id: tabId,
data: reactFlowInstance?.toObject()!,
description,
name,
},
name!, name!,
description description
); );
@ -76,7 +83,12 @@ const ExportModal = forwardRef(
}); });
} else } else
downloadFlow( downloadFlow(
removeApiKeys(flows.find((flow) => flow.id === tabId)!), removeApiKeys({
id: tabId,
data: reactFlowInstance?.toObject()!,
description,
name,
}),
name!, name!,
description description
); );

View file

@ -3,7 +3,7 @@ import EditFlowSettings from "../../components/EditFlowSettingsComponent";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";
import { SETTINGS_DIALOG_SUBTITLE } from "../../constants/constants"; import { SETTINGS_DIALOG_SUBTITLE } from "../../constants/constants";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { FlowSettingsPropsType } from "../../types/components"; import { FlowSettingsPropsType } from "../../types/components";
import BaseModal from "../baseModal"; import BaseModal from "../baseModal";
@ -11,7 +11,7 @@ export default function FlowSettingsModal({
open, open,
setOpen, setOpen,
}: FlowSettingsPropsType): JSX.Element { }: FlowSettingsPropsType): JSX.Element {
const { flows, tabId, updateFlow, saveFlow } = useContext(TabsContext); const { flows, tabId, updateFlow, saveFlow } = useContext(FlowsContext);
const flow = flows.find((f) => f.id === tabId); const flow = flows.find((f) => f.id === tabId);
useEffect(() => { useEffect(() => {
setName(flow!.name); setName(flow!.name);

View file

@ -24,9 +24,9 @@ import {
import { Textarea } from "../../components/ui/textarea"; import { Textarea } from "../../components/ui/textarea";
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants"; import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { getBuildStatus } from "../../controllers/API"; import { getBuildStatus } from "../../controllers/API";
import { TabsState } from "../../types/tabs"; import { FlowsState } from "../../types/tabs";
import { validateNodes } from "../../utils/reactflowUtils"; import { validateNodes } from "../../utils/reactflowUtils";
export default function FormModal({ export default function FormModal({
@ -38,7 +38,7 @@ export default function FormModal({
setOpen: (open: boolean) => void; setOpen: (open: boolean) => void;
flow: FlowType; flow: FlowType;
}): JSX.Element { }): JSX.Element {
const { tabsState, setTabsState } = useContext(TabsContext); const { tabsState, setTabsState } = useContext(FlowsContext);
const [chatValue, setChatValue] = useState(() => { const [chatValue, setChatValue] = useState(() => {
try { try {
const { formKeysData } = tabsState[flow.id]; const { formKeysData } = tabsState[flow.id];
@ -401,7 +401,7 @@ export default function FormModal({
chatKey: chatKey!, chatKey: chatKey!,
}); });
//@ts-ignore //@ts-ignore
setTabsState((old: TabsState) => { setTabsState((old: FlowsState) => {
if (!chatKey) return old; if (!chatKey) return old;
let newTabsState = _.cloneDeep(old); let newTabsState = _.cloneDeep(old);
newTabsState[id.current].formKeysData.input_keys![chatKey] = ""; newTabsState[id.current].formKeysData.input_keys![chatKey] = "";
@ -522,7 +522,7 @@ export default function FormModal({
} }
onChange={(e) => { onChange={(e) => {
//@ts-ignore //@ts-ignore
setTabsState((old: TabsState) => { setTabsState((old: FlowsState) => {
let newTabsState = _.cloneDeep(old); let newTabsState = _.cloneDeep(old);
newTabsState[ newTabsState[
id.current id.current
@ -634,7 +634,7 @@ export default function FormModal({
setChatValue={(value) => { setChatValue={(value) => {
setChatValue(value); setChatValue(value);
//@ts-ignore //@ts-ignore
setTabsState((old: TabsState) => { setTabsState((old: FlowsState) => {
let newTabsState = _.cloneDeep(old); let newTabsState = _.cloneDeep(old);
newTabsState[id.current].formKeysData.input_keys![ newTabsState[id.current].formKeysData.input_keys![
chatKey! chatKey!

View file

@ -22,7 +22,7 @@ import {
} from "../../constants/constants"; } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { import {
addUser, addUser,
deleteUser, deleteUser,
@ -44,7 +44,7 @@ export default function AdminPage() {
const { userData } = useContext(AuthContext); const { userData } = useContext(AuthContext);
const [totalRowsCount, setTotalRowsCount] = useState(0); const [totalRowsCount, setTotalRowsCount] = useState(0);
const { setTabId } = useContext(TabsContext); const { setTabId } = useContext(FlowsContext);
// set null id // set null id
useEffect(() => { useEffect(() => {

View file

@ -1,7 +1,7 @@
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { CardComponent } from "../../components/cardComponent"; import { CardComponent } from "../../components/cardComponent";
@ -12,7 +12,7 @@ import { getExamples } from "../../controllers/API";
import { FlowType } from "../../types/flow"; import { FlowType } from "../../types/flow";
export default function CommunityPage(): JSX.Element { export default function CommunityPage(): JSX.Element {
const { flows, setTabId, downloadFlows, uploadFlows, addFlow } = const { flows, setTabId, downloadFlows, uploadFlows, addFlow } =
useContext(TabsContext); useContext(FlowsContext);
// set null id // set null id
useEffect(() => { useEffect(() => {

View file

@ -28,13 +28,13 @@ import ReactFlow, {
import GenericNode from "../../../../CustomNodes/GenericNode"; import GenericNode from "../../../../CustomNodes/GenericNode";
import Chat from "../../../../components/chatComponent"; import Chat from "../../../../components/chatComponent";
import { alertContext } from "../../../../contexts/alertContext"; import { alertContext } from "../../../../contexts/alertContext";
import { FlowsContext } from "../../../../contexts/flowsContext";
import { locationContext } from "../../../../contexts/locationContext"; import { locationContext } from "../../../../contexts/locationContext";
import { TabsContext } from "../../../../contexts/tabsContext";
import { typesContext } from "../../../../contexts/typesContext"; import { typesContext } from "../../../../contexts/typesContext";
import { undoRedoContext } from "../../../../contexts/undoRedoContext"; import { undoRedoContext } from "../../../../contexts/undoRedoContext";
import { APIClassType } from "../../../../types/api"; import { APIClassType } from "../../../../types/api";
import { FlowType, NodeType, targetHandleType } from "../../../../types/flow"; import { FlowType, NodeType, targetHandleType } from "../../../../types/flow";
import { TabsState } from "../../../../types/tabs"; import { FlowsState } from "../../../../types/tabs";
import { import {
generateFlow, generateFlow,
generateNodeFromFlow, generateNodeFromFlow,
@ -70,7 +70,7 @@ export default function Page({
saveFlow, saveFlow,
setTabsState, setTabsState,
tabId, tabId,
} = useContext(TabsContext); } = useContext(FlowsContext);
const { const {
types, types,
reactFlowInstance, reactFlowInstance,
@ -208,7 +208,7 @@ export default function Page({
return newX; return newX;
}); });
//@ts-ignore //@ts-ignore
setTabsState((prev: TabsState) => { setTabsState((prev: FlowsState) => {
return { return {
...prev, ...prev,
[tabId]: { [tabId]: {
@ -225,7 +225,7 @@ export default function Page({
(change: NodeChange[]) => { (change: NodeChange[]) => {
onNodesChange(change); onNodesChange(change);
//@ts-ignore //@ts-ignore
setTabsState((prev: TabsState) => { setTabsState((prev: FlowsState) => {
return { return {
...prev, ...prev,
[tabId]: { [tabId]: {
@ -310,7 +310,6 @@ export default function Page({
event.dataTransfer.getData("nodedata") event.dataTransfer.getData("nodedata")
); );
// If data type is not "chatInput" or if there are no "chatInputNode" nodes present in the ReactFlow instance, create a new node
// Calculate the position where the node should be created // Calculate the position where the node should be created
const position = reactFlowInstance!.project({ const position = reactFlowInstance!.project({
x: event.clientX - reactflowBounds!.left, x: event.clientX - reactflowBounds!.left,

View file

@ -5,7 +5,7 @@ import IconComponent from "../../../../components/genericIconComponent";
import { Input } from "../../../../components/ui/input"; import { Input } from "../../../../components/ui/input";
import { Separator } from "../../../../components/ui/separator"; import { Separator } from "../../../../components/ui/separator";
import { alertContext } from "../../../../contexts/alertContext"; import { alertContext } from "../../../../contexts/alertContext";
import { TabsContext } from "../../../../contexts/tabsContext"; import { FlowsContext } from "../../../../contexts/flowsContext";
import { typesContext } from "../../../../contexts/typesContext"; import { typesContext } from "../../../../contexts/typesContext";
import ApiModal from "../../../../modals/ApiModal"; import ApiModal from "../../../../modals/ApiModal";
import ExportModal from "../../../../modals/exportModal"; import ExportModal from "../../../../modals/exportModal";
@ -22,7 +22,7 @@ export default function ExtraSidebar(): JSX.Element {
const { data, templates, getFilterEdge, setFilterEdge } = const { data, templates, getFilterEdge, setFilterEdge } =
useContext(typesContext); useContext(typesContext);
const { flows, tabId, uploadFlow, tabsState, saveFlow, isBuilt } = const { flows, tabId, uploadFlow, tabsState, saveFlow, isBuilt } =
useContext(TabsContext); useContext(FlowsContext);
const { setSuccessData, setErrorData } = useContext(alertContext); const { setSuccessData, setErrorData } = useContext(alertContext);
const [dataFilter, setFilterData] = useState(data); const [dataFilter, setFilterData] = useState(data);
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");

View file

@ -8,7 +8,7 @@ import {
SelectItem, SelectItem,
SelectTrigger, SelectTrigger,
} from "../../../../components/ui/select-custom"; } from "../../../../components/ui/select-custom";
import { TabsContext } from "../../../../contexts/tabsContext"; import { FlowsContext } from "../../../../contexts/flowsContext";
import EditNodeModal from "../../../../modals/EditNodeModal"; import EditNodeModal from "../../../../modals/EditNodeModal";
import { nodeToolbarPropsType } from "../../../../types/components"; import { nodeToolbarPropsType } from "../../../../types/components";
import { import {
@ -54,7 +54,7 @@ export default function NodeToolbarComponent({
const isMinimal = canMinimize(); const isMinimal = canMinimize();
const isGroup = data.node?.flow ? true : false; const isGroup = data.node?.flow ? true : false;
const { paste } = useContext(TabsContext); const { paste } = useContext(FlowsContext);
const reactFlowInstance = useReactFlow(); const reactFlowInstance = useReactFlow();
const [showModalAdvanced, setShowModalAdvanced] = useState(false); const [showModalAdvanced, setShowModalAdvanced] = useState(false);
const [selectedValue, setSelectedValue] = useState(""); const [selectedValue, setSelectedValue] = useState("");

View file

@ -1,12 +1,12 @@
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import Header from "../../components/headerComponent"; import Header from "../../components/headerComponent";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { getVersion } from "../../controllers/API"; import { getVersion } from "../../controllers/API";
import Page from "./components/PageComponent"; import Page from "./components/PageComponent";
export default function FlowPage(): JSX.Element { export default function FlowPage(): JSX.Element {
const { flows, tabId, setTabId } = useContext(TabsContext); const { flows, tabId, setTabId } = useContext(FlowsContext);
const { id } = useParams(); const { id } = useParams();
// Set flow tab id // Set flow tab id

View file

@ -8,7 +8,7 @@ import { SkeletonCardComponent } from "../../components/skeletonCardComponent";
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";
import { USER_PROJECTS_HEADER } from "../../constants/constants"; import { USER_PROJECTS_HEADER } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
export default function HomePage(): JSX.Element { export default function HomePage(): JSX.Element {
const { const {
flows, flows,
@ -19,7 +19,7 @@ export default function HomePage(): JSX.Element {
removeFlow, removeFlow,
uploadFlow, uploadFlow,
isLoading, isLoading,
} = useContext(TabsContext); } = useContext(FlowsContext);
const { setErrorData } = useContext(alertContext); const { setErrorData } = useContext(alertContext);
const dropdownOptions = [ const dropdownOptions = [
{ {

View file

@ -9,7 +9,7 @@ import { Button } from "../../components/ui/button";
import { CONTROL_PATCH_USER_STATE } from "../../constants/constants"; import { CONTROL_PATCH_USER_STATE } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { resetPassword, updateUser } from "../../controllers/API"; import { resetPassword, updateUser } from "../../controllers/API";
import { import {
inputHandlerEventType, inputHandlerEventType,
@ -17,7 +17,7 @@ import {
} from "../../types/components"; } from "../../types/components";
import { gradients } from "../../utils/styleUtils"; import { gradients } from "../../utils/styleUtils";
export default function ProfileSettingsPage(): JSX.Element { export default function ProfileSettingsPage(): JSX.Element {
const { setTabId } = useContext(TabsContext); const { setTabId } = useContext(FlowsContext);
const [inputState, setInputState] = useState<patchUserInputStateType>( const [inputState, setInputState] = useState<patchUserInputStateType>(
CONTROL_PATCH_USER_STATE CONTROL_PATCH_USER_STATE

View file

@ -1,11 +1,11 @@
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { TabsContext } from "../../contexts/tabsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { getVersion } from "../../controllers/API"; import { getVersion } from "../../controllers/API";
import Page from "../FlowPage/components/PageComponent"; import Page from "../FlowPage/components/PageComponent";
export default function ViewPage() { export default function ViewPage() {
const { flows, tabId, setTabId } = useContext(TabsContext); const { flows, tabId, setTabId } = useContext(FlowsContext);
const { id } = useParams(); const { id } = useParams();
// Set flow tab id // Set flow tab id

View file

@ -47,6 +47,8 @@ export type TemplateVariableType = {
dynamic?: boolean; dynamic?: boolean;
proxy?: { id: string; field: string }; proxy?: { id: string; field: string };
input_types?: Array<string>; input_types?: Array<string>;
display_name?: string;
name?: string;
[key: string]: any; [key: string]: any;
}; };
export type sendAllProps = { export type sendAllProps = {

View file

@ -1,7 +1,7 @@
import { tweakType } from "../components"; import { tweakType } from "../components";
import { FlowType } from "../flow"; import { FlowType } from "../flow";
export type TabsContextType = { export type FlowsContextType = {
saveFlow: (flow: FlowType, silent?: boolean) => Promise<void>; saveFlow: (flow: FlowType, silent?: boolean) => Promise<void>;
tabId: string; tabId: string;
isLoading: boolean; isLoading: boolean;
@ -26,8 +26,8 @@ export type TabsContextType = {
uploadFlow: (newFlow: boolean, file?: File) => Promise<String | undefined>; uploadFlow: (newFlow: boolean, file?: File) => Promise<String | undefined>;
hardReset: () => void; hardReset: () => void;
getNodeId: (nodeType: string) => string; getNodeId: (nodeType: string) => string;
tabsState: TabsState; tabsState: FlowsState;
setTabsState: (state: TabsState) => void; setTabsState: (state: FlowsState) => void;
paste: ( paste: (
selection: { nodes: any; edges: any }, selection: { nodes: any; edges: any },
position: { x: number; y: number; paneX?: number; paneY?: number } position: { x: number; y: number; paneX?: number; paneY?: number }
@ -38,7 +38,7 @@ export type TabsContextType = {
getTweak: tweakType; getTweak: tweakType;
}; };
export type TabsState = { export type FlowsState = {
[key: string]: { [key: string]: {
isPending: boolean; isPending: boolean;
formKeysData: { formKeysData: {

View file

@ -25,8 +25,7 @@ import {
unselectAllNodesType, unselectAllNodesType,
updateEdgesHandleIdsType, updateEdgesHandleIdsType,
} from "../types/utils/reactflowUtils"; } from "../types/utils/reactflowUtils";
import { toNormalCase, toTitleCase } from "./utils"; import { getFieldTitle, toTitleCase } from "./utils";
const uid = new ShortUniqueId({ length: 5 });
export function cleanEdges({ export function cleanEdges({
flow: { edges, nodes }, flow: { edges, nodes },
@ -240,11 +239,7 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
node.id node.id
) )
) { ) {
errors.push( errors.push(`${type} is missing ${getFieldTitle(template, t)}.`);
`${type} is missing ${
template.display_name || toNormalCase(template[t].name)
}.`
);
} else if ( } else if (
template[t].type === "dict" && template[t].type === "dict" &&
template[t].required && template[t].required &&
@ -255,15 +250,14 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
) { ) {
if (hasDuplicateKeys(template[t].value)) if (hasDuplicateKeys(template[t].value))
errors.push( errors.push(
`${type} (${ `${type} (${getFieldTitle(
template.display_name || template[t].name template,
}) contains duplicate keys with the same values.` t
)}) contains duplicate keys with the same values.`
); );
if (hasEmptyKey(template[t].value)) if (hasEmptyKey(template[t].value))
errors.push( errors.push(
`${type} (${ `${type} (${getFieldTitle(template, t)}) field must not be empty.`
template.display_name || template[t].name
}) field must not be empty.`
); );
} }
return errors; return errors;
@ -512,7 +506,7 @@ export function generateFlow(
name: string name: string
): generateFlowType { ): generateFlowType {
const newFlowData = reactFlowInstance.toObject(); const newFlowData = reactFlowInstance.toObject();
const uid = new ShortUniqueId({ length: 5 });
/* remove edges that are not connected to selected nodes on both ends /* remove edges that are not connected to selected nodes on both ends
in future we can save this edges to when ungrouping reconect to the old nodes in future we can save this edges to when ungrouping reconect to the old nodes
*/ */
@ -875,7 +869,7 @@ export function ungroupNode(
let { field, id } = template[key].proxy!; let { field, id } = template[key].proxy!;
let nodeIndex = gNodes.findIndex((n) => n.id === id); let nodeIndex = gNodes.findIndex((n) => n.id === id);
if (nodeIndex !== -1) { if (nodeIndex !== -1) {
let display_name: string; let display_name: string | undefined;
let show = gNodes[nodeIndex].data.node!.template[field].show; let show = gNodes[nodeIndex].data.node!.template[field].show;
let advanced = gNodes[nodeIndex].data.node!.template[field].advanced; let advanced = gNodes[nodeIndex].data.node!.template[field].advanced;
if (gNodes[nodeIndex].data.node!.template[field].display_name) { if (gNodes[nodeIndex].data.node!.template[field].display_name) {
@ -965,7 +959,7 @@ export function expandGroupNode(
let nodeIndex = gNodes.findIndex((n) => n.id === id); let nodeIndex = gNodes.findIndex((n) => n.id === id);
if (nodeIndex !== -1) { if (nodeIndex !== -1) {
let proxy: { id: string; field: string } | undefined; let proxy: { id: string; field: string } | undefined;
let display_name: string; let display_name: string | undefined;
let show = gNodes[nodeIndex].data.node!.template[field].show; let show = gNodes[nodeIndex].data.node!.template[field].show;
let advanced = gNodes[nodeIndex].data.node!.template[field].advanced; let advanced = gNodes[nodeIndex].data.node!.template[field].advanced;
if (gNodes[nodeIndex].data.node!.template[field].display_name) { if (gNodes[nodeIndex].data.node!.template[field].display_name) {
@ -981,7 +975,8 @@ export function expandGroupNode(
gNodes[nodeIndex].data.node!.template[field].show = show; gNodes[nodeIndex].data.node!.template[field].show = show;
gNodes[nodeIndex].data.node!.template[field].advanced = advanced; gNodes[nodeIndex].data.node!.template[field].advanced = advanced;
gNodes[nodeIndex].data.node!.template[field].display_name = display_name; gNodes[nodeIndex].data.node!.template[field].display_name = display_name;
gNodes[nodeIndex].selected = false; // keep the nodes selected after ungrouping
// gNodes[nodeIndex].selected = false;
if (proxy) { if (proxy) {
gNodes[nodeIndex].data.node!.template[field].proxy = proxy; gNodes[nodeIndex].data.node!.template[field].proxy = proxy;
} else { } else {

View file

@ -87,6 +87,7 @@ import {
Zap, Zap,
} from "lucide-react"; } from "lucide-react";
import { FaApple, FaGithub } from "react-icons/fa"; import { FaApple, FaGithub } from "react-icons/fa";
import { AWSIcon } from "../icons/AWS";
import { AirbyteIcon } from "../icons/Airbyte"; import { AirbyteIcon } from "../icons/Airbyte";
import { AnthropicIcon } from "../icons/Anthropic"; import { AnthropicIcon } from "../icons/Anthropic";
import { BingIcon } from "../icons/Bing"; import { BingIcon } from "../icons/Bing";
@ -199,6 +200,7 @@ export const nodeIconsLucide: iconsType = {
ArrowUpToLine: ArrowUpToLine, ArrowUpToLine: ArrowUpToLine,
Chroma: ChromaIcon, Chroma: ChromaIcon,
AirbyteJSONLoader: AirbyteIcon, AirbyteJSONLoader: AirbyteIcon,
AmazonBedrockEmbeddings: AWSIcon,
Anthropic: AnthropicIcon, Anthropic: AnthropicIcon,
ChatAnthropic: AnthropicIcon, ChatAnthropic: AnthropicIcon,
BingSearchAPIWrapper: BingIcon, BingSearchAPIWrapper: BingIcon,

View file

@ -1,14 +1,18 @@
import clsx, { ClassValue } from "clsx"; import clsx, { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "../flow_constants"; import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "../flow_constants";
import { APIDataType, TemplateVariableType } from "../types/api"; import {
APIDataType,
APITemplateType,
TemplateVariableType,
} from "../types/api";
import { import {
IVarHighlightType, IVarHighlightType,
groupedObjType, groupedObjType,
tweakType, tweakType,
} from "../types/components"; } from "../types/components";
import { FlowType, NodeType } from "../types/flow"; import { FlowType, NodeType } from "../types/flow";
import { TabsState } from "../types/tabs"; import { FlowsState } from "../types/tabs";
import { buildTweaks } from "./reactflowUtils"; import { buildTweaks } from "./reactflowUtils";
export function classNames(...classes: Array<string>): string { export function classNames(...classes: Array<string>): string {
@ -53,7 +57,8 @@ export function normalCaseToSnakeCase(str: string): string {
.join("_"); .join("_");
} }
export function toTitleCase(str: string): string { export function toTitleCase(str: string | undefined): string {
if (!str) return "";
let result = str let result = str
.split("_") .split("_")
.map((word, index) => { .map((word, index) => {
@ -195,7 +200,7 @@ export function groupByFamily(
})); }));
} }
export function buildInputs(tabsState: TabsState, id: string): string { export function buildInputs(tabsState: FlowsState, id: string): string {
return tabsState && return tabsState &&
tabsState[id] && tabsState[id] &&
tabsState[id].formKeysData && tabsState[id].formKeysData &&
@ -273,10 +278,10 @@ export function buildTweakObject(tweak: tweakType) {
/** /**
* Function to get Chat Input Field * Function to get Chat Input Field
* @param {FlowType} flow - The current flow. * @param {FlowType} flow - The current flow.
* @param {TabsState} tabsState - The current tabs state. * @param {FlowsState} tabsState - The current tabs state.
* @returns {string} - The chat input field * @returns {string} - The chat input field
*/ */
export function getChatInputField(flow: FlowType, tabsState?: TabsState) { export function getChatInputField(flow: FlowType, tabsState?: FlowsState) {
let chat_input_field = "text"; let chat_input_field = "text";
if ( if (
@ -301,7 +306,7 @@ export function getPythonApiCode(
flow: FlowType, flow: FlowType,
isAuth: boolean, isAuth: boolean,
tweak?: any[], tweak?: any[],
tabsState?: TabsState tabsState?: FlowsState
): string { ): string {
const flowId = flow.id; const flowId = flow.id;
@ -365,7 +370,7 @@ export function getCurlCode(
flow: FlowType, flow: FlowType,
isAuth: boolean, isAuth: boolean,
tweak?: any[], tweak?: any[],
tabsState?: TabsState tabsState?: FlowsState
): string { ): string {
const flowId = flow.id; const flowId = flow.id;
const tweaks = buildTweaks(flow); const tweaks = buildTweaks(flow);
@ -393,7 +398,7 @@ export function getCurlCode(
export function getPythonCode( export function getPythonCode(
flow: FlowType, flow: FlowType,
tweak?: any[], tweak?: any[],
tabsState?: TabsState tabsState?: FlowsState
): string { ): string {
const flowName = flow.name; const flowName = flow.name;
const tweaks = buildTweaks(flow); const tweaks = buildTweaks(flow);
@ -418,7 +423,7 @@ flow(inputs)`;
export function getWidgetCode( export function getWidgetCode(
flow: FlowType, flow: FlowType,
isAuth: boolean, isAuth: boolean,
tabsState?: TabsState tabsState?: FlowsState
): string { ): string {
const flowId = flow.id; const flowId = flow.id;
const flowName = flow.name; const flowName = flow.name;
@ -550,3 +555,14 @@ export function tabsArray(codes: string[], method: number) {
}, },
]; ];
} }
export function getFieldTitle(
template: APITemplateType,
templateField: string
): string {
return template[templateField].display_name
? template[templateField].display_name!
: template[templateField].name
? toTitleCase(template[templateField].name!)
: toTitleCase(templateField);
}