Merge branch 'feature/store' of github.com:logspace-ai/langflow into feature/store
This commit is contained in:
commit
3192290f1b
9 changed files with 495 additions and 415 deletions
|
|
@ -15,7 +15,7 @@ from langflow.api.v1.schemas import (
|
||||||
)
|
)
|
||||||
from langflow.interface.custom.custom_component import CustomComponent
|
from langflow.interface.custom.custom_component import CustomComponent
|
||||||
from langflow.interface.custom.directory_reader import DirectoryReader
|
from langflow.interface.custom.directory_reader import DirectoryReader
|
||||||
from langflow.interface.types import build_langchain_template_custom_component, create_and_validate_component
|
from langflow.interface.types import build_custom_component_template, create_and_validate_component
|
||||||
from langflow.processing.process import process_graph_cached, process_tweaks
|
from langflow.processing.process import process_graph_cached, process_tweaks
|
||||||
from langflow.services.auth.utils import api_key_security, get_current_active_user
|
from langflow.services.auth.utils import api_key_security, get_current_active_user
|
||||||
from langflow.services.cache.utils import save_uploaded_file
|
from langflow.services.cache.utils import save_uploaded_file
|
||||||
|
|
@ -216,7 +216,7 @@ async def custom_component(
|
||||||
):
|
):
|
||||||
component = create_and_validate_component(raw_code.code)
|
component = create_and_validate_component(raw_code.code)
|
||||||
|
|
||||||
built_frontend_node = build_langchain_template_custom_component(component, user_id=user.id)
|
built_frontend_node = build_custom_component_template(component, user_id=user.id)
|
||||||
|
|
||||||
built_frontend_node = update_frontend_node_with_template_values(built_frontend_node, raw_code)
|
built_frontend_node = update_frontend_node_with_template_values(built_frontend_node, raw_code)
|
||||||
return built_frontend_node
|
return built_frontend_node
|
||||||
|
|
@ -224,7 +224,7 @@ async def custom_component(
|
||||||
|
|
||||||
@router.post("/custom_component/reload", status_code=HTTPStatus.OK)
|
@router.post("/custom_component/reload", status_code=HTTPStatus.OK)
|
||||||
async def reload_custom_component(path: str, user: User = Depends(get_current_active_user)):
|
async def reload_custom_component(path: str, user: User = Depends(get_current_active_user)):
|
||||||
from langflow.interface.types import build_langchain_template_custom_component
|
from langflow.interface.types import build_custom_component_template
|
||||||
|
|
||||||
try:
|
try:
|
||||||
reader = DirectoryReader("")
|
reader = DirectoryReader("")
|
||||||
|
|
@ -234,7 +234,7 @@ async def reload_custom_component(path: str, user: User = Depends(get_current_ac
|
||||||
|
|
||||||
extractor = CustomComponent(code=content)
|
extractor = CustomComponent(code=content)
|
||||||
extractor.validate()
|
extractor.validate()
|
||||||
return build_langchain_template_custom_component(extractor, user_id=user.id)
|
return build_custom_component_template(extractor, user_id=user.id)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise HTTPException(status_code=400, detail=str(exc))
|
raise HTTPException(status_code=400, detail=str(exc))
|
||||||
|
|
||||||
|
|
@ -246,6 +246,6 @@ async def custom_component_update(
|
||||||
):
|
):
|
||||||
component = create_and_validate_component(raw_code.code)
|
component = create_and_validate_component(raw_code.code)
|
||||||
|
|
||||||
component_node = build_langchain_template_custom_component(component, user_id=user.id, update_field=raw_code.field)
|
component_node = build_custom_component_template(component, user_id=user.id, update_field=raw_code.field)
|
||||||
# Update the field
|
# Update the field
|
||||||
return component_node
|
return component_node
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ from uuid import UUID
|
||||||
|
|
||||||
from cachetools import LRUCache, cached
|
from cachetools import LRUCache, cached
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
from langflow.interface.agents.base import agent_creator
|
from langflow.interface.agents.base import agent_creator
|
||||||
from langflow.interface.chains.base import chain_creator
|
from langflow.interface.chains.base import chain_creator
|
||||||
from langflow.interface.custom.custom_component import CustomComponent
|
from langflow.interface.custom.custom_component import CustomComponent
|
||||||
|
|
@ -31,7 +33,6 @@ from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.frontend_node.constants import CLASSES_TO_REMOVE
|
from langflow.template.frontend_node.constants import CLASSES_TO_REMOVE
|
||||||
from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode
|
from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode
|
||||||
from langflow.utils.util import get_base_classes
|
from langflow.utils.util import get_base_classes
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
|
|
||||||
# Used to get the base_classes list
|
# Used to get the base_classes list
|
||||||
|
|
@ -335,7 +336,7 @@ def add_output_types(frontend_node, return_types: List[str]):
|
||||||
frontend_node.get("output_types").append(return_type)
|
frontend_node.get("output_types").append(return_type)
|
||||||
|
|
||||||
|
|
||||||
def build_langchain_template_custom_component(
|
def build_custom_component_template(
|
||||||
custom_component: CustomComponent,
|
custom_component: CustomComponent,
|
||||||
user_id: Optional[Union[str, UUID]] = None,
|
user_id: Optional[Union[str, UUID]] = None,
|
||||||
update_field: Optional[str] = None,
|
update_field: Optional[str] = None,
|
||||||
|
|
@ -394,85 +395,118 @@ def build_and_validate_all_files(reader: DirectoryReader, file_list):
|
||||||
|
|
||||||
|
|
||||||
def build_valid_menu(valid_components):
|
def build_valid_menu(valid_components):
|
||||||
"""Build the valid menu"""
|
"""Build the valid menu."""
|
||||||
valid_menu = {}
|
valid_menu = {}
|
||||||
logger.debug("------------------- VALID COMPONENTS -------------------")
|
logger.debug("------------------- VALID COMPONENTS -------------------")
|
||||||
for menu_item in valid_components["menu"]:
|
for menu_item in valid_components["menu"]:
|
||||||
menu_name = menu_item["name"]
|
menu_name = menu_item["name"]
|
||||||
valid_menu[menu_name] = {}
|
valid_menu[menu_name] = build_menu_items(menu_item)
|
||||||
# menu_path = menu_item["path"]
|
|
||||||
for component in menu_item["components"]:
|
|
||||||
logger.debug(f"Building component: {component.get('name'), component.get('output_types')}")
|
|
||||||
try:
|
|
||||||
component_name = component["name"]
|
|
||||||
component_code = component["code"]
|
|
||||||
component_output_types = component["output_types"]
|
|
||||||
|
|
||||||
component_extractor = CustomComponent(code=component_code)
|
|
||||||
component_extractor.validate()
|
|
||||||
|
|
||||||
component_template = build_langchain_template_custom_component(component_extractor)
|
|
||||||
component_template["output_types"] = component_output_types
|
|
||||||
# full_path = f"{menu_path}/{component.get('file')}"
|
|
||||||
# component_template["full_path"] = full_path
|
|
||||||
if len(component_output_types) == 1:
|
|
||||||
component_name = component_output_types[0]
|
|
||||||
else:
|
|
||||||
file_name = component.get("file").split(".")[0]
|
|
||||||
if "_" in file_name:
|
|
||||||
# turn .py file into camelcase
|
|
||||||
component_name = "".join([word.capitalize() for word in file_name.split("_")])
|
|
||||||
else:
|
|
||||||
component_name = file_name
|
|
||||||
|
|
||||||
valid_menu[menu_name][component_name] = component_template
|
|
||||||
logger.debug(f"Added {component_name} to valid menu to {menu_name}")
|
|
||||||
|
|
||||||
except Exception as exc:
|
|
||||||
logger.error(f"Error loading Component: {component['output_types']}")
|
|
||||||
logger.exception(f"Error while building custom component {component_output_types}: {exc}")
|
|
||||||
|
|
||||||
return valid_menu
|
return valid_menu
|
||||||
|
|
||||||
|
|
||||||
|
def build_menu_items(menu_item):
|
||||||
|
"""Build menu items for a given menu."""
|
||||||
|
menu_items = {}
|
||||||
|
for component in menu_item["components"]:
|
||||||
|
try:
|
||||||
|
component_name, component_template = build_component(component)
|
||||||
|
menu_items[component_name] = component_template
|
||||||
|
logger.debug(f"Added {component_name} to valid menu.")
|
||||||
|
except Exception as exc:
|
||||||
|
logger.error(f"Error loading Component: {component['output_types']}")
|
||||||
|
logger.exception(f"Error while building custom component {component['output_types']}: {exc}")
|
||||||
|
return menu_items
|
||||||
|
|
||||||
|
|
||||||
|
def build_component(component):
|
||||||
|
"""Build a single component."""
|
||||||
|
logger.debug(f"Building component: {component.get('name'), component.get('output_types')}")
|
||||||
|
component_name = determine_component_name(component)
|
||||||
|
component_template = create_component_template(component)
|
||||||
|
return component_name, component_template
|
||||||
|
|
||||||
|
|
||||||
|
def determine_component_name(component):
|
||||||
|
"""Determine the name of the component."""
|
||||||
|
component_output_types = component["output_types"]
|
||||||
|
if len(component_output_types) == 1:
|
||||||
|
return component_output_types[0]
|
||||||
|
else:
|
||||||
|
file_name = component.get("file").split(".")[0]
|
||||||
|
return "".join(word.capitalize() for word in file_name.split("_")) if "_" in file_name else file_name
|
||||||
|
|
||||||
|
|
||||||
|
def create_component_template(component):
|
||||||
|
"""Create a template for a component."""
|
||||||
|
component_code = component["code"]
|
||||||
|
component_output_types = component["output_types"]
|
||||||
|
|
||||||
|
component_extractor = CustomComponent(code=component_code)
|
||||||
|
component_extractor.validate()
|
||||||
|
|
||||||
|
component_template = build_custom_component_template(component_extractor)
|
||||||
|
component_template["output_types"] = component_output_types
|
||||||
|
return component_template
|
||||||
|
|
||||||
|
|
||||||
def build_invalid_menu(invalid_components):
|
def build_invalid_menu(invalid_components):
|
||||||
"""Build the invalid menu"""
|
"""Build the invalid menu."""
|
||||||
if invalid_components.get("menu"):
|
if not invalid_components.get("menu"):
|
||||||
logger.debug("------------------- INVALID COMPONENTS -------------------")
|
return {}
|
||||||
|
|
||||||
|
logger.debug("------------------- INVALID COMPONENTS -------------------")
|
||||||
invalid_menu = {}
|
invalid_menu = {}
|
||||||
for menu_item in invalid_components["menu"]:
|
for menu_item in invalid_components["menu"]:
|
||||||
menu_name = menu_item["name"]
|
menu_name = menu_item["name"]
|
||||||
invalid_menu[menu_name] = {}
|
invalid_menu[menu_name] = build_invalid_menu_items(menu_item)
|
||||||
|
|
||||||
for component in menu_item["components"]:
|
|
||||||
try:
|
|
||||||
component_name = component["name"]
|
|
||||||
component_code = component["code"]
|
|
||||||
|
|
||||||
component_template = (
|
|
||||||
CustomComponentFrontendNode(
|
|
||||||
description="ERROR - Check your Python Code",
|
|
||||||
display_name=f"ERROR - {component_name}",
|
|
||||||
)
|
|
||||||
.to_dict()
|
|
||||||
.get(type(CustomComponent()).__name__)
|
|
||||||
)
|
|
||||||
|
|
||||||
component_template["error"] = component.get("error", None)
|
|
||||||
logger.debug(component)
|
|
||||||
logger.debug(f"Component Path: {component.get('path', None)}")
|
|
||||||
logger.debug(f"Component Error: {component.get('error', None)}")
|
|
||||||
component_template.get("template").get("code")["value"] = component_code
|
|
||||||
|
|
||||||
invalid_menu[menu_name][component_name] = component_template
|
|
||||||
logger.debug(f"Added {component_name} to invalid menu to {menu_name}")
|
|
||||||
|
|
||||||
except Exception as exc:
|
|
||||||
logger.exception(f"Error while creating custom component [{component_name}]: {str(exc)}")
|
|
||||||
|
|
||||||
return invalid_menu
|
return invalid_menu
|
||||||
|
|
||||||
|
|
||||||
|
def build_invalid_menu_items(menu_item):
|
||||||
|
"""Build invalid menu items for a given menu."""
|
||||||
|
menu_items = {}
|
||||||
|
for component in menu_item["components"]:
|
||||||
|
try:
|
||||||
|
component_name, component_template = build_invalid_component(component)
|
||||||
|
menu_items[component_name] = component_template
|
||||||
|
logger.debug(f"Added {component_name} to invalid menu.")
|
||||||
|
except Exception as exc:
|
||||||
|
logger.exception(f"Error while creating custom component [{component_name}]: {str(exc)}")
|
||||||
|
return menu_items
|
||||||
|
|
||||||
|
|
||||||
|
def build_invalid_component(component):
|
||||||
|
"""Build a single invalid component."""
|
||||||
|
component_name = component["name"]
|
||||||
|
component_template = create_invalid_component_template(component, component_name)
|
||||||
|
log_invalid_component_details(component)
|
||||||
|
return component_name, component_template
|
||||||
|
|
||||||
|
|
||||||
|
def create_invalid_component_template(component, component_name):
|
||||||
|
"""Create a template for an invalid component."""
|
||||||
|
component_code = component["code"]
|
||||||
|
component_template = (
|
||||||
|
CustomComponentFrontendNode(
|
||||||
|
description="ERROR - Check your Python Code",
|
||||||
|
display_name=f"ERROR - {component_name}",
|
||||||
|
)
|
||||||
|
.to_dict()
|
||||||
|
.get(type(CustomComponent()).__name__)
|
||||||
|
)
|
||||||
|
|
||||||
|
component_template["error"] = component.get("error", None)
|
||||||
|
component_template.get("template").get("code")["value"] = component_code
|
||||||
|
return component_template
|
||||||
|
|
||||||
|
|
||||||
|
def log_invalid_component_details(component):
|
||||||
|
"""Log details of an invalid component."""
|
||||||
|
logger.debug(component)
|
||||||
|
logger.debug(f"Component Path: {component.get('path', None)}")
|
||||||
|
logger.debug(f"Component Error: {component.get('error', None)}")
|
||||||
|
|
||||||
|
|
||||||
def get_new_key(dictionary, original_key):
|
def get_new_key(dictionary, original_key):
|
||||||
counter = 1
|
counter = 1
|
||||||
new_key = original_key + " (" + str(counter) + ")"
|
new_key = original_key + " (" + str(counter) + ")"
|
||||||
|
|
@ -496,7 +530,7 @@ def merge_nested_dicts_with_renaming(dict1, dict2):
|
||||||
return dict1
|
return dict1
|
||||||
|
|
||||||
|
|
||||||
def build_langchain_custom_component_list_from_path(path: str):
|
def build_custom_component_list_from_path(path: str):
|
||||||
"""Build a list of custom components for the langchain from a given path"""
|
"""Build a list of custom components for the langchain from a given path"""
|
||||||
file_list = load_files_from_path(path)
|
file_list = load_files_from_path(path)
|
||||||
reader = DirectoryReader(path, False)
|
reader = DirectoryReader(path, False)
|
||||||
|
|
@ -510,34 +544,35 @@ def build_langchain_custom_component_list_from_path(path: str):
|
||||||
|
|
||||||
|
|
||||||
def get_all_types_dict(settings_service):
|
def get_all_types_dict(settings_service):
|
||||||
|
"""Get all types dictionary combining native and custom components."""
|
||||||
native_components = build_langchain_types_dict()
|
native_components = build_langchain_types_dict()
|
||||||
# custom_components is a list of dicts
|
custom_components_from_file = build_custom_components(settings_service)
|
||||||
# need to merge all the keys into one dict
|
return merge_nested_dicts_with_renaming(native_components, custom_components_from_file)
|
||||||
custom_components_from_file: dict[str, Any] = {}
|
|
||||||
if settings_service.settings.COMPONENTS_PATH:
|
|
||||||
logger.info(f"Building custom components from {settings_service.settings.COMPONENTS_PATH}")
|
|
||||||
|
|
||||||
custom_component_dicts = []
|
|
||||||
processed_paths = []
|
|
||||||
for path in settings_service.settings.COMPONENTS_PATH:
|
|
||||||
if str(path) in processed_paths:
|
|
||||||
continue
|
|
||||||
custom_component_dict = build_langchain_custom_component_list_from_path(str(path))
|
|
||||||
custom_component_dicts.append(custom_component_dict)
|
|
||||||
processed_paths.append(str(path))
|
|
||||||
|
|
||||||
logger.info(f"Loading {len(custom_component_dicts)} category(ies)")
|
def build_custom_components(settings_service):
|
||||||
for custom_component_dict in custom_component_dicts:
|
"""Build custom components from the specified paths."""
|
||||||
# custom_component_dict is a dict of dicts
|
if not settings_service.settings.COMPONENTS_PATH:
|
||||||
if not custom_component_dict:
|
return {}
|
||||||
continue
|
|
||||||
category = list(custom_component_dict.keys())[0]
|
logger.info(f"Building custom components from {settings_service.settings.COMPONENTS_PATH}")
|
||||||
|
custom_components_from_file = {}
|
||||||
|
processed_paths = set()
|
||||||
|
for path in settings_service.settings.COMPONENTS_PATH:
|
||||||
|
path_str = str(path)
|
||||||
|
if path_str in processed_paths:
|
||||||
|
continue
|
||||||
|
|
||||||
|
custom_component_dict = build_custom_component_list_from_path(path_str)
|
||||||
|
if custom_component_dict:
|
||||||
|
category = next(iter(custom_component_dict))
|
||||||
logger.info(f"Loading {len(custom_component_dict[category])} component(s) from category {category}")
|
logger.info(f"Loading {len(custom_component_dict[category])} component(s) from category {category}")
|
||||||
custom_components_from_file = merge_nested_dicts_with_renaming(
|
custom_components_from_file = merge_nested_dicts_with_renaming(
|
||||||
custom_components_from_file, custom_component_dict
|
custom_components_from_file, custom_component_dict
|
||||||
)
|
)
|
||||||
|
processed_paths.add(path_str)
|
||||||
|
|
||||||
return merge_nested_dicts_with_renaming(native_components, custom_components_from_file)
|
return custom_components_from_file
|
||||||
|
|
||||||
|
|
||||||
def merge_nested_dicts(dict1, dict2):
|
def merge_nested_dicts(dict1, dict2):
|
||||||
|
|
|
||||||
|
|
@ -498,11 +498,13 @@ class StoreService(Service):
|
||||||
comp_count = metadata.get("filter_count", 0)
|
comp_count = metadata.get("filter_count", 0)
|
||||||
except HTTPStatusError as exc:
|
except HTTPStatusError as exc:
|
||||||
if exc.response.status_code == 403:
|
if exc.response.status_code == 403:
|
||||||
raise ForbiddenError("You are not authorized to access this public resource")
|
raise ForbiddenError("You are not authorized to access this public resource") from exc
|
||||||
elif exc.response.status_code == 401:
|
elif exc.response.status_code == 401:
|
||||||
raise APIKeyError("You are not authorized to access this resource. Please check your API key.")
|
raise APIKeyError(
|
||||||
|
"You are not authorized to access this resource. Please check your API key."
|
||||||
|
) from exc
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise ValueError(f"Unexpected error: {exc}")
|
raise ValueError(f"Unexpected error: {exc}") from exc
|
||||||
try:
|
try:
|
||||||
if result and not metadata:
|
if result and not metadata:
|
||||||
if len(result) >= limit:
|
if len(result) >= limit:
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export default function DeleteConfirmationModal({
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger>{children}</DialogTrigger>
|
<DialogTrigger tabIndex={-1}>{children}</DialogTrigger>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import {
|
||||||
convertObjToArray,
|
convertObjToArray,
|
||||||
convertValuesToNumbers,
|
convertValuesToNumbers,
|
||||||
hasDuplicateKeys,
|
hasDuplicateKeys,
|
||||||
|
scapedJSONStringfy,
|
||||||
} from "../../utils/reactflowUtils";
|
} from "../../utils/reactflowUtils";
|
||||||
import { classNames } from "../../utils/utils";
|
import { classNames } from "../../utils/utils";
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
|
|
@ -62,10 +63,6 @@ const EditNodeModal = forwardRef(
|
||||||
|
|
||||||
const { setTabsState, tabId } = useContext(FlowsContext);
|
const { setTabsState, tabId } = useContext(FlowsContext);
|
||||||
const { reactFlowInstance } = useContext(typesContext);
|
const { reactFlowInstance } = useContext(typesContext);
|
||||||
let disabled =
|
|
||||||
reactFlowInstance
|
|
||||||
?.getEdges()
|
|
||||||
.some((edge) => edge.targetHandle === data.id) ?? false;
|
|
||||||
|
|
||||||
function changeAdvanced(n) {
|
function changeAdvanced(n) {
|
||||||
setMyData((old) => {
|
setMyData((old) => {
|
||||||
|
|
@ -150,52 +147,329 @@ const EditNodeModal = forwardRef(
|
||||||
myData.node.template[templateParam].type
|
myData.node.template[templateParam].type
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.map((templateParam, index) => (
|
.map((templateParam, index) => {
|
||||||
<TableRow key={index} className="h-10">
|
let id = {
|
||||||
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
inputTypes:
|
||||||
<ShadTooltip
|
data.node!.template[templateParam].input_types,
|
||||||
content={
|
type: data.node!.template[templateParam].type,
|
||||||
myData.node?.template[templateParam].proxy
|
id: data.id,
|
||||||
? myData.node?.template[templateParam].proxy
|
fieldName: templateParam,
|
||||||
?.id
|
};
|
||||||
: null
|
let disabled =
|
||||||
}
|
reactFlowInstance?.getEdges().some(
|
||||||
>
|
(edge) =>
|
||||||
<span>
|
edge.targetHandle ===
|
||||||
{myData.node?.template[templateParam]
|
scapedJSONStringfy(
|
||||||
.display_name
|
data.node!.template[templateParam].proxy
|
||||||
? myData.node.template[templateParam]
|
? {
|
||||||
.display_name
|
...id,
|
||||||
: myData.node?.template[templateParam].name}
|
proxy:
|
||||||
</span>
|
data.node?.template[templateParam]
|
||||||
</ShadTooltip>
|
.proxy,
|
||||||
</TableCell>
|
}
|
||||||
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
: id
|
||||||
{myData.node?.template[templateParam].type ===
|
)
|
||||||
"str" &&
|
) ?? false;
|
||||||
!myData.node.template[templateParam].options ? (
|
return (
|
||||||
<div className="mx-auto">
|
<TableRow key={index} className="h-10">
|
||||||
{myData.node.template[templateParam].list ? (
|
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
||||||
<InputListComponent
|
<ShadTooltip
|
||||||
editNode={true}
|
content={
|
||||||
|
myData.node?.template[templateParam].proxy
|
||||||
|
? myData.node?.template[templateParam]
|
||||||
|
.proxy?.id
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
{myData.node?.template[templateParam]
|
||||||
|
.display_name
|
||||||
|
? myData.node.template[templateParam]
|
||||||
|
.display_name
|
||||||
|
: myData.node?.template[templateParam]
|
||||||
|
.name}
|
||||||
|
</span>
|
||||||
|
</ShadTooltip>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
||||||
|
{myData.node?.template[templateParam].type ===
|
||||||
|
"str" &&
|
||||||
|
!myData.node.template[templateParam].options ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
{myData.node.template[templateParam]
|
||||||
|
.list ? (
|
||||||
|
<InputListComponent
|
||||||
|
editNode={true}
|
||||||
|
disabled={disabled}
|
||||||
|
value={
|
||||||
|
!myData.node.template[templateParam]
|
||||||
|
.value ||
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value === ""
|
||||||
|
? [""]
|
||||||
|
: myData.node.template[
|
||||||
|
templateParam
|
||||||
|
].value
|
||||||
|
}
|
||||||
|
onChange={(value: string[]) => {
|
||||||
|
handleOnNewValue(
|
||||||
|
value,
|
||||||
|
templateParam
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : myData.node.template[templateParam]
|
||||||
|
.multiline ? (
|
||||||
|
<TextAreaComponent
|
||||||
|
id={"textarea-edit-" + index}
|
||||||
|
disabled={disabled}
|
||||||
|
editNode={true}
|
||||||
|
value={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(
|
||||||
|
value: string | string[]
|
||||||
|
) => {
|
||||||
|
handleOnNewValue(
|
||||||
|
value,
|
||||||
|
templateParam
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<InputComponent
|
||||||
|
id={"input-" + index}
|
||||||
|
editNode={true}
|
||||||
|
disabled={disabled}
|
||||||
|
password={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.password ?? false
|
||||||
|
}
|
||||||
|
value={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value) => {
|
||||||
|
handleOnNewValue(
|
||||||
|
value,
|
||||||
|
templateParam
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : myData.node?.template[templateParam]
|
||||||
|
.type === "NestedDict" ? (
|
||||||
|
<div className=" w-full">
|
||||||
|
<DictComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
!myData.node.template[templateParam]
|
myData.node!.template[
|
||||||
.value ||
|
templateParam
|
||||||
myData.node.template[templateParam]
|
]?.value?.toString() === "{}"
|
||||||
.value === ""
|
? {
|
||||||
? [""]
|
yourkey: "value",
|
||||||
: myData.node.template[templateParam]
|
}
|
||||||
|
: myData.node!.template[templateParam]
|
||||||
.value
|
.value
|
||||||
}
|
}
|
||||||
onChange={(value: string[]) => {
|
onChange={(newValue) => {
|
||||||
|
myData.node!.template[
|
||||||
|
templateParam
|
||||||
|
].value = newValue;
|
||||||
|
handleOnNewValue(
|
||||||
|
newValue,
|
||||||
|
templateParam
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
id="editnode-div-dict-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : myData.node?.template[templateParam]
|
||||||
|
.type === "dict" ? (
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
"max-h-48 w-full overflow-auto custom-scroll",
|
||||||
|
myData.node!.template[templateParam].value
|
||||||
|
?.length > 1
|
||||||
|
? "my-3"
|
||||||
|
: ""
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<KeypairListComponent
|
||||||
|
disabled={disabled}
|
||||||
|
editNode={true}
|
||||||
|
value={
|
||||||
|
myData.node!.template[templateParam]
|
||||||
|
.value?.length === 0 ||
|
||||||
|
!myData.node!.template[templateParam]
|
||||||
|
.value
|
||||||
|
? [{ "": "" }]
|
||||||
|
: convertObjToArray(
|
||||||
|
myData.node!.template[
|
||||||
|
templateParam
|
||||||
|
].value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
duplicateKey={errorDuplicateKey}
|
||||||
|
onChange={(newValue) => {
|
||||||
|
const valueToNumbers =
|
||||||
|
convertValuesToNumbers(newValue);
|
||||||
|
myData.node!.template[
|
||||||
|
templateParam
|
||||||
|
].value = valueToNumbers;
|
||||||
|
setErrorDuplicateKey(
|
||||||
|
hasDuplicateKeys(valueToNumbers)
|
||||||
|
);
|
||||||
|
handleOnNewValue(
|
||||||
|
valueToNumbers,
|
||||||
|
templateParam
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : myData.node?.template[templateParam]
|
||||||
|
.type === "bool" ? (
|
||||||
|
<div className="ml-auto">
|
||||||
|
{" "}
|
||||||
|
<ToggleShadComponent
|
||||||
|
id={"toggle-edit-" + index}
|
||||||
|
disabled={disabled}
|
||||||
|
enabled={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value
|
||||||
|
}
|
||||||
|
setEnabled={(isEnabled) => {
|
||||||
|
handleOnNewValue(
|
||||||
|
isEnabled,
|
||||||
|
templateParam
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : myData.node?.template[templateParam]
|
||||||
|
.type === "float" ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
<FloatComponent
|
||||||
|
disabled={disabled}
|
||||||
|
editNode={true}
|
||||||
|
value={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value) => {
|
||||||
handleOnNewValue(value, templateParam);
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : myData.node.template[templateParam]
|
</div>
|
||||||
.multiline ? (
|
) : myData.node?.template[templateParam]
|
||||||
<TextAreaComponent
|
.type === "str" &&
|
||||||
id={"textarea-edit-" + index}
|
myData.node.template[templateParam]
|
||||||
|
.options ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
<Dropdown
|
||||||
|
numberOfOptions={nodeLength}
|
||||||
|
editNode={true}
|
||||||
|
options={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.options
|
||||||
|
}
|
||||||
|
onSelect={(value) =>
|
||||||
|
handleOnNewValue(value, templateParam)
|
||||||
|
}
|
||||||
|
value={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value ?? "Choose an option"
|
||||||
|
}
|
||||||
|
id={"dropdown-edit-" + index}
|
||||||
|
></Dropdown>
|
||||||
|
</div>
|
||||||
|
) : myData.node?.template[templateParam]
|
||||||
|
.type === "int" ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
<IntComponent
|
||||||
|
id={"int-input-" + index}
|
||||||
|
disabled={disabled}
|
||||||
|
editNode={true}
|
||||||
|
value={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value) => {
|
||||||
|
handleOnNewValue(value, templateParam);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : myData.node?.template[templateParam]
|
||||||
|
.type === "file" ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
<InputFileComponent
|
||||||
|
editNode={true}
|
||||||
|
disabled={disabled}
|
||||||
|
value={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value: string | string[]) => {
|
||||||
|
handleOnNewValue(value, templateParam);
|
||||||
|
}}
|
||||||
|
fileTypes={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.fileTypes
|
||||||
|
}
|
||||||
|
onFileChange={(filePath: string) => {
|
||||||
|
data.node!.template[
|
||||||
|
templateParam
|
||||||
|
].file_path = filePath;
|
||||||
|
}}
|
||||||
|
></InputFileComponent>
|
||||||
|
</div>
|
||||||
|
) : myData.node?.template[templateParam]
|
||||||
|
.type === "prompt" ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
<PromptAreaComponent
|
||||||
|
readonly={
|
||||||
|
myData.node?.flow ? true : false
|
||||||
|
}
|
||||||
|
field_name={templateParam}
|
||||||
|
editNode={true}
|
||||||
|
disabled={disabled}
|
||||||
|
nodeClass={myData.node}
|
||||||
|
setNodeClass={(nodeClass) => {
|
||||||
|
myData.node = nodeClass;
|
||||||
|
}}
|
||||||
|
value={
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.value ?? ""
|
||||||
|
}
|
||||||
|
onChange={(value: string | string[]) => {
|
||||||
|
handleOnNewValue(value, templateParam);
|
||||||
|
}}
|
||||||
|
id={"prompt-area-edit" + index}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : myData.node?.template[templateParam]
|
||||||
|
.type === "code" ? (
|
||||||
|
<div className="mx-auto">
|
||||||
|
<CodeAreaComponent
|
||||||
|
readonly={
|
||||||
|
myData.node?.flow &&
|
||||||
|
myData.node.template[templateParam]
|
||||||
|
.dynamic
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
}
|
||||||
|
dynamic={
|
||||||
|
data.node!.template[templateParam]
|
||||||
|
.dynamic ?? false
|
||||||
|
}
|
||||||
|
setNodeClass={(nodeClass) => {
|
||||||
|
data.node = nodeClass;
|
||||||
|
}}
|
||||||
|
nodeClass={data.node}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
|
|
@ -205,269 +479,38 @@ const EditNodeModal = forwardRef(
|
||||||
onChange={(value: string | string[]) => {
|
onChange={(value: string | string[]) => {
|
||||||
handleOnNewValue(value, templateParam);
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
|
id={"code-area-edit" + index}
|
||||||
/>
|
/>
|
||||||
) : (
|
</div>
|
||||||
<InputComponent
|
) : myData.node?.template[templateParam]
|
||||||
id={"input-" + index}
|
.type === "Any" ? (
|
||||||
editNode={true}
|
"-"
|
||||||
disabled={disabled}
|
) : (
|
||||||
password={
|
<div className="hidden"></div>
|
||||||
myData.node.template[templateParam]
|
)}
|
||||||
.password ?? false
|
</TableCell>
|
||||||
}
|
<TableCell className="p-0 text-right">
|
||||||
value={
|
<div className="items-center text-center">
|
||||||
myData.node.template[templateParam]
|
|
||||||
.value ?? ""
|
|
||||||
}
|
|
||||||
onChange={(value) => {
|
|
||||||
handleOnNewValue(value, templateParam);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
) : myData.node?.template[templateParam].type ===
|
|
||||||
"NestedDict" ? (
|
|
||||||
<div className=" w-full">
|
|
||||||
<DictComponent
|
|
||||||
disabled={disabled}
|
|
||||||
editNode={true}
|
|
||||||
value={
|
|
||||||
myData.node!.template[
|
|
||||||
templateParam
|
|
||||||
]?.value?.toString() === "{}"
|
|
||||||
? {
|
|
||||||
yourkey: "value",
|
|
||||||
}
|
|
||||||
: myData.node!.template[templateParam]
|
|
||||||
.value
|
|
||||||
}
|
|
||||||
onChange={(newValue) => {
|
|
||||||
myData.node!.template[
|
|
||||||
templateParam
|
|
||||||
].value = newValue;
|
|
||||||
handleOnNewValue(newValue, templateParam);
|
|
||||||
}}
|
|
||||||
id="editnode-div-dict-input"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : myData.node?.template[templateParam].type ===
|
|
||||||
"dict" ? (
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
"max-h-48 w-full overflow-auto custom-scroll",
|
|
||||||
myData.node!.template[templateParam].value
|
|
||||||
?.length > 1
|
|
||||||
? "my-3"
|
|
||||||
: ""
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<KeypairListComponent
|
|
||||||
disabled={disabled}
|
|
||||||
editNode={true}
|
|
||||||
value={
|
|
||||||
myData.node!.template[templateParam].value
|
|
||||||
?.length === 0 ||
|
|
||||||
!myData.node!.template[templateParam]
|
|
||||||
.value
|
|
||||||
? [{ "": "" }]
|
|
||||||
: convertObjToArray(
|
|
||||||
myData.node!.template[templateParam]
|
|
||||||
.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
duplicateKey={errorDuplicateKey}
|
|
||||||
onChange={(newValue) => {
|
|
||||||
const valueToNumbers =
|
|
||||||
convertValuesToNumbers(newValue);
|
|
||||||
myData.node!.template[
|
|
||||||
templateParam
|
|
||||||
].value = valueToNumbers;
|
|
||||||
setErrorDuplicateKey(
|
|
||||||
hasDuplicateKeys(valueToNumbers)
|
|
||||||
);
|
|
||||||
handleOnNewValue(
|
|
||||||
valueToNumbers,
|
|
||||||
templateParam
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : myData.node?.template[templateParam].type ===
|
|
||||||
"bool" ? (
|
|
||||||
<div className="ml-auto">
|
|
||||||
{" "}
|
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
id={"toggle-edit-" + index}
|
id={
|
||||||
disabled={disabled}
|
"show" +
|
||||||
enabled={
|
myData.node?.template[templateParam].name
|
||||||
myData.node.template[templateParam].value
|
|
||||||
}
|
}
|
||||||
setEnabled={(isEnabled) => {
|
enabled={
|
||||||
handleOnNewValue(
|
!myData.node?.template[templateParam]
|
||||||
isEnabled,
|
.advanced
|
||||||
templateParam
|
}
|
||||||
);
|
setEnabled={(e) => {
|
||||||
|
changeAdvanced(templateParam);
|
||||||
}}
|
}}
|
||||||
|
disabled={disabled}
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam].type ===
|
</TableCell>
|
||||||
"float" ? (
|
</TableRow>
|
||||||
<div className="mx-auto">
|
);
|
||||||
<FloatComponent
|
})}
|
||||||
disabled={disabled}
|
|
||||||
editNode={true}
|
|
||||||
value={
|
|
||||||
myData.node.template[templateParam]
|
|
||||||
.value ?? ""
|
|
||||||
}
|
|
||||||
onChange={(value) => {
|
|
||||||
handleOnNewValue(value, templateParam);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : myData.node?.template[templateParam].type ===
|
|
||||||
"str" &&
|
|
||||||
myData.node.template[templateParam].options ? (
|
|
||||||
<div className="mx-auto">
|
|
||||||
<Dropdown
|
|
||||||
numberOfOptions={nodeLength}
|
|
||||||
editNode={true}
|
|
||||||
options={
|
|
||||||
myData.node.template[templateParam]
|
|
||||||
.options
|
|
||||||
}
|
|
||||||
onSelect={(value) =>
|
|
||||||
handleOnNewValue(value, templateParam)
|
|
||||||
}
|
|
||||||
value={
|
|
||||||
myData.node.template[templateParam]
|
|
||||||
.value ?? "Choose an option"
|
|
||||||
}
|
|
||||||
id={"dropdown-edit-" + index}
|
|
||||||
></Dropdown>
|
|
||||||
</div>
|
|
||||||
) : myData.node?.template[templateParam].type ===
|
|
||||||
"int" ? (
|
|
||||||
<div className="mx-auto">
|
|
||||||
<IntComponent
|
|
||||||
id={"int-input-" + index}
|
|
||||||
disabled={disabled}
|
|
||||||
editNode={true}
|
|
||||||
value={
|
|
||||||
myData.node.template[templateParam]
|
|
||||||
.value ?? ""
|
|
||||||
}
|
|
||||||
onChange={(value) => {
|
|
||||||
handleOnNewValue(value, templateParam);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : myData.node?.template[templateParam].type ===
|
|
||||||
"file" ? (
|
|
||||||
<div className="mx-auto">
|
|
||||||
<InputFileComponent
|
|
||||||
editNode={true}
|
|
||||||
disabled={disabled}
|
|
||||||
value={
|
|
||||||
myData.node.template[templateParam]
|
|
||||||
.value ?? ""
|
|
||||||
}
|
|
||||||
onChange={(value: string | string[]) => {
|
|
||||||
handleOnNewValue(value, templateParam);
|
|
||||||
}}
|
|
||||||
fileTypes={
|
|
||||||
myData.node.template[templateParam]
|
|
||||||
.fileTypes
|
|
||||||
}
|
|
||||||
onFileChange={(filePath: string) => {
|
|
||||||
data.node!.template[
|
|
||||||
templateParam
|
|
||||||
].file_path = filePath;
|
|
||||||
}}
|
|
||||||
></InputFileComponent>
|
|
||||||
</div>
|
|
||||||
) : myData.node?.template[templateParam].type ===
|
|
||||||
"prompt" ? (
|
|
||||||
<div className="mx-auto">
|
|
||||||
<PromptAreaComponent
|
|
||||||
readonly={myData.node?.flow ? true : false}
|
|
||||||
field_name={templateParam}
|
|
||||||
editNode={true}
|
|
||||||
disabled={disabled}
|
|
||||||
nodeClass={myData.node}
|
|
||||||
setNodeClass={(nodeClass) => {
|
|
||||||
myData.node = nodeClass;
|
|
||||||
}}
|
|
||||||
value={
|
|
||||||
myData.node.template[templateParam]
|
|
||||||
.value ?? ""
|
|
||||||
}
|
|
||||||
onChange={(value: string | string[]) => {
|
|
||||||
handleOnNewValue(value, templateParam);
|
|
||||||
}}
|
|
||||||
id={"prompt-area-edit" + index}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : myData.node?.template[templateParam].type ===
|
|
||||||
"code" ? (
|
|
||||||
<div className="mx-auto">
|
|
||||||
<CodeAreaComponent
|
|
||||||
readonly={
|
|
||||||
myData.node?.flow &&
|
|
||||||
myData.node.template[templateParam]
|
|
||||||
.dynamic
|
|
||||||
? true
|
|
||||||
: false
|
|
||||||
}
|
|
||||||
dynamic={
|
|
||||||
data.node!.template[templateParam]
|
|
||||||
.dynamic ?? false
|
|
||||||
}
|
|
||||||
setNodeClass={(nodeClass) => {
|
|
||||||
data.node = nodeClass;
|
|
||||||
}}
|
|
||||||
nodeClass={data.node}
|
|
||||||
disabled={disabled}
|
|
||||||
editNode={true}
|
|
||||||
value={
|
|
||||||
myData.node.template[templateParam]
|
|
||||||
.value ?? ""
|
|
||||||
}
|
|
||||||
onChange={(value: string | string[]) => {
|
|
||||||
handleOnNewValue(value, templateParam);
|
|
||||||
}}
|
|
||||||
id={"code-area-edit" + index}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : myData.node?.template[templateParam].type ===
|
|
||||||
"Any" ? (
|
|
||||||
"-"
|
|
||||||
) : (
|
|
||||||
<div className="hidden"></div>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="p-0 text-right">
|
|
||||||
<div className="items-center text-center">
|
|
||||||
<ToggleShadComponent
|
|
||||||
id={
|
|
||||||
"show" +
|
|
||||||
myData.node?.template[templateParam].name
|
|
||||||
}
|
|
||||||
enabled={
|
|
||||||
!myData.node?.template[templateParam]
|
|
||||||
.advanced
|
|
||||||
}
|
|
||||||
setEnabled={(e) => {
|
|
||||||
changeAdvanced(templateParam);
|
|
||||||
}}
|
|
||||||
disabled={disabled}
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import PaginatorComponent from "../../../../components/PaginatorComponent";
|
import PaginatorComponent from "../../../../components/PaginatorComponent";
|
||||||
import CollectionCardComponent from "../../../../components/cardComponent";
|
import CollectionCardComponent from "../../../../components/cardComponent";
|
||||||
import CardsWrapComponent from "../../../../components/cardsWrapComponent";
|
import CardsWrapComponent from "../../../../components/cardsWrapComponent";
|
||||||
|
|
@ -142,20 +142,20 @@ export default function ComponentsComponent({
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
button={
|
button={
|
||||||
!is_component ? (
|
!is_component ? (
|
||||||
<Button
|
<Link to={"/flow/" + item.id}>
|
||||||
variant="outline"
|
<Button
|
||||||
size="sm"
|
tabIndex={-1}
|
||||||
className="whitespace-nowrap "
|
variant="outline"
|
||||||
onClick={() => {
|
size="sm"
|
||||||
navigate("/flow/" + item.id);
|
className="whitespace-nowrap "
|
||||||
}}
|
>
|
||||||
>
|
<IconComponent
|
||||||
<IconComponent
|
name="ExternalLink"
|
||||||
name="ExternalLink"
|
className="main-page-nav-button select-none"
|
||||||
className="main-page-nav-button"
|
/>
|
||||||
/>
|
Edit Flow
|
||||||
Edit Flow
|
</Button>
|
||||||
</Button>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,7 @@ def added_vector_store(client, json_vector_store, logged_in_headers):
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def test_component_code():
|
def test_component_code():
|
||||||
path = Path(__file__).parent.absolute() / "data" / "test_component.py"
|
path = Path(__file__).parent.absolute() / "data" / "component_test.py"
|
||||||
# load the content as a string
|
# load the content as a string
|
||||||
with open(path, "r") as f:
|
with open(path, "r") as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ from fastapi import HTTPException
|
||||||
from langflow.interface.custom.base import CustomComponent
|
from langflow.interface.custom.base import CustomComponent
|
||||||
from langflow.interface.custom.code_parser import CodeParser, CodeSyntaxError
|
from langflow.interface.custom.code_parser import CodeParser, CodeSyntaxError
|
||||||
from langflow.interface.custom.component import Component, ComponentCodeNullError
|
from langflow.interface.custom.component import Component, ComponentCodeNullError
|
||||||
from langflow.interface.types import build_langchain_template_custom_component, create_and_validate_component
|
from langflow.interface.types import build_custom_component_template, create_and_validate_component
|
||||||
from langflow.services.database.models.flow import Flow, FlowCreate
|
from langflow.services.database.models.flow import Flow, FlowCreate
|
||||||
|
|
||||||
code_default = """
|
code_default = """
|
||||||
|
|
@ -539,13 +539,13 @@ def test_create_and_validate_component_valid_code(test_component_code):
|
||||||
|
|
||||||
def test_build_langchain_template_custom_component_valid_code(test_component_code):
|
def test_build_langchain_template_custom_component_valid_code(test_component_code):
|
||||||
component = create_and_validate_component(test_component_code)
|
component = create_and_validate_component(test_component_code)
|
||||||
frontend_node = build_langchain_template_custom_component(component)
|
frontend_node = build_custom_component_template(component)
|
||||||
assert isinstance(frontend_node, dict)
|
assert isinstance(frontend_node, dict)
|
||||||
template = frontend_node["template"]
|
template = frontend_node["template"]
|
||||||
assert isinstance(template, dict)
|
assert isinstance(template, dict)
|
||||||
assert "param" in template
|
assert "param" in template
|
||||||
param_options = template["param"]["options"]
|
param_options = template["param"]["options"]
|
||||||
# Now run it again with an update field
|
# Now run it again with an update field
|
||||||
frontend_node = build_langchain_template_custom_component(component, update_field="param")
|
frontend_node = build_custom_component_template(component, update_field="param")
|
||||||
new_param_options = frontend_node["template"]["param"]["options"]
|
new_param_options = frontend_node["template"]["param"]["options"]
|
||||||
assert param_options != new_param_options
|
assert param_options != new_param_options
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue