Merge remote-tracking branch 'origin/form_io' into python_custom_node_component

Merge remote-tracking branch 'origin/form_io' into python_custom_node_component

- Updated the README files to correct the spelling of "Langflow" in various places.
- Added a new `.env.example` file for reference and configuration.
- Updated the CONTRIBUTING.md file to use "Langflow" instead of "LangFlow".
- Updated the GCP_DEPLOYMENT.md file to use the correct GitHub repository URL.
- Updated the README file to use "Langflow" instead of "LangFlow" and corrected the formatting of the table of contents.
- Updated the CLI usage instructions in the README file to use "Langflow" and provided more detailed explanations of each option.
- Added a section on Deployment in the README file with instructions for deploying Langflow on Google Cloud Platform.
- Updated the "Creating Flows" section in the README file to use "Langflow" instead of "LangFlow" and corrected the link to the LangChain components.
- Updated the "Contributing" section in the README file to use "Langflow" instead of "LangFlow" and corrected the link to the contributing guidelines.
- Updated the "License" section in the README file to use "Langflow" instead of "LangFlow".
- Updated the version of the "anyio" package in the poetry.lock file to 3.7.1.

Merge remote-tracking branch 'origin/form_io' into python_custom_node_component

- Updated the README files to correct the spelling of "Langflow" in various places.
- Added a new `.env.example` file for reference and configuration.
- Updated the CONTRIBUTING.md file to use "Langflow" instead of "Langflow".
- Updated the GCP_DEPLOYMENT.md file to use the correct GitHub repository URL.
- Updated the README file to use "Langflow" instead of "Langflow" and corrected the formatting of the table of contents.
- Updated the CLI usage instructions in the README file to use "Langflow" and provided more detailed explanations of each option.
- Added a section on Deployment in the README file with instructions for deploying Langflow on Google Cloud Platform.
- Updated the "Creating Flows" section in the README file to use "Langflow" instead of "Langflow" and corrected the link to the LangChain components.
- Updated the "Contributing" section in the README file to use "Langflow" instead of "Langflow" and corrected the link to the contributing guidelines.
- Updated the "License" section in the README file to use "Langflow" instead of "Langflow".
- Updated the version of the "anyio" package in the poetry.lock file to 3.7.1.

Merge remote-tracking branch 'origin/form_io' into python_custom_node_component

- Updated the README files to correct the spelling of "Langflow" in various places.
- Added a new `.env.example` file for reference and configuration.
- Updated the CONTRIBUTING.md file to use "Langflow" instead of "Langflow".
- Updated the GCP_DEPLOYMENT.md file to use the correct GitHub repository URL.
- Updated the README file to use "Langflow" instead of "Langflow" and corrected the formatting of the table of contents.
- Updated the CLI usage instructions in the README file to use "Langflow" and provided more detailed explanations of each option.
- Added a section on Deployment in the README file with instructions for deploying Langflow on Google Cloud Platform.
- Updated the "Creating Flows" section in the README file to use "Langflow" instead of "Langflow" and corrected the link to the LangChain components.
- Updated the "Contributing" section in the README file to use "
This commit is contained in:
gustavoschaedler 2023-07-07 22:55:17 +01:00
commit da9764b3c5
126 changed files with 3072 additions and 1372 deletions

View file

@ -5,7 +5,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.ico" />
<title>LangFlow</title>
<script src="node_modules/ace-builds/src-min-noconflict/ace.js" type="text/javascript"></script>
<title>Langflow</title>
</head>
<body id='body' style="width: 100%; height:100%">
<noscript>You need to enable JavaScript to run this app.</noscript>

View file

@ -85,6 +85,7 @@
"daisyui": "^3.1.1",
"postcss": "^8.4.23",
"prettier": "^2.8.8",
"prettier-plugin-organize-imports": "^3.2.2",
"prettier-plugin-tailwindcss": "^0.3.0",
"tailwindcss": "^3.3.2",
"typescript": "^5.0.2",
@ -146,33 +147,33 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz",
"integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz",
"integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz",
"integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==",
"version": "7.22.8",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.8.tgz",
"integrity": "sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.22.5",
"@babel/generator": "^7.22.5",
"@babel/helper-compilation-targets": "^7.22.5",
"@babel/generator": "^7.22.7",
"@babel/helper-compilation-targets": "^7.22.6",
"@babel/helper-module-transforms": "^7.22.5",
"@babel/helpers": "^7.22.5",
"@babel/parser": "^7.22.5",
"@babel/helpers": "^7.22.6",
"@babel/parser": "^7.22.7",
"@babel/template": "^7.22.5",
"@babel/traverse": "^7.22.5",
"@babel/traverse": "^7.22.8",
"@babel/types": "^7.22.5",
"@nicolo-ribaudo/semver-v6": "^6.3.3",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.2",
"semver": "^6.3.0"
"json5": "^2.2.2"
},
"engines": {
"node": ">=6.9.0"
@ -194,9 +195,9 @@
}
},
"node_modules/@babel/generator": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz",
"integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==",
"version": "7.22.7",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz",
"integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==",
"dependencies": {
"@babel/types": "^7.22.5",
"@jridgewell/gen-mapping": "^0.3.2",
@ -208,15 +209,15 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz",
"integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz",
"integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==",
"dependencies": {
"@babel/compat-data": "^7.22.5",
"@babel/compat-data": "^7.22.6",
"@babel/helper-validator-option": "^7.22.5",
"browserslist": "^4.21.3",
"lru-cache": "^5.1.1",
"semver": "^6.3.0"
"@nicolo-ribaudo/semver-v6": "^6.3.3",
"browserslist": "^4.21.9",
"lru-cache": "^5.1.1"
},
"engines": {
"node": ">=6.9.0"
@ -297,9 +298,9 @@
}
},
"node_modules/@babel/helper-split-export-declaration": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz",
"integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dependencies": {
"@babel/types": "^7.22.5"
},
@ -332,12 +333,12 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz",
"integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
"integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
"dependencies": {
"@babel/template": "^7.22.5",
"@babel/traverse": "^7.22.5",
"@babel/traverse": "^7.22.6",
"@babel/types": "^7.22.5"
},
"engines": {
@ -358,9 +359,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz",
"integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==",
"version": "7.22.7",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz",
"integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
"bin": {
"parser": "bin/babel-parser.js"
},
@ -404,17 +405,17 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz",
"integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==",
"version": "7.22.8",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz",
"integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==",
"dependencies": {
"@babel/code-frame": "^7.22.5",
"@babel/generator": "^7.22.5",
"@babel/generator": "^7.22.7",
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-function-name": "^7.22.5",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.5",
"@babel/parser": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.22.7",
"@babel/types": "^7.22.5",
"debug": "^4.1.0",
"globals": "^11.1.0"
@ -1337,6 +1338,14 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/@nicolo-ribaudo/semver-v6": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
"integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -2662,39 +2671,6 @@
"node": ">= 10"
}
},
"node_modules/@swc/cli/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/cli/node_modules/semver": {
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/cli/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/@swc/core": {
"version": "1.3.62",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.62.tgz",
@ -4124,14 +4100,14 @@
}
},
"node_modules/bin-version-check": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-5.0.0.tgz",
"integrity": "sha512-Q3FMQnS5eZmrBGqmDXLs4dbAn/f+52voP6ykJYmweSA60t6DyH4UTSwZhtbK5UH+LBoWvDljILUQMLRUtsynsA==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-5.1.0.tgz",
"integrity": "sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g==",
"dev": true,
"dependencies": {
"bin-version": "^6.0.0",
"semver": "^7.3.5",
"semver-truncate": "^2.0.0"
"semver": "^7.5.3",
"semver-truncate": "^3.0.0"
},
"engines": {
"node": ">=12"
@ -4140,39 +4116,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/bin-version-check/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/bin-version-check/node_modules/semver": {
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/bin-version-check/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/bin-version/node_modules/execa": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@ -4306,9 +4249,9 @@
"integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow=="
},
"node_modules/browserslist": {
"version": "4.21.5",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz",
"integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==",
"version": "4.21.9",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
"integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
"funding": [
{
"type": "opencollective",
@ -4317,13 +4260,17 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"caniuse-lite": "^1.0.30001449",
"electron-to-chromium": "^1.4.284",
"node-releases": "^2.0.8",
"update-browserslist-db": "^1.0.10"
"caniuse-lite": "^1.0.30001503",
"electron-to-chromium": "^1.4.431",
"node-releases": "^2.0.12",
"update-browserslist-db": "^1.0.11"
},
"bin": {
"browserslist": "cli.js"
@ -4438,9 +4385,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001486",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz",
"integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==",
"version": "1.0.30001513",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001513.tgz",
"integrity": "sha512-pnjGJo7SOOjAGytZZ203Em95MRM8Cr6jhCXNF/FAXTpCTRTECnqQWLpiTRqrFtdYcth8hf4WECUpkezuYsMVww==",
"funding": [
{
"type": "opencollective",
@ -8616,6 +8563,26 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-plugin-organize-imports": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.2.tgz",
"integrity": "sha512-e97lE6odGSiHonHJMTYC0q0iLXQyw0u5z/PJpvP/3vRy6/Zi9kLBwFAbEGjDzIowpjQv8b+J04PDamoUSQbzGA==",
"dev": true,
"peerDependencies": {
"@volar/vue-language-plugin-pug": "^1.0.4",
"@volar/vue-typescript": "^1.0.4",
"prettier": ">=2.0",
"typescript": ">=2.9"
},
"peerDependenciesMeta": {
"@volar/vue-language-plugin-pug": {
"optional": true
},
"@volar/vue-typescript": {
"optional": true
}
}
},
"node_modules/prettier-plugin-tailwindcss": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.3.0.tgz",
@ -9507,11 +9474,18 @@
}
},
"node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "7.5.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
"integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/semver-regex": {
@ -9527,17 +9501,38 @@
}
},
"node_modules/semver-truncate": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-2.0.0.tgz",
"integrity": "sha512-Rh266MLDYNeML5h90ttdMwfXe1+Nc4LAWd9X1KdJe8pPHP4kFmvLZALtsMNHNdvTyQygbEC0D59sIz47DIaq8w==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-3.0.0.tgz",
"integrity": "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==",
"dev": true,
"dependencies": {
"semver": "^6.0.0"
"semver": "^7.3.5"
},
"engines": {
"node": ">=8"
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semver/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/semver/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/shadcn-ui": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/shadcn-ui/-/shadcn-ui-0.2.2.tgz",

View file

@ -106,6 +106,7 @@
"daisyui": "^3.1.1",
"postcss": "^8.4.23",
"prettier": "^2.8.8",
"prettier-plugin-organize-imports": "^3.2.2",
"prettier-plugin-tailwindcss": "^0.3.0",
"tailwindcss": "^3.3.2",
"typescript": "^5.0.2",

View file

@ -1,20 +1,19 @@
import "reactflow/dist/style.css";
import { useState, useEffect, useContext } from "react";
import "./App.css";
import { useLocation } from "react-router-dom";
import _ from "lodash";
import { useContext, useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import "reactflow/dist/style.css";
import "./App.css";
import { ErrorBoundary } from "react-error-boundary";
import ErrorAlert from "./alerts/error";
import NoticeAlert from "./alerts/notice";
import SuccessAlert from "./alerts/success";
import CrashErrorComponent from "./components/CrashErrorComponent";
import Header from "./components/headerComponent";
import { alertContext } from "./contexts/alertContext";
import { locationContext } from "./contexts/locationContext";
import { ErrorBoundary } from "react-error-boundary";
import CrashErrorComponent from "./components/CrashErrorComponent";
import { TabsContext } from "./contexts/tabsContext";
import { getVersion } from "./controllers/API";
import Router from "./routes";
import Header from "./components/headerComponent";
export default function App() {
let { setCurrent, setShowSideBar, setIsStackedOpen } =
@ -138,10 +137,7 @@ export default function App() {
<Router />
</ErrorBoundary>
<div></div>
<div
className="fixed bottom-5 left-5 flex flex-col-reverse"
style={{ zIndex: 999 }}
>
<div className="app-div" style={{ zIndex: 999 }}>
{alertsList.map((alert) => (
<div key={alert.id}>
{alert.type === "error" ? (

View file

@ -1,31 +1,30 @@
import { Info } from "lucide-react";
import React, { useContext, useEffect, useRef, useState } from "react";
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import CodeAreaComponent from "../../../../components/codeAreaComponent";
import Dropdown from "../../../../components/dropdownComponent";
import FloatComponent from "../../../../components/floatComponent";
import InputComponent from "../../../../components/inputComponent";
import InputFileComponent from "../../../../components/inputFileComponent";
import InputListComponent from "../../../../components/inputListComponent";
import IntComponent from "../../../../components/intComponent";
import PromptAreaComponent from "../../../../components/promptComponent";
import TextAreaComponent from "../../../../components/textAreaComponent";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
import { PopUpContext } from "../../../../contexts/popUpContext";
import { TabsContext } from "../../../../contexts/tabsContext";
import { typesContext } from "../../../../contexts/typesContext";
import { ParameterComponentType } from "../../../../types/components";
import {
classNames,
getRandomKeyByssmm,
groupByFamily,
isValidConnection,
nodeColors,
nodeIconsLucide,
nodeNames,
} from "../../../../utils";
import { useContext, useEffect, useRef, useState } from "react";
import InputComponent from "../../../../components/inputComponent";
import InputListComponent from "../../../../components/inputListComponent";
import TextAreaComponent from "../../../../components/textAreaComponent";
import { typesContext } from "../../../../contexts/typesContext";
import { ParameterComponentType } from "../../../../types/components";
import FloatComponent from "../../../../components/floatComponent";
import Dropdown from "../../../../components/dropdownComponent";
import CodeAreaComponent from "../../../../components/codeAreaComponent";
import InputFileComponent from "../../../../components/inputFileComponent";
import { TabsContext } from "../../../../contexts/tabsContext";
import IntComponent from "../../../../components/intComponent";
import PromptAreaComponent from "../../../../components/promptComponent";
import { nodeNames } from "../../../../utils";
import React from "react";
import { nodeColors } from "../../../../utils";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import { PopUpContext } from "../../../../contexts/popUpContext";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
import { Info } from "lucide-react";
export default function ParameterComponent({
left,
@ -223,7 +222,7 @@ export default function ParameterComponent({
/>
) : data.node.template[name].multiline ? (
<TextAreaComponent
disabled={disabled}
disabled={false}
value={data.node.template[name].value ?? ""}
onChange={handleOnNewValue}
/>

View file

@ -1,3 +1,15 @@
import { Zap } from "lucide-react";
import { useContext, useEffect, useRef, useState } from "react";
import { NodeToolbar } from "reactflow";
import ShadTooltip from "../../components/ShadTooltipComponent";
import Tooltip from "../../components/TooltipComponent";
import { useSSE } from "../../contexts/SSEContext";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { typesContext } from "../../contexts/typesContext";
import NodeModal from "../../modals/NodeModal";
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
import { NodeDataType } from "../../types/flow";
import {
classNames,
nodeColors,
@ -5,17 +17,6 @@ import {
toTitleCase,
} from "../../utils";
import ParameterComponent from "./components/parameterComponent";
import { typesContext } from "../../contexts/typesContext";
import { useContext, useState, useEffect, useRef } from "react";
import { NodeDataType } from "../../types/flow";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import NodeModal from "../../modals/NodeModal";
import Tooltip from "../../components/TooltipComponent";
import { NodeToolbar } from "reactflow";
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
import ShadTooltip from "../../components/ShadTooltipComponent";
import { useSSE } from "../../contexts/SSEContext";
export default function GenericNode({
data,
@ -80,30 +81,27 @@ export default function GenericNode({
<div
className={classNames(
selected ? "border border-ring" : "border",
"prompt-node relative flex w-96 flex-col justify-center rounded-lg bg-background"
"generic-node-div"
)}
>
<div className="flex w-full items-center justify-between gap-8 rounded-t-lg border-b bg-muted p-4 ">
<div className="flex w-full items-center truncate">
<div className="generic-node-div-title">
<div className="generic-node-title-arrangement">
<Icon
strokeWidth={1.5}
className="h-10 w-10 rounded p-1"
className="generic-node-icon"
style={{
color: nodeColors[types[data.type]] ?? nodeColors.unknown,
}}
/>
<div className="ml-2 flex-1 truncate">
<ShadTooltip
delayDuration={1500}
content={data.node.display_name}
>
<div className="ml-2 truncate text-primary">
<div className="generic-node-tooltip-div">
<ShadTooltip content={data.node.display_name}>
<div className="generic-node-tooltip-div text-primary">
{data.node.display_name}
</div>
</ShadTooltip>
</div>
</div>
<div className="flex gap-3">
<div className="round-button-div">
<button
className="relative"
onClick={(event) => {
@ -112,12 +110,19 @@ export default function GenericNode({
}}
></button>
</div>
<div className="flex gap-3">
<div className="round-button-div">
<div>
<Tooltip
title={
!validationStatus ? (
"Validating..."
<span className="flex">
Build{" "}
<Zap
className="mx-0.5 h-5 fill-build-trigger stroke-build-trigger stroke-1"
strokeWidth={1.5}
/>{" "}
flow to validate status.
</span>
) : (
<div className="max-h-96 overflow-auto">
{validationStatus.params
@ -129,29 +134,29 @@ export default function GenericNode({
)
}
>
<div className="relative top-[3px] h-5 w-5">
<div className="generic-node-status-position">
<div
className={classNames(
validationStatus && validationStatus.valid
? "h-4 w-4 rounded-full bg-status-green opacity-100"
: "hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0",
"absolute w-4 duration-200 ease-in-out hover:text-accent-foreground hover:transition-all"
? "green-status"
: "status-build-animation",
"status-div"
)}
></div>
<div
className={classNames(
validationStatus && !validationStatus.valid
? "h-4 w-4 rounded-full bg-status-red opacity-100"
: "hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0",
"absolute w-4 duration-200 ease-in-out hover:text-accent-foreground hover:transition-all"
? "red-status"
: "status-build-animation",
"status-div"
)}
></div>
<div
className={classNames(
!validationStatus || isBuilding
? "h-4 w-4 rounded-full bg-status-yellow opacity-100"
: "hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0",
"absolute w-4 duration-200 ease-in-out hover:text-accent-foreground hover:transition-all"
? "yellow-status"
: "status-build-animation",
"status-div"
)}
></div>
</div>
@ -160,10 +165,8 @@ export default function GenericNode({
</div>
</div>
<div className="h-full w-full py-5 text-foreground">
<div className="w-full px-5 pb-3 text-sm text-muted-foreground">
{data.node.description}
</div>
<div className="generic-node-desc">
<div className="generic-node-desc-text">{data.node.description}</div>
<>
{Object.keys(data.node.template)
@ -232,7 +235,7 @@ export default function GenericNode({
<div
className={classNames(
Object.keys(data.node.template).length < 1 ? "hidden" : "",
"flex w-full justify-center"
"flex-max-width justify-center"
)}
>
{" "}

View file

@ -1,8 +1,8 @@
import { Link } from "react-router-dom";
import { Transition } from "@headlessui/react";
import { CheckCircle2, Info, X, XCircle } from "lucide-react";
import { useState } from "react";
import { Link } from "react-router-dom";
import { SingleAlertComponentType } from "../../../../types/alerts";
import { X, CheckCircle2, Info, XCircle } from "lucide-react";
export default function SingleAlert({
dropItem,

View file

@ -1,10 +1,10 @@
import { useContext, useEffect, useRef } from "react";
import { Trash2, X } from "lucide-react";
import { useContext, useRef } from "react";
import { alertContext } from "../../contexts/alertContext";
import SingleAlert from "./components/singleAlertComponent";
import { AlertDropdownType } from "../../types/alerts";
import { PopUpContext } from "../../contexts/popUpContext";
import { AlertDropdownType } from "../../types/alerts";
import { useOnClickOutside } from "../hooks/useOnClickOutside";
import { X, Trash2 } from "lucide-react";
import SingleAlert from "./components/singleAlertComponent";
export default function AlertDropdown({}: AlertDropdownType) {
const { closePopUp } = useContext(PopUpContext);

View file

@ -1,7 +1,7 @@
import { Transition } from "@headlessui/react";
import { XCircle } from "lucide-react";
import { useEffect, useState } from "react";
import { ErrorAlertType } from "../../types/alerts";
import { XCircle } from "lucide-react";
export default function ErrorAlert({
title,
@ -39,19 +39,20 @@ export default function ErrorAlert({
removeAlert(id);
}, 500);
}}
className="mt-6 w-96 cursor-pointer rounded-md bg-error-background p-4 shadow-xl"
className="error-build-message"
>
<div className="flex">
<div className="flex-shrink-0">
<XCircle className="h-5 w-5 text-status-red" aria-hidden="true" />
<XCircle
className="error-build-message-circle"
aria-hidden="true"
/>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-error-foreground">
{title}
</h3>
<h3 className="error-build-foreground">{title}</h3>
{list.length !== 0 ? (
<div className="mt-2 text-sm text-error-foreground">
<ul className="list-disc space-y-1 pl-5">
<div className="error-build-message-div">
<ul className="error-build-message-list">
{list.map((item, index) => (
<li key={index}>{item}</li>
))}

View file

@ -1,8 +1,8 @@
import { Transition } from "@headlessui/react";
import { Info } from "lucide-react";
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { NoticeAlertType } from "../../types/alerts";
import { Info } from "lucide-react";
export default function NoticeAlert({
title,

View file

@ -1,7 +1,7 @@
import { Transition } from "@headlessui/react";
import { CheckCircle2 } from "lucide-react";
import { useEffect, useState } from "react";
import { SuccessAlertType } from "../../types/alerts";
import { CheckCircle2 } from "lucide-react";
export default function SuccessAlert({
title,
@ -34,19 +34,14 @@ export default function SuccessAlert({
setShow(false);
removeAlert(id);
}}
className="mt-6 w-96 rounded-md bg-success-background p-4 shadow-xl"
className="success-alert"
>
<div className="flex">
<div className="flex-shrink-0">
<CheckCircle2
className="h-5 w-5 text-status-green"
aria-hidden="true"
/>
<CheckCircle2 className="success-alert-icon" aria-hidden="true" />
</div>
<div className="ml-3">
<p className="text-sm font-medium text-success-foreground">
{title}
</p>
<p className="success-alert-message">{title}</p>
</div>
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,16 +1,11 @@
import { ReactElement, useContext, useEffect, useRef, useState } from "react";
import {
AccordionComponentType,
ProgressBarType,
} from "../../types/components";
import { Progress } from "../../components/ui/progress";
import { setInterval } from "timers/promises";
import { useState } from "react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "../../components/ui/accordion";
import { AccordionComponentType } from "../../types/components";
export default function AccordionComponent({
trigger,

View file

@ -1,7 +1,7 @@
import React, { useState, ChangeEvent } from "react";
import { Textarea } from "../../components/ui/textarea";
import { Label } from "../../components/ui/label";
import React, { ChangeEvent, useState } from "react";
import { Input } from "../../components/ui/input";
import { Label } from "../../components/ui/label";
import { Textarea } from "../../components/ui/textarea";
type InputProps = {
name: string | null;
@ -44,12 +44,10 @@ export const EditFlowSettings: React.FC<InputProps> = ({
return (
<>
<Label>
<div className="flex justify-between">
<div className="edit-flow-arrangement">
<span className="font-medium">Name</span>{" "}
{isMaxLength && (
<span className="ml-10 animate-pulse text-status-red">
Character limit reached
</span>
<span className="edit-flow-span">Character limit reached</span>
)}
</div>
<Input

View file

@ -1,8 +1,8 @@
import { Disclosure } from "@headlessui/react";
import { useContext, useState } from "react";
import { useContext } from "react";
import { Link } from "react-router-dom";
import { classNames } from "../../utils";
import { locationContext } from "../../contexts/locationContext";
import { classNames } from "../../utils";
export default function ExtraSidebar() {
const {
@ -16,15 +16,13 @@ export default function ExtraSidebar() {
return (
<>
<aside
className={` ${
isStackedOpen ? "w-52" : "w-0 "
} flex flex-shrink-0 flex-col overflow-hidden border-r transition-all duration-500`}
className={` ${isStackedOpen ? "w-52" : "w-0 "} unused-side-bar-aside`}
>
<div className="flex h-full w-52 flex-col items-start overflow-y-auto border bg-background scrollbar-hide">
<div className="flex w-full flex-grow flex-col">
<div className="unused-side-bar-arrangement">
<div className="unused-side-bar-division">
{extraNavigation.options ? (
<div className="p-4">
<nav className="flex-1 space-y-1">
<nav className="unused-side-bar-nav">
{extraNavigation.options.map((item) =>
!item.children ? (
<div key={item.name}>
@ -32,17 +30,17 @@ export default function ExtraSidebar() {
to={item.href}
className={classNames(
item.href.split("/")[2] === current[4]
? "bg-muted text-foreground"
: "bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
"group flex w-full items-center rounded-md py-2 pl-2 text-sm font-medium"
? "unused-side-bar-link-colors-true"
: "unused-side-bar-link-colors-false",
"unused-side-bar-link"
)}
>
<item.icon
className={classNames(
item.href.split("/")[2] === current[4]
? "text-ring"
: "text-ring group-hover:text-accent-foreground",
"mr-3 h-6 w-6 flex-shrink-0"
: "unused-side-bar-icon-false",
"unused-side-bar-icon"
)}
/>
{item.name}
@ -59,20 +57,22 @@ export default function ExtraSidebar() {
<Disclosure.Button
className={classNames(
item.href.split("/")[2] === current[4]
? "bg-muted text-foreground"
: "bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
"group flex w-full items-center rounded-md py-2 pl-2 pr-1 text-left text-sm font-medium focus:outline-none focus:ring-1 focus:ring-ring"
? "unused-side-bar-link-colors-true"
: "unused-side-bar-link-colors-false",
"unused-side-bar-disclosure"
)}
>
<item.icon
className="mr-3 h-6 w-6 flex-shrink-0 text-ring group-hover:text-accent-foreground"
className="unused-side-bar-disclosure-icon"
aria-hidden="true"
/>
<span className="flex-1">{item.name}</span>
<svg
className={classNames(
open ? "rotate-90 text-ring" : "text-ring",
"transition-rotate ml-3 h-5 w-5 flex-shrink-0 duration-150 ease-in-out group-hover:text-accent-foreground"
open
? "unused-side-bar-svg-true"
: "text-ring",
"unused-side-bar-svg"
)}
viewBox="0 0 20 20"
aria-hidden="true"
@ -90,9 +90,9 @@ export default function ExtraSidebar() {
to={subItem.href}
className={classNames(
subItem.href.split("/")[3] === current[5]
? "bg-muted text-foreground"
: "bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
"group flex w-full items-center rounded-md py-2 pl-11 pr-2 text-sm font-medium"
? "unused-side-bar-link-colors-true"
: "unused-side-bar-link-colors-false",
"unused-side-bar-disclosure-panel"
)}
>
{subItem.name}

View file

@ -1,5 +1,5 @@
import { styled } from "@mui/material/styles";
import Tooltip, { TooltipProps, tooltipClasses } from "@mui/material/Tooltip";
import { styled } from "@mui/material/styles";
export const LightTooltip = styled(({ className, ...props }: TooltipProps) => (
<Tooltip {...props} classes={{ popper: className }} />

View file

@ -1,6 +1,3 @@
import { useContext, useEffect, useRef, useState } from "react";
import { RadialProgressType } from "../../types/components";
export default function LoadingSpinner({}) {
return <></>;
}

View file

@ -1,4 +1,3 @@
import { useContext, useEffect, useRef, useState } from "react";
import { RadialProgressType } from "../../types/components";
export default function RadialProgressComponent({

View file

@ -1,4 +1,4 @@
import { RadialProgressType, ShadToolTipType } from "../../types/components";
import { ShadToolTipType } from "../../types/components";
import {
Tooltip,
TooltipContent,
@ -11,14 +11,20 @@ export default function ShadTooltip({
side,
asChild = true,
children,
delayDuration,
style,
delayDuration = 500,
}: ShadToolTipType) {
return (
<TooltipProvider>
<Tooltip delayDuration={delayDuration}>
<TooltipTrigger asChild={asChild}>{children}</TooltipTrigger>
<TooltipContent side={side} avoidCollisions={false} sticky="always">
<TooltipContent
className={style}
side={side}
avoidCollisions={false}
sticky="always"
>
{content}
</TooltipContent>
</Tooltip>

View file

@ -1,6 +1,5 @@
import { ReactElement } from "react";
import { LightTooltip } from "../LightTooltipComponent";
import { TooltipComponentType } from "../../types/components";
import { LightTooltip } from "../LightTooltipComponent";
export default function Tooltip({
children,

View file

@ -1,26 +1,15 @@
import { Trash2, ExternalLink } from "lucide-react";
import { Trash2 } from "lucide-react";
import { useContext } from "react";
import { Link } from "react-router-dom";
import { TabsContext } from "../../contexts/tabsContext";
import { FlowType } from "../../types/flow";
import { gradients } from "../../utils";
import {
CardTitle,
Card,
CardDescription,
CardFooter,
Card,
CardHeader,
CardTitle,
} from "../ui/card";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../ui/dialog";
import { Button } from "@mui/material";
export const CardComponent = ({
flow,
@ -38,42 +27,22 @@ export const CardComponent = ({
return (
<Card className="group">
<CardHeader>
<CardTitle className="flex w-full items-center gap-4">
<CardTitle className="card-component-title-display">
<span
className={
"flex h-7 w-7 items-center justify-center rounded-full text-2xl " +
"card-component-image " +
gradients[parseInt(flow.id.slice(0, 12), 16) % gradients.length]
}
></span>
<span className="inline-block w-full flex-1 break-words truncate-doubleline">
{flow.name}
</span>
<span className="card-component-title-size">{flow.name}</span>
{onDelete && (
<Dialog>
<DialogTrigger asChild>
<button className="flex self-start">
<Trash2 className="h-4 w-4 text-primary opacity-0 transition-all group-hover:opacity-100" />
</button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you sure absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. Are you sure you want to
permanently delete this file from our servers?
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button type="submit" onClick={onDelete}>
Confirm
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<button className="card-component-delete-button" onClick={onDelete}>
<Trash2 className="card-component-delete-icon" />
</button>
)}
</CardTitle>
<CardDescription className="pb-2 pt-2">
<div className="truncate-doubleline">
<CardDescription className="card-component-desc">
<div className="card-component-desc-text">
{flow.description}
{/* {flow.description} */}
</div>
@ -81,8 +50,8 @@ export const CardComponent = ({
</CardHeader>
<CardFooter>
<div className="flex w-full items-end justify-between gap-2">
<div className="flex flex-wrap gap-2">
<div className="card-component-footer-arrangement">
<div className="card-component-footer">
{/* <Badge variant="secondary">Agent</Badge>
<Badge variant="secondary">
<div className="w-3">

View file

@ -1,16 +1,16 @@
import { useContext, useState } from "react";
import { Transition } from "@headlessui/react";
import { Zap } from "lucide-react";
import { validateNodes } from "../../../utils";
import { FlowType } from "../../../types/flow";
import { useContext, useState } from "react";
import Loading from "../../../components/ui/loading";
import { useSSE } from "../../../contexts/SSEContext";
import { typesContext } from "../../../contexts/typesContext";
import { alertContext } from "../../../contexts/alertContext";
import { typesContext } from "../../../contexts/typesContext";
import { postBuildInit } from "../../../controllers/API";
import { FlowType } from "../../../types/flow";
import { validateNodes } from "../../../utils";
import RadialProgressComponent from "../../RadialProgress";
import { TabsContext } from "../../../contexts/tabsContext";
import RadialProgressComponent from "../../RadialProgress";
export default function BuildTrigger({
open,
@ -168,7 +168,7 @@ export default function BuildTrigger({
>
<div className="fixed bottom-20 right-4">
<div
className={`${eventClick} align-center shadow-round-btn-shadow hover:shadow-round-btn-shadow flex h-12 w-12 cursor-pointer justify-center rounded-full bg-border px-3 py-1 shadow-md`}
className={`${eventClick} round-button-form`}
onClick={() => {
handleBuild(flow);
}}
@ -176,7 +176,7 @@ export default function BuildTrigger({
onMouseLeave={handleMouseLeave}
>
<button>
<div className="flex items-center gap-3">
<div className="round-button-div">
{isBuilding && progress < 1 ? (
// Render your loading animation here when isBuilding is true
<RadialProgressComponent
@ -185,7 +185,10 @@ export default function BuildTrigger({
value={progress}
></RadialProgressComponent>
) : isBuilding ? (
<Loading strokeWidth={1.5} className="stroke-build-trigger" />
<Loading
strokeWidth={1.5}
className="build-trigger-loading-icon"
/>
) : (
<Zap
strokeWidth={1.5}

View file

@ -1,55 +0,0 @@
import { useState } from "react";
import { ChatMessageType } from "../../../types/chat";
import { nodeColors } from "../../../utils";
import Convert from "ansi-to-html";
import { MessageCircle } from "lucide-react";
import DOMPurify from "dompurify";
const convert = new Convert({ newline: true });
export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
const [hidden, setHidden] = useState(true);
return (
<div>
{!chat.isSend ? (
<div className="w-full text-start">
<div
style={{ backgroundColor: nodeColors["chat"] }}
className=" relative inline-block w-fit max-w-[280px] overflow-hidden rounded-xl rounded-tl-none text-start text-sm font-normal text-background"
>
{hidden && chat.thought && chat.thought !== "" && (
<div
onClick={() => setHidden((prev) => !prev)}
className="absolute right-2 top-2 cursor-pointer"
>
<MessageCircle className="h-5 w-5 animate-bounce" />
</div>
)}
{chat.thought && chat.thought !== "" && !hidden && (
<div
onClick={() => setHidden((prev) => !prev)}
style={{ backgroundColor: nodeColors["thought"] }}
className=" inline-block w-full cursor-pointer px-5 pb-3 pt-3 text-start"
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
}}
></div>
)}
{chat.thought && chat.thought !== "" && !hidden && <br></br>}
<div
className="w-full rounded-b-md px-4 pb-3 pr-8 pt-3"
style={{ backgroundColor: nodeColors["chat"] }}
>
{chat.message}
</div>
</div>
</div>
) : (
<div className="w-full text-end">
<div className="inline-block w-fit max-w-[280px] overflow-hidden rounded-xl rounded-tr-none bg-input p-3 px-5 text-start text-sm font-normal text-black">
{chat.message}
</div>
</div>
)}
</div>
);
}

View file

@ -1,7 +1,6 @@
import { Transition } from "@headlessui/react";
import { MessagesSquare } from "lucide-react";
import { alertContext } from "../../../contexts/alertContext";
import { useContext } from "react";
import {
CHAT_CANNOT_OPEN_DESCRIPTION,
@ -9,6 +8,7 @@ import {
FLOW_NOT_BUILT_DESCRIPTION,
FLOW_NOT_BUILT_TITLE,
} from "../../../constants";
import { alertContext } from "../../../contexts/alertContext";
export default function ChatTrigger({ open, setOpen, isBuilt, canOpen }) {
const { setErrorData } = useContext(alertContext);
@ -45,7 +45,7 @@ export default function ChatTrigger({ open, setOpen, isBuilt, canOpen }) {
<button
onClick={handleClick}
className={
"shadow-round-btn-shadow hover:shadow-round-btn-shadow fixed bottom-4 right-4 flex h-12 w-12 items-center justify-center rounded-full bg-border px-3 py-1 shadow-md transition-all " +
"shadow-round-btn-shadow hover:shadow-round-btn-shadow message-button " +
(!isBuilt || !canOpen ? "cursor-not-allowed" : "cursor-pointer")
}
>
@ -54,8 +54,8 @@ export default function ChatTrigger({ open, setOpen, isBuilt, canOpen }) {
className={
"h-6 w-6 transition-all " +
(isBuilt && canOpen
? "fill-chat-trigger stroke-chat-trigger stroke-1"
: "fill-chat-trigger-disabled stroke-chat-trigger-disabled stroke-1")
? "message-button-icon"
: "disabled-message-button-icon")
}
style={{ color: "white" }}
strokeWidth={1.5}

View file

@ -1,14 +1,14 @@
import { useContext, useEffect, useRef, useState } from "react";
import { useNodes } from "reactflow";
import { ChatType } from "../../types/chat";
import ChatTrigger from "./chatTrigger";
import BuildTrigger from "./buildTrigger";
import ChatTrigger from "./chatTrigger";
import { getBuildStatus } from "../../controllers/API";
import { NodeType } from "../../types/flow";
import FormModal from "../../modals/formModal";
import { TabsContext } from "../../contexts/tabsContext";
import * as _ from "lodash";
import { TabsContext } from "../../contexts/tabsContext";
import { getBuildStatus } from "../../controllers/API";
import FormModal from "../../modals/formModal";
import { NodeType } from "../../types/flow";
export default function Chat({ flow }: ChatType) {
const [open, setOpen] = useState(false);

View file

@ -1,10 +1,9 @@
import { Listbox, Transition } from "@headlessui/react";
import { Check, ChevronsUpDown } from "lucide-react";
import { Fragment, useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { DropDownComponentType } from "../../types/components";
import { classNames } from "../../utils";
import { ChevronsUpDown, Check } from "lucide-react";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
export default function Dropdown({
value,
@ -39,20 +38,16 @@ export default function Dropdown({
<Listbox.Button
className={
editNode
? "border-1 input-edit-node relative pr-8"
: "input-primary py-2 pl-3 pr-10 text-left"
? "dropdown-component-outline"
: "dropdown-component-false-outline"
}
>
<span className="block w-full truncate bg-background">
<span className="dropdown-component-display">
{internalValue}
</span>
<span
className={
"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
}
>
<span className={"dropdown-component-arrow"}>
<ChevronsUpDown
className="h-5 w-5 text-muted-foreground"
className="dropdown-component-arrow-color"
aria-hidden="true"
/>
</span>
@ -68,8 +63,8 @@ export default function Dropdown({
<Listbox.Options
className={classNames(
editNode
? "z-10 mt-1 max-h-60 w-[215px] overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
: "nowheel overflow-y z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm ",
? "dropdown-component-true-options nowheel"
: "dropdown-component-false-options nowheel",
apiModal ? "mb-2 w-[250px]" : "absolute"
)}
>
@ -80,8 +75,8 @@ export default function Dropdown({
classNames(
active ? " bg-accent" : "",
editNode
? "relative cursor-default select-none py-0.5 pl-3 pr-12"
: "relative cursor-default select-none py-2 pl-3 pr-9"
? "dropdown-component-false-option"
: "dropdown-component-true-option"
)
}
value={option}
@ -101,14 +96,14 @@ export default function Dropdown({
<span
className={classNames(
active ? "text-background " : "",
"absolute inset-y-0 right-0 flex items-center pr-4"
"dropdown-component-choosal"
)}
>
<Check
className={
active
? "h-5 w-5 text-black"
: "h-5 w-5 text-black"
? "dropdown-component-check-icon"
: "dropdown-component-check-icon"
}
aria-hidden="true"
/>

View file

@ -1,7 +1,7 @@
import { useContext, useEffect, useState } from "react";
import { FloatComponentType } from "../../types/components";
import { TabsContext } from "../../contexts/tabsContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { FloatComponentType } from "../../types/components";
export default function FloatComponent({
value,
@ -30,11 +30,7 @@ export default function FloatComponent({
}, [closePopUp]);
return (
<div
className={
"w-full " + (disabled ? "pointer-events-none cursor-not-allowed" : "")
}
>
<div className={"w-full " + (disabled ? "float-component-pointer" : "")}>
<input
onFocus={() => {
if (disableCopyPaste) setDisableCopyPaste(true);

View file

@ -1,27 +1,25 @@
import { useContext } from "react";
import { TabsContext } from "../../../../contexts/tabsContext";
import { PopUpContext } from "../../../../contexts/popUpContext";
import {
Plus,
ChevronDown,
ChevronLeft,
Undo,
Plus,
Redo,
Settings2,
Undo,
} from "lucide-react";
import { useContext } from "react";
import { PopUpContext } from "../../../../contexts/popUpContext";
import { TabsContext } from "../../../../contexts/tabsContext";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "../../../ui/dropdown-menu";
import { alertContext } from "../../../../contexts/alertContext";
import { Link, useNavigate } from "react-router-dom";
import { alertContext } from "../../../../contexts/alertContext";
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
import FlowSettingsModal from "../../../../modals/flowSettingsModal";
import { Button } from "../../../ui/button";
@ -47,19 +45,19 @@ export const MenuBar = ({ flows, tabId }) => {
let current_flow = flows.find((flow) => flow.id === tabId);
return (
<div className="flex items-center gap-2">
<div className="round-button-div">
<Link to="/">
<ChevronLeft className="w-4" />
</Link>
<div className="flex items-center gap-0.5 rounded-md px-1.5 py-1 text-sm font-medium">
<div className="header-menu-bar">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
className="flex max-w-[200px] items-center gap-2"
className="header-menu-bar-display"
variant="primary"
size="sm"
>
<div className="flex-1 truncate">{current_flow.name}</div>
<div className="header-menu-flow-name">{current_flow.name}</div>
<ChevronDown className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
@ -71,7 +69,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Plus className="mr-2 h-4 w-4" />
<Plus className="header-menu-options" />
New
</DropdownMenuItem>
<DropdownMenuItem
@ -80,7 +78,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Settings2 className="mr-2 h-4 w-4 " />
<Settings2 className="header-menu-options " />
Settings
</DropdownMenuItem>
<DropdownMenuItem
@ -89,7 +87,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Undo className="mr-2 h-4 w-4 " />
<Undo className="header-menu-options " />
Undo
</DropdownMenuItem>
<DropdownMenuItem
@ -98,7 +96,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Redo className="mr-2 h-4 w-4 " />
<Redo className="header-menu-options " />
Redo
</DropdownMenuItem>
<DropdownMenuSeparator />

View file

@ -1,19 +1,18 @@
import { BellIcon, Home, MoonIcon, SunIcon, Users2 } from "lucide-react";
import { Bell, Home, MoonIcon, SunIcon, Users2 } from "lucide-react";
import { useContext, useEffect, useState } from "react";
import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa";
import { Button } from "../ui/button";
import { TabsContext } from "../../contexts/tabsContext";
import { Link, useLocation, useParams } from "react-router-dom";
import AlertDropdown from "../../alerts/alertDropDown";
import { USER_PROJECTS_HEADER } from "../../constants";
import { alertContext } from "../../contexts/alertContext";
import { darkContext } from "../../contexts/darkContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { typesContext } from "../../contexts/typesContext";
import MenuBar from "./components/menuBar";
import { Link, useLocation, useParams } from "react-router-dom";
import { USER_PROJECTS_HEADER } from "../../constants";
import { getRepoStars } from "../../controllers/API";
import { Button } from "../ui/button";
import { Separator } from "../ui/separator";
import { Bell } from "lucide-react";
import MenuBar from "./components/menuBar";
export default function Header() {
const { flows, addFlow, tabId } = useContext(TabsContext);
@ -36,8 +35,8 @@ export default function Header() {
fetchStars();
}, []);
return (
<div className="flex h-12 w-full items-center justify-between border-b bg-muted">
<div className="flex w-96 items-center justify-start gap-2">
<div className="header-arrangement">
<div className="header-start-display">
<Link to="/">
<span className="ml-4 text-2xl">⛓️</span>
</Link>
@ -45,7 +44,7 @@ export default function Header() {
<MenuBar flows={flows} tabId={tabId} />
)}
</div>
<div className="flex items-center gap-2">
<div className="round-button-div">
<Link to="/">
<Button
className="gap-2"
@ -69,19 +68,17 @@ export default function Header() {
</Button>
</Link>
</div>
<div className="flex w-96 justify-end px-2">
<div className="ml-auto mr-2 flex items-center gap-5">
<div className="header-end-division">
<div className="header-end-display">
<a
href="https://github.com/logspace-ai/langflow"
target="_blank"
rel="noreferrer"
className="inline-flex h-9 items-center justify-center rounded-md border border-input px-3 pr-0 text-sm font-medium text-muted-foreground shadow-sm ring-offset-background hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
className="header-github-link"
>
<FaGithub className="mr-2 h-5 w-5" />
Star
<div className="-mr-px ml-2 flex h-9 items-center justify-center rounded-md rounded-l-none border bg-background px-2 text-sm">
{stars}
</div>
<div className="header-github-display">{stars}</div>
</a>
<a
href="https://twitter.com/logspace_ai"
@ -89,7 +86,7 @@ export default function Header() {
rel="noreferrer"
className="text-muted-foreground"
>
<FaTwitter className="h-5 w-5 hover:text-accent-foreground" />
<FaTwitter className="side-bar-button-size" />
</a>
<a
href="https://discord.gg/EqksyE2EX9"
@ -97,24 +94,24 @@ export default function Header() {
rel="noreferrer"
className="text-muted-foreground"
>
<FaDiscord className="h-5 w-5 hover:text-accent-foreground" />
<FaDiscord className="side-bar-button-size" />
</a>
<Separator orientation="vertical" />
<button
className="text-muted-foreground hover:text-accent-foreground "
className="extra-side-bar-save-disable"
onClick={() => {
setDark(!dark);
}}
>
{dark ? (
<SunIcon className="h-5 w-5" />
<SunIcon className="side-bar-button-size" />
) : (
<MoonIcon className="h-5 w-5" />
<MoonIcon className="side-bar-button-size" />
)}
</button>
<button
className="relative text-muted-foreground hover:text-accent-foreground"
className="extra-side-bar-save-disable relative"
onClick={(event: React.MouseEvent<HTMLElement>) => {
setNotificationCenter(false);
const { top, left } = (
@ -128,15 +125,13 @@ export default function Header() {
>
<AlertDropdown />
</div>
<div className="fixed left-0 top-0 h-screen w-screen"></div>
<div className="header-notifications-box"></div>
</>
);
}}
>
{notificationCenter && (
<div className="absolute right-[3px] h-1.5 w-1.5 rounded-full bg-destructive"></div>
)}
<Bell className="h-5 w-5" aria-hidden="true" />
{notificationCenter && <div className="header-notifications"></div>}
<Bell className="side-bar-button-size" aria-hidden="true" />
</button>
</div>
</div>

View file

@ -1,8 +1,8 @@
import { useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { InputComponentType } from "../../types/components";
import { classNames } from "../../utils";
import { TabsContext } from "../../contexts/tabsContext";
import { PopUpContext } from "../../contexts/popUpContext";
export default function InputComponent({
value,
@ -29,13 +29,7 @@ export default function InputComponent({
}, [closePopUp]);
return (
<div
className={
disabled
? "pointer-events-none relative cursor-not-allowed"
: "relative"
}
>
<div className={disabled ? "input-component-div" : "relative"}>
<input
value={myValue}
onFocus={() => {
@ -45,7 +39,7 @@ export default function InputComponent({
if (disableCopyPaste) setDisableCopyPaste(false);
}}
className={classNames(
" pr-12 ",
" pr-9 ",
disabled ? " input-disable " : "",
password && !pwdVisible && myValue !== "" ? "password" : "",
editNode ? " input-edit-node " : " input-primary ",
@ -61,8 +55,8 @@ export default function InputComponent({
<button
className={classNames(
editNode
? "absolute inset-y-0 right-0 items-center pr-2 text-muted-foreground"
: "absolute inset-y-0 right-0 items-center px-4 text-muted-foreground"
? "input-component-true-button"
: "input-component-false-button"
)}
onClick={() => {
setPwdVisible(!pwdVisible);
@ -78,8 +72,8 @@ export default function InputComponent({
stroke="currentColor"
className={classNames(
editNode
? "absolute bottom-0.5 right-2 h-5 w-5"
: "absolute bottom-2 right-3 h-5 w-5"
? "input-component-true-svg"
: "input-component-false-svg"
)}
>
<path
@ -97,8 +91,8 @@ export default function InputComponent({
stroke="currentColor"
className={classNames(
editNode
? "absolute bottom-0.5 right-2 h-5 w-5"
: "absolute bottom-2 right-3 h-5 w-5"
? "input-component-true-svg"
: "input-component-false-svg"
)}
>
<path

View file

@ -1,9 +1,9 @@
import { FileSearch2 } from "lucide-react";
import { useContext, useEffect, useState } from "react";
import { alertContext } from "../../contexts/alertContext";
import { FileComponentType } from "../../types/components";
import { TabsContext } from "../../contexts/tabsContext";
import { FileSearch2 } from "lucide-react";
import { uploadFile } from "../../controllers/API";
import { FileComponentType } from "../../types/components";
export default function InputFileComponent({
value,
@ -91,19 +91,18 @@ export default function InputFileComponent({
input.click();
};
return (
<div
className={
disabled ? "pointer-events-none w-full cursor-not-allowed" : "w-full"
}
>
<div className="flex w-full items-center">
<div className={disabled ? "input-component-div" : "w-full"}>
<div className="input-file-component">
<span
onClick={handleButtonClick}
className={
editNode
? "input-edit-node " + "input-primary "
: "input-primary " + (disabled ? "input-disable " : "")
? " input-edit-node " + " input-dialog "
: (disabled ? " input-disable " : "") +
" input-primary " +
" input-dialog "
}
>
{myValue !== "" ? myValue : "No file"}
@ -112,7 +111,10 @@ export default function InputFileComponent({
{!editNode && !loading && (
<FileSearch2
strokeWidth={1.5}
className="h-6 w-6 hover:text-accent-foreground"
className={
"icons-parameters-comp" +
(disabled ? " text-ring " : " hover:text-accent-foreground")
}
/>
)}
{!editNode && loading && (

View file

@ -1,9 +1,8 @@
import { useContext, useEffect, useState } from "react";
import { InputListComponentType } from "../../types/components";
import { TabsContext } from "../../contexts/tabsContext";
import _ from "lodash";
import { X, Plus } from "lucide-react";
import { Plus, X } from "lucide-react";
import { PopUpContext } from "../../contexts/popUpContext";
export default function InputListComponent({

View file

@ -1,8 +1,7 @@
import { useContext, useEffect, useState } from "react";
import { FloatComponentType } from "../../types/components";
import { TabsContext } from "../../contexts/tabsContext";
import { classNames } from "../../utils";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { FloatComponentType } from "../../types/components";
export default function IntComponent({
value,

View file

@ -1,13 +1,13 @@
import { useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { TextAreaComponentType } from "../../types/components";
import GenericModal from "../../modals/genericModal";
import { TextAreaComponentType } from "../../types/components";
import { TypeModal } from "../../utils";
import { ExternalLink } from "lucide-react";
import { postValidatePrompt } from "../../controllers/API";
import { typesContext } from "../../contexts/typesContext";
import * as _ from "lodash";
import { ExternalLink } from "lucide-react";
import { typesContext } from "../../contexts/typesContext";
import { postValidatePrompt } from "../../controllers/API";
export default function PromptAreaComponent({
field_name,
@ -100,7 +100,7 @@ export default function PromptAreaComponent({
<ExternalLink
strokeWidth={1.5}
className={
"ml-3 h-6 w-6" +
"icons-parameters-comp" +
(disabled ? " text-ring" : " hover:text-accent-foreground")
}
/>

View file

@ -1,7 +1,7 @@
import { useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { TextAreaComponentType } from "../../types/components";
import GenericModal from "../../modals/genericModal";
import { TextAreaComponentType } from "../../types/components";
import { TypeModal } from "../../utils";
import { ExternalLink } from "lucide-react";
@ -30,34 +30,23 @@ export default function TextAreaComponent({
<div className={disabled ? "cursor-not-allowed" : ""}>
<div
className={
(editNode ? "w-full items-center" : "flex w-full items-center") +
(editNode ? "relative top-2 w-full" : "flex w-full items-center") +
(disabled ? " pointer-events-none" : "")
}
>
<span
onClick={() => {
openPopUp(
<GenericModal
type={TypeModal.TEXT}
buttonText="Finishing Editing"
modalTitle="Edit Text"
value={myValue}
setValue={(t: string) => {
setMyValue(t);
onChange(t);
}}
/>
);
}}
<input
value={myValue}
className={
editNode
? "input-edit-node input-dialog "
: "input-dialog input-primary " +
(disabled ? "input-disable" : "")
? "input-edit-node"
: "input-primary" + (disabled ? " input-disable " : "")
}
>
{myValue !== "" ? myValue : "Type something..."}
</span>
placeholder={"Type something..."}
onChange={(e) => {
setMyValue(e.target.value);
onChange(e.target.value);
}}
/>
<button
onClick={() => {
@ -79,7 +68,7 @@ export default function TextAreaComponent({
<ExternalLink
strokeWidth={1.5}
className={
"ml-3 h-6 w-6" +
"icons-parameters-comp" +
(disabled ? " text-ring" : " hover:text-accent-foreground")
}
/>

View file

@ -1,7 +1,7 @@
import { Switch } from "@headlessui/react";
import { classNames } from "../../utils";
import { useEffect } from "react";
import { ToggleComponentType } from "../../types/components";
import { classNames } from "../../utils";
export default function ToggleComponent({
enabled,
@ -22,14 +22,14 @@ export default function ToggleComponent({
}}
className={classNames(
enabled ? "bg-primary" : "bg-input",
"relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-1 focus:ring-primary focus:ring-offset-1"
"toggle-component-switch "
)}
>
<span className="sr-only">Use setting</span>
<span
className={classNames(
enabled ? "translate-x-5" : "translate-x-0",
"pointer-events-none relative inline-block h-5 w-5 transform rounded-full shadow ring-0 transition duration-200 ease-in-out",
"toggle-component-span",
disabled ? "bg-input " : "bg-background"
)}
>
@ -38,7 +38,7 @@ export default function ToggleComponent({
enabled
? "opacity-0 duration-100 ease-out"
: "opacity-100 duration-200 ease-in",
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
"toggle-component-second-span"
)}
aria-hidden="true"
></span>
@ -47,7 +47,7 @@ export default function ToggleComponent({
enabled
? "opacity-100 duration-200 ease-in"
: "opacity-0 duration-100 ease-out",
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
"toggle-component-second-span"
)}
aria-hidden="true"
></span>

View file

@ -1,4 +1,3 @@
import { useEffect } from "react";
import { ToggleComponentType } from "../../types/components";
import { Switch } from "../ui/switch";

View file

@ -1,8 +1,8 @@
"use client";
import * as React from "react";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { ChevronDownIcon } from "@radix-ui/react-icons";
import * as React from "react";
import { cn } from "../../utils";
const Accordion = AccordionPrimitive.Root;

View file

@ -1,5 +1,5 @@
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "../../utils";
const badgeVariants = cva(

View file

@ -1,6 +1,6 @@
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "../../utils";
const buttonVariants = cva(

View file

@ -1,8 +1,8 @@
"use client";
import * as React from "react";
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { Check } from "lucide-react";
import * as React from "react";
import { cn } from "../../utils";
const Checkbox = React.forwardRef<

View file

@ -1,6 +1,6 @@
import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-react";
import * as React from "react";
import { cn } from "../../utils";
const Dialog = DialogPrimitive.Root;

View file

@ -1,8 +1,8 @@
"use client";
import * as React from "react";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Check, ChevronRight, Circle } from "lucide-react";
import * as React from "react";
import { cn } from "../../utils";
const DropdownMenu = DropdownMenuPrimitive.Root;

View file

@ -1,8 +1,8 @@
"use client";
import * as React from "react";
import * as LabelPrimitive from "@radix-ui/react-label";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "../../utils";
const labelVariants = cva(

View file

@ -1,8 +1,8 @@
"use client";
import * as React from "react";
import * as MenubarPrimitive from "@radix-ui/react-menubar";
import { Check, ChevronRight, Circle } from "lucide-react";
import * as React from "react";
import { cn } from "../../utils";

View file

@ -1,7 +1,7 @@
"use client";
import * as React from "react";
import * as ProgressPrimitive from "@radix-ui/react-progress";
import * as React from "react";
import { cn } from "../../utils";
const Progress = React.forwardRef<

View file

@ -1,4 +1,4 @@
import { useState, useEffect, useRef } from "react";
import { useEffect, useRef, useState } from "react";
import { cn } from "../../utils";
export default function RenameLabel(props) {

View file

@ -1,7 +1,7 @@
"use client";
import * as React from "react";
import * as SeparatorPrimitive from "@radix-ui/react-separator";
import * as React from "react";
import { cn } from "../../utils";
const Separator = React.forwardRef<

View file

@ -1,7 +1,7 @@
"use client";
import * as React from "react";
import * as SwitchPrimitives from "@radix-ui/react-switch";
import * as React from "react";
import { cn } from "../../utils";
const Switch = React.forwardRef<

View file

@ -5,7 +5,7 @@ const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="w-full overflow-auto">
<div className="">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}

View file

@ -1,7 +1,7 @@
"use client";
import * as React from "react";
import * as TabsPrimitive from "@radix-ui/react-tabs";
import * as React from "react";
import { cn } from "../../utils";
const Tabs = TabsPrimitive.Root;

View file

@ -1,7 +1,7 @@
"use client";
import * as React from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import * as React from "react";
import { cn } from "../../utils";
const TooltipProvider = TooltipPrimitive.Provider;

View file

@ -1,7 +1,9 @@
// src/constants.tsx
import { MessageSquare } from "lucide-react";
import { FlowType } from "./types/flow";
import { buildTweaks } from "./utils";
import { TabsState } from "./types/tabs";
import { buildInputs, buildTweaks } from "./utils";
/**
* The base text for subtitle of Export Dialog (Toolbar)
@ -56,6 +58,8 @@ export const CHAT_CANNOT_OPEN_DESCRIPTION = "This is not a chat flow.";
export const FLOW_NOT_BUILT_TITLE = "Flow not built";
export const THOUGHTS_ICON = MessageSquare;
export const FLOW_NOT_BUILT_DESCRIPTION =
"Please build the flow before chatting.";
@ -70,7 +74,11 @@ export const TEXT_DIALOG_SUBTITLE = "Edit your text.";
* @param {string} flowId - The id of the flow
* @returns {string} - The python code
*/
export const getPythonApiCode = (flow: FlowType, tweak?): string => {
export const getPythonApiCode = (
flow: FlowType,
tweak?: any[],
tabsState?: TabsState
): string => {
const flowId = flow.id;
// create a dictionary of node ids and the values is an empty dictionary
@ -78,7 +86,9 @@ export const getPythonApiCode = (flow: FlowType, tweak?): string => {
// node.data.id
// }
const tweaks = buildTweaks(flow);
const inputs = buildInputs(tabsState, flow.id);
return `import requests
from typing import Optional
BASE_API_URL = "${window.location.protocol}//${
window.location.host
@ -92,7 +102,7 @@ TWEAKS = ${
: JSON.stringify(tweaks, null, 2)
}
def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
def run_flow(inputs: dict, flow_id: str, tweaks: Optional[dict] = None) -> dict:
"""
Run a flow with a given message and optional tweaks.
@ -103,7 +113,7 @@ def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
"""
api_url = f"{BASE_API_URL}/{flow_id}"
payload = {"inputs": {"input": message}}
payload = {"inputs": inputs}
if tweaks:
payload["tweaks"] = tweaks
@ -112,23 +122,29 @@ def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
return response.json()
# Setup any tweaks you want to apply to the flow
print(run_flow("Your message", flow_id=FLOW_ID, tweaks=TWEAKS))`;
inputs = ${inputs}
print(run_flow(inputs, flow_id=FLOW_ID, tweaks=TWEAKS))`;
};
/**
* Function to get the curl code for the API
* @param {string} flowId - The id of the flow
* @returns {string} - The curl code
*/
export const getCurlCode = (flow: FlowType, tweak?): string => {
export const getCurlCode = (
flow: FlowType,
tweak?: any[],
tabsState?: TabsState
): string => {
const flowId = flow.id;
const tweaks = buildTweaks(flow);
const inputs = buildInputs(tabsState, flow.id);
return `curl -X POST \\
${window.location.protocol}//${
window.location.host
}/api/v1/process/${flowId} \\
-H 'Content-Type: application/json' \\
-d '{"inputs": {"input": message}, "tweaks": ${
-d '{"inputs": ${inputs}, "tweaks": ${
tweak && tweak.length > 0
? buildTweakObject(tweak)
: JSON.stringify(tweaks, null, 2)
@ -139,9 +155,14 @@ export const getCurlCode = (flow: FlowType, tweak?): string => {
* @param {string} flowName - The name of the flow
* @returns {string} - The python code
*/
export const getPythonCode = (flow: FlowType, tweak?): string => {
export const getPythonCode = (
flow: FlowType,
tweak?: any[],
tabsState?: TabsState
): string => {
const flowName = flow.name;
const tweaks = buildTweaks(flow);
const inputs = buildInputs(tabsState, flow.id);
return `from langflow import load_flow_from_json
TWEAKS = ${
tweak && tweak.length > 0
@ -150,7 +171,8 @@ TWEAKS = ${
}
flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS)
# Now you can use it like any chain
flow("Hey, have you heard of LangFlow?")`;
inputs = ${inputs}
flow(inputs)`;
};
function buildTweakObject(tweak) {
@ -529,4 +551,4 @@ export const USER_PROJECTS_HEADER = "My Collection";
*
*/
export const HIGHLIGH_CSS =
"block pl-3 pr-14 py-2 w-full h-full text-sm outline-0 border-0 break-all";
"block pl-3 pr-14 py-2 w-full h-full text-sm outline-0 border-0 break-all overflow-y-hidden max-w-[75vw]";

View file

@ -1,10 +1,4 @@
import {
createContext,
useContext,
useState,
useEffect,
useCallback,
} from "react";
import { createContext, useCallback, useContext, useState } from "react";
const initialValue = {
updateSSEData: ({}) => {},

View file

@ -1,13 +1,13 @@
import { ReactNode } from "react";
import { ReactFlowProvider } from "reactflow";
import { SSEProvider } from "./SSEContext";
import { AlertProvider } from "./alertContext";
import { DarkProvider } from "./darkContext";
import { LocationProvider } from "./locationContext";
import PopUpProvider from "./popUpContext";
import { TabsProvider } from "./tabsContext";
import { TypesProvider } from "./typesContext";
import { ReactFlowProvider } from "reactflow";
import { UndoRedoProvider } from "./undoRedoContext";
import { SSEProvider } from "./SSEContext";
export default function ContextWrapper({ children }: { children: ReactNode }) {
//element to wrap all context

View file

@ -1,5 +1,4 @@
import { createContext } from "react";
import React, { useState } from "react";
import React, { createContext, useState } from "react";
// context to set JSX element on the DOM
export const PopUpContext = createContext({

View file

@ -1,33 +1,33 @@
import _ from "lodash";
import {
createContext,
useEffect,
useState,
useRef,
ReactNode,
createContext,
useContext,
useEffect,
useRef,
useState,
} from "react";
import { addEdge } from "reactflow";
import ShortUniqueId from "short-unique-id";
import {
deleteFlowFromDatabase,
downloadFlowsFromDatabase,
readFlowsFromDatabase,
saveFlowToDatabase,
updateFlowInDatabase,
uploadFlowsToDatabase,
} from "../controllers/API";
import { APIClassType, APITemplateType } from "../types/api";
import { FlowType, NodeType } from "../types/flow";
import { TabsContextType, TabsState } from "../types/tabs";
import {
updateIds,
updateTemplate,
getRandomDescription,
getRandomName,
updateIds,
updateTemplate,
} from "../utils";
import { alertContext } from "./alertContext";
import { typesContext } from "./typesContext";
import { APIClassType, APITemplateType } from "../types/api";
import ShortUniqueId from "short-unique-id";
import { addEdge } from "reactflow";
import {
readFlowsFromDatabase,
deleteFlowFromDatabase,
saveFlowToDatabase,
downloadFlowsFromDatabase,
uploadFlowsToDatabase,
updateFlowInDatabase,
} from "../controllers/API";
import _ from "lodash";
const uid = new ShortUniqueId({ length: 5 });
@ -108,7 +108,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
// function loadCookie(cookie: string) {
// if (cookie && Object.keys(templates).length > 0) {
// let cookieObject: LangFlowState = JSON.parse(cookie);
// let cookieObject: LangflowState = JSON.parse(cookie);
// try {
// cookieObject.flows.forEach((flow) => {
// if (!flow.data) {

View file

@ -1,8 +1,8 @@
import { createContext, ReactNode, useEffect, useState } from "react";
import { Node } from "reactflow";
import { typesContextType } from "../types/typesContext";
import { getAll } from "../controllers/API";
import { APIKindType } from "../types/api";
import { typesContextType } from "../types/typesContext";
//context to share types adn functions from nodes to flow

View file

@ -1,3 +1,4 @@
import { cloneDeep } from "lodash";
import {
createContext,
useCallback,
@ -6,7 +7,6 @@ import {
useState,
} from "react";
import { Edge, Node, useReactFlow } from "reactflow";
import { cloneDeep } from "lodash";
import { TabsContext } from "./tabsContext";
type undoRedoContextType = {

View file

@ -1,15 +1,15 @@
import {
BuildStatusTypeAPI,
errorsTypeAPI,
InitTypeAPI,
UploadFileTypeAPI,
APIClassType,
PromptTypeAPI,
} from "./../../types/api/index";
import { APIObjectType, sendAllProps } from "../../types/api/index";
import axios, { AxiosResponse } from "axios";
import { FlowStyleType, FlowType } from "../../types/flow";
import { ReactFlowJsonObject } from "reactflow";
import { APIObjectType, sendAllProps } from "../../types/api/index";
import { FlowStyleType, FlowType } from "../../types/flow";
import {
APIClassType,
BuildStatusTypeAPI,
InitTypeAPI,
PromptTypeAPI,
UploadFileTypeAPI,
errorsTypeAPI,
} from "./../../types/api/index";
/**
* Fetches all objects from the API endpoint.
@ -339,10 +339,3 @@ export async function uploadFile(
formData.append("file", file);
return await axios.post(`/api/v1/upload/${id}`, formData);
}
export async function postCustomComponent(
code: string,
apiClass: APIClassType
): Promise<AxiosResponse<APIClassType>> {
return await axios.post(`/api/v1/custom_component`, { code });
}

View file

@ -20,7 +20,7 @@ export const DESCRIPTIONS: string[] = [
"Generate, Innovate, Communicate.",
"Conversation Catalyst Engine.",
"Language Chainlink Master.",
"Design Dialogues with LangFlow.",
"Design Dialogues with Langflow.",
"Nurture NLP Nodes Here.",
"Conversational Cartography Unlocked.",
"Design, Develop, Dialogize.",
@ -31,7 +31,7 @@ export const DESCRIPTIONS: string[] = [
"Where Language Meets Logic.",
"Building Intelligent Interactions.",
"Your Passport to Linguistic Landscapes.",
"Create, Curate, Communicate with LangFlow.",
"Create, Curate, Communicate with Langflow.",
"Flow into the Future of Language.",
"Mapping Meaningful Conversations.",
"Unravel the Art of Articulation.",
@ -41,7 +41,7 @@ export const DESCRIPTIONS: string[] = [
"The Pinnacle of Prompt Generation.",
"Language Models, Mapped and Mastered.",
"Powerful Prompts, Perfectly Positioned.",
"Innovation in Interaction with LangFlow.",
"Innovation in Interaction with Langflow.",
"Your Toolkit for Text Generation.",
"Unfolding Linguistic Possibilities.",
"Building Powerful Solutions with Language Models.",

View file

@ -145,6 +145,60 @@ The cursor: default; property value restores the browser's default cursor style
@layer components {
.round-buttons-position {
@apply fixed right-4
}
.side-bar-arrangement {
@apply flex h-full w-52 flex-col overflow-hidden border-r scrollbar-hide
}
.side-bar-search-div-placement {
@apply relative mx-auto mb-2 mt-2 flex items-center
}
.side-bar-components-icon {
@apply h-6 w-4 text-ring
}
.side-bar-components-text {
@apply w-full truncate pr-1 text-xs text-foreground
}
.side-bar-components-div-form {
@apply flex w-full items-center justify-between rounded-md rounded-l-none border border-l-0 border-dashed border-ring bg-white px-3 py-1 text-sm
}
.side-bar-components-border {
@apply cursor-grab rounded-l-md border-l-8
}
.side-bar-components-gap {
@apply flex flex-col gap-2 p-2
}
.side-bar-components-div-arrangement {
@apply w-full overflow-auto scrollbar-hide
}
.search-icon {
@apply absolute inset-y-0 right-0 flex items-center py-1.5 pr-5
}
.extra-side-bar-save-disable {
@apply text-muted-foreground
}
.extra-side-bar-save-disable:hover {
@apply hover:text-accent-foreground
}
.side-bar-button-size {
@apply h-5 w-5
}
.side-bar-button-size:hover {
@apply hover:text-accent-foreground
}
.side-bar-buttons-arrangement {
@apply mb-2 mt-2 flex w-full items-center justify-between gap-2 px-2
}
.extra-side-bar-buttons {
@apply relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out
}
.extra-side-bar-buttons:hover {
@apply hover:bg-muted
}
.button-div-style {
@apply gap-2 flex
}
.input-primary:focus{
@apply focus:placeholder-transparent focus:ring-ring focus:border-ring
}
@ -163,4 +217,701 @@ The cursor: default; property value restores the browser's default cursor style
.input-dialog{
@apply text-ring cursor-pointer bg-transparent
}
.message-button {
@apply message-button-position flex h-12 w-12 items-center justify-center rounded-full bg-border px-3 py-1 shadow-md transition-all
}
.round-button-form {
@apply flex h-12 w-12 cursor-pointer justify-center rounded-full bg-border px-3 py-1 shadow-md
}
.round-button-div {
@apply flex items-center gap-3
}
.build-trigger-loading-icon {
@apply stroke-build-trigger
}
.build-trigger-icon {
@apply w-6 fill-build-trigger stroke-1 stroke-build-trigger
}
.message-button-position {
@apply fixed bottom-4 right-4
}
.message-button-icon {
@apply fill-chat-trigger stroke-chat-trigger stroke-1
}
.disabled-message-button-icon {
@apply fill-chat-trigger-disabled stroke-chat-trigger-disabled stroke-1
}
.components-disclosure-arrangement {
@apply -mt-px flex w-full select-none items-center justify-between border-y border-y-input bg-muted px-3 py-2
}
.components-disclosure-title {
@apply flex items-center text-sm text-primary
}
.components-disclosure-div {
@apply flex gap-2
}
.flow-page-positioning {
@apply h-full w-full overflow-hidden
}
.logspace-page-icon {
@apply absolute bottom-2 left-7 flex h-6 cursor-pointer flex-col items-center justify-start overflow-hidden rounded-lg bg-foreground px-2 text-center font-sans text-xs tracking-wide text-secondary transition-all duration-500 ease-in-out
}
.logspace-page-icon:hover {
@apply hover:h-12
}
.flex-max-width {
@apply flex w-full
}
.main-page-panel {
@apply flex-max-width h-full flex-col overflow-auto bg-muted px-16
}
.main-page-nav-arrangement {
@apply flex-max-width justify-between px-6 py-12 pb-2
}
.main-page-nav-title {
@apply flex items-center justify-center gap-2 text-2xl font-semibold
}
.main-page-nav-button {
@apply mr-2 w-4
}
.main-page-description-text {
@apply flex w-[60%] px-6 pb-14 text-muted-foreground
}
.main-page-flows-display {
@apply grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4
}
.community-page-arrangement {
@apply flex-max-width h-full flex-col overflow-auto bg-muted px-16
}
.community-page-nav-arrangement {
@apply flex-max-width justify-between px-6 py-12 pb-2
}
.community-page-nav-title {
@apply flex items-center justify-center gap-2 text-2xl font-semibold
}
.community-page-nav-button {
@apply flex gap-2
}
.community-page-description-text {
@apply flex w-[70%] px-6 pb-8 text-muted-foreground
}
.community-pages-flows-panel {
@apply grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4
}
.generic-node-div {
@apply relative flex w-96 flex-col justify-center rounded-lg bg-background
}
.generic-node-div-title {
@apply flex w-full items-center justify-between gap-8 rounded-t-lg border-b bg-muted p-4
}
.generic-node-title-arrangement {
@apply flex-max-width items-center truncate
}
.generic-node-icon {
@apply h-10 w-10 rounded p-1
}
.generic-node-tooltip-div {
@apply ml-2 truncate
}
.generic-node-validation-div {
@apply max-h-96 overflow-auto
}
.generic-node-status-position {
@apply relative top-[3px] h-5 w-5
}
.generic-node-status-animation {
@apply hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0
}
.generic-node-status {
@apply h-4 w-4 rounded-full opacity-100
}
.green-status {
@apply generic-node-status bg-status-green
}
.red-status {
@apply generic-node-status bg-status-red
}
.yellow-status {
@apply generic-node-status bg-status-yellow
}
.status-build-animation {
@apply hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0
}
.status-div {
@apply absolute w-4 duration-200 ease-in-out
}
.status-div:hover {
@apply hover:text-accent-foreground hover:transition-all
}
.generic-node-desc {
@apply h-full w-full py-5 text-foreground
}
.generic-node-desc-text {
@apply w-full px-5 pb-3 text-sm text-muted-foreground
}
.alert-icon {
@apply h-5 w-5
}
.alert-font-size {
@apply text-sm font-medium
}
.error-build-message {
@apply mt-6 w-96 cursor-pointer rounded-md bg-error-background p-4 shadow-xl
}
.error-build-message-circle {
@apply text-status-red alert-icon
}
.error-build-text {
@apply text-error-foreground
}
.error-build-foreground {
@apply error-build-text alert-font-size
}
.error-build-message-div {
@apply mt-2 text-sm error-build-text
}
.error-build-message-list {
@apply list-disc space-y-1 pl-5
}
.success-alert {
@apply mt-6 w-96 rounded-md bg-success-background p-4 shadow-xl
}
.success-alert-icon {
@apply alert-icon text-status-green
}
.success-alert-message {
@apply alert-font-size text-success-foreground
}
.card-component-title-display {
@apply round-button-div flex-max-width
}
.card-component-image {
@apply flex h-7 w-7 items-center justify-center rounded-full text-2xl
}
.card-component-title-size {
@apply inline-block w-full flex-1 break-words truncate-doubleline
}
.card-component-delete-button {
@apply flex self-start
}
.card-component-delete-icon {
@apply h-4 w-4 text-primary opacity-0 transition-all group-hover:opacity-100
}
.card-component-desc {
@apply pb-2 pt-2
}
.card-component-desc-text {
@apply truncate-doubleline
}
.card-component-footer-arrangement {
@apply flex-max-width items-end justify-between gap-2
}
.card-component-footer {
@apply flex flex-wrap gap-2
}
.unused-side-bar-aside {
@apply flex flex-shrink-0 flex-col overflow-hidden border-r transition-all duration-500
}
.unused-side-bar-arrangement {
@apply flex h-full w-52 flex-col items-start overflow-y-auto border bg-background scrollbar-hide
}
.unused-side-bar-division {
@apply flex-max-width flex-grow flex-col
}
.unused-side-bar-nav {
@apply flex-1 space-y-1
}
.unused-side-bar-link {
@apply flex-max-width items-center rounded-md py-2 pl-2 text-sm font-medium
}
.unused-side-bar-link-colors-true {
@apply bg-muted text-foreground
}
.unused-side-bar-link-colors-false {
@apply bg-background text-muted-foreground hover:bg-muted hover:text-foreground
}
.unused-side-bar-icon {
@apply mr-3 flex-shrink-0 h-6 w-6
}
.unused-side-bar-icon-false {
@apply text-ring group-hover:text-accent-foreground
}
.unused-side-bar-disclosure {
@apply unused-side-bar-link pr-1 text-left
}
.unused-side-bar-disclosure:focus {
@apply focus:outline-none focus:ring-1 focus:ring-ring
}
.unused-side-bar-disclosure-icon {
@apply unused-side-bar-icon text-ring group-hover:text-accent-foreground
}
.unused-side-bar-svg-true {
@apply text-ring rotate-90
}
.unused-side-bar-svg {
@apply ml-3 h-5 w-5 flex-shrink-0 duration-150 ease-in-out group-hover:text-accent-foreground
}
.unused-side-bar-disclosure-panel {
@apply flex w-full items-center rounded-md py-2 pl-11 pr-2 text-sm font-medium
}
.code-area-component {
@apply pointer-events-none w-full cursor-not-allowed
}
.code-area-input-positioning {
@apply flex-max-width items-center
}
.code-area-external-link {
@apply w-6 h-6 ml-3
}
.code-area-external-link:hover {
@apply hover:text-accent-foreground
}
.dropdown-component-outline {
@apply input-edit-node relative pr-8
}
.dropdown-component-false-outline {
@apply input-primary py-2 pl-3 pr-10 text-left
}
.dropdown-component-display {
@apply block w-full truncate bg-background
}
.dropdown-component-arrow {
@apply pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2
}
.dropdown-component-arrow-color {
@apply h-5 w-5 extra-side-bar-save-disable
}
.dropdown-component-options {
@apply z-10 mt-1 max-h-60 overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm
}
.dropdown-component-true-options {
@apply dropdown-component-options w-[215px]
}
.dropdown-component-false-options {
@apply dropdown-component-options w-full
}
.dropdown-component-option {
@apply relative cursor-default select-none
}
.dropdown-component-false-option {
@apply dropdown-component-option py-0.5 pl-3 pr-12
}
.dropdown-component-true-option {
@apply dropdown-component-option py-2 pl-3 pr-9
}
.dropdown-component-choosal {
@apply absolute inset-y-0 right-0 flex items-center pr-4
}
.dropdown-component-check-icon {
@apply h-5 w-5 text-black
}
.edit-flow-arrangement {
@apply flex justify-between
}
.edit-flow-span {
@apply ml-10 animate-pulse text-status-red
}
.float-component-pointer {
@apply pointer-events-none cursor-not-allowed
}
.header-menu-bar {
@apply flex items-center gap-0.5 rounded-md px-1.5 py-1 text-sm font-medium
}
.header-menu-bar-display {
@apply flex max-w-[200px] items-center gap-2
}
.header-menu-flow-name {
@apply flex-1 truncate
}
.header-menu-options {
@apply mr-2 h-4 w-4
}
.header-arrangement {
@apply flex-max-width h-12 items-center justify-between border-b bg-muted
}
.header-start-display {
@apply flex w-96 items-center justify-start gap-2
}
.header-end-division {
@apply flex w-96 justify-end px-2
}
.header-end-display {
@apply ml-auto mr-2 flex items-center gap-5
}
.header-github-link-box {
@apply border border-input h-9 px-3 pr-0 rounded-md inline-flex shadow-sm items-center justify-center
}
.header-github-link {
@apply text-sm font-medium disabled:opacity-50 disabled:pointer-events-none ring-offset-background text-muted-foreground header-github-link-box
}
.header-github-link:focus-visible {
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
}
.header-github-link:hover {
@apply hover:bg-accent hover:text-accent-foreground
}
.header-github-display {
@apply -mr-px ml-2 flex h-9 items-center justify-center rounded-md rounded-l-none border bg-background px-2 text-sm
}
.header-notifications-box {
@apply fixed left-0 top-0 h-screen w-screen
}
.header-notifications {
@apply absolute right-[3px] h-1.5 w-1.5 rounded-full bg-destructive
}
.input-component-div {
@apply pointer-events-none relative cursor-not-allowed
}
.input-component-button {
@apply absolute inset-y-0 right-0 items-center text-muted-foreground
}
.input-component-true-button {
@apply input-component-button pr-2
}
.input-component-false-button {
@apply input-component-button px-4
}
.input-component-true-svg {
@apply absolute bottom-0.5 right-2 side-bar-button-size
}
.input-component-false-svg {
@apply absolute bottom-2 right-3 side-bar-button-size
}
.input-file-component {
@apply flex-max-width items-center
}
.toggle-component-switch {
@apply relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out
}
.toggle-component-switch:focus {
@apply focus:outline-none focus:ring-1 focus:ring-primary focus:ring-offset-1
}
.toggle-component-span {
@apply pointer-events-none relative inline-block h-5 w-5 transform rounded-full shadow ring-0 transition duration-200 ease-in-out
}
.toggle-component-second-span {
@apply absolute inset-0 flex h-full w-full items-center justify-center transition-opacity
}
.app-div {
@apply fixed bottom-5 left-5 flex flex-col-reverse
}
.chat-input-modal-txtarea {
@apply form-input block w-full rounded-md border-ring pr-10 custom-scroll sm:text-sm
}
.chat-input-modal-div {
@apply absolute bottom-0.5 right-3
}
.chat-input-modal-lock {
@apply side-bar-button-size animate-pulse text-ring
}
.chat-input-modal-send {
@apply side-bar-button-size text-ring hover:text-muted-foreground
}
.code-block-modal {
@apply flex items-center justify-between px-4 py-1.5
}
.code-block-modal-span {
@apply text-xs lowercase text-background
}
.code-block-modal-button {
@apply flex items-center gap-1.5 rounded bg-none p-1 text-xs text-background
}
.chat-message-modal {
@apply flex-max-width py-2 pl-2
}
.chat-message-modal-div {
@apply my-3 flex h-8 w-8 items-center justify-center overflow-hidden rounded-full
}
.chat-message-modal-img {
@apply absolute scale-150 transition-opacity duration-500
}
.chat-message-modal-display {
@apply flex-max-width items-center text-start
}
.chat-message-modal-text {
@apply relative inline-block w-full text-start text-sm font-normal text-muted-foreground
}
.chat-message-modal-icon-div {
@apply absolute -left-2 -top-1 cursor-pointer
}
.chat-message-modal-thought {
@apply ml-3 inline-block h-full w-[95%] rounded-md border border-ring bg-muted px-2 pb-3 pt-3 text-start text-muted-foreground chat-message-modal-thought-cursor
}
.chat-message-modal-thought-cursor {
@apply cursor-pointer scrollbar-hide overflow-scroll
}
.chat-message-modal-markdown {
@apply w-full px-4 pb-3 pr-8 pt-3
}
.chat-message-modal-markdown-span {
@apply mt-1 animate-pulse cursor-default
}
.chat-message-modal-alert {
@apply inline-block px-3 text-start text-muted-foreground
}
.file-card-modal-image-div {
@apply absolute right-0 top-0 rounded-bl-lg bg-muted px-1 text-sm font-bold text-foreground
}
.file-card-modal-image-button {
@apply px-2 py-1 text-ring
}
.file-card-modal-button {
@apply flex w-1/2 items-center justify-between rounded border border-ring bg-muted px-2 py-2 text-foreground shadow hover:drop-shadow-lg
}
.file-card-modal-div {
@apply mr-2 flex-max-width items-center gap-2 text-current
}
.file-card-modal-footer {
@apply flex flex-col items-start
}
.file-card-modal-name {
@apply truncate text-sm text-current
}
.file-card-modal-type {
@apply truncate text-xs text-ring
}
.send-message-modal-transition {
@apply fixed inset-0 bg-black bg-opacity-80 backdrop-blur-sm transition-opacity
}
.chat-modal-box {
@apply fixed inset-0 z-10 overflow-y-auto
}
.chat-modal-box-div {
@apply flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0
}
.chat-modal-dialog-panel {
@apply relative flex h-[95%] w-[690px] transform flex-col justify-between overflow-hidden rounded-lg bg-background text-left shadow-xl drop-shadow-2xl transition-all
}
.chat-modal-dialog-panel-div {
@apply relative w-full p-4
}
.chat-modal-dialog-trash-panel {
@apply absolute right-10 top-2 z-30 text-muted-foreground hover:text-status-red
}
.chat-modal-dialog-x-panel {
@apply absolute right-2 top-1.5 z-30 text-muted-foreground hover:text-status-red
}
.chat-modal-dialog-history {
@apply flex-max-width h-full flex-col items-center overflow-scroll border-t bg-background scrollbar-hide
}
.chat-modal-dialog-span-box {
@apply flex-max-width h-full flex-col items-center justify-center text-center align-middle
}
.chat-modal-dialog-desc {
@apply w-2/4 rounded-md border border-input bg-muted px-6 py-8
}
.chat-modal-input-div {
@apply flex-max-width flex-col items-center justify-between border-t bg-background p-3
}
.chat-modal-input {
@apply relative mt-1 w-full rounded-md shadow-sm
}
.code-area-modal-editor-div {
@apply mt-2 flex-max-width h-full
}
.code-area-modal-editor-box {
@apply h-[300px] w-full rounded-lg border-[1px] border-ring custom-scroll
}
.edit-node-modal-variable {
@apply h-5 w-5 stroke-2 pe-1 text-muted-foreground
}
.edit-node-modal-span {
@apply text-sm font-semibold text-primary
}
.edit-node-modal-arrangement {
@apply flex-max-width h-fit max-h-[400px]
}
.edit-node-modal-box {
@apply w-full rounded-lg border-[1px] border-input bg-background
}
.edit-node-modal-table {
@apply flex h-fit flex-col gap-5
}
.edit-node-modal-table-header {
@apply h-10 border-input text-xs font-medium text-ring
}
.edit-node-modal-table-cell {
@apply p-0 text-center text-sm text-foreground truncate sm:px-3
}
.edit-node-modal-second-cell {
@apply w-[300px] p-0 text-center text-xs text-foreground
}
.generic-modal-txtarea-div {
@apply mt-2 flex-max-width h-full
}
.button-box-modal-div {
@apply flex transform flex-col items-center justify-center rounded-lg border border-ring text-center shadow hover:scale-105 hover:shadow-lg
}
.dialog-header-modal-div {
@apply absolute left-0 top-2 z-50 hidden pl-4 pt-4 sm:block
}
.dialog-header-modal-button {
@apply rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2
}
.dialog-modal-examples-div {
@apply h-full w-full overflow-y-auto scrollbar-hide
}
.dialog-modal-example-true {
@apply mx-auto flex flex-row flex-wrap items-start justify-center overflow-auto
}
.dialog-modal-example-false {
@apply flex flex-row items-center justify-center
}
.dialog-modal-button-box-div {
@apply flex-max-width h-full items-center justify-evenly
}
.document-icon {
@apply h-10 w-10 flex-shrink-0
}
.loading-component-div {
@apply flex items-center justify-center align-middle
}
.dialog-modal-footer {
@apply mt-2 flex-max-width items-center justify-center
}
.dialog-modal-footer-link {
@apply flex items-center justify-center text-muted-foreground
}
.node-modal-div {
@apply fixed inset-0 bg-ring bg-opacity-75 transition-opacity
}
.node-modal-dialog-arrangement {
@apply fixed inset-0 z-10 overflow-y-auto
}
.node-modal-dialog-div {
@apply flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0
}
.node-modal-dialog-panel {
@apply relative flex h-[600px] w-[700px] transform flex-col justify-between overflow-hidden rounded-lg bg-background text-left shadow-xl transition-all sm:my-8
}
.node-modal-dialog-panel-div {
@apply absolute right-0 top-0 z-50 hidden pr-4 pt-4 sm:block
}
.node-modal-dialog-button {
@apply rounded-md text-ring hover:text-accent-foreground
}
.node-modal-dialog-icon-div {
@apply flex-max-width h-full flex-col items-center justify-center
}
.node-modal-icon-arrangement {
@apply z-10 flex-max-width justify-center pb-4 shadow-sm
}
.node-modal-icon {
@apply mt-4 h-10 w-10 rounded p-1
}
.node-modal-title-div {
@apply mt-4 text-center sm:ml-4 sm:text-left
}
.node-modal-title {
@apply text-lg font-medium leading-10 text-foreground
}
.node-modal-template-div {
@apply flex-max-width h-full flex-row items-center justify-center gap-4 bg-input p-4
}
.node-modal-template {
@apply w-full rounded-lg bg-background px-4 shadow sm:p-4
}
.node-modal-template-column {
@apply flex h-full flex-col gap-5
}
.node-modal-button-box {
@apply flex-max-width flex-row-reverse bg-input px-4 pb-3
}
.node-modal-button {
@apply inline-flex w-full justify-center rounded-md border border-transparent bg-status-red px-4 py-2 text-base font-medium text-background shadow-sm hover:bg-ring sm:ml-3 sm:w-auto sm:text-sm
}
.node-modal-button:focus {
@apply focus:outline-none focus:ring-1 focus:ring-ring focus:ring-offset-1
}
.prompt-modal-icon-box {
@apply mx-auto mt-4 flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-almost-light-blue sm:mx-0 sm:h-10 sm:w-10
}
.prompt-modal-icon {
@apply h-6 w-6 text-almost-medium-blue
}
.prompt-modal-txtarea-arrangement {
@apply flex-max-width h-full flex-row items-center justify-center gap-4 overflow-auto bg-accent p-4
}
.prompt-modal-txtarea-box {
@apply h-full w-full overflow-hidden rounded-lg bg-background px-4 py-5 shadow sm:p-6
}
.prompt-modal-txtarea {
@apply form-input h-full w-full rounded-lg border-ring
}
.txtarea-modal-arrangement {
@apply flex h-full w-full flex-row items-center justify-center gap-4 bg-input p-4
}
.txtarea-modal-box {
@apply w-full overflow-hidden rounded-lg bg-background px-4 py-5 shadow sm:p-6
}
.txtarea-modal-input {
@apply form-input h-full w-full
}
.api-modal-tabs {
@apply w-full h-full overflow-hidden text-center bg-muted rounded-md border
}
.api-modal-tablist-div {
@apply flex items-center justify-between px-2
}
.api-modal-tabs-content {
@apply overflow-hidden w-full h-full px-4 pb-4 -mt-1
}
.api-modal-accordion-display {
@apply flex w-full h-full mt-2
}
.api-modal-table-arrangement {
@apply flex flex-col gap-5 h-fit
}
.icons-parameters-comp{
@apply ml-3 h-6 w-6
}
}

View file

@ -1,9 +1,8 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
import ContextWrapper from "./contexts";
import reportWebVitals from "./reportWebVitals";
import "./index.css";

View file

@ -1,42 +1,15 @@
import { useContext, useEffect, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import "ace-builds/src-noconflict/ext-language_tools";
import "ace-builds/src-noconflict/mode-python";
import "ace-builds/src-noconflict/theme-github";
import "ace-builds/src-noconflict/theme-twilight";
import "ace-builds/src-noconflict/ext-language_tools";
import { useContext, useEffect, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
// import "ace-builds/webpack-resolver";
import { darkContext } from "../../contexts/darkContext";
import { Check, Clipboard, Code2 } from "lucide-react";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { FlowType } from "../../types/flow/index";
import { getCurlCode, getPythonApiCode, getPythonCode } from "../../constants";
import { EXPORT_CODE_DIALOG } from "../../constants";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "../../components/ui/tabs";
import { Check, Clipboard, Code2 } from "lucide-react";
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "../../components/ui/table";
import { buildTweaks, classNames, limitScrollFieldsModal } from "../../utils";
import AccordionComponent from "../../components/AccordionComponent";
import ShadTooltip from "../../components/ShadTooltipComponent";
import CodeAreaComponent from "../../components/codeAreaComponent";
import Dropdown from "../../components/dropdownComponent";
import FloatComponent from "../../components/floatComponent";
@ -47,9 +20,38 @@ import IntComponent from "../../components/intComponent";
import PromptAreaComponent from "../../components/promptComponent";
import TextAreaComponent from "../../components/textAreaComponent";
import ToggleShadComponent from "../../components/toggleShadComponent";
import ShadTooltip from "../../components/ShadTooltipComponent";
import { cloneDeep, filter } from "lodash";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "../../components/ui/table";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "../../components/ui/tabs";
import {
EXPORT_CODE_DIALOG,
getCurlCode,
getPythonApiCode,
getPythonCode,
} from "../../constants";
import { darkContext } from "../../contexts/darkContext";
import { TabsContext } from "../../contexts/tabsContext";
import { FlowType } from "../../types/flow/index";
import { buildTweaks, classNames } from "../../utils";
export default function ApiModal({ flow }: { flow: FlowType }) {
const [open, setOpen] = useState(true);
@ -61,7 +63,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
const [openAccordion, setOpenAccordion] = useState([]);
const tweak = useRef([]);
const tweaksList = useRef([]);
const { setTweak, getTweak } = useContext(TabsContext);
const { setTweak, getTweak, tabsState } = useContext(TabsContext);
const copyToClipboard = () => {
if (!navigator.clipboard || !navigator.clipboard.writeText) {
return;
@ -75,9 +77,9 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
}, 2000);
});
};
const pythonApiCode = getPythonApiCode(flow, tweak.current);
const curl_code = getCurlCode(flow, tweak.current);
const pythonCode = getPythonCode(flow, tweak.current);
const pythonApiCode = getPythonApiCode(flow, tweak.current, tabsState);
const curl_code = getCurlCode(flow, tweak.current, tabsState);
const pythonCode = getPythonCode(flow, tweak.current, tabsState);
const tweaksCode = buildTweaks(flow);
const tabs = [
{
@ -111,7 +113,9 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
startTweaks();
}
} else {
startTweaks();
if (tweak?.current) {
startTweaks();
}
}
}, [closeEdit]);
@ -276,7 +280,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
<Tabs
value={activeTab}
className="h-full w-full overflow-hidden rounded-md border bg-muted text-center"
className="api-modal-tabs"
onValueChange={(value) => {
setActiveTab(value);
if (value === "3") {
@ -284,7 +288,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
}
}}
>
<div className="flex items-center justify-between px-2">
<div className="api-modal-tablist-div">
<TabsList>
{tabs.map((tab, index) => (
<TabsTrigger key={index} value={index.toString()}>
@ -308,12 +312,12 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
{tabs.map((tab, index) => (
<TabsContent
value={index.toString()}
className="-mt-1 h-full w-full overflow-hidden px-4 pb-4"
className="api-modal-tabs-content"
key={index} // Remember to add a unique key prop
>
{index < 3 ? (
<SyntaxHighlighter
className="h-[60vh] w-full overflow-auto"
className="h-[60vh] w-full overflow-auto custom-scroll"
language={tab.mode}
style={oneDark}
>
@ -321,7 +325,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
</SyntaxHighlighter>
) : index === 3 ? (
<>
<div className="mt-2 flex h-full w-full">
<div className="api-modal-according-display">
<div
className={classNames(
"h-[60vh] w-full rounded-lg bg-muted",
@ -337,7 +341,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
trigger={t["data"]["id"]}
open={openAccordion}
>
<div className="flex h-fit flex-col gap-5">
<div className="api-modal-table-arrangement">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="h-10 border-input text-xs font-medium text-ring">
<TableRow className="dark:border-b-muted">
@ -418,7 +422,6 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
) : t.data.node.template[n]
.multiline ? (
<ShadTooltip
delayDuration={1000}
content={buildContent(
t.data.node.template[
n
@ -506,7 +509,6 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
) : t.data.node.template[n]
.type === "file" ? (
<ShadTooltip
delayDuration={1000}
content={buildContent(
getValue(
t.data.node.template[n]
@ -622,7 +624,6 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
) : t.data.node.template[n]
.type === "prompt" ? (
<ShadTooltip
delayDuration={1000}
content={buildContent(
getValue(
t.data.node.template[n]
@ -659,7 +660,6 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
) : t.data.node.template[n]
.type === "code" ? (
<ShadTooltip
delayDuration={1000}
content={buildContent(
getValue(
t.data.node.template[n]
@ -720,7 +720,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
</div>
))}
{/*
{/*
<div className="flex flex-col gap-5 bg-muted">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="border-gray-200 text-gray-500 text-xs font-medium h-10">

View file

@ -1,26 +1,17 @@
import { Variable } from "lucide-react";
import { useContext, useEffect, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { NodeDataType } from "../../types/flow";
import { classNames, limitScrollFieldsModal } from "../../utils";
import { typesContext } from "../../contexts/typesContext";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "../../components/ui/table";
import ToggleShadComponent from "../../components/toggleShadComponent";
import InputListComponent from "../../components/inputListComponent";
import TextAreaComponent from "../../components/textAreaComponent";
import InputComponent from "../../components/inputComponent";
import FloatComponent from "../../components/floatComponent";
import Dropdown from "../../components/dropdownComponent";
import IntComponent from "../../components/intComponent";
import InputFileComponent from "../../components/inputFileComponent";
import PromptAreaComponent from "../../components/promptComponent";
import CodeAreaComponent from "../../components/codeAreaComponent";
import Dropdown from "../../components/dropdownComponent";
import FloatComponent from "../../components/floatComponent";
import InputComponent from "../../components/inputComponent";
import InputFileComponent from "../../components/inputFileComponent";
import InputListComponent from "../../components/inputListComponent";
import IntComponent from "../../components/intComponent";
import PromptAreaComponent from "../../components/promptComponent";
import TextAreaComponent from "../../components/textAreaComponent";
import ToggleShadComponent from "../../components/toggleShadComponent";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import {
Dialog,
DialogContent,
@ -30,9 +21,18 @@ import {
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Button } from "../../components/ui/button";
import { Badge } from "../../components/ui/badge";
import { Variable } from "lucide-react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "../../components/ui/table";
import { PopUpContext } from "../../contexts/popUpContext";
import { typesContext } from "../../contexts/typesContext";
import { NodeDataType } from "../../types/flow";
import { classNames, limitScrollFieldsModal } from "../../utils";
export default function EditNodeModal({ data }: { data: NodeDataType }) {
const [open, setOpen] = useState(true);
@ -90,27 +90,25 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
<DialogDescription>
{data.node?.description}
<div className="flex pt-3">
<Variable className="h-5 w-5 stroke-2 pe-1 text-muted-foreground "></Variable>
<span className="text-sm font-semibold text-primary">
Parameters
</span>
<Variable className="edit-node-modal-variable "></Variable>
<span className="edit-node-modal-span">Parameters</span>
</div>
</DialogDescription>
</DialogHeader>
<div className="flex h-fit max-h-[400px] w-full">
<div className="edit-node-modal-arrangement">
<div
className={classNames(
"w-full rounded-lg border-[1px] border-input bg-background",
"edit-node-modal-box",
nodeLength > limitScrollFieldsModal
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
)}
>
{nodeLength > 0 && (
<div className="flex h-fit flex-col gap-5">
<div className="edit-node-modal-table">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="h-10 border-input text-xs font-medium text-ring">
<TableHeader className="edit-node-modal-table-header">
<TableRow className="">
<TableHead className="h-7 text-center">PARAM</TableHead>
<TableHead className="h-7 p-0 text-center">

View file

@ -1,14 +1,14 @@
import { useState } from "react";
import InputListComponent from "../../../../components/inputListComponent";
import Dropdown from "../../../../components/dropdownComponent";
import TextAreaComponent from "../../../../components/textAreaComponent";
import InputComponent from "../../../../components/inputComponent";
import ToggleComponent from "../../../../components/toggleComponent";
import FloatComponent from "../../../../components/floatComponent";
import IntComponent from "../../../../components/intComponent";
import InputFileComponent from "../../../../components/inputFileComponent";
import PromptAreaComponent from "../../../../components/promptComponent";
import CodeAreaComponent from "../../../../components/codeAreaComponent";
import Dropdown from "../../../../components/dropdownComponent";
import FloatComponent from "../../../../components/floatComponent";
import InputComponent from "../../../../components/inputComponent";
import InputFileComponent from "../../../../components/inputFileComponent";
import InputListComponent from "../../../../components/inputListComponent";
import IntComponent from "../../../../components/intComponent";
import PromptAreaComponent from "../../../../components/promptComponent";
import TextAreaComponent from "../../../../components/textAreaComponent";
import ToggleComponent from "../../../../components/toggleComponent";
import { classNames } from "../../../../utils";
export default function ModalField({

View file

@ -1,6 +1,8 @@
import { Dialog, Transition } from "@headlessui/react";
import { X } from "lucide-react";
import { Fragment, useContext, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { typesContext } from "../../contexts/typesContext";
import { NodeDataType } from "../../types/flow";
import {
classNames,
@ -9,9 +11,7 @@ import {
nodeIconsLucide,
toTitleCase,
} from "../../utils";
import { typesContext } from "../../contexts/typesContext";
import ModalField from "./components/ModalField";
import { X } from "lucide-react";
export default function NodeModal({ data }: { data: NodeDataType }) {
const [open, setOpen] = useState(true);
@ -45,11 +45,11 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-ring bg-opacity-75 transition-opacity" />
<div className="node-modal-div" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<div className="node-modal-dialog-arrangement">
<div className="node-modal-dialog-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
@ -59,11 +59,11 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative flex h-[600px] w-[700px] transform flex-col justify-between overflow-hidden rounded-lg bg-background text-left shadow-xl transition-all sm:my-8">
<div className=" absolute right-0 top-0 z-50 hidden pr-4 pt-4 sm:block">
<Dialog.Panel className="node-modal-dialog-panel">
<div className=" node-modal-dialog-panel-div">
<button
type="button"
className="rounded-md text-ring hover:text-accent-foreground"
className="node-modal-dialog-button"
onClick={() => {
setModalOpen(false);
}}
@ -72,30 +72,27 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
<X className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="flex h-full w-full flex-col items-center justify-center">
<div className="z-10 flex w-full justify-center pb-4 shadow-sm">
<div className="node-modal-dialog-icon-div">
<div className="node-modal-icon-arrangement">
<Icon
strokeWidth={1.5}
className="mt-4 h-10 w-10 rounded p-1"
className="node-modal-icon"
style={{
color:
nodeColors[types[data.type]] ?? nodeColors.unknown,
}}
/>
<div className="mt-4 text-center sm:ml-4 sm:text-left">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-10 text-foreground"
>
<div className="node-modal-title-div">
<Dialog.Title as="h3" className="node-modal-title">
{data.type}
</Dialog.Title>
</div>
</div>
<div className="flex h-full w-full flex-row items-center justify-center gap-4 bg-input p-4">
<div className="flex h-[445px] w-full">
<div className="node-modal-template-div">
<div className="flex-max-width h-[445px]">
<div
className={classNames(
"w-full rounded-lg bg-background px-4 shadow sm:p-4",
"node-modal-template",
Object.keys(data.node.template).filter(
(t) =>
t.charAt(0) !== "_" &&
@ -106,7 +103,7 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
: "overflow-hidden"
)}
>
<div className="flex h-full flex-col gap-5">
<div className="node-modal-template-column">
{Object.keys(data.node.template)
.filter(
(t) =>
@ -144,10 +141,10 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
</div>
</div>
</div>
<div className="flex w-full flex-row-reverse bg-input px-4 pb-3">
<div className="node-modal-button-box">
<button
type="button"
className="inline-flex w-full justify-center rounded-md border border-transparent bg-status-red px-4 py-2 text-base font-medium text-background shadow-sm hover:bg-ring focus:outline-none focus:ring-1 focus:ring-ring focus:ring-offset-1 sm:ml-3 sm:w-auto sm:text-sm"
className="node-modal-button"
onClick={() => {
setModalOpen(false);
}}

View file

@ -0,0 +1,157 @@
import Convert from "ansi-to-html";
import DOMPurify from "dompurify";
import { MessageCircle, User2 } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import ReactMarkdown from "react-markdown";
import rehypeMathjax from "rehype-mathjax";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg";
import AiIconStill from "../../../assets/froze-flow.png";
import { ChatMessageType } from "../../../types/chat";
import { classNames } from "../../../utils";
import FileCard from "../fileComponent";
import { CodeBlock } from "./codeBlock";
export default function ChatMessage({
chat,
lockChat,
lastMessage,
}: {
chat: ChatMessageType;
lockChat: boolean;
lastMessage: boolean;
}) {
const convert = new Convert({ newline: true });
const [message, setMessage] = useState("");
const imgRef = useRef(null);
useEffect(() => {
setMessage(chat.message);
}, [chat.message]);
const [hidden, setHidden] = useState(true);
return (
<div
className={classNames(
"chat-message-modal",
chat.isSend ? "bg-background " : "bg-input"
)}
>
<div className={classNames("chat-message-modal-div")}>
{!chat.isSend && (
<div className="relative h-8 w-8">
<img
className={
"chat-message-modal-img " +
(lockChat ? "opacity-100" : "opacity-0")
}
src={lastMessage ? AiIcon : AiIconStill}
/>
<img
className={
"chat-message-modal-img " +
(lockChat ? "opacity-0" : "opacity-100")
}
src={AiIconStill}
/>
</div>
)}
{chat.isSend && <User2 className="-mb-1 h-6 w-6 text-primary " />}
</div>
{!chat.isSend ? (
<div className="chat-message-modal-display">
<div className="chat-message-modal-text">
{hidden && chat.thought && chat.thought !== "" && (
<div
onClick={() => setHidden((prev) => !prev)}
className="chat-message-modal-icon-div"
>
<MessageCircle className="h-5 w-5 animate-bounce " />
</div>
)}
{chat.thought && chat.thought !== "" && !hidden && (
<div
onClick={() => setHidden((prev) => !prev)}
className=" chat-message-modal-thought"
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
}}
></div>
)}
{chat.thought && chat.thought !== "" && !hidden && <br></br>}
<div className="chat-message-modal-markdown">
<div className="w-full">
<div className="w-full">
<ReactMarkdown
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeMathjax]}
className="markdown prose text-muted-foreground "
components={{
code({ node, inline, className, children, ...props }) {
if (children.length) {
if (children[0] == "▍") {
return (
<span className="chat-message-modal-markdown-span">
▍
</span>
);
}
children[0] = (children[0] as string).replace(
"`▍`",
"▍"
);
}
const match = /language-(\w+)/.exec(className || "");
return !inline ? (
<CodeBlock
key={Math.random()}
language={(match && match[1]) || ""}
value={String(children).replace(/\n$/, "")}
{...props}
/>
) : (
<code className={className} {...props}>
{children}
</code>
);
},
}}
>
{message}
</ReactMarkdown>
</div>
{chat.files && (
<div className="my-2 w-full">
{chat.files.map((file, index) => {
return (
<div key={index} className="my-2 w-full">
<FileCard
fileName={"Generated File"}
fileType={file.data_type}
content={file.data}
/>
</div>
);
})}
</div>
)}
</div>
</div>
</div>
</div>
) : (
<div className="flex w-full items-center">
<div className="chat-message-modal-alert ">
{message.split("\n").map((line, index) => (
<span key={index} className="text-muted-foreground ">
{line}
<br />
</span>
))}
</div>
</div>
)}
</div>
);
}

View file

@ -0,0 +1,415 @@
import { Dialog, Transition } from "@headlessui/react";
import { Eraser, MessagesSquare, X } from "lucide-react";
import { Fragment, useContext, useEffect, useRef, useState } from "react";
import { alertContext } from "../../contexts/alertContext";
import { typesContext } from "../../contexts/typesContext";
import { sendAllProps } from "../../types/api";
import { ChatMessageType } from "../../types/chat";
import { FlowType } from "../../types/flow";
import { validateNodes } from "../../utils";
import ChatInput from "./chatInput";
import ChatMessage from "./chatMessage";
import _ from "lodash";
import { getHealth } from "../../controllers/API";
export default function ChatModal({
flow,
open,
setOpen,
}: {
open: boolean;
setOpen: Function;
flow: FlowType;
}) {
const [chatValue, setChatValue] = useState("");
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
const { reactFlowInstance } = useContext(typesContext);
const { setErrorData, setNoticeData } = useContext(alertContext);
const ws = useRef<WebSocket | null>(null);
const [lockChat, setLockChat] = useState(false);
const isOpen = useRef(open);
const messagesRef = useRef(null);
const id = useRef(flow.id);
useEffect(() => {
if (messagesRef.current) {
messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
}
}, [chatHistory]);
useEffect(() => {
isOpen.current = open;
}, [open]);
useEffect(() => {
id.current = flow.id;
}, [flow.id]);
var isStream = false;
const addChatHistory = (
message: string,
isSend: boolean,
thought?: string,
files?: Array<any>
) => {
setChatHistory((old) => {
let newChat = _.cloneDeep(old);
if (files) {
newChat.push({ message, isSend, files, thought });
} else if (thought) {
newChat.push({ message, isSend, thought });
} else {
newChat.push({ message, isSend });
}
return newChat;
});
};
//add proper type signature for function
function updateLastMessage({
str,
thought,
end = false,
files,
}: {
str?: string;
thought?: string;
// end param default is false
end?: boolean;
files?: Array<any>;
}) {
setChatHistory((old) => {
let newChat = [...old];
if (str) {
if (end) {
newChat[newChat.length - 1].message = str;
} else {
newChat[newChat.length - 1].message =
newChat[newChat.length - 1].message + str;
}
}
if (thought) {
newChat[newChat.length - 1].thought = thought;
}
if (files) {
newChat[newChat.length - 1].files = files;
}
return newChat;
});
}
function handleOnClose(event: CloseEvent) {
if (isOpen.current) {
setErrorData({ title: event.reason });
setTimeout(() => {
connectWS();
setLockChat(false);
}, 1000);
}
}
function getWebSocketUrl(chatId, isDevelopment = false) {
const isSecureProtocol = window.location.protocol === "https:";
const webSocketProtocol = isSecureProtocol ? "wss" : "ws";
const host = isDevelopment ? "localhost:7860" : window.location.host;
const chatEndpoint = `/api/v1/chat/${chatId}`;
return `${
isDevelopment ? "ws" : webSocketProtocol
}://${host}${chatEndpoint}`;
}
function handleWsMessage(data: any) {
if (Array.isArray(data)) {
//set chat history
setChatHistory((_) => {
let newChatHistory: ChatMessageType[] = [];
data.forEach(
(chatItem: {
intermediate_steps?: "string";
is_bot: boolean;
message: string;
type: string;
files?: Array<any>;
}) => {
if (chatItem.message) {
newChatHistory.push(
chatItem.files
? {
isSend: !chatItem.is_bot,
message: chatItem.message,
thought: chatItem.intermediate_steps,
files: chatItem.files,
}
: {
isSend: !chatItem.is_bot,
message: chatItem.message,
thought: chatItem.intermediate_steps,
}
);
}
}
);
return newChatHistory;
});
}
if (data.type === "start") {
addChatHistory("", false);
isStream = true;
}
if (data.type === "end") {
if (data.message) {
updateLastMessage({ str: data.message, end: true });
}
if (data.intermediate_steps) {
updateLastMessage({
str: data.message,
thought: data.intermediate_steps,
end: true,
});
}
if (data.files) {
updateLastMessage({
end: true,
files: data.files,
});
}
setLockChat(false);
isStream = false;
}
if (data.type === "stream" && isStream) {
updateLastMessage({ str: data.message });
}
}
function connectWS() {
try {
const urlWs = getWebSocketUrl(
id.current,
process.env.NODE_ENV === "development"
);
const newWs = new WebSocket(urlWs);
newWs.onopen = () => {
console.log("WebSocket connection established!");
};
newWs.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("Received data:", data);
handleWsMessage(data);
//get chat history
};
newWs.onclose = (event) => {
handleOnClose(event);
};
newWs.onerror = (ev) => {
getHealth()
.then((res) => {
if (res.status === 200) {
connectWS();
}
})
.catch((err) => {
setErrorData({
// message when the backend failed
title: "The backend is not responding. Please try again later.",
// possible solution list
list: [
"Check your internet connection.",
"Check if the backend is running.",
],
});
});
};
ws.current = newWs;
} catch (error) {
connectWS();
console.log(error);
}
}
useEffect(() => {
connectWS();
return () => {
console.log("unmount");
console.log(ws);
if (ws.current) {
ws.current.close();
}
};
}, []);
useEffect(() => {
if (
ws.current &&
(ws.current.readyState === ws.current.CLOSED ||
ws.current.readyState === ws.current.CLOSING)
) {
connectWS();
setLockChat(false);
}
}, [lockChat]);
async function sendAll(data: sendAllProps) {
try {
if (ws) {
ws.current.send(JSON.stringify(data));
}
} catch (error) {
setErrorData({
title: "There was an error sending the message",
list: [error.message],
});
setChatValue(data.message);
connectWS();
}
}
useEffect(() => {
if (ref.current) ref.current.scrollIntoView({ behavior: "smooth" });
}, [chatHistory]);
const ref = useRef(null);
useEffect(() => {
if (open && ref.current) {
ref.current.focus();
}
}, [open]);
function sendMessage() {
if (chatValue !== "") {
let nodeValidationErrors = validateNodes(reactFlowInstance);
if (nodeValidationErrors.length === 0) {
setLockChat(true);
let message = chatValue;
setChatValue("");
addChatHistory(message, true);
sendAll({
...reactFlowInstance.toObject(),
message,
chatHistory,
name: flow.name,
description: flow.description,
});
} else {
setErrorData({
title: "Oops! Looks like you missed some required information:",
list: nodeValidationErrors,
});
}
} else {
setErrorData({
title: "Error sending message",
list: ["The message cannot be empty."],
});
}
}
function clearChat() {
setChatHistory([]);
ws.current.send(JSON.stringify({ clear_history: true }));
if (lockChat) setLockChat(false);
}
function setModalOpen(x: boolean) {
setOpen(x);
}
return (
<Transition.Root show={open} appear={open} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={setModalOpen}
initialFocus={ref}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="send-message-modal-transition" />
</Transition.Child>
<div className="chat-modal-box">
<div className="chat-modal-box-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className=" chat-modal-dialog-panel">
<div className="chat-modal-dialog-panel-div">
<button
onClick={() => clearChat()}
className="chat-modal-dialog-trash-panel"
>
<Eraser className="h-4 w-4" />
</button>
<button
onClick={() => setModalOpen(false)}
className="chat-modal-dialog-x-panel"
>
<X className="h-5 w-5" />
</button>
</div>
<div ref={messagesRef} className="chat-modal-dialog-history">
{chatHistory.length > 0 ? (
chatHistory.map((c, i) => (
<ChatMessage
lockChat={lockChat}
chat={c}
lastMessage={chatHistory.length - 1 == i ? true : false}
key={i}
/>
))
) : (
<div className="chat-modal-dialog-span-box">
<span>
👋{" "}
<span className="text-lg text-muted-foreground">
Langflow Chat
</span>
</span>
<br />
<div className="chat-modal-dialog-desc">
<span className="text-base text-ring">
Start a conversation and click the agent’s thoughts{" "}
<span>
<MessagesSquare className="mx-1 inline h-5 w-5 animate-bounce " />
</span>{" "}
to inspect the chaining process.
</span>
</div>
</div>
)}
<div ref={ref}></div>
</div>
<div className="chat-modal-input-div">
<div className="chat-modal-input">
<ChatInput
chatValue={chatValue}
lockChat={lockChat}
sendMessage={sendMessage}
setChatValue={setChatValue}
inputRef={ref}
/>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}

View file

@ -1,15 +1,16 @@
import { useContext, useEffect, useRef, useState } from "react";
// organize-imports-ignore
import { useContext, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import AceEditor from "react-ace";
import "ace-builds/src-noconflict/ext-language_tools";
import "ace-builds/src-noconflict/mode-python";
import "ace-builds/src-noconflict/theme-github";
import "ace-builds/src-noconflict/theme-twilight";
import "ace-builds/src-noconflict/ext-language_tools";
import "ace-builds/src-noconflict/ace";
// import "ace-builds/webpack-resolver";
import { darkContext } from "../../contexts/darkContext";
import { postCustomComponent, postValidateCode } from "../../controllers/API";
import { alertContext } from "../../contexts/alertContext";
import { TerminalSquare } from "lucide-react";
import { Button } from "../../components/ui/button";
import {
Dialog,
DialogContent,
@ -19,9 +20,10 @@ import {
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Button } from "../../components/ui/button";
import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants";
import { TerminalSquare } from "lucide-react";
import { alertContext } from "../../contexts/alertContext";
import { darkContext } from "../../contexts/darkContext";
import { postValidateCode } from "../../controllers/API";
import { APIClassType } from "../../types/api";
import {
Tabs,

View file

@ -1,8 +1,8 @@
import { Download } from "lucide-react";
import { useContext, useRef, useState } from "react";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { removeApiKeys } from "../../utils";
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
import { Button } from "../../components/ui/button";
import { Checkbox } from "../../components/ui/checkbox";
import {
Dialog,
DialogContent,
@ -12,11 +12,11 @@ import {
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Button } from "../../components/ui/button";
import { Checkbox } from "../../components/ui/checkbox";
import { EXPORT_DIALOG_SUBTITLE } from "../../constants";
import { Download } from "lucide-react";
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { removeApiKeys } from "../../utils";
export default function ExportModal() {
const [open, setOpen] = useState(true);

View file

@ -1,7 +1,7 @@
import { Settings2 } from "lucide-react";
import { useContext, useRef, useState } from "react";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
import { Button } from "../../components/ui/button";
import {
Dialog,
DialogContent,
@ -11,11 +11,10 @@ import {
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Button } from "../../components/ui/button";
import { SETTINGS_DIALOG_SUBTITLE } from "../../constants";
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
import { Settings2 } from "lucide-react";
import { updateFlowInDatabase } from "../../controllers/API";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
export default function FlowSettingsModal() {
const [open, setOpen] = useState(true);

View file

@ -1,7 +1,6 @@
import { Lock, LucideSend } from "lucide-react";
import { useEffect } from "react";
import { classNames } from "../../../utils";
import { useContext, useEffect, useRef, useState } from "react";
import { TabsContext } from "../../../contexts/tabsContext";
import { Eraser, Lock, LucideSend, Send } from "lucide-react";
export default function ChatInput({
lockChat,

View file

@ -48,21 +48,15 @@ export const CodeBlock: FC<Props> = memo(({ language, value }) => {
};
return (
<div className="codeblock font-sans text-[16px]">
<div className="flex items-center justify-between px-4 py-1.5">
<span className="text-xs lowercase text-background">{language}</span>
<div className="code-block-modal">
<span className="code-block-modal-span">{language}</span>
<div className="flex items-center">
<button
className="flex items-center gap-1.5 rounded bg-none p-1 text-xs text-background"
onClick={copyToClipboard}
>
<button className="code-block-modal-button" onClick={copyToClipboard}>
{isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
{isCopied ? "Copied!" : "Copy code"}
</button>
<button
className="flex items-center rounded bg-none p-1 text-xs text-background"
onClick={downloadAsFile}
>
<button className="code-block-modal-button" onClick={downloadAsFile}>
<IconDownload size={18} />
</button>
</div>

View file

@ -1,23 +1,17 @@
import { useEffect, useRef, useState } from "react";
import { ChatMessageType } from "../../../types/chat";
import { classNames } from "../../../utils";
import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg";
import AiIconStill from "../../../assets/froze-flow.png";
import FileCard from "../fileComponent";
import Convert from "ansi-to-html";
import { ChevronDown } from "lucide-react";
import { useState } from "react";
import ReactMarkdown from "react-markdown";
import rehypeMathjax from "rehype-mathjax";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import MaleTechnology from "../../../assets/male-technologist.png";
import Robot from "../../../assets/robot.png";
import { THOUGHTS_ICON } from "../../../constants";
import { ChatMessageType } from "../../../types/chat";
import { classNames } from "../../../utils";
import FileCard from "../fileComponent";
import { CodeBlock } from "./codeBlock";
import Convert from "ansi-to-html";
import { User2, MessageSquare } from "lucide-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "../../../components/ui/accordion";
import { Badge } from "../../../components/ui/badge";
export default function ChatMessage({
chat,
@ -31,33 +25,38 @@ export default function ChatMessage({
const convert = new Convert({ newline: true });
const [hidden, setHidden] = useState(true);
const [template, setTemplate] = useState(chat.template);
const [promptOpen, setPromptOpen] = useState(false);
return (
<div
className={classNames(
"flex w-full px-2 py-6 pl-4 pr-9",
chat.isSend ? " bg-border" : " "
chat.isSend ? "" : " "
)}
>
<div className={classNames("mb-3 ml-3 mr-6 mt-1 ")}>
{!chat.isSend ? (
<div className="flex h-8 w-8 items-center justify-center overflow-hidden rounded-md bg-[#afe6ef] p-5 text-2xl ">
🤖
<div className="flex flex-col items-center gap-1">
<div className="relative flex h-8 w-8 items-center justify-center overflow-hidden rounded-md bg-[#afe6ef] p-5 text-2xl ">
<img src={Robot} className="absolute scale-[60%]" />
</div>
</div>
) : (
<div className="flex h-8 w-8 items-center justify-center overflow-hidden rounded-md bg-[#aface9] p-5 text-2xl ">
👨‍💻
<div className="flex flex-col items-center gap-1">
<div className="relative flex h-8 w-8 items-center justify-center overflow-hidden rounded-md bg-[#aface9] p-5 text-2xl ">
<img src={MaleTechnology} className="absolute scale-[60%]" />
</div>
</div>
)}
</div>
{!chat.isSend ? (
<div className="flex w-full items-center text-start">
<div className="relative inline-block w-full text-start text-sm font-normal text-primary">
<div className="flex w-full flex-1 text-start">
<div className="relative inline-block w-full text-start text-sm font-normal text-muted-foreground">
{hidden && chat.thought && chat.thought !== "" && (
<div
onClick={() => setHidden((prev) => !prev)}
className="absolute -left-2 -top-1 cursor-pointer"
className="absolute -left-8 -top-3 cursor-pointer"
>
<MessageSquare className="h-5 w-5 animate-bounce dark:text-white" />
<THOUGHTS_ICON className="h-4 w-4 animate-bounce dark:text-white" />
</div>
)}
{chat.thought && chat.thought !== "" && !hidden && (
@ -77,7 +76,8 @@ export default function ChatMessage({
<ReactMarkdown
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeMathjax]}
className="markdown prose max-w-full text-primary dark:prose-invert"
className="markdown prose inline-block break-words text-primary
dark:prose-invert"
components={{
code({ node, inline, className, children, ...props }) {
if (children.length) {
@ -135,65 +135,52 @@ export default function ChatMessage({
</div>
</div>
) : (
<div className="flex w-full items-center">
<div className="inline-block text-start">
<span className=" break-all text-primary">
<Accordion type="single" collapsible className="mb-4">
<AccordionItem
className=" rounded-md border border-ring/60 bg-muted px-4"
value="prompt"
>
<AccordionTrigger className="flex gap-4 text-base font-semibold">
Initial Prompt
</AccordionTrigger>
<AccordionContent className="max-h-96 overflow-auto break-all p-2 text-base">
{
// Make all the variables that are inside curly braces bold
template.split("\n").map((line, index) => {
const regex = /{([^}]+)}/g;
let match;
let parts = [];
let lastIndex = 0;
while ((match = regex.exec(line)) !== null) {
// Push text up to the match
if (match.index !== lastIndex) {
parts.push(line.substring(lastIndex, match.index));
}
// Push div with matched text
parts.push(
<div>
<div className="my-1 inline-block rounded-md bg-indigo-100 px-2">
<span key={match.index}>
<span className=" text-xs font-semibold text-high-indigo">
{match[1]}
</span>
{chat.message[match[1]] ? (
<span>
&nbsp;&nbsp;{chat.message[match[1]]}
</span>
) : (
""
)}
</span>
</div>
</div>
);
// Update last index
lastIndex = regex.lastIndex;
}
// Push text after the last match
if (lastIndex !== line.length) {
parts.push(line.substring(lastIndex));
}
return <p>{parts}</p>;
})
<div>
<button
className="mb-2 flex items-center gap-4 rounded-md border border-ring/60 bg-background px-4 py-2 text-base font-semibold"
onClick={() => {
setPromptOpen((old) => !old);
}}
>
Initial Prompt
<ChevronDown
className={
"h-3 w-3 transition-all " + (promptOpen ? "rotate-180" : "")
}
/>
</button>
<span className="prose inline-block break-words text-primary dark:prose-invert">
{promptOpen
? template.split("\n").map((line, index) => {
const regex = /{([^}]+)}/g;
let match;
let parts = [];
let lastIndex = 0;
while ((match = regex.exec(line)) !== null) {
// Push text up to the match
if (match.index !== lastIndex) {
parts.push(line.substring(lastIndex, match.index));
}
</AccordionContent>
</AccordionItem>
</Accordion>
{chat.message[chat.chatKey]}
</span>
</div>
// Push div with matched text
if (chat.message[match[1]]) {
parts.push(
<span className="my-1 rounded-md bg-indigo-100">
{chat.message[match[1]]}
</span>
);
}
// Update last index
lastIndex = regex.lastIndex;
}
// Push text after the last match
if (lastIndex !== line.length) {
parts.push(line.substring(lastIndex));
}
return <p>{parts}</p>;
})
: chat.message[chat.chatKey]}
</span>
</div>
)}
</div>

View file

@ -1,6 +1,6 @@
import * as base64js from "base64-js";
import { useState } from "react";
import { DownloadCloud, File } from "lucide-react";
import { useState } from "react";
export default function FileCard({ fileName, content, fileType }) {
const handleDownload = () => {
@ -36,10 +36,11 @@ export default function FileCard({ fileName, content, fileType }) {
className="h-full w-full rounded-lg"
/>
{isHovered && (
<div
className={`absolute right-0 top-0 rounded-bl-lg bg-muted px-1 text-sm font-bold text-foreground `}
>
<button className="px-2 py-1 text-ring " onClick={handleDownload}>
<div className={`file-card-modal-image-div `}>
<button
className="file-card-modal-image-button "
onClick={handleDownload}
>
<DownloadCloud className="h-5 w-5 text-current hover:scale-110" />
</button>
</div>
@ -49,11 +50,8 @@ export default function FileCard({ fileName, content, fileType }) {
}
return (
<button
onClick={handleDownload}
className="flex w-1/2 items-center justify-between rounded border border-ring bg-muted px-2 py-2 text-foreground shadow hover:drop-shadow-lg"
>
<div className="mr-2 flex w-full items-center gap-2 text-current">
<button onClick={handleDownload} className="file-card-modal-button">
<div className="file-card-modal-div">
{" "}
{fileType === "image" ? (
<img
@ -64,10 +62,10 @@ export default function FileCard({ fileName, content, fileType }) {
) : (
<File className="h-8 w-8" />
)}
<div className="flex flex-col items-start">
<div className="file-card-modal-footer">
{" "}
<div className="truncate text-sm text-current">{fileName}</div>
<div className="truncate text-xs text-ring">{fileType}</div>
<div className="file-card-modal-name">{fileName}</div>
<div className="file-card-modal-type">{fileType}</div>
</div>
<DownloadCloud className="ml-auto h-6 w-6 text-current" />
</div>

View file

@ -1,15 +1,23 @@
import { Eraser, TerminalSquare, Variable } from "lucide-react";
import { useContext, useEffect, useRef, useState } from "react";
import { FlowType } from "../../types/flow";
import { alertContext } from "../../contexts/alertContext";
import { classNames, validateNodes } from "../../utils";
import { typesContext } from "../../contexts/typesContext";
import ChatMessage from "./chatMessage";
import { TerminalSquare, MessageSquare, Variable, Eraser } from "lucide-react";
import { sendAllProps } from "../../types/api";
import { ChatMessageType } from "../../types/chat";
import { FlowType } from "../../types/flow";
import { classNames, validateNodes } from "../../utils";
import ChatInput from "./chatInput";
import ChatMessage from "./chatMessage";
import _ from "lodash";
import ToggleShadComponent from "../../components/toggleShadComponent";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "../../components/ui/accordion";
import { Badge } from "../../components/ui/badge";
import {
Dialog,
DialogContent,
@ -18,17 +26,9 @@ import {
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants";
import { TabsContext } from "../../contexts/tabsContext";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "../../components/ui/accordion";
import { Textarea } from "../../components/ui/textarea";
import { Badge } from "../../components/ui/badge";
import ToggleShadComponent from "../../components/toggleShadComponent";
import { CHAT_FORM_DIALOG_SUBTITLE, THOUGHTS_ICON } from "../../constants";
import { TabsContext } from "../../contexts/tabsContext";
export default function FormModal({
flow,
@ -535,7 +535,7 @@ export default function FormModal({
<span className="text-base text-gray-500">
Start a conversation and click the agent's thoughts{" "}
<span>
<MessageSquare className="mx-1 inline h-5 w-5 animate-bounce " />
<THOUGHTS_ICON className="mx-1 inline h-5 w-5 animate-bounce " />
</span>{" "}
to inspect the chaining process.
</span>

View file

@ -1,8 +1,9 @@
import { useContext, useRef, useState, useEffect } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { darkContext } from "../../contexts/darkContext";
import { postValidatePrompt } from "../../controllers/API";
import { alertContext } from "../../contexts/alertContext";
import DOMPurify from "dompurify";
import { FileText, Variable } from "lucide-react";
import { useContext, useEffect, useRef, useState } from "react";
import ShadTooltip from "../../components/ShadTooltipComponent";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import {
Dialog,
DialogContent,
@ -12,14 +13,16 @@ import {
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Button } from "../../components/ui/button";
import { Textarea } from "../../components/ui/textarea";
import {
HIGHLIGH_CSS,
PROMPT_DIALOG_SUBTITLE,
TEXT_DIALOG_SUBTITLE,
} from "../../constants";
import { FileText } from "lucide-react";
import { alertContext } from "../../contexts/alertContext";
import { darkContext } from "../../contexts/darkContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { postValidatePrompt } from "../../controllers/API";
import { APIClassType } from "../../types/api";
import {
INVALID_CHARACTERS,
@ -29,9 +32,6 @@ import {
regexHighlight,
varHighlightHTML,
} from "../../utils";
import { Badge } from "../../components/ui/badge";
import ShadTooltip from "../../components/ShadTooltipComponent";
import DOMPurify from "dompurify";
export default function GenericModal({
field_name = "",
@ -170,7 +170,7 @@ export default function GenericModal({
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger></DialogTrigger>
<DialogContent className="min-w-[80vw]">
<DialogContent className="min-w-[80vw] gap-2">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">{myModalTitle}</span>
@ -196,49 +196,16 @@ export default function GenericModal({
</DialogDescription>
</DialogHeader>
{type == TypeModal.PROMPT &&
inputValue &&
inputValue != "" &&
wordsHighlight.length > 0 && (
<>
<div>
<span className="">Variables: </span>
{wordsHighlight.map((word, index) => (
<ShadTooltip
key={getRandomKeyByssmm() + index}
content={word.replace(/[{}]/g, "")}
asChild={false}
delayDuration={1500}
>
<Badge
key={index}
size="lg"
className="m-1 max-w-[40vw] cursor-default truncate p-2.5 text-sm"
>
<div className="relative bottom-[1px]">
<span>
{word.replace(/[{}]/g, "").length > 59
? word.replace(/[{}]/g, "").slice(0, 56) + "..."
: word.replace(/[{}]/g, "")}
</span>
</div>
</Badge>
</ShadTooltip>
))}
</div>
</>
)}
<div
className={classNames(
!isEdit ? "rounded-lg border" : "",
"flex h-[60vh] w-full"
"flex h-[55vh] w-full"
)}
>
{type == TypeModal.PROMPT && isEdit ? (
<Textarea
ref={ref}
className="form-input h-full w-full rounded-lg border-gray-300 focus-visible:ring-1 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
className="form-input h-full w-full rounded-lg border-gray-300 custom-scroll focus-visible:ring-1 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
value={inputValue}
onBlur={() => {
blur();
@ -268,16 +235,55 @@ export default function GenericModal({
)}
</div>
{type == TypeModal.PROMPT && (
<>
<div className="sm:6/6 mr-28 mt-3 h-[60px] overflow-y-auto custom-scroll">
<div className="flex flex-wrap items-center">
<Variable className=" -ml-px mr-1 flex h-4 w-4 text-primary"></Variable>
<span className="text-md font-semibold text-primary">
Input Variables:
</span>
{wordsHighlight.map((word, index) => (
<ShadTooltip
key={getRandomKeyByssmm() + index}
content={word.replace(/[{}]/g, "")}
asChild={false}
>
<Badge
key={index}
variant="gray"
size="md"
className="m-1 max-w-[40vw] cursor-default truncate p-2.5 text-sm"
>
<div className="relative bottom-[1px]">
<span>
{word.replace(/[{}]/g, "").length > 59
? word.replace(/[{}]/g, "").slice(0, 56) + "..."
: word.replace(/[{}]/g, "")}
</span>
</div>
</Badge>
</ShadTooltip>
))}
</div>
</div>
</>
)}
<DialogFooter>
<Button
className="mt-3"
onClick={() => {
switch (myModalType) {
case 1:
setValue(inputValue);
setModalOpen(false);
break;
case 2:
validatePrompt(false);
!inputValue || inputValue == ""
? setModalOpen(false)
: validatePrompt(false);
break;
default:

View file

@ -1,4 +1,4 @@
import React, { ReactNode } from "react";
import { ReactNode } from "react";
import { classNames } from "../../../utils";
export default function ButtonBox({
@ -77,7 +77,7 @@ export default function ButtonBox({
<button disabled={deactivate} onClick={onClick}>
<div
className={classNames(
"flex transform flex-col items-center justify-center rounded-lg border border-ring text-center shadow hover:scale-105 hover:shadow-lg",
"button-box-modal-div",
bgColor,
height,
width,

View file

@ -1,22 +1,11 @@
import {
XMarkIcon,
ArrowDownTrayIcon,
DocumentDuplicateIcon,
ComputerDesktopIcon,
ArrowUpTrayIcon,
ArrowLeftIcon,
CommandLineIcon,
ArrowUpTrayIcon,
ComputerDesktopIcon,
DocumentDuplicateIcon,
} from "@heroicons/react/24/outline";
import { Fragment, useContext, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import ButtonBox from "./buttonBox";
import { getExamples } from "../../controllers/API";
import { error } from "console";
import { alertContext } from "../../contexts/alertContext";
import { useContext, useRef, useState } from "react";
import LoadingComponent from "../../components/loadingComponent";
import { FlowType } from "../../types/flow";
import { classNames, snakeToSpaces, toNormalCase } from "../../utils";
import {
Dialog,
DialogContent,
@ -26,8 +15,14 @@ import {
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Button } from "../../components/ui/button";
import { IMPORT_DIALOG_SUBTITLE } from "../../constants";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { getExamples } from "../../controllers/API";
import { FlowType } from "../../types/flow";
import { classNames } from "../../utils";
import ButtonBox from "./buttonBox";
export default function ImportModal() {
const [open, setOpen] = useState(true);
@ -76,10 +71,10 @@ export default function ImportModal() {
<DialogTitle className="flex items-center">
{showExamples && (
<>
<div className="absolute left-0 top-2 z-50 hidden pl-4 pt-4 sm:block">
<div className="dialog-header-modal-div">
<button
type="button"
className="rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
className="dialog-header-modal-button disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
onClick={() => {
setShowExamples(false);
}}
@ -106,21 +101,19 @@ export default function ImportModal() {
<div
className={classNames(
"h-full w-full overflow-y-auto scrollbar-hide",
"dialog-modal-examples-div",
showExamples && !loadingExamples
? "start mx-auto flex flex-row flex-wrap items-start justify-center overflow-auto"
: "flex flex-row items-center justify-center"
? "dialog-modal-example-true"
: "dialog-modal-example-false"
)}
>
{!showExamples && (
<div className="flex h-full w-full items-center justify-evenly">
<div className="dialog-modal-button-box-div">
<ButtonBox
size="big"
bgColor="bg-medium-emerald "
description="Prebuilt Examples"
icon={
<DocumentDuplicateIcon className="h-10 w-10 flex-shrink-0" />
}
icon={<DocumentDuplicateIcon className="document-icon" />}
onClick={() => {
setShowExamples(true);
handleExamples();
@ -132,9 +125,7 @@ export default function ImportModal() {
size="big"
bgColor="bg-almost-dark-blue "
description="Import from Local"
icon={
<ComputerDesktopIcon className="h-10 w-10 flex-shrink-0" />
}
icon={<ComputerDesktopIcon className="document-icon" />}
onClick={() => {
uploadFlow();
setModalOpen(false);
@ -145,7 +136,7 @@ export default function ImportModal() {
</div>
)}
{showExamples && loadingExamples && (
<div className="flex items-center justify-center align-middle">
<div className="loading-component-div">
<LoadingComponent remSize={30} />
</div>
)}
@ -178,11 +169,11 @@ export default function ImportModal() {
</div>
<DialogFooter>
<div className="mt-2 flex w-full items-center justify-center">
<div className="dialog-modal-footer">
<a
href="https://github.com/logspace-ai/langflow_examples"
target="_blank"
className="flex items-center justify-center text-muted-foreground "
className="dialog-modal-footer-link "
rel="noreferrer"
>
<svg
@ -197,7 +188,7 @@ export default function ImportModal() {
fill="currentColor"
/>
</svg>
<span className="ml-2 ">LangFlow Examples</span>
<span className="ml-2 ">Langflow Examples</span>
</a>
</div>
</DialogFooter>

View file

@ -0,0 +1,151 @@
import { Dialog, Transition } from "@headlessui/react";
import { DocumentTextIcon, XMarkIcon } from "@heroicons/react/24/outline";
import { Fragment, useContext, useRef, useState } from "react";
import { alertContext } from "../../contexts/alertContext";
import { darkContext } from "../../contexts/darkContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { checkPrompt } from "../../controllers/API";
export default function PromptAreaModal({
value,
setValue,
}: {
setValue: (value: string) => void;
value: string;
}) {
const [open, setOpen] = useState(true);
const [myValue, setMyValue] = useState(value);
const { dark } = useContext(darkContext);
const { setErrorData, setSuccessData } = useContext(alertContext);
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
const ref = useRef();
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
setCloseEdit("prompt");
closePopUp();
}, 300);
}
}
return (
<Transition.Root show={open} appear={true} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={setModalOpen}
initialFocus={ref}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="node-modal-div" />
</Transition.Child>
<div className="node-modal-dialog-arrangement">
<div className="node-modal-dialog-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="node-modal-dialog-panel">
<div className=" node-modal-dialog-panel-div ">
<button
type="button"
className="node-modal-dialog-button"
onClick={() => {
setModalOpen(false);
}}
>
<span className="sr-only">Close</span>
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="node-modal-dialog-icon-div">
<div className="node-modal-icon-arrangement">
<div className="prompt-modal-icon-box">
<DocumentTextIcon
className="prompt-modal-icon"
aria-hidden="true"
/>
</div>
<div className="node-modal-title-div ">
<Dialog.Title as="h3" className="node-modal-title">
Edit Prompt
</Dialog.Title>
</div>
</div>
<div className="prompt-modal-txtarea-arrangement">
<div className="flex-max-width h-full">
<div className="prompt-modal-txtarea-box">
<textarea
ref={ref}
className="prompt-modal-txtarea"
value={myValue}
onChange={(e) => {
setMyValue(e.target.value);
setValue(e.target.value);
}}
/>
</div>
</div>
</div>
<div className="node-modal-button-box">
<button
type="button"
className="node-modal-button"
onClick={() => {
checkPrompt(myValue)
.then((apiReturn) => {
if (apiReturn.data) {
let inputVariables =
apiReturn.data.input_variables;
if (inputVariables.length === 0) {
setErrorData({
title:
"The template you are attempting to use does not contain any variables for data entry.",
});
} else {
setSuccessData({
title: "Prompt is ready",
});
setModalOpen(false);
setValue(myValue);
}
} else {
setErrorData({
title: "Something went wrong, please try again",
});
}
})
.catch((error) => {
return setErrorData({
title:
"There is something wrong with this prompt, please review it",
list: [error.response.data.detail],
});
});
}}
>
Check & Save
</button>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}

View file

@ -0,0 +1,121 @@
import { Dialog, Transition } from "@headlessui/react";
import {
ClipboardDocumentListIcon,
XMarkIcon,
} from "@heroicons/react/24/outline";
import { Fragment, useContext, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
export default function TextAreaModal({
value,
setValue,
}: {
setValue: (value: string) => void;
value: string | string[];
}) {
const [open, setOpen] = useState(true);
const [myValue, setMyValue] = useState(value);
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
const ref = useRef();
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
setCloseEdit("textarea");
closePopUp();
}, 300);
}
}
return (
<Transition.Root show={open} appear={true} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={setModalOpen}
initialFocus={ref}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="node-modal-div" />
</Transition.Child>
<div className="node-modal-dialog-arrangement">
<div className="node-modal-dialog-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="node-modal-dialog-panel">
<div className=" node-modal-dialog-panel-div">
<button
type="button"
className="node-modal-dialog-button"
onClick={() => {
setModalOpen(false);
}}
>
<span className="sr-only">Close</span>
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="node-modal-dialog-icon-div">
<div className="node-modal-icon-arrangement">
<div className="prompt-modal-icon-box">
<ClipboardDocumentListIcon
className="prompt-modal-icon"
aria-hidden="true"
/>
</div>
<div className="node-modal-title-div">
<Dialog.Title as="h3" className="node-modal-title">
Edit text
</Dialog.Title>
</div>
</div>
<div className="txtarea-modal-arrangement">
<div className="flex h-full w-full">
<div className="txtarea-modal-box">
<textarea
ref={ref}
className="txtarea-modal-input"
value={myValue}
onChange={(e) => {
setMyValue(e.target.value);
setValue(e.target.value);
}}
/>
</div>
</div>
</div>
<div className="node-modal-button-box">
<button
type="button"
className="node-modal-button"
onClick={() => {
setModalOpen(false);
}}
>
Finish editing
</button>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}

View file

@ -1,13 +1,13 @@
import { GitFork, GithubIcon, Users2 } from "lucide-react";
import { useContext, useEffect, useState } from "react";
import { GithubIcon, Users2, GitFork } from "lucide-react";
import { TabsContext } from "../../contexts/tabsContext";
import { alertContext } from "../../contexts/alertContext";
import { Button } from "../../components/ui/button";
import { alertContext } from "../../contexts/alertContext";
import { TabsContext } from "../../contexts/tabsContext";
import { useNavigate } from "react-router-dom";
import { CardComponent } from "../../components/cardComponent";
import { getExamples } from "../../controllers/API";
import { FlowType } from "../../types/flow";
import { CardComponent } from "../../components/cardComponent";
import { useNavigate } from "react-router-dom";
export default function CommunityPage() {
const { flows, setTabId, downloadFlows, uploadFlows, addFlow } =
useContext(TabsContext);
@ -37,31 +37,31 @@ export default function CommunityPage() {
handleExamples();
}, []);
return (
<div className="flex h-full w-full flex-col overflow-auto bg-muted px-16">
<div className="flex w-full justify-between px-6 py-12 pb-2">
<span className="flex items-center justify-center gap-2 text-2xl font-semibold">
<div className="community-page-arrangement">
<div className="community-page-nav-arrangement">
<span className="community-page-nav-title">
<Users2 className="w-6" />
Community Examples
</span>
<div className="flex gap-2">
<div className="community-page-nav-button">
<a
href="https://github.com/logspace-ai/langflow_examples"
target="_blank"
rel="noreferrer"
>
<Button variant="primary">
<GithubIcon className="mr-2 w-4" />
<GithubIcon className="main-page-nav-button" />
Add Your Example
</Button>
</a>
</div>
</div>
<span className="flex w-[70%] px-6 pb-8 text-muted-foreground">
Discover and learn from shared examples by the LangFlow community. We
<span className="community-page-description-text">
Discover and learn from shared examples by the Langflow community. We
welcome new example contributions that can help our community explore
new and powerful features.
</span>
<div className="grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4">
<div className="community-pages-flows-panel">
{!loadingExamples &&
examples.map((flow, idx) => (
<CardComponent
@ -79,7 +79,7 @@ export default function CommunityPage() {
});
}}
>
<GitFork className="mr-2 w-4" />
<GitFork className="main-page-nav-button" />
Fork Example
</Button>
}

View file

@ -1,6 +1,6 @@
import { Disclosure } from "@headlessui/react";
import { DisclosureComponentType } from "../../../../types/components";
import { ChevronRight } from "lucide-react";
import { DisclosureComponentType } from "../../../../types/components";
export default function DisclosureComponent({
button: { title, Icon, buttons = [] },
@ -12,14 +12,12 @@ export default function DisclosureComponent({
{({ open }) => (
<>
<div>
<Disclosure.Button className="-mt-px flex w-full select-none items-center justify-between border-y border-y-input bg-muted px-3 py-2">
<Disclosure.Button className="components-disclosure-arrangement">
<div className="flex gap-4">
<Icon strokeWidth={1.5} size={22} className="text-primary " />
<span className="flex items-center text-sm text-primary">
{title}
</span>
<Icon strokeWidth={1.5} size={22} className="text-primary" />
<span className="components-disclosure-title">{title}</span>
</div>
<div className="flex gap-2">
<div className="components-disclosure-div">
{buttons.map((x, index) => (
<button key={index} onClick={x.onClick}>
{x.Icon}
@ -35,7 +33,7 @@ export default function DisclosureComponent({
</div>
</Disclosure.Button>
</div>
<Disclosure.Panel as="div" className="-mt-px" static={openDisc}>
<Disclosure.Panel as="div" static={openDisc}>
{children}
</Disclosure.Panel>
</>

View file

@ -1,21 +1,21 @@
import _, { set } from "lodash";
import { useContext, useRef, useState, useEffect, useCallback } from "react";
import _ from "lodash";
import { useCallback, useContext, useEffect, useRef, useState } from "react";
import ReactFlow, {
OnSelectionChangeParams,
useNodesState,
useEdgesState,
useReactFlow,
EdgeChange,
Connection,
addEdge,
NodeDragHandler,
SelectionDragHandler,
OnEdgesDelete,
Edge,
updateEdge,
Background,
Connection,
Controls,
Edge,
EdgeChange,
NodeChange,
NodeDragHandler,
OnEdgesDelete,
OnSelectionChangeParams,
SelectionDragHandler,
addEdge,
updateEdge,
useEdgesState,
useNodesState,
useReactFlow,
} from "reactflow";
import GenericNode from "../../../../CustomNodes/GenericNode";
import Chat from "../../../../components/chatComponent";
@ -23,12 +23,12 @@ import { alertContext } from "../../../../contexts/alertContext";
import { locationContext } from "../../../../contexts/locationContext";
import { TabsContext } from "../../../../contexts/tabsContext";
import { typesContext } from "../../../../contexts/typesContext";
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
import { APIClassType } from "../../../../types/api";
import { FlowType, NodeType } from "../../../../types/flow";
import { isValidConnection } from "../../../../utils";
import ConnectionLineComponent from "../ConnectionLineComponent";
import ExtraSidebar from "../extraSidebarComponent";
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
const nodeTypes = {
genericNode: GenericNode,

View file

@ -1,22 +1,21 @@
import DisclosureComponent from "../DisclosureComponent";
import { Code2, FileDown, FileUp, Menu, Save, Search } from "lucide-react";
import { useContext, useState } from "react";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import { Separator } from "../../../../components/ui/separator";
import { alertContext } from "../../../../contexts/alertContext";
import { PopUpContext } from "../../../../contexts/popUpContext";
import { TabsContext } from "../../../../contexts/tabsContext";
import { typesContext } from "../../../../contexts/typesContext";
import ApiModal from "../../../../modals/ApiModal";
import ExportModal from "../../../../modals/exportModal";
import { APIClassType, APIObjectType } from "../../../../types/api";
import {
classNames,
nodeColors,
nodeIconsLucide,
nodeNames,
} from "../../../../utils";
import { useContext, useState } from "react";
import { typesContext } from "../../../../contexts/typesContext";
import { APIClassType, APIObjectType } from "../../../../types/api";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import { Code2, FileDown, FileUp, Save, Search } from "lucide-react";
import { PopUpContext } from "../../../../contexts/popUpContext";
import ExportModal from "../../../../modals/exportModal";
import ApiModal from "../../../../modals/ApiModal";
import { TabsContext } from "../../../../contexts/tabsContext";
import { alertContext } from "../../../../contexts/alertContext";
import { Separator } from "../../../../components/ui/separator";
import { Menu } from "lucide-react";
import DisclosureComponent from "../DisclosureComponent";
export default function ExtraSidebar() {
const { data } = useContext(typesContext);
@ -59,48 +58,50 @@ export default function ExtraSidebar() {
}
return (
<div className="flex h-full w-52 flex-col overflow-hidden border-r scrollbar-hide">
<div className="mb-2 mt-2 flex w-full items-center justify-between gap-2 px-2">
<div className="side-bar-arrangement">
<div className="side-bar-buttons-arrangement">
<ShadTooltip content="Import" side="top">
<button
className="relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
className="extra-side-bar-buttons"
onClick={() => {
// openPopUp(<ImportModal />);
uploadFlow();
}}
>
<FileUp strokeWidth={1.5} className="h-5 w-5 "></FileUp>
<FileUp
strokeWidth={1.5}
className="side-bar-button-size "
></FileUp>
</button>
</ShadTooltip>
<ShadTooltip content="Export" side="top">
<button
className={classNames(
"relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
)}
className={classNames("extra-side-bar-buttons")}
onClick={(event) => {
openPopUp(<ExportModal />);
}}
>
<FileDown strokeWidth={1.5} className="h-5 w-5 "></FileDown>
<FileDown
strokeWidth={1.5}
className="side-bar-button-size"
></FileDown>
</button>
</ShadTooltip>
<ShadTooltip content="Code" side="top">
<button
className={classNames(
"relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
)}
className={classNames("extra-side-bar-buttons")}
onClick={(event) => {
openPopUp(<ApiModal flow={flows.find((f) => f.id === tabId)} />);
}}
>
<Code2 strokeWidth={1.5} className="h-5 w-5 "></Code2>
<Code2 strokeWidth={1.5} className="side-bar-button-size"></Code2>
</button>
</ShadTooltip>
<ShadTooltip content="Save" side="top">
<button
className="relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
className="extra-side-bar-buttons"
onClick={(event) => {
saveFlow(flows.find((f) => f.id === tabId));
setSuccessData({ title: "Changes saved successfully" });
@ -110,14 +111,15 @@ export default function ExtraSidebar() {
<Save
strokeWidth={1.5}
className={
"h-5 w-5" + (isPending ? " " : " text-muted-foreground")
"side-bar-button-size" +
(isPending ? " " : " extra-side-bar-save-disable")
}
></Save>
</button>
</ShadTooltip>
</div>
<Separator />
<div className="relative mx-auto mb-2 mt-2 flex items-center">
<div className="side-bar-search-div-placement">
<input
type="text"
name="search"
@ -129,13 +131,13 @@ export default function ExtraSidebar() {
setSearch(e.target.value);
}}
/>
<div className="absolute inset-y-0 right-0 flex items-center py-1.5 pr-3">
<div className="search-icon">
{/* ! replace hash color here */}
<Search size={20} strokeWidth={1.5} className="text-primary" />
</div>
</div>
<div className="w-full overflow-auto pb-10 scrollbar-hide">
<div className="side-bar-components-div-arrangement">
{Object.keys(dataFilter)
.sort()
.map((d: keyof APIObjectType, i) =>
@ -148,7 +150,7 @@ export default function ExtraSidebar() {
Icon: nodeIconsLucide[d] ?? nodeIconsLucide.unknown,
}}
>
<div className="flex flex-col gap-2 p-2">
<div className="side-bar-components-gap">
{Object.keys(dataFilter[d])
.sort()
.map((t: string, k) => (
@ -160,7 +162,7 @@ export default function ExtraSidebar() {
<div key={k} data-tooltip-id={t}>
<div
draggable
className={"cursor-grab rounded-l-md border-l-8"}
className={"side-bar-components-border"}
style={{
borderLeftColor:
nodeColors[d] ?? nodeColors.unknown,
@ -179,11 +181,11 @@ export default function ExtraSidebar() {
);
}}
>
<div className="flex w-full items-center justify-between rounded-md rounded-l-none border border-l-0 border-dashed border-ring bg-white px-3 py-1 text-sm">
<span className="w-full truncate pr-1 text-xs text-foreground">
<div className="side-bar-components-div-form">
<span className="side-bar-components-text">
{data[d][t].display_name}
</span>
<Menu className="h-6 w-4 text-ring " />
<Menu className="side-bar-components-icon " />
</div>
</div>
</div>

View file

@ -1,11 +1,10 @@
import { Copy, FileText, Settings2, Trash2 } from "lucide-react";
import { useContext, useState } from "react";
import { Settings2, Copy, Trash2, FileText } from "lucide-react";
import { classNames } from "../../../../utils";
import { TabsContext } from "../../../../contexts/tabsContext";
import { useReactFlow } from "reactflow";
import EditNodeModal from "../../../../modals/EditNodeModal";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import { EllipsisVerticalIcon } from "@heroicons/react/24/outline";
import { TabsContext } from "../../../../contexts/tabsContext";
import EditNodeModal from "../../../../modals/EditNodeModal";
import { classNames } from "../../../../utils";
const NodeToolbarComponent = (props) => {
const [nodeLength, setNodeLength] = useState(

View file

@ -1,8 +1,8 @@
import { useContext, useEffect, useState } from "react";
import Page from "./components/PageComponent";
import { TabsContext } from "../../contexts/tabsContext";
import { useParams } from "react-router-dom";
import { TabsContext } from "../../contexts/tabsContext";
import { getVersion } from "../../controllers/API";
import Page from "./components/PageComponent";
export default function FlowPage() {
const { flows, tabId, setTabId } = useContext(TabsContext);
@ -20,7 +20,7 @@ export default function FlowPage() {
}, []);
return (
<div className="h-full w-full overflow-hidden">
<div className="flow-page-positioning">
{flows.length > 0 &&
tabId !== "" &&
flows.findIndex((flow) => flow.id === tabId) !== -1 && (
@ -29,9 +29,9 @@ export default function FlowPage() {
<a
target={"_blank"}
href="https://logspace.ai/"
className="absolute bottom-2 left-7 flex h-6 cursor-pointer flex-col items-center justify-start overflow-hidden rounded-lg bg-foreground px-2 text-center font-sans text-xs tracking-wide text-secondary transition-all duration-500 ease-in-out hover:h-12"
className="logspace-page-icon"
>
{version && <div className="mt-1">⛓️ LangFlow v{version}</div>}
{version && <div className="mt-1">⛓️ Langflow v{version}</div>}
<div className={version ? "mt-2" : "mt-1"}>Created by Logspace</div>
</a>
</div>

View file

@ -1,11 +1,10 @@
import { Download, ExternalLink, Home, Plus, Upload } from "lucide-react";
import { useContext, useEffect } from "react";
import { Download, Upload, Plus, Home, ExternalLink } from "lucide-react";
import { TabsContext } from "../../contexts/tabsContext";
import { Button } from "../../components/ui/button";
import { Link, useNavigate } from "react-router-dom";
import { CardComponent } from "../../components/cardComponent";
import { Button } from "../../components/ui/button";
import { USER_PROJECTS_HEADER } from "../../constants";
import { BUTTON_DIV_STYLE } from "../../constants";
import { TabsContext } from "../../contexts/tabsContext";
export default function HomePage() {
const { flows, setTabId, downloadFlows, uploadFlows, addFlow, removeFlow } =
useContext(TabsContext);
@ -14,20 +13,20 @@ export default function HomePage() {
}, []);
const navigate = useNavigate();
return (
<div className="flex h-full w-full flex-col overflow-auto bg-muted px-16">
<div className="flex w-full justify-between px-6 py-12 pb-2">
<span className="flex items-center justify-center gap-2 text-2xl font-semibold">
<div className="main-page-panel">
<div className="main-page-nav-arrangement">
<span className="main-page-nav-title">
<Home className="w-6" />
{USER_PROJECTS_HEADER}
</span>
<div className={`${BUTTON_DIV_STYLE}`}>
<div className="button-div-style">
<Button
variant="primary"
onClick={() => {
downloadFlows();
}}
>
<Download className="mr-2 w-4" />
<Download className="main-page-nav-button" />
Download Collection
</Button>
<Button
@ -36,7 +35,7 @@ export default function HomePage() {
uploadFlows();
}}
>
<Upload className="mr-2 w-4" />
<Upload className="main-page-nav-button" />
Upload Collection
</Button>
<Button
@ -47,15 +46,15 @@ export default function HomePage() {
});
}}
>
<Plus className="mr-2 w-4" />
<Plus className="main-page-nav-button" />
New Project
</Button>
</div>
</div>
<span className="flex w-[60%] px-6 pb-14 text-muted-foreground">
<span className="main-page-description-text">
Manage your personal projects. Download or upload your collection.
</span>
<div className="grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4">
<div className="main-page-flows-display">
{flows.map((flow, idx) => (
<CardComponent
key={idx}
@ -68,7 +67,7 @@ export default function HomePage() {
size="sm"
className="whitespace-nowrap "
>
<ExternalLink className="mr-2 w-4" />
<ExternalLink className="main-page-nav-button" />
Edit Flow
</Button>
</Link>

View file

@ -0,0 +1,4 @@
module.exports = {
// ...
organizeImportsSkipDestructiveCodeActions: true,
};

View file

@ -1,7 +1,7 @@
import { Route, Routes } from "react-router-dom";
import HomePage from "./pages/MainPage";
import FlowPage from "./pages/FlowPage";
import CommunityPage from "./pages/CommunityPage";
import FlowPage from "./pages/FlowPage";
import HomePage from "./pages/MainPage";
const Router = () => {
return (

View file

@ -1,4 +1,4 @@
import { Node, Edge, Viewport } from "reactflow";
import { Edge, Node, Viewport } from "reactflow";
//kind and class are just representative names to represent the actual structure of the object received by the API
export type APIObjectType = { kind: APIKindType; [key: string]: APIKindType };

View file

@ -1,7 +1,7 @@
import { ReactElement, ReactNode } from "react";
import { APIClassType } from "../api";
import { NodeDataType } from "../flow/index";
import { typesContextType } from "../typesContext";
import { APIClassType } from "../api";
export type InputComponentType = {
value: string;
disabled?: boolean;
@ -143,11 +143,12 @@ export type ShadTooltipProps = {
style?: string;
};
export type ShadToolTipType = {
content?: string;
content?: ReactNode;
side?: "top" | "right" | "bottom" | "left";
asChild?: boolean;
children?: ReactElement;
delayDuration?: number;
style?: string;
};
export type TextHighlightType = {

View file

@ -1,6 +1,5 @@
import { ChatMessageType } from "./../chat/index";
import { APIClassType } from "../api/index";
import { ReactFlowJsonObject, XYPosition } from "reactflow";
import { APIClassType } from "../api/index";
export type FlowType = {
name: string;

View file

@ -1,35 +1,10 @@
import { Connection, Edge, Node, ReactFlowInstance } from "reactflow";
import { FlowType, NodeType } from "./types/flow";
import { APITemplateType } from "./types/api";
import _ from "lodash";
import { ChromaIcon } from "./icons/ChromaIcon";
import { AnthropicIcon } from "./icons/Anthropic";
import { AirbyteIcon } from "./icons/Airbyte";
import { BingIcon } from "./icons/Bing";
import { CohereIcon } from "./icons/Cohere";
import { EvernoteIcon } from "./icons/Evernote";
import { FBIcon } from "./icons/FacebookMessenger";
import { GitBookIcon } from "./icons/GitBook";
import { GoogleIcon } from "./icons/Google";
import { HackerNewsIcon } from "./icons/hackerNews";
import { HugginFaceIcon } from "./icons/HuggingFace";
import { IFixIcon } from "./icons/IFixIt";
import { MetaIcon } from "./icons/Meta";
import { MidjourneyIcon } from "./icons/Midjorney";
import { NotionIcon } from "./icons/Notion";
import { OpenAiIcon } from "./icons/OpenAi";
import { QDrantIcon } from "./icons/QDrant";
import { SearxIcon } from "./icons/Searx";
import { SlackIcon } from "./icons/Slack";
import { PineconeIcon } from "./icons/Pinecone";
import clsx, { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "./flow_constants";
import { ComponentType, SVGProps } from "react";
import _ from "lodash";
import {
Compass,
Cpu,
Edit,
FileSearch,
Fingerprint,
Gift,
Hammer,
@ -42,16 +17,41 @@ import {
Paperclip,
Rocket,
Scissors,
FileSearch,
TerminalSquare,
Wand2,
Wrench,
Sparkles,
} from "lucide-react";
import { SupabaseIcon } from "./icons/supabase";
import { ComponentType, SVGProps } from "react";
import { Connection, Edge, Node, ReactFlowInstance } from "reactflow";
import { twMerge } from "tailwind-merge";
import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "./flow_constants";
import { AirbyteIcon } from "./icons/Airbyte";
import { AnthropicIcon } from "./icons/Anthropic";
import { BingIcon } from "./icons/Bing";
import { ChromaIcon } from "./icons/ChromaIcon";
import { CohereIcon } from "./icons/Cohere";
import { EvernoteIcon } from "./icons/Evernote";
import { FBIcon } from "./icons/FacebookMessenger";
import { GitBookIcon } from "./icons/GitBook";
import { GoogleIcon } from "./icons/Google";
import { HugginFaceIcon } from "./icons/HuggingFace";
import { IFixIcon } from "./icons/IFixIt";
import { MetaIcon } from "./icons/Meta";
import { MidjourneyIcon } from "./icons/Midjorney";
import { MongoDBIcon } from "./icons/MongoDB";
import { NotionIcon } from "./icons/Notion";
import { OpenAiIcon } from "./icons/OpenAi";
import { PineconeIcon } from "./icons/Pinecone";
import { QDrantIcon } from "./icons/QDrant";
import { SearxIcon } from "./icons/Searx";
import { SlackIcon } from "./icons/Slack";
import { VertexAIIcon } from "./icons/VertexAI";
import { HackerNewsIcon } from "./icons/hackerNews";
import { SupabaseIcon } from "./icons/supabase";
import { APITemplateType } from "./types/api";
import { IVarHighlightType } from "./types/components";
import { FlowType, NodeType } from "./types/flow";
export function classNames(...classes: Array<string>) {
return classes.filter(Boolean).join(" ");
@ -914,6 +914,16 @@ export function groupByFamily(data, baseClasses, left, type) {
}
}
export function buildInputs(tabsState, id) {
return tabsState &&
tabsState[id] &&
tabsState[id].formKeysData &&
tabsState[id].formKeysData.input_keys &&
Object.keys(tabsState[id].formKeysData.input_keys).length > 0
? JSON.stringify(tabsState[id].formKeysData.input_keys)
: '{"input": "message"}';
}
export function buildTweaks(flow) {
return flow.data.nodes.reduce((acc, node) => {
acc[node.data.id] = {};
@ -1032,6 +1042,7 @@ export const INVALID_CHARACTERS = [
")",
"[",
"]",
"\n",
];
export const regexHighlight = /\{([^}]+)\}/g;

View file

@ -1,5 +1,5 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import { defineConfig } from "vite";
import svgr from "vite-plugin-svgr";
const apiRoutes = ["^/api/v1/", "/health"];