Merge branch 'python_custom_node_component' of personal:logspace-ai/langflow into python_custom_node_component

This commit is contained in:
anovazzi1 2023-07-05 16:04:47 -03:00
commit b7124de011
146 changed files with 5363 additions and 2950 deletions

View file

@ -17,6 +17,7 @@
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-menubar": "^1.0.3",
"@radix-ui/react-progress": "^1.0.3",
@ -28,6 +29,7 @@
"@tabler/icons-react": "^2.18.0",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/line-clamp": "^0.4.4",
"accordion": "^3.0.2",
"ace-builds": "^1.16.0",
"add": "^2.0.6",
"ansi-to-html": "^0.7.2",
@ -35,6 +37,7 @@
"base64-js": "^1.5.1",
"class-variance-authority": "^0.6.0",
"clsx": "^1.2.1",
"dompurify": "^3.0.3",
"esbuild": "^0.17.18",
"lodash": "^4.17.21",
"lucide-react": "^0.233.0",
@ -54,7 +57,7 @@
"rehype-mathjax": "^4.0.2",
"remark-gfm": "^3.0.1",
"remark-math": "^5.1.1",
"shadcn-ui": "^0.1.3",
"shadcn-ui": "^0.2.2",
"short-unique-id": "^4.4.4",
"switch": "^0.0.0",
"table": "^6.8.1",
@ -81,6 +84,8 @@
"autoprefixer": "^10.4.14",
"daisyui": "^3.1.1",
"postcss": "^8.4.23",
"prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.3.0",
"tailwindcss": "^3.3.2",
"typescript": "^5.0.2",
"vite": "^4.3.9"
@ -115,6 +120,20 @@
"node": ">=6.0.0"
}
},
"node_modules/@antfu/ni": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/@antfu/ni/-/ni-0.21.4.tgz",
"integrity": "sha512-O0Uv9LbLDSoEg26fnMDdDRiPwFJnQSoD4WnrflDwKCJm8Cx/0mV4cGxwBLXan5mGIrpK4Dd7vizf4rQm0QCEAA==",
"bin": {
"na": "bin/na.mjs",
"nci": "bin/nci.mjs",
"ni": "bin/ni.mjs",
"nlx": "bin/nlx.mjs",
"nr": "bin/nr.mjs",
"nu": "bin/nu.mjs",
"nun": "bin/nun.mjs"
}
},
"node_modules/@babel/code-frame": {
"version": "7.21.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
@ -1213,15 +1232,15 @@
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
"node_modules/@mui/system": {
"version": "5.13.5",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.5.tgz",
"integrity": "sha512-n0gzUxoZ2ZHZgnExkh2Htvo9uW2oakofgPRQrDoa/GQOWyRD0NH9MDszBwOb6AAoXZb+OV5TE7I4LeZ/dzgHYA==",
"version": "5.13.6",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.6.tgz",
"integrity": "sha512-G3Xr28uLqU3DyF6r2LQkHGw/ku4P0AHzlKVe7FGXOPl7X1u+hoe2xxj8Vdiq/69II/mh9OP21i38yBWgWb7WgQ==",
"dependencies": {
"@babel/runtime": "^7.21.0",
"@babel/runtime": "^7.22.5",
"@mui/private-theming": "^5.13.1",
"@mui/styled-engine": "^5.13.2",
"@mui/types": "^7.2.4",
"@mui/utils": "^5.13.1",
"@mui/utils": "^5.13.6",
"clsx": "^1.2.1",
"csstype": "^3.1.2",
"prop-types": "^15.8.1"
@ -1281,11 +1300,11 @@
}
},
"node_modules/@mui/utils": {
"version": "5.13.1",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.1.tgz",
"integrity": "sha512-6lXdWwmlUbEU2jUI8blw38Kt+3ly7xkmV9ljzY4Q20WhsJMWiNry9CX8M+TaP/HbtuyR8XKsdMgQW7h7MM3n3A==",
"version": "5.13.6",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.6.tgz",
"integrity": "sha512-ggNlxl5NPSbp+kNcQLmSig6WVB0Id+4gOxhx644987v4fsji+CSXc+MFYLocFB/x4oHtzCUlSzbVHlJfP/fXoQ==",
"dependencies": {
"@babel/runtime": "^7.21.0",
"@babel/runtime": "^7.22.5",
"@types/prop-types": "^15.7.5",
"@types/react-is": "^18.2.0",
"prop-types": "^15.8.1",
@ -1692,6 +1711,14 @@
}
}
},
"node_modules/@radix-ui/react-icons": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
"integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==",
"peerDependencies": {
"react": "^16.x || ^17.x || ^18.x"
}
},
"node_modules/@radix-ui/react-id": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
@ -3168,6 +3195,39 @@
"node": ">= 10"
}
},
"node_modules/@ts-morph/common": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.19.0.tgz",
"integrity": "sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ==",
"dependencies": {
"fast-glob": "^3.2.12",
"minimatch": "^7.4.3",
"mkdirp": "^2.1.6",
"path-browserify": "^1.0.1"
}
},
"node_modules/@ts-morph/common/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@ts-morph/common/node_modules/minimatch": {
"version": "7.4.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz",
"integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@types/aria-query": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz",
@ -3609,6 +3669,11 @@
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA=="
},
"node_modules/accordion": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/accordion/-/accordion-3.0.2.tgz",
"integrity": "sha512-jbQfFaw+57OBwPt7qSNHuW+RA8smmRwkWRS1Ozh6K/QxUspBgBV/LpdSzlY7vee8TomS6j3D33B9rIeH1qMwsA=="
},
"node_modules/ace-builds": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.16.0.tgz",
@ -3776,9 +3841,9 @@
}
},
"node_modules/aria-query": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.2.1.tgz",
"integrity": "sha512-7uFg4b+lETFgdaJyETnILsXgnnzVnkHcgRbwbPwevm5x/LmUlt3MjczMRe1zg824iBgXZNRPTBftNYyRSKLp2g==",
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
"dev": true,
"dependencies": {
"dequal": "^2.0.3"
@ -4553,6 +4618,11 @@
"node": ">=6"
}
},
"node_modules/code-block-writer": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz",
"integrity": "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w=="
},
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -5071,10 +5141,15 @@
"node": ">=12"
}
},
"node_modules/dompurify": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
"integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
},
"node_modules/electron-to-chromium": {
"version": "1.4.438",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.438.tgz",
"integrity": "sha512-x94U0FhphEsHsOloCvlsujHCvoir0ZQ73ZAs/QN4PLx98uNvyEU79F75rq1db75Bx/atvuh7KPeuxelh+xfYJw=="
"version": "1.4.440",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.440.tgz",
"integrity": "sha512-r6dCgNpRhPwiWlxbHzZQ/d9swfPaEJGi8ekqRBwQYaR3WmA5VkqQfBWSDDjuJU1ntO+W9tHx8OHV/96Q8e0dVw=="
},
"node_modules/emoji-regex": {
"version": "8.0.0",
@ -6807,9 +6882,9 @@
}
},
"node_modules/katex": {
"version": "0.16.7",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.7.tgz",
"integrity": "sha512-Xk9C6oGKRwJTfqfIbtr0Kes9OSv6IFsuhFGc7tW4urlpMJtuh+7YhzU6YEG9n8gmWKcMAFzkp7nr+r69kV0zrA==",
"version": "0.16.8",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz",
"integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==",
"funding": [
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"
@ -6925,9 +7000,9 @@
}
},
"node_modules/log-symbols/node_modules/chalk": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
@ -7900,11 +7975,33 @@
"node": "*"
}
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/mj-context-menu": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
"integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA=="
},
"node_modules/mkdirp": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz",
"integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==",
"bin": {
"mkdirp": "dist/cjs/src/bin.js"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
@ -8173,9 +8270,9 @@
}
},
"node_modules/ora/node_modules/chalk": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
@ -8272,6 +8369,11 @@
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"node_modules/path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -8499,6 +8601,95 @@
"node": ">= 0.8.0"
}
},
"node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-plugin-tailwindcss": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.3.0.tgz",
"integrity": "sha512-009/Xqdy7UmkcTBpwlq7jsViDqXAYSOMLDrHAdTMlVZOrKfM2o9Ci7EMWTMZ7SkKBFTG04UM9F9iM2+4i6boDA==",
"dev": true,
"engines": {
"node": ">=12.17.0"
},
"peerDependencies": {
"@ianvs/prettier-plugin-sort-imports": "*",
"@prettier/plugin-pug": "*",
"@shopify/prettier-plugin-liquid": "*",
"@shufo/prettier-plugin-blade": "*",
"@trivago/prettier-plugin-sort-imports": "*",
"prettier": ">=2.2.0",
"prettier-plugin-astro": "*",
"prettier-plugin-css-order": "*",
"prettier-plugin-import-sort": "*",
"prettier-plugin-jsdoc": "*",
"prettier-plugin-marko": "*",
"prettier-plugin-organize-attributes": "*",
"prettier-plugin-organize-imports": "*",
"prettier-plugin-style-order": "*",
"prettier-plugin-svelte": "*",
"prettier-plugin-twig-melody": "*"
},
"peerDependenciesMeta": {
"@ianvs/prettier-plugin-sort-imports": {
"optional": true
},
"@prettier/plugin-pug": {
"optional": true
},
"@shopify/prettier-plugin-liquid": {
"optional": true
},
"@shufo/prettier-plugin-blade": {
"optional": true
},
"@trivago/prettier-plugin-sort-imports": {
"optional": true
},
"prettier-plugin-astro": {
"optional": true
},
"prettier-plugin-css-order": {
"optional": true
},
"prettier-plugin-import-sort": {
"optional": true
},
"prettier-plugin-jsdoc": {
"optional": true
},
"prettier-plugin-marko": {
"optional": true
},
"prettier-plugin-organize-attributes": {
"optional": true
},
"prettier-plugin-organize-imports": {
"optional": true
},
"prettier-plugin-style-order": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
},
"prettier-plugin-twig-melody": {
"optional": true
}
}
},
"node_modules/pretty-format": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
@ -9348,23 +9539,40 @@
}
},
"node_modules/shadcn-ui": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/shadcn-ui/-/shadcn-ui-0.1.3.tgz",
"integrity": "sha512-f6Wa4ZIxsigfOonC3yyJkPb2JXJnuGFyUn1fJJrDUHvIJOydUukcdQsZg7Lp6F6llkmfRjra1dZOo0KpSfdjuQ==",
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/shadcn-ui/-/shadcn-ui-0.2.2.tgz",
"integrity": "sha512-T76EeZymSB45Yz63gkYOv9P0Ke+UA9IZenysx+975nyNzXxU7HRBgfwuHiMcrcubtOLrzRVedTLX3lcOMqDeRQ==",
"dependencies": {
"@antfu/ni": "^0.21.4",
"chalk": "5.2.0",
"commander": "^10.0.0",
"cosmiconfig": "^8.1.3",
"diff": "^5.1.0",
"execa": "^7.0.0",
"fs-extra": "^11.1.0",
"https-proxy-agent": "^6.2.0",
"node-fetch": "^3.3.0",
"ora": "^6.1.2",
"prompts": "^2.4.2",
"ts-morph": "^18.0.0",
"tsconfig-paths": "^4.2.0",
"zod": "^3.20.2"
},
"bin": {
"shadcn-ui": "dist/index.js"
}
},
"node_modules/shadcn-ui/node_modules/agent-base": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",
"integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==",
"dependencies": {
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/shadcn-ui/node_modules/chalk": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
@ -9384,6 +9592,35 @@
"node": ">=14"
}
},
"node_modules/shadcn-ui/node_modules/cosmiconfig": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz",
"integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==",
"dependencies": {
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.0",
"parse-json": "^5.0.0",
"path-type": "^4.0.0"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/d-fischer"
}
},
"node_modules/shadcn-ui/node_modules/https-proxy-agent": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-6.2.1.tgz",
"integrity": "sha512-ONsE3+yfZF2caH5+bJlcddtWqNI3Gvs5A38+ngvljxaBiRXRswym2c7yf8UAeFpRFKjFNHIFEHqR/OLAWJzyiA==",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -9637,6 +9874,14 @@
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
"engines": {
"node": ">=4"
}
},
"node_modules/strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
@ -10012,6 +10257,28 @@
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
},
"node_modules/ts-morph": {
"version": "18.0.0",
"resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-18.0.0.tgz",
"integrity": "sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA==",
"dependencies": {
"@ts-morph/common": "~0.19.0",
"code-block-writer": "^12.0.0"
}
},
"node_modules/tsconfig-paths": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
"integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==",
"dependencies": {
"json5": "^2.2.2",
"minimist": "^1.2.6",
"strip-bom": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/tslib": {
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",

View file

@ -12,6 +12,7 @@
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-menubar": "^1.0.3",
"@radix-ui/react-progress": "^1.0.3",
@ -23,6 +24,7 @@
"@tabler/icons-react": "^2.18.0",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/line-clamp": "^0.4.4",
"accordion": "^3.0.2",
"ace-builds": "^1.16.0",
"add": "^2.0.6",
"ansi-to-html": "^0.7.2",
@ -30,6 +32,7 @@
"base64-js": "^1.5.1",
"class-variance-authority": "^0.6.0",
"clsx": "^1.2.1",
"dompurify": "^3.0.3",
"esbuild": "^0.17.18",
"lodash": "^4.17.21",
"lucide-react": "^0.233.0",
@ -49,7 +52,7 @@
"rehype-mathjax": "^4.0.2",
"remark-gfm": "^3.0.1",
"remark-math": "^5.1.1",
"shadcn-ui": "^0.1.3",
"shadcn-ui": "^0.2.2",
"short-unique-id": "^4.4.4",
"switch": "^0.0.0",
"table": "^6.8.1",
@ -102,6 +105,8 @@
"autoprefixer": "^10.4.14",
"daisyui": "^3.1.1",
"postcss": "^8.4.23",
"prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.3.0",
"tailwindcss": "^3.3.2",
"typescript": "^5.0.2",
"vite": "^4.3.9"

View file

@ -0,0 +1,3 @@
module.exports = {
plugins: [require("prettier-plugin-tailwindcss")],
};

View file

@ -51,6 +51,13 @@ export default function App() {
useEffect(() => {
// If there is an error alert open with data, add it to the alertsList
if (errorOpen && errorData) {
if (
alertsList.length > 0 &&
JSON.stringify(alertsList[alertsList.length - 1].data) ===
JSON.stringify(errorData)
) {
return;
}
setErrorOpen(false);
setAlertsList((old) => {
let newAlertsList = [
@ -62,6 +69,13 @@ export default function App() {
}
// If there is a notice alert open with data, add it to the alertsList
else if (noticeOpen && noticeData) {
if (
alertsList.length > 0 &&
JSON.stringify(alertsList[alertsList.length - 1].data) ===
JSON.stringify(noticeData)
) {
return;
}
setNoticeOpen(false);
setAlertsList((old) => {
let newAlertsList = [
@ -73,6 +87,13 @@ export default function App() {
}
// If there is a success alert open with data, add it to the alertsList
else if (successOpen && successData) {
if (
alertsList.length > 0 &&
JSON.stringify(alertsList[alertsList.length - 1].data) ===
JSON.stringify(successData)
) {
return;
}
setSuccessOpen(false);
setAlertsList((old) => {
let newAlertsList = [
@ -103,7 +124,7 @@ export default function App() {
return (
//need parent component with width and height
<div className="h-full flex flex-col">
<div className="flex h-full flex-col">
<ErrorBoundary
onReset={() => {
window.localStorage.removeItem("tabsData");
@ -118,7 +139,7 @@ export default function App() {
</ErrorBoundary>
<div></div>
<div
className="flex flex-col-reverse fixed bottom-5 left-5"
className="fixed bottom-5 left-5 flex flex-col-reverse"
style={{ zIndex: 999 }}
>
{alertsList.map((alert) => (

View file

@ -25,7 +25,7 @@ import { nodeColors } from "../../../../utils";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import { PopUpContext } from "../../../../contexts/popUpContext";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
import * as _ from "lodash";
import { Info } from "lucide-react";
export default function ParameterComponent({
left,
@ -38,9 +38,11 @@ export default function ParameterComponent({
name = "",
required = false,
optionalHandle = null,
info = "",
}: ParameterComponentType) {
const ref = useRef(null);
const refHtml = useRef(null);
const infoHtml = useRef(null);
const updateNodeInternals = useUpdateNodeInternals();
const [position, setPosition] = useState(0);
const { closePopUp } = useContext(PopUpContext);
@ -84,72 +86,107 @@ export default function ParameterComponent({
};
useEffect(() => {
const groupedObj = groupByFamily(myData, tooltipTitle);
infoHtml.current = (
<div className="h-full w-full break-words">
{info.split("\n").map((line, i) => (
<p key={i} className="block">
{line}
</p>
))}
</div>
);
}, [info]);
refHtml.current = groupedObj.map((item, i) => (
<span
key={getRandomKeyByssmm() + item.family + i}
className={classNames(
i > 0 ? "items-center flex mt-3" : "items-center flex"
)}
>
<div
className="h-6 w-6"
style={{
color: nodeColors[item.family],
}}
useEffect(() => {
const groupedObj = groupByFamily(myData, tooltipTitle, left, data.type);
refHtml.current = groupedObj.map((item, i) => {
const Icon: any = nodeIconsLucide[item.family];
return (
<span
key={getRandomKeyByssmm() + item.family + i}
className={classNames(
i > 0 ? "mt-2 flex items-center" : "flex items-center"
)}
>
{React.createElement(nodeIconsLucide[item.family])}
</div>
<span className="ps-2 text-gray-950">
{nodeNames[item.family] ?? ""}{" "}
<span className={classNames(left ? "hidden" : "")}>
{" "}
-&nbsp;
{item.type.split(", ").length > 2
? item.type.split(", ").map((el, i) => (
<React.Fragment key={el + i}>
<span>
{i === item.type.split(", ").length - 1
? el
: (el += `, `)}
</span>
{i % 2 === 0 && i > 0 && <br />}
</React.Fragment>
))
: item.type}
<div
className="h-5 w-5"
style={{
color: nodeColors[item.family],
}}
>
<Icon
className="h-5 w-5"
strokeWidth={1.5}
style={{
color: nodeColors[item.family] ?? nodeColors.unknown,
}}
/>
</div>
<span className="ps-2 text-xs text-foreground">
{nodeNames[item.family] ?? ""}{" "}
<span className="text-xs">
{" "}
{item.type == "" ? '' : ' - '}
{item.type.split(", ").length > 2
? item.type.split(", ").map((el, i) => (
<React.Fragment key={el + i}>
<span>
{i === item.type.split(", ").length - 1
? el
: (el += `, `)}
</span>
</React.Fragment>
))
: item.type}
</span>
</span>
</span>
</span>
));
);
});
}, [tooltipTitle]);
return (
<div
ref={ref}
className="w-full flex flex-wrap justify-between items-center bg-muted dark:bg-gray-800 dark:text-white mt-1 px-5 py-2"
className="mt-1 flex w-full flex-wrap items-center justify-between bg-muted px-5 py-2"
>
<>
<div className={"text-sm truncate w-full " + (left ? "" : "text-end")}>
<div
className={
"w-full truncate text-sm" +
(left ? "" : " text-end") +
(info !== "" ? " flex items-center" : "")
}
>
{title}
<span className="text-red-600">{required ? " *" : ""}</span>
<span className="text-destructive">{required ? " *" : ""}</span>
<div className="">
{info !== "" && (
<ShadTooltip content={infoHtml.current}>
<Info className="relative bottom-0.5 ml-2 h-3 w-3" />
</ShadTooltip>
)}
</div>
</div>
{left &&
((type === "str" ||
(type === "str" ||
type === "bool" ||
type === "float" ||
type === "code" ||
type === "prompt" ||
type === "file" ||
type === "int") && !optionalHandle
) ? (
type === "int") &&
!optionalHandle ? (
<></>
) : (
<ShadTooltip
style="max-w-[30vw] max-h-[20vh] overflow-auto custom-scroll"
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
open={refHtml?.current?.length > 0}
>
<Handle
type={left ? "target" : "source"}
@ -160,7 +197,7 @@ export default function ParameterComponent({
}
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
"w-3 h-3 rounded-full border-2 bg-white dark:bg-gray-800"
"h-3 w-3 rounded-full border-2 bg-background"
)}
style={{
borderColor: color,
@ -202,7 +239,7 @@ export default function ParameterComponent({
)}
</div>
) : left === true && type === "bool" ? (
<div className="mt-2">
<div className="mt-2 w-full">
<ToggleShadComponent
disabled={disabled}
enabled={enabled}
@ -225,7 +262,7 @@ export default function ParameterComponent({
) : left === true &&
type === "str" &&
data.node.template[name].options ? (
<div className="w-full">
<div className="mt-2 w-full">
<Dropdown
options={data.node.template[name].options}
onSelect={handleOnNewValue}
@ -233,28 +270,32 @@ export default function ParameterComponent({
></Dropdown>
</div>
) : left === true && type === "code" ? (
<CodeAreaComponent
dynamic = {data.node.template[name].dynamic ?? false}
setNodeClass={(nodeClass) => {
data.node = nodeClass;
}}
nodeClass={data.node}
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={handleOnNewValue}
/>
<div className="mt-2 w-full">
<CodeAreaComponent
dynamic = {data.node.template[name].dynamic ?? false}
setNodeClass={(nodeClass) => {
data.node = nodeClass;
}}
nodeClass={data.node}
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={handleOnNewValue}
/>
</div>
) : left === true && type === "file" ? (
<InputFileComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={handleOnNewValue}
fileTypes={data.node.template[name].fileTypes}
suffixes={data.node.template[name].suffixes}
onFileChange={(t: string) => {
data.node.template[name].file_path = t;
save();
}}
></InputFileComponent>
<div className="mt-2 w-full">
<InputFileComponent
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={handleOnNewValue}
fileTypes={data.node.template[name].fileTypes}
suffixes={data.node.template[name].suffixes}
onFileChange={(t: string) => {
data.node.template[name].file_path = t;
save();
}}
></InputFileComponent>
</div>
) : left === true && type === "int" ? (
<div className="mt-2 w-full">
<IntComponent
@ -265,15 +306,18 @@ export default function ParameterComponent({
/>
</div>
) : left === true && type === "prompt" ? (
<PromptAreaComponent
setNodeClass={(nodeClass) => {
data.node = nodeClass;
}}
nodeClass={data.node}
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={handleOnNewValue}
/>
<div className="mt-2 w-full">
<PromptAreaComponent
field_name={name}
setNodeClass={(nodeClass) => {
data.node = nodeClass;
}}
nodeClass={data.node}
disabled={disabled}
value={data.node.template[name].value ?? ""}
onChange={handleOnNewValue}
/>
</div>
) : (
<></>
)}

View file

@ -6,16 +6,7 @@ import {
} from "../../utils";
import ParameterComponent from "./components/parameterComponent";
import { typesContext } from "../../contexts/typesContext";
import {
useContext,
useState,
useEffect,
useRef,
ForwardRefExoticComponent,
ComponentType,
SVGProps,
ReactNode,
} from "react";
import { useContext, useState, useEffect, useRef } from "react";
import { NodeDataType } from "../../types/flow";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
@ -23,10 +14,8 @@ 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";
import { ReactElement } from "react-markdown/lib/react-markdown";
export default function GenericNode({
data,
@ -46,6 +35,7 @@ export default function GenericNode({
const [validationStatus, setValidationStatus] = useState(null);
// State for outline color
const { sseData, isBuilding } = useSSE();
const refHtml = useRef(null);
// useEffect(() => {
// if (reactFlowInstance) {
@ -90,24 +80,25 @@ export default function GenericNode({
<div
className={classNames(
selected ? "border border-ring" : "border dark:border-gray-700",
"prompt-node relative flex w-96 flex-col justify-center rounded-lg bg-white dark:bg-gray-900"
selected ? "border border-ring" : "border",
"prompt-node relative flex w-96 flex-col justify-center rounded-lg bg-background"
)}
>
<div className="flex w-full items-center justify-between gap-8 rounded-t-lg border-b bg-muted p-4 dark:border-b-gray-700 dark:bg-gray-800 dark:text-white ">
<div className="flex w-full items-center gap-2 truncate text-lg">
<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">
<Icon
strokeWidth={1.5}
className="h-10 w-10 rounded p-1"
style={{
color: nodeColors[types[data.type]] ?? nodeColors.unknown,
}}
/>
<div className="ml-2 truncate flex-1">
<div className="ml-2 flex-1 truncate">
<ShadTooltip
delayDuration={1500}
content={data.node.display_name}
>
<div className="ml-2 truncate text-gray-800">
<div className="ml-2 truncate text-primary">
{data.node.display_name}
</div>
</ShadTooltip>
@ -138,29 +129,29 @@ export default function GenericNode({
)
}
>
<div className="w-5 h-5 relative top-[3px]">
<div className="relative top-[3px] h-5 w-5">
<div
className={classNames(
validationStatus && validationStatus.valid
? "w-4 h-4 rounded-full bg-green-500 opacity-100"
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
? "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"
)}
></div>
<div
className={classNames(
validationStatus && !validationStatus.valid
? "w-4 h-4 rounded-full bg-red-500 opacity-100"
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
? "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"
)}
></div>
<div
className={classNames(
!validationStatus || isBuilding
? "w-4 h-4 rounded-full bg-yellow-500 opacity-100"
: "w-4 h-4 rounded-full bg-gray-500 opacity-0 hidden animate-spin",
"absolute w-4 hover:text-gray-500 hover:dark:text-gray-300 transition-all ease-in-out duration-200"
? "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"
)}
></div>
</div>
@ -169,7 +160,7 @@ export default function GenericNode({
</div>
</div>
<div className="h-full w-full py-5 text-gray-800">
<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>
@ -182,7 +173,7 @@ export default function GenericNode({
{/* {idx === 0 ? (
<div
className={classNames(
"px-5 py-2 mt-2 dark:text-white text-center",
"px-5 py-2 mt-2 text-center",
Object.keys(data.node.template).filter(
(key) =>
!key.startsWith("_") &&
@ -214,10 +205,21 @@ export default function GenericNode({
? toTitleCase(data.node.template[t].name)
: toTitleCase(t)
}
info={data.node.template[t].info}
name={t}
tooltipTitle={data.node.template[t].input_types?.join("\n") ?? data.node.template[t].type}
tooltipTitle={
data.node.template[t].input_types?.join("\n") ??
data.node.template[t].type
}
required={data.node.template[t].required}
id={(data.node.template[t].input_types?.join(";") ?? data.node.template[t].type) + "|" + t + "|" + data.id}
id={
(data.node.template[t].input_types?.join(";") ??
data.node.template[t].type) +
"|" +
t +
"|" +
data.id
}
left={true}
type={data.node.template[t].type}
optionalHandle={data.node.template[t].input_types}
@ -235,14 +237,18 @@ export default function GenericNode({
>
{" "}
</div>
{/* <div className="px-5 py-2 mt-2 dark:text-white text-center">
{/* <div className="px-5 py-2 mt-2 text-center">
Output
</div> */}
<ParameterComponent
data={data}
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
title={data.type}
tooltipTitle={`${data.node.base_classes.join("\n")}`}
title={
data.node.output_types && data.node.output_types.length > 0
? data.node.output_types.join("|")
: data.type
}
tooltipTitle={data.node.base_classes.join("\n")}
id={[data.type, data.id, ...data.node.base_classes].join("|")}
type={data.node.base_classes.join("|")}
left={false}

View file

@ -25,21 +25,18 @@ export default function SingleAlert({
>
{type === "error" ? (
<div
className="flex bg-red-50 dark:bg-red-900 rounded-md p-3 mb-2 mx-2"
className="mx-2 mb-2 flex rounded-md bg-error-background p-3"
key={dropItem.id}
>
<div className="flex-shrink-0">
<XCircle
className="h-5 w-5 text-red-400 dark:text-red-50"
aria-hidden="true"
/>
<XCircle className="h-5 w-5 text-status-red" aria-hidden="true" />
</div>
<div className="ml-3">
<h3 className="text-sm break-words font-medium text-red-800 dark:text-white/80">
<h3 className="break-words text-sm font-medium text-error-foreground">
{dropItem.title}
</h3>
{dropItem.list ? (
<div className="mt-2 text-sm text-red-700 dark:text-red-50">
<div className="mt-2 text-sm text-error-foreground">
<ul className="list-disc space-y-1 pl-5">
{dropItem.list.map((item, idx) => (
<li className="break-words" key={idx}>
@ -62,34 +59,34 @@ export default function SingleAlert({
removeAlert(dropItem.id);
}, 500);
}}
className="inline-flex rounded-md bg-red-50 dark:bg-transparent p-1.5 text-red-500 dark:text-red-50"
className="inline-flex rounded-md p-1.5 text-status-red"
>
<span className="sr-only">Dismiss</span>
<X className="h-5 w-5" aria-hidden="true" />
<X
className="h-4 w-4 text-error-foreground"
aria-hidden="true"
/>
</button>
</div>
</div>
</div>
) : type === "notice" ? (
<div
className="flex rounded-md bg-blue-50 dark:bg-blue-900 p-3 mb-2 mx-2"
className="mx-2 mb-2 flex rounded-md bg-info-background p-3"
key={dropItem.id}
>
<div className="flex-shrink-0">
<Info
className="h-5 w-5 text-blue-400 dark:text-blue-50"
aria-hidden="true"
/>
<Info className="h-5 w-5 text-status-blue " aria-hidden="true" />
</div>
<div className="ml-3 flex-1 md:flex md:justify-between">
<p className="text-sm text-blue-700 dark:text-white/80">
<p className="text-sm font-medium text-info-foreground">
{dropItem.title}
</p>
<p className="mt-3 text-sm md:mt-0 md:ml-6">
<p className="mt-3 text-sm md:ml-6 md:mt-0">
{dropItem.link ? (
<Link
to={dropItem.link}
className="whitespace-nowrap font-medium text-blue-700 dark:text-blue-50 dark:hover:text-blue-100 hover:text-ring"
className="whitespace-nowrap font-medium text-info-foreground hover:text-accent-foreground"
>
Details
</Link>
@ -108,27 +105,30 @@ export default function SingleAlert({
removeAlert(dropItem.id);
}, 500);
}}
className="inline-flex rounded-md bg-blue-50 dark:bg-transparent p-1.5 text-blue-500 dark:text-blue-50"
className="inline-flex rounded-md p-1.5 text-info-foreground"
>
<span className="sr-only">Dismiss</span>
<X className="h-5 w-5" aria-hidden="true" />
<X
className="h-4 w-4 text-info-foreground"
aria-hidden="true"
/>
</button>
</div>
</div>
</div>
) : (
<div
className="flex bg-green-50 dark:bg-green-900 p-3 mb-2 mx-2 rounded-md"
className="mx-2 mb-2 flex rounded-md bg-success-background p-3"
key={dropItem.id}
>
<div className="flex-shrink-0">
<CheckCircle2
className="h-5 w-5 text-green-400 dark:text-green-50"
className="h-5 w-5 text-status-green"
aria-hidden="true"
/>
</div>
<div className="ml-3">
<p className="text-sm font-medium text-green-800 dark:bg-white/80">
<p className="text-sm font-medium text-success-foreground">
{dropItem.title}
</p>
</div>
@ -142,10 +142,13 @@ export default function SingleAlert({
removeAlert(dropItem.id);
}, 500);
}}
className="inline-flex rounded-md bg-green-50 dark:bg-transparent p-1.5 text-green-500 dark:text-green-50"
className="inline-flex rounded-md p-1.5 text-status-green"
>
<span className="sr-only">Dismiss</span>
<X className="h-5 w-5" aria-hidden="true" />
<X
className="h-4 w-4 text-success-foreground"
aria-hidden="true"
/>
</button>
</div>
</div>

View file

@ -24,29 +24,29 @@ export default function AlertDropdown({}: AlertDropdownType) {
return (
<div
ref={componentRef}
className="z-10 py-3 pb-4 px-2 rounded-md bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 shadow-lg focus:outline-none overflow-hidden w-[400px] h-[500px] flex flex-col"
className="z-10 flex h-[500px] w-[400px] flex-col overflow-hidden rounded-md bg-background px-2 py-3 pb-4 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div className="flex pl-3 flex-row justify-between text-md font-medium text-gray-800 dark:text-gray-200">
<div className="text-md flex flex-row justify-between pl-3 font-medium text-foreground">
Notifications
<div className="flex gap-3 pr-3 ">
<button
className="text-gray-800 hover:text-red-500 dark:text-gray-200 dark:hover:text-red-500"
className="text-foreground hover:text-status-red"
onClick={() => {
closePopUp();
setTimeout(clearNotificationList, 100);
}}
>
<Trash2 className="w-[1.1rem] h-[1.1rem]" />
<Trash2 className="h-[1.1rem] w-[1.1rem]" />
</button>
<button
className="text-gray-800 hover:text-red-500 dark:text-gray-200 dark:hover:text-red-500"
className="text-foreground hover:text-status-red"
onClick={closePopUp}
>
<X className="h-5 w-5" />
</button>
</div>
</div>
<div className="mt-3 flex flex-col overflow-y-scroll w-full h-full scrollbar-hide text-gray-900 dark:text-gray-300">
<div className="text-high-foreground mt-3 flex h-full w-full flex-col overflow-y-scroll scrollbar-hide">
{notificationList.length !== 0 ? (
notificationList.map((alertItem, index) => (
<SingleAlert
@ -56,7 +56,7 @@ export default function AlertDropdown({}: AlertDropdownType) {
/>
))
) : (
<div className="h-full w-full pb-16 text-gray-500 dark:text-gray-500 flex justify-center items-center">
<div className="flex h-full w-full items-center justify-center pb-16 text-ring">
No new notifications
</div>
)}

View file

@ -39,21 +39,18 @@ export default function ErrorAlert({
removeAlert(id);
}, 500);
}}
className="rounded-md w-96 mt-6 shadow-xl bg-red-50 dark:bg-red-900 p-4 cursor-pointer"
className="mt-6 w-96 cursor-pointer rounded-md bg-error-background p-4 shadow-xl"
>
<div className="flex">
<div className="flex-shrink-0">
<XCircle
className="h-5 w-5 text-red-400 dark:text-red-50"
aria-hidden="true"
/>
<XCircle className="h-5 w-5 text-status-red" aria-hidden="true" />
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800 dark:text-white/80">
<h3 className="text-sm font-medium text-error-foreground">
{title}
</h3>
{list.length !== 0 ? (
<div className="mt-2 text-sm text-red-700 dark:text-red-50">
<div className="mt-2 text-sm text-error-foreground">
<ul className="list-disc space-y-1 pl-5">
{list.map((item, index) => (
<li key={index}>{item}</li>

View file

@ -36,22 +36,19 @@ export default function NoticeAlert({
setShow(false);
removeAlert(id);
}}
className="rounded-md w-96 mt-6 shadow-xl bg-blue-50 dark:bg-blue-900 p-4"
className="mt-6 w-96 rounded-md bg-info-background p-4 shadow-xl"
>
<div className="flex">
<div className="flex-shrink-0">
<Info
className="h-5 w-5 text-blue-400 dark:text-blue-50"
aria-hidden="true"
/>
<Info className="h-5 w-5 text-status-blue " aria-hidden="true" />
</div>
<div className="ml-3 flex-1 md:flex md:justify-between">
<p className="text-sm text-blue-700 dark:text-white/80">{title}</p>
<p className="mt-3 text-sm md:mt-0 md:ml-6">
<p className="text-sm text-info-foreground">{title}</p>
<p className="mt-3 text-sm md:ml-6 md:mt-0">
{link !== "" ? (
<Link
to={link}
className="whitespace-nowrap font-medium text-blue-700 dark:text-blue-50 hover:dark:text-blue-10 hover:text-ring"
className="whitespace-nowrap font-medium text-info-foreground hover:text-accent-foreground"
>
Details
</Link>

View file

@ -34,17 +34,17 @@ export default function SuccessAlert({
setShow(false);
removeAlert(id);
}}
className="rounded-md w-96 mt-6 shadow-xl bg-green-50 dark:bg-green-900 p-4"
className="mt-6 w-96 rounded-md bg-success-background p-4 shadow-xl"
>
<div className="flex">
<div className="flex-shrink-0">
<CheckCircle2
className="h-5 w-5 text-green-400 dark:text-green-50"
className="h-5 w-5 text-status-green"
aria-hidden="true"
/>
</div>
<div className="ml-3">
<p className="text-sm font-medium text-green-800 dark:text-white/80">
<p className="text-sm font-medium text-success-foreground">
{title}
</p>
</div>

View file

@ -0,0 +1,56 @@
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 {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "../../components/ui/accordion";
export default function AccordionComponent({
trigger,
children,
open = [],
}: AccordionComponentType) {
const [value, setValue] = useState(
open.length == 0 ? "" : getOpenAccordion()
);
function getOpenAccordion() {
let value = "";
open.forEach((el) => {
if (el == trigger) {
value = trigger;
}
});
return value;
}
function handleClick() {
value == "" ? setValue(trigger) : setValue("");
}
return (
<>
<Accordion type="single" value={value} onValueChange={setValue}>
<AccordionItem value={trigger} className="border-none">
<AccordionTrigger
onClick={() => {
handleClick();
}}
className="ml-3"
>
{trigger}
</AccordionTrigger>
<AccordionContent>{children}</AccordionContent>
</AccordionItem>
</Accordion>
</>
);
}

View file

@ -1,11 +1,11 @@
export default function CrashErrorComponent({ error, resetErrorBoundary }) {
return (
<div className="fixed top-0 left-0 w-full h-full flex items-center justify-center bg-gray-800 bg-opacity-50 z-50">
<div className="bg-white max-w-4xl h-1/3 min-h-fit rounded-lg shadow-lg p-8 text-start flex flex-col justify-evenly">
<h1 className="text-red-500 text-3xl mb-4">
<div className="fixed left-0 top-0 z-50 flex h-full w-full items-center justify-center bg-foreground bg-opacity-50">
<div className="flex h-1/3 min-h-fit max-w-4xl flex-col justify-evenly rounded-lg bg-background p-8 text-start shadow-lg">
<h1 className="mb-4 text-3xl text-status-red">
Oops! An unknown error has occurred.
</h1>
<p className="text-gray-700 mb-4 text-xl">
<p className="mb-4 text-xl text-foreground">
Please click the 'Reset Application' button to restore the
application's state. If the error persists, please create an issue on
our GitHub page. We apologize for any inconvenience this may have
@ -14,7 +14,7 @@ export default function CrashErrorComponent({ error, resetErrorBoundary }) {
<div className="flex justify-center">
<button
onClick={resetErrorBoundary}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mr-4"
className="mr-4 rounded bg-primary px-4 py-2 font-bold text-background hover:bg-ring"
>
Reset Application
</button>
@ -22,7 +22,7 @@ export default function CrashErrorComponent({ error, resetErrorBoundary }) {
href="https://github.com/logspace-ai/langflow/issues/new"
target="_blank"
rel="noopener noreferrer"
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
className="rounded bg-status-red px-4 py-2 font-bold text-background hover:bg-error-foreground"
>
Create Issue
</a>

View file

@ -47,7 +47,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
<div className="flex justify-between">
<span className="font-medium">Name</span>{" "}
{isMaxLength && (
<span className="text-red-500 animate-pulse ml-10">
<span className="ml-10 animate-pulse text-status-red">
Character limit reached
</span>
)}
@ -71,7 +71,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
onChange={handleDescriptionChange}
value={description ?? ""}
placeholder="Flow description"
className="max-h-[100px] mt-2 font-normal"
className="mt-2 max-h-[100px] font-normal"
rows={3}
/>
</Label>

View file

@ -18,10 +18,10 @@ export default function ExtraSidebar() {
<aside
className={` ${
isStackedOpen ? "w-52" : "w-0 "
} flex-shrink-0 flex overflow-hidden flex-col border-r dark:border-r-gray-700 transition-all duration-500`}
} flex flex-shrink-0 flex-col overflow-hidden border-r transition-all duration-500`}
>
<div className="w-52 dark:bg-gray-800 border dark:border-gray-700 overflow-y-auto scrollbar-hide h-full flex flex-col items-start bg-white">
<div className="flex flex-grow flex-col w-full">
<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">
{extraNavigation.options ? (
<div className="p-4">
<nav className="flex-1 space-y-1">
@ -32,16 +32,16 @@ export default function ExtraSidebar() {
to={item.href}
className={classNames(
item.href.split("/")[2] === current[4]
? "bg-muted text-gray-900"
: "bg-white text-gray-600 hover:bg-muted hover:text-gray-900",
"group w-full flex items-center pl-2 py-2 text-sm font-medium rounded-md"
? "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"
)}
>
<item.icon
className={classNames(
item.href.split("/")[2] === current[4]
? "text-gray-500"
: "text-gray-400 group-hover:text-gray-500",
? "text-ring"
: "text-ring group-hover:text-accent-foreground",
"mr-3 flex-shrink-0 h-6 w-6"
)}
/>
@ -59,22 +59,20 @@ export default function ExtraSidebar() {
<Disclosure.Button
className={classNames(
item.href.split("/")[2] === current[4]
? "bg-muted text-gray-900"
: "bg-white text-gray-600 hover:bg-muted hover:text-gray-900",
"group w-full flex items-center pl-2 pr-1 py-2 text-left text-sm font-medium rounded-md focus:outline-none focus:ring-1 focus:ring-indigo-500"
? "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"
)}
>
<item.icon
className="mr-3 h-6 w-6 flex-shrink-0 text-gray-400 group-hover:text-gray-500"
className="mr-3 h-6 w-6 flex-shrink-0 text-ring group-hover:text-accent-foreground"
aria-hidden="true"
/>
<span className="flex-1">{item.name}</span>
<svg
className={classNames(
open
? "text-gray-400 rotate-90"
: "text-gray-300",
"ml-3 h-5 w-5 flex-shrink-0 transition-rotate duration-150 ease-in-out group-hover:text-gray-400"
open ? "text-ring rotate-90" : "text-ring",
"ml-3 h-5 w-5 flex-shrink-0 transition-rotate duration-150 ease-in-out group-hover:text-accent-foreground"
)}
viewBox="0 0 20 20"
aria-hidden="true"
@ -92,8 +90,8 @@ export default function ExtraSidebar() {
to={subItem.href}
className={classNames(
subItem.href.split("/")[3] === current[5]
? "bg-muted text-gray-900"
: "bg-white text-gray-600 hover:bg-muted hover:text-gray-900",
? "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"
)}
>

View file

@ -37,7 +37,7 @@ const TooltipReact: FC<TooltipProps> = ({
id={selector}
content={content}
className={classNames(
"!bg-white !text-xs !font-normal !text-gray-700 !shadow-md !opacity-100 z-[9999]",
"z-[9999] !bg-white !text-xs !font-normal !text-foreground !opacity-100 !shadow-md",
className
)}
place={position}

View file

@ -1,3 +1,4 @@
import { ShadTooltipProps } from "../../types/components";
import {
Tooltip,
TooltipContent,
@ -5,18 +6,22 @@ import {
TooltipTrigger,
} from "../ui/tooltip";
const ShadTooltip = (props) => {
const ShadTooltip = ({
delayDuration = 500,
side,
content,
children,
style
}: ShadTooltipProps) => {
return (
<TooltipProvider>
<Tooltip delayDuration={props.delayDuration}>
<TooltipTrigger asChild>{props.children}</TooltipTrigger>
<Tooltip delayDuration={delayDuration}>
<TooltipTrigger asChild>{children}</TooltipTrigger>
<TooltipContent
side={props.side}
avoidCollisions={false}
sticky="always"
>
{props.content}
<TooltipContent
className={style}
side={side} avoidCollisions={false} sticky="always">
{content}
</TooltipContent>
</Tooltip>
</TooltipProvider>

View file

@ -11,6 +11,8 @@ import {
Card,
CardHeader,
} from "../ui/card";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "../ui/dialog";
import { Button } from "@mui/material";
export const CardComponent = ({
flow,
@ -31,20 +33,36 @@ export const CardComponent = ({
<CardTitle className="flex w-full items-center gap-4">
<span
className={
"rounded-full w-7 h-7 flex items-center justify-center text-2xl " +
"flex h-7 w-7 items-center justify-center rounded-full text-2xl " +
gradients[parseInt(flow.id.slice(0, 12), 16) % gradients.length]
}
></span>
<span className="flex-1 w-full inline-block truncate-doubleline break-words">
<span className="inline-block w-full flex-1 break-words truncate-doubleline">
{flow.name}
</span>
{onDelete && (
<button className="flex self-start" onClick={onDelete}>
<Dialog>
<DialogTrigger asChild>
<button className="flex self-start">
<Trash2 className="w-4 h-4 text-primary opacity-0 group-hover:opacity-100 transition-all" />
</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>
)}
</CardTitle>
<CardDescription className="pt-2 pb-2">
<CardDescription className="pb-2 pt-2">
<div className="truncate-doubleline">
{flow.description}
{/* {flow.description} */}
@ -53,7 +71,7 @@ export const CardComponent = ({
</CardHeader>
<CardFooter>
<div className="flex gap-2 w-full justify-between items-end">
<div className="flex w-full items-end justify-between gap-2">
<div className="flex flex-wrap gap-2">
{/* <Badge variant="secondary">Agent</Badge>
<Badge variant="secondary">

View file

@ -8,6 +8,7 @@ import { useSSE } from "../../../contexts/SSEContext";
import { typesContext } from "../../../contexts/typesContext";
import { alertContext } from "../../../contexts/alertContext";
import { postBuildInit } from "../../../controllers/API";
import ShadTooltip from "../../ShadTooltipComponent";
import RadialProgressComponent from "../../RadialProgress";
import { TabsContext } from "../../../contexts/tabsContext";
@ -16,7 +17,6 @@ export default function BuildTrigger({
open,
flow,
setIsBuilt,
isBuilt,
}: {
open: boolean;
flow: FlowType;
@ -168,9 +168,9 @@ export default function BuildTrigger({
leaveFrom="translate-y-0"
leaveTo="translate-y-96"
>
<div className={`fixed right-4` + (isBuilt ? " bottom-20" : " bottom-4")}>
<div className="fixed right-4 bottom-20">
<div
className={`${eventClick} flex justify-center align-center py-1 px-3 w-12 h-12 rounded-full shadow-md shadow-[#0000002a] hover:shadow-[#00000032] bg-[#E2E7EE] dark:border-gray-600 cursor-pointer`}
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`}
onClick={() => {
handleBuild(flow);
}}
@ -178,17 +178,18 @@ export default function BuildTrigger({
onMouseLeave={handleMouseLeave}
>
<button>
<div className="flex gap-3 items-center">
<div className="flex items-center gap-3">
{isBuilding && progress < 1 ? (
// Render your loading animation here when isBuilding is true
<RadialProgressComponent
color={"text-orange-400"}
// ! confirm below works
color={"text-build-trigger"}
value={progress}
></RadialProgressComponent>
) : isBuilding ? (
<Loading strokeWidth={1.5} style={{ color: "#fb923c" }} />
<Loading strokeWidth={1.5} className="stroke-build-trigger" />
) : (
<Zap className="sh-6 w-6 fill-orange-400 stroke-1 stroke-orange-400" />
<Zap strokeWidth={1.5} className="sh-6 w-6 fill-build-trigger stroke-1 stroke-build-trigger" />
)}
</div>
</button>

View file

@ -2,9 +2,9 @@ import { useState } from "react";
import { ChatMessageType } from "../../../types/chat";
import { nodeColors } from "../../../utils";
import Convert from "ansi-to-html";
const convert = new Convert({ newline: true });
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 (
@ -13,29 +13,30 @@ export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
<div className="w-full text-start">
<div
style={{ backgroundColor: nodeColors["chat"] }}
className=" relative text-start inline-block text-white rounded-xl overflow-hidden w-fit max-w-[280px] text-sm font-normal rounded-tl-none"
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 top-2 right-2 cursor-pointer"
className="absolute right-2 top-2 cursor-pointer"
>
<MessageCircle className="w-5 h-5 animate-bounce" />
<MessageCircle className="h-5 w-5 animate-bounce" />
</div>
)}
{chat.thought && chat.thought !== "" && !hidden && (
<div
onClick={() => setHidden((prev) => !prev)}
style={{ backgroundColor: nodeColors["thought"] }}
className=" text-start inline-block w-full pb-3 pt-3 px-5 cursor-pointer"
className=" inline-block w-full cursor-pointer px-5 pb-3 pt-3 text-start"
dangerouslySetInnerHTML={{
__html: convert.toHtml(chat.thought),
__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 pt-3 pr-8"
className="w-full rounded-b-md px-4 pb-3 pr-8 pt-3"
style={{ backgroundColor: nodeColors["chat"] }}
>
{chat.message}
@ -44,7 +45,7 @@ export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
</div>
) : (
<div className="w-full text-end">
<div className="text-start inline-block rounded-xl p-3 overflow-hidden w-fit max-w-[280px] px-5 text-sm text-black dark:text-white dark:bg-gray-700 bg-gray-200 font-normal rounded-tr-none">
<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>

View file

@ -3,6 +3,7 @@ import { MessagesSquare } from "lucide-react";
import { alertContext } from "../../../contexts/alertContext";
import { useContext } from "react";
import ShadTooltip from "../../ShadTooltipComponent";
export default function ChatTrigger({ open, setOpen, isBuilt }) {
const { setErrorData } = useContext(alertContext);
@ -29,23 +30,15 @@ export default function ChatTrigger({ open, setOpen, isBuilt }) {
leaveFrom="translate-y-0"
leaveTo="translate-y-96"
>
<div className="fixed bottom-4 right-4">
<div
className="flex justify-center align-center py-1 px-3 w-12 h-12 rounded-full shadow-md shadow-[#0000002a] hover:shadow-[#00000032]
bg-[#E2E7EE] dark:border-gray-600 cursor-pointer"
onClick={handleClick}
>
<button>
<button onClick={handleClick} className={ "transition-all fixed bottom-4 right-4 flex justify-center items-center py-1 px-3 w-12 h-12 rounded-full shadow-md shadow-round-btn-shadow hover:shadow-round-btn-shadow bg-border "+ (!isBuilt ? "cursor-not-allowed" : "cursor-pointer")}>
<div className="flex gap-3">
<MessagesSquare
className="pth-6 w-6 fill-[#5c8be1] stroke-1 stroke-[#5c8be1]"
className={"h-6 w-6 transition-all " + (isBuilt ? "fill-chat-trigger stroke-chat-trigger stroke-1" : "fill-chat-trigger-disabled stroke-1 stroke-chat-trigger-disabled")}
style={{ color: "white" }}
strokeWidth={1.5}
/>
</div>
</button>
</div>
</div>
</Transition>
);
}

View file

@ -13,7 +13,7 @@ import * as _ from "lodash";
export default function Chat({ flow }: ChatType) {
const [open, setOpen] = useState(false);
const [isBuilt, setIsBuilt] = useState(false);
const {tabsState} = useContext(TabsContext);
const { tabsState } = useContext(TabsContext);
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
@ -47,12 +47,14 @@ export default function Chat({ flow }: ChatType) {
const nodes = useNodes();
useEffect(() => {
const prevNodes = prevNodesRef.current;
const currentNodes = nodes.map(
(node: NodeType) => _.cloneDeep(node.data.node.template)
);
const currentNodes = nodes.map((node: NodeType) =>
_.cloneDeep(node.data.node.template)
);
if (
tabsState && tabsState[flow.id] && tabsState[flow.id].isPending
&& JSON.stringify(prevNodes) !== JSON.stringify(currentNodes)
tabsState &&
tabsState[flow.id] &&
tabsState[flow.id].isPending &&
JSON.stringify(prevNodes) !== JSON.stringify(currentNodes)
) {
setIsBuilt(false);
}
@ -62,25 +64,18 @@ export default function Chat({ flow }: ChatType) {
return (
<>
{isBuilt ? (
<div>
<BuildTrigger
open={open}
flow={flow}
setIsBuilt={setIsBuilt}
isBuilt={isBuilt}
/>
<FormModal key={flow.id} flow={flow} open={open} setOpen={setOpen} />
<ChatTrigger open={open} setOpen={setOpen} isBuilt={isBuilt} />
</div>
) : (
<div>
<BuildTrigger
open={open}
flow={flow}
setIsBuilt={setIsBuilt}
isBuilt={isBuilt}
/>
)}
{isBuilt && (
<FormModal key={flow.id} flow={flow} open={open} setOpen={setOpen} />
)}
<ChatTrigger open={open} setOpen={setOpen} isBuilt={isBuilt} />
</div>
</>
);
}

View file

@ -3,7 +3,8 @@ import { PopUpContext } from "../../contexts/popUpContext";
import CodeAreaModal from "../../modals/codeAreaModal";
import TextAreaModal from "../../modals/textAreaModal";
import { CodeAreaComponentType, TextAreaComponentType } from "../../types/components";
import { INPUT_STYLE } from "../../constants";
import { ExternalLink } from "lucide-react";
export default function CodeAreaComponent({
@ -25,16 +26,16 @@ export default function CodeAreaComponent({
}, [disabled, onChange]);
useEffect(() => {
setMyValue(value);
setMyValue(typeof value == "string" ? value : JSON.stringify(value));
}, [value]);
return (
<div
className={
disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full"
disabled ? "pointer-events-none w-full cursor-not-allowed" : "w-full"
}
>
<div className="w-full flex items-center">
<div className="flex w-full items-center">
<span
onClick={() => {
openPopUp(
@ -52,11 +53,8 @@ export default function CodeAreaComponent({
}}
className={
editNode
? "truncate cursor-pointer placeholder:text-center text-gray-500 block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 border-1 shadow-sm sm:text-sm" +
INPUT_STYLE
: "truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm sm:text-sm" +
INPUT_STYLE +
(disabled ? " bg-gray-200" : "")
? "input-edit-node input-dialog "
: "input-primary input-dialog " + (disabled ? "input-disable" : "")
}
>
{myValue !== "" ? myValue : "Type something..."}
@ -78,7 +76,7 @@ export default function CodeAreaComponent({
}}
>
{!editNode && (
<ExternalLink className="w-6 h-6 hover:text-ring dark:text-gray-300 ml-3" />
<ExternalLink strokeWidth={1.5} className="w-6 h-6 hover:text-accent-foreground ml-3" />
)}
</button>
</div>

View file

@ -1,9 +1,10 @@
import { Listbox, Transition } from "@headlessui/react";
import { Fragment, useEffect, useState } from "react";
import { Fragment, useContext, useEffect, useState } from "react";
import { DropDownComponentType } from "../../types/components";
import { classNames } from "../../utils";
import { INPUT_STYLE } from "../../constants";
import { ChevronsUpDown, Check } from "lucide-react";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
export default function Dropdown({
value,
@ -11,13 +12,17 @@ export default function Dropdown({
onSelect,
editNode = false,
numberOfOptions = 0,
apiModal = false,
}: DropDownComponentType) {
const { closePopUp } = useContext(PopUpContext);
let [internalValue, setInternalValue] = useState(
value === "" || !value ? "Choose an option" : value
);
useEffect(() => {
setInternalValue(value === "" || !value ? "Choose an option" : value);
}, [value]);
}, [closePopUp]);
return (
<>
@ -34,20 +39,20 @@ export default function Dropdown({
<Listbox.Button
className={
editNode
? "relative pr-8 placeholder:text-center block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md shadow-sm sm:text-sm border-gray-300 border-1" +
INPUT_STYLE
: "ring-1 ring-slate-300 dark:ring-slate-600 w-full py-2 pl-3 pr-10 text-left dark:focus:ring-offset-2 dark:focus:ring-offset-gray-900 dark:focus:ring-1 dark:focus:ring-gray-600 dark:focus-visible:ring-gray-900 dark:focus-visible:ring-offset-2 focus-visible:outline-none dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm sm:text-sm" +
INPUT_STYLE
? "border-1 relative pr-8 input-edit-node"
: "py-2 pl-3 pr-10 text-left input-primary"
}
>
<span className="block truncate w-full">{internalValue}</span>
<span className="block w-full truncate bg-background">
{internalValue}
</span>
<span
className={
"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
}
>
<ChevronsUpDown
className="h-5 w-5 text-gray-400"
className="h-5 w-5 text-muted-foreground"
aria-hidden="true"
/>
</span>
@ -61,23 +66,22 @@ export default function Dropdown({
leaveTo="opacity-0"
>
<Listbox.Options
className={
className={classNames(
editNode
? "absolute z-10 mt-1 max-h-60 overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm w-[215px]"
: "nowheel absolute z-10 mt-1 max-h-60 w-full overflow-auto overflow-y rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm "
}
? "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 ",
apiModal ? "mb-2 w-[250px]" : "absolute"
)}
>
{options.map((option, id) => (
<Listbox.Option
key={id}
className={({ active }) =>
classNames(
active
? " bg-accent dark:bg-white dark:text-gray-500"
: "",
active ? " bg-accent" : "",
editNode
? "relative cursor-default select-none py-0.5 pl-3 pr-12 dark:text-gray-300 dark:bg-gray-800"
: "relative cursor-default select-none py-2 pl-3 pr-9 dark:text-gray-300 dark:bg-gray-800"
? "relative cursor-default select-none py-0.5 pl-3 pr-12"
: "relative cursor-default select-none py-2 pl-3 pr-9"
)
}
value={option}
@ -96,15 +100,15 @@ export default function Dropdown({
{selected ? (
<span
className={classNames(
active ? "text-white dark:text-black" : "",
active ? "text-background " : "",
"absolute inset-y-0 right-0 flex items-center pr-4"
)}
>
<Check
className={
active
? "h-5 w-5 dark:text-black text-black"
: "h-5 w-5 dark:text-white text-black"
? "h-5 w-5 text-black"
: "h-5 w-5 text-black"
}
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 { INPUT_STYLE } from "../../constants";
import { PopUpContext } from "../../contexts/popUpContext";
export default function FloatComponent({
value,
@ -12,6 +12,7 @@ export default function FloatComponent({
}: FloatComponentType) {
const [myValue, setMyValue] = useState(value ?? "");
const { setDisableCopyPaste } = useContext(TabsContext);
const { closePopUp } = useContext(PopUpContext);
const step = 0.1;
const min = 0;
@ -26,7 +27,7 @@ export default function FloatComponent({
useEffect(() => {
setMyValue(value);
}, [value]);
}, [closePopUp]);
return (
<div
@ -56,11 +57,8 @@ export default function FloatComponent({
value={myValue}
className={
editNode
? "focus:placeholder-transparent text-center placeholder:text-center border-1 block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm sm:text-sm" +
INPUT_STYLE
: "focus:placeholder-transparent block w-full form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm ring-offset-gray-200 sm:text-sm" +
INPUT_STYLE +
(disabled ? " bg-gray-200 dark:bg-gray-700" : "")
? "input-edit-node"
: "input-primary" + (disabled ? " input-disable " : "")
}
placeholder={
editNode ? "Number 0 to 1" : "Type a number from zero to one"

View file

@ -47,20 +47,20 @@ export const MenuBar = ({ flows, tabId }) => {
let current_flow = flows.find((flow) => flow.id === tabId);
return (
<div className="flex gap-2 items-center">
<div className="flex items-center gap-2">
<Link to="/">
<ChevronLeft className="w-4" />
</Link>
<div className="flex items-center font-medium text-sm rounded-md py-1 px-1.5 gap-0.5">
<div className="flex items-center gap-0.5 rounded-md px-1.5 py-1 text-sm font-medium">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
className="gap-2 flex items-center max-w-[200px]"
className="flex max-w-[200px] items-center gap-2"
variant="primary"
size="sm"
>
<div className="truncate flex-1">{current_flow.name}</div>
<ChevronDown className="w-4 h-4" />
<div className="flex-1 truncate">{current_flow.name}</div>
<ChevronDown className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-44">
@ -71,7 +71,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Plus className="w-4 h-4 mr-2" />
<Plus className="mr-2 h-4 w-4" />
New
</DropdownMenuItem>
<DropdownMenuItem
@ -80,7 +80,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Settings2 className="w-4 h-4 mr-2 dark:text-gray-300" />
<Settings2 className="mr-2 h-4 w-4 " />
Settings
</DropdownMenuItem>
<DropdownMenuItem
@ -89,7 +89,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Undo className="w-4 h-4 mr-2 dark:text-gray-300" />
<Undo className="mr-2 h-4 w-4 " />
Undo
</DropdownMenuItem>
<DropdownMenuItem
@ -98,7 +98,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Redo className="w-4 h-4 mr-2 dark:text-gray-300" />
<Redo className="mr-2 h-4 w-4 " />
Redo
</DropdownMenuItem>
<DropdownMenuSeparator />

View file

@ -36,23 +36,23 @@ export default function Header() {
fetchStars();
}, []);
return (
<div className="w-full h-12 flex justify-between items-center border-b bg-muted">
<div className="flex gap-2 justify-start items-center w-96">
<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">
<Link to="/">
<span className="text-2xl ml-4"></span>
<span className="ml-4 text-2xl"></span>
</Link>
{flows.findIndex((f) => tabId === f.id) !== -1 && tabId !== "" && (
<MenuBar flows={flows} tabId={tabId} />
)}
</div>
<div className="flex gap-2 items-center">
<div className="flex items-center gap-2">
<Link to="/">
<Button
className="gap-2"
variant={location.pathname === "/" ? "primary" : "secondary"}
size="sm"
>
<Home className="w-4 h-4" />
<Home className="h-4 w-4" />
<div className="flex-1">{USER_PROJECTS_HEADER}</div>
</Button>
</Link>
@ -64,22 +64,22 @@ export default function Header() {
}
size="sm"
>
<Users2 className="w-4 h-4" />
<Users2 className="h-4 w-4" />
<div className="flex-1">Community Examples</div>
</Button>
</Link>
</div>
<div className="flex justify-end px-2 w-96">
<div className="ml-auto mr-2 flex gap-5 items-center">
<div className="flex w-96 justify-end px-2">
<div className="ml-auto mr-2 flex items-center gap-5">
<a
href="https://github.com/logspace-ai/langflow"
target="_blank"
rel="noreferrer"
className="inline-flex shadow-sm items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background text-gray-600 dark:text-gray-300 border border-input hover:bg-accent hover:text-accent-foreground h-9 px-3 pr-0 rounded-md"
className="inline-flex shadow-sm items-center justify-center text-sm font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background text-muted-foreground border border-input hover:bg-accent hover:text-accent-foreground h-9 px-3 pr-0 rounded-md"
>
<FaGithub className="h-5 w-5 mr-2" />
<FaGithub className="mr-2 h-5 w-5" />
Star
<div className="ml-2 flex text-sm bg-background rounded-md rounded-l-none border px-2 h-9 -mr-px items-center justify-center">
<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>
</a>
@ -89,7 +89,7 @@ export default function Header() {
rel="noreferrer"
className="text-muted-foreground"
>
<FaTwitter className="h-5 w-5" />
<FaTwitter className="h-5 w-5 hover:text-accent-foreground" />
</a>
<a
href="https://discord.gg/EqksyE2EX9"
@ -97,11 +97,12 @@ export default function Header() {
rel="noreferrer"
className="text-muted-foreground"
>
<FaDiscord className="h-5 w-5" />
<FaDiscord className="h-5 w-5 hover:text-accent-foreground" />
</a>
{/* <Separator orientation="vertical" />
<Separator orientation="vertical" />
<button
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200"
className="text-muted-foreground hover:text-accent-foreground "
onClick={() => {
setDark(!dark);
}}
@ -111,9 +112,9 @@ export default function Header() {
) : (
<MoonIcon className="h-5 w-5" />
)}
</button> */}
</button>
<button
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200 relative"
className="text-muted-foreground hover:text-accent-foreground relative"
onClick={(event: React.MouseEvent<HTMLElement>) => {
setNotificationCenter(false);
const { top, left } = (
@ -122,18 +123,18 @@ export default function Header() {
openPopUp(
<>
<div
className="z-10 absolute"
className="absolute z-10"
style={{ top: top + 34, left: left - AlertWidth }}
>
<AlertDropdown />
</div>
<div className="h-screen w-screen fixed top-0 left-0"></div>
<div className="fixed left-0 top-0 h-screen w-screen"></div>
</>
);
}}
>
{notificationCenter && (
<div className="absolute w-1.5 h-1.5 rounded-full bg-destructive right-[3px]"></div>
<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" />
</button>

View file

@ -3,7 +3,6 @@ import { InputComponentType } from "../../types/components";
import { classNames } from "../../utils";
import { TabsContext } from "../../contexts/tabsContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { INPUT_STYLE } from "../../constants";
export default function InputComponent({
value,
@ -33,7 +32,7 @@ export default function InputComponent({
<div
className={
disabled
? "relative pointer-events-none cursor-not-allowed"
? "pointer-events-none relative cursor-not-allowed"
: "relative"
}
>
@ -46,13 +45,10 @@ export default function InputComponent({
if (disableCopyPaste) setDisableCopyPaste(false);
}}
className={classNames(
"block w-full pr-12 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm sm:text-sm focus:placeholder-transparent",
disabled ? " bg-gray-200 dark:bg-gray-700" : "",
" pr-12 ",
disabled ? " input-disable " : "",
password && !pwdVisible && myValue !== "" ? "password" : "",
editNode
? "border-1 block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm sm:text-sm text-center" +
INPUT_STYLE
: "ring-offset-gray-200" + INPUT_STYLE,
editNode ? " input-edit-node " : " input-primary ",
password && editNode ? "pr-8" : "pr-3"
)}
placeholder={password && editNode ? "Key" : "Type something..."}
@ -65,8 +61,8 @@ export default function InputComponent({
<button
className={classNames(
editNode
? "absolute inset-y-0 right-0 pr-2 items-center text-gray-600"
: "absolute inset-y-0 right-0 items-center px-4 text-gray-600"
? "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"
)}
onClick={() => {
setPwdVisible(!pwdVisible);
@ -82,8 +78,8 @@ export default function InputComponent({
stroke="currentColor"
className={classNames(
editNode
? "w-5 h-5 absolute bottom-0.5 right-2"
: "w-5 h-5 absolute bottom-2 right-3"
? "absolute bottom-0.5 right-2 h-5 w-5"
: "absolute bottom-2 right-3 h-5 w-5"
)}
>
<path
@ -101,8 +97,8 @@ export default function InputComponent({
stroke="currentColor"
className={classNames(
editNode
? "w-5 h-5 absolute bottom-0.5 right-2"
: "w-5 h-5 absolute bottom-2 right-3"
? "absolute bottom-0.5 right-2 h-5 w-5"
: "absolute bottom-2 right-3 h-5 w-5"
)}
>
<path

View file

@ -2,7 +2,6 @@ import { useContext, useEffect, useState } from "react";
import { alertContext } from "../../contexts/alertContext";
import { FileComponentType } from "../../types/components";
import { TabsContext } from "../../contexts/tabsContext";
import { INPUT_STYLE } from "../../constants";
import { FileSearch2 } from "lucide-react";
import { uploadFile } from "../../controllers/API";
@ -95,29 +94,26 @@ export default function InputFileComponent({
return (
<div
className={
disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full"
disabled ? "pointer-events-none w-full cursor-not-allowed" : "w-full"
}
>
<div className="w-full flex items-center gap-2">
<div className="flex w-full items-center">
<span
onClick={handleButtonClick}
className={
editNode
? "truncate placeholder:text-center text-gray-500 block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm sm:text-sm border-1" +
INPUT_STYLE
: "truncate block w-full text-gray-500 dark:text-gray-300 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm sm:text-sm" +
INPUT_STYLE +
(disabled ? " bg-gray-200" : "")
? "input-edit-node " + "input-primary "
: "input-primary " + (disabled ? "input-disable " : "")
}
>
{myValue !== "" ? myValue : "No file"}
</span>
<button onClick={handleButtonClick}>
{!editNode && !loading && (
<FileSearch2 className="w-6 h-6 hover:text-ring" />
<FileSearch2 strokeWidth={1.5} className="w-6 h-6 hover:text-accent-foreground" />
)}
{!editNode && loading && (
<span className="loading loading-spinner loading-sm pl-3 h-8 pointer-events-none"></span>
<span className="loading loading-spinner loading-sm pointer-events-none h-8 pl-3"></span>
)}
</button>
</div>

View file

@ -3,81 +3,88 @@ import { InputListComponentType } from "../../types/components";
import { TabsContext } from "../../contexts/tabsContext";
import _ from "lodash";
import { INPUT_STYLE } from "../../constants";
import { X, Plus } from "lucide-react";
import { PopUpContext } from "../../contexts/popUpContext";
export default function InputListComponent({
value,
onChange,
disabled,
editNode = false,
onAddInput,
}: InputListComponentType) {
const [inputList, setInputList] = useState(value ?? [""]);
const { closePopUp } = useContext(PopUpContext);
useEffect(() => {
if (disabled) {
setInputList([""]);
onChange([""]);
}
}, [disabled, onChange]);
useEffect(() => {
setInputList(value);
}, [closePopUp]);
return (
<div
className={
(disabled ? "pointer-events-none cursor-not-allowed" : "") +
"flex flex-col gap-3 py-2"
"flex flex-col gap-3"
}
>
{inputList.map((i, idx) => (
<div key={idx} className="w-full flex gap-3">
<input
type="text"
value={i}
className={
editNode
? "border-[1px] truncate cursor-pointer text-center placeholder:text-center text-gray-500 block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm sm:text-sm" +
INPUT_STYLE
: "block w-full form-input rounded-md border-gray-300 shadow-sm focus:border-gray-500 focus:ring-gray-500 sm:text-sm" +
(disabled ? " bg-gray-200" : "") +
"focus:placeholder-transparent"
}
placeholder="Type something..."
onChange={(e) => {
setInputList((old) => {
let newInputList = _.cloneDeep(old);
newInputList[idx] = e.target.value;
return newInputList;
});
onChange(inputList);
}}
/>
{idx === inputList.length - 1 ? (
<button
onClick={() => {
{inputList.map((i, idx) => {
return (
<div key={idx} className="flex w-full gap-3">
<input
type="text"
value={i}
className={
editNode
? "input-edit-node "
: "input-primary " + (disabled ? "input-disable" : "")
}
placeholder="Type something..."
onChange={(e) => {
setInputList((old) => {
let newInputList = _.cloneDeep(old);
newInputList.push("");
newInputList[idx] = e.target.value;
return newInputList;
});
onChange(inputList);
}}
>
<Plus className={"w-4 h-4 hover:text-ring"} />
</button>
) : (
<button
onClick={() => {
setInputList((old) => {
let newInputList = _.cloneDeep(old);
newInputList.splice(idx, 1);
return newInputList;
});
onChange(inputList);
}}
>
<X className="w-4 h-4 hover:text-red-600" />
</button>
)}
</div>
))}
/>
{idx === inputList.length - 1 ? (
<button
onClick={() => {
setInputList((old) => {
let newInputList = _.cloneDeep(old);
newInputList.push("");
return newInputList;
});
onChange(inputList);
}}
>
<Plus className={"h-4 w-4 hover:text-accent-foreground"} />
</button>
) : (
<button
onClick={() => {
setInputList((old) => {
let newInputList = _.cloneDeep(old);
newInputList.splice(idx, 1);
return newInputList;
});
onChange(inputList);
}}
>
<X className="h-4 w-4 hover:text-status-red" />
</button>
)}
</div>
);
})}
</div>
);
}

View file

@ -2,7 +2,7 @@ import { useContext, useEffect, useState } from "react";
import { FloatComponentType } from "../../types/components";
import { TabsContext } from "../../contexts/tabsContext";
import { classNames } from "../../utils";
import { INPUT_STYLE } from "../../constants";
import { PopUpContext } from "../../contexts/popUpContext";
export default function IntComponent({
value,
@ -14,6 +14,7 @@ export default function IntComponent({
const [myValue, setMyValue] = useState(value ?? "");
const { setDisableCopyPaste } = useContext(TabsContext);
const min = 0;
const { closePopUp } = useContext(PopUpContext);
useEffect(() => {
if (disabled) {
@ -24,13 +25,13 @@ export default function IntComponent({
useEffect(() => {
setMyValue(value);
}, [value]);
}, [closePopUp]);
return (
<div
className={
"w-full " +
(disabled ? "pointer-events-none cursor-not-allowed w-full" : "w-full")
(disabled ? "pointer-events-none w-full cursor-not-allowed" : "w-full")
}
>
<input
@ -69,13 +70,10 @@ export default function IntComponent({
value={myValue}
className={
editNode
? "focus:placeholder-transparent text-center placeholder:text-center border-1 block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm sm:text-sm" +
INPUT_STYLE
: "focus:placeholder-transparent block w-full form-input dark:bg-gray-900 dark:border-gray-600 dark:text-gray-300 rounded-md border-gray-300 shadow-sm ring-offset-background sm:text-sm" +
INPUT_STYLE +
(disabled ? " bg-gray-200 dark:bg-gray-700" : "")
? " input-edit-node "
: " input-primary " + (disabled ? " input-disable " : "")
}
placeholder={editNode ? "Integer number" : "Type a integer number"}
placeholder={editNode ? "Integer number" : "Type an integer number"}
onChange={(e) => {
setMyValue(e.target.value);
onChange(e.target.value);

View file

@ -4,10 +4,10 @@ type LoadingComponentProps = {
export default function LoadingComponent({ remSize }: LoadingComponentProps) {
return (
<div role="status" className="w-min m-auto">
<div role="status" className="m-auto w-min">
<svg
aria-hidden="true"
className={`w-${remSize} h-${remSize} mr-2 text-muted animate-spin dark:text-gray-600 fill-blue-600`}
className={`w-${remSize} h-${remSize} mr-2 animate-spin fill-almost-medium-blue text-muted`}
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
@ -22,7 +22,9 @@ export default function LoadingComponent({ remSize }: LoadingComponentProps) {
/>
</svg>
<br></br>
<span className="animate-pulse text-blue-600 text-lg">Loading...</span>
<span className="animate-pulse text-lg text-almost-medium-blue">
Loading...
</span>
</div>
);
}

View file

@ -3,13 +3,14 @@ import { PopUpContext } from "../../contexts/popUpContext";
import { TextAreaComponentType } from "../../types/components";
import GenericModal from "../../modals/genericModal";
import { TypeModal } from "../../utils";
import { INPUT_STYLE } from "../../constants";
import { ExternalLink } from "lucide-react";
import { postValidatePrompt } from "../../controllers/API";
import { typesContext } from "../../contexts/typesContext";
import * as _ from "lodash";
export default function PromptAreaComponent({
field_name,
setNodeClass,
nodeClass,
value,
@ -20,7 +21,6 @@ export default function PromptAreaComponent({
const [myValue, setMyValue] = useState("");
const { openPopUp } = useContext(PopUpContext);
const { reactFlowInstance } = useContext(typesContext);
useEffect(() => {
if (disabled) {
setMyValue("");
@ -29,27 +29,30 @@ export default function PromptAreaComponent({
}, [disabled, onChange]);
useEffect(() => {
if (value !== "" && myValue !== value && reactFlowInstance) { // only executed once
if (value !== "" && myValue !== value && reactFlowInstance) {
// only executed once
setMyValue(value);
postValidatePrompt(value, nodeClass)
postValidatePrompt(field_name, value, nodeClass)
.then((apiReturn) => {
if (apiReturn.data) {
setNodeClass(apiReturn.data.frontend_node);
// need to update reactFlowInstance to re-render the nodes.
reactFlowInstance.setEdges(_.cloneDeep(reactFlowInstance.getEdges()));
reactFlowInstance.setEdges(
_.cloneDeep(reactFlowInstance.getEdges())
);
}
})
.catch((error) => {});
}
}, [reactFlowInstance]);
}, [reactFlowInstance, field_name]);
return (
<div
className={
disabled ? "pointer-events-none cursor-not-allowed w-full" : " w-full"
disabled ? "pointer-events-none w-full cursor-not-allowed" : " w-full"
}
>
<div className="w-full flex items-center gap-3">
<div className="flex w-full items-center">
<span
onClick={() => {
openPopUp(
@ -69,10 +72,10 @@ export default function PromptAreaComponent({
}}
className={
editNode
? "cursor-pointer truncate placeholder:text-center text-gray-500 border-1 block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm sm:text-sm" +
INPUT_STYLE
: "truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm sm:text-sm" +
(disabled ? " bg-gray-200" : "")
? " input-edit-node " + " input-dialog "
: (disabled ? " input-disable " : "") +
" input-primary " +
" input-dialog "
}
>
{myValue !== "" ? myValue : "Type your prompt here"}
@ -81,6 +84,7 @@ export default function PromptAreaComponent({
onClick={() => {
openPopUp(
<GenericModal
field_name={field_name}
type={TypeModal.PROMPT}
value={myValue}
buttonText="Check & Save"
@ -96,7 +100,10 @@ export default function PromptAreaComponent({
}}
>
{!editNode && (
<ExternalLink className="w-6 h-6 hover:text-ring dark:text-gray-300" />
<ExternalLink
strokeWidth={1.5}
className="ml-3 h-6 w-6 hover:text-accent-foreground"
/>
)}
</button>
</div>

View file

@ -3,7 +3,7 @@ import { PopUpContext } from "../../contexts/popUpContext";
import { TextAreaComponentType } from "../../types/components";
import GenericModal from "../../modals/genericModal";
import { TypeModal } from "../../utils";
import { INPUT_STYLE } from "../../constants";
import { ExternalLink } from "lucide-react";
export default function TextAreaComponent({
@ -31,8 +31,8 @@ export default function TextAreaComponent({
<div
className={
editNode
? "w-full flex items-center"
: "w-full flex items-center gap-3"
? "w-full items-center"
: "w-full flex items-center"
}
>
<span
@ -52,10 +52,8 @@ export default function TextAreaComponent({
}}
className={
editNode
? "truncate cursor-pointer placeholder:text-center text-gray-500 border-1 block w-full pt-0.5 pb-0.5 form-input dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 rounded-md border-gray-300 shadow-sm sm:text-sm" +
INPUT_STYLE
: "truncate block w-full text-gray-500 dark:text-muted px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm sm:text-sm" +
(disabled ? " bg-gray-200" : "")
? "input-edit-node input-dialog "
: "input-primary input-dialog " + (disabled ? "input-disable" : "")
}
>
{myValue !== "" ? myValue : "Type something..."}
@ -76,9 +74,7 @@ export default function TextAreaComponent({
);
}}
>
{!editNode && (
<ExternalLink className="w-6 h-6 hover:text-ring dark:text-gray-300" />
)}
{!editNode && <ExternalLink strokeWidth={1.5} className="w-6 h-6 hover:text-accent-foreground ml-3" />}
</button>
</div>
</div>

View file

@ -21,7 +21,7 @@ export default function ToggleComponent({
setEnabled(x);
}}
className={classNames(
enabled ? "bg-primary" : "bg-gray-200",
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"
)}
>
@ -30,16 +30,14 @@ export default function ToggleComponent({
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",
disabled
? "bg-gray-200 dark:bg-gray-600"
: "bg-white dark:bg-gray-800"
disabled ? "bg-input " : "bg-background"
)}
>
<span
className={classNames(
enabled
? "opacity-0 ease-out duration-100"
: "opacity-100 ease-in duration-200",
? "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"
)}
aria-hidden="true"
@ -47,8 +45,8 @@ export default function ToggleComponent({
<span
className={classNames(
enabled
? "opacity-100 ease-in duration-200"
: "opacity-0 ease-out duration-100",
? "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"
)}
aria-hidden="true"

View file

@ -33,7 +33,7 @@ export default function ToggleShadComponent({
transform: `scaleX(${scaleX}) scaleY(${scaleY})`,
}}
disabled={disabled}
className="data-[state=unchecked]:bg-slate-500"
className=""
checked={enabled}
onCheckedChange={(x: boolean) => {
setEnabled(x);

View file

@ -1,11 +1,11 @@
"use client"
"use client";
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { ChevronDown } from "lucide-react"
import { cn } from "../../utils"
import * as React from "react";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { ChevronDownIcon } from "@radix-ui/react-icons";
import { cn } from "../../utils";
const Accordion = AccordionPrimitive.Root
const Accordion = AccordionPrimitive.Root;
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
@ -16,8 +16,8 @@ const AccordionItem = React.forwardRef<
className={cn("border-b", className)}
{...props}
/>
))
AccordionItem.displayName = "AccordionItem"
));
AccordionItem.displayName = "AccordionItem";
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
@ -27,17 +27,17 @@ const AccordionTrigger = React.forwardRef<
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
<ChevronDownIcon className="h-4 w-4 text-muted-foreground transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
));
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
@ -46,14 +46,14 @@ const AccordionContent = React.forwardRef<
<AccordionPrimitive.Content
ref={ref}
className={cn(
"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
className
)}
{...props}
>
<div className="pb-4 pt-0">{children}</div>
</AccordionPrimitive.Content>
))
AccordionContent.displayName = AccordionPrimitive.Content.displayName
));
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };

View file

@ -14,7 +14,7 @@ const buttonVariants = cva(
outline:
"border border-input hover:bg-accent hover:text-accent-foreground",
primary:
"border bg-background text-secondary-foreground hover:bg-background/80 hover:shadow-sm",
"border bg-background text-secondary-foreground hover:bg-background/80 dark:hover:bg-background/10 hover:shadow-sm",
secondary:
"border border-muted bg-muted text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",

View file

@ -8,7 +8,7 @@ const Card = React.forwardRef<
<div
ref={ref}
className={cn(
"rounded-lg flex flex-col justify-between border bg-card text-card-foreground shadow-sm hover:shadow-lg transition-all",
"flex flex-col justify-between rounded-lg border bg-card text-card-foreground shadow-sm transition-all hover:shadow-lg",
className
)}
{...props}

View file

@ -27,7 +27,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-primary/80 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",
"fixed inset-0 z-50 bg-blur-shared backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",
className
)}
{...props}
@ -44,7 +44,7 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed z-50 grid w-full gap-4 rounded-b-lg border bg-background p-6 shadow-lg animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",
"fixed gap-3 z-50 grid w-full rounded-b-lg border bg-background p-6 shadow-lg animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",
className
)}
{...props}

View file

@ -146,7 +146,7 @@ const DropdownMenuLabel = React.forwardRef<
<DropdownMenuPrimitive.Label
ref={ref}
className={cn(
"px-2 pl-2 py-1.5 text-sm font-semibold",
"px-2 py-1.5 pl-2 text-sm font-semibold",
inset && "pl-8",
className
)}

View file

@ -57,7 +57,7 @@ export default function RenameLabel(props) {
ref={inputRef}
onInput={resizeInput}
className={cn(
"px-2 bg-transparent focus:border-none active:outline hover:outline focus:outline outline-gray-300 rounded-md",
"rounded-md bg-transparent px-2 outline-ring hover:outline focus:border-none focus:outline active:outline",
props.className
)}
onBlur={() => {
@ -74,7 +74,7 @@ export default function RenameLabel(props) {
) : (
<div className="flex items-center gap-2">
<span
className={cn("px-2 text-left truncate", props.className)}
className={cn("truncate px-2 text-left", props.className)}
onDoubleClick={() => {
setIsRename(true);
setMyValue(props.value);

View file

@ -10,15 +10,16 @@ const Switch = React.forwardRef<
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
"peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-ring",
className
)}
{...props}
ref={ref}
>
<SwitchPrimitives.Thumb
aria-disabled={props.disabled}
className={cn(
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 aria-disabled:bg-muted/70 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
)}
/>
</SwitchPrimitives.Root>

View file

@ -28,7 +28,7 @@ const TabsTrigger = React.forwardRef<
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm data-[state=inactive]:hover:bg-secondary/80 data-[state=active]:border data-[state=inactive]:border data-[state=inactive]:border-muted",
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border data-[state=inactive]:border data-[state=inactive]:border-muted data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm data-[state=inactive]:hover:bg-secondary/80",
className
)}
{...props}

View file

@ -61,7 +61,7 @@ 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): string => {
export const getPythonApiCode = (flow: FlowType, tweak?): string => {
const flowId = flow.id;
// create a dictionary of node ids and the values is an empty dictionary
@ -77,7 +77,11 @@ BASE_API_URL = "${window.location.protocol}//${
FLOW_ID = "${flowId}"
# You can tweak the flow by adding a tweaks dictionary
# e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}}
TWEAKS = ${JSON.stringify(tweaks, null, 2)}
TWEAKS = ${
tweak && tweak.length > 0
? buildTweakObject(tweak)
: JSON.stringify(tweaks, null, 2)
}
def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
"""
@ -107,7 +111,7 @@ print(run_flow("Your message", flow_id=FLOW_ID, tweaks=TWEAKS))`;
* @param {string} flowId - The id of the flow
* @returns {string} - The curl code
*/
export const getCurlCode = (flow: FlowType): string => {
export const getCurlCode = (flow: FlowType, tweak?): string => {
const flowId = flow.id;
const tweaks = buildTweaks(flow);
return `curl -X POST \\
@ -115,27 +119,46 @@ export const getCurlCode = (flow: FlowType): string => {
window.location.host
}/api/v1/process/${flowId} \\
-H 'Content-Type: application/json' \\
-d '{"inputs": {"input": message}, "tweaks": ${JSON.stringify(
tweaks,
null,
2
)}}'`;
-d '{"inputs": {"input": message}, "tweaks": ${
tweak && tweak.length > 0
? buildTweakObject(tweak)
: JSON.stringify(tweaks, null, 2)
}}'`;
};
/**
* Function to get the python code for the API
* @param {string} flowName - The name of the flow
* @returns {string} - The python code
*/
export const getPythonCode = (flow: FlowType): string => {
export const getPythonCode = (flow: FlowType, tweak?): string => {
const flowName = flow.name;
const tweaks = buildTweaks(flow);
return `from langflow import load_flow_from_json
TWEAKS = ${JSON.stringify(tweaks, null, 2)}
TWEAKS = ${
tweak && tweak.length > 0
? buildTweakObject(tweak)
: JSON.stringify(tweaks, null, 2)
}
flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS)
# Now you can use it like any chain
flow("Hey, have you heard of LangFlow?")`;
};
function buildTweakObject(tweak) {
tweak.forEach((el) => {
Object.keys(el).forEach((key) => {
for (let kp in el[key]) {
try {
el[key][kp] = JSON.parse(el[key][kp]);
} catch {}
}
});
});
const tweakString = JSON.stringify(tweak, null, 2);
return tweakString;
}
/**
* The base text for subtitle of Import Dialog
* @constant
@ -154,11 +177,14 @@ export const EXPORT_CODE_DIALOG =
* The base text for subtitle of code dialog
* @constant
*/
export const INPUT_STYLE =
" focus:ring-1 focus:ring-offset-1 focus:ring-ring focus:outline-none ";
export const COLUMN_DIV_STYLE =
" w-full h-full flex overflow-auto flex-col bg-muted px-16 ";
export const NAV_DISPLAY_STYLE =
" w-full flex justify-between py-12 pb-2 px-6 ";
/**
* Default description for the flow
* The base text for subtitle of code dialog
* @constant
*/
export const DESCRIPTIONS: string[] = [
@ -173,7 +199,7 @@ export const DESCRIPTIONS: string[] = [
"Your Hub for Text Generation.",
"Promptly Ingenious!",
"Building Linguistic Labyrinths.",
"Create, Chain, Communicate.",
"LangFlow: Create, Chain, Communicate.",
"Connect the Dots, Craft Language.",
"Interactive Language Weaving.",
"Generate, Innovate, Communicate.",
@ -183,52 +209,12 @@ export const DESCRIPTIONS: string[] = [
"Nurture NLP Nodes Here.",
"Conversational Cartography Unlocked.",
"Design, Develop, Dialogize.",
"Unleashing Linguistic Creativity.",
"Graph Your Way to Great Conversations.",
"The Power of Language at Your Fingertips.",
"Sculpting Language with Precision.",
"Where Language Meets Logic.",
"Building Intelligent Interactions.",
"Your Passport to Linguistic Landscapes.",
"Create, Curate, Communicate with LangFlow.",
"Flow into the Future of Language.",
"Mapping Meaningful Conversations.",
"Unravel the Art of Articulation.",
"Language Engineering Excellence.",
"Navigate the Networks of Conversation.",
"Crafting Conversations, One Node at a Time.",
"The Pinnacle of Prompt Generation.",
"Language Models, Mapped and Mastered.",
"Powerful Prompts, Perfectly Positioned.",
"Innovation in Interaction with LangFlow.",
"Your Toolkit for Text Generation.",
"Unfolding Linguistic Possibilities.",
"Building Powerful Solutions with Language Models.",
"Uncover Business Opportunities with NLP.",
"Harness the Power of Conversational AI.",
"Transform Your Business with Smart Dialogues.",
"Craft Meaningful Interactions, Generate Value.",
"Unleashing Business Potential through Language Engineering.",
"Empowering Enterprises with Intelligent Interactions.",
"Driving Innovation in Business Communication.",
"Catalyzing Business Growth through Conversational AI.",
"Text Generation Meets Business Transformation.",
"Navigate the Linguistic Landscape, Discover Opportunities.",
"Create Powerful Connections, Boost Business Value.",
"Empowering Communication, Enabling Opportunities.",
"Advanced NLP for Groundbreaking Business Solutions.",
"Innovation in Interaction, Revolution in Revenue.",
"Maximize Impact with Intelligent Conversations.",
"Beyond Text Generation - Unleashing Business Opportunities.",
"Unlock the Power of AI in Your Business Conversations.",
"Crafting Dialogues that Drive Business Success.",
"Engineered for Excellence, Built for Business.",
];
export const BUTTON_DIV_STYLE = " flex gap-2 focus:ring-1 focus:ring-offset-1 focus:ring-ring focus:outline-none ";
/**
* Adjectives for the name of the flow
* The base text for subtitle of code dialog
* @constant
*
*/
export const ADJECTIVES: string[] = [
"admiring",

View file

@ -78,9 +78,9 @@ export function AlertProvider({ children }: { children: ReactNode }) {
* @param newState An object containing the new error data, including title and optional list of error messages
*/
function setErrorData(newState: { title: string; list?: Array<string> }) {
setErrorDataState(newState);
setErrorOpen(true);
if (newState.title && newState.title !== "") {
setErrorDataState(newState);
setErrorOpen(true);
setNotificationCenter(true);
pushNotificationList({
type: "error",
@ -95,9 +95,9 @@ export function AlertProvider({ children }: { children: ReactNode }) {
* @param newState An object containing the title of the notice and optionally a link.
*/
function setNoticeData(newState: { title: string; link?: string }) {
setNoticeDataState(newState);
setNoticeOpen(true);
if (newState.title && newState.title !== "") {
setNoticeDataState(newState);
setNoticeOpen(true);
// Add new notice to notification center
setNotificationCenter(true);
pushNotificationList({
@ -113,11 +113,10 @@ export function AlertProvider({ children }: { children: ReactNode }) {
* @param newState - A state object with a "title" property to set in the success data state.
*/
function setSuccessData(newState: { title: string }) {
setSuccessDataState(newState); // update the success data state with the provided new state
setSuccessOpen(true); // open the success alert
// If the new state has a "title" property, add a new success notification to the list
if (newState.title && newState.title !== "") {
setSuccessDataState(newState); // update the success data state with the provided new state
setSuccessOpen(true); // open the success alert
setNotificationCenter(true); // show the notification center
pushNotificationList({
// add the new notification to the list

View file

@ -5,6 +5,8 @@ import React, { useState } from "react";
export const PopUpContext = createContext({
openPopUp: (popUpElement: JSX.Element) => {},
closePopUp: () => {},
setCloseEdit: (value: string) => {},
closeEdit: "",
});
interface PopUpProviderProps {
@ -22,8 +24,12 @@ const PopUpProvider = ({ children }: PopUpProviderProps) => {
setPopUpElements((prevPopUps) => prevPopUps.slice(1));
};
const [closeEdit, setCloseEdit] = useState("");
return (
<PopUpContext.Provider value={{ openPopUp, closePopUp }}>
<PopUpContext.Provider
value={{ openPopUp, closePopUp, closeEdit, setCloseEdit }}
>
{children}
{popUpElements[0]}
</PopUpContext.Provider>

View file

@ -53,6 +53,8 @@ const TabsContextInitialValue: TabsContextType = {
tabsState: {},
setTabsState: (state: TabsState) => {},
getNodeId: (nodeType: string) => "",
setTweak: (tweak: any) => {},
getTweak: {},
paste: (
selection: { nodes: any; edges: any },
position: { x: number; y: number; paneX?: number; paneY?: number }
@ -73,6 +75,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
const { templates, reactFlowInstance } = useContext(typesContext);
const [lastCopiedSelection, setLastCopiedSelection] = useState(null);
const [tabsState, setTabsState] = useState<TabsState>({});
const [getTweak, setTweak] = useState({});
const newNodeId = useRef(uid());
function incrementNodeId() {
@ -195,10 +198,13 @@ export function TabsProvider({ children }: { children: ReactNode }) {
edge.style = { stroke: "#555555" };
});
}
function updateDisplay_name(node: NodeType, template: APIClassType) {
node.data.node.display_name = template["display_name"]
? template["display_name"]
: node.data.type;
node.data.node.display_name = template["display_name"] || node.data.type;
}
function updateNodeDocumentation(node: NodeType, template: APIClassType) {
node.data.node.documentation = template["documentation"];
}
function processFlowNodes(flow) {
@ -215,6 +221,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
updateNodeEdges(flow, node, template);
updateNodeDescription(node, template);
updateNodeTemplate(node, template);
updateNodeDocumentation(node, template);
}
});
}
@ -265,16 +272,20 @@ export function TabsProvider({ children }: { children: ReactNode }) {
/**
* Downloads the current flow as a JSON file
*/
function downloadFlow(flow: FlowType) {
function downloadFlow(
flow: FlowType,
flowName: string,
flowDescription?: string
) {
// create a data URI with the current flow data
const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
JSON.stringify(flow)
JSON.stringify({ ...flow, name: flowName, description: flowDescription })
)}`;
// create a link element and set its properties
const link = document.createElement("a");
link.href = jsonString;
link.download = `${flows.find((f) => f.id === tabId).name}.json`;
link.download = `${flowName && flowName != "" ? flowName : flows.find((f) => f.id === tabId).name}.json`;
// simulate a click on the link element to trigger the download
link.click();
@ -418,7 +429,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
y: insidePosition.y + n.position.y - minimumY,
},
data: {
...n.data,
..._.cloneDeep(n.data),
id: newId,
},
};
@ -460,8 +471,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
style: { stroke: "inherit" },
className:
targetHandle.split("|")[0] === "Text"
? "stroke-gray-800 dark:stroke-gray-300"
: "stroke-gray-900 dark:stroke-gray-200",
? "stroke-gray-800 "
: "stroke-gray-900 ",
animated: targetHandle.split("|")[0] === "Text",
selected: false,
},
@ -527,8 +538,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
edge.style = { stroke: "inherit" };
edge.className =
edge.targetHandle.split("|")[0] === "Text"
? "stroke-gray-800 dark:stroke-gray-300"
: "stroke-gray-900 dark:stroke-gray-200";
? "stroke-gray-800 "
: "stroke-gray-900 ";
edge.animated = edge.targetHandle.split("|")[0] === "Text";
});
};
@ -649,6 +660,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
tabsState,
setTabsState,
paste,
getTweak,
setTweak,
}}
>
{children}

View file

@ -52,16 +52,18 @@ export async function postValidateCode(
/**
* Checks the prompt for the code block by sending it to an API endpoint.
*
* @param {string} name - The name of the field to check.
* @param {string} template - The template string of the prompt to check.
* @param {APIClassType} frontend_node - The frontend node to check.
* @returns {Promise<AxiosResponse<PromptTypeAPI>>} A promise that resolves to an AxiosResponse containing the validation results.
*/
export async function postValidatePrompt(
name: string,
template: string,
frontend_node: APIClassType
): Promise<AxiosResponse<PromptTypeAPI>> {
return await axios.post("/api/v1/validate/prompt", {
name: name,
template: template,
frontend_node: frontend_node,
});
@ -317,7 +319,7 @@ export async function getBuildStatus(
export async function postBuildInit(
flow: FlowType
): Promise<AxiosResponse<InitTypeAPI>> {
return await axios.post(`/api/v1/build/init`, flow);
return await axios.post(`/api/v1/build/init/${flow.id}`, flow);
}
// fetch(`/upload/${id}`, {

View file

@ -0,0 +1,364 @@
/**
* Default description for the flow
* @constant
*/
export const DESCRIPTIONS: string[] = [
"Chain the Words, Master Language!",
"Language Architect at Work!",
"Empowering Language Engineering.",
"Craft Language Connections Here.",
"Create, Connect, Converse.",
"Smart Chains, Smarter Conversations.",
"Bridging Prompts for Brilliance.",
"Language Models, Unleashed.",
"Your Hub for Text Generation.",
"Promptly Ingenious!",
"Building Linguistic Labyrinths.",
"Create, Chain, Communicate.",
"Connect the Dots, Craft Language.",
"Interactive Language Weaving.",
"Generate, Innovate, Communicate.",
"Conversation Catalyst Engine.",
"Language Chainlink Master.",
"Design Dialogues with LangFlow.",
"Nurture NLP Nodes Here.",
"Conversational Cartography Unlocked.",
"Design, Develop, Dialogize.",
"Unleashing Linguistic Creativity.",
"Graph Your Way to Great Conversations.",
"The Power of Language at Your Fingertips.",
"Sculpting Language with Precision.",
"Where Language Meets Logic.",
"Building Intelligent Interactions.",
"Your Passport to Linguistic Landscapes.",
"Create, Curate, Communicate with LangFlow.",
"Flow into the Future of Language.",
"Mapping Meaningful Conversations.",
"Unravel the Art of Articulation.",
"Language Engineering Excellence.",
"Navigate the Networks of Conversation.",
"Crafting Conversations, One Node at a Time.",
"The Pinnacle of Prompt Generation.",
"Language Models, Mapped and Mastered.",
"Powerful Prompts, Perfectly Positioned.",
"Innovation in Interaction with LangFlow.",
"Your Toolkit for Text Generation.",
"Unfolding Linguistic Possibilities.",
"Building Powerful Solutions with Language Models.",
"Uncover Business Opportunities with NLP.",
"Harness the Power of Conversational AI.",
"Transform Your Business with Smart Dialogues.",
"Craft Meaningful Interactions, Generate Value.",
"Unleashing Business Potential through Language Engineering.",
"Empowering Enterprises with Intelligent Interactions.",
"Driving Innovation in Business Communication.",
"Catalyzing Business Growth through Conversational AI.",
"Text Generation Meets Business Transformation.",
"Navigate the Linguistic Landscape, Discover Opportunities.",
"Create Powerful Connections, Boost Business Value.",
"Empowering Communication, Enabling Opportunities.",
"Advanced NLP for Groundbreaking Business Solutions.",
"Innovation in Interaction, Revolution in Revenue.",
"Maximize Impact with Intelligent Conversations.",
"Beyond Text Generation - Unleashing Business Opportunities.",
"Unlock the Power of AI in Your Business Conversations.",
"Crafting Dialogues that Drive Business Success.",
"Engineered for Excellence, Built for Business.",
];
/**
* Adjectives for the name of the flow
* @constant
*
*/
export const ADJECTIVES: string[] = [
"admiring",
"adoring",
"agitated",
"amazing",
"angry",
"awesome",
"backstabbing",
"berserk",
"big",
"boring",
"clever",
"cocky",
"compassionate",
"condescending",
"cranky",
"desperate",
"determined",
"distracted",
"dreamy",
"drunk",
"ecstatic",
"elated",
"elegant",
"evil",
"fervent",
"focused",
"furious",
"gigantic",
"gloomy",
"goofy",
"grave",
"happy",
"high",
"hopeful",
"hungry",
"insane",
"jolly",
"jovial",
"kickass",
"lonely",
"loving",
"mad",
"modest",
"naughty",
"nauseous",
"nostalgic",
"pedantic",
"pensive",
"prickly",
"reverent",
"romantic",
"sad",
"serene",
"sharp",
"sick",
"silly",
"sleepy",
"small",
"stoic",
"stupefied",
"suspicious",
"tender",
"thirsty",
"tiny",
"trusting",
"bubbly",
"charming",
"cheerful",
"comical",
"dazzling",
"delighted",
"dynamic",
"effervescent",
"enthusiastic",
"exuberant",
"fluffy",
"friendly",
"funky",
"giddy",
"giggly",
"gleeful",
"goofy",
"graceful",
"grinning",
"hilarious",
"inquisitive",
"joyous",
"jubilant",
"lively",
"mirthful",
"mischievous",
"optimistic",
"peppy",
"perky",
"playful",
"quirky",
"radiant",
"sassy",
"silly",
"spirited",
"sprightly",
"twinkly",
"upbeat",
"vibrant",
"witty",
"zany",
"zealous",
];
/**
* Nouns for the name of the flow
* @constant
*
*/
export const NOUNS: string[] = [
"albattani",
"allen",
"almeida",
"archimedes",
"ardinghelli",
"aryabhata",
"austin",
"babbage",
"banach",
"bardeen",
"bartik",
"bassi",
"bell",
"bhabha",
"bhaskara",
"blackwell",
"bohr",
"booth",
"borg",
"bose",
"boyd",
"brahmagupta",
"brattain",
"brown",
"carson",
"chandrasekhar",
"colden",
"cori",
"cray",
"curie",
"darwin",
"davinci",
"dijkstra",
"dubinsky",
"easley",
"einstein",
"elion",
"engelbart",
"euclid",
"euler",
"fermat",
"fermi",
"feynman",
"franklin",
"galileo",
"gates",
"goldberg",
"goldstine",
"goldwasser",
"golick",
"goodall",
"hamilton",
"hawking",
"heisenberg",
"heyrovsky",
"hodgkin",
"hoover",
"hopper",
"hugle",
"hypatia",
"jang",
"jennings",
"jepsen",
"joliot",
"jones",
"kalam",
"kare",
"keller",
"khorana",
"kilby",
"kirch",
"knuth",
"kowalevski",
"lalande",
"lamarr",
"leakey",
"leavitt",
"lichterman",
"liskov",
"lovelace",
"lumiere",
"mahavira",
"mayer",
"mccarthy",
"mcclintock",
"mclean",
"mcnulty",
"meitner",
"meninsky",
"mestorf",
"minsky",
"mirzakhani",
"morse",
"murdock",
"newton",
"nobel",
"noether",
"northcutt",
"noyce",
"panini",
"pare",
"pasteur",
"payne",
"perlman",
"pike",
"poincare",
"poitras",
"ptolemy",
"raman",
"ramanujan",
"ride",
"ritchie",
"roentgen",
"rosalind",
"saha",
"sammet",
"shaw",
"shirley",
"shockley",
"sinoussi",
"snyder",
"spence",
"stallman",
"stonebraker",
"swanson",
"swartz",
"swirles",
"tesla",
"thompson",
"torvalds",
"turing",
"varahamihira",
"visvesvaraya",
"volhard",
"wescoff",
"williams",
"wilson",
"wing",
"wozniak",
"wright",
"yalow",
"yonath",
"coulomb",
"degrasse",
"dewey",
"edison",
"eratosthenes",
"faraday",
"galton",
"gauss",
"herschel",
"hubble",
"joule",
"kaku",
"kepler",
"khayyam",
"lavoisier",
"maxwell",
"mendel",
"mendeleev",
"ohm",
"pascal",
"planck",
"riemann",
"schrodinger",
"sagan",
"tesla",
"tyson",
"volta",
"watt",
"weber",
"wien",
"zoBell",
"zuse",
"carroll",
];

View file

@ -0,0 +1,9 @@
import React, { forwardRef } from "react";
import { ReactComponent as VertexAISVG } from "./vertex_ai.svg";
export const VertexAIIcon = forwardRef<
SVGSVGElement,
React.PropsWithChildren<{}>
>((props, ref) => {
return <VertexAISVG ref={ref} {...props} />;
});

View file

@ -0,0 +1 @@
<svg viewBox="0 0 32 32" fit="" height="100%" width="100%" preserveAspectRatio="xMidYMid meet" focusable="false"><path d="M26.69 18.53a1 1 0 00-1.4-.22L16 25.17v.29a1 1 0 110 1.91v.05a1 1 0 00.6-.19l9.88-7.3a1 1 0 00.21-1.4z" fill="#80868b"></path><path d="M16 27.37a1 1 0 110-1.91v-.29l-9.29-6.86a1 1 0 00-1.4.22 1 1 0 00.21 1.4l9.89 7.3a1 1 0 00.59.19v-.05z" fill="#9ba0a5"></path><path d="M16 24.46a2 2 0 102 2 2 2 0 00-2-2zm0 2.91a1 1 0 111-.95 1 1 0 01-1 .95z" fill="#606368"></path><path d="M8 8.14a1 1 0 01-1-1V4.63a1 1 0 112 0v2.51a1 1 0 01-1 1z" fill="#9ba0a5"></path><circle cx="7.97" cy="16" r="1.01" fill="#9ba0a5"></circle><circle cx="7.97" cy="13.05" r="1.01" fill="#9ba0a5"></circle><circle cx="7.97" cy="10.09" r="1.01" fill="#9ba0a5"></circle><path d="M24 11.07a1 1 0 01-1-1V7.55a1 1 0 012 0v2.52a1 1 0 01-1 1z" fill="#606368"></path><circle cx="24.03" cy="16.01" r="1.01" fill="#606368"></circle><circle cx="24.03" cy="13.02" r="1.01" fill="#606368"></circle><circle cx="24.03" cy="4.63" r="1.01" fill="#606368"></circle><path d="M16 20a1 1 0 01-1-1v-2.54a1 1 0 012 0V19a1 1 0 01-1 1z" fill="#80868b"></path><circle cx="16" cy="21.93" r="1.01" fill="#80868b"></circle><circle cx="16" cy="13.51" r="1.01" fill="#80868b"></circle><circle cx="16" cy="10.56" r="1.01" fill="#80868b"></circle><path d="M20 14.05a1 1 0 01-1-1v-2.51a1 1 0 112 0v2.51a1 1 0 01-1 1z" fill="#606368"></path><circle cx="20.02" cy="7.58" r="1.01" fill="#606368"></circle><circle cx="20.02" cy="18.92" r="1.01" fill="#606368"></circle><circle cx="20.02" cy="15.97" r="1.01" fill="#606368"></circle><circle cx="11.98" cy="18.92" r="1.01" fill="#9ba0a5"></circle><circle cx="11.98" cy="10.56" r="1.01" fill="#9ba0a5"></circle><circle cx="11.98" cy="7.58" r="1.01" fill="#9ba0a5"></circle><path d="M12 17a1 1 0 01-1-1v-2.54a1 1 0 012 0V16a1 1 0 01-1 1z" fill="#9ba0a5"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -2,73 +2,10 @@
@tailwind components;
@tailwind utilities;
/* TODO: Confirm that all colors here are found in tailwind config */
@layer base {
:root {
--background: 0 0% 100%; /* hsl(0 0% 100%) */
--foreground: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
--muted: 210 40% 96.1%; /* hsl(210 40% 96%) */
--muted-foreground: 215.4 16.3% 46.9%; /* hsl(215 16% 46%) */
--popover: 0 0% 100%; /* hsl(0 0% 100%) */
--popover-foreground: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
--card: 0 0% 100%; /* hsl(0 0% 100%) */
--card-foreground: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
--border: 214.3 31.8% 91.4%; /* hsl(214 32% 91%) */
--input: 214.3 31.8% 91.4%; /* hsl(214 32% 91%) */
--primary: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
--primary-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
--secondary: 210 40% 96.1%; /* hsl(210 40% 96%) */
--secondary-foreground: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
--accent: 210 40% 96.1%; /* hsl(210 40% 96%) */
--accent-foreground: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
--destructive: 0 100% 50%; /* hsl(0 100% 50%) */
--destructive-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
--ring: 215 20.2% 65.1%; /* hsl(215 20% 65%) */
--radius: 0.5rem;
}
.dark {
--background: 224 71% 4%; /* hsl(224 71% 4%) */
--foreground: 213 31% 91%; /* hsl(213 31% 91%) */
--muted: 223 47% 11%; /* hsl(223 47% 11%) */
--muted-foreground: 215.4 16.3% 56.9%; /* hsl(215 16% 56%) */
--popover: 224 71% 4%; /* hsl(224 71% 4%) */
--popover-foreground: 215 20.2% 65.1%; /* hsl(215 20% 65%) */
--card: 224 71% 4%; /* hsl(224 71% 4%) */
--card-foreground: 213 31% 91%; /* hsl(213 31% 91%) */
--border: 216 34% 17%; /* hsl(216 34% 17%) */
--input: 216 34% 17%; /* hsl(216 34% 17%) */
--primary: 210 40% 98%; /* hsl(210 40% 98%) */
--primary-foreground: 222.2 47.4% 1.2%; /* hsl(222 47% 1%) */
--secondary: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
--secondary-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
--accent: 216 34% 17%; /* hsl(216 34% 17%) */
--accent-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
--destructive: 0 63% 31%; /* hsl(0 63% 31%) */
--destructive-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
--ring: 216 34% 17%; /* hsl(216 34% 17%) */
--radius: 0.5rem;
}
}
:root {
--background: 0 0% 100%; /* hsl(0 0% 100%) */
@ -89,51 +26,91 @@
--accent-foreground: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
--destructive: 0 100% 50%; /* hsl(0 100% 50%) */
--destructive-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
--ring: 215 20.2% 65.1%; /* hsl(215 20% 65%) */
--radius: 0.5rem;
--ring: 215 20.2% 65.1%; /* hsl(215 20% 65%) */
--round-btn-shadow: #00000063;
--error-background: #fef2f2;
--error-foreground: #991b1b;
--success-background: #f0fdf4;
--success-foreground: #14532d;
--info-background: #f0f4fd;
--info-foreground: #141653;
--high-indigo: #4338ca;
--medium-indigo: #6366f1;
/* Colors that are shared in dark and light mode */
--blur-shared: #151923de;
--build-trigger: #dc735b;
--chat-trigger: #5c8be1;
--chat-trigger-disabled: #9db7e8;
--status-red: #ef4444;
--status-yellow: #eab308;
--status-green: #4ade80;
--status-blue:#2563eb;
}
.dark {
-background: 224 71% 4%;
/* hsl(224 71% 4%) */
-foreground: 213 31% 91%;
/* hsl(213 31% 91%) */
-muted: 223 47% 11%;
/* hsl(223 47% 11%) */
-muted-foreground: 215.4 16.3% 56.9%;
/* hsl(215 16% 56%) */
-popover: 224 71% 4%;
/* hsl(224 71% 4%) */
-popover-foreground: 215 20.2% 65.1%;
/* hsl(215 20% 65%) */
-card: 224 71% 4%;
/* hsl(224 71% 4%) */
-card-foreground: 213 31% 91%;
/* hsl(213 31% 91%) */
-border: 216 34% 17%;
/* hsl(216 34% 17%) */
-input: 216 34% 17%;
/* hsl(216 34% 17%) */
-primary: 210 40% 98%;
/* hsl(210 40% 98%) */
-primary-foreground: 222.2 47.4% 1.2%;
/* hsl(222 47% 1%) */
-secondary: 222.2 47.4% 11.2%;
/* hsl(222 47% 11%) */
-secondary-foreground: 210 40% 98%;
/* hsl(210 40% 98%) */
-accent: 216 34% 17%;
/* hsl(216 34% 17%) */
-accent-foreground: 210 40% 98%;
/* hsl(210 40% 98%) */
-destructive: 0 63% 31%;
/* hsl(0 63% 31%) */
-destructive-foreground: 210 40% 98%;
/* hsl(210 40% 98%) */
-ring: 216 34% 17%;
/* hsl(216 34% 17%) */
-radius: 0.5rem;
}
--background: 224 35% 7.5%; /* hsl(224 40% 10%) */
--foreground: 213 31% 85%; /* hsl(213 31% 91%) */
--muted: 223 27% 11%; /* hsl(223 27% 11%) */
--muted-foreground: 215.4 16.3% 56.9%; /* hsl(215 16% 56%) */
--popover: 224 71% 4%; /* hsl(224 71% 4%) */
--popover-foreground: 215 20.2% 65.1%; /* hsl(215 20% 65%) */
--card: 224 25% 15.5%; /* hsl(224 71% 4%) */
--card-foreground: 213 31% 80%; /* hsl(213 31% 91%) */
--border: 216 24% 17%; /* hsl(216 34% 17%) */
--input: 216 24% 17%; /* hsl(216 34% 17%) */
--primary: 210 20% 80%; /* hsl(210 40% 98%) */
--primary-foreground: 222.2 27.4% 1.2%; /* hsl(222 47% 1%) */
--secondary: 222.2 47.4% 11.2%; /* hsl(222 47% 11%) */
--secondary-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
--accent: 216 24% 17%; /* hsl(216 34% 17%) */
--accent-foreground: 210 30% 98%; /* hsl(210 40% 98%) */
--destructive: 0 63% 31%; /* hsl(0 63% 31%) */
--destructive-foreground: 210 40% 98%; /* hsl(210 40% 98%) */
--ring: 216 24% 30%; /* hsl(216 24% 30%) */
--radius: 0.5rem;
--round-btn-shadow: #00000063;
--success-background: #022c22;
--success-foreground: #ecfdf5;
--error-foreground: #fef2f2;
--error-background: #450a0a;
--info-foreground: #eff6ff;
--info-background: #172554;
--high-indigo: #4338ca;
--medium-indigo: #6366f1;
/* Colors that are shared in dark and light mode */
--blur-shared: #151923d2;
--build-trigger: #dc735b;
--chat-trigger: #5c8be1;
--chat-trigger-disabled: #2b4470;
--status-red: #ef4444;
--status-yellow: #eab308;
--status-green: #4ade80;
--status-blue: #2563eb;
}}
@layer base {
* {
@ -165,3 +142,25 @@ The cursor: default; property value restores the browser's default cursor style
.react-flow__pane {
cursor: default;
}
@layer components {
.input-primary:focus{
@apply focus:placeholder-transparent focus:ring-ring focus:border-ring
}
.input-primary {
@apply bg-background block border-ring form-input px-3 placeholder:text-muted-foreground rounded-md shadow-sm sm:text-sm truncate w-full;
}
.input-edit-node{
@apply input-primary placeholder:text-center pt-0.5 pb-0.5 text-center
}
.input-search{
@apply input-primary pr-7 mx-2
}
.input-disable{
@apply bg-input
}
.input-dialog{
@apply text-ring cursor-pointer bg-transparent
}
}

View file

@ -1,4 +1,4 @@
import { useContext, useState } from "react";
import { useContext, useEffect, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import "ace-builds/src-noconflict/mode-python";
import "ace-builds/src-noconflict/theme-github";
@ -26,14 +26,42 @@ import {
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 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 ShadTooltip from "../../components/ShadTooltipComponent";
import { cloneDeep, filter } from "lodash";
import { TabsContext } from "../../contexts/tabsContext";
export default function ApiModal({ flow }: { flow: FlowType }) {
const [open, setOpen] = useState(true);
const { dark } = useContext(darkContext);
const { closePopUp } = useContext(PopUpContext);
const { closePopUp, closeEdit, setCloseEdit } = useContext(PopUpContext);
const [activeTab, setActiveTab] = useState("0");
const [isCopied, setIsCopied] = useState<Boolean>(false);
const [enabled, setEnabled] = useState(null);
const [openAccordion, setOpenAccordion] = useState([]);
const tweak = useRef([]);
const tweaksList = useRef([]);
const { setTweak, getTweak } = useContext(TabsContext);
const copyToClipboard = () => {
if (!navigator.clipboard || !navigator.clipboard.writeText) {
return;
@ -47,18 +75,10 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
}, 2000);
});
};
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
closePopUp();
}
}
const pythonApiCode = getPythonApiCode(flow);
const curl_code = getCurlCode(flow);
const pythonCode = getPythonCode(flow);
const pythonApiCode = getPythonApiCode(flow, tweak.current);
const curl_code = getCurlCode(flow, tweak.current);
const pythonCode = getPythonCode(flow, tweak.current);
const tweaksCode = buildTweaks(flow);
const tabs = [
{
name: "cURL",
@ -80,10 +100,170 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
code: pythonCode,
},
];
useEffect(() => {
if (closeEdit !== "") {
tweak.current = getTweak;
if(tweak.current.length > 0){
setActiveTab("3");
openAccordions();
}
else{
startTweaks();
}
} else {
startTweaks();
}
}, [closeEdit]);
useEffect(() => {
filterNodes();
}, []);
if (Object.keys(tweaksCode).length > 0) {
tabs.push({
name: "Tweaks",
mode: "python",
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
code: pythonCode,
});
}
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setCloseEdit("");
setTweak([]);
closePopUp();
}
}
function startTweaks() {
tweak?.current?.push(buildTweaks(flow));
}
function filterNodes() {
let arrNodesWithValues = [];
flow["data"]["nodes"].forEach((t) => {
Object.keys(t["data"]["node"]["template"])
.filter(
(n) =>
n.charAt(0) !== "_" &&
t.data.node.template[n].show &&
(t.data.node.template[n].type === "str" ||
t.data.node.template[n].type === "bool" ||
t.data.node.template[n].type === "float" ||
t.data.node.template[n].type === "code" ||
t.data.node.template[n].type === "prompt" ||
t.data.node.template[n].type === "file" ||
t.data.node.template[n].type === "int")
)
.map((n, i) => {
arrNodesWithValues.push(t["id"]);
});
});
tweaksList.current = arrNodesWithValues.filter((value, index, self) => {
return self.indexOf(value) === index;
});
}
function buildTweakObject(tw, changes, template) {
if (template.type === "float") {
changes = parseFloat(changes);
}
if (template.type === "int") {
changes = parseInt(changes);
}
if (template.list === true && Array.isArray(changes)) {
changes = changes?.filter((x) => x !== "");
}
const existingTweak = tweak.current.find((element) =>
element.hasOwnProperty(tw)
);
if (existingTweak) {
existingTweak[tw][template["name"]] = changes;
if (existingTweak[tw][template["name"]] == template.value) {
tweak.current.forEach((element) => {
if (element[tw] && Object.keys(element[tw])?.length === 0) {
tweak.current = tweak.current.filter((obj) => {
const prop = obj[Object.keys(obj)[0]].prop;
return prop !== undefined && prop !== null && prop !== "";
});
}
});
}
} else {
const newTweak = {
[tw]: {
[template["name"]]: changes,
},
};
tweak.current.push(newTweak);
}
const pythonApiCode = getPythonApiCode(flow, tweak.current);
const curl_code = getCurlCode(flow, tweak.current);
const pythonCode = getPythonCode(flow, tweak.current);
tabs[0].code = curl_code;
tabs[1].code = pythonApiCode;
tabs[2].code = pythonCode;
setTweak(tweak.current);
}
function buildContent(value) {
const htmlContent = (
<div className="w-[200px]">
<span>{value != null && value != "" ? value : "None"}</span>
</div>
);
return htmlContent;
}
function getValue(value, node, template) {
let returnValue = value ?? "";
if (getTweak.length > 0) {
for (const obj of getTweak) {
Object.keys(obj).forEach((key) => {
const value = obj[key];
if (key == node["id"]) {
Object.keys(value).forEach((key) => {
if (key == template["name"]) {
returnValue = value[key];
}
});
}
});
}
} else {
return value ?? "";
}
return returnValue;
}
function openAccordions() {
let accordionsToOpen = [];
tweak.current.forEach((el) => {
Object.keys(el).forEach((key) => {
if (Object.keys(el[key]).length > 0) {
accordionsToOpen.push(key);
setOpenAccordion(accordionsToOpen);
}
});
});
}
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger></DialogTrigger>
<DialogContent className="lg:max-w-[800px] sm:max-w-[600px] h-[580px]">
<DialogContent className="lg:max-w-[80vw] h-[80vh]">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Code</span>
@ -96,39 +276,482 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
</DialogHeader>
<Tabs
defaultValue={"0"}
value={activeTab}
className="w-full h-full overflow-hidden text-center bg-muted rounded-md border"
onValueChange={(value) => setActiveTab(value)}
onValueChange={(value) => {
setActiveTab(value);
if (value === "3") {
openAccordions();
}
}}
>
<div className="flex items-center justify-between px-2">
<TabsList>
{tabs.map((tab, index) => (
<TabsTrigger key={index} value={index.toString()}>{tab.name}</TabsTrigger>
<TabsTrigger key={index} value={index.toString()}>
{tab.name}
</TabsTrigger>
))}
</TabsList>
<div className="float-right">
<button
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-500 dark:text-gray-300"
onClick={copyToClipboard}
>
{isCopied ? <Check size={18} /> : <Clipboard size={15} />}
{isCopied ? "Copied!" : "Copy code"}
</button>
</div>
{Number(activeTab) < 3 && (
<div className="float-right">
<button
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-500 dark:text-gray-300"
onClick={copyToClipboard}
>
{isCopied ? <Check size={18} /> : <Clipboard size={15} />}
{isCopied ? "Copied!" : "Copy code"}
</button>
</div>
)}
</div>
{tabs.map((tab, index) => (
<TabsContent
value={index.toString()}
className="overflow-hidden w-full h-full px-4 pb-4 -mt-1"
key={index} // Remember to add a unique key prop
>
<SyntaxHighlighter
className="h-[400px] w-full overflow-auto"
language={tab.mode}
style={oneDark}
>
{tab.code}
</SyntaxHighlighter>
{index < 3 ? (
<SyntaxHighlighter
className="w-full overflow-auto h-[60vh]"
language={tab.mode}
style={oneDark}
>
{tab.code}
</SyntaxHighlighter>
) : index === 3 ? (
<>
<div className="flex w-full h-full mt-2">
<div
className={classNames(
"w-full rounded-lg bg-muted h-[60vh]",
1 == 1
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
)}
>
{flow["data"]["nodes"].map((t: any, index) => (
<div className="px-3" key={index}>
{tweaksList.current.includes(t["data"]["id"]) && (
<AccordionComponent
trigger={t["data"]["id"]}
open={openAccordion}
>
<div className="flex flex-col gap-5 h-fit">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="border-input text-xs font-medium text-ring h-10">
<TableRow className="dark:border-b-muted">
<TableHead className="h-7 text-center">
PARAM
</TableHead>
<TableHead className="p-0 h-7 text-center">
VALUE
</TableHead>
</TableRow>
</TableHeader>
<TableBody className="p-0">
{Object.keys(t["data"]["node"]["template"])
.filter(
(n) =>
n.charAt(0) !== "_" &&
t.data.node.template[n].show &&
(t.data.node.template[n].type ===
"str" ||
t.data.node.template[n].type ===
"bool" ||
t.data.node.template[n].type ===
"float" ||
t.data.node.template[n].type ===
"code" ||
t.data.node.template[n].type ===
"prompt" ||
t.data.node.template[n].type ===
"file" ||
t.data.node.template[n].type ===
"int")
)
.map((n, i) => {
//console.log(t.data.node.template[n]);
return (
<TableRow
key={i}
className="h-10 dark:border-b-muted"
>
<TableCell className="p-0 text-center text-gray-900 text-sm">
{n}
</TableCell>
<TableCell className="p-0 text-center text-gray-900 text-xs dark:text-gray-300">
<div className="w-[250px] m-auto">
{t.data.node.template[n]
.type === "str" &&
!t.data.node.template[n]
.options ? (
<div className="mx-auto">
{t.data.node.template[n]
.list ? (
<InputListComponent
editNode={true}
disabled={false}
value={
!t.data.node.template[
n
].value ||
t.data.node.template[
n
].value === ""
? [""]
: t.data.node
.template[n]
.value
}
onChange={(k) => {}}
onAddInput={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node
.template[n]
);
}}
/>
) : t.data.node.template[n]
.multiline ? (
<ShadTooltip
delayDuration={1000}
content={buildContent(
t.data.node.template[
n
].value
)}
>
<div>
<TextAreaComponent
disabled={false}
editNode={true}
value={getValue(
t.data.node
.template[n]
.value,
t.data,
t.data.node
.template[n]
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node
.template[n]
);
}}
/>
</div>
</ShadTooltip>
) : (
<InputComponent
editNode={true}
disabled={false}
password={
t.data.node.template[
n
].password ?? false
}
value={getValue(
t.data.node.template[
n
].value,
t.data,
t.data.node.template[
n
]
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node
.template[n]
);
}}
/>
)}
</div>
) : t.data.node.template[n]
.type === "bool" ? (
<div className="ml-auto">
{" "}
<ToggleShadComponent
enabled={
t.data.node.template[n]
.value
}
setEnabled={(e) => {
t.data.node.template[
n
].value = e;
setEnabled(e);
buildTweakObject(
t["data"]["id"],
e,
t.data.node.template[
n
]
);
}}
size="small"
disabled={false}
/>
</div>
) : t.data.node.template[n]
.type === "file" ? (
<ShadTooltip
delayDuration={1000}
content={buildContent(
getValue(
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
)
)}
>
<div className="mx-auto">
<InputFileComponent
editNode={true}
disabled={false}
value={
t.data.node.template[
n
].value ?? ""
}
onChange={(
k: any
) => {}}
fileTypes={
t.data.node.template[
n
].fileTypes
}
suffixes={
t.data.node.template[
n
].suffixes
}
onFileChange={(
k: any
) => {}}
></InputFileComponent>
</div>
</ShadTooltip>
) : t.data.node.template[n]
.type === "float" ? (
<div className="mx-auto">
<FloatComponent
disabled={false}
editNode={true}
value={getValue(
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node.template[
n
]
);
}}
/>
</div>
) : t.data.node.template[n]
.type === "str" &&
t.data.node.template[n]
.options ? (
<div className="mx-auto">
<Dropdown
editNode={true}
apiModal={true}
options={
t.data.node.template[n]
.options
}
onSelect={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node.template[
n
]
);
}}
value={getValue(
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
)}
></Dropdown>
</div>
) : t.data.node.template[n]
.type === "int" ? (
<div className="mx-auto">
<IntComponent
disabled={false}
editNode={true}
value={getValue(
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node.template[
n
]
);
}}
/>
</div>
) : t.data.node.template[n]
.type === "prompt" ? (
<ShadTooltip
delayDuration={1000}
content={buildContent(
getValue(
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
)
)}
>
<div className="mx-auto">
<PromptAreaComponent
editNode={true}
disabled={false}
value={getValue(
t.data.node.template[
n
].value,
t.data,
t.data.node.template[
n
]
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node
.template[n]
);
}}
/>
</div>
</ShadTooltip>
) : t.data.node.template[n]
.type === "code" ? (
<ShadTooltip
delayDuration={1000}
content={buildContent(
getValue(
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
)
)}
>
<div className="mx-auto">
<CodeAreaComponent
disabled={false}
editNode={true}
value={getValue(
t.data.node.template[
n
].value,
t.data,
t.data.node.template[
n
]
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node
.template[n]
);
}}
/>
</div>
</ShadTooltip>
) : t.data.node.template[n]
.type === "Any" ? (
"-"
) : (
<div className="hidden"></div>
)}
</div>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
</AccordionComponent>
)}
{tweaksList.current.length === 0 && (
<>
<div className="pt-3">
No tweaks are available for this flow.
</div>
</>
)}
</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">
<TableRow className="dark:border-b-muted">
<TableHead className="h-5 text-center">
TWEAK
</TableHead>
<TableHead className="p-0 h-5 text-center">
VALUE
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{invoices.map((invoice) => (
<TableRow className="p-0 text-center text-gray-900 text-sm">
<TableCell className="p-2 text-center text-gray-900 text-sm truncate">
{invoice.paymentStatus}
</TableCell>
<TableCell className="p-2 text-center text-gray-900 text-sm truncate">
{invoice.paymentMethod}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div> */}
</div>
</div>
</>
) : null}
</TabsContent>
))}
</Tabs>

View file

@ -79,9 +79,9 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
}
return (
<Dialog open={true} onOpenChange={setModalOpen} >
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger asChild></DialogTrigger>
<DialogContent className="lg:max-w-[700px] ">
<DialogContent className="sm:max-w-[600px] lg:max-w-[700px]">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">{data.type}</span>
@ -89,34 +89,34 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
</DialogTitle>
<DialogDescription>
{data.node?.description}
<div className="flex pt-4">
<Variable className="w-5 h-5 pe-1 text-gray-700 stroke-2 dark:text-slate-200"></Variable>
<span className="text-sm font-semibold text-gray-800 dark:text-white">
<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>
</div>
</DialogDescription>
</DialogHeader>
<div className="flex w-full max-h-[350px] h-fit">
<div className="flex h-fit max-h-[400px] w-full">
<div
className={classNames(
"w-full rounded-lg bg-white dark:bg-gray-800 border-[1px] border-gray-200",
"w-full rounded-lg border-[1px] border-input bg-background",
nodeLength > limitScrollFieldsModal
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
)}
>
{nodeLength > 0 && (
<div className="flex flex-col gap-5 h-fit">
<div className="flex h-fit flex-col gap-5">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="border-gray-200 text-gray-500 text-xs font-medium h-10">
<TableRow className="dark:border-b-muted">
<TableHeader className="h-10 border-input text-xs font-medium text-ring">
<TableRow className="">
<TableHead className="h-7 text-center">PARAM</TableHead>
<TableHead className="p-0 h-7 text-center">
<TableHead className="h-7 p-0 text-center">
VALUE
</TableHead>
<TableHead className="text-center h-7">SHOW</TableHead>
<TableHead className="h-7 text-center">SHOW</TableHead>
</TableRow>
</TableHeader>
<TableBody className="p-0">
@ -134,13 +134,13 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
data.node.template[t].type === "int")
)
.map((n, i) => (
<TableRow key={i} className="h-10 dark:border-b-muted">
<TableCell className="p-0 text-center text-gray-900 dark:text-gray-300 text-sm">
<TableRow key={i} className="h-10">
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
{data.node.template[n].name
? data.node.template[n].name
: data.node.template[n].display_name}
</TableCell>
<TableCell className="p-0 text-center text-gray-900 text-xs w-[300px] dark:text-gray-300">
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
{data.node.template[n].type === "str" &&
!data.node.template[n].options ? (
<div className="mx-auto">
@ -251,6 +251,7 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
) : data.node.template[n].type === "prompt" ? (
<div className="mx-auto">
<PromptAreaComponent
field_name={n}
editNode={true}
disabled={false}
value={data.node.template[n].value ?? ""}

View file

@ -1,5 +1,4 @@
import { useContext, useState } from "react";
import { TabsContext } from "../../../../contexts/tabsContext";
import { useState } from "react";
import InputListComponent from "../../../../components/inputListComponent";
import Dropdown from "../../../../components/dropdownComponent";
import TextAreaComponent from "../../../../components/textAreaComponent";
@ -36,7 +35,7 @@ export default function ModalField({
return (
<div
className={classNames(
"flex flex-row w-full items-center justify-between",
"flex w-full flex-row items-center justify-between",
display ? "" : "hidden",
Object.keys(data.node.template).filter(
(t) =>
@ -52,8 +51,8 @@ export default function ModalField({
>
{display && (
<div>
<span className="mx-2 dark:text-gray-300">{title}</span>
<span className="text-red-600">{required ? " *" : ""}</span>
<span className="mx-2">{title}</span>
<span className="text-destructive">{required ? " *" : ""}</span>
</div>
)}
@ -150,6 +149,7 @@ export default function ModalField({
) : type === "prompt" ? (
<div className="w-1/2">
<PromptAreaComponent
field_name={name}
disabled={false}
value={data.node.template[name].value ?? ""}
onChange={(t: string) => {

View file

@ -6,8 +6,7 @@ import {
classNames,
limitScrollFieldsModal,
nodeColors,
nodeIcons,
toNormalCase,
nodeIconsLucide,
toTitleCase,
} from "../../utils";
import { typesContext } from "../../contexts/typesContext";
@ -28,7 +27,7 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
}
}
// any to avoid type conflict
const Icon: any = nodeIcons[types[data.type]];
const Icon: any = nodeIconsLucide[types[data.type]];
return (
<Transition.Root show={open} appear={true} as={Fragment}>
<Dialog
@ -46,7 +45,7 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-500 dark:bg-gray-600 dark:bg-opacity-75 bg-opacity-75 transition-opacity" />
<div className="fixed inset-0 bg-ring bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
@ -60,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 flex-col justify-between transform h-[600px] overflow-hidden rounded-lg bg-white dark:bg-gray-800 text-left shadow-xl transition-all sm:my-8 w-[700px]">
<div className=" z-50 absolute top-0 right-0 hidden pt-4 pr-4 sm:block">
<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">
<button
type="button"
className="rounded-md text-gray-400 hover:text-gray-500"
className="rounded-md text-ring hover:text-accent-foreground"
onClick={() => {
setModalOpen(false);
}}
@ -73,10 +72,11 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
<X className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="h-full w-full flex flex-col justify-center items-center">
<div className="flex w-full pb-4 z-10 justify-center shadow-sm">
<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">
<Icon
className="w-10 mt-4 h-10 p-1 rounded"
strokeWidth={1.5}
className="mt-4 h-10 w-10 rounded p-1"
style={{
color:
nodeColors[types[data.type]] ?? nodeColors.unknown,
@ -85,17 +85,17 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
<div className="mt-4 text-center sm:ml-4 sm:text-left">
<Dialog.Title
as="h3"
className="text-lg font-medium dark:text-white leading-10 text-gray-900"
className="text-lg font-medium leading-10 text-foreground"
>
{data.type}
</Dialog.Title>
</div>
</div>
<div className="h-full w-full bg-gray-200 dark:bg-gray-900 p-4 gap-4 flex flex-row justify-center items-center">
<div className="flex w-full h-[445px]">
<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={classNames(
"px-4 sm:p-4 w-full rounded-lg bg-white dark:bg-gray-800 shadow",
"w-full rounded-lg bg-background px-4 shadow sm:p-4",
Object.keys(data.node.template).filter(
(t) =>
t.charAt(0) !== "_" &&
@ -106,7 +106,7 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
: "overflow-hidden"
)}
>
<div className="flex flex-col h-full gap-5">
<div className="flex h-full flex-col gap-5">
{Object.keys(data.node.template)
.filter(
(t) =>
@ -144,10 +144,10 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
</div>
</div>
</div>
<div className="bg-gray-200 dark:bg-gray-900 w-full pb-3 flex flex-row-reverse px-4">
<div className="flex w-full flex-row-reverse bg-input px-4 pb-3">
<button
type="button"
className="inline-flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:ring-offset-1 sm:ml-3 sm:w-auto sm:text-sm"
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"
onClick={() => {
setModalOpen(false);
}}

View file

@ -48,14 +48,15 @@ export default function CodeAreaModal({
const [loading, setLoading] = useState(false);
const { dark } = useContext(darkContext);
const { setErrorData, setSuccessData } = useContext(alertContext);
const { closePopUp } = useContext(PopUpContext);
const [activeTab, setActiveTab] = useState("0");
const [error, setError] = useState<{ detail: { error: string, traceback: string } }>(null)
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
const ref = useRef();
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
setCloseEdit("editcode");
closePopUp();
}, 300);
}
@ -128,12 +129,13 @@ export default function CodeAreaModal({
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger></DialogTrigger>
<DialogContent className="lg:max-w-[700px] h-[500px]">
<DialogContent className="h-[500px] lg:max-w-[700px]">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Edit Code</span>
<TerminalSquare
className="h-6 w-6 text-gray-800 pl-1 dark:text-white"
strokeWidth={1.5}
className="h-6 w-6 text-primary pl-1 "
aria-hidden="true"
/>
</DialogTitle>
@ -181,9 +183,6 @@ export default function CodeAreaModal({
}
</div>
</Tabs>
<DialogFooter>
<Button className="mt-3" onClick={handleClick} type="submit">
{/* {loading?(<Loading/>):'Check & Save'} */}

View file

@ -23,7 +23,8 @@ export default function ExportModal() {
const { closePopUp } = useContext(PopUpContext);
const ref = useRef();
const { setErrorData } = useContext(alertContext);
const { flows, tabId, updateFlow, downloadFlow } = useContext(TabsContext);
const { flows, tabId, updateFlow, downloadFlow, saveFlow } =
useContext(TabsContext);
const [isMaxLength, setIsMaxLength] = useState(false);
function setModalOpen(x: boolean) {
setOpen(x);
@ -41,12 +42,13 @@ export default function ExportModal() {
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger asChild></DialogTrigger>
<DialogContent className="lg:max-w-[600px] h-[420px] ">
<DialogContent className="h-[420px] lg:max-w-[600px] ">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Export</span>
<Download
className="h-6 w-6 text-gray-800 pl-1 dark:text-white"
strokeWidth={1.5}
className="h-6 w-6 text-foreground pl-1"
aria-hidden="true"
/>
</DialogTitle>
@ -80,9 +82,18 @@ export default function ExportModal() {
<DialogFooter>
<Button
onClick={() => {
if (checked) downloadFlow(flows.find((f) => f.id === tabId));
if (checked)
downloadFlow(
flows.find((f) => f.id === tabId),
name,
description
);
else
downloadFlow(removeApiKeys(flows.find((f) => f.id === tabId)));
downloadFlow(
removeApiKeys(flows.find((f) => f.id === tabId)),
name,
description
);
closePopUp();
}}

View file

@ -48,11 +48,11 @@ export default function FlowSettingsModal() {
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger asChild></DialogTrigger>
<DialogContent className="lg:max-w-[600px] h-[390px]">
<DialogContent className="h-[390px] lg:max-w-[600px]">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Settings </span>
<Settings2 className="w-4 h-4 mr-2 dark:text-gray-300" />
<Settings2 className="mr-2 h-4 w-4 " />
</DialogTitle>
<DialogDescription>{SETTINGS_DIALOG_SUBTITLE}</DialogDescription>
</DialogHeader>

View file

@ -1,7 +1,6 @@
import { classNames } from "../../../utils";
import { useContext, useEffect, useRef, useState } from "react";
import { TabsContext } from "../../../contexts/tabsContext";
import { INPUT_STYLE } from "../../../constants";
import { Eraser, Lock, LucideSend, Send } from "lucide-react";
export default function ChatInput({
@ -53,8 +52,7 @@ export default function ChatInput({
lockChat
? " bg-input text-black dark:bg-gray-700 dark:text-gray-300"
: " bg-white-200 text-black dark:bg-gray-900 dark:text-gray-300",
"p-4 form-input block w-full custom-scroll rounded-md border-gray-300 dark:border-gray-600 pr-16 sm:text-sm" +
INPUT_STYLE
"p-4 form-input block w-full custom-scroll rounded-md border-gray-300 dark:border-gray-600 pr-16 sm:text-sm"
)}
placeholder={"Send a message..."}
/>

View file

@ -48,19 +48,19 @@ export const CodeBlock: FC<Props> = memo(({ language, value }) => {
};
return (
<div className="codeblock font-sans text-[16px]">
<div className="flex items-center justify-between py-1.5 px-4">
<span className="text-xs lowercase text-white">{language}</span>
<div className="flex items-center justify-between px-4 py-1.5">
<span className="text-xs lowercase text-background">{language}</span>
<div className="flex items-center">
<button
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-white"
className="flex items-center gap-1.5 rounded bg-none p-1 text-xs text-background"
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-white"
className="flex items-center rounded bg-none p-1 text-xs text-background"
onClick={downloadAsFile}
>
<IconDownload size={18} />

View file

@ -26,24 +26,21 @@ export default function FileCard({ fileName, content, fileType }) {
if (fileType === "image") {
return (
<div
className="relative w-1/4 h-1/4"
className="relative h-1/4 w-1/4"
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<img
src={`data:image/png;base64,${content}`}
alt="generated image"
className="rounded-lg w-full h-full"
className="h-full w-full rounded-lg"
/>
{isHovered && (
<div
className={`absolute top-0 right-0 bg-muted text-gray-700 rounded-bl-lg px-1 text-sm font-bold dark:bg-gray-700 dark:text-gray-300`}
className={`absolute right-0 top-0 rounded-bl-lg bg-muted px-1 text-sm font-bold text-foreground `}
>
<button
className="text-gray-500 py-1 px-2 dark:bg-gray-700 dark:text-gray-300"
onClick={handleDownload}
>
<DownloadCloud className="hover:scale-110 w-5 h-5 text-current" />
<button className="px-2 py-1 text-ring " onClick={handleDownload}>
<DownloadCloud className="h-5 w-5 text-current hover:scale-110" />
</button>
</div>
)}
@ -54,25 +51,25 @@ export default function FileCard({ fileName, content, fileType }) {
return (
<button
onClick={handleDownload}
className="bg-muted shadow rounded w-1/2 text-gray-700 hover:drop-shadow-lg px-2 py-2 flex justify-between items-center border border-gray-300"
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="flex gap-2 text-current items-center w-full mr-2">
<div className="mr-2 flex w-full items-center gap-2 text-current">
{" "}
{fileType === "image" ? (
<img
src={`data:image/png;base64,${content}`}
alt=""
className="w-8 h-8"
className="h-8 w-8"
/>
) : (
<File className="w-8 h-8" />
<File className="h-8 w-8" />
)}
<div className="flex flex-col items-start">
{" "}
<div className="truncate text-sm text-current">{fileName}</div>
<div className="truncate text-xs text-gray-500">{fileType}</div>
<div className="truncate text-xs text-ring">{fileType}</div>
</div>
<DownloadCloud className="w-6 h-6 text-current ml-auto" />
<DownloadCloud className="ml-auto h-6 w-6 text-current" />
</div>
</button>
);

View file

@ -4,13 +4,7 @@ import { alertContext } from "../../contexts/alertContext";
import { classNames, validateNodes } from "../../utils";
import { typesContext } from "../../contexts/typesContext";
import ChatMessage from "./chatMessage";
import {
TerminalSquare,
MessageSquare,
Variable,
Eraser,
MessageSquarePlus,
} from "lucide-react";
import { TerminalSquare, MessageSquare, Variable, Eraser } from "lucide-react";
import { sendAllProps } from "../../types/api";
import { ChatMessageType } from "../../types/chat";
import ChatInput from "./chatInput";
@ -25,7 +19,6 @@ import {
DialogTrigger,
} from "../../components/ui/dialog";
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants";
import { Label } from "../../components/ui/label";
import { TabsContext } from "../../contexts/tabsContext";
import {
Accordion,
@ -36,14 +29,6 @@ import {
import { Textarea } from "../../components/ui/textarea";
import { Badge } from "../../components/ui/badge";
import ToggleShadComponent from "../../components/toggleShadComponent";
import Dropdown from "../../components/dropdownComponent";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "../../components/ui/dropdown-menu";
import { Button } from "../../components/ui/button";
export default function FormModal({
flow,
@ -55,13 +40,27 @@ export default function FormModal({
flow: FlowType;
}) {
const { tabsState, setTabsState } = useContext(TabsContext);
const [chatValue, setChatValue] = useState(
tabsState[flow.id].formKeysData.input_keys[
Object.keys(tabsState[flow.id].formKeysData.input_keys).find(
(k) => !tabsState[flow.id].formKeysData.handle_keys.some((j) => j === k)
)
]
);
const [chatValue, setChatValue] = useState(() => {
try {
const { formKeysData } = tabsState[flow.id];
if (!formKeysData) {
throw new Error("formKeysData is undefined");
}
const inputKeys = formKeysData.input_keys;
const handleKeys = formKeysData.handle_keys;
const keyToUse = Object.keys(inputKeys).find(
(k) => !handleKeys.some((j) => j === k)
);
return inputKeys[keyToUse];
} catch (error) {
console.error(error);
// return a sensible default or `undefined` if no default is possible
return undefined;
}
});
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
const { reactFlowInstance } = useContext(typesContext);
const { setErrorData, setNoticeData } = useContext(alertContext);
@ -397,24 +396,27 @@ export default function FormModal({
<DialogTitle className="flex items-center">
<span className="pr-2">Chat</span>
<TerminalSquare
className="h-6 w-6 text-gray-800 pl-1 dark:text-white"
className="h-6 w-6 pl-1 text-gray-800 dark:text-white"
aria-hidden="true"
/>
</DialogTitle>
<DialogDescription>{CHAT_FORM_DIALOG_SUBTITLE}</DialogDescription>
</DialogHeader>
<div className="flex h-[80vh] w-full mt-2 ">
<div className="w-2/5 h-full overflow-auto scrollbar-hide flex flex-col justify-start mr-6">
<div className="flex justify-between items-center">
<div className="flex py-2 items-center">
<Variable className="w-4 h-4 mr-1 text-primary"></Variable>
<span className="text-sm font-semibold text-primary">
Input Variables
</span>
<div className="mt-2 flex h-[80vh] w-full ">
<div className="mr-6 flex h-full w-2/5 flex-col justify-start overflow-auto scrollbar-hide">
<div className="flex items-center py-2">
<Variable className=" -ml-px mr-1 h-4 w-4 text-primary"></Variable>
<span className="text-md font-semibold text-primary">
Input Variables
</span>
</div>
<div className="flex items-center justify-between pt-2">
<div className="mr-2.5 flex items-center">
<span className="text-sm font-medium text-primary">Name</span>
</div>
<div className="flex mr-2.5 py-2 items-center">
<span className="text-sm font-semibold text-primary">
<div className="mr-2.5 flex items-center">
<span className="text-sm font-medium text-primary">
Chat Input
</span>
</div>
@ -425,7 +427,7 @@ export default function FormModal({
<div className="flex items-start gap-3" key={k}>
<AccordionItem className="w-full" key={k} value={i}>
<AccordionTrigger className="flex gap-2">
<div className="flex items-center w-full justify-between">
<div className="flex w-full items-center justify-between">
<Badge variant="gray" size="md">
{i}
</Badge>
@ -450,7 +452,7 @@ export default function FormModal({
</div>
</AccordionTrigger>
<AccordionContent>
<div className="p-1 flex flex-col gap-2">
<div className="flex flex-col gap-2 p-1">
{tabsState[
id.current
].formKeysData.handle_keys.some((t) => t === i) && (
@ -482,7 +484,7 @@ export default function FormModal({
)}
{tabsState[id.current].formKeysData.memory_keys.map((i, k) => (
<AccordionItem key={k} value={i}>
<div className="flex flex-1 items-center justify-between py-4 font-normal transition-all group text-muted-foreground text-sm">
<div className="group flex flex-1 items-center justify-between py-4 text-sm font-normal text-muted-foreground transition-all">
<div className="group-hover:underline">
<Badge size="md" variant="gray">
{i}
@ -495,14 +497,14 @@ export default function FormModal({
</Accordion>
</div>
<div className="w-full">
<div className="flex flex-col rounded-md border bg-muted w-full h-full relative">
<div className="relative flex h-full w-full flex-col rounded-md border bg-muted">
<div className="absolute right-3 top-3 z-50">
<button disabled={lockChat} onClick={() => clearChat()}>
<Eraser
className={classNames(
"h-5 w-5",
lockChat
? "text-primary animate-pulse"
? "animate-pulse text-primary"
: "text-primary hover:text-gray-600"
)}
aria-hidden="true"
@ -511,7 +513,7 @@ export default function FormModal({
</div>
<div
ref={messagesRef}
className="w-full h-full flex-col flex items-center overflow-scroll scrollbar-hide"
className="flex h-full w-full flex-col items-center overflow-scroll scrollbar-hide"
>
{chatHistory.length > 0 ? (
chatHistory.map((c, i) => (
@ -523,19 +525,19 @@ export default function FormModal({
/>
))
) : (
<div className="flex flex-col h-full text-center justify-center w-full items-center align-middle">
<div className="flex h-full w-full flex-col items-center justify-center text-center align-middle">
<span>
👋{" "}
<span className="text-gray-600 dark:text-gray-300 text-lg">
<span className="text-lg text-gray-600 dark:text-gray-300">
LangFlow Chat
</span>
</span>
<br />
<div className="bg-muted dark:bg-gray-900 rounded-md w-2/4 px-6 py-8 border border-gray-200 dark:border-gray-700">
<div className="w-2/4 rounded-md border border-gray-200 bg-muted px-6 py-8 dark:border-gray-700 dark:bg-gray-900">
<span className="text-base text-gray-500">
Start a conversation and click the agent's thoughts{" "}
<span>
<MessageSquare className="w-5 h-5 inline animate-bounce mx-1 " />
<MessageSquare className="mx-1 inline h-5 w-5 animate-bounce " />
</span>{" "}
to inspect the chaining process.
</span>
@ -544,7 +546,7 @@ export default function FormModal({
)}
<div ref={ref}></div>
</div>
<div className="w-full px-8 pb-6 flex-col flex items-center justify-between">
<div className="flex w-full flex-col items-center justify-between px-8 pb-6">
<div className="relative w-full rounded-md shadow-sm">
<ChatInput
chatValue={chatValue}
@ -556,7 +558,7 @@ export default function FormModal({
let newTabsState = _.cloneDeep(old);
newTabsState[id.current].formKeysData.input_keys[
chatKey
] = chatValue;
] = value;
return newTabsState;
});
}}

View file

@ -19,6 +19,7 @@ import { FileText } from "lucide-react";
import { APIClassType } from "../../types/api";
export default function GenericModal({
field_name = "",
value,
setValue,
buttonText,
@ -27,6 +28,7 @@ export default function GenericModal({
nodeClass,
setNodeClass,
}: {
field_name?: string;
setValue: (value: string) => void;
value: string;
buttonText: string;
@ -42,11 +44,12 @@ export default function GenericModal({
const [myValue, setMyValue] = useState(value);
const { dark } = useContext(darkContext);
const { setErrorData, setSuccessData } = useContext(alertContext);
const { closePopUp } = useContext(PopUpContext);
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
const ref = useRef();
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setCloseEdit("generic");
closePopUp();
}
}
@ -59,7 +62,8 @@ export default function GenericModal({
<DialogTitle className="flex items-center">
<span className="pr-2">{myModalTitle}</span>
<FileText
className="h-6 w-6 text-gray-800 pl-1 dark:text-white"
strokeWidth={1.5}
className="h-6 w-6 pl-1 text-primary "
aria-hidden="true"
/>
</DialogTitle>
@ -79,10 +83,10 @@ export default function GenericModal({
</DialogDescription>
</DialogHeader>
<div className="flex h-full w-full mt-2">
<div className="mt-2 flex h-full w-full">
<Textarea
ref={ref}
className="form-input h-[300px] w-full rounded-lg border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-white focus-visible:ring-1"
className=" form-primary h-[300px] w-full "
value={myValue}
onChange={(e) => {
setMyValue(e.target.value);
@ -101,7 +105,8 @@ export default function GenericModal({
setModalOpen(false);
break;
case 2:
postValidatePrompt(myValue, nodeClass)
console.log("postValidatePrompt");
postValidatePrompt(field_name, myValue, nodeClass)
.then((apiReturn) => {
if (apiReturn.data) {
setNodeClass(apiReturn.data.frontend_node);

View file

@ -77,7 +77,7 @@ export default function ButtonBox({
<button disabled={deactivate} onClick={onClick}>
<div
className={classNames(
"flex flex-col justify-center items-center rounded-lg text-center shadow border border-gray-300 dark:border-gray-800 hover:shadow-lg transform hover:scale-105",
"flex transform flex-col items-center justify-center rounded-lg border border-ring text-center shadow hover:scale-105 hover:shadow-lg",
bgColor,
height,
width,
@ -85,18 +85,18 @@ export default function ButtonBox({
)}
>
<div
className={`flex items-center justify-center ${bigCircle} bg-white/30 dark:bg-white/30 rounded-full mb-1`}
className={`flex items-center justify-center ${bigCircle} mb-1 rounded-full bg-background/30`}
>
<div
className={`flex items-center justify-center ${smallCircle} bg-white dark:bg-white/80 rounded-full`}
className={`flex items-center justify-center ${smallCircle} rounded-full bg-background`}
>
<div className={textColor}>{icon}</div>
</div>
</div>
<div className="w-full mt-auto mb-auto">
<div className="mb-auto mt-auto w-full">
<h3
className={classNames(
"w-full font-semibold break-words text-white dark:text-white/80 truncate-multiline",
"w-full break-words font-semibold text-background truncate-multiline",
titleFontSize,
marginTop
)}

View file

@ -68,15 +68,15 @@ export default function ImportModal() {
<DialogContent
className={classNames(
showExamples
? "lg:max-w-[650px] h-[600px]"
: "lg:max-w-[650px] h-[450px]"
? "h-[600px] lg:max-w-[650px]"
: "h-[450px] lg:max-w-[650px]"
)}
>
<DialogHeader>
<DialogTitle className="flex items-center">
{showExamples && (
<>
<div className="z-50 absolute top-2 left-0 hidden pt-4 pl-4 sm:block">
<div className="absolute left-0 top-2 z-50 hidden pl-4 pt-4 sm:block">
<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"
@ -85,7 +85,7 @@ export default function ImportModal() {
}}
>
<ArrowLeftIcon
className="h-5 w-5 text-gray-800 ml-1 dark:text-white"
className="ml-1 h-5 w-5 text-foreground"
aria-hidden="true"
/>
</button>
@ -97,7 +97,7 @@ export default function ImportModal() {
{showExamples ? "Select an example" : "Import"}
</span>
<ArrowUpTrayIcon
className="h-5 w-5 text-gray-800 ml-1 dark:text-white"
className="ml-1 h-5 w-5 text-foreground"
aria-hidden="true"
/>
</DialogTitle>
@ -106,17 +106,17 @@ export default function ImportModal() {
<div
className={classNames(
"h-full w-full dark:bg-gray-900 overflow-y-auto scrollbar-hide",
"h-full w-full overflow-y-auto scrollbar-hide",
showExamples && !loadingExamples
? "flex flex-row start justify-center items-start flex-wrap overflow-auto mx-auto"
: "flex flex-row justify-center items-center"
? "start mx-auto flex flex-row flex-wrap items-start justify-center overflow-auto"
: "flex flex-row items-center justify-center"
)}
>
{!showExamples && (
<div className="flex h-full w-full justify-evenly items-center">
<div className="flex h-full w-full items-center justify-evenly">
<ButtonBox
size="big"
bgColor="bg-emerald-500 dark:bg-emerald-500/75"
bgColor="bg-medium-emerald "
description="Prebuilt Examples"
icon={
<DocumentDuplicateIcon className="h-10 w-10 flex-shrink-0" />
@ -125,12 +125,12 @@ export default function ImportModal() {
setShowExamples(true);
handleExamples();
}}
textColor="text-emerald-500 dark:text-emerald-500/75"
textColor="text-medium-emerald "
title="Examples"
></ButtonBox>
<ButtonBox
size="big"
bgColor="bg-blue-500 dark:bg-blue-500/75"
bgColor="bg-almost-dark-blue "
description="Import from Local"
icon={
<ComputerDesktopIcon className="h-10 w-10 flex-shrink-0" />
@ -139,13 +139,13 @@ export default function ImportModal() {
uploadFlow();
setModalOpen(false);
}}
textColor="text-blue-500 dark:text-blue-500/75"
textColor="text-almost-dark-blue "
title="Local File"
></ButtonBox>
</div>
)}
{showExamples && loadingExamples && (
<div className="flex align-middle justify-center items-center">
<div className="flex items-center justify-center align-middle">
<LoadingComponent remSize={30} />
</div>
)}
@ -157,16 +157,16 @@ export default function ImportModal() {
{" "}
<ButtonBox
size="small"
bgColor="bg-emerald-500 dark:bg-emerald-500/75"
bgColor="bg-medium-emerald "
description={example.description ?? "Prebuilt Examples"}
icon={
<DocumentDuplicateIcon className="h-6 w-6 flex-shrink-0" />
<DocumentDuplicateIcon strokeWidth={1.5} className="h-6 w-6 flex-shrink-0" />
}
onClick={() => {
addFlow(example, false);
setModalOpen(false);
}}
textColor="text-emerald-500 dark:text-emerald-500/75"
textColor="text-medium-emerald "
title={example.name}
></ButtonBox>
</div>
@ -175,11 +175,11 @@ export default function ImportModal() {
</div>
<DialogFooter>
<div className="w-full flex items-center justify-center mt-2">
<div className="mt-2 flex w-full items-center justify-center">
<a
href="https://github.com/logspace-ai/langflow_examples"
target="_blank"
className="flex items-center justify-center text-gray-600 dark:text-gray-300"
className="flex items-center justify-center text-muted-foreground "
rel="noreferrer"
>
<svg

View file

@ -15,12 +15,13 @@ export default function TextAreaModal({
}) {
const [open, setOpen] = useState(true);
const [myValue, setMyValue] = useState(value);
const { closePopUp } = useContext(PopUpContext);
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
const ref = useRef();
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
setCloseEdit("textarea");
closePopUp();
}, 300);
}
@ -42,7 +43,7 @@ export default function TextAreaModal({
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-500 dark:bg-gray-600 dark:bg-opacity-75 bg-opacity-75 transition-opacity" />
<div className="fixed inset-0 bg-ring bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
@ -56,11 +57,11 @@ export default function TextAreaModal({
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 flex-col justify-between transform h-[600px] overflow-hidden rounded-lg bg-white dark:bg-gray-800 text-left shadow-xl transition-all sm:my-8 w-[700px]">
<div className=" z-50 absolute top-0 right-0 hidden pt-4 pr-4 sm:block">
<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">
<button
type="button"
className="rounded-md text-gray-400 hover:text-gray-500"
className="rounded-md text-ring hover:text-accent-foreground"
onClick={() => {
setModalOpen(false);
}}
@ -69,29 +70,29 @@ export default function TextAreaModal({
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="h-full w-full flex flex-col justify-center items-center">
<div className="flex w-full pb-4 z-10 justify-center shadow-sm">
<div className="mx-auto mt-4 flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-blue-100 dark:bg-gray-900 sm:mx-0 sm:h-10 sm:w-10">
<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="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">
<ClipboardDocumentListIcon
className="h-6 w-6 text-blue-600"
className="h-6 w-6 text-almost-medium-blue"
aria-hidden="true"
/>
</div>
<div className="mt-4 text-center sm:ml-4 sm:text-left">
<Dialog.Title
as="h3"
className="text-lg font-medium dark:text-white leading-10 text-gray-900"
className="text-lg font-medium leading-10 text-foreground"
>
Edit text
</Dialog.Title>
</div>
</div>
<div className="h-full w-full bg-gray-200 dark:bg-gray-900 p-4 gap-4 flex flex-row justify-center items-center">
<div className="flex h-full w-full flex-row items-center justify-center gap-4 bg-input p-4">
<div className="flex h-full w-full">
<div className="overflow-hidden px-4 py-5 sm:p-6 w-full rounded-lg bg-white dark:bg-gray-800 shadow">
<div className="w-full overflow-hidden rounded-lg bg-background px-4 py-5 shadow sm:p-6">
<textarea
ref={ref}
className="form-input h-full w-full rounded-lg border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-white"
className="form-input h-full w-full form-primary"
value={myValue}
onChange={(e) => {
setMyValue(e.target.value);
@ -101,10 +102,10 @@ export default function TextAreaModal({
</div>
</div>
</div>
<div className="bg-gray-200 dark:bg-gray-900 w-full pb-3 flex flex-row-reverse px-4">
<div className="flex w-full flex-row-reverse bg-input px-4 pb-3">
<button
type="button"
className="inline-flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:ring-offset-1 sm:ml-3 sm:w-auto sm:text-sm"
className="inline-flex w-full justify-center rounded-md border border-transparent 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"
onClick={() => {
setModalOpen(false);
}}

View file

@ -37,9 +37,9 @@ export default function CommunityPage() {
handleExamples();
}, []);
return (
<div className="w-full h-full flex overflow-auto flex-col bg-muted px-16">
<div className="w-full flex justify-between py-12 pb-2 px-6">
<span className="text-2xl flex items-center justify-center gap-2 font-semibold">
<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">
<Users2 className="w-6" />
Community Examples
</span>
@ -50,18 +50,18 @@ export default function CommunityPage() {
rel="noreferrer"
>
<Button variant="primary">
<GithubIcon className="w-4 mr-2" />
<GithubIcon className="mr-2 w-4" />
Add Your Example
</Button>
</a>
</div>
</div>
<span className="flex pb-8 px-6 w-[70%] text-muted-foreground">
<span className="flex w-[70%] px-6 pb-8 text-muted-foreground">
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="w-full p-4 grid gap-4 md:grid-cols-2 lg:grid-cols-4">
<div className="grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4">
{!loadingExamples &&
examples.map((flow, idx) => (
<CardComponent
@ -79,7 +79,7 @@ export default function CommunityPage() {
});
}}
>
<GitFork className="w-4 mr-2" />
<GitFork className="mr-2 w-4" />
Fork Example
</Button>
}

View file

@ -11,9 +11,10 @@ const ConnectionLineComponent = ({
<g>
<path
fill="none"
// ! Replace hash # colors here
stroke="#222"
strokeWidth={1.5}
className="animated dark:stroke-gray-400"
className="animated "
d={`M${fromX},${fromY} C ${fromX} ${toY} ${fromX} ${toY} ${toX},${toY}`}
style={connectionLineStyle}
/>
@ -23,7 +24,7 @@ const ConnectionLineComponent = ({
fill="#fff"
r={3}
stroke="#222"
className="dark:stroke-gray-400 dark:fill-gray-800"
className=""
strokeWidth={1.5}
/>
</g>

View file

@ -12,10 +12,10 @@ export default function DisclosureComponent({
{({ open }) => (
<>
<div>
<Disclosure.Button className="select-none bg-muted dark:bg-gray-700/60 dark:border-y-gray-600 w-full flex justify-between items-center -mt-px px-3 py-2 border-y border-y-gray-200">
<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">
<div className="flex gap-4">
<Icon size={22} className="text-gray-800 dark:text-white/80" />
<span className="flex items-center text-sm text-gray-800 dark:text-white/80 font-medium">
<Icon strokeWidth={1.5} size={22} className="text-primary " />
<span className="flex items-center text-sm text-primary">
{title}
</span>
</div>
@ -29,7 +29,7 @@ export default function DisclosureComponent({
<ChevronRight
className={`${
open || openDisc ? "rotate-90 transform" : ""
} h-4 w-4 text-gray-800 dark:text-white`}
} h-4 w-4 text-foreground`}
/>
</div>
</div>

View file

@ -187,8 +187,8 @@ export default function Page({ flow }: { flow: FlowType }) {
style: { stroke: "inherit" },
className:
params.targetHandle.split("|")[0] === "Text"
? "stroke-gray-800 dark:stroke-gray-300"
: "stroke-gray-900 dark:stroke-gray-200",
? "stroke-foreground "
: "stroke-foreground ",
animated: params.targetHandle.split("|")[0] === "Text",
},
eds
@ -361,13 +361,13 @@ export default function Page({ flow }: { flow: FlowType }) {
<div className="flex h-full overflow-hidden">
<ExtraSidebar />
{/* Main area */}
<main className="flex-1 flex">
<main className="flex flex-1">
{/* Primary column */}
<div className="w-full h-full">
<div className="w-full h-full" ref={reactFlowWrapper}>
<div className="h-full w-full">
<div className="h-full w-full" ref={reactFlowWrapper}>
{Object.keys(templates).length > 0 &&
Object.keys(types).length > 0 ? (
<div className="w-full h-full">
<div className="h-full w-full">
<ReactFlow
nodes={nodes}
onMove={() => {
@ -414,8 +414,11 @@ export default function Page({ flow }: { flow: FlowType }) {
minZoom={0.01}
maxZoom={8}
>
<Background className="dark:bg-gray-900" />
<Controls className="[&>button]:text-black [&>button]:dark:bg-gray-800 hover:[&>button]:dark:bg-gray-700 [&>button]:dark:text-gray-400 [&>button]:dark:fill-gray-400 [&>button]:dark:border-gray-600"></Controls>
<Background className="" />
<Controls
className="bg-muted fill-foreground stroke-foreground text-primary
[&>button]:border-b-border hover:[&>button]:bg-border"
></Controls>
</ReactFlow>
<Chat flow={flow} reactFlowInstance={reactFlowInstance} />
</div>

View file

@ -15,7 +15,6 @@ import ExportModal from "../../../../modals/exportModal";
import ApiModal from "../../../../modals/ApiModal";
import { TabsContext } from "../../../../contexts/tabsContext";
import { alertContext } from "../../../../contexts/alertContext";
import { INPUT_STYLE } from "../../../../constants";
import { Separator } from "../../../../components/ui/separator";
import { Menu } from "lucide-react";
@ -60,48 +59,48 @@ export default function ExtraSidebar() {
}
return (
<div className="w-52 flex flex-col overflow-hidden scrollbar-hide h-full border-r">
<div className="mt-2 mb-2 w-full flex gap-2 justify-between px-2 items-center">
<ShadTooltip delayDuration={1000} content="Import" side="top">
<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">
<ShadTooltip content="Import" side="top">
<button
className="hover:dark:hover:bg-[#242f47] text-gray-700 w-full justify-center shadow-sm transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 relative inline-flex items-center rounded-md bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
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"
onClick={() => {
// openPopUp(<ImportModal />);
uploadFlow();
}}
>
<FileUp className="w-5 h-5 dark:text-gray-300"></FileUp>
<FileUp strokeWidth={1.5} className="h-5 w-5 "></FileUp>
</button>
</ShadTooltip>
<ShadTooltip delayDuration={1000} content="Export" side="top">
<ShadTooltip content="Export" side="top">
<button
className={classNames(
"hover:dark:hover:bg-[#242f47] text-gray-700 w-full justify-center shadow-sm transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 relative inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 rounded-md"
"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"
)}
onClick={(event) => {
openPopUp(<ExportModal />);
}}
>
<FileDown className="w-5 h-5 dark:text-gray-300"></FileDown>
<FileDown strokeWidth={1.5} className="h-5 w-5 "></FileDown>
</button>
</ShadTooltip>
<ShadTooltip delayDuration={1000} content="Code" side="top">
<ShadTooltip content="Code" side="top">
<button
className={classNames(
"hover:dark:hover:bg-[#242f47] text-gray-700 w-full justify-center shadow-sm transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 relative inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 rounded-md"
"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"
)}
onClick={(event) => {
openPopUp(<ApiModal flow={flows.find((f) => f.id === tabId)} />);
}}
>
<Code2 className="w-5 h-5 dark:text-gray-300"></Code2>
<Code2 strokeWidth={1.5} className="h-5 w-5 "></Code2>
</button>
</ShadTooltip>
<ShadTooltip delayDuration={1000} content="Save" side="top">
<ShadTooltip content="Save" side="top">
<button
className="hover:dark:hover:bg-[#242f47] text-gray-700 w-full justify-center transition-all shadow-sm duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 relative inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 rounded-md"
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"
onClick={(event) => {
saveFlow(flows.find((f) => f.id === tabId));
setSuccessData({ title: "Changes saved successfully" });
@ -109,35 +108,34 @@ export default function ExtraSidebar() {
disabled={!isPending}
>
<Save
strokeWidth={1.5}
className={
"w-5 h-5" + (isPending ? " " : " text-muted-foreground")
"h-5 w-5" + (isPending ? " " : " text-muted-foreground")
}
></Save>
</button>
</ShadTooltip>
</div>
<Separator />
<div className="relative mt-2 flex items-center mb-2 mx-2">
<div className="relative mx-auto mb-2 mt-2 flex items-center">
<input
type="text"
name="search"
id="search"
placeholder="Search"
className={
INPUT_STYLE +
"w-full border-1 dark:border-slate-600 dark:border-0.5 dark:ring-0 focus-visible:dark:ring-0 focus-visible:dark:ring-offset-1 rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
}
className="input-search"
onChange={(e) => {
handleSearchInput(e.target.value);
setSearch(e.target.value);
}}
/>
<div className="absolute inset-y-0 right-0 flex py-1.5 pr-3 items-center">
<Search size={20} color="#000000" />
<div className="absolute inset-y-0 right-0 flex items-center py-1.5 pr-3">
{/* ! replace hash color here */}
<Search size={20} strokeWidth={1.5} className="text-primary" />
</div>
</div>
<div className="w-full overflow-auto scrollbar-hide">
<div className="w-full overflow-auto scrollbar-hide pb-10">
{Object.keys(dataFilter)
.sort()
.map((d: keyof APIObjectType, i) =>
@ -150,20 +148,19 @@ export default function ExtraSidebar() {
Icon: nodeIconsLucide[d] ?? nodeIconsLucide.unknown,
}}
>
<div className="p-2 flex flex-col gap-2">
<div className="flex flex-col gap-2 p-2">
{Object.keys(dataFilter[d])
.sort()
.map((t: string, k) => (
<ShadTooltip
content={data[d][t].display_name}
delayDuration={1500}
side="right"
key={data[d][t].display_name}
>
<div key={k} data-tooltip-id={t}>
<div
draggable
className={" cursor-grab border-l-8 rounded-l-md"}
className={"cursor-grab rounded-l-md border-l-8"}
style={{
borderLeftColor:
nodeColors[d] ?? nodeColors.unknown,
@ -182,11 +179,11 @@ export default function ExtraSidebar() {
);
}}
>
<div className="flex w-full justify-between text-sm px-3 py-1 bg-white dark:bg-gray-800 items-center border-dashed border-gray-400 dark:border-gray-600 border-l-0 rounded-md rounded-l-none border">
<span className="text-black dark:text-white w-full pr-1 truncate text-xs">
<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">
{data[d][t].display_name}
</span>
<Menu className="w-4 h-6 text-gray-400 dark:text-gray-600" />
<Menu className="h-6 w-4 text-ring " />
</div>
</div>
</div>

View file

@ -1,10 +1,11 @@
import { useContext, useState } from "react";
import { Settings2, Copy, Trash2 } from "lucide-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";
const NodeToolbarComponent = (props) => {
const [nodeLength, setNodeLength] = useState(
@ -27,25 +28,23 @@ const NodeToolbarComponent = (props) => {
const reactFlowInstance = useReactFlow();
return (
<>
<div className="h-10 w-26">
<div className="w-26 h-10">
<span className="isolate inline-flex rounded-md shadow-sm">
<ShadTooltip delayDuration={1000} content="Delete" side="top">
<ShadTooltip content="Delete" side="top">
<button
className="hover:dark:hover:bg-[#242f47] text-gray-700 transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 shadow-md relative inline-flex items-center rounded-l-md bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10"
className="relative inline-flex items-center rounded-l-md bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
onClick={() => {
props.deleteNode(props.data.id);
}}
>
<Trash2 className="w-4 h-4 dark:text-gray-300"></Trash2>
<Trash2 className="h-4 w-4"></Trash2>
</button>
</ShadTooltip>
<ShadTooltip delayDuration={1000} content="Duplicate" side="top">
<ShadTooltip content="Duplicate" side="top">
<button
className={classNames(
nodeLength > 0
? "hover:dark:hover:bg-[#242f47] text-gray-700 transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 shadow-md relative -ml-px inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10"
: "hover:dark:hover:bg-[#242f47] text-gray-700 transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 shadow-md relative -ml-px inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10 rounded-r-md"
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
)}
onClick={(event) => {
event.preventDefault();
@ -63,23 +62,58 @@ const NodeToolbarComponent = (props) => {
);
}}
>
<Copy className="w-4 h-4 dark:text-gray-300"></Copy>
<Copy className="h-4 w-4"></Copy>
</button>
</ShadTooltip>
{nodeLength > 0 && (
<ShadTooltip delayDuration={1000} content="Edit" side="top">
<button
className="hover:dark:hover:bg-[#242f47] text-gray-700 transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 shadow-md relative -ml-px inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10 rounded-r-md"
onClick={(event) => {
<ShadTooltip
content={
props.data.node.documentation === ""
? "Coming Soon"
: "Documentation"
}
side="top"
>
<a
className={classNames(
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10" +
(props.data.node.documentation === ""
? " text-muted-foreground"
: " text-foreground")
)}
target="_blank"
rel="noopener noreferrer"
href={props.data.node.documentation}
// deactivate link if no documentation is provided
onClick={(event) => {
if (props.data.node.documentation === "") {
event.preventDefault();
props.openPopUp(<EditNodeModal data={props.data} />);
}}
>
<Settings2 className="w-4 h-4 dark:text-gray-300"></Settings2>
</button>
</ShadTooltip>
)}
}
}}
>
<FileText className="h-4 w-4 "></FileText>
</a>
</ShadTooltip>
<ShadTooltip content="Edit" side="top">
<button
className={classNames(
"relative -ml-px inline-flex items-center rounded-r-md bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10" +
(nodeLength == 0
? " text-muted-foreground"
: " text-foreground")
)}
onClick={(event) => {
if (nodeLength == 0) {
event.preventDefault();
}
event.preventDefault();
props.openPopUp(<EditNodeModal data={props.data} />);
}}
>
<Settings2 className="h-4 w-4 "></Settings2>
</button>
</ShadTooltip>
{/*
<Menu as="div" className="relative inline-block text-left z-100">
@ -87,7 +121,7 @@ const NodeToolbarComponent = (props) => {
<div>
<Menu.Button className="flex items-center">
<EllipsisVerticalIcon
className="w-5 h-5 dark:text-gray-300"
className="w-5 h-5 "
aria-hidden="true"
/>
</Menu.Button>
@ -102,7 +136,7 @@ const NodeToolbarComponent = (props) => {
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute z-40 mt-2 w-56 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none top-[28px]">
<Menu.Items className="absolute z-40 mt-2 w-56 origin-top-right rounded-md bg-background shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none top-[28px]">
<div className="py-1">
<Menu.Item>
{({ active }) => (
@ -116,7 +150,7 @@ const NodeToolbarComponent = (props) => {
className={classNames(
active
? "bg-muted text-gray-900"
: "text-gray-700",
: "text-foreground",
"w-full group flex items-center px-4 py-2 text-sm"
)}
>
@ -156,7 +190,7 @@ const NodeToolbarComponent = (props) => {
className={classNames(
active
? "bg-muted text-gray-900"
: "text-gray-700",
: "text-foreground",
"w-full group flex items-center px-4 py-2 text-sm"
)}
>

View file

@ -29,7 +29,7 @@ export default function FlowPage() {
<a
target={"_blank"}
href="https://logspace.ai/"
className="absolute left-7 bottom-2 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="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"
>
{version && <div className="mt-1"> LangFlow v{version}</div>}
<div className={version ? "mt-2" : "mt-1"}>Created by Logspace</div>

View file

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

View file

@ -13,6 +13,8 @@ export type APIClassType = {
template: APITemplateType;
display_name: string;
input_types?: Array<string>;
output_types?: Array<string>;
documentation: string;
[key: string]: Array<string> | string | APITemplateType;
};

View file

@ -23,6 +23,7 @@ export type DropDownComponentType = {
options: string[];
onSelect: (value: string) => void;
editNode?: boolean;
apiModal?: boolean;
numberOfOptions?: number;
};
export type ParameterComponentType = {
@ -37,15 +38,18 @@ export type ParameterComponentType = {
tooltipTitle: string;
dataContext?: typesContextType;
optionalHandle?: Array<String>;
info?: string;
};
export type InputListComponentType = {
value: string[];
onChange: (value: string[]) => void;
disabled: boolean;
editNode?: boolean;
onAddInput?: (value?: string[]) => void;
};
export type TextAreaComponentType = {
field_name?: string;
nodeClass?: APIClassType;
setNodeClass?: (value: APIClassType) => void;
disabled: boolean;
@ -123,3 +127,18 @@ export type RadialProgressType = {
value?: number;
color?: string;
};
export type AccordionComponentType = {
children?: ReactElement;
open?: string[];
trigger?: string;
};
export type Side = "top" | "right" | "bottom" | "left";
export type ShadTooltipProps = {
delayDuration?: number;
side?: Side;
content: ReactNode;
children: ReactNode;
style?: string;
};

View file

@ -11,7 +11,11 @@ export type TabsContextType = {
addFlow: (flowData?: FlowType, newProject?: boolean) => Promise<String>;
updateFlow: (newFlow: FlowType) => void;
incrementNodeId: () => string;
downloadFlow: (flow: FlowType) => void;
downloadFlow: (
flow: FlowType,
flowName: string,
flowDescription?: string
) => void;
downloadFlows: () => void;
uploadFlows: () => void;
uploadFlow: (newFlow?: boolean, file?: File) => void;
@ -28,6 +32,8 @@ export type TabsContextType = {
) => void;
lastCopiedSelection: { nodes: any; edges: any };
setLastCopiedSelection: (selection: { nodes: any; edges: any }) => void;
setTweak: (tweak: any) => void;
getTweak: any;
};
export type TabsState = {

View file

@ -1,21 +1,3 @@
import {
RocketLaunchIcon,
LinkIcon,
CpuChipIcon,
LightBulbIcon,
CommandLineIcon,
WrenchScrewdriverIcon,
WrenchIcon,
ComputerDesktopIcon,
GiftIcon,
PaperClipIcon,
QuestionMarkCircleIcon,
FingerPrintIcon,
ScissorsIcon,
CircleStackIcon,
Squares2X2Icon,
Bars3CenterLeftIcon,
} from "@heroicons/react/24/outline";
import { Connection, Edge, Node, ReactFlowInstance } from "reactflow";
import { FlowType, NodeType } from "./types/flow";
import { APITemplateType } from "./types/api";
@ -42,7 +24,7 @@ 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 "./constants";
import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "./flow_constants";
import { ComponentType, SVGProps } from "react";
import {
Compass,
@ -60,12 +42,14 @@ import {
Paperclip,
Rocket,
Scissors,
FileSearch,
TerminalSquare,
Wand2,
Wrench,
} from "lucide-react";
import { SupabaseIcon } from "./icons/supabase";
import { MongoDBIcon } from "./icons/MongoDB";
import { VertexAIIcon } from "./icons/VertexAI";
export function classNames(...classes: Array<string>) {
return classes.filter(Boolean).join(" ");
@ -143,6 +127,7 @@ export const nodeColors: { [char: string]: string } = {
utilities: "#31A3CC",
output_parsers: "#E6A627",
str: "#049524",
retrievers: "#e6b25a",
unknown: "#9CA3AF",
};
@ -161,73 +146,12 @@ export const nodeNames: { [char: string]: string } = {
toolkits: "Toolkits",
wrappers: "Wrappers",
textsplitters: "Text Splitters",
retrievers: "Retrievers",
utilities: "Utilities",
output_parsers: "Output Parsers",
unknown: "Unknown",
};
export const nodeIcons: {
[char: string]: React.ForwardRefExoticComponent<
React.SVGProps<SVGSVGElement>
>;
} = {
Chroma: ChromaIcon,
AirbyteJSONLoader: AirbyteIcon,
// SerpAPIWrapper: SerperIcon,
// AZLyricsLoader: AzIcon,
Anthropic: AnthropicIcon,
ChatAnthropic: AnthropicIcon,
BingSearchAPIWrapper: BingIcon,
BingSearchRun: BingIcon,
Cohere: CohereIcon,
CohereEmbeddings: CohereIcon,
EverNoteLoader: EvernoteIcon,
FacebookChatLoader: FBIcon,
GitbookLoader: GitBookIcon,
GoogleSearchAPIWrapper: GoogleIcon,
GoogleSearchResults: GoogleIcon,
GoogleSearchRun: GoogleIcon,
HNLoader: HackerNewsIcon,
HuggingFaceHub: HugginFaceIcon,
HuggingFaceEmbeddings: HugginFaceIcon,
IFixitLoader: IFixIcon,
Meta: MetaIcon,
Midjourney: MidjourneyIcon,
NotionDirectoryLoader: NotionIcon,
ChatOpenAI: OpenAiIcon,
OpenAI: OpenAiIcon,
OpenAIEmbeddings: OpenAiIcon,
Pinecone: PineconeIcon,
SupabaseVectorStore: SupabaseIcon,
MongoDBAtlasVectorSearch: MongoDBIcon,
// UnstructuredPowerPointLoader: PowerPointIcon, // word and powerpoint have differente styles
Qdrant: QDrantIcon,
// ReadTheDocsLoader: ReadTheDocsIcon, // does not work
Searx: SearxIcon,
SlackDirectoryLoader: SlackIcon,
// Weaviate: WeaviateIcon, // does not work
// WikipediaAPIWrapper: WikipediaIcon,
// WolframAlphaQueryRun: WolframIcon,
// WolframAlphaAPIWrapper: WolframIcon,
// UnstructuredWordDocumentLoader: WordIcon, // word and powerpoint have differente styles
agents: RocketLaunchIcon,
chains: LinkIcon,
memories: CpuChipIcon,
llms: LightBulbIcon,
prompts: CommandLineIcon,
tools: WrenchIcon,
advanced: ComputerDesktopIcon,
chat: Bars3CenterLeftIcon,
embeddings: FingerPrintIcon,
documentloaders: PaperClipIcon,
vectorstores: CircleStackIcon,
toolkits: WrenchScrewdriverIcon,
textsplitters: ScissorsIcon,
wrappers: GiftIcon,
utilities: Squares2X2Icon,
unknown: QuestionMarkCircleIcon,
};
export const nodeIconsLucide: {
[char: string]: React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
@ -323,6 +247,12 @@ export const nodeIconsLucide: {
SupabaseVectorStore: SupabaseIcon as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
VertexAI: VertexAIIcon as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
ChatVertexAI: VertexAIIcon as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
agents: Rocket as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
@ -371,6 +301,9 @@ export const nodeIconsLucide: {
output_parsers: Compass as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
retrievers: FileSearch as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
unknown: HelpCircle as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
@ -394,6 +327,23 @@ export const gradients = [
"bg-gradient-to-br from-green-500 to-green-700",
"bg-gradient-to-br from-rose-400 via-fuchsia-500 to-indigo-500",
"bg-gradient-to-br from-sky-400 to-blue-500",
"bg-gradient-to-br from-green-200 via-green-400 to-green-500",
"bg-gradient-to-br from-red-400 via-gray-300 to-blue-500",
"bg-gradient-to-br from-gray-900 to-gray-600 bg-gradient-to-r",
"bg-gradient-to-br from-rose-500 via-red-400 to-red-500",
"bg-gradient-to-br from-fuchsia-600 to-pink-600",
"bg-gradient-to-br from-emerald-500 to-lime-600",
"bg-gradient-to-br from-rose-500 to-indigo-700",
"bg-gradient-to-br bg-gradient-to-tr from-violet-500 to-orange-300",
"bg-gradient-to-br from-gray-900 via-purple-900 to-violet-600",
"bg-gradient-to-br from-yellow-200 via-red-500 to-fuchsia-500",
"bg-gradient-to-br from-sky-400 to-indigo-900",
"bg-gradient-to-br from-amber-200 via-violet-600 to-sky-900",
"bg-gradient-to-br from-amber-700 via-orange-300 to-rose-800",
"bg-gradient-to-br from-gray-300 via-fuchsia-600 to-orange-600",
"bg-gradient-to-br from-fuchsia-500 via-red-600 to-orange-400",
"bg-gradient-to-br from-sky-400 via-rose-400 to-lime-400",
"bg-gradient-to-br from-lime-600 via-yellow-300 to-red-600",
];
export const bgColors = {
@ -636,11 +586,19 @@ export function isValidConnection(
reactFlowInstance: ReactFlowInstance
) {
if (
targetHandle.split("|")[0].split(";").some((n) => n === sourceHandle.split("|")[0]) ||
targetHandle
.split("|")[0]
.split(";")
.some((n) => n === sourceHandle.split("|")[0]) ||
sourceHandle
.split("|")
.slice(2)
.some((t) => targetHandle.split("|")[0].split(";").some((n) => n === t)) ||
.some((t) =>
targetHandle
.split("|")[0]
.split(";")
.some((n) => n === t)
) ||
targetHandle.split("|")[0] === "str"
) {
let targetNode = reactFlowInstance.getNode(target).data.node;
@ -834,30 +792,40 @@ export function updateIds(newFlow, getNodeId) {
});
}
export function groupByFamily(data, baseClasses) {
export function groupByFamily(data, baseClasses, left, type) {
let parentOutput: string;
let arrOfParent: string[] = [];
let arrOfType: { family: string; type: string }[] = [];
let arrOfType: { family: string; type: string; component: string }[] = [];
let arrOfLength: { length: number; type: string; }[] = [];
let lastType = "";
Object.keys(data).map((d) => {
Object.keys(data[d]).map((n) => {
try {
if (
data[d][n].base_classes.some((r) =>
baseClasses.split("\n").includes(r)
)
) {
arrOfParent.push(d);
}
} catch (e) {
console.log(e);
}
});
Object.keys(data[d]).map((n) => {
try {
if (
data[d][n].base_classes.some((r) =>
baseClasses.split("\n").includes(r)
)
) {
arrOfParent.push(d);
}
if (n === type) {
parentOutput = d;
}
if (d !== lastType) {
arrOfLength.push({
length: Object.keys(data[d]).length,
type: d
});
lastType = d;
}
} catch (e) {
console.log(e);
}
});
});
let uniq = arrOfParent.filter(
(item, index) => arrOfParent.indexOf(item) === index
);
Object.keys(data).map((d) => {
Object.keys(data[d]).map((n) => {
try {
@ -867,6 +835,7 @@ export function groupByFamily(data, baseClasses) {
arrOfType.push({
family: d,
type: data,
component: n
});
}
});
@ -877,24 +846,62 @@ export function groupByFamily(data, baseClasses) {
});
});
let groupedBy = arrOfType.filter((object, index, self) => {
const foundIndex = self.findIndex(
(o) => o.family === object.family && o.type === object.type
);
return foundIndex === index;
});
if(left == false){
let groupedBy = arrOfType.filter((object, index, self) => {
const foundIndex = self.findIndex(
(o) => o.family === object.family && o.type === object.type
);
return foundIndex === index;
});
return groupedBy.reduce((result, item) => {
const existingGroup = result.find((group) => group.family === item.family);
if (existingGroup) {
existingGroup.type += `, ${item.type}`;
} else {
result.push({ family: item.family, type: item.type, component: item.component });
}
if (left == false) {
let resFil = result.filter((group) => group.family === parentOutput);
result = resFil;
}
return result;
}, []);
}
return groupedBy.reduce((result, item) => {
const existingGroup = result.find((group) => group.family === item.family);
if (existingGroup) {
existingGroup.type += `, ${item.type}`;
} else {
result.push({ family: item.family, type: item.type });
else{
const groupedArray = [];
const groupedData = {};
arrOfType.forEach((item) => {
const { family, type, component } = item;
const key = `${family}-${type}`;
if (!groupedData[key]) {
groupedData[key] = { family, type, component: [component] };
} else {
groupedData[key].component.push(component);
}
});
for (const key in groupedData) {
groupedArray.push(groupedData[key]);
}
return result;
}, []);
groupedArray.forEach((object, index, self) => {
const findObj = arrOfLength.find(x => x.type == object.family);
if(object.component.length == findObj.length){
self[index]['type'] = "";
}
else{
self[index]['type'] = object.component.join(', ');
}
})
return groupedArray
}
}
export function buildTweaks(flow) {
@ -998,5 +1005,5 @@ export function getRandomKeyByssmm(): string {
const now = new Date();
const seconds = String(now.getSeconds()).padStart(2, "0");
const milliseconds = String(now.getMilliseconds()).padStart(3, "0");
return seconds + milliseconds;
return seconds + milliseconds + Math.abs(Math.floor(Math.random() * 10001));
}

View file

@ -3,97 +3,21 @@ const { fontFamily } = require("tailwindcss/defaultTheme");
import plugin from "tailwindcss/plugin";
// ! Check if removing the other module.exports made sense
module.exports = {
darkMode: ["class"],
content: ["app/**/*.{ts,tsx}", "components/**/*.{ts,tsx}"],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
keyframes: {
"accordion-down": {
from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: `var(--radius)`,
md: `calc(var(--radius) - 2px)`,
sm: "calc(var(--radius) - 4px)",
},
fontFamily: {
sans: ["var(--font-sans)", ...fontFamily.sans],
},
keyframes: {
"accordion-down": {
from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
},
plugins: [require("tailwindcss-animate")],
};
module.exports = {
content: ["./index.html", "./src/**/*.{js,ts,tsx,jsx}"],
darkMode: "class",
content: [
"app/**/*.{ts,tsx}",
"components/**/*.{ts,tsx}",
"./index.html",
"./src/**/*.{js,ts,tsx,jsx}",
],
safelist: [
"bg-status-blue",
"bg-status-green",
"bg-status-red",
"bg-status-yellow",
],
important: true,
theme: {
container: {
@ -104,7 +28,62 @@ module.exports = {
},
},
extend: {
keyframes: {
"accordion-down": {
from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
colors: {
"almost-dark-gray": "var(--almost-dark-gray)",
"almost-light-blue": "var(--almost-light-blue)",
"almost-medium-blue": "var(--almost-medium-blue)",
"almost-medium-gray": "var(--almost-medium-gray)",
"almost-medium-green": "var(--almost-medium-green)",
"almost-medium-red": "var(--almost-medium-red)",
"btn-shadow": "var(--round-btn-shadow)",
"build-trigger": "var(--build-trigger)",
"chat-trigger": "var(--chat-trigger)",
"chat-trigger-disabled": "var(--chat-trigger-disabled)",
"blur-shared": "var(--blur-shared)",
"dark-blue": "var(--dark-blue)",
"dark-gray": "var(--dark-gray)",
"dark-red": "var(--dark-red)",
"error-background": "var(--error-background)",
"error-foreground": "var(--error-foreground)",
"high-dark-gray": "var(--high-dark-gray)",
"high-indigo": "var(--high-indigo)",
"high-light-gray": "var(--high-light-gray)",
"info-background": "var(--info-background)",
"info-foreground": "var(--info-foreground)",
"light-blue": "var(--light-blue)",
"light-gray": "var(--light-gray)",
"light-slate": "var(--light-slate)",
"medium-blue": "var(--medium-blue)",
"status-blue": "var(--status-blue)",
"medium-dark-gray": "var(--medium-dark-gray)",
"medium-dark-green": "var(--medium-dark-green)",
"medium-dark-red": "var(--medium-dark-red)",
"medium-emerald": "var(--medium-emerald)",
"medium-gray": "var(--medium-gray)",
"medium-high-indigo": "var(--medium-high-indigo)",
"medium-indigo": "var(--medium-indigo)",
"medium-low-gray": "var(--medium-low-gray)",
"status-green": "var(--status-green)",
"status-red": "var(--status-red)",
"status-yellow": "var(--status-yellow)",
"success-background": "var(--success-background)",
"success-foreground": "var(--success-foreground)",
white: "var(--white)",
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
@ -156,27 +135,14 @@ module.exports = {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
pulseGreen: {
"0%": { boxShadow: "0 0 0 0 rgba(72, 187, 120, 0.7)" },
"100%": { boxShadow: "0 0 0 10px rgba(72, 187, 120, 0)" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
"pulse-green": "pulseGreen 1s linear",
"spin-once": "spin 1s linear 0.7",
},
borderColor: {
"red-outline": "rgba(255, 0, 0, 0.8)",
"green-outline": "rgba(72, 187, 120, 0.7)",
},
boxShadow: {
"red-outline": "0 0 5px rgba(255, 0, 0, 0.5)",
"green-outline": "0 0 5px rgba(72, 187, 120, 0.7)",
},
},
},
plugins: [
require("tailwindcss-animate"),
require("@tailwindcss/forms")({