From 3f854a88aeca0124f6abc422ac367321968ffa26 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Tue, 23 May 2023 16:31:20 -0300 Subject: [PATCH 01/44] hot fix for dinamic size of font for buttonBox component --- .../modals/importModal/buttonBox/index.tsx | 89 +++++++++---------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/src/frontend/src/modals/importModal/buttonBox/index.tsx b/src/frontend/src/modals/importModal/buttonBox/index.tsx index 2e8978597..2f120d30b 100644 --- a/src/frontend/src/modals/importModal/buttonBox/index.tsx +++ b/src/frontend/src/modals/importModal/buttonBox/index.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode, useEffect } from "react"; +import React, { ReactNode, useEffect, useRef, useState } from "react"; import { DocumentDuplicateIcon } from "@heroicons/react/solid"; import { classNames } from "../../../utils"; import Tooltip from "../../../components/TooltipComponent"; @@ -24,7 +24,7 @@ export default function ButtonBox({ }) { let bigCircle: string; let smallCircle: string; - let titleFontSize: string; + let titleFontSize: number; let descriptionFontSize: string; let padding: string; let marginTop: string; @@ -36,19 +36,19 @@ export default function ButtonBox({ case "small": bigCircle = "h-12 w-12"; smallCircle = "h-8 w-8"; - titleFontSize = "text-sm"; + titleFontSize = 14; descriptionFontSize = "text-xs"; padding = "p-2 py-3"; marginTop = "mt-2"; height = "h-36"; textHeight = 70; - textWidth = 80; + textWidth = 40; width = "w-32"; break; case "medium": bigCircle = "h-16 w-16"; smallCircle = "h-12 w-12"; - titleFontSize = "text-base"; + titleFontSize = 16; descriptionFontSize = "text-sm"; padding = "p-4 py-5"; marginTop = "mt-3"; @@ -60,7 +60,7 @@ export default function ButtonBox({ case "big": bigCircle = "h-20 w-20"; smallCircle = "h-16 w-16"; - titleFontSize = "text-lg"; + titleFontSize = 18; descriptionFontSize = "text-sm"; padding = "p-8 py-10"; marginTop = "mt-6"; @@ -70,7 +70,7 @@ export default function ButtonBox({ default: bigCircle = "h-20 w-20"; smallCircle = "h-16 w-16"; - titleFontSize = "text-lg"; + titleFontSize = 18; descriptionFontSize = "text-sm"; padding = "p-8 py-10"; marginTop = "mt-6"; @@ -79,43 +79,36 @@ export default function ButtonBox({ break; } - const titleRef = React.useRef(null); + const [fontSize, setFontSize] = useState(16); // Initial font size value + + const titleRef = useRef(null); + const parentDivRef = useRef(null); useEffect(() => { - const resizeFont = () => { - const titleElement = titleRef.current; - if (titleElement) { - const containerWidth = titleElement.offsetWidth; - const containerHeight = titleElement.offsetHeight; - - const titleComputedStyle = window.getComputedStyle(titleElement); - const titleWidth = titleElement.getBoundingClientRect().width; - - const currentFontSize = parseFloat(titleComputedStyle.fontSize); - - const desiredWidth = textWidth - 10; // Subtracting the desired padding - - // Calculate the desired font size based on the adjusted width - let desiredFontSize = currentFontSize * (desiredWidth / titleWidth); - - // Adjust the desired font size to fit within the container height, if needed - const maxHeight = containerHeight - 10; // Subtracting the desired top padding - const maxHeightFontSize = maxHeight * 0.8; // Adjust the scaling factor as needed - desiredFontSize = Math.min(desiredFontSize, maxHeightFontSize); - - // Apply the desired font size and padding to the title element - titleElement.style.fontSize = `${desiredFontSize}px`; - titleElement.style.paddingLeft = "5px"; - titleElement.style.paddingRight = "5px"; - } - }; - - resizeFont(); - window.addEventListener("resize", resizeFont); - return () => { - window.removeEventListener("resize", resizeFont); - }; - }, []); + const textElement = titleRef.current; + const parentDivElement = parentDivRef.current; + + if (!textElement || !parentDivElement) return; + + const parentDivHeight = parentDivElement.offsetHeight; + const parentDivWidth = parentDivElement.offsetWidth; + let textElementHeight = textElement.scrollHeight; + let textElementWidth = textElement.scrollWidth; + + if (textElementHeight > parentDivHeight || textElementWidth > parentDivWidth) { + let newFontSize = fontSize; + + while (textElementHeight > parentDivHeight || textElementWidth > parentDivWidth) { + newFontSize -= 1; + textElement.style.fontSize = `${newFontSize}px`; + textElementHeight = textElement.scrollHeight; + textElementWidth = textElement.scrollWidth; + } + + setFontSize(newFontSize); + } + }, [title, size, fontSize]); + return ( ); From e597a6e20a59f7a6ff8690e634ca202df7d89271 Mon Sep 17 00:00:00 2001 From: Gabriel Almeida Date: Tue, 23 May 2023 16:51:29 -0300 Subject: [PATCH 02/44] =?UTF-8?q?=F0=9F=94=80=20chore(config):=20add=20Doc?= =?UTF-8?q?ArrayHnswSearch=20and=20DocArrayInMemorySearch=20to=20vectorsto?= =?UTF-8?q?res=20=F0=9F=90=9B=20fix(base.py):=20correctly=20handle=20neste?= =?UTF-8?q?d=20lists=20in=20Node.build()=20method=20=E2=9C=A8=20feat(vecto?= =?UTF-8?q?r=5Fstore):=20add=20VectorStoreFrontendNode=20to=20handle=20vec?= =?UTF-8?q?tor=20store=20templates=20=F0=9F=90=9B=20fix(util.py):=20add=20?= =?UTF-8?q?build=5Ftemplate=5Ffrom=5Fmethod=20to=20correctly=20build=20tem?= =?UTF-8?q?plates=20from=20class=20methods=20The=20configuration=20file=20?= =?UTF-8?q?now=20includes=20two=20new=20vector=20stores,=20DocArrayHnswSea?= =?UTF-8?q?rch=20and=20DocArrayInMemorySearch.=20The=20Node.build()=20meth?= =?UTF-8?q?od=20now=20correctly=20handles=20nested=20lists.=20A=20new=20Ve?= =?UTF-8?q?ctorStoreFrontendNode=20has=20been=20added=20to=20handle=20vect?= =?UTF-8?q?or=20store=20templates.=20The=20build=5Ftemplate=5Ffrom=5Fmetho?= =?UTF-8?q?d=20function=20has=20been=20added=20to=20correctly=20build=20te?= =?UTF-8?q?mplates=20from=20class=20methods.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #335 --- src/backend/langflow/config.yaml | 2 + src/backend/langflow/graph/base.py | 8 ++- .../langflow/interface/vector_store/base.py | 47 ++++++++------ src/backend/langflow/template/nodes.py | 29 +++++++++ src/backend/langflow/utils/util.py | 64 +++++++++++++++++++ 5 files changed, 130 insertions(+), 20 deletions(-) diff --git a/src/backend/langflow/config.yaml b/src/backend/langflow/config.yaml index 84fd12fcd..36668c737 100644 --- a/src/backend/langflow/config.yaml +++ b/src/backend/langflow/config.yaml @@ -83,6 +83,8 @@ embeddings: vectorstores: - Chroma + - DocArrayHnswSearch + - DocArrayInMemorySearch documentloaders: - AirbyteJSONLoader diff --git a/src/backend/langflow/graph/base.py b/src/backend/langflow/graph/base.py index 976a9c1cf..187d2983e 100644 --- a/src/backend/langflow/graph/base.py +++ b/src/backend/langflow/graph/base.py @@ -180,7 +180,13 @@ class Node: elif isinstance(value, list) and all( isinstance(node, Node) for node in value ): - self.params[key] = [node.build() for node in value] # type: ignore + self.params[key] = [] + for node in value: + built = node.build() + if isinstance(built, list): + self.params[key].extend(built) + else: + self.params[key].append(built) # Get the class from LANGCHAIN_TYPES_DICT # and instantiate it with the params diff --git a/src/backend/langflow/interface/vector_store/base.py b/src/backend/langflow/interface/vector_store/base.py index 7fca2ba0c..425fa9559 100644 --- a/src/backend/langflow/interface/vector_store/base.py +++ b/src/backend/langflow/interface/vector_store/base.py @@ -1,15 +1,20 @@ -from typing import Dict, List, Optional +from typing import Dict, List, Optional, Type from langflow.interface.base import LangChainTypeCreator from langflow.interface.custom_lists import vectorstores_type_to_cls_dict from langflow.settings import settings +from langflow.template.nodes import VectorStoreFrontendNode from langflow.utils.logger import logger -from langflow.utils.util import build_template_from_class +from langflow.utils.util import build_template_from_class, build_template_from_method class VectorstoreCreator(LangChainTypeCreator): type_name: str = "vectorstores" + @property + def frontend_node_class(self) -> Type[VectorStoreFrontendNode]: + return VectorStoreFrontendNode + @property def type_to_loader_dict(self) -> Dict: return vectorstores_type_to_cls_dict @@ -17,25 +22,29 @@ class VectorstoreCreator(LangChainTypeCreator): def get_signature(self, name: str) -> Optional[Dict]: """Get the signature of an embedding.""" try: - signature = build_template_from_class(name, vectorstores_type_to_cls_dict) + signature = build_template_from_method( + name, + type_to_cls_dict=vectorstores_type_to_cls_dict, + method_name="from_texts", + ) # TODO: Use FrontendendNode class to build the signature - signature["template"] = { - "documents": { - "type": "TextSplitter", - "required": True, - "show": True, - "name": "documents", - "display_name": "Text Splitter", - }, - "embedding": { - "type": "Embeddings", - "required": True, - "show": True, - "name": "embedding", - "display_name": "Embedding", - }, - } + # signature["template"] = { + # "documents": { + # "type": "TextSplitter", + # "required": True, + # "show": True, + # "name": "documents", + # "display_name": "Text Splitter", + # }, + # "embedding": { + # "type": "Embeddings", + # "required": True, + # "show": True, + # "name": "embedding", + # "display_name": "Embedding", + # }, + # } return signature except ValueError as exc: diff --git a/src/backend/langflow/template/nodes.py b/src/backend/langflow/template/nodes.py index 9fad19508..f01a99144 100644 --- a/src/backend/langflow/template/nodes.py +++ b/src/backend/langflow/template/nodes.py @@ -628,3 +628,32 @@ class EmbeddingFrontendNode(FrontendNode): FrontendNode.format_field(field, name) if field.name == "headers": field.show = False + + +class VectorStoreFrontendNode(FrontendNode): + @staticmethod + def format_field(field: TemplateField, name: Optional[str] = None) -> None: + FrontendNode.format_field(field, name) + if field.name == "texts": + field.name = "documents" + field.field_type = "TextSplitter" + field.display_name = "Text Splitter" + field.required = True + field.show = True + field.advanced = False + + if "embedding" in field.name: + # for backwards compatibility + field.name = "embedding" + field.required = True + field.show = True + field.advanced = False + field.display_name = "Embedding" + field.field_type = "Embeddings" + + elif field.name == "n_dim": + field.show = True + field.advanced = True + elif field.name == "work_dir": + field.show = True + field.advanced = False diff --git a/src/backend/langflow/utils/util.py b/src/backend/langflow/utils/util.py index e959b0103..9f2e53bc5 100644 --- a/src/backend/langflow/utils/util.py +++ b/src/backend/langflow/utils/util.py @@ -160,6 +160,70 @@ def build_template_from_class( } +def build_template_from_method( + class_name: str, + method_name: str, + type_to_cls_dict: Dict, + add_function: bool = False, +): + classes = [item.__name__ for item in type_to_cls_dict.values()] + + # Raise error if class_name is not in classes + if class_name not in classes: + raise ValueError(f"{class_name} not found.") + + for _type, v in type_to_cls_dict.items(): + if v.__name__ == class_name: + _class = v + + # Check if the method exists in this class + if not hasattr(_class, method_name): + raise ValueError( + f"Method {method_name} not found in class {class_name}" + ) + + # Get the method + method = getattr(_class, method_name) + + # Get the docstring + docs = parse(method.__doc__) + + # Get the signature of the method + sig = inspect.signature(method) + + # Get the parameters of the method + params = sig.parameters + + # Initialize the variables dictionary with method parameters + variables = { + "_type": _type, + **{ + name: { + "default": param.default + if param.default != param.empty + else None, + "type": param.annotation + if param.annotation != param.empty + else None, + "required": param.default == param.empty, + } + for name, param in params.items() + }, + } + + base_classes = get_base_classes(_class) + + # Adding function to base classes to allow the output to be a function + if add_function: + base_classes.append("function") + + return { + "template": format_dict(variables, class_name), + "description": docs.short_description or "", + "base_classes": base_classes, + } + + def get_base_classes(cls): """Get the base classes of a class. These are used to determine the output of the nodes. From f7cf6a378f86a2ffed0aa06731b4a94766d6b5d3 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Tue, 23 May 2023 19:28:27 -0300 Subject: [PATCH 03/44] create min font size with truncate for buttonBox component --- .../modals/importModal/buttonBox/index.tsx | 27 +++++++++++-------- src/frontend/src/modals/importModal/index.tsx | 2 +- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/frontend/src/modals/importModal/buttonBox/index.tsx b/src/frontend/src/modals/importModal/buttonBox/index.tsx index 2f120d30b..d0e22611e 100644 --- a/src/frontend/src/modals/importModal/buttonBox/index.tsx +++ b/src/frontend/src/modals/importModal/buttonBox/index.tsx @@ -24,7 +24,7 @@ export default function ButtonBox({ }) { let bigCircle: string; let smallCircle: string; - let titleFontSize: number; + let minTitleFontSize: number; let descriptionFontSize: string; let padding: string; let marginTop: string; @@ -32,11 +32,12 @@ export default function ButtonBox({ let width: string; let textHeight: number; let textWidth: number; + const [truncate, setTruncate] = useState(false); switch (size) { case "small": bigCircle = "h-12 w-12"; smallCircle = "h-8 w-8"; - titleFontSize = 14; + minTitleFontSize =9; descriptionFontSize = "text-xs"; padding = "p-2 py-3"; marginTop = "mt-2"; @@ -48,7 +49,7 @@ export default function ButtonBox({ case "medium": bigCircle = "h-16 w-16"; smallCircle = "h-12 w-12"; - titleFontSize = 16; + minTitleFontSize = 11; descriptionFontSize = "text-sm"; padding = "p-4 py-5"; marginTop = "mt-3"; @@ -60,7 +61,7 @@ export default function ButtonBox({ case "big": bigCircle = "h-20 w-20"; smallCircle = "h-16 w-16"; - titleFontSize = 18; + minTitleFontSize = 12; descriptionFontSize = "text-sm"; padding = "p-8 py-10"; marginTop = "mt-6"; @@ -70,7 +71,7 @@ export default function ButtonBox({ default: bigCircle = "h-20 w-20"; smallCircle = "h-16 w-16"; - titleFontSize = 18; + minTitleFontSize = 12; descriptionFontSize = "text-sm"; padding = "p-8 py-10"; marginTop = "mt-6"; @@ -95,7 +96,7 @@ export default function ButtonBox({ let textElementHeight = textElement.scrollHeight; let textElementWidth = textElement.scrollWidth; - if (textElementHeight > parentDivHeight || textElementWidth > parentDivWidth) { + if (textElementHeight > parentDivHeight || textElementWidth > parentDivWidth && fontSize > minTitleFontSize) { let newFontSize = fontSize; while (textElementHeight > parentDivHeight || textElementWidth > parentDivWidth) { @@ -104,8 +105,13 @@ export default function ButtonBox({ textElementHeight = textElement.scrollHeight; textElementWidth = textElement.scrollWidth; } - - setFontSize(newFontSize); + if(newFontSize <= minTitleFontSize){ + setTruncate(true); + setFontSize(minTitleFontSize); + } + else{ + setFontSize(newFontSize); + } } }, [title, size, fontSize]); @@ -133,10 +139,9 @@ export default function ButtonBox({
+ )} > {title}
diff --git a/src/frontend/src/modals/importModal/index.tsx b/src/frontend/src/modals/importModal/index.tsx index ba7136bd1..2d983a685 100644 --- a/src/frontend/src/modals/importModal/index.tsx +++ b/src/frontend/src/modals/importModal/index.tsx @@ -180,7 +180,7 @@ export default function ImportModal() {
{" "} Date: Tue, 23 May 2023 21:00:12 -0300 Subject: [PATCH 04/44] Fixed Undo and Redo on different pages --- .../src/CustomNodes/GenericNode/index.tsx | 1 - src/frontend/src/contexts/tabsContext.tsx | 5 -- src/frontend/src/modals/chatModal/index.tsx | 1 - .../src/modals/codeAreaModal/index.tsx | 2 - src/frontend/src/modals/promptModal/index.tsx | 1 - .../src/pages/FlowPage/hooks/useUndoRedo.ts | 69 ++++++++++++++----- src/frontend/src/pages/FlowPage/index.tsx | 1 - 7 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index 059fdfb81..96890d76e 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -58,7 +58,6 @@ export default function GenericNode({ if (response.status === 200) { let jsonResponse = await response.json(); let jsonResponseParsed = await JSON.parse(jsonResponse); - console.log(jsonResponseParsed); setValidationStatus(jsonResponseParsed); } } catch (error) { diff --git a/src/frontend/src/contexts/tabsContext.tsx b/src/frontend/src/contexts/tabsContext.tsx index 8f0832c3a..f07c500f5 100644 --- a/src/frontend/src/contexts/tabsContext.tsx +++ b/src/frontend/src/contexts/tabsContext.tsx @@ -58,7 +58,6 @@ export function TabsProvider({ children }: { children: ReactNode }) { } useEffect(() => { //save tabs locally - // console.log(id) save(); }, [flows, id, tabIndex, newNodeId]); @@ -173,8 +172,6 @@ export function TabsProvider({ children }: { children: ReactNode }) { */ function paste(selectionInstance, position){ - console.log(position); - console.log(selectionInstance) let minimumX = Infinity; let minimumY = Infinity; let idsMap = {}; @@ -214,7 +211,6 @@ export function TabsProvider({ children }: { children: ReactNode }) { nodes = nodes .map((e) => ({ ...e, selected: false })) .concat({ ...newNode, selected: false }) - console.log(nodes); }); reactFlowInstance.setNodes(nodes); @@ -250,7 +246,6 @@ export function TabsProvider({ children }: { children: ReactNode }) { }, edges.map((e) => ({ ...e, selected: false })) ); - console.log(edges); }); reactFlowInstance.setEdges(edges); }; diff --git a/src/frontend/src/modals/chatModal/index.tsx b/src/frontend/src/modals/chatModal/index.tsx index d4f3849ee..76aa801f3 100644 --- a/src/frontend/src/modals/chatModal/index.tsx +++ b/src/frontend/src/modals/chatModal/index.tsx @@ -183,7 +183,6 @@ export default function ChatModal({ newWs.onopen = () => { console.log("WebSocket connection established!"); }; - console.log(flow.id); newWs.onmessage = (event) => { const data = JSON.parse(event.data); console.log("Received data:", data); diff --git a/src/frontend/src/modals/codeAreaModal/index.tsx b/src/frontend/src/modals/codeAreaModal/index.tsx index 515e9089e..dc3e5ab1f 100644 --- a/src/frontend/src/modals/codeAreaModal/index.tsx +++ b/src/frontend/src/modals/codeAreaModal/index.tsx @@ -129,9 +129,7 @@ export default function CodeAreaModal({ onClick={() => { checkCode(code) .then((apiReturn) => { - console.log(apiReturn); if (apiReturn.data) { - console.log(apiReturn.data); let importsErrors = apiReturn.data.imports.errors; let funcErrors = apiReturn.data.function.errors; if ( diff --git a/src/frontend/src/modals/promptModal/index.tsx b/src/frontend/src/modals/promptModal/index.tsx index 6ba410f18..5dbeb2264 100644 --- a/src/frontend/src/modals/promptModal/index.tsx +++ b/src/frontend/src/modals/promptModal/index.tsx @@ -109,7 +109,6 @@ export default function PromptAreaModal({ onClick={() => { checkPrompt(myValue) .then((apiReturn) => { - console.log(apiReturn); if (apiReturn.data) { let inputVariables = apiReturn.data.input_variables; diff --git a/src/frontend/src/pages/FlowPage/hooks/useUndoRedo.ts b/src/frontend/src/pages/FlowPage/hooks/useUndoRedo.ts index 72dc6699c..85b135b73 100644 --- a/src/frontend/src/pages/FlowPage/hooks/useUndoRedo.ts +++ b/src/frontend/src/pages/FlowPage/hooks/useUndoRedo.ts @@ -1,5 +1,7 @@ -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useContext, useEffect, useState } from 'react'; import { Edge, Node, useReactFlow } from 'reactflow'; +import { TabsContext } from '../../../contexts/tabsContext'; +import { cloneDeep } from 'lodash'; type UseUndoRedoOptions = { maxHistorySize: number; @@ -30,47 +32,80 @@ export const useUndoRedo: UseUndoRedo = ({ enableShortcuts = defaultOptions.enableShortcuts, } = defaultOptions) => { // the past and future arrays store the states that we can jump to - const [past, setPast] = useState([]); - const [future, setFuture] = useState([]); + const { tabIndex, flows } = useContext(TabsContext); + + const [past, setPast] = useState(flows.map(()=>[])); + const [future, setFuture] = useState(flows.map(()=>[])); + + useEffect(() => { + // whenever the flows variable changes, we need to add one array to the past and future states + setPast((old) => flows.map((f, i)=>old[i] ? old[i] : [])); + setFuture((old) => flows.map((f, i)=>old[i] ? old[i] : [])); + }, [flows]); + const { setNodes, setEdges, getNodes, getEdges } = useReactFlow(); const takeSnapshot = useCallback(() => { // push the current graph to the past state - setPast((past) => [ - ...past.slice(past.length - maxHistorySize + 1, past.length), - { nodes: getNodes(), edges: getEdges() }, - ]); + setPast((old) => { + let newPast = cloneDeep(old); + newPast[tabIndex] = old[tabIndex].slice(old[tabIndex].length - maxHistorySize + 1, old[tabIndex].length); + newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() }); + return newPast; + }); // whenever we take a new snapshot, the redo operations need to be cleared to avoid state mismatches - setFuture([]); - }, [getNodes, getEdges, maxHistorySize]); + setFuture((old) => { + let newFuture = cloneDeep(old); + newFuture[tabIndex] = []; + return newFuture + }); + }, [getNodes, getEdges, past, future, tabIndex, setPast, setFuture, maxHistorySize]); const undo = useCallback(() => { // get the last state that we want to go back to - const pastState = past[past.length - 1]; + const pastState = past[tabIndex][past[tabIndex].length - 1]; if (pastState) { // first we remove the state from the history - setPast((past) => past.slice(0, past.length - 1)); + setPast((old) => { + let newPast = cloneDeep(old); + newPast[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1); + return newPast + }); // we store the current graph for the redo operation - setFuture((future) => [...future, { nodes: getNodes(), edges: getEdges() }]); + setFuture((old) => { + let newFuture = cloneDeep(old); + newFuture[tabIndex] = old[tabIndex] + newFuture[tabIndex].push({ nodes: getNodes(), edges: getEdges() }); + return newFuture + }); // now we can set the graph to the past state setNodes(pastState.nodes); setEdges(pastState.edges); } - }, [setNodes, setEdges, getNodes, getEdges, past]); + }, [setNodes, setEdges, getNodes, getEdges, future, past, setFuture, setPast, tabIndex]); const redo = useCallback(() => { - const futureState = future[future.length - 1]; + const futureState = future[tabIndex][future[tabIndex].length - 1]; if (futureState) { - setFuture((future) => future.slice(0, future.length - 1)); - setPast((past) => [...past, { nodes: getNodes(), edges: getEdges() }]); + setFuture((old) => { + let newFuture = cloneDeep(old); + newFuture[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1); + return newFuture + }); + setPast((old) => { + let newPast = cloneDeep(old); + newPast[tabIndex] = old[tabIndex]; + newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() }); + return newPast + }); setNodes(futureState.nodes); setEdges(futureState.edges); } - }, [setNodes, setEdges, getNodes, getEdges, future]); + }, [future, past, setFuture, setPast, setNodes, setEdges, getNodes, getEdges, future, tabIndex]); useEffect(() => { // this effect is used to attach the global event handlers diff --git a/src/frontend/src/pages/FlowPage/index.tsx b/src/frontend/src/pages/FlowPage/index.tsx index 57e77159e..e7978cc16 100644 --- a/src/frontend/src/pages/FlowPage/index.tsx +++ b/src/frontend/src/pages/FlowPage/index.tsx @@ -56,7 +56,6 @@ export default function FlowPage({ flow }: { flow: FlowType }) { // this effect is used to attach the global event handlers const onKeyDown = (event: KeyboardEvent) => { - console.log("keydownou", lastCopiedSelection, position); if ( (event.ctrlKey || event.metaKey) && event.key === "c" && From a66adff004b34b1bf852ebb57405297384925468 Mon Sep 17 00:00:00 2001 From: Gabriel Almeida Date: Wed, 24 May 2023 09:27:00 -0300 Subject: [PATCH 05/44] =?UTF-8?q?=F0=9F=94=A5=20refactor(custom=5Flists.py?= =?UTF-8?q?):=20remove=20unused=20vectorstores=5Ftype=5Fto=5Fcls=5Fdict=20?= =?UTF-8?q?variable=20=F0=9F=94=A8=20refactor(vector=5Fstore/base.py):=20r?= =?UTF-8?q?efactor=20VectorstoreCreator=20to=20use=20import=5Fclass=20from?= =?UTF-8?q?=20langflow.interface.importing.utils=20The=20`vectorstores=5Ft?= =?UTF-8?q?ype=5Fto=5Fcls=5Fdict`=20variable=20was=20not=20being=20used,?= =?UTF-8?q?=20so=20it=20was=20removed.=20The=20`VectorstoreCreator`=20clas?= =?UTF-8?q?s=20was=20refactored=20to=20use=20the=20`import=5Fclass`=20func?= =?UTF-8?q?tion=20from=20`langflow.interface.importing.utils`=20instead=20?= =?UTF-8?q?of=20importing=20it=20directly.=20This=20improves=20the=20code'?= =?UTF-8?q?s=20readability=20and=20maintainability.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../langflow/interface/custom_lists.py | 5 --- .../langflow/interface/vector_store/base.py | 41 +++++++------------ 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/backend/langflow/interface/custom_lists.py b/src/backend/langflow/interface/custom_lists.py index f07b03f04..af453139b 100644 --- a/src/backend/langflow/interface/custom_lists.py +++ b/src/backend/langflow/interface/custom_lists.py @@ -60,11 +60,6 @@ embedding_type_to_cls_dict: dict[str, Any] = { for embedding_name in embeddings.__all__ } -## Vector Stores -vectorstores_type_to_cls_dict: dict[str, Any] = { - vectorstore_name: import_class(f"langchain.vectorstores.{vectorstore_name}") - for vectorstore_name in vectorstores.__all__ -} ## Document Loaders documentloaders_type_to_cls_dict: dict[str, Any] = { diff --git a/src/backend/langflow/interface/vector_store/base.py b/src/backend/langflow/interface/vector_store/base.py index 425fa9559..d30563d7b 100644 --- a/src/backend/langflow/interface/vector_store/base.py +++ b/src/backend/langflow/interface/vector_store/base.py @@ -1,11 +1,13 @@ -from typing import Dict, List, Optional, Type +from typing import Any, Dict, List, Optional, Type + +from langchain import vectorstores from langflow.interface.base import LangChainTypeCreator -from langflow.interface.custom_lists import vectorstores_type_to_cls_dict +from langflow.interface.importing.utils import import_class from langflow.settings import settings from langflow.template.nodes import VectorStoreFrontendNode from langflow.utils.logger import logger -from langflow.utils.util import build_template_from_class, build_template_from_method +from langflow.utils.util import build_template_from_method class VectorstoreCreator(LangChainTypeCreator): @@ -17,36 +19,23 @@ class VectorstoreCreator(LangChainTypeCreator): @property def type_to_loader_dict(self) -> Dict: - return vectorstores_type_to_cls_dict + if self.type_dict is None: + self.type_dict: dict[str, Any] = { + vectorstore_name: import_class( + f"langchain.vectorstores.{vectorstore_name}" + ) + for vectorstore_name in vectorstores.__all__ + } + return self.type_dict def get_signature(self, name: str) -> Optional[Dict]: """Get the signature of an embedding.""" try: - signature = build_template_from_method( + return build_template_from_method( name, - type_to_cls_dict=vectorstores_type_to_cls_dict, + type_to_cls_dict=self.type_to_loader_dict, method_name="from_texts", ) - - # TODO: Use FrontendendNode class to build the signature - # signature["template"] = { - # "documents": { - # "type": "TextSplitter", - # "required": True, - # "show": True, - # "name": "documents", - # "display_name": "Text Splitter", - # }, - # "embedding": { - # "type": "Embeddings", - # "required": True, - # "show": True, - # "name": "embedding", - # "display_name": "Embedding", - # }, - # } - return signature - except ValueError as exc: raise ValueError(f"Vector Store {name} not found") from exc except AttributeError as exc: From 59951a3f68106f65629a07012830a5297b8d9e42 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Wed, 24 May 2023 16:26:51 -0300 Subject: [PATCH 06/44] add useEffect to prevent chat lock on fail of onClose method --- src/frontend/src/modals/chatModal/index.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/modals/chatModal/index.tsx b/src/frontend/src/modals/chatModal/index.tsx index 76aa801f3..20080ad7f 100644 --- a/src/frontend/src/modals/chatModal/index.tsx +++ b/src/frontend/src/modals/chatModal/index.tsx @@ -15,7 +15,7 @@ import { sendAllProps } from "../../types/api"; import { ChatMessageType, ChatType } from "../../types/chat"; import ChatInput from "./chatInput"; -import _ from "lodash"; +import _, { set } from "lodash"; export default function ChatModal({ flow, @@ -100,9 +100,9 @@ export default function ChatModal({ function handleOnClose(event: CloseEvent) { if (isOpen.current) { setErrorData({ title: event.reason }); - setLockChat(false); setTimeout(() => { connectWS(); + setLockChat(false); }, 1000); } } @@ -235,6 +235,13 @@ export default function ChatModal({ }; }, []); + useEffect(() => { + if((ws.current.readyState=== ws.current.CLOSED || ws.current.readyState=== ws.current.CLOSING)){ + connectWS(); + setLockChat(false); + } + },[lockChat]); + async function sendAll(data: sendAllProps) { try { if (ws) { @@ -339,6 +346,7 @@ export default function ChatModal({ function clearChat() { setChatHistory([]); ws.current.send(JSON.stringify({ clear_history: true })); + if(lockChat) setLockChat(false); } function setModalOpen(x: boolean) { From 2866e4ea78b1c470134547be3b8e3fd2ecca71de Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Wed, 24 May 2023 16:27:21 -0300 Subject: [PATCH 07/44] fix size of import on dev --- src/frontend/src/modals/importModal/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/modals/importModal/index.tsx b/src/frontend/src/modals/importModal/index.tsx index 2d983a685..ba7136bd1 100644 --- a/src/frontend/src/modals/importModal/index.tsx +++ b/src/frontend/src/modals/importModal/index.tsx @@ -180,7 +180,7 @@ export default function ImportModal() {
{" "} Date: Thu, 25 May 2023 09:03:28 -0300 Subject: [PATCH 08/44] =?UTF-8?q?=F0=9F=90=9B=20fix(=5F=5Fmain=5F=5F.py):?= =?UTF-8?q?=20pass=20dev=20flag=20to=20update=5Fsettings=20function=20?= =?UTF-8?q?=E2=9C=A8=20feat(=5F=5Fmain=5F=5F.py):=20add=20serve=5Fon=5Fjcl?= =?UTF-8?q?oud=20function=20to=20deploy=20Langflow=20server=20on=20Jina=20?= =?UTF-8?q?AI=20Cloud=20=F0=9F=90=9B=20fix(config.yaml):=20remove=20duplic?= =?UTF-8?q?ate=20entries=20and=20fix=20indentation=20The=20update=5Fsettin?= =?UTF-8?q?gs=20function=20now=20accepts=20a=20dev=20flag=20to=20enable=20?= =?UTF-8?q?running=20the=20app=20in=20development=20mode.=20The=20serve=5F?= =?UTF-8?q?on=5Fjcloud=20function=20has=20been=20added=20to=20deploy=20the?= =?UTF-8?q?=20Langflow=20server=20on=20Jina=20AI=20Cloud.=20The=20config.y?= =?UTF-8?q?aml=20file=20has=20been=20cleaned=20up=20by=20removing=20duplic?= =?UTF-8?q?ate=20entries=20and=20fixing=20indentation.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/__main__.py | 103 ++++++++++++------------ src/backend/langflow/config.yaml | 132 ++++++++++++++----------------- src/backend/langflow/settings.py | 4 +- 3 files changed, 113 insertions(+), 126 deletions(-) diff --git a/src/backend/langflow/__main__.py b/src/backend/langflow/__main__.py index 21833d551..af57ed381 100644 --- a/src/backend/langflow/__main__.py +++ b/src/backend/langflow/__main__.py @@ -18,59 +18,10 @@ def get_number_of_workers(workers=None): return workers -def update_settings(config: str): +def update_settings(config: str, dev: bool = False): """Update the settings from a config file.""" if config: - settings.update_from_yaml(config) - - -@app.command() -def serve( - host: str = typer.Option("127.0.0.1", help="Host to bind the server to."), - workers: int = typer.Option(1, help="Number of worker processes."), - timeout: int = typer.Option(60, help="Worker timeout in seconds."), - port: int = typer.Option(7860, help="Port to listen on."), - config: str = typer.Option("config.yaml", help="Path to the configuration file."), - log_level: str = typer.Option("info", help="Logging level."), - log_file: Path = typer.Option("logs/langflow.log", help="Path to the log file."), - jcloud: bool = typer.Option(False, help="Deploy on Jina AI Cloud"), -): - """ - Run the Langflow server. - """ - - if jcloud: - return serve_on_jcloud() - - configure(log_level=log_level, log_file=log_file) - update_settings(config) - app = create_app() - # get the directory of the current file - path = Path(__file__).parent - static_files_dir = path / "frontend" - app.mount( - "/", - StaticFiles(directory=static_files_dir, html=True), - name="static", - ) - options = { - "bind": f"{host}:{port}", - "workers": get_number_of_workers(workers), - "worker_class": "uvicorn.workers.UvicornWorker", - "timeout": timeout, - } - - if platform.system() in ["Darwin", "Windows"]: - # Run using uvicorn on MacOS and Windows - # Windows doesn't support gunicorn - # MacOS requires an env variable to be set to use gunicorn - import uvicorn - - uvicorn.run(app, host=host, port=port, log_level=log_level) - else: - from langflow.server import LangflowApplication - - LangflowApplication(app, options).run() + settings.update_from_yaml(config, dev=dev) def serve_on_jcloud(): @@ -119,6 +70,56 @@ def serve_on_jcloud(): click.secho("https://github.com/jina-ai/langchain-serve", fg="blue") +@app.command() +def serve( + host: str = typer.Option("127.0.0.1", help="Host to bind the server to."), + workers: int = typer.Option(1, help="Number of worker processes."), + timeout: int = typer.Option(60, help="Worker timeout in seconds."), + port: int = typer.Option(7860, help="Port to listen on."), + config: str = typer.Option("config.yaml", help="Path to the configuration file."), + log_level: str = typer.Option("info", help="Logging level."), + log_file: Path = typer.Option("logs/langflow.log", help="Path to the log file."), + jcloud: bool = typer.Option(False, help="Deploy on Jina AI Cloud"), + dev: bool = typer.Option(False, help="Run in development mode (may contain bugs)"), +): + """ + Run the Langflow server. + """ + + if jcloud: + return serve_on_jcloud() + + configure(log_level=log_level, log_file=log_file) + update_settings(config, dev=dev) + app = create_app() + # get the directory of the current file + path = Path(__file__).parent + static_files_dir = path / "frontend" + app.mount( + "/", + StaticFiles(directory=static_files_dir, html=True), + name="static", + ) + options = { + "bind": f"{host}:{port}", + "workers": get_number_of_workers(workers), + "worker_class": "uvicorn.workers.UvicornWorker", + "timeout": timeout, + } + + if platform.system() in ["Darwin", "Windows"]: + # Run using uvicorn on MacOS and Windows + # Windows doesn't support gunicorn + # MacOS requires an env variable to be set to use gunicorn + import uvicorn + + uvicorn.run(app, host=host, port=port, log_level=log_level) + else: + from langflow.server import LangflowApplication + + LangflowApplication(app, options).run() + + def main(): app() diff --git a/src/backend/langflow/config.yaml b/src/backend/langflow/config.yaml index 84fd12fcd..4ce6a28fc 100644 --- a/src/backend/langflow/config.yaml +++ b/src/backend/langflow/config.yaml @@ -1,3 +1,12 @@ +--- +agents: + - ZeroShotAgent + - JsonAgent + - CSVAgent + - initialize_agent + - VectorStoreAgent + - VectorStoreRouterAgent + - SQLAgent chains: - LLMChain - LLMMathChain @@ -7,32 +16,55 @@ chains: - MidJourneyPromptChain - TimeTravelGuideChain - SQLDatabaseChain - -agents: - - ZeroShotAgent - - JsonAgent - - CSVAgent - - initialize_agent - - VectorStoreAgent - - VectorStoreRouterAgent - - SQLAgent - -prompts: - - PromptTemplate - - FewShotPromptTemplate - - ZeroShotPrompt - # Wait more tests - # - ChatPromptTemplate - # - SystemMessagePromptTemplate - # - HumanMessagePromptTemplate - +documentloaders: + - AirbyteJSONLoader + - CoNLLULoader + - CSVLoader + - UnstructuredEmailLoader + - EverNoteLoader + - FacebookChatLoader + - GutenbergLoader + - BSHTMLLoader + - UnstructuredHTMLLoader + # - UnstructuredImageLoader # Issue with Python 3.11 (https://github.com/Unstructured-IO/unstructured-inference/issues/83) + - UnstructuredMarkdownLoader + - PyPDFLoader + - UnstructuredPowerPointLoader + - SRTLoader + - TelegramChatLoader + - TextLoader + - UnstructuredWordDocumentLoader + - WebBaseLoader + - AZLyricsLoader + - CollegeConfidentialLoader + - HNLoader + - IFixitLoader + - IMSDbLoader + - GitbookLoader + - ReadTheDocsLoader +embeddings: + - OpenAIEmbeddings llms: - OpenAI # - AzureOpenAI - ChatOpenAI - HuggingFaceHub - LlamaCpp - +memories: + - ConversationBufferMemory + - ConversationSummaryMemory + - ConversationKGMemory +prompts: + - PromptTemplate + - FewShotPromptTemplate + - ZeroShotPrompt +textsplitters: + - CharacterTextSplitter +toolkits: + - OpenAPIToolkit + - JsonToolkit + - VectorStoreInfo + - VectorStoreRouterToolkit tools: - Search - PAL-MATH @@ -63,57 +95,6 @@ tools: - RequestsDeleteTool - WikipediaQueryRun - WolframAlphaQueryRun - -wrappers: - - RequestsWrapper - -toolkits: - - OpenAPIToolkit - - JsonToolkit - - VectorStoreInfo - - VectorStoreRouterToolkit - -memories: - - ConversationBufferMemory - - ConversationSummaryMemory - - ConversationKGMemory - -embeddings: - - OpenAIEmbeddings - -vectorstores: - - Chroma - -documentloaders: - - AirbyteJSONLoader - - CoNLLULoader - - CSVLoader - - UnstructuredEmailLoader - - EverNoteLoader - - FacebookChatLoader - - GutenbergLoader - - BSHTMLLoader - - UnstructuredHTMLLoader - # - UnstructuredImageLoader # Issue with Python 3.11 (https://github.com/Unstructured-IO/unstructured-inference/issues/83) - - UnstructuredMarkdownLoader - - PyPDFLoader - - UnstructuredPowerPointLoader - - SRTLoader - - TelegramChatLoader - - TextLoader - - UnstructuredWordDocumentLoader - - WebBaseLoader - - AZLyricsLoader - - CollegeConfidentialLoader - - HNLoader - - IFixitLoader - - IMSDbLoader - - GitbookLoader - - ReadTheDocsLoader - -textsplitters: - - CharacterTextSplitter - utilities: - BingSearchAPIWrapper - GoogleSearchAPIWrapper @@ -125,5 +106,10 @@ utilities: - WolframAlphaAPIWrapper # - ZapierNLAWrapper - SQLDatabase - -dev: false +vectorstores: + - Chroma +wrappers: + - RequestsWrapper # Wait more tests + # - ChatPromptTemplate + # - SystemMessagePromptTemplate + # - HumanMessagePromptTemplate diff --git a/src/backend/langflow/settings.py b/src/backend/langflow/settings.py index 48aa5939d..5ef61ab7b 100644 --- a/src/backend/langflow/settings.py +++ b/src/backend/langflow/settings.py @@ -32,7 +32,7 @@ class Settings(BaseSettings): values[key] = [] return values - def update_from_yaml(self, file_path: str): + def update_from_yaml(self, file_path: str, dev: bool = False): new_settings = load_settings_from_yaml(file_path) self.chains = new_settings.chains or [] self.agents = new_settings.agents or [] @@ -44,7 +44,7 @@ class Settings(BaseSettings): self.toolkits = new_settings.toolkits or [] self.textsplitters = new_settings.textsplitters or [] self.utilities = new_settings.utilities or [] - self.dev = new_settings.dev or False + self.dev = dev def save_settings_to_yaml(settings: Settings, file_path: str): From 41b6a2c6fef842bd895e39f329f52811ae3d624d Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 25 May 2023 18:20:17 -0300 Subject: [PATCH 09/44] Fixed visual bug at Import Flows modal cards --- .../modals/importModal/buttonBox/index.tsx | 142 +++++++----------- src/frontend/src/modals/importModal/index.tsx | 2 +- src/frontend/tailwind.config.js | 8 + 3 files changed, 61 insertions(+), 91 deletions(-) diff --git a/src/frontend/src/modals/importModal/buttonBox/index.tsx b/src/frontend/src/modals/importModal/buttonBox/index.tsx index d0e22611e..b8e51e388 100644 --- a/src/frontend/src/modals/importModal/buttonBox/index.tsx +++ b/src/frontend/src/modals/importModal/buttonBox/index.tsx @@ -24,7 +24,7 @@ export default function ButtonBox({ }) { let bigCircle: string; let smallCircle: string; - let minTitleFontSize: number; + let titleFontSize: string; let descriptionFontSize: string; let padding: string; let marginTop: string; @@ -32,88 +32,48 @@ export default function ButtonBox({ let width: string; let textHeight: number; let textWidth: number; - const [truncate, setTruncate] = useState(false); switch (size) { - case "small": - bigCircle = "h-12 w-12"; - smallCircle = "h-8 w-8"; - minTitleFontSize =9; - descriptionFontSize = "text-xs"; - padding = "p-2 py-3"; - marginTop = "mt-2"; - height = "h-36"; - textHeight = 70; - textWidth = 40; - width = "w-32"; - break; - case "medium": - bigCircle = "h-16 w-16"; - smallCircle = "h-12 w-12"; - minTitleFontSize = 11; - descriptionFontSize = "text-sm"; - padding = "p-4 py-5"; - marginTop = "mt-3"; - textHeight = 112; - textWidth = 162; - height = "h-44"; - width = "w-36"; - break; - case "big": - bigCircle = "h-20 w-20"; - smallCircle = "h-16 w-16"; - minTitleFontSize = 12; - descriptionFontSize = "text-sm"; - padding = "p-8 py-10"; - marginTop = "mt-6"; - height = "h-56"; - width = "w-44"; - break; - default: - bigCircle = "h-20 w-20"; - smallCircle = "h-16 w-16"; - minTitleFontSize = 12; - descriptionFontSize = "text-sm"; - padding = "p-8 py-10"; - marginTop = "mt-6"; - height = "h-56"; - width = "w-44"; - break; - } - - const [fontSize, setFontSize] = useState(16); // Initial font size value - - const titleRef = useRef(null); - const parentDivRef = useRef(null); - - useEffect(() => { - const textElement = titleRef.current; - const parentDivElement = parentDivRef.current; - - if (!textElement || !parentDivElement) return; - - const parentDivHeight = parentDivElement.offsetHeight; - const parentDivWidth = parentDivElement.offsetWidth; - let textElementHeight = textElement.scrollHeight; - let textElementWidth = textElement.scrollWidth; - - if (textElementHeight > parentDivHeight || textElementWidth > parentDivWidth && fontSize > minTitleFontSize) { - let newFontSize = fontSize; - - while (textElementHeight > parentDivHeight || textElementWidth > parentDivWidth) { - newFontSize -= 1; - textElement.style.fontSize = `${newFontSize}px`; - textElementHeight = textElement.scrollHeight; - textElementWidth = textElement.scrollWidth; - } - if(newFontSize <= minTitleFontSize){ - setTruncate(true); - setFontSize(minTitleFontSize); - } - else{ - setFontSize(newFontSize); - } + case "small": + bigCircle = "h-12 w-12"; + smallCircle = "h-8 w-8"; + titleFontSize = "text-sm"; + descriptionFontSize = "text-xs"; + padding = "p-2 py-3"; + marginTop = "mt-2"; + height = "h-36"; + width = "w-32"; + break; + case "medium": + bigCircle = "h-16 w-16"; + smallCircle = "h-12 w-12"; + titleFontSize = "text-base"; + descriptionFontSize = "text-sm"; + padding = "p-4 py-5"; + marginTop = "mt-3"; + height = "h-44"; + width = "w-36"; + break; + case "big": + bigCircle = "h-20 w-20"; + smallCircle = "h-16 w-16"; + titleFontSize = "text-lg"; + descriptionFontSize = "text-sm"; + padding = "p-8 py-10"; + marginTop = "mt-6"; + height = "h-56"; + width = "w-44"; + break; + default: + bigCircle = "h-20 w-20"; + smallCircle = "h-16 w-16"; + titleFontSize = "text-lg"; + descriptionFontSize = "text-sm"; + padding = "p-8 py-10"; + marginTop = "mt-6"; + height = "h-56"; + width = "w-44"; + break; } - }, [title, size, fontSize]); return ( @@ -136,15 +96,17 @@ export default function ButtonBox({
{icon}
-
-
- {title} -
-
+
+

+ {title} +

+
); diff --git a/src/frontend/src/modals/importModal/index.tsx b/src/frontend/src/modals/importModal/index.tsx index ba7136bd1..2d3ef979a 100644 --- a/src/frontend/src/modals/importModal/index.tsx +++ b/src/frontend/src/modals/importModal/index.tsx @@ -177,7 +177,7 @@ export default function ImportModal() { !loadingExamples && examples.map((example, index) => { return ( -
+
{" "} Date: Thu, 25 May 2023 19:56:42 -0300 Subject: [PATCH 10/44] Fixed Copy Paste issues by disabling it when the user clicks at the node --- .../src/components/floatComponent/index.tsx | 8 +------ .../src/components/inputComponent/index.tsx | 8 +------ .../components/inputListComponent/index.tsx | 7 ------- .../src/components/intComponent/index.tsx | 8 +------ .../src/modals/chatModal/chatInput/index.tsx | 8 ------- .../src/modals/codeAreaModal/index.tsx | 7 ------- src/frontend/src/modals/exportModal/index.tsx | 21 ++----------------- .../components/tabComponent/index.tsx | 6 +----- src/frontend/src/pages/FlowPage/index.tsx | 7 ++++++- 9 files changed, 12 insertions(+), 68 deletions(-) diff --git a/src/frontend/src/components/floatComponent/index.tsx b/src/frontend/src/components/floatComponent/index.tsx index c09f3b9e0..2752db43c 100644 --- a/src/frontend/src/components/floatComponent/index.tsx +++ b/src/frontend/src/components/floatComponent/index.tsx @@ -14,7 +14,6 @@ export default function FloatComponent({ onChange(""); } }, [disabled, onChange]); - const {setDisableCopyPaste} = useContext(TabsContext) return (
{ - setDisableCopyPaste(false) - }} - onFocus={() => { - setDisableCopyPaste(true) - }} + />
); diff --git a/src/frontend/src/components/inputComponent/index.tsx b/src/frontend/src/components/inputComponent/index.tsx index b4f52902d..648458f2b 100644 --- a/src/frontend/src/components/inputComponent/index.tsx +++ b/src/frontend/src/components/inputComponent/index.tsx @@ -11,7 +11,6 @@ export default function InputComponent({ }: InputComponentType) { const [myValue, setMyValue] = useState(value ?? ""); const [pwdVisible, setPwdVisible] = useState(false); - const {setDisableCopyPaste} = useContext(TabsContext) useEffect(() => { if (disabled) { setMyValue(""); @@ -28,12 +27,7 @@ export default function InputComponent({ > { - setDisableCopyPaste(false) - }} - onFocus={() => { - setDisableCopyPaste(true) - }} + className={classNames( "block w-full pr-12 form-input dark:bg-gray-900 dark:border-gray-600 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm", disabled ? " bg-gray-200 dark:bg-gray-700" : "", diff --git a/src/frontend/src/components/inputListComponent/index.tsx b/src/frontend/src/components/inputListComponent/index.tsx index 57ddd7a4e..01f783ad6 100644 --- a/src/frontend/src/components/inputListComponent/index.tsx +++ b/src/frontend/src/components/inputListComponent/index.tsx @@ -17,7 +17,6 @@ export default function InputListComponent({ onChange([""]); } }, [disabled, onChange]); - const {setDisableCopyPaste} = useContext(TabsContext) return (
{ - setDisableCopyPaste(false) - }} - onFocus={() => { - setDisableCopyPaste(true) - }} /> {idx === inputList.length - 1 ? (
diff --git a/src/frontend/src/modals/chatModal/chatInput/index.tsx b/src/frontend/src/modals/chatModal/chatInput/index.tsx index 5cddb9c14..5a979499a 100644 --- a/src/frontend/src/modals/chatModal/chatInput/index.tsx +++ b/src/frontend/src/modals/chatModal/chatInput/index.tsx @@ -17,8 +17,6 @@ export default function ChatInput({ } }, [chatValue]); - const { setDisableCopyPaste } = useContext(TabsContext); - return (
-
+
+
+ + +
+ +
+
+
+
+
+
+ + Export as + +
+
+
+
+ + { + if (event.target.value != "") { + let newFlow = flows[tabIndex]; + newFlow.name = event.target.value; + setName(event.target.value); + updateFlow(newFlow); + } else { + setName(event.target.value); + } + }} + type="text" + name="name" + value={name ?? null} + placeholder="File name" + id="name" + className="focus:border focus:border-blue block w-full px-3 py-2 border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:border-gray-600 dark:focus:border-blue-500 dark:focus:ring-blue-500 text-gray-900 dark:text-gray-100" + /> +
+
+ + +
-
- -
-
- -
-
-
-
-
-
-
- - - ); +
+ +
+
+ +
+
+
+ + + + + + + ); } diff --git a/src/frontend/src/modals/importModal/buttonBox/index.tsx b/src/frontend/src/modals/importModal/buttonBox/index.tsx index b8e51e388..2c408a120 100644 --- a/src/frontend/src/modals/importModal/buttonBox/index.tsx +++ b/src/frontend/src/modals/importModal/buttonBox/index.tsx @@ -33,48 +33,47 @@ export default function ButtonBox({ let textHeight: number; let textWidth: number; switch (size) { - case "small": - bigCircle = "h-12 w-12"; - smallCircle = "h-8 w-8"; - titleFontSize = "text-sm"; - descriptionFontSize = "text-xs"; - padding = "p-2 py-3"; - marginTop = "mt-2"; - height = "h-36"; - width = "w-32"; - break; - case "medium": - bigCircle = "h-16 w-16"; - smallCircle = "h-12 w-12"; - titleFontSize = "text-base"; - descriptionFontSize = "text-sm"; - padding = "p-4 py-5"; - marginTop = "mt-3"; - height = "h-44"; - width = "w-36"; - break; - case "big": - bigCircle = "h-20 w-20"; - smallCircle = "h-16 w-16"; - titleFontSize = "text-lg"; - descriptionFontSize = "text-sm"; - padding = "p-8 py-10"; - marginTop = "mt-6"; - height = "h-56"; - width = "w-44"; - break; - default: - bigCircle = "h-20 w-20"; - smallCircle = "h-16 w-16"; - titleFontSize = "text-lg"; - descriptionFontSize = "text-sm"; - padding = "p-8 py-10"; - marginTop = "mt-6"; - height = "h-56"; - width = "w-44"; - break; - } - + case "small": + bigCircle = "h-12 w-12"; + smallCircle = "h-8 w-8"; + titleFontSize = "text-sm"; + descriptionFontSize = "text-xs"; + padding = "p-2 py-3"; + marginTop = "mt-2"; + height = "h-36"; + width = "w-32"; + break; + case "medium": + bigCircle = "h-16 w-16"; + smallCircle = "h-12 w-12"; + titleFontSize = "text-base"; + descriptionFontSize = "text-sm"; + padding = "p-4 py-5"; + marginTop = "mt-3"; + height = "h-44"; + width = "w-36"; + break; + case "big": + bigCircle = "h-20 w-20"; + smallCircle = "h-16 w-16"; + titleFontSize = "text-lg"; + descriptionFontSize = "text-sm"; + padding = "p-8 py-10"; + marginTop = "mt-6"; + height = "h-56"; + width = "w-44"; + break; + default: + bigCircle = "h-20 w-20"; + smallCircle = "h-16 w-16"; + titleFontSize = "text-lg"; + descriptionFontSize = "text-sm"; + padding = "p-8 py-10"; + marginTop = "mt-6"; + height = "h-56"; + width = "w-44"; + break; + } return ( ); diff --git a/src/frontend/src/modals/importModal/index.tsx b/src/frontend/src/modals/importModal/index.tsx index 2d3ef979a..aa25e058b 100644 --- a/src/frontend/src/modals/importModal/index.tsx +++ b/src/frontend/src/modals/importModal/index.tsx @@ -1,11 +1,11 @@ import { Dialog, Transition } from "@headlessui/react"; import { - XMarkIcon, - ArrowDownTrayIcon, - DocumentDuplicateIcon, - ComputerDesktopIcon, - ArrowUpTrayIcon, - ArrowLeftIcon, + XMarkIcon, + ArrowDownTrayIcon, + DocumentDuplicateIcon, + ComputerDesktopIcon, + ArrowUpTrayIcon, + ArrowLeftIcon, } from "@heroicons/react/24/outline"; import { Fragment, useContext, useRef, useState } from "react"; import { PopUpContext } from "../../contexts/popUpContext"; @@ -19,214 +19,214 @@ import { FlowType } from "../../types/flow"; import { classNames, snakeToSpaces, toNormalCase } from "../../utils"; export default function ImportModal() { - const [open, setOpen] = useState(true); - const { setErrorData } = useContext(alertContext); - const { closePopUp } = useContext(PopUpContext); - const ref = useRef(); - const [showExamples, setShowExamples] = useState(false); - const [loadingExamples, setLoadingExamples] = useState(false); - const [examples, setExamples] = useState([]); - const { uploadFlow, addFlow } = useContext(TabsContext); - function setModalOpen(x: boolean) { - setOpen(x); - if (x === false) { - setTimeout(() => { - closePopUp(); - }, 300); - } - } + const [open, setOpen] = useState(true); + const { setErrorData } = useContext(alertContext); + const { closePopUp } = useContext(PopUpContext); + const ref = useRef(); + const [showExamples, setShowExamples] = useState(false); + const [loadingExamples, setLoadingExamples] = useState(false); + const [examples, setExamples] = useState([]); + const { uploadFlow, addFlow } = useContext(TabsContext); + function setModalOpen(x: boolean) { + setOpen(x); + if (x === false) { + setTimeout(() => { + closePopUp(); + }, 300); + } + } - function handleExamples() { - setLoadingExamples(true); - getExamples() - .then((result) => { - setLoadingExamples(false); - setExamples(result); - }) - .catch((error) => - setErrorData({ - title: "there was an error loading examples, please try again", - list: [error.message], - }) - ); - } + function handleExamples() { + setLoadingExamples(true); + getExamples() + .then((result) => { + setLoadingExamples(false); + setExamples(result); + }) + .catch((error) => + setErrorData({ + title: "there was an error loading examples, please try again", + list: [error.message], + }) + ); + } - return ( - - - -
- + return ( + + + +
+ -
-
- - -
- -
- {showExamples && ( - <> -
- -
- - )} -
-
-
-
-
- - {showExamples ? "Select an example" : "Import from"} - -
-
-
- {!showExamples && ( -
- - } - onClick={() => { - setShowExamples(true); - handleExamples(); - }} - textColor="text-emerald-500 dark:text-emerald-500/75" - title="Examples" - > - - } - onClick={() => { - uploadFlow(); - setModalOpen(false); - }} - textColor="text-blue-500 dark:text-blue-500/75" - title="Local File" - > -
- )} - {showExamples && loadingExamples && ( -
- -
- )} - {showExamples && - !loadingExamples && - examples.map((example, index) => { - return ( -
- {" "} - - } - onClick={() => { - addFlow(example); - setModalOpen(false); - }} - textColor="text-emerald-500 dark:text-emerald-500/75" - title={example.name} - > -
- ); - })} -
- -
-
-
-
-
-
-
- ); +
+
+ + +
+ +
+ {showExamples && ( + <> +
+ +
+ + )} +
+
+
+
+
+ + {showExamples ? "Select an example" : "Import from"} + +
+
+
+ {!showExamples && ( +
+ + } + onClick={() => { + setShowExamples(true); + handleExamples(); + }} + textColor="text-emerald-500 dark:text-emerald-500/75" + title="Examples" + > + + } + onClick={() => { + uploadFlow(); + setModalOpen(false); + }} + textColor="text-blue-500 dark:text-blue-500/75" + title="Local File" + > +
+ )} + {showExamples && loadingExamples && ( +
+ +
+ )} + {showExamples && + !loadingExamples && + examples.map((example, index) => { + return ( +
+ {" "} + + } + onClick={() => { + addFlow(example); + setModalOpen(false); + }} + textColor="text-emerald-500 dark:text-emerald-500/75" + title={example.name} + > +
+ ); + })} +
+ +
+
+
+
+
+
+
+ ); } diff --git a/src/frontend/src/modals/promptModal/index.tsx b/src/frontend/src/modals/promptModal/index.tsx index 5dbeb2264..508042a1c 100644 --- a/src/frontend/src/modals/promptModal/index.tsx +++ b/src/frontend/src/modals/promptModal/index.tsx @@ -6,148 +6,148 @@ import { darkContext } from "../../contexts/darkContext"; import { checkPrompt } from "../../controllers/API"; import { alertContext } from "../../contexts/alertContext"; export default function PromptAreaModal({ - value, - setValue, + value, + setValue, }: { - setValue: (value: string) => void; - value: string; + setValue: (value: string) => void; + value: string; }) { - const [open, setOpen] = useState(true); - const [myValue, setMyValue] = useState(value); - const { dark } = useContext(darkContext); - const { setErrorData, setSuccessData } = useContext(alertContext); - const { closePopUp } = useContext(PopUpContext); - const ref = useRef(); - function setModalOpen(x: boolean) { - setOpen(x); - if (x === false) { - setTimeout(() => { - closePopUp(); - }, 300); - } - } - return ( - - - -
- + const [open, setOpen] = useState(true); + const [myValue, setMyValue] = useState(value); + const { dark } = useContext(darkContext); + const { setErrorData, setSuccessData } = useContext(alertContext); + const { closePopUp } = useContext(PopUpContext); + const ref = useRef(); + function setModalOpen(x: boolean) { + setOpen(x); + if (x === false) { + setTimeout(() => { + closePopUp(); + }, 300); + } + } + return ( + + + +
+ -
-
- - -
- -
-
-
-
-
-
- - Edit Prompt - -
-
-
-
-
-