diff --git a/docs/static/data/AstraDB-RAG-Flows.json b/docs/static/data/AstraDB-RAG-Flows.json index 1825fe798..0e814c93c 100644 --- a/docs/static/data/AstraDB-RAG-Flows.json +++ b/docs/static/data/AstraDB-RAG-Flows.json @@ -684,7 +684,6 @@ "max": 1, "step": 0.1 }, -<<<<<<< HEAD "data": { "type": "Prompt", "node": { @@ -823,8 +822,7 @@ "x": 2969.0261961391298, "y": 442.1613649809069 }, - "dragging": false -======= + "dragging": false, "load_from_db": false, "title_case": false }, @@ -907,7 +905,6 @@ ] }, "_type": "CustomComponent" ->>>>>>> origin/dev }, "description": "Generate embeddings using OpenAI models.", "base_classes": [ diff --git a/src/backend/base/langflow/api/utils.py b/src/backend/base/langflow/api/utils.py index 1dbd68d8f..82bd32165 100644 --- a/src/backend/base/langflow/api/utils.py +++ b/src/backend/base/langflow/api/utils.py @@ -219,7 +219,7 @@ async def build_and_cache_graph_from_db(flow_id: str, session: Session, chat_ser if vertex is None: raise ValueError(f"Vertex {vertex_id} not found") if not vertex._raw_params.get("session_id"): - vertex.update_raw_params({"session_id": flow_id}) + vertex.update_raw_params({"session_id": flow_id}, overwrite=True) await chat_service.set_cache(flow_id, graph) return graph diff --git a/src/backend/base/langflow/base/vectorstores/__init__.py b/src/backend/base/langflow/base/vectorstores/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/base/langflow/base/vectorstores/utils.py b/src/backend/base/langflow/base/vectorstores/utils.py new file mode 100644 index 000000000..739181600 --- /dev/null +++ b/src/backend/base/langflow/base/vectorstores/utils.py @@ -0,0 +1,24 @@ +from langflow.schema import Record + + +def chroma_collection_to_records(collection_dict: dict): + """ + Converts a collection of chroma vectors into a list of records. + + Args: + collection_dict (dict): A dictionary containing the collection of chroma vectors. + + Returns: + list: A list of records, where each record represents a document in the collection. + """ + records = [] + for i, doc in enumerate(collection_dict["documents"]): + record_dict = { + "id": collection_dict["ids"][i], + "text": doc, + } + if "metadatas" in collection_dict: + for key, value in collection_dict["metadatas"][i].items(): + record_dict[key] = value + records.append(Record(**record_dict)) + return records diff --git a/src/backend/base/langflow/components/outputs/RecordsOutput.py b/src/backend/base/langflow/components/outputs/RecordsOutput.py index f03b0ccd6..a8a288864 100644 --- a/src/backend/base/langflow/components/outputs/RecordsOutput.py +++ b/src/backend/base/langflow/components/outputs/RecordsOutput.py @@ -15,4 +15,5 @@ class RecordsOutput(Component): ] def record_response(self) -> Record: + self.status = self.input_value return self.input_value diff --git a/src/backend/base/langflow/components/retrievers/SelfQueryRetriever.py b/src/backend/base/langflow/components/retrievers/SelfQueryRetriever.py new file mode 100644 index 000000000..3e6d6f696 --- /dev/null +++ b/src/backend/base/langflow/components/retrievers/SelfQueryRetriever.py @@ -0,0 +1,68 @@ +# from langflow.field_typing import Data +from langchain.chains.query_constructor.base import AttributeInfo +from langchain.retrievers.self_query.base import SelfQueryRetriever +from langchain_core.vectorstores import VectorStore + +from langflow.custom import CustomComponent +from langflow.field_typing import BaseLanguageModel, Text +from langflow.schema import Record +from langflow.schema.message import Message + + +class SelfQueryRetrieverComponent(CustomComponent): + display_name: str = "Self Query Retriever" + description: str = "Retriever that uses a vector store and an LLM to generate the vector store queries." + icon = "LangChain" + + def build_config(self): + return { + "query": { + "display_name": "Query", + "input_types": ["Message", "Text"], + "info": "Query to be passed as input.", + }, + "vectorstore": { + "display_name": "Vector Store", + "info": "Vector Store to be passed as input.", + }, + "attribute_infos": { + "display_name": "Metadata Field Info", + "info": "Metadata Field Info to be passed as input.", + }, + "document_content_description": { + "display_name": "Document Content Description", + "info": "Document Content Description to be passed as input.", + }, + "llm": { + "display_name": "LLM", + "info": "LLM to be passed as input.", + }, + } + + def build( + self, + query: Message, + vectorstore: VectorStore, + attribute_infos: list[Record], + document_content_description: Text, + llm: BaseLanguageModel, + ) -> Record: + metadata_field_infos = [AttributeInfo(**record.data) for record in attribute_infos] + self_query_retriever = SelfQueryRetriever.from_llm( + llm=llm, + vectorstore=vectorstore, + document_contents=document_content_description, + metadata_field_info=metadata_field_infos, + enable_limit=True, + ) + + if isinstance(query, Message): + input_text = query.text + elif isinstance(query, str): + input_text = query + else: + raise ValueError(f"Query type {type(query)} not supported.") + documents = self_query_retriever.invoke(input=input_text) + records = [Record.from_document(document) for document in documents] + self.status = records + return records diff --git a/src/backend/base/langflow/components/vectorstores/Chroma.py b/src/backend/base/langflow/components/vectorstores/Chroma.py index 5742aad7b..6001b119c 100644 --- a/src/backend/base/langflow/components/vectorstores/Chroma.py +++ b/src/backend/base/langflow/components/vectorstores/Chroma.py @@ -1,3 +1,4 @@ +from copy import deepcopy from typing import List, Optional, Union import chromadb @@ -7,6 +8,7 @@ from langchain_core.embeddings import Embeddings from langchain_core.retrievers import BaseRetriever from langchain_core.vectorstores import VectorStore +from langflow.base.vectorstores.utils import chroma_collection_to_records from langflow.custom import CustomComponent from langflow.schema import Record @@ -48,6 +50,11 @@ class ChromaComponent(CustomComponent): "display_name": "Server SSL Enabled", "advanced": True, }, + "allow_duplicates": { + "display_name": "Allow Duplicates", + "advanced": True, + "info": "If false, will not add documents that are already in the Vector Store.", + }, } def build( @@ -61,6 +68,7 @@ class ChromaComponent(CustomComponent): chroma_server_host: Optional[str] = None, chroma_server_http_port: Optional[int] = None, chroma_server_grpc_port: Optional[int] = None, + allow_duplicates: bool = False, ) -> Union[VectorStore, BaseRetriever]: """ Builds the Vector Store or BaseRetriever object. @@ -75,6 +83,7 @@ class ChromaComponent(CustomComponent): - chroma_server_host (Optional[str]): The host for the Chroma server. - chroma_server_http_port (Optional[int]): The HTTP port for the Chroma server. - chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server. + - allow_duplicates (bool): Whether to allow duplicates in the Vector Store. Returns: - Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object. @@ -93,32 +102,34 @@ class ChromaComponent(CustomComponent): ) client = chromadb.HttpClient(settings=chroma_settings) - # If documents, then we need to create a Chroma instance using .from_documents - # Check index_directory and expand it if it is a relative path if index_directory is not None: index_directory = self.resolve_path(index_directory) + chroma = Chroma( + persist_directory=index_directory, + client=client, + embedding_function=embedding, + collection_name=collection_name, + ) + if allow_duplicates: + stored_records = [] + else: + stored_records = chroma_collection_to_records(chroma.get()) + _stored_documents_without_id = [] + for record in deepcopy(stored_records): + del record.id + _stored_documents_without_id.append(record) documents = [] for _input in inputs or []: if isinstance(_input, Record): - documents.append(_input.to_lc_document()) + if _input not in _stored_documents_without_id: + documents.append(_input.to_lc_document()) else: - documents.append(_input) - if documents is not None and embedding is not None: - if len(documents) == 0: - raise ValueError("If documents are provided, there must be at least one document.") - chroma = Chroma.from_documents( - documents=documents, # type: ignore - persist_directory=index_directory, - collection_name=collection_name, - embedding=embedding, - client=client, - ) - else: - chroma = Chroma( - persist_directory=index_directory, - client=client, - embedding_function=embedding, - ) + raise ValueError("Inputs must be a Record objects.") + + if documents and embedding is not None: + chroma.add_documents(documents) + + self.status = stored_records return chroma diff --git a/src/backend/base/langflow/custom/custom_component/custom_component.py b/src/backend/base/langflow/custom/custom_component/custom_component.py index 46ea3de21..72e47b612 100644 --- a/src/backend/base/langflow/custom/custom_component/custom_component.py +++ b/src/backend/base/langflow/custom/custom_component/custom_component.py @@ -123,8 +123,11 @@ class CustomComponent(BaseComponent): @staticmethod def resolve_path(path: str) -> str: """Resolves the path to an absolute path.""" + if not path: + return path path_object = Path(path) - if path_object.parts[0] == "~": + + if path_object.parts and path_object.parts[0] == "~": path_object = path_object.expanduser() elif path_object.is_relative_to("."): path_object = path_object.resolve() diff --git a/src/backend/base/langflow/field_typing/prompt.py b/src/backend/base/langflow/field_typing/prompt.py index ef6c7ce9a..029261ac7 100644 --- a/src/backend/base/langflow/field_typing/prompt.py +++ b/src/backend/base/langflow/field_typing/prompt.py @@ -25,6 +25,7 @@ class Prompt(Record): prompt_template = PromptTemplate.from_template(self.template) variables_with_str_values = dict_values_to_string(self.variables) formatted_prompt = prompt_template.format(**variables_with_str_values) + self.text = formatted_prompt return formatted_prompt @classmethod diff --git a/src/backend/base/langflow/schema/record.py b/src/backend/base/langflow/schema/record.py index 830f576ba..67d9b5da8 100644 --- a/src/backend/base/langflow/schema/record.py +++ b/src/backend/base/langflow/schema/record.py @@ -1,12 +1,12 @@ import copy import json -from typing import cast, Optional +from typing import Optional, cast from langchain_core.documents import Document from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage +from langchain_core.prompt_values import ImagePromptValue from langchain_core.prompts.image import ImagePromptTemplate from pydantic import BaseModel, model_serializer, model_validator -from langchain_core.prompt_values import ImagePromptValue class Record(BaseModel): @@ -200,3 +200,6 @@ class Record(BaseModel): def __contains__(self, key): return key in self.data + + def __eq__(self, other): + return isinstance(other, Record) and self.data == other.data diff --git a/src/frontend/.prettierignore b/src/frontend/.prettierignore index 07ed7069a..a007feab0 100644 --- a/src/frontend/.prettierignore +++ b/src/frontend/.prettierignore @@ -1 +1 @@ -build/* \ No newline at end of file +build/* diff --git a/src/frontend/package.json b/src/frontend/package.json index c069b9da1..b29dd6a1e 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -82,7 +82,7 @@ "start": "vite", "build": "vite build", "serve": "vite preview", - "format": "npx prettier --write \"{docs,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore", + "format": "npx prettier --write \"{tests,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore", "type-check": "tsc --noEmit --pretty --project tsconfig.json && vite" }, "simple-git-hooks": { @@ -138,4 +138,4 @@ "ua-parser-js": "^1.0.37", "vite": "^4.5.2" } -} +} \ No newline at end of file diff --git a/src/frontend/src/CustomNodes/GenericNode/components/outputModal/components/switchOutputView/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/outputModal/components/switchOutputView/index.tsx index 307c77c1a..468f573a0 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/outputModal/components/switchOutputView/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/outputModal/components/switchOutputView/index.tsx @@ -28,7 +28,6 @@ export default function SwitchOutputView(nodeId): JSX.Element { if (resultMessage.raw) { resultMessage = resultMessage.raw; } - console.log("resultType", results); return ( <> diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 5ac82a823..8e5a214e9 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -43,6 +43,7 @@ import useHandleNodeClass from "../../../hooks/use-handle-node-class"; import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons"; import HandleTooltips from "../HandleTooltipComponent"; import OutputComponent from "../OutputComponent"; +import OutputModal from "../outputModal"; import { TEXT_FIELD_TYPES } from "./constants"; export default function ParameterComponent({ @@ -64,6 +65,7 @@ export default function ParameterComponent({ outputProxy, }: ParameterComponentType): JSX.Element { const infoHtml = useRef(null); + const currentFlow = useFlowsManagerStore((state) => state.currentFlow); const nodes = useFlowStore((state) => state.nodes); const edges = useFlowStore((state) => state.edges); const setNode = useFlowStore((state) => state.setNode); @@ -73,6 +75,17 @@ export default function ParameterComponent({ const updateNodeInternals = useUpdateNodeInternals(); const [errorDuplicateKey, setErrorDuplicateKey] = useState(false); const setFilterEdge = useFlowStore((state) => state.setFilterEdge); + const [openOutputModal, setOpenOutputModal] = useState(false); + const flowPool = useFlowStore((state) => state.flowPool); + + const displayOutputPreview = !!flowPool[data.id]; + + const unknownOutput = !!( + flowPool[data.id] && + flowPool[data.id][flowPool[data.id].length - 1]?.data?.logs[0]?.type === + "unknown" + ); + const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue( data, name, @@ -80,7 +93,7 @@ export default function ParameterComponent({ handleUpdateValues, debouncedHandleUpdateValues, setNode, - setIsLoading, + setIsLoading ); const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass( @@ -88,7 +101,7 @@ export default function ParameterComponent({ name, takeSnapshot, setNode, - updateNodeInternals, + updateNodeInternals ); const { handleRefreshButtonPress: handleRefreshButtonPressHook } = @@ -97,7 +110,7 @@ export default function ParameterComponent({ let disabled = edges.some( (edge) => - edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id), + edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id) ) ?? false; const handleRefreshButtonPress = async (name, data) => { @@ -108,7 +121,7 @@ export default function ParameterComponent({ const handleOnNewValue = async ( newValue: string | string[] | boolean | Object[], - skipSnapshot: boolean | undefined = false, + skipSnapshot: boolean | undefined = false ): Promise => { handleOnNewValueHook(newValue, skipSnapshot); }; @@ -195,14 +208,14 @@ export default function ParameterComponent({ className={classNames( left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ", "h-3 w-3 rounded-full border-2 bg-background", - !showNode ? "mt-0" : "", + !showNode ? "mt-0" : "" )} style={{ borderColor: color ?? nodeColors.unknown, }} onClick={() => { setFilterEdge( - groupByFamily(myData, tooltipTitle!, left, nodes!), + groupByFamily(myData, tooltipTitle!, left, nodes!) ); }} > @@ -238,7 +251,40 @@ export default function ParameterComponent({ {renderTitle()} ) : ( - renderTitle() +
+ + {renderTitle()} + + {!left && ( + + + + )} +
)} {required ? "*" : ""} @@ -287,12 +333,12 @@ export default function ParameterComponent({ } className={classNames( left ? "-ml-0.5" : "-mr-0.5", - "h-3 w-3 rounded-full border-2 bg-background", + "h-3 w-3 rounded-full border-2 bg-background" )} style={{ borderColor: color ?? nodeColors.unknown }} onClick={() => { setFilterEdge( - groupByFamily(myData, tooltipTitle!, left, nodes!), + groupByFamily(myData, tooltipTitle!, left, nodes!) ); }} /> @@ -387,7 +433,7 @@ export default function ParameterComponent({ }); }} name={name} - data={data.node?.template[name]} + data={data.node?.template[name]!} /> {data.node?.template[name]?.refresh_button && ( @@ -574,6 +620,13 @@ export default function ParameterComponent({ />
+ {openOutputModal && ( + + )} ); diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index c1c05f68d..74acf5638 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -1,47 +1,52 @@ import emojiRegex from "emoji-regex"; -import { cloneDeep } from "lodash"; -import { useCallback, useEffect, useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { NodeToolbar, useUpdateNodeInternals } from "reactflow"; import IconComponent from "../../components/genericIconComponent"; import InputComponent from "../../components/inputComponent"; import ShadTooltip from "../../components/shadTooltipComponent"; import { Button } from "../../components/ui/button"; -import Checkmark from "../../components/ui/checkmark"; -import Loading from "../../components/ui/loading"; import { Textarea } from "../../components/ui/textarea"; -import Xmark from "../../components/ui/xmark"; import { RUN_TIMESTAMP_PREFIX, STATUS_BUILD, STATUS_BUILDING, + TOOLTIP_OUTDATED_NODE, } from "../../constants/constants"; import { BuildStatus } from "../../constants/enums"; +import { postCustomComponent } from "../../controllers/API"; import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent"; import useAlertStore from "../../stores/alertStore"; import { useDarkStore } from "../../stores/darkStore"; import useFlowStore from "../../stores/flowStore"; import useFlowsManagerStore from "../../stores/flowsManagerStore"; +import { useShortcutsStore } from "../../stores/shortcuts"; import { useTypesStore } from "../../stores/typesStore"; -import { APIClassType } from "../../types/api"; -import { validationStatusType } from "../../types/components"; +import { VertexBuildTypeAPI } from "../../types/api"; import { NodeDataType } from "../../types/flow"; import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils"; import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils"; import { classNames, cn } from "../../utils/utils"; +import { countHandlesFn } from "../helpers/count-handles"; +import { getSpecificClassFromBuildStatus } from "../helpers/get-class-from-build-status"; +import useCheckCodeValidity from "../hooks/use-check-code-validity"; +import useIconNodeRender from "../hooks/use-icon-render"; +import useIconStatus from "../hooks/use-icons-status"; +import useUpdateNodeCode from "../hooks/use-update-node-code"; +import useUpdateValidationStatus from "../hooks/use-update-validation-status"; +import useValidationStatusString from "../hooks/use-validation-status-string"; import getFieldTitle from "../utils/get-field-title"; import sortFields from "../utils/sort-fields"; import ParameterComponent from "./components/parameterComponent"; export default function GenericNode({ data, - xPos, - yPos, + selected, }: { data: NodeDataType; selected: boolean; - xPos: number; - yPos: number; + xPos?: number; + yPos?: number; }): JSX.Element { const types = useTypesStore((state) => state.types); const templates = useTypesStore((state) => state.templates); @@ -51,192 +56,47 @@ export default function GenericNode({ const setNode = useFlowStore((state) => state.setNode); const updateNodeInternals = useUpdateNodeInternals(); const setErrorData = useAlertStore((state) => state.setErrorData); - const name = nodeIconsLucide[data.type] ? data.type : types[data.type]; + const isDark = useDarkStore((state) => state.dark); + const buildStatus = useFlowStore( + (state) => state.flowBuildStatus[data.id]?.status + ); + const lastRunTime = useFlowStore( + (state) => state.flowBuildStatus[data.id]?.timestamp + ); + const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot); + const [inputName, setInputName] = useState(false); const [nodeName, setNodeName] = useState(data.node!.display_name); const [inputDescription, setInputDescription] = useState(false); const [nodeDescription, setNodeDescription] = useState( - data.node?.description!, + data.node?.description! ); const [isOutdated, setIsOutdated] = useState(false); const buildStatus = useFlowStore( - (state) => state.flowBuildStatus[data.id]?.status, + (state) => state.flowBuildStatus[data.id]?.status ); const lastRunTime = useFlowStore( - (state) => state.flowBuildStatus[data.id]?.timestamp, + (state) => state.flowBuildStatus[data.id]?.timestamp ); const [validationStatus, setValidationStatus] = - useState(null); + useState(null); const [handles, setHandles] = useState(0); - const [validationString, setValidationString] = useState(""); - const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot); - - useEffect(() => { - // This one should run only once - // first check if data.type in NATIVE_CATEGORIES - // if not return - if (!data.node?.template?.code?.value) return; - const thisNodeTemplate = templates[data.type]?.template; - // if the template does not have a code key - // return - if (!thisNodeTemplate?.code) return; - const currentCode = thisNodeTemplate.code?.value; - const thisNodesCode = data.node!.template?.code?.value; - const componentsToIgnore = ["Custom Component"]; - if ( - currentCode !== thisNodesCode && - !componentsToIgnore.includes(data.node!.display_name) - ) { - setIsOutdated(true); - } else { - setIsOutdated(false); - } - // template.code can be undefined - }, [data.node?.template?.code?.value]); - - const updateNodeCode = useCallback( - (newNodeClass: APIClassType, code: string, name: string) => { - setNode(data.id, (oldNode) => { - let newNode = cloneDeep(oldNode); - - newNode.data = { - ...newNode.data, - node: newNodeClass, - description: newNodeClass.description ?? data.node!.description, - display_name: newNodeClass.display_name ?? data.node!.display_name, - }; - - newNode.data.node.template[name].value = code; - setIsOutdated(false); - - return newNode; - }); - - updateNodeInternals(data.id); - }, - [data.id, data.node, setNode, setIsOutdated], - ); - - if (!data.node!.template) { - setErrorData({ - title: `Error in component ${data.node!.display_name}`, - list: [ - `The component ${data.node!.display_name} has no template.`, - `Please contact the developer of the component to fix this issue.`, - ], - }); - takeSnapshot(); - deleteNode(data.id); - } - - function countHandles(): void { - let count = Object.keys(data.node!.template) - .filter((templateField) => templateField.charAt(0) !== "_") - .map((templateCamp) => { - const { template } = data.node!; - if (template[templateCamp].input_types) return true; - if (!template[templateCamp].show) return false; - switch (template[templateCamp].type) { - case "str": - case "bool": - case "float": - case "code": - case "prompt": - case "file": - case "int": - return false; - default: - return true; - } - }) - .reduce((total, value) => total + (value ? 1 : 0), 0); - - setHandles(count); - } - useEffect(() => { - countHandles(); - }, [data, data.node]); - - useEffect(() => { - if (!selected) { - setInputName(false); - setInputDescription(false); - } - }, [selected]); - + const iconStatus = useIconStatus(buildStatus, validationStatus); + const [showNode, setShowNode] = useState(data.showNode ?? true); // State for outline color const isBuilding = useFlowStore((state) => state.isBuilding); - // should be empty string if no duration - // else should be `Duration: ${duration}` - const getDurationString = (duration: number | undefined): string => { - if (duration === undefined) { - return ""; - } else { - return `${duration}`; - } - }; - const durationString = getDurationString(validationStatus?.data.duration); + const updateNodeCode = useUpdateNodeCode( + data?.id, + data.node!, + setNode, + setIsOutdated, + updateNodeInternals + ); - useEffect(() => { - setNodeDescription(data.node!.description); - }, [data.node!.description]); - - useEffect(() => { - setNodeName(data.node!.display_name); - }, [data.node!.display_name]); - - useEffect(() => { - const relevantData = - flowPool[data.id] && flowPool[data.id]?.length > 0 - ? flowPool[data.id][flowPool[data.id].length - 1] - : null; - if (relevantData) { - // Extract validation information from relevantData and update the validationStatus state - setValidationStatus(relevantData); - } else { - setValidationStatus(null); - } - }, [flowPool[data.id], data.id]); - - useEffect(() => { - if (validationStatus?.params) { - // if it is not a string turn it into a string - let newValidationString = validationStatus.params; - if (typeof newValidationString !== "string") { - newValidationString = JSON.stringify(validationStatus.params); - } - - setValidationString(newValidationString); - } - }, [validationStatus, validationStatus?.params]); - - const [showNode, setShowNode] = useState(data.showNode ?? true); - - useEffect(() => { - setShowNode(data.showNode ?? true); - }, [data.showNode]); - - const nameEditable = true; - - const isEmoji = emojiRegex().test(data?.node?.icon!); - - const iconNodeRender = useCallback(() => { - const iconElement = data?.node?.icon; - const iconColor = nodeColors[types[data.type]]; - const iconName = - iconElement || (data.node?.flow ? "group_components" : name); - const iconClassName = `generic-node-icon ${ - !showNode ? " absolute inset-x-6 h-12 w-12 " : "" - }`; - if (iconElement && isEmoji) { - return nodeIconFragment(iconElement); - } else { - return checkNodeIconFragment(iconColor, iconName, iconClassName); - } - }, [data, isEmoji, name, showNode]); + const name = nodeIconsLucide[data.type] ? data.type : types[data.type]; const nodeIconFragment = (icon) => { return {icon}; @@ -252,87 +112,24 @@ export default function GenericNode({ ); }; - const isDark = useDarkStore((state) => state.dark); - const renderIconStatus = ( - buildStatus: BuildStatus | undefined, - validationStatus: validationStatusType | null, - ) => { - const conditionSuccess = validationStatus && validationStatus.valid; - const conditionInactive = - validationStatus && - !validationStatus.valid && - buildStatus === BuildStatus.INACTIVE; - const conditionError = - buildStatus === BuildStatus.ERROR || - (validationStatus && !validationStatus.valid); - - if (buildStatus === BuildStatus.BUILDING) { - return ; - } else { - return ( - <> - - {conditionSuccess ? ( - - ) : conditionInactive ? ( - - ) : conditionError ? ( - - ) : ( - <> - )} - - ); - } - }; - const getSpecificClassFromBuildStatus = ( - buildStatus: BuildStatus | undefined, - validationStatus: validationStatusType | null, - ) => { - let isInvalid = validationStatus && !validationStatus.valid; - - if (buildStatus === BuildStatus.INACTIVE) { - // INACTIVE should have its own class - return "inactive-status"; - } - if ( - (buildStatus === BuildStatus.BUILT && isInvalid) || - buildStatus === BuildStatus.ERROR - ) { - return isDark ? "built-invalid-status-dark" : "built-invalid-status"; - } else if (buildStatus === BuildStatus.BUILDING) { - return "building-status"; - } else { - return ""; - } + const renderIconStatus = () => { + return ( +
+ {iconStatus} +
+ ); }; const getNodeBorderClassName = ( selected: boolean, showNode: boolean, buildStatus: BuildStatus | undefined, - validationStatus: validationStatusType | null, + validationStatus: VertexBuildTypeAPI | null ) => { const specificClassFromBuildStatus = getSpecificClassFromBuildStatus( buildStatus, validationStatus, + isDark ); const baseBorderClass = getBaseBorderClass(selected); @@ -341,11 +138,13 @@ export default function GenericNode({ baseBorderClass, nodeSizeClass, "generic-node-div group/node", - specificClassFromBuildStatus, + specificClassFromBuildStatus ); return names; }; + // const [openWDoubleCLick, setOpenWDoubleCLick] = useState(false); + const getBaseBorderClass = (selected) => { let className = selected ? "border border-ring" : "border"; let frozenClass = selected ? "border-ring-frozen" : "border-frozen"; @@ -355,10 +154,99 @@ export default function GenericNode({ const getNodeSizeClass = (showNode) => showNode ? "w-96 rounded-lg" : "w-26 h-26 rounded-full"; + const nameEditable = true; + const isEmoji = emojiRegex().test(data?.node?.icon!); + + if (!data.node!.template) { + setErrorData({ + title: `Error in component ${data.node!.display_name}`, + list: [ + `The component ${data.node!.display_name} has no template.`, + `Please contact the developer of the component to fix this issue.`, + ], + }); + takeSnapshot(); + deleteNode(data.id); + } + + useCheckCodeValidity(data, templates, setIsOutdated, types); + useValidationStatusString(validationStatus, setValidationString); + useUpdateValidationStatus(data?.id, flowPool, setValidationStatus); + + const iconNodeRender = useIconNodeRender( + data, + types, + nodeColors, + name, + showNode, + isEmoji, + nodeIconFragment, + checkNodeIconFragment + ); + + function countHandles(): void { + const count = countHandlesFn(data); + setHandles(count); + } + + useEffect(() => { + countHandles(); + }, [data, data.node]); + + useEffect(() => { + if (!selected) { + setInputName(false); + setInputDescription(false); + } + }, [selected]); + + useEffect(() => { + setNodeDescription(data.node!.description); + }, [data.node!.description]); + + useEffect(() => { + setNodeName(data.node!.display_name); + }, [data.node!.display_name]); + + useEffect(() => { + setShowNode(data.showNode ?? true); + }, [data.showNode]); + + const [loadingUpdate, setLoadingUpdate] = useState(false); + + const handleUpdateCode = () => { + setLoadingUpdate(true); + takeSnapshot(); + // to update we must get the code from the templates in useTypesStore + const thisNodeTemplate = templates[data.type]?.template; + // if the template does not have a code key + // return + if (!thisNodeTemplate?.code) return; + + const currentCode = thisNodeTemplate.code.value; + if (data.node) { + postCustomComponent(currentCode, data.node) + .then((apiReturn) => { + const { data } = apiReturn; + if (data && updateNodeCode) { + updateNodeCode(data, currentCode, "code"); + setLoadingUpdate(false); + } + }) + .catch((err) => { + console.log(err); + }); + } + }; + + const shortcuts = useShortcutsStore((state) => state.shortcuts); + const memoizedNodeToolbarComponent = useMemo(() => { return ( { takeSnapshot(); @@ -375,8 +263,6 @@ export default function GenericNode({ showNode={showNode} openAdvancedModal={false} onCloseAdvancedModal={() => {}} - updateNodeCode={updateNodeCode} - isOutdated={isOutdated} selected={selected} /> @@ -392,16 +278,23 @@ export default function GenericNode({ updateNodeCode, isOutdated, selected, + shortcuts, + // openWDoubleCLick, + // setOpenWDoubleCLick, ]); return ( <> {memoizedNodeToolbarComponent}
{ + // if (!isWrappedWithClass(event, "nodoubleclick")) + // setOpenWDoubleCLick(true); + // }} className={getNodeBorderClassName( selected, showNode, buildStatus, - validationStatus, + validationStatus )} > {data.node?.beta && showNode && ( @@ -470,7 +363,7 @@ export default function GenericNode({ event.preventDefault(); }} data-testid={"title-" + data.node?.display_name} - className="generic-node-tooltip-div cursor-text text-primary" + className="nodoubleclick generic-node-tooltip-div cursor-text text-primary" > {data.node?.display_name}
@@ -532,7 +425,7 @@ export default function GenericNode({ } title={getFieldTitle( data.node?.template!, - templateField, + templateField )} info={data.node?.template[templateField].info} name={templateField} @@ -560,7 +453,7 @@ export default function GenericNode({ proxy={data.node?.template[templateField].proxy} showNode={showNode} /> - ), + ) )} {/* {showNode && ( - {STATUS_BUILDING} - ) : !validationStatus ? ( - {STATUS_BUILD} - ) : ( -
-
- {lastRunTime && ( + <> +
+ {isOutdated && ( + + + + )} + {STATUS_BUILDING} + ) : !validationStatus ? ( + {STATUS_BUILD} + ) : ( +
+
+ {lastRunTime && ( +
+
{RUN_TIMESTAMP_PREFIX}
+
+ {lastRunTime} +
+
+ )} +
-
{RUN_TIMESTAMP_PREFIX}
+
Duration:
- {lastRunTime} + {validationStatus?.data.duration}
- )} -
-
-
Duration:
-
- {validationStatus?.data.duration}
-
-
- - Output - -
- {validationString.split("\n").map((line, index) => ( -
- {line} -
- ))} -
-
- ) - } - side="bottom" - > - - + + +
+ )}
@@ -714,12 +613,12 @@ export default function GenericNode({ ) : (
{ setInputDescription(true); @@ -781,13 +680,13 @@ export default function GenericNode({ } title={getFieldTitle( data.node?.template!, - templateField, + templateField )} info={data.node?.template[templateField].info} name={templateField} tooltipTitle={ data.node?.template[templateField].input_types?.join( - "\n", + "\n" ) ?? data.node?.template[templateField].type } required={data.node!.template[templateField].required} @@ -814,7 +713,7 @@ export default function GenericNode({
{" "} diff --git a/src/frontend/src/components/csvOutputComponent/index.tsx b/src/frontend/src/components/csvOutputComponent/index.tsx index 6de273170..1d4e342de 100644 --- a/src/frontend/src/components/csvOutputComponent/index.tsx +++ b/src/frontend/src/components/csvOutputComponent/index.tsx @@ -7,7 +7,7 @@ import { CSVViewErrorTitle, } from "../../constants/constants"; import { useDarkStore } from "../../stores/darkStore"; -import { FlowPoolObjectType } from "../../types/chat"; +import { VertexBuildTypeAPI } from "../../types/api"; import { NodeType } from "../../types/flow"; import ForwardedIconComponent from "../genericIconComponent"; import TableComponent from "../tableComponent"; @@ -19,7 +19,7 @@ function CsvOutputComponent({ flowPool, }: { csvNode: NodeType; - flowPool: FlowPoolObjectType; + flowPool: VertexBuildTypeAPI; }) { const csvNodeArtifacts = flowPool?.data?.artifacts?.repr; const jsonString = csvNodeArtifacts?.replace(/'/g, '"'); diff --git a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx index 5419f5d88..cbdb541b4 100644 --- a/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx +++ b/src/frontend/src/components/tableComponent/components/TableOptions/index.tsx @@ -18,7 +18,7 @@ export default function TableOptions({ }): JSX.Element { return (
-
+
@@ -81,8 +84,8 @@ export default function TableOptions({ diff --git a/src/frontend/src/components/tableComponent/index.tsx b/src/frontend/src/components/tableComponent/index.tsx index b78e03896..fdf3fb060 100644 --- a/src/frontend/src/components/tableComponent/index.tsx +++ b/src/frontend/src/components/tableComponent/index.tsx @@ -159,6 +159,19 @@ const TableComponent = forwardRef< }, 100); }} /> + 0} + duplicateRow={props.onDuplicate ? props.onDuplicate : undefined} + deleteRow={props.onDelete ? props.onDelete : undefined} + resetGrid={() => { + console.log("teste"); + resetGrid(realRef, initialColumnDefs); + setTimeout(() => { + setColumnStateChange(false); + }, 100); + }} + /> resetGrid(realRef, initialColumnDefs)} />
); diff --git a/src/frontend/src/constants/constants.ts b/src/frontend/src/constants/constants.ts index df003c021..885b360cc 100644 --- a/src/frontend/src/constants/constants.ts +++ b/src/frontend/src/constants/constants.ts @@ -829,3 +829,9 @@ export const MAX_BATCH_SIZE = 50; export const MODAL_CLASSES = "nopan nodelete nodrag noundo nocopy fixed inset-0 bottom-0 left-0 right-0 top-0 z-50 overflow-auto bg-blur-shared backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"; + +export const ALLOWED_IMAGE_INPUT_EXTENSIONS = ["png", "jpg", "jpeg"]; + +export const FS_ERROR_TEXT = + "Please ensure your file has one of the following extensions:"; +export const SN_ERROR_TEXT = ALLOWED_IMAGE_INPUT_EXTENSIONS.join(", "); diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 1c18a9fd7..b0f16d7d2 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -1092,20 +1092,11 @@ export async function getMessagesTable( } const rows = await api.get(`${BASE_URL_API}monitor/messages`, config); const columns = extractColumnsFromRows(rows.data, mode, excludedFields); - return { rows: rows.data, columns }; -} - -export async function getSessions(id?: string): Promise> { - const config = {}; - if (id) { - config["params"] = { flow_id: id }; - } - const rows = await api.get(`${BASE_URL_API}monitor/messages`, config); const sessions = new Set(); rows.data.forEach((row) => { sessions.add(row.session_id); }); - return Array.from(sessions); + return { rows: rows.data, columns }; } export async function deleteMessagesFn(ids: number[]) { diff --git a/src/frontend/src/icons/LangChain/LangChainIcon.jsx b/src/frontend/src/icons/LangChain/LangChainIcon.jsx new file mode 100644 index 000000000..aa5e98bec --- /dev/null +++ b/src/frontend/src/icons/LangChain/LangChainIcon.jsx @@ -0,0 +1,24 @@ +const SvgLangChainIcon = (props) => ( + + + + + +); +export default SvgLangChainIcon; diff --git a/src/frontend/src/icons/LangChain/index.tsx b/src/frontend/src/icons/LangChain/index.tsx new file mode 100644 index 000000000..48b8566e1 --- /dev/null +++ b/src/frontend/src/icons/LangChain/index.tsx @@ -0,0 +1,9 @@ +import React, { forwardRef } from "react"; +import SvgLangChainIcon from "./LangChainIcon"; + +export const LangChainIcon = forwardRef< + SVGSVGElement, + React.PropsWithChildren<{}> +>((props, ref) => { + return ; +}); diff --git a/src/frontend/src/icons/LangChain/langchain-icon.svg b/src/frontend/src/icons/LangChain/langchain-icon.svg new file mode 100644 index 000000000..e80068b50 --- /dev/null +++ b/src/frontend/src/icons/LangChain/langchain-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx b/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx index e841797be..d8c18aba9 100644 --- a/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx +++ b/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx @@ -49,8 +49,6 @@ export default function IOFieldView({ (flowPool[node!.id] ?? [])[(flowPool[node!.id]?.length ?? 1) - 1]?.data .results.result ?? ""; - console.log(flowPoolNode?.data?.artifacts?.records); - function handleOutputType() { if (!node) return <>"No node found!"; switch (type) { @@ -252,7 +250,11 @@ export default function IOFieldView({
artifact.data + ) ?? [] + } columnMode="union" />
diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-drag-and-drop.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-drag-and-drop.tsx index 326563a0b..e7ce85745 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-drag-and-drop.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-drag-and-drop.tsx @@ -1,9 +1,7 @@ import ShortUniqueId from "short-unique-id"; +import { ALLOWED_IMAGE_INPUT_EXTENSIONS, FS_ERROR_TEXT, SN_ERROR_TEXT } from "../../../../../../constants/constants"; import useFileUpload from "./use-file-upload"; -const fsErrorText = - "Please ensure your file has one of the following extensions:"; -const snErrorTxt = "png, jpg, jpeg, gif, bmp, webp"; const useDragAndDrop = ( setIsDragging, @@ -48,14 +46,16 @@ const useDragAndDrop = ( const handleFiles = (files, setFiles, currentFlowId, setErrorData) => { if (files) { - const allowedExtensions = ["png", "jpg", "jpeg", "gif", "bmp", "webp"]; const file = files?.[0]; const fileExtension = file.name.split(".").pop()?.toLowerCase(); - if (!fileExtension || !allowedExtensions.includes(fileExtension)) { + if ( + !fileExtension || + !ALLOWED_IMAGE_INPUT_EXTENSIONS.includes(fileExtension) + ) { console.log("Error uploading file"); setErrorData({ title: "Error uploading file", - list: [fsErrorText, snErrorTxt], + list: [FS_ERROR_TEXT, SN_ERROR_TEXT], }); return; } diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-handle-file-change.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-handle-file-change.tsx index 1ed15711f..1784f2e40 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-handle-file-change.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-handle-file-change.tsx @@ -1,11 +1,12 @@ import ShortUniqueId from "short-unique-id"; +import { + ALLOWED_IMAGE_INPUT_EXTENSIONS, + FS_ERROR_TEXT, + SN_ERROR_TEXT, +} from "../../../../../../constants/constants"; import useAlertStore from "../../../../../../stores/alertStore"; import useFileUpload from "./use-file-upload"; -const fsErrorText = - "Please ensure your file has one of the following extensions:"; -const snErrorTxt = "png, jpg, jpeg, gif, bmp, webp"; - export const useHandleFileChange = (setFiles, currentFlowId) => { const setErrorData = useAlertStore((state) => state.setErrorData); const handleFileChange = async ( @@ -14,13 +15,15 @@ export const useHandleFileChange = (setFiles, currentFlowId) => { const fileInput = event.target; const file = fileInput.files?.[0]; if (file) { - const allowedExtensions = ["png", "jpg", "jpeg", "gif", "bmp", "webp"]; const fileExtension = file.name.split(".").pop()?.toLowerCase(); - if (!fileExtension || !allowedExtensions.includes(fileExtension)) { + if ( + !fileExtension || + !ALLOWED_IMAGE_INPUT_EXTENSIONS.includes(fileExtension) + ) { setErrorData({ title: "Error uploading file", - list: [fsErrorText, snErrorTxt], + list: [FS_ERROR_TEXT, SN_ERROR_TEXT], }); return; } diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-upload.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-upload.tsx index 1e8d338de..6d3eac14e 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-upload.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/hooks/use-upload.tsx @@ -1,12 +1,13 @@ import { useEffect } from "react"; import ShortUniqueId from "short-unique-id"; +import { + ALLOWED_IMAGE_INPUT_EXTENSIONS, + FS_ERROR_TEXT, + SN_ERROR_TEXT, +} from "../../../../../../constants/constants"; import useAlertStore from "../../../../../../stores/alertStore"; import useFileUpload from "./use-file-upload"; -const fsErrorText = - "Please ensure your file has one of the following extensions:"; -const snErrorTxt = "png, jpg, jpeg, gif, bmp, webp"; - const useUpload = (uploadFile, currentFlowId, setFiles, lockChat) => { const setErrorData = useAlertStore((state) => state.setErrorData); useEffect(() => { @@ -21,20 +22,15 @@ const useUpload = (uploadFile, currentFlowId, setFiles, lockChat) => { const uid = new ShortUniqueId({ length: 3 }); const blob = items[i].getAsFile(); if (blob) { - const allowedExtensions = [ - "png", - "jpg", - "jpeg", - "gif", - "bmp", - "webp", - ]; const fileExtension = blob.name.split(".").pop()?.toLowerCase(); - if (!fileExtension || !allowedExtensions.includes(fileExtension)) { + if ( + !fileExtension || + !ALLOWED_IMAGE_INPUT_EXTENSIONS.includes(fileExtension) + ) { setErrorData({ title: "Error uploading file", - list: [fsErrorText, snErrorTxt], + list: [FS_ERROR_TEXT, SN_ERROR_TEXT], }); return; } diff --git a/src/frontend/src/modals/editNodeModal/hooks/use-column-defs.tsx b/src/frontend/src/modals/editNodeModal/hooks/use-column-defs.tsx index dbeecc9d6..b05696791 100644 --- a/src/frontend/src/modals/editNodeModal/hooks/use-column-defs.tsx +++ b/src/frontend/src/modals/editNodeModal/hooks/use-column-defs.tsx @@ -2,7 +2,6 @@ import { ColDef, ValueGetterParams } from "ag-grid-community"; import { useMemo } from "react"; import TableNodeCellRender from "../../../components/tableComponent/components/tableNodeCellRender"; import TableToggleCellRender from "../../../components/tableComponent/components/tableToggleCellRender"; -import TableTooltipRender from "../../../components/tableComponent/components/tableTooltipRender"; const useColumnDefs = ( myData: any, @@ -23,8 +22,6 @@ const useColumnDefs = ( : templateParam.name) ?? params.data.key ); }, - tooltipField: "display_name", - tooltipComponent: TableTooltipRender, wrapText: true, autoHeight: true, flex: 1, @@ -35,7 +32,6 @@ const useColumnDefs = ( headerName: "Description", field: "info", tooltipField: "info", - tooltipComponent: TableTooltipRender, wrapText: true, autoHeight: true, flex: 2, diff --git a/src/frontend/src/modals/editNodeModal/index.tsx b/src/frontend/src/modals/editNodeModal/index.tsx index e382b6e9c..6c603288a 100644 --- a/src/frontend/src/modals/editNodeModal/index.tsx +++ b/src/frontend/src/modals/editNodeModal/index.tsx @@ -3,6 +3,7 @@ import { forwardRef, useEffect, useRef, useState } from "react"; import IconComponent from "../../components/genericIconComponent"; import TableComponent from "../../components/tableComponent"; import { Badge } from "../../components/ui/badge"; +import { useDarkStore } from "../../stores/darkStore"; import useFlowStore from "../../stores/flowStore"; import { NodeDataType } from "../../types/flow"; import BaseModal from "../baseModal"; @@ -28,6 +29,8 @@ const EditNodeModal = forwardRef( ) => { const myData = useRef(data); + const isDark = useDarkStore((state) => state.dark); + const setNode = useFlowStore((state) => state.setNode); function changeAdvanced(n) { @@ -57,6 +60,12 @@ const EditNodeModal = forwardRef( } }, [gridApi, open]); + // useEffect(() => { + // return () => { + // setOpenWDoubleClick(false); + // }; + // }, []); + return ( {data.type} - ID: {data.id} + + ID: {data.id} +
diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index e76272284..2844df8f3 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -179,6 +179,7 @@ export default function Page({ function handleUndo(e: KeyboardEvent) { e.preventDefault(); + e.stopImmediatePropagation(); if (!isWrappedWithClass(e, "noundo")) { undo(); } @@ -186,6 +187,7 @@ export default function Page({ function handleRedo(e: KeyboardEvent) { e.preventDefault(); + e.stopImmediatePropagation(); if (!isWrappedWithClass(e, "noundo")) { redo(); } @@ -193,6 +195,7 @@ export default function Page({ function handleGroup(e: KeyboardEvent) { e.preventDefault(); + e.stopImmediatePropagation(); if (selectionMenuVisible) { handleGroupNode(); } @@ -201,6 +204,7 @@ export default function Page({ function handleDuplicate(e: KeyboardEvent) { e.preventDefault(); e.stopPropagation(); + e.stopImmediatePropagation(); const selectedNode = nodes.filter((obj) => obj.selected); if (selectedNode.length > 0) { paste( @@ -215,6 +219,7 @@ export default function Page({ function handleCopy(e: KeyboardEvent) { e.preventDefault(); + e.stopImmediatePropagation(); if ( !isWrappedWithClass(e, "nocopy") && window.getSelection()?.toString().length === 0 && @@ -226,6 +231,7 @@ export default function Page({ function handleCut(e: KeyboardEvent) { e.preventDefault(); + e.stopImmediatePropagation(); if ( !isWrappedWithClass(e, "nocopy") && window.getSelection()?.toString().length === 0 && @@ -237,6 +243,7 @@ export default function Page({ function handlePaste(e: KeyboardEvent) { e.preventDefault(); + e.stopImmediatePropagation(); if ( !isWrappedWithClass(e, "nocopy") && window.getSelection()?.toString().length === 0 && @@ -252,6 +259,7 @@ export default function Page({ function handleDelete(e: KeyboardEvent) { e.preventDefault(); + e.stopImmediatePropagation(); if (!isWrappedWithClass(e, "nodelete") && lastSelection) { takeSnapshot(); deleteNode(lastSelection.nodes.map((node) => node.id)); diff --git a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx index 432496fd7..81d2aa18d 100644 --- a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx @@ -7,7 +7,6 @@ import IconComponent from "../../../../components/genericIconComponent"; import PaginatorComponent from "../../../../components/paginatorComponent"; import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent"; import { Button } from "../../../../components/ui/button"; -import { UPLOAD_ERROR_ALERT } from "../../../../constants/alerts_constants"; import DeleteConfirmationModal from "../../../../modals/deleteConfirmationModal"; import useAlertStore from "../../../../stores/alertStore"; import { useDarkStore } from "../../../../stores/darkStore"; @@ -113,104 +112,6 @@ export default function ComponentsComponent({ setValue ); - const handleSelectOptionsChange = (action: string) => { - const hasSelected = selectedFlowsComponentsCards?.length > 0; - if (!hasSelected) { - setErrorData({ - title: "No items selected", - list: ["Please select items to delete"], - }); - return; - } - if (action === "delete") { - setOpenDelete(true); - } else if (action === "duplicate") { - handleDuplicate(); - } else if (action === "export") { - handleExport(); - } - }; - - const handleDuplicate = () => { - Promise.all( - selectedFlowsComponentsCards.map((selectedFlow) => - addFlow( - true, - allFlows.find((flow) => flow.id === selectedFlow) - ) - ) - ).then(() => { - resetFilter(); - getFoldersApi(true); - if (!folderId || folderId === myCollectionId) { - getFolderById(folderId ? folderId : myCollectionId); - } - setSelectedFlowsComponentsCards([]); - - setSuccessData({ title: "Flows duplicated successfully" }); - }); - }; - - const handleImport = () => { - uploadFlow({ newProject: true, isComponent: false }) - .then(() => { - resetFilter(); - getFoldersApi(true); - if (!folderId || folderId === myCollectionId) { - getFolderById(folderId ? folderId : myCollectionId); - } - setSelectedFlowsComponentsCards([]); - - setSuccessData({ title: "Flows imported successfully" }); - }) - .catch((error) => { - setErrorData({ - title: UPLOAD_ERROR_ALERT, - list: [error], - }); - }); - }; - - const version = useDarkStore((state) => state.version); - - const handleExport = () => { - selectedFlowsComponentsCards.map((selectedFlowId) => { - const selectedFlow = allFlows.find((flow) => flow.id === selectedFlowId); - downloadFlow( - removeApiKeys({ - id: selectedFlow!.id, - data: selectedFlow!.data!, - description: selectedFlow!.description, - name: selectedFlow!.name, - last_tested_version: version, - is_component: false, - }), - selectedFlow!.name, - selectedFlow!.description - ); - }); - setSuccessData({ title: "Flows exported successfully" }); - }; - - const handleDeleteMultiple = () => { - removeFlow(selectedFlowsComponentsCards) - .then(() => { - resetFilter(); - getFoldersApi(true); - if (!folderId || folderId === myCollectionId) { - getFolderById(folderId ? folderId : myCollectionId); - } - setSuccessData({ - title: "Selected items deleted successfully", - }); - }) - .catch(() => { - setErrorData({ - title: "Error deleting items", - list: ["Please try again"], - }); - }); - }; const { handleDuplicate } = useDuplicateFlows( selectedFlowsComponentsCards, addFlow, diff --git a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx index bd8c7d107..26999fbd5 100644 --- a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx @@ -107,7 +107,7 @@ const HeaderComponent = ({ name="Trash2" className={cn( "h-5 w-5 text-primary transition-all", - disableFunctions ? "" : "hover:text-destructive" + disableFunctions ? "" : "hover:text-status-red" )} /> diff --git a/src/frontend/src/pages/SettingsPage/pages/messagesPage/components/headerMessages/index.tsx b/src/frontend/src/pages/SettingsPage/pages/messagesPage/components/headerMessages/index.tsx index 339a1a7bd..f7802fe41 100644 --- a/src/frontend/src/pages/SettingsPage/pages/messagesPage/components/headerMessages/index.tsx +++ b/src/frontend/src/pages/SettingsPage/pages/messagesPage/components/headerMessages/index.tsx @@ -1,15 +1,6 @@ import ForwardedIconComponent from "../../../../../../components/genericIconComponent"; -import { Button } from "../../../../../../components/ui/button"; -import { cn } from "../../../../../../utils/utils"; -type HeaderMessagesComponentProps = { - selectedRows: number[]; - handleRemoveMessages: () => void; -}; -const HeaderMessagesComponent = ({ - selectedRows, - handleRemoveMessages, -}: HeaderMessagesComponentProps) => { +const HeaderMessagesComponent = () => { return ( <>
@@ -26,22 +17,6 @@ const HeaderMessagesComponent = ({ behaviors.

-
- -
); diff --git a/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx b/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx index 5b1766d8c..553db9ba5 100644 --- a/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx +++ b/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx @@ -46,10 +46,7 @@ export default function MessagesPage() { return (
- +
((set, get) => ({ readFlowsFromDatabase() .then((dbData) => { if (dbData) { - const { data, flows } = processFlows(dbData, false); + const { data, flows } = processFlows(dbData); const examples = flows.filter( (flow) => flow.folder_id === starterFolderId ); diff --git a/src/frontend/src/stores/shortcuts.ts b/src/frontend/src/stores/shortcuts.ts index c0b271849..d792a0d6c 100644 --- a/src/frontend/src/stores/shortcuts.ts +++ b/src/frontend/src/stores/shortcuts.ts @@ -23,7 +23,7 @@ export const useShortcutsStore = create((set, get) => ({ group: "mod+g", cut: "mod+x", paste: "mod+v", - api: "mod+r", + api: "mod+shift+r", update: "mod+u", download: "mod+j", freeze: "mod+f", diff --git a/src/frontend/src/types/zustand/flow/index.ts b/src/frontend/src/types/zustand/flow/index.ts index a9049458f..e8b88e8d3 100644 --- a/src/frontend/src/types/zustand/flow/index.ts +++ b/src/frontend/src/types/zustand/flow/index.ts @@ -129,6 +129,7 @@ export type FlowStoreType = { stopNodeId?: string; input_value?: string; files?: string[]; + silent?: boolean; }) => Promise; getFlow: () => { nodes: Node[]; edges: Edge[]; viewport: Viewport }; updateVerticesBuild: ( diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index fbdb720fc..9a65e4f27 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -176,6 +176,7 @@ import { import { GroqIcon } from "../icons/Groq"; import { HuggingFaceIcon } from "../icons/HuggingFace"; import { IFixIcon } from "../icons/IFixIt"; +import { LangChainIcon } from "../icons/LangChain"; import { MetaIcon } from "../icons/Meta"; import { MidjourneyIcon } from "../icons/Midjorney"; import { MongoDBIcon } from "../icons/MongoDB"; @@ -324,6 +325,7 @@ export const nodeIconsLucide: iconsType = { ChatOllamaModel: OllamaIcon, Faiss: MetaIcon, FaissSearch: MetaIcon, + LangChain: LangChainIcon, AzureOpenAiModel: AzureIcon, Redis: RedisIcon, RedisSearch: RedisIcon, diff --git a/src/frontend/tailwind.config.js b/src/frontend/tailwind.config.js index 6f99f7b58..11e9c9d25 100644 --- a/src/frontend/tailwind.config.js +++ b/src/frontend/tailwind.config.js @@ -237,6 +237,10 @@ module.exports = { ".text-align-last-right": { "text-align-last": "right", }, + ":focus-visible": { + outline: "none !important", + outlineOffset: "0px !important", + }, }); }), require("@tailwindcss/typography"), diff --git a/src/frontend/tests/end-to-end/actionsMainPage.spec.ts b/src/frontend/tests/end-to-end/actionsMainPage.spec.ts index 916d09718..e2635cf57 100644 --- a/src/frontend/tests/end-to-end/actionsMainPage.spec.ts +++ b/src/frontend/tests/end-to-end/actionsMainPage.spec.ts @@ -90,6 +90,8 @@ test("search components", async ({ page }) => { await page.getByRole("heading", { name: "Basic Prompting" }).click(); await page.getByText("Chat Input").first().click(); + await page.getByTestId("more-options-modal").click(); + await page.getByTestId("icon-SaveAll").first().click(); await page.keyboard.press("Escape"); await page @@ -98,6 +100,8 @@ test("search components", async ({ page }) => { }) .first() .click(); + await page.getByTestId("more-options-modal").click(); + await page.getByTestId("icon-SaveAll").first().click(); await page.keyboard.press("Escape"); @@ -107,6 +111,8 @@ test("search components", async ({ page }) => { }) .first() .click(); + await page.getByTestId("more-options-modal").click(); + await page.getByTestId("icon-SaveAll").first().click(); await page.keyboard.press("Escape"); await page.getByTestId("icon-ChevronLeft").first().click(); diff --git a/src/frontend/tests/end-to-end/assets/ChatTest.json b/src/frontend/tests/end-to-end/assets/ChatTest.json index cadb3fe12..045d0cddf 100644 --- a/src/frontend/tests/end-to-end/assets/ChatTest.json +++ b/src/frontend/tests/end-to-end/assets/ChatTest.json @@ -44,9 +44,7 @@ "name": "input_value", "display_name": "Message", "advanced": false, - "input_types": [ - "Text" - ], + "input_types": ["Text"], "dynamic": false, "info": "", "load_from_db": false, @@ -70,9 +68,7 @@ "info": "In case of Message being a Record, this template will be used to convert it to text.", "load_from_db": false, "title_case": false, - "input_types": [ - "Text" - ] + "input_types": ["Text"] }, "return_record": { "type": "bool", @@ -104,10 +100,7 @@ "fileTypes": [], "file_path": "", "password": false, - "options": [ - "Machine", - "User" - ], + "options": ["Machine", "User"], "name": "sender", "display_name": "Sender Type", "advanced": true, @@ -115,9 +108,7 @@ "info": "", "load_from_db": false, "title_case": false, - "input_types": [ - "Text" - ] + "input_types": ["Text"] }, "sender_name": { "type": "str", @@ -137,9 +128,7 @@ "info": "", "load_from_db": false, "title_case": false, - "input_types": [ - "Text" - ] + "input_types": ["Text"] }, "session_id": { "type": "str", @@ -158,20 +147,13 @@ "info": "If provided, the message will be stored in the memory.", "load_from_db": false, "title_case": false, - "input_types": [ - "Text" - ] + "input_types": ["Text"] }, "_type": "CustomComponent" }, "description": "Display a chat message in the Playground.", "icon": "ChatOutput", - "base_classes": [ - "object", - "Record", - "str", - "Text" - ], + "base_classes": ["object", "Record", "str", "Text"], "display_name": "Chat Output", "documentation": "", "custom_fields": { @@ -182,10 +164,7 @@ "return_record": null, "record_template": null }, - "output_types": [ - "Text", - "Record" - ], + "output_types": ["Text", "Record"], "field_formatters": {}, "frozen": false, "field_order": [], @@ -280,10 +259,7 @@ "fileTypes": [], "file_path": "", "password": false, - "options": [ - "Machine", - "User" - ], + "options": ["Machine", "User"], "name": "sender", "display_name": "Sender Type", "advanced": true, @@ -291,9 +267,7 @@ "info": "", "load_from_db": false, "title_case": false, - "input_types": [ - "Text" - ] + "input_types": ["Text"] }, "sender_name": { "type": "str", @@ -313,9 +287,7 @@ "info": "", "load_from_db": false, "title_case": false, - "input_types": [ - "Text" - ] + "input_types": ["Text"] }, "session_id": { "type": "str", @@ -334,20 +306,13 @@ "info": "If provided, the message will be stored in the memory.", "load_from_db": false, "title_case": false, - "input_types": [ - "Text" - ] + "input_types": ["Text"] }, "_type": "CustomComponent" }, "description": "Get chat inputs from the Playground.", "icon": "ChatInput", - "base_classes": [ - "object", - "Record", - "str", - "Text" - ], + "base_classes": ["object", "Record", "str", "Text"], "display_name": "Chat Input", "documentation": "", "custom_fields": { @@ -357,10 +322,7 @@ "session_id": null, "return_record": null }, - "output_types": [ - "Text", - "Record" - ], + "output_types": ["Text", "Record"], "field_formatters": {}, "frozen": false, "field_order": [], @@ -383,18 +345,11 @@ "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-xPeM1", - "inputTypes": [ - "Text" - ], + "inputTypes": ["Text"], "type": "str" }, "sourceHandle": { - "baseClasses": [ - "object", - "Record", - "str", - "Text" - ], + "baseClasses": ["object", "Record", "str", "Text"], "dataType": "ChatInput", "id": "ChatInput-XYvUc" } @@ -416,4 +371,4 @@ "name": "ChatTest", "last_tested_version": "1.0.0a14", "is_component": false -} \ No newline at end of file +} diff --git a/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts b/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts index ce1a9ce27..c3e24018a 100644 --- a/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts +++ b/src/frontend/tests/end-to-end/chatInputOutputUser.spec.ts @@ -58,7 +58,7 @@ test("user must interact with chat with Input/Output", async ({ page }) => { .getByTestId("textarea-input_value") .nth(1) .fill( - "testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!", + "testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!" ); await page.getByTestId("icon-LucideSend").click(); await page.getByText("Close", { exact: true }).click(); @@ -89,9 +89,9 @@ test("user must interact with chat with Input/Output", async ({ page }) => { await page .getByText( "testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!", - { exact: true }, + { exact: true } ) - .isVisible(), + .isVisible() ); }); @@ -197,7 +197,7 @@ test("user must be able to send an image on chat", async ({ page }) => { await page.getByTestId("edit-button-modal").click(); await page.getByTestId("toggle-edit-return_record").click(); expect( - await page.getByTestId("toggle-edit-return_record").isChecked(), + await page.getByTestId("toggle-edit-return_record").isChecked() ).toBeTruthy(); await page.getByText("Save Changes").click(); @@ -205,7 +205,7 @@ test("user must be able to send an image on chat", async ({ page }) => { const jsonContent = readFileSync( "src/frontend/tests/end-to-end/assets/chain.png", - "utf-8", + "utf-8" ); // Create the DataTransfer and File diff --git a/src/frontend/tests/end-to-end/curl_api_generation.spec.ts b/src/frontend/tests/end-to-end/curl_api_generation.spec.ts index 74e3ee11e..406ecf268 100644 --- a/src/frontend/tests/end-to-end/curl_api_generation.spec.ts +++ b/src/frontend/tests/end-to-end/curl_api_generation.spec.ts @@ -23,7 +23,7 @@ test("curl_api_generation", async ({ page, context }) => { await page.getByRole("tab", { name: "cURL" }).click(); await page.getByRole("button", { name: "Copy Code" }).click(); const handle = await page.evaluateHandle(() => - navigator.clipboard.readText(), + navigator.clipboard.readText() ); const clipboardContent = await handle.jsonValue(); expect(clipboardContent.length).toBeGreaterThan(0); diff --git a/src/frontend/tests/end-to-end/dragAndDrop.spec.ts b/src/frontend/tests/end-to-end/dragAndDrop.spec.ts index 03d11aaf7..3e760901d 100644 --- a/src/frontend/tests/end-to-end/dragAndDrop.spec.ts +++ b/src/frontend/tests/end-to-end/dragAndDrop.spec.ts @@ -27,7 +27,7 @@ test.describe("drag and drop test", () => { // Read your file into a buffer. const jsonContent = readFileSync( "src/frontend/tests/end-to-end/assets/collection.json", - "utf-8", + "utf-8" ); // Create the DataTransfer and File @@ -47,7 +47,7 @@ test.describe("drag and drop test", () => { "drop", { dataTransfer, - }, + } ); const genericNoda = page.getByTestId("div-generic-node"); diff --git a/src/frontend/tests/end-to-end/dropdownComponent.spec.ts b/src/frontend/tests/end-to-end/dropdownComponent.spec.ts index 6c0a7dd9e..0152ca7ed 100644 --- a/src/frontend/tests/end-to-end/dropdownComponent.spec.ts +++ b/src/frontend/tests/end-to-end/dropdownComponent.spec.ts @@ -80,32 +80,32 @@ test("dropDownComponent", async ({ page }) => { await page.locator('//*[@id="showcredentials_profile_name"]').click(); expect( - await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showcredentials_profile_name"]').click(); expect( - await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showendpoint_url"]').click(); expect( - await page.locator('//*[@id="showendpoint_url"]').isChecked(), + await page.locator('//*[@id="showendpoint_url"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showendpoint_url"]').click(); expect( - await page.locator('//*[@id="showendpoint_url"]').isChecked(), + await page.locator('//*[@id="showendpoint_url"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showregion_name"]').click(); expect( - await page.locator('//*[@id="showregion_name"]').isChecked(), + await page.locator('//*[@id="showregion_name"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showregion_name"]').click(); expect( - await page.locator('//*[@id="showregion_name"]').isChecked(), + await page.locator('//*[@id="showregion_name"]').isChecked() ).toBeTruthy(); // showmodel_id @@ -115,7 +115,7 @@ test("dropDownComponent", async ({ page }) => { // showmodel_id await page.locator('//*[@id="showmodel_id"]').click(); expect( - await page.locator('//*[@id="showmodel_id"]').isChecked(), + await page.locator('//*[@id="showmodel_id"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showcache"]').click(); @@ -126,32 +126,32 @@ test("dropDownComponent", async ({ page }) => { await page.locator('//*[@id="showcredentials_profile_name"]').click(); expect( - await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showcredentials_profile_name"]').click(); expect( - await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showendpoint_url"]').click(); expect( - await page.locator('//*[@id="showendpoint_url"]').isChecked(), + await page.locator('//*[@id="showendpoint_url"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showendpoint_url"]').click(); expect( - await page.locator('//*[@id="showendpoint_url"]').isChecked(), + await page.locator('//*[@id="showendpoint_url"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showregion_name"]').click(); expect( - await page.locator('//*[@id="showregion_name"]').isChecked(), + await page.locator('//*[@id="showregion_name"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showregion_name"]').click(); expect( - await page.locator('//*[@id="showregion_name"]').isChecked(), + await page.locator('//*[@id="showregion_name"]').isChecked() ).toBeTruthy(); // showmodel_id @@ -161,7 +161,7 @@ test("dropDownComponent", async ({ page }) => { // showmodel_id await page.locator('//*[@id="showmodel_id"]').click(); expect( - await page.locator('//*[@id="showmodel_id"]').isChecked(), + await page.locator('//*[@id="showmodel_id"]').isChecked() ).toBeTruthy(); await page.getByTestId("dropdown-edit-model_id").click(); diff --git a/src/frontend/tests/end-to-end/fileUploadComponent.spec.ts b/src/frontend/tests/end-to-end/fileUploadComponent.spec.ts index 00f761dea..93b471c43 100644 --- a/src/frontend/tests/end-to-end/fileUploadComponent.spec.ts +++ b/src/frontend/tests/end-to-end/fileUploadComponent.spec.ts @@ -64,7 +64,7 @@ test("dropDownComponent", async ({ page }) => { // Click and hold on the first element await page .locator( - '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div', + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div' ) .hover(); await page.mouse.down(); @@ -72,7 +72,7 @@ test("dropDownComponent", async ({ page }) => { // Move to the second element await page .locator( - '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[3]/div/button/div/div', + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[3]/div/button/div/div' ) .hover(); diff --git a/src/frontend/tests/end-to-end/filterEdge.spec.ts b/src/frontend/tests/end-to-end/filterEdge.spec.ts index 7edbc0436..9cb5a567e 100644 --- a/src/frontend/tests/end-to-end/filterEdge.spec.ts +++ b/src/frontend/tests/end-to-end/filterEdge.spec.ts @@ -40,7 +40,7 @@ test("LLMChain - Tooltip", async ({ page }) => { await page .locator( - '//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[3]/div/button/div/div', + '//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[3]/div/button/div/div' ) .hover() .then(async () => { @@ -60,17 +60,17 @@ test("LLMChain - Tooltip", async ({ page }) => { await page.getByTitle("zoom out").click(); await page .locator( - '//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div', + '//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div' ) .hover() .then(async () => { await expect( - page.getByTestId("tooltip-Model Specs").first(), + page.getByTestId("tooltip-Model Specs").first() ).toBeVisible(); await page.waitForTimeout(2000); await expect( - page.getByTestId("tooltip-Model Specs").first(), + page.getByTestId("tooltip-Model Specs").first() ).toBeVisible(); await page.getByTestId("icon-Search").click(); @@ -81,12 +81,12 @@ test("LLMChain - Tooltip", async ({ page }) => { await page .locator( - '//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[5]/div/button/div/div', + '//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[5]/div/button/div/div' ) .hover() .then(async () => { await expect( - page.getByTestId("empty-tooltip-filter").first(), + page.getByTestId("empty-tooltip-filter").first() ).toBeVisible(); }); }); @@ -113,7 +113,7 @@ test("LLMChain - Filter", async ({ page }) => { await page.waitForTimeout(1000); await page.getByTestId( - "input-list-plus-btn-edit_metadata_indexing_include-2", + "input-list-plus-btn-edit_metadata_indexing_include-2" ); await page.getByTestId("blank-flow").click(); @@ -136,7 +136,7 @@ test("LLMChain - Filter", async ({ page }) => { await page .locator( - '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[4]/div/button/div/div', + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[4]/div/button/div/div' ) .click(); @@ -149,14 +149,14 @@ test("LLMChain - Filter", async ({ page }) => { await expect(page.getByTestId("model_specsChatOpenAI")).toBeVisible(); await expect(page.getByTestId("model_specsChatVertexAI")).toBeVisible(); await expect( - page.getByTestId("model_specsGoogle Generative AI"), + page.getByTestId("model_specsGoogle Generative AI") ).toBeVisible(); await expect( - page.getByTestId("model_specsHugging Face Inference API"), + page.getByTestId("model_specsHugging Face Inference API") ).toBeVisible(); await expect(page.getByTestId("model_specsOllama")).toBeVisible(); await expect( - page.getByTestId("model_specsQianfanChatEndpoint"), + page.getByTestId("model_specsQianfanChatEndpoint") ).toBeVisible(); await expect(page.getByTestId("model_specsQianfanLLMEndpoint")).toBeVisible(); await expect(page.getByTestId("model_specsVertexAI")).toBeVisible(); @@ -168,7 +168,7 @@ test("LLMChain - Filter", async ({ page }) => { await expect(page.getByTestId("model_specsAmazon Bedrock")).not.toBeVisible(); await expect(page.getByTestId("modelsAzure OpenAI")).not.toBeVisible(); await expect( - page.getByTestId("model_specsAzureChatOpenAI"), + page.getByTestId("model_specsAzureChatOpenAI") ).not.toBeVisible(); await expect(page.getByTestId("model_specsChatAnthropic")).not.toBeVisible(); await expect(page.getByTestId("model_specsChatLiteLLM")).not.toBeVisible(); @@ -178,13 +178,13 @@ test("LLMChain - Filter", async ({ page }) => { await page .locator( - '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div', + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div' ) .click(); await page .locator( - '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div', + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div' ) .click(); diff --git a/src/frontend/tests/end-to-end/floatComponent.spec.ts b/src/frontend/tests/end-to-end/floatComponent.spec.ts index e172a92e3..dfac6ec1b 100644 --- a/src/frontend/tests/end-to-end/floatComponent.spec.ts +++ b/src/frontend/tests/end-to-end/floatComponent.spec.ts @@ -71,27 +71,32 @@ test("FloatComponent", async ({ page }) => { await page.getByTestId("showmirostat").click(); expect( - await page.locator('//*[@id="showmirostat"]').isChecked(), + await page.locator('//*[@id="showmirostat"]').isChecked() ).toBeTruthy(); await page.getByTestId("showmirostat_eta").click(); expect( - await page.locator('//*[@id="showmirostat_eta"]').isChecked(), + await page.locator('//*[@id="showmirostat"]').isChecked() ).toBeTruthy(); await page.getByTestId("showmirostat_eta").click(); expect( - await page.locator('//*[@id="showmirostat_eta"]').isChecked(), + await page.locator('//*[@id="showmirostat_eta"]').isChecked() + ).toBeTruthy(); + + await page.getByTestId("showmirostat_eta").click(); + expect( + await page.locator('//*[@id="showmirostat_eta"]').isChecked() ).toBeFalsy(); await page.getByTestId("showmirostat_tau").click(); expect( - await page.locator('//*[@id="showmirostat_tau"]').isChecked(), + await page.locator('//*[@id="showmirostat_tau"]').isChecked() ).toBeTruthy(); await page.getByTestId("showmirostat_tau").click(); expect( - await page.locator('//*[@id="showmirostat_tau"]').isChecked(), + await page.locator('//*[@id="showmirostat_tau"]').isChecked() ).toBeFalsy(); await page.getByTestId("showmodel").click(); @@ -114,22 +119,22 @@ test("FloatComponent", async ({ page }) => { await page.getByTestId("shownum_thread").click(); expect( - await page.locator('//*[@id="shownum_thread"]').isChecked(), + await page.locator('//*[@id="shownum_thread"]').isChecked() ).toBeTruthy(); await page.getByTestId("shownum_thread").click(); expect( - await page.locator('//*[@id="shownum_thread"]').isChecked(), + await page.locator('//*[@id="shownum_thread"]').isChecked() ).toBeFalsy(); await page.getByTestId("showrepeat_last_n").click(); expect( - await page.locator('//*[@id="showrepeat_last_n"]').isChecked(), + await page.locator('//*[@id="showrepeat_last_n"]').isChecked() ).toBeTruthy(); await page.getByTestId("showrepeat_last_n").click(); expect( - await page.locator('//*[@id="showrepeat_last_n"]').isChecked(), + await page.locator('//*[@id="showrepeat_last_n"]').isChecked() ).toBeFalsy(); await page.getByText("Save Changes", { exact: true }).click(); @@ -145,7 +150,7 @@ test("FloatComponent", async ({ page }) => { // showtemperature await page.locator('//*[@id="showtemperature"]').click(); expect( - await page.locator('//*[@id="showtemperature"]').isChecked(), + await page.locator('//*[@id="showtemperature"]').isChecked() ).toBeTruthy(); await page.getByText("Save Changes", { exact: true }).click(); diff --git a/src/frontend/tests/end-to-end/flowSettings.spec.ts b/src/frontend/tests/end-to-end/flowSettings.spec.ts index 25807ed88..a2e9f25c0 100644 --- a/src/frontend/tests/end-to-end/flowSettings.spec.ts +++ b/src/frontend/tests/end-to-end/flowSettings.spec.ts @@ -29,7 +29,7 @@ test("flowSettings", async ({ page }) => { await page .getByPlaceholder("Flow name") .fill( - "Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test", + "Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test" ); await page.getByText("Character limit reached").isVisible(); @@ -41,7 +41,7 @@ test("flowSettings", async ({ page }) => { await page .getByPlaceholder("Flow description") .fill( - "Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test", + "Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test" ); await page.getByTestId("save-flow-settings").click(); diff --git a/src/frontend/tests/end-to-end/inputComponent.spec.ts b/src/frontend/tests/end-to-end/inputComponent.spec.ts index 3e6936b43..d944cffe5 100644 --- a/src/frontend/tests/end-to-end/inputComponent.spec.ts +++ b/src/frontend/tests/end-to-end/inputComponent.spec.ts @@ -60,69 +60,69 @@ test("InputComponent", async ({ page }) => { expect( await page .locator('//*[@id="showchroma_server_cors_allow_origins"]') - .isChecked(), + .isChecked() ).toBeTruthy(); await page.locator('//*[@id="showchroma_server_grpc_port"]').click(); expect( - await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked(), + await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showchroma_server_host"]').click(); expect( - await page.locator('//*[@id="showchroma_server_host"]').isChecked(), + await page.locator('//*[@id="showchroma_server_host"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showchroma_server_http_port"]').click(); expect( - await page.locator('//*[@id="showchroma_server_http_port"]').isChecked(), + await page.locator('//*[@id="showchroma_server_http_port"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click(); expect( - await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked(), + await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showcollection_name"]').click(); expect( - await page.locator('//*[@id="showcollection_name"]').isChecked(), + await page.locator('//*[@id="showcollection_name"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showindex_directory"]').click(); expect( - await page.locator('//*[@id="showindex_directory"]').isChecked(), + await page.locator('//*[@id="showindex_directory"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showchroma_server_cors_allow_origins"]').click(); expect( await page .locator('//*[@id="showchroma_server_cors_allow_origins"]') - .isChecked(), + .isChecked() ).toBeFalsy(); await page.locator('//*[@id="showchroma_server_grpc_port"]').click(); expect( - await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked(), + await page.locator('//*[@id="showchroma_server_grpc_port"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showchroma_server_host"]').click(); expect( - await page.locator('//*[@id="showchroma_server_host"]').isChecked(), + await page.locator('//*[@id="showchroma_server_host"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showchroma_server_http_port"]').click(); expect( - await page.locator('//*[@id="showchroma_server_http_port"]').isChecked(), + await page.locator('//*[@id="showchroma_server_http_port"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click(); expect( - await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked(), + await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showindex_directory"]').click(); expect( - await page.locator('//*[@id="showindex_directory"]').isChecked(), + await page.locator('//*[@id="showindex_directory"]').isChecked() ).toBeTruthy(); let valueEditNode = await page @@ -152,7 +152,7 @@ test("InputComponent", async ({ page }) => { await page.locator('//*[@id="showcollection_name"]').click(); expect( - await page.locator('//*[@id="showcollection_name"]').isChecked(), + await page.locator('//*[@id="showcollection_name"]').isChecked() ).toBeTruthy(); await page.getByText("Save Changes", { exact: true }).click(); diff --git a/src/frontend/tests/end-to-end/intComponent.spec.ts b/src/frontend/tests/end-to-end/intComponent.spec.ts index 6ec81819a..9b4ed14e2 100644 --- a/src/frontend/tests/end-to-end/intComponent.spec.ts +++ b/src/frontend/tests/end-to-end/intComponent.spec.ts @@ -87,77 +87,77 @@ test("IntComponent", async ({ page }) => { await page.locator('//*[@id="showmodel_kwargs"]').click(); expect( - await page.locator('//*[@id="showmodel_kwargs"]').isChecked(), + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showmodel_name"]').click(); expect( - await page.locator('//*[@id="showmodel_name"]').isChecked(), + await page.locator('//*[@id="showmodel_name"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showopenai_api_base"]').click(); expect( - await page.locator('//*[@id="showopenai_api_base"]').isChecked(), + await page.locator('//*[@id="showopenai_api_base"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showopenai_api_key"]').click(); expect( - await page.locator('//*[@id="showopenai_api_key"]').isChecked(), + await page.locator('//*[@id="showopenai_api_key"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showtemperature"]').click(); expect( - await page.locator('//*[@id="showtemperature"]').isChecked(), + await page.locator('//*[@id="showtemperature"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showmodel_kwargs"]').click(); expect( - await page.locator('//*[@id="showmodel_kwargs"]').isChecked(), + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showmodel_name"]').click(); expect( - await page.locator('//*[@id="showmodel_name"]').isChecked(), + await page.locator('//*[@id="showmodel_name"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showopenai_api_base"]').click(); expect( - await page.locator('//*[@id="showopenai_api_base"]').isChecked(), + await page.locator('//*[@id="showopenai_api_base"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showopenai_api_key"]').click(); expect( - await page.locator('//*[@id="showopenai_api_key"]').isChecked(), + await page.locator('//*[@id="showopenai_api_key"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showtemperature"]').click(); expect( - await page.locator('//*[@id="showtemperature"]').isChecked(), + await page.locator('//*[@id="showtemperature"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showmodel_kwargs"]').click(); expect( - await page.locator('//*[@id="showmodel_kwargs"]').isChecked(), + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showmodel_name"]').click(); expect( - await page.locator('//*[@id="showmodel_name"]').isChecked(), + await page.locator('//*[@id="showmodel_name"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showopenai_api_base"]').click(); expect( - await page.locator('//*[@id="showopenai_api_base"]').isChecked(), + await page.locator('//*[@id="showopenai_api_base"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showopenai_api_key"]').click(); expect( - await page.locator('//*[@id="showopenai_api_key"]').isChecked(), + await page.locator('//*[@id="showopenai_api_key"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showtemperature"]').click(); expect( - await page.locator('//*[@id="showtemperature"]').isChecked(), + await page.locator('//*[@id="showtemperature"]').isChecked() ).toBeFalsy(); await page.getByText("Save Changes", { exact: true }).click(); @@ -172,7 +172,7 @@ test("IntComponent", async ({ page }) => { await page.locator('//*[@id="showtimeout"]').click(); expect( - await page.locator('//*[@id="showtimeout"]').isChecked(), + await page.locator('//*[@id="showtimeout"]').isChecked() ).toBeTruthy(); const valueEditNode = await page diff --git a/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts b/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts index 31a4521ae..165dd685b 100644 --- a/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts +++ b/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts @@ -81,7 +81,7 @@ test("KeypairListComponent", async ({ page }) => { expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeFalsy(); await page.locator('//*[@id="showcredentials_profile_name"]').click(); expect( - await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() ).toBeFalsy(); await page.getByText("Save Changes", { exact: true }).click(); @@ -96,7 +96,7 @@ test("KeypairListComponent", async ({ page }) => { await page.locator('//*[@id="showcredentials_profile_name"]').click(); expect( - await page.locator('//*[@id="showcredentials_profile_name"]').isChecked(), + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showcache"]').click(); expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeTruthy(); diff --git a/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts b/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts index 42b8744d1..58615dd55 100644 --- a/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts +++ b/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts @@ -61,7 +61,7 @@ test("LangflowShortcuts", async ({ page }) => { await page .locator( - '//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]', + '//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]' ) .click(); await page.keyboard.press("Backspace"); @@ -84,7 +84,7 @@ test("LangflowShortcuts", async ({ page }) => { await page .locator( - '//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]', + '//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]' ) .click(); await page.keyboard.press("Backspace"); diff --git a/src/frontend/tests/end-to-end/nestedComponent.spec.ts b/src/frontend/tests/end-to-end/nestedComponent.spec.ts index 2df9c1b7b..3cd319576 100644 --- a/src/frontend/tests/end-to-end/nestedComponent.spec.ts +++ b/src/frontend/tests/end-to-end/nestedComponent.spec.ts @@ -41,7 +41,7 @@ test("NestedComponent", async ({ page }) => { await page.locator('//*[@id="showpool_threads"]').click(); expect( - await page.locator('//*[@id="showpool_threads"]').isChecked(), + await page.locator('//*[@id="showpool_threads"]').isChecked() ).toBeTruthy(); //showtext_key @@ -53,140 +53,140 @@ test("NestedComponent", async ({ page }) => { await page.locator('//*[@id="showindex_name"]').click(); expect( - await page.locator('//*[@id="showindex_name"]').isChecked(), + await page.locator('//*[@id="showindex_name"]').isChecked() ).toBeFalsy(); // shownamespace await page.locator('//*[@id="shownamespace"]').click(); expect( - await page.locator('//*[@id="shownamespace"]').isChecked(), + await page.locator('//*[@id="shownamespace"]').isChecked() ).toBeFalsy(); // showpinecone_api_key await page.locator('//*[@id="showpinecone_api_key"]').click(); expect( - await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), + await page.locator('//*[@id="showpinecone_api_key"]').isChecked() ).toBeFalsy(); // showindex_name await page.locator('//*[@id="showindex_name"]').click(); expect( - await page.locator('//*[@id="showindex_name"]').isChecked(), + await page.locator('//*[@id="showindex_name"]').isChecked() ).toBeTruthy(); // shownamespace await page.locator('//*[@id="shownamespace"]').click(); expect( - await page.locator('//*[@id="shownamespace"]').isChecked(), + await page.locator('//*[@id="shownamespace"]').isChecked() ).toBeTruthy(); // showpinecone_api_key await page.locator('//*[@id="showpinecone_api_key"]').click(); expect( - await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), + await page.locator('//*[@id="showpinecone_api_key"]').isChecked() ).toBeTruthy(); // showindex_name await page.locator('//*[@id="showindex_name"]').click(); expect( - await page.locator('//*[@id="showindex_name"]').isChecked(), + await page.locator('//*[@id="showindex_name"]').isChecked() ).toBeFalsy(); // shownamespace await page.locator('//*[@id="shownamespace"]').click(); expect( - await page.locator('//*[@id="shownamespace"]').isChecked(), + await page.locator('//*[@id="shownamespace"]').isChecked() ).toBeFalsy(); // showpinecone_api_key await page.locator('//*[@id="showpinecone_api_key"]').click(); expect( - await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), + await page.locator('//*[@id="showpinecone_api_key"]').isChecked() ).toBeFalsy(); // showindex_name await page.locator('//*[@id="showindex_name"]').click(); expect( - await page.locator('//*[@id="showindex_name"]').isChecked(), + await page.locator('//*[@id="showindex_name"]').isChecked() ).toBeTruthy(); // shownamespace await page.locator('//*[@id="shownamespace"]').click(); expect( - await page.locator('//*[@id="shownamespace"]').isChecked(), + await page.locator('//*[@id="shownamespace"]').isChecked() ).toBeTruthy(); // showpinecone_api_key await page.locator('//*[@id="showpinecone_api_key"]').click(); expect( - await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), + await page.locator('//*[@id="showpinecone_api_key"]').isChecked() ).toBeTruthy(); // showindex_name await page.locator('//*[@id="showindex_name"]').click(); expect( - await page.locator('//*[@id="showindex_name"]').isChecked(), + await page.locator('//*[@id="showindex_name"]').isChecked() ).toBeFalsy(); // shownamespace await page.locator('//*[@id="shownamespace"]').click(); expect( - await page.locator('//*[@id="shownamespace"]').isChecked(), + await page.locator('//*[@id="shownamespace"]').isChecked() ).toBeFalsy(); // showpinecone_api_key await page.locator('//*[@id="showpinecone_api_key"]').click(); expect( - await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), + await page.locator('//*[@id="showpinecone_api_key"]').isChecked() ).toBeFalsy(); // showindex_name await page.locator('//*[@id="showindex_name"]').click(); expect( - await page.locator('//*[@id="showindex_name"]').isChecked(), + await page.locator('//*[@id="showindex_name"]').isChecked() ).toBeTruthy(); // shownamespace await page.locator('//*[@id="shownamespace"]').click(); expect( - await page.locator('//*[@id="shownamespace"]').isChecked(), + await page.locator('//*[@id="shownamespace"]').isChecked() ).toBeTruthy(); // showpinecone_api_key await page.locator('//*[@id="showpinecone_api_key"]').click(); expect( - await page.locator('//*[@id="showpinecone_api_key"]').isChecked(), + await page.locator('//*[@id="showpinecone_api_key"]').isChecked() ).toBeTruthy(); //showpool_threads await page.locator('//*[@id="showpool_threads"]').click(); expect( - await page.locator('//*[@id="showpool_threads"]').isChecked(), + await page.locator('//*[@id="showpool_threads"]').isChecked() ).toBeFalsy(); //showtext_key await page.locator('//*[@id="showtext_key"]').click(); expect( - await page.locator('//*[@id="showtext_key"]').isChecked(), + await page.locator('//*[@id="showtext_key"]').isChecked() ).toBeTruthy(); await page.getByText("Save Changes", { exact: true }).click(); diff --git a/src/frontend/tests/end-to-end/promptModalComponent.spec.ts b/src/frontend/tests/end-to-end/promptModalComponent.spec.ts index 8c6a5ab84..ed8162a4e 100644 --- a/src/frontend/tests/end-to-end/promptModalComponent.spec.ts +++ b/src/frontend/tests/end-to-end/promptModalComponent.spec.ts @@ -138,7 +138,7 @@ test("PromptTemplateComponent", async ({ page }) => { await page.locator('//*[@id="showtemplate"]').click(); expect( - await page.locator('//*[@id="showtemplate"]').isChecked(), + await page.locator('//*[@id="showtemplate"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showprompt"]').click(); @@ -158,7 +158,7 @@ test("PromptTemplateComponent", async ({ page }) => { await page.locator('//*[@id="showtemplate"]').click(); expect( - await page.locator('//*[@id="showtemplate"]').isChecked(), + await page.locator('//*[@id="showtemplate"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showprompt"]').click(); diff --git a/src/frontend/tests/end-to-end/python_api_generation.spec.ts b/src/frontend/tests/end-to-end/python_api_generation.spec.ts index 2857c9eb5..d75dd2c5e 100644 --- a/src/frontend/tests/end-to-end/python_api_generation.spec.ts +++ b/src/frontend/tests/end-to-end/python_api_generation.spec.ts @@ -23,7 +23,7 @@ test("python_api_generation", async ({ page, context }) => { await page.getByRole("tab", { name: "Python API" }).click(); await page.getByRole("button", { name: "Copy Code" }).click(); const handle = await page.evaluateHandle(() => - navigator.clipboard.readText(), + navigator.clipboard.readText() ); const clipboardContent = await handle.jsonValue(); expect(clipboardContent.length).toBeGreaterThan(0); diff --git a/src/frontend/tests/end-to-end/saveComponents.spec.ts b/src/frontend/tests/end-to-end/saveComponents.spec.ts index 624bb5b2e..94fab8f39 100644 --- a/src/frontend/tests/end-to-end/saveComponents.spec.ts +++ b/src/frontend/tests/end-to-end/saveComponents.spec.ts @@ -27,7 +27,7 @@ test.describe("save component tests", () => { // Read your file into a buffer. const jsonContent = readFileSync( "src/frontend/tests/end-to-end/assets/flow_group_test.json", - "utf-8", + "utf-8" ); // Create the DataTransfer and File @@ -49,7 +49,7 @@ test.describe("save component tests", () => { "drop", { dataTransfer, - }, + } ); const genericNoda = page.getByTestId("div-generic-node"); diff --git a/src/frontend/tests/end-to-end/store.spec.ts b/src/frontend/tests/end-to-end/store.spec.ts index 8e443ecdd..13963d698 100644 --- a/src/frontend/tests/end-to-end/store.spec.ts +++ b/src/frontend/tests/end-to-end/store.spec.ts @@ -262,7 +262,7 @@ test("should share component with share button", async ({ page }) => { await page.getByText("Set workflow status to public").isVisible(); await page .getByText( - "Attention: API keys in specified fields are automatically removed upon sharing.", + "Attention: API keys in specified fields are automatically removed upon sharing." ) .isVisible(); await page.getByText("Export").first().isVisible(); diff --git a/src/frontend/tests/end-to-end/textAreaModalComponent.spec.ts b/src/frontend/tests/end-to-end/textAreaModalComponent.spec.ts index 9443586e6..fa4248a63 100644 --- a/src/frontend/tests/end-to-end/textAreaModalComponent.spec.ts +++ b/src/frontend/tests/end-to-end/textAreaModalComponent.spec.ts @@ -51,7 +51,7 @@ test("TextAreaModalComponent", async ({ page }) => { await page .getByTestId("textarea-text") .fill( - "test test test test test test test test test test test !@#%*)( 123456789101010101010101111111111 !!!!!!!!!!", + "test test test test test test test test test test test !@#%*)( 123456789101010101010101111111111 !!!!!!!!!!" ); await page.getByTestId("textarea-text-ExternalLink").click(); diff --git a/src/frontend/tests/end-to-end/textInputOutput.spec.ts b/src/frontend/tests/end-to-end/textInputOutput.spec.ts index 3da77e867..94804d956 100644 --- a/src/frontend/tests/end-to-end/textInputOutput.spec.ts +++ b/src/frontend/tests/end-to-end/textInputOutput.spec.ts @@ -60,7 +60,7 @@ test("TextInputOutputComponent", async ({ page }) => { // Click and hold on the first element await page .locator( - '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div', + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div' ) .hover(); await page.mouse.down(); @@ -68,7 +68,7 @@ test("TextInputOutputComponent", async ({ page }) => { // Move to the second element await page .locator( - '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[9]/div/button/div/div', + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[9]/div/button/div/div' ) .hover(); @@ -92,7 +92,7 @@ test("TextInputOutputComponent", async ({ page }) => { // Click and hold on the first element await page .locator( - '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[13]/button/div/div', + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[13]/button/div/div' ) .hover(); await page.mouse.down(); @@ -100,7 +100,7 @@ test("TextInputOutputComponent", async ({ page }) => { // Move to the second element await page .locator( - '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[3]/div/div[2]/div[3]/div/button/div/div', + '//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[3]/div/div[2]/div[3]/div/button/div/div' ) .hover(); diff --git a/src/frontend/tests/end-to-end/toggleComponent.spec.ts b/src/frontend/tests/end-to-end/toggleComponent.spec.ts index 58d909af4..5a8d9a36a 100644 --- a/src/frontend/tests/end-to-end/toggleComponent.spec.ts +++ b/src/frontend/tests/end-to-end/toggleComponent.spec.ts @@ -45,7 +45,7 @@ test("ToggleComponent", async ({ page }) => { await page.locator('//*[@id="showload_hidden"]').click(); expect( - await page.locator('//*[@id="showload_hidden"]').isChecked(), + await page.locator('//*[@id="showload_hidden"]').isChecked() ).toBeTruthy(); await page.getByText("Save Changes", { exact: true }).click(); @@ -81,12 +81,12 @@ test("ToggleComponent", async ({ page }) => { await page.locator('//*[@id="showload_hidden"]').click(); expect( - await page.locator('//*[@id="showload_hidden"]').isChecked(), + await page.locator('//*[@id="showload_hidden"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showmax_concurrency"]').click(); expect( - await page.locator('//*[@id="showmax_concurrency"]').isChecked(), + await page.locator('//*[@id="showmax_concurrency"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showpath"]').click(); @@ -94,22 +94,22 @@ test("ToggleComponent", async ({ page }) => { await page.locator('//*[@id="showrecursive"]').click(); expect( - await page.locator('//*[@id="showrecursive"]').isChecked(), + await page.locator('//*[@id="showrecursive"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showsilent_errors"]').click(); expect( - await page.locator('//*[@id="showsilent_errors"]').isChecked(), + await page.locator('//*[@id="showsilent_errors"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showuse_multithreading"]').click(); expect( - await page.locator('//*[@id="showuse_multithreading"]').isChecked(), + await page.locator('//*[@id="showuse_multithreading"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showmax_concurrency"]').click(); expect( - await page.locator('//*[@id="showmax_concurrency"]').isChecked(), + await page.locator('//*[@id="showmax_concurrency"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showpath"]').click(); @@ -117,17 +117,17 @@ test("ToggleComponent", async ({ page }) => { await page.locator('//*[@id="showrecursive"]').click(); expect( - await page.locator('//*[@id="showrecursive"]').isChecked(), + await page.locator('//*[@id="showrecursive"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showsilent_errors"]').click(); expect( - await page.locator('//*[@id="showsilent_errors"]').isChecked(), + await page.locator('//*[@id="showsilent_errors"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showuse_multithreading"]').click(); expect( - await page.locator('//*[@id="showuse_multithreading"]').isChecked(), + await page.locator('//*[@id="showuse_multithreading"]').isChecked() ).toBeFalsy(); await page.getByText("Save Changes", { exact: true }).click(); @@ -144,38 +144,38 @@ test("ToggleComponent", async ({ page }) => { await page.locator('//*[@id="showload_hidden"]').click(); expect( - await page.locator('//*[@id="showload_hidden"]').isChecked(), + await page.locator('//*[@id="showload_hidden"]').isChecked() ).toBeTruthy(); expect( - await page.getByTestId("toggle-edit-load_hidden").isChecked(), + await page.getByTestId("toggle-edit-load_hidden").isChecked() ).toBeTruthy(); await page.getByText("Save Changes", { exact: true }).click(); await page.getByTestId("toggle-load_hidden").click(); expect( - await page.getByTestId("toggle-load_hidden").isChecked(), + await page.getByTestId("toggle-load_hidden").isChecked() ).toBeFalsy(); await page.getByTestId("toggle-load_hidden").click(); expect( - await page.getByTestId("toggle-load_hidden").isChecked(), + await page.getByTestId("toggle-load_hidden").isChecked() ).toBeTruthy(); await page.getByTestId("toggle-load_hidden").click(); expect( - await page.getByTestId("toggle-load_hidden").isChecked(), + await page.getByTestId("toggle-load_hidden").isChecked() ).toBeFalsy(); await page.getByTestId("toggle-load_hidden").click(); expect( - await page.getByTestId("toggle-load_hidden").isChecked(), + await page.getByTestId("toggle-load_hidden").isChecked() ).toBeTruthy(); await page.getByTestId("toggle-load_hidden").click(); expect( - await page.getByTestId("toggle-load_hidden").isChecked(), + await page.getByTestId("toggle-load_hidden").isChecked() ).toBeFalsy(); } }); diff --git a/src/frontend/tests/end-to-end/tweaks_test.spec.ts b/src/frontend/tests/end-to-end/tweaks_test.spec.ts index 586d0d9e1..0006456af 100644 --- a/src/frontend/tests/end-to-end/tweaks_test.spec.ts +++ b/src/frontend/tests/end-to-end/tweaks_test.spec.ts @@ -24,7 +24,7 @@ test("curl_api_generation", async ({ page, context }) => { await page.getByRole("tab", { name: "cURL" }).click(); await page.getByRole("button", { name: "Copy Code" }).click(); const handle = await page.evaluateHandle(() => - navigator.clipboard.readText(), + navigator.clipboard.readText() ); const clipboardContent = await handle.jsonValue(); const oldValue = clipboardContent; @@ -50,7 +50,7 @@ test("curl_api_generation", async ({ page, context }) => { await page.getByRole("tab", { name: "cURL" }).click(); await page.getByRole("button", { name: "Copy Code" }).click(); const handle2 = await page.evaluateHandle(() => - navigator.clipboard.readText(), + navigator.clipboard.readText() ); const clipboardContent2 = await handle2.jsonValue(); const newValue = clipboardContent2; diff --git a/tests/test_endpoints.py b/tests/test_endpoints.py index ab016ab17..98fc2d613 100644 --- a/tests/test_endpoints.py +++ b/tests/test_endpoints.py @@ -4,6 +4,7 @@ from uuid import UUID, uuid4 import pytest from fastapi import status from fastapi.testclient import TestClient + from langflow.custom.directory_reader.directory_reader import DirectoryReader from langflow.services.deps import get_settings_service