Merge remote-tracking branch 'origin/form_io' into python_custom_node_component
Merge remote-tracking branch 'origin/form_io' into python_custom_node_component - Updated the README files to correct the spelling of "Langflow" in various places. - Added a new `.env.example` file for reference and configuration. - Updated the CONTRIBUTING.md file to use "Langflow" instead of "LangFlow". - Updated the GCP_DEPLOYMENT.md file to use the correct GitHub repository URL. - Updated the README file to use "Langflow" instead of "LangFlow" and corrected the formatting of the table of contents. - Updated the CLI usage instructions in the README file to use "Langflow" and provided more detailed explanations of each option. - Added a section on Deployment in the README file with instructions for deploying Langflow on Google Cloud Platform. - Updated the "Creating Flows" section in the README file to use "Langflow" instead of "LangFlow" and corrected the link to the LangChain components. - Updated the "Contributing" section in the README file to use "Langflow" instead of "LangFlow" and corrected the link to the contributing guidelines. - Updated the "License" section in the README file to use "Langflow" instead of "LangFlow". - Updated the version of the "anyio" package in the poetry.lock file to 3.7.1. Merge remote-tracking branch 'origin/form_io' into python_custom_node_component - Updated the README files to correct the spelling of "Langflow" in various places. - Added a new `.env.example` file for reference and configuration. - Updated the CONTRIBUTING.md file to use "Langflow" instead of "Langflow". - Updated the GCP_DEPLOYMENT.md file to use the correct GitHub repository URL. - Updated the README file to use "Langflow" instead of "Langflow" and corrected the formatting of the table of contents. - Updated the CLI usage instructions in the README file to use "Langflow" and provided more detailed explanations of each option. - Added a section on Deployment in the README file with instructions for deploying Langflow on Google Cloud Platform. - Updated the "Creating Flows" section in the README file to use "Langflow" instead of "Langflow" and corrected the link to the LangChain components. - Updated the "Contributing" section in the README file to use "Langflow" instead of "Langflow" and corrected the link to the contributing guidelines. - Updated the "License" section in the README file to use "Langflow" instead of "Langflow". - Updated the version of the "anyio" package in the poetry.lock file to 3.7.1. Merge remote-tracking branch 'origin/form_io' into python_custom_node_component - Updated the README files to correct the spelling of "Langflow" in various places. - Added a new `.env.example` file for reference and configuration. - Updated the CONTRIBUTING.md file to use "Langflow" instead of "Langflow". - Updated the GCP_DEPLOYMENT.md file to use the correct GitHub repository URL. - Updated the README file to use "Langflow" instead of "Langflow" and corrected the formatting of the table of contents. - Updated the CLI usage instructions in the README file to use "Langflow" and provided more detailed explanations of each option. - Added a section on Deployment in the README file with instructions for deploying Langflow on Google Cloud Platform. - Updated the "Creating Flows" section in the README file to use "Langflow" instead of "Langflow" and corrected the link to the LangChain components. - Updated the "Contributing" section in the README file to use "
This commit is contained in:
commit
da9764b3c5
126 changed files with 3072 additions and 1372 deletions
|
|
@ -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 = ""
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class Code(BaseModel):
|
|||
|
||||
|
||||
class FrontendNodeRequest(FrontendNode):
|
||||
template: dict
|
||||
template: dict # type: ignore
|
||||
|
||||
|
||||
class ValidatePromptRequest(BaseModel):
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class GraphData(BaseModel):
|
|||
|
||||
|
||||
class ExportedFlow(BaseModel):
|
||||
"""Exported flow from LangFlow."""
|
||||
"""Exported flow from Langflow."""
|
||||
|
||||
description: str
|
||||
name: str
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ async def process_graph(
|
|||
|
||||
# Generate result and thought
|
||||
try:
|
||||
if not chat_inputs.message:
|
||||
logger.debug("No message provided")
|
||||
raise ValueError("No message provided")
|
||||
|
||||
logger.debug("Generating result and thought")
|
||||
result, intermediate_steps = await get_result_and_steps(
|
||||
langchain_object, chat_inputs.message, websocket=websocket
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ memories:
|
|||
documentation: "https://python.langchain.com/docs/modules/memory/how_to/vectorstore_retriever_memory"
|
||||
MongoDBChatMessageHistory:
|
||||
documentation: "https://python.langchain.com/docs/modules/memory/integrations/mongodb_chat_message_history"
|
||||
prompts:
|
||||
ChatMessagePromptTemplate:
|
||||
documentation: "https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/msg_prompt_templates"
|
||||
HumanMessagePromptTemplate:
|
||||
|
|
@ -161,7 +162,6 @@ memories:
|
|||
documentation: "https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts"
|
||||
ChatPromptTemplate:
|
||||
documentation: "https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts"
|
||||
prompts:
|
||||
PromptTemplate:
|
||||
documentation: "https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/"
|
||||
textsplitters:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ CUSTOM_NODES = {
|
|||
},
|
||||
"memories": {
|
||||
"PostgresChatMessageHistory": frontend_node.memories.PostgresChatMessageHistoryFrontendNode(),
|
||||
"MongoDBChatMessageHistory": frontend_node.memories.MongoDBChatMessageHistoryFrontendNode(),
|
||||
},
|
||||
"chains": {
|
||||
"SeriesCharacterChain": frontend_node.chains.SeriesCharacterChainNode(),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ def instantiate_memory(node_type, class_object, params):
|
|||
# process input_key and output_key to remove them if
|
||||
# they are empty strings
|
||||
for key in ["input_key", "output_key"]:
|
||||
if key in params and not params[key]:
|
||||
if key in params and (params[key] == "" or not params[key]):
|
||||
params.pop(key)
|
||||
|
||||
try:
|
||||
|
|
@ -205,7 +205,7 @@ def instantiate_prompt(node_type, class_object, params: Dict):
|
|||
|
||||
prompt = class_object(**params)
|
||||
|
||||
format_kwargs = {}
|
||||
format_kwargs: Dict[str, Any] = {}
|
||||
for input_variable in prompt.input_variables:
|
||||
if input_variable in params:
|
||||
variable = params[input_variable]
|
||||
|
|
|
|||
|
|
@ -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,3 +1,4 @@
|
|||
from typing import Union
|
||||
from langflow.api.v1.callback import (
|
||||
AsyncStreamingLLMCallbackHandler,
|
||||
StreamingLLMCallbackHandler,
|
||||
|
|
@ -6,7 +7,7 @@ from langflow.processing.process import fix_memory_inputs, format_actions
|
|||
from langflow.utils.logger import logger
|
||||
|
||||
|
||||
async def get_result_and_steps(langchain_object, inputs: dict, **kwargs):
|
||||
async def get_result_and_steps(langchain_object, inputs: Union[dict, str], **kwargs):
|
||||
"""Get result and thought from extracted json"""
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
from typing import Optional
|
||||
|
||||
import yaml
|
||||
from pydantic import BaseSettings, root_validator
|
||||
|
|
@ -24,16 +25,18 @@ class Settings(BaseSettings):
|
|||
custom_components: 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"
|
||||
|
|
@ -42,7 +45,6 @@ class Settings(BaseSettings):
|
|||
class Config:
|
||||
validate_assignment = True
|
||||
extra = "ignore"
|
||||
env_prefix = "LANGFLOW_"
|
||||
|
||||
@root_validator(allow_reuse=True)
|
||||
def validate_lists(cls, values):
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@ class AgentFrontendNode(FrontendNode):
|
|||
if field.name in ["suffix", "prefix"]:
|
||||
field.show = True
|
||||
if field.name == "Tools" and name == "ZeroShotAgent":
|
||||
# field.
|
||||
field.type_name = "BaseTool"
|
||||
field.field_type = "BaseTool"
|
||||
field.is_list = True
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ from langflow.template.field.base import TemplateField
|
|||
from langflow.template.frontend_node.base import FrontendNode
|
||||
from langflow.template.template.base import Template
|
||||
from langchain.memory.chat_message_histories.postgres import DEFAULT_CONNECTION_STRING
|
||||
from langchain.memory.chat_message_histories.mongodb import (
|
||||
DEFAULT_COLLECTION_NAME,
|
||||
DEFAULT_DBNAME,
|
||||
)
|
||||
|
||||
|
||||
class MemoryFrontendNode(FrontendNode):
|
||||
|
|
@ -120,3 +124,56 @@ class PostgresChatMessageHistoryFrontendNode(MemoryFrontendNode):
|
|||
)
|
||||
description: str = "Memory store with Postgres"
|
||||
base_classes: list[str] = ["PostgresChatMessageHistory", "BaseChatMessageHistory"]
|
||||
|
||||
|
||||
class MongoDBChatMessageHistoryFrontendNode(MemoryFrontendNode):
|
||||
name: str = "MongoDBChatMessageHistory"
|
||||
template: Template = Template(
|
||||
# langchain/memory/chat_message_histories/mongodb.py
|
||||
# connection_string: str,
|
||||
# session_id: str,
|
||||
# database_name: str = DEFAULT_DBNAME,
|
||||
# collection_name: str = DEFAULT_COLLECTION_NAME,
|
||||
type_name="MongoDBChatMessageHistory",
|
||||
fields=[
|
||||
TemplateField(
|
||||
field_type="str",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
multiline=False,
|
||||
name="session_id",
|
||||
),
|
||||
TemplateField(
|
||||
field_type="str",
|
||||
required=True,
|
||||
show=True,
|
||||
name="connection_string",
|
||||
value="",
|
||||
info="MongoDB connection string (e.g mongodb://mongo_user:password123@mongo:27017)",
|
||||
),
|
||||
TemplateField(
|
||||
field_type="str",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
multiline=False,
|
||||
value=DEFAULT_DBNAME,
|
||||
name="database_name",
|
||||
),
|
||||
TemplateField(
|
||||
field_type="str",
|
||||
required=True,
|
||||
placeholder="",
|
||||
is_list=False,
|
||||
show=True,
|
||||
multiline=False,
|
||||
value=DEFAULT_COLLECTION_NAME,
|
||||
name="collection_name",
|
||||
),
|
||||
],
|
||||
)
|
||||
description: str = "Memory store with MongoDB"
|
||||
base_classes: list[str] = ["MongoDBChatMessageHistory", "BaseChatMessageHistory"]
|
||||
|
|
|
|||
|
|
@ -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,8 @@
|
|||
<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>
|
||||
<script src="node_modules/ace-builds/src-min-noconflict/ace.js" type="text/javascript"></script>
|
||||
<title>Langflow</title>
|
||||
</head>
|
||||
<body id='body' style="width: 100%; height:100%">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
|
|
|||
251
src/frontend/package-lock.json
generated
251
src/frontend/package-lock.json
generated
|
|
@ -85,6 +85,7 @@
|
|||
"daisyui": "^3.1.1",
|
||||
"postcss": "^8.4.23",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-organize-imports": "^3.2.2",
|
||||
"prettier-plugin-tailwindcss": "^0.3.0",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"typescript": "^5.0.2",
|
||||
|
|
@ -146,33 +147,33 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz",
|
||||
"integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==",
|
||||
"version": "7.22.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz",
|
||||
"integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz",
|
||||
"integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==",
|
||||
"version": "7.22.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.8.tgz",
|
||||
"integrity": "sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==",
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.22.5",
|
||||
"@babel/generator": "^7.22.5",
|
||||
"@babel/helper-compilation-targets": "^7.22.5",
|
||||
"@babel/generator": "^7.22.7",
|
||||
"@babel/helper-compilation-targets": "^7.22.6",
|
||||
"@babel/helper-module-transforms": "^7.22.5",
|
||||
"@babel/helpers": "^7.22.5",
|
||||
"@babel/parser": "^7.22.5",
|
||||
"@babel/helpers": "^7.22.6",
|
||||
"@babel/parser": "^7.22.7",
|
||||
"@babel/template": "^7.22.5",
|
||||
"@babel/traverse": "^7.22.5",
|
||||
"@babel/traverse": "^7.22.8",
|
||||
"@babel/types": "^7.22.5",
|
||||
"@nicolo-ribaudo/semver-v6": "^6.3.3",
|
||||
"convert-source-map": "^1.7.0",
|
||||
"debug": "^4.1.0",
|
||||
"gensync": "^1.0.0-beta.2",
|
||||
"json5": "^2.2.2",
|
||||
"semver": "^6.3.0"
|
||||
"json5": "^2.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
|
|
@ -194,9 +195,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz",
|
||||
"integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==",
|
||||
"version": "7.22.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz",
|
||||
"integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.5",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
|
|
@ -208,15 +209,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/helper-compilation-targets": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz",
|
||||
"integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==",
|
||||
"version": "7.22.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz",
|
||||
"integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.22.5",
|
||||
"@babel/compat-data": "^7.22.6",
|
||||
"@babel/helper-validator-option": "^7.22.5",
|
||||
"browserslist": "^4.21.3",
|
||||
"lru-cache": "^5.1.1",
|
||||
"semver": "^6.3.0"
|
||||
"@nicolo-ribaudo/semver-v6": "^6.3.3",
|
||||
"browserslist": "^4.21.9",
|
||||
"lru-cache": "^5.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
|
|
@ -297,9 +298,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/helper-split-export-declaration": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz",
|
||||
"integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==",
|
||||
"version": "7.22.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
|
||||
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
|
|
@ -332,12 +333,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz",
|
||||
"integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==",
|
||||
"version": "7.22.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
|
||||
"integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.22.5",
|
||||
"@babel/traverse": "^7.22.5",
|
||||
"@babel/traverse": "^7.22.6",
|
||||
"@babel/types": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
|
|
@ -358,9 +359,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz",
|
||||
"integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==",
|
||||
"version": "7.22.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz",
|
||||
"integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
|
|
@ -404,17 +405,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz",
|
||||
"integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==",
|
||||
"version": "7.22.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz",
|
||||
"integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.22.5",
|
||||
"@babel/generator": "^7.22.5",
|
||||
"@babel/generator": "^7.22.7",
|
||||
"@babel/helper-environment-visitor": "^7.22.5",
|
||||
"@babel/helper-function-name": "^7.22.5",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.5",
|
||||
"@babel/parser": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.22.7",
|
||||
"@babel/types": "^7.22.5",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
|
|
@ -1337,6 +1338,14 @@
|
|||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
},
|
||||
"node_modules/@nicolo-ribaudo/semver-v6": {
|
||||
"version": "6.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
|
||||
"integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
|
@ -2662,39 +2671,6 @@
|
|||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/cli/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/cli/node_modules/semver": {
|
||||
"version": "7.5.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
|
||||
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/cli/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@swc/core": {
|
||||
"version": "1.3.62",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.62.tgz",
|
||||
|
|
@ -4124,14 +4100,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/bin-version-check": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-5.0.0.tgz",
|
||||
"integrity": "sha512-Q3FMQnS5eZmrBGqmDXLs4dbAn/f+52voP6ykJYmweSA60t6DyH4UTSwZhtbK5UH+LBoWvDljILUQMLRUtsynsA==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-5.1.0.tgz",
|
||||
"integrity": "sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"bin-version": "^6.0.0",
|
||||
"semver": "^7.3.5",
|
||||
"semver-truncate": "^2.0.0"
|
||||
"semver": "^7.5.3",
|
||||
"semver-truncate": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
|
|
@ -4140,39 +4116,6 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/bin-version-check/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/bin-version-check/node_modules/semver": {
|
||||
"version": "7.5.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
|
||||
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/bin-version-check/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/bin-version/node_modules/execa": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
||||
|
|
@ -4306,9 +4249,9 @@
|
|||
"integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow=="
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.21.5",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz",
|
||||
"integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==",
|
||||
"version": "4.21.9",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
|
||||
"integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
|
@ -4317,13 +4260,17 @@
|
|||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/browserslist"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001449",
|
||||
"electron-to-chromium": "^1.4.284",
|
||||
"node-releases": "^2.0.8",
|
||||
"update-browserslist-db": "^1.0.10"
|
||||
"caniuse-lite": "^1.0.30001503",
|
||||
"electron-to-chromium": "^1.4.431",
|
||||
"node-releases": "^2.0.12",
|
||||
"update-browserslist-db": "^1.0.11"
|
||||
},
|
||||
"bin": {
|
||||
"browserslist": "cli.js"
|
||||
|
|
@ -4438,9 +4385,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001486",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz",
|
||||
"integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==",
|
||||
"version": "1.0.30001513",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001513.tgz",
|
||||
"integrity": "sha512-pnjGJo7SOOjAGytZZ203Em95MRM8Cr6jhCXNF/FAXTpCTRTECnqQWLpiTRqrFtdYcth8hf4WECUpkezuYsMVww==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
|
@ -8616,6 +8563,26 @@
|
|||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-organize-imports": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.2.tgz",
|
||||
"integrity": "sha512-e97lE6odGSiHonHJMTYC0q0iLXQyw0u5z/PJpvP/3vRy6/Zi9kLBwFAbEGjDzIowpjQv8b+J04PDamoUSQbzGA==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@volar/vue-language-plugin-pug": "^1.0.4",
|
||||
"@volar/vue-typescript": "^1.0.4",
|
||||
"prettier": ">=2.0",
|
||||
"typescript": ">=2.9"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@volar/vue-language-plugin-pug": {
|
||||
"optional": true
|
||||
},
|
||||
"@volar/vue-typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-tailwindcss": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.3.0.tgz",
|
||||
|
|
@ -9507,11 +9474,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"version": "7.5.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
|
||||
"integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/semver-regex": {
|
||||
|
|
@ -9527,17 +9501,38 @@
|
|||
}
|
||||
},
|
||||
"node_modules/semver-truncate": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-2.0.0.tgz",
|
||||
"integrity": "sha512-Rh266MLDYNeML5h90ttdMwfXe1+Nc4LAWd9X1KdJe8pPHP4kFmvLZALtsMNHNdvTyQygbEC0D59sIz47DIaq8w==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-3.0.0.tgz",
|
||||
"integrity": "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"semver": "^6.0.0"
|
||||
"semver": "^7.3.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/semver/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/semver/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/shadcn-ui": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/shadcn-ui/-/shadcn-ui-0.2.2.tgz",
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@
|
|||
"daisyui": "^3.1.1",
|
||||
"postcss": "^8.4.23",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-organize-imports": "^3.2.2",
|
||||
"prettier-plugin-tailwindcss": "^0.3.0",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"typescript": "^5.0.2",
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
import "reactflow/dist/style.css";
|
||||
import { useState, useEffect, useContext } from "react";
|
||||
import "./App.css";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import _ from "lodash";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import "reactflow/dist/style.css";
|
||||
import "./App.css";
|
||||
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import ErrorAlert from "./alerts/error";
|
||||
import NoticeAlert from "./alerts/notice";
|
||||
import SuccessAlert from "./alerts/success";
|
||||
import CrashErrorComponent from "./components/CrashErrorComponent";
|
||||
import Header from "./components/headerComponent";
|
||||
import { alertContext } from "./contexts/alertContext";
|
||||
import { locationContext } from "./contexts/locationContext";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import CrashErrorComponent from "./components/CrashErrorComponent";
|
||||
import { TabsContext } from "./contexts/tabsContext";
|
||||
import { getVersion } from "./controllers/API";
|
||||
import Router from "./routes";
|
||||
import Header from "./components/headerComponent";
|
||||
|
||||
export default function App() {
|
||||
let { setCurrent, setShowSideBar, setIsStackedOpen } =
|
||||
|
|
@ -138,10 +137,7 @@ export default function App() {
|
|||
<Router />
|
||||
</ErrorBoundary>
|
||||
<div></div>
|
||||
<div
|
||||
className="fixed bottom-5 left-5 flex flex-col-reverse"
|
||||
style={{ zIndex: 999 }}
|
||||
>
|
||||
<div className="app-div" style={{ zIndex: 999 }}>
|
||||
{alertsList.map((alert) => (
|
||||
<div key={alert.id}>
|
||||
{alert.type === "error" ? (
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
import { Info } from "lucide-react";
|
||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||
import Dropdown from "../../../../components/dropdownComponent";
|
||||
import FloatComponent from "../../../../components/floatComponent";
|
||||
import InputComponent from "../../../../components/inputComponent";
|
||||
import InputFileComponent from "../../../../components/inputFileComponent";
|
||||
import InputListComponent from "../../../../components/inputListComponent";
|
||||
import IntComponent from "../../../../components/intComponent";
|
||||
import PromptAreaComponent from "../../../../components/promptComponent";
|
||||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
||||
import { PopUpContext } from "../../../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||
import { typesContext } from "../../../../contexts/typesContext";
|
||||
import { ParameterComponentType } from "../../../../types/components";
|
||||
import {
|
||||
classNames,
|
||||
getRandomKeyByssmm,
|
||||
groupByFamily,
|
||||
isValidConnection,
|
||||
nodeColors,
|
||||
nodeIconsLucide,
|
||||
nodeNames,
|
||||
} from "../../../../utils";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import InputComponent from "../../../../components/inputComponent";
|
||||
import InputListComponent from "../../../../components/inputListComponent";
|
||||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||
import { typesContext } from "../../../../contexts/typesContext";
|
||||
import { ParameterComponentType } from "../../../../types/components";
|
||||
import FloatComponent from "../../../../components/floatComponent";
|
||||
import Dropdown from "../../../../components/dropdownComponent";
|
||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||
import InputFileComponent from "../../../../components/inputFileComponent";
|
||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||
import IntComponent from "../../../../components/intComponent";
|
||||
import PromptAreaComponent from "../../../../components/promptComponent";
|
||||
import { nodeNames } from "../../../../utils";
|
||||
import React from "react";
|
||||
import { nodeColors } from "../../../../utils";
|
||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
||||
import { PopUpContext } from "../../../../contexts/popUpContext";
|
||||
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
||||
import { Info } from "lucide-react";
|
||||
|
||||
export default function ParameterComponent({
|
||||
left,
|
||||
|
|
@ -223,7 +222,7 @@ export default function ParameterComponent({
|
|||
/>
|
||||
) : data.node.template[name].multiline ? (
|
||||
<TextAreaComponent
|
||||
disabled={disabled}
|
||||
disabled={false}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
import { Zap } from "lucide-react";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { NodeToolbar } from "reactflow";
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import Tooltip from "../../components/TooltipComponent";
|
||||
import { useSSE } from "../../contexts/SSEContext";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import NodeModal from "../../modals/NodeModal";
|
||||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import {
|
||||
classNames,
|
||||
nodeColors,
|
||||
|
|
@ -5,17 +17,6 @@ import {
|
|||
toTitleCase,
|
||||
} from "../../utils";
|
||||
import ParameterComponent from "./components/parameterComponent";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import { useContext, useState, useEffect, useRef } from "react";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import NodeModal from "../../modals/NodeModal";
|
||||
import Tooltip from "../../components/TooltipComponent";
|
||||
import { NodeToolbar } from "reactflow";
|
||||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import { useSSE } from "../../contexts/SSEContext";
|
||||
|
||||
export default function GenericNode({
|
||||
data,
|
||||
|
|
@ -80,30 +81,27 @@ 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">
|
||||
<ShadTooltip
|
||||
delayDuration={1500}
|
||||
content={data.node.display_name}
|
||||
>
|
||||
<div className="ml-2 truncate text-primary">
|
||||
<div className="generic-node-tooltip-div">
|
||||
<ShadTooltip content={data.node.display_name}>
|
||||
<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) => {
|
||||
|
|
@ -112,12 +110,19 @@ export default function GenericNode({
|
|||
}}
|
||||
></button>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<div className="round-button-div">
|
||||
<div>
|
||||
<Tooltip
|
||||
title={
|
||||
!validationStatus ? (
|
||||
"Validating..."
|
||||
<span className="flex">
|
||||
Build{" "}
|
||||
<Zap
|
||||
className="mx-0.5 h-5 fill-build-trigger stroke-build-trigger stroke-1"
|
||||
strokeWidth={1.5}
|
||||
/>{" "}
|
||||
flow to validate status.
|
||||
</span>
|
||||
) : (
|
||||
<div className="max-h-96 overflow-auto">
|
||||
{validationStatus.params
|
||||
|
|
@ -129,29 +134,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>
|
||||
|
|
@ -160,10 +165,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">
|
||||
{data.node.description}
|
||||
</div>
|
||||
<div className="generic-node-desc">
|
||||
<div className="generic-node-desc-text">{data.node.description}</div>
|
||||
|
||||
<>
|
||||
{Object.keys(data.node.template)
|
||||
|
|
@ -232,7 +235,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"
|
||||
)}
|
||||
>
|
||||
{" "}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Link } from "react-router-dom";
|
||||
import { Transition } from "@headlessui/react";
|
||||
import { CheckCircle2, Info, X, XCircle } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { SingleAlertComponentType } from "../../../../types/alerts";
|
||||
import { X, CheckCircle2, Info, XCircle } from "lucide-react";
|
||||
|
||||
export default function SingleAlert({
|
||||
dropItem,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useContext, useEffect, useRef } from "react";
|
||||
import { Trash2, X } from "lucide-react";
|
||||
import { useContext, useRef } from "react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import SingleAlert from "./components/singleAlertComponent";
|
||||
import { AlertDropdownType } from "../../types/alerts";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { AlertDropdownType } from "../../types/alerts";
|
||||
import { useOnClickOutside } from "../hooks/useOnClickOutside";
|
||||
import { X, Trash2 } from "lucide-react";
|
||||
import SingleAlert from "./components/singleAlertComponent";
|
||||
|
||||
export default function AlertDropdown({}: AlertDropdownType) {
|
||||
const { closePopUp } = useContext(PopUpContext);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Transition } from "@headlessui/react";
|
||||
import { XCircle } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ErrorAlertType } from "../../types/alerts";
|
||||
import { XCircle } from "lucide-react";
|
||||
|
||||
export default function ErrorAlert({
|
||||
title,
|
||||
|
|
@ -39,19 +39,20 @@ 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">
|
||||
{title}
|
||||
</h3>
|
||||
<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>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Transition } from "@headlessui/react";
|
||||
import { Info } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { NoticeAlertType } from "../../types/alerts";
|
||||
import { Info } from "lucide-react";
|
||||
|
||||
export default function NoticeAlert({
|
||||
title,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Transition } from "@headlessui/react";
|
||||
import { CheckCircle2 } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SuccessAlertType } from "../../types/alerts";
|
||||
import { CheckCircle2 } from "lucide-react";
|
||||
|
||||
export default function SuccessAlert({
|
||||
title,
|
||||
|
|
@ -34,19 +34,14 @@ 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"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<CheckCircle2 className="success-alert-icon" aria-hidden="true" />
|
||||
</div>
|
||||
<div className="ml-3">
|
||||
<p className="text-sm font-medium text-success-foreground">
|
||||
{title}
|
||||
</p>
|
||||
<p className="success-alert-message">{title}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
BIN
src/frontend/src/assets/male-technologist.png
Normal file
BIN
src/frontend/src/assets/male-technologist.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
src/frontend/src/assets/robot.png
Normal file
BIN
src/frontend/src/assets/robot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -1,16 +1,11 @@
|
|||
import { ReactElement, useContext, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
AccordionComponentType,
|
||||
ProgressBarType,
|
||||
} from "../../types/components";
|
||||
import { Progress } from "../../components/ui/progress";
|
||||
import { setInterval } from "timers/promises";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "../../components/ui/accordion";
|
||||
import { AccordionComponentType } from "../../types/components";
|
||||
|
||||
export default function AccordionComponent({
|
||||
trigger,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, ChangeEvent } from "react";
|
||||
import { Textarea } from "../../components/ui/textarea";
|
||||
import { Label } from "../../components/ui/label";
|
||||
import React, { ChangeEvent, useState } from "react";
|
||||
import { Input } from "../../components/ui/input";
|
||||
import { Label } from "../../components/ui/label";
|
||||
import { Textarea } from "../../components/ui/textarea";
|
||||
|
||||
type InputProps = {
|
||||
name: string | null;
|
||||
|
|
@ -44,12 +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">
|
||||
Character limit reached
|
||||
</span>
|
||||
<span className="edit-flow-span">Character limit reached</span>
|
||||
)}
|
||||
</div>
|
||||
<Input
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
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";
|
||||
import { classNames } from "../../utils";
|
||||
|
||||
export default function ExtraSidebar() {
|
||||
const {
|
||||
|
|
@ -16,15 +16,13 @@ export default function ExtraSidebar() {
|
|||
return (
|
||||
<>
|
||||
<aside
|
||||
className={` ${
|
||||
isStackedOpen ? "w-52" : "w-0 "
|
||||
} flex flex-shrink-0 flex-col overflow-hidden border-r transition-all duration-500`}
|
||||
className={` ${isStackedOpen ? "w-52" : "w-0 "} 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 +30,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 +57,22 @@ 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}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { styled } from "@mui/material/styles";
|
||||
import Tooltip, { TooltipProps, tooltipClasses } from "@mui/material/Tooltip";
|
||||
import { styled } from "@mui/material/styles";
|
||||
|
||||
export const LightTooltip = styled(({ className, ...props }: TooltipProps) => (
|
||||
<Tooltip {...props} classes={{ popper: className }} />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { RadialProgressType } from "../../types/components";
|
||||
|
||||
export default function LoadingSpinner({}) {
|
||||
return <></>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { RadialProgressType } from "../../types/components";
|
||||
|
||||
export default function RadialProgressComponent({
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { RadialProgressType, ShadToolTipType } from "../../types/components";
|
||||
import { ShadToolTipType } from "../../types/components";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
|
|
@ -11,14 +11,20 @@ export default function ShadTooltip({
|
|||
side,
|
||||
asChild = true,
|
||||
children,
|
||||
delayDuration,
|
||||
style,
|
||||
delayDuration = 500,
|
||||
}: ShadToolTipType) {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip delayDuration={delayDuration}>
|
||||
<TooltipTrigger asChild={asChild}>{children}</TooltipTrigger>
|
||||
|
||||
<TooltipContent side={side} avoidCollisions={false} sticky="always">
|
||||
<TooltipContent
|
||||
className={style}
|
||||
side={side}
|
||||
avoidCollisions={false}
|
||||
sticky="always"
|
||||
>
|
||||
{content}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { ReactElement } from "react";
|
||||
import { LightTooltip } from "../LightTooltipComponent";
|
||||
import { TooltipComponentType } from "../../types/components";
|
||||
import { LightTooltip } from "../LightTooltipComponent";
|
||||
|
||||
export default function Tooltip({
|
||||
children,
|
||||
|
|
|
|||
|
|
@ -1,26 +1,15 @@
|
|||
import { Trash2, ExternalLink } from "lucide-react";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { useContext } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { FlowType } from "../../types/flow";
|
||||
import { gradients } from "../../utils";
|
||||
import {
|
||||
CardTitle,
|
||||
Card,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
Card,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../ui/card";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../ui/dialog";
|
||||
import { Button } from "@mui/material";
|
||||
|
||||
export const CardComponent = ({
|
||||
flow,
|
||||
|
|
@ -38,42 +27,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">
|
||||
{flow.name}
|
||||
</span>
|
||||
<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>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Are you sure absolutely sure?</DialogTitle>
|
||||
<DialogDescription>
|
||||
This action cannot be undone. Are you sure you want to
|
||||
permanently delete this file from our servers?
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<Button type="submit" onClick={onDelete}>
|
||||
Confirm
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<button className="card-component-delete-button" onClick={onDelete}>
|
||||
<Trash2 className="card-component-delete-icon" />
|
||||
</button>
|
||||
)}
|
||||
</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 +50,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">
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import { useContext, useState } from "react";
|
||||
import { Transition } from "@headlessui/react";
|
||||
import { Zap } from "lucide-react";
|
||||
import { validateNodes } from "../../../utils";
|
||||
import { FlowType } from "../../../types/flow";
|
||||
import { useContext, useState } from "react";
|
||||
import Loading from "../../../components/ui/loading";
|
||||
import { useSSE } from "../../../contexts/SSEContext";
|
||||
import { typesContext } from "../../../contexts/typesContext";
|
||||
import { alertContext } from "../../../contexts/alertContext";
|
||||
import { typesContext } from "../../../contexts/typesContext";
|
||||
import { postBuildInit } from "../../../controllers/API";
|
||||
import { FlowType } from "../../../types/flow";
|
||||
import { validateNodes } from "../../../utils";
|
||||
|
||||
import RadialProgressComponent from "../../RadialProgress";
|
||||
import { TabsContext } from "../../../contexts/tabsContext";
|
||||
import RadialProgressComponent from "../../RadialProgress";
|
||||
|
||||
export default function BuildTrigger({
|
||||
open,
|
||||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
import { useState } from "react";
|
||||
import { ChatMessageType } from "../../../types/chat";
|
||||
import { nodeColors } from "../../../utils";
|
||||
import Convert from "ansi-to-html";
|
||||
import { MessageCircle } from "lucide-react";
|
||||
import DOMPurify from "dompurify";
|
||||
const convert = new Convert({ newline: true });
|
||||
export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
|
||||
const [hidden, setHidden] = useState(true);
|
||||
return (
|
||||
<div>
|
||||
{!chat.isSend ? (
|
||||
<div className="w-full text-start">
|
||||
<div
|
||||
style={{ backgroundColor: nodeColors["chat"] }}
|
||||
className=" relative inline-block w-fit max-w-[280px] overflow-hidden rounded-xl rounded-tl-none text-start text-sm font-normal text-background"
|
||||
>
|
||||
{hidden && chat.thought && chat.thought !== "" && (
|
||||
<div
|
||||
onClick={() => setHidden((prev) => !prev)}
|
||||
className="absolute right-2 top-2 cursor-pointer"
|
||||
>
|
||||
<MessageCircle className="h-5 w-5 animate-bounce" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{chat.thought && chat.thought !== "" && !hidden && (
|
||||
<div
|
||||
onClick={() => setHidden((prev) => !prev)}
|
||||
style={{ backgroundColor: nodeColors["thought"] }}
|
||||
className=" inline-block w-full cursor-pointer px-5 pb-3 pt-3 text-start"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
|
||||
}}
|
||||
></div>
|
||||
)}
|
||||
{chat.thought && chat.thought !== "" && !hidden && <br></br>}
|
||||
<div
|
||||
className="w-full rounded-b-md px-4 pb-3 pr-8 pt-3"
|
||||
style={{ backgroundColor: nodeColors["chat"] }}
|
||||
>
|
||||
{chat.message}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="w-full text-end">
|
||||
<div className="inline-block w-fit max-w-[280px] overflow-hidden rounded-xl rounded-tr-none bg-input p-3 px-5 text-start text-sm font-normal text-black">
|
||||
{chat.message}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import { Transition } from "@headlessui/react";
|
||||
import { MessagesSquare } from "lucide-react";
|
||||
|
||||
import { alertContext } from "../../../contexts/alertContext";
|
||||
import { useContext } from "react";
|
||||
import {
|
||||
CHAT_CANNOT_OPEN_DESCRIPTION,
|
||||
|
|
@ -9,6 +8,7 @@ import {
|
|||
FLOW_NOT_BUILT_DESCRIPTION,
|
||||
FLOW_NOT_BUILT_TITLE,
|
||||
} from "../../../constants";
|
||||
import { alertContext } from "../../../contexts/alertContext";
|
||||
|
||||
export default function ChatTrigger({ open, setOpen, isBuilt, canOpen }) {
|
||||
const { setErrorData } = useContext(alertContext);
|
||||
|
|
@ -45,7 +45,7 @@ export default function ChatTrigger({ open, setOpen, isBuilt, canOpen }) {
|
|||
<button
|
||||
onClick={handleClick}
|
||||
className={
|
||||
"shadow-round-btn-shadow hover:shadow-round-btn-shadow fixed bottom-4 right-4 flex h-12 w-12 items-center justify-center rounded-full bg-border px-3 py-1 shadow-md transition-all " +
|
||||
"shadow-round-btn-shadow hover:shadow-round-btn-shadow message-button " +
|
||||
(!isBuilt || !canOpen ? "cursor-not-allowed" : "cursor-pointer")
|
||||
}
|
||||
>
|
||||
|
|
@ -54,8 +54,8 @@ export default function ChatTrigger({ open, setOpen, isBuilt, canOpen }) {
|
|||
className={
|
||||
"h-6 w-6 transition-all " +
|
||||
(isBuilt && canOpen
|
||||
? "fill-chat-trigger stroke-chat-trigger stroke-1"
|
||||
: "fill-chat-trigger-disabled stroke-chat-trigger-disabled stroke-1")
|
||||
? "message-button-icon"
|
||||
: "disabled-message-button-icon")
|
||||
}
|
||||
style={{ color: "white" }}
|
||||
strokeWidth={1.5}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { useNodes } from "reactflow";
|
||||
import { ChatType } from "../../types/chat";
|
||||
import ChatTrigger from "./chatTrigger";
|
||||
import BuildTrigger from "./buildTrigger";
|
||||
import ChatTrigger from "./chatTrigger";
|
||||
|
||||
import { getBuildStatus } from "../../controllers/API";
|
||||
import { NodeType } from "../../types/flow";
|
||||
import FormModal from "../../modals/formModal";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import * as _ from "lodash";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { getBuildStatus } from "../../controllers/API";
|
||||
import FormModal from "../../modals/formModal";
|
||||
import { NodeType } from "../../types/flow";
|
||||
|
||||
export default function Chat({ flow }: ChatType) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { Listbox, Transition } from "@headlessui/react";
|
||||
import { Check, ChevronsUpDown } from "lucide-react";
|
||||
import { Fragment, useContext, useEffect, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
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,16 @@ 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"
|
||||
}
|
||||
>
|
||||
<span className={"dropdown-component-arrow"}>
|
||||
<ChevronsUpDown
|
||||
className="h-5 w-5 text-muted-foreground"
|
||||
className="dropdown-component-arrow-color"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
|
|
@ -68,8 +63,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 nowheel"
|
||||
: "dropdown-component-false-options nowheel",
|
||||
apiModal ? "mb-2 w-[250px]" : "absolute"
|
||||
)}
|
||||
>
|
||||
|
|
@ -80,8 +75,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 +96,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"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useContext, useEffect, useState } from "react";
|
||||
import { FloatComponentType } from "../../types/components";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { FloatComponentType } from "../../types/components";
|
||||
|
||||
export default function FloatComponent({
|
||||
value,
|
||||
|
|
@ -30,11 +30,7 @@ export default function FloatComponent({
|
|||
}, [closePopUp]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
"w-full " + (disabled ? "pointer-events-none cursor-not-allowed" : "")
|
||||
}
|
||||
>
|
||||
<div className={"w-full " + (disabled ? "float-component-pointer" : "")}>
|
||||
<input
|
||||
onFocus={() => {
|
||||
if (disableCopyPaste) setDisableCopyPaste(true);
|
||||
|
|
|
|||
|
|
@ -1,27 +1,25 @@
|
|||
import { useContext } from "react";
|
||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||
import { PopUpContext } from "../../../../contexts/popUpContext";
|
||||
import {
|
||||
Plus,
|
||||
ChevronDown,
|
||||
ChevronLeft,
|
||||
Undo,
|
||||
Plus,
|
||||
Redo,
|
||||
Settings2,
|
||||
Undo,
|
||||
} from "lucide-react";
|
||||
import { useContext } from "react";
|
||||
import { PopUpContext } from "../../../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "../../../ui/dropdown-menu";
|
||||
|
||||
import { alertContext } from "../../../../contexts/alertContext";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { alertContext } from "../../../../contexts/alertContext";
|
||||
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
|
||||
import FlowSettingsModal from "../../../../modals/flowSettingsModal";
|
||||
import { Button } from "../../../ui/button";
|
||||
|
|
@ -47,19 +45,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 +69,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 +78,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 +87,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 +96,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,19 +1,18 @@
|
|||
import { BellIcon, Home, MoonIcon, SunIcon, Users2 } from "lucide-react";
|
||||
import { Bell, 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";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { Link, useLocation, useParams } from "react-router-dom";
|
||||
import AlertDropdown from "../../alerts/alertDropDown";
|
||||
import { USER_PROJECTS_HEADER } from "../../constants";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import MenuBar from "./components/menuBar";
|
||||
import { Link, useLocation, useParams } from "react-router-dom";
|
||||
import { USER_PROJECTS_HEADER } from "../../constants";
|
||||
import { getRepoStars } from "../../controllers/API";
|
||||
import { Button } from "../ui/button";
|
||||
import { Separator } from "../ui/separator";
|
||||
import { Bell } from "lucide-react";
|
||||
import MenuBar from "./components/menuBar";
|
||||
|
||||
export default function Header() {
|
||||
const { flows, addFlow, tabId } = useContext(TabsContext);
|
||||
|
|
@ -36,8 +35,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 +44,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,19 +68,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">
|
||||
{stars}
|
||||
</div>
|
||||
<div className="header-github-display">{stars}</div>
|
||||
</a>
|
||||
<a
|
||||
href="https://twitter.com/logspace_ai"
|
||||
|
|
@ -89,7 +86,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 +94,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 +125,13 @@ 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>
|
||||
)}
|
||||
<Bell className="h-5 w-5" aria-hidden="true" />
|
||||
{notificationCenter && <div className="header-notifications"></div>}
|
||||
<Bell className="side-bar-button-size" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useContext, useEffect, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { InputComponentType } from "../../types/components";
|
||||
import { classNames } from "../../utils";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
|
||||
export default function InputComponent({
|
||||
value,
|
||||
|
|
@ -29,13 +29,7 @@ export default function InputComponent({
|
|||
}, [closePopUp]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
disabled
|
||||
? "pointer-events-none relative cursor-not-allowed"
|
||||
: "relative"
|
||||
}
|
||||
>
|
||||
<div className={disabled ? "input-component-div" : "relative"}>
|
||||
<input
|
||||
value={myValue}
|
||||
onFocus={() => {
|
||||
|
|
@ -45,7 +39,7 @@ export default function InputComponent({
|
|||
if (disableCopyPaste) setDisableCopyPaste(false);
|
||||
}}
|
||||
className={classNames(
|
||||
" pr-12 ",
|
||||
" pr-9 ",
|
||||
disabled ? " input-disable " : "",
|
||||
password && !pwdVisible && myValue !== "" ? "password" : "",
|
||||
editNode ? " input-edit-node " : " input-primary ",
|
||||
|
|
@ -61,8 +55,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 +72,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 +91,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
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { FileSearch2 } from "lucide-react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { FileComponentType } from "../../types/components";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { FileSearch2 } from "lucide-react";
|
||||
import { uploadFile } from "../../controllers/API";
|
||||
import { FileComponentType } from "../../types/components";
|
||||
|
||||
export default function InputFileComponent({
|
||||
value,
|
||||
|
|
@ -91,19 +91,18 @@ export default function InputFileComponent({
|
|||
input.click();
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
disabled ? "pointer-events-none w-full cursor-not-allowed" : "w-full"
|
||||
}
|
||||
>
|
||||
<div className="flex w-full items-center">
|
||||
<div className={disabled ? "input-component-div" : "w-full"}>
|
||||
<div className="input-file-component">
|
||||
<span
|
||||
onClick={handleButtonClick}
|
||||
className={
|
||||
editNode
|
||||
? "input-edit-node " + "input-primary "
|
||||
: "input-primary " + (disabled ? "input-disable " : "")
|
||||
? " input-edit-node " + " input-dialog "
|
||||
: (disabled ? " input-disable " : "") +
|
||||
" input-primary " +
|
||||
" input-dialog "
|
||||
}
|
||||
>
|
||||
{myValue !== "" ? myValue : "No file"}
|
||||
|
|
@ -112,7 +111,10 @@ export default function InputFileComponent({
|
|||
{!editNode && !loading && (
|
||||
<FileSearch2
|
||||
strokeWidth={1.5}
|
||||
className="h-6 w-6 hover:text-accent-foreground"
|
||||
className={
|
||||
"icons-parameters-comp" +
|
||||
(disabled ? " text-ring " : " hover:text-accent-foreground")
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{!editNode && loading && (
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { useContext, useEffect, useState } from "react";
|
||||
import { InputListComponentType } from "../../types/components";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
|
||||
import _ from "lodash";
|
||||
import { X, Plus } from "lucide-react";
|
||||
import { Plus, X } from "lucide-react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
|
||||
export default function InputListComponent({
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { useContext, useEffect, useState } from "react";
|
||||
import { FloatComponentType } from "../../types/components";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { classNames } from "../../utils";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { FloatComponentType } from "../../types/components";
|
||||
|
||||
export default function IntComponent({
|
||||
value,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { useContext, useEffect, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
import GenericModal from "../../modals/genericModal";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
import { TypeModal } from "../../utils";
|
||||
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import { postValidatePrompt } from "../../controllers/API";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import * as _ from "lodash";
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import { postValidatePrompt } from "../../controllers/API";
|
||||
|
||||
export default function PromptAreaComponent({
|
||||
field_name,
|
||||
|
|
@ -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")
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useContext, useEffect, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
import GenericModal from "../../modals/genericModal";
|
||||
import { TextAreaComponentType } from "../../types/components";
|
||||
import { TypeModal } from "../../utils";
|
||||
|
||||
import { ExternalLink } from "lucide-react";
|
||||
|
|
@ -30,34 +30,23 @@ export default function TextAreaComponent({
|
|||
<div className={disabled ? "cursor-not-allowed" : ""}>
|
||||
<div
|
||||
className={
|
||||
(editNode ? "w-full items-center" : "flex w-full items-center") +
|
||||
(editNode ? "relative top-2 w-full" : "flex w-full items-center") +
|
||||
(disabled ? " pointer-events-none" : "")
|
||||
}
|
||||
>
|
||||
<span
|
||||
onClick={() => {
|
||||
openPopUp(
|
||||
<GenericModal
|
||||
type={TypeModal.TEXT}
|
||||
buttonText="Finishing Editing"
|
||||
modalTitle="Edit Text"
|
||||
value={myValue}
|
||||
setValue={(t: string) => {
|
||||
setMyValue(t);
|
||||
onChange(t);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
<input
|
||||
value={myValue}
|
||||
className={
|
||||
editNode
|
||||
? "input-edit-node input-dialog "
|
||||
: "input-dialog input-primary " +
|
||||
(disabled ? "input-disable" : "")
|
||||
? "input-edit-node"
|
||||
: "input-primary" + (disabled ? " input-disable " : "")
|
||||
}
|
||||
>
|
||||
{myValue !== "" ? myValue : "Type something..."}
|
||||
</span>
|
||||
placeholder={"Type something..."}
|
||||
onChange={(e) => {
|
||||
setMyValue(e.target.value);
|
||||
onChange(e.target.value);
|
||||
}}
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
|
|
@ -79,7 +68,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")
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Switch } from "@headlessui/react";
|
||||
import { classNames } from "../../utils";
|
||||
import { useEffect } from "react";
|
||||
import { ToggleComponentType } from "../../types/components";
|
||||
import { classNames } from "../../utils";
|
||||
|
||||
export default function ToggleComponent({
|
||||
enabled,
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { useEffect } from "react";
|
||||
import { ToggleComponentType } from "../../types/components";
|
||||
import { Switch } from "../ui/switch";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
||||
import { ChevronDownIcon } from "@radix-ui/react-icons";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Accordion = AccordionPrimitive.Root;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from "react";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const badgeVariants = cva(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react";
|
||||
import { Slot } from "@radix-ui/react-slot";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
||||
import { Check } from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Checkbox = React.forwardRef<
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react";
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import { X } from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Dialog = DialogPrimitive.Root;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const DropdownMenu = DropdownMenuPrimitive.Root;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as LabelPrimitive from "@radix-ui/react-label";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const labelVariants = cva(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as MenubarPrimitive from "@radix-ui/react-menubar";
|
||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Progress = React.forwardRef<
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
export default function RenameLabel(props) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Separator = React.forwardRef<
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Switch = React.forwardRef<
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const Table = React.forwardRef<
|
|||
HTMLTableElement,
|
||||
React.HTMLAttributes<HTMLTableElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div className="w-full overflow-auto">
|
||||
<div className="">
|
||||
<table
|
||||
ref={ref}
|
||||
className={cn("w-full caption-bottom text-sm", className)}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Tabs = TabsPrimitive.Root;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||
import * as React from "react";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const TooltipProvider = TooltipPrimitive.Provider;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
// src/constants.tsx
|
||||
|
||||
import { MessageSquare } from "lucide-react";
|
||||
import { FlowType } from "./types/flow";
|
||||
import { buildTweaks } from "./utils";
|
||||
import { TabsState } from "./types/tabs";
|
||||
import { buildInputs, buildTweaks } from "./utils";
|
||||
|
||||
/**
|
||||
* The base text for subtitle of Export Dialog (Toolbar)
|
||||
|
|
@ -56,6 +58,8 @@ export const CHAT_CANNOT_OPEN_DESCRIPTION = "This is not a chat flow.";
|
|||
|
||||
export const FLOW_NOT_BUILT_TITLE = "Flow not built";
|
||||
|
||||
export const THOUGHTS_ICON = MessageSquare;
|
||||
|
||||
export const FLOW_NOT_BUILT_DESCRIPTION =
|
||||
"Please build the flow before chatting.";
|
||||
|
||||
|
|
@ -70,7 +74,11 @@ export const TEXT_DIALOG_SUBTITLE = "Edit your text.";
|
|||
* @param {string} flowId - The id of the flow
|
||||
* @returns {string} - The python code
|
||||
*/
|
||||
export const getPythonApiCode = (flow: FlowType, tweak?): string => {
|
||||
export const getPythonApiCode = (
|
||||
flow: FlowType,
|
||||
tweak?: any[],
|
||||
tabsState?: TabsState
|
||||
): string => {
|
||||
const flowId = flow.id;
|
||||
|
||||
// create a dictionary of node ids and the values is an empty dictionary
|
||||
|
|
@ -78,7 +86,9 @@ export const getPythonApiCode = (flow: FlowType, tweak?): string => {
|
|||
// node.data.id
|
||||
// }
|
||||
const tweaks = buildTweaks(flow);
|
||||
const inputs = buildInputs(tabsState, flow.id);
|
||||
return `import requests
|
||||
from typing import Optional
|
||||
|
||||
BASE_API_URL = "${window.location.protocol}//${
|
||||
window.location.host
|
||||
|
|
@ -92,7 +102,7 @@ TWEAKS = ${
|
|||
: JSON.stringify(tweaks, null, 2)
|
||||
}
|
||||
|
||||
def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
|
||||
def run_flow(inputs: dict, flow_id: str, tweaks: Optional[dict] = None) -> dict:
|
||||
"""
|
||||
Run a flow with a given message and optional tweaks.
|
||||
|
||||
|
|
@ -103,7 +113,7 @@ def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
|
|||
"""
|
||||
api_url = f"{BASE_API_URL}/{flow_id}"
|
||||
|
||||
payload = {"inputs": {"input": message}}
|
||||
payload = {"inputs": inputs}
|
||||
|
||||
if tweaks:
|
||||
payload["tweaks"] = tweaks
|
||||
|
|
@ -112,23 +122,29 @@ def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
|
|||
return response.json()
|
||||
|
||||
# Setup any tweaks you want to apply to the flow
|
||||
|
||||
print(run_flow("Your message", flow_id=FLOW_ID, tweaks=TWEAKS))`;
|
||||
inputs = ${inputs}
|
||||
print(run_flow(inputs, flow_id=FLOW_ID, tweaks=TWEAKS))`;
|
||||
};
|
||||
/**
|
||||
* Function to get the curl code for the API
|
||||
* @param {string} flowId - The id of the flow
|
||||
* @returns {string} - The curl code
|
||||
*/
|
||||
export const getCurlCode = (flow: FlowType, tweak?): string => {
|
||||
export const getCurlCode = (
|
||||
flow: FlowType,
|
||||
tweak?: any[],
|
||||
tabsState?: TabsState
|
||||
): string => {
|
||||
const flowId = flow.id;
|
||||
const tweaks = buildTweaks(flow);
|
||||
const inputs = buildInputs(tabsState, flow.id);
|
||||
|
||||
return `curl -X POST \\
|
||||
${window.location.protocol}//${
|
||||
window.location.host
|
||||
}/api/v1/process/${flowId} \\
|
||||
-H 'Content-Type: application/json' \\
|
||||
-d '{"inputs": {"input": message}, "tweaks": ${
|
||||
-d '{"inputs": ${inputs}, "tweaks": ${
|
||||
tweak && tweak.length > 0
|
||||
? buildTweakObject(tweak)
|
||||
: JSON.stringify(tweaks, null, 2)
|
||||
|
|
@ -139,9 +155,14 @@ export const getCurlCode = (flow: FlowType, tweak?): string => {
|
|||
* @param {string} flowName - The name of the flow
|
||||
* @returns {string} - The python code
|
||||
*/
|
||||
export const getPythonCode = (flow: FlowType, tweak?): string => {
|
||||
export const getPythonCode = (
|
||||
flow: FlowType,
|
||||
tweak?: any[],
|
||||
tabsState?: TabsState
|
||||
): string => {
|
||||
const flowName = flow.name;
|
||||
const tweaks = buildTweaks(flow);
|
||||
const inputs = buildInputs(tabsState, flow.id);
|
||||
return `from langflow import load_flow_from_json
|
||||
TWEAKS = ${
|
||||
tweak && tweak.length > 0
|
||||
|
|
@ -150,7 +171,8 @@ 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?")`;
|
||||
inputs = ${inputs}
|
||||
flow(inputs)`;
|
||||
};
|
||||
|
||||
function buildTweakObject(tweak) {
|
||||
|
|
@ -529,4 +551,4 @@ export const USER_PROJECTS_HEADER = "My Collection";
|
|||
*
|
||||
*/
|
||||
export const HIGHLIGH_CSS =
|
||||
"block pl-3 pr-14 py-2 w-full h-full text-sm outline-0 border-0 break-all";
|
||||
"block pl-3 pr-14 py-2 w-full h-full text-sm outline-0 border-0 break-all overflow-y-hidden max-w-[75vw]";
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
useCallback,
|
||||
} from "react";
|
||||
import { createContext, useCallback, useContext, useState } from "react";
|
||||
|
||||
const initialValue = {
|
||||
updateSSEData: ({}) => {},
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { ReactNode } from "react";
|
||||
import { ReactFlowProvider } from "reactflow";
|
||||
import { SSEProvider } from "./SSEContext";
|
||||
import { AlertProvider } from "./alertContext";
|
||||
import { DarkProvider } from "./darkContext";
|
||||
import { LocationProvider } from "./locationContext";
|
||||
import PopUpProvider from "./popUpContext";
|
||||
import { TabsProvider } from "./tabsContext";
|
||||
import { TypesProvider } from "./typesContext";
|
||||
import { ReactFlowProvider } from "reactflow";
|
||||
import { UndoRedoProvider } from "./undoRedoContext";
|
||||
import { SSEProvider } from "./SSEContext";
|
||||
|
||||
export default function ContextWrapper({ children }: { children: ReactNode }) {
|
||||
//element to wrap all context
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { createContext } from "react";
|
||||
import React, { useState } from "react";
|
||||
import React, { createContext, useState } from "react";
|
||||
|
||||
// context to set JSX element on the DOM
|
||||
export const PopUpContext = createContext({
|
||||
|
|
|
|||
|
|
@ -1,33 +1,33 @@
|
|||
import _ from "lodash";
|
||||
import {
|
||||
createContext,
|
||||
useEffect,
|
||||
useState,
|
||||
useRef,
|
||||
ReactNode,
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { addEdge } from "reactflow";
|
||||
import ShortUniqueId from "short-unique-id";
|
||||
import {
|
||||
deleteFlowFromDatabase,
|
||||
downloadFlowsFromDatabase,
|
||||
readFlowsFromDatabase,
|
||||
saveFlowToDatabase,
|
||||
updateFlowInDatabase,
|
||||
uploadFlowsToDatabase,
|
||||
} from "../controllers/API";
|
||||
import { APIClassType, APITemplateType } from "../types/api";
|
||||
import { FlowType, NodeType } from "../types/flow";
|
||||
import { TabsContextType, TabsState } from "../types/tabs";
|
||||
import {
|
||||
updateIds,
|
||||
updateTemplate,
|
||||
getRandomDescription,
|
||||
getRandomName,
|
||||
updateIds,
|
||||
updateTemplate,
|
||||
} from "../utils";
|
||||
import { alertContext } from "./alertContext";
|
||||
import { typesContext } from "./typesContext";
|
||||
import { APIClassType, APITemplateType } from "../types/api";
|
||||
import ShortUniqueId from "short-unique-id";
|
||||
import { addEdge } from "reactflow";
|
||||
import {
|
||||
readFlowsFromDatabase,
|
||||
deleteFlowFromDatabase,
|
||||
saveFlowToDatabase,
|
||||
downloadFlowsFromDatabase,
|
||||
uploadFlowsToDatabase,
|
||||
updateFlowInDatabase,
|
||||
} from "../controllers/API";
|
||||
import _ from "lodash";
|
||||
|
||||
const uid = new ShortUniqueId({ length: 5 });
|
||||
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { createContext, ReactNode, useEffect, useState } from "react";
|
||||
import { Node } from "reactflow";
|
||||
import { typesContextType } from "../types/typesContext";
|
||||
import { getAll } from "../controllers/API";
|
||||
import { APIKindType } from "../types/api";
|
||||
import { typesContextType } from "../types/typesContext";
|
||||
|
||||
//context to share types adn functions from nodes to flow
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
|
|
@ -6,7 +7,6 @@ import {
|
|||
useState,
|
||||
} from "react";
|
||||
import { Edge, Node, useReactFlow } from "reactflow";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { TabsContext } from "./tabsContext";
|
||||
|
||||
type undoRedoContextType = {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import {
|
||||
BuildStatusTypeAPI,
|
||||
errorsTypeAPI,
|
||||
InitTypeAPI,
|
||||
UploadFileTypeAPI,
|
||||
APIClassType,
|
||||
PromptTypeAPI,
|
||||
} from "./../../types/api/index";
|
||||
import { APIObjectType, sendAllProps } from "../../types/api/index";
|
||||
import axios, { AxiosResponse } from "axios";
|
||||
import { FlowStyleType, FlowType } from "../../types/flow";
|
||||
import { ReactFlowJsonObject } from "reactflow";
|
||||
import { APIObjectType, sendAllProps } from "../../types/api/index";
|
||||
import { FlowStyleType, FlowType } from "../../types/flow";
|
||||
import {
|
||||
APIClassType,
|
||||
BuildStatusTypeAPI,
|
||||
InitTypeAPI,
|
||||
PromptTypeAPI,
|
||||
UploadFileTypeAPI,
|
||||
errorsTypeAPI,
|
||||
} from "./../../types/api/index";
|
||||
|
||||
/**
|
||||
* Fetches all objects from the API endpoint.
|
||||
|
|
@ -339,10 +339,3 @@ export async function uploadFile(
|
|||
formData.append("file", file);
|
||||
return await axios.post(`/api/v1/upload/${id}`, formData);
|
||||
}
|
||||
|
||||
export async function postCustomComponent(
|
||||
code: string,
|
||||
apiClass: APIClassType
|
||||
): Promise<AxiosResponse<APIClassType>> {
|
||||
return await axios.post(`/api/v1/custom_component`, { code });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
|
|
|
|||
|
|
@ -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-5
|
||||
}
|
||||
.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,701 @@ The cursor: default; property value restores the browser's default cursor style
|
|||
.input-dialog{
|
||||
@apply text-ring cursor-pointer bg-transparent
|
||||
}
|
||||
.message-button {
|
||||
@apply message-button-position flex h-12 w-12 items-center justify-center rounded-full bg-border px-3 py-1 shadow-md transition-all
|
||||
}
|
||||
|
||||
.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 fixed bottom-4 right-4
|
||||
}
|
||||
.message-button-icon {
|
||||
@apply fill-chat-trigger stroke-chat-trigger stroke-1
|
||||
}
|
||||
.disabled-message-button-icon {
|
||||
@apply fill-chat-trigger-disabled stroke-chat-trigger-disabled 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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App";
|
||||
import reportWebVitals from "./reportWebVitals";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import App from "./App";
|
||||
import ContextWrapper from "./contexts";
|
||||
import reportWebVitals from "./reportWebVitals";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,42 +1,15 @@
|
|||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import "ace-builds/src-noconflict/ext-language_tools";
|
||||
import "ace-builds/src-noconflict/mode-python";
|
||||
import "ace-builds/src-noconflict/theme-github";
|
||||
import "ace-builds/src-noconflict/theme-twilight";
|
||||
import "ace-builds/src-noconflict/ext-language_tools";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
// import "ace-builds/webpack-resolver";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
import { Check, Clipboard, Code2 } from "lucide-react";
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { FlowType } from "../../types/flow/index";
|
||||
import { getCurlCode, getPythonApiCode, getPythonCode } from "../../constants";
|
||||
import { EXPORT_CODE_DIALOG } from "../../constants";
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "../../components/ui/tabs";
|
||||
import { Check, Clipboard, Code2 } from "lucide-react";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCaption,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import { buildTweaks, classNames, limitScrollFieldsModal } from "../../utils";
|
||||
import AccordionComponent from "../../components/AccordionComponent";
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import CodeAreaComponent from "../../components/codeAreaComponent";
|
||||
import Dropdown from "../../components/dropdownComponent";
|
||||
import FloatComponent from "../../components/floatComponent";
|
||||
|
|
@ -47,9 +20,38 @@ import IntComponent from "../../components/intComponent";
|
|||
import PromptAreaComponent from "../../components/promptComponent";
|
||||
import TextAreaComponent from "../../components/textAreaComponent";
|
||||
import ToggleShadComponent from "../../components/toggleShadComponent";
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import { cloneDeep, filter } from "lodash";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "../../components/ui/tabs";
|
||||
import {
|
||||
EXPORT_CODE_DIALOG,
|
||||
getCurlCode,
|
||||
getPythonApiCode,
|
||||
getPythonCode,
|
||||
} from "../../constants";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { FlowType } from "../../types/flow/index";
|
||||
import { buildTweaks, classNames } from "../../utils";
|
||||
|
||||
export default function ApiModal({ flow }: { flow: FlowType }) {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
@ -61,7 +63,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
const [openAccordion, setOpenAccordion] = useState([]);
|
||||
const tweak = useRef([]);
|
||||
const tweaksList = useRef([]);
|
||||
const { setTweak, getTweak } = useContext(TabsContext);
|
||||
const { setTweak, getTweak, tabsState } = useContext(TabsContext);
|
||||
const copyToClipboard = () => {
|
||||
if (!navigator.clipboard || !navigator.clipboard.writeText) {
|
||||
return;
|
||||
|
|
@ -75,9 +77,9 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
}, 2000);
|
||||
});
|
||||
};
|
||||
const pythonApiCode = getPythonApiCode(flow, tweak.current);
|
||||
const curl_code = getCurlCode(flow, tweak.current);
|
||||
const pythonCode = getPythonCode(flow, tweak.current);
|
||||
const pythonApiCode = getPythonApiCode(flow, tweak.current, tabsState);
|
||||
const curl_code = getCurlCode(flow, tweak.current, tabsState);
|
||||
const pythonCode = getPythonCode(flow, tweak.current, tabsState);
|
||||
const tweaksCode = buildTweaks(flow);
|
||||
const tabs = [
|
||||
{
|
||||
|
|
@ -111,7 +113,9 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
startTweaks();
|
||||
}
|
||||
} else {
|
||||
startTweaks();
|
||||
if (tweak?.current) {
|
||||
startTweaks();
|
||||
}
|
||||
}
|
||||
}, [closeEdit]);
|
||||
|
||||
|
|
@ -276,7 +280,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") {
|
||||
|
|
@ -284,7 +288,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()}>
|
||||
|
|
@ -308,12 +312,12 @@ 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 ? (
|
||||
<SyntaxHighlighter
|
||||
className="h-[60vh] w-full overflow-auto"
|
||||
className="h-[60vh] w-full overflow-auto custom-scroll"
|
||||
language={tab.mode}
|
||||
style={oneDark}
|
||||
>
|
||||
|
|
@ -321,7 +325,7 @@ 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",
|
||||
|
|
@ -337,7 +341,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">
|
||||
|
|
@ -418,7 +422,6 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
) : t.data.node.template[n]
|
||||
.multiline ? (
|
||||
<ShadTooltip
|
||||
delayDuration={1000}
|
||||
content={buildContent(
|
||||
t.data.node.template[
|
||||
n
|
||||
|
|
@ -506,7 +509,6 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
) : t.data.node.template[n]
|
||||
.type === "file" ? (
|
||||
<ShadTooltip
|
||||
delayDuration={1000}
|
||||
content={buildContent(
|
||||
getValue(
|
||||
t.data.node.template[n]
|
||||
|
|
@ -622,7 +624,6 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
) : t.data.node.template[n]
|
||||
.type === "prompt" ? (
|
||||
<ShadTooltip
|
||||
delayDuration={1000}
|
||||
content={buildContent(
|
||||
getValue(
|
||||
t.data.node.template[n]
|
||||
|
|
@ -659,7 +660,6 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
) : t.data.node.template[n]
|
||||
.type === "code" ? (
|
||||
<ShadTooltip
|
||||
delayDuration={1000}
|
||||
content={buildContent(
|
||||
getValue(
|
||||
t.data.node.template[n]
|
||||
|
|
@ -720,7 +720,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
|
|||
</div>
|
||||
))}
|
||||
|
||||
{/*
|
||||
{/*
|
||||
<div className="flex flex-col gap-5 bg-muted">
|
||||
<Table className="table-fixed bg-muted outline-1">
|
||||
<TableHeader className="border-gray-200 text-gray-500 text-xs font-medium h-10">
|
||||
|
|
|
|||
|
|
@ -1,26 +1,17 @@
|
|||
import { Variable } from "lucide-react";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import { classNames, limitScrollFieldsModal } from "../../utils";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import ToggleShadComponent from "../../components/toggleShadComponent";
|
||||
import InputListComponent from "../../components/inputListComponent";
|
||||
import TextAreaComponent from "../../components/textAreaComponent";
|
||||
import InputComponent from "../../components/inputComponent";
|
||||
import FloatComponent from "../../components/floatComponent";
|
||||
import Dropdown from "../../components/dropdownComponent";
|
||||
import IntComponent from "../../components/intComponent";
|
||||
import InputFileComponent from "../../components/inputFileComponent";
|
||||
import PromptAreaComponent from "../../components/promptComponent";
|
||||
import CodeAreaComponent from "../../components/codeAreaComponent";
|
||||
import Dropdown from "../../components/dropdownComponent";
|
||||
import FloatComponent from "../../components/floatComponent";
|
||||
import InputComponent from "../../components/inputComponent";
|
||||
import InputFileComponent from "../../components/inputFileComponent";
|
||||
import InputListComponent from "../../components/inputListComponent";
|
||||
import IntComponent from "../../components/intComponent";
|
||||
import PromptAreaComponent from "../../components/promptComponent";
|
||||
import TextAreaComponent from "../../components/textAreaComponent";
|
||||
import ToggleShadComponent from "../../components/toggleShadComponent";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -30,9 +21,18 @@ import {
|
|||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Variable } from "lucide-react";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import { classNames, limitScrollFieldsModal } from "../../utils";
|
||||
|
||||
export default function EditNodeModal({ data }: { data: NodeDataType }) {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
@ -90,27 +90,25 @@ 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">
|
||||
Parameters
|
||||
</span>
|
||||
<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"
|
||||
)}
|
||||
>
|
||||
{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">
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { useState } from "react";
|
||||
import InputListComponent from "../../../../components/inputListComponent";
|
||||
import Dropdown from "../../../../components/dropdownComponent";
|
||||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||
import InputComponent from "../../../../components/inputComponent";
|
||||
import ToggleComponent from "../../../../components/toggleComponent";
|
||||
import FloatComponent from "../../../../components/floatComponent";
|
||||
import IntComponent from "../../../../components/intComponent";
|
||||
import InputFileComponent from "../../../../components/inputFileComponent";
|
||||
import PromptAreaComponent from "../../../../components/promptComponent";
|
||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||
import Dropdown from "../../../../components/dropdownComponent";
|
||||
import FloatComponent from "../../../../components/floatComponent";
|
||||
import InputComponent from "../../../../components/inputComponent";
|
||||
import InputFileComponent from "../../../../components/inputFileComponent";
|
||||
import InputListComponent from "../../../../components/inputListComponent";
|
||||
import IntComponent from "../../../../components/intComponent";
|
||||
import PromptAreaComponent from "../../../../components/promptComponent";
|
||||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||
import ToggleComponent from "../../../../components/toggleComponent";
|
||||
import { classNames } from "../../../../utils";
|
||||
|
||||
export default function ModalField({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { X } from "lucide-react";
|
||||
import { Fragment, useContext, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import {
|
||||
classNames,
|
||||
|
|
@ -9,9 +11,7 @@ import {
|
|||
nodeIconsLucide,
|
||||
toTitleCase,
|
||||
} from "../../utils";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import ModalField from "./components/ModalField";
|
||||
import { X } from "lucide-react";
|
||||
|
||||
export default function NodeModal({ data }: { data: NodeDataType }) {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
@ -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,30 +72,27 @@ 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">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="text-lg font-medium leading-10 text-foreground"
|
||||
>
|
||||
<div className="node-modal-title-div">
|
||||
<Dialog.Title as="h3" 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) !== "_" &&
|
||||
|
|
@ -106,7 +103,7 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
|
|||
: "overflow-hidden"
|
||||
)}
|
||||
>
|
||||
<div className="flex h-full flex-col gap-5">
|
||||
<div className="node-modal-template-column">
|
||||
{Object.keys(data.node.template)
|
||||
.filter(
|
||||
(t) =>
|
||||
|
|
@ -144,10 +141,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);
|
||||
}}
|
||||
|
|
|
|||
157
src/frontend/src/modals/chatModal/chatMessage/index.tsx
Normal file
157
src/frontend/src/modals/chatModal/chatMessage/index.tsx
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
import Convert from "ansi-to-html";
|
||||
import DOMPurify from "dompurify";
|
||||
import { MessageCircle, User2 } from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import rehypeMathjax from "rehype-mathjax";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg";
|
||||
import AiIconStill from "../../../assets/froze-flow.png";
|
||||
import { ChatMessageType } from "../../../types/chat";
|
||||
import { classNames } from "../../../utils";
|
||||
import FileCard from "../fileComponent";
|
||||
import { CodeBlock } from "./codeBlock";
|
||||
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>
|
||||
);
|
||||
}
|
||||
415
src/frontend/src/modals/chatModal/index.tsx
Normal file
415
src/frontend/src/modals/chatModal/index.tsx
Normal file
|
|
@ -0,0 +1,415 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { Eraser, MessagesSquare, X } from "lucide-react";
|
||||
import { Fragment, useContext, useEffect, useRef, useState } from "react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import { sendAllProps } from "../../types/api";
|
||||
import { ChatMessageType } from "../../types/chat";
|
||||
import { FlowType } from "../../types/flow";
|
||||
import { validateNodes } from "../../utils";
|
||||
import ChatInput from "./chatInput";
|
||||
import ChatMessage from "./chatMessage";
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,15 +1,16 @@
|
|||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
// organize-imports-ignore
|
||||
import { useContext, useRef, useState } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import AceEditor from "react-ace";
|
||||
import "ace-builds/src-noconflict/ext-language_tools";
|
||||
import "ace-builds/src-noconflict/mode-python";
|
||||
import "ace-builds/src-noconflict/theme-github";
|
||||
import "ace-builds/src-noconflict/theme-twilight";
|
||||
import "ace-builds/src-noconflict/ext-language_tools";
|
||||
import "ace-builds/src-noconflict/ace";
|
||||
// import "ace-builds/webpack-resolver";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
import { postCustomComponent, postValidateCode } from "../../controllers/API";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { TerminalSquare } from "lucide-react";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -19,9 +20,10 @@ import {
|
|||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants";
|
||||
import { TerminalSquare } from "lucide-react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
import { postValidateCode } from "../../controllers/API";
|
||||
import { APIClassType } from "../../types/api";
|
||||
import {
|
||||
Tabs,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Download } from "lucide-react";
|
||||
import { useContext, useRef, useState } from "react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { removeApiKeys } from "../../utils";
|
||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Checkbox } from "../../components/ui/checkbox";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -12,11 +12,11 @@ import {
|
|||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Checkbox } from "../../components/ui/checkbox";
|
||||
import { EXPORT_DIALOG_SUBTITLE } from "../../constants";
|
||||
import { Download } from "lucide-react";
|
||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { removeApiKeys } from "../../utils";
|
||||
|
||||
export default function ExportModal() {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Settings2 } from "lucide-react";
|
||||
import { useContext, useRef, useState } from "react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -11,11 +11,10 @@ import {
|
|||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { SETTINGS_DIALOG_SUBTITLE } from "../../constants";
|
||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
||||
import { Settings2 } from "lucide-react";
|
||||
import { updateFlowInDatabase } from "../../controllers/API";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
|
||||
export default function FlowSettingsModal() {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { Lock, LucideSend } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { classNames } from "../../../utils";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { TabsContext } from "../../../contexts/tabsContext";
|
||||
import { Eraser, Lock, LucideSend, Send } from "lucide-react";
|
||||
|
||||
export default function ChatInput({
|
||||
lockChat,
|
||||
|
|
|
|||
|
|
@ -48,21 +48,15 @@ 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"
|
||||
onClick={copyToClipboard}
|
||||
>
|
||||
<button 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"
|
||||
onClick={downloadAsFile}
|
||||
>
|
||||
<button className="code-block-modal-button" onClick={downloadAsFile}>
|
||||
<IconDownload size={18} />
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,17 @@
|
|||
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 Convert from "ansi-to-html";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import rehypeMathjax from "rehype-mathjax";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
import MaleTechnology from "../../../assets/male-technologist.png";
|
||||
import Robot from "../../../assets/robot.png";
|
||||
import { THOUGHTS_ICON } from "../../../constants";
|
||||
import { ChatMessageType } from "../../../types/chat";
|
||||
import { classNames } from "../../../utils";
|
||||
import FileCard from "../fileComponent";
|
||||
import { CodeBlock } from "./codeBlock";
|
||||
import Convert from "ansi-to-html";
|
||||
import { User2, MessageSquare } from "lucide-react";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "../../../components/ui/accordion";
|
||||
import { Badge } from "../../../components/ui/badge";
|
||||
|
||||
export default function ChatMessage({
|
||||
chat,
|
||||
|
|
@ -31,33 +25,38 @@ export default function ChatMessage({
|
|||
const convert = new Convert({ newline: true });
|
||||
const [hidden, setHidden] = useState(true);
|
||||
const [template, setTemplate] = useState(chat.template);
|
||||
const [promptOpen, setPromptOpen] = useState(false);
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"flex w-full px-2 py-6 pl-4 pr-9",
|
||||
chat.isSend ? " bg-border" : " "
|
||||
chat.isSend ? "" : " "
|
||||
)}
|
||||
>
|
||||
<div className={classNames("mb-3 ml-3 mr-6 mt-1 ")}>
|
||||
{!chat.isSend ? (
|
||||
<div className="flex h-8 w-8 items-center justify-center overflow-hidden rounded-md bg-[#afe6ef] p-5 text-2xl ">
|
||||
🤖
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<div className="relative flex h-8 w-8 items-center justify-center overflow-hidden rounded-md bg-[#afe6ef] p-5 text-2xl ">
|
||||
<img src={Robot} className="absolute scale-[60%]" />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex h-8 w-8 items-center justify-center overflow-hidden rounded-md bg-[#aface9] p-5 text-2xl ">
|
||||
👨💻
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<div className="relative flex h-8 w-8 items-center justify-center overflow-hidden rounded-md bg-[#aface9] p-5 text-2xl ">
|
||||
<img src={MaleTechnology} className="absolute scale-[60%]" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!chat.isSend ? (
|
||||
<div className="flex w-full items-center text-start">
|
||||
<div className="relative inline-block w-full text-start text-sm font-normal text-primary">
|
||||
<div className="flex w-full flex-1 text-start">
|
||||
<div className="relative inline-block w-full text-start text-sm font-normal text-muted-foreground">
|
||||
{hidden && chat.thought && chat.thought !== "" && (
|
||||
<div
|
||||
onClick={() => setHidden((prev) => !prev)}
|
||||
className="absolute -left-2 -top-1 cursor-pointer"
|
||||
className="absolute -left-8 -top-3 cursor-pointer"
|
||||
>
|
||||
<MessageSquare className="h-5 w-5 animate-bounce dark:text-white" />
|
||||
<THOUGHTS_ICON className="h-4 w-4 animate-bounce dark:text-white" />
|
||||
</div>
|
||||
)}
|
||||
{chat.thought && chat.thought !== "" && !hidden && (
|
||||
|
|
@ -77,7 +76,8 @@ export default function ChatMessage({
|
|||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm, remarkMath]}
|
||||
rehypePlugins={[rehypeMathjax]}
|
||||
className="markdown prose max-w-full text-primary dark:prose-invert"
|
||||
className="markdown prose inline-block break-words text-primary
|
||||
dark:prose-invert"
|
||||
components={{
|
||||
code({ node, inline, className, children, ...props }) {
|
||||
if (children.length) {
|
||||
|
|
@ -135,65 +135,52 @@ export default function ChatMessage({
|
|||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex w-full items-center">
|
||||
<div className="inline-block text-start">
|
||||
<span className=" break-all text-primary">
|
||||
<Accordion type="single" collapsible className="mb-4">
|
||||
<AccordionItem
|
||||
className=" rounded-md border border-ring/60 bg-muted px-4"
|
||||
value="prompt"
|
||||
>
|
||||
<AccordionTrigger className="flex gap-4 text-base font-semibold">
|
||||
Initial Prompt
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="max-h-96 overflow-auto break-all p-2 text-base">
|
||||
{
|
||||
// Make all the variables that are inside curly braces bold
|
||||
template.split("\n").map((line, index) => {
|
||||
const regex = /{([^}]+)}/g;
|
||||
let match;
|
||||
let parts = [];
|
||||
let lastIndex = 0;
|
||||
while ((match = regex.exec(line)) !== null) {
|
||||
// Push text up to the match
|
||||
if (match.index !== lastIndex) {
|
||||
parts.push(line.substring(lastIndex, match.index));
|
||||
}
|
||||
// Push div with matched text
|
||||
parts.push(
|
||||
<div>
|
||||
<div className="my-1 inline-block rounded-md bg-indigo-100 px-2">
|
||||
<span key={match.index}>
|
||||
<span className=" text-xs font-semibold text-high-indigo">
|
||||
{match[1]}
|
||||
</span>
|
||||
{chat.message[match[1]] ? (
|
||||
<span>
|
||||
{chat.message[match[1]]}
|
||||
</span>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
// Update last index
|
||||
lastIndex = regex.lastIndex;
|
||||
}
|
||||
// Push text after the last match
|
||||
if (lastIndex !== line.length) {
|
||||
parts.push(line.substring(lastIndex));
|
||||
}
|
||||
return <p>{parts}</p>;
|
||||
})
|
||||
<div>
|
||||
<button
|
||||
className="mb-2 flex items-center gap-4 rounded-md border border-ring/60 bg-background px-4 py-2 text-base font-semibold"
|
||||
onClick={() => {
|
||||
setPromptOpen((old) => !old);
|
||||
}}
|
||||
>
|
||||
Initial Prompt
|
||||
<ChevronDown
|
||||
className={
|
||||
"h-3 w-3 transition-all " + (promptOpen ? "rotate-180" : "")
|
||||
}
|
||||
/>
|
||||
</button>
|
||||
<span className="prose inline-block break-words text-primary dark:prose-invert">
|
||||
{promptOpen
|
||||
? template.split("\n").map((line, index) => {
|
||||
const regex = /{([^}]+)}/g;
|
||||
let match;
|
||||
let parts = [];
|
||||
let lastIndex = 0;
|
||||
while ((match = regex.exec(line)) !== null) {
|
||||
// Push text up to the match
|
||||
if (match.index !== lastIndex) {
|
||||
parts.push(line.substring(lastIndex, match.index));
|
||||
}
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
{chat.message[chat.chatKey]}
|
||||
</span>
|
||||
</div>
|
||||
// Push div with matched text
|
||||
if (chat.message[match[1]]) {
|
||||
parts.push(
|
||||
<span className="my-1 rounded-md bg-indigo-100">
|
||||
{chat.message[match[1]]}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
// Update last index
|
||||
lastIndex = regex.lastIndex;
|
||||
}
|
||||
// Push text after the last match
|
||||
if (lastIndex !== line.length) {
|
||||
parts.push(line.substring(lastIndex));
|
||||
}
|
||||
return <p>{parts}</p>;
|
||||
})
|
||||
: chat.message[chat.chatKey]}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as base64js from "base64-js";
|
||||
import { useState } from "react";
|
||||
import { DownloadCloud, File } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function FileCard({ fileName, content, fileType }) {
|
||||
const handleDownload = () => {
|
||||
|
|
@ -36,10 +36,11 @@ export default function FileCard({ fileName, content, fileType }) {
|
|||
className="h-full w-full rounded-lg"
|
||||
/>
|
||||
{isHovered && (
|
||||
<div
|
||||
className={`absolute right-0 top-0 rounded-bl-lg bg-muted px-1 text-sm font-bold text-foreground `}
|
||||
>
|
||||
<button className="px-2 py-1 text-ring " onClick={handleDownload}>
|
||||
<div className={`file-card-modal-image-div `}>
|
||||
<button
|
||||
className="file-card-modal-image-button "
|
||||
onClick={handleDownload}
|
||||
>
|
||||
<DownloadCloud className="h-5 w-5 text-current hover:scale-110" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -49,11 +50,8 @@ 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"
|
||||
>
|
||||
<div className="mr-2 flex w-full items-center gap-2 text-current">
|
||||
<button onClick={handleDownload} className="file-card-modal-button">
|
||||
<div className="file-card-modal-div">
|
||||
{" "}
|
||||
{fileType === "image" ? (
|
||||
<img
|
||||
|
|
@ -64,10 +62,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>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,23 @@
|
|||
import { Eraser, TerminalSquare, Variable } from "lucide-react";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { FlowType } from "../../types/flow";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { classNames, validateNodes } from "../../utils";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import ChatMessage from "./chatMessage";
|
||||
import { TerminalSquare, MessageSquare, Variable, Eraser } from "lucide-react";
|
||||
import { sendAllProps } from "../../types/api";
|
||||
import { ChatMessageType } from "../../types/chat";
|
||||
import { FlowType } from "../../types/flow";
|
||||
import { classNames, validateNodes } from "../../utils";
|
||||
import ChatInput from "./chatInput";
|
||||
import ChatMessage from "./chatMessage";
|
||||
|
||||
import _ from "lodash";
|
||||
import ToggleShadComponent from "../../components/toggleShadComponent";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "../../components/ui/accordion";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -18,17 +26,9 @@ import {
|
|||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "../../components/ui/accordion";
|
||||
import { Textarea } from "../../components/ui/textarea";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import ToggleShadComponent from "../../components/toggleShadComponent";
|
||||
import { CHAT_FORM_DIALOG_SUBTITLE, THOUGHTS_ICON } from "../../constants";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
|
||||
export default function FormModal({
|
||||
flow,
|
||||
|
|
@ -535,7 +535,7 @@ export default function FormModal({
|
|||
<span className="text-base text-gray-500">
|
||||
Start a conversation and click the agent's thoughts{" "}
|
||||
<span>
|
||||
<MessageSquare className="mx-1 inline h-5 w-5 animate-bounce " />
|
||||
<THOUGHTS_ICON className="mx-1 inline h-5 w-5 animate-bounce " />
|
||||
</span>{" "}
|
||||
to inspect the chaining process.
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { useContext, useRef, useState, useEffect } from "react";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
import { postValidatePrompt } from "../../controllers/API";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import DOMPurify from "dompurify";
|
||||
import { FileText, Variable } from "lucide-react";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -12,14 +13,16 @@ import {
|
|||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Textarea } from "../../components/ui/textarea";
|
||||
import {
|
||||
HIGHLIGH_CSS,
|
||||
PROMPT_DIALOG_SUBTITLE,
|
||||
TEXT_DIALOG_SUBTITLE,
|
||||
} from "../../constants";
|
||||
import { FileText } from "lucide-react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { postValidatePrompt } from "../../controllers/API";
|
||||
import { APIClassType } from "../../types/api";
|
||||
import {
|
||||
INVALID_CHARACTERS,
|
||||
|
|
@ -29,9 +32,6 @@ import {
|
|||
regexHighlight,
|
||||
varHighlightHTML,
|
||||
} from "../../utils";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import DOMPurify from "dompurify";
|
||||
|
||||
export default function GenericModal({
|
||||
field_name = "",
|
||||
|
|
@ -170,7 +170,7 @@ export default function GenericModal({
|
|||
return (
|
||||
<Dialog open={true} onOpenChange={setModalOpen}>
|
||||
<DialogTrigger></DialogTrigger>
|
||||
<DialogContent className="min-w-[80vw]">
|
||||
<DialogContent className="min-w-[80vw] gap-2">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center">
|
||||
<span className="pr-2">{myModalTitle}</span>
|
||||
|
|
@ -196,49 +196,16 @@ export default function GenericModal({
|
|||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
{type == TypeModal.PROMPT &&
|
||||
inputValue &&
|
||||
inputValue != "" &&
|
||||
wordsHighlight.length > 0 && (
|
||||
<>
|
||||
<div>
|
||||
<span className="">Variables: </span>
|
||||
{wordsHighlight.map((word, index) => (
|
||||
<ShadTooltip
|
||||
key={getRandomKeyByssmm() + index}
|
||||
content={word.replace(/[{}]/g, "")}
|
||||
asChild={false}
|
||||
delayDuration={1500}
|
||||
>
|
||||
<Badge
|
||||
key={index}
|
||||
size="lg"
|
||||
className="m-1 max-w-[40vw] cursor-default truncate p-2.5 text-sm"
|
||||
>
|
||||
<div className="relative bottom-[1px]">
|
||||
<span>
|
||||
{word.replace(/[{}]/g, "").length > 59
|
||||
? word.replace(/[{}]/g, "").slice(0, 56) + "..."
|
||||
: word.replace(/[{}]/g, "")}
|
||||
</span>
|
||||
</div>
|
||||
</Badge>
|
||||
</ShadTooltip>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={classNames(
|
||||
!isEdit ? "rounded-lg border" : "",
|
||||
"flex h-[60vh] w-full"
|
||||
"flex h-[55vh] w-full"
|
||||
)}
|
||||
>
|
||||
{type == TypeModal.PROMPT && isEdit ? (
|
||||
<Textarea
|
||||
ref={ref}
|
||||
className="form-input h-full w-full rounded-lg border-gray-300 focus-visible:ring-1 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
|
||||
className="form-input h-full w-full rounded-lg border-gray-300 custom-scroll focus-visible:ring-1 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
|
||||
value={inputValue}
|
||||
onBlur={() => {
|
||||
blur();
|
||||
|
|
@ -268,16 +235,55 @@ export default function GenericModal({
|
|||
)}
|
||||
</div>
|
||||
|
||||
{type == TypeModal.PROMPT && (
|
||||
<>
|
||||
<div className="sm:6/6 mr-28 mt-3 h-[60px] overflow-y-auto custom-scroll">
|
||||
<div className="flex flex-wrap items-center">
|
||||
<Variable className=" -ml-px mr-1 flex h-4 w-4 text-primary"></Variable>
|
||||
<span className="text-md font-semibold text-primary">
|
||||
Input Variables:
|
||||
</span>
|
||||
|
||||
{wordsHighlight.map((word, index) => (
|
||||
<ShadTooltip
|
||||
key={getRandomKeyByssmm() + index}
|
||||
content={word.replace(/[{}]/g, "")}
|
||||
asChild={false}
|
||||
>
|
||||
<Badge
|
||||
key={index}
|
||||
variant="gray"
|
||||
size="md"
|
||||
className="m-1 max-w-[40vw] cursor-default truncate p-2.5 text-sm"
|
||||
>
|
||||
<div className="relative bottom-[1px]">
|
||||
<span>
|
||||
{word.replace(/[{}]/g, "").length > 59
|
||||
? word.replace(/[{}]/g, "").slice(0, 56) + "..."
|
||||
: word.replace(/[{}]/g, "")}
|
||||
</span>
|
||||
</div>
|
||||
</Badge>
|
||||
</ShadTooltip>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
className="mt-3"
|
||||
onClick={() => {
|
||||
switch (myModalType) {
|
||||
case 1:
|
||||
setValue(inputValue);
|
||||
setModalOpen(false);
|
||||
break;
|
||||
case 2:
|
||||
validatePrompt(false);
|
||||
!inputValue || inputValue == ""
|
||||
? setModalOpen(false)
|
||||
: validatePrompt(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { ReactNode } from "react";
|
||||
import { ReactNode } from "react";
|
||||
import { classNames } from "../../../utils";
|
||||
|
||||
export default function ButtonBox({
|
||||
|
|
@ -77,7 +77,7 @@ 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,
|
||||
|
|
|
|||
|
|
@ -1,22 +1,11 @@
|
|||
import {
|
||||
XMarkIcon,
|
||||
ArrowDownTrayIcon,
|
||||
DocumentDuplicateIcon,
|
||||
ComputerDesktopIcon,
|
||||
ArrowUpTrayIcon,
|
||||
ArrowLeftIcon,
|
||||
CommandLineIcon,
|
||||
ArrowUpTrayIcon,
|
||||
ComputerDesktopIcon,
|
||||
DocumentDuplicateIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import { Fragment, 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 { useContext, useRef, useState } from "react";
|
||||
import LoadingComponent from "../../components/loadingComponent";
|
||||
import { FlowType } from "../../types/flow";
|
||||
import { classNames, snakeToSpaces, toNormalCase } from "../../utils";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -26,8 +15,14 @@ import {
|
|||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { IMPORT_DIALOG_SUBTITLE } from "../../constants";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { getExamples } from "../../controllers/API";
|
||||
import { FlowType } from "../../types/flow";
|
||||
import { classNames } from "../../utils";
|
||||
import ButtonBox from "./buttonBox";
|
||||
|
||||
export default function ImportModal() {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
|
@ -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,21 +101,19 @@ 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" />
|
||||
}
|
||||
icon={<DocumentDuplicateIcon className="document-icon" />}
|
||||
onClick={() => {
|
||||
setShowExamples(true);
|
||||
handleExamples();
|
||||
|
|
@ -132,9 +125,7 @@ export default function ImportModal() {
|
|||
size="big"
|
||||
bgColor="bg-almost-dark-blue "
|
||||
description="Import from Local"
|
||||
icon={
|
||||
<ComputerDesktopIcon className="h-10 w-10 flex-shrink-0" />
|
||||
}
|
||||
icon={<ComputerDesktopIcon className="document-icon" />}
|
||||
onClick={() => {
|
||||
uploadFlow();
|
||||
setModalOpen(false);
|
||||
|
|
@ -145,7 +136,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 +169,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 +188,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>
|
||||
|
|
|
|||
151
src/frontend/src/modals/promptModal/index.tsx
Normal file
151
src/frontend/src/modals/promptModal/index.tsx
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { DocumentTextIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||
import { Fragment, useContext, useRef, useState } from "react";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { darkContext } from "../../contexts/darkContext";
|
||||
import { PopUpContext } from "../../contexts/popUpContext";
|
||||
import { checkPrompt } from "../../controllers/API";
|
||||
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>
|
||||
);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue