merge fix
This commit is contained in:
commit
fbc9eb6d1b
97 changed files with 2357 additions and 575 deletions
|
|
@ -1,6 +1,6 @@
|
|||
from importlib import metadata
|
||||
from langflow.cache import cache_manager
|
||||
from langflow.processing.process import load_flow_from_json
|
||||
from langflow.cache import cache_manager # noqa: E402
|
||||
from langflow.processing.process import load_flow_from_json # noqa: E402
|
||||
|
||||
try:
|
||||
__version__ = metadata.version(__package__)
|
||||
|
|
@ -9,4 +9,5 @@ except metadata.PackageNotFoundError:
|
|||
__version__ = ""
|
||||
del metadata # optional, avoids polluting the results of dir(__package__)
|
||||
|
||||
|
||||
__all__ = ["load_flow_from_json", "cache_manager"]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import os
|
||||
import sys
|
||||
import time
|
||||
import httpx
|
||||
|
|
@ -33,6 +34,10 @@ def update_settings(
|
|||
remove_api_keys: bool = False,
|
||||
):
|
||||
"""Update the settings from a config file."""
|
||||
|
||||
# Check for database_url in the environment variables
|
||||
database_url = database_url or os.getenv("langflow_database_url")
|
||||
|
||||
if config:
|
||||
settings.update_from_yaml(config, dev=dev)
|
||||
if database_url:
|
||||
|
|
@ -43,6 +48,26 @@ def update_settings(
|
|||
settings.update_settings(cache=cache)
|
||||
|
||||
|
||||
def load_params():
|
||||
"""
|
||||
Load the parameters from the environment variables.
|
||||
"""
|
||||
global_vars = globals()
|
||||
|
||||
for key, value in global_vars.items():
|
||||
env_key = f"LANGFLOW_{key.upper()}"
|
||||
if env_key in os.environ:
|
||||
if isinstance(value, bool):
|
||||
# Handle booleans
|
||||
global_vars[key] = os.getenv(env_key, str(value)).lower() == "true"
|
||||
elif isinstance(value, int):
|
||||
# Handle integers
|
||||
global_vars[key] = int(os.getenv(env_key, str(value)))
|
||||
elif isinstance(value, str) or value is None:
|
||||
# Handle strings and None values
|
||||
global_vars[key] = os.getenv(env_key, str(value))
|
||||
|
||||
|
||||
def serve_on_jcloud():
|
||||
"""
|
||||
Deploy Langflow server on Jina AI Cloud
|
||||
|
|
@ -91,19 +116,27 @@ def serve_on_jcloud():
|
|||
|
||||
@app.command()
|
||||
def serve(
|
||||
host: str = typer.Option("127.0.0.1", help="Host to bind the server to."),
|
||||
workers: int = typer.Option(1, help="Number of worker processes."),
|
||||
host: str = typer.Option(
|
||||
"127.0.0.1", help="Host to bind the server to.", envvar="LANGFLOW_HOST"
|
||||
),
|
||||
workers: int = typer.Option(
|
||||
1, help="Number of worker processes.", envvar="LANGFLOW_WORKERS"
|
||||
),
|
||||
timeout: int = typer.Option(60, help="Worker timeout in seconds."),
|
||||
port: int = typer.Option(7860, help="Port to listen on."),
|
||||
port: int = typer.Option(7860, help="Port to listen on.", envvar="LANGFLOW_PORT"),
|
||||
config: str = typer.Option("config.yaml", help="Path to the configuration file."),
|
||||
# .env file param
|
||||
env_file: Path = typer.Option(
|
||||
".env", help="Path to the .env file containing environment variables."
|
||||
),
|
||||
log_level: str = typer.Option("critical", help="Logging level."),
|
||||
log_file: Path = typer.Option("logs/langflow.log", help="Path to the log file."),
|
||||
cache: str = typer.Argument(
|
||||
envvar="LANGCHAIN_CACHE",
|
||||
log_level: str = typer.Option(
|
||||
"critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"
|
||||
),
|
||||
log_file: Path = typer.Option(
|
||||
"logs/langflow.log", help="Path to the log file.", envvar="LANGFLOW_LOG_FILE"
|
||||
),
|
||||
cache: str = typer.Option(
|
||||
envvar="LANGFLOW_LANGCHAIN_CACHE",
|
||||
help="Type of cache to use. (InMemoryCache, SQLiteCache)",
|
||||
default="SQLiteCache",
|
||||
),
|
||||
|
|
@ -112,27 +145,35 @@ def serve(
|
|||
database_url: str = typer.Option(
|
||||
None,
|
||||
help="Database URL to connect to. If not provided, a local SQLite database will be used.",
|
||||
envvar="LANGFLOW_DATABASE_URL",
|
||||
),
|
||||
path: str = typer.Option(
|
||||
None,
|
||||
help="Path to the frontend directory containing build files. This is for development purposes only.",
|
||||
envvar="LANGFLOW_FRONTEND_PATH",
|
||||
),
|
||||
open_browser: bool = typer.Option(
|
||||
True, help="Open the browser after starting the server."
|
||||
True,
|
||||
help="Open the browser after starting the server.",
|
||||
envvar="LANGFLOW_OPEN_BROWSER",
|
||||
),
|
||||
remove_api_keys: bool = typer.Option(
|
||||
False, help="Remove API keys from the projects saved in the database."
|
||||
False,
|
||||
help="Remove API keys from the projects saved in the database.",
|
||||
envvar="LANGFLOW_REMOVE_API_KEYS",
|
||||
),
|
||||
):
|
||||
"""
|
||||
Run the Langflow server.
|
||||
"""
|
||||
# override env variables with .env file
|
||||
if env_file:
|
||||
load_dotenv(env_file, override=True)
|
||||
load_params()
|
||||
|
||||
if jcloud:
|
||||
return serve_on_jcloud()
|
||||
|
||||
load_dotenv(env_file)
|
||||
|
||||
configure(log_level=log_level, log_file=log_file)
|
||||
update_settings(
|
||||
config,
|
||||
|
|
@ -224,7 +265,7 @@ def get_free_port(port):
|
|||
def print_banner(host, port):
|
||||
# console = Console()
|
||||
|
||||
word = "LangFlow"
|
||||
word = "Langflow"
|
||||
colors = ["#3300cc"]
|
||||
|
||||
styled_word = ""
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class GraphData(BaseModel):
|
|||
|
||||
|
||||
class ExportedFlow(BaseModel):
|
||||
"""Exported flow from LangFlow."""
|
||||
"""Exported flow from Langflow."""
|
||||
|
||||
description: str
|
||||
name: str
|
||||
|
|
|
|||
|
|
@ -2,17 +2,34 @@ from langflow.settings import settings
|
|||
from sqlmodel import SQLModel, Session, create_engine
|
||||
from langflow.utils.logger import logger
|
||||
|
||||
if settings.database_url.startswith("sqlite"):
|
||||
if settings.database_url and settings.database_url.startswith("sqlite"):
|
||||
connect_args = {"check_same_thread": False}
|
||||
else:
|
||||
connect_args = {}
|
||||
if not settings.database_url:
|
||||
raise RuntimeError("No database_url provided")
|
||||
engine = create_engine(settings.database_url, connect_args=connect_args)
|
||||
|
||||
|
||||
def create_db_and_tables():
|
||||
logger.debug("Creating database and tables")
|
||||
SQLModel.metadata.create_all(engine)
|
||||
logger.debug("Database and tables created")
|
||||
try:
|
||||
SQLModel.metadata.create_all(engine)
|
||||
except Exception as exc:
|
||||
logger.error(f"Error creating database and tables: {exc}")
|
||||
raise RuntimeError("Error creating database and tables") from exc
|
||||
# Now check if the table Flow exists, if not, something went wrong
|
||||
# and we need to create the tables again.
|
||||
from sqlalchemy import inspect
|
||||
|
||||
inspector = inspect(engine)
|
||||
if "flow" not in inspector.get_table_names():
|
||||
logger.error("Something went wrong creating the database and tables.")
|
||||
logger.error("Please check your database settings.")
|
||||
|
||||
raise RuntimeError("Something went wrong creating the database and tables.")
|
||||
else:
|
||||
logger.debug("Database and tables created successfully")
|
||||
|
||||
|
||||
def get_session():
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ class Vertex:
|
|||
self.edges.append(edge)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Node(id={self.id}, data={self.data})"
|
||||
return f"Vertex(id={self.id}, data={self.data})"
|
||||
|
||||
def __eq__(self, __o: object) -> bool:
|
||||
return self.id == __o.id if isinstance(__o, Vertex) else False
|
||||
|
|
|
|||
|
|
@ -66,17 +66,24 @@ def extract_input_variables_from_prompt(prompt: str) -> list[str]:
|
|||
def setup_llm_caching():
|
||||
"""Setup LLM caching."""
|
||||
|
||||
from langflow.settings import settings
|
||||
|
||||
try:
|
||||
import langchain
|
||||
from langflow.settings import settings
|
||||
from langflow.interface.importing.utils import import_class
|
||||
|
||||
cache_class = import_class(f"langchain.cache.{settings.cache}")
|
||||
|
||||
logger.debug(f"Setting up LLM caching with {cache_class.__name__}")
|
||||
langchain.llm_cache = cache_class()
|
||||
logger.info(f"LLM caching setup with {cache_class.__name__}")
|
||||
set_langchain_cache(settings)
|
||||
except ImportError:
|
||||
logger.warning(f"Could not import {settings.cache}. ")
|
||||
except Exception as exc:
|
||||
logger.warning(f"Could not setup LLM caching. Error: {exc}")
|
||||
|
||||
|
||||
# TODO Rename this here and in `setup_llm_caching`
|
||||
def set_langchain_cache(settings):
|
||||
import langchain
|
||||
from langflow.interface.importing.utils import import_class
|
||||
|
||||
cache_type = os.getenv("LANGFLOW_LANGCHAIN_CACHE")
|
||||
cache_class = import_class(f"langchain.cache.{cache_type or settings.cache}")
|
||||
|
||||
logger.debug(f"Setting up LLM caching with {cache_class.__name__}")
|
||||
langchain.llm_cache = cache_class()
|
||||
logger.info(f"LLM caching setup with {cache_class.__name__}")
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
# This file is used by lc-serve to load the mounted app and serve it.
|
||||
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
# Use the JCLOUD_WORKSPACE for db URL if it's provided by JCloud.
|
||||
if 'JCLOUD_WORKSPACE' in os.environ:
|
||||
os.environ[
|
||||
'LANGFLOW_DATABASE_URL'
|
||||
] = f"sqlite:///{os.environ['JCLOUD_WORKSPACE']}/langflow.db"
|
||||
|
||||
from langflow.main import create_app
|
||||
from langflow.main import setup_app
|
||||
from langflow.utils.logger import configure
|
||||
|
||||
app = create_app()
|
||||
path = Path(__file__).parent
|
||||
static_files_dir = path / "frontend"
|
||||
app.mount(
|
||||
"/",
|
||||
StaticFiles(directory=static_files_dir, html=True),
|
||||
name="static",
|
||||
)
|
||||
configure(log_level="DEBUG")
|
||||
app = setup_app()
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ def setup_static_files(app: FastAPI, static_files_dir: Path):
|
|||
|
||||
# app = create_app()
|
||||
# setup_static_files(app, static_files_dir)
|
||||
def setup_app(static_files_dir: Optional[Path]) -> FastAPI:
|
||||
def setup_app(static_files_dir: Optional[Path] = None) -> FastAPI:
|
||||
"""Setup the FastAPI app."""
|
||||
# get the directory of the current file
|
||||
if not static_files_dir:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
from typing import Optional
|
||||
|
||||
import yaml
|
||||
from pydantic import BaseSettings, root_validator
|
||||
|
|
@ -22,16 +23,18 @@ class Settings(BaseSettings):
|
|||
utilities: dict = {}
|
||||
output_parsers: dict = {}
|
||||
dev: bool = False
|
||||
database_url: str
|
||||
database_url: Optional[str] = None
|
||||
cache: str = "InMemoryCache"
|
||||
remove_api_keys: bool = False
|
||||
|
||||
@root_validator(pre=True)
|
||||
def set_database_url(cls, values):
|
||||
if "database_url" not in values:
|
||||
logger.debug("No database_url provided, trying DATABASE_URL env variable")
|
||||
if database_url := os.getenv("DATABASE_URL"):
|
||||
values["database_url"] = database_url
|
||||
logger.debug(
|
||||
"No database_url provided, trying LANGFLOW_DATABASE_URL env variable"
|
||||
)
|
||||
if langflow_database_url := os.getenv("LANGFLOW_DATABASE_URL"):
|
||||
values["database_url"] = langflow_database_url
|
||||
else:
|
||||
logger.debug("No DATABASE_URL env variable, using sqlite database")
|
||||
values["database_url"] = "sqlite:///./langflow.db"
|
||||
|
|
@ -40,7 +43,6 @@ class Settings(BaseSettings):
|
|||
class Config:
|
||||
validate_assignment = True
|
||||
extra = "ignore"
|
||||
env_prefix = "LANGFLOW_"
|
||||
|
||||
@root_validator(allow_reuse=True)
|
||||
def validate_lists(cls, values):
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ class DocumentLoaderFrontNode(FrontendNode):
|
|||
"SlackDirectoryLoader": build_file_field(suffixes=[".zip"], fileTypes=["zip"]),
|
||||
"EverNoteLoader": build_file_field(suffixes=[".xml"], fileTypes=["xml"]),
|
||||
"FacebookChatLoader": build_file_field(suffixes=[".json"], fileTypes=["json"]),
|
||||
"GutenbergLoader": build_file_field(suffixes=[".txt"], fileTypes=["txt"]),
|
||||
"BSHTMLLoader": build_file_field(suffixes=[".html"], fileTypes=["html"]),
|
||||
"UnstructuredHTMLLoader": build_file_field(
|
||||
suffixes=[".html"], fileTypes=["html"]
|
||||
|
|
@ -116,8 +115,11 @@ class DocumentLoaderFrontNode(FrontendNode):
|
|||
"HNLoader",
|
||||
"IFixitLoader",
|
||||
"IMSDbLoader",
|
||||
"GutenbergLoader",
|
||||
}:
|
||||
name = "web_path"
|
||||
elif self.template.type_name in {"GutenbergLoader"}:
|
||||
name = "file_path"
|
||||
elif self.template.type_name in {"GitbookLoader"}:
|
||||
name = "web_page"
|
||||
elif self.template.type_name in {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ class VectorStoreFrontendNode(FrontendNode):
|
|||
show=True,
|
||||
advanced=True,
|
||||
multiline=False,
|
||||
password=True,
|
||||
value="",
|
||||
)
|
||||
extra_field2 = TemplateField(
|
||||
|
|
@ -142,6 +143,7 @@ class VectorStoreFrontendNode(FrontendNode):
|
|||
show=True,
|
||||
advanced=True,
|
||||
multiline=False,
|
||||
password=True,
|
||||
value="",
|
||||
)
|
||||
extra_fields.extend((extra_field, extra_field2, extra_field3, extra_field4))
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<title>LangFlow</title>
|
||||
<title>Langflow</title>
|
||||
</head>
|
||||
<body id='body' style="width: 100%; height:100%">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ export default function App() {
|
|||
|
||||
const removeAlert = (id: string) => {
|
||||
setAlertsList((prevAlertsList) =>
|
||||
prevAlertsList.filter((alert) => alert.id !== id)
|
||||
prevAlertsList.filter((alert) => alert.id !== id),
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ export default function App() {
|
|||
</ErrorBoundary>
|
||||
<div></div>
|
||||
<div
|
||||
className="fixed bottom-5 left-5 flex flex-col-reverse"
|
||||
className="app-div"
|
||||
style={{ zIndex: 999 }}
|
||||
>
|
||||
{alertsList.map((alert) => (
|
||||
|
|
|
|||
|
|
@ -81,30 +81,30 @@ export default function GenericNode({
|
|||
<div
|
||||
className={classNames(
|
||||
selected ? "border border-ring" : "border",
|
||||
"prompt-node relative flex w-96 flex-col justify-center rounded-lg bg-background"
|
||||
"generic-node-div"
|
||||
)}
|
||||
>
|
||||
<div className="flex w-full items-center justify-between gap-8 rounded-t-lg border-b bg-muted p-4 ">
|
||||
<div className="flex w-full items-center truncate">
|
||||
<div className="generic-node-div-title">
|
||||
<div className="generic-node-title-arrangement">
|
||||
<Icon
|
||||
strokeWidth={1.5}
|
||||
className="h-10 w-10 rounded p-1"
|
||||
className="generic-node-icon"
|
||||
style={{
|
||||
color: nodeColors[types[data.type]] ?? nodeColors.unknown,
|
||||
}}
|
||||
/>
|
||||
<div className="ml-2 flex-1 truncate">
|
||||
<div className="generic-node-tooltip-div">
|
||||
<ShadTooltip
|
||||
delayDuration={1500}
|
||||
content={data.node.display_name}
|
||||
>
|
||||
<div className="ml-2 truncate text-primary">
|
||||
<div className="generic-node-tooltip-div text-primary">
|
||||
{data.node.display_name}
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<div className="round-button-div">
|
||||
<button
|
||||
className="relative"
|
||||
onClick={(event) => {
|
||||
|
|
@ -113,7 +113,7 @@ export default function GenericNode({
|
|||
}}
|
||||
></button>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<div className="round-button-div">
|
||||
<div>
|
||||
<Tooltip
|
||||
title={
|
||||
|
|
@ -131,29 +131,29 @@ export default function GenericNode({
|
|||
)
|
||||
}
|
||||
>
|
||||
<div className="relative top-[3px] h-5 w-5">
|
||||
<div className="generic-node-status-position">
|
||||
<div
|
||||
className={classNames(
|
||||
validationStatus && validationStatus.valid
|
||||
? "h-4 w-4 rounded-full bg-status-green opacity-100"
|
||||
: "hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0",
|
||||
"absolute w-4 duration-200 ease-in-out hover:text-accent-foreground hover:transition-all"
|
||||
? "green-status"
|
||||
: "status-build-animation",
|
||||
"status-div"
|
||||
)}
|
||||
></div>
|
||||
<div
|
||||
className={classNames(
|
||||
validationStatus && !validationStatus.valid
|
||||
? "h-4 w-4 rounded-full bg-status-red opacity-100"
|
||||
: "hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0",
|
||||
"absolute w-4 duration-200 ease-in-out hover:text-accent-foreground hover:transition-all"
|
||||
? "red-status"
|
||||
: "status-build-animation",
|
||||
"status-div"
|
||||
)}
|
||||
></div>
|
||||
<div
|
||||
className={classNames(
|
||||
!validationStatus || isBuilding
|
||||
? "h-4 w-4 rounded-full bg-status-yellow opacity-100"
|
||||
: "hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0",
|
||||
"absolute w-4 duration-200 ease-in-out hover:text-accent-foreground hover:transition-all"
|
||||
? "yellow-status"
|
||||
: "status-build-animation",
|
||||
"status-div"
|
||||
)}
|
||||
></div>
|
||||
</div>
|
||||
|
|
@ -162,8 +162,8 @@ export default function GenericNode({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="h-full w-full py-5 text-foreground">
|
||||
<div className="w-full px-5 pb-3 text-sm text-muted-foreground">
|
||||
<div className="generic-node-desc">
|
||||
<div className="generic-node-desc-text">
|
||||
{data.node.description}
|
||||
</div>
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ export default function GenericNode({
|
|||
<div
|
||||
className={classNames(
|
||||
Object.keys(data.node.template).length < 1 ? "hidden" : "",
|
||||
"flex w-full justify-center"
|
||||
"flex-max-width justify-center"
|
||||
)}
|
||||
>
|
||||
{" "}
|
||||
|
|
|
|||
|
|
@ -39,19 +39,19 @@ export default function ErrorAlert({
|
|||
removeAlert(id);
|
||||
}, 500);
|
||||
}}
|
||||
className="mt-6 w-96 cursor-pointer rounded-md bg-error-background p-4 shadow-xl"
|
||||
className="error-build-message"
|
||||
>
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<XCircle className="h-5 w-5 text-status-red" aria-hidden="true" />
|
||||
<XCircle className="error-build-message-circle" aria-hidden="true" />
|
||||
</div>
|
||||
<div className="ml-3">
|
||||
<h3 className="text-sm font-medium text-error-foreground">
|
||||
<h3 className="error-build-foreground">
|
||||
{title}
|
||||
</h3>
|
||||
{list.length !== 0 ? (
|
||||
<div className="mt-2 text-sm text-error-foreground">
|
||||
<ul className="list-disc space-y-1 pl-5">
|
||||
<div className="error-build-message-div">
|
||||
<ul className="error-build-message-list">
|
||||
{list.map((item, index) => (
|
||||
<li key={index}>{item}</li>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -34,17 +34,17 @@ export default function SuccessAlert({
|
|||
setShow(false);
|
||||
removeAlert(id);
|
||||
}}
|
||||
className="mt-6 w-96 rounded-md bg-success-background p-4 shadow-xl"
|
||||
className="success-alert"
|
||||
>
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<CheckCircle2
|
||||
className="h-5 w-5 text-status-green"
|
||||
className="success-alert-icon"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<div className="ml-3">
|
||||
<p className="text-sm font-medium text-success-foreground">
|
||||
<p className="success-alert-message">
|
||||
{title}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default function AccordionComponent({
|
|||
open = [],
|
||||
}: AccordionComponentType) {
|
||||
const [value, setValue] = useState(
|
||||
open.length == 0 ? "" : getOpenAccordion()
|
||||
open.length == 0 ? "" : getOpenAccordion(),
|
||||
);
|
||||
|
||||
function getOpenAccordion() {
|
||||
|
|
|
|||
|
|
@ -44,10 +44,10 @@ export const EditFlowSettings: React.FC<InputProps> = ({
|
|||
return (
|
||||
<>
|
||||
<Label>
|
||||
<div className="flex justify-between">
|
||||
<div className="edit-flow-arrangement">
|
||||
<span className="font-medium">Name</span>{" "}
|
||||
{isMaxLength && (
|
||||
<span className="ml-10 animate-pulse text-status-red">
|
||||
<span className="edit-flow-span">
|
||||
Character limit reached
|
||||
</span>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Disclosure } from "@headlessui/react";
|
||||
import { useContext, useState } from "react";
|
||||
import { useContext } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { classNames } from "../../utils";
|
||||
import { locationContext } from "../../contexts/locationContext";
|
||||
|
|
@ -18,13 +18,13 @@ export default function ExtraSidebar() {
|
|||
<aside
|
||||
className={` ${
|
||||
isStackedOpen ? "w-52" : "w-0 "
|
||||
} flex flex-shrink-0 flex-col overflow-hidden border-r transition-all duration-500`}
|
||||
} unused-side-bar-aside`}
|
||||
>
|
||||
<div className="flex h-full w-52 flex-col items-start overflow-y-auto border bg-background scrollbar-hide">
|
||||
<div className="flex w-full flex-grow flex-col">
|
||||
<div className="unused-side-bar-arrangement">
|
||||
<div className="unused-side-bar-division">
|
||||
{extraNavigation.options ? (
|
||||
<div className="p-4">
|
||||
<nav className="flex-1 space-y-1">
|
||||
<nav className="unused-side-bar-nav">
|
||||
{extraNavigation.options.map((item) =>
|
||||
!item.children ? (
|
||||
<div key={item.name}>
|
||||
|
|
@ -32,17 +32,17 @@ export default function ExtraSidebar() {
|
|||
to={item.href}
|
||||
className={classNames(
|
||||
item.href.split("/")[2] === current[4]
|
||||
? "bg-muted text-foreground"
|
||||
: "bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
"group flex w-full items-center rounded-md py-2 pl-2 text-sm font-medium"
|
||||
? "unused-side-bar-link-colors-true"
|
||||
: "unused-side-bar-link-colors-false",
|
||||
"unused-side-bar-link"
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
className={classNames(
|
||||
item.href.split("/")[2] === current[4]
|
||||
? "text-ring"
|
||||
: "text-ring group-hover:text-accent-foreground",
|
||||
"mr-3 h-6 w-6 flex-shrink-0"
|
||||
: "unused-side-bar-icon-false",
|
||||
"unused-side-bar-icon"
|
||||
)}
|
||||
/>
|
||||
{item.name}
|
||||
|
|
@ -59,20 +59,20 @@ export default function ExtraSidebar() {
|
|||
<Disclosure.Button
|
||||
className={classNames(
|
||||
item.href.split("/")[2] === current[4]
|
||||
? "bg-muted text-foreground"
|
||||
: "bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
"group flex w-full items-center rounded-md py-2 pl-2 pr-1 text-left text-sm font-medium focus:outline-none focus:ring-1 focus:ring-ring"
|
||||
? "unused-side-bar-link-colors-true"
|
||||
: "unused-side-bar-link-colors-false",
|
||||
"unused-side-bar-disclosure"
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
className="mr-3 h-6 w-6 flex-shrink-0 text-ring group-hover:text-accent-foreground"
|
||||
className="unused-side-bar-disclosure-icon"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span className="flex-1">{item.name}</span>
|
||||
<svg
|
||||
className={classNames(
|
||||
open ? "rotate-90 text-ring" : "text-ring",
|
||||
"transition-rotate ml-3 h-5 w-5 flex-shrink-0 duration-150 ease-in-out group-hover:text-accent-foreground"
|
||||
open ? "unused-side-bar-svg-true" : "text-ring",
|
||||
"unused-side-bar-svg"
|
||||
)}
|
||||
viewBox="0 0 20 20"
|
||||
aria-hidden="true"
|
||||
|
|
@ -90,9 +90,9 @@ export default function ExtraSidebar() {
|
|||
to={subItem.href}
|
||||
className={classNames(
|
||||
subItem.href.split("/")[3] === current[5]
|
||||
? "bg-muted text-foreground"
|
||||
: "bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
"group flex w-full items-center rounded-md py-2 pl-11 pr-2 text-sm font-medium"
|
||||
? "unused-side-bar-link-colors-true"
|
||||
: "unused-side-bar-link-colors-false",
|
||||
"unused-side-bar-disclosure-panel"
|
||||
)}
|
||||
>
|
||||
{subItem.name}
|
||||
|
|
|
|||
|
|
@ -38,22 +38,22 @@ export const CardComponent = ({
|
|||
return (
|
||||
<Card className="group">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex w-full items-center gap-4">
|
||||
<CardTitle className="card-component-title-display">
|
||||
<span
|
||||
className={
|
||||
"flex h-7 w-7 items-center justify-center rounded-full text-2xl " +
|
||||
"card-component-image " +
|
||||
gradients[parseInt(flow.id.slice(0, 12), 16) % gradients.length]
|
||||
}
|
||||
></span>
|
||||
<span className="inline-block w-full flex-1 break-words truncate-doubleline">
|
||||
<span className="card-component-title-size">
|
||||
{flow.name}
|
||||
</span>
|
||||
{onDelete && (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<button className="flex self-start">
|
||||
<Trash2 className="h-4 w-4 text-primary opacity-0 transition-all group-hover:opacity-100" />
|
||||
</button>
|
||||
<button className="card-component-delete-button" onClick={onDelete}>
|
||||
<Trash2 className="card-component-delete-icon" />
|
||||
</button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
|
|
@ -72,8 +72,8 @@ export const CardComponent = ({
|
|||
</Dialog>
|
||||
)}
|
||||
</CardTitle>
|
||||
<CardDescription className="pb-2 pt-2">
|
||||
<div className="truncate-doubleline">
|
||||
<CardDescription className="card-component-desc">
|
||||
<div className="card-component-desc-text">
|
||||
{flow.description}
|
||||
{/* {flow.description} */}
|
||||
</div>
|
||||
|
|
@ -81,8 +81,8 @@ export const CardComponent = ({
|
|||
</CardHeader>
|
||||
|
||||
<CardFooter>
|
||||
<div className="flex w-full items-end justify-between gap-2">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<div className="card-component-footer-arrangement">
|
||||
<div className="card-component-footer">
|
||||
{/* <Badge variant="secondary">Agent</Badge>
|
||||
<Badge variant="secondary">
|
||||
<div className="w-3">
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ export default function BuildTrigger({
|
|||
|
||||
async function enforceMinimumLoadingTime(
|
||||
startTime: number,
|
||||
minimumLoadingTime: number
|
||||
minimumLoadingTime: number,
|
||||
) {
|
||||
const elapsedTime = Date.now() - startTime;
|
||||
const remainingTime = minimumLoadingTime - elapsedTime;
|
||||
|
|
@ -168,7 +168,7 @@ export default function BuildTrigger({
|
|||
>
|
||||
<div className="fixed bottom-20 right-4">
|
||||
<div
|
||||
className={`${eventClick} align-center shadow-round-btn-shadow hover:shadow-round-btn-shadow flex h-12 w-12 cursor-pointer justify-center rounded-full bg-border px-3 py-1 shadow-md`}
|
||||
className={`${eventClick} round-button-form`}
|
||||
onClick={() => {
|
||||
handleBuild(flow);
|
||||
}}
|
||||
|
|
@ -176,7 +176,7 @@ export default function BuildTrigger({
|
|||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<button>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="round-button-div">
|
||||
{isBuilding && progress < 1 ? (
|
||||
// Render your loading animation here when isBuilding is true
|
||||
<RadialProgressComponent
|
||||
|
|
@ -185,7 +185,10 @@ export default function BuildTrigger({
|
|||
value={progress}
|
||||
></RadialProgressComponent>
|
||||
) : isBuilding ? (
|
||||
<Loading strokeWidth={1.5} className="stroke-build-trigger" />
|
||||
<Loading
|
||||
strokeWidth={1.5}
|
||||
className="build-trigger-loading-icon"
|
||||
/>
|
||||
) : (
|
||||
<Zap
|
||||
strokeWidth={1.5}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default function CodeAreaComponent({
|
|||
setNodeClass,
|
||||
}: TextAreaComponentType) {
|
||||
const [myValue, setMyValue] = useState(
|
||||
typeof value == "string" ? value : JSON.stringify(value)
|
||||
typeof value == "string" ? value : JSON.stringify(value),
|
||||
);
|
||||
const { openPopUp } = useContext(PopUpContext);
|
||||
useEffect(() => {
|
||||
|
|
@ -80,7 +80,7 @@ export default function CodeAreaComponent({
|
|||
<ExternalLink
|
||||
strokeWidth={1.5}
|
||||
className={
|
||||
"ml-3 h-6 w-6" +
|
||||
"icons-parameters-comp" +
|
||||
(disabled ? " text-ring" : " hover:text-accent-foreground")
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import { DropDownComponentType } from "../../types/components";
|
|||
import { classNames } from "../../utils";
|
||||
import { ChevronsUpDown, Check } from "lucide-react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
|
||||
export default function Dropdown({
|
||||
value,
|
||||
|
|
@ -39,20 +38,20 @@ export default function Dropdown({
|
|||
<Listbox.Button
|
||||
className={
|
||||
editNode
|
||||
? "border-1 input-edit-node relative pr-8"
|
||||
: "input-primary py-2 pl-3 pr-10 text-left"
|
||||
? "dropdown-component-outline"
|
||||
: "dropdown-component-false-outline"
|
||||
}
|
||||
>
|
||||
<span className="block w-full truncate bg-background">
|
||||
<span className="dropdown-component-display">
|
||||
{internalValue}
|
||||
</span>
|
||||
<span
|
||||
className={
|
||||
"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
|
||||
"dropdown-component-arrow"
|
||||
}
|
||||
>
|
||||
<ChevronsUpDown
|
||||
className="h-5 w-5 text-muted-foreground"
|
||||
className="dropdown-component-arrow-color"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
|
|
@ -68,8 +67,8 @@ export default function Dropdown({
|
|||
<Listbox.Options
|
||||
className={classNames(
|
||||
editNode
|
||||
? "z-10 mt-1 max-h-60 w-[215px] overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
|
||||
: "nowheel overflow-y z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm ",
|
||||
? "dropdown-component-true-options "
|
||||
: "dropdown-component-false-options ",
|
||||
apiModal ? "mb-2 w-[250px]" : "absolute"
|
||||
)}
|
||||
>
|
||||
|
|
@ -80,8 +79,8 @@ export default function Dropdown({
|
|||
classNames(
|
||||
active ? " bg-accent" : "",
|
||||
editNode
|
||||
? "relative cursor-default select-none py-0.5 pl-3 pr-12"
|
||||
: "relative cursor-default select-none py-2 pl-3 pr-9"
|
||||
? "dropdown-component-false-option"
|
||||
: "dropdown-component-true-option"
|
||||
)
|
||||
}
|
||||
value={option}
|
||||
|
|
@ -101,14 +100,14 @@ export default function Dropdown({
|
|||
<span
|
||||
className={classNames(
|
||||
active ? "text-background " : "",
|
||||
"absolute inset-y-0 right-0 flex items-center pr-4"
|
||||
"dropdown-component-choosal"
|
||||
)}
|
||||
>
|
||||
<Check
|
||||
className={
|
||||
active
|
||||
? "h-5 w-5 text-black"
|
||||
: "h-5 w-5 text-black"
|
||||
? "dropdown-component-check-icon"
|
||||
: "dropdown-component-check-icon"
|
||||
}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export default function FloatComponent({
|
|||
return (
|
||||
<div
|
||||
className={
|
||||
"w-full " + (disabled ? "pointer-events-none cursor-not-allowed" : "")
|
||||
"w-full " + (disabled ? "float-component-pointer" : "")
|
||||
}
|
||||
>
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -47,19 +47,19 @@ export const MenuBar = ({ flows, tabId }) => {
|
|||
let current_flow = flows.find((flow) => flow.id === tabId);
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="round-button-div">
|
||||
<Link to="/">
|
||||
<ChevronLeft className="w-4" />
|
||||
</Link>
|
||||
<div className="flex items-center gap-0.5 rounded-md px-1.5 py-1 text-sm font-medium">
|
||||
<div className="header-menu-bar">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
className="flex max-w-[200px] items-center gap-2"
|
||||
className="header-menu-bar-display"
|
||||
variant="primary"
|
||||
size="sm"
|
||||
>
|
||||
<div className="flex-1 truncate">{current_flow.name}</div>
|
||||
<div className="header-menu-flow-name">{current_flow.name}</div>
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
|
|
@ -71,7 +71,7 @@ export const MenuBar = ({ flows, tabId }) => {
|
|||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
<Plus className="header-menu-options" />
|
||||
New
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
|
|
@ -80,7 +80,7 @@ export const MenuBar = ({ flows, tabId }) => {
|
|||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Settings2 className="mr-2 h-4 w-4 " />
|
||||
<Settings2 className="header-menu-options " />
|
||||
Settings
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
|
|
@ -89,7 +89,7 @@ export const MenuBar = ({ flows, tabId }) => {
|
|||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Undo className="mr-2 h-4 w-4 " />
|
||||
<Undo className="header-menu-options " />
|
||||
Undo
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
|
|
@ -98,7 +98,7 @@ export const MenuBar = ({ flows, tabId }) => {
|
|||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Redo className="mr-2 h-4 w-4 " />
|
||||
<Redo className="header-menu-options " />
|
||||
Redo
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { BellIcon, Home, MoonIcon, SunIcon, Users2 } from "lucide-react";
|
||||
import { Home, MoonIcon, SunIcon, Users2 } from "lucide-react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa";
|
||||
import { Button } from "../ui/button";
|
||||
|
|
@ -36,8 +36,8 @@ export default function Header() {
|
|||
fetchStars();
|
||||
}, []);
|
||||
return (
|
||||
<div className="flex h-12 w-full items-center justify-between border-b bg-muted">
|
||||
<div className="flex w-96 items-center justify-start gap-2">
|
||||
<div className="header-arrangement">
|
||||
<div className="header-start-display">
|
||||
<Link to="/">
|
||||
<span className="ml-4 text-2xl">⛓️</span>
|
||||
</Link>
|
||||
|
|
@ -45,7 +45,7 @@ export default function Header() {
|
|||
<MenuBar flows={flows} tabId={tabId} />
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="round-button-div">
|
||||
<Link to="/">
|
||||
<Button
|
||||
className="gap-2"
|
||||
|
|
@ -69,17 +69,17 @@ export default function Header() {
|
|||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex w-96 justify-end px-2">
|
||||
<div className="ml-auto mr-2 flex items-center gap-5">
|
||||
<div className="header-end-division">
|
||||
<div className="header-end-display">
|
||||
<a
|
||||
href="https://github.com/logspace-ai/langflow"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex h-9 items-center justify-center rounded-md border border-input px-3 pr-0 text-sm font-medium text-muted-foreground shadow-sm ring-offset-background hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
|
||||
className="header-github-link"
|
||||
>
|
||||
<FaGithub className="mr-2 h-5 w-5" />
|
||||
Star
|
||||
<div className="-mr-px ml-2 flex h-9 items-center justify-center rounded-md rounded-l-none border bg-background px-2 text-sm">
|
||||
<div className="header-github-display">
|
||||
{stars}
|
||||
</div>
|
||||
</a>
|
||||
|
|
@ -89,7 +89,7 @@ export default function Header() {
|
|||
rel="noreferrer"
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
<FaTwitter className="h-5 w-5 hover:text-accent-foreground" />
|
||||
<FaTwitter className="side-bar-button-size" />
|
||||
</a>
|
||||
<a
|
||||
href="https://discord.gg/EqksyE2EX9"
|
||||
|
|
@ -97,24 +97,24 @@ export default function Header() {
|
|||
rel="noreferrer"
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
<FaDiscord className="h-5 w-5 hover:text-accent-foreground" />
|
||||
<FaDiscord className="side-bar-button-size" />
|
||||
</a>
|
||||
|
||||
<Separator orientation="vertical" />
|
||||
<button
|
||||
className="text-muted-foreground hover:text-accent-foreground "
|
||||
className="extra-side-bar-save-disable"
|
||||
onClick={() => {
|
||||
setDark(!dark);
|
||||
}}
|
||||
>
|
||||
{dark ? (
|
||||
<SunIcon className="h-5 w-5" />
|
||||
<SunIcon className="side-bar-button-size" />
|
||||
) : (
|
||||
<MoonIcon className="h-5 w-5" />
|
||||
<MoonIcon className="side-bar-button-size" />
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
className="relative text-muted-foreground hover:text-accent-foreground"
|
||||
className="extra-side-bar-save-disable relative"
|
||||
onClick={(event: React.MouseEvent<HTMLElement>) => {
|
||||
setNotificationCenter(false);
|
||||
const { top, left } = (
|
||||
|
|
@ -128,15 +128,15 @@ export default function Header() {
|
|||
>
|
||||
<AlertDropdown />
|
||||
</div>
|
||||
<div className="fixed left-0 top-0 h-screen w-screen"></div>
|
||||
<div className="header-notifications-box"></div>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
>
|
||||
{notificationCenter && (
|
||||
<div className="absolute right-[3px] h-1.5 w-1.5 rounded-full bg-destructive"></div>
|
||||
<div className="header-notifications"></div>
|
||||
)}
|
||||
<Bell className="h-5 w-5" aria-hidden="true" />
|
||||
<Bell className="side-bar-button-size" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export default function InputComponent({
|
|||
<div
|
||||
className={
|
||||
disabled
|
||||
? "pointer-events-none relative cursor-not-allowed"
|
||||
? "input-component-div"
|
||||
: "relative"
|
||||
}
|
||||
>
|
||||
|
|
@ -61,8 +61,8 @@ export default function InputComponent({
|
|||
<button
|
||||
className={classNames(
|
||||
editNode
|
||||
? "absolute inset-y-0 right-0 items-center pr-2 text-muted-foreground"
|
||||
: "absolute inset-y-0 right-0 items-center px-4 text-muted-foreground"
|
||||
? "input-component-true-button"
|
||||
: "input-component-false-button"
|
||||
)}
|
||||
onClick={() => {
|
||||
setPwdVisible(!pwdVisible);
|
||||
|
|
@ -78,8 +78,8 @@ export default function InputComponent({
|
|||
stroke="currentColor"
|
||||
className={classNames(
|
||||
editNode
|
||||
? "absolute bottom-0.5 right-2 h-5 w-5"
|
||||
: "absolute bottom-2 right-3 h-5 w-5"
|
||||
? "input-component-true-svg"
|
||||
: "input-component-false-svg"
|
||||
)}
|
||||
>
|
||||
<path
|
||||
|
|
@ -97,8 +97,8 @@ export default function InputComponent({
|
|||
stroke="currentColor"
|
||||
className={classNames(
|
||||
editNode
|
||||
? "absolute bottom-0.5 right-2 h-5 w-5"
|
||||
: "absolute bottom-2 right-3 h-5 w-5"
|
||||
? "input-component-true-svg"
|
||||
: "input-component-false-svg"
|
||||
)}
|
||||
>
|
||||
<path
|
||||
|
|
|
|||
|
|
@ -94,10 +94,10 @@ export default function InputFileComponent({
|
|||
return (
|
||||
<div
|
||||
className={
|
||||
disabled ? "pointer-events-none w-full cursor-not-allowed" : "w-full"
|
||||
disabled ? "input-component-div" : "w-full"
|
||||
}
|
||||
>
|
||||
<div className="flex w-full items-center">
|
||||
<div className="input-file-component">
|
||||
<span
|
||||
onClick={handleButtonClick}
|
||||
className={
|
||||
|
|
@ -112,7 +112,10 @@ export default function InputFileComponent({
|
|||
{!editNode && !loading && (
|
||||
<FileSearch2
|
||||
strokeWidth={1.5}
|
||||
className="h-6 w-6 hover:text-accent-foreground ml-3"
|
||||
className={
|
||||
"icons-parameters-comp" +
|
||||
(disabled ? " text-ring " : " hover:text-accent-foreground")
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{!editNode && loading && (
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ export default function PromptAreaComponent({
|
|||
<ExternalLink
|
||||
strokeWidth={1.5}
|
||||
className={
|
||||
"ml-3 h-6 w-6" +
|
||||
"icons-parameters-comp" +
|
||||
(disabled ? " text-ring" : " hover:text-accent-foreground")
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export default function TextAreaComponent({
|
|||
setMyValue(t);
|
||||
onChange(t);
|
||||
}}
|
||||
/>
|
||||
/>,
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
|
@ -69,7 +69,7 @@ export default function TextAreaComponent({
|
|||
<ExternalLink
|
||||
strokeWidth={1.5}
|
||||
className={
|
||||
"ml-3 h-6 w-6" +
|
||||
"icons-parameters-comp" +
|
||||
(disabled ? " text-ring" : " hover:text-accent-foreground")
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ export default function ToggleComponent({
|
|||
}}
|
||||
className={classNames(
|
||||
enabled ? "bg-primary" : "bg-input",
|
||||
"relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-1 focus:ring-primary focus:ring-offset-1"
|
||||
"toggle-component-switch "
|
||||
)}
|
||||
>
|
||||
<span className="sr-only">Use setting</span>
|
||||
<span
|
||||
className={classNames(
|
||||
enabled ? "translate-x-5" : "translate-x-0",
|
||||
"pointer-events-none relative inline-block h-5 w-5 transform rounded-full shadow ring-0 transition duration-200 ease-in-out",
|
||||
"toggle-component-span",
|
||||
disabled ? "bg-input " : "bg-background"
|
||||
)}
|
||||
>
|
||||
|
|
@ -38,7 +38,7 @@ export default function ToggleComponent({
|
|||
enabled
|
||||
? "opacity-0 duration-100 ease-out"
|
||||
: "opacity-100 duration-200 ease-in",
|
||||
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
|
||||
"toggle-component-second-span"
|
||||
)}
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
|
|
@ -47,7 +47,7 @@ export default function ToggleComponent({
|
|||
enabled
|
||||
? "opacity-100 duration-200 ease-in"
|
||||
: "opacity-0 duration-100 ease-out",
|
||||
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
|
||||
"toggle-component-second-span"
|
||||
)}
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ const AccordionContent = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const badgeVariants = cva(
|
|||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export interface BadgeProps
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const buttonVariants = cva(
|
|||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export interface ButtonProps
|
||||
|
|
@ -49,7 +49,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
Button.displayName = "Button";
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ const Checkbox = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
|||
className={cn(
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
|
||||
inset && "pl-8",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
@ -47,7 +47,7 @@ const DropdownMenuSubContent = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in 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}
|
||||
/>
|
||||
|
|
@ -65,7 +65,7 @@ const DropdownMenuContent = React.forwardRef<
|
|||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -84,7 +84,7 @@ const DropdownMenuItem = React.forwardRef<
|
|||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
inset && "pl-8",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -99,7 +99,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
|
|
@ -123,7 +123,7 @@ const DropdownMenuRadioItem = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
@ -148,7 +148,7 @@ const DropdownMenuLabel = React.forwardRef<
|
|||
className={cn(
|
||||
"px-2 py-1.5 pl-2 text-sm font-semibold",
|
||||
inset && "pl-8",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|||
type={type}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
Input.displayName = "Input";
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|||
import { cn } from "../../utils";
|
||||
|
||||
const labelVariants = cva(
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
||||
);
|
||||
|
||||
const Label = React.forwardRef<
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ const Menubar = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-10 items-center space-x-1 rounded-md border bg-background p-1",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -39,7 +39,7 @@ const MenubarTrigger = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -57,7 +57,7 @@ const MenubarSubTrigger = React.forwardRef<
|
|||
className={cn(
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
||||
inset && "pl-8",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
@ -75,7 +75,7 @@ const MenubarSubContent = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in 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}
|
||||
/>
|
||||
|
|
@ -88,7 +88,7 @@ const MenubarContent = React.forwardRef<
|
|||
>(
|
||||
(
|
||||
{ className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
|
||||
ref
|
||||
ref,
|
||||
) => (
|
||||
<MenubarPrimitive.Portal>
|
||||
<MenubarPrimitive.Content
|
||||
|
|
@ -98,12 +98,12 @@ const MenubarContent = React.forwardRef<
|
|||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in slide-in-from-top-1",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</MenubarPrimitive.Portal>
|
||||
)
|
||||
),
|
||||
);
|
||||
MenubarContent.displayName = MenubarPrimitive.Content.displayName;
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ const MenubarItem = React.forwardRef<
|
|||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
inset && "pl-8",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -133,7 +133,7 @@ const MenubarCheckboxItem = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
|
|
@ -156,7 +156,7 @@ const MenubarRadioItem = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
@ -181,7 +181,7 @@ const MenubarLabel = React.forwardRef<
|
|||
className={cn(
|
||||
"px-2 py-1.5 text-sm font-semibold",
|
||||
inset && "pl-8",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -208,7 +208,7 @@ const MenubarShortcut = ({
|
|||
<span
|
||||
className={cn(
|
||||
"ml-auto text-xs tracking-widest text-muted-foreground",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ const Progress = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const Separator = React.forwardRef<
|
|||
>(
|
||||
(
|
||||
{ className, orientation = "horizontal", decorative = true, ...props },
|
||||
ref
|
||||
ref,
|
||||
) => (
|
||||
<SeparatorPrimitive.Root
|
||||
ref={ref}
|
||||
|
|
@ -19,11 +19,11 @@ const Separator = React.forwardRef<
|
|||
className={cn(
|
||||
"shrink-0 bg-border",
|
||||
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
),
|
||||
);
|
||||
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ const TableRow = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -70,7 +70,7 @@ const TableHead = React.forwardRef<
|
|||
ref={ref}
|
||||
className={cn(
|
||||
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|||
<textarea
|
||||
className={cn(
|
||||
"flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
Textarea.displayName = "Textarea";
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const TooltipContent = React.forwardRef<
|
|||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 overflow-hidden 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}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ TWEAKS = ${
|
|||
}
|
||||
flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS)
|
||||
# Now you can use it like any chain
|
||||
flow("Hey, have you heard of LangFlow?")`;
|
||||
flow("Hey, have you heard of Langflow?")`;
|
||||
};
|
||||
|
||||
function buildTweakObject(tweak) {
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ export function AlertProvider({ children }: { children: ReactNode }) {
|
|||
function removeFromNotificationList(index: string) {
|
||||
// set the notification list to a new array that filters out the alert with the matching id
|
||||
setNotificationList((prevAlertsList) =>
|
||||
prevAlertsList.filter((alert) => alert.id !== index)
|
||||
prevAlertsList.filter((alert) => alert.id !== index),
|
||||
);
|
||||
}
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export const darkContext = createContext<darkContextType>(initialValue);
|
|||
|
||||
export function DarkProvider({ children }) {
|
||||
const [dark, setDark] = useState(
|
||||
JSON.parse(window.localStorage.getItem("isDark")) ?? false
|
||||
JSON.parse(window.localStorage.getItem("isDark")) ?? false,
|
||||
);
|
||||
useEffect(() => {
|
||||
if (dark) {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export const locationContext = createContext<locationContextType>(initialValue);
|
|||
export function LocationProvider({ children }: { children: ReactNode }) {
|
||||
const [current, setCurrent] = useState(initialValue.current);
|
||||
const [isStackedOpen, setIsStackedOpen] = useState(
|
||||
initialValue.isStackedOpen
|
||||
initialValue.isStackedOpen,
|
||||
);
|
||||
const [showSideBar, setShowSideBar] = useState(initialValue.showSideBar);
|
||||
const [extraNavigation, setExtraNavigation] = useState({ title: "" });
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
// function loadCookie(cookie: string) {
|
||||
// if (cookie && Object.keys(templates).length > 0) {
|
||||
// let cookieObject: LangFlowState = JSON.parse(cookie);
|
||||
// let cookieObject: LangflowState = JSON.parse(cookie);
|
||||
// try {
|
||||
// cookieObject.flows.forEach((flow) => {
|
||||
// if (!flow.data) {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
|
|||
acc[c] = result.data[curr][c];
|
||||
});
|
||||
return acc;
|
||||
}, {})
|
||||
}, {}),
|
||||
);
|
||||
// Set the types by reducing over the keys of the result data and updating the accumulator.
|
||||
setTypes(
|
||||
|
|
@ -62,10 +62,10 @@ export function TypesProvider({ children }: { children: ReactNode }) {
|
|||
result.data[curr][c].base_classes?.forEach((b) => {
|
||||
acc[b] = curr;
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
return acc;
|
||||
}, {})
|
||||
}, {}),
|
||||
);
|
||||
}
|
||||
// Clear the interval if successful.
|
||||
|
|
@ -99,12 +99,12 @@ export function TypesProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
function deleteNode(idx: string) {
|
||||
reactFlowInstance.setNodes(
|
||||
reactFlowInstance.getNodes().filter((n: Node) => n.id !== idx)
|
||||
reactFlowInstance.getNodes().filter((n: Node) => n.id !== idx),
|
||||
);
|
||||
reactFlowInstance.setEdges(
|
||||
reactFlowInstance
|
||||
.getEdges()
|
||||
.filter((ns) => ns.source !== idx && ns.target !== idx)
|
||||
.filter((ns) => ns.source !== idx && ns.target !== idx),
|
||||
);
|
||||
}
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export function UndoRedoProvider({ children }) {
|
|||
const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => []));
|
||||
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => []));
|
||||
const [tabIndex, setTabIndex] = useState(
|
||||
flows.findIndex((f) => f.id === tabId)
|
||||
flows.findIndex((f) => f.id === tabId),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -70,7 +70,7 @@ export function UndoRedoProvider({ children }) {
|
|||
let newPast = cloneDeep(old);
|
||||
newPast[tabIndex] = old[tabIndex].slice(
|
||||
old[tabIndex].length - defaultOptions.maxHistorySize + 1,
|
||||
old[tabIndex].length
|
||||
old[tabIndex].length,
|
||||
);
|
||||
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
|
||||
return newPast;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const GITHUB_API_URL = "https://api.github.com";
|
|||
export async function getRepoStars(owner, repo) {
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`${GITHUB_API_URL}/repos/${owner}/${repo}`
|
||||
`${GITHUB_API_URL}/repos/${owner}/${repo}`,
|
||||
);
|
||||
return response.data.stargazers_count;
|
||||
} catch (error) {
|
||||
|
|
@ -45,7 +45,7 @@ export async function sendAll(data: sendAllProps) {
|
|||
}
|
||||
|
||||
export async function postValidateCode(
|
||||
code: string
|
||||
code: string,
|
||||
): Promise<AxiosResponse<errorsTypeAPI>> {
|
||||
return await axios.post("/api/v1/validate/code", { code });
|
||||
}
|
||||
|
|
@ -128,7 +128,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 axios.patch(`/api/v1/flows/${updatedFlow.id}`, {
|
||||
|
|
@ -304,7 +304,7 @@ export async function getHealth() {
|
|||
*
|
||||
*/
|
||||
export async function getBuildStatus(
|
||||
flowId: string
|
||||
flowId: string,
|
||||
): Promise<BuildStatusTypeAPI> {
|
||||
return await axios.get(`/api/v1/build/${flowId}/status`);
|
||||
}
|
||||
|
|
@ -317,7 +317,7 @@ export async function getBuildStatus(
|
|||
*
|
||||
*/
|
||||
export async function postBuildInit(
|
||||
flow: FlowType
|
||||
flow: FlowType,
|
||||
): Promise<AxiosResponse<InitTypeAPI>> {
|
||||
return await axios.post(`/api/v1/build/init/${flow.id}`, flow);
|
||||
}
|
||||
|
|
@ -333,7 +333,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);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export const DESCRIPTIONS: string[] = [
|
|||
"Generate, Innovate, Communicate.",
|
||||
"Conversation Catalyst Engine.",
|
||||
"Language Chainlink Master.",
|
||||
"Design Dialogues with LangFlow.",
|
||||
"Design Dialogues with Langflow.",
|
||||
"Nurture NLP Nodes Here.",
|
||||
"Conversational Cartography Unlocked.",
|
||||
"Design, Develop, Dialogize.",
|
||||
|
|
@ -31,7 +31,7 @@ export const DESCRIPTIONS: string[] = [
|
|||
"Where Language Meets Logic.",
|
||||
"Building Intelligent Interactions.",
|
||||
"Your Passport to Linguistic Landscapes.",
|
||||
"Create, Curate, Communicate with LangFlow.",
|
||||
"Create, Curate, Communicate with Langflow.",
|
||||
"Flow into the Future of Language.",
|
||||
"Mapping Meaningful Conversations.",
|
||||
"Unravel the Art of Articulation.",
|
||||
|
|
@ -41,7 +41,7 @@ export const DESCRIPTIONS: string[] = [
|
|||
"The Pinnacle of Prompt Generation.",
|
||||
"Language Models, Mapped and Mastered.",
|
||||
"Powerful Prompts, Perfectly Positioned.",
|
||||
"Innovation in Interaction with LangFlow.",
|
||||
"Innovation in Interaction with Langflow.",
|
||||
"Your Toolkit for Text Generation.",
|
||||
"Unfolding Linguistic Possibilities.",
|
||||
"Building Powerful Solutions with Language Models.",
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ import { ReactComponent as AzSVG } from "./az_logo.svg";
|
|||
export const AzIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <AzSVG ref={ref} {...props} />;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ import { ReactComponent as BingSVG } from "./bing.svg";
|
|||
export const BingIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <BingSVG ref={ref} {...props} />;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ import { ReactComponent as FacebookMessengerSVG } from "./Facebook_Messenger_log
|
|||
export const FBIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <FacebookMessengerSVG ref={ref} {...props} />;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ import { ReactComponent as IFixItSVG } from "./ifixit-seeklogo.com.svg";
|
|||
export const IFixIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <IFixItSVG ref={ref} {...props} />;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ import { ReactComponent as MetaSVG } from "./meta-icon.svg";
|
|||
export const MetaIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <MetaSVG ref={ref} {...props} />;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ import { ReactComponent as SearxSVG } from "./Searx_logo.svg";
|
|||
export const SearxIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <SearxSVG ref={ref} {...props} />;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ import { ReactComponent as SlackSVG } from "./slack-icon.svg";
|
|||
export const SlackIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <SlackSVG ref={ref} {...props} />;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ import { ReactComponent as WordSVG } from "./word.svg";
|
|||
export const WordIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
|
||||
(props, ref) => {
|
||||
return <WordSVG ref={ref} {...props} />;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -145,6 +145,60 @@ The cursor: default; property value restores the browser's default cursor style
|
|||
|
||||
|
||||
@layer components {
|
||||
.round-buttons-position {
|
||||
@apply fixed right-4
|
||||
}
|
||||
.side-bar-arrangement {
|
||||
@apply flex h-full w-52 flex-col overflow-hidden border-r scrollbar-hide
|
||||
}
|
||||
.side-bar-search-div-placement {
|
||||
@apply relative mx-auto mb-2 mt-2 flex items-center
|
||||
}
|
||||
.side-bar-components-icon {
|
||||
@apply h-6 w-4 text-ring
|
||||
}
|
||||
.side-bar-components-text {
|
||||
@apply w-full truncate pr-1 text-xs text-foreground
|
||||
}
|
||||
.side-bar-components-div-form {
|
||||
@apply flex w-full items-center justify-between rounded-md rounded-l-none border border-l-0 border-dashed border-ring bg-white px-3 py-1 text-sm
|
||||
}
|
||||
.side-bar-components-border {
|
||||
@apply cursor-grab rounded-l-md border-l-8
|
||||
}
|
||||
.side-bar-components-gap {
|
||||
@apply flex flex-col gap-2 p-2
|
||||
}
|
||||
.side-bar-components-div-arrangement {
|
||||
@apply w-full overflow-auto scrollbar-hide
|
||||
}
|
||||
.search-icon {
|
||||
@apply absolute inset-y-0 right-0 flex items-center py-1.5 pr-3
|
||||
}
|
||||
.extra-side-bar-save-disable {
|
||||
@apply text-muted-foreground
|
||||
}
|
||||
.extra-side-bar-save-disable:hover {
|
||||
@apply hover:text-accent-foreground
|
||||
}
|
||||
.side-bar-button-size {
|
||||
@apply h-5 w-5
|
||||
}
|
||||
.side-bar-button-size:hover {
|
||||
@apply hover:text-accent-foreground
|
||||
}
|
||||
.side-bar-buttons-arrangement {
|
||||
@apply mb-2 mt-2 flex w-full items-center justify-between gap-2 px-2
|
||||
}
|
||||
.extra-side-bar-buttons {
|
||||
@apply relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out
|
||||
}
|
||||
.extra-side-bar-buttons:hover {
|
||||
@apply hover:bg-muted
|
||||
}
|
||||
.button-div-style {
|
||||
@apply gap-2 flex
|
||||
}
|
||||
.input-primary:focus{
|
||||
@apply focus:placeholder-transparent focus:ring-ring focus:border-ring
|
||||
}
|
||||
|
|
@ -163,4 +217,694 @@ The cursor: default; property value restores the browser's default cursor style
|
|||
.input-dialog{
|
||||
@apply text-ring cursor-pointer bg-transparent
|
||||
}
|
||||
.round-button-form {
|
||||
@apply flex h-12 w-12 cursor-pointer justify-center rounded-full bg-border px-3 py-1 shadow-md
|
||||
}
|
||||
.round-button-div {
|
||||
@apply flex items-center gap-3
|
||||
}
|
||||
.build-trigger-loading-icon {
|
||||
@apply stroke-build-trigger
|
||||
}
|
||||
.build-trigger-icon {
|
||||
@apply w-6 fill-build-trigger stroke-1 stroke-build-trigger
|
||||
}
|
||||
.message-button-position {
|
||||
@apply absolute bottom-4 right-3
|
||||
}
|
||||
.message-button-icon {
|
||||
@apply w-6 fill-chat-trigger stroke-chat-trigger stroke-1
|
||||
}
|
||||
.components-disclosure-arrangement {
|
||||
@apply -mt-px flex w-full select-none items-center justify-between border-y border-y-input bg-muted px-3 py-2
|
||||
}
|
||||
.components-disclosure-title {
|
||||
@apply flex items-center text-sm text-primary
|
||||
}
|
||||
.components-disclosure-div {
|
||||
@apply flex gap-2
|
||||
}
|
||||
.flow-page-positioning {
|
||||
@apply h-full w-full overflow-hidden
|
||||
}
|
||||
.logspace-page-icon {
|
||||
@apply absolute bottom-2 left-7 flex h-6 cursor-pointer flex-col items-center justify-start overflow-hidden rounded-lg bg-foreground px-2 text-center font-sans text-xs tracking-wide text-secondary transition-all duration-500 ease-in-out
|
||||
}
|
||||
|
||||
.logspace-page-icon:hover {
|
||||
@apply hover:h-12
|
||||
}
|
||||
|
||||
.flex-max-width {
|
||||
@apply flex w-full
|
||||
}
|
||||
|
||||
.main-page-panel {
|
||||
@apply flex-max-width h-full flex-col overflow-auto bg-muted px-16
|
||||
}
|
||||
|
||||
.main-page-nav-arrangement {
|
||||
@apply flex-max-width justify-between px-6 py-12 pb-2
|
||||
}
|
||||
|
||||
.main-page-nav-title {
|
||||
@apply flex items-center justify-center gap-2 text-2xl font-semibold
|
||||
}
|
||||
|
||||
.main-page-nav-button {
|
||||
@apply mr-2 w-4
|
||||
}
|
||||
|
||||
.main-page-description-text {
|
||||
@apply flex w-[60%] px-6 pb-14 text-muted-foreground
|
||||
}
|
||||
|
||||
.main-page-flows-display {
|
||||
@apply grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4
|
||||
}
|
||||
|
||||
.community-page-arrangement {
|
||||
@apply flex-max-width h-full flex-col overflow-auto bg-muted px-16
|
||||
}
|
||||
|
||||
.community-page-nav-arrangement {
|
||||
@apply flex-max-width justify-between px-6 py-12 pb-2
|
||||
}
|
||||
|
||||
.community-page-nav-title {
|
||||
@apply flex items-center justify-center gap-2 text-2xl font-semibold
|
||||
}
|
||||
|
||||
.community-page-nav-button {
|
||||
@apply flex gap-2
|
||||
}
|
||||
|
||||
.community-page-description-text {
|
||||
@apply flex w-[70%] px-6 pb-8 text-muted-foreground
|
||||
}
|
||||
|
||||
.community-pages-flows-panel {
|
||||
@apply grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4
|
||||
}
|
||||
.generic-node-div {
|
||||
@apply relative flex w-96 flex-col justify-center rounded-lg bg-background
|
||||
}
|
||||
.generic-node-div-title {
|
||||
@apply flex w-full items-center justify-between gap-8 rounded-t-lg border-b bg-muted p-4
|
||||
}
|
||||
.generic-node-title-arrangement {
|
||||
@apply flex-max-width items-center truncate
|
||||
}
|
||||
.generic-node-icon {
|
||||
@apply h-10 w-10 rounded p-1
|
||||
}
|
||||
.generic-node-tooltip-div {
|
||||
@apply ml-2 truncate
|
||||
}
|
||||
.generic-node-validation-div {
|
||||
@apply max-h-96 overflow-auto
|
||||
}
|
||||
|
||||
.generic-node-status-position {
|
||||
@apply relative top-[3px] h-5 w-5
|
||||
}
|
||||
|
||||
.generic-node-status-animation {
|
||||
@apply hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0
|
||||
}
|
||||
.generic-node-status {
|
||||
@apply h-4 w-4 rounded-full opacity-100
|
||||
}
|
||||
.green-status {
|
||||
@apply generic-node-status bg-status-green
|
||||
}
|
||||
.red-status {
|
||||
@apply generic-node-status bg-status-red
|
||||
}
|
||||
.yellow-status {
|
||||
@apply generic-node-status bg-status-yellow
|
||||
}
|
||||
.status-build-animation {
|
||||
@apply hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0
|
||||
}
|
||||
.status-div {
|
||||
@apply absolute w-4 duration-200 ease-in-out
|
||||
}
|
||||
.status-div:hover {
|
||||
@apply hover:text-accent-foreground hover:transition-all
|
||||
}
|
||||
.generic-node-desc {
|
||||
@apply h-full w-full py-5 text-foreground
|
||||
}
|
||||
.generic-node-desc-text {
|
||||
@apply w-full px-5 pb-3 text-sm text-muted-foreground
|
||||
}
|
||||
|
||||
.alert-icon {
|
||||
@apply h-5 w-5
|
||||
}
|
||||
.alert-font-size {
|
||||
@apply text-sm font-medium
|
||||
}
|
||||
|
||||
.error-build-message {
|
||||
@apply mt-6 w-96 cursor-pointer rounded-md bg-error-background p-4 shadow-xl
|
||||
}
|
||||
.error-build-message-circle {
|
||||
@apply text-status-red alert-icon
|
||||
}
|
||||
.error-build-text {
|
||||
@apply text-error-foreground
|
||||
}
|
||||
.error-build-foreground {
|
||||
@apply error-build-text alert-font-size
|
||||
}
|
||||
.error-build-message-div {
|
||||
@apply mt-2 text-sm error-build-text
|
||||
}
|
||||
.error-build-message-list {
|
||||
@apply list-disc space-y-1 pl-5
|
||||
}
|
||||
|
||||
.success-alert {
|
||||
@apply mt-6 w-96 rounded-md bg-success-background p-4 shadow-xl
|
||||
}
|
||||
.success-alert-icon {
|
||||
@apply alert-icon text-status-green
|
||||
}
|
||||
.success-alert-message {
|
||||
@apply alert-font-size text-success-foreground
|
||||
}
|
||||
|
||||
.card-component-title-display {
|
||||
@apply round-button-div flex-max-width
|
||||
}
|
||||
.card-component-image {
|
||||
@apply flex h-7 w-7 items-center justify-center rounded-full text-2xl
|
||||
}
|
||||
.card-component-title-size {
|
||||
@apply inline-block w-full flex-1 break-words truncate-doubleline
|
||||
}
|
||||
.card-component-delete-button {
|
||||
@apply flex self-start
|
||||
}
|
||||
.card-component-delete-icon {
|
||||
@apply h-4 w-4 text-primary opacity-0 transition-all group-hover:opacity-100
|
||||
}
|
||||
.card-component-desc {
|
||||
@apply pb-2 pt-2
|
||||
}
|
||||
.card-component-desc-text {
|
||||
@apply truncate-doubleline
|
||||
}
|
||||
.card-component-footer-arrangement {
|
||||
@apply flex-max-width items-end justify-between gap-2
|
||||
}
|
||||
.card-component-footer {
|
||||
@apply flex flex-wrap gap-2
|
||||
}
|
||||
|
||||
.unused-side-bar-aside {
|
||||
@apply flex flex-shrink-0 flex-col overflow-hidden border-r transition-all duration-500
|
||||
}
|
||||
.unused-side-bar-arrangement {
|
||||
@apply flex h-full w-52 flex-col items-start overflow-y-auto border bg-background scrollbar-hide
|
||||
}
|
||||
.unused-side-bar-division {
|
||||
@apply flex-max-width flex-grow flex-col
|
||||
}
|
||||
.unused-side-bar-nav {
|
||||
@apply flex-1 space-y-1
|
||||
}
|
||||
.unused-side-bar-link {
|
||||
@apply flex-max-width items-center rounded-md py-2 pl-2 text-sm font-medium
|
||||
}
|
||||
.unused-side-bar-link-colors-true {
|
||||
@apply bg-muted text-foreground
|
||||
}
|
||||
.unused-side-bar-link-colors-false {
|
||||
@apply bg-background text-muted-foreground hover:bg-muted hover:text-foreground
|
||||
}
|
||||
.unused-side-bar-icon {
|
||||
@apply mr-3 flex-shrink-0 h-6 w-6
|
||||
}
|
||||
.unused-side-bar-icon-false {
|
||||
@apply text-ring group-hover:text-accent-foreground
|
||||
}
|
||||
.unused-side-bar-disclosure {
|
||||
@apply unused-side-bar-link pr-1 text-left
|
||||
}
|
||||
.unused-side-bar-disclosure:focus {
|
||||
@apply focus:outline-none focus:ring-1 focus:ring-ring
|
||||
}
|
||||
.unused-side-bar-disclosure-icon {
|
||||
@apply unused-side-bar-icon text-ring group-hover:text-accent-foreground
|
||||
}
|
||||
.unused-side-bar-svg-true {
|
||||
@apply text-ring rotate-90
|
||||
}
|
||||
.unused-side-bar-svg {
|
||||
@apply ml-3 h-5 w-5 flex-shrink-0 duration-150 ease-in-out group-hover:text-accent-foreground
|
||||
}
|
||||
.unused-side-bar-disclosure-panel {
|
||||
@apply flex w-full items-center rounded-md py-2 pl-11 pr-2 text-sm font-medium
|
||||
}
|
||||
|
||||
.code-area-component {
|
||||
@apply pointer-events-none w-full cursor-not-allowed
|
||||
}
|
||||
.code-area-input-positioning {
|
||||
@apply flex-max-width items-center
|
||||
}
|
||||
.code-area-external-link {
|
||||
@apply w-6 h-6 ml-3
|
||||
}
|
||||
.code-area-external-link:hover {
|
||||
@apply hover:text-accent-foreground
|
||||
}
|
||||
|
||||
.dropdown-component-outline {
|
||||
@apply input-edit-node relative pr-8
|
||||
}
|
||||
.dropdown-component-false-outline {
|
||||
@apply input-primary py-2 pl-3 pr-10 text-left
|
||||
}
|
||||
.dropdown-component-display {
|
||||
@apply block w-full truncate bg-background
|
||||
}
|
||||
.dropdown-component-arrow {
|
||||
@apply pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2
|
||||
}
|
||||
.dropdown-component-arrow-color {
|
||||
@apply h-5 w-5 extra-side-bar-save-disable
|
||||
}
|
||||
.dropdown-component-options {
|
||||
@apply z-10 mt-1 max-h-60 overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm
|
||||
}
|
||||
.dropdown-component-true-options {
|
||||
@apply dropdown-component-options w-[215px]
|
||||
}
|
||||
.dropdown-component-false-options {
|
||||
@apply dropdown-component-options w-full
|
||||
}
|
||||
.dropdown-component-option {
|
||||
@apply relative cursor-default select-none
|
||||
}
|
||||
.dropdown-component-false-option {
|
||||
@apply dropdown-component-option py-0.5 pl-3 pr-12
|
||||
}
|
||||
.dropdown-component-true-option {
|
||||
@apply dropdown-component-option py-2 pl-3 pr-9
|
||||
}
|
||||
.dropdown-component-choosal {
|
||||
@apply absolute inset-y-0 right-0 flex items-center pr-4
|
||||
}
|
||||
.dropdown-component-check-icon {
|
||||
@apply h-5 w-5 text-black
|
||||
}
|
||||
|
||||
.edit-flow-arrangement {
|
||||
@apply flex justify-between
|
||||
}
|
||||
.edit-flow-span {
|
||||
@apply ml-10 animate-pulse text-status-red
|
||||
}
|
||||
|
||||
.float-component-pointer {
|
||||
@apply pointer-events-none cursor-not-allowed
|
||||
}
|
||||
|
||||
.header-menu-bar {
|
||||
@apply flex items-center gap-0.5 rounded-md px-1.5 py-1 text-sm font-medium
|
||||
}
|
||||
.header-menu-bar-display {
|
||||
@apply flex max-w-[200px] items-center gap-2
|
||||
}
|
||||
.header-menu-flow-name {
|
||||
@apply flex-1 truncate
|
||||
}
|
||||
.header-menu-options {
|
||||
@apply mr-2 h-4 w-4
|
||||
}
|
||||
|
||||
.header-arrangement {
|
||||
@apply flex-max-width h-12 items-center justify-between border-b bg-muted
|
||||
}
|
||||
.header-start-display {
|
||||
@apply flex w-96 items-center justify-start gap-2
|
||||
}
|
||||
.header-end-division {
|
||||
@apply flex w-96 justify-end px-2
|
||||
}
|
||||
.header-end-display {
|
||||
@apply ml-auto mr-2 flex items-center gap-5
|
||||
}
|
||||
.header-github-link-box {
|
||||
@apply border border-input h-9 px-3 pr-0 rounded-md inline-flex shadow-sm items-center justify-center
|
||||
}
|
||||
.header-github-link {
|
||||
@apply text-sm font-medium disabled:opacity-50 disabled:pointer-events-none ring-offset-background text-muted-foreground header-github-link-box
|
||||
}
|
||||
.header-github-link:focus-visible {
|
||||
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
|
||||
}
|
||||
.header-github-link:hover {
|
||||
@apply hover:bg-accent hover:text-accent-foreground
|
||||
}
|
||||
.header-github-display {
|
||||
@apply -mr-px ml-2 flex h-9 items-center justify-center rounded-md rounded-l-none border bg-background px-2 text-sm
|
||||
}
|
||||
.header-notifications-box {
|
||||
@apply fixed left-0 top-0 h-screen w-screen
|
||||
}
|
||||
.header-notifications {
|
||||
@apply absolute right-[3px] h-1.5 w-1.5 rounded-full bg-destructive
|
||||
}
|
||||
|
||||
.input-component-div {
|
||||
@apply pointer-events-none relative cursor-not-allowed
|
||||
}
|
||||
.input-component-button {
|
||||
@apply absolute inset-y-0 right-0 items-center text-muted-foreground
|
||||
}
|
||||
.input-component-true-button {
|
||||
@apply input-component-button pr-2
|
||||
}
|
||||
.input-component-false-button {
|
||||
@apply input-component-button px-4
|
||||
}
|
||||
.input-component-true-svg {
|
||||
@apply absolute bottom-0.5 right-2 side-bar-button-size
|
||||
}
|
||||
.input-component-false-svg {
|
||||
@apply absolute bottom-2 right-3 side-bar-button-size
|
||||
}
|
||||
|
||||
.input-file-component {
|
||||
@apply flex-max-width items-center
|
||||
}
|
||||
|
||||
.toggle-component-switch {
|
||||
@apply relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out
|
||||
}
|
||||
.toggle-component-switch:focus {
|
||||
@apply focus:outline-none focus:ring-1 focus:ring-primary focus:ring-offset-1
|
||||
}
|
||||
.toggle-component-span {
|
||||
@apply pointer-events-none relative inline-block h-5 w-5 transform rounded-full shadow ring-0 transition duration-200 ease-in-out
|
||||
}
|
||||
.toggle-component-second-span {
|
||||
@apply absolute inset-0 flex h-full w-full items-center justify-center transition-opacity
|
||||
}
|
||||
|
||||
.app-div {
|
||||
@apply fixed bottom-5 left-5 flex flex-col-reverse
|
||||
}
|
||||
|
||||
.chat-input-modal-txtarea {
|
||||
@apply form-input block w-full rounded-md border-ring pr-10 custom-scroll sm:text-sm
|
||||
}
|
||||
.chat-input-modal-div {
|
||||
@apply absolute bottom-0.5 right-3
|
||||
}
|
||||
.chat-input-modal-lock {
|
||||
@apply side-bar-button-size animate-pulse text-ring
|
||||
}
|
||||
.chat-input-modal-send {
|
||||
@apply side-bar-button-size text-ring hover:text-muted-foreground
|
||||
}
|
||||
|
||||
.code-block-modal {
|
||||
@apply flex items-center justify-between px-4 py-1.5
|
||||
}
|
||||
.code-block-modal-span {
|
||||
@apply text-xs lowercase text-background
|
||||
}
|
||||
.code-block-modal-button {
|
||||
@apply flex items-center gap-1.5 rounded bg-none p-1 text-xs text-background
|
||||
}
|
||||
|
||||
.chat-message-modal {
|
||||
@apply flex-max-width py-2 pl-2
|
||||
}
|
||||
.chat-message-modal-div {
|
||||
@apply my-3 flex h-8 w-8 items-center justify-center overflow-hidden rounded-full
|
||||
}
|
||||
.chat-message-modal-img {
|
||||
@apply absolute scale-150 transition-opacity duration-500
|
||||
}
|
||||
.chat-message-modal-display {
|
||||
@apply flex-max-width items-center text-start
|
||||
}
|
||||
.chat-message-modal-text {
|
||||
@apply relative inline-block w-full text-start text-sm font-normal text-muted-foreground
|
||||
}
|
||||
.chat-message-modal-icon-div {
|
||||
@apply absolute -left-2 -top-1 cursor-pointer
|
||||
}
|
||||
.chat-message-modal-thought {
|
||||
@apply ml-3 inline-block h-full w-[95%] rounded-md border border-ring bg-muted px-2 pb-3 pt-3 text-start text-muted-foreground chat-message-modal-thought-cursor
|
||||
}
|
||||
.chat-message-modal-thought-cursor {
|
||||
@apply cursor-pointer scrollbar-hide overflow-scroll
|
||||
}
|
||||
.chat-message-modal-markdown {
|
||||
@apply w-full px-4 pb-3 pr-8 pt-3
|
||||
}
|
||||
.chat-message-modal-markdown-span {
|
||||
@apply mt-1 animate-pulse cursor-default
|
||||
}
|
||||
.chat-message-modal-alert {
|
||||
@apply inline-block px-3 text-start text-muted-foreground
|
||||
}
|
||||
|
||||
.file-card-modal-image-div {
|
||||
@apply absolute right-0 top-0 rounded-bl-lg bg-muted px-1 text-sm font-bold text-foreground
|
||||
}
|
||||
.file-card-modal-image-button {
|
||||
@apply px-2 py-1 text-ring
|
||||
}
|
||||
.file-card-modal-button {
|
||||
@apply flex w-1/2 items-center justify-between rounded border border-ring bg-muted px-2 py-2 text-foreground shadow hover:drop-shadow-lg
|
||||
}
|
||||
.file-card-modal-div {
|
||||
@apply mr-2 flex-max-width items-center gap-2 text-current
|
||||
}
|
||||
.file-card-modal-footer {
|
||||
@apply flex flex-col items-start
|
||||
}
|
||||
.file-card-modal-name {
|
||||
@apply truncate text-sm text-current
|
||||
}
|
||||
.file-card-modal-type {
|
||||
@apply truncate text-xs text-ring
|
||||
}
|
||||
|
||||
.send-message-modal-transition {
|
||||
@apply fixed inset-0 bg-black bg-opacity-80 backdrop-blur-sm transition-opacity
|
||||
}
|
||||
.chat-modal-box {
|
||||
@apply fixed inset-0 z-10 overflow-y-auto
|
||||
}
|
||||
.chat-modal-box-div {
|
||||
@apply flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0
|
||||
}
|
||||
.chat-modal-dialog-panel {
|
||||
@apply relative flex h-[95%] w-[690px] transform flex-col justify-between overflow-hidden rounded-lg bg-background text-left shadow-xl drop-shadow-2xl transition-all
|
||||
}
|
||||
.chat-modal-dialog-panel-div {
|
||||
@apply relative w-full p-4
|
||||
}
|
||||
.chat-modal-dialog-trash-panel {
|
||||
@apply absolute right-10 top-2 z-30 text-muted-foreground hover:text-status-red
|
||||
}
|
||||
.chat-modal-dialog-x-panel {
|
||||
@apply absolute right-2 top-1.5 z-30 text-muted-foreground hover:text-status-red
|
||||
}
|
||||
.chat-modal-dialog-history {
|
||||
@apply flex-max-width h-full flex-col items-center overflow-scroll border-t bg-background scrollbar-hide
|
||||
}
|
||||
.chat-modal-dialog-span-box {
|
||||
@apply flex-max-width h-full flex-col items-center justify-center text-center align-middle
|
||||
}
|
||||
.chat-modal-dialog-desc {
|
||||
@apply w-2/4 rounded-md border border-input bg-muted px-6 py-8
|
||||
}
|
||||
.chat-modal-input-div {
|
||||
@apply flex-max-width flex-col items-center justify-between border-t bg-background p-3
|
||||
}
|
||||
.chat-modal-input {
|
||||
@apply relative mt-1 w-full rounded-md shadow-sm
|
||||
}
|
||||
.code-area-modal-editor-div {
|
||||
@apply mt-2 flex-max-width h-full
|
||||
}
|
||||
.code-area-modal-editor-box {
|
||||
@apply h-[300px] w-full rounded-lg border-[1px] border-ring custom-scroll
|
||||
}
|
||||
|
||||
.edit-node-modal-variable {
|
||||
@apply h-5 w-5 stroke-2 pe-1 text-muted-foreground
|
||||
}
|
||||
.edit-node-modal-span {
|
||||
@apply text-sm font-semibold text-primary
|
||||
}
|
||||
.edit-node-modal-arrangement {
|
||||
@apply flex-max-width h-fit max-h-[400px]
|
||||
}
|
||||
.edit-node-modal-box {
|
||||
@apply w-full rounded-lg border-[1px] border-input bg-background
|
||||
}
|
||||
.edit-node-modal-table {
|
||||
@apply flex h-fit flex-col gap-5
|
||||
}
|
||||
.edit-node-modal-table-header {
|
||||
@apply h-10 border-input text-xs font-medium text-ring
|
||||
}
|
||||
.edit-node-modal-table-cell {
|
||||
@apply p-0 text-center text-sm text-foreground truncate sm:px-3
|
||||
}
|
||||
.edit-node-modal-second-cell {
|
||||
@apply w-[300px] p-0 text-center text-xs text-foreground
|
||||
}
|
||||
|
||||
.generic-modal-txtarea-div {
|
||||
@apply mt-2 flex-max-width h-full
|
||||
}
|
||||
|
||||
.button-box-modal-div {
|
||||
@apply flex transform flex-col items-center justify-center rounded-lg border border-ring text-center shadow hover:scale-105 hover:shadow-lg
|
||||
}
|
||||
|
||||
.dialog-header-modal-div {
|
||||
@apply absolute left-0 top-2 z-50 hidden pl-4 pt-4 sm:block
|
||||
}
|
||||
.dialog-header-modal-button {
|
||||
@apply rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2
|
||||
}
|
||||
|
||||
.dialog-modal-examples-div {
|
||||
@apply h-full w-full overflow-y-auto scrollbar-hide
|
||||
}
|
||||
.dialog-modal-example-true {
|
||||
@apply mx-auto flex flex-row flex-wrap items-start justify-center overflow-auto
|
||||
}
|
||||
.dialog-modal-example-false {
|
||||
@apply flex flex-row items-center justify-center
|
||||
}
|
||||
.dialog-modal-button-box-div {
|
||||
@apply flex-max-width h-full items-center justify-evenly
|
||||
}
|
||||
.document-icon {
|
||||
@apply h-10 w-10 flex-shrink-0
|
||||
}
|
||||
.loading-component-div {
|
||||
@apply flex items-center justify-center align-middle
|
||||
}
|
||||
.dialog-modal-footer {
|
||||
@apply mt-2 flex-max-width items-center justify-center
|
||||
}
|
||||
.dialog-modal-footer-link {
|
||||
@apply flex items-center justify-center text-muted-foreground
|
||||
}
|
||||
|
||||
.node-modal-div {
|
||||
@apply fixed inset-0 bg-ring bg-opacity-75 transition-opacity
|
||||
}
|
||||
.node-modal-dialog-arrangement {
|
||||
@apply fixed inset-0 z-10 overflow-y-auto
|
||||
}
|
||||
.node-modal-dialog-div {
|
||||
@apply flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0
|
||||
}
|
||||
.node-modal-dialog-panel {
|
||||
@apply relative flex h-[600px] w-[700px] transform flex-col justify-between overflow-hidden rounded-lg bg-background text-left shadow-xl transition-all sm:my-8
|
||||
}
|
||||
.node-modal-dialog-panel-div {
|
||||
@apply absolute right-0 top-0 z-50 hidden pr-4 pt-4 sm:block
|
||||
}
|
||||
.node-modal-dialog-button {
|
||||
@apply rounded-md text-ring hover:text-accent-foreground
|
||||
}
|
||||
.node-modal-dialog-icon-div {
|
||||
@apply flex-max-width h-full flex-col items-center justify-center
|
||||
}
|
||||
.node-modal-icon-arrangement {
|
||||
@apply z-10 flex-max-width justify-center pb-4 shadow-sm
|
||||
}
|
||||
.node-modal-icon {
|
||||
@apply mt-4 h-10 w-10 rounded p-1
|
||||
}
|
||||
.node-modal-title-div {
|
||||
@apply mt-4 text-center sm:ml-4 sm:text-left
|
||||
}
|
||||
.node-modal-title {
|
||||
@apply text-lg font-medium leading-10 text-foreground
|
||||
}
|
||||
.node-modal-template-div {
|
||||
@apply flex-max-width h-full flex-row items-center justify-center gap-4 bg-input p-4
|
||||
}
|
||||
.node-modal-template {
|
||||
@apply w-full rounded-lg bg-background px-4 shadow sm:p-4
|
||||
}
|
||||
.node-modal-template-column {
|
||||
@apply flex h-full flex-col gap-5
|
||||
}
|
||||
.node-modal-button-box {
|
||||
@apply flex-max-width flex-row-reverse bg-input px-4 pb-3
|
||||
}
|
||||
.node-modal-button {
|
||||
@apply inline-flex w-full justify-center rounded-md border border-transparent bg-status-red px-4 py-2 text-base font-medium text-background shadow-sm hover:bg-ring sm:ml-3 sm:w-auto sm:text-sm
|
||||
}
|
||||
.node-modal-button:focus {
|
||||
@apply focus:outline-none focus:ring-1 focus:ring-ring focus:ring-offset-1
|
||||
}
|
||||
|
||||
.prompt-modal-icon-box {
|
||||
@apply mx-auto mt-4 flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-almost-light-blue sm:mx-0 sm:h-10 sm:w-10
|
||||
}
|
||||
.prompt-modal-icon {
|
||||
@apply h-6 w-6 text-almost-medium-blue
|
||||
}
|
||||
.prompt-modal-txtarea-arrangement {
|
||||
@apply flex-max-width h-full flex-row items-center justify-center gap-4 overflow-auto bg-accent p-4
|
||||
}
|
||||
.prompt-modal-txtarea-box {
|
||||
@apply h-full w-full overflow-hidden rounded-lg bg-background px-4 py-5 shadow sm:p-6
|
||||
}
|
||||
.prompt-modal-txtarea {
|
||||
@apply form-input h-full w-full rounded-lg border-ring
|
||||
}
|
||||
|
||||
.txtarea-modal-arrangement {
|
||||
@apply flex h-full w-full flex-row items-center justify-center gap-4 bg-input p-4
|
||||
}
|
||||
.txtarea-modal-box {
|
||||
@apply w-full overflow-hidden rounded-lg bg-background px-4 py-5 shadow sm:p-6
|
||||
}
|
||||
.txtarea-modal-input {
|
||||
@apply form-input h-full w-full
|
||||
}
|
||||
|
||||
.api-modal-tabs {
|
||||
@apply w-full h-full overflow-hidden text-center bg-muted rounded-md border
|
||||
}
|
||||
.api-modal-tablist-div {
|
||||
@apply flex items-center justify-between px-2
|
||||
}
|
||||
.api-modal-tabs-content {
|
||||
@apply overflow-hidden w-full h-full px-4 pb-4 -mt-1
|
||||
}
|
||||
.api-modal-accordion-display {
|
||||
@apply flex w-full h-full mt-2
|
||||
}
|
||||
.api-modal-table-arrangement {
|
||||
@apply flex flex-col gap-5 h-fit
|
||||
}
|
||||
|
||||
.icons-parameters-comp{
|
||||
@apply ml-3 h-6 w-6
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -8,13 +8,13 @@ import ContextWrapper from "./contexts";
|
|||
import "./index.css";
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById("root") as HTMLElement
|
||||
document.getElementById("root") as HTMLElement,
|
||||
);
|
||||
root.render(
|
||||
<ContextWrapper>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</ContextWrapper>
|
||||
</ContextWrapper>,
|
||||
);
|
||||
reportWebVitals();
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data.node.template[n].type === "code" ||
|
||||
t.data.node.template[n].type === "prompt" ||
|
||||
t.data.node.template[n].type === "file" ||
|
||||
t.data.node.template[n].type === "int")
|
||||
t.data.node.template[n].type === "int"),
|
||||
)
|
||||
.map((n, i) => {
|
||||
arrNodesWithValues.push(t["id"]);
|
||||
|
|
@ -182,7 +182,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
}
|
||||
|
||||
const existingTweak = tweak.current.find((element) =>
|
||||
element.hasOwnProperty(tw)
|
||||
element.hasOwnProperty(tw),
|
||||
);
|
||||
|
||||
if (existingTweak) {
|
||||
|
|
@ -278,7 +278,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
className="h-full w-full overflow-hidden rounded-md border bg-muted text-center"
|
||||
className="api-modal-tabs"
|
||||
onValueChange={(value) => {
|
||||
setActiveTab(value);
|
||||
if (value === "3") {
|
||||
|
|
@ -286,7 +286,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
}
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center justify-between px-2">
|
||||
<div className="api-modal-tablist-div">
|
||||
<TabsList>
|
||||
{tabs.map((tab, index) => (
|
||||
<TabsTrigger key={index} value={index.toString()}>
|
||||
|
|
@ -310,7 +310,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
{tabs.map((tab, index) => (
|
||||
<TabsContent
|
||||
value={index.toString()}
|
||||
className="-mt-1 h-full w-full overflow-hidden px-4 pb-4"
|
||||
className="api-modal-tabs-content"
|
||||
key={index} // Remember to add a unique key prop
|
||||
>
|
||||
{index < 3 ? (
|
||||
|
|
@ -323,13 +323,13 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
</SyntaxHighlighter>
|
||||
) : index === 3 ? (
|
||||
<>
|
||||
<div className="mt-2 flex h-full w-full">
|
||||
<div className="api-modal-according-display">
|
||||
<div
|
||||
className={classNames(
|
||||
"h-[60vh] w-full rounded-lg bg-muted",
|
||||
1 == 1
|
||||
? "overflow-scroll overflow-x-hidden custom-scroll"
|
||||
: "overflow-hidden"
|
||||
: "overflow-hidden",
|
||||
)}
|
||||
>
|
||||
{flow["data"]["nodes"].map((t: any, index) => (
|
||||
|
|
@ -339,7 +339,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
trigger={t["data"]["id"]}
|
||||
open={openAccordion}
|
||||
>
|
||||
<div className="flex h-fit flex-col gap-5">
|
||||
<div className="api-modal-table-arrangement">
|
||||
<Table className="table-fixed bg-muted outline-1">
|
||||
<TableHeader className="h-10 border-input text-xs font-medium text-ring">
|
||||
<TableRow className="dark:border-b-muted">
|
||||
|
|
@ -370,7 +370,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data.node.template[n].type ===
|
||||
"file" ||
|
||||
t.data.node.template[n].type ===
|
||||
"int")
|
||||
"int"),
|
||||
)
|
||||
.map((n, i) => {
|
||||
//console.log(t.data.node.template[n]);
|
||||
|
|
@ -413,7 +413,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t["data"]["id"],
|
||||
k,
|
||||
t.data.node
|
||||
.template[n]
|
||||
.template[n],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -424,7 +424,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
content={buildContent(
|
||||
t.data.node.template[
|
||||
n
|
||||
].value
|
||||
].value,
|
||||
)}
|
||||
>
|
||||
<div>
|
||||
|
|
@ -437,14 +437,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
.value,
|
||||
t.data,
|
||||
t.data.node
|
||||
.template[n]
|
||||
.template[n],
|
||||
)}
|
||||
onChange={(k) => {
|
||||
buildTweakObject(
|
||||
t["data"]["id"],
|
||||
k,
|
||||
t.data.node
|
||||
.template[n]
|
||||
.template[n],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -466,14 +466,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data,
|
||||
t.data.node.template[
|
||||
n
|
||||
]
|
||||
],
|
||||
)}
|
||||
onChange={(k) => {
|
||||
buildTweakObject(
|
||||
t["data"]["id"],
|
||||
k,
|
||||
t.data.node
|
||||
.template[n]
|
||||
.template[n],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -498,7 +498,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
e,
|
||||
t.data.node.template[
|
||||
n
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
size="small"
|
||||
|
|
@ -514,8 +514,8 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data.node.template[n]
|
||||
.value,
|
||||
t.data,
|
||||
t.data.node.template[n]
|
||||
)
|
||||
t.data.node.template[n],
|
||||
),
|
||||
)}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
|
|
@ -528,7 +528,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
].value ?? ""
|
||||
}
|
||||
onChange={(
|
||||
k: any
|
||||
k: any,
|
||||
) => {}}
|
||||
fileTypes={
|
||||
t.data.node.template[
|
||||
|
|
@ -541,7 +541,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
].suffixes
|
||||
}
|
||||
onFileChange={(
|
||||
k: any
|
||||
k: any,
|
||||
) => {}}
|
||||
></InputFileComponent>
|
||||
</div>
|
||||
|
|
@ -556,7 +556,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data.node.template[n]
|
||||
.value,
|
||||
t.data,
|
||||
t.data.node.template[n]
|
||||
t.data.node.template[n],
|
||||
)}
|
||||
onChange={(k) => {
|
||||
buildTweakObject(
|
||||
|
|
@ -564,7 +564,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
k,
|
||||
t.data.node.template[
|
||||
n
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -587,14 +587,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
k,
|
||||
t.data.node.template[
|
||||
n
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
value={getValue(
|
||||
t.data.node.template[n]
|
||||
.value,
|
||||
t.data,
|
||||
t.data.node.template[n]
|
||||
t.data.node.template[n],
|
||||
)}
|
||||
></Dropdown>
|
||||
</div>
|
||||
|
|
@ -608,7 +608,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data.node.template[n]
|
||||
.value,
|
||||
t.data,
|
||||
t.data.node.template[n]
|
||||
t.data.node.template[n],
|
||||
)}
|
||||
onChange={(k) => {
|
||||
buildTweakObject(
|
||||
|
|
@ -616,7 +616,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
k,
|
||||
t.data.node.template[
|
||||
n
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -630,8 +630,8 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data.node.template[n]
|
||||
.value,
|
||||
t.data,
|
||||
t.data.node.template[n]
|
||||
)
|
||||
t.data.node.template[n],
|
||||
),
|
||||
)}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
|
|
@ -645,14 +645,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data,
|
||||
t.data.node.template[
|
||||
n
|
||||
]
|
||||
],
|
||||
)}
|
||||
onChange={(k) => {
|
||||
buildTweakObject(
|
||||
t["data"]["id"],
|
||||
k,
|
||||
t.data.node
|
||||
.template[n]
|
||||
.template[n],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -667,8 +667,8 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data.node.template[n]
|
||||
.value,
|
||||
t.data,
|
||||
t.data.node.template[n]
|
||||
)
|
||||
t.data.node.template[n],
|
||||
),
|
||||
)}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
|
|
@ -682,14 +682,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
t.data,
|
||||
t.data.node.template[
|
||||
n
|
||||
]
|
||||
],
|
||||
)}
|
||||
onChange={(k) => {
|
||||
buildTweakObject(
|
||||
t["data"]["id"],
|
||||
k,
|
||||
t.data.node
|
||||
.template[n]
|
||||
.template[n],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
|
|||
data.node.template[t].type === "code" ||
|
||||
data.node.template[t].type === "prompt" ||
|
||||
data.node.template[t].type === "file" ||
|
||||
data.node.template[t].type === "int")
|
||||
).length
|
||||
data.node.template[t].type === "int"),
|
||||
).length,
|
||||
);
|
||||
const [nodeValue, setNodeValue] = useState(null);
|
||||
const { closePopUp } = useContext(PopUpContext);
|
||||
|
|
@ -90,27 +90,27 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
|
|||
<DialogDescription>
|
||||
{data.node?.description}
|
||||
<div className="flex pt-3">
|
||||
<Variable className="h-5 w-5 stroke-2 pe-1 text-muted-foreground "></Variable>
|
||||
<span className="text-sm font-semibold text-primary">
|
||||
<Variable className="edit-node-modal-variable "></Variable>
|
||||
<span className="edit-node-modal-span">
|
||||
Parameters
|
||||
</span>
|
||||
</div>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex h-fit max-h-[400px] w-full">
|
||||
<div className="edit-node-modal-arrangement">
|
||||
<div
|
||||
className={classNames(
|
||||
"w-full rounded-lg border-[1px] border-input bg-background",
|
||||
"edit-node-modal-box",
|
||||
nodeLength > limitScrollFieldsModal
|
||||
? "overflow-scroll overflow-x-hidden custom-scroll"
|
||||
: "overflow-hidden"
|
||||
: "overflow-hidden",
|
||||
)}
|
||||
>
|
||||
{nodeLength > 0 && (
|
||||
<div className="flex h-fit flex-col gap-5">
|
||||
<div className="edit-node-modal-table">
|
||||
<Table className="table-fixed bg-muted outline-1">
|
||||
<TableHeader className="h-10 border-input text-xs font-medium text-ring">
|
||||
<TableHeader className="edit-node-modal-table-header">
|
||||
<TableRow className="">
|
||||
<TableHead className="h-7 text-center">PARAM</TableHead>
|
||||
<TableHead className="h-7 p-0 text-center">
|
||||
|
|
@ -131,7 +131,7 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
|
|||
data.node.template[t].type === "code" ||
|
||||
data.node.template[t].type === "prompt" ||
|
||||
data.node.template[t].type === "file" ||
|
||||
data.node.template[t].type === "int")
|
||||
data.node.template[t].type === "int"),
|
||||
)
|
||||
.map((n, i) => (
|
||||
<TableRow key={i} className="h-10">
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export default function ModalField({
|
|||
index,
|
||||
}) {
|
||||
const [enabled, setEnabled] = useState(
|
||||
data.node.template[name]?.value ?? false
|
||||
data.node.template[name]?.value ?? false,
|
||||
);
|
||||
const display =
|
||||
type === "str" ||
|
||||
|
|
@ -41,12 +41,12 @@ export default function ModalField({
|
|||
(t) =>
|
||||
t.charAt(0) !== "_" &&
|
||||
data.node.template[t].advanced &&
|
||||
data.node.template[t].show
|
||||
data.node.template[t].show,
|
||||
).length -
|
||||
1 ===
|
||||
index
|
||||
? "pb-4"
|
||||
: ""
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
{display && (
|
||||
|
|
|
|||
|
|
@ -45,11 +45,11 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
|
|||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-ring bg-opacity-75 transition-opacity" />
|
||||
<div className="node-modal-div" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-10 overflow-y-auto">
|
||||
<div className="flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
||||
<div className="node-modal-dialog-arrangement">
|
||||
<div className="node-modal-dialog-div">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
|
|
@ -59,11 +59,11 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
|
|||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative flex h-[600px] w-[700px] transform flex-col justify-between overflow-hidden rounded-lg bg-background text-left shadow-xl transition-all sm:my-8">
|
||||
<div className=" absolute right-0 top-0 z-50 hidden pr-4 pt-4 sm:block">
|
||||
<Dialog.Panel className="node-modal-dialog-panel">
|
||||
<div className=" node-modal-dialog-panel-div">
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-md text-ring hover:text-accent-foreground"
|
||||
className="node-modal-dialog-button"
|
||||
onClick={() => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
|
|
@ -72,47 +72,47 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
|
|||
<X className="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||
<div className="z-10 flex w-full justify-center pb-4 shadow-sm">
|
||||
<div className="node-modal-dialog-icon-div">
|
||||
<div className="node-modal-icon-arrangement">
|
||||
<Icon
|
||||
strokeWidth={1.5}
|
||||
className="mt-4 h-10 w-10 rounded p-1"
|
||||
className="node-modal-icon"
|
||||
style={{
|
||||
color:
|
||||
nodeColors[types[data.type]] ?? nodeColors.unknown,
|
||||
}}
|
||||
/>
|
||||
<div className="mt-4 text-center sm:ml-4 sm:text-left">
|
||||
<div className="node-modal-title-div">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="text-lg font-medium leading-10 text-foreground"
|
||||
className="node-modal-title"
|
||||
>
|
||||
{data.type}
|
||||
</Dialog.Title>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex h-full w-full flex-row items-center justify-center gap-4 bg-input p-4">
|
||||
<div className="flex h-[445px] w-full">
|
||||
<div className="node-modal-template-div">
|
||||
<div className="flex-max-width h-[445px]">
|
||||
<div
|
||||
className={classNames(
|
||||
"w-full rounded-lg bg-background px-4 shadow sm:p-4",
|
||||
"node-modal-template",
|
||||
Object.keys(data.node.template).filter(
|
||||
(t) =>
|
||||
t.charAt(0) !== "_" &&
|
||||
data.node.template[t].advanced &&
|
||||
data.node.template[t].show
|
||||
data.node.template[t].show,
|
||||
).length > limitScrollFieldsModal
|
||||
? "overflow-scroll overflow-x-hidden custom-scroll"
|
||||
: "overflow-hidden"
|
||||
: "overflow-hidden",
|
||||
)}
|
||||
>
|
||||
<div className="flex h-full flex-col gap-5">
|
||||
<div className="node-modal-template-column">
|
||||
{Object.keys(data.node.template)
|
||||
.filter(
|
||||
(t) =>
|
||||
t.charAt(0) !== "_" &&
|
||||
data.node.template[t].advanced &&
|
||||
data.node.template[t].show
|
||||
data.node.template[t].show,
|
||||
)
|
||||
.map((t: string, idx) => {
|
||||
return (
|
||||
|
|
@ -144,10 +144,10 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-full flex-row-reverse bg-input px-4 pb-3">
|
||||
<div className="node-modal-button-box">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex w-full justify-center rounded-md border border-transparent bg-status-red px-4 py-2 text-base font-medium text-background shadow-sm hover:bg-ring focus:outline-none focus:ring-1 focus:ring-ring focus:ring-offset-1 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
className="node-modal-button"
|
||||
onClick={() => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
|
|
|
|||
161
src/frontend/src/modals/chatModal/chatMessage/index.tsx
Normal file
161
src/frontend/src/modals/chatModal/chatMessage/index.tsx
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import { ChatMessageType } from "../../../types/chat";
|
||||
import { classNames } from "../../../utils";
|
||||
import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg";
|
||||
import AiIconStill from "../../../assets/froze-flow.png";
|
||||
import FileCard from "../fileComponent";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import rehypeMathjax from "rehype-mathjax";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
import { CodeBlock } from "./codeBlock";
|
||||
import Convert from "ansi-to-html";
|
||||
import { User2, MessageCircle } from "lucide-react";
|
||||
import DOMPurify from "dompurify";
|
||||
export default function ChatMessage({
|
||||
chat,
|
||||
lockChat,
|
||||
lastMessage,
|
||||
}: {
|
||||
chat: ChatMessageType;
|
||||
lockChat: boolean;
|
||||
lastMessage: boolean;
|
||||
}) {
|
||||
const convert = new Convert({ newline: true });
|
||||
const [message, setMessage] = useState("");
|
||||
const imgRef = useRef(null);
|
||||
useEffect(() => {
|
||||
setMessage(chat.message);
|
||||
}, [chat.message]);
|
||||
const [hidden, setHidden] = useState(true);
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"chat-message-modal",
|
||||
chat.isSend ? "bg-background " : "bg-input"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
"chat-message-modal-div"
|
||||
)}
|
||||
>
|
||||
{!chat.isSend && (
|
||||
<div className="relative h-8 w-8">
|
||||
<img
|
||||
className={
|
||||
"chat-message-modal-img " +
|
||||
(lockChat ? "opacity-100" : "opacity-0")
|
||||
}
|
||||
src={lastMessage ? AiIcon : AiIconStill}
|
||||
/>
|
||||
<img
|
||||
className={
|
||||
"chat-message-modal-img " +
|
||||
(lockChat ? "opacity-0" : "opacity-100")
|
||||
}
|
||||
src={AiIconStill}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{chat.isSend && <User2 className="-mb-1 h-6 w-6 text-primary " />}
|
||||
</div>
|
||||
{!chat.isSend ? (
|
||||
<div className="chat-message-modal-display">
|
||||
<div className="chat-message-modal-text">
|
||||
{hidden && chat.thought && chat.thought !== "" && (
|
||||
<div
|
||||
onClick={() => setHidden((prev) => !prev)}
|
||||
className="chat-message-modal-icon-div"
|
||||
>
|
||||
<MessageCircle className="h-5 w-5 animate-bounce " />
|
||||
</div>
|
||||
)}
|
||||
{chat.thought && chat.thought !== "" && !hidden && (
|
||||
<div
|
||||
onClick={() => setHidden((prev) => !prev)}
|
||||
className=" chat-message-modal-thought"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
|
||||
}}
|
||||
></div>
|
||||
)}
|
||||
{chat.thought && chat.thought !== "" && !hidden && <br></br>}
|
||||
<div className="chat-message-modal-markdown">
|
||||
<div className="w-full">
|
||||
<div className="w-full">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm, remarkMath]}
|
||||
rehypePlugins={[rehypeMathjax]}
|
||||
className="markdown prose text-muted-foreground "
|
||||
components={{
|
||||
code({ node, inline, className, children, ...props }) {
|
||||
if (children.length) {
|
||||
if (children[0] == "▍") {
|
||||
return (
|
||||
<span className="chat-message-modal-markdown-span">
|
||||
▍
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
children[0] = (children[0] as string).replace(
|
||||
"`▍`",
|
||||
"▍"
|
||||
);
|
||||
}
|
||||
|
||||
const match = /language-(\w+)/.exec(className || "");
|
||||
|
||||
return !inline ? (
|
||||
<CodeBlock
|
||||
key={Math.random()}
|
||||
language={(match && match[1]) || ""}
|
||||
value={String(children).replace(/\n$/, "")}
|
||||
{...props}
|
||||
/>
|
||||
) : (
|
||||
<code className={className} {...props}>
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
},
|
||||
}}
|
||||
>
|
||||
{message}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
{chat.files && (
|
||||
<div className="my-2 w-full">
|
||||
{chat.files.map((file, index) => {
|
||||
return (
|
||||
<div key={index} className="my-2 w-full">
|
||||
<FileCard
|
||||
fileName={"Generated File"}
|
||||
fileType={file.data_type}
|
||||
content={file.data}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex w-full items-center">
|
||||
<div className="chat-message-modal-alert ">
|
||||
{message.split("\n").map((line, index) => (
|
||||
<span key={index} className="text-muted-foreground ">
|
||||
{line}
|
||||
<br />
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
418
src/frontend/src/modals/chatModal/index.tsx
Normal file
418
src/frontend/src/modals/chatModal/index.tsx
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { Fragment, useContext, useEffect, useRef, useState } from "react";
|
||||
import { FlowType } from "../../types/flow";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { validateNodes } from "../../utils";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import ChatMessage from "./chatMessage";
|
||||
import { X, MessagesSquare, Eraser } from "lucide-react";
|
||||
import { sendAllProps } from "../../types/api";
|
||||
import { ChatMessageType } from "../../types/chat";
|
||||
import ChatInput from "./chatInput";
|
||||
|
||||
import _ from "lodash";
|
||||
import { getHealth } from "../../controllers/API";
|
||||
|
||||
export default function ChatModal({
|
||||
flow,
|
||||
open,
|
||||
setOpen,
|
||||
}: {
|
||||
open: boolean;
|
||||
setOpen: Function;
|
||||
flow: FlowType;
|
||||
}) {
|
||||
const [chatValue, setChatValue] = useState("");
|
||||
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
|
||||
const { reactFlowInstance } = useContext(typesContext);
|
||||
const { setErrorData, setNoticeData } = useContext(alertContext);
|
||||
const ws = useRef<WebSocket | null>(null);
|
||||
const [lockChat, setLockChat] = useState(false);
|
||||
const isOpen = useRef(open);
|
||||
const messagesRef = useRef(null);
|
||||
const id = useRef(flow.id);
|
||||
|
||||
useEffect(() => {
|
||||
if (messagesRef.current) {
|
||||
messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
|
||||
}
|
||||
}, [chatHistory]);
|
||||
|
||||
useEffect(() => {
|
||||
isOpen.current = open;
|
||||
}, [open]);
|
||||
useEffect(() => {
|
||||
id.current = flow.id;
|
||||
}, [flow.id]);
|
||||
|
||||
var isStream = false;
|
||||
|
||||
const addChatHistory = (
|
||||
message: string,
|
||||
isSend: boolean,
|
||||
thought?: string,
|
||||
files?: Array<any>
|
||||
) => {
|
||||
setChatHistory((old) => {
|
||||
let newChat = _.cloneDeep(old);
|
||||
if (files) {
|
||||
newChat.push({ message, isSend, files, thought });
|
||||
} else if (thought) {
|
||||
newChat.push({ message, isSend, thought });
|
||||
} else {
|
||||
newChat.push({ message, isSend });
|
||||
}
|
||||
return newChat;
|
||||
});
|
||||
};
|
||||
|
||||
//add proper type signature for function
|
||||
|
||||
function updateLastMessage({
|
||||
str,
|
||||
thought,
|
||||
end = false,
|
||||
files,
|
||||
}: {
|
||||
str?: string;
|
||||
thought?: string;
|
||||
// end param default is false
|
||||
end?: boolean;
|
||||
files?: Array<any>;
|
||||
}) {
|
||||
setChatHistory((old) => {
|
||||
let newChat = [...old];
|
||||
if (str) {
|
||||
if (end) {
|
||||
newChat[newChat.length - 1].message = str;
|
||||
} else {
|
||||
newChat[newChat.length - 1].message =
|
||||
newChat[newChat.length - 1].message + str;
|
||||
}
|
||||
}
|
||||
if (thought) {
|
||||
newChat[newChat.length - 1].thought = thought;
|
||||
}
|
||||
if (files) {
|
||||
newChat[newChat.length - 1].files = files;
|
||||
}
|
||||
return newChat;
|
||||
});
|
||||
}
|
||||
|
||||
function handleOnClose(event: CloseEvent) {
|
||||
if (isOpen.current) {
|
||||
setErrorData({ title: event.reason });
|
||||
setTimeout(() => {
|
||||
connectWS();
|
||||
setLockChat(false);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function getWebSocketUrl(chatId, isDevelopment = false) {
|
||||
const isSecureProtocol = window.location.protocol === "https:";
|
||||
const webSocketProtocol = isSecureProtocol ? "wss" : "ws";
|
||||
const host = isDevelopment ? "localhost:7860" : window.location.host;
|
||||
const chatEndpoint = `/api/v1/chat/${chatId}`;
|
||||
|
||||
return `${
|
||||
isDevelopment ? "ws" : webSocketProtocol
|
||||
}://${host}${chatEndpoint}`;
|
||||
}
|
||||
|
||||
function handleWsMessage(data: any) {
|
||||
if (Array.isArray(data)) {
|
||||
//set chat history
|
||||
setChatHistory((_) => {
|
||||
let newChatHistory: ChatMessageType[] = [];
|
||||
data.forEach(
|
||||
(chatItem: {
|
||||
intermediate_steps?: "string";
|
||||
is_bot: boolean;
|
||||
message: string;
|
||||
type: string;
|
||||
files?: Array<any>;
|
||||
}) => {
|
||||
if (chatItem.message) {
|
||||
newChatHistory.push(
|
||||
chatItem.files
|
||||
? {
|
||||
isSend: !chatItem.is_bot,
|
||||
message: chatItem.message,
|
||||
thought: chatItem.intermediate_steps,
|
||||
files: chatItem.files,
|
||||
}
|
||||
: {
|
||||
isSend: !chatItem.is_bot,
|
||||
message: chatItem.message,
|
||||
thought: chatItem.intermediate_steps,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
return newChatHistory;
|
||||
});
|
||||
}
|
||||
if (data.type === "start") {
|
||||
addChatHistory("", false);
|
||||
isStream = true;
|
||||
}
|
||||
if (data.type === "end") {
|
||||
if (data.message) {
|
||||
updateLastMessage({ str: data.message, end: true });
|
||||
}
|
||||
if (data.intermediate_steps) {
|
||||
updateLastMessage({
|
||||
str: data.message,
|
||||
thought: data.intermediate_steps,
|
||||
end: true,
|
||||
});
|
||||
}
|
||||
if (data.files) {
|
||||
updateLastMessage({
|
||||
end: true,
|
||||
files: data.files,
|
||||
});
|
||||
}
|
||||
|
||||
setLockChat(false);
|
||||
isStream = false;
|
||||
}
|
||||
if (data.type === "stream" && isStream) {
|
||||
updateLastMessage({ str: data.message });
|
||||
}
|
||||
}
|
||||
|
||||
function connectWS() {
|
||||
try {
|
||||
const urlWs = getWebSocketUrl(
|
||||
id.current,
|
||||
process.env.NODE_ENV === "development"
|
||||
);
|
||||
const newWs = new WebSocket(urlWs);
|
||||
newWs.onopen = () => {
|
||||
console.log("WebSocket connection established!");
|
||||
};
|
||||
newWs.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
console.log("Received data:", data);
|
||||
handleWsMessage(data);
|
||||
//get chat history
|
||||
};
|
||||
newWs.onclose = (event) => {
|
||||
handleOnClose(event);
|
||||
};
|
||||
newWs.onerror = (ev) => {
|
||||
getHealth()
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
connectWS();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setErrorData({
|
||||
// message when the backend failed
|
||||
title: "The backend is not responding. Please try again later.",
|
||||
// possible solution list
|
||||
list: [
|
||||
"Check your internet connection.",
|
||||
"Check if the backend is running.",
|
||||
],
|
||||
});
|
||||
});
|
||||
};
|
||||
ws.current = newWs;
|
||||
} catch (error) {
|
||||
connectWS();
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
connectWS();
|
||||
return () => {
|
||||
console.log("unmount");
|
||||
console.log(ws);
|
||||
if (ws.current) {
|
||||
ws.current.close();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
ws.current &&
|
||||
(ws.current.readyState === ws.current.CLOSED ||
|
||||
ws.current.readyState === ws.current.CLOSING)
|
||||
) {
|
||||
connectWS();
|
||||
setLockChat(false);
|
||||
}
|
||||
}, [lockChat]);
|
||||
|
||||
async function sendAll(data: sendAllProps) {
|
||||
try {
|
||||
if (ws) {
|
||||
ws.current.send(JSON.stringify(data));
|
||||
}
|
||||
} catch (error) {
|
||||
setErrorData({
|
||||
title: "There was an error sending the message",
|
||||
list: [error.message],
|
||||
});
|
||||
setChatValue(data.message);
|
||||
connectWS();
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current) ref.current.scrollIntoView({ behavior: "smooth" });
|
||||
}, [chatHistory]);
|
||||
|
||||
const ref = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (open && ref.current) {
|
||||
ref.current.focus();
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
function sendMessage() {
|
||||
if (chatValue !== "") {
|
||||
let nodeValidationErrors = validateNodes(reactFlowInstance);
|
||||
if (nodeValidationErrors.length === 0) {
|
||||
setLockChat(true);
|
||||
let message = chatValue;
|
||||
setChatValue("");
|
||||
addChatHistory(message, true);
|
||||
sendAll({
|
||||
...reactFlowInstance.toObject(),
|
||||
message,
|
||||
chatHistory,
|
||||
name: flow.name,
|
||||
description: flow.description,
|
||||
});
|
||||
} else {
|
||||
setErrorData({
|
||||
title: "Oops! Looks like you missed some required information:",
|
||||
list: nodeValidationErrors,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setErrorData({
|
||||
title: "Error sending message",
|
||||
list: ["The message cannot be empty."],
|
||||
});
|
||||
}
|
||||
}
|
||||
function clearChat() {
|
||||
setChatHistory([]);
|
||||
ws.current.send(JSON.stringify({ clear_history: true }));
|
||||
if (lockChat) setLockChat(false);
|
||||
}
|
||||
|
||||
function setModalOpen(x: boolean) {
|
||||
setOpen(x);
|
||||
}
|
||||
return (
|
||||
<Transition.Root show={open} appear={open} as={Fragment}>
|
||||
<Dialog
|
||||
as="div"
|
||||
className="relative z-10"
|
||||
onClose={setModalOpen}
|
||||
initialFocus={ref}
|
||||
>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="send-message-modal-transition" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="chat-modal-box">
|
||||
<div className="chat-modal-box-div">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className=" chat-modal-dialog-panel">
|
||||
<div className="chat-modal-dialog-panel-div">
|
||||
<button
|
||||
onClick={() => clearChat()}
|
||||
className="chat-modal-dialog-trash-panel"
|
||||
>
|
||||
<Eraser className="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setModalOpen(false)}
|
||||
className="chat-modal-dialog-x-panel"
|
||||
>
|
||||
<X className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
ref={messagesRef}
|
||||
className="chat-modal-dialog-history"
|
||||
>
|
||||
{chatHistory.length > 0 ? (
|
||||
chatHistory.map((c, i) => (
|
||||
<ChatMessage
|
||||
lockChat={lockChat}
|
||||
chat={c}
|
||||
lastMessage={chatHistory.length - 1 == i ? true : false}
|
||||
key={i}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<div className="chat-modal-dialog-span-box">
|
||||
<span>
|
||||
👋{" "}
|
||||
<span className="text-lg text-muted-foreground">
|
||||
Langflow Chat
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<div className="chat-modal-dialog-desc">
|
||||
<span className="text-base text-ring">
|
||||
Start a conversation and click the agent’s thoughts{" "}
|
||||
<span>
|
||||
<MessagesSquare className="mx-1 inline h-5 w-5 animate-bounce " />
|
||||
</span>{" "}
|
||||
to inspect the chaining process.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div ref={ref}></div>
|
||||
</div>
|
||||
<div className="chat-modal-input-div">
|
||||
<div className="chat-modal-input">
|
||||
<ChatInput
|
||||
chatValue={chatValue}
|
||||
lockChat={lockChat}
|
||||
sendMessage={sendMessage}
|
||||
setChatValue={setChatValue}
|
||||
inputRef={ref}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
);
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ export default function CodeAreaModal({
|
|||
<DialogDescription>{CODE_PROMPT_DIALOG_SUBTITLE}</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="mt-2 flex h-[60vh] w-full">
|
||||
<div className="code-area-modal-editor-div">
|
||||
<AceEditor
|
||||
value={code}
|
||||
mode="python"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export default function ExportModal() {
|
|||
const [checked, setChecked] = useState(false);
|
||||
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
|
||||
const [description, setDescription] = useState(
|
||||
flows.find((f) => f.id === tabId).description
|
||||
flows.find((f) => f.id === tabId).description,
|
||||
);
|
||||
return (
|
||||
<Dialog open={true} onOpenChange={setModalOpen}>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export default function FlowSettingsModal() {
|
|||
const maxLength = 50;
|
||||
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
|
||||
const [description, setDescription] = useState(
|
||||
flows.find((f) => f.id === tabId).description
|
||||
flows.find((f) => f.id === tabId).description,
|
||||
);
|
||||
function setModalOpen(x: boolean) {
|
||||
setOpen(x);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { classNames } from "../../../utils";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { TabsContext } from "../../../contexts/tabsContext";
|
||||
import { Eraser, Lock, LucideSend, Send } from "lucide-react";
|
||||
import { Eraser, Lock, LucideSend } from "lucide-react";
|
||||
|
||||
export default function ChatInput({
|
||||
lockChat,
|
||||
|
|
|
|||
|
|
@ -48,19 +48,19 @@ export const CodeBlock: FC<Props> = memo(({ language, value }) => {
|
|||
};
|
||||
return (
|
||||
<div className="codeblock font-sans text-[16px]">
|
||||
<div className="flex items-center justify-between px-4 py-1.5">
|
||||
<span className="text-xs lowercase text-background">{language}</span>
|
||||
<div className="code-block-modal">
|
||||
<span className="code-block-modal-span">{language}</span>
|
||||
|
||||
<div className="flex items-center">
|
||||
<button
|
||||
className="flex items-center gap-1.5 rounded bg-none p-1 text-xs text-background"
|
||||
className="code-block-modal-button"
|
||||
onClick={copyToClipboard}
|
||||
>
|
||||
{isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
|
||||
{isCopied ? "Copied!" : "Copy code"}
|
||||
</button>
|
||||
<button
|
||||
className="flex items-center rounded bg-none p-1 text-xs text-background"
|
||||
className="code-block-modal-button"
|
||||
onClick={downloadAsFile}
|
||||
>
|
||||
<IconDownload size={18} />
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ export default function FileCard({ fileName, content, fileType }) {
|
|||
/>
|
||||
{isHovered && (
|
||||
<div
|
||||
className={`absolute right-0 top-0 rounded-bl-lg bg-muted px-1 text-sm font-bold text-foreground `}
|
||||
className={`file-card-modal-image-div `}
|
||||
>
|
||||
<button className="px-2 py-1 text-ring " onClick={handleDownload}>
|
||||
<button className="file-card-modal-image-button " onClick={handleDownload}>
|
||||
<DownloadCloud className="h-5 w-5 text-current hover:scale-110" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -51,9 +51,9 @@ export default function FileCard({ fileName, content, fileType }) {
|
|||
return (
|
||||
<button
|
||||
onClick={handleDownload}
|
||||
className="flex w-1/2 items-center justify-between rounded border border-ring bg-muted px-2 py-2 text-foreground shadow hover:drop-shadow-lg"
|
||||
className="file-card-modal-button"
|
||||
>
|
||||
<div className="mr-2 flex w-full items-center gap-2 text-current">
|
||||
<div className="file-card-modal-div">
|
||||
{" "}
|
||||
{fileType === "image" ? (
|
||||
<img
|
||||
|
|
@ -64,10 +64,10 @@ export default function FileCard({ fileName, content, fileType }) {
|
|||
) : (
|
||||
<File className="h-8 w-8" />
|
||||
)}
|
||||
<div className="flex flex-col items-start">
|
||||
<div className="file-card-modal-footer">
|
||||
{" "}
|
||||
<div className="truncate text-sm text-current">{fileName}</div>
|
||||
<div className="truncate text-xs text-ring">{fileType}</div>
|
||||
<div className="file-card-modal-name">{fileName}</div>
|
||||
<div className="file-card-modal-type">{fileType}</div>
|
||||
</div>
|
||||
<DownloadCloud className="ml-auto h-6 w-6 text-current" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -77,11 +77,11 @@ export default function ButtonBox({
|
|||
<button disabled={deactivate} onClick={onClick}>
|
||||
<div
|
||||
className={classNames(
|
||||
"flex transform flex-col items-center justify-center rounded-lg border border-ring text-center shadow hover:scale-105 hover:shadow-lg",
|
||||
"button-box-modal-div",
|
||||
bgColor,
|
||||
height,
|
||||
width,
|
||||
padding
|
||||
padding,
|
||||
)}
|
||||
>
|
||||
<div
|
||||
|
|
@ -98,7 +98,7 @@ export default function ButtonBox({
|
|||
className={classNames(
|
||||
"w-full break-words font-semibold text-background truncate-multiline",
|
||||
titleFontSize,
|
||||
marginTop
|
||||
marginTop,
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,18 @@
|
|||
import {
|
||||
XMarkIcon,
|
||||
ArrowDownTrayIcon,
|
||||
DocumentDuplicateIcon,
|
||||
ComputerDesktopIcon,
|
||||
ArrowUpTrayIcon,
|
||||
ArrowLeftIcon,
|
||||
CommandLineIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import { Fragment, useContext, useRef, useState } from "react";
|
||||
import { useContext, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import ButtonBox from "./buttonBox";
|
||||
import { getExamples } from "../../controllers/API";
|
||||
import { error } from "console";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import LoadingComponent from "../../components/loadingComponent";
|
||||
import { FlowType } from "../../types/flow";
|
||||
import { classNames, snakeToSpaces, toNormalCase } from "../../utils";
|
||||
import { classNames } from "../../utils";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -26,7 +22,6 @@ import {
|
|||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { IMPORT_DIALOG_SUBTITLE } from "../../constants";
|
||||
|
||||
export default function ImportModal() {
|
||||
|
|
@ -76,10 +71,10 @@ export default function ImportModal() {
|
|||
<DialogTitle className="flex items-center">
|
||||
{showExamples && (
|
||||
<>
|
||||
<div className="absolute left-0 top-2 z-50 hidden pl-4 pt-4 sm:block">
|
||||
<div className="dialog-header-modal-div">
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
|
||||
className="dialog-header-modal-button disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
|
||||
onClick={() => {
|
||||
setShowExamples(false);
|
||||
}}
|
||||
|
|
@ -106,20 +101,20 @@ export default function ImportModal() {
|
|||
|
||||
<div
|
||||
className={classNames(
|
||||
"h-full w-full overflow-y-auto scrollbar-hide",
|
||||
"dialog-modal-examples-div",
|
||||
showExamples && !loadingExamples
|
||||
? "start mx-auto flex flex-row flex-wrap items-start justify-center overflow-auto"
|
||||
: "flex flex-row items-center justify-center"
|
||||
? "dialog-modal-example-true"
|
||||
: "dialog-modal-example-false"
|
||||
)}
|
||||
>
|
||||
{!showExamples && (
|
||||
<div className="flex h-full w-full items-center justify-evenly">
|
||||
<div className="dialog-modal-button-box-div">
|
||||
<ButtonBox
|
||||
size="big"
|
||||
bgColor="bg-medium-emerald "
|
||||
description="Prebuilt Examples"
|
||||
icon={
|
||||
<DocumentDuplicateIcon className="h-10 w-10 flex-shrink-0" />
|
||||
<DocumentDuplicateIcon className="document-icon" />
|
||||
}
|
||||
onClick={() => {
|
||||
setShowExamples(true);
|
||||
|
|
@ -133,7 +128,7 @@ export default function ImportModal() {
|
|||
bgColor="bg-almost-dark-blue "
|
||||
description="Import from Local"
|
||||
icon={
|
||||
<ComputerDesktopIcon className="h-10 w-10 flex-shrink-0" />
|
||||
<ComputerDesktopIcon className="document-icon" />
|
||||
}
|
||||
onClick={() => {
|
||||
uploadFlow();
|
||||
|
|
@ -145,7 +140,7 @@ export default function ImportModal() {
|
|||
</div>
|
||||
)}
|
||||
{showExamples && loadingExamples && (
|
||||
<div className="flex items-center justify-center align-middle">
|
||||
<div className="loading-component-div">
|
||||
<LoadingComponent remSize={30} />
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -178,11 +173,11 @@ export default function ImportModal() {
|
|||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<div className="mt-2 flex w-full items-center justify-center">
|
||||
<div className="dialog-modal-footer">
|
||||
<a
|
||||
href="https://github.com/logspace-ai/langflow_examples"
|
||||
target="_blank"
|
||||
className="flex items-center justify-center text-muted-foreground "
|
||||
className="dialog-modal-footer-link "
|
||||
rel="noreferrer"
|
||||
>
|
||||
<svg
|
||||
|
|
@ -197,7 +192,7 @@ export default function ImportModal() {
|
|||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<span className="ml-2 ">LangFlow Examples</span>
|
||||
<span className="ml-2 ">Langflow Examples</span>
|
||||
</a>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
|
|
|
|||
154
src/frontend/src/modals/promptModal/index.tsx
Normal file
154
src/frontend/src/modals/promptModal/index.tsx
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { XMarkIcon, DocumentTextIcon } from "@heroicons/react/24/outline";
|
||||
import { Fragment, useContext, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
import { checkPrompt } from "../../controllers/API";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
export default function PromptAreaModal({
|
||||
value,
|
||||
setValue,
|
||||
}: {
|
||||
setValue: (value: string) => void;
|
||||
value: string;
|
||||
}) {
|
||||
const [open, setOpen] = useState(true);
|
||||
const [myValue, setMyValue] = useState(value);
|
||||
const { dark } = useContext(darkContext);
|
||||
const { setErrorData, setSuccessData } = useContext(alertContext);
|
||||
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
|
||||
const ref = useRef();
|
||||
function setModalOpen(x: boolean) {
|
||||
setOpen(x);
|
||||
if (x === false) {
|
||||
setTimeout(() => {
|
||||
setCloseEdit("prompt");
|
||||
closePopUp();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Transition.Root show={open} appear={true} as={Fragment}>
|
||||
<Dialog
|
||||
as="div"
|
||||
className="relative z-10"
|
||||
onClose={setModalOpen}
|
||||
initialFocus={ref}
|
||||
>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="node-modal-div" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="node-modal-dialog-arrangement">
|
||||
<div className="node-modal-dialog-div">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="node-modal-dialog-panel">
|
||||
<div className=" node-modal-dialog-panel-div ">
|
||||
<button
|
||||
type="button"
|
||||
className="node-modal-dialog-button"
|
||||
onClick={() => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Close</span>
|
||||
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="node-modal-dialog-icon-div">
|
||||
<div className="node-modal-icon-arrangement">
|
||||
<div className="prompt-modal-icon-box">
|
||||
<DocumentTextIcon
|
||||
className="prompt-modal-icon"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<div className="node-modal-title-div ">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="node-modal-title"
|
||||
>
|
||||
Edit Prompt
|
||||
</Dialog.Title>
|
||||
</div>
|
||||
</div>
|
||||
<div className="prompt-modal-txtarea-arrangement">
|
||||
<div className="flex-max-width h-full">
|
||||
<div className="prompt-modal-txtarea-box">
|
||||
<textarea
|
||||
ref={ref}
|
||||
className="prompt-modal-txtarea"
|
||||
value={myValue}
|
||||
onChange={(e) => {
|
||||
setMyValue(e.target.value);
|
||||
setValue(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="node-modal-button-box">
|
||||
<button
|
||||
type="button"
|
||||
className="node-modal-button"
|
||||
onClick={() => {
|
||||
checkPrompt(myValue)
|
||||
.then((apiReturn) => {
|
||||
if (apiReturn.data) {
|
||||
let inputVariables =
|
||||
apiReturn.data.input_variables;
|
||||
if (inputVariables.length === 0) {
|
||||
setErrorData({
|
||||
title:
|
||||
"The template you are attempting to use does not contain any variables for data entry.",
|
||||
});
|
||||
} else {
|
||||
setSuccessData({
|
||||
title: "Prompt is ready",
|
||||
});
|
||||
setModalOpen(false);
|
||||
setValue(myValue);
|
||||
}
|
||||
} else {
|
||||
setErrorData({
|
||||
title: "Something went wrong, please try again",
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
return setErrorData({
|
||||
title:
|
||||
"There is something wrong with this prompt, please review it",
|
||||
list: [error.response.data.detail],
|
||||
});
|
||||
});
|
||||
}}
|
||||
>
|
||||
Check & Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
);
|
||||
}
|
||||
124
src/frontend/src/modals/textAreaModal/index.tsx
Normal file
124
src/frontend/src/modals/textAreaModal/index.tsx
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import {
|
||||
XMarkIcon,
|
||||
ClipboardDocumentListIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import { Fragment, useContext, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
|
||||
export default function TextAreaModal({
|
||||
value,
|
||||
setValue,
|
||||
}: {
|
||||
setValue: (value: string) => void;
|
||||
value: string | string[];
|
||||
}) {
|
||||
const [open, setOpen] = useState(true);
|
||||
const [myValue, setMyValue] = useState(value);
|
||||
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
|
||||
const ref = useRef();
|
||||
function setModalOpen(x: boolean) {
|
||||
setOpen(x);
|
||||
if (x === false) {
|
||||
setTimeout(() => {
|
||||
setCloseEdit("textarea");
|
||||
closePopUp();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Transition.Root show={open} appear={true} as={Fragment}>
|
||||
<Dialog
|
||||
as="div"
|
||||
className="relative z-10"
|
||||
onClose={setModalOpen}
|
||||
initialFocus={ref}
|
||||
>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="node-modal-div" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="node-modal-dialog-arrangement">
|
||||
<div className="node-modal-dialog-div">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="node-modal-dialog-panel">
|
||||
<div className=" node-modal-dialog-panel-div">
|
||||
<button
|
||||
type="button"
|
||||
className="node-modal-dialog-button"
|
||||
onClick={() => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Close</span>
|
||||
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="node-modal-dialog-icon-div">
|
||||
<div className="node-modal-icon-arrangement">
|
||||
<div className="prompt-modal-icon-box">
|
||||
<ClipboardDocumentListIcon
|
||||
className="prompt-modal-icon"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<div className="node-modal-title-div">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="node-modal-title"
|
||||
>
|
||||
Edit text
|
||||
</Dialog.Title>
|
||||
</div>
|
||||
</div>
|
||||
<div className="txtarea-modal-arrangement">
|
||||
<div className="flex h-full w-full">
|
||||
<div className="txtarea-modal-box">
|
||||
<textarea
|
||||
ref={ref}
|
||||
className="txtarea-modal-input"
|
||||
value={myValue}
|
||||
onChange={(e) => {
|
||||
setMyValue(e.target.value);
|
||||
setValue(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="node-modal-button-box">
|
||||
<button
|
||||
type="button"
|
||||
className="node-modal-button"
|
||||
onClick={() => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
>
|
||||
Finish editing
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
);
|
||||
}
|
||||
|
|
@ -37,31 +37,31 @@ export default function CommunityPage() {
|
|||
handleExamples();
|
||||
}, []);
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col overflow-auto bg-muted px-16">
|
||||
<div className="flex w-full justify-between px-6 py-12 pb-2">
|
||||
<span className="flex items-center justify-center gap-2 text-2xl font-semibold">
|
||||
<div className="community-page-arrangement">
|
||||
<div className="community-page-nav-arrangement">
|
||||
<span className="community-page-nav-title">
|
||||
<Users2 className="w-6" />
|
||||
Community Examples
|
||||
</span>
|
||||
<div className="flex gap-2">
|
||||
<div className="community-page-nav-button">
|
||||
<a
|
||||
href="https://github.com/logspace-ai/langflow_examples"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button variant="primary">
|
||||
<GithubIcon className="mr-2 w-4" />
|
||||
<GithubIcon className="main-page-nav-button" />
|
||||
Add Your Example
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<span className="flex w-[70%] px-6 pb-8 text-muted-foreground">
|
||||
Discover and learn from shared examples by the LangFlow community. We
|
||||
<span className="community-page-description-text">
|
||||
Discover and learn from shared examples by the Langflow community. We
|
||||
welcome new example contributions that can help our community explore
|
||||
new and powerful features.
|
||||
</span>
|
||||
<div className="grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<div className="community-pages-flows-panel">
|
||||
{!loadingExamples &&
|
||||
examples.map((flow, idx) => (
|
||||
<CardComponent
|
||||
|
|
@ -79,7 +79,7 @@ export default function CommunityPage() {
|
|||
});
|
||||
}}
|
||||
>
|
||||
<GitFork className="mr-2 w-4" />
|
||||
<GitFork className="main-page-nav-button" />
|
||||
Fork Example
|
||||
</Button>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,14 +12,12 @@ export default function DisclosureComponent({
|
|||
{({ open }) => (
|
||||
<>
|
||||
<div>
|
||||
<Disclosure.Button className="-mt-px flex w-full select-none items-center justify-between border-y border-y-input bg-muted px-3 py-2">
|
||||
<Disclosure.Button className="components-disclosure-arrangement">
|
||||
<div className="flex gap-4">
|
||||
<Icon strokeWidth={1.5} size={22} className="text-primary " />
|
||||
<span className="flex items-center text-sm text-primary">
|
||||
{title}
|
||||
</span>
|
||||
<Icon strokeWidth={1.5} size={22} className="text-primary" />
|
||||
<span className="components-disclosure-title">{title}</span>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="components-disclosure-div">
|
||||
{buttons.map((x, index) => (
|
||||
<button key={index} onClick={x.onClick}>
|
||||
{x.Icon}
|
||||
|
|
@ -35,7 +33,7 @@ export default function DisclosureComponent({
|
|||
</div>
|
||||
</Disclosure.Button>
|
||||
</div>
|
||||
<Disclosure.Panel as="div" className="-mt-px" static={openDisc}>
|
||||
<Disclosure.Panel as="div" static={openDisc}>
|
||||
{children}
|
||||
</Disclosure.Panel>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -112,10 +112,10 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
|
||||
const { setErrorData } = useContext(alertContext);
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(
|
||||
flow.data?.nodes ?? []
|
||||
flow.data?.nodes ?? [],
|
||||
);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(
|
||||
flow.data?.edges ?? []
|
||||
flow.data?.edges ?? [],
|
||||
);
|
||||
const { setViewport } = useReactFlow();
|
||||
const edgeUpdateSuccessful = useRef(true);
|
||||
|
|
@ -158,7 +158,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
};
|
||||
});
|
||||
},
|
||||
[onEdgesChange, setNodes, setTabsState, tabId]
|
||||
[onEdgesChange, setNodes, setTabsState, tabId],
|
||||
);
|
||||
|
||||
const onNodesChangeMod = useCallback(
|
||||
|
|
@ -174,7 +174,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
};
|
||||
});
|
||||
},
|
||||
[onNodesChange, setTabsState, tabId]
|
||||
[onNodesChange, setTabsState, tabId],
|
||||
);
|
||||
|
||||
const onConnect = useCallback(
|
||||
|
|
@ -191,15 +191,15 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
: "stroke-foreground ",
|
||||
animated: params.targetHandle.split("|")[0] === "Text",
|
||||
},
|
||||
eds
|
||||
)
|
||||
eds,
|
||||
),
|
||||
);
|
||||
setNodes((x) => {
|
||||
let newX = _.cloneDeep(x);
|
||||
return newX;
|
||||
});
|
||||
},
|
||||
[setEdges, setNodes, takeSnapshot]
|
||||
[setEdges, setNodes, takeSnapshot],
|
||||
);
|
||||
|
||||
const onNodeDragStart: NodeDragHandler = useCallback(() => {
|
||||
|
|
@ -288,7 +288,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
}
|
||||
},
|
||||
// Specify dependencies for useCallback
|
||||
[getNodeId, reactFlowInstance, setErrorData, setNodes, takeSnapshot]
|
||||
[getNodeId, reactFlowInstance, setErrorData, setNodes, takeSnapshot],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -304,11 +304,12 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
takeSnapshot();
|
||||
setEdges(
|
||||
edges.filter(
|
||||
(ns) => !mynodes.some((n) => ns.source === n.id || ns.target === n.id)
|
||||
)
|
||||
(ns) =>
|
||||
!mynodes.some((n) => ns.source === n.id || ns.target === n.id),
|
||||
),
|
||||
);
|
||||
},
|
||||
[takeSnapshot, edges, setEdges]
|
||||
[takeSnapshot, edges, setEdges],
|
||||
);
|
||||
|
||||
const onEdgeUpdateStart = useCallback(() => {
|
||||
|
|
@ -322,7 +323,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
|||
setEdges((els) => updateEdge(oldEdge, newConnection, els));
|
||||
}
|
||||
},
|
||||
[]
|
||||
[],
|
||||
);
|
||||
|
||||
const onEdgeUpdateEnd = useCallback((_, edge) => {
|
||||
|
|
|
|||
|
|
@ -59,48 +59,50 @@ export default function ExtraSidebar() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-52 flex-col overflow-hidden border-r scrollbar-hide">
|
||||
<div className="mb-2 mt-2 flex w-full items-center justify-between gap-2 px-2">
|
||||
<div className="side-bar-arrangement">
|
||||
<div className="side-bar-buttons-arrangement">
|
||||
<ShadTooltip content="Import" side="top">
|
||||
<button
|
||||
className="relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
|
||||
className="extra-side-bar-buttons"
|
||||
onClick={() => {
|
||||
// openPopUp(<ImportModal />);
|
||||
uploadFlow();
|
||||
}}
|
||||
>
|
||||
<FileUp strokeWidth={1.5} className="h-5 w-5 "></FileUp>
|
||||
<FileUp
|
||||
strokeWidth={1.5}
|
||||
className="side-bar-button-size "
|
||||
></FileUp>
|
||||
</button>
|
||||
</ShadTooltip>
|
||||
|
||||
<ShadTooltip content="Export" side="top">
|
||||
<button
|
||||
className={classNames(
|
||||
"relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
|
||||
)}
|
||||
className={classNames("extra-side-bar-buttons")}
|
||||
onClick={(event) => {
|
||||
openPopUp(<ExportModal />);
|
||||
}}
|
||||
>
|
||||
<FileDown strokeWidth={1.5} className="h-5 w-5 "></FileDown>
|
||||
<FileDown
|
||||
strokeWidth={1.5}
|
||||
className="side-bar-button-size"
|
||||
></FileDown>
|
||||
</button>
|
||||
</ShadTooltip>
|
||||
<ShadTooltip content="Code" side="top">
|
||||
<button
|
||||
className={classNames(
|
||||
"relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
|
||||
)}
|
||||
className={classNames("extra-side-bar-buttons")}
|
||||
onClick={(event) => {
|
||||
openPopUp(<ApiModal flow={flows.find((f) => f.id === tabId)} />);
|
||||
}}
|
||||
>
|
||||
<Code2 strokeWidth={1.5} className="h-5 w-5 "></Code2>
|
||||
<Code2 strokeWidth={1.5} className="side-bar-button-size"></Code2>
|
||||
</button>
|
||||
</ShadTooltip>
|
||||
|
||||
<ShadTooltip content="Save" side="top">
|
||||
<button
|
||||
className="relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
|
||||
className="extra-side-bar-buttons"
|
||||
onClick={(event) => {
|
||||
saveFlow(flows.find((f) => f.id === tabId));
|
||||
setSuccessData({ title: "Changes saved successfully" });
|
||||
|
|
@ -110,14 +112,15 @@ export default function ExtraSidebar() {
|
|||
<Save
|
||||
strokeWidth={1.5}
|
||||
className={
|
||||
"h-5 w-5" + (isPending ? " " : " text-muted-foreground")
|
||||
"side-bar-button-size" +
|
||||
(isPending ? " " : " extra-side-bar-save-disable")
|
||||
}
|
||||
></Save>
|
||||
</button>
|
||||
</ShadTooltip>
|
||||
</div>
|
||||
<Separator />
|
||||
<div className="relative mx-auto mb-2 mt-2 flex items-center">
|
||||
<div className="side-bar-search-div-placement">
|
||||
<input
|
||||
type="text"
|
||||
name="search"
|
||||
|
|
@ -129,13 +132,13 @@ export default function ExtraSidebar() {
|
|||
setSearch(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<div className="absolute inset-y-0 right-0 flex items-center py-1.5 pr-3">
|
||||
<div className="search-icon">
|
||||
{/* ! replace hash color here */}
|
||||
<Search size={20} strokeWidth={1.5} className="text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full overflow-auto pb-10 scrollbar-hide">
|
||||
<div className="side-bar-components-div-arrangement">
|
||||
{Object.keys(dataFilter)
|
||||
.sort()
|
||||
.map((d: keyof APIObjectType, i) =>
|
||||
|
|
@ -148,7 +151,7 @@ export default function ExtraSidebar() {
|
|||
Icon: nodeIconsLucide[d] ?? nodeIconsLucide.unknown,
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col gap-2 p-2">
|
||||
<div className="side-bar-components-gap">
|
||||
{Object.keys(dataFilter[d])
|
||||
.sort()
|
||||
.map((t: string, k) => (
|
||||
|
|
@ -160,7 +163,7 @@ export default function ExtraSidebar() {
|
|||
<div key={k} data-tooltip-id={t}>
|
||||
<div
|
||||
draggable
|
||||
className={"cursor-grab rounded-l-md border-l-8"}
|
||||
className={"side-bar-components-border"}
|
||||
style={{
|
||||
borderLeftColor:
|
||||
nodeColors[d] ?? nodeColors.unknown,
|
||||
|
|
@ -179,11 +182,11 @@ export default function ExtraSidebar() {
|
|||
);
|
||||
}}
|
||||
>
|
||||
<div className="flex w-full items-center justify-between rounded-md rounded-l-none border border-l-0 border-dashed border-ring bg-white px-3 py-1 text-sm">
|
||||
<span className="w-full truncate pr-1 text-xs text-foreground">
|
||||
<div className="side-bar-components-div-form">
|
||||
<span className="side-bar-components-text">
|
||||
{data[d][t].display_name}
|
||||
</span>
|
||||
<Menu className="h-6 w-4 text-ring " />
|
||||
<Menu className="side-bar-components-icon " />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { TabsContext } from "../../../../contexts/tabsContext";
|
|||
import { useReactFlow } from "reactflow";
|
||||
import EditNodeModal from "../../../../modals/EditNodeModal";
|
||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
||||
import { EllipsisVerticalIcon } from "@heroicons/react/24/outline";
|
||||
|
||||
const NodeToolbarComponent = (props) => {
|
||||
const [nodeLength, setNodeLength] = useState(
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default function FlowPage() {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className="h-full w-full overflow-hidden">
|
||||
<div className="flow-page-positioning">
|
||||
{flows.length > 0 &&
|
||||
tabId !== "" &&
|
||||
flows.findIndex((flow) => flow.id === tabId) !== -1 && (
|
||||
|
|
@ -29,9 +29,9 @@ export default function FlowPage() {
|
|||
<a
|
||||
target={"_blank"}
|
||||
href="https://logspace.ai/"
|
||||
className="absolute bottom-2 left-7 flex h-6 cursor-pointer flex-col items-center justify-start overflow-hidden rounded-lg bg-foreground px-2 text-center font-sans text-xs tracking-wide text-secondary transition-all duration-500 ease-in-out hover:h-12"
|
||||
className="logspace-page-icon"
|
||||
>
|
||||
{version && <div className="mt-1">⛓️ LangFlow v{version}</div>}
|
||||
{version && <div className="mt-1">⛓️ Langflow v{version}</div>}
|
||||
<div className={version ? "mt-2" : "mt-1"}>Created by Logspace</div>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { Button } from "../../components/ui/button";
|
|||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { CardComponent } from "../../components/cardComponent";
|
||||
import { USER_PROJECTS_HEADER } from "../../constants";
|
||||
import { BUTTON_DIV_STYLE } from "../../constants";
|
||||
export default function HomePage() {
|
||||
const { flows, setTabId, downloadFlows, uploadFlows, addFlow, removeFlow } =
|
||||
useContext(TabsContext);
|
||||
|
|
@ -14,20 +13,20 @@ export default function HomePage() {
|
|||
}, []);
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col overflow-auto bg-muted px-16">
|
||||
<div className="flex w-full justify-between px-6 py-12 pb-2">
|
||||
<span className="flex items-center justify-center gap-2 text-2xl font-semibold">
|
||||
<div className="main-page-panel">
|
||||
<div className="main-page-nav-arrangement">
|
||||
<span className="main-page-nav-title">
|
||||
<Home className="w-6" />
|
||||
{USER_PROJECTS_HEADER}
|
||||
</span>
|
||||
<div className={`${BUTTON_DIV_STYLE}`}>
|
||||
<div className="button-div-style">
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
downloadFlows();
|
||||
}}
|
||||
>
|
||||
<Download className="mr-2 w-4" />
|
||||
<Download className="main-page-nav-button" />
|
||||
Download Collection
|
||||
</Button>
|
||||
<Button
|
||||
|
|
@ -36,7 +35,7 @@ export default function HomePage() {
|
|||
uploadFlows();
|
||||
}}
|
||||
>
|
||||
<Upload className="mr-2 w-4" />
|
||||
<Upload className="main-page-nav-button" />
|
||||
Upload Collection
|
||||
</Button>
|
||||
<Button
|
||||
|
|
@ -47,15 +46,15 @@ export default function HomePage() {
|
|||
});
|
||||
}}
|
||||
>
|
||||
<Plus className="mr-2 w-4" />
|
||||
<Plus className="main-page-nav-button" />
|
||||
New Project
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<span className="flex w-[60%] px-6 pb-14 text-muted-foreground">
|
||||
<span className="main-page-description-text">
|
||||
Manage your personal projects. Download or upload your collection.
|
||||
</span>
|
||||
<div className="grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<div className="main-page-flows-display">
|
||||
{flows.map((flow, idx) => (
|
||||
<CardComponent
|
||||
key={idx}
|
||||
|
|
@ -68,7 +67,7 @@ export default function HomePage() {
|
|||
size="sm"
|
||||
className="whitespace-nowrap "
|
||||
>
|
||||
<ExternalLink className="mr-2 w-4" />
|
||||
<ExternalLink className="main-page-nav-button" />
|
||||
Edit Flow
|
||||
</Button>
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ export type ShadTooltipProps = {
|
|||
style?: string;
|
||||
};
|
||||
export type ShadToolTipType = {
|
||||
content?: string;
|
||||
content?: ReactNode;
|
||||
side?: "top" | "right" | "bottom" | "left";
|
||||
asChild?: boolean;
|
||||
children?: ReactElement;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export type TabsContextType = {
|
|||
setTabsState: Dispatch<SetStateAction<TabsState>>;
|
||||
paste: (
|
||||
selection: { nodes: any; edges: any },
|
||||
position: { x: number; y: number; paneX?: number; paneY?: number }
|
||||
position: { x: number; y: number; paneX?: number; paneY?: number },
|
||||
) => void;
|
||||
lastCopiedSelection: { nodes: any; edges: any };
|
||||
setLastCopiedSelection: (selection: { nodes: any; edges: any }) => void;
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ export function cn(...inputs: ClassValue[]) {
|
|||
export function measureTextHeight(
|
||||
text: string,
|
||||
width: number,
|
||||
fontSize: number
|
||||
fontSize: number,
|
||||
) {
|
||||
const charHeight = fontSize;
|
||||
const lineHeight = charHeight * 1.5;
|
||||
|
|
@ -519,7 +519,7 @@ export function toCamelCase(str: string) {
|
|||
.map((word, index) =>
|
||||
index === 0
|
||||
? word.toLowerCase()
|
||||
: word[0].toUpperCase() + word.slice(1).toLowerCase()
|
||||
: word[0].toUpperCase() + word.slice(1).toLowerCase(),
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
|
@ -580,7 +580,7 @@ export function getConnectedNodes(edge: Edge, nodes: Array<Node>): Array<Node> {
|
|||
|
||||
export function isValidConnection(
|
||||
{ source, target, sourceHandle, targetHandle }: Connection,
|
||||
reactFlowInstance: ReactFlowInstance
|
||||
reactFlowInstance: ReactFlowInstance,
|
||||
) {
|
||||
if (
|
||||
targetHandle
|
||||
|
|
@ -634,7 +634,7 @@ export function removeApiKeys(flow: FlowType): FlowType {
|
|||
|
||||
export function updateObject<T extends Record<string, any>>(
|
||||
reference: T,
|
||||
objectToUpdate: T
|
||||
objectToUpdate: T,
|
||||
): T {
|
||||
let clonedObject = _.cloneDeep(objectToUpdate);
|
||||
// Loop through each key in the object to update
|
||||
|
|
@ -665,7 +665,7 @@ export function debounce(func, wait) {
|
|||
|
||||
export function updateTemplate(
|
||||
reference: APITemplateType,
|
||||
objectToUpdate: APITemplateType
|
||||
objectToUpdate: APITemplateType,
|
||||
): APITemplateType {
|
||||
let clonedObject: APITemplateType = _.cloneDeep(reference);
|
||||
|
||||
|
|
@ -723,7 +723,7 @@ export function toTitleCase(str: string) {
|
|||
.map((word, index) => {
|
||||
if (index === 0) {
|
||||
return checkUpperWords(
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase()
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase(),
|
||||
);
|
||||
}
|
||||
return checkUpperWords(word.toLowerCase());
|
||||
|
|
@ -735,7 +735,7 @@ export function toTitleCase(str: string) {
|
|||
.map((word, index) => {
|
||||
if (index === 0) {
|
||||
return checkUpperWords(
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase()
|
||||
word[0].toUpperCase() + word.slice(1).toLowerCase(),
|
||||
);
|
||||
}
|
||||
return checkUpperWords(word.toLowerCase());
|
||||
|
|
@ -912,7 +912,7 @@ export function buildTweaks(flow) {
|
|||
}
|
||||
export function validateNode(
|
||||
n: NodeType,
|
||||
reactFlowInstance: ReactFlowInstance
|
||||
reactFlowInstance: ReactFlowInstance,
|
||||
): Array<string> {
|
||||
if (!n.data?.node?.template || !Object.keys(n.data.node.template)) {
|
||||
return [
|
||||
|
|
@ -938,16 +938,16 @@ export function validateNode(
|
|||
.some(
|
||||
(e) =>
|
||||
e.targetHandle.split("|")[1] === t &&
|
||||
e.targetHandle.split("|")[2] === n.id
|
||||
e.targetHandle.split("|")[2] === n.id,
|
||||
)
|
||||
? [
|
||||
`${type} is missing ${
|
||||
template.display_name || toNormalCase(template[t].name)
|
||||
}.`,
|
||||
]
|
||||
: []
|
||||
: [],
|
||||
),
|
||||
[] as string[]
|
||||
[] as string[],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -972,7 +972,7 @@ export function getRandomDescription(): string {
|
|||
export function getRandomName(
|
||||
retry: number = 0,
|
||||
noSpace: boolean = false,
|
||||
maxRetries: number = 3
|
||||
maxRetries: number = 3,
|
||||
): string {
|
||||
const left: string[] = ADJECTIVES;
|
||||
const right: string[] = NOUNS;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue