diff --git a/src/backend/langflow/api/validate.py b/src/backend/langflow/api/validate.py index 36b954f95..3a64080a3 100644 --- a/src/backend/langflow/api/validate.py +++ b/src/backend/langflow/api/validate.py @@ -1,3 +1,5 @@ +import json + from fastapi import APIRouter, HTTPException from langflow.api.base import ( @@ -46,8 +48,8 @@ def post_validate_node(node_id: str, data: dict): node = graph.get_node(node_id) if node is not None: _ = node.build() - return str(node.params) - raise Exception(f"Node {node_id} not found") + return json.dumps({"valid": True, "params": str(node.params)}) + else: + return json.dumps({"valid": False}) except Exception as e: logger.error(e) - raise HTTPException(status_code=500, detail=str(e)) from e diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index a85623dc7..1722f2514 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -13,7 +13,7 @@ "@headlessui/react": "^1.7.10", "@heroicons/react": "^2.0.15", "@mui/material": "^5.11.9", - "@tabler/icons-react": "^2.17.0", + "@tabler/icons-react": "^2.18.0", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/line-clamp": "^0.4.4", "@testing-library/jest-dom": "^5.16.5", @@ -3930,31 +3930,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@tabler/icons": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-2.17.0.tgz", - "integrity": "sha512-UeJaylOGNRhQKyDlgZfrQ3UPSGlfVQuXcmCsTYeXioKKepibW6VZ3H36Lo1jvBTBkQD2e9m+k2NxwkztOTXwrA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/codecalm" - } - }, - "node_modules/@tabler/icons-react": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-2.17.0.tgz", - "integrity": "sha512-kuEW+qNwRqcK5iMl7qTapzX2NiMOwPg4Az01d+IZ1DIMwaZ7iKPJaIor2ihKFLPYrT9D5BZHXB8R5mSkw0FETg==", - "dependencies": { - "@tabler/icons": "2.17.0", - "prop-types": "^15.7.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/codecalm" - }, - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/@tailwindcss/forms": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz", @@ -4815,16 +4790,6 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" }, - "node_modules/@types/unist": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", - "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" - }, - "node_modules/@types/web": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.46.tgz", - "integrity": "sha512-ki0OmbjSdAEfvmy5AYWFpMkRsPW+6h4ibQ4tzk8SJsS9dkrrD3B/U1eVvdNNWxAzntjq6o2sjSia6UBCoPH+Yg==" - }, "node_modules/@types/ws": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", @@ -6309,33 +6274,6 @@ "node": ">=10" } }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/check-types": { "version": "11.2.2", "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz", @@ -6513,15 +6451,6 @@ "node": ">= 0.8" } }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/commander": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", @@ -9582,84 +9511,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hast-util-from-dom": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz", - "integrity": "sha512-t1RJW/OpJbCAJQeKi3Qrj1cAOLA0+av/iPFori112+0X7R3wng+jxLA+kXec8K4szqPRGI8vPxbbpEYvvpwaeQ==", - "dependencies": { - "hastscript": "^7.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-is-element": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz", - "integrity": "sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==", - "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-parse-selector": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", - "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", - "dependencies": { - "@types/hast": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-text": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz", - "integrity": "sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw==", - "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", - "hast-util-is-element": "^2.0.0", - "unist-util-find-after": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", - "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", - "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", - "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^3.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -14450,32 +14301,6 @@ "node": ">=6" } }, - "node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", - "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-entities/node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -15987,15 +15812,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/property-information": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.2.0.tgz", - "integrity": "sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -16633,83 +16449,6 @@ "node": ">=8" } }, - "node_modules/refractor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", - "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", - "dependencies": { - "hastscript": "^6.0.0", - "parse-entities": "^2.0.0", - "prismjs": "~1.27.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/refractor/node_modules/hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", - "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/refractor/node_modules/prismjs": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", - "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/refractor/node_modules/property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", - "dependencies": { - "xtend": "^4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -17814,15 +17553,6 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "deprecated": "Please use @jridgewell/sourcemap-codec instead" }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", diff --git a/src/frontend/package.json b/src/frontend/package.json index 316eb97a1..9a035a0ea 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -8,7 +8,7 @@ "@headlessui/react": "^1.7.10", "@heroicons/react": "^2.0.15", "@mui/material": "^5.11.9", - "@tabler/icons-react": "^2.17.0", + "@tabler/icons-react": "^2.18.0", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/line-clamp": "^0.4.4", "@testing-library/jest-dom": "^5.16.5", @@ -34,6 +34,7 @@ "react-router-dom": "^6.8.1", "react-scripts": "5.0.1", "react-syntax-highlighter": "^15.5.0", + "react-syntax-highlighter": "^15.5.0", "react-tabs": "^6.0.0", "reactflow": "^11.5.5", "rehype-mathjax": "^4.0.2", diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index 8af96387c..85e7810a1 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -1,8 +1,8 @@ -import { Cog6ToothIcon, TrashIcon } from "@heroicons/react/24/outline"; +import { BugAntIcon, Cog6ToothIcon, ExclamationCircleIcon, InformationCircleIcon, TrashIcon } from "@heroicons/react/24/outline"; import { classNames, nodeColors, nodeIcons, toNormalCase } from "../../utils"; import ParameterComponent from "./components/parameterComponent"; import { typesContext } from "../../contexts/typesContext"; -import { useContext, useState, useEffect, useRef } from "react"; +import { useContext, useState, useEffect, useRef, Fragment } from "react"; import { NodeDataType } from "../../types/flow"; import { alertContext } from "../../contexts/alertContext"; import { PopUpContext } from "../../contexts/popUpContext"; @@ -10,6 +10,7 @@ import NodeModal from "../../modals/NodeModal"; import { useCallback } from "react"; import { TabsContext } from "../../contexts/tabsContext"; import { debounce } from "../../utils"; +import Tooltip from "../../components/TooltipComponent"; export default function GenericNode({ data, selected, @@ -17,17 +18,17 @@ export default function GenericNode({ data: NodeDataType; selected: boolean; }) { - const { setErrorData } = useContext(alertContext); - const showError = useRef(true); - const { types, deleteNode } = useContext(typesContext); - const { openPopUp } = useContext(PopUpContext); - const Icon = nodeIcons[types[data.type]]; - const [validationStatus, setValidationStatus] = useState("idle"); - // State for outline color - const [isValid, setIsValid] = useState(false); - const { save } = useContext(TabsContext); - const { reactFlowInstance } = useContext(typesContext); - const [params, setParams] = useState([]); + const { setErrorData } = useContext(alertContext); + const showError = useRef(true); + const { types, deleteNode } = useContext(typesContext); + const { openPopUp } = useContext(PopUpContext); + const Icon = nodeIcons[types[data.type]]; + const [validationStatus, setValidationStatus] = useState(null); + // State for outline color + const [isValid, setIsValid] = useState(false); + const { save } = useContext(TabsContext); + const { reactFlowInstance } = useContext(typesContext); + const [params, setParams] = useState([]); useEffect(() => { if (reactFlowInstance) { @@ -46,31 +47,36 @@ export default function GenericNode({ body: JSON.stringify(reactFlowInstance.toObject()), }); - if (response.status === 200) { - setValidationStatus("success"); - } else if (response.status === 500) { - setValidationStatus("error"); - } - } catch (error) { - // console.error("Error validating node:", error); - setValidationStatus("error"); - } - }, 1000), // Adjust the debounce delay (500ms) as needed - [reactFlowInstance, data.id] - ); - useEffect(() => { - if (params.length > 0) { - validateNode(); - } - }, [params, validateNode]); + if (response.status === 200) { + let jsonResponse = await response.json(); + let jsonResponseParsed = await JSON.parse(jsonResponse); + console.log(jsonResponseParsed); + if(jsonResponseParsed.valid){ + setValidationStatus(jsonResponseParsed.params); + } else { + setValidationStatus("error"); + } + } + } catch (error) { + // console.error("Error validating node:", error); + setValidationStatus("error"); + } + }, 1000), // Adjust the debounce delay (500ms) as needed + [reactFlowInstance, data.id] + ); + useEffect(() => { + if (params.length > 0) { + validateNode(); + } + }, [params, validateNode]); - useEffect(() => { - if (validationStatus === "success") { - setIsValid(true); - } else { - setIsValid(false); - } - }, [validationStatus]); + useEffect(() => { + if (validationStatus !== "error") { + setIsValid(true); + } else { + setIsValid(false); + } + }, [validationStatus]); if (!Icon) { if (showError.current) { @@ -85,67 +91,76 @@ export default function GenericNode({ return; } - return ( -
-
-
- -
{data.type}
-
-
- - -
-
+ return ( +
+
+
+ +
{data.type}
+ {validationStatus && validationStatus !== "error" ? + + {validationStatus} +
}> + + + : <> +} +
+
+ + +
+
-
-
- {data.node.description} -
+
+
+ {data.node.description} +
<> {Object.keys(data.node.template) diff --git a/src/frontend/src/components/inputComponent/index.tsx b/src/frontend/src/components/inputComponent/index.tsx index 05be68532..67eff6abf 100644 --- a/src/frontend/src/components/inputComponent/index.tsx +++ b/src/frontend/src/components/inputComponent/index.tsx @@ -8,79 +8,79 @@ export default function InputComponent({ disabled, password, }: InputComponentType) { - const [myValue, setMyValue] = useState(value ?? ""); - const [pwdVisible, setPwdVisible] = useState(false); - useEffect(() => { - if (disabled) { - setMyValue(""); - onChange(""); - } - }, [disabled, onChange]); - return ( -
- { - setMyValue(e.target.value); - onChange(e.target.value); - }} - /> - -
- ); + const [myValue, setMyValue] = useState(value ?? ""); + const [pwdVisible, setPwdVisible] = useState(false); + useEffect(() => { + if (disabled) { + setMyValue(""); + onChange(""); + } + }, [disabled, onChange]); + return ( +
+ { + setMyValue(e.target.value); + onChange(e.target.value); + }} + /> + +
+ ); } diff --git a/src/frontend/src/components/inputFileComponent/index.tsx b/src/frontend/src/components/inputFileComponent/index.tsx index d20044571..01a500f91 100644 --- a/src/frontend/src/components/inputFileComponent/index.tsx +++ b/src/frontend/src/components/inputFileComponent/index.tsx @@ -71,7 +71,7 @@ export default function InputFileComponent({ diff --git a/src/frontend/src/components/textAreaComponent/index.tsx b/src/frontend/src/components/textAreaComponent/index.tsx index 93b0ddb62..17afe304e 100644 --- a/src/frontend/src/components/textAreaComponent/index.tsx +++ b/src/frontend/src/components/textAreaComponent/index.tsx @@ -4,57 +4,30 @@ import { PopUpContext } from "../../contexts/popUpContext"; import TextAreaModal from "../../modals/textAreaModal"; import { TextAreaComponentType } from "../../types/components"; -export default function TextAreaComponent({ - value, - onChange, - disabled, -}: TextAreaComponentType) { - const [myValue, setMyValue] = useState(value); - const { openPopUp } = useContext(PopUpContext); - useEffect(() => { - if (disabled) { - setMyValue(""); - onChange(""); - } - }, [disabled, onChange]); - return ( -
-
- { - openPopUp( - { - setMyValue(t); - onChange(t); - }} - /> - ); - }} - className={ - "truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + - (disabled ? " bg-gray-200" : "") - } - > - {myValue !== "" ? myValue : "Text empty"} - - -
-
- ); +export default function TextAreaComponent({ value, onChange, disabled }:TextAreaComponentType) { + const [myValue, setMyValue] = useState(value); + const { openPopUp } = useContext(PopUpContext); + useEffect(() => { + if (disabled) { + setMyValue(""); + onChange(""); + } + }, [disabled, onChange]); + return ( +
+
+ {openPopUp( {setMyValue(t); onChange(t);}}/>)}} + className={ + "truncate block w-full text-gray-500 dark:text-gray-100 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + + (disabled ? " bg-gray-200" : "") + } + > + {myValue !== "" ? myValue : 'Text empty'} + + +
+
+ ); } diff --git a/src/frontend/src/modals/ApiModal/index.tsx b/src/frontend/src/modals/ApiModal/index.tsx new file mode 100644 index 000000000..9c91070b3 --- /dev/null +++ b/src/frontend/src/modals/ApiModal/index.tsx @@ -0,0 +1,170 @@ +import { Dialog, Transition } from "@headlessui/react"; +import { IconCheck, IconClipboard, IconDownload } from '@tabler/icons-react'; +import { XMarkIcon, CommandLineIcon, CodeBracketSquareIcon } from "@heroicons/react/24/outline"; +import { Fragment, useContext, useRef, useState } from "react"; +import { PopUpContext } from "../../contexts/popUpContext"; +import "ace-builds/src-noconflict/mode-python"; +import "ace-builds/src-noconflict/theme-github"; +import "ace-builds/src-noconflict/theme-twilight"; +import "ace-builds/src-noconflict/ext-language_tools"; +import "ace-builds/webpack-resolver"; +import { darkContext } from "../../contexts/darkContext"; +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; +import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'; + + + +export default function ApiModal({ flowName }) { + const [open, setOpen] = useState(true); + const { dark } = useContext(darkContext); + const { closePopUp } = useContext(PopUpContext); + const [activeTab, setActiveTab] = useState(0); + const ref = useRef(); + const [isCopied, setIsCopied] = useState(false); + + const copyToClipboard = () => { + if (!navigator.clipboard || !navigator.clipboard.writeText) { + return; + } + + navigator.clipboard.writeText(tabs[activeTab].code).then(() => { + setIsCopied(true); + + setTimeout(() => { + setIsCopied(false); + }, 2000); + }); + }; + function setModalOpen(x: boolean) { + setOpen(x); + if (x === false) { + setTimeout(() => { + closePopUp(); + }, 300); + } + } + + const pythonCode = `import requests + +API_URL = "${window.location.protocol}//${window.location.host}/predict" + +def predict(message): + with open("${flowName}.json", "r") as f: + json_data = json.load(f) + payload = {'exported_flow': json_data, 'message': message} + response = requests.post(API_URL, json=payload) + return response.json() # JSON {"result": "Response"} + +print(predict("Your message"))`; + + const tabs = [ + { + name: "Python", + mode: "python", + image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png", + code: pythonCode, + }, + + ] + return ( + + + +
+ + +
+
+ + +
+ +
+
+
+
+
+
+ + Use API + +
+
+
+
+
+ {tabs.map((tab, index) => ( + + ))} +
+
+
+ +
+ + {tabs[activeTab].code} + +
+
+
+
+
+
+
+
+
+
+ ); +} diff --git a/src/frontend/src/modals/chatModal/index.tsx b/src/frontend/src/modals/chatModal/index.tsx index 50ad42b23..dfa2dd602 100644 --- a/src/frontend/src/modals/chatModal/index.tsx +++ b/src/frontend/src/modals/chatModal/index.tsx @@ -353,7 +353,7 @@ export default function ChatModal({
@@ -365,12 +365,12 @@ export default function ChatModal({
👋{" "} - + LangFlow Chat
-
+
Start a conversation and click the agent’s thoughts{" "} diff --git a/src/frontend/src/modals/importModal/buttonBox/index.tsx b/src/frontend/src/modals/importModal/buttonBox/index.tsx index b0757cdae..2386bfeb4 100644 --- a/src/frontend/src/modals/importModal/buttonBox/index.tsx +++ b/src/frontend/src/modals/importModal/buttonBox/index.tsx @@ -29,47 +29,47 @@ export default function ButtonBox({ let padding: string; let marginTop: string; let height: string; - let widht: string; + let width: string; switch (size) { case "small": bigCircle = "h-12 w-12"; smallCircle = "h-8 w-8"; titleFontSize = "text-sm"; descriptionFontSize = "text-xs"; - padding = "p-2"; + padding = "p-2 py-3"; marginTop = "mt-2"; height = "h-36"; - widht = "w-32"; + width = "w-32"; break; case "medium": bigCircle = "h-16 w-16"; smallCircle = "h-12 w-12"; titleFontSize = "text-base"; descriptionFontSize = "text-sm"; - padding = "p-4"; + padding = "p-4 py-5"; marginTop = "mt-3"; height = "h-44"; - widht = "w-36"; + width = "w-36"; break; case "big": bigCircle = "h-20 w-20"; smallCircle = "h-16 w-16"; titleFontSize = "text-lg"; descriptionFontSize = "text-sm"; - padding = "p-8"; + padding = "p-8 py-10"; marginTop = "mt-6"; height = "h-56"; - widht = "w-44"; + width = "w-44"; break; default: bigCircle = "h-20 w-20"; smallCircle = "h-16 w-16"; titleFontSize = "text-lg"; descriptionFontSize = "text-sm"; - padding = "p-8"; + padding = "p-8 py-10"; marginTop = "mt-6"; height = "h-56"; - widht = "w-44"; + width = "w-44"; break; } return ( @@ -77,22 +77,23 @@ export default function ButtonBox({
-
{icon}
+

{title}

-
-
{title}
- {/*
- {deactivate ? "Coming soon" : description} -
*/}
-
diff --git a/src/frontend/src/modals/importModal/index.tsx b/src/frontend/src/modals/importModal/index.tsx index d351b847a..1405a3c68 100644 --- a/src/frontend/src/modals/importModal/index.tsx +++ b/src/frontend/src/modals/importModal/index.tsx @@ -82,7 +82,7 @@ export default function ImportModal() { leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" > - +
- )}
@@ -152,7 +130,7 @@ export default function ImportModal() {
diff --git a/src/frontend/src/pages/FlowPage/components/tabsManagerComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/tabsManagerComponent/index.tsx index 4873c9a6d..06787743b 100644 --- a/src/frontend/src/pages/FlowPage/components/tabsManagerComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/tabsManagerComponent/index.tsx @@ -8,6 +8,7 @@ import { ArrowDownTrayIcon, ArrowUpTrayIcon, BellIcon, + CodeBracketSquareIcon, MoonIcon, SunIcon, } from "@heroicons/react/24/outline"; @@ -17,6 +18,7 @@ import { alertContext } from "../../../../contexts/alertContext"; import ImportModal from "../../../../modals/importModal"; import ExportModal from "../../../../modals/exportModal"; import { typesContext } from "../../../../contexts/typesContext"; +import ApiModal from "../../../../modals/ApiModal"; export default function TabsManagerComponent() { const { flows, addFlow, tabIndex, setTabIndex, uploadFlow, downloadFlow } = @@ -55,20 +57,26 @@ export default function TabsManagerComponent() { flow={null} />
+