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

This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-09-19 16:07:39 -03:00
commit f081a0079c
16 changed files with 274 additions and 179 deletions

View file

@ -55,7 +55,7 @@ def display_results(results):
def update_settings( def update_settings(
config: str, config: str,
cache: str, cache: Optional[str] = None,
dev: bool = False, dev: bool = False,
remove_api_keys: bool = False, remove_api_keys: bool = False,
components_path: Optional[Path] = None, components_path: Optional[Path] = None,
@ -153,10 +153,10 @@ def run(
log_file: Path = typer.Option( log_file: Path = typer.Option(
"logs/langflow.log", help="Path to the log file.", envvar="LANGFLOW_LOG_FILE" "logs/langflow.log", help="Path to the log file.", envvar="LANGFLOW_LOG_FILE"
), ),
cache: str = typer.Option( cache: Optional[str] = typer.Option(
envvar="LANGFLOW_LANGCHAIN_CACHE", envvar="LANGFLOW_LANGCHAIN_CACHE",
help="Type of cache to use. (InMemoryCache, SQLiteCache)", help="Type of cache to use. (InMemoryCache, SQLiteCache)",
default="SQLiteCache", default=None,
), ),
jcloud: bool = typer.Option(False, help="Deploy on Jina AI Cloud"), jcloud: bool = typer.Option(False, help="Deploy on Jina AI Cloud"),
dev: bool = typer.Option(False, help="Run in development mode (may contain bugs)"), dev: bool = typer.Option(False, help="Run in development mode (may contain bugs)"),

View file

@ -58,6 +58,16 @@ def post_validate_prompt(prompt_request: ValidatePromptRequest):
def get_old_custom_fields(prompt_request): def get_old_custom_fields(prompt_request):
try: try:
if (
len(prompt_request.frontend_node.custom_fields) == 1
and prompt_request.name == ""
):
# If there is only one custom field and the name is empty string
# then we are dealing with the first prompt request after the node was created
prompt_request.name = list(
prompt_request.frontend_node.custom_fields.keys()
)[0]
old_custom_fields = prompt_request.frontend_node.custom_fields[ old_custom_fields = prompt_request.frontend_node.custom_fields[
prompt_request.name prompt_request.name
].copy() ].copy()

View file

@ -290,31 +290,42 @@ def add_base_classes(frontend_node, return_types: List[str]):
def build_langchain_template_custom_component(custom_component: CustomComponent): def build_langchain_template_custom_component(custom_component: CustomComponent):
"""Build a custom component template for the langchain""" """Build a custom component template for the langchain"""
logger.debug("Building custom component template") try:
frontend_node = build_frontend_node(custom_component) logger.debug("Building custom component template")
frontend_node = build_frontend_node(custom_component)
if frontend_node is None: if frontend_node is None:
return None return None
logger.debug("Built base frontend node") logger.debug("Built base frontend node")
template_config = custom_component.build_template_config template_config = custom_component.build_template_config
update_attributes(frontend_node, template_config) update_attributes(frontend_node, template_config)
logger.debug("Updated attributes") logger.debug("Updated attributes")
field_config = build_field_config(custom_component) field_config = build_field_config(custom_component)
logger.debug("Built field config") logger.debug("Built field config")
add_extra_fields( add_extra_fields(
frontend_node, field_config, custom_component.get_function_entrypoint_args frontend_node, field_config, custom_component.get_function_entrypoint_args
) )
logger.debug("Added extra fields") logger.debug("Added extra fields")
frontend_node = add_code_field( frontend_node = add_code_field(
frontend_node, custom_component.code, field_config.get("code", {}) frontend_node, custom_component.code, field_config.get("code", {})
) )
logger.debug("Added code field") logger.debug("Added code field")
add_base_classes( add_base_classes(
frontend_node, custom_component.get_function_entrypoint_return_type frontend_node, custom_component.get_function_entrypoint_return_type
) )
logger.debug("Added base classes") logger.debug("Added base classes")
return frontend_node return frontend_node
except Exception as exc:
raise HTTPException(
status_code=400,
detail={
"error": (
"Invalid type convertion. Please check your code and try again."
),
"traceback": traceback.format_exc(),
},
) from exc
def load_files_from_path(path: str): def load_files_from_path(path: str):

View file

@ -77,9 +77,16 @@ def set_langchain_cache(settings):
import langchain import langchain
from langflow.interface.importing.utils import import_class from langflow.interface.importing.utils import import_class
cache_type = os.getenv("LANGFLOW_LANGCHAIN_CACHE") if cache_type := os.getenv("LANGFLOW_LANGCHAIN_CACHE"):
cache_class = import_class(f"langchain.cache.{cache_type or settings.CACHE}") try:
cache_class = import_class(
f"langchain.cache.{cache_type or settings.CACHE}"
)
logger.debug(f"Setting up LLM caching with {cache_class.__name__}") logger.debug(f"Setting up LLM caching with {cache_class.__name__}")
langchain.llm_cache = cache_class() langchain.llm_cache = cache_class()
logger.info(f"LLM caching setup with {cache_class.__name__}") logger.info(f"LLM caching setup with {cache_class.__name__}")
except ImportError:
logger.warning(f"Could not import {cache_type}. ")
else:
logger.info("No LLM cache set.")

View file

@ -146,9 +146,8 @@ def generate_result(langchain_object: Union[Chain, VectorStore], inputs: dict):
elif isinstance(langchain_object, Document): elif isinstance(langchain_object, Document):
result = langchain_object.dict() result = langchain_object.dict()
else: else:
raise ValueError( logger.warning(f"Unknown langchain_object type: {type(langchain_object)}")
f"Unknown langchain_object type: {type(langchain_object).__name__}" result = langchain_object
)
return result return result

View file

@ -37,7 +37,7 @@ class Settings(BaseSettings):
DEV: bool = False DEV: bool = False
DATABASE_URL: Optional[str] = None DATABASE_URL: Optional[str] = None
CACHE: str = "InMemoryCache" CACHE: Optional[str] = None
REMOVE_API_KEYS: bool = False REMOVE_API_KEYS: bool = False
COMPONENTS_PATH: List[str] = [] COMPONENTS_PATH: List[str] = []

View file

@ -359,11 +359,16 @@ export default function ParameterComponent({
field_name={name} field_name={name}
setNodeClass={(nodeClass) => { setNodeClass={(nodeClass) => {
data.node = nodeClass; data.node = nodeClass;
const clone = cloneDeep(data);
clone.node = nodeClass;
setData(clone);
}} }}
nodeClass={data.node} nodeClass={data.node}
disabled={disabled} disabled={disabled}
value={data.node?.template[name].value ?? ""} value={data.node?.template[name].value ?? ""}
onChange={handleOnNewValue} onChange={(e) => {
handleOnNewValue(e);
}}
/> />
</div> </div>
) : left === true && type === "NestedDict" ? ( ) : left === true && type === "NestedDict" ? (

View file

@ -19,7 +19,9 @@ export default function InputListComponent({
}, [disabled]); }, [disabled]);
// @TODO Recursive Character Text Splitter - the value might be in string format, whereas the InputListComponent specifically requires an array format. To ensure smooth operation and prevent potential errors, it's crucial that we handle the conversion from a string to an array with the string as its element. // @TODO Recursive Character Text Splitter - the value might be in string format, whereas the InputListComponent specifically requires an array format. To ensure smooth operation and prevent potential errors, it's crucial that we handle the conversion from a string to an array with the string as its element.
typeof value === "string" ? (value = [value]) : (value = value); if (typeof value === "string") {
value = [value];
}
return ( return (
<div <div

View file

@ -3,7 +3,7 @@ import { useEffect } from "react";
import { TypeModal } from "../../constants/enums"; import { TypeModal } from "../../constants/enums";
import { postValidatePrompt } from "../../controllers/API"; import { postValidatePrompt } from "../../controllers/API";
import GenericModal from "../../modals/genericModal"; import GenericModal from "../../modals/genericModal";
import { TextAreaComponentType } from "../../types/components"; import { PromptAreaComponentType } from "../../types/components";
import IconComponent from "../genericIconComponent"; import IconComponent from "../genericIconComponent";
export default function PromptAreaComponent({ export default function PromptAreaComponent({
@ -14,7 +14,7 @@ export default function PromptAreaComponent({
onChange, onChange,
disabled, disabled,
editNode = false, editNode = false,
}: TextAreaComponentType): JSX.Element { }: PromptAreaComponentType) {
useEffect(() => { useEffect(() => {
if (disabled) { if (disabled) {
onChange(""); onChange("");

View file

@ -1,3 +1,4 @@
import { InfinityIcon } from "lucide-react";
import { forwardRef } from "react"; import { forwardRef } from "react";
export const GradientSparkles = forwardRef< export const GradientSparkles = forwardRef<
@ -14,26 +15,7 @@ export const GradientSparkles = forwardRef<
</linearGradient> </linearGradient>
</defs> </defs>
</svg> </svg>
{/* this svg comes from the source code of lucide, <InfinityIcon stroke="url(#grad1)" ref={ref} {...props} />
we do not use the import because it crashes the ui (why? no one knows...).
source code from the used svg:
https://github.com/lucide-icons/lucide/blob/a4076db69b52ff0debc383f76d4d671c3bad5345/icons/infinity.svg?short_path=f79de91
*/}
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
stroke="url(#grad1)"
ref={ref}
{...props}
>
<path d="M12 12c-2-2.67-4-4-6-4a4 4 0 1 0 0 8c2 0 4-1.33 6-4Zm0 0c2 2.67 4 4 6 4a4 4 0 0 0 0-8c-2 0-4 1.33-6 4Z" />
</svg>
</> </>
); );
}); });

View file

@ -1,5 +1,12 @@
import { cloneDeep } from "lodash"; import { cloneDeep } from "lodash";
import { ReactNode, forwardRef, useContext, useEffect, useState } from "react"; import {
ReactNode,
forwardRef,
useContext,
useEffect,
useRef,
useState,
} from "react";
import CodeAreaComponent from "../../components/codeAreaComponent"; import CodeAreaComponent from "../../components/codeAreaComponent";
import DictComponent from "../../components/dictComponent"; import DictComponent from "../../components/dictComponent";
import Dropdown from "../../components/dropdownComponent"; import Dropdown from "../../components/dropdownComponent";
@ -51,37 +58,29 @@ const EditNodeModal = forwardRef(
ref ref
) => { ) => {
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
const [myData, setMyData] = useState(data);
const { setTabsState, tabId } = useContext(TabsContext); const { setTabsState, tabId } = useContext(TabsContext);
const { reactFlowInstance } = useContext(typesContext); const { reactFlowInstance } = useContext(typesContext);
const myData = useRef(data);
let disabled = let disabled =
reactFlowInstance reactFlowInstance
?.getEdges() ?.getEdges()
.some((edge) => edge.targetHandle === data.id) ?? false; .some((edge) => edge.targetHandle === data.id) ?? false;
function changeAdvanced(templateParam: string): void { function changeAdvanced(n) {
setMyData((old) => { let newData = cloneDeep(data);
let newData = cloneDeep(old); newData.node!.template[n].advanced = !newData.node!.template[n].advanced;
newData.node!.template[templateParam].advanced = myData.current = newData;
!newData.node!.template[templateParam].advanced;
return newData;
});
} }
const handleOnNewValue = ( const handleOnNewValue = (newValue: any, name) => {
newValue: string | string[] | boolean, let newData = cloneDeep(data);
name: string newData.node!.template[name].value = newValue;
) => { myData.current = newData;
setMyData((old) => {
let newData = cloneDeep(old);
newData.node!.template[name].value = newValue;
return newData;
});
}; };
useEffect(() => { useEffect(() => {
setMyData(data); // reset data to what it is on node when opening modal myData.current = data;
}, [modalOpen]); }, [modalOpen]);
const [obj, setObj] = useState({ const [obj, setObj] = useState({
@ -104,9 +103,17 @@ const EditNodeModal = forwardRef(
] as Object[]); ] as Object[]);
return ( return (
<BaseModal size="large-h-full" open={modalOpen} setOpen={setModalOpen}> <BaseModal
size="large-h-full"
open={modalOpen}
setOpen={setModalOpen}
onChangeOpenModal={(open) => {
let newData = cloneDeep(data);
myData.current = newData;
}}
>
<BaseModal.Trigger>{children}</BaseModal.Trigger> <BaseModal.Trigger>{children}</BaseModal.Trigger>
<BaseModal.Header description={myData.node?.description!}> <BaseModal.Header description={myData.current.node?.description!}>
<span className="pr-2">{myData.type}</span> <span className="pr-2">{myData.type}</span>
<Badge variant="secondary">ID: {myData.id}</Badge> <Badge variant="secondary">ID: {myData.id}</Badge>
</BaseModal.Header> </BaseModal.Header>
@ -141,58 +148,65 @@ const EditNodeModal = forwardRef(
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody className="p-0"> <TableBody className="p-0">
{Object.keys(myData.node!.template) {Object.keys(myData.current.node!.template)
.filter( .filter(
(templateParam) => (templateParam) =>
templateParam.charAt(0) !== "_" && templateParam.charAt(0) !== "_" &&
myData.node?.template[templateParam].show && myData.current.node?.template[templateParam].show &&
(myData.node.template[templateParam].type === (myData.current.node.template[templateParam]
"str" || .type === "str" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam]
"bool" || .type === "bool" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam]
"float" || .type === "float" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam]
"code" || .type === "code" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam]
"prompt" || .type === "prompt" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam]
"file" || .type === "file" ||
myData.node.template[templateParam].type === myData.current.node.template[templateParam]
"int") .type === "int")
) )
.map((templateParam, index) => ( .map((templateParam, index) => (
<TableRow key={index} className="h-10"> <TableRow key={index} className="h-10">
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3"> <TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
{myData.node?.template[templateParam].name {myData.current.node?.template[templateParam].name
? myData.node.template[templateParam].name ? myData.current.node.template[templateParam]
: myData.node?.template[templateParam] .name
: myData.current.node?.template[templateParam]
.display_name} .display_name}
</TableCell> </TableCell>
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground "> <TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
{myData.node?.template[templateParam].type === {myData.current.node?.template[templateParam]
"str" && .type === "str" &&
!myData.node.template[templateParam].options ? ( !myData.current.node.template[templateParam]
.options ? (
<div className="mx-auto"> <div className="mx-auto">
{myData.node.template[templateParam].list ? ( {myData.current.node.template[templateParam]
.list ? (
<InputListComponent <InputListComponent
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
value={ value={
!myData.node.template[templateParam] !myData.current.node.template[
.value || templateParam
myData.node.template[templateParam] ].value ||
.value === "" myData.current.node.template[
templateParam
].value === ""
? [""] ? [""]
: myData.node.template[templateParam] : myData.current.node.template[
.value templateParam
].value
} }
onChange={(value: string[]) => { onChange={(value: string[]) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
}} }}
/> />
) : myData.node?.template[templateParam] ) : myData.current.node?.template[
.type === "NestedDict" ? ( templateParam
].type === "NestedDict" ? (
<div className="mt-2 w-full"> <div className="mt-2 w-full">
<DictComponent <DictComponent
disabled={disabled} disabled={disabled}
@ -203,20 +217,23 @@ const EditNodeModal = forwardRef(
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam] ) : myData.current.node?.template[
.type === "dict" ? ( templateParam
].type === "dict" ? (
<div className="mt-2 w-full"> <div className="mt-2 w-full">
<KeypairListComponent <KeypairListComponent
disabled={disabled} disabled={disabled}
editNode={false} editNode={false}
value={ value={
myData.node.template[templateParam] myData.current.node.template[
.value?.length === 0 || templateParam
!myData.node.template[templateParam] ].value?.length === 0 ||
.value !myData.current.node.template[
templateParam
].value
? dictArr ? dictArr
: convertObjToArray( : convertObjToArray(
myData.node.template[ myData.current.node.template[
templateParam templateParam
].value ].value
) )
@ -230,21 +247,23 @@ const EditNodeModal = forwardRef(
setDictArr(newValue); setDictArr(newValue);
} else { } else {
setDictArr(newValue); setDictArr(newValue);
myData.node!.template[ myData.current.node!.template[
templateParam templateParam
].value = newValue; ].value = newValue;
} }
}} }}
/> />
</div> </div>
) : myData.node.template[templateParam] ) : myData.current.node.template[
.multiline ? ( templateParam
].multiline ? (
<TextAreaComponent <TextAreaComponent
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node.template[templateParam] myData.current.node.template[
.value ?? "" templateParam
].value ?? ""
} }
onChange={(value: string | string[]) => { onChange={(value: string | string[]) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
@ -255,12 +274,14 @@ const EditNodeModal = forwardRef(
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
password={ password={
myData.node.template[templateParam] myData.current.node.template[
.password ?? false templateParam
].password ?? false
} }
value={ value={
myData.node.template[templateParam] myData.current.node.template[
.value ?? "" templateParam
].value ?? ""
} }
onChange={(value) => { onChange={(value) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
@ -268,14 +289,16 @@ const EditNodeModal = forwardRef(
/> />
)} )}
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam]
"bool" ? ( .type === "bool" ? (
<div className="ml-auto"> <div className="ml-auto">
{" "} {" "}
<ToggleShadComponent <ToggleShadComponent
disabled={disabled} disabled={disabled}
enabled={ enabled={
myData.node.template[templateParam].value myData.current.node.template[
templateParam
].value
} }
setEnabled={(isEnabled) => { setEnabled={(isEnabled) => {
handleOnNewValue( handleOnNewValue(
@ -286,76 +309,84 @@ const EditNodeModal = forwardRef(
size="small" size="small"
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam]
"float" ? ( .type === "float" ? (
<div className="mx-auto"> <div className="mx-auto">
<FloatComponent <FloatComponent
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node.template[templateParam] myData.current.node.template[
.value ?? "" templateParam
].value ?? ""
} }
onChange={(value) => { onChange={(value) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam]
"str" && .type === "str" &&
myData.node.template[templateParam].options ? ( myData.current.node.template[templateParam]
.options ? (
<div className="mx-auto"> <div className="mx-auto">
<Dropdown <Dropdown
numberOfOptions={nodeLength} numberOfOptions={nodeLength}
editNode={true} editNode={true}
options={ options={
myData.node.template[templateParam] myData.current.node.template[
.options templateParam
].options
} }
onSelect={(value) => onSelect={(value) =>
handleOnNewValue(value, templateParam) handleOnNewValue(value, templateParam)
} }
value={ value={
myData.node.template[templateParam] myData.current.node.template[
.value ?? "Choose an option" templateParam
].value ?? "Choose an option"
} }
></Dropdown> ></Dropdown>
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam]
"int" ? ( .type === "int" ? (
<div className="mx-auto"> <div className="mx-auto">
<IntComponent <IntComponent
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node.template[templateParam] myData.current.node.template[
.value ?? "" templateParam
].value ?? ""
} }
onChange={(value) => { onChange={(value) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam]
"file" ? ( .type === "file" ? (
<div className="mx-auto"> <div className="mx-auto">
<InputFileComponent <InputFileComponent
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
value={ value={
myData.node.template[templateParam] myData.current.node.template[
.value ?? "" templateParam
].value ?? ""
} }
onChange={(value: string | string[]) => { onChange={(value: string | string[]) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
}} }}
fileTypes={ fileTypes={
myData.node.template[templateParam] myData.current.node.template[
.fileTypes templateParam
].fileTypes
} }
suffixes={ suffixes={
myData.node.template[templateParam] myData.current.node.template[
.suffixes templateParam
].suffixes
} }
onFileChange={(filePath: string) => { onFileChange={(filePath: string) => {
data.node!.template[ data.node!.template[
@ -364,28 +395,29 @@ const EditNodeModal = forwardRef(
}} }}
></InputFileComponent> ></InputFileComponent>
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam]
"prompt" ? ( .type === "prompt" ? (
<div className="mx-auto"> <div className="mx-auto">
<PromptAreaComponent <PromptAreaComponent
field_name={templateParam} field_name={templateParam}
editNode={true} editNode={true}
disabled={disabled} disabled={disabled}
nodeClass={myData.node} nodeClass={myData.current.node}
setNodeClass={(nodeClass) => { setNodeClass={(nodeClass) => {
myData.node = nodeClass; myData.current.node = nodeClass;
}} }}
value={ value={
myData.node.template[templateParam] myData.current.node.template[
.value ?? "" templateParam
].value ?? ""
} }
onChange={(value: string | string[]) => { onChange={(value: string | string[]) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam]
"code" ? ( .type === "code" ? (
<div className="mx-auto"> <div className="mx-auto">
<CodeAreaComponent <CodeAreaComponent
dynamic={ dynamic={
@ -399,16 +431,17 @@ const EditNodeModal = forwardRef(
disabled={disabled} disabled={disabled}
editNode={true} editNode={true}
value={ value={
myData.node.template[templateParam] myData.current.node.template[
.value ?? "" templateParam
].value ?? ""
} }
onChange={(value: string | string[]) => { onChange={(value: string | string[]) => {
handleOnNewValue(value, templateParam); handleOnNewValue(value, templateParam);
}} }}
/> />
</div> </div>
) : myData.node?.template[templateParam].type === ) : myData.current.node?.template[templateParam]
"Any" ? ( .type === "Any" ? (
"-" "-"
) : ( ) : (
<div className="hidden"></div> <div className="hidden"></div>
@ -418,8 +451,9 @@ const EditNodeModal = forwardRef(
<div className="items-center text-center"> <div className="items-center text-center">
<ToggleShadComponent <ToggleShadComponent
enabled={ enabled={
!myData.node?.template[templateParam] !myData.current.node?.template[
.advanced templateParam
].advanced
} }
setEnabled={(e) => setEnabled={(e) =>
changeAdvanced(templateParam) changeAdvanced(templateParam)

View file

@ -1,4 +1,4 @@
import { ReactNode } from "react"; import { ReactNode, useEffect } from "react";
import React from "react"; import React from "react";
import { import {
@ -68,12 +68,16 @@ interface BaseModalProps {
| "large-h-full" | "large-h-full"
| "small-h-full" | "small-h-full"
| "medium-h-full"; | "medium-h-full";
disable?: boolean;
onChangeOpenModal?: (open: boolean) => void;
} }
function BaseModal({ function BaseModal({
open, open,
setOpen, setOpen,
children, children,
size = "large", size = "large",
onChangeOpenModal,
}: BaseModalProps) { }: BaseModalProps) {
const headerChild = React.Children.toArray(children).find( const headerChild = React.Children.toArray(children).find(
(child) => (child as React.ReactElement).type === Header (child) => (child as React.ReactElement).type === Header
@ -127,6 +131,12 @@ function BaseModal({
break; break;
} }
useEffect(() => {
if (onChangeOpenModal) {
onChangeOpenModal(open);
}
}, [open]);
//UPDATE COLORS AND STYLE CLASSSES //UPDATE COLORS AND STYLE CLASSSES
return ( return (
<Dialog open={open} onOpenChange={setOpen}> <Dialog open={open} onOpenChange={setOpen}>

View file

@ -164,18 +164,18 @@ export default function CodeAreaModal({
</div> </div>
<div <div
className={ className={
"w-full transition-all delay-500 " + "whitespace-break-spaces transition-all delay-500" +
(error?.detail.error !== undefined ? "h-2/6" : "h-0") (error?.detail?.error !== undefined ? "h-2/6" : "h-0")
} }
> >
<div className="mt-1 h-full w-full overflow-y-auto overflow-x-clip text-left custom-scroll"> <div className="mt-1 h-full max-h-[10rem] w-full overflow-y-auto overflow-x-clip text-left custom-scroll">
<h1 className="text-lg text-destructive"> <h1 className="text-lg text-destructive">
{error?.detail?.error} {error?.detail?.error}
</h1> </h1>
<div className="ml-2 w-full text-sm text-status-red word-break-break-word"> <div className="ml-2 w-full text-sm text-status-red word-break-break-word">
<pre className="w-full word-break-break-word"> <span className="w-full word-break-break-word">
{error?.detail?.traceback} {error?.detail?.traceback}
</pre> </span>
</div> </div>
</div> </div>
</div> </div>

View file

@ -122,9 +122,15 @@ export default function GenericModal({
function validatePrompt(closeModal: boolean): void { function validatePrompt(closeModal: boolean): void {
//nodeClass is always null on tweaks //nodeClass is always null on tweaks
postValidatePrompt(field_name, inputValue, nodeClass!) postValidatePrompt(field_name, inputValue, nodeClass!)
.then((apiReturn) => { .then((apiReturn) => {
if (apiReturn.data) { if (apiReturn.data) {
setValue(inputValue);
apiReturn.data.frontend_node["template"]["template"]["value"] =
inputValue;
setNodeClass!(apiReturn?.data?.frontend_node);
let inputVariables = apiReturn.data.input_variables ?? []; let inputVariables = apiReturn.data.input_variables ?? [];
if (inputVariables && inputVariables.length === 0) { if (inputVariables && inputVariables.length === 0) {
setIsEdit(true); setIsEdit(true);
@ -164,7 +170,11 @@ export default function GenericModal({
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
return ( return (
<BaseModal open={modalOpen} setOpen={setModalOpen}> <BaseModal
onChangeOpenModal={(open) => {}}
open={modalOpen}
setOpen={setModalOpen}
>
<BaseModal.Trigger>{children}</BaseModal.Trigger> <BaseModal.Trigger>{children}</BaseModal.Trigger>
<BaseModal.Header <BaseModal.Header
description={(() => { description={(() => {
@ -291,9 +301,7 @@ export default function GenericModal({
setModalOpen(false); setModalOpen(false);
break; break;
case TypeModal.PROMPT: case TypeModal.PROMPT:
!inputValue || inputValue === "" validatePrompt(false);
? setModalOpen(false)
: validatePrompt(false);
break; break;
default: default:

View file

@ -29,7 +29,6 @@ pre {
animation: slideUp 300ms ease-out; animation: slideUp 300ms ease-out;
} }
.gradient-end { .gradient-end {
animation: gradient-motion-end 3s infinite forwards; animation: gradient-motion-end 3s infinite forwards;
} }
@ -51,3 +50,21 @@ select:-webkit-autofill:focus {
box-shadow: 0 0 0px 1000px #fff6d0 inset; box-shadow: 0 0 0px 1000px #fff6d0 inset;
color: black; color: black;
} }
.ace_scrollbar::-webkit-scrollbar {
height: 8px;
width: 8px;
}
.ace_scrollbar::-webkit-scrollbar-track {
background-color: #f1f1f1;
}
.ace_scrollbar::-webkit-scrollbar-thumb {
background-color: #ccc;
border-radius: 999px;
}
.ace_scrollbar::-webkit-scrollbar-thumb:hover {
background-color: #bbb;
border-radius: 999px;
}

View file

@ -79,6 +79,16 @@ export type TextAreaComponentType = {
editNode?: boolean; editNode?: boolean;
}; };
export type PromptAreaComponentType = {
field_name?: string;
nodeClass?: APIClassType;
setNodeClass?: (value: APIClassType) => void;
disabled: boolean;
onChange: (value: string[] | string) => void;
value: string;
editNode?: boolean;
};
export type CodeAreaComponentType = { export type CodeAreaComponentType = {
disabled: boolean; disabled: boolean;
onChange: (value: string[] | string) => void; onChange: (value: string[] | string) => void;