Refactor: Revamp utils Folder Structure (#1940)
This PR focuses on a comprehensive refactor of the utils folder to improve code organization, readability, and maintainability.
This commit is contained in:
commit
9141bbbb86
66 changed files with 14859 additions and 13671 deletions
|
|
@ -17,7 +17,7 @@ export class Rds extends Construct {
|
||||||
const { vpc, dbSG } = props;
|
const { vpc, dbSG } = props;
|
||||||
const instanceType = ec2.InstanceType.of(
|
const instanceType = ec2.InstanceType.of(
|
||||||
ec2.InstanceClass.BURSTABLE4_GRAVITON,
|
ec2.InstanceClass.BURSTABLE4_GRAVITON,
|
||||||
ec2.InstanceSize.MEDIUM
|
ec2.InstanceSize.MEDIUM,
|
||||||
);
|
);
|
||||||
|
|
||||||
// RDSのパスワードを自動生成してSecrets Managerに格納
|
// RDSのパスワードを自動生成してSecrets Managerに格納
|
||||||
|
|
@ -33,11 +33,11 @@ export class Rds extends Construct {
|
||||||
engine: rds.DatabaseClusterEngine.auroraMysql({
|
engine: rds.DatabaseClusterEngine.auroraMysql({
|
||||||
version: rds.AuroraMysqlEngineVersion.of(
|
version: rds.AuroraMysqlEngineVersion.of(
|
||||||
"8.0.mysql_aurora.3.05.2",
|
"8.0.mysql_aurora.3.05.2",
|
||||||
"8.0"
|
"8.0",
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
description: "for-langflow",
|
description: "for-langflow",
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
clusterParameterGroup.bindToCluster({});
|
clusterParameterGroup.bindToCluster({});
|
||||||
|
|
||||||
|
|
@ -49,11 +49,11 @@ export class Rds extends Construct {
|
||||||
engine: rds.DatabaseClusterEngine.auroraMysql({
|
engine: rds.DatabaseClusterEngine.auroraMysql({
|
||||||
version: rds.AuroraMysqlEngineVersion.of(
|
version: rds.AuroraMysqlEngineVersion.of(
|
||||||
"8.0.mysql_aurora.3.05.2",
|
"8.0.mysql_aurora.3.05.2",
|
||||||
"8.0"
|
"8.0",
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
description: "for-langflow",
|
description: "for-langflow",
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
instanceParameterGroup.bindToInstance({});
|
instanceParameterGroup.bindToInstance({});
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ export class Rds extends Construct {
|
||||||
engine: rds.DatabaseClusterEngine.auroraMysql({
|
engine: rds.DatabaseClusterEngine.auroraMysql({
|
||||||
version: rds.AuroraMysqlEngineVersion.of(
|
version: rds.AuroraMysqlEngineVersion.of(
|
||||||
"8.0.mysql_aurora.3.05.2",
|
"8.0.mysql_aurora.3.05.2",
|
||||||
"8.0"
|
"8.0",
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
storageEncrypted: true,
|
storageEncrypted: true,
|
||||||
|
|
|
||||||
26627
src/frontend/package-lock.json
generated
26627
src/frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,137 +1,137 @@
|
||||||
{
|
{
|
||||||
"name": "langflow",
|
"name": "langflow",
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.7.17",
|
"@headlessui/react": "^1.7.17",
|
||||||
"@hookform/resolvers": "^3.3.4",
|
"@hookform/resolvers": "^3.3.4",
|
||||||
"@million/lint": "^0.0.73",
|
"@million/lint": "^0.0.73",
|
||||||
"@radix-ui/react-accordion": "^1.1.2",
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-checkbox": "^1.0.4",
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-dialog": "^1.0.4",
|
"@radix-ui/react-dialog": "^1.0.4",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||||
"@radix-ui/react-form": "^0.0.3",
|
"@radix-ui/react-form": "^0.0.3",
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.0.2",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
"@radix-ui/react-menubar": "^1.0.3",
|
"@radix-ui/react-menubar": "^1.0.3",
|
||||||
"@radix-ui/react-popover": "^1.0.6",
|
"@radix-ui/react-popover": "^1.0.6",
|
||||||
"@radix-ui/react-progress": "^1.0.3",
|
"@radix-ui/react-progress": "^1.0.3",
|
||||||
"@radix-ui/react-select": "^2.0.0",
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
"@radix-ui/react-separator": "^1.0.3",
|
"@radix-ui/react-separator": "^1.0.3",
|
||||||
"@radix-ui/react-slot": "^1.0.2",
|
"@radix-ui/react-slot": "^1.0.2",
|
||||||
"@radix-ui/react-switch": "^1.0.3",
|
"@radix-ui/react-switch": "^1.0.3",
|
||||||
"@radix-ui/react-tabs": "^1.0.4",
|
"@radix-ui/react-tabs": "^1.0.4",
|
||||||
"@radix-ui/react-tooltip": "^1.0.6",
|
"@radix-ui/react-tooltip": "^1.0.6",
|
||||||
"@tabler/icons-react": "^2.32.0",
|
"@tabler/icons-react": "^2.32.0",
|
||||||
"@tailwindcss/forms": "^0.5.6",
|
"@tailwindcss/forms": "^0.5.6",
|
||||||
"@tailwindcss/line-clamp": "^0.4.4",
|
"@tailwindcss/line-clamp": "^0.4.4",
|
||||||
"@types/axios": "^0.14.0",
|
"@types/axios": "^0.14.0",
|
||||||
"ace-builds": "^1.24.1",
|
"ace-builds": "^1.24.1",
|
||||||
"ag-grid-community": "^31.2.1",
|
"ag-grid-community": "^31.2.1",
|
||||||
"ag-grid-react": "^31.2.1",
|
"ag-grid-react": "^31.2.1",
|
||||||
"ansi-to-html": "^0.7.2",
|
"ansi-to-html": "^0.7.2",
|
||||||
"axios": "^1.5.0",
|
"axios": "^1.5.0",
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"class-variance-authority": "^0.6.1",
|
"class-variance-authority": "^0.6.1",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"cmdk": "^1.0.0",
|
"cmdk": "^1.0.0",
|
||||||
"dompurify": "^3.0.5",
|
"dompurify": "^3.0.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"esbuild": "^0.17.19",
|
"esbuild": "^0.17.19",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"framer-motion": "^11.0.6",
|
"framer-motion": "^11.0.6",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lucide-react": "^0.331.0",
|
"lucide-react": "^0.331.0",
|
||||||
"million": "^3.0.6",
|
"million": "^3.0.6",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"openseadragon": "^4.1.1",
|
"openseadragon": "^4.1.1",
|
||||||
"playwright": "^1.42.0",
|
"playwright": "^1.42.0",
|
||||||
"react": "^18.2.21",
|
"react": "^18.2.21",
|
||||||
"react-ace": "^10.1.0",
|
"react-ace": "^10.1.0",
|
||||||
"react-cookie": "^4.1.1",
|
"react-cookie": "^4.1.1",
|
||||||
"react-dom": "^18.2.21",
|
"react-dom": "^18.2.21",
|
||||||
"react-error-boundary": "^4.0.11",
|
"react-error-boundary": "^4.0.11",
|
||||||
"react-hook-form": "^7.51.4",
|
"react-hook-form": "^7.51.4",
|
||||||
"react-icons": "^5.0.1",
|
"react-icons": "^5.0.1",
|
||||||
"react-laag": "^2.0.5",
|
"react-laag": "^2.0.5",
|
||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^8.0.7",
|
||||||
"react-pdf": "^7.7.1",
|
"react-pdf": "^7.7.1",
|
||||||
"react-router-dom": "^6.15.0",
|
"react-router-dom": "^6.15.0",
|
||||||
"react-syntax-highlighter": "^15.5.0",
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"react18-json-view": "^0.2.3",
|
"react18-json-view": "^0.2.3",
|
||||||
"reactflow": "^11.9.2",
|
"reactflow": "^11.9.2",
|
||||||
"rehype-mathjax": "^4.0.3",
|
"rehype-mathjax": "^4.0.3",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-math": "^5.1.1",
|
"remark-math": "^5.1.1",
|
||||||
"shadcn-ui": "^0.2.3",
|
"shadcn-ui": "^0.2.3",
|
||||||
"short-unique-id": "^4.4.4",
|
"short-unique-id": "^4.4.4",
|
||||||
"tailwind-merge": "^1.14.0",
|
"tailwind-merge": "^1.14.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"vite-plugin-svgr": "^3.2.0",
|
"vite-plugin-svgr": "^3.2.0",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
"zod": "^3.23.7",
|
"zod": "^3.23.7",
|
||||||
"zustand": "^4.4.7"
|
"zustand": "^4.4.7"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:docker": "vite --host 0.0.0.0",
|
"dev:docker": "vite --host 0.0.0.0",
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"serve": "vite preview",
|
"serve": "vite preview",
|
||||||
"format": "npx prettier --write \"{docs,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore",
|
"format": "npx prettier --write \"{docs,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore",
|
||||||
"type-check": "tsc --noEmit --pretty --project tsconfig.json && vite"
|
"type-check": "tsc --noEmit --pretty --project tsconfig.json && vite"
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
"pre-commit": "npx pretty-quick --staged"
|
"pre-commit": "npx pretty-quick --staged"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
"react-app",
|
"react-app",
|
||||||
"react-app/jest"
|
"react-app/jest"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
">0.2%",
|
">0.2%",
|
||||||
"not dead",
|
"not dead",
|
||||||
"not op_mini all"
|
"not op_mini all"
|
||||||
],
|
],
|
||||||
"development": [
|
"development": [
|
||||||
"last 1 chrome version",
|
"last 1 chrome version",
|
||||||
"last 1 firefox version",
|
"last 1 firefox version",
|
||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"proxy": "http://127.0.0.1:7860",
|
"proxy": "http://127.0.0.1:7860",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.44.0",
|
"@playwright/test": "^1.44.0",
|
||||||
"@swc/cli": "^0.1.62",
|
"@swc/cli": "^0.1.62",
|
||||||
"@swc/core": "^1.3.80",
|
"@swc/core": "^1.3.80",
|
||||||
"@tailwindcss/typography": "^0.5.9",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"@types/jest": "^27.5.2",
|
"@types/jest": "^27.5.2",
|
||||||
"@types/lodash": "^4.14.197",
|
"@types/lodash": "^4.14.197",
|
||||||
"@types/node": "^16.18.46",
|
"@types/node": "^16.18.46",
|
||||||
"@types/react": "^18.2.21",
|
"@types/react": "^18.2.21",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.7",
|
||||||
"@types/uuid": "^9.0.2",
|
"@types/uuid": "^9.0.2",
|
||||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||||
"autoprefixer": "^10.4.15",
|
"autoprefixer": "^10.4.15",
|
||||||
"daisyui": "^4.0.4",
|
"daisyui": "^4.0.4",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"postcss": "^8.4.29",
|
"postcss": "^8.4.29",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"prettier-plugin-organize-imports": "^3.2.3",
|
"prettier-plugin-organize-imports": "^3.2.3",
|
||||||
"prettier-plugin-tailwindcss": "^0.3.0",
|
"prettier-plugin-tailwindcss": "^0.3.0",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
"simple-git-hooks": "^2.11.1",
|
"simple-git-hooks": "^2.11.1",
|
||||||
"tailwindcss": "^3.3.3",
|
"tailwindcss": "^3.3.3",
|
||||||
"tailwindcss-dotted-background": "^1.1.0",
|
"tailwindcss-dotted-background": "^1.1.0",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"ua-parser-js": "^1.0.37",
|
"ua-parser-js": "^1.0.37",
|
||||||
"vite": "^4.5.2"
|
"vite": "^4.5.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,15 @@ import useAlertStore from "./stores/alertStore";
|
||||||
import { useDarkStore } from "./stores/darkStore";
|
import { useDarkStore } from "./stores/darkStore";
|
||||||
import useFlowsManagerStore from "./stores/flowsManagerStore";
|
import useFlowsManagerStore from "./stores/flowsManagerStore";
|
||||||
import { useFolderStore } from "./stores/foldersStore";
|
import { useFolderStore } from "./stores/foldersStore";
|
||||||
import { useGlobalVariablesStore } from "./stores/globalVariables";
|
import { useGlobalVariablesStore } from "./stores/globalVariablesStore/globalVariables";
|
||||||
import { useStoreStore } from "./stores/storeStore";
|
import { useStoreStore } from "./stores/storeStore";
|
||||||
import { useTypesStore } from "./stores/typesStore";
|
import { useTypesStore } from "./stores/typesStore";
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const removeFromTempNotificationList = useAlertStore(
|
const removeFromTempNotificationList = useAlertStore(
|
||||||
(state) => state.removeFromTempNotificationList
|
(state) => state.removeFromTempNotificationList,
|
||||||
);
|
);
|
||||||
const tempNotificationList = useAlertStore(
|
const tempNotificationList = useAlertStore(
|
||||||
(state) => state.tempNotificationList
|
(state) => state.tempNotificationList,
|
||||||
);
|
);
|
||||||
const [fetchError, setFetchError] = useState(false);
|
const [fetchError, setFetchError] = useState(false);
|
||||||
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
||||||
|
|
@ -46,7 +46,7 @@ export default function App() {
|
||||||
const refreshVersion = useDarkStore((state) => state.refreshVersion);
|
const refreshVersion = useDarkStore((state) => state.refreshVersion);
|
||||||
const refreshStars = useDarkStore((state) => state.refreshStars);
|
const refreshStars = useDarkStore((state) => state.refreshStars);
|
||||||
const setGlobalVariables = useGlobalVariablesStore(
|
const setGlobalVariables = useGlobalVariablesStore(
|
||||||
(state) => state.setGlobalVariables
|
(state) => state.setGlobalVariables,
|
||||||
);
|
);
|
||||||
const checkHasStore = useStoreStore((state) => state.checkHasStore);
|
const checkHasStore = useStoreStore((state) => state.checkHasStore);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,14 @@ export default function ImageViewer({ image }) {
|
||||||
const fullPageButton = document.getElementById("full-page-button");
|
const fullPageButton = document.getElementById("full-page-button");
|
||||||
|
|
||||||
zoomInButton!.addEventListener("click", () =>
|
zoomInButton!.addEventListener("click", () =>
|
||||||
viewer.viewport.zoomBy(1.2)
|
viewer.viewport.zoomBy(1.2),
|
||||||
);
|
);
|
||||||
zoomOutButton!.addEventListener("click", () =>
|
zoomOutButton!.addEventListener("click", () =>
|
||||||
viewer.viewport.zoomBy(0.8)
|
viewer.viewport.zoomBy(0.8),
|
||||||
);
|
);
|
||||||
homeButton!.addEventListener("click", () => viewer.viewport.goHome());
|
homeButton!.addEventListener("click", () => viewer.viewport.goHome());
|
||||||
fullPageButton!.addEventListener("click", () =>
|
fullPageButton!.addEventListener("click", () =>
|
||||||
viewer.setFullScreen(true)
|
viewer.setFullScreen(true),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Optionally, you can set additional viewer options here
|
// Optionally, you can set additional viewer options here
|
||||||
|
|
@ -47,16 +47,16 @@ export default function ImageViewer({ image }) {
|
||||||
return () => {
|
return () => {
|
||||||
viewer.destroy();
|
viewer.destroy();
|
||||||
zoomInButton!.removeEventListener("click", () =>
|
zoomInButton!.removeEventListener("click", () =>
|
||||||
viewer.viewport.zoomBy(1.2)
|
viewer.viewport.zoomBy(1.2),
|
||||||
);
|
);
|
||||||
zoomOutButton!.removeEventListener("click", () =>
|
zoomOutButton!.removeEventListener("click", () =>
|
||||||
viewer.viewport.zoomBy(0.8)
|
viewer.viewport.zoomBy(0.8),
|
||||||
);
|
);
|
||||||
homeButton!.removeEventListener("click", () =>
|
homeButton!.removeEventListener("click", () =>
|
||||||
viewer.viewport.goHome()
|
viewer.viewport.goHome(),
|
||||||
);
|
);
|
||||||
fullPageButton!.removeEventListener("click", () =>
|
fullPageButton!.removeEventListener("click", () =>
|
||||||
viewer.setFullScreen(true)
|
viewer.setFullScreen(true),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export default function AccordionComponent({
|
||||||
sideBar,
|
sideBar,
|
||||||
}: AccordionComponentType): JSX.Element {
|
}: AccordionComponentType): JSX.Element {
|
||||||
const [value, setValue] = useState(
|
const [value, setValue] = useState(
|
||||||
open.length === 0 ? "" : getOpenAccordion()
|
open.length === 0 ? "" : getOpenAccordion(),
|
||||||
);
|
);
|
||||||
|
|
||||||
function getOpenAccordion(): string {
|
function getOpenAccordion(): string {
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@ import { useState } from "react";
|
||||||
import { registerGlobalVariable } from "../../controllers/API";
|
import { registerGlobalVariable } from "../../controllers/API";
|
||||||
import BaseModal from "../../modals/baseModal";
|
import BaseModal from "../../modals/baseModal";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import { useGlobalVariablesStore } from "../../stores/globalVariables";
|
import { useGlobalVariablesStore } from "../../stores/globalVariablesStore/globalVariables";
|
||||||
import { useTypesStore } from "../../stores/typesStore";
|
import { useTypesStore } from "../../stores/typesStore";
|
||||||
import { ResponseErrorDetailAPI } from "../../types/api";
|
import { ResponseErrorDetailAPI } from "../../types/api";
|
||||||
import { sortByName } from "../../utils/utils";
|
|
||||||
import ForwardedIconComponent from "../genericIconComponent";
|
import ForwardedIconComponent from "../genericIconComponent";
|
||||||
import InputComponent from "../inputComponent";
|
import InputComponent from "../inputComponent";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { Input } from "../ui/input";
|
import { Input } from "../ui/input";
|
||||||
import { Label } from "../ui/label";
|
import { Label } from "../ui/label";
|
||||||
import { Textarea } from "../ui/textarea";
|
import { Textarea } from "../ui/textarea";
|
||||||
|
import sortByName from "./utils/sort-by-name";
|
||||||
|
|
||||||
//TODO IMPLEMENT FORM LOGIC
|
//TODO IMPLEMENT FORM LOGIC
|
||||||
|
|
||||||
|
|
@ -24,19 +24,19 @@ export default function AddNewVariableButton({ children }): JSX.Element {
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
const componentFields = useTypesStore((state) => state.ComponentFields);
|
const componentFields = useTypesStore((state) => state.ComponentFields);
|
||||||
const unavaliableFields = new Set(
|
const unavaliableFields = new Set(
|
||||||
Object.keys(useGlobalVariablesStore((state) => state.unavaliableFields))
|
Object.keys(useGlobalVariablesStore((state) => state.unavaliableFields)),
|
||||||
);
|
);
|
||||||
|
|
||||||
const availableFields = () => {
|
const availableFields = () => {
|
||||||
const fields = Array.from(componentFields).filter(
|
const fields = Array.from(componentFields).filter(
|
||||||
(field) => !unavaliableFields.has(field)
|
(field) => !unavaliableFields.has(field),
|
||||||
);
|
);
|
||||||
|
|
||||||
return sortByName(fields);
|
return sortByName(fields);
|
||||||
};
|
};
|
||||||
|
|
||||||
const addGlobalVariable = useGlobalVariablesStore(
|
const addGlobalVariable = useGlobalVariablesStore(
|
||||||
(state) => state.addGlobalVariable
|
(state) => state.addGlobalVariable,
|
||||||
);
|
);
|
||||||
|
|
||||||
function handleSaveVariable() {
|
function handleSaveVariable() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
export default function sortByName(stringList: string[]): string[] {
|
||||||
|
return stringList.sort((a, b) => a.localeCompare(b));
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@ import { storeComponent } from "../../types/store";
|
||||||
import cloneFLowWithParent, {
|
import cloneFLowWithParent, {
|
||||||
getInputsAndOutputs,
|
getInputsAndOutputs,
|
||||||
} from "../../utils/storeUtils";
|
} from "../../utils/storeUtils";
|
||||||
import { cn, convertTestName } from "../../utils/utils";
|
import { cn } from "../../utils/utils";
|
||||||
import IconComponent from "../genericIconComponent";
|
import IconComponent from "../genericIconComponent";
|
||||||
import ShadTooltip from "../shadTooltipComponent";
|
import ShadTooltip from "../shadTooltipComponent";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
|
@ -27,6 +27,7 @@ import {
|
||||||
import { Checkbox } from "../ui/checkbox";
|
import { Checkbox } from "../ui/checkbox";
|
||||||
import { FormControl, FormField } from "../ui/form";
|
import { FormControl, FormField } from "../ui/form";
|
||||||
import Loading from "../ui/loading";
|
import Loading from "../ui/loading";
|
||||||
|
import { convertTestName } from "./utils/convert-test-name";
|
||||||
import DragCardComponent from "./components/dragCardComponent";
|
import DragCardComponent from "./components/dragCardComponent";
|
||||||
|
|
||||||
export default function CollectionCardComponent({
|
export default function CollectionCardComponent({
|
||||||
|
|
@ -59,11 +60,11 @@ export default function CollectionCardComponent({
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [loadingLike, setLoadingLike] = useState(false);
|
const [loadingLike, setLoadingLike] = useState(false);
|
||||||
const [liked_by_user, setLiked_by_user] = useState(
|
const [liked_by_user, setLiked_by_user] = useState(
|
||||||
data?.liked_by_user ?? false
|
data?.liked_by_user ?? false,
|
||||||
);
|
);
|
||||||
const [likes_count, setLikes_count] = useState(data?.liked_by_count ?? 0);
|
const [likes_count, setLikes_count] = useState(data?.liked_by_count ?? 0);
|
||||||
const [downloads_count, setDownloads_count] = useState(
|
const [downloads_count, setDownloads_count] = useState(
|
||||||
data?.downloads_count ?? 0
|
data?.downloads_count ?? 0,
|
||||||
);
|
);
|
||||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||||
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
||||||
|
|
@ -74,12 +75,12 @@ export default function CollectionCardComponent({
|
||||||
const [openPlayground, setOpenPlayground] = useState(false);
|
const [openPlayground, setOpenPlayground] = useState(false);
|
||||||
const [openDelete, setOpenDelete] = useState(false);
|
const [openDelete, setOpenDelete] = useState(false);
|
||||||
const setCurrentFlowId = useFlowsManagerStore(
|
const setCurrentFlowId = useFlowsManagerStore(
|
||||||
(state) => state.setCurrentFlowId
|
(state) => state.setCurrentFlowId,
|
||||||
);
|
);
|
||||||
const [loadingPlayground, setLoadingPlayground] = useState(false);
|
const [loadingPlayground, setLoadingPlayground] = useState(false);
|
||||||
|
|
||||||
const selectedFlowsComponentsCards = useFlowsManagerStore(
|
const selectedFlowsComponentsCards = useFlowsManagerStore(
|
||||||
(state) => state.selectedFlowsComponentsCards
|
(state) => state.selectedFlowsComponentsCards,
|
||||||
);
|
);
|
||||||
|
|
||||||
const name = data.is_component ? "Component" : "Flow";
|
const name = data.is_component ? "Component" : "Flow";
|
||||||
|
|
@ -219,7 +220,7 @@ export default function CollectionCardComponent({
|
||||||
"group relative flex min-h-[11rem] flex-col justify-between overflow-hidden transition-all hover:bg-muted/50 hover:shadow-md hover:dark:bg-[#ffffff10]",
|
"group relative flex min-h-[11rem] flex-col justify-between overflow-hidden transition-all hover:bg-muted/50 hover:shadow-md hover:dark:bg-[#ffffff10]",
|
||||||
disabled ? "pointer-events-none opacity-50" : "",
|
disabled ? "pointer-events-none opacity-50" : "",
|
||||||
onClick ? "cursor-pointer" : "",
|
onClick ? "cursor-pointer" : "",
|
||||||
isSelectedCard ? "border border-selected" : ""
|
isSelectedCard ? "border border-selected" : "",
|
||||||
)}
|
)}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
|
|
@ -232,7 +233,7 @@ export default function CollectionCardComponent({
|
||||||
"visible flex-shrink-0",
|
"visible flex-shrink-0",
|
||||||
data.is_component
|
data.is_component
|
||||||
? "mx-0.5 h-6 w-6 text-component-icon"
|
? "mx-0.5 h-6 w-6 text-component-icon"
|
||||||
: "h-7 w-7 flex-shrink-0 text-flow-icon"
|
: "h-7 w-7 flex-shrink-0 text-flow-icon",
|
||||||
)}
|
)}
|
||||||
name={data.is_component ? "ToyBrick" : "Group"}
|
name={data.is_component ? "ToyBrick" : "Group"}
|
||||||
/>
|
/>
|
||||||
|
|
@ -427,7 +428,7 @@ export default function CollectionCardComponent({
|
||||||
name="Trash2"
|
name="Trash2"
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-5 w-5",
|
"h-5 w-5",
|
||||||
!authorized ? " text-ring" : ""
|
!authorized ? " text-ring" : "",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -462,7 +463,7 @@ export default function CollectionCardComponent({
|
||||||
liked_by_user
|
liked_by_user
|
||||||
? "fill-destructive stroke-destructive"
|
? "fill-destructive stroke-destructive"
|
||||||
: "",
|
: "",
|
||||||
!authorized ? " text-ring" : ""
|
!authorized ? " text-ring" : "",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -500,7 +501,7 @@ export default function CollectionCardComponent({
|
||||||
}
|
}
|
||||||
className={cn(
|
className={cn(
|
||||||
loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
|
loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
|
||||||
!authorized ? " text-ring" : ""
|
!authorized ? " text-ring" : "",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function convertTestName(name: string): string {
|
||||||
|
return name.replace(/ /g, "-").toLowerCase();
|
||||||
|
}
|
||||||
|
|
@ -65,7 +65,7 @@ export default function CardsWrapComponent({
|
||||||
"h-full w-full",
|
"h-full w-full",
|
||||||
isDragging
|
isDragging
|
||||||
? "mb-36 flex flex-col items-center justify-center gap-4 text-2xl font-light"
|
? "mb-36 flex flex-col items-center justify-center gap-4 text-2xl font-light"
|
||||||
: ""
|
: "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{isDragging ? (
|
{isDragging ? (
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ export default function FlowToolbar(): JSX.Element {
|
||||||
"relative inline-flex h-full w-full items-center justify-center gap-[4px] bg-muted px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-background hover:bg-hover ",
|
"relative inline-flex h-full w-full items-center justify-center gap-[4px] bg-muted px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-background hover:bg-hover ",
|
||||||
!hasApiKey || !validApiKey || !hasStore
|
!hasApiKey || !validApiKey || !hasStore
|
||||||
? " button-disable text-muted-foreground "
|
? " button-disable text-muted-foreground "
|
||||||
: ""
|
: "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ForwardedIconComponent
|
<ForwardedIconComponent
|
||||||
|
|
@ -59,14 +59,14 @@ export default function FlowToolbar(): JSX.Element {
|
||||||
"-m-0.5 -ml-1 h-6 w-6",
|
"-m-0.5 -ml-1 h-6 w-6",
|
||||||
!hasApiKey || !validApiKey || !hasStore
|
!hasApiKey || !validApiKey || !hasStore
|
||||||
? "extra-side-bar-save-disable"
|
? "extra-side-bar-save-disable"
|
||||||
: ""
|
: "",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
Share
|
Share
|
||||||
</button>
|
</button>
|
||||||
</ShareModal>
|
</ShareModal>
|
||||||
),
|
),
|
||||||
[hasApiKey, validApiKey, currentFlow, hasStore]
|
[hasApiKey, validApiKey, currentFlow, hasStore],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -118,7 +118,7 @@ export default function FlowToolbar(): JSX.Element {
|
||||||
<ApiModal flow={currentFlow}>
|
<ApiModal flow={currentFlow}>
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover"
|
"relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ForwardedIconComponent
|
<ForwardedIconComponent
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,7 @@ export default function CodeTabsComponent({
|
||||||
<div className="api-modal-according-display">
|
<div className="api-modal-according-display">
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"h-[70vh] w-full overflow-y-auto overflow-x-hidden rounded-lg bg-muted custom-scroll"
|
"h-[70vh] w-full overflow-y-auto overflow-x-hidden rounded-lg bg-muted custom-scroll",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{data?.map((node: any, i) => (
|
{data?.map((node: any, i) => (
|
||||||
|
|
@ -275,8 +275,8 @@ export default function CodeTabsComponent({
|
||||||
.show &&
|
.show &&
|
||||||
LANGFLOW_SUPPORTED_TYPES.has(
|
LANGFLOW_SUPPORTED_TYPES.has(
|
||||||
node.data.node.template[templateField]
|
node.data.node.template[templateField]
|
||||||
.type
|
.type,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
.map((templateField, indx) => {
|
.map((templateField, indx) => {
|
||||||
return (
|
return (
|
||||||
|
|
@ -334,7 +334,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -380,7 +380,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -433,7 +433,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -470,7 +470,7 @@ export default function CodeTabsComponent({
|
||||||
e,
|
e,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
|
|
@ -501,7 +501,7 @@ export default function CodeTabsComponent({
|
||||||
].fileTypes
|
].fileTypes
|
||||||
}
|
}
|
||||||
onFileChange={(
|
onFileChange={(
|
||||||
value: any
|
value: any,
|
||||||
) => {
|
) => {
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
|
|
@ -554,7 +554,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -594,7 +594,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
value={
|
value={
|
||||||
|
|
@ -656,7 +656,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -702,7 +702,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -748,7 +748,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -780,8 +780,8 @@ export default function CodeTabsComponent({
|
||||||
].value,
|
].value,
|
||||||
type(
|
type(
|
||||||
node,
|
node,
|
||||||
templateField
|
templateField,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
duplicateKey={
|
duplicateKey={
|
||||||
|
|
@ -790,15 +790,15 @@ export default function CodeTabsComponent({
|
||||||
onChange={(target) => {
|
onChange={(target) => {
|
||||||
const valueToNumbers =
|
const valueToNumbers =
|
||||||
convertValuesToNumbers(
|
convertValuesToNumbers(
|
||||||
target
|
target,
|
||||||
);
|
);
|
||||||
node.data.node!.template[
|
node.data.node!.template[
|
||||||
templateField
|
templateField
|
||||||
].value = valueToNumbers;
|
].value = valueToNumbers;
|
||||||
setErrorDuplicateKey(
|
setErrorDuplicateKey(
|
||||||
hasDuplicateKeys(
|
hasDuplicateKeys(
|
||||||
valueToNumbers
|
valueToNumbers,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
setData((old) => {
|
setData((old) => {
|
||||||
let newInputList =
|
let newInputList =
|
||||||
|
|
@ -815,7 +815,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
isList={
|
isList={
|
||||||
|
|
@ -865,7 +865,7 @@ export default function CodeTabsComponent({
|
||||||
target,
|
target,
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ function CsvOutputComponent({
|
||||||
if (file) {
|
if (file) {
|
||||||
const { rowData: data, colDefs: columns } = convertCSVToData(
|
const { rowData: data, colDefs: columns } = convertCSVToData(
|
||||||
file,
|
file,
|
||||||
separator
|
separator,
|
||||||
);
|
);
|
||||||
setRowData(data);
|
setRowData(data);
|
||||||
setColDefs(columns);
|
setColDefs(columns);
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,9 @@ const CustomInputPopover = ({
|
||||||
(selectedOption !== "" || !onChange) && setSelectedOption
|
(selectedOption !== "" || !onChange) && setSelectedOption
|
||||||
? selectedOption
|
? selectedOption
|
||||||
: (selectedOptions?.length !== 0 || !onChange) &&
|
: (selectedOptions?.length !== 0 || !onChange) &&
|
||||||
setSelectedOptions
|
setSelectedOptions
|
||||||
? selectedOptions?.join(", ")
|
? selectedOptions?.join(", ")
|
||||||
: value
|
: value
|
||||||
}
|
}
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
@ -96,7 +96,7 @@ const CustomInputPopover = ({
|
||||||
(password && !(setSelectedOption || setSelectedOptions))
|
(password && !(setSelectedOption || setSelectedOptions))
|
||||||
? "pr-8"
|
? "pr-8"
|
||||||
: "",
|
: "",
|
||||||
className!
|
className!,
|
||||||
)}
|
)}
|
||||||
placeholder={password && editNode ? "Key" : placeholder}
|
placeholder={password && editNode ? "Key" : placeholder}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
|
|
@ -134,15 +134,15 @@ const CustomInputPopover = ({
|
||||||
onSelect={(currentValue) => {
|
onSelect={(currentValue) => {
|
||||||
setSelectedOption &&
|
setSelectedOption &&
|
||||||
setSelectedOption(
|
setSelectedOption(
|
||||||
currentValue === selectedOption ? "" : currentValue
|
currentValue === selectedOption ? "" : currentValue,
|
||||||
);
|
);
|
||||||
setSelectedOptions &&
|
setSelectedOptions &&
|
||||||
setSelectedOptions(
|
setSelectedOptions(
|
||||||
selectedOptions?.includes(currentValue)
|
selectedOptions?.includes(currentValue)
|
||||||
? selectedOptions.filter(
|
? selectedOptions.filter(
|
||||||
(item) => item !== currentValue
|
(item) => item !== currentValue,
|
||||||
)
|
)
|
||||||
: [...selectedOptions, currentValue]
|
: [...selectedOptions, currentValue],
|
||||||
);
|
);
|
||||||
!setSelectedOptions && setShowOptions(false);
|
!setSelectedOptions && setShowOptions(false);
|
||||||
}}
|
}}
|
||||||
|
|
@ -155,7 +155,7 @@ const CustomInputPopover = ({
|
||||||
selectedOption === option ||
|
selectedOption === option ||
|
||||||
selectedOptions?.includes(option)
|
selectedOptions?.includes(option)
|
||||||
? "opacity-100"
|
? "opacity-100"
|
||||||
: "opacity-0"
|
: "opacity-0",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="absolute opacity-100 transition-all group-hover:opacity-0">
|
<div className="absolute opacity-100 transition-all group-hover:opacity-0">
|
||||||
|
|
|
||||||
|
|
@ -51,14 +51,14 @@ const CustomInputPopoverObject = ({
|
||||||
? options.find((option) => option.id === selectedOption)?.name ||
|
? options.find((option) => option.id === selectedOption)?.name ||
|
||||||
""
|
""
|
||||||
: (selectedOptions?.length !== 0 || !onChange) &&
|
: (selectedOptions?.length !== 0 || !onChange) &&
|
||||||
setSelectedOptions
|
setSelectedOptions
|
||||||
? selectedOptions
|
? selectedOptions
|
||||||
.map(
|
.map(
|
||||||
(optionId) =>
|
(optionId) =>
|
||||||
options.find((option) => option.id === optionId)?.name
|
options.find((option) => option.id === optionId)?.name,
|
||||||
)
|
)
|
||||||
.join(", ")
|
.join(", ")
|
||||||
: value
|
: value
|
||||||
}
|
}
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
@ -106,15 +106,15 @@ const CustomInputPopoverObject = ({
|
||||||
onSelect={(currentValue) => {
|
onSelect={(currentValue) => {
|
||||||
setSelectedOption &&
|
setSelectedOption &&
|
||||||
setSelectedOption(
|
setSelectedOption(
|
||||||
currentValue === selectedOption ? "" : currentValue
|
currentValue === selectedOption ? "" : currentValue,
|
||||||
);
|
);
|
||||||
setSelectedOptions &&
|
setSelectedOptions &&
|
||||||
setSelectedOptions(
|
setSelectedOptions(
|
||||||
selectedOptions?.includes(currentValue)
|
selectedOptions?.includes(currentValue)
|
||||||
? selectedOptions.filter(
|
? selectedOptions.filter(
|
||||||
(item) => item !== currentValue
|
(item) => item !== currentValue,
|
||||||
)
|
)
|
||||||
: [...selectedOptions, currentValue]
|
: [...selectedOptions, currentValue],
|
||||||
);
|
);
|
||||||
!setSelectedOptions && setShowOptions(false);
|
!setSelectedOptions && setShowOptions(false);
|
||||||
}}
|
}}
|
||||||
|
|
@ -127,7 +127,7 @@ const CustomInputPopoverObject = ({
|
||||||
selectedOption === option.id ||
|
selectedOption === option.id ||
|
||||||
selectedOptions?.includes(option.id)
|
selectedOptions?.includes(option.id)
|
||||||
? "opacity-100"
|
? "opacity-100"
|
||||||
: "opacity-0"
|
: "opacity-0",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="absolute opacity-100 transition-all group-hover:opacity-0">
|
<div className="absolute opacity-100 transition-all group-hover:opacity-0">
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ export default function InputComponent({
|
||||||
editNode ? " input-edit-node " : "",
|
editNode ? " input-edit-node " : "",
|
||||||
password && editNode ? "pr-8" : "",
|
password && editNode ? "pr-8" : "",
|
||||||
password && !editNode ? "pr-10" : "",
|
password && !editNode ? "pr-10" : "",
|
||||||
className!
|
className!,
|
||||||
)}
|
)}
|
||||||
placeholder={password && editNode ? "Key" : placeholder}
|
placeholder={password && editNode ? "Key" : placeholder}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|
@ -147,7 +147,7 @@ export default function InputComponent({
|
||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
password && selectedOption === "" ? "right-8" : "right-0",
|
password && selectedOption === "" ? "right-8" : "right-0",
|
||||||
"absolute inset-y-0 flex items-center pr-2.5"
|
"absolute inset-y-0 flex items-center pr-2.5",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
|
@ -160,7 +160,7 @@ export default function InputComponent({
|
||||||
selectedOption !== ""
|
selectedOption !== ""
|
||||||
? "text-medium-indigo"
|
? "text-medium-indigo"
|
||||||
: "text-muted-foreground",
|
: "text-muted-foreground",
|
||||||
"hover:text-accent-foreground"
|
"hover:text-accent-foreground",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ForwardedIconComponent
|
<ForwardedIconComponent
|
||||||
|
|
@ -180,7 +180,7 @@ export default function InputComponent({
|
||||||
"mb-px",
|
"mb-px",
|
||||||
editNode
|
editNode
|
||||||
? "input-component-true-button"
|
? "input-component-true-button"
|
||||||
: "input-component-false-button"
|
: "input-component-false-button",
|
||||||
)}
|
)}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -197,7 +197,7 @@ export default function InputComponent({
|
||||||
className={classNames(
|
className={classNames(
|
||||||
editNode
|
editNode
|
||||||
? "input-component-true-svg"
|
? "input-component-true-svg"
|
||||||
: "input-component-false-svg"
|
: "input-component-false-svg",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
|
|
@ -216,7 +216,7 @@ export default function InputComponent({
|
||||||
className={classNames(
|
className={classNames(
|
||||||
editNode
|
editNode
|
||||||
? "input-component-true-svg"
|
? "input-component-true-svg"
|
||||||
: "input-component-false-svg"
|
: "input-component-false-svg",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { useEffect } from "react";
|
||||||
import { deleteGlobalVariable } from "../../controllers/API";
|
import { deleteGlobalVariable } from "../../controllers/API";
|
||||||
import DeleteConfirmationModal from "../../modals/deleteConfirmationModal";
|
import DeleteConfirmationModal from "../../modals/deleteConfirmationModal";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import { useGlobalVariablesStore } from "../../stores/globalVariables";
|
import { useGlobalVariablesStore } from "../../stores/globalVariablesStore/globalVariables";
|
||||||
import { InputGlobalComponentType } from "../../types/components";
|
import { InputGlobalComponentType } from "../../types/components";
|
||||||
import { cn } from "../../utils/utils";
|
import { cn } from "../../utils/utils";
|
||||||
import AddNewVariableButton from "../addNewVariableButtonComponent/addNewVariableButton";
|
import AddNewVariableButton from "../addNewVariableButtonComponent/addNewVariableButton";
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
||||||
e:
|
e:
|
||||||
| React.DragEvent<HTMLDivElement>
|
| React.DragEvent<HTMLDivElement>
|
||||||
| React.DragEvent<HTMLButtonElement>
|
| React.DragEvent<HTMLButtonElement>
|
||||||
| React.DragEvent<HTMLAnchorElement>
|
| React.DragEvent<HTMLAnchorElement>,
|
||||||
) => {
|
) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
||||||
e:
|
e:
|
||||||
| React.DragEvent<HTMLDivElement>
|
| React.DragEvent<HTMLDivElement>
|
||||||
| React.DragEvent<HTMLButtonElement>
|
| React.DragEvent<HTMLButtonElement>
|
||||||
| React.DragEvent<HTMLAnchorElement>
|
| React.DragEvent<HTMLAnchorElement>,
|
||||||
) => {
|
) => {
|
||||||
if (e.dataTransfer.types.some((types) => types === "Files")) {
|
if (e.dataTransfer.types.some((types) => types === "Files")) {
|
||||||
setFolderDragging(true);
|
setFolderDragging(true);
|
||||||
|
|
@ -66,7 +66,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
||||||
e:
|
e:
|
||||||
| React.DragEvent<HTMLDivElement>
|
| React.DragEvent<HTMLDivElement>
|
||||||
| React.DragEvent<HTMLButtonElement>
|
| React.DragEvent<HTMLButtonElement>
|
||||||
| React.DragEvent<HTMLAnchorElement>
|
| React.DragEvent<HTMLAnchorElement>,
|
||||||
) => {
|
) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (e.target === e.currentTarget) {
|
if (e.target === e.currentTarget) {
|
||||||
|
|
@ -79,7 +79,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
||||||
| React.DragEvent<HTMLDivElement>
|
| React.DragEvent<HTMLDivElement>
|
||||||
| React.DragEvent<HTMLButtonElement>
|
| React.DragEvent<HTMLButtonElement>
|
||||||
| React.DragEvent<HTMLAnchorElement>,
|
| React.DragEvent<HTMLAnchorElement>,
|
||||||
folderId: string
|
folderId: string,
|
||||||
) => {
|
) => {
|
||||||
if (e?.dataTransfer?.getData("flow")) {
|
if (e?.dataTransfer?.getData("flow")) {
|
||||||
const data = JSON.parse(e?.dataTransfer?.getData("flow"));
|
const data = JSON.parse(e?.dataTransfer?.getData("flow"));
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ const TableComponent = forwardRef<
|
||||||
alertDescription = DEFAULT_TABLE_ALERT_MSG,
|
alertDescription = DEFAULT_TABLE_ALERT_MSG,
|
||||||
...props
|
...props
|
||||||
},
|
},
|
||||||
ref
|
ref,
|
||||||
) => {
|
) => {
|
||||||
const dark = useDarkStore((state) => state.dark);
|
const dark = useDarkStore((state) => state.dark);
|
||||||
var currentRowHeight: number;
|
var currentRowHeight: number;
|
||||||
|
|
@ -67,14 +67,14 @@ const TableComponent = forwardRef<
|
||||||
(params: any) => {
|
(params: any) => {
|
||||||
updateRowHeight(params);
|
updateRowHeight(params);
|
||||||
},
|
},
|
||||||
[updateRowHeight]
|
[updateRowHeight],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onGridSizeChanged = useCallback(
|
const onGridSizeChanged = useCallback(
|
||||||
(params: any) => {
|
(params: any) => {
|
||||||
updateRowHeight(params);
|
updateRowHeight(params);
|
||||||
},
|
},
|
||||||
[updateRowHeight]
|
[updateRowHeight],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (props.rowData.length === 0) {
|
if (props.rowData.length === 0) {
|
||||||
|
|
@ -96,7 +96,7 @@ const TableComponent = forwardRef<
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
dark ? "ag-theme-quartz-dark" : "ag-theme-quartz",
|
dark ? "ag-theme-quartz-dark" : "ag-theme-quartz",
|
||||||
"ag-theme-shadcn flex h-full flex-col"
|
"ag-theme-shadcn flex h-full flex-col",
|
||||||
)} // applying the grid theme
|
)} // applying the grid theme
|
||||||
>
|
>
|
||||||
<AgGridReact
|
<AgGridReact
|
||||||
|
|
@ -113,7 +113,7 @@ const TableComponent = forwardRef<
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export default TableComponent;
|
export default TableComponent;
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ export async function sendAll(data: sendAllProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function postValidateCode(
|
export async function postValidateCode(
|
||||||
code: string
|
code: string,
|
||||||
): Promise<AxiosResponse<errorsTypeAPI>> {
|
): Promise<AxiosResponse<errorsTypeAPI>> {
|
||||||
return await api.post(`${BASE_URL_API}validate/code`, { code });
|
return await api.post(`${BASE_URL_API}validate/code`, { code });
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ export async function postValidateCode(
|
||||||
export async function postValidatePrompt(
|
export async function postValidatePrompt(
|
||||||
name: string,
|
name: string,
|
||||||
template: string,
|
template: string,
|
||||||
frontend_node: APIClassType
|
frontend_node: APIClassType,
|
||||||
): Promise<AxiosResponse<PromptTypeAPI>> {
|
): Promise<AxiosResponse<PromptTypeAPI>> {
|
||||||
return api.post(`${BASE_URL_API}validate/prompt`, {
|
return api.post(`${BASE_URL_API}validate/prompt`, {
|
||||||
name,
|
name,
|
||||||
|
|
@ -149,7 +149,7 @@ export async function saveFlowToDatabase(newFlow: {
|
||||||
* @throws Will throw an error if the update fails.
|
* @throws Will throw an error if the update fails.
|
||||||
*/
|
*/
|
||||||
export async function updateFlowInDatabase(
|
export async function updateFlowInDatabase(
|
||||||
updatedFlow: FlowType
|
updatedFlow: FlowType,
|
||||||
): Promise<FlowType> {
|
): Promise<FlowType> {
|
||||||
try {
|
try {
|
||||||
const response = await api.patch(`${BASE_URL_API}flows/${updatedFlow.id}`, {
|
const response = await api.patch(`${BASE_URL_API}flows/${updatedFlow.id}`, {
|
||||||
|
|
@ -326,7 +326,7 @@ export async function getHealth() {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export async function getBuildStatus(
|
export async function getBuildStatus(
|
||||||
flowId: string
|
flowId: string,
|
||||||
): Promise<AxiosResponse<BuildStatusTypeAPI>> {
|
): Promise<AxiosResponse<BuildStatusTypeAPI>> {
|
||||||
return await api.get(`${BASE_URL_API}build/${flowId}/status`);
|
return await api.get(`${BASE_URL_API}build/${flowId}/status`);
|
||||||
}
|
}
|
||||||
|
|
@ -339,7 +339,7 @@ export async function getBuildStatus(
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export async function postBuildInit(
|
export async function postBuildInit(
|
||||||
flow: FlowType
|
flow: FlowType,
|
||||||
): Promise<AxiosResponse<InitTypeAPI>> {
|
): Promise<AxiosResponse<InitTypeAPI>> {
|
||||||
return await api.post(`${BASE_URL_API}build/init/${flow.id}`, flow);
|
return await api.post(`${BASE_URL_API}build/init/${flow.id}`, flow);
|
||||||
}
|
}
|
||||||
|
|
@ -355,7 +355,7 @@ export async function postBuildInit(
|
||||||
*/
|
*/
|
||||||
export async function uploadFile(
|
export async function uploadFile(
|
||||||
file: File,
|
file: File,
|
||||||
id: string
|
id: string,
|
||||||
): Promise<AxiosResponse<UploadFileTypeAPI>> {
|
): Promise<AxiosResponse<UploadFileTypeAPI>> {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("file", file);
|
formData.append("file", file);
|
||||||
|
|
@ -364,7 +364,7 @@ export async function uploadFile(
|
||||||
|
|
||||||
export async function postCustomComponent(
|
export async function postCustomComponent(
|
||||||
code: string,
|
code: string,
|
||||||
apiClass: APIClassType
|
apiClass: APIClassType,
|
||||||
): Promise<AxiosResponse<APIClassType>> {
|
): Promise<AxiosResponse<APIClassType>> {
|
||||||
// let template = apiClass.template;
|
// let template = apiClass.template;
|
||||||
return await api.post(`${BASE_URL_API}custom_component`, {
|
return await api.post(`${BASE_URL_API}custom_component`, {
|
||||||
|
|
@ -377,7 +377,7 @@ export async function postCustomComponentUpdate(
|
||||||
code: string,
|
code: string,
|
||||||
template: APITemplateType,
|
template: APITemplateType,
|
||||||
field: string,
|
field: string,
|
||||||
field_value: any
|
field_value: any,
|
||||||
): Promise<AxiosResponse<APIClassType>> {
|
): Promise<AxiosResponse<APIClassType>> {
|
||||||
return await api.post(`${BASE_URL_API}custom_component/update`, {
|
return await api.post(`${BASE_URL_API}custom_component/update`, {
|
||||||
code,
|
code,
|
||||||
|
|
@ -399,7 +399,7 @@ export async function onLogin(user: LoginType) {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
|
|
@ -461,11 +461,11 @@ export async function addUser(user: UserInputType): Promise<Array<Users>> {
|
||||||
|
|
||||||
export async function getUsersPage(
|
export async function getUsersPage(
|
||||||
skip: number,
|
skip: number,
|
||||||
limit: number
|
limit: number,
|
||||||
): Promise<Array<Users>> {
|
): Promise<Array<Users>> {
|
||||||
try {
|
try {
|
||||||
const res = await api.get(
|
const res = await api.get(
|
||||||
`${BASE_URL_API}users/?skip=${skip}&limit=${limit}`
|
`${BASE_URL_API}users/?skip=${skip}&limit=${limit}`,
|
||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|
@ -502,7 +502,7 @@ export async function resetPassword(user_id: string, user: resetPasswordType) {
|
||||||
try {
|
try {
|
||||||
const res = await api.patch(
|
const res = await api.patch(
|
||||||
`${BASE_URL_API}users/${user_id}/reset-password`,
|
`${BASE_URL_API}users/${user_id}/reset-password`,
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|
@ -576,7 +576,7 @@ export async function saveFlowStore(
|
||||||
last_tested_version?: string;
|
last_tested_version?: string;
|
||||||
},
|
},
|
||||||
tags: string[],
|
tags: string[],
|
||||||
publicFlow = false
|
publicFlow = false,
|
||||||
): Promise<FlowType> {
|
): Promise<FlowType> {
|
||||||
try {
|
try {
|
||||||
const response = await api.post(`${BASE_URL_API}store/components/`, {
|
const response = await api.post(`${BASE_URL_API}store/components/`, {
|
||||||
|
|
@ -705,7 +705,7 @@ export async function postStoreComponents(component: Component) {
|
||||||
export async function getComponent(component_id: string) {
|
export async function getComponent(component_id: string) {
|
||||||
try {
|
try {
|
||||||
const res = await api.get(
|
const res = await api.get(
|
||||||
`${BASE_URL_API}store/components/${component_id}`
|
`${BASE_URL_API}store/components/${component_id}`,
|
||||||
);
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|
@ -720,7 +720,7 @@ export async function searchComponent(
|
||||||
page?: number | null,
|
page?: number | null,
|
||||||
limit?: number | null,
|
limit?: number | null,
|
||||||
status?: string | null,
|
status?: string | null,
|
||||||
tags?: string[]
|
tags?: string[],
|
||||||
): Promise<StoreComponentResponse | undefined> {
|
): Promise<StoreComponentResponse | undefined> {
|
||||||
try {
|
try {
|
||||||
let url = `${BASE_URL_API}store/components/`;
|
let url = `${BASE_URL_API}store/components/`;
|
||||||
|
|
@ -832,7 +832,7 @@ export async function updateFlowStore(
|
||||||
},
|
},
|
||||||
tags: string[],
|
tags: string[],
|
||||||
publicFlow = false,
|
publicFlow = false,
|
||||||
id: string
|
id: string,
|
||||||
): Promise<FlowType> {
|
): Promise<FlowType> {
|
||||||
try {
|
try {
|
||||||
const response = await api.patch(`${BASE_URL_API}store/components/${id}`, {
|
const response = await api.patch(`${BASE_URL_API}store/components/${id}`, {
|
||||||
|
|
@ -916,7 +916,7 @@ export async function deleteGlobalVariable(id: string) {
|
||||||
export async function updateGlobalVariable(
|
export async function updateGlobalVariable(
|
||||||
name: string,
|
name: string,
|
||||||
value: string,
|
value: string,
|
||||||
id: string
|
id: string,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const response = api.patch(`${BASE_URL_API}variables/${id}`, {
|
const response = api.patch(`${BASE_URL_API}variables/${id}`, {
|
||||||
|
|
@ -935,7 +935,7 @@ export async function getVerticesOrder(
|
||||||
startNodeId?: string | null,
|
startNodeId?: string | null,
|
||||||
stopNodeId?: string | null,
|
stopNodeId?: string | null,
|
||||||
nodes?: Node[],
|
nodes?: Node[],
|
||||||
Edges?: Edge[]
|
Edges?: Edge[],
|
||||||
): Promise<AxiosResponse<VerticesOrderTypeAPI>> {
|
): Promise<AxiosResponse<VerticesOrderTypeAPI>> {
|
||||||
// nodeId is optional and is a query parameter
|
// nodeId is optional and is a query parameter
|
||||||
// if nodeId is not provided, the API will return all vertices
|
// if nodeId is not provided, the API will return all vertices
|
||||||
|
|
@ -955,19 +955,19 @@ export async function getVerticesOrder(
|
||||||
return await api.post(
|
return await api.post(
|
||||||
`${BASE_URL_API}build/${flowId}/vertices`,
|
`${BASE_URL_API}build/${flowId}/vertices`,
|
||||||
data,
|
data,
|
||||||
config
|
config,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function postBuildVertex(
|
export async function postBuildVertex(
|
||||||
flowId: string,
|
flowId: string,
|
||||||
vertexId: string,
|
vertexId: string,
|
||||||
input_value: string
|
input_value: string,
|
||||||
): Promise<AxiosResponse<VertexBuildTypeAPI>> {
|
): Promise<AxiosResponse<VertexBuildTypeAPI>> {
|
||||||
// input_value is optional and is a query parameter
|
// input_value is optional and is a query parameter
|
||||||
return await api.post(
|
return await api.post(
|
||||||
`${BASE_URL_API}build/${flowId}/vertices/${vertexId}`,
|
`${BASE_URL_API}build/${flowId}/vertices/${vertexId}`,
|
||||||
input_value ? { inputs: { input_value: input_value } } : undefined
|
input_value ? { inputs: { input_value: input_value } } : undefined,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -991,7 +991,7 @@ export async function getFlowPool({
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteFlowPool(
|
export async function deleteFlowPool(
|
||||||
flowId: string
|
flowId: string,
|
||||||
): Promise<AxiosResponse<any>> {
|
): Promise<AxiosResponse<any>> {
|
||||||
const config = {};
|
const config = {};
|
||||||
config["params"] = { flow_id: flowId };
|
config["params"] = { flow_id: flowId };
|
||||||
|
|
@ -999,7 +999,7 @@ export async function deleteFlowPool(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function multipleDeleteFlowsComponents(
|
export async function multipleDeleteFlowsComponents(
|
||||||
flowIds: string[]
|
flowIds: string[],
|
||||||
): Promise<AxiosResponse<any>> {
|
): Promise<AxiosResponse<any>> {
|
||||||
return await api.post(`${BASE_URL_API}flows/multiple_delete/`, {
|
return await api.post(`${BASE_URL_API}flows/multiple_delete/`, {
|
||||||
flow_ids: flowIds,
|
flow_ids: flowIds,
|
||||||
|
|
@ -1009,7 +1009,7 @@ export async function multipleDeleteFlowsComponents(
|
||||||
export async function getTransactionTable(
|
export async function getTransactionTable(
|
||||||
id: string,
|
id: string,
|
||||||
mode: "intersection" | "union",
|
mode: "intersection" | "union",
|
||||||
params = {}
|
params = {},
|
||||||
): Promise<{ rows: Array<object>; columns: Array<ColDef | ColGroupDef> }> {
|
): Promise<{ rows: Array<object>; columns: Array<ColDef | ColGroupDef> }> {
|
||||||
const config = {};
|
const config = {};
|
||||||
config["params"] = { flow_id: id };
|
config["params"] = { flow_id: id };
|
||||||
|
|
@ -1024,7 +1024,7 @@ export async function getTransactionTable(
|
||||||
export async function getMessagesTable(
|
export async function getMessagesTable(
|
||||||
id: string,
|
id: string,
|
||||||
mode: "intersection" | "union",
|
mode: "intersection" | "union",
|
||||||
params = {}
|
params = {},
|
||||||
): Promise<{ rows: Array<object>; columns: Array<ColDef | ColGroupDef> }> {
|
): Promise<{ rows: Array<object>; columns: Array<ColDef | ColGroupDef> }> {
|
||||||
const config = {};
|
const config = {};
|
||||||
config["params"] = { flow_id: id };
|
config["params"] = { flow_id: id };
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ export default function ParameterComponent({
|
||||||
setNode,
|
setNode,
|
||||||
renderTooltips,
|
renderTooltips,
|
||||||
isLoading,
|
isLoading,
|
||||||
setIsLoading
|
setIsLoading,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
|
const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
|
||||||
|
|
@ -98,7 +98,7 @@ export default function ParameterComponent({
|
||||||
takeSnapshot,
|
takeSnapshot,
|
||||||
setNode,
|
setNode,
|
||||||
updateNodeInternals,
|
updateNodeInternals,
|
||||||
renderTooltips
|
renderTooltips,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
|
const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
|
||||||
|
|
@ -107,7 +107,7 @@ export default function ParameterComponent({
|
||||||
let disabled =
|
let disabled =
|
||||||
edges.some(
|
edges.some(
|
||||||
(edge) =>
|
(edge) =>
|
||||||
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id)
|
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
|
||||||
) ?? false;
|
) ?? false;
|
||||||
|
|
||||||
const handleRefreshButtonPress = async (name, data) => {
|
const handleRefreshButtonPress = async (name, data) => {
|
||||||
|
|
@ -120,12 +120,12 @@ export default function ParameterComponent({
|
||||||
handleUpdateValues,
|
handleUpdateValues,
|
||||||
setNode,
|
setNode,
|
||||||
renderTooltips,
|
renderTooltips,
|
||||||
setIsLoading
|
setIsLoading,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleOnNewValue = async (
|
const handleOnNewValue = async (
|
||||||
newValue: string | string[] | boolean | Object[],
|
newValue: string | string[] | boolean | Object[],
|
||||||
skipSnapshot: boolean | undefined = false
|
skipSnapshot: boolean | undefined = false,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
handleOnNewValueHook(newValue, skipSnapshot);
|
handleOnNewValueHook(newValue, skipSnapshot);
|
||||||
};
|
};
|
||||||
|
|
@ -209,7 +209,7 @@ export default function ParameterComponent({
|
||||||
className={classNames(
|
className={classNames(
|
||||||
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
|
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
|
||||||
"h-3 w-3 rounded-full border-2 bg-background",
|
"h-3 w-3 rounded-full border-2 bg-background",
|
||||||
!showNode ? "mt-0" : ""
|
!showNode ? "mt-0" : "",
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
borderColor: color ?? nodeColors.unknown,
|
borderColor: color ?? nodeColors.unknown,
|
||||||
|
|
@ -298,7 +298,7 @@ export default function ParameterComponent({
|
||||||
}
|
}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
left ? "-ml-0.5" : "-mr-0.5",
|
left ? "-ml-0.5" : "-mr-0.5",
|
||||||
"h-3 w-3 rounded-full border-2 bg-background"
|
"h-3 w-3 rounded-full border-2 bg-background",
|
||||||
)}
|
)}
|
||||||
style={{ borderColor: color ?? nodeColors.unknown }}
|
style={{ borderColor: color ?? nodeColors.unknown }}
|
||||||
onClick={() => setFilterEdge(groupedEdge.current)}
|
onClick={() => setFilterEdge(groupedEdge.current)}
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,10 @@ import { validationStatusType } from "../../types/components";
|
||||||
import { NodeDataType } from "../../types/flow";
|
import { NodeDataType } from "../../types/flow";
|
||||||
import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils";
|
import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils";
|
||||||
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
|
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
|
||||||
import { classNames, cn, getFieldTitle, sortFields } from "../../utils/utils";
|
import { classNames, cn } from "../../utils/utils";
|
||||||
import ParameterComponent from "./components/parameterComponent";
|
import ParameterComponent from "./components/parameterComponent";
|
||||||
|
import getFieldTitle from "../utils/get-field-title";
|
||||||
|
import sortFields from "../utils/sort-fields";
|
||||||
|
|
||||||
export default function GenericNode({
|
export default function GenericNode({
|
||||||
data,
|
data,
|
||||||
|
|
|
||||||
10
src/frontend/src/customNodes/utils/get-field-title.tsx
Normal file
10
src/frontend/src/customNodes/utils/get-field-title.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { APITemplateType } from "../../types/api";
|
||||||
|
|
||||||
|
export default function getFieldTitle(
|
||||||
|
template: APITemplateType,
|
||||||
|
templateField: string,
|
||||||
|
): string {
|
||||||
|
return template[templateField].display_name
|
||||||
|
? template[templateField].display_name!
|
||||||
|
: template[templateField].name ?? templateField;
|
||||||
|
}
|
||||||
40
src/frontend/src/customNodes/utils/sort-fields.tsx
Normal file
40
src/frontend/src/customNodes/utils/sort-fields.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { priorityFields } from "../../constants/constants";
|
||||||
|
|
||||||
|
export default function sortFields(a, b, fieldOrder) {
|
||||||
|
// Early return for empty fields
|
||||||
|
if (!a && !b) return 0;
|
||||||
|
if (!a) return 1;
|
||||||
|
if (!b) return -1;
|
||||||
|
|
||||||
|
// Normalize the case to ensure case-insensitive comparison
|
||||||
|
const normalizedFieldA = a.toLowerCase();
|
||||||
|
const normalizedFieldB = b.toLowerCase();
|
||||||
|
|
||||||
|
const aIsPriority = priorityFields.has(normalizedFieldA);
|
||||||
|
const bIsPriority = priorityFields.has(normalizedFieldB);
|
||||||
|
|
||||||
|
// Sort by priority
|
||||||
|
if (aIsPriority && !bIsPriority) return -1;
|
||||||
|
if (!aIsPriority && bIsPriority) return 1;
|
||||||
|
|
||||||
|
// Check if either field is in the fieldOrder array
|
||||||
|
const indexOfA = fieldOrder.indexOf(normalizedFieldA);
|
||||||
|
const indexOfB = fieldOrder.indexOf(normalizedFieldB);
|
||||||
|
|
||||||
|
// If both fields are in fieldOrder, sort by their order in the array
|
||||||
|
if (indexOfA !== -1 && indexOfB !== -1) {
|
||||||
|
return indexOfA - indexOfB;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If only one of the fields is in fieldOrder, that field comes first
|
||||||
|
if (indexOfA !== -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (indexOfB !== -1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default case for fields not in priorityFields and not found in fieldOrder
|
||||||
|
// You might want to sort them alphabetically or in another specific manner
|
||||||
|
return a.localeCompare(b);
|
||||||
|
}
|
||||||
|
|
@ -34,25 +34,25 @@ export default function IOModal({
|
||||||
}: IOModalPropsType): JSX.Element {
|
}: IOModalPropsType): JSX.Element {
|
||||||
const allNodes = useFlowStore((state) => state.nodes);
|
const allNodes = useFlowStore((state) => state.nodes);
|
||||||
const inputs = useFlowStore((state) => state.inputs).filter(
|
const inputs = useFlowStore((state) => state.inputs).filter(
|
||||||
(input) => input.type !== "ChatInput"
|
(input) => input.type !== "ChatInput",
|
||||||
);
|
);
|
||||||
const chatInput = useFlowStore((state) => state.inputs).find(
|
const chatInput = useFlowStore((state) => state.inputs).find(
|
||||||
(input) => input.type === "ChatInput"
|
(input) => input.type === "ChatInput",
|
||||||
);
|
);
|
||||||
const outputs = useFlowStore((state) => state.outputs).filter(
|
const outputs = useFlowStore((state) => state.outputs).filter(
|
||||||
(output) => output.type !== "ChatOutput"
|
(output) => output.type !== "ChatOutput",
|
||||||
);
|
);
|
||||||
const chatOutput = useFlowStore((state) => state.outputs).find(
|
const chatOutput = useFlowStore((state) => state.outputs).find(
|
||||||
(output) => output.type === "ChatOutput"
|
(output) => output.type === "ChatOutput",
|
||||||
);
|
);
|
||||||
const nodes = useFlowStore((state) => state.nodes).filter(
|
const nodes = useFlowStore((state) => state.nodes).filter(
|
||||||
(node) =>
|
(node) =>
|
||||||
inputs.some((input) => input.id === node.id) ||
|
inputs.some((input) => input.id === node.id) ||
|
||||||
outputs.some((output) => output.id === node.id)
|
outputs.some((output) => output.id === node.id),
|
||||||
);
|
);
|
||||||
const haveChat = chatInput || chatOutput;
|
const haveChat = chatInput || chatOutput;
|
||||||
const [selectedTab, setSelectedTab] = useState(
|
const [selectedTab, setSelectedTab] = useState(
|
||||||
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0
|
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
function startView() {
|
function startView() {
|
||||||
|
|
@ -140,7 +140,7 @@ export default function IOModal({
|
||||||
{selectedTab !== 0 && (
|
{selectedTab !== 0 && (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start transition-all duration-300"
|
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start transition-all duration-300",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|
@ -173,11 +173,11 @@ export default function IOModal({
|
||||||
</div>
|
</div>
|
||||||
{nodes
|
{nodes
|
||||||
.filter((node) =>
|
.filter((node) =>
|
||||||
inputs.some((input) => input.id === node.id)
|
inputs.some((input) => input.id === node.id),
|
||||||
)
|
)
|
||||||
.map((node, index) => {
|
.map((node, index) => {
|
||||||
const input = inputs.find(
|
const input = inputs.find(
|
||||||
(input) => input.id === node.id
|
(input) => input.id === node.id,
|
||||||
)!;
|
)!;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
@ -241,11 +241,11 @@ export default function IOModal({
|
||||||
</div>
|
</div>
|
||||||
{nodes
|
{nodes
|
||||||
.filter((node) =>
|
.filter((node) =>
|
||||||
outputs.some((output) => output.id === node.id)
|
outputs.some((output) => output.id === node.id),
|
||||||
)
|
)
|
||||||
.map((node, index) => {
|
.map((node, index) => {
|
||||||
const output = outputs.find(
|
const output = outputs.find(
|
||||||
(output) => output.id === node.id
|
(output) => output.id === node.id,
|
||||||
)!;
|
)!;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
@ -308,7 +308,7 @@ export default function IOModal({
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full w-full flex-col items-start gap-4 pt-4",
|
"flex h-full w-full flex-col items-start gap-4 pt-4",
|
||||||
!selectedViewField ? "hidden" : ""
|
!selectedViewField ? "hidden" : "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="font-xl flex items-center justify-center gap-3 font-semibold">
|
<div className="font-xl flex items-center justify-center gap-3 font-semibold">
|
||||||
|
|
@ -327,7 +327,7 @@ export default function IOModal({
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full w-full">
|
<div className="h-full w-full">
|
||||||
{inputs.some(
|
{inputs.some(
|
||||||
(input) => input.id === selectedViewField.id
|
(input) => input.id === selectedViewField.id,
|
||||||
) ? (
|
) ? (
|
||||||
<IOFieldView
|
<IOFieldView
|
||||||
type={InputOutput.INPUT}
|
type={InputOutput.INPUT}
|
||||||
|
|
@ -349,7 +349,7 @@ export default function IOModal({
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full w-full",
|
"flex h-full w-full",
|
||||||
selectedViewField ? "hidden" : ""
|
selectedViewField ? "hidden" : "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{haveChat ? (
|
{haveChat ? (
|
||||||
|
|
@ -384,7 +384,7 @@ export default function IOModal({
|
||||||
"h-4 w-4",
|
"h-4 w-4",
|
||||||
isBuilding
|
isBuilding
|
||||||
? "animate-spin"
|
? "animate-spin"
|
||||||
: "fill-current text-medium-indigo"
|
: "fill-current text-medium-indigo",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
Run Flow
|
Run Flow
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ export const checkCanBuildTweakObject = (element, templateField) => {
|
||||||
templateField.charAt(0) !== "_" &&
|
templateField.charAt(0) !== "_" &&
|
||||||
element.data.node.template[templateField].show &&
|
element.data.node.template[templateField].show &&
|
||||||
LANGFLOW_SUPPORTED_TYPES.has(
|
LANGFLOW_SUPPORTED_TYPES.has(
|
||||||
element.data.node.template[templateField].type
|
element.data.node.template[templateField].type,
|
||||||
) &&
|
) &&
|
||||||
templateField !== "code"
|
templateField !== "code"
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { convertArrayToObj } from "../../../utils/reactflowUtils";
|
||||||
|
|
||||||
export const getChangesType = (
|
export const getChangesType = (
|
||||||
changes: string | string[] | boolean | number | Object[] | Object,
|
changes: string | string[] | boolean | number | Object[] | Object,
|
||||||
template: TemplateVariableType
|
template: TemplateVariableType,
|
||||||
) => {
|
) => {
|
||||||
if (typeof changes === "string" && template.type === "float") {
|
if (typeof changes === "string" && template.type === "float") {
|
||||||
changes = parseFloat(changes);
|
changes = parseFloat(changes);
|
||||||
|
|
|
||||||
26
src/frontend/src/modals/apiModal/utils/get-curl-code.tsx
Normal file
26
src/frontend/src/modals/apiModal/utils/get-curl-code.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
* Function to get the curl code for the API
|
||||||
|
* @param {string} flowId - The id of the flow
|
||||||
|
* @param {boolean} isAuth - If the API is authenticated
|
||||||
|
* @returns {string} - The curl code
|
||||||
|
*/
|
||||||
|
export default function getCurlCode(
|
||||||
|
flowId: string,
|
||||||
|
isAuth: boolean,
|
||||||
|
tweaksBuildedObject,
|
||||||
|
): string {
|
||||||
|
const tweaksObject = tweaksBuildedObject[0];
|
||||||
|
|
||||||
|
return `curl -X POST \\
|
||||||
|
${window.location.protocol}//${
|
||||||
|
window.location.host
|
||||||
|
}/api/v1/run/${flowId}?stream=false \\
|
||||||
|
-H 'Content-Type: application/json'\\${
|
||||||
|
!isAuth ? `\n -H 'x-api-key: <your api key>'\\` : ""
|
||||||
|
}
|
||||||
|
-d '{"input_value": "message",
|
||||||
|
"output_type": "chat",
|
||||||
|
"input_type": "chat",
|
||||||
|
"tweaks": ${JSON.stringify(tweaksObject, null, 2)}'
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
@ -13,8 +13,8 @@ export const getNodesWithDefaultValue = (flow) => {
|
||||||
templateField.charAt(0) !== "_" &&
|
templateField.charAt(0) !== "_" &&
|
||||||
node.data.node.template[templateField].show &&
|
node.data.node.template[templateField].show &&
|
||||||
LANGFLOW_SUPPORTED_TYPES.has(
|
LANGFLOW_SUPPORTED_TYPES.has(
|
||||||
node.data.node.template[templateField].type
|
node.data.node.template[templateField].type,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
.map((n, i) => {
|
.map((n, i) => {
|
||||||
arrNodesWithValues.push(node["id"]);
|
arrNodesWithValues.push(node["id"]);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
* Function to get the python code for the API
|
||||||
|
* @param {string} flowId - The id of the flow
|
||||||
|
* @param {boolean} isAuth - If the API is authenticated
|
||||||
|
* @param {any[]} tweak - The tweaks
|
||||||
|
* @returns {string} - The python code
|
||||||
|
*/
|
||||||
|
export default function getPythonApiCode(
|
||||||
|
flowId: string,
|
||||||
|
isAuth: boolean,
|
||||||
|
tweaksBuildedObject,
|
||||||
|
): string {
|
||||||
|
const tweaksObject = tweaksBuildedObject[0];
|
||||||
|
return `import requests
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
BASE_API_URL = "${window.location.protocol}//${window.location.host}/api/v1/run"
|
||||||
|
FLOW_ID = "${flowId}"
|
||||||
|
# You can tweak the flow by adding a tweaks dictionary
|
||||||
|
# e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}}
|
||||||
|
TWEAKS = ${JSON.stringify(tweaksObject, null, 2)}
|
||||||
|
|
||||||
|
def run_flow(message: str,
|
||||||
|
flow_id: str,
|
||||||
|
output_type: str = "chat",
|
||||||
|
input_type: str = "chat",
|
||||||
|
tweaks: Optional[dict] = None,
|
||||||
|
api_key: Optional[str] = None) -> dict:
|
||||||
|
"""
|
||||||
|
Run a flow with a given message and optional tweaks.
|
||||||
|
|
||||||
|
:param message: The message to send to the flow
|
||||||
|
:param flow_id: The ID of the flow to run
|
||||||
|
:param tweaks: Optional tweaks to customize the flow
|
||||||
|
:return: The JSON response from the flow
|
||||||
|
"""
|
||||||
|
api_url = f"{BASE_API_URL}/{flow_id}"
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"input_value": message,
|
||||||
|
"output_type": output_type,
|
||||||
|
"input_type": input_type,
|
||||||
|
}
|
||||||
|
headers = None
|
||||||
|
if tweaks:
|
||||||
|
payload["tweaks"] = tweaks
|
||||||
|
if api_key:
|
||||||
|
headers = {"x-api-key": api_key}
|
||||||
|
response = requests.post(api_url, json=payload, headers=headers)
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
# Setup any tweaks you want to apply to the flow
|
||||||
|
message = "message"
|
||||||
|
${!isAuth ? `api_key = "<your api key>"` : ""}
|
||||||
|
print(run_flow(message=message, flow_id=FLOW_ID, tweaks=TWEAKS${
|
||||||
|
!isAuth ? `, api_key=api_key` : ""
|
||||||
|
}))`;
|
||||||
|
}
|
||||||
17
src/frontend/src/modals/apiModal/utils/get-python-code.tsx
Normal file
17
src/frontend/src/modals/apiModal/utils/get-python-code.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* Function to get the python code for the API
|
||||||
|
* @param {string} flow - The current flow
|
||||||
|
* @param {any[]} tweak - The tweaks
|
||||||
|
* @returns {string} - The python code
|
||||||
|
*/
|
||||||
|
export default function getPythonCode(flowName: string, tweaksBuildedObject): string {
|
||||||
|
const tweaksObject = tweaksBuildedObject[0];
|
||||||
|
|
||||||
|
return `from langflow.load import run_flow_from_json
|
||||||
|
TWEAKS = ${JSON.stringify(tweaksObject, null, 2)}
|
||||||
|
|
||||||
|
result = run_flow_from_json(flow="${flowName}.json",
|
||||||
|
input_value="message",
|
||||||
|
fallback_to_env_vars=True, # False by default
|
||||||
|
tweaks=TWEAKS)`;
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ export const getValue = (
|
||||||
value: string,
|
value: string,
|
||||||
node: NodeType,
|
node: NodeType,
|
||||||
template: TemplateVariableType,
|
template: TemplateVariableType,
|
||||||
tweak: Object[]
|
tweak: Object[],
|
||||||
) => {
|
) => {
|
||||||
let returnValue = value ?? "";
|
let returnValue = value ?? "";
|
||||||
|
|
||||||
|
|
|
||||||
24
src/frontend/src/modals/apiModal/utils/get-widget-code.tsx
Normal file
24
src/frontend/src/modals/apiModal/utils/get-widget-code.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* Function to get the widget code for the API
|
||||||
|
* @param {string} flow - The current flow.
|
||||||
|
* @returns {string} - The widget code
|
||||||
|
*/
|
||||||
|
export default function getWidgetCode(
|
||||||
|
flowId: string,
|
||||||
|
flowName: string,
|
||||||
|
isAuth: boolean,
|
||||||
|
): string {
|
||||||
|
return `<script src="https://cdn.jsdelivr.net/gh/langflow-ai/langflow-embedded-chat@1.0_alpha/dist/build/static/js/bundle.min.js"></script>
|
||||||
|
|
||||||
|
<langflow-chat
|
||||||
|
window_title="${flowName}"
|
||||||
|
flow_id="${flowId}"
|
||||||
|
host_url="http://localhost:7860"${
|
||||||
|
!isAuth
|
||||||
|
? `
|
||||||
|
api_key="..."`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
></langflow-chat>`;
|
||||||
|
}
|
||||||
78
src/frontend/src/modals/apiModal/utils/tabs-array.tsx
Normal file
78
src/frontend/src/modals/apiModal/utils/tabs-array.tsx
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
export default function tabsArray(codes: string[], method: number) {
|
||||||
|
if (!method) return;
|
||||||
|
if (method === 0) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: "cURL",
|
||||||
|
mode: "bash",
|
||||||
|
image: "https://curl.se/logo/curl-symbol-transparent.png",
|
||||||
|
language: "sh",
|
||||||
|
code: codes[0],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python API",
|
||||||
|
mode: "python",
|
||||||
|
image:
|
||||||
|
"https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w",
|
||||||
|
language: "py",
|
||||||
|
code: codes[1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python Code",
|
||||||
|
mode: "python",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
language: "py",
|
||||||
|
code: codes[2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Chat Widget HTML",
|
||||||
|
description:
|
||||||
|
"Insert this code anywhere in your <body> tag. To use with react and other libs, check our <a class='link-color' href='https://langflow.org/guidelines/widget'>documentation</a>.",
|
||||||
|
mode: "html",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
language: "py",
|
||||||
|
code: codes[3],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: "cURL",
|
||||||
|
mode: "bash",
|
||||||
|
image: "https://curl.se/logo/curl-symbol-transparent.png",
|
||||||
|
language: "sh",
|
||||||
|
code: codes[0],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python API",
|
||||||
|
mode: "python",
|
||||||
|
image:
|
||||||
|
"https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w",
|
||||||
|
language: "py",
|
||||||
|
code: codes[1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Python Code",
|
||||||
|
mode: "python",
|
||||||
|
language: "py",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
code: codes[2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Chat Widget HTML",
|
||||||
|
description:
|
||||||
|
"Insert this code anywhere in your <body> tag. To use with react and other libs, check our <a class='link-color' href='https://langflow.org/guidelines/widget'>documentation</a>.",
|
||||||
|
mode: "html",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
language: "py",
|
||||||
|
code: codes[3],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Tweaks",
|
||||||
|
mode: "python",
|
||||||
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
|
language: "py",
|
||||||
|
code: codes[4],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -13,13 +13,6 @@ import { useTweaksStore } from "../../../stores/tweaksStore";
|
||||||
import { TemplateVariableType } from "../../../types/api";
|
import { TemplateVariableType } from "../../../types/api";
|
||||||
import { uniqueTweakType } from "../../../types/components";
|
import { uniqueTweakType } from "../../../types/components";
|
||||||
import { FlowType } from "../../../types/flow/index";
|
import { FlowType } from "../../../types/flow/index";
|
||||||
import {
|
|
||||||
getCurlCode,
|
|
||||||
getPythonApiCode,
|
|
||||||
getPythonCode,
|
|
||||||
getWidgetCode,
|
|
||||||
tabsArray,
|
|
||||||
} from "../../../utils/utils";
|
|
||||||
import BaseModal from "../../baseModal";
|
import BaseModal from "../../baseModal";
|
||||||
import { buildContent } from "../utils/build-content";
|
import { buildContent } from "../utils/build-content";
|
||||||
import { buildTweaks } from "../utils/build-tweaks";
|
import { buildTweaks } from "../utils/build-tweaks";
|
||||||
|
|
@ -27,6 +20,11 @@ import { checkCanBuildTweakObject } from "../utils/check-can-build-tweak-object"
|
||||||
import { getChangesType } from "../utils/get-changes-types";
|
import { getChangesType } from "../utils/get-changes-types";
|
||||||
import { getNodesWithDefaultValue } from "../utils/get-nodes-with-default-value";
|
import { getNodesWithDefaultValue } from "../utils/get-nodes-with-default-value";
|
||||||
import { getValue } from "../utils/get-value";
|
import { getValue } from "../utils/get-value";
|
||||||
|
import getPythonApiCode from "../utils/get-python-api-code";
|
||||||
|
import getCurlCode from "../utils/get-curl-code";
|
||||||
|
import getPythonCode from "../utils/get-python-code";
|
||||||
|
import getWidgetCode from "../utils/get-widget-code";
|
||||||
|
import tabsArray from "../utils/tabs-array";
|
||||||
|
|
||||||
const ApiModal = forwardRef(
|
const ApiModal = forwardRef(
|
||||||
(
|
(
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ interface BaseModalProps {
|
||||||
React.ReactElement<ContentProps>,
|
React.ReactElement<ContentProps>,
|
||||||
React.ReactElement<HeaderProps>,
|
React.ReactElement<HeaderProps>,
|
||||||
React.ReactElement<TriggerProps>?,
|
React.ReactElement<TriggerProps>?,
|
||||||
React.ReactElement<FooterProps>?
|
React.ReactElement<FooterProps>?,
|
||||||
];
|
];
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
setOpen?: (open: boolean) => void;
|
setOpen?: (open: boolean) => void;
|
||||||
|
|
@ -101,16 +101,16 @@ function BaseModal({
|
||||||
type = "dialog",
|
type = "dialog",
|
||||||
}: BaseModalProps) {
|
}: BaseModalProps) {
|
||||||
const headerChild = React.Children.toArray(children).find(
|
const headerChild = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Header
|
(child) => (child as React.ReactElement).type === Header,
|
||||||
);
|
);
|
||||||
const triggerChild = React.Children.toArray(children).find(
|
const triggerChild = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Trigger
|
(child) => (child as React.ReactElement).type === Trigger,
|
||||||
);
|
);
|
||||||
const ContentChild = React.Children.toArray(children).find(
|
const ContentChild = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Content
|
(child) => (child as React.ReactElement).type === Content,
|
||||||
);
|
);
|
||||||
const ContentFooter = React.Children.toArray(children).find(
|
const ContentFooter = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Footer
|
(child) => (child as React.ReactElement).type === Footer,
|
||||||
);
|
);
|
||||||
|
|
||||||
let minWidth: string;
|
let minWidth: string;
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,9 @@ import { postValidatePrompt } from "../../controllers/API";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import { genericModalPropsType } from "../../types/components";
|
import { genericModalPropsType } from "../../types/components";
|
||||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||||
import { classNames, varHighlightHTML } from "../../utils/utils";
|
import { classNames } from "../../utils/utils";
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
|
import varHighlightHTML from "./utils/var-highlight-html";
|
||||||
|
|
||||||
export default function GenericModal({
|
export default function GenericModal({
|
||||||
field_name = "",
|
field_name = "",
|
||||||
|
|
@ -82,7 +83,7 @@ export default function GenericModal({
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredWordsHighlight = matches.filter(
|
const filteredWordsHighlight = matches.filter(
|
||||||
(word) => !invalid_chars.includes(word)
|
(word) => !invalid_chars.includes(word),
|
||||||
);
|
);
|
||||||
|
|
||||||
setWordsHighlight(filteredWordsHighlight);
|
setWordsHighlight(filteredWordsHighlight);
|
||||||
|
|
@ -133,7 +134,7 @@ export default function GenericModal({
|
||||||
// to the first key of the custom_fields object
|
// to the first key of the custom_fields object
|
||||||
if (field_name === "") {
|
if (field_name === "") {
|
||||||
field_name = Array.isArray(
|
field_name = Array.isArray(
|
||||||
apiReturn.data?.frontend_node?.custom_fields?.[""]
|
apiReturn.data?.frontend_node?.custom_fields?.[""],
|
||||||
)
|
)
|
||||||
? apiReturn.data?.frontend_node?.custom_fields?.[""][0] ?? ""
|
? apiReturn.data?.frontend_node?.custom_fields?.[""][0] ?? ""
|
||||||
: apiReturn.data?.frontend_node?.custom_fields?.[""] ?? "";
|
: apiReturn.data?.frontend_node?.custom_fields?.[""] ?? "";
|
||||||
|
|
@ -209,7 +210,7 @@ export default function GenericModal({
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
!isEdit ? "rounded-lg border" : "",
|
!isEdit ? "rounded-lg border" : "",
|
||||||
"flex h-full w-full"
|
"flex h-full w-full",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{type === TypeModal.PROMPT && isEdit && !readonly ? (
|
{type === TypeModal.PROMPT && isEdit && !readonly ? (
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { IVarHighlightType } from "../../../types/components";
|
||||||
|
|
||||||
|
export default function varHighlightHTML({ name }: IVarHighlightType): string {
|
||||||
|
const html = `<span class="font-semibold chat-message-highlight">{${name}}</span>`;
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
@ -32,7 +32,7 @@ export default function NewFlowModal({
|
||||||
key={0}
|
key={0}
|
||||||
flow={
|
flow={
|
||||||
examples.find(
|
examples.find(
|
||||||
(e) => e.name == "Basic Prompting (Hello, World)"
|
(e) => e.name == "Basic Prompting (Hello, World)",
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ import {
|
||||||
removeFileNameFromComponents,
|
removeFileNameFromComponents,
|
||||||
removeGlobalVariableFromComponents,
|
removeGlobalVariableFromComponents,
|
||||||
} from "../../utils/reactflowUtils";
|
} from "../../utils/reactflowUtils";
|
||||||
import { getTagsIds } from "../../utils/storeUtils";
|
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
import ConfirmationModal from "../confirmationModal";
|
import ConfirmationModal from "../confirmationModal";
|
||||||
import ExportModal from "../exportModal";
|
import ExportModal from "../exportModal";
|
||||||
|
import getTagsIds from "./utils/get-tags-ids";
|
||||||
|
|
||||||
export default function ShareModal({
|
export default function ShareModal({
|
||||||
component,
|
component,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
export default function getTagsIds(
|
||||||
|
tags: string[],
|
||||||
|
tagListId: { name: string; id: string }[],
|
||||||
|
) {
|
||||||
|
return tags
|
||||||
|
.map((tag) => tagListId.find((tagObj) => tagObj.name === tag))!
|
||||||
|
.map((tag) => tag!.id);
|
||||||
|
}
|
||||||
|
|
@ -34,9 +34,10 @@ import {
|
||||||
updateIds,
|
updateIds,
|
||||||
validateSelection,
|
validateSelection,
|
||||||
} from "../../../../utils/reactflowUtils";
|
} from "../../../../utils/reactflowUtils";
|
||||||
import { getRandomName, isWrappedWithClass } from "../../../../utils/utils";
|
|
||||||
import ConnectionLineComponent from "../ConnectionLineComponent";
|
import ConnectionLineComponent from "../ConnectionLineComponent";
|
||||||
import SelectionMenu from "../SelectionMenuComponent";
|
import SelectionMenu from "../SelectionMenuComponent";
|
||||||
|
import isWrappedWithClass from "./utils/is-wrapped-with-class";
|
||||||
|
import getRandomName from "./utils/get-random-name";
|
||||||
|
|
||||||
const nodeTypes = {
|
const nodeTypes = {
|
||||||
genericNode: GenericNode,
|
genericNode: GenericNode,
|
||||||
|
|
@ -51,19 +52,19 @@ export default function Page({
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||||
const autoSaveCurrentFlow = useFlowsManagerStore(
|
const autoSaveCurrentFlow = useFlowsManagerStore(
|
||||||
(state) => state.autoSaveCurrentFlow
|
(state) => state.autoSaveCurrentFlow,
|
||||||
);
|
);
|
||||||
const types = useTypesStore((state) => state.types);
|
const types = useTypesStore((state) => state.types);
|
||||||
const templates = useTypesStore((state) => state.templates);
|
const templates = useTypesStore((state) => state.templates);
|
||||||
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
||||||
const reactFlowWrapper = useRef<HTMLDivElement>(null);
|
const reactFlowWrapper = useRef<HTMLDivElement>(null);
|
||||||
const [showCanvas, setSHowCanvas] = useState(
|
const [showCanvas, setSHowCanvas] = useState(
|
||||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0
|
Object.keys(templates).length > 0 && Object.keys(types).length > 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance);
|
const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance);
|
||||||
const setReactFlowInstance = useFlowStore(
|
const setReactFlowInstance = useFlowStore(
|
||||||
(state) => state.setReactFlowInstance
|
(state) => state.setReactFlowInstance,
|
||||||
);
|
);
|
||||||
const nodes = useFlowStore((state) => state.nodes);
|
const nodes = useFlowStore((state) => state.nodes);
|
||||||
const edges = useFlowStore((state) => state.edges);
|
const edges = useFlowStore((state) => state.edges);
|
||||||
|
|
@ -80,10 +81,10 @@ export default function Page({
|
||||||
const paste = useFlowStore((state) => state.paste);
|
const paste = useFlowStore((state) => state.paste);
|
||||||
const resetFlow = useFlowStore((state) => state.resetFlow);
|
const resetFlow = useFlowStore((state) => state.resetFlow);
|
||||||
const lastCopiedSelection = useFlowStore(
|
const lastCopiedSelection = useFlowStore(
|
||||||
(state) => state.lastCopiedSelection
|
(state) => state.lastCopiedSelection,
|
||||||
);
|
);
|
||||||
const setLastCopiedSelection = useFlowStore(
|
const setLastCopiedSelection = useFlowStore(
|
||||||
(state) => state.setLastCopiedSelection
|
(state) => state.setLastCopiedSelection,
|
||||||
);
|
);
|
||||||
const onConnect = useFlowStore((state) => state.onConnect);
|
const onConnect = useFlowStore((state) => state.onConnect);
|
||||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||||
|
|
@ -106,7 +107,7 @@ export default function Page({
|
||||||
clonedSelection!,
|
clonedSelection!,
|
||||||
clonedNodes,
|
clonedNodes,
|
||||||
clonedEdges,
|
clonedEdges,
|
||||||
getRandomName()
|
getRandomName(),
|
||||||
);
|
);
|
||||||
const newGroupNode = generateNodeFromFlow(newFlow, getNodeId);
|
const newGroupNode = generateNodeFromFlow(newFlow, getNodeId);
|
||||||
const newEdges = reconnectEdges(newGroupNode, removedEdges);
|
const newEdges = reconnectEdges(newGroupNode, removedEdges);
|
||||||
|
|
@ -114,8 +115,8 @@ export default function Page({
|
||||||
...clonedNodes.filter(
|
...clonedNodes.filter(
|
||||||
(oldNodes) =>
|
(oldNodes) =>
|
||||||
!clonedSelection?.nodes.some(
|
!clonedSelection?.nodes.some(
|
||||||
(selectionNode) => selectionNode.id === oldNodes.id
|
(selectionNode) => selectionNode.id === oldNodes.id,
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
newGroupNode,
|
newGroupNode,
|
||||||
]);
|
]);
|
||||||
|
|
@ -125,8 +126,8 @@ export default function Page({
|
||||||
!clonedSelection!.nodes.some(
|
!clonedSelection!.nodes.some(
|
||||||
(selectionNode) =>
|
(selectionNode) =>
|
||||||
selectionNode.id === oldEdge.target ||
|
selectionNode.id === oldEdge.target ||
|
||||||
selectionNode.id === oldEdge.source
|
selectionNode.id === oldEdge.source,
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
...newEdges,
|
...newEdges,
|
||||||
]);
|
]);
|
||||||
|
|
@ -179,7 +180,7 @@ export default function Page({
|
||||||
{
|
{
|
||||||
x: position.current.x,
|
x: position.current.x,
|
||||||
y: position.current.y,
|
y: position.current.y,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!isWrappedWithClass(event, "noundo")) {
|
if (!isWrappedWithClass(event, "noundo")) {
|
||||||
|
|
@ -275,7 +276,7 @@ export default function Page({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSHowCanvas(
|
setSHowCanvas(
|
||||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0
|
Object.keys(templates).length > 0 && Object.keys(types).length > 0,
|
||||||
);
|
);
|
||||||
}, [templates, types]);
|
}, [templates, types]);
|
||||||
|
|
||||||
|
|
@ -284,7 +285,7 @@ export default function Page({
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
onConnect(params);
|
onConnect(params);
|
||||||
},
|
},
|
||||||
[takeSnapshot, onConnect]
|
[takeSnapshot, onConnect],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onNodeDragStart: NodeDragHandler = useCallback(() => {
|
const onNodeDragStart: NodeDragHandler = useCallback(() => {
|
||||||
|
|
@ -325,7 +326,7 @@ export default function Page({
|
||||||
|
|
||||||
// Extract the data from the drag event and parse it as a JSON object
|
// Extract the data from the drag event and parse it as a JSON object
|
||||||
const data: { type: string; node?: APIClassType } = JSON.parse(
|
const data: { type: string; node?: APIClassType } = JSON.parse(
|
||||||
event.dataTransfer.getData("nodedata")
|
event.dataTransfer.getData("nodedata"),
|
||||||
);
|
);
|
||||||
|
|
||||||
const newId = getNodeId(data.type);
|
const newId = getNodeId(data.type);
|
||||||
|
|
@ -341,7 +342,7 @@ export default function Page({
|
||||||
};
|
};
|
||||||
paste(
|
paste(
|
||||||
{ nodes: [newNode], edges: [] },
|
{ nodes: [newNode], edges: [] },
|
||||||
{ x: event.clientX, y: event.clientY }
|
{ x: event.clientX, y: event.clientY },
|
||||||
);
|
);
|
||||||
} else if (event.dataTransfer.types.some((types) => types === "Files")) {
|
} else if (event.dataTransfer.types.some((types) => types === "Files")) {
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
|
|
@ -370,7 +371,7 @@ export default function Page({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Specify dependencies for useCallback
|
// Specify dependencies for useCallback
|
||||||
[getNodeId, setNodes, takeSnapshot, paste]
|
[getNodeId, setNodes, takeSnapshot, paste],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onEdgeUpdateStart = useCallback(() => {
|
const onEdgeUpdateStart = useCallback(() => {
|
||||||
|
|
@ -386,7 +387,7 @@ export default function Page({
|
||||||
setEdges((els) => updateEdge(oldEdge, newConnection, els));
|
setEdges((els) => updateEdge(oldEdge, newConnection, els));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[setEdges]
|
[setEdges],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onEdgeUpdateEnd = useCallback((_, edge: Edge): void => {
|
const onEdgeUpdateEnd = useCallback((_, edge: Edge): void => {
|
||||||
|
|
@ -419,7 +420,7 @@ export default function Page({
|
||||||
(flow: OnSelectionChangeParams): void => {
|
(flow: OnSelectionChangeParams): void => {
|
||||||
setLastSelection(flow);
|
setLastSelection(flow);
|
||||||
},
|
},
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onPaneClick = useCallback((flow) => {
|
const onPaneClick = useCallback((flow) => {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { ADJECTIVES, NOUNS } from "../../../../../flow_constants";
|
||||||
|
import { getRandomElement } from "../../../../../utils/reactflowUtils";
|
||||||
|
import { toTitleCase } from "../../../../../utils/utils";
|
||||||
|
|
||||||
|
export default function getRandomName(
|
||||||
|
retry: number = 0,
|
||||||
|
noSpace: boolean = false,
|
||||||
|
maxRetries: number = 3,
|
||||||
|
): string {
|
||||||
|
const left: string[] = ADJECTIVES;
|
||||||
|
const right: string[] = NOUNS;
|
||||||
|
|
||||||
|
const lv = getRandomElement(left);
|
||||||
|
const rv = getRandomElement(right);
|
||||||
|
|
||||||
|
// Condition to avoid "boring wozniak"
|
||||||
|
if (lv === "boring" && rv === "wozniak") {
|
||||||
|
if (retry < maxRetries) {
|
||||||
|
return getRandomName(retry + 1, noSpace, maxRetries);
|
||||||
|
} else {
|
||||||
|
console.warn("Max retries reached, returning as is");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append a suffix if retrying and noSpace is true
|
||||||
|
if (retry > 0 && noSpace) {
|
||||||
|
const retrySuffix = Math.floor(Math.random() * 10);
|
||||||
|
return `${lv}_${rv}${retrySuffix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the final name
|
||||||
|
let final_name = noSpace ? `${lv}_${rv}` : `${lv} ${rv}`;
|
||||||
|
// Return title case final name
|
||||||
|
return toTitleCase(final_name);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
const isWrappedWithClass = (event: any, className: string | undefined) =>
|
||||||
|
event.target.closest(`.${className}`);
|
||||||
|
|
||||||
|
export default isWrappedWithClass;
|
||||||
|
|
@ -13,7 +13,7 @@ export default function SelectionMenu({
|
||||||
const [disable, setDisable] = useState<boolean>(
|
const [disable, setDisable] = useState<boolean>(
|
||||||
lastSelection && edges.length > 0
|
lastSelection && edges.length > 0
|
||||||
? validateSelection(lastSelection!, edges).length > 0
|
? validateSelection(lastSelection!, edges).length > 0
|
||||||
: false
|
: false,
|
||||||
);
|
);
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [isTransitioning, setIsTransitioning] = useState(false);
|
const [isTransitioning, setIsTransitioning] = useState(false);
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,12 @@ import {
|
||||||
import {
|
import {
|
||||||
classNames,
|
classNames,
|
||||||
removeCountFromString,
|
removeCountFromString,
|
||||||
sensitiveSort,
|
|
||||||
} from "../../../../utils/utils";
|
} from "../../../../utils/utils";
|
||||||
import DisclosureComponent from "../DisclosureComponent";
|
import DisclosureComponent from "../DisclosureComponent";
|
||||||
import ParentDisclosureComponent from "../ParentDisclosureComponent";
|
import ParentDisclosureComponent from "../ParentDisclosureComponent";
|
||||||
import SidebarDraggableComponent from "./sideBarDraggableComponent";
|
import SidebarDraggableComponent from "./sideBarDraggableComponent";
|
||||||
import { sortKeys } from "./utils";
|
import { sortKeys } from "./utils";
|
||||||
|
import sensitiveSort from "./utils/sensitive-sort";
|
||||||
|
|
||||||
export default function ExtraSidebar(): JSX.Element {
|
export default function ExtraSidebar(): JSX.Element {
|
||||||
const data = useTypesStore((state) => state.data);
|
const data = useTypesStore((state) => state.data);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
export default function sensitiveSort(a: string, b: string): number {
|
||||||
|
// Extract the name and number from each string using regular expressions
|
||||||
|
const regex = /(.+) \((\w+)\)/;
|
||||||
|
const matchA = a.match(regex);
|
||||||
|
const matchB = b.match(regex);
|
||||||
|
|
||||||
|
if (matchA && matchB) {
|
||||||
|
// Compare the names alphabetically
|
||||||
|
const nameA = matchA[1];
|
||||||
|
const nameB = matchB[1];
|
||||||
|
if (nameA !== nameB) {
|
||||||
|
return nameA.localeCompare(nameB);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the names are the same, compare the numbers numerically
|
||||||
|
const numberA = parseInt(matchA[2]);
|
||||||
|
const numberB = parseInt(matchB[2]);
|
||||||
|
return numberA - numberB;
|
||||||
|
} else {
|
||||||
|
// Handle cases where one or both strings do not match the expected pattern
|
||||||
|
// Simple strings are treated as pure alphabetical comparisons
|
||||||
|
return a.localeCompare(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ export default function NodeToolbarComponent({
|
||||||
data.node.template[templateField].type === "Any" ||
|
data.node.template[templateField].type === "Any" ||
|
||||||
data.node.template[templateField].type === "int" ||
|
data.node.template[templateField].type === "int" ||
|
||||||
data.node.template[templateField].type === "dict" ||
|
data.node.template[templateField].type === "dict" ||
|
||||||
data.node.template[templateField].type === "NestedDict")
|
data.node.template[templateField].type === "NestedDict"),
|
||||||
).length;
|
).length;
|
||||||
const templates = useTypesStore((state) => state.templates);
|
const templates = useTypesStore((state) => state.templates);
|
||||||
const hasStore = useStoreStore((state) => state.hasStore);
|
const hasStore = useStoreStore((state) => state.hasStore);
|
||||||
|
|
@ -85,7 +85,7 @@ export default function NodeToolbarComponent({
|
||||||
const [showconfirmShare, setShowconfirmShare] = useState(false);
|
const [showconfirmShare, setShowconfirmShare] = useState(false);
|
||||||
const [showOverrideModal, setShowOverrideModal] = useState(false);
|
const [showOverrideModal, setShowOverrideModal] = useState(false);
|
||||||
const [flowComponent, setFlowComponent] = useState<FlowType>(
|
const [flowComponent, setFlowComponent] = useState<FlowType>(
|
||||||
createFlowComponent(cloneDeep(data), version)
|
createFlowComponent(cloneDeep(data), version),
|
||||||
);
|
);
|
||||||
|
|
||||||
const openInNewTab = (url) => {
|
const openInNewTab = (url) => {
|
||||||
|
|
@ -100,7 +100,7 @@ export default function NodeToolbarComponent({
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
|
|
||||||
const setLastCopiedSelection = useFlowStore(
|
const setLastCopiedSelection = useFlowStore(
|
||||||
(state) => state.setLastCopiedSelection
|
(state) => state.setLastCopiedSelection,
|
||||||
);
|
);
|
||||||
|
|
||||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||||
|
|
@ -150,7 +150,7 @@ export default function NodeToolbarComponent({
|
||||||
nodes,
|
nodes,
|
||||||
edges,
|
edges,
|
||||||
setNodes,
|
setNodes,
|
||||||
setEdges
|
setEdges,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "override":
|
case "override":
|
||||||
|
|
@ -174,7 +174,7 @@ export default function NodeToolbarComponent({
|
||||||
y: 10,
|
y: 10,
|
||||||
paneX: nodes.find((node) => node.id === data.id)?.position.x,
|
paneX: nodes.find((node) => node.id === data.id)?.position.x,
|
||||||
paneY: nodes.find((node) => node.id === data.id)?.position.y,
|
paneY: nodes.find((node) => node.id === data.id)?.position.y,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "update":
|
case "update":
|
||||||
|
|
@ -212,13 +212,13 @@ export default function NodeToolbarComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
const isSaved = flows.some((flow) =>
|
const isSaved = flows.some((flow) =>
|
||||||
Object.values(flow).includes(data.node?.display_name!)
|
Object.values(flow).includes(data.node?.display_name!),
|
||||||
);
|
);
|
||||||
|
|
||||||
const setNode = useFlowStore((state) => state.setNode);
|
const setNode = useFlowStore((state) => state.setNode);
|
||||||
|
|
||||||
const handleOnNewValue = (
|
const handleOnNewValue = (
|
||||||
newValue: string | string[] | boolean | Object[]
|
newValue: string | string[] | boolean | Object[],
|
||||||
): void => {
|
): void => {
|
||||||
if (data.node!.template[name].value !== newValue) {
|
if (data.node!.template[name].value !== newValue) {
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
|
|
@ -393,7 +393,7 @@ export default function NodeToolbarComponent({
|
||||||
data-testid="save-button-modal"
|
data-testid="save-button-modal"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10",
|
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10",
|
||||||
hasCode ? " " : " rounded-l-md "
|
hasCode ? " " : " rounded-l-md ",
|
||||||
)}
|
)}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -411,7 +411,7 @@ export default function NodeToolbarComponent({
|
||||||
<button
|
<button
|
||||||
data-testid="duplicate-button-modal"
|
data-testid="duplicate-button-modal"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
|
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10",
|
||||||
)}
|
)}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -459,7 +459,7 @@ export default function NodeToolbarComponent({
|
||||||
<div
|
<div
|
||||||
data-testid="more-options-modal"
|
data-testid="more-options-modal"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"relative -ml-px inline-flex h-8 w-[31px] items-center rounded-r-md bg-background text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
|
"relative -ml-px inline-flex h-8 w-[31px] items-center rounded-r-md bg-background text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import useDropdownOptions from "../../hooks/use-dropdown-options";
|
||||||
export default function HomePage(): JSX.Element {
|
export default function HomePage(): JSX.Element {
|
||||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||||
const setCurrentFlowId = useFlowsManagerStore(
|
const setCurrentFlowId = useFlowsManagerStore(
|
||||||
(state) => state.setCurrentFlowId
|
(state) => state.setCurrentFlowId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ export default function PlaygroundPage() {
|
||||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||||
const getFlowById = useFlowsManagerStore((state) => state.getFlowById);
|
const getFlowById = useFlowsManagerStore((state) => state.getFlowById);
|
||||||
const setCurrentFlowId = useFlowsManagerStore(
|
const setCurrentFlowId = useFlowsManagerStore(
|
||||||
(state) => state.setCurrentFlowId
|
(state) => state.setCurrentFlowId,
|
||||||
);
|
);
|
||||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||||
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { Badge } from "../../../../components/ui/badge";
|
||||||
import { Card, CardContent } from "../../../../components/ui/card";
|
import { Card, CardContent } from "../../../../components/ui/card";
|
||||||
import { deleteGlobalVariable } from "../../../../controllers/API";
|
import { deleteGlobalVariable } from "../../../../controllers/API";
|
||||||
import useAlertStore from "../../../../stores/alertStore";
|
import useAlertStore from "../../../../stores/alertStore";
|
||||||
import { useGlobalVariablesStore } from "../../../../stores/globalVariables";
|
import { useGlobalVariablesStore } from "../../../../stores/globalVariablesStore/globalVariables";
|
||||||
import { cn } from "../../../../utils/utils";
|
import { cn } from "../../../../utils/utils";
|
||||||
|
|
||||||
export default function GlobalVariablesPage() {
|
export default function GlobalVariablesPage() {
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
updateFlowPool: (
|
updateFlowPool: (
|
||||||
nodeId: string,
|
nodeId: string,
|
||||||
data: FlowPoolObjectType | ChatOutputType | chatInputType,
|
data: FlowPoolObjectType | ChatOutputType | chatInputType,
|
||||||
buildId?: string
|
buildId?: string,
|
||||||
) => {
|
) => {
|
||||||
let newFlowPool = cloneDeep({ ...get().flowPool });
|
let newFlowPool = cloneDeep({ ...get().flowPool });
|
||||||
if (!newFlowPool[nodeId]) {
|
if (!newFlowPool[nodeId]) {
|
||||||
|
|
@ -170,7 +170,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
flowsManager.autoSaveCurrentFlow(
|
flowsManager.autoSaveCurrentFlow(
|
||||||
newChange,
|
newChange,
|
||||||
newEdges,
|
newEdges,
|
||||||
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 }
|
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -186,7 +186,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
flowsManager.autoSaveCurrentFlow(
|
flowsManager.autoSaveCurrentFlow(
|
||||||
get().nodes,
|
get().nodes,
|
||||||
newChange,
|
newChange,
|
||||||
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 }
|
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -204,7 +204,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
return newChange;
|
return newChange;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
getNode: (id: string) => {
|
getNode: (id: string) => {
|
||||||
|
|
@ -215,8 +215,8 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
get().nodes.filter((node) =>
|
get().nodes.filter((node) =>
|
||||||
typeof nodeId === "string"
|
typeof nodeId === "string"
|
||||||
? node.id !== nodeId
|
? node.id !== nodeId
|
||||||
: !nodeId.includes(node.id)
|
: !nodeId.includes(node.id),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
deleteEdge: (edgeId) => {
|
deleteEdge: (edgeId) => {
|
||||||
|
|
@ -224,8 +224,8 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
get().edges.filter((edge) =>
|
get().edges.filter((edge) =>
|
||||||
typeof edgeId === "string"
|
typeof edgeId === "string"
|
||||||
? edge.id !== edgeId
|
? edge.id !== edgeId
|
||||||
: !edgeId.includes(edge.id)
|
: !edgeId.includes(edge.id),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
paste: (selection, position) => {
|
paste: (selection, position) => {
|
||||||
|
|
@ -291,7 +291,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
let source = idsMap[edge.source];
|
let source = idsMap[edge.source];
|
||||||
let target = idsMap[edge.target];
|
let target = idsMap[edge.target];
|
||||||
const sourceHandleObject: sourceHandleType = scapeJSONParse(
|
const sourceHandleObject: sourceHandleType = scapeJSONParse(
|
||||||
edge.sourceHandle!
|
edge.sourceHandle!,
|
||||||
);
|
);
|
||||||
let sourceHandle = scapedJSONStringfy({
|
let sourceHandle = scapedJSONStringfy({
|
||||||
...sourceHandleObject,
|
...sourceHandleObject,
|
||||||
|
|
@ -301,7 +301,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
|
|
||||||
edge.data.sourceHandle = sourceHandleObject;
|
edge.data.sourceHandle = sourceHandleObject;
|
||||||
const targetHandleObject: targetHandleType = scapeJSONParse(
|
const targetHandleObject: targetHandleType = scapeJSONParse(
|
||||||
edge.targetHandle!
|
edge.targetHandle!,
|
||||||
);
|
);
|
||||||
let targetHandle = scapedJSONStringfy({
|
let targetHandle = scapedJSONStringfy({
|
||||||
...targetHandleObject,
|
...targetHandleObject,
|
||||||
|
|
@ -322,7 +322,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
className: "stroke-gray-900 ",
|
className: "stroke-gray-900 ",
|
||||||
selected: false,
|
selected: false,
|
||||||
},
|
},
|
||||||
newEdges.map((edge) => ({ ...edge, selected: false }))
|
newEdges.map((edge) => ({ ...edge, selected: false })),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
get().setEdges(newEdges);
|
get().setEdges(newEdges);
|
||||||
|
|
@ -341,10 +341,10 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const newNodes = get().nodes.filter(
|
const newNodes = get().nodes.filter(
|
||||||
(node) => !nodesIdsSelected.includes(node.id)
|
(node) => !nodesIdsSelected.includes(node.id),
|
||||||
);
|
);
|
||||||
const newEdges = get().edges.filter(
|
const newEdges = get().edges.filter(
|
||||||
(edge) => !edgesIdsSelected.includes(edge.id)
|
(edge) => !edgesIdsSelected.includes(edge.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
set({ nodes: newNodes, edges: newEdges });
|
set({ nodes: newNodes, edges: newEdges });
|
||||||
|
|
@ -402,7 +402,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
style: { stroke: "#555" },
|
style: { stroke: "#555" },
|
||||||
className: "stroke-foreground stroke-connection",
|
className: "stroke-foreground stroke-connection",
|
||||||
},
|
},
|
||||||
oldEdges
|
oldEdges,
|
||||||
);
|
);
|
||||||
|
|
||||||
return newEdges;
|
return newEdges;
|
||||||
|
|
@ -412,7 +412,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
.autoSaveCurrentFlow(
|
.autoSaveCurrentFlow(
|
||||||
get().nodes,
|
get().nodes,
|
||||||
newEdges,
|
newEdges,
|
||||||
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 }
|
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 },
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
unselectAll: () => {
|
unselectAll: () => {
|
||||||
|
|
@ -443,7 +443,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
function validateSubgraph(nodes: string[]) {
|
function validateSubgraph(nodes: string[]) {
|
||||||
const errorsObjs = validateNodes(
|
const errorsObjs = validateNodes(
|
||||||
get().nodes.filter((node) => nodes.includes(node.id)),
|
get().nodes.filter((node) => nodes.includes(node.id)),
|
||||||
get().edges
|
get().edges,
|
||||||
);
|
);
|
||||||
|
|
||||||
const errors = errorsObjs.map((obj) => obj.errors).flat();
|
const errors = errorsObjs.map((obj) => obj.errors).flat();
|
||||||
|
|
@ -462,14 +462,14 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
function handleBuildUpdate(
|
function handleBuildUpdate(
|
||||||
vertexBuildData: VertexBuildTypeAPI,
|
vertexBuildData: VertexBuildTypeAPI,
|
||||||
status: BuildStatus,
|
status: BuildStatus,
|
||||||
runId: string
|
runId: string,
|
||||||
) {
|
) {
|
||||||
console.log("handleBuildUpdate", vertexBuildData, status, runId);
|
console.log("handleBuildUpdate", vertexBuildData, status, runId);
|
||||||
if (vertexBuildData && vertexBuildData.inactivated_vertices) {
|
if (vertexBuildData && vertexBuildData.inactivated_vertices) {
|
||||||
get().removeFromVerticesBuild(vertexBuildData.inactivated_vertices);
|
get().removeFromVerticesBuild(vertexBuildData.inactivated_vertices);
|
||||||
get().updateBuildStatus(
|
get().updateBuildStatus(
|
||||||
vertexBuildData.inactivated_vertices,
|
vertexBuildData.inactivated_vertices,
|
||||||
BuildStatus.INACTIVE
|
BuildStatus.INACTIVE,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -485,14 +485,15 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
|
|
||||||
// next_vertices_ids should be next_vertices_ids without the inactivated vertices
|
// next_vertices_ids should be next_vertices_ids without the inactivated vertices
|
||||||
const next_vertices_ids = vertexBuildData.next_vertices_ids.filter(
|
const next_vertices_ids = vertexBuildData.next_vertices_ids.filter(
|
||||||
(id) => !vertexBuildData.inactivated_vertices?.includes(id)
|
(id) => !vertexBuildData.inactivated_vertices?.includes(id),
|
||||||
);
|
);
|
||||||
const top_level_vertices = vertexBuildData.top_level_vertices.filter(
|
const top_level_vertices = vertexBuildData.top_level_vertices.filter(
|
||||||
(vertex) => !vertexBuildData.inactivated_vertices?.includes(vertex.id)
|
(vertex) =>
|
||||||
|
!vertexBuildData.inactivated_vertices?.includes(vertex.id),
|
||||||
);
|
);
|
||||||
const nextVertices: VertexLayerElementType[] = zip(
|
const nextVertices: VertexLayerElementType[] = zip(
|
||||||
next_vertices_ids,
|
next_vertices_ids,
|
||||||
top_level_vertices
|
top_level_vertices,
|
||||||
).map(([id, reference]) => ({ id: id!, reference }));
|
).map(([id, reference]) => ({ id: id!, reference }));
|
||||||
|
|
||||||
const newLayers = [
|
const newLayers = [
|
||||||
|
|
@ -514,7 +515,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
|
|
||||||
get().addDataToFlowPool(
|
get().addDataToFlowPool(
|
||||||
{ ...vertexBuildData, buildId: runId },
|
{ ...vertexBuildData, buildId: runId },
|
||||||
vertexBuildData.id
|
vertexBuildData.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
useFlowStore.getState().updateBuildStatus([vertexBuildData.id], status);
|
useFlowStore.getState().updateBuildStatus([vertexBuildData.id], status);
|
||||||
|
|
@ -523,7 +524,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
const newFlowBuildStatus = { ...get().flowBuildStatus };
|
const newFlowBuildStatus = { ...get().flowBuildStatus };
|
||||||
// filter out the vertices that are not status
|
// filter out the vertices that are not status
|
||||||
const verticesToUpdate = verticesIds?.filter(
|
const verticesToUpdate = verticesIds?.filter(
|
||||||
(id) => newFlowBuildStatus[id]?.status !== BuildStatus.BUILT
|
(id) => newFlowBuildStatus[id]?.status !== BuildStatus.BUILT,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (verticesToUpdate) {
|
if (verticesToUpdate) {
|
||||||
|
|
@ -588,7 +589,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
verticesLayers: VertexLayerElementType[][];
|
verticesLayers: VertexLayerElementType[][];
|
||||||
runId: string;
|
runId: string;
|
||||||
verticesToRun: string[];
|
verticesToRun: string[];
|
||||||
} | null
|
} | null,
|
||||||
) => {
|
) => {
|
||||||
set({ verticesBuild: vertices });
|
set({ verticesBuild: vertices });
|
||||||
},
|
},
|
||||||
|
|
@ -613,7 +614,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
// that are going to be built
|
// that are going to be built
|
||||||
verticesIds: get().verticesBuild!.verticesIds.filter(
|
verticesIds: get().verticesBuild!.verticesIds.filter(
|
||||||
// keep the vertices that are not in the list of vertices to remove
|
// keep the vertices that are not in the list of vertices to remove
|
||||||
(vertex) => !vertices.includes(vertex)
|
(vertex) => !vertices.includes(vertex),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -89,10 +89,10 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
if (dbData) {
|
if (dbData) {
|
||||||
const { data, flows } = processFlows(dbData, false);
|
const { data, flows } = processFlows(dbData, false);
|
||||||
const starterProjectsIds = starterProjects.flows!.map(
|
const starterProjectsIds = starterProjects.flows!.map(
|
||||||
(flow) => flow.id
|
(flow) => flow.id,
|
||||||
);
|
);
|
||||||
get().setFlows(
|
get().setFlows(
|
||||||
flows.filter((f) => !starterProjectsIds.includes(f.id))
|
flows.filter((f) => !starterProjectsIds.includes(f.id)),
|
||||||
);
|
);
|
||||||
useTypesStore.setState((state) => ({
|
useTypesStore.setState((state) => ({
|
||||||
data: { ...state.data, ["saved_components"]: data },
|
data: { ...state.data, ["saved_components"]: data },
|
||||||
|
|
@ -119,7 +119,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
if (get().currentFlow) {
|
if (get().currentFlow) {
|
||||||
get().saveFlow(
|
get().saveFlow(
|
||||||
{ ...get().currentFlow!, data: { nodes, edges, viewport } },
|
{ ...get().currentFlow!, data: { nodes, edges, viewport } },
|
||||||
true
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -145,7 +145,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
return updatedFlow;
|
return updatedFlow;
|
||||||
}
|
}
|
||||||
return flow;
|
return flow;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
//update tabs state
|
//update tabs state
|
||||||
|
|
||||||
|
|
@ -196,7 +196,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
flow?: FlowType,
|
flow?: FlowType,
|
||||||
override?: boolean,
|
override?: boolean,
|
||||||
position?: XYPosition,
|
position?: XYPosition,
|
||||||
fromDragAndDrop?: boolean
|
fromDragAndDrop?: boolean,
|
||||||
): Promise<string | undefined> => {
|
): Promise<string | undefined> => {
|
||||||
if (newProject) {
|
if (newProject) {
|
||||||
let flowData = flow
|
let flowData = flow
|
||||||
|
|
@ -263,7 +263,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
.getState()
|
.getState()
|
||||||
.paste(
|
.paste(
|
||||||
{ nodes: flow!.data!.nodes, edges: flow!.data!.edges },
|
{ nodes: flow!.data!.nodes, edges: flow!.data!.edges },
|
||||||
position ?? { x: 10, y: 10 }
|
position ?? { x: 10, y: 10 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -273,7 +273,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
multipleDeleteFlowsComponents(id)
|
multipleDeleteFlowsComponents(id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const { data, flows } = processFlows(
|
const { data, flows } = processFlows(
|
||||||
get().flows.filter((flow) => !id.includes(flow.id))
|
get().flows.filter((flow) => !id.includes(flow.id)),
|
||||||
);
|
);
|
||||||
get().setFlows(flows);
|
get().setFlows(flows);
|
||||||
set({ isLoading: false });
|
set({ isLoading: false });
|
||||||
|
|
@ -293,7 +293,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
deleteFlowFromDatabase(id)
|
deleteFlowFromDatabase(id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const { data, flows } = processFlows(
|
const { data, flows } = processFlows(
|
||||||
get().flows.filter((flow) => flow.id !== id)
|
get().flows.filter((flow) => flow.id !== id),
|
||||||
);
|
);
|
||||||
get().setFlows(flows);
|
get().setFlows(flows);
|
||||||
set({ isLoading: false });
|
set({ isLoading: false });
|
||||||
|
|
@ -315,7 +315,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
let componentFlow = get().flows.find(
|
let componentFlow = get().flows.find(
|
||||||
(componentFlow) =>
|
(componentFlow) =>
|
||||||
componentFlow.is_component && componentFlow.name === key
|
componentFlow.is_component && componentFlow.name === key,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (componentFlow) {
|
if (componentFlow) {
|
||||||
|
|
@ -363,7 +363,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
fileData,
|
fileData,
|
||||||
undefined,
|
undefined,
|
||||||
position,
|
position,
|
||||||
true
|
true,
|
||||||
);
|
);
|
||||||
resolve(id);
|
resolve(id);
|
||||||
}
|
}
|
||||||
|
|
@ -404,7 +404,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
return get().addFlow(
|
return get().addFlow(
|
||||||
true,
|
true,
|
||||||
createFlowComponent(component, useDarkStore.getState().version),
|
createFlowComponent(component, useDarkStore.getState().version),
|
||||||
override
|
override,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
takeSnapshot: () => {
|
takeSnapshot: () => {
|
||||||
|
|
@ -425,7 +425,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
if (pastLength > 0) {
|
if (pastLength > 0) {
|
||||||
past[currentFlowId] = past[currentFlowId].slice(
|
past[currentFlowId] = past[currentFlowId].slice(
|
||||||
pastLength - defaultOptions.maxHistorySize + 1,
|
pastLength - defaultOptions.maxHistorySize + 1,
|
||||||
pastLength
|
pastLength,
|
||||||
);
|
);
|
||||||
|
|
||||||
past[currentFlowId].push(newState);
|
past[currentFlowId].push(newState);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export const useFolderStore = create<FoldersStoreType>((set, get) => ({
|
||||||
(res) => {
|
(res) => {
|
||||||
set({ folders: res });
|
set({ folders: res });
|
||||||
const myCollectionId = res?.find(
|
const myCollectionId = res?.find(
|
||||||
(f) => f.name === DEFAULT_FOLDER
|
(f) => f.name === DEFAULT_FOLDER,
|
||||||
)?.id;
|
)?.id;
|
||||||
set({ myCollectionId });
|
set({ myCollectionId });
|
||||||
get().setLoading(false);
|
get().setLoading(false);
|
||||||
|
|
@ -26,7 +26,7 @@ export const useFolderStore = create<FoldersStoreType>((set, get) => ({
|
||||||
() => {
|
() => {
|
||||||
set({ folders: [] });
|
set({ folders: [] });
|
||||||
get().setLoading(false);
|
get().setLoading(false);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -45,7 +45,7 @@ export const useFolderStore = create<FoldersStoreType>((set, get) => ({
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
get().setLoadingById(false);
|
get().setLoadingById(false);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { GlobalVariablesStore } from "../types/zustand/globalVariables";
|
import { GlobalVariablesStore } from "../../types/zustand/globalVariables";
|
||||||
import { getUnavailableFields } from "../utils/utils";
|
import getUnavailableFields from "./utils/get-unavailable-fields";
|
||||||
|
|
||||||
export const useGlobalVariablesStore = create<GlobalVariablesStore>(
|
export const useGlobalVariablesStore = create<GlobalVariablesStore>(
|
||||||
(set, get) => ({
|
(set, get) => ({
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
export default function getUnavailableFields(variables: {
|
||||||
|
[key: string]: { default_fields?: string[] };
|
||||||
|
}): { [name: string]: string } {
|
||||||
|
const unVariables: { [name: string]: string } = {};
|
||||||
|
Object.keys(variables).forEach((key) => {
|
||||||
|
if (variables[key].default_fields) {
|
||||||
|
variables[key].default_fields!.forEach((field) => {
|
||||||
|
unVariables[field] = key;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return unVariables;
|
||||||
|
}
|
||||||
|
|
@ -515,7 +515,7 @@ export type nodeToolbarPropsType = {
|
||||||
updateNodeCode?: (
|
updateNodeCode?: (
|
||||||
newNodeClass: APIClassType,
|
newNodeClass: APIClassType,
|
||||||
code: string,
|
code: string,
|
||||||
name: string
|
name: string,
|
||||||
) => void;
|
) => void;
|
||||||
setShowState: (show: boolean | SetStateAction<boolean>) => void;
|
setShowState: (show: boolean | SetStateAction<boolean>) => void;
|
||||||
isOutdated?: boolean;
|
isOutdated?: boolean;
|
||||||
|
|
@ -565,7 +565,7 @@ export type chatMessagePropsType = {
|
||||||
updateChat: (
|
updateChat: (
|
||||||
chat: ChatMessageType,
|
chat: ChatMessageType,
|
||||||
message: string,
|
message: string,
|
||||||
stream_url?: string
|
stream_url?: string,
|
||||||
) => void;
|
) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -657,12 +657,12 @@ export type codeTabsPropsType = {
|
||||||
value: string,
|
value: string,
|
||||||
node: NodeType,
|
node: NodeType,
|
||||||
template: TemplateVariableType,
|
template: TemplateVariableType,
|
||||||
tweak: tweakType
|
tweak: tweakType,
|
||||||
) => string;
|
) => string;
|
||||||
buildTweakObject?: (
|
buildTweakObject?: (
|
||||||
tw: string,
|
tw: string,
|
||||||
changes: string | string[] | boolean | number | Object[] | Object,
|
changes: string | string[] | boolean | number | Object[] | Object,
|
||||||
template: TemplateVariableType
|
template: TemplateVariableType,
|
||||||
) => Promise<string | void>;
|
) => Promise<string | void>;
|
||||||
};
|
};
|
||||||
activeTweaks?: boolean;
|
activeTweaks?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ export type FlowStoreType = {
|
||||||
state:
|
state:
|
||||||
| FlowState
|
| FlowState
|
||||||
| undefined
|
| undefined
|
||||||
| ((oldState: FlowState | undefined) => FlowState)
|
| ((oldState: FlowState | undefined) => FlowState),
|
||||||
) => void;
|
) => void;
|
||||||
nodes: Node[];
|
nodes: Node[];
|
||||||
edges: Edge[];
|
edges: Edge[];
|
||||||
|
|
@ -78,11 +78,11 @@ export type FlowStoreType = {
|
||||||
onEdgesChange: OnEdgesChange;
|
onEdgesChange: OnEdgesChange;
|
||||||
setNodes: (
|
setNodes: (
|
||||||
update: Node[] | ((oldState: Node[]) => Node[]),
|
update: Node[] | ((oldState: Node[]) => Node[]),
|
||||||
skipSave?: boolean
|
skipSave?: boolean,
|
||||||
) => void;
|
) => void;
|
||||||
setEdges: (
|
setEdges: (
|
||||||
update: Edge[] | ((oldState: Edge[]) => Edge[]),
|
update: Edge[] | ((oldState: Edge[]) => Edge[]),
|
||||||
skipSave?: boolean
|
skipSave?: boolean,
|
||||||
) => void;
|
) => void;
|
||||||
setNode: (id: string, update: Node | ((oldState: Node) => Node)) => void;
|
setNode: (id: string, update: Node | ((oldState: Node) => Node)) => void;
|
||||||
getNode: (id: string) => Node | undefined;
|
getNode: (id: string) => Node | undefined;
|
||||||
|
|
@ -90,12 +90,12 @@ export type FlowStoreType = {
|
||||||
deleteEdge: (edgeId: string | Array<string>) => void;
|
deleteEdge: (edgeId: string | Array<string>) => void;
|
||||||
paste: (
|
paste: (
|
||||||
selection: { nodes: any; edges: any },
|
selection: { nodes: any; edges: any },
|
||||||
position: { x: number; y: number; paneX?: number; paneY?: number }
|
position: { x: number; y: number; paneX?: number; paneY?: number },
|
||||||
) => void;
|
) => void;
|
||||||
lastCopiedSelection: { nodes: any; edges: any } | null;
|
lastCopiedSelection: { nodes: any; edges: any } | null;
|
||||||
setLastCopiedSelection: (
|
setLastCopiedSelection: (
|
||||||
newSelection: { nodes: any; edges: any } | null,
|
newSelection: { nodes: any; edges: any } | null,
|
||||||
isCrop?: boolean
|
isCrop?: boolean,
|
||||||
) => void;
|
) => void;
|
||||||
cleanFlow: () => void;
|
cleanFlow: () => void;
|
||||||
setFilterEdge: (newState) => void;
|
setFilterEdge: (newState) => void;
|
||||||
|
|
@ -119,7 +119,7 @@ export type FlowStoreType = {
|
||||||
verticesLayers: VertexLayerElementType[][];
|
verticesLayers: VertexLayerElementType[][];
|
||||||
runId: string;
|
runId: string;
|
||||||
verticesToRun: string[];
|
verticesToRun: string[];
|
||||||
} | null
|
} | null,
|
||||||
) => void;
|
) => void;
|
||||||
addToVerticesBuild: (vertices: string[]) => void;
|
addToVerticesBuild: (vertices: string[]) => void;
|
||||||
removeFromVerticesBuild: (vertices: string[]) => void;
|
removeFromVerticesBuild: (vertices: string[]) => void;
|
||||||
|
|
@ -137,7 +137,7 @@ export type FlowStoreType = {
|
||||||
updateFlowPool: (
|
updateFlowPool: (
|
||||||
nodeId: string,
|
nodeId: string,
|
||||||
data: FlowPoolObjectType | ChatOutputType | chatInputType,
|
data: FlowPoolObjectType | ChatOutputType | chatInputType,
|
||||||
buildId?: string
|
buildId?: string,
|
||||||
) => void;
|
) => void;
|
||||||
getNodePosition: (nodeId: string) => { x: number; y: number };
|
getNodePosition: (nodeId: string) => { x: number; y: number };
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export const handleUpdateValues = async (name: string, data: NodeDataType) => {
|
||||||
code,
|
code,
|
||||||
template,
|
template,
|
||||||
name,
|
name,
|
||||||
data.node?.template[name]?.value
|
data.node?.template[name]?.value,
|
||||||
);
|
);
|
||||||
if (res.status === 200 && data.node?.template) {
|
if (res.status === 200 && data.node?.template) {
|
||||||
return res.data.template;
|
return res.data.template;
|
||||||
|
|
@ -34,5 +34,5 @@ export const handleUpdateValues = async (name: string, data: NodeDataType) => {
|
||||||
|
|
||||||
export const debouncedHandleUpdateValues = debounce(
|
export const debouncedHandleUpdateValues = debounce(
|
||||||
handleUpdateValues,
|
handleUpdateValues,
|
||||||
SAVE_DEBOUNCE_TIME
|
SAVE_DEBOUNCE_TIME,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,9 @@ import {
|
||||||
unselectAllNodesType,
|
unselectAllNodesType,
|
||||||
updateEdgesHandleIdsType,
|
updateEdgesHandleIdsType,
|
||||||
} from "../types/utils/reactflowUtils";
|
} from "../types/utils/reactflowUtils";
|
||||||
import {
|
import { createRandomKey, toTitleCase } from "./utils";
|
||||||
createRandomKey,
|
import { DESCRIPTIONS } from "../flow_constants";
|
||||||
getFieldTitle,
|
import getFieldTitle from "../customNodes/utils/get-field-title";
|
||||||
getRandomDescription,
|
|
||||||
toTitleCase,
|
|
||||||
} from "./utils";
|
|
||||||
const uid = new ShortUniqueId({ length: 5 });
|
const uid = new ShortUniqueId({ length: 5 });
|
||||||
|
|
||||||
export function checkChatInput(nodes: Node[]) {
|
export function checkChatInput(nodes: Node[]) {
|
||||||
|
|
@ -102,18 +99,18 @@ export function unselectAllNodes({ updateNodes, data }: unselectAllNodesType) {
|
||||||
export function isValidConnection(
|
export function isValidConnection(
|
||||||
{ source, target, sourceHandle, targetHandle }: Connection,
|
{ source, target, sourceHandle, targetHandle }: Connection,
|
||||||
nodes: Node[],
|
nodes: Node[],
|
||||||
edges: Edge[]
|
edges: Edge[],
|
||||||
) {
|
) {
|
||||||
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
|
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
|
||||||
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
|
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
|
||||||
if (
|
if (
|
||||||
targetHandleObject.inputTypes?.some(
|
targetHandleObject.inputTypes?.some(
|
||||||
(n) => n === sourceHandleObject.dataType
|
(n) => n === sourceHandleObject.dataType,
|
||||||
) ||
|
) ||
|
||||||
sourceHandleObject.baseClasses.some(
|
sourceHandleObject.baseClasses.some(
|
||||||
(t) =>
|
(t) =>
|
||||||
targetHandleObject.inputTypes?.some((n) => n === t) ||
|
targetHandleObject.inputTypes?.some((n) => n === t) ||
|
||||||
t === targetHandleObject.type
|
t === targetHandleObject.type,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
let targetNode = nodes.find((node) => node.id === target!)?.data?.node;
|
let targetNode = nodes.find((node) => node.id === target!)?.data?.node;
|
||||||
|
|
@ -146,7 +143,7 @@ export function removeApiKeys(flow: FlowType): FlowType {
|
||||||
|
|
||||||
export function updateTemplate(
|
export function updateTemplate(
|
||||||
reference: APITemplateType,
|
reference: APITemplateType,
|
||||||
objectToUpdate: APITemplateType
|
objectToUpdate: APITemplateType,
|
||||||
): APITemplateType {
|
): APITemplateType {
|
||||||
let clonedObject: APITemplateType = cloneDeep(reference);
|
let clonedObject: APITemplateType = cloneDeep(reference);
|
||||||
|
|
||||||
|
|
@ -206,7 +203,7 @@ export const processDataFromFlow = (flow: FlowType, refreshIds = true) => {
|
||||||
|
|
||||||
export function updateIds(
|
export function updateIds(
|
||||||
{ edges, nodes }: { edges: Edge[]; nodes: Node[] },
|
{ edges, nodes }: { edges: Edge[]; nodes: Node[] },
|
||||||
selection?: { edges: Edge[]; nodes: Node[] }
|
selection?: { edges: Edge[]; nodes: Node[] },
|
||||||
) {
|
) {
|
||||||
let idsMap = {};
|
let idsMap = {};
|
||||||
const selectionIds = selection?.nodes.map((n) => n.id);
|
const selectionIds = selection?.nodes.map((n) => n.id);
|
||||||
|
|
@ -234,7 +231,7 @@ export function updateIds(
|
||||||
edge.source = idsMap[edge.source];
|
edge.source = idsMap[edge.source];
|
||||||
edge.target = idsMap[edge.target];
|
edge.target = idsMap[edge.target];
|
||||||
const sourceHandleObject: sourceHandleType = scapeJSONParse(
|
const sourceHandleObject: sourceHandleType = scapeJSONParse(
|
||||||
edge.sourceHandle!
|
edge.sourceHandle!,
|
||||||
);
|
);
|
||||||
edge.sourceHandle = scapedJSONStringfy({
|
edge.sourceHandle = scapedJSONStringfy({
|
||||||
...sourceHandleObject,
|
...sourceHandleObject,
|
||||||
|
|
@ -244,7 +241,7 @@ export function updateIds(
|
||||||
edge.data.sourceHandle.id = edge.source;
|
edge.data.sourceHandle.id = edge.source;
|
||||||
}
|
}
|
||||||
const targetHandleObject: targetHandleType = scapeJSONParse(
|
const targetHandleObject: targetHandleType = scapeJSONParse(
|
||||||
edge.targetHandle!
|
edge.targetHandle!,
|
||||||
);
|
);
|
||||||
edge.targetHandle = scapedJSONStringfy({
|
edge.targetHandle = scapedJSONStringfy({
|
||||||
...targetHandleObject,
|
...targetHandleObject,
|
||||||
|
|
@ -290,11 +287,11 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
|
||||||
(scapeJSONParse(edge.targetHandle!) as targetHandleType).fieldName ===
|
(scapeJSONParse(edge.targetHandle!) as targetHandleType).fieldName ===
|
||||||
t &&
|
t &&
|
||||||
(scapeJSONParse(edge.targetHandle!) as targetHandleType).id ===
|
(scapeJSONParse(edge.targetHandle!) as targetHandleType).id ===
|
||||||
node.id
|
node.id,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
errors.push(
|
errors.push(
|
||||||
`${displayName || type} is missing ${getFieldTitle(template, t)}.`
|
`${displayName || type} is missing ${getFieldTitle(template, t)}.`,
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
template[t].type === "dict" &&
|
template[t].type === "dict" &&
|
||||||
|
|
@ -308,15 +305,15 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
|
||||||
errors.push(
|
errors.push(
|
||||||
`${displayName || type} (${getFieldTitle(
|
`${displayName || type} (${getFieldTitle(
|
||||||
template,
|
template,
|
||||||
t
|
t,
|
||||||
)}) contains duplicate keys with the same values.`
|
)}) contains duplicate keys with the same values.`,
|
||||||
);
|
);
|
||||||
if (hasEmptyKey(template[t].value))
|
if (hasEmptyKey(template[t].value))
|
||||||
errors.push(
|
errors.push(
|
||||||
`${displayName || type} (${getFieldTitle(
|
`${displayName || type} (${getFieldTitle(
|
||||||
template,
|
template,
|
||||||
t
|
t,
|
||||||
)}) field must not be empty.`
|
)}) field must not be empty.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return errors;
|
return errors;
|
||||||
|
|
@ -325,7 +322,7 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
|
||||||
|
|
||||||
export function validateNodes(
|
export function validateNodes(
|
||||||
nodes: Node[],
|
nodes: Node[],
|
||||||
edges: Edge[]
|
edges: Edge[],
|
||||||
): // this returns an array of tuples with the node id and the errors
|
): // this returns an array of tuples with the node id and the errors
|
||||||
Array<{ id: string; errors: Array<string> }> {
|
Array<{ id: string; errors: Array<string> }> {
|
||||||
if (nodes.length === 0) {
|
if (nodes.length === 0) {
|
||||||
|
|
@ -346,7 +343,7 @@ export function updateEdges(edges: Edge[]) {
|
||||||
if (edges)
|
if (edges)
|
||||||
edges.forEach((edge) => {
|
edges.forEach((edge) => {
|
||||||
const targetHandleObject: targetHandleType = scapeJSONParse(
|
const targetHandleObject: targetHandleType = scapeJSONParse(
|
||||||
edge.targetHandle!
|
edge.targetHandle!,
|
||||||
);
|
);
|
||||||
edge.className = "stroke-gray-900 stroke-connection";
|
edge.className = "stroke-gray-900 stroke-connection";
|
||||||
});
|
});
|
||||||
|
|
@ -413,7 +410,7 @@ export function handleKeyDown(
|
||||||
| React.KeyboardEvent<HTMLInputElement>
|
| React.KeyboardEvent<HTMLInputElement>
|
||||||
| React.KeyboardEvent<HTMLTextAreaElement>,
|
| React.KeyboardEvent<HTMLTextAreaElement>,
|
||||||
inputValue: string | string[] | null,
|
inputValue: string | string[] | null,
|
||||||
block: string
|
block: string,
|
||||||
) {
|
) {
|
||||||
//condition to fix bug control+backspace on Windows/Linux
|
//condition to fix bug control+backspace on Windows/Linux
|
||||||
if (
|
if (
|
||||||
|
|
@ -438,7 +435,7 @@ export function handleKeyDown(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleOnlyIntegerInput(
|
export function handleOnlyIntegerInput(
|
||||||
event: React.KeyboardEvent<HTMLInputElement>
|
event: React.KeyboardEvent<HTMLInputElement>,
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
event.key === "." ||
|
event.key === "." ||
|
||||||
|
|
@ -454,7 +451,7 @@ export function handleOnlyIntegerInput(
|
||||||
|
|
||||||
export function getConnectedNodes(
|
export function getConnectedNodes(
|
||||||
edge: Edge,
|
edge: Edge,
|
||||||
nodes: Array<NodeType>
|
nodes: Array<NodeType>,
|
||||||
): Array<NodeType> {
|
): Array<NodeType> {
|
||||||
const sourceId = edge.source;
|
const sourceId = edge.source;
|
||||||
const targetId = edge.target;
|
const targetId = edge.target;
|
||||||
|
|
@ -555,7 +552,7 @@ export function checkOldEdgesHandles(edges: Edge[]): boolean {
|
||||||
!edge.sourceHandle ||
|
!edge.sourceHandle ||
|
||||||
!edge.targetHandle ||
|
!edge.targetHandle ||
|
||||||
!edge.sourceHandle.includes("{") ||
|
!edge.sourceHandle.includes("{") ||
|
||||||
!edge.targetHandle.includes("{")
|
!edge.targetHandle.includes("{"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -578,7 +575,7 @@ export function customStringify(obj: any): string {
|
||||||
|
|
||||||
const keys = Object.keys(obj).sort();
|
const keys = Object.keys(obj).sort();
|
||||||
const keyValuePairs = keys.map(
|
const keyValuePairs = keys.map(
|
||||||
(key) => `"${key}":${customStringify(obj[key])}`
|
(key) => `"${key}":${customStringify(obj[key])}`,
|
||||||
);
|
);
|
||||||
return `{${keyValuePairs.join(",")}}`;
|
return `{${keyValuePairs.join(",")}}`;
|
||||||
}
|
}
|
||||||
|
|
@ -607,7 +604,7 @@ export function getHandleId(
|
||||||
source: string,
|
source: string,
|
||||||
sourceHandle: string,
|
sourceHandle: string,
|
||||||
target: string,
|
target: string,
|
||||||
targetHandle: string
|
targetHandle: string,
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
"reactflow__edge-" + source + sourceHandle + "-" + target + targetHandle
|
"reactflow__edge-" + source + sourceHandle + "-" + target + targetHandle
|
||||||
|
|
@ -618,7 +615,7 @@ export function generateFlow(
|
||||||
selection: OnSelectionChangeParams,
|
selection: OnSelectionChangeParams,
|
||||||
nodes: Node[],
|
nodes: Node[],
|
||||||
edges: Edge[],
|
edges: Edge[],
|
||||||
name: string
|
name: string,
|
||||||
): generateFlowType {
|
): generateFlowType {
|
||||||
const newFlowData = { nodes, edges, viewport: { zoom: 1, x: 0, y: 0 } };
|
const newFlowData = { nodes, edges, viewport: { zoom: 1, x: 0, y: 0 } };
|
||||||
const uid = new ShortUniqueId({ length: 5 });
|
const uid = new ShortUniqueId({ length: 5 });
|
||||||
|
|
@ -627,7 +624,7 @@ export function generateFlow(
|
||||||
newFlowData.edges = selection.edges.filter(
|
newFlowData.edges = selection.edges.filter(
|
||||||
(edge) =>
|
(edge) =>
|
||||||
selection.nodes.some((node) => node.id === edge.target) &&
|
selection.nodes.some((node) => node.id === edge.target) &&
|
||||||
selection.nodes.some((node) => node.id === edge.source)
|
selection.nodes.some((node) => node.id === edge.source),
|
||||||
);
|
);
|
||||||
newFlowData.nodes = selection.nodes;
|
newFlowData.nodes = selection.nodes;
|
||||||
|
|
||||||
|
|
@ -648,7 +645,7 @@ export function generateFlow(
|
||||||
(edge) =>
|
(edge) =>
|
||||||
(selection.nodes.some((node) => node.id === edge.target) ||
|
(selection.nodes.some((node) => node.id === edge.target) ||
|
||||||
selection.nodes.some((node) => node.id === edge.source)) &&
|
selection.nodes.some((node) => node.id === edge.source)) &&
|
||||||
newFlowData.edges.every((e) => e.id !== edge.id)
|
newFlowData.edges.every((e) => e.id !== edge.id),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -659,13 +656,13 @@ export function reconnectEdges(groupNode: NodeType, excludedEdges: Edge[]) {
|
||||||
const { nodes, edges } = groupNode.data.node!.flow!.data!;
|
const { nodes, edges } = groupNode.data.node!.flow!.data!;
|
||||||
const lastNode = findLastNode(groupNode.data.node!.flow!.data!);
|
const lastNode = findLastNode(groupNode.data.node!.flow!.data!);
|
||||||
newEdges = newEdges.filter(
|
newEdges = newEdges.filter(
|
||||||
(e) => !(nodes.some((n) => n.id === e.source) && e.source !== lastNode?.id)
|
(e) => !(nodes.some((n) => n.id === e.source) && e.source !== lastNode?.id),
|
||||||
);
|
);
|
||||||
newEdges.forEach((edge) => {
|
newEdges.forEach((edge) => {
|
||||||
if (lastNode && edge.source === lastNode.id) {
|
if (lastNode && edge.source === lastNode.id) {
|
||||||
edge.source = groupNode.id;
|
edge.source = groupNode.id;
|
||||||
let newSourceHandle: sourceHandleType = scapeJSONParse(
|
let newSourceHandle: sourceHandleType = scapeJSONParse(
|
||||||
edge.sourceHandle!
|
edge.sourceHandle!,
|
||||||
);
|
);
|
||||||
newSourceHandle.id = groupNode.id;
|
newSourceHandle.id = groupNode.id;
|
||||||
edge.sourceHandle = scapedJSONStringfy(newSourceHandle);
|
edge.sourceHandle = scapedJSONStringfy(newSourceHandle);
|
||||||
|
|
@ -692,7 +689,7 @@ export function reconnectEdges(groupNode: NodeType, excludedEdges: Edge[]) {
|
||||||
export function filterFlow(
|
export function filterFlow(
|
||||||
selection: OnSelectionChangeParams,
|
selection: OnSelectionChangeParams,
|
||||||
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
|
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
|
||||||
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void
|
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
|
||||||
) {
|
) {
|
||||||
setNodes((nodes) => nodes.filter((node) => !selection.nodes.includes(node)));
|
setNodes((nodes) => nodes.filter((node) => !selection.nodes.includes(node)));
|
||||||
setEdges((edges) => edges.filter((edge) => !selection.edges.includes(edge)));
|
setEdges((edges) => edges.filter((edge) => !selection.edges.includes(edge)));
|
||||||
|
|
@ -730,7 +727,7 @@ export function updateFlowPosition(NewPosition: XYPosition, flow: FlowType) {
|
||||||
export function concatFlows(
|
export function concatFlows(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
|
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
|
||||||
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void
|
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
|
||||||
) {
|
) {
|
||||||
const { nodes, edges } = flow.data!;
|
const { nodes, edges } = flow.data!;
|
||||||
setNodes((old) => [...old, ...nodes]);
|
setNodes((old) => [...old, ...nodes]);
|
||||||
|
|
@ -739,7 +736,7 @@ export function concatFlows(
|
||||||
|
|
||||||
export function validateSelection(
|
export function validateSelection(
|
||||||
selection: OnSelectionChangeParams,
|
selection: OnSelectionChangeParams,
|
||||||
edges: Edge[]
|
edges: Edge[],
|
||||||
): Array<string> {
|
): Array<string> {
|
||||||
const clonedSelection = cloneDeep(selection);
|
const clonedSelection = cloneDeep(selection);
|
||||||
const clonedEdges = cloneDeep(edges);
|
const clonedEdges = cloneDeep(edges);
|
||||||
|
|
@ -753,7 +750,7 @@ export function validateSelection(
|
||||||
let nodesSet = new Set(clonedSelection.nodes.map((n) => n.id));
|
let nodesSet = new Set(clonedSelection.nodes.map((n) => n.id));
|
||||||
// then filter the edges that are connected to the nodes in the set
|
// then filter the edges that are connected to the nodes in the set
|
||||||
let connectedEdges = clonedSelection.edges.filter(
|
let connectedEdges = clonedSelection.edges.filter(
|
||||||
(e) => nodesSet.has(e.source) && nodesSet.has(e.target)
|
(e) => nodesSet.has(e.source) && nodesSet.has(e.target),
|
||||||
);
|
);
|
||||||
// add the edges to the selection
|
// add the edges to the selection
|
||||||
clonedSelection.edges = connectedEdges;
|
clonedSelection.edges = connectedEdges;
|
||||||
|
|
@ -767,17 +764,17 @@ export function validateSelection(
|
||||||
clonedSelection.nodes.some(
|
clonedSelection.nodes.some(
|
||||||
(node) =>
|
(node) =>
|
||||||
isInputNode(node.data as NodeDataType) ||
|
isInputNode(node.data as NodeDataType) ||
|
||||||
isOutputNode(node.data as NodeDataType)
|
isOutputNode(node.data as NodeDataType),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
errorsArray.push(
|
errorsArray.push(
|
||||||
"Please select only nodes that are not input or output nodes"
|
"Please select only nodes that are not input or output nodes",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
//check if there are two or more nodes with free outputs
|
//check if there are two or more nodes with free outputs
|
||||||
if (
|
if (
|
||||||
clonedSelection.nodes.filter(
|
clonedSelection.nodes.filter(
|
||||||
(n) => !clonedSelection.edges.some((e) => e.source === n.id)
|
(n) => !clonedSelection.edges.some((e) => e.source === n.id),
|
||||||
).length > 1
|
).length > 1
|
||||||
) {
|
) {
|
||||||
errorsArray.push("Please select only one node with free outputs");
|
errorsArray.push("Please select only one node with free outputs");
|
||||||
|
|
@ -788,7 +785,7 @@ export function validateSelection(
|
||||||
clonedSelection.nodes.some(
|
clonedSelection.nodes.some(
|
||||||
(node) =>
|
(node) =>
|
||||||
!clonedSelection.edges.some((edge) => edge.target === node.id) &&
|
!clonedSelection.edges.some((edge) => edge.target === node.id) &&
|
||||||
!clonedSelection.edges.some((edge) => edge.source === node.id)
|
!clonedSelection.edges.some((edge) => edge.source === node.id),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
errorsArray.push("Please select only nodes that are connected");
|
errorsArray.push("Please select only nodes that are connected");
|
||||||
|
|
@ -845,8 +842,8 @@ export function mergeNodeTemplates({
|
||||||
nodeTemplate[key].display_name
|
nodeTemplate[key].display_name
|
||||||
? nodeTemplate[key].display_name
|
? nodeTemplate[key].display_name
|
||||||
: nodeTemplate[key].name
|
: nodeTemplate[key].name
|
||||||
? toTitleCase(nodeTemplate[key].name)
|
? toTitleCase(nodeTemplate[key].name)
|
||||||
: toTitleCase(key);
|
: toTitleCase(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -857,7 +854,7 @@ function isHandleConnected(
|
||||||
edges: Edge[],
|
edges: Edge[],
|
||||||
key: string,
|
key: string,
|
||||||
field: TemplateVariableType,
|
field: TemplateVariableType,
|
||||||
nodeId: string
|
nodeId: string,
|
||||||
) {
|
) {
|
||||||
/*
|
/*
|
||||||
this function receives a flow and a handleId and check if there is a connection with this handle
|
this function receives a flow and a handleId and check if there is a connection with this handle
|
||||||
|
|
@ -873,7 +870,7 @@ function isHandleConnected(
|
||||||
id: nodeId,
|
id: nodeId,
|
||||||
proxy: { id: field.proxy!.id, field: field.proxy!.field },
|
proxy: { id: field.proxy!.id, field: field.proxy!.field },
|
||||||
inputTypes: field.input_types,
|
inputTypes: field.input_types,
|
||||||
} as targetHandleType)
|
} as targetHandleType),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -888,7 +885,7 @@ function isHandleConnected(
|
||||||
fieldName: key,
|
fieldName: key,
|
||||||
id: nodeId,
|
id: nodeId,
|
||||||
inputTypes: field.input_types,
|
inputTypes: field.input_types,
|
||||||
} as targetHandleType)
|
} as targetHandleType),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -911,7 +908,7 @@ export function generateNodeTemplate(Flow: FlowType) {
|
||||||
|
|
||||||
export function generateNodeFromFlow(
|
export function generateNodeFromFlow(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
getNodeId: (type: string) => string
|
getNodeId: (type: string) => string,
|
||||||
): NodeType {
|
): NodeType {
|
||||||
const { nodes } = flow.data!;
|
const { nodes } = flow.data!;
|
||||||
const outputNode = cloneDeep(findLastNode(flow.data!));
|
const outputNode = cloneDeep(findLastNode(flow.data!));
|
||||||
|
|
@ -942,7 +939,7 @@ export function generateNodeFromFlow(
|
||||||
export function connectedInputNodesOnHandle(
|
export function connectedInputNodesOnHandle(
|
||||||
nodeId: string,
|
nodeId: string,
|
||||||
handleId: string,
|
handleId: string,
|
||||||
{ nodes, edges }: { nodes: NodeType[]; edges: Edge[] }
|
{ nodes, edges }: { nodes: NodeType[]; edges: Edge[] },
|
||||||
) {
|
) {
|
||||||
const connectedNodes: Array<{ name: string; id: string; isGroup: boolean }> =
|
const connectedNodes: Array<{ name: string; id: string; isGroup: boolean }> =
|
||||||
[];
|
[];
|
||||||
|
|
@ -979,7 +976,7 @@ export function connectedInputNodesOnHandle(
|
||||||
|
|
||||||
export function updateProxyIdsOnTemplate(
|
export function updateProxyIdsOnTemplate(
|
||||||
template: APITemplateType,
|
template: APITemplateType,
|
||||||
idsMap: { [key: string]: string }
|
idsMap: { [key: string]: string },
|
||||||
) {
|
) {
|
||||||
Object.keys(template).forEach((key) => {
|
Object.keys(template).forEach((key) => {
|
||||||
if (template[key].proxy && idsMap[template[key].proxy!.id]) {
|
if (template[key].proxy && idsMap[template[key].proxy!.id]) {
|
||||||
|
|
@ -990,7 +987,7 @@ export function updateProxyIdsOnTemplate(
|
||||||
|
|
||||||
export function updateEdgesIds(
|
export function updateEdgesIds(
|
||||||
edges: Edge[],
|
edges: Edge[],
|
||||||
idsMap: { [key: string]: string }
|
idsMap: { [key: string]: string },
|
||||||
) {
|
) {
|
||||||
edges.forEach((edge) => {
|
edges.forEach((edge) => {
|
||||||
let targetHandle: targetHandleType = edge.data.targetHandle;
|
let targetHandle: targetHandleType = edge.data.targetHandle;
|
||||||
|
|
@ -1022,7 +1019,7 @@ export function expandGroupNode(
|
||||||
nodes: Node[],
|
nodes: Node[],
|
||||||
edges: Edge[],
|
edges: Edge[],
|
||||||
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
|
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
|
||||||
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void
|
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
|
||||||
) {
|
) {
|
||||||
const idsMap = updateIds(flow!.data!);
|
const idsMap = updateIds(flow!.data!);
|
||||||
updateProxyIdsOnTemplate(template, idsMap);
|
updateProxyIdsOnTemplate(template, idsMap);
|
||||||
|
|
@ -1065,7 +1062,7 @@ export function expandGroupNode(
|
||||||
const lastNode = cloneDeep(findLastNode(flow!.data!));
|
const lastNode = cloneDeep(findLastNode(flow!.data!));
|
||||||
newEdge.source = lastNode!.id;
|
newEdge.source = lastNode!.id;
|
||||||
let newSourceHandle: sourceHandleType = scapeJSONParse(
|
let newSourceHandle: sourceHandleType = scapeJSONParse(
|
||||||
newEdge.sourceHandle!
|
newEdge.sourceHandle!,
|
||||||
);
|
);
|
||||||
newSourceHandle.id = lastNode!.id;
|
newSourceHandle.id = lastNode!.id;
|
||||||
newEdge.data.sourceHandle = newSourceHandle;
|
newEdge.data.sourceHandle = newSourceHandle;
|
||||||
|
|
@ -1122,7 +1119,7 @@ export function expandGroupNode(
|
||||||
|
|
||||||
export function getGroupStatus(
|
export function getGroupStatus(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
ssData: { [key: string]: { valid: boolean; params: string } }
|
ssData: { [key: string]: { valid: boolean; params: string } },
|
||||||
) {
|
) {
|
||||||
let status = { valid: true, params: SUCCESS_BUILD };
|
let status = { valid: true, params: SUCCESS_BUILD };
|
||||||
const { nodes } = flow.data!;
|
const { nodes } = flow.data!;
|
||||||
|
|
@ -1141,7 +1138,7 @@ export function getGroupStatus(
|
||||||
|
|
||||||
export function createFlowComponent(
|
export function createFlowComponent(
|
||||||
nodeData: NodeDataType,
|
nodeData: NodeDataType,
|
||||||
version: string
|
version: string,
|
||||||
): FlowType {
|
): FlowType {
|
||||||
const flowNode: FlowType = {
|
const flowNode: FlowType = {
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -1177,7 +1174,7 @@ export function downloadNode(NodeFLow: FlowType) {
|
||||||
|
|
||||||
export function updateComponentNameAndType(
|
export function updateComponentNameAndType(
|
||||||
data: any,
|
data: any,
|
||||||
component: NodeDataType
|
component: NodeDataType,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
export function removeFileNameFromComponents(flow: FlowType) {
|
export function removeFileNameFromComponents(flow: FlowType) {
|
||||||
|
|
@ -1251,7 +1248,7 @@ export function extractFieldsFromComponenents(data: APIObjectType) {
|
||||||
export function downloadFlow(
|
export function downloadFlow(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
flowName: string,
|
flowName: string,
|
||||||
flowDescription?: string
|
flowDescription?: string,
|
||||||
) {
|
) {
|
||||||
let clonedFlow = cloneDeep(flow);
|
let clonedFlow = cloneDeep(flow);
|
||||||
removeFileNameFromComponents(clonedFlow);
|
removeFileNameFromComponents(clonedFlow);
|
||||||
|
|
@ -1261,7 +1258,7 @@ export function downloadFlow(
|
||||||
...clonedFlow,
|
...clonedFlow,
|
||||||
name: flowName,
|
name: flowName,
|
||||||
description: flowDescription,
|
description: flowDescription,
|
||||||
})
|
}),
|
||||||
)}`;
|
)}`;
|
||||||
|
|
||||||
// create a link element and set its properties
|
// create a link element and set its properties
|
||||||
|
|
@ -1276,7 +1273,7 @@ export function downloadFlow(
|
||||||
export function downloadFlows() {
|
export function downloadFlows() {
|
||||||
downloadFlowsFromDatabase().then((flows) => {
|
downloadFlowsFromDatabase().then((flows) => {
|
||||||
const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
|
const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
|
||||||
JSON.stringify(flows)
|
JSON.stringify(flows),
|
||||||
)}`;
|
)}`;
|
||||||
|
|
||||||
// create a link element and set its properties
|
// create a link element and set its properties
|
||||||
|
|
@ -1289,9 +1286,17 @@ export function downloadFlows() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRandomElement<T>(array: T[]): T {
|
||||||
|
return array[Math.floor(Math.random() * array.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRandomDescription(): string {
|
||||||
|
return getRandomElement(DESCRIPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
export const createNewFlow = (
|
export const createNewFlow = (
|
||||||
flowData: ReactFlowJsonObject,
|
flowData: ReactFlowJsonObject,
|
||||||
flow: FlowType
|
flow: FlowType,
|
||||||
) => {
|
) => {
|
||||||
return {
|
return {
|
||||||
description: flow?.description ?? getRandomDescription(),
|
description: flow?.description ?? getRandomDescription(),
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export default function cloneFLowWithParent(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
parent: string,
|
parent: string,
|
||||||
is_component: boolean,
|
is_component: boolean,
|
||||||
keepId = false
|
keepId = false,
|
||||||
) {
|
) {
|
||||||
let childFLow = cloneDeep(flow);
|
let childFLow = cloneDeep(flow);
|
||||||
childFLow.parent = parent;
|
childFLow.parent = parent;
|
||||||
|
|
@ -20,15 +20,6 @@ export default function cloneFLowWithParent(
|
||||||
return childFLow;
|
return childFLow;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTagsIds(
|
|
||||||
tags: string[],
|
|
||||||
tagListId: { name: string; id: string }[]
|
|
||||||
) {
|
|
||||||
return tags
|
|
||||||
.map((tag) => tagListId.find((tagObj) => tagObj.name === tag))!
|
|
||||||
.map((tag) => tag!.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getInputsAndOutputs(nodes: Node[]) {
|
export function getInputsAndOutputs(nodes: Node[]) {
|
||||||
let inputs: { type: string; id: string; displayName: string }[] = [];
|
let inputs: { type: string; id: string; displayName: string }[] = [];
|
||||||
let outputs: { type: string; id: string; displayName: string }[] = [];
|
let outputs: { type: string; id: string; displayName: string }[] = [];
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,8 @@ import { twMerge } from "tailwind-merge";
|
||||||
import TableAutoCellRender from "../components/tableAutoCellRender";
|
import TableAutoCellRender from "../components/tableAutoCellRender";
|
||||||
import { priorityFields } from "../constants/constants";
|
import { priorityFields } from "../constants/constants";
|
||||||
import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "../flow_constants";
|
import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "../flow_constants";
|
||||||
|
import { APIDataType, TemplateVariableType } from "../types/api";
|
||||||
import {
|
import {
|
||||||
APIDataType,
|
|
||||||
APITemplateType,
|
|
||||||
TemplateVariableType,
|
|
||||||
} from "../types/api";
|
|
||||||
import {
|
|
||||||
IVarHighlightType,
|
|
||||||
groupedObjType,
|
groupedObjType,
|
||||||
nodeGroupedObjType,
|
nodeGroupedObjType,
|
||||||
tweakType,
|
tweakType,
|
||||||
|
|
@ -92,20 +87,6 @@ export function toTitleCase(
|
||||||
.join(" ");
|
.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUnavailableFields(variables: {
|
|
||||||
[key: string]: { default_fields?: string[] };
|
|
||||||
}): { [name: string]: string } {
|
|
||||||
const unVariables: { [name: string]: string } = {};
|
|
||||||
Object.keys(variables).forEach((key) => {
|
|
||||||
if (variables[key].default_fields) {
|
|
||||||
variables[key].default_fields!.forEach((field) => {
|
|
||||||
unVariables[field] = key;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return unVariables;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const upperCaseWords: string[] = ["llm", "uri"];
|
export const upperCaseWords: string[] = ["llm", "uri"];
|
||||||
export function checkUpperWords(str: string): string {
|
export function checkUpperWords(str: string): string {
|
||||||
const words = str.split(" ").map((word) => {
|
const words = str.split(" ").map((word) => {
|
||||||
|
|
@ -117,8 +98,121 @@ export function checkUpperWords(str: string): string {
|
||||||
return words.join(" ");
|
return words.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isWrappedWithClass = (event: any, className: string | undefined) =>
|
export function buildInputs(): string {
|
||||||
event.target.closest(`.${className}`);
|
return '{"input_value": "message"}';
|
||||||
|
}
|
||||||
|
|
||||||
|
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 + Math.abs(Math.floor(Math.random() * 10001));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildTweakObject(tweak: tweakType) {
|
||||||
|
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.at(-1), null, 2);
|
||||||
|
return tweakString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to get Chat Input Field
|
||||||
|
* @param {FlowsState} tabsState - The current tabs state.
|
||||||
|
* @returns {string} - The chat input field
|
||||||
|
*/
|
||||||
|
export function getChatInputField(flowState?: FlowState) {
|
||||||
|
let chat_input_field = "text";
|
||||||
|
|
||||||
|
if (flowState && flowState.input_keys) {
|
||||||
|
chat_input_field = Object.keys(flowState.input_keys!)[0];
|
||||||
|
}
|
||||||
|
return chat_input_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getOutputIds(flow) {
|
||||||
|
const nodes = flow.data!.nodes;
|
||||||
|
|
||||||
|
const arrayOfOutputs = nodes.reduce((acc: string[], node) => {
|
||||||
|
if (node.data.type.toLowerCase().includes("output")) {
|
||||||
|
acc.push(node.id);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const arrayOfOutputsJoin = arrayOfOutputs
|
||||||
|
.map((output) => `"${output}"`)
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
return arrayOfOutputsJoin;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function truncateLongId(id: string): string {
|
||||||
|
let [componentName, newId] = id.split("-");
|
||||||
|
if (componentName.length > 15) {
|
||||||
|
componentName = componentName.slice(0, 15);
|
||||||
|
componentName += "...";
|
||||||
|
return componentName + "-" + newId;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function extractIdFromLongId(id: string): string {
|
||||||
|
let [_, newId] = id.split("-");
|
||||||
|
return newId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function truncateDisplayName(name: string): string {
|
||||||
|
if (name.length > 15) {
|
||||||
|
name = name.slice(0, 15);
|
||||||
|
name += "...";
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkLocalStorageKey(key: string): boolean {
|
||||||
|
return localStorage.getItem(key) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IncrementObjectKey(
|
||||||
|
object: object,
|
||||||
|
key: string,
|
||||||
|
): { newKey: string; increment: number } {
|
||||||
|
let count = 1;
|
||||||
|
const type = removeCountFromString(key);
|
||||||
|
let newKey = type + " " + `(${count})`;
|
||||||
|
while (object[newKey]) {
|
||||||
|
count++;
|
||||||
|
newKey = type + " " + `(${count})`;
|
||||||
|
}
|
||||||
|
return { newKey, increment: count };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeCountFromString(input: string): string {
|
||||||
|
// Define a regex pattern to match the count in parentheses
|
||||||
|
const pattern = /\s*\(\w+\)\s*$/;
|
||||||
|
|
||||||
|
// Use the `replace` method to remove the matched pattern
|
||||||
|
const result = input.replace(pattern, "");
|
||||||
|
|
||||||
|
return result.trim(); // Trim any leading/trailing spaces
|
||||||
|
}
|
||||||
|
|
||||||
|
export function extractTypeFromLongId(id: string): string {
|
||||||
|
let [newId, _] = id.split("-");
|
||||||
|
return newId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createRandomKey(key: string, uid: string): string {
|
||||||
|
return removeCountFromString(key) + ` (${uid})`;
|
||||||
|
}
|
||||||
|
|
||||||
export function groupByFamily(
|
export function groupByFamily(
|
||||||
data: APIDataType,
|
data: APIDataType,
|
||||||
|
|
@ -233,398 +327,6 @@ export function groupByFamily(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildInputs(): string {
|
|
||||||
return '{"input_value": "message"}';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getRandomElement<T>(array: T[]): T {
|
|
||||||
return array[Math.floor(Math.random() * array.length)];
|
|
||||||
}
|
|
||||||
export function getRandomDescription(): string {
|
|
||||||
return getRandomElement(DESCRIPTIONS);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getRandomName(
|
|
||||||
retry: number = 0,
|
|
||||||
noSpace: boolean = false,
|
|
||||||
maxRetries: number = 3,
|
|
||||||
): string {
|
|
||||||
const left: string[] = ADJECTIVES;
|
|
||||||
const right: string[] = NOUNS;
|
|
||||||
|
|
||||||
const lv = getRandomElement(left);
|
|
||||||
const rv = getRandomElement(right);
|
|
||||||
|
|
||||||
// Condition to avoid "boring wozniak"
|
|
||||||
if (lv === "boring" && rv === "wozniak") {
|
|
||||||
if (retry < maxRetries) {
|
|
||||||
return getRandomName(retry + 1, noSpace, maxRetries);
|
|
||||||
} else {
|
|
||||||
console.warn("Max retries reached, returning as is");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append a suffix if retrying and noSpace is true
|
|
||||||
if (retry > 0 && noSpace) {
|
|
||||||
const retrySuffix = Math.floor(Math.random() * 10);
|
|
||||||
return `${lv}_${rv}${retrySuffix}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct the final name
|
|
||||||
let final_name = noSpace ? `${lv}_${rv}` : `${lv} ${rv}`;
|
|
||||||
// Return title case final name
|
|
||||||
return toTitleCase(final_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 + Math.abs(Math.floor(Math.random() * 10001));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function varHighlightHTML({ name }: IVarHighlightType): string {
|
|
||||||
const html = `<span class="font-semibold chat-message-highlight">{${name}}</span>`;
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildTweakObject(tweak: tweakType) {
|
|
||||||
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.at(-1), null, 2);
|
|
||||||
return tweakString;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to get Chat Input Field
|
|
||||||
* @param {FlowsState} tabsState - The current tabs state.
|
|
||||||
* @returns {string} - The chat input field
|
|
||||||
*/
|
|
||||||
export function getChatInputField(flowState?: FlowState) {
|
|
||||||
let chat_input_field = "text";
|
|
||||||
|
|
||||||
if (flowState && flowState.input_keys) {
|
|
||||||
chat_input_field = Object.keys(flowState.input_keys!)[0];
|
|
||||||
}
|
|
||||||
return chat_input_field;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to get the python code for the API
|
|
||||||
* @param {string} flowId - The id of the flow
|
|
||||||
* @param {boolean} isAuth - If the API is authenticated
|
|
||||||
* @param {any[]} tweak - The tweaks
|
|
||||||
* @returns {string} - The python code
|
|
||||||
*/
|
|
||||||
export function getPythonApiCode(
|
|
||||||
flowId: string,
|
|
||||||
isAuth: boolean,
|
|
||||||
tweaksBuildedObject,
|
|
||||||
): string {
|
|
||||||
const tweaksObject = tweaksBuildedObject[0];
|
|
||||||
return `import requests
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
BASE_API_URL = "${window.location.protocol}//${window.location.host}/api/v1/run"
|
|
||||||
FLOW_ID = "${flowId}"
|
|
||||||
# You can tweak the flow by adding a tweaks dictionary
|
|
||||||
# e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}}
|
|
||||||
TWEAKS = ${JSON.stringify(tweaksObject, null, 2)}
|
|
||||||
|
|
||||||
def run_flow(message: str,
|
|
||||||
flow_id: str,
|
|
||||||
output_type: str = "chat",
|
|
||||||
input_type: str = "chat",
|
|
||||||
tweaks: Optional[dict] = None,
|
|
||||||
api_key: Optional[str] = None) -> dict:
|
|
||||||
"""
|
|
||||||
Run a flow with a given message and optional tweaks.
|
|
||||||
|
|
||||||
:param message: The message to send to the flow
|
|
||||||
:param flow_id: The ID of the flow to run
|
|
||||||
:param tweaks: Optional tweaks to customize the flow
|
|
||||||
:return: The JSON response from the flow
|
|
||||||
"""
|
|
||||||
api_url = f"{BASE_API_URL}/{flow_id}"
|
|
||||||
|
|
||||||
payload = {
|
|
||||||
"input_value": message,
|
|
||||||
"output_type": output_type,
|
|
||||||
"input_type": input_type,
|
|
||||||
}
|
|
||||||
headers = None
|
|
||||||
if tweaks:
|
|
||||||
payload["tweaks"] = tweaks
|
|
||||||
if api_key:
|
|
||||||
headers = {"x-api-key": api_key}
|
|
||||||
response = requests.post(api_url, json=payload, headers=headers)
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
# Setup any tweaks you want to apply to the flow
|
|
||||||
message = "message"
|
|
||||||
${!isAuth ? `api_key = "<your api key>"` : ""}
|
|
||||||
print(run_flow(message=message, flow_id=FLOW_ID, tweaks=TWEAKS${
|
|
||||||
!isAuth ? `, api_key=api_key` : ""
|
|
||||||
}))`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to get the curl code for the API
|
|
||||||
* @param {string} flowId - The id of the flow
|
|
||||||
* @param {boolean} isAuth - If the API is authenticated
|
|
||||||
* @returns {string} - The curl code
|
|
||||||
*/
|
|
||||||
export function getCurlCode(
|
|
||||||
flowId: string,
|
|
||||||
isAuth: boolean,
|
|
||||||
tweaksBuildedObject,
|
|
||||||
): string {
|
|
||||||
const tweaksObject = tweaksBuildedObject[0];
|
|
||||||
|
|
||||||
return `curl -X POST \\
|
|
||||||
${window.location.protocol}//${
|
|
||||||
window.location.host
|
|
||||||
}/api/v1/run/${flowId}?stream=false \\
|
|
||||||
-H 'Content-Type: application/json'\\${
|
|
||||||
!isAuth ? `\n -H 'x-api-key: <your api key>'\\` : ""
|
|
||||||
}
|
|
||||||
-d '{"input_value": "message",
|
|
||||||
"output_type": "chat",
|
|
||||||
"input_type": "chat",
|
|
||||||
"tweaks": ${JSON.stringify(tweaksObject, null, 2)}}'
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getOutputIds(flow) {
|
|
||||||
const nodes = flow.data!.nodes;
|
|
||||||
|
|
||||||
const arrayOfOutputs = nodes.reduce((acc: string[], node) => {
|
|
||||||
if (node.data.type.toLowerCase().includes("output")) {
|
|
||||||
acc.push(node.id);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const arrayOfOutputsJoin = arrayOfOutputs
|
|
||||||
.map((output) => `"${output}"`)
|
|
||||||
.join(", ");
|
|
||||||
|
|
||||||
return arrayOfOutputsJoin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to get the python code for the API
|
|
||||||
* @param {string} flow - The current flow
|
|
||||||
* @param {any[]} tweak - The tweaks
|
|
||||||
* @returns {string} - The python code
|
|
||||||
*/
|
|
||||||
export function getPythonCode(flowName: string, tweaksBuildedObject): string {
|
|
||||||
const tweaksObject = tweaksBuildedObject[0];
|
|
||||||
|
|
||||||
return `from langflow.load import run_flow_from_json
|
|
||||||
TWEAKS = ${JSON.stringify(tweaksObject, null, 2)}
|
|
||||||
|
|
||||||
result = run_flow_from_json(flow="${flowName}.json",
|
|
||||||
input_value="message",
|
|
||||||
fallback_to_env_vars=True, # False by default
|
|
||||||
tweaks=TWEAKS)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to get the widget code for the API
|
|
||||||
* @param {string} flow - The current flow.
|
|
||||||
* @returns {string} - The widget code
|
|
||||||
*/
|
|
||||||
export function getWidgetCode(
|
|
||||||
flowId: string,
|
|
||||||
flowName: string,
|
|
||||||
isAuth: boolean,
|
|
||||||
): string {
|
|
||||||
return `<script src="https://cdn.jsdelivr.net/gh/langflow-ai/langflow-embedded-chat@1.0_alpha/dist/build/static/js/bundle.min.js"></script>
|
|
||||||
|
|
||||||
<langflow-chat
|
|
||||||
window_title="${flowName}"
|
|
||||||
flow_id="${flowId}"
|
|
||||||
host_url="http://localhost:7860"${
|
|
||||||
!isAuth
|
|
||||||
? `
|
|
||||||
api_key="..."`
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
></langflow-chat>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function truncateLongId(id: string): string {
|
|
||||||
let [componentName, newId] = id.split("-");
|
|
||||||
if (componentName.length > 15) {
|
|
||||||
componentName = componentName.slice(0, 15);
|
|
||||||
componentName += "...";
|
|
||||||
return componentName + "-" + newId;
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function extractIdFromLongId(id: string): string {
|
|
||||||
let [_, newId] = id.split("-");
|
|
||||||
return newId;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function truncateDisplayName(name: string): string {
|
|
||||||
if (name.length > 15) {
|
|
||||||
name = name.slice(0, 15);
|
|
||||||
name += "...";
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function tabsArray(codes: string[], method: number) {
|
|
||||||
if (!method) return;
|
|
||||||
if (method === 0) {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
name: "cURL",
|
|
||||||
mode: "bash",
|
|
||||||
image: "https://curl.se/logo/curl-symbol-transparent.png",
|
|
||||||
language: "sh",
|
|
||||||
code: codes[0],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Python API",
|
|
||||||
mode: "python",
|
|
||||||
image:
|
|
||||||
"https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w",
|
|
||||||
language: "py",
|
|
||||||
code: codes[1],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Python Code",
|
|
||||||
mode: "python",
|
|
||||||
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
|
||||||
language: "py",
|
|
||||||
code: codes[2],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Chat Widget HTML",
|
|
||||||
description:
|
|
||||||
"Insert this code anywhere in your <body> tag. To use with react and other libs, check our <a class='link-color' href='https://langflow.org/guidelines/widget'>documentation</a>.",
|
|
||||||
mode: "html",
|
|
||||||
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
|
||||||
language: "py",
|
|
||||||
code: codes[3],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
name: "cURL",
|
|
||||||
mode: "bash",
|
|
||||||
image: "https://curl.se/logo/curl-symbol-transparent.png",
|
|
||||||
language: "sh",
|
|
||||||
code: codes[0],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Python API",
|
|
||||||
mode: "python",
|
|
||||||
image:
|
|
||||||
"https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w",
|
|
||||||
language: "py",
|
|
||||||
code: codes[1],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Python Code",
|
|
||||||
mode: "python",
|
|
||||||
language: "py",
|
|
||||||
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
|
||||||
code: codes[2],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Chat Widget HTML",
|
|
||||||
description:
|
|
||||||
"Insert this code anywhere in your <body> tag. To use with react and other libs, check our <a class='link-color' href='https://langflow.org/guidelines/widget'>documentation</a>.",
|
|
||||||
mode: "html",
|
|
||||||
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
|
||||||
language: "py",
|
|
||||||
code: codes[3],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Tweaks",
|
|
||||||
mode: "python",
|
|
||||||
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
|
||||||
language: "py",
|
|
||||||
code: codes[4],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function checkLocalStorageKey(key: string): boolean {
|
|
||||||
return localStorage.getItem(key) !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function IncrementObjectKey(
|
|
||||||
object: object,
|
|
||||||
key: string,
|
|
||||||
): { newKey: string; increment: number } {
|
|
||||||
let count = 1;
|
|
||||||
const type = removeCountFromString(key);
|
|
||||||
let newKey = type + " " + `(${count})`;
|
|
||||||
while (object[newKey]) {
|
|
||||||
count++;
|
|
||||||
newKey = type + " " + `(${count})`;
|
|
||||||
}
|
|
||||||
return { newKey, increment: count };
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeCountFromString(input: string): string {
|
|
||||||
// Define a regex pattern to match the count in parentheses
|
|
||||||
const pattern = /\s*\(\w+\)\s*$/;
|
|
||||||
|
|
||||||
// Use the `replace` method to remove the matched pattern
|
|
||||||
const result = input.replace(pattern, "");
|
|
||||||
|
|
||||||
return result.trim(); // Trim any leading/trailing spaces
|
|
||||||
}
|
|
||||||
|
|
||||||
export function extractTypeFromLongId(id: string): string {
|
|
||||||
let [newId, _] = id.split("-");
|
|
||||||
return newId;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createRandomKey(key: string, uid: string): string {
|
|
||||||
return removeCountFromString(key) + ` (${uid})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function sensitiveSort(a: string, b: string): number {
|
|
||||||
// Extract the name and number from each string using regular expressions
|
|
||||||
const regex = /(.+) \((\w+)\)/;
|
|
||||||
const matchA = a.match(regex);
|
|
||||||
const matchB = b.match(regex);
|
|
||||||
|
|
||||||
if (matchA && matchB) {
|
|
||||||
// Compare the names alphabetically
|
|
||||||
const nameA = matchA[1];
|
|
||||||
const nameB = matchB[1];
|
|
||||||
if (nameA !== nameB) {
|
|
||||||
return nameA.localeCompare(nameB);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the names are the same, compare the numbers numerically
|
|
||||||
const numberA = parseInt(matchA[2]);
|
|
||||||
const numberB = parseInt(matchB[2]);
|
|
||||||
return numberA - numberB;
|
|
||||||
} else {
|
|
||||||
// Handle cases where one or both strings do not match the expected pattern
|
|
||||||
// Simple strings are treated as pure alphabetical comparisons
|
|
||||||
return a.localeCompare(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// this function is used to get the set of keys from an object
|
// this function is used to get the set of keys from an object
|
||||||
export function getSetFromObject(obj: object, key?: string): Set<string> {
|
export function getSetFromObject(obj: object, key?: string): Set<string> {
|
||||||
const set = new Set<string>();
|
const set = new Set<string>();
|
||||||
|
|
@ -640,67 +342,10 @@ export function getSetFromObject(obj: object, key?: string): Set<string> {
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFieldTitle(
|
|
||||||
template: APITemplateType,
|
|
||||||
templateField: string,
|
|
||||||
): string {
|
|
||||||
return template[templateField].display_name
|
|
||||||
? template[templateField].display_name!
|
|
||||||
: template[templateField].name ?? templateField;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function sortFields(a, b, fieldOrder) {
|
|
||||||
// Early return for empty fields
|
|
||||||
if (!a && !b) return 0;
|
|
||||||
if (!a) return 1;
|
|
||||||
if (!b) return -1;
|
|
||||||
|
|
||||||
// Normalize the case to ensure case-insensitive comparison
|
|
||||||
const normalizedFieldA = a.toLowerCase();
|
|
||||||
const normalizedFieldB = b.toLowerCase();
|
|
||||||
|
|
||||||
const aIsPriority = priorityFields.has(normalizedFieldA);
|
|
||||||
const bIsPriority = priorityFields.has(normalizedFieldB);
|
|
||||||
|
|
||||||
// Sort by priority
|
|
||||||
if (aIsPriority && !bIsPriority) return -1;
|
|
||||||
if (!aIsPriority && bIsPriority) return 1;
|
|
||||||
|
|
||||||
// Check if either field is in the fieldOrder array
|
|
||||||
const indexOfA = fieldOrder.indexOf(normalizedFieldA);
|
|
||||||
const indexOfB = fieldOrder.indexOf(normalizedFieldB);
|
|
||||||
|
|
||||||
// If both fields are in fieldOrder, sort by their order in the array
|
|
||||||
if (indexOfA !== -1 && indexOfB !== -1) {
|
|
||||||
return indexOfA - indexOfB;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If only one of the fields is in fieldOrder, that field comes first
|
|
||||||
if (indexOfA !== -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (indexOfB !== -1) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default case for fields not in priorityFields and not found in fieldOrder
|
|
||||||
// You might want to sort them alphabetically or in another specific manner
|
|
||||||
return a.localeCompare(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function freezeObject(obj: any) {
|
export function freezeObject(obj: any) {
|
||||||
if (!obj) return obj;
|
if (!obj) return obj;
|
||||||
return JSON.parse(JSON.stringify(obj));
|
return JSON.parse(JSON.stringify(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertTestName(name: string): string {
|
|
||||||
return name.replace(/ /g, "-").toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function sortByName(stringList: string[]): string[] {
|
|
||||||
return stringList.sort((a, b) => a.localeCompare(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isTimeStampString(str: string): boolean {
|
export function isTimeStampString(str: string): boolean {
|
||||||
const timestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3}Z)?$/;
|
const timestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3}Z)?$/;
|
||||||
return timestampRegex.test(str);
|
return timestampRegex.test(str);
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ test("add folder by drag and drop", async ({ page }) => {
|
||||||
|
|
||||||
const jsonContent = readFileSync(
|
const jsonContent = readFileSync(
|
||||||
"tests/end-to-end/assets/collection.json",
|
"tests/end-to-end/assets/collection.json",
|
||||||
"utf-8"
|
"utf-8",
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create the DataTransfer and File
|
// Create the DataTransfer and File
|
||||||
|
|
@ -95,7 +95,7 @@ test("add folder by drag and drop", async ({ page }) => {
|
||||||
"drop",
|
"drop",
|
||||||
{
|
{
|
||||||
dataTransfer,
|
dataTransfer,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.getByText("Getting Started").first().isVisible();
|
await page.getByText("Getting Started").first().isVisible();
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ test("NestedComponent", async ({ page }) => {
|
||||||
await page.locator('//*[@id="showpool_threads"]').click();
|
await page.locator('//*[@id="showpool_threads"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showpool_threads"]').isChecked()
|
await page.locator('//*[@id="showpool_threads"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
//showtext_key
|
//showtext_key
|
||||||
|
|
@ -53,140 +53,140 @@ test("NestedComponent", async ({ page }) => {
|
||||||
await page.locator('//*[@id="showindex_name"]').click();
|
await page.locator('//*[@id="showindex_name"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
// shownamespace
|
// shownamespace
|
||||||
await page.locator('//*[@id="shownamespace"]').click();
|
await page.locator('//*[@id="shownamespace"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
// showpinecone_api_key
|
// showpinecone_api_key
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
// showindex_name
|
// showindex_name
|
||||||
await page.locator('//*[@id="showindex_name"]').click();
|
await page.locator('//*[@id="showindex_name"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
// shownamespace
|
// shownamespace
|
||||||
await page.locator('//*[@id="shownamespace"]').click();
|
await page.locator('//*[@id="shownamespace"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
// showpinecone_api_key
|
// showpinecone_api_key
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
// showindex_name
|
// showindex_name
|
||||||
await page.locator('//*[@id="showindex_name"]').click();
|
await page.locator('//*[@id="showindex_name"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
// shownamespace
|
// shownamespace
|
||||||
await page.locator('//*[@id="shownamespace"]').click();
|
await page.locator('//*[@id="shownamespace"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
// showpinecone_api_key
|
// showpinecone_api_key
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
// showindex_name
|
// showindex_name
|
||||||
await page.locator('//*[@id="showindex_name"]').click();
|
await page.locator('//*[@id="showindex_name"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
// shownamespace
|
// shownamespace
|
||||||
await page.locator('//*[@id="shownamespace"]').click();
|
await page.locator('//*[@id="shownamespace"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
// showpinecone_api_key
|
// showpinecone_api_key
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
// showindex_name
|
// showindex_name
|
||||||
await page.locator('//*[@id="showindex_name"]').click();
|
await page.locator('//*[@id="showindex_name"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
// shownamespace
|
// shownamespace
|
||||||
await page.locator('//*[@id="shownamespace"]').click();
|
await page.locator('//*[@id="shownamespace"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
// showpinecone_api_key
|
// showpinecone_api_key
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
// showindex_name
|
// showindex_name
|
||||||
await page.locator('//*[@id="showindex_name"]').click();
|
await page.locator('//*[@id="showindex_name"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
// shownamespace
|
// shownamespace
|
||||||
await page.locator('//*[@id="shownamespace"]').click();
|
await page.locator('//*[@id="shownamespace"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
// showpinecone_api_key
|
// showpinecone_api_key
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
//showpool_threads
|
//showpool_threads
|
||||||
await page.locator('//*[@id="showpool_threads"]').click();
|
await page.locator('//*[@id="showpool_threads"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showpool_threads"]').isChecked()
|
await page.locator('//*[@id="showpool_threads"]').isChecked(),
|
||||||
).toBeFalsy();
|
).toBeFalsy();
|
||||||
|
|
||||||
//showtext_key
|
//showtext_key
|
||||||
await page.locator('//*[@id="showtext_key"]').click();
|
await page.locator('//*[@id="showtext_key"]').click();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.locator('//*[@id="showtext_key"]').isChecked()
|
await page.locator('//*[@id="showtext_key"]').isChecked(),
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
|
|
||||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"failedTests": []
|
"failedTests": []
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue