Merge branch 'dev' into docs-how-to-contribute-components
This commit is contained in:
commit
fbae9f59c0
86 changed files with 691 additions and 521 deletions
90
.eslintrc.json
Normal file
90
.eslintrc.json
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:prettier/recommended"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"react",
|
||||||
|
"import-helpers",
|
||||||
|
"prettier"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"project": [
|
||||||
|
"./tsconfig.node.json",
|
||||||
|
"./tsconfig.json"
|
||||||
|
],
|
||||||
|
"extraFileExtensions:": [
|
||||||
|
".mdx"
|
||||||
|
],
|
||||||
|
"extensions:": [
|
||||||
|
".mdx"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"no-console": "warn",
|
||||||
|
"no-self-assign": "warn",
|
||||||
|
"no-self-compare": "warn",
|
||||||
|
"complexity": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"max": 15
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
"SwitchCase": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-dupe-keys": "error",
|
||||||
|
"no-invalid-regexp": "error",
|
||||||
|
"no-undef": "error",
|
||||||
|
"no-return-assign": "error",
|
||||||
|
"no-redeclare": "error",
|
||||||
|
"no-empty": "error",
|
||||||
|
"no-await-in-loop": "error",
|
||||||
|
"react/react-in-jsx-scope": 0,
|
||||||
|
"node/exports-style": [
|
||||||
|
"error",
|
||||||
|
"module.exports"
|
||||||
|
],
|
||||||
|
"node/file-extension-in-import": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"node/prefer-global/buffer": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"node/prefer-global/console": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"node/prefer-global/process": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"node/prefer-global/url-search-params": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"node/prefer-global/url": [
|
||||||
|
"error",
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"node/prefer-promises/dns": "error",
|
||||||
|
"node/prefer-promises/fs": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
44
.pre-commit-config.yaml
Normal file
44
.pre-commit-config.yaml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
fail_fast: true
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-eslint
|
||||||
|
rev: "v9.1.1"
|
||||||
|
hooks:
|
||||||
|
- id: eslint
|
||||||
|
files: \.[jt]sx?$ # *.js, *.jsx, *.ts and *.tsx
|
||||||
|
types: [file]
|
||||||
|
args: ["--fix", "--no-warn-ignored"]
|
||||||
|
additional_dependencies:
|
||||||
|
- eslint@9.1.1
|
||||||
|
- eslint-plugin-prettier
|
||||||
|
- eslint-config-prettier
|
||||||
|
- prettier
|
||||||
|
- eslint-plugin-react@latest
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.1.0
|
||||||
|
hooks:
|
||||||
|
- id: check-case-conflict
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: mixed-line-ending
|
||||||
|
args:
|
||||||
|
- --fix=lf
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: pretty-format-json
|
||||||
|
exclude: ^tsconfig.*.json
|
||||||
|
args:
|
||||||
|
- --autofix
|
||||||
|
- --indent=4
|
||||||
|
- --no-sort-keys
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
# Ruff version.
|
||||||
|
rev: v0.4.2
|
||||||
|
hooks:
|
||||||
|
# Run the linter.
|
||||||
|
- id: ruff
|
||||||
|
# Python
|
||||||
|
files: \.py$
|
||||||
|
types: [file]
|
||||||
|
# Run the formatter.
|
||||||
|
- id: ruff-format
|
||||||
|
files: \.py$
|
||||||
|
types: [file]
|
||||||
1
Makefile
1
Makefile
|
|
@ -135,6 +135,7 @@ frontendc:
|
||||||
install_backend:
|
install_backend:
|
||||||
@echo 'Installing backend dependencies'
|
@echo 'Installing backend dependencies'
|
||||||
@poetry install
|
@poetry install
|
||||||
|
@poetry run pre-commit install
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
@echo 'Setting up the environment'
|
@echo 'Setting up the environment'
|
||||||
|
|
|
||||||
90
poetry.lock
generated
90
poetry.lock
generated
|
|
@ -828,6 +828,17 @@ files = [
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pycparser = "*"
|
pycparser = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfgv"
|
||||||
|
version = "3.4.0"
|
||||||
|
description = "Validate configuration and produce human readable error messages."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
|
||||||
|
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chardet"
|
name = "chardet"
|
||||||
version = "5.2.0"
|
version = "5.2.0"
|
||||||
|
|
@ -1604,6 +1615,17 @@ files = [
|
||||||
{file = "diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc"},
|
{file = "diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "distlib"
|
||||||
|
version = "0.3.8"
|
||||||
|
description = "Distribution utilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
|
||||||
|
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "distro"
|
name = "distro"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
|
|
@ -3143,6 +3165,20 @@ files = [
|
||||||
{file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"},
|
{file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "identify"
|
||||||
|
version = "2.5.36"
|
||||||
|
description = "File identification library for Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"},
|
||||||
|
{file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
license = ["ukkonen"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.7"
|
version = "3.7"
|
||||||
|
|
@ -5229,6 +5265,20 @@ plot = ["matplotlib"]
|
||||||
tgrep = ["pyparsing"]
|
tgrep = ["pyparsing"]
|
||||||
twitter = ["twython"]
|
twitter = ["twython"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nodeenv"
|
||||||
|
version = "1.8.0"
|
||||||
|
description = "Node.js virtual environment builder"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
|
||||||
|
files = [
|
||||||
|
{file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
|
||||||
|
{file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
setuptools = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "numexpr"
|
name = "numexpr"
|
||||||
version = "2.10.0"
|
version = "2.10.0"
|
||||||
|
|
@ -6215,6 +6265,24 @@ dev = ["black", "flake8", "flake8-print", "isort", "pre-commit"]
|
||||||
sentry = ["django", "sentry-sdk"]
|
sentry = ["django", "sentry-sdk"]
|
||||||
test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint", "pytest", "pytest-timeout"]
|
test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint", "pytest", "pytest-timeout"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pre-commit"
|
||||||
|
version = "3.7.0"
|
||||||
|
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "pre_commit-3.7.0-py2.py3-none-any.whl", hash = "sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab"},
|
||||||
|
{file = "pre_commit-3.7.0.tar.gz", hash = "sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
cfgv = ">=2.0.0"
|
||||||
|
identify = ">=1.0.0"
|
||||||
|
nodeenv = ">=0.11.1"
|
||||||
|
pyyaml = ">=5.1"
|
||||||
|
virtualenv = ">=20.10.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prometheus-client"
|
name = "prometheus-client"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
|
|
@ -9561,6 +9629,26 @@ files = [
|
||||||
{file = "vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0"},
|
{file = "vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "virtualenv"
|
||||||
|
version = "20.26.1"
|
||||||
|
description = "Virtual Python Environment builder"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "virtualenv-20.26.1-py3-none-any.whl", hash = "sha256:7aa9982a728ae5892558bff6a2839c00b9ed145523ece2274fad6f414690ae75"},
|
||||||
|
{file = "virtualenv-20.26.1.tar.gz", hash = "sha256:604bfdceaeece392802e6ae48e69cec49168b9c5f4a44e483963f9242eb0e78b"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
distlib = ">=0.3.7,<1"
|
||||||
|
filelock = ">=3.12.2,<4"
|
||||||
|
platformdirs = ">=3.9.1,<5"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
||||||
|
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "watchfiles"
|
name = "watchfiles"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
|
|
@ -10253,4 +10341,4 @@ local = ["ctransformers", "llama-cpp-python", "sentence-transformers"]
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = ">=3.10,<3.12"
|
python-versions = ">=3.10,<3.12"
|
||||||
content-hash = "bec34397b534f882551511558c76785c7cd67e6a1eefc1d45f6a64d97175d886"
|
content-hash = "b3d424bc8e83a9f10a8e71f95e2499b3018711d8edf7a594814b9388e5393a84"
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@ respx = "^0.21.1"
|
||||||
pytest-instafail = "^0.5.0"
|
pytest-instafail = "^0.5.0"
|
||||||
pytest-asyncio = "^0.23.0"
|
pytest-asyncio = "^0.23.0"
|
||||||
pytest-profiling = "^1.7.0"
|
pytest-profiling = "^1.7.0"
|
||||||
|
pre-commit = "^3.7.0"
|
||||||
|
|
||||||
[tool.poetry.extras]
|
[tool.poetry.extras]
|
||||||
deploy = ["celery", "redis", "flower"]
|
deploy = ["celery", "redis", "flower"]
|
||||||
|
|
|
||||||
|
|
@ -32,90 +32,6 @@ case "$OS" in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo "Detected Operating System: $OS"
|
|
||||||
|
|
||||||
# Installation of pipx based on the detected OS
|
|
||||||
install_pipx() {
|
|
||||||
case $1 in
|
|
||||||
macOS)
|
|
||||||
# macOS installation using Homebrew
|
|
||||||
command -v brew >/dev/null 2>&1 || exit_with_message "Homebrew is not installed. Please install Homebrew first."
|
|
||||||
echo "Installing pipx using Homebrew..."
|
|
||||||
brew install pipx
|
|
||||||
pipx ensurepath
|
|
||||||
;;
|
|
||||||
Linux)
|
|
||||||
# Linux installation. Further checks are needed to distinguish between distributions
|
|
||||||
if grep -qEi "(ubuntu|debian)" /etc/*release; then
|
|
||||||
echo "Installing pipx on Ubuntu/Debian..."
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install pipx -y
|
|
||||||
elif grep -qEi "fedora" /etc/*release; then
|
|
||||||
echo "Installing pipx on Fedora..."
|
|
||||||
sudo dnf install pipx -y
|
|
||||||
else
|
|
||||||
echo "Installing pipx using pip (other Linux distributions)..."
|
|
||||||
python3 -m pip install --user pipx
|
|
||||||
fi
|
|
||||||
pipx ensurepath
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
exit_with_message "Unsupported operating system for pipx installation."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to fetch the latest version of pipx from GitHub and compare with the installed version
|
|
||||||
check_for_pipx_update() {
|
|
||||||
echo "Checking for updates to pipx..."
|
|
||||||
# Fetch the latest version of pipx, ensuring only to capture the numeric version without 'v' prefix.
|
|
||||||
local latest_version=$(curl -s https://api.github.com/repos/pypa/pipx/releases/latest | grep '"tag_name":' | sed -E 's/.*"tag_name": "v?([^"]+)".*/\1/')
|
|
||||||
# Extract the current installed version of pipx.
|
|
||||||
local current_version=$(pipx --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
|
|
||||||
|
|
||||||
if [[ "$latest_version" == "$current_version" ]]; then
|
|
||||||
echo "You have the latest version of pipx ($current_version)."
|
|
||||||
else
|
|
||||||
echo "A newer version of pipx ($latest_version) is available. You have $current_version. Do you want to update? (yes/no)"
|
|
||||||
read -r user_input
|
|
||||||
if [[ "$user_input" == "yes" ]]; then
|
|
||||||
echo "Updating pipx..."
|
|
||||||
case "$OS" in
|
|
||||||
macOS)
|
|
||||||
brew upgrade pipx
|
|
||||||
;;
|
|
||||||
Linux)
|
|
||||||
if grep -qEi "(ubuntu|debian)" /etc/*release; then
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install --only-upgrade pipx -y
|
|
||||||
elif grep -qEi "fedora" /etc/*release; then
|
|
||||||
sudo dnf upgrade pipx -y
|
|
||||||
else
|
|
||||||
python3 -m pip install --user --upgrade pipx
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
exit_with_message "Unsupported operating system for pipx update."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
pipx ensurepath
|
|
||||||
echo "pipx updated to version $latest_version"
|
|
||||||
else
|
|
||||||
echo "Not updating pipx at this time."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Now, modify the existing check to call check_for_pipx_update even if pipx is installed
|
|
||||||
if ! command -v pipx &> /dev/null; then
|
|
||||||
echo "Pipx is not installed. Installing..."
|
|
||||||
install_pipx "$OS"
|
|
||||||
echo "Pipx installed successfully."
|
|
||||||
else
|
|
||||||
echo "Pipx is already installed."
|
|
||||||
check_for_pipx_update
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
echo "Checking Poetry installation..."
|
echo "Checking Poetry installation..."
|
||||||
|
|
||||||
|
|
@ -124,7 +40,7 @@ if ! command -v poetry &> /dev/null
|
||||||
then
|
then
|
||||||
echo "Poetry is not installed. Installing..."
|
echo "Poetry is not installed. Installing..."
|
||||||
# Also install python 3.10 and use
|
# Also install python 3.10 and use
|
||||||
pipx install poetry --python python3.10 --fetch-missing-python
|
curl -sSL https://install.python-poetry.org | python3 -
|
||||||
echo "Poetry installed successfully."
|
echo "Poetry installed successfully."
|
||||||
else
|
else
|
||||||
echo "Poetry is already installed."
|
echo "Poetry is already installed."
|
||||||
|
|
@ -146,3 +62,5 @@ else
|
||||||
echo "Poetry version is $1 or higher. No need to update."
|
echo "Poetry version is $1 or higher. No need to update."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,17 +205,12 @@ async def build_and_cache_graph_from_db(
|
||||||
flow_id: str,
|
flow_id: str,
|
||||||
session: Session,
|
session: Session,
|
||||||
chat_service: "ChatService",
|
chat_service: "ChatService",
|
||||||
graph: Optional[Graph] = None,
|
|
||||||
):
|
):
|
||||||
"""Build and cache the graph."""
|
"""Build and cache the graph."""
|
||||||
flow: Optional[Flow] = session.get(Flow, flow_id)
|
flow: Optional[Flow] = session.get(Flow, flow_id)
|
||||||
if not flow or not flow.data:
|
if not flow or not flow.data:
|
||||||
raise ValueError("Invalid flow ID")
|
raise ValueError("Invalid flow ID")
|
||||||
other_graph = Graph.from_payload(flow.data, flow_id)
|
graph = Graph.from_payload(flow.data, flow_id)
|
||||||
if graph is None:
|
|
||||||
graph = other_graph
|
|
||||||
else:
|
|
||||||
graph = graph.update(other_graph)
|
|
||||||
await chat_service.set_cache(flow_id, graph)
|
await chat_service.set_cache(flow_id, graph)
|
||||||
return graph
|
return graph
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,13 +79,8 @@ async def retrieve_vertices_order(
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# First, we need to check if the flow_id is in the cache
|
# First, we need to check if the flow_id is in the cache
|
||||||
graph = None
|
|
||||||
if not data:
|
if not data:
|
||||||
if cache := await chat_service.get_cache(flow_id):
|
graph = await build_and_cache_graph_from_db(flow_id=flow_id, session=session, chat_service=chat_service)
|
||||||
graph = cache.get("result")
|
|
||||||
graph = await build_and_cache_graph_from_db(
|
|
||||||
flow_id=flow_id, session=session, chat_service=chat_service, graph=graph
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
graph = await build_and_cache_graph_from_data(
|
graph = await build_and_cache_graph_from_data(
|
||||||
flow_id=flow_id, graph_data=data.model_dump(), chat_service=chat_service
|
flow_id=flow_id, graph_data=data.model_dump(), chat_service=chat_service
|
||||||
|
|
|
||||||
|
|
@ -93,14 +93,14 @@ class APIRequest(CustomComponent):
|
||||||
self,
|
self,
|
||||||
method: str,
|
method: str,
|
||||||
urls: List[str],
|
urls: List[str],
|
||||||
_headers: Optional[Record] = None,
|
headers: Optional[Record] = None,
|
||||||
body: Optional[Record] = None,
|
body: Optional[Record] = None,
|
||||||
timeout: int = 5,
|
timeout: int = 5,
|
||||||
) -> List[Record]:
|
) -> List[Record]:
|
||||||
if _headers is None:
|
if headers is None:
|
||||||
headers = {}
|
headers_dict = {}
|
||||||
else:
|
else:
|
||||||
headers = _headers.data
|
headers_dict = headers.data
|
||||||
|
|
||||||
bodies = []
|
bodies = []
|
||||||
if body:
|
if body:
|
||||||
|
|
@ -114,7 +114,7 @@ class APIRequest(CustomComponent):
|
||||||
bodies += [None] * (len(urls) - len(bodies)) # type: ignore
|
bodies += [None] * (len(urls) - len(bodies)) # type: ignore
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
results = await asyncio.gather(
|
results = await asyncio.gather(
|
||||||
*[self.make_request(client, method, u, headers, rec, timeout) for u, rec in zip(urls, bodies)]
|
*[self.make_request(client, method, u, headers_dict, rec, timeout) for u, rec in zip(urls, bodies)]
|
||||||
)
|
)
|
||||||
self.status = results
|
self.status = results
|
||||||
return results
|
return results
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any, Dict
|
|
||||||
|
|
||||||
from langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record
|
|
||||||
from langflow.interface.custom.custom_component import CustomComponent
|
|
||||||
from langflow.schema import Record
|
|
||||||
|
|
||||||
|
|
||||||
class FileInput(CustomComponent):
|
|
||||||
display_name = "File Input"
|
|
||||||
description = "A generic file input."
|
|
||||||
icon = "file-text"
|
|
||||||
|
|
||||||
def build_config(self) -> Dict[str, Any]:
|
|
||||||
return {
|
|
||||||
"path": {
|
|
||||||
"display_name": "Path",
|
|
||||||
"field_type": "file",
|
|
||||||
"file_types": TEXT_FILE_TYPES,
|
|
||||||
"info": f"Supported file types: {', '.join(TEXT_FILE_TYPES)}",
|
|
||||||
},
|
|
||||||
"silent_errors": {
|
|
||||||
"display_name": "Silent Errors",
|
|
||||||
"advanced": True,
|
|
||||||
"info": "If true, errors will not raise an exception.",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
def load_file(self, path: str, silent_errors: bool = False) -> Record:
|
|
||||||
resolved_path = self.resolve_path(path)
|
|
||||||
path_obj = Path(resolved_path)
|
|
||||||
extension = path_obj.suffix[1:].lower()
|
|
||||||
if extension == "doc":
|
|
||||||
raise ValueError("doc files are not supported. Please save as .docx")
|
|
||||||
if extension not in TEXT_FILE_TYPES:
|
|
||||||
raise ValueError(f"Unsupported file type: {extension}")
|
|
||||||
record = parse_text_file_to_record(resolved_path, silent_errors)
|
|
||||||
self.status = record if record else "No data"
|
|
||||||
return record or Record()
|
|
||||||
|
|
||||||
def build(
|
|
||||||
self,
|
|
||||||
path: str,
|
|
||||||
silent_errors: bool = False,
|
|
||||||
) -> Record:
|
|
||||||
record = self.load_file(path, silent_errors)
|
|
||||||
self.status = record
|
|
||||||
return record
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
from langflow.base.io.text import TextComponent
|
|
||||||
from langflow.field_typing.constants import Data, NestedDict
|
|
||||||
|
|
||||||
class JsonInput(TextComponent):
|
|
||||||
display_name = "JSON Input"
|
|
||||||
description = "JSON Input."
|
|
||||||
|
|
||||||
def build_config(self):
|
|
||||||
return {
|
|
||||||
"input_value": {
|
|
||||||
"display_name": "JSON",
|
|
||||||
"field_type": "NestedDict"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def build(self, input_value: NestedDict) -> NestedDict:
|
|
||||||
return input_value
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
from langflow.base.io.text import TextComponent
|
|
||||||
from langflow.field_typing.constants import Data
|
|
||||||
|
|
||||||
|
|
||||||
class KeyPairInput(TextComponent):
|
|
||||||
display_name = "Dictionary Input"
|
|
||||||
description = "Dictionary Input."
|
|
||||||
|
|
||||||
def build_config(self):
|
|
||||||
return {
|
|
||||||
"input_value": {
|
|
||||||
"display_name": "Dictionaries",
|
|
||||||
"field_type": "dict",
|
|
||||||
"list": True
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def build(self, input_value: dict) -> dict:
|
|
||||||
return input_value
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# from langflow.field_typing import Data
|
|
||||||
from langflow.schema import Record
|
|
||||||
from langflow.interface.custom.custom_component import CustomComponent
|
|
||||||
|
|
||||||
|
|
||||||
class StringListInput(CustomComponent):
|
|
||||||
display_name = "String List Input"
|
|
||||||
|
|
||||||
def build_config(self):
|
|
||||||
return {"input_value": {"display_name": "String List Input", "field_type": "str", "list": True}}
|
|
||||||
|
|
||||||
def build(self, input_value: list) -> Record:
|
|
||||||
return Record(data=input_value)
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from langflow.base.io.text import TextComponent
|
|
||||||
from langflow.field_typing import Text, Data
|
|
||||||
|
|
||||||
|
|
||||||
class CSVOutput(TextComponent):
|
|
||||||
display_name = "CSV Output"
|
|
||||||
description = "Used view csv files"
|
|
||||||
|
|
||||||
field_config = {
|
|
||||||
"input_value": {"display_name": "csv","info":"A csv blob","input_types":["Data"]},
|
|
||||||
"separator": {"display_name": "separator","info":"The separator used in the csv file","input_types":["Text"], "field_type":"Text","default_value":";","options":[";", ",", "|"]},
|
|
||||||
}
|
|
||||||
|
|
||||||
def build(self, input_value: Data, separator) -> Data:
|
|
||||||
return {"data": input_value, "separator": separator}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from langflow.base.io.text import TextComponent
|
|
||||||
from langflow.field_typing import Text
|
|
||||||
|
|
||||||
class ImageOutput(TextComponent):
|
|
||||||
display_name = "Image Output"
|
|
||||||
description = "Used view image files"
|
|
||||||
|
|
||||||
field_config = {
|
|
||||||
"input_value": {"display_name": "image","info":"A image url","input_types":["Text"]},
|
|
||||||
}
|
|
||||||
|
|
||||||
def build(self, input_value: Text) -> Text:
|
|
||||||
return input_value
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
from langflow.base.io.text import TextComponent
|
|
||||||
from langflow.field_typing.constants import Data, NestedDict
|
|
||||||
|
|
||||||
class JsonOutput(TextComponent):
|
|
||||||
display_name = "JSON Output"
|
|
||||||
description = "JSON Output."
|
|
||||||
|
|
||||||
def build_config(self):
|
|
||||||
return {
|
|
||||||
"input_value": {
|
|
||||||
"display_name": "JSON",
|
|
||||||
"field_type": "NestedDict"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def build(self, input_value: NestedDict) -> NestedDict:
|
|
||||||
return input_value
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
from langflow.base.io.text import TextComponent
|
|
||||||
from langflow.field_typing.constants import Data
|
|
||||||
|
|
||||||
|
|
||||||
class KeyPairOutput(TextComponent):
|
|
||||||
display_name = "Dictionary Output"
|
|
||||||
description = "Dictionary Output."
|
|
||||||
|
|
||||||
def build_config(self):
|
|
||||||
return {
|
|
||||||
"input_value": {
|
|
||||||
"display_name": "Dictionaries",
|
|
||||||
"field_type": "dict",
|
|
||||||
"list": True
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def build(self, input_value: dict) -> dict:
|
|
||||||
return input_value
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from langflow.base.io.text import TextComponent
|
|
||||||
from langflow.field_typing import Text
|
|
||||||
|
|
||||||
|
|
||||||
class PDFOutput(TextComponent):
|
|
||||||
display_name = "PDF Output"
|
|
||||||
description = "Used view pdf files"
|
|
||||||
|
|
||||||
field_config = {
|
|
||||||
"input_value": {"display_name": "pdf","info":"A pdf url","input_types":["Text"]},
|
|
||||||
}
|
|
||||||
|
|
||||||
def build(self, input_value: Text) -> Text:
|
|
||||||
return input_value
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# from langflow.field_typing import Data
|
|
||||||
from langflow.schema import Record
|
|
||||||
from langflow.interface.custom.custom_component import CustomComponent
|
|
||||||
|
|
||||||
|
|
||||||
class StringListOutput(CustomComponent):
|
|
||||||
display_name = "String List Output"
|
|
||||||
|
|
||||||
def build_config(self):
|
|
||||||
return {"input_value": {"display_name": "String List Output", "field_type": "str", "list": True}}
|
|
||||||
|
|
||||||
def build(self, input_value: list) -> Record:
|
|
||||||
return Record(data=input_value)
|
|
||||||
|
|
@ -445,9 +445,16 @@ class Graph:
|
||||||
vertex = self.get_vertex(vertex_id)
|
vertex = self.get_vertex(vertex_id)
|
||||||
vertex.set_state(state)
|
vertex.set_state(state)
|
||||||
|
|
||||||
def mark_branch(self, vertex_id: str, state: str):
|
def mark_branch(self, vertex_id: str, state: str, visited: Optional[set] = None):
|
||||||
"""Marks a branch of the graph."""
|
"""Marks a branch of the graph."""
|
||||||
|
if visited is None:
|
||||||
|
visited = set()
|
||||||
|
visited.add(vertex_id)
|
||||||
|
if vertex_id in visited:
|
||||||
|
return
|
||||||
|
|
||||||
self.mark_vertex(vertex_id, state)
|
self.mark_vertex(vertex_id, state)
|
||||||
|
|
||||||
for child_id in self.parent_child_map[vertex_id]:
|
for child_id in self.parent_child_map[vertex_id]:
|
||||||
self.mark_branch(child_id, state)
|
self.mark_branch(child_id, state)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ async def instantiate_custom_component(params, user_id, vertex):
|
||||||
# Call the build method directly if it's sync
|
# Call the build method directly if it's sync
|
||||||
build_result = custom_component.build(**params_copy)
|
build_result = custom_component.build(**params_copy)
|
||||||
custom_repr = custom_component.custom_repr()
|
custom_repr = custom_component.custom_repr()
|
||||||
if not custom_repr and isinstance(build_result, (dict, Record, str)):
|
if custom_repr is None and isinstance(build_result, (dict, Record, str)):
|
||||||
custom_repr = build_result
|
custom_repr = build_result
|
||||||
if not isinstance(custom_repr, str):
|
if not isinstance(custom_repr, str):
|
||||||
custom_repr = str(custom_repr)
|
custom_repr = str(custom_repr)
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ def get_id_from_search_string(search_string: str) -> Optional[str]:
|
||||||
Returns:
|
Returns:
|
||||||
Optional[str]: The extracted ID, or None if no ID is found.
|
Optional[str]: The extracted ID, or None if no ID is found.
|
||||||
"""
|
"""
|
||||||
possible_id = search_string
|
possible_id: Optional[str] = search_string
|
||||||
if "www.langflow.store/store/" in search_string:
|
if "www.langflow.store/store/" in search_string:
|
||||||
possible_id = search_string.split("/")[-1]
|
possible_id = search_string.split("/")[-1]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,24 @@
|
||||||
{
|
{
|
||||||
"extends": ["eslint:recommended", "plugin:node/recommended"],
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:prettier/recommended"
|
||||||
|
],
|
||||||
|
"plugins": ["react", "import-helpers", "prettier"],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 2018
|
"project": ["./tsconfig.node.json", "./tsconfig.json"],
|
||||||
|
"extraFileExtensions:": [".mdx"],
|
||||||
|
"extensions:": [".mdx"]
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-console": "warn",
|
"no-console": "warn",
|
||||||
|
|
@ -16,6 +33,7 @@
|
||||||
"no-redeclare": "error",
|
"no-redeclare": "error",
|
||||||
"no-empty": "error",
|
"no-empty": "error",
|
||||||
"no-await-in-loop": "error",
|
"no-await-in-loop": "error",
|
||||||
|
"react/react-in-jsx-scope": 0,
|
||||||
"node/exports-style": ["error", "module.exports"],
|
"node/exports-style": ["error", "module.exports"],
|
||||||
"node/file-extension-in-import": ["error", "always"],
|
"node/file-extension-in-import": ["error", "always"],
|
||||||
"node/prefer-global/buffer": ["error", "always"],
|
"node/prefer-global/buffer": ["error", "always"],
|
||||||
|
|
|
||||||
11
src/frontend/package-lock.json
generated
11
src/frontend/package-lock.json
generated
|
|
@ -99,6 +99,7 @@
|
||||||
"prettier-plugin-organize-imports": "^3.2.3",
|
"prettier-plugin-organize-imports": "^3.2.3",
|
||||||
"prettier-plugin-tailwindcss": "^0.3.0",
|
"prettier-plugin-tailwindcss": "^0.3.0",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
|
"simple-git-hooks": "^2.11.1",
|
||||||
"tailwindcss": "^3.3.3",
|
"tailwindcss": "^3.3.3",
|
||||||
"tailwindcss-dotted-background": "^1.1.0",
|
"tailwindcss-dotted-background": "^1.1.0",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
|
|
@ -11917,6 +11918,16 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/simple-git-hooks": {
|
||||||
|
"version": "2.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-git-hooks/-/simple-git-hooks-2.11.1.tgz",
|
||||||
|
"integrity": "sha512-tgqwPUMDcNDhuf1Xf6KTUsyeqGdgKMhzaH4PAZZuzguOgTl5uuyeYe/8mWgAr6IBxB5V06uqEf6Dy37gIWDtDg==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"simple-git-hooks": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sisteransi": {
|
"node_modules/sisteransi": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,9 @@
|
||||||
"format": "npx prettier --write \"./**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore",
|
"format": "npx prettier --write \"./**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore",
|
||||||
"type-check": "tsc --noEmit --pretty --project tsconfig.json && vite"
|
"type-check": "tsc --noEmit --pretty --project tsconfig.json && vite"
|
||||||
},
|
},
|
||||||
|
"simple-git-hooks": {
|
||||||
|
"pre-commit": "npx pretty-quick --staged"
|
||||||
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
"react-app",
|
"react-app",
|
||||||
|
|
@ -121,10 +124,11 @@
|
||||||
"prettier-plugin-organize-imports": "^3.2.3",
|
"prettier-plugin-organize-imports": "^3.2.3",
|
||||||
"prettier-plugin-tailwindcss": "^0.3.0",
|
"prettier-plugin-tailwindcss": "^0.3.0",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
|
"simple-git-hooks": "^2.11.1",
|
||||||
"tailwindcss": "^3.3.3",
|
"tailwindcss": "^3.3.3",
|
||||||
"tailwindcss-dotted-background": "^1.1.0",
|
"tailwindcss-dotted-background": "^1.1.0",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"ua-parser-js": "^1.0.37",
|
"ua-parser-js": "^1.0.37",
|
||||||
"vite": "^4.5.2"
|
"vite": "^4.5.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ import "./App.css";
|
||||||
import ErrorAlert from "./alerts/error";
|
import ErrorAlert from "./alerts/error";
|
||||||
import NoticeAlert from "./alerts/notice";
|
import NoticeAlert from "./alerts/notice";
|
||||||
import SuccessAlert from "./alerts/success";
|
import SuccessAlert from "./alerts/success";
|
||||||
import CrashErrorComponent from "./components/CrashErrorComponent";
|
import CrashErrorComponent from "./components/crashErrorComponent";
|
||||||
import FetchErrorComponent from "./components/fetchErrorComponent";
|
import FetchErrorComponent from "./components/fetchErrorComponent";
|
||||||
import LoadingComponent from "./components/loadingComponent";
|
import LoadingComponent from "./components/loadingComponent";
|
||||||
import {
|
import {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import useAlertStore from "../../stores/alertStore";
|
||||||
import { useGlobalVariablesStore } from "../../stores/globalVariables";
|
import { useGlobalVariablesStore } from "../../stores/globalVariables";
|
||||||
import { useTypesStore } from "../../stores/typesStore";
|
import { useTypesStore } from "../../stores/typesStore";
|
||||||
import { ResponseErrorDetailAPI } from "../../types/api";
|
import { ResponseErrorDetailAPI } from "../../types/api";
|
||||||
|
import { sortByName } from "../../utils/utils";
|
||||||
import ForwardedIconComponent from "../genericIconComponent";
|
import ForwardedIconComponent from "../genericIconComponent";
|
||||||
import InputComponent from "../inputComponent";
|
import InputComponent from "../inputComponent";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
|
@ -22,15 +23,20 @@ export default function AddNewVariableButton({ children }): JSX.Element {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
const componentFields = useTypesStore((state) => state.ComponentFields);
|
const componentFields = useTypesStore((state) => state.ComponentFields);
|
||||||
const unavaliableFields =new Set(Object.keys(useGlobalVariablesStore(
|
const unavaliableFields = new Set(
|
||||||
(state) => state.unavaliableFields
|
Object.keys(useGlobalVariablesStore((state) => state.unavaliableFields)),
|
||||||
)));
|
|
||||||
|
|
||||||
const availableFields = Array.from(componentFields).filter(
|
|
||||||
(field) => !unavaliableFields.has(field)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const availableFields = () => {
|
||||||
|
const fields = Array.from(componentFields).filter(
|
||||||
|
(field) => !unavaliableFields.has(field),
|
||||||
|
);
|
||||||
|
|
||||||
|
return sortByName(fields);
|
||||||
|
};
|
||||||
|
|
||||||
const addGlobalVariable = useGlobalVariablesStore(
|
const addGlobalVariable = useGlobalVariablesStore(
|
||||||
(state) => state.addGlobalVariable
|
(state) => state.addGlobalVariable,
|
||||||
);
|
);
|
||||||
|
|
||||||
function handleSaveVariable() {
|
function handleSaveVariable() {
|
||||||
|
|
@ -97,6 +103,7 @@ export default function AddNewVariableButton({ children }): JSX.Element {
|
||||||
password={false}
|
password={false}
|
||||||
options={["Generic", "Credential"]}
|
options={["Generic", "Credential"]}
|
||||||
placeholder="Choose a type for the variable..."
|
placeholder="Choose a type for the variable..."
|
||||||
|
id={"type-global-variables"}
|
||||||
></InputComponent>
|
></InputComponent>
|
||||||
<Label>Value</Label>
|
<Label>Value</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
|
|
@ -112,8 +119,9 @@ export default function AddNewVariableButton({ children }): JSX.Element {
|
||||||
setSelectedOptions={(value) => setFields(value)}
|
setSelectedOptions={(value) => setFields(value)}
|
||||||
selectedOptions={fields}
|
selectedOptions={fields}
|
||||||
password={false}
|
password={false}
|
||||||
options={availableFields}
|
options={availableFields()}
|
||||||
placeholder="Choose a field for the variable..."
|
placeholder="Choose a field for the variable..."
|
||||||
|
id={"apply-to-fields"}
|
||||||
></InputComponent>
|
></InputComponent>
|
||||||
</div>
|
</div>
|
||||||
</BaseModal.Content>
|
</BaseModal.Content>
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { getComponent, postLikeComponent } from "../../controllers/API";
|
import { getComponent, postLikeComponent } from "../../controllers/API";
|
||||||
import DeleteConfirmationModal from "../../modals/DeleteConfirmationModal";
|
|
||||||
import IOModal from "../../modals/IOModal";
|
import IOModal from "../../modals/IOModal";
|
||||||
|
import DeleteConfirmationModal from "../../modals/deleteConfirmationModal";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import useFlowStore from "../../stores/flowStore";
|
import useFlowStore from "../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
import { useStoreStore } from "../../stores/storeStore";
|
import { useStoreStore } from "../../stores/storeStore";
|
||||||
import { storeComponent } from "../../types/store";
|
import { storeComponent } from "../../types/store";
|
||||||
import cloneFLowWithParent from "../../utils/storeUtils";
|
import cloneFLowWithParent from "../../utils/storeUtils";
|
||||||
import { cn } from "../../utils/utils";
|
import { cn, convertTestName } from "../../utils/utils";
|
||||||
import ShadTooltip from "../ShadTooltipComponent";
|
|
||||||
import IconComponent from "../genericIconComponent";
|
import IconComponent from "../genericIconComponent";
|
||||||
import { Badge } from "../ui/badge";
|
import ShadTooltip from "../shadTooltipComponent";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -48,11 +47,11 @@ export default function CollectionCardComponent({
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [loadingLike, setLoadingLike] = useState(false);
|
const [loadingLike, setLoadingLike] = useState(false);
|
||||||
const [liked_by_user, setLiked_by_user] = useState(
|
const [liked_by_user, setLiked_by_user] = useState(
|
||||||
data?.liked_by_user ?? false
|
data?.liked_by_user ?? false,
|
||||||
);
|
);
|
||||||
const [likes_count, setLikes_count] = useState(data?.liked_by_count ?? 0);
|
const [likes_count, setLikes_count] = useState(data?.liked_by_count ?? 0);
|
||||||
const [downloads_count, setDownloads_count] = useState(
|
const [downloads_count, setDownloads_count] = useState(
|
||||||
data?.downloads_count ?? 0
|
data?.downloads_count ?? 0,
|
||||||
);
|
);
|
||||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||||
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
||||||
|
|
@ -61,8 +60,9 @@ export default function CollectionCardComponent({
|
||||||
const setNodes = useFlowStore((state) => state.setNodes);
|
const setNodes = useFlowStore((state) => state.setNodes);
|
||||||
const setEdges = useFlowStore((state) => state.setEdges);
|
const setEdges = useFlowStore((state) => state.setEdges);
|
||||||
const [openPlayground, setOpenPlayground] = useState(false);
|
const [openPlayground, setOpenPlayground] = useState(false);
|
||||||
|
const [openDelete, setOpenDelete] = useState(false);
|
||||||
const setCurrentFlowId = useFlowsManagerStore(
|
const setCurrentFlowId = useFlowsManagerStore(
|
||||||
(state) => state.setCurrentFlowId
|
(state) => state.setCurrentFlowId,
|
||||||
);
|
);
|
||||||
const [loadingPlayground, setLoadingPlayground] = useState(false);
|
const [loadingPlayground, setLoadingPlayground] = useState(false);
|
||||||
|
|
||||||
|
|
@ -82,8 +82,8 @@ export default function CollectionCardComponent({
|
||||||
} else {
|
} else {
|
||||||
setNodes([], true);
|
setNodes([], true);
|
||||||
setEdges([], true);
|
setEdges([], true);
|
||||||
cleanFlowPool();
|
|
||||||
}
|
}
|
||||||
|
cleanFlowPool();
|
||||||
}
|
}
|
||||||
}, [openPlayground]);
|
}, [openPlayground]);
|
||||||
|
|
||||||
|
|
@ -168,10 +168,12 @@ export default function CollectionCardComponent({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card
|
<Card
|
||||||
|
data-testid={`card-${convertTestName(data.name)}`}
|
||||||
|
//TODO check color schema
|
||||||
className={cn(
|
className={cn(
|
||||||
"group relative flex min-h-[11rem] flex-col justify-between overflow-hidden transition-all hover:shadow-md",
|
"group relative flex min-h-[11rem] flex-col justify-between overflow-hidden transition-all hover:bg-muted/50 hover:shadow-md hover:dark:bg-[#ffffff10]",
|
||||||
disabled ? "pointer-events-none opacity-50" : "",
|
disabled ? "pointer-events-none opacity-50" : "",
|
||||||
onClick ? "cursor-pointer" : ""
|
onClick ? "cursor-pointer" : "",
|
||||||
)}
|
)}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
|
|
@ -184,7 +186,7 @@ export default function CollectionCardComponent({
|
||||||
"flex-shrink-0",
|
"flex-shrink-0",
|
||||||
data.is_component
|
data.is_component
|
||||||
? "mx-0.5 h-6 w-6 text-component-icon"
|
? "mx-0.5 h-6 w-6 text-component-icon"
|
||||||
: "h-7 w-7 flex-shrink-0 text-flow-icon"
|
: "h-7 w-7 flex-shrink-0 text-flow-icon",
|
||||||
)}
|
)}
|
||||||
name={data.is_component ? "ToyBrick" : "Group"}
|
name={data.is_component ? "ToyBrick" : "Group"}
|
||||||
/>
|
/>
|
||||||
|
|
@ -236,16 +238,18 @@ export default function CollectionCardComponent({
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{onDelete && data?.metadata === undefined && (
|
{onDelete && data?.metadata === undefined && (
|
||||||
<DeleteConfirmationModal
|
<button
|
||||||
onConfirm={() => {
|
className="z-50"
|
||||||
onDelete();
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setOpenDelete(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
name="Trash2"
|
name="Trash2"
|
||||||
className="h-5 w-5 text-primary opacity-0 transition-all hover:text-destructive group-hover:opacity-100"
|
className="h-5 w-5 text-primary opacity-0 transition-all hover:text-destructive group-hover:opacity-100"
|
||||||
/>
|
/>
|
||||||
</DeleteConfirmationModal>
|
</button>
|
||||||
)}
|
)}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -266,7 +270,7 @@ export default function CollectionCardComponent({
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<div className="flex w-full flex-1 flex-wrap gap-2">
|
<div className="flex w-full flex-1 flex-wrap gap-2">
|
||||||
{data.tags &&
|
{/* {data.tags &&
|
||||||
data.tags.length > 0 &&
|
data.tags.length > 0 &&
|
||||||
data.tags.map((tag, index) => (
|
data.tags.map((tag, index) => (
|
||||||
<Badge
|
<Badge
|
||||||
|
|
@ -277,7 +281,7 @@ export default function CollectionCardComponent({
|
||||||
>
|
>
|
||||||
{tag.name}
|
{tag.name}
|
||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))} */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -288,8 +292,8 @@ export default function CollectionCardComponent({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CardFooter>
|
<CardFooter>
|
||||||
<div className="flex w-full items-center justify-between gap-2">
|
<div className="z-50 flex w-full items-center justify-between gap-2">
|
||||||
<div className="flex w-full flex-wrap items-end justify-between gap-2">
|
<div className="flex w-full flex-wrap items-end justify-end gap-2">
|
||||||
{playground && data?.metadata !== undefined ? (
|
{playground && data?.metadata !== undefined ? (
|
||||||
<Button
|
<Button
|
||||||
disabled={loadingPlayground}
|
disabled={loadingPlayground}
|
||||||
|
|
@ -297,7 +301,7 @@ export default function CollectionCardComponent({
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="gap-2 whitespace-nowrap"
|
className="z-50 gap-2 whitespace-nowrap"
|
||||||
data-testid={"playground-flow-button-" + data.id}
|
data-testid={"playground-flow-button-" + data.id}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
@ -326,9 +330,7 @@ export default function CollectionCardComponent({
|
||||||
)}
|
)}
|
||||||
Playground
|
Playground
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : undefined}
|
||||||
<div></div>
|
|
||||||
)}
|
|
||||||
{data.liked_by_count != undefined && (
|
{data.liked_by_count != undefined && (
|
||||||
<div className="flex gap-0.5">
|
<div className="flex gap-0.5">
|
||||||
{onDelete && data?.metadata !== undefined ? (
|
{onDelete && data?.metadata !== undefined ? (
|
||||||
|
|
@ -351,10 +353,11 @@ export default function CollectionCardComponent({
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
|
data-testid={`delete-${convertTestName(data.name)}`}
|
||||||
name="Trash2"
|
name="Trash2"
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-5 w-5",
|
"h-5 w-5",
|
||||||
!authorized ? " text-ring" : ""
|
!authorized ? " text-ring" : "",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -389,7 +392,7 @@ export default function CollectionCardComponent({
|
||||||
liked_by_user
|
liked_by_user
|
||||||
? "fill-destructive stroke-destructive"
|
? "fill-destructive stroke-destructive"
|
||||||
: "",
|
: "",
|
||||||
!authorized ? " text-ring" : ""
|
!authorized ? " text-ring" : "",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -427,22 +430,21 @@ export default function CollectionCardComponent({
|
||||||
}
|
}
|
||||||
className={cn(
|
className={cn(
|
||||||
loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
|
loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
|
||||||
!authorized ? " text-ring" : ""
|
!authorized ? " text-ring" : "",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{button && button}
|
|
||||||
{playground && data?.metadata === undefined && (
|
{playground && data?.metadata === undefined && (
|
||||||
<Button
|
<Button
|
||||||
disabled={loadingPlayground}
|
disabled={loadingPlayground}
|
||||||
key={data.id}
|
key={data.id}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
variant="outline"
|
variant="primary"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="gap-2 whitespace-nowrap"
|
className="gap-2 whitespace-nowrap bg-muted"
|
||||||
data-testid={"playground-flow-button-" + data.id}
|
data-testid={"playground-flow-button-" + data.id}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
@ -485,6 +487,17 @@ export default function CollectionCardComponent({
|
||||||
<></>
|
<></>
|
||||||
</IOModal>
|
</IOModal>
|
||||||
)}
|
)}
|
||||||
|
{openDelete && (
|
||||||
|
<DeleteConfirmationModal
|
||||||
|
open={openDelete}
|
||||||
|
setOpen={setOpenDelete}
|
||||||
|
onConfirm={() => {
|
||||||
|
if (onDelete) onDelete();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<></>
|
||||||
|
</DeleteConfirmationModal>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Transition } from "@headlessui/react";
|
import { Transition } from "@headlessui/react";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import ApiModal from "../../modals/ApiModal";
|
|
||||||
import IOModal from "../../modals/IOModal";
|
import IOModal from "../../modals/IOModal";
|
||||||
|
import ApiModal from "../../modals/apiModal";
|
||||||
import ShareModal from "../../modals/shareModal";
|
import ShareModal from "../../modals/shareModal";
|
||||||
import useFlowStore from "../../stores/flowStore";
|
import useFlowStore from "../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
|
|
@ -50,7 +50,7 @@ export default function FlowToolbar(): JSX.Element {
|
||||||
"relative inline-flex h-full w-full items-center justify-center gap-[4px] bg-muted px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-background hover:bg-hover ",
|
"relative inline-flex h-full w-full items-center justify-center gap-[4px] bg-muted px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-background hover:bg-hover ",
|
||||||
!hasApiKey || !validApiKey || !hasStore
|
!hasApiKey || !validApiKey || !hasStore
|
||||||
? " button-disable text-muted-foreground "
|
? " button-disable text-muted-foreground "
|
||||||
: ""
|
: "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ForwardedIconComponent
|
<ForwardedIconComponent
|
||||||
|
|
@ -59,14 +59,14 @@ export default function FlowToolbar(): JSX.Element {
|
||||||
"-m-0.5 -ml-1 h-6 w-6",
|
"-m-0.5 -ml-1 h-6 w-6",
|
||||||
!hasApiKey || !validApiKey || !hasStore
|
!hasApiKey || !validApiKey || !hasStore
|
||||||
? "extra-side-bar-save-disable"
|
? "extra-side-bar-save-disable"
|
||||||
: ""
|
: "",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
Share
|
Share
|
||||||
</button>
|
</button>
|
||||||
</ShareModal>
|
</ShareModal>
|
||||||
),
|
),
|
||||||
[hasApiKey, validApiKey, currentFlow, hasStore]
|
[hasApiKey, validApiKey, currentFlow, hasStore],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -103,12 +103,10 @@ export default function FlowToolbar(): JSX.Element {
|
||||||
className={`relative inline-flex w-full cursor-not-allowed items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-muted-foreground transition-all duration-150 ease-in-out ease-in-out`}
|
className={`relative inline-flex w-full cursor-not-allowed items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-muted-foreground transition-all duration-150 ease-in-out ease-in-out`}
|
||||||
>
|
>
|
||||||
<ForwardedIconComponent
|
<ForwardedIconComponent
|
||||||
name="Zap"
|
name="BotMessageSquareIcon"
|
||||||
className={
|
className={" h-5 w-5 transition-all"}
|
||||||
"message-button-icon h-5 w-5 fill-muted-foreground stroke-muted-foreground transition-all"
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
Run
|
Playground
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -120,7 +118,7 @@ export default function FlowToolbar(): JSX.Element {
|
||||||
<ApiModal flow={currentFlow}>
|
<ApiModal flow={currentFlow}>
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover"
|
"relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ForwardedIconComponent
|
<ForwardedIconComponent
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import { cloneDeep } from "lodash";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||||
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
|
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
|
||||||
import AccordionComponent from "../../components/AccordionComponent";
|
|
||||||
import CodeAreaComponent from "../../components/codeAreaComponent";
|
import CodeAreaComponent from "../../components/codeAreaComponent";
|
||||||
import Dropdown from "../../components/dropdownComponent";
|
import Dropdown from "../../components/dropdownComponent";
|
||||||
import FloatComponent from "../../components/floatComponent";
|
import FloatComponent from "../../components/floatComponent";
|
||||||
|
|
@ -36,11 +35,12 @@ import {
|
||||||
hasDuplicateKeys,
|
hasDuplicateKeys,
|
||||||
} from "../../utils/reactflowUtils";
|
} from "../../utils/reactflowUtils";
|
||||||
import { classNames } from "../../utils/utils";
|
import { classNames } from "../../utils/utils";
|
||||||
import ShadTooltip from "../ShadTooltipComponent";
|
import AccordionComponent from "../accordionComponent";
|
||||||
import DictComponent from "../dictComponent";
|
import DictComponent from "../dictComponent";
|
||||||
import IconComponent from "../genericIconComponent";
|
import IconComponent from "../genericIconComponent";
|
||||||
import KeypairListComponent from "../keypairListComponent";
|
|
||||||
import InputComponent from "../inputComponent";
|
import InputComponent from "../inputComponent";
|
||||||
|
import KeypairListComponent from "../keypairListComponent";
|
||||||
|
import ShadTooltip from "../shadTooltipComponent";
|
||||||
|
|
||||||
export default function CodeTabsComponent({
|
export default function CodeTabsComponent({
|
||||||
flow,
|
flow,
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ function CsvOutputComponent({
|
||||||
if (file) {
|
if (file) {
|
||||||
const { rowData: data, colDefs: columns } = convertCSVToData(
|
const { rowData: data, colDefs: columns } = convertCSVToData(
|
||||||
file,
|
file,
|
||||||
separator
|
separator,
|
||||||
);
|
);
|
||||||
setRowData(data);
|
setRowData(data);
|
||||||
setColDefs(columns);
|
setColDefs(columns);
|
||||||
|
|
@ -114,14 +114,14 @@ function CsvOutputComponent({
|
||||||
(params: any) => {
|
(params: any) => {
|
||||||
updateRowHeight(params);
|
updateRowHeight(params);
|
||||||
},
|
},
|
||||||
[updateRowHeight]
|
[updateRowHeight],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onGridSizeChanged = useCallback(
|
const onGridSizeChanged = useCallback(
|
||||||
(params: any) => {
|
(params: any) => {
|
||||||
updateRowHeight(params);
|
updateRowHeight(params);
|
||||||
},
|
},
|
||||||
[updateRowHeight]
|
[updateRowHeight],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -167,6 +167,7 @@ function CsvOutputComponent({
|
||||||
onFirstDataRendered={onFirstDataRendered}
|
onFirstDataRendered={onFirstDataRendered}
|
||||||
onGridSizeChanged={onGridSizeChanged}
|
onGridSizeChanged={onGridSizeChanged}
|
||||||
scrollbarWidth={8}
|
scrollbarWidth={8}
|
||||||
|
overlayNoRowsTemplate="No data available"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
import { FlowType } from "../../types/flow";
|
import { FlowType } from "../../types/flow";
|
||||||
import { updateIds } from "../../utils/reactflowUtils";
|
import { updateIds } from "../../utils/reactflowUtils";
|
||||||
import { cn } from "../../utils/utils";
|
import { cn } from "../../utils/utils";
|
||||||
import ShadTooltip from "../ShadTooltipComponent";
|
|
||||||
import IconComponent from "../genericIconComponent";
|
import IconComponent from "../genericIconComponent";
|
||||||
|
import ShadTooltip from "../shadTooltipComponent";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ import useAlertStore from "../../../../stores/alertStore";
|
||||||
import useFlowStore from "../../../../stores/flowStore";
|
import useFlowStore from "../../../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||||
import { cn } from "../../../../utils/utils";
|
import { cn } from "../../../../utils/utils";
|
||||||
import ShadTooltip from "../../../ShadTooltipComponent";
|
|
||||||
import IconComponent from "../../../genericIconComponent";
|
import IconComponent from "../../../genericIconComponent";
|
||||||
|
import ShadTooltip from "../../../shadTooltipComponent";
|
||||||
import { Button } from "../../../ui/button";
|
import { Button } from "../../../ui/button";
|
||||||
|
|
||||||
export const MenuBar = ({
|
export const MenuBar = ({
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,7 @@ export default function Header(): JSX.Element {
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<button
|
<button
|
||||||
|
data-testid="user-profile-settings"
|
||||||
className={
|
className={
|
||||||
"h-7 w-7 rounded-full focus-visible:outline-0 " +
|
"h-7 w-7 rounded-full focus-visible:outline-0 " +
|
||||||
(userData?.profile_image ??
|
(userData?.profile_image ??
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,7 @@ export default function InputComponent({
|
||||||
</PopoverContentWithoutPortal>
|
</PopoverContentWithoutPortal>
|
||||||
</Popover>
|
</Popover>
|
||||||
<div
|
<div
|
||||||
|
data-testid={"popover-anchor-" + id}
|
||||||
className={cn(
|
className={cn(
|
||||||
"pointer-events-auto absolute inset-y-0 h-full w-full cursor-pointer",
|
"pointer-events-auto absolute inset-y-0 h-full w-full cursor-pointer",
|
||||||
((selectedOption !== "" || !onChange) && setSelectedOption) ||
|
((selectedOption !== "" || !onChange) && setSelectedOption) ||
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { deleteGlobalVariable } from "../../controllers/API";
|
import { deleteGlobalVariable } from "../../controllers/API";
|
||||||
import DeleteConfirmationModal from "../../modals/DeleteConfirmationModal";
|
import DeleteConfirmationModal from "../../modals/deleteConfirmationModal";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import { useGlobalVariablesStore } from "../../stores/globalVariables";
|
import { useGlobalVariablesStore } from "../../stores/globalVariables";
|
||||||
import { InputGlobalComponentType } from "../../types/components";
|
import { InputGlobalComponentType } from "../../types/components";
|
||||||
|
|
@ -49,7 +49,10 @@ export default function InputGlobalComponent({
|
||||||
!data.node?.template[name].value &&
|
!data.node?.template[name].value &&
|
||||||
data.node?.template[name].display_name
|
data.node?.template[name].display_name
|
||||||
) {
|
) {
|
||||||
if (unavaliableFields[data.node?.template[name].display_name!] && !disabled) {
|
if (
|
||||||
|
unavaliableFields[data.node?.template[name].display_name!] &&
|
||||||
|
!disabled
|
||||||
|
) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setDb(true);
|
setDb(true);
|
||||||
onChange(unavaliableFields[data.node?.template[name].display_name!]);
|
onChange(unavaliableFields[data.node?.template[name].display_name!]);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react";
|
||||||
import { useDarkStore } from "../../stores/darkStore";
|
import { useDarkStore } from "../../stores/darkStore";
|
||||||
import "../../style/ag-theme-shadcn.css"; // Custom CSS applied to the grid
|
import "../../style/ag-theme-shadcn.css"; // Custom CSS applied to the grid
|
||||||
import { cn } from "../../utils/utils";
|
import { cn } from "../../utils/utils";
|
||||||
|
import { Card, CardContent } from "../ui/card";
|
||||||
|
|
||||||
const TableComponent = forwardRef<
|
const TableComponent = forwardRef<
|
||||||
ElementRef<typeof AgGridReact>,
|
ElementRef<typeof AgGridReact>,
|
||||||
|
|
@ -17,10 +18,18 @@ const TableComponent = forwardRef<
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
dark ? "ag-theme-quartz-dark" : "ag-theme-quartz",
|
dark ? "ag-theme-quartz-dark" : "ag-theme-quartz",
|
||||||
"ag-theme-shadcn flex h-full flex-col"
|
"ag-theme-shadcn flex h-full flex-col",
|
||||||
)} // applying the grid theme
|
)} // applying the grid theme
|
||||||
>
|
>
|
||||||
<AgGridReact ref={ref} {...props} />
|
<Card x-chunk="dashboard-04-chunk-2" className="pt-4">
|
||||||
|
<CardContent>
|
||||||
|
<AgGridReact
|
||||||
|
overlayNoRowsTemplate="No data available"
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import React, { ReactNode, useEffect, useRef, useState } from "react";
|
import React, { ReactNode, useEffect, useRef, useState } from "react";
|
||||||
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
||||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
|
||||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||||
import DictComponent from "../../../../components/dictComponent";
|
import DictComponent from "../../../../components/dictComponent";
|
||||||
import Dropdown from "../../../../components/dropdownComponent";
|
import Dropdown from "../../../../components/dropdownComponent";
|
||||||
|
|
@ -13,6 +12,7 @@ import InputListComponent from "../../../../components/inputListComponent";
|
||||||
import IntComponent from "../../../../components/intComponent";
|
import IntComponent from "../../../../components/intComponent";
|
||||||
import KeypairListComponent from "../../../../components/keypairListComponent";
|
import KeypairListComponent from "../../../../components/keypairListComponent";
|
||||||
import PromptAreaComponent from "../../../../components/promptComponent";
|
import PromptAreaComponent from "../../../../components/promptComponent";
|
||||||
|
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
||||||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||||
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
||||||
import { Button } from "../../../../components/ui/button";
|
import { Button } from "../../../../components/ui/button";
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
|
import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import InputComponent from "../../components/inputComponent";
|
import InputComponent from "../../components/inputComponent";
|
||||||
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import Checkmark from "../../components/ui/checkmark";
|
import Checkmark from "../../components/ui/checkmark";
|
||||||
import Loading from "../../components/ui/loading";
|
import Loading from "../../components/ui/loading";
|
||||||
|
|
@ -6,9 +6,9 @@ import remarkGfm from "remark-gfm";
|
||||||
import remarkMath from "remark-math";
|
import remarkMath from "remark-math";
|
||||||
import MaleTechnology from "../../../../../assets/male-technologist.png";
|
import MaleTechnology from "../../../../../assets/male-technologist.png";
|
||||||
import Robot from "../../../../../assets/robot.png";
|
import Robot from "../../../../../assets/robot.png";
|
||||||
import SanitizedHTMLWrapper from "../../../../../components/SanitizedHTMLWrapper";
|
|
||||||
import CodeTabsComponent from "../../../../../components/codeTabsComponent";
|
import CodeTabsComponent from "../../../../../components/codeTabsComponent";
|
||||||
import IconComponent from "../../../../../components/genericIconComponent";
|
import IconComponent from "../../../../../components/genericIconComponent";
|
||||||
|
import SanitizedHTMLWrapper from "../../../../../components/sanitizedHTMLWrapper";
|
||||||
import useAlertStore from "../../../../../stores/alertStore";
|
import useAlertStore from "../../../../../stores/alertStore";
|
||||||
import useFlowStore from "../../../../../stores/flowStore";
|
import useFlowStore from "../../../../../stores/flowStore";
|
||||||
import { chatMessagePropsType } from "../../../../../types/components";
|
import { chatMessagePropsType } from "../../../../../types/components";
|
||||||
|
|
@ -271,7 +271,7 @@ dark:prose-invert"
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div className="form-modal-chat-text-position min-w-96 flex-grow">
|
||||||
{template ? (
|
{template ? (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
|
|
@ -324,6 +324,7 @@ dark:prose-invert"
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<span
|
<span
|
||||||
|
className="prose text-primary word-break-break-word dark:prose-invert"
|
||||||
data-testid={
|
data-testid={
|
||||||
"chat-message-" + chat.sender_name + "-" + chatMessage
|
"chat-message-" + chat.sender_name + "-" + chatMessage
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import AccordionComponent from "../../components/AccordionComponent";
|
import AccordionComponent from "../../components/accordionComponent";
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import { Badge } from "../../components/ui/badge";
|
import { Badge } from "../../components/ui/badge";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import {
|
import {
|
||||||
|
|
@ -34,25 +34,25 @@ export default function IOModal({
|
||||||
}: IOModalPropsType): JSX.Element {
|
}: IOModalPropsType): JSX.Element {
|
||||||
const allNodes = useFlowStore((state) => state.nodes);
|
const allNodes = useFlowStore((state) => state.nodes);
|
||||||
const inputs = useFlowStore((state) => state.inputs).filter(
|
const inputs = useFlowStore((state) => state.inputs).filter(
|
||||||
(input) => input.type !== "ChatInput"
|
(input) => input.type !== "ChatInput",
|
||||||
);
|
);
|
||||||
const chatInput = useFlowStore((state) => state.inputs).find(
|
const chatInput = useFlowStore((state) => state.inputs).find(
|
||||||
(input) => input.type === "ChatInput"
|
(input) => input.type === "ChatInput",
|
||||||
);
|
);
|
||||||
const outputs = useFlowStore((state) => state.outputs).filter(
|
const outputs = useFlowStore((state) => state.outputs).filter(
|
||||||
(output) => output.type !== "ChatOutput"
|
(output) => output.type !== "ChatOutput",
|
||||||
);
|
);
|
||||||
const chatOutput = useFlowStore((state) => state.outputs).find(
|
const chatOutput = useFlowStore((state) => state.outputs).find(
|
||||||
(output) => output.type === "ChatOutput"
|
(output) => output.type === "ChatOutput",
|
||||||
);
|
);
|
||||||
const nodes = useFlowStore((state) => state.nodes).filter(
|
const nodes = useFlowStore((state) => state.nodes).filter(
|
||||||
(node) =>
|
(node) =>
|
||||||
inputs.some((input) => input.id === node.id) ||
|
inputs.some((input) => input.id === node.id) ||
|
||||||
outputs.some((output) => output.id === node.id)
|
outputs.some((output) => output.id === node.id),
|
||||||
);
|
);
|
||||||
const haveChat = chatInput || chatOutput;
|
const haveChat = chatInput || chatOutput;
|
||||||
const [selectedTab, setSelectedTab] = useState(
|
const [selectedTab, setSelectedTab] = useState(
|
||||||
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0
|
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
function startView() {
|
function startView() {
|
||||||
|
|
@ -117,7 +117,7 @@ export default function IOModal({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseModal
|
<BaseModal
|
||||||
size={selectedTab === 0 ? "large-thin" : "large"}
|
size={selectedTab === 0 ? "sm-thin" : "md-thin"}
|
||||||
open={open}
|
open={open}
|
||||||
setOpen={setOpen}
|
setOpen={setOpen}
|
||||||
disable={disable}
|
disable={disable}
|
||||||
|
|
@ -140,7 +140,7 @@ export default function IOModal({
|
||||||
{selectedTab !== 0 && (
|
{selectedTab !== 0 && (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start transition-all duration-300"
|
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start transition-all duration-300",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|
@ -173,11 +173,11 @@ export default function IOModal({
|
||||||
</div>
|
</div>
|
||||||
{nodes
|
{nodes
|
||||||
.filter((node) =>
|
.filter((node) =>
|
||||||
inputs.some((input) => input.id === node.id)
|
inputs.some((input) => input.id === node.id),
|
||||||
)
|
)
|
||||||
.map((node, index) => {
|
.map((node, index) => {
|
||||||
const input = inputs.find(
|
const input = inputs.find(
|
||||||
(input) => input.id === node.id
|
(input) => input.id === node.id,
|
||||||
)!;
|
)!;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
@ -241,11 +241,11 @@ export default function IOModal({
|
||||||
</div>
|
</div>
|
||||||
{nodes
|
{nodes
|
||||||
.filter((node) =>
|
.filter((node) =>
|
||||||
outputs.some((output) => output.id === node.id)
|
outputs.some((output) => output.id === node.id),
|
||||||
)
|
)
|
||||||
.map((node, index) => {
|
.map((node, index) => {
|
||||||
const output = outputs.find(
|
const output = outputs.find(
|
||||||
(output) => output.id === node.id
|
(output) => output.id === node.id,
|
||||||
)!;
|
)!;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
@ -308,7 +308,7 @@ export default function IOModal({
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full w-full flex-col items-start gap-4 pt-4",
|
"flex h-full w-full flex-col items-start gap-4 pt-4",
|
||||||
!selectedViewField ? "hidden" : ""
|
!selectedViewField ? "hidden" : "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="font-xl flex items-center justify-center gap-3 font-semibold">
|
<div className="font-xl flex items-center justify-center gap-3 font-semibold">
|
||||||
|
|
@ -327,7 +327,7 @@ export default function IOModal({
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full w-full">
|
<div className="h-full w-full">
|
||||||
{inputs.some(
|
{inputs.some(
|
||||||
(input) => input.id === selectedViewField.id
|
(input) => input.id === selectedViewField.id,
|
||||||
) ? (
|
) ? (
|
||||||
<IOFieldView
|
<IOFieldView
|
||||||
type={InputOutput.INPUT}
|
type={InputOutput.INPUT}
|
||||||
|
|
@ -349,7 +349,7 @@ export default function IOModal({
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full w-full",
|
"flex h-full w-full",
|
||||||
selectedViewField ? "hidden" : ""
|
selectedViewField ? "hidden" : "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{haveChat ? (
|
{haveChat ? (
|
||||||
|
|
@ -384,7 +384,7 @@ export default function IOModal({
|
||||||
"h-4 w-4",
|
"h-4 w-4",
|
||||||
isBuilding
|
isBuilding
|
||||||
? "animate-spin"
|
? "animate-spin"
|
||||||
: "fill-current text-medium-indigo"
|
: "fill-current text-medium-indigo",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
Run Flow
|
Run Flow
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ interface BaseModalProps {
|
||||||
React.ReactElement<ContentProps>,
|
React.ReactElement<ContentProps>,
|
||||||
React.ReactElement<HeaderProps>,
|
React.ReactElement<HeaderProps>,
|
||||||
React.ReactElement<TriggerProps>?,
|
React.ReactElement<TriggerProps>?,
|
||||||
React.ReactElement<FooterProps>?
|
React.ReactElement<FooterProps>?,
|
||||||
];
|
];
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
setOpen?: (open: boolean) => void;
|
setOpen?: (open: boolean) => void;
|
||||||
|
|
@ -78,6 +78,8 @@ interface BaseModalProps {
|
||||||
| "large-h-full"
|
| "large-h-full"
|
||||||
| "small-h-full"
|
| "small-h-full"
|
||||||
| "medium-h-full"
|
| "medium-h-full"
|
||||||
|
| "md-thin"
|
||||||
|
| "sm-thin"
|
||||||
| "smaller-h-full";
|
| "smaller-h-full";
|
||||||
|
|
||||||
disable?: boolean;
|
disable?: boolean;
|
||||||
|
|
@ -93,16 +95,16 @@ function BaseModal({
|
||||||
type = "dialog",
|
type = "dialog",
|
||||||
}: BaseModalProps) {
|
}: BaseModalProps) {
|
||||||
const headerChild = React.Children.toArray(children).find(
|
const headerChild = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Header
|
(child) => (child as React.ReactElement).type === Header,
|
||||||
);
|
);
|
||||||
const triggerChild = React.Children.toArray(children).find(
|
const triggerChild = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Trigger
|
(child) => (child as React.ReactElement).type === Trigger,
|
||||||
);
|
);
|
||||||
const ContentChild = React.Children.toArray(children).find(
|
const ContentChild = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Content
|
(child) => (child as React.ReactElement).type === Content,
|
||||||
);
|
);
|
||||||
const ContentFooter = React.Children.toArray(children).find(
|
const ContentFooter = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Footer
|
(child) => (child as React.ReactElement).type === Footer,
|
||||||
);
|
);
|
||||||
|
|
||||||
let minWidth: string;
|
let minWidth: string;
|
||||||
|
|
@ -147,6 +149,17 @@ function BaseModal({
|
||||||
minWidth = "min-w-[65vw]";
|
minWidth = "min-w-[65vw]";
|
||||||
height = "h-[80vh]";
|
height = "h-[80vh]";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "md-thin":
|
||||||
|
minWidth = "min-w-[85vw]";
|
||||||
|
height = "h-[70vh]";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "sm-thin":
|
||||||
|
minWidth = "min-w-[65vw]";
|
||||||
|
height = "h-[70vh]";
|
||||||
|
break;
|
||||||
|
|
||||||
case "large-h-full":
|
case "large-h-full":
|
||||||
minWidth = "min-w-[80vw]";
|
minWidth = "min-w-[80vw]";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import {
|
import {
|
||||||
ConfirmationModalType,
|
ConfirmationModalType,
|
||||||
|
|
@ -15,14 +15,18 @@ export default function DeleteConfirmationModal({
|
||||||
onConfirm,
|
onConfirm,
|
||||||
description,
|
description,
|
||||||
asChild,
|
asChild,
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
}: {
|
}: {
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
onConfirm: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
onConfirm: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
||||||
description?: string;
|
description?: string;
|
||||||
asChild?: boolean;
|
asChild?: boolean;
|
||||||
|
open?: boolean;
|
||||||
|
setOpen?: (open: boolean) => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Dialog>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogTrigger asChild={asChild} tabIndex={-1}>
|
<DialogTrigger asChild={asChild} tabIndex={-1}>
|
||||||
{children}
|
{children}
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import { forwardRef, useEffect, useState } from "react";
|
import { forwardRef, useEffect, useState } from "react";
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
|
||||||
import CodeAreaComponent from "../../components/codeAreaComponent";
|
import CodeAreaComponent from "../../components/codeAreaComponent";
|
||||||
import DictComponent from "../../components/dictComponent";
|
import DictComponent from "../../components/dictComponent";
|
||||||
import Dropdown from "../../components/dropdownComponent";
|
import Dropdown from "../../components/dropdownComponent";
|
||||||
|
|
@ -12,6 +11,7 @@ import InputListComponent from "../../components/inputListComponent";
|
||||||
import IntComponent from "../../components/intComponent";
|
import IntComponent from "../../components/intComponent";
|
||||||
import KeypairListComponent from "../../components/keypairListComponent";
|
import KeypairListComponent from "../../components/keypairListComponent";
|
||||||
import PromptAreaComponent from "../../components/promptComponent";
|
import PromptAreaComponent from "../../components/promptComponent";
|
||||||
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import TextAreaComponent from "../../components/textAreaComponent";
|
import TextAreaComponent from "../../components/textAreaComponent";
|
||||||
import ToggleShadComponent from "../../components/toggleShadComponent";
|
import ToggleShadComponent from "../../components/toggleShadComponent";
|
||||||
import { Badge } from "../../components/ui/badge";
|
import { Badge } from "../../components/ui/badge";
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { ReactNode, forwardRef, useEffect, useState } from "react";
|
import { ReactNode, forwardRef, useEffect, useState } from "react";
|
||||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
import EditFlowSettings from "../../components/editFlowSettingsComponent";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { Checkbox } from "../../components/ui/checkbox";
|
import { Checkbox } from "../../components/ui/checkbox";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
import EditFlowSettings from "../../components/editFlowSettingsComponent";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { SETTINGS_DIALOG_SUBTITLE } from "../../constants/constants";
|
import { SETTINGS_DIALOG_SUBTITLE } from "../../constants/constants";
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import SanitizedHTMLWrapper from "../../components/SanitizedHTMLWrapper";
|
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
|
import SanitizedHTMLWrapper from "../../components/sanitizedHTMLWrapper";
|
||||||
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import { Badge } from "../../components/ui/badge";
|
import { Badge } from "../../components/ui/badge";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { Textarea } from "../../components/ui/textarea";
|
import { Textarea } from "../../components/ui/textarea";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { ReactNode, useEffect, useMemo, useState } from "react";
|
import { ReactNode, useEffect, useMemo, useState } from "react";
|
||||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
import EditFlowSettings from "../../components/editFlowSettingsComponent";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import { TagsSelector } from "../../components/tagsSelectorComponent";
|
import { TagsSelector } from "../../components/tagsSelectorComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
|
|
@ -23,8 +23,8 @@ import {
|
||||||
removeGlobalVariableFromComponents,
|
removeGlobalVariableFromComponents,
|
||||||
} from "../../utils/reactflowUtils";
|
} from "../../utils/reactflowUtils";
|
||||||
import { getTagsIds } from "../../utils/storeUtils";
|
import { getTagsIds } from "../../utils/storeUtils";
|
||||||
import ConfirmationModal from "../ConfirmationModal";
|
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
|
import ConfirmationModal from "../confirmationModal";
|
||||||
import ExportModal from "../exportModal";
|
import ExportModal from "../exportModal";
|
||||||
|
|
||||||
export default function ShareModal({
|
export default function ShareModal({
|
||||||
|
|
@ -207,8 +207,9 @@ export default function ShareModal({
|
||||||
{children ? children : <></>}
|
{children ? children : <></>}
|
||||||
</BaseModal.Trigger>
|
</BaseModal.Trigger>
|
||||||
<BaseModal.Header
|
<BaseModal.Header
|
||||||
description={`Publish ${is_component ? "your component" : "workflow"
|
description={`Publish ${
|
||||||
} to the Langflow Store.`}
|
is_component ? "your component" : "workflow"
|
||||||
|
} to the Langflow Store.`}
|
||||||
>
|
>
|
||||||
<span className="pr-2">Share</span>
|
<span className="pr-2">Share</span>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
|
|
@ -251,34 +252,35 @@ export default function ShareModal({
|
||||||
|
|
||||||
<BaseModal.Footer>
|
<BaseModal.Footer>
|
||||||
<div className="flex w-full justify-between gap-2">
|
<div className="flex w-full justify-between gap-2">
|
||||||
{!is_component && <ExportModal>
|
{!is_component && (
|
||||||
|
<ExportModal>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
className="gap-2"
|
||||||
|
onClick={() => {
|
||||||
|
// (setOpen || internalSetOpen)(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconComponent name="Download" className="h-4 w-4" />
|
||||||
|
Export
|
||||||
|
</Button>
|
||||||
|
</ExportModal>
|
||||||
|
)}
|
||||||
|
{is_component && (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="gap-2"
|
className="gap-2"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// (setOpen || internalSetOpen)(false);
|
(setOpen || internalSetOpen)(false);
|
||||||
|
handleExportComponent();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconComponent name="Download" className="h-4 w-4" />
|
<IconComponent name="Download" className="h-4 w-4" />
|
||||||
Export
|
Export
|
||||||
</Button>
|
</Button>
|
||||||
</ExportModal>
|
)}
|
||||||
}
|
|
||||||
{is_component && <Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
className="gap-2"
|
|
||||||
onClick={() => {
|
|
||||||
(setOpen || internalSetOpen)(false);
|
|
||||||
handleExportComponent();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconComponent name="Download" className="h-4 w-4" />
|
|
||||||
Export
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
}
|
|
||||||
<Button
|
<Button
|
||||||
disabled={loadingNames}
|
disabled={loadingNames}
|
||||||
type="button"
|
type="button"
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import { useContext, useEffect, useRef, useState } from "react";
|
import { useContext, useEffect, useRef, useState } from "react";
|
||||||
import PaginatorComponent from "../../components/PaginatorComponent";
|
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import Header from "../../components/headerComponent";
|
import Header from "../../components/headerComponent";
|
||||||
import LoadingComponent from "../../components/loadingComponent";
|
import LoadingComponent from "../../components/loadingComponent";
|
||||||
|
import PaginatorComponent from "../../components/paginatorComponent";
|
||||||
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { CheckBoxDiv } from "../../components/ui/checkbox";
|
import { CheckBoxDiv } from "../../components/ui/checkbox";
|
||||||
import { Input } from "../../components/ui/input";
|
import { Input } from "../../components/ui/input";
|
||||||
|
|
@ -35,8 +35,8 @@ import {
|
||||||
getUsersPage,
|
getUsersPage,
|
||||||
updateUser,
|
updateUser,
|
||||||
} from "../../controllers/API";
|
} from "../../controllers/API";
|
||||||
import ConfirmationModal from "../../modals/ConfirmationModal";
|
import ConfirmationModal from "../../modals/confirmationModal";
|
||||||
import UserManagementModal from "../../modals/UserManagementModal";
|
import UserManagementModal from "../../modals/userManagementModal";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
import { Users } from "../../types/api";
|
import { Users } from "../../types/api";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useContext, useEffect, useRef, useState } from "react";
|
import { useContext, useEffect, useRef, useState } from "react";
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
|
|
@ -12,8 +12,8 @@ import {
|
||||||
} from "../../components/ui/table";
|
} from "../../components/ui/table";
|
||||||
import { AuthContext } from "../../contexts/authContext";
|
import { AuthContext } from "../../contexts/authContext";
|
||||||
import { deleteApiKey, getApiKey } from "../../controllers/API";
|
import { deleteApiKey, getApiKey } from "../../controllers/API";
|
||||||
import ConfirmationModal from "../../modals/ConfirmationModal";
|
import ConfirmationModal from "../../modals/confirmationModal";
|
||||||
import SecretKeyModal from "../../modals/SecretKeyModal";
|
import SecretKeyModal from "../../modals/secretKeyModal";
|
||||||
|
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import Header from "../../components/headerComponent";
|
import Header from "../../components/headerComponent";
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@ import ReactFlow, {
|
||||||
SelectionDragHandler,
|
SelectionDragHandler,
|
||||||
updateEdge,
|
updateEdge,
|
||||||
} from "reactflow";
|
} from "reactflow";
|
||||||
import GenericNode from "../../../../CustomNodes/GenericNode";
|
|
||||||
import {
|
import {
|
||||||
INVALID_SELECTION_ERROR_ALERT,
|
INVALID_SELECTION_ERROR_ALERT,
|
||||||
UPLOAD_ALERT_LIST,
|
UPLOAD_ALERT_LIST,
|
||||||
UPLOAD_ERROR_ALERT,
|
UPLOAD_ERROR_ALERT,
|
||||||
WRONG_FILE_ERROR_ALERT,
|
WRONG_FILE_ERROR_ALERT,
|
||||||
} from "../../../../constants/alerts_constants";
|
} from "../../../../constants/alerts_constants";
|
||||||
|
import GenericNode from "../../../../customNodes/genericNode";
|
||||||
import useAlertStore from "../../../../stores/alertStore";
|
import useAlertStore from "../../../../stores/alertStore";
|
||||||
import useFlowStore from "../../../../stores/flowStore";
|
import useFlowStore from "../../../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import { LinkIcon, SparklesIcon } from "lucide-react";
|
import { LinkIcon, SparklesIcon } from "lucide-react";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
|
||||||
import IconComponent from "../../../../components/genericIconComponent";
|
import IconComponent from "../../../../components/genericIconComponent";
|
||||||
|
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
||||||
import { Input } from "../../../../components/ui/input";
|
import { Input } from "../../../../components/ui/input";
|
||||||
import { Separator } from "../../../../components/ui/separator";
|
import { Separator } from "../../../../components/ui/separator";
|
||||||
import { PRIORITY_SIDEBAR_ORDER } from "../../../../constants/constants";
|
import { PRIORITY_SIDEBAR_ORDER } from "../../../../constants/constants";
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import _, { cloneDeep } from "lodash";
|
import _, { cloneDeep } from "lodash";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useUpdateNodeInternals } from "reactflow";
|
import { useUpdateNodeInternals } from "reactflow";
|
||||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
|
||||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||||
import IconComponent from "../../../../components/genericIconComponent";
|
import IconComponent from "../../../../components/genericIconComponent";
|
||||||
|
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
|
|
@ -11,8 +11,8 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
} from "../../../../components/ui/select-custom";
|
} from "../../../../components/ui/select-custom";
|
||||||
import { postCustomComponent } from "../../../../controllers/API";
|
import { postCustomComponent } from "../../../../controllers/API";
|
||||||
import ConfirmationModal from "../../../../modals/ConfirmationModal";
|
import ConfirmationModal from "../../../../modals/confirmationModal";
|
||||||
import EditNodeModal from "../../../../modals/EditNodeModal";
|
import EditNodeModal from "../../../../modals/editNodeModal";
|
||||||
import ShareModal from "../../../../modals/shareModal";
|
import ShareModal from "../../../../modals/shareModal";
|
||||||
import useAlertStore from "../../../../stores/alertStore";
|
import useAlertStore from "../../../../stores/alertStore";
|
||||||
import { useDarkStore } from "../../../../stores/darkStore";
|
import { useDarkStore } from "../../../../stores/darkStore";
|
||||||
|
|
@ -58,7 +58,7 @@ export default function NodeToolbarComponent({
|
||||||
data.node.template[templateField].type === "Any" ||
|
data.node.template[templateField].type === "Any" ||
|
||||||
data.node.template[templateField].type === "int" ||
|
data.node.template[templateField].type === "int" ||
|
||||||
data.node.template[templateField].type === "dict" ||
|
data.node.template[templateField].type === "dict" ||
|
||||||
data.node.template[templateField].type === "NestedDict")
|
data.node.template[templateField].type === "NestedDict"),
|
||||||
).length;
|
).length;
|
||||||
const templates = useTypesStore((state) => state.templates);
|
const templates = useTypesStore((state) => state.templates);
|
||||||
const hasStore = useStoreStore((state) => state.hasStore);
|
const hasStore = useStoreStore((state) => state.hasStore);
|
||||||
|
|
@ -85,7 +85,7 @@ export default function NodeToolbarComponent({
|
||||||
const [showconfirmShare, setShowconfirmShare] = useState(false);
|
const [showconfirmShare, setShowconfirmShare] = useState(false);
|
||||||
const [showOverrideModal, setShowOverrideModal] = useState(false);
|
const [showOverrideModal, setShowOverrideModal] = useState(false);
|
||||||
const [flowComponent, setFlowComponent] = useState<FlowType>(
|
const [flowComponent, setFlowComponent] = useState<FlowType>(
|
||||||
createFlowComponent(cloneDeep(data), version)
|
createFlowComponent(cloneDeep(data), version),
|
||||||
);
|
);
|
||||||
|
|
||||||
const openInNewTab = (url) => {
|
const openInNewTab = (url) => {
|
||||||
|
|
@ -100,7 +100,7 @@ export default function NodeToolbarComponent({
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
|
|
||||||
const setLastCopiedSelection = useFlowStore(
|
const setLastCopiedSelection = useFlowStore(
|
||||||
(state) => state.setLastCopiedSelection
|
(state) => state.setLastCopiedSelection,
|
||||||
);
|
);
|
||||||
|
|
||||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||||
|
|
@ -150,7 +150,7 @@ export default function NodeToolbarComponent({
|
||||||
nodes,
|
nodes,
|
||||||
edges,
|
edges,
|
||||||
setNodes,
|
setNodes,
|
||||||
setEdges
|
setEdges,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "override":
|
case "override":
|
||||||
|
|
@ -174,7 +174,7 @@ export default function NodeToolbarComponent({
|
||||||
y: 10,
|
y: 10,
|
||||||
paneX: nodes.find((node) => node.id === data.id)?.position.x,
|
paneX: nodes.find((node) => node.id === data.id)?.position.x,
|
||||||
paneY: nodes.find((node) => node.id === data.id)?.position.y,
|
paneY: nodes.find((node) => node.id === data.id)?.position.y,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "update":
|
case "update":
|
||||||
|
|
@ -212,13 +212,13 @@ export default function NodeToolbarComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
const isSaved = flows.some((flow) =>
|
const isSaved = flows.some((flow) =>
|
||||||
Object.values(flow).includes(data.node?.display_name!)
|
Object.values(flow).includes(data.node?.display_name!),
|
||||||
);
|
);
|
||||||
|
|
||||||
const setNode = useFlowStore((state) => state.setNode);
|
const setNode = useFlowStore((state) => state.setNode);
|
||||||
|
|
||||||
const handleOnNewValue = (
|
const handleOnNewValue = (
|
||||||
newValue: string | string[] | boolean | Object[]
|
newValue: string | string[] | boolean | Object[],
|
||||||
): void => {
|
): void => {
|
||||||
if (data.node!.template[name].value !== newValue) {
|
if (data.node!.template[name].value !== newValue) {
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
|
|
@ -325,7 +325,6 @@ export default function NodeToolbarComponent({
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
selected &&
|
selected &&
|
||||||
!isGroup &&
|
|
||||||
(event.ctrlKey || event.metaKey) &&
|
(event.ctrlKey || event.metaKey) &&
|
||||||
event.shiftKey &&
|
event.shiftKey &&
|
||||||
event.key === "A"
|
event.key === "A"
|
||||||
|
|
@ -394,7 +393,7 @@ export default function NodeToolbarComponent({
|
||||||
data-testid="save-button-modal"
|
data-testid="save-button-modal"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10",
|
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10",
|
||||||
hasCode ? " " : " rounded-l-md "
|
hasCode ? " " : " rounded-l-md ",
|
||||||
)}
|
)}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -412,7 +411,7 @@ export default function NodeToolbarComponent({
|
||||||
<button
|
<button
|
||||||
data-testid="duplicate-button-modal"
|
data-testid="duplicate-button-modal"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
|
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10",
|
||||||
)}
|
)}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -460,7 +459,7 @@ export default function NodeToolbarComponent({
|
||||||
<div
|
<div
|
||||||
data-testid="more-options-modal"
|
data-testid="more-options-modal"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative -ml-px inline-flex h-8 w-[31px] items-center rounded-r-md bg-background text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
|
"relative -ml-px inline-flex h-8 w-[31px] items-center rounded-r-md bg-background text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import PaginatorComponent from "../../../../components/PaginatorComponent";
|
|
||||||
import CollectionCardComponent from "../../../../components/cardComponent";
|
import CollectionCardComponent from "../../../../components/cardComponent";
|
||||||
import CardsWrapComponent from "../../../../components/cardsWrapComponent";
|
import CardsWrapComponent from "../../../../components/cardsWrapComponent";
|
||||||
import IconComponent from "../../../../components/genericIconComponent";
|
import IconComponent from "../../../../components/genericIconComponent";
|
||||||
|
import PaginatorComponent from "../../../../components/paginatorComponent";
|
||||||
import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent";
|
import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent";
|
||||||
import { Button } from "../../../../components/ui/button";
|
import { Button } from "../../../../components/ui/button";
|
||||||
import {
|
import {
|
||||||
|
|
@ -30,7 +30,6 @@ export default function ComponentsComponent({
|
||||||
const [pageIndex, setPageIndex] = useState(1);
|
const [pageIndex, setPageIndex] = useState(1);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const all: FlowType[] = flows
|
const all: FlowType[] = flows
|
||||||
.filter((f) => (f.is_component ?? false) === is_component)
|
.filter((f) => (f.is_component ?? false) === is_component)
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
|
|
@ -86,12 +85,10 @@ export default function ComponentsComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function resetFilter() {
|
function resetFilter() {
|
||||||
setPageIndex(1);
|
setPageIndex(1);
|
||||||
setPageSize(20);
|
setPageSize(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardsWrapComponent
|
<CardsWrapComponent
|
||||||
onFileDrop={onFileDrop}
|
onFileDrop={onFileDrop}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Group, ToyBrick } from "lucide-react";
|
import { Group, ToyBrick } from "lucide-react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||||
import DropdownButton from "../../components/DropdownButtonComponent";
|
import DropdownButton from "../../components/dropdownButtonComponent";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import PageLayout from "../../components/pageLayout";
|
import PageLayout from "../../components/pageLayout";
|
||||||
import SidebarNav from "../../components/sidebarComponent";
|
import SidebarNav from "../../components/sidebarComponent";
|
||||||
|
|
@ -11,7 +11,7 @@ import {
|
||||||
MY_COLLECTION_DESC,
|
MY_COLLECTION_DESC,
|
||||||
USER_PROJECTS_HEADER,
|
USER_PROJECTS_HEADER,
|
||||||
} from "../../constants/constants";
|
} from "../../constants/constants";
|
||||||
import NewFlowModal from "../../modals/NewFlowModal";
|
import NewFlowModal from "../../modals/newFlowModal";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
import { downloadFlows } from "../../utils/reactflowUtils";
|
import { downloadFlows } from "../../utils/reactflowUtils";
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,13 @@ import { cn } from "../../../../utils/utils";
|
||||||
|
|
||||||
export default function GlobalVariablesPage() {
|
export default function GlobalVariablesPage() {
|
||||||
const globalVariablesEntries = useGlobalVariablesStore(
|
const globalVariablesEntries = useGlobalVariablesStore(
|
||||||
(state) => state.globalVariablesEntries
|
(state) => state.globalVariablesEntries,
|
||||||
);
|
);
|
||||||
const removeGlobalVariable = useGlobalVariablesStore(
|
const removeGlobalVariable = useGlobalVariablesStore(
|
||||||
(state) => state.removeGlobalVariable
|
(state) => state.removeGlobalVariable,
|
||||||
);
|
);
|
||||||
const globalVariables = useGlobalVariablesStore(
|
const globalVariables = useGlobalVariablesStore(
|
||||||
(state) => state.globalVariables
|
(state) => state.globalVariables,
|
||||||
);
|
);
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
const getVariableId = useGlobalVariablesStore((state) => state.getVariableId);
|
const getVariableId = useGlobalVariablesStore((state) => state.getVariableId);
|
||||||
|
|
@ -154,7 +154,7 @@ export default function GlobalVariablesPage() {
|
||||||
<IconComponent
|
<IconComponent
|
||||||
name="Trash2"
|
name="Trash2"
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-5 w-5 text-destructive group-disabled:text-primary"
|
"h-5 w-5 text-destructive group-disabled:text-primary",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -174,6 +174,8 @@ export default function GlobalVariablesPage() {
|
||||||
}}
|
}}
|
||||||
rowSelection="multiple"
|
rowSelection="multiple"
|
||||||
suppressRowClickSelection={true}
|
suppressRowClickSelection={true}
|
||||||
|
domLayout="autoHeight"
|
||||||
|
pagination={false}
|
||||||
columnDefs={colDefs}
|
columnDefs={colDefs}
|
||||||
rowData={rowData}
|
rowData={rowData}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,6 @@ import { ColDef, ColGroupDef } from "ag-grid-community";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import ForwardedIconComponent from "../../../../components/genericIconComponent";
|
import ForwardedIconComponent from "../../../../components/genericIconComponent";
|
||||||
import TableComponent from "../../../../components/tableComponent";
|
import TableComponent from "../../../../components/tableComponent";
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "../../../../components/ui/card";
|
|
||||||
|
|
||||||
export default function ShortcutsPage() {
|
export default function ShortcutsPage() {
|
||||||
const advancedShortcut = "Ctrl + Shift + A";
|
const advancedShortcut = "Ctrl + Shift + A";
|
||||||
|
|
@ -84,7 +77,7 @@ export default function ShortcutsPage() {
|
||||||
shortcut: redoShortcut,
|
shortcut: redoShortcut,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col gap-6">
|
<div className="flex h-full w-full flex-col gap-6">
|
||||||
<div className="flex w-full items-center justify-between gap-4 space-y-0.5">
|
<div className="flex w-full items-center justify-between gap-4 space-y-0.5">
|
||||||
|
|
@ -97,22 +90,17 @@ export default function ShortcutsPage() {
|
||||||
/>
|
/>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
Manage Shortcuts for quick access to
|
Manage Shortcuts for quick access to frequently used actions.
|
||||||
frequently used actions.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-6 pb-8">
|
<div className="grid gap-6 pb-8">
|
||||||
<Card x-chunk="dashboard-04-chunk-2" className="pt-4">
|
<TableComponent
|
||||||
<CardContent>
|
domLayout="autoHeight"
|
||||||
<TableComponent
|
pagination={false}
|
||||||
domLayout="autoHeight"
|
columnDefs={colDefs}
|
||||||
pagination={false}
|
rowData={nodesRowData}
|
||||||
columnDefs={colDefs}
|
/>
|
||||||
rowData={nodesRowData}
|
|
||||||
/>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
import { uniqueId } from "lodash";
|
import { uniqueId } from "lodash";
|
||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import PaginatorComponent from "../../components/PaginatorComponent";
|
|
||||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
|
||||||
import CollectionCardComponent from "../../components/cardComponent";
|
import CollectionCardComponent from "../../components/cardComponent";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import PageLayout from "../../components/pageLayout";
|
import PageLayout from "../../components/pageLayout";
|
||||||
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import { SkeletonCardComponent } from "../../components/skeletonCardComponent";
|
import { SkeletonCardComponent } from "../../components/skeletonCardComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { Input } from "../../components/ui/input";
|
import { Input } from "../../components/ui/input";
|
||||||
|
|
||||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||||
|
import PaginatorComponent from "../../components/paginatorComponent";
|
||||||
import { TagsSelector } from "../../components/tagsSelectorComponent";
|
import { TagsSelector } from "../../components/tagsSelectorComponent";
|
||||||
import { Badge } from "../../components/ui/badge";
|
import { Badge } from "../../components/ui/badge";
|
||||||
import {
|
import {
|
||||||
|
|
@ -29,7 +29,7 @@ import {
|
||||||
import { STORE_DESC, STORE_TITLE } from "../../constants/constants";
|
import { STORE_DESC, STORE_TITLE } from "../../constants/constants";
|
||||||
import { AuthContext } from "../../contexts/authContext";
|
import { AuthContext } from "../../contexts/authContext";
|
||||||
import { getStoreComponents, getStoreTags } from "../../controllers/API";
|
import { getStoreComponents, getStoreTags } from "../../controllers/API";
|
||||||
import StoreApiKeyModal from "../../modals/StoreApiKeyModal";
|
import StoreApiKeyModal from "../../modals/storeApiKeyModal";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
import { useStoreStore } from "../../stores/storeStore";
|
import { useStoreStore } from "../../stores/storeStore";
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,19 @@ import { StoreGuard } from "./components/storeGuard";
|
||||||
import AdminPage from "./pages/AdminPage";
|
import AdminPage from "./pages/AdminPage";
|
||||||
import LoginAdminPage from "./pages/AdminPage/LoginPage";
|
import LoginAdminPage from "./pages/AdminPage/LoginPage";
|
||||||
import ApiKeysPage from "./pages/ApiKeysPage";
|
import ApiKeysPage from "./pages/ApiKeysPage";
|
||||||
|
import DeleteAccountPage from "./pages/DeleteAccountPage";
|
||||||
import FlowPage from "./pages/FlowPage";
|
import FlowPage from "./pages/FlowPage";
|
||||||
|
import LoginPage from "./pages/LoginPage";
|
||||||
import HomePage from "./pages/MainPage";
|
import HomePage from "./pages/MainPage";
|
||||||
import ComponentsComponent from "./pages/MainPage/components/components";
|
import ComponentsComponent from "./pages/MainPage/components/components";
|
||||||
|
import PlaygroundPage from "./pages/Playground";
|
||||||
import SettingsPage from "./pages/SettingsPage";
|
import SettingsPage from "./pages/SettingsPage";
|
||||||
import GeneralPage from "./pages/SettingsPage/pages/GeneralPage";
|
import GeneralPage from "./pages/SettingsPage/pages/GeneralPage";
|
||||||
import GlobalVariablesPage from "./pages/SettingsPage/pages/GlobalVariablesPage";
|
import GlobalVariablesPage from "./pages/SettingsPage/pages/GlobalVariablesPage";
|
||||||
import ShortcutsPage from "./pages/SettingsPage/pages/ShortcutsPage";
|
import ShortcutsPage from "./pages/SettingsPage/pages/ShortcutsPage";
|
||||||
|
import SignUp from "./pages/SignUpPage";
|
||||||
import StorePage from "./pages/StorePage";
|
import StorePage from "./pages/StorePage";
|
||||||
import ViewPage from "./pages/ViewPage";
|
import ViewPage from "./pages/ViewPage";
|
||||||
import DeleteAccountPage from "./pages/deleteAccountPage";
|
|
||||||
import LoginPage from "./pages/loginPage";
|
|
||||||
import SignUp from "./pages/signUpPage";
|
|
||||||
import PlaygroundPage from "./pages/Playground";
|
|
||||||
|
|
||||||
const Router = () => {
|
const Router = () => {
|
||||||
return (
|
return (
|
||||||
|
|
@ -76,10 +76,16 @@ const Router = () => {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route path="/playground/:id/">
|
<Route path="/playground/:id/">
|
||||||
element={
|
element=
|
||||||
<Route path="" element={<ProtectedRoute>
|
{
|
||||||
<PlaygroundPage />
|
<Route
|
||||||
</ProtectedRoute>} />
|
path=""
|
||||||
|
element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<PlaygroundPage />
|
||||||
|
</ProtectedRoute>
|
||||||
|
}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/flow/:id/">
|
<Route path="/flow/:id/">
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
font-feature-settings: "rlig" 1, "calt" 1;
|
font-feature-settings:
|
||||||
|
"rlig" 1,
|
||||||
|
"calt" 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1018,6 +1020,9 @@
|
||||||
.langflow-chat-span {
|
.langflow-chat-span {
|
||||||
@apply text-lg text-foreground;
|
@apply text-lg text-foreground;
|
||||||
}
|
}
|
||||||
|
.card-filter {
|
||||||
|
@apply bg-background bg-fixed opacity-20;
|
||||||
|
}
|
||||||
.langflow-chat-desc {
|
.langflow-chat-desc {
|
||||||
@apply w-2/4 rounded-md border border-border bg-muted px-6 py-8;
|
@apply w-2/4 rounded-md border border-border bg-muted px-6 py-8;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -116,33 +116,29 @@ export async function buildVertices({
|
||||||
nodes,
|
nodes,
|
||||||
edges,
|
edges,
|
||||||
}: BuildVerticesParams) {
|
}: BuildVerticesParams) {
|
||||||
let verticesBuild = useFlowStore.getState().verticesBuild;
|
|
||||||
// if startNodeId and stopNodeId are provided
|
// if startNodeId and stopNodeId are provided
|
||||||
// something is wrong
|
// something is wrong
|
||||||
if (startNodeId && stopNodeId) {
|
if (startNodeId && stopNodeId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let verticesOrderResponse = await updateVerticesOrder(
|
||||||
|
flowId,
|
||||||
|
startNodeId,
|
||||||
|
stopNodeId,
|
||||||
|
nodes,
|
||||||
|
edges
|
||||||
|
);
|
||||||
|
if (onValidateNodes) {
|
||||||
|
try {
|
||||||
|
onValidateNodes(verticesOrderResponse.verticesToRun);
|
||||||
|
} catch (e) {
|
||||||
|
useFlowStore.getState().setIsBuilding(false);
|
||||||
|
|
||||||
if (!verticesBuild || startNodeId || stopNodeId) {
|
return;
|
||||||
let verticesOrderResponse = await updateVerticesOrder(
|
|
||||||
flowId,
|
|
||||||
startNodeId,
|
|
||||||
stopNodeId,
|
|
||||||
nodes,
|
|
||||||
edges
|
|
||||||
);
|
|
||||||
if (onValidateNodes) {
|
|
||||||
try {
|
|
||||||
onValidateNodes(verticesOrderResponse.verticesToRun);
|
|
||||||
} catch (e) {
|
|
||||||
useFlowStore.getState().setIsBuilding(false);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (onGetOrderSuccess) onGetOrderSuccess();
|
|
||||||
verticesBuild = useFlowStore.getState().verticesBuild;
|
|
||||||
}
|
}
|
||||||
|
if (onGetOrderSuccess) onGetOrderSuccess();
|
||||||
|
let verticesBuild = useFlowStore.getState().verticesBuild;
|
||||||
|
|
||||||
const verticesIds = verticesBuild?.verticesIds!;
|
const verticesIds = verticesBuild?.verticesIds!;
|
||||||
const verticesLayers = verticesBuild?.verticesLayers!;
|
const verticesLayers = verticesBuild?.verticesLayers!;
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ export function normalCaseToSnakeCase(str: string): string {
|
||||||
|
|
||||||
export function toTitleCase(
|
export function toTitleCase(
|
||||||
str: string | undefined,
|
str: string | undefined,
|
||||||
isNodeField?: boolean
|
isNodeField?: boolean,
|
||||||
): string {
|
): string {
|
||||||
if (!str) return "";
|
if (!str) return "";
|
||||||
let result = str
|
let result = str
|
||||||
|
|
@ -70,7 +70,7 @@ export function toTitleCase(
|
||||||
if (isNodeField) return word;
|
if (isNodeField) return word;
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
return checkUpperWords(
|
return checkUpperWords(
|
||||||
word[0].toUpperCase() + word.slice(1).toLowerCase()
|
word[0].toUpperCase() + word.slice(1).toLowerCase(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return checkUpperWords(word.toLowerCase());
|
return checkUpperWords(word.toLowerCase());
|
||||||
|
|
@ -83,7 +83,7 @@ export function toTitleCase(
|
||||||
if (isNodeField) return word;
|
if (isNodeField) return word;
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
return checkUpperWords(
|
return checkUpperWords(
|
||||||
word[0].toUpperCase() + word.slice(1).toLowerCase()
|
word[0].toUpperCase() + word.slice(1).toLowerCase(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return checkUpperWords(word.toLowerCase());
|
return checkUpperWords(word.toLowerCase());
|
||||||
|
|
@ -93,8 +93,8 @@ export function toTitleCase(
|
||||||
|
|
||||||
export function getUnavailableFields(variables: {
|
export function getUnavailableFields(variables: {
|
||||||
[key: string]: { default_fields?: string[] };
|
[key: string]: { default_fields?: string[] };
|
||||||
}): {[name: string]: string} {
|
}): { [name: string]: string } {
|
||||||
const unVariables:{[name: string]: string} = {};
|
const unVariables: { [name: string]: string } = {};
|
||||||
Object.keys(variables).forEach((key) => {
|
Object.keys(variables).forEach((key) => {
|
||||||
if (variables[key].default_fields) {
|
if (variables[key].default_fields) {
|
||||||
variables[key].default_fields!.forEach((field) => {
|
variables[key].default_fields!.forEach((field) => {
|
||||||
|
|
@ -123,7 +123,7 @@ export function groupByFamily(
|
||||||
data: APIDataType,
|
data: APIDataType,
|
||||||
baseClasses: string,
|
baseClasses: string,
|
||||||
left: boolean,
|
left: boolean,
|
||||||
flow?: NodeType[]
|
flow?: NodeType[],
|
||||||
): groupedObjType[] {
|
): groupedObjType[] {
|
||||||
const baseClassesSet = new Set(baseClasses.split("\n"));
|
const baseClassesSet = new Set(baseClasses.split("\n"));
|
||||||
let arrOfPossibleInputs: Array<{
|
let arrOfPossibleInputs: Array<{
|
||||||
|
|
@ -149,7 +149,7 @@ export function groupByFamily(
|
||||||
baseClassesSet.has(template.type)) ||
|
baseClassesSet.has(template.type)) ||
|
||||||
(template.input_types &&
|
(template.input_types &&
|
||||||
template.input_types.some((inputType) =>
|
template.input_types.some((inputType) =>
|
||||||
baseClassesSet.has(inputType)
|
baseClassesSet.has(inputType),
|
||||||
)))
|
)))
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -169,7 +169,7 @@ export function groupByFamily(
|
||||||
hasBaseClassInBaseClasses:
|
hasBaseClassInBaseClasses:
|
||||||
foundNode?.hasBaseClassInBaseClasses ||
|
foundNode?.hasBaseClassInBaseClasses ||
|
||||||
nodeData.node!.base_classes.some((baseClass) =>
|
nodeData.node!.base_classes.some((baseClass) =>
|
||||||
baseClassesSet.has(baseClass)
|
baseClassesSet.has(baseClass),
|
||||||
), //seta como anterior ou verifica se o node tem base class
|
), //seta como anterior ou verifica se o node tem base class
|
||||||
displayName: nodeData.node?.display_name,
|
displayName: nodeData.node?.display_name,
|
||||||
});
|
});
|
||||||
|
|
@ -186,10 +186,10 @@ export function groupByFamily(
|
||||||
if (!foundNode) {
|
if (!foundNode) {
|
||||||
foundNode = {
|
foundNode = {
|
||||||
hasBaseClassInTemplate: Object.values(node!.template).some(
|
hasBaseClassInTemplate: Object.values(node!.template).some(
|
||||||
checkBaseClass
|
checkBaseClass,
|
||||||
),
|
),
|
||||||
hasBaseClassInBaseClasses: node!.base_classes.some((baseClass) =>
|
hasBaseClassInBaseClasses: node!.base_classes.some((baseClass) =>
|
||||||
baseClassesSet.has(baseClass)
|
baseClassesSet.has(baseClass),
|
||||||
),
|
),
|
||||||
displayName: node?.display_name,
|
displayName: node?.display_name,
|
||||||
};
|
};
|
||||||
|
|
@ -246,7 +246,7 @@ export function getRandomDescription(): string {
|
||||||
export function getRandomName(
|
export function getRandomName(
|
||||||
retry: number = 0,
|
retry: number = 0,
|
||||||
noSpace: boolean = false,
|
noSpace: boolean = false,
|
||||||
maxRetries: number = 3
|
maxRetries: number = 3,
|
||||||
): string {
|
): string {
|
||||||
const left: string[] = ADJECTIVES;
|
const left: string[] = ADJECTIVES;
|
||||||
const right: string[] = NOUNS;
|
const right: string[] = NOUNS;
|
||||||
|
|
@ -325,7 +325,7 @@ export function getChatInputField(flowState?: FlowState) {
|
||||||
export function getPythonApiCode(
|
export function getPythonApiCode(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
isAuth: boolean,
|
isAuth: boolean,
|
||||||
tweak?: any[]
|
tweak?: any[],
|
||||||
): string {
|
): string {
|
||||||
const flowId = flow.id;
|
const flowId = flow.id;
|
||||||
|
|
||||||
|
|
@ -393,7 +393,7 @@ print(run_flow(message=message, flow_id=FLOW_ID, tweaks=TWEAKS${
|
||||||
export function getCurlCode(
|
export function getCurlCode(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
isAuth: boolean,
|
isAuth: boolean,
|
||||||
tweak?: any[]
|
tweak?: any[],
|
||||||
): string {
|
): string {
|
||||||
const flowId = flow.id;
|
const flowId = flow.id;
|
||||||
const tweaks = buildTweaks(flow);
|
const tweaks = buildTweaks(flow);
|
||||||
|
|
@ -463,7 +463,7 @@ result = run_flow_from_json(flow="${flowName}.json",
|
||||||
export function getWidgetCode(
|
export function getWidgetCode(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
isAuth: boolean,
|
isAuth: boolean,
|
||||||
flowState?: FlowState
|
flowState?: FlowState,
|
||||||
): string {
|
): string {
|
||||||
const flowId = flow.id;
|
const flowId = flow.id;
|
||||||
const flowName = flow.name;
|
const flowName = flow.name;
|
||||||
|
|
@ -593,7 +593,7 @@ export function checkLocalStorageKey(key: string): boolean {
|
||||||
|
|
||||||
export function IncrementObjectKey(
|
export function IncrementObjectKey(
|
||||||
object: object,
|
object: object,
|
||||||
key: string
|
key: string,
|
||||||
): { newKey: string; increment: number } {
|
): { newKey: string; increment: number } {
|
||||||
let count = 1;
|
let count = 1;
|
||||||
const type = removeCountFromString(key);
|
const type = removeCountFromString(key);
|
||||||
|
|
@ -665,7 +665,7 @@ export function getSetFromObject(obj: object, key?: string): Set<string> {
|
||||||
|
|
||||||
export function getFieldTitle(
|
export function getFieldTitle(
|
||||||
template: APITemplateType,
|
template: APITemplateType,
|
||||||
templateField: string
|
templateField: string,
|
||||||
): string {
|
): string {
|
||||||
return template[templateField].display_name
|
return template[templateField].display_name
|
||||||
? template[templateField].display_name!
|
? template[templateField].display_name!
|
||||||
|
|
@ -715,3 +715,11 @@ export function freezeObject(obj: any) {
|
||||||
if (!obj) return obj;
|
if (!obj) return obj;
|
||||||
return JSON.parse(JSON.stringify(obj));
|
return JSON.parse(JSON.stringify(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function convertTestName(name: string): string {
|
||||||
|
return name.replace(/ /g, "-").toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortByName(stringList: string[]): string[] {
|
||||||
|
return stringList.sort((a, b) => a.localeCompare(b));
|
||||||
|
}
|
||||||
|
|
|
||||||
46
src/frontend/tests/end-to-end/deleteComponentFlows.spec.ts
Normal file
46
src/frontend/tests/end-to-end/deleteComponentFlows.spec.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { test } from "@playwright/test";
|
||||||
|
|
||||||
|
test("shoud delete a flow", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await page.getByText("Store").nth(0).click();
|
||||||
|
await page.getByTestId("install-Website Content QA").click();
|
||||||
|
await page.waitForTimeout(5000);
|
||||||
|
await page.getByText("My Collection").nth(0).click();
|
||||||
|
await page.getByText("Website Content QA").first().isVisible();
|
||||||
|
await page
|
||||||
|
.getByTestId("card-website-content-qa")
|
||||||
|
.first()
|
||||||
|
.hover()
|
||||||
|
.then(async () => {
|
||||||
|
await page.getByTestId("icon-Trash2").first().click();
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
});
|
||||||
|
await page.getByText("Confirm deletion of component?").isVisible();
|
||||||
|
await page.getByText("Delete").nth(1).click();
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
await page.getByText("Successfully").first().isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("shoud delete a component", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await page.getByText("Store").nth(0).click();
|
||||||
|
await page.getByTestId("install-Basic RAG").click();
|
||||||
|
await page.waitForTimeout(5000);
|
||||||
|
await page.getByText("My Collection").nth(0).click();
|
||||||
|
await page.getByText("Components").first().click();
|
||||||
|
await page.getByText("Basic RAG").first().isVisible();
|
||||||
|
await page
|
||||||
|
.getByTestId("card-basic-rag")
|
||||||
|
.first()
|
||||||
|
.hover()
|
||||||
|
.then(async () => {
|
||||||
|
await page.getByTestId("icon-Trash2").first().click();
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
});
|
||||||
|
await page.getByText("Confirm deletion of component?").isVisible();
|
||||||
|
await page.getByText("Delete").nth(1).click();
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
await page.getByText("Successfully").first().isVisible();
|
||||||
|
});
|
||||||
91
src/frontend/tests/end-to-end/userSettings.spec.ts
Normal file
91
src/frontend/tests/end-to-end/userSettings.spec.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import { test } from "@playwright/test";
|
||||||
|
|
||||||
|
test("should see general profile gradient", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await page.getByTestId("user-profile-settings").click();
|
||||||
|
await page.getByText("Settings").click();
|
||||||
|
await page.getByText("General").nth(2).isVisible();
|
||||||
|
await page.getByText("Profile Gradient").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should interact with global variables", async ({ page }) => {
|
||||||
|
const randomName = Math.random().toString(36).substring(2);
|
||||||
|
|
||||||
|
await page.goto("/");
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await page.getByTestId("user-profile-settings").click();
|
||||||
|
await page.getByText("Settings").click();
|
||||||
|
await page.getByText("Global Variables").click();
|
||||||
|
await page.getByText("Global Variables").nth(2);
|
||||||
|
await page.getByText("Global Variables", { exact: true }).nth(1).isVisible();
|
||||||
|
await page.getByText("Add New").click();
|
||||||
|
await page
|
||||||
|
.getByPlaceholder("Insert a name for the variable...")
|
||||||
|
.fill(randomName);
|
||||||
|
await page.getByTestId("popover-anchor-type-global-variables").click();
|
||||||
|
await page.getByPlaceholder("Search options...").fill("Generic");
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await page.getByText("Generic", { exact: true }).last().isVisible();
|
||||||
|
await page.getByText("Generic", { exact: true }).last().click();
|
||||||
|
|
||||||
|
await page.getByTestId("popover-anchor-type-global-variables").click();
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await page.getByPlaceholder("Search options...").fill("Generic");
|
||||||
|
await page.getByText("Generic", { exact: true }).last().isVisible();
|
||||||
|
await page.getByText("Generic", { exact: true }).last().click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByPlaceholder("Insert a value for the variable...")
|
||||||
|
.fill("testtesttesttesttesttesttesttest");
|
||||||
|
await page.getByTestId("popover-anchor-apply-to-fields").click();
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
|
await page.getByPlaceholder("Search options...").fill("System Message");
|
||||||
|
|
||||||
|
await page.getByText("System Message").first().click();
|
||||||
|
|
||||||
|
await page.getByPlaceholder("Search options...").fill("openAI");
|
||||||
|
|
||||||
|
await page.getByText("OpenAI API Base").first().click();
|
||||||
|
|
||||||
|
await page.getByPlaceholder("Search options...").fill("llama");
|
||||||
|
|
||||||
|
await page.getByText("Ollama").first().click();
|
||||||
|
|
||||||
|
await page.keyboard.press("Escape");
|
||||||
|
await page.getByText("Save Variable", { exact: true }).click();
|
||||||
|
|
||||||
|
await page.getByText(randomName).isVisible();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByLabel("Press Space to toggle all rows selection (unchecked)")
|
||||||
|
.nth(0)
|
||||||
|
.click();
|
||||||
|
await page.getByTestId("icon-Trash2").click();
|
||||||
|
await page.getByText("No data available").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should see shortcuts", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
await page.getByTestId("user-profile-settings").click();
|
||||||
|
await page.getByText("Settings").click();
|
||||||
|
await page.getByText("General").nth(2).isVisible();
|
||||||
|
await page.getByText("Shortcuts").nth(0).click();
|
||||||
|
await page.getByText("Shortcuts", { exact: true }).nth(1).isVisible();
|
||||||
|
await page
|
||||||
|
.getByText("Advanced Settings Component", { exact: true })
|
||||||
|
.isVisible();
|
||||||
|
await page.getByText("Minimize Component", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Code Component", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Copy Component", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Duplicate Component", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Share Component", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Docs Component", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Save Component", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Delete Component", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Open Playground", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Undo", { exact: true }).isVisible();
|
||||||
|
await page.getByText("Redo", { exact: true }).isVisible();
|
||||||
|
});
|
||||||
|
|
@ -393,13 +393,13 @@ def test_various_prompts(client, prompt, expected_input_variables):
|
||||||
|
|
||||||
|
|
||||||
def test_get_vertices_flow_not_found(client, logged_in_headers):
|
def test_get_vertices_flow_not_found(client, logged_in_headers):
|
||||||
response = client.get("/api/v1/build/nonexistent_id/vertices", headers=logged_in_headers)
|
response = client.post("/api/v1/build/nonexistent_id/vertices", headers=logged_in_headers)
|
||||||
assert response.status_code == 500 # Or whatever status code you've set for invalid ID
|
assert response.status_code == 500 # Or whatever status code you've set for invalid ID
|
||||||
|
|
||||||
|
|
||||||
def test_get_vertices(client, added_flow_with_prompt_and_history, logged_in_headers):
|
def test_get_vertices(client, added_flow_with_prompt_and_history, logged_in_headers):
|
||||||
flow_id = added_flow_with_prompt_and_history["id"]
|
flow_id = added_flow_with_prompt_and_history["id"]
|
||||||
response = client.get(f"/api/v1/build/{flow_id}/vertices", headers=logged_in_headers)
|
response = client.post(f"/api/v1/build/{flow_id}/vertices", headers=logged_in_headers)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert "ids" in response.json()
|
assert "ids" in response.json()
|
||||||
# The response should contain the list in this order
|
# The response should contain the list in this order
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue