merge fix
This commit is contained in:
commit
686a07faaa
156 changed files with 1698 additions and 1641 deletions
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
# 📝 Conteúdo
|
||||
|
||||
- [](#)
|
||||
- [📝 Conteúdo](#-conteúdo)
|
||||
- [📦 Introdução](#-introdução)
|
||||
- [🎨 Criar Fluxos](#-criar-fluxos)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
<div align="center">
|
||||
<a href="./README.md"><img alt="README in English" src="https://img.shields.io/badge/English-d9d9d9"></a>
|
||||
<a href="./README.PT.md"><img alt="README in Portuguese" src="https://img.shields.io/badge/Portuguese-d9d9d9"></a>
|
||||
<a href="./README.zh_CN.md"><img alt="README in Simplified Chinese" src="https://img.shields.io/badge/简体中文-d9d9d9"></a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
44
poetry.lock
generated
44
poetry.lock
generated
|
|
@ -4058,19 +4058,19 @@ text-helpers = ["chardet (>=5.1.0,<6.0.0)"]
|
|||
|
||||
[[package]]
|
||||
name = "langchain-anthropic"
|
||||
version = "0.1.15"
|
||||
version = "0.1.13"
|
||||
description = "An integration package connecting AnthropicMessages and LangChain"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8.1"
|
||||
files = [
|
||||
{file = "langchain_anthropic-0.1.15-py3-none-any.whl", hash = "sha256:7cceea526f473e4d514f39295dc128eec57da628a4bbb54850d11dda7aa959fc"},
|
||||
{file = "langchain_anthropic-0.1.15.tar.gz", hash = "sha256:c5c3c6eaccb11ed99a63886e50873ac21eaf8e9441e0f75c7ae7cd8cdef65155"},
|
||||
{file = "langchain_anthropic-0.1.13-py3-none-any.whl", hash = "sha256:121f6f480da7685c239573d98322adb94fe486d40651ac341637f65da36881de"},
|
||||
{file = "langchain_anthropic-0.1.13.tar.gz", hash = "sha256:32e7ac51e1874c47e1a20493e75f5bfc88b0ffeaf5f1aed6091547e1ae44bb85"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
anthropic = ">=0.28.0,<1"
|
||||
anthropic = ">=0.26.0,<1"
|
||||
defusedxml = ">=0.7.1,<0.8.0"
|
||||
langchain-core = ">=0.2.2rc1,<0.3"
|
||||
langchain-core = ">=0.1.43,<0.3"
|
||||
|
||||
[[package]]
|
||||
name = "langchain-astradb"
|
||||
|
|
@ -6844,7 +6844,7 @@ files = [
|
|||
]
|
||||
|
||||
[package.dependencies]
|
||||
pydantic = ">=2.7.0"
|
||||
pydantic = ">=2.3.0"
|
||||
python-dotenv = ">=0.21.0"
|
||||
|
||||
[package.extras]
|
||||
|
|
@ -9013,13 +9013,13 @@ types-pyOpenSSL = "*"
|
|||
|
||||
[[package]]
|
||||
name = "types-requests"
|
||||
version = "2.32.0.20240602"
|
||||
version = "2.32.0.20240523"
|
||||
description = "Typing stubs for requests"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-requests-2.32.0.20240602.tar.gz", hash = "sha256:3f98d7bbd0dd94ebd10ff43a7fbe20c3b8528acace6d8efafef0b6a184793f06"},
|
||||
{file = "types_requests-2.32.0.20240602-py3-none-any.whl", hash = "sha256:ed3946063ea9fbc6b5fc0c44fa279188bae42d582cb63760be6cb4b9d06c3de8"},
|
||||
{file = "types-requests-2.32.0.20240523.tar.gz", hash = "sha256:26b8a6de32d9f561192b9942b41c0ab2d8010df5677ca8aa146289d11d505f57"},
|
||||
{file = "types_requests-2.32.0.20240523-py3-none-any.whl", hash = "sha256:f19ed0e2daa74302069bbbbf9e82902854ffa780bc790742a810a9aaa52f65ec"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
@ -9038,13 +9038,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.12.1"
|
||||
version = "4.12.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "typing_extensions-4.12.1-py3-none-any.whl", hash = "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a"},
|
||||
{file = "typing_extensions-4.12.1.tar.gz", hash = "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1"},
|
||||
{file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"},
|
||||
{file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -9230,13 +9230,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.30.1"
|
||||
version = "0.29.0"
|
||||
description = "The lightning-fast ASGI server."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "uvicorn-0.30.1-py3-none-any.whl", hash = "sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81"},
|
||||
{file = "uvicorn-0.30.1.tar.gz", hash = "sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8"},
|
||||
{file = "uvicorn-0.29.0-py3-none-any.whl", hash = "sha256:2c2aac7ff4f4365c206fd773a39bf4ebd1047c238f8b8268ad996829323473de"},
|
||||
{file = "uvicorn-0.29.0.tar.gz", hash = "sha256:6a69214c0b6a087462412670b3ef21224fa48cae0e452b5883e8e8bdfdd11dd0"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
@ -9300,13 +9300,13 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)"
|
|||
|
||||
[[package]]
|
||||
name = "validators"
|
||||
version = "0.28.3"
|
||||
version = "0.28.1"
|
||||
description = "Python Data Validation for Humans™"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "validators-0.28.3-py3-none-any.whl", hash = "sha256:53cafa854f13850156259d9cc479b864ee901f6a96e6b109e6fc33f98f37d99f"},
|
||||
{file = "validators-0.28.3.tar.gz", hash = "sha256:c6c79840bcde9ba77b19f6218f7738188115e27830cbaff43264bc4ed24c429d"},
|
||||
{file = "validators-0.28.1-py3-none-any.whl", hash = "sha256:890c98789ad884037f059af6ea915ec2d667129d509180c2c590b8009a4c4219"},
|
||||
{file = "validators-0.28.1.tar.gz", hash = "sha256:5ac88e7916c3405f0ce38ac2ac82a477fcf4d90dbbeddd04c8193171fc17f7dc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -9454,13 +9454,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "weaviate-client"
|
||||
version = "4.6.4"
|
||||
version = "4.6.3"
|
||||
description = "A python native Weaviate client"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "weaviate_client-4.6.4-py3-none-any.whl", hash = "sha256:19b76fb923a5f0b6fcb7471ef3cd990d2791ede71731e53429e1066a9dbf2af2"},
|
||||
{file = "weaviate_client-4.6.4.tar.gz", hash = "sha256:5378db8a33bf1d48adff3f9efa572d9fb04eaeb36444817cab56f1ba3c595500"},
|
||||
{file = "weaviate_client-4.6.3-py3-none-any.whl", hash = "sha256:b2921f9aea84a4eccb1c75d55dd2857a87241e5536540fb96ffdf4737ed4fe8a"},
|
||||
{file = "weaviate_client-4.6.3.tar.gz", hash = "sha256:a6e638f746f91c310fe6680cffa77949718f17d8b40b966f7037028cacfd94e0"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
@ -9471,7 +9471,7 @@ grpcio-tools = ">=1.57.0,<2.0.0"
|
|||
httpx = ">=0.25.0,<=0.27.0"
|
||||
pydantic = ">=2.5.0,<3.0.0"
|
||||
requests = ">=2.30.0,<3.0.0"
|
||||
validators = "0.28.3"
|
||||
validators = "0.28.1"
|
||||
|
||||
[[package]]
|
||||
name = "websocket-client"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ if not space:
|
|||
print("Please provide a space to restart.")
|
||||
exit()
|
||||
|
||||
if not parsed_args.api_token:
|
||||
if not parsed_args.token:
|
||||
print("Please provide an API token.")
|
||||
exit()
|
||||
|
||||
|
|
|
|||
|
|
@ -71,9 +71,7 @@ async def login_to_get_access_token(
|
|||
|
||||
@router.get("/auto_login")
|
||||
async def auto_login(
|
||||
response: Response,
|
||||
db: Session = Depends(get_session),
|
||||
settings_service=Depends(get_settings_service)
|
||||
response: Response, db: Session = Depends(get_session), settings_service=Depends(get_settings_service)
|
||||
):
|
||||
auth_settings = settings_service.auth_settings
|
||||
if settings_service.auth_settings.AUTO_LOGIN:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from typing import List, Optional
|
||||
from uuid import UUID
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
|
||||
from langflow.services.deps import get_monitor_service
|
||||
|
|
|
|||
|
|
@ -15,10 +15,25 @@ import shlex
|
|||
from collections import OrderedDict, namedtuple
|
||||
from http.cookies import SimpleCookie
|
||||
|
||||
from uncurl.api import parser # type: ignore
|
||||
|
||||
parser.add_argument("-x", "--proxy", default={})
|
||||
parser.add_argument("-U", "--proxy-user", default="")
|
||||
ParsedArgs = namedtuple(
|
||||
"ParsedContext",
|
||||
[
|
||||
"command",
|
||||
"url",
|
||||
"data",
|
||||
"data_binary",
|
||||
"method",
|
||||
"headers",
|
||||
"compressed",
|
||||
"insecure",
|
||||
"user",
|
||||
"include",
|
||||
"silent",
|
||||
"proxy",
|
||||
"proxy_user",
|
||||
"cookies",
|
||||
],
|
||||
)
|
||||
|
||||
ParsedContext = namedtuple("ParsedContext", ["method", "url", "data", "headers", "cookies", "verify", "auth", "proxy"])
|
||||
|
||||
|
|
@ -27,24 +42,89 @@ def normalize_newlines(multiline_text):
|
|||
return multiline_text.replace(" \\\n", " ")
|
||||
|
||||
|
||||
def parse_curl_command(curl_command):
|
||||
tokens = shlex.split(normalize_newlines(curl_command))
|
||||
tokens = [token for token in tokens if token and token != " "]
|
||||
if "curl" not in tokens[0]:
|
||||
raise ValueError("Invalid curl command")
|
||||
args_template = {
|
||||
"command": None,
|
||||
"url": None,
|
||||
"data": None,
|
||||
"data_binary": None,
|
||||
"method": "get",
|
||||
"headers": [],
|
||||
"compressed": False,
|
||||
"insecure": False,
|
||||
"user": (),
|
||||
"include": False,
|
||||
"silent": False,
|
||||
"proxy": None,
|
||||
"proxy_user": None,
|
||||
"cookies": {},
|
||||
}
|
||||
args = args_template.copy()
|
||||
|
||||
i = 0
|
||||
while i < len(tokens):
|
||||
token = tokens[i]
|
||||
if token == "-X":
|
||||
i += 1
|
||||
args["method"] = tokens[i].lower()
|
||||
elif token in ("-d", "--data"):
|
||||
i += 1
|
||||
args["data"] = tokens[i]
|
||||
args["method"] = "post"
|
||||
elif token in ("-b", "--data-binary", "--data-raw"):
|
||||
i += 1
|
||||
args["data_binary"] = tokens[i]
|
||||
args["method"] = "post"
|
||||
elif token in ("-H", "--header"):
|
||||
i += 1
|
||||
args["headers"].append(tokens[i])
|
||||
elif token == "--compressed":
|
||||
args["compressed"] = True
|
||||
elif token in ("-k", "--insecure"):
|
||||
args["insecure"] = True
|
||||
elif token in ("-u", "--user"):
|
||||
i += 1
|
||||
args["user"] = tuple(tokens[i].split(":"))
|
||||
elif token in ("-I", "--include"):
|
||||
args["include"] = True
|
||||
elif token in ("-s", "--silent"):
|
||||
args["silent"] = True
|
||||
elif token in ("-x", "--proxy"):
|
||||
i += 1
|
||||
args["proxy"] = tokens[i]
|
||||
elif token in ("-U", "--proxy-user"):
|
||||
i += 1
|
||||
args["proxy_user"] = tokens[i]
|
||||
elif not token.startswith("-"):
|
||||
if args["command"] is None:
|
||||
args["command"] = token
|
||||
else:
|
||||
args["url"] = token
|
||||
i += 1
|
||||
|
||||
return ParsedArgs(**args)
|
||||
|
||||
|
||||
def parse_context(curl_command):
|
||||
method = "get"
|
||||
|
||||
tokens = shlex.split(normalize_newlines(curl_command))
|
||||
tokens = [token for token in tokens if token and token != " "]
|
||||
parsed_args = parser.parse_args(tokens)
|
||||
parsed_args: ParsedArgs = parse_curl_command(curl_command)
|
||||
|
||||
post_data = parsed_args.data or parsed_args.data_binary
|
||||
if post_data:
|
||||
method = "post"
|
||||
|
||||
if parsed_args.X:
|
||||
method = parsed_args.X.lower()
|
||||
if parsed_args.method:
|
||||
method = parsed_args.method.lower()
|
||||
|
||||
cookie_dict = OrderedDict()
|
||||
quoted_headers = OrderedDict()
|
||||
|
||||
for curl_header in parsed_args.header:
|
||||
for curl_header in parsed_args.headers:
|
||||
if curl_header.startswith(":"):
|
||||
occurrence = [m.start() for m in re.finditer(":", curl_header)]
|
||||
header_key, header_value = curl_header[: occurrence[1]], curl_header[occurrence[1] + 1 :]
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ def read_text_file(file_path: str) -> str:
|
|||
with open(file_path, "rb") as f:
|
||||
raw_data = f.read()
|
||||
result = chardet.detect(raw_data)
|
||||
encoding = result['encoding']
|
||||
encoding = result["encoding"]
|
||||
|
||||
with open(file_path, "r", encoding=encoding) as f:
|
||||
return f.read()
|
||||
|
|
|
|||
|
|
@ -90,7 +90,9 @@ async def run_flow(
|
|||
|
||||
fallback_to_env_vars = get_settings_service().settings.fallback_to_env_var
|
||||
|
||||
return await graph.arun(inputs_list, inputs_components=inputs_components, types=types, fallback_to_env_vars=fallback_to_env_vars)
|
||||
return await graph.arun(
|
||||
inputs_list, inputs_components=inputs_components, types=types, fallback_to_env_vars=fallback_to_env_vars
|
||||
)
|
||||
|
||||
|
||||
def generate_function_for_flow(
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ from langflow.services.database.models.user.crud import get_user_by_username
|
|||
from langflow.services.deps import get_settings_service, session_scope
|
||||
|
||||
from langflow.services.database.models.folder.utils import create_default_folder_if_it_doesnt_exist
|
||||
from langflow.services.deps import get_settings_service, session_scope, get_variable_service
|
||||
from langflow.services.deps import get_variable_service
|
||||
|
||||
|
||||
STARTER_FOLDER_NAME = "Starter Projects"
|
||||
|
|
@ -221,6 +221,7 @@ def _is_valid_uuid(val):
|
|||
return False
|
||||
return str(uuid_obj) == val
|
||||
|
||||
|
||||
def load_flows_from_directory():
|
||||
settings_service = get_settings_service()
|
||||
flows_path = settings_service.settings.load_flows_path
|
||||
|
|
@ -262,6 +263,7 @@ def load_flows_from_directory():
|
|||
session.add(flow)
|
||||
session.commit()
|
||||
|
||||
|
||||
def find_existing_flow(session, flow_id, flow_endpoint_name):
|
||||
if flow_endpoint_name:
|
||||
stmt = select(Flow).where(Flow.endpoint_name == flow_endpoint_name)
|
||||
|
|
@ -271,6 +273,8 @@ def find_existing_flow(session, flow_id, flow_endpoint_name):
|
|||
if existing := session.exec(stmt).first():
|
||||
return existing
|
||||
return None
|
||||
|
||||
|
||||
def create_or_update_starter_projects():
|
||||
components_paths = get_settings_service().settings.components_path
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ async def run_graph_internal(
|
|||
outputs or [],
|
||||
stream=stream,
|
||||
session_id=session_id_str or "",
|
||||
fallback_to_env_vars=fallback_to_env_vars
|
||||
fallback_to_env_vars=fallback_to_env_vars,
|
||||
)
|
||||
if session_id_str and session_service:
|
||||
await session_service.update_session(session_id_str, (graph, artifacts))
|
||||
|
|
|
|||
|
|
@ -215,10 +215,7 @@ def create_user_longterm_token(db: Session = Depends(get_session)) -> tuple[UUID
|
|||
username = settings_service.auth_settings.SUPERUSER
|
||||
super_user = get_user_by_username(db, username)
|
||||
if not super_user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Super user hasn't been created"
|
||||
)
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Super user hasn't been created")
|
||||
access_token_expires_longterm = timedelta(days=365)
|
||||
access_token = create_token(
|
||||
data={"sub": str(super_user.id)},
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class ApiKeyRead(ApiKeyBase):
|
|||
id: UUID
|
||||
api_key: str = Field(schema_extra={"validate_default": True})
|
||||
user_id: UUID = Field()
|
||||
created_at: datetime = Field()
|
||||
|
||||
@field_validator("api_key")
|
||||
@classmethod
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import os
|
||||
from typing import Optional
|
||||
|
||||
import yaml
|
||||
from loguru import logger
|
||||
|
|
@ -8,6 +7,7 @@ from langflow.services.base import Service
|
|||
from langflow.services.settings.auth import AuthSettings
|
||||
from langflow.services.settings.base import Settings
|
||||
|
||||
|
||||
class SettingsService(Service):
|
||||
name = "settings_service"
|
||||
|
||||
|
|
|
|||
17
src/frontend/package-lock.json
generated
17
src/frontend/package-lock.json
generated
|
|
@ -44,6 +44,7 @@
|
|||
"debounce-promise": "^3.1.2",
|
||||
"dompurify": "^3.0.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"emoji-regex": "^10.3.0",
|
||||
"esbuild": "^0.17.19",
|
||||
"file-saver": "^2.0.5",
|
||||
"framer-motion": "^11.0.6",
|
||||
|
|
@ -5997,9 +5998,9 @@
|
|||
"integrity": "sha512-NPtACGFe7vunRYzvYqVRhQvsDrTevxpgDKxG/Vcbe0BTNOY+5+/2mOXSw2ls7ToNbE5Bf/+uQbjTxcmwMozpCw=="
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
|
||||
"integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw=="
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
|
|
@ -12205,6 +12206,16 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width-cjs/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"node_modules/string-width/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
"debounce-promise": "^3.1.2",
|
||||
"dompurify": "^3.0.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"emoji-regex": "^10.3.0",
|
||||
"esbuild": "^0.17.19",
|
||||
"file-saver": "^2.0.5",
|
||||
"framer-motion": "^11.0.6",
|
||||
|
|
|
|||
|
|
@ -164,3 +164,13 @@ body {
|
|||
.ag-body-vertical-scroll-viewport::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
/* This CSS is to not apply the border for the column having 'no-border' class */
|
||||
.no-border.ag-cell:focus {
|
||||
border: none !important;
|
||||
outline: none;
|
||||
}
|
||||
.no-border.ag-cell {
|
||||
border: none !important;
|
||||
outline: none;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import axios from "axios";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
|
@ -30,10 +29,10 @@ export default function App() {
|
|||
useTrackLastVisitedPath();
|
||||
|
||||
const removeFromTempNotificationList = useAlertStore(
|
||||
(state) => state.removeFromTempNotificationList,
|
||||
(state) => state.removeFromTempNotificationList
|
||||
);
|
||||
const tempNotificationList = useAlertStore(
|
||||
(state) => state.tempNotificationList,
|
||||
(state) => state.tempNotificationList
|
||||
);
|
||||
const [fetchError, setFetchError] = useState(false);
|
||||
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
||||
|
|
@ -51,7 +50,7 @@ export default function App() {
|
|||
const refreshVersion = useDarkStore((state) => state.refreshVersion);
|
||||
const refreshStars = useDarkStore((state) => state.refreshStars);
|
||||
const setGlobalVariables = useGlobalVariablesStore(
|
||||
(state) => state.setGlobalVariables,
|
||||
(state) => state.setGlobalVariables
|
||||
);
|
||||
const checkHasStore = useStoreStore((state) => state.checkHasStore);
|
||||
const navigate = useNavigate();
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ export default function AlertDropdown({
|
|||
}: AlertDropdownType): JSX.Element {
|
||||
const notificationList = useAlertStore((state) => state.notificationList);
|
||||
const clearNotificationList = useAlertStore(
|
||||
(state) => state.clearNotificationList,
|
||||
(state) => state.clearNotificationList
|
||||
);
|
||||
const removeFromNotificationList = useAlertStore(
|
||||
(state) => state.removeFromNotificationList,
|
||||
(state) => state.removeFromNotificationList
|
||||
);
|
||||
const setNotificationCenter = useAlertStore(
|
||||
(state) => state.setNotificationCenter,
|
||||
(state) => state.setNotificationCenter
|
||||
);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
|
|
|||
|
|
@ -31,14 +31,14 @@ export default function ImageViewer({ image }) {
|
|||
const fullPageButton = document.getElementById("full-page-button");
|
||||
|
||||
zoomInButton!.addEventListener("click", () =>
|
||||
viewer.viewport.zoomBy(1.2),
|
||||
viewer.viewport.zoomBy(1.2)
|
||||
);
|
||||
zoomOutButton!.addEventListener("click", () =>
|
||||
viewer.viewport.zoomBy(0.8),
|
||||
viewer.viewport.zoomBy(0.8)
|
||||
);
|
||||
homeButton!.addEventListener("click", () => viewer.viewport.goHome());
|
||||
fullPageButton!.addEventListener("click", () =>
|
||||
viewer.setFullScreen(true),
|
||||
viewer.setFullScreen(true)
|
||||
);
|
||||
|
||||
// Optionally, you can set additional viewer options here
|
||||
|
|
@ -47,16 +47,16 @@ export default function ImageViewer({ image }) {
|
|||
return () => {
|
||||
viewer.destroy();
|
||||
zoomInButton!.removeEventListener("click", () =>
|
||||
viewer.viewport.zoomBy(1.2),
|
||||
viewer.viewport.zoomBy(1.2)
|
||||
);
|
||||
zoomOutButton!.removeEventListener("click", () =>
|
||||
viewer.viewport.zoomBy(0.8),
|
||||
viewer.viewport.zoomBy(0.8)
|
||||
);
|
||||
homeButton!.removeEventListener("click", () =>
|
||||
viewer.viewport.goHome(),
|
||||
viewer.viewport.goHome()
|
||||
);
|
||||
fullPageButton!.removeEventListener("click", () =>
|
||||
viewer.setFullScreen(true),
|
||||
viewer.setFullScreen(true)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import {
|
|||
} from "../../components/ui/accordion";
|
||||
import { AccordionComponentType } from "../../types/components";
|
||||
import { cn } from "../../utils/utils";
|
||||
import ShadTooltip from "../shadTooltipComponent";
|
||||
|
||||
export default function AccordionComponent({
|
||||
trigger,
|
||||
|
|
@ -18,7 +17,7 @@ export default function AccordionComponent({
|
|||
sideBar,
|
||||
}: AccordionComponentType): JSX.Element {
|
||||
const [value, setValue] = useState(
|
||||
open.length === 0 ? "" : getOpenAccordion(),
|
||||
open.length === 0 ? "" : getOpenAccordion()
|
||||
);
|
||||
|
||||
function getOpenAccordion(): string {
|
||||
|
|
@ -53,7 +52,7 @@ export default function AccordionComponent({
|
|||
disabled={disabled}
|
||||
className={cn(
|
||||
sideBar ? "w-full bg-muted px-[0.75rem] py-[0.5rem]" : "ml-3",
|
||||
disabled ? "cursor-not-allowed" : "cursor-pointer",
|
||||
disabled ? "cursor-not-allowed" : "cursor-pointer"
|
||||
)}
|
||||
>
|
||||
{trigger}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ import {
|
|||
import { Checkbox } from "../ui/checkbox";
|
||||
import { FormControl, FormField } from "../ui/form";
|
||||
import Loading from "../ui/loading";
|
||||
import { convertTestName } from "./utils/convert-test-name";
|
||||
import DragCardComponent from "./components/dragCardComponent";
|
||||
import { convertTestName } from "./utils/convert-test-name";
|
||||
|
||||
export default function CollectionCardComponent({
|
||||
data,
|
||||
|
|
@ -60,11 +60,11 @@ export default function CollectionCardComponent({
|
|||
const [loading, setLoading] = useState(false);
|
||||
const [loadingLike, setLoadingLike] = useState(false);
|
||||
const [liked_by_user, setLiked_by_user] = useState(
|
||||
data?.liked_by_user ?? false,
|
||||
data?.liked_by_user ?? false
|
||||
);
|
||||
const [likes_count, setLikes_count] = useState(data?.liked_by_count ?? 0);
|
||||
const [downloads_count, setDownloads_count] = useState(
|
||||
data?.downloads_count ?? 0,
|
||||
data?.downloads_count ?? 0
|
||||
);
|
||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
||||
|
|
@ -75,12 +75,12 @@ export default function CollectionCardComponent({
|
|||
const [openPlayground, setOpenPlayground] = useState(false);
|
||||
const [openDelete, setOpenDelete] = useState(false);
|
||||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId,
|
||||
(state) => state.setCurrentFlowId
|
||||
);
|
||||
const [loadingPlayground, setLoadingPlayground] = useState(false);
|
||||
|
||||
const selectedFlowsComponentsCards = useFlowsManagerStore(
|
||||
(state) => state.selectedFlowsComponentsCards,
|
||||
(state) => state.selectedFlowsComponentsCards
|
||||
);
|
||||
|
||||
const name = data.is_component ? "Component" : "Flow";
|
||||
|
|
@ -220,7 +220,7 @@ export default function CollectionCardComponent({
|
|||
"group relative flex min-h-[11rem] flex-col justify-between overflow-hidden transition-all hover:bg-muted/50 hover:shadow-md hover:dark:bg-[#ffffff10]",
|
||||
disabled ? "pointer-events-none opacity-50" : "",
|
||||
onClick ? "cursor-pointer" : "",
|
||||
isSelectedCard ? "border border-selected" : "",
|
||||
isSelectedCard ? "border border-selected" : ""
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
|
|
@ -233,7 +233,7 @@ export default function CollectionCardComponent({
|
|||
"visible flex-shrink-0",
|
||||
data.is_component
|
||||
? "mx-0.5 h-6 w-6 text-component-icon"
|
||||
: "h-7 w-7 flex-shrink-0 text-flow-icon",
|
||||
: "h-7 w-7 flex-shrink-0 text-flow-icon"
|
||||
)}
|
||||
name={data.is_component ? "ToyBrick" : "Group"}
|
||||
/>
|
||||
|
|
@ -428,7 +428,7 @@ export default function CollectionCardComponent({
|
|||
name="Trash2"
|
||||
className={cn(
|
||||
"h-5 w-5",
|
||||
!authorized ? " text-ring" : "",
|
||||
!authorized ? " text-ring" : ""
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
|
@ -463,7 +463,7 @@ export default function CollectionCardComponent({
|
|||
liked_by_user
|
||||
? "fill-destructive stroke-destructive"
|
||||
: "",
|
||||
!authorized ? " text-ring" : "",
|
||||
!authorized ? " text-ring" : ""
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
|
@ -501,7 +501,7 @@ export default function CollectionCardComponent({
|
|||
}
|
||||
className={cn(
|
||||
loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
|
||||
!authorized ? " text-ring" : "",
|
||||
!authorized ? " text-ring" : ""
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export default function CardsWrapComponent({
|
|||
"h-full w-full",
|
||||
isDragging
|
||||
? "mb-36 flex flex-col items-center justify-center gap-4 text-2xl font-light"
|
||||
: "",
|
||||
: ""
|
||||
)}
|
||||
>
|
||||
{isDragging ? (
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export default function FlowToolbar(): JSX.Element {
|
|||
"relative inline-flex h-full w-full items-center justify-center gap-[4px] bg-muted px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-background hover:bg-hover ",
|
||||
!hasApiKey || !validApiKey || !hasStore
|
||||
? " button-disable text-muted-foreground "
|
||||
: "",
|
||||
: ""
|
||||
)}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
|
|
@ -59,14 +59,14 @@ export default function FlowToolbar(): JSX.Element {
|
|||
"-m-0.5 -ml-1 h-6 w-6",
|
||||
!hasApiKey || !validApiKey || !hasStore
|
||||
? "extra-side-bar-save-disable"
|
||||
: "",
|
||||
: ""
|
||||
)}
|
||||
/>
|
||||
Share
|
||||
</button>
|
||||
</ShareModal>
|
||||
),
|
||||
[hasApiKey, validApiKey, currentFlow, hasStore],
|
||||
[hasApiKey, validApiKey, currentFlow, hasStore]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
@ -118,7 +118,7 @@ export default function FlowToolbar(): JSX.Element {
|
|||
<ApiModal flow={currentFlow}>
|
||||
<div
|
||||
className={classNames(
|
||||
"relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover",
|
||||
"relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover"
|
||||
)}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ export default function CodeTabsComponent({
|
|||
<div className="api-modal-according-display">
|
||||
<div
|
||||
className={classNames(
|
||||
"h-[70vh] w-full overflow-y-auto overflow-x-hidden rounded-lg bg-muted custom-scroll",
|
||||
"h-[70vh] w-full overflow-y-auto overflow-x-hidden rounded-lg bg-muted custom-scroll"
|
||||
)}
|
||||
>
|
||||
{data?.map((node: any, i) => (
|
||||
|
|
@ -275,8 +275,8 @@ export default function CodeTabsComponent({
|
|||
.show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
node.data.node.template[templateField]
|
||||
.type,
|
||||
),
|
||||
.type
|
||||
)
|
||||
)
|
||||
.map((templateField, indx) => {
|
||||
return (
|
||||
|
|
@ -334,7 +334,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -380,7 +380,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -433,7 +433,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -470,7 +470,7 @@ export default function CodeTabsComponent({
|
|||
e,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
size="small"
|
||||
|
|
@ -501,7 +501,7 @@ export default function CodeTabsComponent({
|
|||
].fileTypes
|
||||
}
|
||||
onFileChange={(
|
||||
value: any,
|
||||
value: any
|
||||
) => {
|
||||
node.data.node.template[
|
||||
templateField
|
||||
|
|
@ -554,7 +554,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -594,7 +594,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
value={
|
||||
|
|
@ -656,7 +656,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -702,7 +702,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -748,7 +748,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -780,8 +780,8 @@ export default function CodeTabsComponent({
|
|||
].value,
|
||||
type(
|
||||
node,
|
||||
templateField,
|
||||
),
|
||||
templateField
|
||||
)
|
||||
)
|
||||
}
|
||||
duplicateKey={
|
||||
|
|
@ -790,15 +790,15 @@ export default function CodeTabsComponent({
|
|||
onChange={(target) => {
|
||||
const valueToNumbers =
|
||||
convertValuesToNumbers(
|
||||
target,
|
||||
target
|
||||
);
|
||||
node.data.node!.template[
|
||||
templateField
|
||||
].value = valueToNumbers;
|
||||
setErrorDuplicateKey(
|
||||
hasDuplicateKeys(
|
||||
valueToNumbers,
|
||||
),
|
||||
valueToNumbers
|
||||
)
|
||||
);
|
||||
setData((old) => {
|
||||
let newInputList =
|
||||
|
|
@ -815,7 +815,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
isList={
|
||||
|
|
@ -863,7 +863,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
],
|
||||
]
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ function CsvOutputComponent({
|
|||
if (file) {
|
||||
const { rowData: data, colDefs: columns } = convertCSVToData(
|
||||
file,
|
||||
separator,
|
||||
separator
|
||||
);
|
||||
setRowData(data);
|
||||
setColDefs(columns);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export default function DictComponent({
|
|||
<div
|
||||
className={classNames(
|
||||
value.length > 1 && editNode ? "my-1" : "",
|
||||
"flex flex-col gap-3",
|
||||
"flex flex-col gap-3"
|
||||
)}
|
||||
>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,9 +33,8 @@ export default function Dropdown({
|
|||
|
||||
const refButton = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const PopoverContentDropdown = children
|
||||
? PopoverContent
|
||||
: PopoverContentWithoutPortal;
|
||||
const PopoverContentDropdown =
|
||||
children || editNode ? PopoverContent : PopoverContentWithoutPortal;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
|
|||
<span
|
||||
className={cn(
|
||||
"font-normal text-muted-foreground word-break-break-word",
|
||||
description === "" ? "font-light italic" : "",
|
||||
description === "" ? "font-light italic" : ""
|
||||
)}
|
||||
>
|
||||
{description === "" ? "No description" : description}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
|||
title: UPLOAD_ERROR_ALERT,
|
||||
list: [error],
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
|
@ -195,7 +195,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
|||
name={isBuilding || saveLoading ? "Loader2" : "CheckCircle2"}
|
||||
className={cn(
|
||||
"h-4 w-4",
|
||||
isBuilding || saveLoading ? "animate-spin" : "animate-wiggle",
|
||||
isBuilding || saveLoading ? "animate-spin" : "animate-wiggle"
|
||||
)}
|
||||
/>
|
||||
{printByBuildStatus()}
|
||||
|
|
|
|||
|
|
@ -181,18 +181,6 @@ export default function Header(): JSX.Element {
|
|||
/>
|
||||
</div>
|
||||
</AlertDropdown>
|
||||
{autoLogin && (
|
||||
<button
|
||||
onClick={() => {
|
||||
navigate("/account/api-keys");
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="Key"
|
||||
className="side-bar-button-size text-muted-foreground hover:text-accent-foreground"
|
||||
/>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<>
|
||||
<Separator orientation="vertical" />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,11 @@ import {
|
|||
CommandList,
|
||||
} from "../../../ui/command";
|
||||
import { Input } from "../../../ui/input";
|
||||
import { Popover, PopoverContentWithoutPortal } from "../../../ui/popover";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverContentWithoutPortal,
|
||||
} from "../../../ui/popover";
|
||||
const CustomInputPopover = ({
|
||||
id,
|
||||
refInput,
|
||||
|
|
@ -39,6 +43,9 @@ const CustomInputPopover = ({
|
|||
showOptions,
|
||||
}) => {
|
||||
const setErrorData = useAlertStore.getState().setErrorData;
|
||||
const PopoverContentInput = editNode
|
||||
? PopoverContent
|
||||
: PopoverContentWithoutPortal;
|
||||
|
||||
const handleInputChange = (e) => {
|
||||
if (password) {
|
||||
|
|
@ -68,9 +75,9 @@ const CustomInputPopover = ({
|
|||
(selectedOption !== "" || !onChange) && setSelectedOption
|
||||
? selectedOption
|
||||
: (selectedOptions?.length !== 0 || !onChange) &&
|
||||
setSelectedOptions
|
||||
? selectedOptions?.join(", ")
|
||||
: value
|
||||
setSelectedOptions
|
||||
? selectedOptions?.join(", ")
|
||||
: value
|
||||
}
|
||||
autoFocus={autoFocus}
|
||||
disabled={disabled}
|
||||
|
|
@ -96,7 +103,7 @@ const CustomInputPopover = ({
|
|||
(password && !(setSelectedOption || setSelectedOptions))
|
||||
? "pr-8"
|
||||
: "",
|
||||
className!,
|
||||
className!
|
||||
)}
|
||||
placeholder={password && editNode ? "Key" : placeholder}
|
||||
onChange={handleInputChange}
|
||||
|
|
@ -107,7 +114,7 @@ const CustomInputPopover = ({
|
|||
data-testid={editNode ? id + "-edit" : id}
|
||||
/>
|
||||
</PopoverAnchor>
|
||||
<PopoverContentWithoutPortal
|
||||
<PopoverContentInput
|
||||
className="nocopy nowheel nopan nodelete nodrag noundo p-0"
|
||||
style={{ minWidth: refInput?.current?.clientWidth ?? "200px" }}
|
||||
side="bottom"
|
||||
|
|
@ -134,15 +141,15 @@ const CustomInputPopover = ({
|
|||
onSelect={(currentValue) => {
|
||||
setSelectedOption &&
|
||||
setSelectedOption(
|
||||
currentValue === selectedOption ? "" : currentValue,
|
||||
currentValue === selectedOption ? "" : currentValue
|
||||
);
|
||||
setSelectedOptions &&
|
||||
setSelectedOptions(
|
||||
selectedOptions?.includes(currentValue)
|
||||
? selectedOptions.filter(
|
||||
(item) => item !== currentValue,
|
||||
(item) => item !== currentValue
|
||||
)
|
||||
: [...selectedOptions, currentValue],
|
||||
: [...selectedOptions, currentValue]
|
||||
);
|
||||
!setSelectedOptions && setShowOptions(false);
|
||||
}}
|
||||
|
|
@ -155,7 +162,7 @@ const CustomInputPopover = ({
|
|||
selectedOption === option ||
|
||||
selectedOptions?.includes(option)
|
||||
? "opacity-100"
|
||||
: "opacity-0",
|
||||
: "opacity-0"
|
||||
)}
|
||||
>
|
||||
<div className="absolute opacity-100 transition-all group-hover:opacity-0">
|
||||
|
|
@ -184,7 +191,7 @@ const CustomInputPopover = ({
|
|||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContentWithoutPortal>
|
||||
</PopoverContentInput>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,11 @@ import {
|
|||
CommandList,
|
||||
} from "../../../ui/command";
|
||||
import { Input } from "../../../ui/input";
|
||||
import { Popover, PopoverContentWithoutPortal } from "../../../ui/popover";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverContentWithoutPortal,
|
||||
} from "../../../ui/popover";
|
||||
const CustomInputPopoverObject = ({
|
||||
id,
|
||||
refInput,
|
||||
|
|
@ -23,6 +27,7 @@ const CustomInputPopoverObject = ({
|
|||
disabled,
|
||||
setShowOptions,
|
||||
required,
|
||||
editNode,
|
||||
className,
|
||||
placeholder,
|
||||
onChange,
|
||||
|
|
@ -34,6 +39,10 @@ const CustomInputPopoverObject = ({
|
|||
handleKeyDown,
|
||||
showOptions,
|
||||
}) => {
|
||||
const PopoverContentInput = editNode
|
||||
? PopoverContent
|
||||
: PopoverContentWithoutPortal;
|
||||
|
||||
const handleInputChange = (e) => {
|
||||
onChange && onChange(e.target.value);
|
||||
};
|
||||
|
|
@ -51,14 +60,14 @@ const CustomInputPopoverObject = ({
|
|||
? options.find((option) => option.id === selectedOption)?.name ||
|
||||
""
|
||||
: (selectedOptions?.length !== 0 || !onChange) &&
|
||||
setSelectedOptions
|
||||
? selectedOptions
|
||||
.map(
|
||||
(optionId) =>
|
||||
options.find((option) => option.id === optionId)?.name,
|
||||
)
|
||||
.join(", ")
|
||||
: value
|
||||
setSelectedOptions
|
||||
? selectedOptions
|
||||
.map(
|
||||
(optionId) =>
|
||||
options.find((option) => option.id === optionId)?.name
|
||||
)
|
||||
.join(", ")
|
||||
: value
|
||||
}
|
||||
autoFocus={autoFocus}
|
||||
disabled={disabled}
|
||||
|
|
@ -79,7 +88,7 @@ const CustomInputPopoverObject = ({
|
|||
data-testid={id}
|
||||
/>
|
||||
</PopoverAnchor>
|
||||
<PopoverContentWithoutPortal
|
||||
<PopoverContentInput
|
||||
className="nocopy nowheel nopan nodelete nodrag noundo p-0"
|
||||
style={{ minWidth: refInput?.current?.clientWidth ?? "200px" }}
|
||||
side="bottom"
|
||||
|
|
@ -106,15 +115,15 @@ const CustomInputPopoverObject = ({
|
|||
onSelect={(currentValue) => {
|
||||
setSelectedOption &&
|
||||
setSelectedOption(
|
||||
currentValue === selectedOption ? "" : currentValue,
|
||||
currentValue === selectedOption ? "" : currentValue
|
||||
);
|
||||
setSelectedOptions &&
|
||||
setSelectedOptions(
|
||||
selectedOptions?.includes(currentValue)
|
||||
? selectedOptions.filter(
|
||||
(item) => item !== currentValue,
|
||||
(item) => item !== currentValue
|
||||
)
|
||||
: [...selectedOptions, currentValue],
|
||||
: [...selectedOptions, currentValue]
|
||||
);
|
||||
!setSelectedOptions && setShowOptions(false);
|
||||
}}
|
||||
|
|
@ -127,7 +136,7 @@ const CustomInputPopoverObject = ({
|
|||
selectedOption === option.id ||
|
||||
selectedOptions?.includes(option.id)
|
||||
? "opacity-100"
|
||||
: "opacity-0",
|
||||
: "opacity-0"
|
||||
)}
|
||||
>
|
||||
<div className="absolute opacity-100 transition-all group-hover:opacity-0">
|
||||
|
|
@ -159,7 +168,7 @@ const CustomInputPopoverObject = ({
|
|||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContentWithoutPortal>
|
||||
</PopoverContentInput>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export default function InputComponent({
|
|||
editNode ? " input-edit-node " : "",
|
||||
password && editNode ? "pr-8" : "",
|
||||
password && !editNode ? "pr-10" : "",
|
||||
className!,
|
||||
className!
|
||||
)}
|
||||
placeholder={password && editNode ? "Key" : placeholder}
|
||||
onChange={(e) => {
|
||||
|
|
@ -108,6 +108,7 @@ export default function InputComponent({
|
|||
setSelectedOptions={setSelectedOptions}
|
||||
options={objectOptions}
|
||||
value={value}
|
||||
editNode={editNode}
|
||||
autoFocus={autoFocus}
|
||||
disabled={disabled}
|
||||
setShowOptions={setShowOptions}
|
||||
|
|
@ -153,7 +154,7 @@ export default function InputComponent({
|
|||
<span
|
||||
className={cn(
|
||||
password && selectedOption === "" ? "right-8" : "right-0",
|
||||
"absolute inset-y-0 flex items-center pr-2.5",
|
||||
"absolute inset-y-0 flex items-center pr-2.5"
|
||||
)}
|
||||
>
|
||||
<button
|
||||
|
|
@ -166,7 +167,7 @@ export default function InputComponent({
|
|||
selectedOption !== ""
|
||||
? "text-medium-indigo"
|
||||
: "text-muted-foreground",
|
||||
"hover:text-accent-foreground",
|
||||
"hover:text-accent-foreground"
|
||||
)}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
|
|
@ -186,7 +187,7 @@ export default function InputComponent({
|
|||
"mb-px",
|
||||
editNode
|
||||
? "input-component-true-button"
|
||||
: "input-component-false-button",
|
||||
: "input-component-false-button"
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
|
|
@ -203,7 +204,7 @@ export default function InputComponent({
|
|||
className={classNames(
|
||||
editNode
|
||||
? "input-component-true-svg"
|
||||
: "input-component-false-svg",
|
||||
: "input-component-false-svg"
|
||||
)}
|
||||
>
|
||||
<path
|
||||
|
|
@ -222,7 +223,7 @@ export default function InputComponent({
|
|||
className={classNames(
|
||||
editNode
|
||||
? "input-component-true-svg"
|
||||
: "input-component-false-svg",
|
||||
: "input-component-false-svg"
|
||||
)}
|
||||
>
|
||||
<path
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
CONSOLE_ERROR_MSG,
|
||||
CONSOLE_SUCCESS_MSG,
|
||||
INVALID_FILE_ALERT,
|
||||
} from "../../constants/alerts_constants";
|
||||
import { uploadFile } from "../../controllers/API";
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ export default function InputGlobalComponent({
|
|||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
|
||||
useEffect(() => {
|
||||
if (data.node?.template[name])
|
||||
if (data)
|
||||
if (
|
||||
globalVariablesEntries &&
|
||||
!globalVariablesEntries.includes(data.node?.template[name].value) &&
|
||||
data.node?.template[name].load_from_db
|
||||
!globalVariablesEntries.includes(data.value) &&
|
||||
data.load_from_db
|
||||
) {
|
||||
setTimeout(() => {
|
||||
onChange("", true);
|
||||
|
|
@ -46,17 +46,11 @@ export default function InputGlobalComponent({
|
|||
}, [globalVariablesEntries]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!data.node?.template[name].value &&
|
||||
data.node?.template[name].display_name
|
||||
) {
|
||||
if (
|
||||
unavaliableFields[data.node?.template[name].display_name!] &&
|
||||
!disabled
|
||||
) {
|
||||
if (!data.value && data.display_name) {
|
||||
if (unavaliableFields[data.display_name!] && !disabled) {
|
||||
setTimeout(() => {
|
||||
setDb(true);
|
||||
onChange(unavaliableFields[data.node?.template[name].display_name!]);
|
||||
onChange(unavaliableFields[data.display_name!]);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
|
@ -68,10 +62,7 @@ export default function InputGlobalComponent({
|
|||
await deleteGlobalVariable(id)
|
||||
.then(() => {
|
||||
removeGlobalVariable(key);
|
||||
if (
|
||||
data?.node?.template[name].value === key &&
|
||||
data?.node?.template[name].load_from_db
|
||||
) {
|
||||
if (data?.value === key && data?.load_from_db) {
|
||||
onChange("");
|
||||
setDb(false);
|
||||
}
|
||||
|
|
@ -94,8 +85,8 @@ export default function InputGlobalComponent({
|
|||
id={"input-" + name}
|
||||
editNode={editNode}
|
||||
disabled={disabled}
|
||||
password={data.node?.template[name].password ?? false}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
password={data.password ?? false}
|
||||
value={data.value ?? ""}
|
||||
options={globalVariablesEntries}
|
||||
optionsPlaceholder={"Global Variables"}
|
||||
optionsIcon="Globe"
|
||||
|
|
@ -138,10 +129,10 @@ export default function InputGlobalComponent({
|
|||
</DeleteConfirmationModal>
|
||||
)}
|
||||
selectedOption={
|
||||
data?.node?.template[name].load_from_db &&
|
||||
data?.load_from_db &&
|
||||
globalVariablesEntries &&
|
||||
globalVariablesEntries.includes(data?.node?.template[name].value ?? "")
|
||||
? data?.node?.template[name].value
|
||||
globalVariablesEntries.includes(data?.value ?? "")
|
||||
? data?.value
|
||||
: ""
|
||||
}
|
||||
setSelectedOption={(value) => {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export default function ShadTooltip({
|
|||
delayDuration = 500,
|
||||
}: ShadToolTipType): JSX.Element {
|
||||
return (
|
||||
<Tooltip delayDuration={delayDuration}>
|
||||
<Tooltip defaultOpen={!children} delayDuration={delayDuration}>
|
||||
<TooltipTrigger asChild={asChild}>{children}</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className={cn(styleClasses, "max-w-96")}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { Link } from "react-router-dom";
|
||||
import { cn } from "../../../../utils/utils";
|
||||
import { buttonVariants } from "../../../ui/button";
|
||||
import ForwardedIconComponent from "../../../genericIconComponent";
|
||||
|
||||
type SideBarButtonsComponentProps = {
|
||||
items: {
|
||||
|
|
@ -28,7 +27,7 @@ const SideBarButtonsComponent = ({
|
|||
pathname === item.href
|
||||
? "border border-border bg-muted hover:bg-muted"
|
||||
: "border border-transparent hover:border-border hover:bg-transparent",
|
||||
"flex w-full shrink-0 justify-start gap-4",
|
||||
"flex w-full shrink-0 justify-start gap-4"
|
||||
)}
|
||||
>
|
||||
{item.icon}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { addVersionToDuplicates } from "../../../utils/reactflowUtils";
|
|||
const useFileDrop = (folderId, folderChangeCallback) => {
|
||||
const setFolderDragging = useFolderStore((state) => state.setFolderDragging);
|
||||
const setFolderIdDragging = useFolderStore(
|
||||
(state) => state.setFolderIdDragging,
|
||||
(state) => state.setFolderIdDragging
|
||||
);
|
||||
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
|
|
@ -45,7 +45,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
| React.DragEvent<HTMLDivElement>
|
||||
| React.DragEvent<HTMLButtonElement>
|
||||
| React.DragEvent<HTMLAnchorElement>,
|
||||
folderId: string,
|
||||
folderId: string
|
||||
) => {
|
||||
e.preventDefault();
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
| React.DragEvent<HTMLDivElement>
|
||||
| React.DragEvent<HTMLButtonElement>
|
||||
| React.DragEvent<HTMLAnchorElement>,
|
||||
folderId: string,
|
||||
folderId: string
|
||||
) => {
|
||||
if (e.dataTransfer.types.some((types) => types === "Files")) {
|
||||
setFolderDragging(true);
|
||||
|
|
@ -73,7 +73,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
e:
|
||||
| React.DragEvent<HTMLDivElement>
|
||||
| React.DragEvent<HTMLButtonElement>
|
||||
| React.DragEvent<HTMLAnchorElement>,
|
||||
| React.DragEvent<HTMLAnchorElement>
|
||||
) => {
|
||||
e.preventDefault();
|
||||
if (e.target === e.currentTarget) {
|
||||
|
|
@ -87,7 +87,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
| React.DragEvent<HTMLDivElement>
|
||||
| React.DragEvent<HTMLButtonElement>
|
||||
| React.DragEvent<HTMLAnchorElement>,
|
||||
folderId: string,
|
||||
folderId: string
|
||||
) => {
|
||||
if (e?.dataTransfer?.getData("flow")) {
|
||||
const data = JSON.parse(e?.dataTransfer?.getData("flow"));
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@ import { cn } from "../../utils/utils";
|
|||
import HorizontalScrollFadeComponent from "../horizontalScrollFadeComponent";
|
||||
import SideBarButtonsComponent from "./components/sideBarButtons";
|
||||
import SideBarFoldersButtonsComponent from "./components/sideBarFolderButtons";
|
||||
import { addFolder } from "../../pages/MainPage/services";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
|
||||
type SidebarNavProps = {
|
||||
items: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { cn } from "../../../../utils/utils";
|
||||
import ShadTooltip from "../../../shadTooltipComponent";
|
||||
import { Toggle } from "../../../ui/toggle";
|
||||
|
||||
export default function ResetColumns({
|
||||
resetGrid,
|
||||
|
|
@ -8,15 +6,6 @@ export default function ResetColumns({
|
|||
resetGrid: () => void;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
/*<div className="absolute left-2 bottom-1 cursor-pointer">
|
||||
<div
|
||||
className="flex h-10 items-center justify-center px-2 pl-3 rounded-md border border-ring/60 text-sm text-[#bccadc] ring-offset-background placeholder:text-muted-foreground hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
onClick={() => setShow(!show)}
|
||||
>
|
||||
<ForwardedIconComponent name="Settings"></ForwardedIconComponent>
|
||||
<ForwardedIconComponent name={show ? "ChevronLeft" : "ChevronRight"} className="transition-all"></ForwardedIconComponent>
|
||||
</div>
|
||||
</div>*/
|
||||
<div className={cn("absolute bottom-4 left-6")}>
|
||||
<span
|
||||
className="cursor-pointer underline"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { CustomCellRendererProps } from "ag-grid-react";
|
||||
import { cn, isTimeStampString } from "../../utils/utils";
|
||||
import ArrayReader from "../arrayReaderComponent";
|
||||
import DateReader from "../dateReaderComponent";
|
||||
import NumberReader from "../numberReader";
|
||||
import ObjectRender from "../objectRender";
|
||||
import StringReader from "../stringReaderComponent";
|
||||
import { Badge } from "../ui/badge";
|
||||
import { cn, isTimeStampString } from "../../../../utils/utils";
|
||||
import ArrayReader from "../../../arrayReaderComponent";
|
||||
import DateReader from "../../../dateReaderComponent";
|
||||
import NumberReader from "../../../numberReader";
|
||||
import ObjectRender from "../../../objectRender";
|
||||
import StringReader from "../../../stringReaderComponent";
|
||||
import { Badge } from "../../../ui/badge";
|
||||
|
||||
export default function TableAutoCellRender({
|
||||
value,
|
||||
|
|
@ -43,7 +43,6 @@ export default function TableAutoCellRender({
|
|||
} else {
|
||||
return <StringReader string={value} />;
|
||||
}
|
||||
break;
|
||||
case "number":
|
||||
return <NumberReader number={value} />;
|
||||
default:
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
import { CustomCellRendererProps } from "ag-grid-react";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { useState } from "react";
|
||||
import CodeAreaComponent from "../../../codeAreaComponent";
|
||||
import DictComponent from "../../../dictComponent";
|
||||
import Dropdown from "../../../dropdownComponent";
|
||||
import FloatComponent from "../../../floatComponent";
|
||||
import InputFileComponent from "../../../inputFileComponent";
|
||||
import InputGlobalComponent from "../../../inputGlobalComponent";
|
||||
import InputListComponent from "../../../inputListComponent";
|
||||
import IntComponent from "../../../intComponent";
|
||||
import KeypairListComponent from "../../../keypairListComponent";
|
||||
import PromptAreaComponent from "../../../promptComponent";
|
||||
import TextAreaComponent from "../../../textAreaComponent";
|
||||
import ToggleShadComponent from "../../../toggleShadComponent";
|
||||
import useFlowStore from "../../../../stores/flowStore";
|
||||
import {
|
||||
convertObjToArray,
|
||||
convertValuesToNumbers,
|
||||
hasDuplicateKeys,
|
||||
scapedJSONStringfy,
|
||||
} from "../../../../utils/reactflowUtils";
|
||||
import { classNames } from "../../../../utils/utils";
|
||||
|
||||
export default function TableNodeCellRender({
|
||||
node: { data },
|
||||
value: {
|
||||
value,
|
||||
nodeClass,
|
||||
handleOnNewValue: handleOnNewValueNode,
|
||||
handleOnChangeDb,
|
||||
},
|
||||
}: CustomCellRendererProps) {
|
||||
const handleOnNewValue = (newValue: any, name: string) => {
|
||||
handleOnNewValueNode(newValue, name);
|
||||
setTemplateData((old) => {
|
||||
let newData = cloneDeep(old);
|
||||
newData.value = newValue;
|
||||
return newData;
|
||||
});
|
||||
setTemplateValue(newValue);
|
||||
};
|
||||
|
||||
const [templateValue, setTemplateValue] = useState(value);
|
||||
const [templateData, setTemplateData] = useState(data);
|
||||
|
||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||
const edges = useFlowStore((state) => state.edges);
|
||||
|
||||
const id = {
|
||||
inputTypes: templateData.input_types,
|
||||
type: templateData.type,
|
||||
id: nodeClass.id,
|
||||
fieldName: templateData.key,
|
||||
};
|
||||
const disabled =
|
||||
edges.some(
|
||||
(edge) =>
|
||||
edge.targetHandle ===
|
||||
scapedJSONStringfy(
|
||||
templateData.proxy
|
||||
? {
|
||||
...id,
|
||||
proxy: templateData.proxy,
|
||||
}
|
||||
: id,
|
||||
),
|
||||
) ?? false;
|
||||
function getCellType() {
|
||||
switch (templateData.type) {
|
||||
case "str":
|
||||
if (!templateData.options) {
|
||||
return templateData?.list ? (
|
||||
<InputListComponent
|
||||
componentName={templateData.key ?? undefined}
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
value={
|
||||
!templateValue || templateValue === "" ? [""] : templateValue
|
||||
}
|
||||
onChange={(value: string[]) => {
|
||||
handleOnNewValue(value, templateData.key);
|
||||
}}
|
||||
/>
|
||||
) : templateData.multiline ? (
|
||||
<TextAreaComponent
|
||||
id={"textarea-edit-" + templateData.name}
|
||||
data-testid={"textarea-edit-" + templateData.name}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={templateValue ?? ""}
|
||||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateData.key);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<InputGlobalComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
onChange={(value) => handleOnNewValue(value, templateData.key)}
|
||||
setDb={(value) => {
|
||||
handleOnChangeDb(value, templateData.key);
|
||||
}}
|
||||
name={templateData.key}
|
||||
data={templateData}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Dropdown
|
||||
editNode={true}
|
||||
options={templateData.options}
|
||||
onSelect={(value) => handleOnNewValue(value, templateData.key)}
|
||||
value={templateValue ?? "Choose an option"}
|
||||
id={"dropdown-edit-" + templateData.name}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
case "NestedDict":
|
||||
return (
|
||||
<DictComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={templateValue.toString() === "{}" ? {} : templateValue}
|
||||
onChange={(newValue) => {
|
||||
handleOnNewValue(newValue, templateData.key);
|
||||
}}
|
||||
id="editnode-div-dict-input"
|
||||
/>
|
||||
);
|
||||
|
||||
case "dict":
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"max-h-48 w-full overflow-auto custom-scroll",
|
||||
templateValue?.length > 1 ? "my-3" : "",
|
||||
)}
|
||||
>
|
||||
<KeypairListComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
templateValue?.length === 0 || !templateValue
|
||||
? [{ "": "" }]
|
||||
: convertObjToArray(templateValue, templateData.type)
|
||||
}
|
||||
duplicateKey={errorDuplicateKey}
|
||||
onChange={(newValue) => {
|
||||
const valueToNumbers = convertValuesToNumbers(newValue);
|
||||
setErrorDuplicateKey(hasDuplicateKeys(valueToNumbers));
|
||||
handleOnNewValue(valueToNumbers, templateData.key);
|
||||
}}
|
||||
isList={templateData.list ?? false}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
case "bool":
|
||||
return (
|
||||
<ToggleShadComponent
|
||||
id={"toggle-edit-" + templateData.name}
|
||||
disabled={disabled}
|
||||
enabled={templateValue}
|
||||
setEnabled={(isEnabled) => {
|
||||
handleOnNewValue(isEnabled, templateData.key);
|
||||
}}
|
||||
size="small"
|
||||
editNode={true}
|
||||
/>
|
||||
);
|
||||
|
||||
case "float":
|
||||
return (
|
||||
<FloatComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
rangeSpec={templateData.rangeSpec}
|
||||
value={templateValue ?? ""}
|
||||
onChange={(value) => {
|
||||
handleOnNewValue(value, templateData.key);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
case "int":
|
||||
return (
|
||||
<IntComponent
|
||||
rangeSpec={templateData.rangeSpec}
|
||||
id={"edit-int-input-" + templateData.name}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={templateValue ?? ""}
|
||||
onChange={(value) => {
|
||||
handleOnNewValue(value, templateData.key);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
case "file":
|
||||
return (
|
||||
<InputFileComponent
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
value={templateValue ?? ""}
|
||||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateData.key);
|
||||
}}
|
||||
fileTypes={templateData.fileTypes}
|
||||
onFileChange={(filePath: string) => {
|
||||
templateData.file_path = filePath;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
case "prompt":
|
||||
return (
|
||||
<PromptAreaComponent
|
||||
readonly={nodeClass.flow ? true : false}
|
||||
field_name={templateData.key}
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
nodeClass={nodeClass}
|
||||
setNodeClass={(value) => {
|
||||
nodeClass = value;
|
||||
}}
|
||||
value={templateValue ?? ""}
|
||||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateData.key);
|
||||
}}
|
||||
id={"prompt-area-edit-" + templateData.name}
|
||||
data-testid={"modal-prompt-input-" + templateData.name}
|
||||
/>
|
||||
);
|
||||
|
||||
case "code":
|
||||
return (
|
||||
<CodeAreaComponent
|
||||
readonly={nodeClass.flow && templateData.dynamic ? true : false}
|
||||
dynamic={templateData.dynamic ?? false}
|
||||
setNodeClass={(value) => {
|
||||
nodeClass = value;
|
||||
}}
|
||||
nodeClass={nodeClass}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={templateValue ?? ""}
|
||||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateData.key);
|
||||
}}
|
||||
id={"code-area-edit" + templateData.name}
|
||||
/>
|
||||
);
|
||||
case "Any":
|
||||
return <>-</>;
|
||||
default:
|
||||
return String(templateValue);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="group flex h-full w-[300px] items-center justify-center py-2.5">
|
||||
{getCellType()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { CustomCellRendererProps } from "ag-grid-react";
|
||||
import { useState } from "react";
|
||||
import ToggleShadComponent from "../../../toggleShadComponent";
|
||||
|
||||
export default function TableToggleCellRender({
|
||||
value: { name, enabled, setEnabled },
|
||||
}: CustomCellRendererProps) {
|
||||
const [value, setValue] = useState(enabled);
|
||||
|
||||
return (
|
||||
<div className="flex h-full items-center">
|
||||
<ToggleShadComponent
|
||||
id={"show" + name}
|
||||
enabled={value}
|
||||
setEnabled={(e) => {
|
||||
setValue(e);
|
||||
setEnabled(e);
|
||||
}}
|
||||
size="small"
|
||||
editNode={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { CustomTooltipProps } from "ag-grid-react";
|
||||
|
||||
export default function TableTooltipRender({ value }: CustomTooltipProps) {
|
||||
return (
|
||||
<div className="z-45 overflow-y-auto rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1">
|
||||
{value}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import "ag-grid-community/styles/ag-grid.css"; // Mandatory CSS required by the grid
|
||||
import "ag-grid-community/styles/ag-theme-quartz.css"; // Optional Theme applied to the grid
|
||||
import { AgGridReact, AgGridReactProps } from "ag-grid-react";
|
||||
import { ElementRef, forwardRef, useEffect, useRef } from "react";
|
||||
import { ElementRef, forwardRef, useRef } from "react";
|
||||
import {
|
||||
DEFAULT_TABLE_ALERT_MSG,
|
||||
DEFAULT_TABLE_ALERT_TITLE,
|
||||
|
|
@ -11,10 +11,8 @@ import "../../style/ag-theme-shadcn.css"; // Custom CSS applied to the grid
|
|||
import { cn, toTitleCase } from "../../utils/utils";
|
||||
import ForwardedIconComponent from "../genericIconComponent";
|
||||
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
|
||||
import { Toggle } from "../ui/toggle";
|
||||
import ShadTooltip from "../shadTooltipComponent";
|
||||
import resetGrid from "./utils/reset-grid-columns";
|
||||
import ResetColumns from "./components/ResetColumns";
|
||||
import resetGrid from "./utils/reset-grid-columns";
|
||||
|
||||
interface TableComponentProps extends AgGridReactProps {
|
||||
columnDefs: NonNullable<AgGridReactProps["columnDefs"]>;
|
||||
|
|
@ -34,7 +32,7 @@ const TableComponent = forwardRef<
|
|||
alertDescription = DEFAULT_TABLE_ALERT_MSG,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
ref
|
||||
) => {
|
||||
let colDef = props.columnDefs.map((col, index) => {
|
||||
let newCol = {
|
||||
|
|
@ -91,7 +89,7 @@ const TableComponent = forwardRef<
|
|||
|
||||
const onColumnMoved = (params) => {
|
||||
const updatedColumnDefs = makeLastColumnNonResizable(
|
||||
params.columnApi.getAllGridColumns().map((col) => col.getColDef()),
|
||||
params.columnApi.getAllGridColumns().map((col) => col.getColDef())
|
||||
);
|
||||
params.api.setColumnDefs(updatedColumnDefs);
|
||||
if (props.onColumnMoved) props.onColumnMoved(params);
|
||||
|
|
@ -116,7 +114,7 @@ const TableComponent = forwardRef<
|
|||
className={cn(
|
||||
dark ? "ag-theme-quartz-dark" : "ag-theme-quartz",
|
||||
"ag-theme-shadcn flex h-full flex-col",
|
||||
"relative",
|
||||
"relative"
|
||||
)} // applying the grid theme
|
||||
>
|
||||
<AgGridReact
|
||||
|
|
@ -126,9 +124,11 @@ const TableComponent = forwardRef<
|
|||
minWidth: 100,
|
||||
autoHeight: true,
|
||||
}}
|
||||
tooltipInteraction={true}
|
||||
columnDefs={colDef}
|
||||
ref={realRef}
|
||||
getRowId={(params) => {
|
||||
return params.data.id;
|
||||
}}
|
||||
pagination={true}
|
||||
onGridReady={onGridReady}
|
||||
onColumnMoved={onColumnMoved}
|
||||
|
|
@ -136,7 +136,7 @@ const TableComponent = forwardRef<
|
|||
<ResetColumns resetGrid={() => resetGrid(realRef, initialColumnDefs)} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export default TableComponent;
|
||||
|
|
|
|||
|
|
@ -29,20 +29,18 @@ export default function ToggleShadComponent({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={disabled ? "pointer-events-none cursor-not-allowed " : ""}>
|
||||
<Switch
|
||||
id={id}
|
||||
data-testid={id}
|
||||
style={{
|
||||
transform: `scaleX(${scaleX}) scaleY(${scaleY})`,
|
||||
}}
|
||||
disabled={disabled}
|
||||
className=""
|
||||
checked={enabled}
|
||||
onCheckedChange={(isEnabled: boolean) => {
|
||||
setEnabled(isEnabled);
|
||||
}}
|
||||
></Switch>
|
||||
</div>
|
||||
<Switch
|
||||
id={id}
|
||||
data-testid={id}
|
||||
style={{
|
||||
transform: `scaleX(${scaleX}) scaleY(${scaleY})`,
|
||||
}}
|
||||
disabled={disabled}
|
||||
className=""
|
||||
checked={enabled}
|
||||
onCheckedChange={(isEnabled: boolean) => {
|
||||
setEnabled(isEnabled);
|
||||
}}
|
||||
></Switch>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ const AccordionTrigger = React.forwardRef<
|
|||
<div
|
||||
className={cn(
|
||||
"flex flex-1 cursor-pointer items-center justify-between py-4 text-sm font-medium transition-all [&[data-state=open]>svg]:rotate-180",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
|
@ -46,7 +46,7 @@ const AccordionTrigger = React.forwardRef<
|
|||
<ChevronDownIcon
|
||||
className={cn(
|
||||
"h-4 w-4 font-bold transition-transform duration-200",
|
||||
disabled ? "text-muted-foreground" : "text-primary",
|
||||
disabled ? "text-muted-foreground" : "text-primary"
|
||||
)}
|
||||
/>
|
||||
</ShadTooltip>
|
||||
|
|
@ -64,7 +64,7 @@ const AccordionContent = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const buttonVariants = cva(
|
|||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export interface ButtonProps
|
||||
|
|
@ -59,12 +59,13 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|||
variant,
|
||||
size,
|
||||
loading,
|
||||
type,
|
||||
disabled,
|
||||
asChild = false,
|
||||
children,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
ref
|
||||
) => {
|
||||
const Comp = asChild ? Slot : "button";
|
||||
let newChildren = children;
|
||||
|
|
@ -76,6 +77,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
disabled={loading || disabled}
|
||||
{...(asChild ? {} : { type: type || "button" })}
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
|
|
@ -95,7 +97,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|||
</Comp>
|
||||
</>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
Button.displayName = "Button";
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const Card = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"flex flex-col justify-between rounded-lg border bg-muted text-card-foreground shadow-sm transition-all",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -36,7 +36,7 @@ const CardTitle = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"text-base font-semibold leading-tight tracking-tight",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -31,11 +31,7 @@ function RefreshButton({
|
|||
|
||||
// icon class name should take into account the disabled state and the loading state
|
||||
const disabledIconTextClass = disabled ? "text-muted-foreground" : "";
|
||||
const iconClassName = cn(
|
||||
"h-4 w-4",
|
||||
isLoading ? "animate-spin" : "animate-wiggle",
|
||||
disabledIconTextClass
|
||||
);
|
||||
const iconClassName = cn("h-4 w-4 animate-wiggle", disabledIconTextClass);
|
||||
|
||||
return (
|
||||
<Button
|
||||
|
|
@ -44,10 +40,11 @@ function RefreshButton({
|
|||
className={classNames}
|
||||
onClick={handleClick}
|
||||
id={id}
|
||||
loading={isLoading}
|
||||
>
|
||||
{button_text && <span className="mr-1">{button_text}</span>}
|
||||
<IconComponent
|
||||
name={isLoading ? "Loader2" : "RefreshCcw"}
|
||||
name={"RefreshCcw"}
|
||||
className={iconClassName}
|
||||
id={id + "-icon"}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as TogglePrimitive from "@radix-ui/react-toggle";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../utils/utils";
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ const toggleVariants = cva(
|
|||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const Toggle = React.forwardRef<
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ const TooltipContent = React.forwardRef<
|
|||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-45 overflow-y-auto rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -37,7 +37,7 @@ const TooltipContentWithoutPortal = React.forwardRef<
|
|||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-45 overflow-y-auto rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export const USER_EDIT_ERROR_ALERT = "Error on edit user";
|
|||
export const USER_ADD_ERROR_ALERT = "Error when adding new user";
|
||||
export const SIGNIN_ERROR_ALERT = "Error signing in";
|
||||
export const DEL_KEY_ERROR_ALERT = "Error on delete key";
|
||||
export const DEL_KEY_ERROR_ALERT_PLURAL = "Error on delete keys";
|
||||
export const UPLOAD_ERROR_ALERT = "Error uploading file";
|
||||
export const WRONG_FILE_ERROR_ALERT = "Invalid file type";
|
||||
export const UPLOAD_ALERT_LIST = "Please upload a JSON file";
|
||||
|
|
@ -54,6 +55,7 @@ export const USER_DEL_SUCCESS_ALERT = "Success! User deleted!";
|
|||
export const USER_EDIT_SUCCESS_ALERT = "Success! User edited!";
|
||||
export const USER_ADD_SUCCESS_ALERT = "Success! New user added!";
|
||||
export const DEL_KEY_SUCCESS_ALERT = "Success! Key deleted!";
|
||||
export const DEL_KEY_SUCCESS_ALERT_PLURAL = "Success! Keys deleted!";
|
||||
export const FLOW_BUILD_SUCCESS_ALERT = `Flow built successfully`;
|
||||
export const SAVE_SUCCESS_ALERT = "Changes saved successfully!";
|
||||
|
||||
|
|
|
|||
|
|
@ -613,11 +613,8 @@ export const FETCH_ERROR_DESCRIPION =
|
|||
|
||||
export const SIGN_UP_SUCCESS = "Account created! Await admin activation. ";
|
||||
|
||||
export const API_PAGE_PARAGRAPH_1 =
|
||||
"Your secret API keys are listed below. Please note that we do not display your secret API keys again after you generate them.";
|
||||
|
||||
export const API_PAGE_PARAGRAPH_2 =
|
||||
"Do not share your API key with others, or expose it in the browser or other client-side code.";
|
||||
export const API_PAGE_PARAGRAPH =
|
||||
"Your secret API keys are listed below. Do not share your API key with others, or expose it in the browser or other client-side code.";
|
||||
|
||||
export const API_PAGE_USER_KEYS =
|
||||
"This user does not have any keys assigned at the moment.";
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export function checkDuplicateRequestAndStoreRequest(config) {
|
|||
const currentTime = Date.now();
|
||||
|
||||
const isContained = AUTHORIZED_DUPLICATE_REQUESTS.some((request) =>
|
||||
config?.url!.includes(request),
|
||||
config?.url!.includes(request)
|
||||
);
|
||||
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
} from "../../types/api/index";
|
||||
import { UserInputType } from "../../types/components";
|
||||
import { FlowStyleType, FlowType } from "../../types/flow";
|
||||
import { Message } from "../../types/messages";
|
||||
import { StoreComponentResponse } from "../../types/store";
|
||||
import { FlowPoolType } from "../../types/zustand/flow";
|
||||
import { extractColumnsFromRows } from "../../utils/utils";
|
||||
|
|
@ -28,7 +29,6 @@ import {
|
|||
UploadFileTypeAPI,
|
||||
errorsTypeAPI,
|
||||
} from "./../../types/api/index";
|
||||
import { Message } from "../../types/messages";
|
||||
|
||||
/**
|
||||
* Fetches all objects from the API endpoint.
|
||||
|
|
@ -62,7 +62,7 @@ export async function sendAll(data: sendAllProps) {
|
|||
}
|
||||
|
||||
export async function postValidateCode(
|
||||
code: string,
|
||||
code: string
|
||||
): Promise<AxiosResponse<errorsTypeAPI>> {
|
||||
return await api.post(`${BASE_URL_API}validate/code`, { code });
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ export async function postValidateCode(
|
|||
export async function postValidatePrompt(
|
||||
name: string,
|
||||
template: string,
|
||||
frontend_node: APIClassType,
|
||||
frontend_node: APIClassType
|
||||
): Promise<AxiosResponse<PromptTypeAPI>> {
|
||||
return api.post(`${BASE_URL_API}validate/prompt`, {
|
||||
name,
|
||||
|
|
@ -150,7 +150,7 @@ export async function saveFlowToDatabase(newFlow: {
|
|||
* @throws Will throw an error if the update fails.
|
||||
*/
|
||||
export async function updateFlowInDatabase(
|
||||
updatedFlow: FlowType,
|
||||
updatedFlow: FlowType
|
||||
): Promise<FlowType> {
|
||||
try {
|
||||
const response = await api.patch(`${BASE_URL_API}flows/${updatedFlow.id}`, {
|
||||
|
|
@ -328,7 +328,7 @@ export async function getHealth() {
|
|||
*
|
||||
*/
|
||||
export async function getBuildStatus(
|
||||
flowId: string,
|
||||
flowId: string
|
||||
): Promise<AxiosResponse<BuildStatusTypeAPI>> {
|
||||
return await api.get(`${BASE_URL_API}build/${flowId}/status`);
|
||||
}
|
||||
|
|
@ -341,7 +341,7 @@ export async function getBuildStatus(
|
|||
*
|
||||
*/
|
||||
export async function postBuildInit(
|
||||
flow: FlowType,
|
||||
flow: FlowType
|
||||
): Promise<AxiosResponse<InitTypeAPI>> {
|
||||
return await api.post(`${BASE_URL_API}build/init/${flow.id}`, flow);
|
||||
}
|
||||
|
|
@ -357,7 +357,7 @@ export async function postBuildInit(
|
|||
*/
|
||||
export async function uploadFile(
|
||||
file: File,
|
||||
id: string,
|
||||
id: string
|
||||
): Promise<AxiosResponse<UploadFileTypeAPI>> {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
|
@ -366,7 +366,7 @@ export async function uploadFile(
|
|||
|
||||
export async function postCustomComponent(
|
||||
code: string,
|
||||
apiClass: APIClassType,
|
||||
apiClass: APIClassType
|
||||
): Promise<AxiosResponse<APIClassType>> {
|
||||
// let template = apiClass.template;
|
||||
return await api.post(`${BASE_URL_API}custom_component`, {
|
||||
|
|
@ -379,7 +379,7 @@ export async function postCustomComponentUpdate(
|
|||
code: string,
|
||||
template: APITemplateType,
|
||||
field: string,
|
||||
field_value: any,
|
||||
field_value: any
|
||||
): Promise<AxiosResponse<APIClassType>> {
|
||||
return await api.post(`${BASE_URL_API}custom_component/update`, {
|
||||
code,
|
||||
|
|
@ -401,7 +401,7 @@ export async function onLogin(user: LoginType) {
|
|||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
|
|
@ -463,11 +463,11 @@ export async function addUser(user: UserInputType): Promise<Array<Users>> {
|
|||
|
||||
export async function getUsersPage(
|
||||
skip: number,
|
||||
limit: number,
|
||||
limit: number
|
||||
): Promise<Array<Users>> {
|
||||
try {
|
||||
const res = await api.get(
|
||||
`${BASE_URL_API}users/?skip=${skip}&limit=${limit}`,
|
||||
`${BASE_URL_API}users/?skip=${skip}&limit=${limit}`
|
||||
);
|
||||
if (res.status === 200) {
|
||||
return res.data;
|
||||
|
|
@ -504,7 +504,7 @@ export async function resetPassword(user_id: string, user: resetPasswordType) {
|
|||
try {
|
||||
const res = await api.patch(
|
||||
`${BASE_URL_API}users/${user_id}/reset-password`,
|
||||
user,
|
||||
user
|
||||
);
|
||||
if (res.status === 200) {
|
||||
return res.data;
|
||||
|
|
@ -578,7 +578,7 @@ export async function saveFlowStore(
|
|||
last_tested_version?: string;
|
||||
},
|
||||
tags: string[],
|
||||
publicFlow = false,
|
||||
publicFlow = false
|
||||
): Promise<FlowType> {
|
||||
try {
|
||||
const response = await api.post(`${BASE_URL_API}store/components/`, {
|
||||
|
|
@ -707,7 +707,7 @@ export async function postStoreComponents(component: Component) {
|
|||
export async function getComponent(component_id: string) {
|
||||
try {
|
||||
const res = await api.get(
|
||||
`${BASE_URL_API}store/components/${component_id}`,
|
||||
`${BASE_URL_API}store/components/${component_id}`
|
||||
);
|
||||
if (res.status === 200) {
|
||||
return res.data;
|
||||
|
|
@ -722,7 +722,7 @@ export async function searchComponent(
|
|||
page?: number | null,
|
||||
limit?: number | null,
|
||||
status?: string | null,
|
||||
tags?: string[],
|
||||
tags?: string[]
|
||||
): Promise<StoreComponentResponse | undefined> {
|
||||
try {
|
||||
let url = `${BASE_URL_API}store/components/`;
|
||||
|
|
@ -834,7 +834,7 @@ export async function updateFlowStore(
|
|||
},
|
||||
tags: string[],
|
||||
publicFlow = false,
|
||||
id: string,
|
||||
id: string
|
||||
): Promise<FlowType> {
|
||||
try {
|
||||
const response = await api.patch(`${BASE_URL_API}store/components/${id}`, {
|
||||
|
|
@ -918,7 +918,7 @@ export async function deleteGlobalVariable(id: string) {
|
|||
export async function updateGlobalVariable(
|
||||
name: string,
|
||||
value: string,
|
||||
id: string,
|
||||
id: string
|
||||
) {
|
||||
try {
|
||||
const response = api.patch(`${BASE_URL_API}variables/${id}`, {
|
||||
|
|
@ -937,7 +937,7 @@ export async function getVerticesOrder(
|
|||
startNodeId?: string | null,
|
||||
stopNodeId?: string | null,
|
||||
nodes?: Node[],
|
||||
Edges?: Edge[],
|
||||
Edges?: Edge[]
|
||||
): Promise<AxiosResponse<VerticesOrderTypeAPI>> {
|
||||
// nodeId is optional and is a query parameter
|
||||
// if nodeId is not provided, the API will return all vertices
|
||||
|
|
@ -957,7 +957,7 @@ export async function getVerticesOrder(
|
|||
return await api.post(
|
||||
`${BASE_URL_API}build/${flowId}/vertices`,
|
||||
data,
|
||||
config,
|
||||
config
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -965,7 +965,7 @@ export async function postBuildVertex(
|
|||
flowId: string,
|
||||
vertexId: string,
|
||||
input_value: string,
|
||||
files?: string[],
|
||||
files?: string[]
|
||||
): Promise<AxiosResponse<VertexBuildTypeAPI>> {
|
||||
// input_value is optional and is a query parameter
|
||||
const data = input_value
|
||||
|
|
@ -976,7 +976,7 @@ export async function postBuildVertex(
|
|||
}
|
||||
return await api.post(
|
||||
`${BASE_URL_API}build/${flowId}/vertices/${vertexId}`,
|
||||
data,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1000,7 +1000,7 @@ export async function getFlowPool({
|
|||
}
|
||||
|
||||
export async function deleteFlowPool(
|
||||
flowId: string,
|
||||
flowId: string
|
||||
): Promise<AxiosResponse<any>> {
|
||||
const config = {};
|
||||
config["params"] = { flow_id: flowId };
|
||||
|
|
@ -1014,7 +1014,7 @@ export async function deleteFlowPool(
|
|||
* @returns A promise that resolves to an array of AxiosResponse objects representing the delete responses.
|
||||
*/
|
||||
export async function multipleDeleteFlowsComponents(
|
||||
flowIds: string[],
|
||||
flowIds: string[]
|
||||
): Promise<AxiosResponse<any>[]> {
|
||||
const batches: string[][] = [];
|
||||
|
||||
|
|
@ -1037,7 +1037,7 @@ export async function multipleDeleteFlowsComponents(
|
|||
|
||||
// Execute all delete requests
|
||||
const responses: Promise<AxiosResponse<any>>[] = batches.map((batch) =>
|
||||
deleteBatch(batch),
|
||||
deleteBatch(batch)
|
||||
);
|
||||
|
||||
// Return the responses after all requests are completed
|
||||
|
|
@ -1047,7 +1047,7 @@ export async function multipleDeleteFlowsComponents(
|
|||
export async function getTransactionTable(
|
||||
id: string,
|
||||
mode: "intersection" | "union",
|
||||
params = {},
|
||||
params = {}
|
||||
): Promise<{ rows: Array<object>; columns: Array<ColDef | ColGroupDef> }> {
|
||||
const config = {};
|
||||
config["params"] = { flow_id: id };
|
||||
|
|
@ -1063,7 +1063,7 @@ export async function getMessagesTable(
|
|||
mode: "intersection" | "union",
|
||||
id?: string,
|
||||
excludedFields?: string[],
|
||||
params = {},
|
||||
params = {}
|
||||
): Promise<{ rows: Array<Message>; columns: Array<ColDef | ColGroupDef> }> {
|
||||
const config = {};
|
||||
if (id) {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ export default function ParameterComponent({
|
|||
debouncedHandleUpdateValues,
|
||||
setNode,
|
||||
renderTooltips,
|
||||
setIsLoading,
|
||||
setIsLoading
|
||||
);
|
||||
|
||||
const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
|
||||
|
|
@ -107,7 +107,7 @@ export default function ParameterComponent({
|
|||
takeSnapshot,
|
||||
setNode,
|
||||
updateNodeInternals,
|
||||
renderTooltips,
|
||||
renderTooltips
|
||||
);
|
||||
|
||||
const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
|
||||
|
|
@ -116,7 +116,7 @@ export default function ParameterComponent({
|
|||
let disabled =
|
||||
edges.some(
|
||||
(edge) =>
|
||||
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
|
||||
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id)
|
||||
) ?? false;
|
||||
|
||||
const handleRefreshButtonPress = async (name, data) => {
|
||||
|
|
@ -129,12 +129,12 @@ export default function ParameterComponent({
|
|||
handleUpdateValues,
|
||||
setNode,
|
||||
renderTooltips,
|
||||
setIsLoading,
|
||||
setIsLoading
|
||||
);
|
||||
|
||||
const handleOnNewValue = async (
|
||||
newValue: string | string[] | boolean | Object[],
|
||||
skipSnapshot: boolean | undefined = false,
|
||||
skipSnapshot: boolean | undefined = false
|
||||
): Promise<void> => {
|
||||
handleOnNewValueHook(newValue, skipSnapshot);
|
||||
};
|
||||
|
|
@ -216,7 +216,7 @@ export default function ParameterComponent({
|
|||
className={classNames(
|
||||
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
|
||||
"h-3 w-3 rounded-full border-2 bg-background",
|
||||
!showNode ? "mt-0" : "",
|
||||
!showNode ? "mt-0" : ""
|
||||
)}
|
||||
style={{
|
||||
borderColor: color ?? nodeColors.unknown,
|
||||
|
|
@ -334,7 +334,7 @@ export default function ParameterComponent({
|
|||
}
|
||||
className={classNames(
|
||||
left ? "-ml-0.5" : "-mr-0.5",
|
||||
"h-3 w-3 rounded-full border-2 bg-background",
|
||||
"h-3 w-3 rounded-full border-2 bg-background"
|
||||
)}
|
||||
style={{ borderColor: color ?? nodeColors.unknown }}
|
||||
onClick={() => setFilterEdge(groupedEdge.current)}
|
||||
|
|
@ -430,7 +430,7 @@ export default function ParameterComponent({
|
|||
});
|
||||
}}
|
||||
name={name}
|
||||
data={data}
|
||||
data={data.node?.template[name]}
|
||||
/>
|
||||
</div>
|
||||
{data.node?.template[name]?.refresh_button && (
|
||||
|
|
@ -486,8 +486,8 @@ export default function ParameterComponent({
|
|||
data.node?.template[name]?.real_time_refresh)
|
||||
}
|
||||
>
|
||||
<div className="mt-2 flex w-full items-center">
|
||||
<div className="w-5/6 flex-grow">
|
||||
<div className="mt-2 flex w-full items-center gap-2">
|
||||
<div className="flex-1">
|
||||
<Dropdown
|
||||
disabled={disabled}
|
||||
isLoading={isLoading}
|
||||
|
|
@ -505,7 +505,6 @@ export default function ParameterComponent({
|
|||
name={name}
|
||||
data={data}
|
||||
button_text={data.node?.template[name]?.refresh_button_text}
|
||||
className="extra-side-bar-buttons ml-2 mt-1"
|
||||
handleUpdateValues={handleRefreshButtonPress}
|
||||
id={"refresh-button-" + name}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -54,10 +54,10 @@ export default function GenericNode({
|
|||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const isDark = useDarkStore((state) => state.dark);
|
||||
const buildStatus = useFlowStore(
|
||||
(state) => state.flowBuildStatus[data.id]?.status,
|
||||
(state) => state.flowBuildStatus[data.id]?.status
|
||||
);
|
||||
const lastRunTime = useFlowStore(
|
||||
(state) => state.flowBuildStatus[data.id]?.timestamp,
|
||||
(state) => state.flowBuildStatus[data.id]?.timestamp
|
||||
);
|
||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ export default function GenericNode({
|
|||
const [nodeName, setNodeName] = useState(data.node!.display_name);
|
||||
const [inputDescription, setInputDescription] = useState(false);
|
||||
const [nodeDescription, setNodeDescription] = useState(
|
||||
data.node?.description!,
|
||||
data.node?.description!
|
||||
);
|
||||
const [isOutdated, setIsOutdated] = useState(false);
|
||||
const [validationStatus, setValidationStatus] =
|
||||
|
|
@ -83,7 +83,7 @@ export default function GenericNode({
|
|||
data.node!,
|
||||
setNode,
|
||||
setIsOutdated,
|
||||
updateNodeInternals,
|
||||
updateNodeInternals
|
||||
);
|
||||
|
||||
const name = nodeIconsLucide[data.type] ? data.type : types[data.type];
|
||||
|
|
@ -114,12 +114,12 @@ export default function GenericNode({
|
|||
selected: boolean,
|
||||
showNode: boolean,
|
||||
buildStatus: BuildStatus | undefined,
|
||||
validationStatus: VertexBuildTypeAPI | null,
|
||||
validationStatus: validationStatusType | null
|
||||
) => {
|
||||
const specificClassFromBuildStatus = getSpecificClassFromBuildStatus(
|
||||
buildStatus,
|
||||
validationStatus,
|
||||
isDark,
|
||||
isDark
|
||||
);
|
||||
|
||||
const baseBorderClass = getBaseBorderClass(selected);
|
||||
|
|
@ -128,7 +128,7 @@ export default function GenericNode({
|
|||
baseBorderClass,
|
||||
nodeSizeClass,
|
||||
"generic-node-div",
|
||||
specificClassFromBuildStatus,
|
||||
specificClassFromBuildStatus
|
||||
);
|
||||
return names;
|
||||
};
|
||||
|
|
@ -170,7 +170,7 @@ export default function GenericNode({
|
|||
showNode,
|
||||
isEmoji,
|
||||
nodeIconFragment,
|
||||
checkNodeIconFragment,
|
||||
checkNodeIconFragment
|
||||
);
|
||||
|
||||
function countHandles(): void {
|
||||
|
|
@ -247,7 +247,7 @@ export default function GenericNode({
|
|||
selected,
|
||||
showNode,
|
||||
buildStatus,
|
||||
validationStatus,
|
||||
validationStatus
|
||||
)}
|
||||
>
|
||||
{data.node?.beta && showNode && (
|
||||
|
|
@ -378,7 +378,7 @@ export default function GenericNode({
|
|||
}
|
||||
title={getFieldTitle(
|
||||
data.node?.template!,
|
||||
templateField,
|
||||
templateField
|
||||
)}
|
||||
info={data.node?.template[templateField].info}
|
||||
name={templateField}
|
||||
|
|
@ -406,7 +406,7 @@ export default function GenericNode({
|
|||
proxy={data.node?.template[templateField].proxy}
|
||||
showNode={showNode}
|
||||
/>
|
||||
),
|
||||
)
|
||||
)}
|
||||
<ParameterComponent
|
||||
key={scapedJSONStringfy({
|
||||
|
|
@ -552,7 +552,7 @@ export default function GenericNode({
|
|||
!data.node?.description) &&
|
||||
nameEditable
|
||||
? "font-light italic"
|
||||
: "",
|
||||
: ""
|
||||
)}
|
||||
onClick={(e) => {
|
||||
setInputDescription(true);
|
||||
|
|
@ -614,13 +614,13 @@ export default function GenericNode({
|
|||
}
|
||||
title={getFieldTitle(
|
||||
data.node?.template!,
|
||||
templateField,
|
||||
templateField
|
||||
)}
|
||||
info={data.node?.template[templateField].info}
|
||||
name={templateField}
|
||||
tooltipTitle={
|
||||
data.node?.template[templateField].input_types?.join(
|
||||
"\n",
|
||||
"\n"
|
||||
) ?? data.node?.template[templateField].type
|
||||
}
|
||||
required={data.node!.template[templateField].required}
|
||||
|
|
@ -647,7 +647,7 @@ export default function GenericNode({
|
|||
<div
|
||||
className={classNames(
|
||||
Object.keys(data.node!.template).length < 1 ? "hidden" : "",
|
||||
"flex-max-width justify-center",
|
||||
"flex-max-width justify-center"
|
||||
)}
|
||||
>
|
||||
{" "}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { APITemplateType } from "../../types/api";
|
|||
|
||||
export default function getFieldTitle(
|
||||
template: APITemplateType,
|
||||
templateField: string,
|
||||
templateField: string
|
||||
): string {
|
||||
return template[templateField].display_name
|
||||
? template[templateField].display_name!
|
||||
|
|
|
|||
25
src/frontend/src/icons/Streamlit/SvgStreamlit.jsx
Normal file
25
src/frontend/src/icons/Streamlit/SvgStreamlit.jsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
export default function SvgStreamlit(props) {
|
||||
return (
|
||||
<svg
|
||||
width="301"
|
||||
height="165"
|
||||
viewBox="0 0 301 165"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M150.731 101.547L98.1387 73.7471L6.84674 25.4969C6.7634 25.4136 6.59674 25.4136 6.51341 25.4136C3.18007 23.8303 -0.236608 27.1636 1.0134 30.497L47.5302 149.139L47.5385 149.164C47.5885 149.281 47.6302 149.397 47.6802 149.514C49.5885 153.939 53.7552 156.672 58.2886 157.747C58.6719 157.831 58.9461 157.906 59.4064 157.998C59.8645 158.1 60.5052 158.239 61.0552 158.281C61.1469 158.289 61.2302 158.289 61.3219 158.297H61.3886C61.4552 158.306 61.5219 158.306 61.5886 158.314H61.6802C61.7386 158.322 61.8052 158.322 61.8636 158.322H61.9719C62.0386 158.331 62.1052 158.331 62.1719 158.331V158.331C121.084 164.754 180.519 164.754 239.431 158.331V158.331C240.139 158.331 240.831 158.297 241.497 158.231C241.714 158.206 241.922 158.181 242.131 158.156C242.156 158.147 242.189 158.147 242.214 158.139C242.356 158.122 242.497 158.097 242.639 158.072C242.847 158.047 243.056 158.006 243.264 157.964C243.681 157.872 243.87 157.806 244.436 157.611C245.001 157.417 245.94 157.077 246.527 156.794C247.115 156.511 247.522 156.239 248.014 155.931C248.622 155.547 249.201 155.155 249.788 154.715C250.041 154.521 250.214 154.397 250.397 154.222L250.297 154.164L150.731 101.547Z"
|
||||
fill="#FF4B4B"
|
||||
/>
|
||||
<path
|
||||
d="M294.766 25.4981H294.683L203.357 73.7483L254.124 149.357L300.524 30.4981V30.3315C301.691 26.8314 298.108 23.6648 294.766 25.4981"
|
||||
fill="#7D353B"
|
||||
/>
|
||||
<path
|
||||
d="M155.598 2.55572C153.264 -0.852624 148.181 -0.852624 145.931 2.55572L98.1389 73.7477L150.731 101.548L250.398 154.222C251.024 153.609 251.526 153.012 252.056 152.381C252.806 151.456 253.506 150.465 254.123 149.356L203.356 73.7477L155.598 2.55572Z"
|
||||
fill="#BD4043"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
8
src/frontend/src/icons/Streamlit/index.tsx
Normal file
8
src/frontend/src/icons/Streamlit/index.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import SvgStreamlit from "./SvgStreamlit";
|
||||
|
||||
export const Streamlit = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <SvgStreamlit className="icon" ref={ref} {...props} />;
|
||||
}
|
||||
);
|
||||
|
|
@ -27,7 +27,7 @@ const useFolderSubmit = (setOpen, folderToEdit) => {
|
|||
getFoldersApi(true);
|
||||
setOpen(false);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
} else {
|
||||
addFolder(data).then(
|
||||
|
|
@ -42,7 +42,7 @@ const useFolderSubmit = (setOpen, folderToEdit) => {
|
|||
setErrorData({
|
||||
title: `Error creating folder.`,
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -114,19 +114,19 @@ export default function ChatMessage({
|
|||
<div
|
||||
className={classNames(
|
||||
"form-modal-chat-position",
|
||||
chat.isSend ? "" : " ",
|
||||
chat.isSend ? "" : " "
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
"mr-3 mt-1 flex w-24 flex-col items-center gap-1 overflow-hidden px-3 pb-3",
|
||||
"mr-3 mt-1 flex w-24 flex-col items-center gap-1 overflow-hidden px-3 pb-3"
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<div
|
||||
className={cn(
|
||||
"relative flex h-8 w-8 items-center justify-center overflow-hidden rounded-md p-5 text-2xl",
|
||||
!chat.isSend ? "bg-chat-bot-icon" : "bg-chat-user-icon",
|
||||
!chat.isSend ? "bg-chat-bot-icon" : "bg-chat-user-icon"
|
||||
)}
|
||||
>
|
||||
<img
|
||||
|
|
@ -210,12 +210,12 @@ dark:prose-invert"
|
|||
|
||||
children[0] = (children[0] as string).replace(
|
||||
"`▍`",
|
||||
"▍",
|
||||
"▍"
|
||||
);
|
||||
}
|
||||
|
||||
const match = /language-(\w+)/.exec(
|
||||
className || "",
|
||||
className || ""
|
||||
);
|
||||
|
||||
return !inline ? (
|
||||
|
|
@ -230,12 +230,12 @@ dark:prose-invert"
|
|||
language: (match && match[1]) || "",
|
||||
code: String(children).replace(
|
||||
/\n$/,
|
||||
"",
|
||||
""
|
||||
),
|
||||
},
|
||||
]}
|
||||
activeTab={"0"}
|
||||
setActiveTab={() => { }}
|
||||
setActiveTab={() => {}}
|
||||
/>
|
||||
) : (
|
||||
<code className={className} {...props}>
|
||||
|
|
@ -248,7 +248,7 @@ dark:prose-invert"
|
|||
{chatMessage}
|
||||
</Markdown>
|
||||
),
|
||||
[chat.message, chatMessage],
|
||||
[chat.message, chatMessage]
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -277,33 +277,33 @@ dark:prose-invert"
|
|||
<span className="prose text-primary word-break-break-word dark:prose-invert">
|
||||
{promptOpen
|
||||
? template?.split("\n")?.map((line, index) => {
|
||||
const regex = /{([^}]+)}/g;
|
||||
let match;
|
||||
let parts: Array<JSX.Element | string> = [];
|
||||
let lastIndex = 0;
|
||||
while ((match = regex.exec(line)) !== null) {
|
||||
// Push text up to the match
|
||||
if (match.index !== lastIndex) {
|
||||
parts.push(line.substring(lastIndex, match.index));
|
||||
}
|
||||
// Push div with matched text
|
||||
if (chat.message[match[1]]) {
|
||||
parts.push(
|
||||
<span className="chat-message-highlight">
|
||||
{chat.message[match[1]]}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
const regex = /{([^}]+)}/g;
|
||||
let match;
|
||||
let parts: Array<JSX.Element | string> = [];
|
||||
let lastIndex = 0;
|
||||
while ((match = regex.exec(line)) !== null) {
|
||||
// Push text up to the match
|
||||
if (match.index !== lastIndex) {
|
||||
parts.push(line.substring(lastIndex, match.index));
|
||||
}
|
||||
// Push div with matched text
|
||||
if (chat.message[match[1]]) {
|
||||
parts.push(
|
||||
<span className="chat-message-highlight">
|
||||
{chat.message[match[1]]}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
// Update last index
|
||||
lastIndex = regex.lastIndex;
|
||||
}
|
||||
// Push text after the last match
|
||||
if (lastIndex !== line.length) {
|
||||
parts.push(line.substring(lastIndex));
|
||||
}
|
||||
return <p>{parts}</p>;
|
||||
})
|
||||
// Update last index
|
||||
lastIndex = regex.lastIndex;
|
||||
}
|
||||
// Push text after the last match
|
||||
if (lastIndex !== line.length) {
|
||||
parts.push(line.substring(lastIndex));
|
||||
}
|
||||
return <p>{parts}</p>;
|
||||
})
|
||||
: chatMessage}
|
||||
</span>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import IconComponent from "../../../../components/genericIconComponent";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
} from "../../../../components/ui/select";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import {
|
||||
CHAT_FIRST_INITIAL_TEXT,
|
||||
CHAT_SECOND_INITIAL_TEXT,
|
||||
|
|
@ -67,7 +62,7 @@ export default function ChatView({
|
|||
.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp))
|
||||
//
|
||||
.filter(
|
||||
(output) => output.data.messages && output.data.messages.length > 0,
|
||||
(output) => output.data.messages && output.data.messages.length > 0
|
||||
)
|
||||
.map((output, index) => {
|
||||
try {
|
||||
|
|
@ -136,7 +131,7 @@ export default function ChatView({
|
|||
function updateChat(
|
||||
chat: ChatMessageType,
|
||||
message: string,
|
||||
stream_url?: string,
|
||||
stream_url?: string
|
||||
) {
|
||||
// if (message === "") return;
|
||||
chat.message = message;
|
||||
|
|
@ -164,19 +159,21 @@ export default function ChatView({
|
|||
<div className="eraser-column-arrangement">
|
||||
<div className="eraser-size">
|
||||
<div className="eraser-position">
|
||||
<button
|
||||
<Button
|
||||
className="flex gap-1"
|
||||
size="none"
|
||||
variant="none"
|
||||
onClick={() => handleSelectChange("builds")}
|
||||
>
|
||||
<IconComponent
|
||||
name="Eraser"
|
||||
className={classNames(
|
||||
"h-5 w-5 transition-all duration-100",
|
||||
lockChat ? "animate-pulse text-primary" : "text-primary",
|
||||
lockChat ? "animate-pulse text-primary" : "text-primary"
|
||||
)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</Button>
|
||||
{/* <Select
|
||||
onValueChange={handleSelectChange}
|
||||
value=""
|
||||
|
|
|
|||
|
|
@ -34,25 +34,25 @@ export default function IOModal({
|
|||
}: IOModalPropsType): JSX.Element {
|
||||
const allNodes = useFlowStore((state) => state.nodes);
|
||||
const inputs = useFlowStore((state) => state.inputs).filter(
|
||||
(input) => input.type !== "ChatInput",
|
||||
(input) => input.type !== "ChatInput"
|
||||
);
|
||||
const chatInput = useFlowStore((state) => state.inputs).find(
|
||||
(input) => input.type === "ChatInput",
|
||||
(input) => input.type === "ChatInput"
|
||||
);
|
||||
const outputs = useFlowStore((state) => state.outputs).filter(
|
||||
(output) => output.type !== "ChatOutput",
|
||||
(output) => output.type !== "ChatOutput"
|
||||
);
|
||||
const chatOutput = useFlowStore((state) => state.outputs).find(
|
||||
(output) => output.type === "ChatOutput",
|
||||
(output) => output.type === "ChatOutput"
|
||||
);
|
||||
const nodes = useFlowStore((state) => state.nodes).filter(
|
||||
(node) =>
|
||||
inputs.some((input) => input.id === node.id) ||
|
||||
outputs.some((output) => output.id === node.id),
|
||||
outputs.some((output) => output.id === node.id)
|
||||
);
|
||||
const haveChat = chatInput || chatOutput;
|
||||
const [selectedTab, setSelectedTab] = useState(
|
||||
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0,
|
||||
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0
|
||||
);
|
||||
|
||||
function startView() {
|
||||
|
|
@ -161,7 +161,7 @@ export default function IOModal({
|
|||
{selectedTab !== 0 && (
|
||||
<div
|
||||
className={cn(
|
||||
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start transition-all duration-300",
|
||||
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start transition-all duration-300"
|
||||
)}
|
||||
>
|
||||
<Tabs
|
||||
|
|
@ -197,11 +197,11 @@ export default function IOModal({
|
|||
</div>
|
||||
{nodes
|
||||
.filter((node) =>
|
||||
inputs.some((input) => input.id === node.id),
|
||||
inputs.some((input) => input.id === node.id)
|
||||
)
|
||||
.map((node, index) => {
|
||||
const input = inputs.find(
|
||||
(input) => input.id === node.id,
|
||||
(input) => input.id === node.id
|
||||
)!;
|
||||
return (
|
||||
<div
|
||||
|
|
@ -265,11 +265,11 @@ export default function IOModal({
|
|||
</div>
|
||||
{nodes
|
||||
.filter((node) =>
|
||||
outputs.some((output) => output.id === node.id),
|
||||
outputs.some((output) => output.id === node.id)
|
||||
)
|
||||
.map((node, index) => {
|
||||
const output = outputs.find(
|
||||
(output) => output.id === node.id,
|
||||
(output) => output.id === node.id
|
||||
)!;
|
||||
return (
|
||||
<div
|
||||
|
|
@ -336,7 +336,7 @@ export default function IOModal({
|
|||
<div
|
||||
className={cn(
|
||||
"flex h-full w-full flex-col items-start gap-4 pt-4",
|
||||
!selectedViewField ? "hidden" : "",
|
||||
!selectedViewField ? "hidden" : ""
|
||||
)}
|
||||
>
|
||||
<div className="font-xl flex items-center justify-center gap-3 font-semibold">
|
||||
|
|
@ -355,7 +355,7 @@ export default function IOModal({
|
|||
</div>
|
||||
<div className="h-full w-full">
|
||||
{inputs.some(
|
||||
(input) => input.id === selectedViewField.id,
|
||||
(input) => input.id === selectedViewField.id
|
||||
) ? (
|
||||
<IOFieldView
|
||||
type={InputOutput.INPUT}
|
||||
|
|
@ -377,7 +377,7 @@ export default function IOModal({
|
|||
<div
|
||||
className={cn(
|
||||
"flex h-full w-full",
|
||||
selectedViewField ? "hidden" : "",
|
||||
selectedViewField ? "hidden" : ""
|
||||
)}
|
||||
>
|
||||
{haveChat ? (
|
||||
|
|
@ -409,7 +409,7 @@ export default function IOModal({
|
|||
"h-4 w-4",
|
||||
isBuilding
|
||||
? "animate-spin"
|
||||
: "fill-current text-medium-indigo",
|
||||
: "fill-current text-medium-indigo"
|
||||
)}
|
||||
/>
|
||||
),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export const checkCanBuildTweakObject = (element, templateField) => {
|
|||
templateField.charAt(0) !== "_" &&
|
||||
element.data.node.template[templateField].show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
element.data.node.template[templateField].type,
|
||||
element.data.node.template[templateField].type
|
||||
) &&
|
||||
templateField !== "code"
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { convertArrayToObj } from "../../../utils/reactflowUtils";
|
|||
|
||||
export const getChangesType = (
|
||||
changes: string | string[] | boolean | number | Object[] | Object,
|
||||
template: TemplateVariableType,
|
||||
template: TemplateVariableType
|
||||
) => {
|
||||
if (typeof changes === "string" && template.type === "float") {
|
||||
changes = parseFloat(changes);
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ export function getCurlRunCode(
|
|||
flowId: string,
|
||||
isAuth: boolean,
|
||||
tweaksBuildedObject,
|
||||
endpointName?: string,
|
||||
endpointName?: string
|
||||
): string {
|
||||
const tweaksObject = tweaksBuildedObject[0];
|
||||
// show the endpoint name in the curl command if it exists
|
||||
return `curl -X POST \\
|
||||
"${window.location.protocol}//${window.location.host}/api/v1/run/${
|
||||
endpointName || flowId
|
||||
}?stream=false" \\
|
||||
endpointName || flowId
|
||||
}?stream=false" \\
|
||||
-H 'Content-Type: application/json'\\${
|
||||
!isAuth ? `\n -H 'x-api-key: <your api key>'\\` : ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ export const getNodesWithDefaultValue = (flow) => {
|
|||
templateField.charAt(0) !== "_" &&
|
||||
node.data.node.template[templateField].show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
node.data.node.template[templateField].type,
|
||||
),
|
||||
node.data.node.template[templateField].type
|
||||
)
|
||||
)
|
||||
.map((n, i) => {
|
||||
arrNodesWithValues.push(node["id"]);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
export default function getPythonCode(
|
||||
flowName: string,
|
||||
tweaksBuildedObject,
|
||||
tweaksBuildedObject
|
||||
): string {
|
||||
const tweaksObject = tweaksBuildedObject[0];
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export const getValue = (
|
|||
value: string,
|
||||
node: NodeType,
|
||||
template: TemplateVariableType,
|
||||
tweak: Object[],
|
||||
tweak: Object[]
|
||||
) => {
|
||||
let returnValue = value ?? "";
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
export default function getWidgetCode(
|
||||
flowId: string,
|
||||
flowName: string,
|
||||
isAuth: boolean,
|
||||
isAuth: boolean
|
||||
): string {
|
||||
return `<script src="https://cdn.jsdelivr.net/gh/langflow-ai/langflow-embedded-chat@1.0_alpha/dist/build/static/js/bundle.min.js"></script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export function createTabsArray(
|
||||
codes,
|
||||
includeWebhookCurl = false,
|
||||
includeTweaks = false,
|
||||
includeTweaks = false
|
||||
) {
|
||||
const tabs = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const ApiModal = forwardRef(
|
|||
flow: FlowType;
|
||||
children: ReactNode;
|
||||
},
|
||||
ref,
|
||||
ref
|
||||
) => {
|
||||
const tweak = useTweaksStore((state) => state.tweak);
|
||||
const addTweaks = useTweaksStore((state) => state.setTweak);
|
||||
|
|
@ -50,22 +50,21 @@ const ApiModal = forwardRef(
|
|||
flow?.id,
|
||||
autoLogin,
|
||||
tweak,
|
||||
flow?.endpoint_name,
|
||||
flow?.endpoint_name
|
||||
);
|
||||
const curl_run_code = getCurlRunCode(
|
||||
flow?.id,
|
||||
autoLogin,
|
||||
tweak,
|
||||
flow?.endpoint_name,
|
||||
flow?.endpoint_name
|
||||
);
|
||||
const curl_webhook_code = getCurlWebhookCode(
|
||||
flow?.id,
|
||||
autoLogin,
|
||||
flow?.endpoint_name,
|
||||
flow?.endpoint_name
|
||||
);
|
||||
const pythonCode = getPythonCode(flow?.name, tweak);
|
||||
const widgetCode = getWidgetCode(flow?.id, flow?.name, autoLogin);
|
||||
|
||||
const includeWebhook = flow.webhook;
|
||||
const tweaksCode = buildTweaks(flow);
|
||||
const codesArray = [
|
||||
|
|
@ -77,7 +76,7 @@ const ApiModal = forwardRef(
|
|||
pythonCode,
|
||||
];
|
||||
const [tabs, setTabs] = useState(
|
||||
createTabsArray(codesArray, includeWebhook),
|
||||
createTabsArray(codesArray, includeWebhook)
|
||||
);
|
||||
|
||||
const canShowTweaks =
|
||||
|
|
@ -126,7 +125,7 @@ const ApiModal = forwardRef(
|
|||
buildTweakObject(
|
||||
nodeId,
|
||||
element.data.node.template[templateField].value,
|
||||
element.data.node.template[templateField],
|
||||
element.data.node.template[templateField]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
@ -143,7 +142,7 @@ const ApiModal = forwardRef(
|
|||
async function buildTweakObject(
|
||||
tw: string,
|
||||
changes: string | string[] | boolean | number | Object[] | Object,
|
||||
template: TemplateVariableType,
|
||||
template: TemplateVariableType
|
||||
) {
|
||||
changes = getChangesType(changes, template);
|
||||
|
||||
|
|
@ -185,7 +184,7 @@ const ApiModal = forwardRef(
|
|||
flow?.id,
|
||||
autoLogin,
|
||||
cloneTweak,
|
||||
flow?.endpoint_name,
|
||||
flow?.endpoint_name
|
||||
);
|
||||
const pythonCode = getPythonCode(flow?.name, cloneTweak);
|
||||
const widgetCode = getWidgetCode(flow?.id, flow?.name, autoLogin);
|
||||
|
|
@ -229,7 +228,7 @@ const ApiModal = forwardRef(
|
|||
</BaseModal.Content>
|
||||
</BaseModal>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export default ApiModal;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export const switchCaseModalSize = (size: string) => {
|
|||
switch (size) {
|
||||
case "x-small":
|
||||
minWidth = "min-w-[20vw]";
|
||||
height = "h-full";
|
||||
height = "";
|
||||
break;
|
||||
case "smaller":
|
||||
minWidth = "min-w-[40vw]";
|
||||
|
|
@ -12,7 +12,7 @@ export const switchCaseModalSize = (size: string) => {
|
|||
break;
|
||||
case "smaller-h-full":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-full";
|
||||
height = "";
|
||||
break;
|
||||
case "small":
|
||||
minWidth = "min-w-[40vw]";
|
||||
|
|
@ -20,16 +20,19 @@ export const switchCaseModalSize = (size: string) => {
|
|||
break;
|
||||
case "small-h-full":
|
||||
minWidth = "min-w-[40vw]";
|
||||
height = "h-full";
|
||||
height = "";
|
||||
break;
|
||||
case "medium":
|
||||
minWidth = "min-w-[60vw]";
|
||||
height = "h-[60vh]";
|
||||
break;
|
||||
case "medium-tall":
|
||||
minWidth = "min-w-[60vw]";
|
||||
height = "h-[90vh]";
|
||||
break;
|
||||
case "medium-h-full":
|
||||
minWidth = "min-w-[60vw]";
|
||||
height = "h-full";
|
||||
|
||||
height = "";
|
||||
break;
|
||||
case "large":
|
||||
minWidth = "min-w-[85vw]";
|
||||
|
|
@ -56,11 +59,11 @@ export const switchCaseModalSize = (size: string) => {
|
|||
|
||||
case "large-h-full":
|
||||
minWidth = "min-w-[80vw]";
|
||||
height = "h-full";
|
||||
height = "";
|
||||
break;
|
||||
default:
|
||||
minWidth = "min-w-[80vw]";
|
||||
height = "h-[80vh]";
|
||||
height = "h-[90vh]";
|
||||
break;
|
||||
}
|
||||
return { minWidth, height };
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { Button } from "../../components/ui/button";
|
|||
import { modalHeaderType } from "../../types/components";
|
||||
import { cn } from "../../utils/utils";
|
||||
import { switchCaseModalSize } from "./helpers/switch-case-size";
|
||||
import * as Form from "@radix-ui/react-form";
|
||||
|
||||
type ContentProps = { children: ReactNode };
|
||||
type HeaderProps = { children: ReactNode; description: string };
|
||||
|
|
@ -52,10 +53,10 @@ const Trigger: React.FC<TriggerProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
const Header: React.FC<{ children: ReactNode; description: string | null }> = ({
|
||||
children,
|
||||
description,
|
||||
}: modalHeaderType): JSX.Element => {
|
||||
const Header: React.FC<{
|
||||
children: ReactNode;
|
||||
description: string | JSX.Element | null;
|
||||
}> = ({ children, description }: modalHeaderType): JSX.Element => {
|
||||
return (
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center">{children}</DialogTitle>
|
||||
|
|
@ -102,7 +103,7 @@ interface BaseModalProps {
|
|||
React.ReactElement<ContentProps>,
|
||||
React.ReactElement<HeaderProps>,
|
||||
React.ReactElement<TriggerProps>?,
|
||||
React.ReactElement<FooterProps>?,
|
||||
React.ReactElement<FooterProps>?
|
||||
];
|
||||
open?: boolean;
|
||||
setOpen?: (open: boolean) => void;
|
||||
|
|
@ -111,6 +112,7 @@ interface BaseModalProps {
|
|||
| "smaller"
|
||||
| "small"
|
||||
| "medium"
|
||||
| "medium-tall"
|
||||
| "large"
|
||||
| "three-cards"
|
||||
| "large-thin"
|
||||
|
|
@ -137,16 +139,16 @@ function BaseModal({
|
|||
onSubmit,
|
||||
}: BaseModalProps) {
|
||||
const headerChild = React.Children.toArray(children).find(
|
||||
(child) => (child as React.ReactElement).type === Header,
|
||||
(child) => (child as React.ReactElement).type === Header
|
||||
);
|
||||
const triggerChild = React.Children.toArray(children).find(
|
||||
(child) => (child as React.ReactElement).type === Trigger,
|
||||
(child) => (child as React.ReactElement).type === Trigger
|
||||
);
|
||||
const ContentChild = React.Children.toArray(children).find(
|
||||
(child) => (child as React.ReactElement).type === Content,
|
||||
(child) => (child as React.ReactElement).type === Content
|
||||
);
|
||||
const ContentFooter = React.Children.toArray(children).find(
|
||||
(child) => (child as React.ReactElement).type === Footer,
|
||||
(child) => (child as React.ReactElement).type === Footer
|
||||
);
|
||||
|
||||
let { minWidth, height } = switchCaseModalSize(size);
|
||||
|
|
@ -180,31 +182,33 @@ function BaseModal({
|
|||
) : (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
{triggerChild}
|
||||
<DialogContent className={cn(minWidth, "duration-300")}>
|
||||
<DialogContent
|
||||
className={cn(minWidth, height, "flex flex-col duration-300")}
|
||||
>
|
||||
<div className="truncate-doubleline word-break-break-word">
|
||||
{headerChild}
|
||||
</div>
|
||||
{onSubmit ? (
|
||||
<form
|
||||
<Form.Root
|
||||
onSubmit={(event) => {
|
||||
event.preventDefault();
|
||||
onSubmit();
|
||||
}}
|
||||
className="flex flex-col gap-6"
|
||||
className="flex flex-1 flex-col gap-6"
|
||||
>
|
||||
<div
|
||||
className={`flex flex-col ${height} w-full transition-all duration-300`}
|
||||
className={`flex w-full flex-1 flex-col transition-all duration-300`}
|
||||
>
|
||||
{ContentChild}
|
||||
</div>
|
||||
{ContentFooter && (
|
||||
<div className="flex flex-row-reverse">{ContentFooter}</div>
|
||||
)}
|
||||
</form>
|
||||
</Form.Root>
|
||||
) : (
|
||||
<>
|
||||
<div
|
||||
className={`flex flex-col ${height} w-full transition-all duration-300`}
|
||||
className={`flex w-full flex-1 flex-col transition-all duration-300`}
|
||||
>
|
||||
{ContentChild}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
import { ColDef, ValueGetterParams } from "ag-grid-community";
|
||||
import { useMemo } from "react";
|
||||
import TableAutoCellRender from "../../../components/tableComponent/components/tableAutoCellRender";
|
||||
import TableNodeCellRender from "../../../components/tableComponent/components/tableNodeCellRender";
|
||||
import TableToggleCellRender from "../../../components/tableComponent/components/tableToggleCellRender";
|
||||
import TableTooltipRender from "../../../components/tableComponent/components/tableTooltipRender";
|
||||
|
||||
const useColumnDefs = (
|
||||
myData: any,
|
||||
handleOnNewValue: (newValue: any, name: string) => void,
|
||||
changeAdvanced: (n: string) => void,
|
||||
open: boolean,
|
||||
) => {
|
||||
const columnDefs: ColDef[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
headerName: "Name",
|
||||
field: "display_name",
|
||||
valueGetter: (params) => {
|
||||
const templateParam = params.data;
|
||||
return (
|
||||
(templateParam.display_name
|
||||
? templateParam.display_name
|
||||
: templateParam.name) ?? params.data.key
|
||||
);
|
||||
},
|
||||
tooltipField: "display_name",
|
||||
tooltipComponent: TableTooltipRender,
|
||||
wrapText: true,
|
||||
autoHeight: true,
|
||||
flex: 1,
|
||||
resizable: false,
|
||||
cellClass: "no-border",
|
||||
},
|
||||
{
|
||||
headerName: "Description",
|
||||
field: "info",
|
||||
tooltipField: "info",
|
||||
tooltipComponent: TableTooltipRender,
|
||||
wrapText: true,
|
||||
autoHeight: true,
|
||||
flex: 2,
|
||||
resizable: false,
|
||||
cellClass: "no-border",
|
||||
},
|
||||
{
|
||||
headerName: "Value",
|
||||
field: "value",
|
||||
cellRenderer: TableNodeCellRender,
|
||||
valueGetter: (params: ValueGetterParams) => {
|
||||
return {
|
||||
value: params.data.value,
|
||||
nodeClass: myData.node,
|
||||
handleOnNewValue: handleOnNewValue,
|
||||
handleOnChangeDb: (value, key) => {
|
||||
myData.node!.template[key].load_from_db = value;
|
||||
},
|
||||
};
|
||||
},
|
||||
minWidth: 330,
|
||||
autoHeight: true,
|
||||
flex: 1,
|
||||
resizable: false,
|
||||
cellClass: "no-border",
|
||||
},
|
||||
{
|
||||
headerName: "Show",
|
||||
field: "advanced",
|
||||
cellRenderer: TableToggleCellRender,
|
||||
valueGetter: (params: ValueGetterParams) => {
|
||||
return {
|
||||
name: params.data.name,
|
||||
enabled: !params.data.advanced,
|
||||
setEnabled: () => {
|
||||
changeAdvanced(params.data.key);
|
||||
},
|
||||
};
|
||||
},
|
||||
editable: false,
|
||||
maxWidth: 80,
|
||||
resizable: false,
|
||||
cellClass: "no-border",
|
||||
},
|
||||
],
|
||||
[open, myData],
|
||||
);
|
||||
|
||||
return columnDefs;
|
||||
};
|
||||
|
||||
export default useColumnDefs;
|
||||
37
src/frontend/src/modals/editNodeModal/hooks/use-row-data.tsx
Normal file
37
src/frontend/src/modals/editNodeModal/hooks/use-row-data.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { useMemo } from "react";
|
||||
import { LANGFLOW_SUPPORTED_TYPES } from "../../../constants/constants";
|
||||
import { TemplateVariableType } from "../../../types/api";
|
||||
|
||||
const useRowData = (myData, open) => {
|
||||
const rowData = useMemo(() => {
|
||||
return Object.keys(myData.node!.template)
|
||||
.filter((key: string) => {
|
||||
const templateParam = myData.node!.template[
|
||||
key
|
||||
] as TemplateVariableType;
|
||||
return (
|
||||
key.charAt(0) !== "_" &&
|
||||
templateParam.show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(templateParam.type) &&
|
||||
!(
|
||||
(key === "code" && templateParam.type === "code") ||
|
||||
(key.includes("code") && templateParam.proxy)
|
||||
)
|
||||
);
|
||||
})
|
||||
.map((key: string) => {
|
||||
const templateParam = myData.node!.template[
|
||||
key
|
||||
] as TemplateVariableType;
|
||||
return {
|
||||
...templateParam,
|
||||
key: key,
|
||||
id: key,
|
||||
};
|
||||
});
|
||||
}, [open, myData]);
|
||||
|
||||
return rowData;
|
||||
};
|
||||
|
||||
export default useRowData;
|
||||
|
|
@ -1,43 +1,13 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import { forwardRef, useEffect, useState } from "react";
|
||||
import CodeAreaComponent from "../../components/codeAreaComponent";
|
||||
import DictComponent from "../../components/dictComponent";
|
||||
import Dropdown from "../../components/dropdownComponent";
|
||||
import FloatComponent from "../../components/floatComponent";
|
||||
import { ColDef, GridApi } from "ag-grid-community";
|
||||
import { forwardRef, useEffect, useRef, useState } from "react";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import InputFileComponent from "../../components/inputFileComponent";
|
||||
import InputGlobalComponent from "../../components/inputGlobalComponent";
|
||||
import InputListComponent from "../../components/inputListComponent";
|
||||
import IntComponent from "../../components/intComponent";
|
||||
import KeypairListComponent from "../../components/keypairListComponent";
|
||||
import PromptAreaComponent from "../../components/promptComponent";
|
||||
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||
import TextAreaComponent from "../../components/textAreaComponent";
|
||||
import ToggleShadComponent from "../../components/toggleShadComponent";
|
||||
import TableComponent from "../../components/tableComponent";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import {
|
||||
LANGFLOW_SUPPORTED_TYPES,
|
||||
limitScrollFieldsModal,
|
||||
} from "../../constants/constants";
|
||||
import { Case } from "../../shared/components/caseComponent";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import {
|
||||
convertObjToArray,
|
||||
convertValuesToNumbers,
|
||||
hasDuplicateKeys,
|
||||
scapedJSONStringfy,
|
||||
} from "../../utils/reactflowUtils";
|
||||
import { classNames } from "../../utils/utils";
|
||||
import BaseModal from "../baseModal";
|
||||
import useColumnDefs from "./hooks/use-column-defs";
|
||||
import useRowData from "./hooks/use-row-data";
|
||||
|
||||
const EditNodeModal = forwardRef(
|
||||
(
|
||||
|
|
@ -52,61 +22,51 @@ const EditNodeModal = forwardRef(
|
|||
setOpen: (open: boolean) => void;
|
||||
data: NodeDataType;
|
||||
},
|
||||
ref,
|
||||
ref
|
||||
) => {
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const myData = useRef(data);
|
||||
|
||||
const dataFromStore = nodes.find((node) => node.id === node.id)?.data;
|
||||
|
||||
const [myData, setMyData] = useState(dataFromStore ?? data);
|
||||
|
||||
const edges = useFlowStore((state) => state.edges);
|
||||
const setNode = useFlowStore((state) => state.setNode);
|
||||
|
||||
function changeAdvanced(n) {
|
||||
setMyData((old) => {
|
||||
let newData = cloneDeep(old);
|
||||
newData.node!.template[n].advanced =
|
||||
!newData.node!.template[n].advanced;
|
||||
return newData;
|
||||
});
|
||||
myData.current.node!.template[n].advanced =
|
||||
!myData.current.node!.template[n]?.advanced;
|
||||
}
|
||||
|
||||
const handleOnNewValue = (newValue: any, name) => {
|
||||
setMyData((old) => {
|
||||
let newData = cloneDeep(old);
|
||||
newData.node!.template[name].value = newValue;
|
||||
return newData;
|
||||
});
|
||||
myData.current.node!.template[name].value = newValue;
|
||||
};
|
||||
|
||||
const rowData = useRowData(data, open);
|
||||
|
||||
const columnDefs: ColDef[] = useColumnDefs(
|
||||
data,
|
||||
handleOnNewValue,
|
||||
changeAdvanced,
|
||||
open
|
||||
);
|
||||
|
||||
const [gridApi, setGridApi] = useState<GridApi | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setMyData(data); // reset data to what it is on node when opening modal
|
||||
if (gridApi && open) {
|
||||
myData.current = data;
|
||||
gridApi.refreshCells();
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||
|
||||
const type = (templateParam) => {
|
||||
return myData.node?.template[templateParam].type;
|
||||
};
|
||||
}, [gridApi, open]);
|
||||
|
||||
return (
|
||||
<BaseModal
|
||||
key={data.id}
|
||||
size="large-h-full"
|
||||
size="medium-tall"
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
onChangeOpenModal={(open) => {
|
||||
setMyData(data);
|
||||
}}
|
||||
onSubmit={() => {
|
||||
setNode(data.id, (old) => ({
|
||||
...old,
|
||||
data: {
|
||||
...old.data,
|
||||
node: myData.node,
|
||||
node: myData.current.node,
|
||||
},
|
||||
}));
|
||||
setOpen(false);
|
||||
|
|
@ -115,526 +75,30 @@ const EditNodeModal = forwardRef(
|
|||
<BaseModal.Trigger>
|
||||
<></>
|
||||
</BaseModal.Trigger>
|
||||
<BaseModal.Header description={myData.node?.description!}>
|
||||
<span className="pr-2">{myData.type}</span>
|
||||
<Badge variant="secondary">ID: {myData.id}</Badge>
|
||||
<BaseModal.Header description={data.node?.description!}>
|
||||
<span className="pr-2">{data.type}</span>
|
||||
<Badge variant="secondary">ID: {data.id}</Badge>
|
||||
</BaseModal.Header>
|
||||
<BaseModal.Content>
|
||||
<div className="flex pb-2">
|
||||
<IconComponent
|
||||
name="Variable"
|
||||
className="edit-node-modal-variable "
|
||||
/>
|
||||
<span className="edit-node-modal-span">Parameters</span>
|
||||
</div>
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="flex pb-2">
|
||||
<IconComponent
|
||||
name="Variable"
|
||||
className="edit-node-modal-variable "
|
||||
/>
|
||||
<span className="edit-node-modal-span">Parameters</span>
|
||||
</div>
|
||||
|
||||
<div className="edit-node-modal-arrangement">
|
||||
<div
|
||||
className={classNames(
|
||||
"edit-node-modal-box",
|
||||
nodeLength > limitScrollFieldsModal
|
||||
? "overflow-scroll overflow-x-hidden custom-scroll"
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
<div className="h-full">
|
||||
{nodeLength > 0 && (
|
||||
<div className="edit-node-modal-table">
|
||||
<Table className="table-fixed bg-muted outline-1">
|
||||
<TableHeader className="edit-node-modal-table-header">
|
||||
<TableRow className="">
|
||||
<TableHead className="h-7 text-center">PARAM</TableHead>
|
||||
<TableHead className="h-7 text-center">DESC</TableHead>
|
||||
<TableHead className="h-7 p-0 text-center">
|
||||
VALUE
|
||||
</TableHead>
|
||||
<TableHead className="h-7 text-center">SHOW</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody className="p-0">
|
||||
{Object.keys(myData.node!.template)
|
||||
.filter(
|
||||
(templateParam) =>
|
||||
templateParam.charAt(0) !== "_" &&
|
||||
myData.node?.template[templateParam].show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
myData.node!.template[templateParam].type,
|
||||
),
|
||||
)
|
||||
.map((templateParam, index) => {
|
||||
let id = {
|
||||
inputTypes:
|
||||
myData.node!.template[templateParam].input_types,
|
||||
type: myData.node!.template[templateParam].type,
|
||||
id: myData.id,
|
||||
fieldName: templateParam,
|
||||
};
|
||||
let disabled =
|
||||
edges.some(
|
||||
(edge) =>
|
||||
edge.targetHandle ===
|
||||
scapedJSONStringfy(
|
||||
myData.node!.template[templateParam].proxy
|
||||
? {
|
||||
...id,
|
||||
proxy:
|
||||
myData.node?.template[templateParam]
|
||||
.proxy,
|
||||
}
|
||||
: id,
|
||||
),
|
||||
) ?? false;
|
||||
return (
|
||||
<TableRow
|
||||
key={index}
|
||||
className={
|
||||
"h-10 " +
|
||||
((templateParam === "code" &&
|
||||
type(templateParam) === "code") ||
|
||||
(templateParam.includes("code") &&
|
||||
myData.node?.template[templateParam].proxy)
|
||||
? " hidden "
|
||||
: "")
|
||||
}
|
||||
>
|
||||
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
||||
<ShadTooltip
|
||||
styleClasses="z-50"
|
||||
content={
|
||||
myData.node?.template[templateParam].proxy
|
||||
? myData.node?.template[templateParam]
|
||||
.proxy?.id
|
||||
: myData.node?.template[templateParam]
|
||||
.display_name
|
||||
? myData.node!.template[templateParam]
|
||||
.display_name
|
||||
: myData.node?.template[templateParam]
|
||||
.name
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{myData.node?.template[templateParam]
|
||||
.display_name
|
||||
? myData.node!.template[templateParam]
|
||||
.display_name
|
||||
: myData.node?.template[templateParam]
|
||||
.name}
|
||||
</span>
|
||||
</ShadTooltip>
|
||||
</TableCell>
|
||||
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
||||
<ShadTooltip
|
||||
styleClasses="z-50"
|
||||
content={
|
||||
data.node?.template[templateParam]?.info ??
|
||||
null
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{data.node?.template[templateParam]?.info ??
|
||||
""}
|
||||
</span>
|
||||
</ShadTooltip>
|
||||
</TableCell>
|
||||
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
||||
<Case
|
||||
condition={
|
||||
type(templateParam) === "str" &&
|
||||
!myData.node!.template[templateParam]
|
||||
.options
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
{myData.node!.template[templateParam]
|
||||
?.list ? (
|
||||
<InputListComponent
|
||||
componentName={templateParam}
|
||||
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-" +
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
data-testid={
|
||||
"textarea-edit-" +
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(
|
||||
value: string | string[],
|
||||
) => {
|
||||
handleOnNewValue(
|
||||
value,
|
||||
templateParam,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<InputGlobalComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
onChange={(value) =>
|
||||
handleOnNewValue(value, templateParam)
|
||||
}
|
||||
setDb={(value) => {
|
||||
setMyData((oldData) => {
|
||||
let newData = cloneDeep(oldData);
|
||||
newData.node!.template[
|
||||
templateParam
|
||||
].load_from_db = value;
|
||||
return newData;
|
||||
});
|
||||
}}
|
||||
name={templateParam}
|
||||
data={myData}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(templateParam) === "NestedDict"
|
||||
}
|
||||
>
|
||||
<div className=" w-full">
|
||||
<DictComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
]?.value?.toString() === "{}"
|
||||
? {}
|
||||
: myData.node!.template[templateParam]
|
||||
.value
|
||||
}
|
||||
onChange={(newValue) => {
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
].value = newValue;
|
||||
handleOnNewValue(
|
||||
newValue,
|
||||
templateParam,
|
||||
);
|
||||
}}
|
||||
id="editnode-div-dict-input"
|
||||
/>
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "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,
|
||||
type(templateParam)!,
|
||||
)
|
||||
}
|
||||
duplicateKey={errorDuplicateKey}
|
||||
onChange={(newValue) => {
|
||||
const valueToNumbers =
|
||||
convertValuesToNumbers(newValue);
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
].value = valueToNumbers;
|
||||
setErrorDuplicateKey(
|
||||
hasDuplicateKeys(valueToNumbers),
|
||||
);
|
||||
handleOnNewValue(
|
||||
valueToNumbers,
|
||||
templateParam,
|
||||
);
|
||||
}}
|
||||
isList={
|
||||
data.node?.template[templateParam]
|
||||
?.list ?? false
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "bool"}
|
||||
>
|
||||
<div className="ml-auto">
|
||||
{" "}
|
||||
<ToggleShadComponent
|
||||
id={
|
||||
"toggle-edit-" +
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
disabled={disabled}
|
||||
enabled={
|
||||
myData.node!.template[templateParam]
|
||||
.value
|
||||
}
|
||||
setEnabled={(isEnabled) => {
|
||||
handleOnNewValue(
|
||||
isEnabled,
|
||||
templateParam,
|
||||
);
|
||||
}}
|
||||
size="small"
|
||||
editNode={true}
|
||||
/>
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "float"}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<FloatComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
rangeSpec={
|
||||
myData.node!.template[templateParam]
|
||||
.rangeSpec
|
||||
}
|
||||
value={
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(templateParam) === "str" &&
|
||||
myData.node!.template[templateParam].options
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<Dropdown
|
||||
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-" +
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
></Dropdown>
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case condition={type(templateParam) === "int"}>
|
||||
<div className="mx-auto">
|
||||
<IntComponent
|
||||
rangeSpec={
|
||||
data.node?.template[templateParam]
|
||||
?.rangeSpec
|
||||
}
|
||||
id={
|
||||
"edit-int-input-" +
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "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>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "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-" +
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
data-testid={
|
||||
"modal-prompt-input-" +
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "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" +
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case condition={type(templateParam) === "Any"}>
|
||||
<>-</>
|
||||
</Case>
|
||||
</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"
|
||||
editNode={true}
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<TableComponent
|
||||
onGridReady={(params) => {
|
||||
setGridApi(params.api);
|
||||
}}
|
||||
tooltipShowDelay={0.5}
|
||||
columnDefs={columnDefs}
|
||||
rowData={rowData}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -643,7 +107,7 @@ const EditNodeModal = forwardRef(
|
|||
<BaseModal.Footer submit={{ label: "Save Changes" }} />
|
||||
</BaseModal>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export default EditNodeModal;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ const ExportModal = forwardRef(
|
|||
is_component: false,
|
||||
},
|
||||
name!,
|
||||
description,
|
||||
description
|
||||
);
|
||||
setNoticeData({
|
||||
title: API_WARNING_NOTICE_ALERT,
|
||||
|
|
@ -61,7 +61,7 @@ const ExportModal = forwardRef(
|
|||
is_component: false,
|
||||
}),
|
||||
name!,
|
||||
description,
|
||||
description
|
||||
);
|
||||
setOpen(false);
|
||||
}}
|
||||
|
|
@ -102,6 +102,6 @@ const ExportModal = forwardRef(
|
|||
<BaseModal.Footer submit={{ label: "Download Flow" }} />
|
||||
</BaseModal>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
export default ExportModal;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { ColDef, ColGroupDef } from "ag-grid-community";
|
||||
import { AxiosError } from "axios";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import TableComponent from "../../components/tableComponent";
|
||||
|
|
@ -9,7 +8,7 @@ import useAlertStore from "../../stores/alertStore";
|
|||
import useFlowStore from "../../stores/flowStore";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { FlowSettingsPropsType } from "../../types/components";
|
||||
import { FlowType, NodeDataType } from "../../types/flow";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import BaseModal from "../baseModal";
|
||||
|
||||
export default function FlowLogsModal({
|
||||
|
|
@ -38,7 +37,7 @@ export default function FlowLogsModal({
|
|||
const { columns, rows } = data;
|
||||
setColumns(columns.map((col) => ({ ...col, editable: true })));
|
||||
setRows(rows);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +47,7 @@ export default function FlowLogsModal({
|
|||
.some((template) => template["stream"] && template["stream"].value);
|
||||
console.log(
|
||||
haStream,
|
||||
nodes.map((nodes) => (nodes.data as NodeDataType).node!.template),
|
||||
nodes.map((nodes) => (nodes.data as NodeDataType).node!.template)
|
||||
);
|
||||
if (haStream) {
|
||||
setNoticeData({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import InputComponent from "../../../components/inputComponent";
|
||||
import {
|
||||
FormControl,
|
||||
FormField,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const useFolderSubmit = (setOpen, folderToEdit) => {
|
|||
getFoldersApi(true);
|
||||
setOpen(false);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
} else {
|
||||
addFolder(data).then(
|
||||
|
|
@ -49,7 +49,7 @@ const useFolderSubmit = (setOpen, folderToEdit) => {
|
|||
setErrorData({
|
||||
title: `Error creating folder.`,
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export default function NewFlowModal({
|
|||
key={0}
|
||||
flow={
|
||||
examples.find(
|
||||
(e) => e.name == "Basic Prompting (Hello, World)",
|
||||
(e) => e.name == "Basic Prompting (Hello, World)"
|
||||
)!
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -11,15 +11,10 @@ import { nodeIconsLucide } from "../../utils/styleUtils";
|
|||
import BaseModal from "../baseModal";
|
||||
|
||||
export default function SecretKeyModal({
|
||||
title,
|
||||
cancelText,
|
||||
confirmationText,
|
||||
children,
|
||||
icon,
|
||||
data,
|
||||
onCloseModal,
|
||||
}: ApiKeyType) {
|
||||
const Icon: any = nodeIconsLucide[icon];
|
||||
const [open, setOpen] = useState(false);
|
||||
const [apiKeyName, setApiKeyName] = useState(data?.apikeyname ?? "");
|
||||
const [apiKeyValue, setApiKeyValue] = useState("");
|
||||
|
|
@ -66,118 +61,91 @@ export default function SecretKeyModal({
|
|||
.catch((err) => {});
|
||||
}
|
||||
|
||||
function handleSubmitForm() {
|
||||
if (!renderKey) {
|
||||
setRenderKey(true);
|
||||
handleAddNewKey();
|
||||
} else {
|
||||
setOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<BaseModal size="small-h-full" open={open} setOpen={setOpen}>
|
||||
<BaseModal
|
||||
onSubmit={handleSubmitForm}
|
||||
size="small-h-full"
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
>
|
||||
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
||||
<BaseModal.Header description={""}>
|
||||
<span className="pr-2">{title}</span>
|
||||
<Icon
|
||||
name="icon"
|
||||
className="h-6 w-6 pl-1 text-foreground"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</BaseModal.Header>
|
||||
<BaseModal.Content>
|
||||
{renderKey === true && (
|
||||
<>
|
||||
<span className="text-xs">
|
||||
<BaseModal.Header
|
||||
description={
|
||||
renderKey ? (
|
||||
<>
|
||||
{" "}
|
||||
Please save this secret key somewhere safe and accessible. For
|
||||
security reasons,{" "}
|
||||
<strong>you won't be able to view it again</strong> through your
|
||||
account. If you lose this secret key, you'll need to generate a
|
||||
new one.
|
||||
</span>
|
||||
<div className="flex pt-3">
|
||||
</>
|
||||
) : (
|
||||
<>Create a secret API Key to use Langflow API.</>
|
||||
)
|
||||
}
|
||||
>
|
||||
<span className="pr-2">Create API Key</span>
|
||||
<IconComponent
|
||||
name="Key"
|
||||
className="h-6 w-6 pl-1 text-foreground"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</BaseModal.Header>
|
||||
<BaseModal.Content>
|
||||
{renderKey ? (
|
||||
<>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-full">
|
||||
<Input ref={inputRef} readOnly={true} value={apiKeyValue} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Button
|
||||
className="ml-3"
|
||||
onClick={() => {
|
||||
handleCopyClick();
|
||||
}}
|
||||
>
|
||||
{textCopied ? (
|
||||
<IconComponent name="Copy" className="h-4 w-4" />
|
||||
) : (
|
||||
<IconComponent name="Check" className="h-4 w-4" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleCopyClick();
|
||||
}}
|
||||
variant="none"
|
||||
size="none"
|
||||
>
|
||||
{textCopied ? (
|
||||
<IconComponent name="Copy" className="h-4 w-4" />
|
||||
) : (
|
||||
<IconComponent name="Check" className="h-4 w-4" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Form.Root
|
||||
onSubmit={(event) => {
|
||||
setRenderKey(true);
|
||||
handleAddNewKey();
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{renderKey === false && (
|
||||
<div className="grid gap-5">
|
||||
<Form.Field name="username">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "baseline",
|
||||
justifyContent: "space-between",
|
||||
) : (
|
||||
<Form.Field name="apikey">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<Form.Control asChild>
|
||||
<Input
|
||||
//fake api key
|
||||
id="primary-input"
|
||||
value={apiKeyName}
|
||||
ref={inputRef}
|
||||
onChange={({ target: { value } }) => {
|
||||
setApiKeyName(value);
|
||||
}}
|
||||
>
|
||||
<Form.Label className="data-[invalid]:label-invalid">
|
||||
Name (optional){" "}
|
||||
</Form.Label>
|
||||
</div>
|
||||
<Form.Control asChild>
|
||||
<input
|
||||
onChange={({ target: { value } }) => {
|
||||
setApiKeyName(value);
|
||||
}}
|
||||
value={apiKeyName}
|
||||
className="primary-input"
|
||||
placeholder="My key name"
|
||||
/>
|
||||
</Form.Control>
|
||||
</Form.Field>
|
||||
placeholder="Insert a name for your API Key"
|
||||
/>
|
||||
</Form.Control>
|
||||
</div>
|
||||
)}
|
||||
{renderKey === false && (
|
||||
<div className="float-right">
|
||||
<Button
|
||||
type="button"
|
||||
className="mr-3"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
{cancelText}
|
||||
</Button>
|
||||
|
||||
<Form.Submit asChild>
|
||||
<Button className="mt-8">{confirmationText}</Button>
|
||||
</Form.Submit>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{renderKey === true && (
|
||||
<div className="float-right">
|
||||
<Button
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
setRenderKey(false);
|
||||
}}
|
||||
className="mt-8"
|
||||
>
|
||||
Done
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</Form.Root>
|
||||
</Form.Field>
|
||||
)}
|
||||
</BaseModal.Content>
|
||||
<BaseModal.Footer
|
||||
submit={{ label: renderKey ? "Done" : "Create Secret Key" }}
|
||||
/>
|
||||
</BaseModal>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,14 +128,14 @@ export default function ShareModal({
|
|||
title: "Error sharing " + is_component ? "component" : "flow",
|
||||
list: [err["response"]["data"]["detail"]],
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
else
|
||||
updateFlowStore(
|
||||
flow!,
|
||||
getTagsIds(selectedTags, tags),
|
||||
sharePublic,
|
||||
unavaliableNames.find((e) => e.name === name)!.id,
|
||||
unavaliableNames.find((e) => e.name === name)!.id
|
||||
).then(successShare, (err) => {
|
||||
setErrorData({
|
||||
title: "Error sharing " + is_component ? "component" : "flow",
|
||||
|
|
@ -203,7 +203,7 @@ export default function ShareModal({
|
|||
setOpen={setOpen ?? internalSetOpen}
|
||||
onSubmit={() => {
|
||||
const isNameAvailable = !unavaliableNames.some(
|
||||
(element) => element.name === name,
|
||||
(element) => element.name === name
|
||||
);
|
||||
|
||||
if (isNameAvailable) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export default function getTagsIds(
|
||||
tags: string[],
|
||||
tagListId: { name: string; id: string }[],
|
||||
tagListId: { name: string; id: string }[]
|
||||
) {
|
||||
return tags
|
||||
.map((tag) => tagListId.find((tagObj) => tagObj.name === tag))!
|
||||
|
|
|
|||
|
|
@ -1,291 +0,0 @@
|
|||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import { AuthContext } from "../../contexts/authContext";
|
||||
import { deleteApiKey, getApiKey } from "../../controllers/API";
|
||||
import ConfirmationModal from "../../modals/confirmationModal";
|
||||
import SecretKeyModal from "../../modals/secretKeyModal";
|
||||
|
||||
import moment from "moment";
|
||||
import Header from "../../components/headerComponent";
|
||||
import {
|
||||
DEL_KEY_ERROR_ALERT,
|
||||
DEL_KEY_SUCCESS_ALERT,
|
||||
} from "../../constants/alerts_constants";
|
||||
import {
|
||||
API_PAGE_PARAGRAPH_1,
|
||||
API_PAGE_PARAGRAPH_2,
|
||||
API_PAGE_USER_KEYS,
|
||||
LAST_USED_SPAN_1,
|
||||
LAST_USED_SPAN_2,
|
||||
} from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { ApiKey } from "../../types/components";
|
||||
|
||||
export default function ApiKeysPage() {
|
||||
const [loadingKeys, setLoadingKeys] = useState(true);
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const { userData } = useContext(AuthContext);
|
||||
const [userId, setUserId] = useState("");
|
||||
const keysList = useRef([]);
|
||||
|
||||
useEffect(() => {
|
||||
getKeys();
|
||||
}, [userData]);
|
||||
|
||||
function getKeys() {
|
||||
setLoadingKeys(true);
|
||||
if (userData) {
|
||||
getApiKey()
|
||||
.then((keys: [ApiKey]) => {
|
||||
keysList.current = keys["api_keys"];
|
||||
setUserId(keys["user_id"]);
|
||||
setLoadingKeys(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
setLoadingKeys(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function resetFilter() {
|
||||
getKeys();
|
||||
}
|
||||
|
||||
function handleDeleteKey(keys) {
|
||||
deleteApiKey(keys)
|
||||
.then((res) => {
|
||||
resetFilter();
|
||||
setSuccessData({
|
||||
title: DEL_KEY_SUCCESS_ALERT,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
setErrorData({
|
||||
title: DEL_KEY_ERROR_ALERT,
|
||||
list: [error["response"]["data"]["detail"]],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function lastUsedMessage() {
|
||||
return (
|
||||
<div className="text-xs">
|
||||
<span>
|
||||
{LAST_USED_SPAN_1}
|
||||
<br></br> {LAST_USED_SPAN_2}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header></Header>
|
||||
{userData && (
|
||||
<div className="main-page-panel">
|
||||
<div className="m-auto flex h-full flex-row justify-center">
|
||||
<div className="basis-5/6">
|
||||
<div className="m-auto flex h-full flex-col space-y-8 p-8 ">
|
||||
<div className="flex items-center justify-between space-y-2">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold tracking-tight">
|
||||
API keys
|
||||
</h2>
|
||||
<p className="text-muted-foreground">
|
||||
{API_PAGE_PARAGRAPH_1}
|
||||
<br />
|
||||
{API_PAGE_PARAGRAPH_2}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2"></div>
|
||||
</div>
|
||||
|
||||
{keysList.current &&
|
||||
keysList.current.length === 0 &&
|
||||
!loadingKeys && (
|
||||
<>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2>{API_PAGE_USER_KEYS}</h2>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<>
|
||||
{loadingKeys && (
|
||||
<div>
|
||||
<strong>Loading...</strong>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={
|
||||
"max-h-[15rem] overflow-scroll overflow-x-hidden rounded-md border-2 bg-muted custom-scroll" +
|
||||
(loadingKeys ? " border-0" : "")
|
||||
}
|
||||
>
|
||||
{keysList.current &&
|
||||
keysList.current.length > 0 &&
|
||||
!loadingKeys && (
|
||||
<Table className={"table-fixed bg-muted outline-1"}>
|
||||
<TableHeader
|
||||
className={
|
||||
loadingKeys
|
||||
? "hidden"
|
||||
: "table-fixed bg-muted outline-1"
|
||||
}
|
||||
>
|
||||
<TableRow>
|
||||
<TableHead className="h-10">Name</TableHead>
|
||||
<TableHead className="h-10">Key</TableHead>
|
||||
<TableHead className="h-10">Created</TableHead>
|
||||
<TableHead className="flex h-10 items-center">
|
||||
Last Used
|
||||
<ShadTooltip
|
||||
side="top"
|
||||
content={lastUsedMessage()}
|
||||
>
|
||||
<div>
|
||||
<IconComponent
|
||||
name="Info"
|
||||
className="ml-1 h-3 w-3"
|
||||
/>
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
</TableHead>
|
||||
<TableHead className="h-10">Total Uses</TableHead>
|
||||
<TableHead className="h-10 w-[100px] text-right"></TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
{!loadingKeys && (
|
||||
<TableBody>
|
||||
{keysList.current.map(
|
||||
(api_keys: ApiKey, index: number) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell className="truncate py-2">
|
||||
<ShadTooltip content={api_keys.name}>
|
||||
<span className="cursor-default">
|
||||
{api_keys.name ? api_keys.name : "-"}
|
||||
</span>
|
||||
</ShadTooltip>
|
||||
</TableCell>
|
||||
<TableCell className="truncate py-2">
|
||||
<span className="cursor-default">
|
||||
{api_keys.api_key}
|
||||
</span>
|
||||
</TableCell>
|
||||
<TableCell className="truncate py-2 ">
|
||||
<ShadTooltip
|
||||
side="top"
|
||||
content={moment(
|
||||
api_keys.created_at
|
||||
).format("YYYY-MM-DD HH:mm")}
|
||||
>
|
||||
<div>
|
||||
{moment(api_keys.created_at).format(
|
||||
"YYYY-MM-DD HH:mm"
|
||||
)}
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
</TableCell>
|
||||
<TableCell className="truncate py-2">
|
||||
<ShadTooltip
|
||||
side="top"
|
||||
content={
|
||||
moment(api_keys.last_used_at).format(
|
||||
"YYYY-MM-DD HH:mm"
|
||||
) === "Invalid date"
|
||||
? "Never"
|
||||
: moment(
|
||||
api_keys.last_used_at
|
||||
).format("YYYY-MM-DD HH:mm")
|
||||
}
|
||||
>
|
||||
<div>
|
||||
{moment(api_keys.last_used_at).format(
|
||||
"YYYY-MM-DD HH:mm"
|
||||
) === "Invalid date"
|
||||
? "Never"
|
||||
: moment(
|
||||
api_keys.last_used_at
|
||||
).format("YYYY-MM-DD HH:mm")}
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
</TableCell>
|
||||
<TableCell className="truncate py-2">
|
||||
{api_keys.total_uses}
|
||||
</TableCell>
|
||||
<TableCell className="flex w-[100px] py-2 text-right">
|
||||
<div className="flex">
|
||||
<ConfirmationModal
|
||||
title="Delete"
|
||||
titleHeader="Delete User"
|
||||
modalContentTitle="Attention!"
|
||||
cancelText="Cancel"
|
||||
confirmationText="Delete"
|
||||
icon={"UserMinus2"}
|
||||
data={api_keys.id}
|
||||
index={index}
|
||||
onConfirm={(index, keys) => {
|
||||
handleDeleteKey(keys);
|
||||
}}
|
||||
>
|
||||
<ConfirmationModal.Content>
|
||||
<span>
|
||||
Are you sure you want to delete
|
||||
this key? This action cannot be
|
||||
undone.
|
||||
</span>
|
||||
</ConfirmationModal.Content>
|
||||
<ConfirmationModal.Trigger>
|
||||
<IconComponent
|
||||
name="Trash2"
|
||||
className="ml-2 h-4 w-4 cursor-pointer"
|
||||
/>
|
||||
</ConfirmationModal.Trigger>
|
||||
</ConfirmationModal>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
)}
|
||||
</TableBody>
|
||||
)}
|
||||
</Table>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<SecretKeyModal
|
||||
title="Create new secret key"
|
||||
cancelText="Cancel"
|
||||
confirmationText="Create secret key"
|
||||
icon={"Key"}
|
||||
data={userId}
|
||||
onCloseModal={getKeys}
|
||||
>
|
||||
<Button>
|
||||
<IconComponent name="Plus" className="mr-1 h-5 w-5" />
|
||||
Create new secret key
|
||||
</Button>
|
||||
</SecretKeyModal>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -36,8 +36,8 @@ import {
|
|||
} from "../../../../utils/reactflowUtils";
|
||||
import ConnectionLineComponent from "../ConnectionLineComponent";
|
||||
import SelectionMenu from "../SelectionMenuComponent";
|
||||
import isWrappedWithClass from "./utils/is-wrapped-with-class";
|
||||
import getRandomName from "./utils/get-random-name";
|
||||
import isWrappedWithClass from "./utils/is-wrapped-with-class";
|
||||
|
||||
const nodeTypes = {
|
||||
genericNode: GenericNode,
|
||||
|
|
@ -52,19 +52,19 @@ export default function Page({
|
|||
}): JSX.Element {
|
||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||
const autoSaveCurrentFlow = useFlowsManagerStore(
|
||||
(state) => state.autoSaveCurrentFlow,
|
||||
(state) => state.autoSaveCurrentFlow
|
||||
);
|
||||
const types = useTypesStore((state) => state.types);
|
||||
const templates = useTypesStore((state) => state.templates);
|
||||
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
||||
const reactFlowWrapper = useRef<HTMLDivElement>(null);
|
||||
const [showCanvas, setSHowCanvas] = useState(
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0,
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0
|
||||
);
|
||||
|
||||
const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance);
|
||||
const setReactFlowInstance = useFlowStore(
|
||||
(state) => state.setReactFlowInstance,
|
||||
(state) => state.setReactFlowInstance
|
||||
);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const edges = useFlowStore((state) => state.edges);
|
||||
|
|
@ -81,10 +81,10 @@ export default function Page({
|
|||
const paste = useFlowStore((state) => state.paste);
|
||||
const resetFlow = useFlowStore((state) => state.resetFlow);
|
||||
const lastCopiedSelection = useFlowStore(
|
||||
(state) => state.lastCopiedSelection,
|
||||
(state) => state.lastCopiedSelection
|
||||
);
|
||||
const setLastCopiedSelection = useFlowStore(
|
||||
(state) => state.setLastCopiedSelection,
|
||||
(state) => state.setLastCopiedSelection
|
||||
);
|
||||
const onConnect = useFlowStore((state) => state.onConnect);
|
||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
|
|
@ -107,7 +107,7 @@ export default function Page({
|
|||
clonedSelection!,
|
||||
clonedNodes,
|
||||
clonedEdges,
|
||||
getRandomName(),
|
||||
getRandomName()
|
||||
);
|
||||
const newGroupNode = generateNodeFromFlow(newFlow, getNodeId);
|
||||
const newEdges = reconnectEdges(newGroupNode, removedEdges);
|
||||
|
|
@ -115,8 +115,8 @@ export default function Page({
|
|||
...clonedNodes.filter(
|
||||
(oldNodes) =>
|
||||
!clonedSelection?.nodes.some(
|
||||
(selectionNode) => selectionNode.id === oldNodes.id,
|
||||
),
|
||||
(selectionNode) => selectionNode.id === oldNodes.id
|
||||
)
|
||||
),
|
||||
newGroupNode,
|
||||
]);
|
||||
|
|
@ -126,8 +126,8 @@ export default function Page({
|
|||
!clonedSelection!.nodes.some(
|
||||
(selectionNode) =>
|
||||
selectionNode.id === oldEdge.target ||
|
||||
selectionNode.id === oldEdge.source,
|
||||
),
|
||||
selectionNode.id === oldEdge.source
|
||||
)
|
||||
),
|
||||
...newEdges,
|
||||
]);
|
||||
|
|
@ -180,7 +180,7 @@ export default function Page({
|
|||
{
|
||||
x: position.current.x,
|
||||
y: position.current.y,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
if (!isWrappedWithClass(event, "noundo")) {
|
||||
|
|
@ -276,7 +276,7 @@ export default function Page({
|
|||
|
||||
useEffect(() => {
|
||||
setSHowCanvas(
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0,
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0
|
||||
);
|
||||
}, [templates, types]);
|
||||
|
||||
|
|
@ -285,7 +285,7 @@ export default function Page({
|
|||
takeSnapshot();
|
||||
onConnect(params);
|
||||
},
|
||||
[takeSnapshot, onConnect],
|
||||
[takeSnapshot, onConnect]
|
||||
);
|
||||
|
||||
const onNodeDragStart: NodeDragHandler = useCallback(() => {
|
||||
|
|
@ -326,7 +326,7 @@ export default function Page({
|
|||
|
||||
// Extract the data from the drag event and parse it as a JSON object
|
||||
const data: { type: string; node?: APIClassType } = JSON.parse(
|
||||
event.dataTransfer.getData("nodedata"),
|
||||
event.dataTransfer.getData("nodedata")
|
||||
);
|
||||
|
||||
const newId = getNodeId(data.type);
|
||||
|
|
@ -342,7 +342,7 @@ export default function Page({
|
|||
};
|
||||
paste(
|
||||
{ nodes: [newNode], edges: [] },
|
||||
{ x: event.clientX, y: event.clientY },
|
||||
{ x: event.clientX, y: event.clientY }
|
||||
);
|
||||
} else if (event.dataTransfer.types.some((types) => types === "Files")) {
|
||||
takeSnapshot();
|
||||
|
|
@ -371,7 +371,7 @@ export default function Page({
|
|||
}
|
||||
},
|
||||
// Specify dependencies for useCallback
|
||||
[getNodeId, setNodes, takeSnapshot, paste],
|
||||
[getNodeId, setNodes, takeSnapshot, paste]
|
||||
);
|
||||
|
||||
const onEdgeUpdateStart = useCallback(() => {
|
||||
|
|
@ -387,7 +387,7 @@ export default function Page({
|
|||
setEdges((els) => updateEdge(oldEdge, newConnection, els));
|
||||
}
|
||||
},
|
||||
[setEdges],
|
||||
[setEdges]
|
||||
);
|
||||
|
||||
const onEdgeUpdateEnd = useCallback((_, edge: Edge): void => {
|
||||
|
|
@ -420,7 +420,7 @@ export default function Page({
|
|||
(flow: OnSelectionChangeParams): void => {
|
||||
setLastSelection(flow);
|
||||
},
|
||||
[],
|
||||
[]
|
||||
);
|
||||
|
||||
const onPaneClick = useCallback((flow) => {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { toTitleCase } from "../../../../../utils/utils";
|
|||
export default function getRandomName(
|
||||
retry: number = 0,
|
||||
noSpace: boolean = false,
|
||||
maxRetries: number = 3,
|
||||
maxRetries: number = 3
|
||||
): string {
|
||||
const left: string[] = ADJECTIVES;
|
||||
const right: string[] = NOUNS;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export default function SelectionMenu({
|
|||
const [disable, setDisable] = useState<boolean>(
|
||||
lastSelection && edges.length > 0
|
||||
? validateSelection(lastSelection!, edges).length > 0
|
||||
: false,
|
||||
: false
|
||||
);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isTransitioning, setIsTransitioning] = useState(false);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
const [search, setSearch] = useState("");
|
||||
function onDragStart(
|
||||
event: React.DragEvent<any>,
|
||||
data: { type: string; node?: APIClassType },
|
||||
data: { type: string; node?: APIClassType }
|
||||
): void {
|
||||
//start drag event
|
||||
var crt = event.currentTarget.cloneNode(true);
|
||||
|
|
@ -67,7 +67,7 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
let keys = Object.keys(data[d]).filter(
|
||||
(nd) =>
|
||||
nd.toLowerCase().includes(e.toLowerCase()) ||
|
||||
data[d][nd].display_name?.toLowerCase().includes(e.toLowerCase()),
|
||||
data[d][nd].display_name?.toLowerCase().includes(e.toLowerCase())
|
||||
);
|
||||
keys.forEach((element) => {
|
||||
ret[d][element] = data[d][element];
|
||||
|
|
@ -134,7 +134,7 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
|
||||
if (filtered.some((x) => x !== "")) {
|
||||
let keys = Object.keys(dataClone[d]).filter((nd) =>
|
||||
filtered.includes(nd),
|
||||
filtered.includes(nd)
|
||||
);
|
||||
Object.keys(dataClone[d]).forEach((element) => {
|
||||
if (!keys.includes(element)) {
|
||||
|
|
@ -171,7 +171,7 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
|
||||
if (filtered.some((x) => x !== "")) {
|
||||
let keys = Object.keys(dataClone[d]).filter((nd) =>
|
||||
filtered.includes(nd),
|
||||
filtered.includes(nd)
|
||||
);
|
||||
Object.keys(dataClone[d]).forEach((element) => {
|
||||
if (!keys.includes(element)) {
|
||||
|
|
@ -200,7 +200,7 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
"extra-side-bar-buttons gap-[4px] text-sm font-semibold",
|
||||
!hasApiKey || !validApiKey || !hasStore
|
||||
? "button-disable cursor-default text-muted-foreground"
|
||||
: "",
|
||||
: ""
|
||||
)}
|
||||
>
|
||||
<IconComponent
|
||||
|
|
@ -209,14 +209,14 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
"-m-0.5 -ml-1 h-6 w-6",
|
||||
!hasApiKey || !validApiKey || !hasStore
|
||||
? "extra-side-bar-save-disable"
|
||||
: "",
|
||||
: ""
|
||||
)}
|
||||
/>
|
||||
Share
|
||||
</button>
|
||||
</ShareModal>
|
||||
),
|
||||
[hasApiKey, validApiKey, currentFlow, hasStore],
|
||||
[hasApiKey, validApiKey, currentFlow, hasStore]
|
||||
);
|
||||
|
||||
const ExportMemo = useMemo(
|
||||
|
|
@ -227,7 +227,7 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
</button>
|
||||
</ExportModal>
|
||||
),
|
||||
[],
|
||||
[]
|
||||
);
|
||||
|
||||
const getIcon = useMemo(() => {
|
||||
|
|
@ -311,8 +311,8 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
.sort((a, b) =>
|
||||
sensitiveSort(
|
||||
dataFilter[SBSectionName][a].display_name,
|
||||
dataFilter[SBSectionName][b].display_name,
|
||||
),
|
||||
dataFilter[SBSectionName][b].display_name
|
||||
)
|
||||
)
|
||||
.map((SBItemName: string, index) => (
|
||||
<ShadTooltip
|
||||
|
|
@ -356,7 +356,7 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
</>
|
||||
) : (
|
||||
<div key={index}></div>
|
||||
),
|
||||
)
|
||||
)}{" "}
|
||||
<ParentDisclosureComponent
|
||||
openDisc={false}
|
||||
|
|
@ -393,8 +393,8 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
.sort((a, b) =>
|
||||
sensitiveSort(
|
||||
dataFilter[SBSectionName][a].display_name,
|
||||
dataFilter[SBSectionName][b].display_name,
|
||||
),
|
||||
dataFilter[SBSectionName][b].display_name
|
||||
)
|
||||
)
|
||||
.map((SBItemName: string, index) => (
|
||||
<ShadTooltip
|
||||
|
|
@ -468,7 +468,7 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
</>
|
||||
) : (
|
||||
<div key={index}></div>
|
||||
),
|
||||
)
|
||||
)}
|
||||
</ParentDisclosureComponent>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import ExtraSidebar from "./components/extraSidebarComponent";
|
|||
|
||||
export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
||||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId,
|
||||
(state) => state.setCurrentFlowId
|
||||
);
|
||||
const version = useDarkStore((state) => state.version);
|
||||
const setOnFlowPage = useFlowStore((state) => state.setOnFlowPage);
|
||||
|
|
|
|||
|
|
@ -31,22 +31,22 @@ export default function ComponentsComponent({
|
|||
const allFlows = useFlowsManagerStore((state) => state.allFlows);
|
||||
|
||||
const flowsFromFolder = useFolderStore(
|
||||
(state) => state.selectedFolder?.flows,
|
||||
(state) => state.selectedFolder?.flows
|
||||
);
|
||||
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const [openDelete, setOpenDelete] = useState(false);
|
||||
const searchFlowsComponents = useFlowsManagerStore(
|
||||
(state) => state.searchFlowsComponents,
|
||||
(state) => state.searchFlowsComponents
|
||||
);
|
||||
|
||||
const setSelectedFlowsComponentsCards = useFlowsManagerStore(
|
||||
(state) => state.setSelectedFlowsComponentsCards,
|
||||
(state) => state.setSelectedFlowsComponentsCards
|
||||
);
|
||||
|
||||
const selectedFlowsComponentsCards = useFlowsManagerStore(
|
||||
(state) => state.selectedFlowsComponentsCards,
|
||||
(state) => state.selectedFlowsComponentsCards
|
||||
);
|
||||
|
||||
const [handleFileDrop] = useFileDrop(uploadFlow, type)!;
|
||||
|
|
@ -82,7 +82,7 @@ export default function ComponentsComponent({
|
|||
f.name.toLowerCase().includes(searchFlowsComponents.toLowerCase()) ||
|
||||
f.description
|
||||
.toLowerCase()
|
||||
.includes(searchFlowsComponents.toLowerCase()),
|
||||
.includes(searchFlowsComponents.toLowerCase())
|
||||
);
|
||||
|
||||
if (searchFlowsComponents === "") {
|
||||
|
|
@ -137,9 +137,9 @@ export default function ComponentsComponent({
|
|||
selectedFlowsComponentsCards.map((selectedFlow) =>
|
||||
addFlow(
|
||||
true,
|
||||
allFlows.find((flow) => flow.id === selectedFlow),
|
||||
),
|
||||
),
|
||||
allFlows.find((flow) => flow.id === selectedFlow)
|
||||
)
|
||||
)
|
||||
).then(() => {
|
||||
resetFilter();
|
||||
getFoldersApi(true);
|
||||
|
|
@ -180,7 +180,7 @@ export default function ComponentsComponent({
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
setSelectedFlowsComponentsCards(selectedFlows);
|
||||
|
|
@ -215,7 +215,7 @@ export default function ComponentsComponent({
|
|||
if (type === "all") return allFlows?.length;
|
||||
|
||||
return allFlows?.filter(
|
||||
(f) => (f.is_component ?? false) === (type === "component"),
|
||||
(f) => (f.is_component ?? false) === (type === "component")
|
||||
)?.length;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useNavigate } from "react-router-dom";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
import NewFlowModal from "../../../../modals/newFlowModal";
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import NewFlowModal from "../../../../modals/newFlowModal";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
|
||||
type EmptyComponentProps = {};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,8 @@
|
|||
import { useState } from "react";
|
||||
import IconComponent from "../../../../components/genericIconComponent";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "../../../../components/ui/select";
|
||||
import { Checkbox } from "../../../../components/ui/checkbox";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import { cn } from "../../../../utils/utils";
|
||||
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
||||
import { Checkbox } from "../../../../components/ui/checkbox";
|
||||
import { cn } from "../../../../utils/utils";
|
||||
|
||||
type HeaderComponentProps = {
|
||||
handleSelectAll: (select) => void;
|
||||
|
|
@ -91,7 +82,7 @@ const HeaderComponent = ({
|
|||
name="Trash2"
|
||||
className={cn(
|
||||
"h-5 w-5 text-primary transition-all",
|
||||
disableFunctions ? "" : "hover:text-destructive",
|
||||
disableFunctions ? "" : "hover:text-destructive"
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import { useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import useAlertStore from "../../../../../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../../../../../stores/flowsManagerStore";
|
||||
import { useFolderStore } from "../../../../../../stores/foldersStore";
|
||||
import { handleDownloadFolderFn } from "../../../../utils/handle-download-folder";
|
||||
import InputSearchComponent from "../inputSearchComponent";
|
||||
import TabsSearchComponent from "../tabsComponent";
|
||||
import { Button } from "../../../../../../components/ui/button";
|
||||
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
|
||||
import useAlertStore from "../../../../../../stores/alertStore";
|
||||
import { handleDownloadFolderFn } from "../../../../utils/handle-download-folder";
|
||||
import { useFolderStore } from "../../../../../../stores/foldersStore";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
type HeaderTabsSearchComponentProps = {};
|
||||
|
||||
|
|
@ -22,7 +20,7 @@ const HeaderTabsSearchComponent = ({}: HeaderTabsSearchComponentProps) => {
|
|||
const [inputValue, setInputValue] = useState("");
|
||||
|
||||
const setSearchFlowsComponents = useFlowsManagerStore(
|
||||
(state) => state.setSearchFlowsComponents,
|
||||
(state) => state.setSearchFlowsComponents
|
||||
);
|
||||
|
||||
const handleDownloadFolder = () => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { ChangeEvent, KeyboardEvent } from "react";
|
||||
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
|
||||
import { Input } from "../../../../../../components/ui/input";
|
||||
import useFlowsManagerStore from "../../../../../../stores/flowsManagerStore";
|
||||
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
|
||||
|
||||
type InputSearchComponentProps = {
|
||||
loading: boolean;
|
||||
|
|
@ -23,7 +23,7 @@ const InputSearchComponent = ({
|
|||
const pagePath = window.location.pathname;
|
||||
const allFlows = useFlowsManagerStore((state) => state.allFlows);
|
||||
const searchFlowsComponents = useFlowsManagerStore(
|
||||
(state) => state.searchFlowsComponents,
|
||||
(state) => state.searchFlowsComponents
|
||||
);
|
||||
|
||||
const disableInputSearch =
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import useDropdownOptions from "../../hooks/use-dropdown-options";
|
|||
export default function HomePage(): JSX.Element {
|
||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId,
|
||||
(state) => state.setCurrentFlowId
|
||||
);
|
||||
|
||||
const location = useLocation();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue