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 instanceType = ec2.InstanceType.of(
|
||||
ec2.InstanceClass.BURSTABLE4_GRAVITON,
|
||||
ec2.InstanceSize.MEDIUM
|
||||
ec2.InstanceSize.MEDIUM,
|
||||
);
|
||||
|
||||
// RDSのパスワードを自動生成してSecrets Managerに格納
|
||||
|
|
@ -33,11 +33,11 @@ export class Rds extends Construct {
|
|||
engine: rds.DatabaseClusterEngine.auroraMysql({
|
||||
version: rds.AuroraMysqlEngineVersion.of(
|
||||
"8.0.mysql_aurora.3.05.2",
|
||||
"8.0"
|
||||
"8.0",
|
||||
),
|
||||
}),
|
||||
description: "for-langflow",
|
||||
}
|
||||
},
|
||||
);
|
||||
clusterParameterGroup.bindToCluster({});
|
||||
|
||||
|
|
@ -49,11 +49,11 @@ export class Rds extends Construct {
|
|||
engine: rds.DatabaseClusterEngine.auroraMysql({
|
||||
version: rds.AuroraMysqlEngineVersion.of(
|
||||
"8.0.mysql_aurora.3.05.2",
|
||||
"8.0"
|
||||
"8.0",
|
||||
),
|
||||
}),
|
||||
description: "for-langflow",
|
||||
}
|
||||
},
|
||||
);
|
||||
instanceParameterGroup.bindToInstance({});
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ export class Rds extends Construct {
|
|||
engine: rds.DatabaseClusterEngine.auroraMysql({
|
||||
version: rds.AuroraMysqlEngineVersion.of(
|
||||
"8.0.mysql_aurora.3.05.2",
|
||||
"8.0"
|
||||
"8.0",
|
||||
),
|
||||
}),
|
||||
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",
|
||||
"version": "0.1.2",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.7.17",
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@million/lint": "^0.0.73",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-dialog": "^1.0.4",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||
"@radix-ui/react-form": "^0.0.3",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-menubar": "^1.0.3",
|
||||
"@radix-ui/react-popover": "^1.0.6",
|
||||
"@radix-ui/react-progress": "^1.0.3",
|
||||
"@radix-ui/react-select": "^2.0.0",
|
||||
"@radix-ui/react-separator": "^1.0.3",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.0.6",
|
||||
"@tabler/icons-react": "^2.32.0",
|
||||
"@tailwindcss/forms": "^0.5.6",
|
||||
"@tailwindcss/line-clamp": "^0.4.4",
|
||||
"@types/axios": "^0.14.0",
|
||||
"ace-builds": "^1.24.1",
|
||||
"ag-grid-community": "^31.2.1",
|
||||
"ag-grid-react": "^31.2.1",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"axios": "^1.5.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"class-variance-authority": "^0.6.1",
|
||||
"clsx": "^1.2.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"dompurify": "^3.0.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"esbuild": "^0.17.19",
|
||||
"file-saver": "^2.0.5",
|
||||
"framer-motion": "^11.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.331.0",
|
||||
"million": "^3.0.6",
|
||||
"moment": "^2.29.4",
|
||||
"openseadragon": "^4.1.1",
|
||||
"playwright": "^1.42.0",
|
||||
"react": "^18.2.21",
|
||||
"react-ace": "^10.1.0",
|
||||
"react-cookie": "^4.1.1",
|
||||
"react-dom": "^18.2.21",
|
||||
"react-error-boundary": "^4.0.11",
|
||||
"react-hook-form": "^7.51.4",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-laag": "^2.0.5",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-pdf": "^7.7.1",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react18-json-view": "^0.2.3",
|
||||
"reactflow": "^11.9.2",
|
||||
"rehype-mathjax": "^4.0.3",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-math": "^5.1.1",
|
||||
"shadcn-ui": "^0.2.3",
|
||||
"short-unique-id": "^4.4.4",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uuid": "^9.0.0",
|
||||
"vite-plugin-svgr": "^3.2.0",
|
||||
"web-vitals": "^2.1.4",
|
||||
"zod": "^3.23.7",
|
||||
"zustand": "^4.4.7"
|
||||
},
|
||||
"scripts": {
|
||||
"dev:docker": "vite --host 0.0.0.0",
|
||||
"start": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"format": "npx prettier --write \"{docs,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore",
|
||||
"type-check": "tsc --noEmit --pretty --project tsconfig.json && vite"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "npx pretty-quick --staged"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"proxy": "http://127.0.0.1:7860",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.44.0",
|
||||
"@swc/cli": "^0.1.62",
|
||||
"@swc/core": "^1.3.80",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/lodash": "^4.14.197",
|
||||
"@types/node": "^16.18.46",
|
||||
"@types/react": "^18.2.21",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@types/uuid": "^9.0.2",
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"autoprefixer": "^10.4.15",
|
||||
"daisyui": "^4.0.4",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"postcss": "^8.4.29",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-organize-imports": "^3.2.3",
|
||||
"prettier-plugin-tailwindcss": "^0.3.0",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"tailwindcss-dotted-background": "^1.1.0",
|
||||
"typescript": "^5.2.2",
|
||||
"ua-parser-js": "^1.0.37",
|
||||
"vite": "^4.5.2"
|
||||
}
|
||||
"name": "langflow",
|
||||
"version": "0.1.2",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.7.17",
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@million/lint": "^0.0.73",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-dialog": "^1.0.4",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||
"@radix-ui/react-form": "^0.0.3",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-menubar": "^1.0.3",
|
||||
"@radix-ui/react-popover": "^1.0.6",
|
||||
"@radix-ui/react-progress": "^1.0.3",
|
||||
"@radix-ui/react-select": "^2.0.0",
|
||||
"@radix-ui/react-separator": "^1.0.3",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.0.6",
|
||||
"@tabler/icons-react": "^2.32.0",
|
||||
"@tailwindcss/forms": "^0.5.6",
|
||||
"@tailwindcss/line-clamp": "^0.4.4",
|
||||
"@types/axios": "^0.14.0",
|
||||
"ace-builds": "^1.24.1",
|
||||
"ag-grid-community": "^31.2.1",
|
||||
"ag-grid-react": "^31.2.1",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"axios": "^1.5.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"class-variance-authority": "^0.6.1",
|
||||
"clsx": "^1.2.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"dompurify": "^3.0.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"esbuild": "^0.17.19",
|
||||
"file-saver": "^2.0.5",
|
||||
"framer-motion": "^11.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.331.0",
|
||||
"million": "^3.0.6",
|
||||
"moment": "^2.29.4",
|
||||
"openseadragon": "^4.1.1",
|
||||
"playwright": "^1.42.0",
|
||||
"react": "^18.2.21",
|
||||
"react-ace": "^10.1.0",
|
||||
"react-cookie": "^4.1.1",
|
||||
"react-dom": "^18.2.21",
|
||||
"react-error-boundary": "^4.0.11",
|
||||
"react-hook-form": "^7.51.4",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-laag": "^2.0.5",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-pdf": "^7.7.1",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react18-json-view": "^0.2.3",
|
||||
"reactflow": "^11.9.2",
|
||||
"rehype-mathjax": "^4.0.3",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-math": "^5.1.1",
|
||||
"shadcn-ui": "^0.2.3",
|
||||
"short-unique-id": "^4.4.4",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uuid": "^9.0.0",
|
||||
"vite-plugin-svgr": "^3.2.0",
|
||||
"web-vitals": "^2.1.4",
|
||||
"zod": "^3.23.7",
|
||||
"zustand": "^4.4.7"
|
||||
},
|
||||
"scripts": {
|
||||
"dev:docker": "vite --host 0.0.0.0",
|
||||
"start": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"format": "npx prettier --write \"{docs,src}/**/*.{js,jsx,ts,tsx,json,md}\" --ignore-path .prettierignore",
|
||||
"type-check": "tsc --noEmit --pretty --project tsconfig.json && vite"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "npx pretty-quick --staged"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"proxy": "http://127.0.0.1:7860",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.44.0",
|
||||
"@swc/cli": "^0.1.62",
|
||||
"@swc/core": "^1.3.80",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/lodash": "^4.14.197",
|
||||
"@types/node": "^16.18.46",
|
||||
"@types/react": "^18.2.21",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@types/uuid": "^9.0.2",
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"autoprefixer": "^10.4.15",
|
||||
"daisyui": "^4.0.4",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"postcss": "^8.4.29",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-organize-imports": "^3.2.3",
|
||||
"prettier-plugin-tailwindcss": "^0.3.0",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"simple-git-hooks": "^2.11.1",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"tailwindcss-dotted-background": "^1.1.0",
|
||||
"typescript": "^5.2.2",
|
||||
"ua-parser-js": "^1.0.37",
|
||||
"vite": "^4.5.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,15 +20,15 @@ import useAlertStore from "./stores/alertStore";
|
|||
import { useDarkStore } from "./stores/darkStore";
|
||||
import useFlowsManagerStore from "./stores/flowsManagerStore";
|
||||
import { useFolderStore } from "./stores/foldersStore";
|
||||
import { useGlobalVariablesStore } from "./stores/globalVariables";
|
||||
import { useGlobalVariablesStore } from "./stores/globalVariablesStore/globalVariables";
|
||||
import { useStoreStore } from "./stores/storeStore";
|
||||
import { useTypesStore } from "./stores/typesStore";
|
||||
export default function App() {
|
||||
const removeFromTempNotificationList = useAlertStore(
|
||||
(state) => state.removeFromTempNotificationList
|
||||
(state) => state.removeFromTempNotificationList,
|
||||
);
|
||||
const tempNotificationList = useAlertStore(
|
||||
(state) => state.tempNotificationList
|
||||
(state) => state.tempNotificationList,
|
||||
);
|
||||
const [fetchError, setFetchError] = useState(false);
|
||||
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
||||
|
|
@ -46,7 +46,7 @@ export default function App() {
|
|||
const refreshVersion = useDarkStore((state) => state.refreshVersion);
|
||||
const refreshStars = useDarkStore((state) => state.refreshStars);
|
||||
const setGlobalVariables = useGlobalVariablesStore(
|
||||
(state) => state.setGlobalVariables
|
||||
(state) => state.setGlobalVariables,
|
||||
);
|
||||
const checkHasStore = useStoreStore((state) => state.checkHasStore);
|
||||
const navigate = useNavigate();
|
||||
|
|
|
|||
|
|
@ -31,14 +31,14 @@ export default function ImageViewer({ image }) {
|
|||
const fullPageButton = document.getElementById("full-page-button");
|
||||
|
||||
zoomInButton!.addEventListener("click", () =>
|
||||
viewer.viewport.zoomBy(1.2)
|
||||
viewer.viewport.zoomBy(1.2),
|
||||
);
|
||||
zoomOutButton!.addEventListener("click", () =>
|
||||
viewer.viewport.zoomBy(0.8)
|
||||
viewer.viewport.zoomBy(0.8),
|
||||
);
|
||||
homeButton!.addEventListener("click", () => viewer.viewport.goHome());
|
||||
fullPageButton!.addEventListener("click", () =>
|
||||
viewer.setFullScreen(true)
|
||||
viewer.setFullScreen(true),
|
||||
);
|
||||
|
||||
// Optionally, you can set additional viewer options here
|
||||
|
|
@ -47,16 +47,16 @@ export default function ImageViewer({ image }) {
|
|||
return () => {
|
||||
viewer.destroy();
|
||||
zoomInButton!.removeEventListener("click", () =>
|
||||
viewer.viewport.zoomBy(1.2)
|
||||
viewer.viewport.zoomBy(1.2),
|
||||
);
|
||||
zoomOutButton!.removeEventListener("click", () =>
|
||||
viewer.viewport.zoomBy(0.8)
|
||||
viewer.viewport.zoomBy(0.8),
|
||||
);
|
||||
homeButton!.removeEventListener("click", () =>
|
||||
viewer.viewport.goHome()
|
||||
viewer.viewport.goHome(),
|
||||
);
|
||||
fullPageButton!.removeEventListener("click", () =>
|
||||
viewer.setFullScreen(true)
|
||||
viewer.setFullScreen(true),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default function AccordionComponent({
|
|||
sideBar,
|
||||
}: AccordionComponentType): JSX.Element {
|
||||
const [value, setValue] = useState(
|
||||
open.length === 0 ? "" : getOpenAccordion()
|
||||
open.length === 0 ? "" : getOpenAccordion(),
|
||||
);
|
||||
|
||||
function getOpenAccordion(): string {
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ import { useState } from "react";
|
|||
import { registerGlobalVariable } from "../../controllers/API";
|
||||
import BaseModal from "../../modals/baseModal";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { useGlobalVariablesStore } from "../../stores/globalVariables";
|
||||
import { useGlobalVariablesStore } from "../../stores/globalVariablesStore/globalVariables";
|
||||
import { useTypesStore } from "../../stores/typesStore";
|
||||
import { ResponseErrorDetailAPI } from "../../types/api";
|
||||
import { sortByName } from "../../utils/utils";
|
||||
import ForwardedIconComponent from "../genericIconComponent";
|
||||
import InputComponent from "../inputComponent";
|
||||
import { Button } from "../ui/button";
|
||||
import { Input } from "../ui/input";
|
||||
import { Label } from "../ui/label";
|
||||
import { Textarea } from "../ui/textarea";
|
||||
import sortByName from "./utils/sort-by-name";
|
||||
|
||||
//TODO IMPLEMENT FORM LOGIC
|
||||
|
||||
|
|
@ -24,19 +24,19 @@ export default function AddNewVariableButton({ children }): JSX.Element {
|
|||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const componentFields = useTypesStore((state) => state.ComponentFields);
|
||||
const unavaliableFields = new Set(
|
||||
Object.keys(useGlobalVariablesStore((state) => state.unavaliableFields))
|
||||
Object.keys(useGlobalVariablesStore((state) => state.unavaliableFields)),
|
||||
);
|
||||
|
||||
const availableFields = () => {
|
||||
const fields = Array.from(componentFields).filter(
|
||||
(field) => !unavaliableFields.has(field)
|
||||
(field) => !unavaliableFields.has(field),
|
||||
);
|
||||
|
||||
return sortByName(fields);
|
||||
};
|
||||
|
||||
const addGlobalVariable = useGlobalVariablesStore(
|
||||
(state) => state.addGlobalVariable
|
||||
(state) => state.addGlobalVariable,
|
||||
);
|
||||
|
||||
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, {
|
||||
getInputsAndOutputs,
|
||||
} from "../../utils/storeUtils";
|
||||
import { cn, convertTestName } from "../../utils/utils";
|
||||
import { cn } from "../../utils/utils";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import ShadTooltip from "../shadTooltipComponent";
|
||||
import { Button } from "../ui/button";
|
||||
|
|
@ -27,6 +27,7 @@ import {
|
|||
import { Checkbox } from "../ui/checkbox";
|
||||
import { FormControl, FormField } from "../ui/form";
|
||||
import Loading from "../ui/loading";
|
||||
import { convertTestName } from "./utils/convert-test-name";
|
||||
import DragCardComponent from "./components/dragCardComponent";
|
||||
|
||||
export default function CollectionCardComponent({
|
||||
|
|
@ -59,11 +60,11 @@ export default function CollectionCardComponent({
|
|||
const [loading, setLoading] = useState(false);
|
||||
const [loadingLike, setLoadingLike] = useState(false);
|
||||
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 [downloads_count, setDownloads_count] = useState(
|
||||
data?.downloads_count ?? 0
|
||||
data?.downloads_count ?? 0,
|
||||
);
|
||||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
||||
|
|
@ -74,12 +75,12 @@ export default function CollectionCardComponent({
|
|||
const [openPlayground, setOpenPlayground] = useState(false);
|
||||
const [openDelete, setOpenDelete] = useState(false);
|
||||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId
|
||||
(state) => state.setCurrentFlowId,
|
||||
);
|
||||
const [loadingPlayground, setLoadingPlayground] = useState(false);
|
||||
|
||||
const selectedFlowsComponentsCards = useFlowsManagerStore(
|
||||
(state) => state.selectedFlowsComponentsCards
|
||||
(state) => state.selectedFlowsComponentsCards,
|
||||
);
|
||||
|
||||
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]",
|
||||
disabled ? "pointer-events-none opacity-50" : "",
|
||||
onClick ? "cursor-pointer" : "",
|
||||
isSelectedCard ? "border border-selected" : ""
|
||||
isSelectedCard ? "border border-selected" : "",
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
|
|
@ -232,7 +233,7 @@ export default function CollectionCardComponent({
|
|||
"visible flex-shrink-0",
|
||||
data.is_component
|
||||
? "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"}
|
||||
/>
|
||||
|
|
@ -427,7 +428,7 @@ export default function CollectionCardComponent({
|
|||
name="Trash2"
|
||||
className={cn(
|
||||
"h-5 w-5",
|
||||
!authorized ? " text-ring" : ""
|
||||
!authorized ? " text-ring" : "",
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
|
@ -462,7 +463,7 @@ export default function CollectionCardComponent({
|
|||
liked_by_user
|
||||
? "fill-destructive stroke-destructive"
|
||||
: "",
|
||||
!authorized ? " text-ring" : ""
|
||||
!authorized ? " text-ring" : "",
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
|
@ -500,7 +501,7 @@ export default function CollectionCardComponent({
|
|||
}
|
||||
className={cn(
|
||||
loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
|
||||
!authorized ? " text-ring" : ""
|
||||
!authorized ? " text-ring" : "",
|
||||
)}
|
||||
/>
|
||||
</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",
|
||||
isDragging
|
||||
? "mb-36 flex flex-col items-center justify-center gap-4 text-2xl font-light"
|
||||
: ""
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
{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 ",
|
||||
!hasApiKey || !validApiKey || !hasStore
|
||||
? " button-disable text-muted-foreground "
|
||||
: ""
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
|
|
@ -59,14 +59,14 @@ export default function FlowToolbar(): JSX.Element {
|
|||
"-m-0.5 -ml-1 h-6 w-6",
|
||||
!hasApiKey || !validApiKey || !hasStore
|
||||
? "extra-side-bar-save-disable"
|
||||
: ""
|
||||
: "",
|
||||
)}
|
||||
/>
|
||||
Share
|
||||
</button>
|
||||
</ShareModal>
|
||||
),
|
||||
[hasApiKey, validApiKey, currentFlow, hasStore]
|
||||
[hasApiKey, validApiKey, currentFlow, hasStore],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
@ -118,7 +118,7 @@ export default function FlowToolbar(): JSX.Element {
|
|||
<ApiModal flow={currentFlow}>
|
||||
<div
|
||||
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
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ export default function CodeTabsComponent({
|
|||
<div className="api-modal-according-display">
|
||||
<div
|
||||
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) => (
|
||||
|
|
@ -275,8 +275,8 @@ export default function CodeTabsComponent({
|
|||
.show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
node.data.node.template[templateField]
|
||||
.type
|
||||
)
|
||||
.type,
|
||||
),
|
||||
)
|
||||
.map((templateField, indx) => {
|
||||
return (
|
||||
|
|
@ -334,7 +334,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -380,7 +380,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -433,7 +433,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -470,7 +470,7 @@ export default function CodeTabsComponent({
|
|||
e,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
size="small"
|
||||
|
|
@ -501,7 +501,7 @@ export default function CodeTabsComponent({
|
|||
].fileTypes
|
||||
}
|
||||
onFileChange={(
|
||||
value: any
|
||||
value: any,
|
||||
) => {
|
||||
node.data.node.template[
|
||||
templateField
|
||||
|
|
@ -554,7 +554,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -594,7 +594,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
value={
|
||||
|
|
@ -656,7 +656,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -702,7 +702,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -748,7 +748,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -780,8 +780,8 @@ export default function CodeTabsComponent({
|
|||
].value,
|
||||
type(
|
||||
node,
|
||||
templateField
|
||||
)
|
||||
templateField,
|
||||
),
|
||||
)
|
||||
}
|
||||
duplicateKey={
|
||||
|
|
@ -790,15 +790,15 @@ export default function CodeTabsComponent({
|
|||
onChange={(target) => {
|
||||
const valueToNumbers =
|
||||
convertValuesToNumbers(
|
||||
target
|
||||
target,
|
||||
);
|
||||
node.data.node!.template[
|
||||
templateField
|
||||
].value = valueToNumbers;
|
||||
setErrorDuplicateKey(
|
||||
hasDuplicateKeys(
|
||||
valueToNumbers
|
||||
)
|
||||
valueToNumbers,
|
||||
),
|
||||
);
|
||||
setData((old) => {
|
||||
let newInputList =
|
||||
|
|
@ -815,7 +815,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
isList={
|
||||
|
|
@ -865,7 +865,7 @@ export default function CodeTabsComponent({
|
|||
target,
|
||||
node.data.node.template[
|
||||
templateField
|
||||
]
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ function CsvOutputComponent({
|
|||
if (file) {
|
||||
const { rowData: data, colDefs: columns } = convertCSVToData(
|
||||
file,
|
||||
separator
|
||||
separator,
|
||||
);
|
||||
setRowData(data);
|
||||
setColDefs(columns);
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ const CustomInputPopover = ({
|
|||
(selectedOption !== "" || !onChange) && setSelectedOption
|
||||
? selectedOption
|
||||
: (selectedOptions?.length !== 0 || !onChange) &&
|
||||
setSelectedOptions
|
||||
? selectedOptions?.join(", ")
|
||||
: value
|
||||
setSelectedOptions
|
||||
? selectedOptions?.join(", ")
|
||||
: value
|
||||
}
|
||||
autoFocus={autoFocus}
|
||||
disabled={disabled}
|
||||
|
|
@ -96,7 +96,7 @@ const CustomInputPopover = ({
|
|||
(password && !(setSelectedOption || setSelectedOptions))
|
||||
? "pr-8"
|
||||
: "",
|
||||
className!
|
||||
className!,
|
||||
)}
|
||||
placeholder={password && editNode ? "Key" : placeholder}
|
||||
onChange={handleInputChange}
|
||||
|
|
@ -134,15 +134,15 @@ const CustomInputPopover = ({
|
|||
onSelect={(currentValue) => {
|
||||
setSelectedOption &&
|
||||
setSelectedOption(
|
||||
currentValue === selectedOption ? "" : currentValue
|
||||
currentValue === selectedOption ? "" : currentValue,
|
||||
);
|
||||
setSelectedOptions &&
|
||||
setSelectedOptions(
|
||||
selectedOptions?.includes(currentValue)
|
||||
? selectedOptions.filter(
|
||||
(item) => item !== currentValue
|
||||
(item) => item !== currentValue,
|
||||
)
|
||||
: [...selectedOptions, currentValue]
|
||||
: [...selectedOptions, currentValue],
|
||||
);
|
||||
!setSelectedOptions && setShowOptions(false);
|
||||
}}
|
||||
|
|
@ -155,7 +155,7 @@ const CustomInputPopover = ({
|
|||
selectedOption === option ||
|
||||
selectedOptions?.includes(option)
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
: "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 ||
|
||||
""
|
||||
: (selectedOptions?.length !== 0 || !onChange) &&
|
||||
setSelectedOptions
|
||||
? selectedOptions
|
||||
.map(
|
||||
(optionId) =>
|
||||
options.find((option) => option.id === optionId)?.name
|
||||
)
|
||||
.join(", ")
|
||||
: value
|
||||
setSelectedOptions
|
||||
? selectedOptions
|
||||
.map(
|
||||
(optionId) =>
|
||||
options.find((option) => option.id === optionId)?.name,
|
||||
)
|
||||
.join(", ")
|
||||
: value
|
||||
}
|
||||
autoFocus={autoFocus}
|
||||
disabled={disabled}
|
||||
|
|
@ -106,15 +106,15 @@ const CustomInputPopoverObject = ({
|
|||
onSelect={(currentValue) => {
|
||||
setSelectedOption &&
|
||||
setSelectedOption(
|
||||
currentValue === selectedOption ? "" : currentValue
|
||||
currentValue === selectedOption ? "" : currentValue,
|
||||
);
|
||||
setSelectedOptions &&
|
||||
setSelectedOptions(
|
||||
selectedOptions?.includes(currentValue)
|
||||
? selectedOptions.filter(
|
||||
(item) => item !== currentValue
|
||||
(item) => item !== currentValue,
|
||||
)
|
||||
: [...selectedOptions, currentValue]
|
||||
: [...selectedOptions, currentValue],
|
||||
);
|
||||
!setSelectedOptions && setShowOptions(false);
|
||||
}}
|
||||
|
|
@ -127,7 +127,7 @@ const CustomInputPopoverObject = ({
|
|||
selectedOption === option.id ||
|
||||
selectedOptions?.includes(option.id)
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
: "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 " : "",
|
||||
password && editNode ? "pr-8" : "",
|
||||
password && !editNode ? "pr-10" : "",
|
||||
className!
|
||||
className!,
|
||||
)}
|
||||
placeholder={password && editNode ? "Key" : placeholder}
|
||||
onChange={(e) => {
|
||||
|
|
@ -147,7 +147,7 @@ export default function InputComponent({
|
|||
<span
|
||||
className={cn(
|
||||
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
|
||||
|
|
@ -160,7 +160,7 @@ export default function InputComponent({
|
|||
selectedOption !== ""
|
||||
? "text-medium-indigo"
|
||||
: "text-muted-foreground",
|
||||
"hover:text-accent-foreground"
|
||||
"hover:text-accent-foreground",
|
||||
)}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
|
|
@ -180,7 +180,7 @@ export default function InputComponent({
|
|||
"mb-px",
|
||||
editNode
|
||||
? "input-component-true-button"
|
||||
: "input-component-false-button"
|
||||
: "input-component-false-button",
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
|
|
@ -197,7 +197,7 @@ export default function InputComponent({
|
|||
className={classNames(
|
||||
editNode
|
||||
? "input-component-true-svg"
|
||||
: "input-component-false-svg"
|
||||
: "input-component-false-svg",
|
||||
)}
|
||||
>
|
||||
<path
|
||||
|
|
@ -216,7 +216,7 @@ export default function InputComponent({
|
|||
className={classNames(
|
||||
editNode
|
||||
? "input-component-true-svg"
|
||||
: "input-component-false-svg"
|
||||
: "input-component-false-svg",
|
||||
)}
|
||||
>
|
||||
<path
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useEffect } from "react";
|
|||
import { deleteGlobalVariable } from "../../controllers/API";
|
||||
import DeleteConfirmationModal from "../../modals/deleteConfirmationModal";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { useGlobalVariablesStore } from "../../stores/globalVariables";
|
||||
import { useGlobalVariablesStore } from "../../stores/globalVariablesStore/globalVariables";
|
||||
import { InputGlobalComponentType } from "../../types/components";
|
||||
import { cn } from "../../utils/utils";
|
||||
import AddNewVariableButton from "../addNewVariableButtonComponent/addNewVariableButton";
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
e:
|
||||
| React.DragEvent<HTMLDivElement>
|
||||
| React.DragEvent<HTMLButtonElement>
|
||||
| React.DragEvent<HTMLAnchorElement>
|
||||
| React.DragEvent<HTMLAnchorElement>,
|
||||
) => {
|
||||
e.preventDefault();
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
e:
|
||||
| React.DragEvent<HTMLDivElement>
|
||||
| React.DragEvent<HTMLButtonElement>
|
||||
| React.DragEvent<HTMLAnchorElement>
|
||||
| React.DragEvent<HTMLAnchorElement>,
|
||||
) => {
|
||||
if (e.dataTransfer.types.some((types) => types === "Files")) {
|
||||
setFolderDragging(true);
|
||||
|
|
@ -66,7 +66,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
e:
|
||||
| React.DragEvent<HTMLDivElement>
|
||||
| React.DragEvent<HTMLButtonElement>
|
||||
| React.DragEvent<HTMLAnchorElement>
|
||||
| React.DragEvent<HTMLAnchorElement>,
|
||||
) => {
|
||||
e.preventDefault();
|
||||
if (e.target === e.currentTarget) {
|
||||
|
|
@ -79,7 +79,7 @@ const useFileDrop = (folderId, folderChangeCallback) => {
|
|||
| React.DragEvent<HTMLDivElement>
|
||||
| React.DragEvent<HTMLButtonElement>
|
||||
| React.DragEvent<HTMLAnchorElement>,
|
||||
folderId: string
|
||||
folderId: string,
|
||||
) => {
|
||||
if (e?.dataTransfer?.getData("flow")) {
|
||||
const data = JSON.parse(e?.dataTransfer?.getData("flow"));
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const TableComponent = forwardRef<
|
|||
alertDescription = DEFAULT_TABLE_ALERT_MSG,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
ref,
|
||||
) => {
|
||||
const dark = useDarkStore((state) => state.dark);
|
||||
var currentRowHeight: number;
|
||||
|
|
@ -67,14 +67,14 @@ const TableComponent = forwardRef<
|
|||
(params: any) => {
|
||||
updateRowHeight(params);
|
||||
},
|
||||
[updateRowHeight]
|
||||
[updateRowHeight],
|
||||
);
|
||||
|
||||
const onGridSizeChanged = useCallback(
|
||||
(params: any) => {
|
||||
updateRowHeight(params);
|
||||
},
|
||||
[updateRowHeight]
|
||||
[updateRowHeight],
|
||||
);
|
||||
|
||||
if (props.rowData.length === 0) {
|
||||
|
|
@ -96,7 +96,7 @@ const TableComponent = forwardRef<
|
|||
<div
|
||||
className={cn(
|
||||
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
|
||||
>
|
||||
<AgGridReact
|
||||
|
|
@ -113,7 +113,7 @@ const TableComponent = forwardRef<
|
|||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export default TableComponent;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export async function sendAll(data: sendAllProps) {
|
|||
}
|
||||
|
||||
export async function postValidateCode(
|
||||
code: string
|
||||
code: string,
|
||||
): Promise<AxiosResponse<errorsTypeAPI>> {
|
||||
return await api.post(`${BASE_URL_API}validate/code`, { code });
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ export async function postValidateCode(
|
|||
export async function postValidatePrompt(
|
||||
name: string,
|
||||
template: string,
|
||||
frontend_node: APIClassType
|
||||
frontend_node: APIClassType,
|
||||
): Promise<AxiosResponse<PromptTypeAPI>> {
|
||||
return api.post(`${BASE_URL_API}validate/prompt`, {
|
||||
name,
|
||||
|
|
@ -149,7 +149,7 @@ export async function saveFlowToDatabase(newFlow: {
|
|||
* @throws Will throw an error if the update fails.
|
||||
*/
|
||||
export async function updateFlowInDatabase(
|
||||
updatedFlow: FlowType
|
||||
updatedFlow: FlowType,
|
||||
): Promise<FlowType> {
|
||||
try {
|
||||
const response = await api.patch(`${BASE_URL_API}flows/${updatedFlow.id}`, {
|
||||
|
|
@ -326,7 +326,7 @@ export async function getHealth() {
|
|||
*
|
||||
*/
|
||||
export async function getBuildStatus(
|
||||
flowId: string
|
||||
flowId: string,
|
||||
): Promise<AxiosResponse<BuildStatusTypeAPI>> {
|
||||
return await api.get(`${BASE_URL_API}build/${flowId}/status`);
|
||||
}
|
||||
|
|
@ -339,7 +339,7 @@ export async function getBuildStatus(
|
|||
*
|
||||
*/
|
||||
export async function postBuildInit(
|
||||
flow: FlowType
|
||||
flow: FlowType,
|
||||
): Promise<AxiosResponse<InitTypeAPI>> {
|
||||
return await api.post(`${BASE_URL_API}build/init/${flow.id}`, flow);
|
||||
}
|
||||
|
|
@ -355,7 +355,7 @@ export async function postBuildInit(
|
|||
*/
|
||||
export async function uploadFile(
|
||||
file: File,
|
||||
id: string
|
||||
id: string,
|
||||
): Promise<AxiosResponse<UploadFileTypeAPI>> {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
|
@ -364,7 +364,7 @@ export async function uploadFile(
|
|||
|
||||
export async function postCustomComponent(
|
||||
code: string,
|
||||
apiClass: APIClassType
|
||||
apiClass: APIClassType,
|
||||
): Promise<AxiosResponse<APIClassType>> {
|
||||
// let template = apiClass.template;
|
||||
return await api.post(`${BASE_URL_API}custom_component`, {
|
||||
|
|
@ -377,7 +377,7 @@ export async function postCustomComponentUpdate(
|
|||
code: string,
|
||||
template: APITemplateType,
|
||||
field: string,
|
||||
field_value: any
|
||||
field_value: any,
|
||||
): Promise<AxiosResponse<APIClassType>> {
|
||||
return await api.post(`${BASE_URL_API}custom_component/update`, {
|
||||
code,
|
||||
|
|
@ -399,7 +399,7 @@ export async function onLogin(user: LoginType) {
|
|||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
|
|
@ -461,11 +461,11 @@ export async function addUser(user: UserInputType): Promise<Array<Users>> {
|
|||
|
||||
export async function getUsersPage(
|
||||
skip: number,
|
||||
limit: number
|
||||
limit: number,
|
||||
): Promise<Array<Users>> {
|
||||
try {
|
||||
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) {
|
||||
return res.data;
|
||||
|
|
@ -502,7 +502,7 @@ export async function resetPassword(user_id: string, user: resetPasswordType) {
|
|||
try {
|
||||
const res = await api.patch(
|
||||
`${BASE_URL_API}users/${user_id}/reset-password`,
|
||||
user
|
||||
user,
|
||||
);
|
||||
if (res.status === 200) {
|
||||
return res.data;
|
||||
|
|
@ -576,7 +576,7 @@ export async function saveFlowStore(
|
|||
last_tested_version?: string;
|
||||
},
|
||||
tags: string[],
|
||||
publicFlow = false
|
||||
publicFlow = false,
|
||||
): Promise<FlowType> {
|
||||
try {
|
||||
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) {
|
||||
try {
|
||||
const res = await api.get(
|
||||
`${BASE_URL_API}store/components/${component_id}`
|
||||
`${BASE_URL_API}store/components/${component_id}`,
|
||||
);
|
||||
if (res.status === 200) {
|
||||
return res.data;
|
||||
|
|
@ -720,7 +720,7 @@ export async function searchComponent(
|
|||
page?: number | null,
|
||||
limit?: number | null,
|
||||
status?: string | null,
|
||||
tags?: string[]
|
||||
tags?: string[],
|
||||
): Promise<StoreComponentResponse | undefined> {
|
||||
try {
|
||||
let url = `${BASE_URL_API}store/components/`;
|
||||
|
|
@ -832,7 +832,7 @@ export async function updateFlowStore(
|
|||
},
|
||||
tags: string[],
|
||||
publicFlow = false,
|
||||
id: string
|
||||
id: string,
|
||||
): Promise<FlowType> {
|
||||
try {
|
||||
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(
|
||||
name: string,
|
||||
value: string,
|
||||
id: string
|
||||
id: string,
|
||||
) {
|
||||
try {
|
||||
const response = api.patch(`${BASE_URL_API}variables/${id}`, {
|
||||
|
|
@ -935,7 +935,7 @@ export async function getVerticesOrder(
|
|||
startNodeId?: string | null,
|
||||
stopNodeId?: string | null,
|
||||
nodes?: Node[],
|
||||
Edges?: Edge[]
|
||||
Edges?: Edge[],
|
||||
): Promise<AxiosResponse<VerticesOrderTypeAPI>> {
|
||||
// nodeId is optional and is a query parameter
|
||||
// if nodeId is not provided, the API will return all vertices
|
||||
|
|
@ -955,19 +955,19 @@ export async function getVerticesOrder(
|
|||
return await api.post(
|
||||
`${BASE_URL_API}build/${flowId}/vertices`,
|
||||
data,
|
||||
config
|
||||
config,
|
||||
);
|
||||
}
|
||||
|
||||
export async function postBuildVertex(
|
||||
flowId: string,
|
||||
vertexId: string,
|
||||
input_value: string
|
||||
input_value: string,
|
||||
): Promise<AxiosResponse<VertexBuildTypeAPI>> {
|
||||
// input_value is optional and is a query parameter
|
||||
return await api.post(
|
||||
`${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(
|
||||
flowId: string
|
||||
flowId: string,
|
||||
): Promise<AxiosResponse<any>> {
|
||||
const config = {};
|
||||
config["params"] = { flow_id: flowId };
|
||||
|
|
@ -999,7 +999,7 @@ export async function deleteFlowPool(
|
|||
}
|
||||
|
||||
export async function multipleDeleteFlowsComponents(
|
||||
flowIds: string[]
|
||||
flowIds: string[],
|
||||
): Promise<AxiosResponse<any>> {
|
||||
return await api.post(`${BASE_URL_API}flows/multiple_delete/`, {
|
||||
flow_ids: flowIds,
|
||||
|
|
@ -1009,7 +1009,7 @@ export async function multipleDeleteFlowsComponents(
|
|||
export async function getTransactionTable(
|
||||
id: string,
|
||||
mode: "intersection" | "union",
|
||||
params = {}
|
||||
params = {},
|
||||
): Promise<{ rows: Array<object>; columns: Array<ColDef | ColGroupDef> }> {
|
||||
const config = {};
|
||||
config["params"] = { flow_id: id };
|
||||
|
|
@ -1024,7 +1024,7 @@ export async function getTransactionTable(
|
|||
export async function getMessagesTable(
|
||||
id: string,
|
||||
mode: "intersection" | "union",
|
||||
params = {}
|
||||
params = {},
|
||||
): Promise<{ rows: Array<object>; columns: Array<ColDef | ColGroupDef> }> {
|
||||
const config = {};
|
||||
config["params"] = { flow_id: id };
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ export default function ParameterComponent({
|
|||
setNode,
|
||||
renderTooltips,
|
||||
isLoading,
|
||||
setIsLoading
|
||||
setIsLoading,
|
||||
);
|
||||
|
||||
const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
|
||||
|
|
@ -98,7 +98,7 @@ export default function ParameterComponent({
|
|||
takeSnapshot,
|
||||
setNode,
|
||||
updateNodeInternals,
|
||||
renderTooltips
|
||||
renderTooltips,
|
||||
);
|
||||
|
||||
const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
|
||||
|
|
@ -107,7 +107,7 @@ export default function ParameterComponent({
|
|||
let disabled =
|
||||
edges.some(
|
||||
(edge) =>
|
||||
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id)
|
||||
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
|
||||
) ?? false;
|
||||
|
||||
const handleRefreshButtonPress = async (name, data) => {
|
||||
|
|
@ -120,12 +120,12 @@ export default function ParameterComponent({
|
|||
handleUpdateValues,
|
||||
setNode,
|
||||
renderTooltips,
|
||||
setIsLoading
|
||||
setIsLoading,
|
||||
);
|
||||
|
||||
const handleOnNewValue = async (
|
||||
newValue: string | string[] | boolean | Object[],
|
||||
skipSnapshot: boolean | undefined = false
|
||||
skipSnapshot: boolean | undefined = false,
|
||||
): Promise<void> => {
|
||||
handleOnNewValueHook(newValue, skipSnapshot);
|
||||
};
|
||||
|
|
@ -209,7 +209,7 @@ export default function ParameterComponent({
|
|||
className={classNames(
|
||||
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
|
||||
"h-3 w-3 rounded-full border-2 bg-background",
|
||||
!showNode ? "mt-0" : ""
|
||||
!showNode ? "mt-0" : "",
|
||||
)}
|
||||
style={{
|
||||
borderColor: color ?? nodeColors.unknown,
|
||||
|
|
@ -298,7 +298,7 @@ export default function ParameterComponent({
|
|||
}
|
||||
className={classNames(
|
||||
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 }}
|
||||
onClick={() => setFilterEdge(groupedEdge.current)}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ import { validationStatusType } from "../../types/components";
|
|||
import { NodeDataType } from "../../types/flow";
|
||||
import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils";
|
||||
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 getFieldTitle from "../utils/get-field-title";
|
||||
import sortFields from "../utils/sort-fields";
|
||||
|
||||
export default function GenericNode({
|
||||
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 {
|
||||
const allNodes = useFlowStore((state) => state.nodes);
|
||||
const inputs = useFlowStore((state) => state.inputs).filter(
|
||||
(input) => input.type !== "ChatInput"
|
||||
(input) => input.type !== "ChatInput",
|
||||
);
|
||||
const chatInput = useFlowStore((state) => state.inputs).find(
|
||||
(input) => input.type === "ChatInput"
|
||||
(input) => input.type === "ChatInput",
|
||||
);
|
||||
const outputs = useFlowStore((state) => state.outputs).filter(
|
||||
(output) => output.type !== "ChatOutput"
|
||||
(output) => output.type !== "ChatOutput",
|
||||
);
|
||||
const chatOutput = useFlowStore((state) => state.outputs).find(
|
||||
(output) => output.type === "ChatOutput"
|
||||
(output) => output.type === "ChatOutput",
|
||||
);
|
||||
const nodes = useFlowStore((state) => state.nodes).filter(
|
||||
(node) =>
|
||||
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 [selectedTab, setSelectedTab] = useState(
|
||||
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0
|
||||
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0,
|
||||
);
|
||||
|
||||
function startView() {
|
||||
|
|
@ -140,7 +140,7 @@ export default function IOModal({
|
|||
{selectedTab !== 0 && (
|
||||
<div
|
||||
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
|
||||
|
|
@ -173,11 +173,11 @@ export default function IOModal({
|
|||
</div>
|
||||
{nodes
|
||||
.filter((node) =>
|
||||
inputs.some((input) => input.id === node.id)
|
||||
inputs.some((input) => input.id === node.id),
|
||||
)
|
||||
.map((node, index) => {
|
||||
const input = inputs.find(
|
||||
(input) => input.id === node.id
|
||||
(input) => input.id === node.id,
|
||||
)!;
|
||||
return (
|
||||
<div
|
||||
|
|
@ -241,11 +241,11 @@ export default function IOModal({
|
|||
</div>
|
||||
{nodes
|
||||
.filter((node) =>
|
||||
outputs.some((output) => output.id === node.id)
|
||||
outputs.some((output) => output.id === node.id),
|
||||
)
|
||||
.map((node, index) => {
|
||||
const output = outputs.find(
|
||||
(output) => output.id === node.id
|
||||
(output) => output.id === node.id,
|
||||
)!;
|
||||
return (
|
||||
<div
|
||||
|
|
@ -308,7 +308,7 @@ export default function IOModal({
|
|||
<div
|
||||
className={cn(
|
||||
"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">
|
||||
|
|
@ -327,7 +327,7 @@ export default function IOModal({
|
|||
</div>
|
||||
<div className="h-full w-full">
|
||||
{inputs.some(
|
||||
(input) => input.id === selectedViewField.id
|
||||
(input) => input.id === selectedViewField.id,
|
||||
) ? (
|
||||
<IOFieldView
|
||||
type={InputOutput.INPUT}
|
||||
|
|
@ -349,7 +349,7 @@ export default function IOModal({
|
|||
<div
|
||||
className={cn(
|
||||
"flex h-full w-full",
|
||||
selectedViewField ? "hidden" : ""
|
||||
selectedViewField ? "hidden" : "",
|
||||
)}
|
||||
>
|
||||
{haveChat ? (
|
||||
|
|
@ -384,7 +384,7 @@ export default function IOModal({
|
|||
"h-4 w-4",
|
||||
isBuilding
|
||||
? "animate-spin"
|
||||
: "fill-current text-medium-indigo"
|
||||
: "fill-current text-medium-indigo",
|
||||
)}
|
||||
/>
|
||||
Run Flow
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export const checkCanBuildTweakObject = (element, templateField) => {
|
|||
templateField.charAt(0) !== "_" &&
|
||||
element.data.node.template[templateField].show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
element.data.node.template[templateField].type
|
||||
element.data.node.template[templateField].type,
|
||||
) &&
|
||||
templateField !== "code"
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { convertArrayToObj } from "../../../utils/reactflowUtils";
|
|||
|
||||
export const getChangesType = (
|
||||
changes: string | string[] | boolean | number | Object[] | Object,
|
||||
template: TemplateVariableType
|
||||
template: TemplateVariableType,
|
||||
) => {
|
||||
if (typeof changes === "string" && template.type === "float") {
|
||||
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) !== "_" &&
|
||||
node.data.node.template[templateField].show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
node.data.node.template[templateField].type
|
||||
)
|
||||
node.data.node.template[templateField].type,
|
||||
),
|
||||
)
|
||||
.map((n, i) => {
|
||||
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,
|
||||
node: NodeType,
|
||||
template: TemplateVariableType,
|
||||
tweak: Object[]
|
||||
tweak: Object[],
|
||||
) => {
|
||||
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 { uniqueTweakType } from "../../../types/components";
|
||||
import { FlowType } from "../../../types/flow/index";
|
||||
import {
|
||||
getCurlCode,
|
||||
getPythonApiCode,
|
||||
getPythonCode,
|
||||
getWidgetCode,
|
||||
tabsArray,
|
||||
} from "../../../utils/utils";
|
||||
import BaseModal from "../../baseModal";
|
||||
import { buildContent } from "../utils/build-content";
|
||||
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 { getNodesWithDefaultValue } from "../utils/get-nodes-with-default-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(
|
||||
(
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ interface BaseModalProps {
|
|||
React.ReactElement<ContentProps>,
|
||||
React.ReactElement<HeaderProps>,
|
||||
React.ReactElement<TriggerProps>?,
|
||||
React.ReactElement<FooterProps>?
|
||||
React.ReactElement<FooterProps>?,
|
||||
];
|
||||
open?: boolean;
|
||||
setOpen?: (open: boolean) => void;
|
||||
|
|
@ -101,16 +101,16 @@ function BaseModal({
|
|||
type = "dialog",
|
||||
}: BaseModalProps) {
|
||||
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(
|
||||
(child) => (child as React.ReactElement).type === Trigger
|
||||
(child) => (child as React.ReactElement).type === Trigger,
|
||||
);
|
||||
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(
|
||||
(child) => (child as React.ReactElement).type === Footer
|
||||
(child) => (child as React.ReactElement).type === Footer,
|
||||
);
|
||||
|
||||
let minWidth: string;
|
||||
|
|
|
|||
|
|
@ -24,8 +24,9 @@ import { postValidatePrompt } from "../../controllers/API";
|
|||
import useAlertStore from "../../stores/alertStore";
|
||||
import { genericModalPropsType } from "../../types/components";
|
||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||
import { classNames, varHighlightHTML } from "../../utils/utils";
|
||||
import { classNames } from "../../utils/utils";
|
||||
import BaseModal from "../baseModal";
|
||||
import varHighlightHTML from "./utils/var-highlight-html";
|
||||
|
||||
export default function GenericModal({
|
||||
field_name = "",
|
||||
|
|
@ -82,7 +83,7 @@ export default function GenericModal({
|
|||
}
|
||||
|
||||
const filteredWordsHighlight = matches.filter(
|
||||
(word) => !invalid_chars.includes(word)
|
||||
(word) => !invalid_chars.includes(word),
|
||||
);
|
||||
|
||||
setWordsHighlight(filteredWordsHighlight);
|
||||
|
|
@ -133,7 +134,7 @@ export default function GenericModal({
|
|||
// to the first key of the custom_fields object
|
||||
if (field_name === "") {
|
||||
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?.[""] ?? "";
|
||||
|
|
@ -209,7 +210,7 @@ export default function GenericModal({
|
|||
<div
|
||||
className={classNames(
|
||||
!isEdit ? "rounded-lg border" : "",
|
||||
"flex h-full w-full"
|
||||
"flex h-full w-full",
|
||||
)}
|
||||
>
|
||||
{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}
|
||||
flow={
|
||||
examples.find(
|
||||
(e) => e.name == "Basic Prompting (Hello, World)"
|
||||
(e) => e.name == "Basic Prompting (Hello, World)",
|
||||
)!
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ import {
|
|||
removeFileNameFromComponents,
|
||||
removeGlobalVariableFromComponents,
|
||||
} from "../../utils/reactflowUtils";
|
||||
import { getTagsIds } from "../../utils/storeUtils";
|
||||
import BaseModal from "../baseModal";
|
||||
import ConfirmationModal from "../confirmationModal";
|
||||
import ExportModal from "../exportModal";
|
||||
import getTagsIds from "./utils/get-tags-ids";
|
||||
|
||||
export default function ShareModal({
|
||||
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,
|
||||
validateSelection,
|
||||
} from "../../../../utils/reactflowUtils";
|
||||
import { getRandomName, isWrappedWithClass } from "../../../../utils/utils";
|
||||
import ConnectionLineComponent from "../ConnectionLineComponent";
|
||||
import SelectionMenu from "../SelectionMenuComponent";
|
||||
import isWrappedWithClass from "./utils/is-wrapped-with-class";
|
||||
import getRandomName from "./utils/get-random-name";
|
||||
|
||||
const nodeTypes = {
|
||||
genericNode: GenericNode,
|
||||
|
|
@ -51,19 +52,19 @@ export default function Page({
|
|||
}): JSX.Element {
|
||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||
const autoSaveCurrentFlow = useFlowsManagerStore(
|
||||
(state) => state.autoSaveCurrentFlow
|
||||
(state) => state.autoSaveCurrentFlow,
|
||||
);
|
||||
const types = useTypesStore((state) => state.types);
|
||||
const templates = useTypesStore((state) => state.templates);
|
||||
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
||||
const reactFlowWrapper = useRef<HTMLDivElement>(null);
|
||||
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 setReactFlowInstance = useFlowStore(
|
||||
(state) => state.setReactFlowInstance
|
||||
(state) => state.setReactFlowInstance,
|
||||
);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const edges = useFlowStore((state) => state.edges);
|
||||
|
|
@ -80,10 +81,10 @@ export default function Page({
|
|||
const paste = useFlowStore((state) => state.paste);
|
||||
const resetFlow = useFlowStore((state) => state.resetFlow);
|
||||
const lastCopiedSelection = useFlowStore(
|
||||
(state) => state.lastCopiedSelection
|
||||
(state) => state.lastCopiedSelection,
|
||||
);
|
||||
const setLastCopiedSelection = useFlowStore(
|
||||
(state) => state.setLastCopiedSelection
|
||||
(state) => state.setLastCopiedSelection,
|
||||
);
|
||||
const onConnect = useFlowStore((state) => state.onConnect);
|
||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
|
|
@ -106,7 +107,7 @@ export default function Page({
|
|||
clonedSelection!,
|
||||
clonedNodes,
|
||||
clonedEdges,
|
||||
getRandomName()
|
||||
getRandomName(),
|
||||
);
|
||||
const newGroupNode = generateNodeFromFlow(newFlow, getNodeId);
|
||||
const newEdges = reconnectEdges(newGroupNode, removedEdges);
|
||||
|
|
@ -114,8 +115,8 @@ export default function Page({
|
|||
...clonedNodes.filter(
|
||||
(oldNodes) =>
|
||||
!clonedSelection?.nodes.some(
|
||||
(selectionNode) => selectionNode.id === oldNodes.id
|
||||
)
|
||||
(selectionNode) => selectionNode.id === oldNodes.id,
|
||||
),
|
||||
),
|
||||
newGroupNode,
|
||||
]);
|
||||
|
|
@ -125,8 +126,8 @@ export default function Page({
|
|||
!clonedSelection!.nodes.some(
|
||||
(selectionNode) =>
|
||||
selectionNode.id === oldEdge.target ||
|
||||
selectionNode.id === oldEdge.source
|
||||
)
|
||||
selectionNode.id === oldEdge.source,
|
||||
),
|
||||
),
|
||||
...newEdges,
|
||||
]);
|
||||
|
|
@ -179,7 +180,7 @@ export default function Page({
|
|||
{
|
||||
x: position.current.x,
|
||||
y: position.current.y,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
if (!isWrappedWithClass(event, "noundo")) {
|
||||
|
|
@ -275,7 +276,7 @@ export default function Page({
|
|||
|
||||
useEffect(() => {
|
||||
setSHowCanvas(
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0
|
||||
Object.keys(templates).length > 0 && Object.keys(types).length > 0,
|
||||
);
|
||||
}, [templates, types]);
|
||||
|
||||
|
|
@ -284,7 +285,7 @@ export default function Page({
|
|||
takeSnapshot();
|
||||
onConnect(params);
|
||||
},
|
||||
[takeSnapshot, onConnect]
|
||||
[takeSnapshot, onConnect],
|
||||
);
|
||||
|
||||
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
|
||||
const data: { type: string; node?: APIClassType } = JSON.parse(
|
||||
event.dataTransfer.getData("nodedata")
|
||||
event.dataTransfer.getData("nodedata"),
|
||||
);
|
||||
|
||||
const newId = getNodeId(data.type);
|
||||
|
|
@ -341,7 +342,7 @@ export default function Page({
|
|||
};
|
||||
paste(
|
||||
{ nodes: [newNode], edges: [] },
|
||||
{ x: event.clientX, y: event.clientY }
|
||||
{ x: event.clientX, y: event.clientY },
|
||||
);
|
||||
} else if (event.dataTransfer.types.some((types) => types === "Files")) {
|
||||
takeSnapshot();
|
||||
|
|
@ -370,7 +371,7 @@ export default function Page({
|
|||
}
|
||||
},
|
||||
// Specify dependencies for useCallback
|
||||
[getNodeId, setNodes, takeSnapshot, paste]
|
||||
[getNodeId, setNodes, takeSnapshot, paste],
|
||||
);
|
||||
|
||||
const onEdgeUpdateStart = useCallback(() => {
|
||||
|
|
@ -386,7 +387,7 @@ export default function Page({
|
|||
setEdges((els) => updateEdge(oldEdge, newConnection, els));
|
||||
}
|
||||
},
|
||||
[setEdges]
|
||||
[setEdges],
|
||||
);
|
||||
|
||||
const onEdgeUpdateEnd = useCallback((_, edge: Edge): void => {
|
||||
|
|
@ -419,7 +420,7 @@ export default function Page({
|
|||
(flow: OnSelectionChangeParams): void => {
|
||||
setLastSelection(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>(
|
||||
lastSelection && edges.length > 0
|
||||
? validateSelection(lastSelection!, edges).length > 0
|
||||
: false
|
||||
: false,
|
||||
);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isTransitioning, setIsTransitioning] = useState(false);
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ import {
|
|||
import {
|
||||
classNames,
|
||||
removeCountFromString,
|
||||
sensitiveSort,
|
||||
} from "../../../../utils/utils";
|
||||
import DisclosureComponent from "../DisclosureComponent";
|
||||
import ParentDisclosureComponent from "../ParentDisclosureComponent";
|
||||
import SidebarDraggableComponent from "./sideBarDraggableComponent";
|
||||
import { sortKeys } from "./utils";
|
||||
import sensitiveSort from "./utils/sensitive-sort";
|
||||
|
||||
export default function ExtraSidebar(): JSX.Element {
|
||||
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 === "int" ||
|
||||
data.node.template[templateField].type === "dict" ||
|
||||
data.node.template[templateField].type === "NestedDict")
|
||||
data.node.template[templateField].type === "NestedDict"),
|
||||
).length;
|
||||
const templates = useTypesStore((state) => state.templates);
|
||||
const hasStore = useStoreStore((state) => state.hasStore);
|
||||
|
|
@ -85,7 +85,7 @@ export default function NodeToolbarComponent({
|
|||
const [showconfirmShare, setShowconfirmShare] = useState(false);
|
||||
const [showOverrideModal, setShowOverrideModal] = useState(false);
|
||||
const [flowComponent, setFlowComponent] = useState<FlowType>(
|
||||
createFlowComponent(cloneDeep(data), version)
|
||||
createFlowComponent(cloneDeep(data), version),
|
||||
);
|
||||
|
||||
const openInNewTab = (url) => {
|
||||
|
|
@ -100,7 +100,7 @@ export default function NodeToolbarComponent({
|
|||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
|
||||
const setLastCopiedSelection = useFlowStore(
|
||||
(state) => state.setLastCopiedSelection
|
||||
(state) => state.setLastCopiedSelection,
|
||||
);
|
||||
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
|
|
@ -150,7 +150,7 @@ export default function NodeToolbarComponent({
|
|||
nodes,
|
||||
edges,
|
||||
setNodes,
|
||||
setEdges
|
||||
setEdges,
|
||||
);
|
||||
break;
|
||||
case "override":
|
||||
|
|
@ -174,7 +174,7 @@ export default function NodeToolbarComponent({
|
|||
y: 10,
|
||||
paneX: nodes.find((node) => node.id === data.id)?.position.x,
|
||||
paneY: nodes.find((node) => node.id === data.id)?.position.y,
|
||||
}
|
||||
},
|
||||
);
|
||||
break;
|
||||
case "update":
|
||||
|
|
@ -212,13 +212,13 @@ export default function NodeToolbarComponent({
|
|||
};
|
||||
|
||||
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 handleOnNewValue = (
|
||||
newValue: string | string[] | boolean | Object[]
|
||||
newValue: string | string[] | boolean | Object[],
|
||||
): void => {
|
||||
if (data.node!.template[name].value !== newValue) {
|
||||
takeSnapshot();
|
||||
|
|
@ -393,7 +393,7 @@ export default function NodeToolbarComponent({
|
|||
data-testid="save-button-modal"
|
||||
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",
|
||||
hasCode ? " " : " rounded-l-md "
|
||||
hasCode ? " " : " rounded-l-md ",
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
|
|
@ -411,7 +411,7 @@ export default function NodeToolbarComponent({
|
|||
<button
|
||||
data-testid="duplicate-button-modal"
|
||||
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) => {
|
||||
event.preventDefault();
|
||||
|
|
@ -459,7 +459,7 @@ export default function NodeToolbarComponent({
|
|||
<div
|
||||
data-testid="more-options-modal"
|
||||
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
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import useDropdownOptions from "../../hooks/use-dropdown-options";
|
|||
export default function HomePage(): JSX.Element {
|
||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId
|
||||
(state) => state.setCurrentFlowId,
|
||||
);
|
||||
|
||||
const location = useLocation();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export default function PlaygroundPage() {
|
|||
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||
const getFlowById = useFlowsManagerStore((state) => state.getFlowById);
|
||||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId
|
||||
(state) => state.setCurrentFlowId,
|
||||
);
|
||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { Badge } from "../../../../components/ui/badge";
|
|||
import { Card, CardContent } from "../../../../components/ui/card";
|
||||
import { deleteGlobalVariable } from "../../../../controllers/API";
|
||||
import useAlertStore from "../../../../stores/alertStore";
|
||||
import { useGlobalVariablesStore } from "../../../../stores/globalVariables";
|
||||
import { useGlobalVariablesStore } from "../../../../stores/globalVariablesStore/globalVariables";
|
||||
import { cn } from "../../../../utils/utils";
|
||||
|
||||
export default function GlobalVariablesPage() {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
updateFlowPool: (
|
||||
nodeId: string,
|
||||
data: FlowPoolObjectType | ChatOutputType | chatInputType,
|
||||
buildId?: string
|
||||
buildId?: string,
|
||||
) => {
|
||||
let newFlowPool = cloneDeep({ ...get().flowPool });
|
||||
if (!newFlowPool[nodeId]) {
|
||||
|
|
@ -170,7 +170,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
flowsManager.autoSaveCurrentFlow(
|
||||
newChange,
|
||||
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(
|
||||
get().nodes,
|
||||
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 node;
|
||||
})
|
||||
}),
|
||||
);
|
||||
},
|
||||
getNode: (id: string) => {
|
||||
|
|
@ -215,8 +215,8 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
get().nodes.filter((node) =>
|
||||
typeof nodeId === "string"
|
||||
? node.id !== nodeId
|
||||
: !nodeId.includes(node.id)
|
||||
)
|
||||
: !nodeId.includes(node.id),
|
||||
),
|
||||
);
|
||||
},
|
||||
deleteEdge: (edgeId) => {
|
||||
|
|
@ -224,8 +224,8 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
get().edges.filter((edge) =>
|
||||
typeof edgeId === "string"
|
||||
? edge.id !== edgeId
|
||||
: !edgeId.includes(edge.id)
|
||||
)
|
||||
: !edgeId.includes(edge.id),
|
||||
),
|
||||
);
|
||||
},
|
||||
paste: (selection, position) => {
|
||||
|
|
@ -291,7 +291,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
let source = idsMap[edge.source];
|
||||
let target = idsMap[edge.target];
|
||||
const sourceHandleObject: sourceHandleType = scapeJSONParse(
|
||||
edge.sourceHandle!
|
||||
edge.sourceHandle!,
|
||||
);
|
||||
let sourceHandle = scapedJSONStringfy({
|
||||
...sourceHandleObject,
|
||||
|
|
@ -301,7 +301,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
|
||||
edge.data.sourceHandle = sourceHandleObject;
|
||||
const targetHandleObject: targetHandleType = scapeJSONParse(
|
||||
edge.targetHandle!
|
||||
edge.targetHandle!,
|
||||
);
|
||||
let targetHandle = scapedJSONStringfy({
|
||||
...targetHandleObject,
|
||||
|
|
@ -322,7 +322,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
className: "stroke-gray-900 ",
|
||||
selected: false,
|
||||
},
|
||||
newEdges.map((edge) => ({ ...edge, selected: false }))
|
||||
newEdges.map((edge) => ({ ...edge, selected: false })),
|
||||
);
|
||||
});
|
||||
get().setEdges(newEdges);
|
||||
|
|
@ -341,10 +341,10 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
});
|
||||
|
||||
const newNodes = get().nodes.filter(
|
||||
(node) => !nodesIdsSelected.includes(node.id)
|
||||
(node) => !nodesIdsSelected.includes(node.id),
|
||||
);
|
||||
const newEdges = get().edges.filter(
|
||||
(edge) => !edgesIdsSelected.includes(edge.id)
|
||||
(edge) => !edgesIdsSelected.includes(edge.id),
|
||||
);
|
||||
|
||||
set({ nodes: newNodes, edges: newEdges });
|
||||
|
|
@ -402,7 +402,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
style: { stroke: "#555" },
|
||||
className: "stroke-foreground stroke-connection",
|
||||
},
|
||||
oldEdges
|
||||
oldEdges,
|
||||
);
|
||||
|
||||
return newEdges;
|
||||
|
|
@ -412,7 +412,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
.autoSaveCurrentFlow(
|
||||
get().nodes,
|
||||
newEdges,
|
||||
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 }
|
||||
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 },
|
||||
);
|
||||
},
|
||||
unselectAll: () => {
|
||||
|
|
@ -443,7 +443,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
function validateSubgraph(nodes: string[]) {
|
||||
const errorsObjs = validateNodes(
|
||||
get().nodes.filter((node) => nodes.includes(node.id)),
|
||||
get().edges
|
||||
get().edges,
|
||||
);
|
||||
|
||||
const errors = errorsObjs.map((obj) => obj.errors).flat();
|
||||
|
|
@ -462,14 +462,14 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
function handleBuildUpdate(
|
||||
vertexBuildData: VertexBuildTypeAPI,
|
||||
status: BuildStatus,
|
||||
runId: string
|
||||
runId: string,
|
||||
) {
|
||||
console.log("handleBuildUpdate", vertexBuildData, status, runId);
|
||||
if (vertexBuildData && vertexBuildData.inactivated_vertices) {
|
||||
get().removeFromVerticesBuild(vertexBuildData.inactivated_vertices);
|
||||
get().updateBuildStatus(
|
||||
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
|
||||
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(
|
||||
(vertex) => !vertexBuildData.inactivated_vertices?.includes(vertex.id)
|
||||
(vertex) =>
|
||||
!vertexBuildData.inactivated_vertices?.includes(vertex.id),
|
||||
);
|
||||
const nextVertices: VertexLayerElementType[] = zip(
|
||||
next_vertices_ids,
|
||||
top_level_vertices
|
||||
top_level_vertices,
|
||||
).map(([id, reference]) => ({ id: id!, reference }));
|
||||
|
||||
const newLayers = [
|
||||
|
|
@ -514,7 +515,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
|
||||
get().addDataToFlowPool(
|
||||
{ ...vertexBuildData, buildId: runId },
|
||||
vertexBuildData.id
|
||||
vertexBuildData.id,
|
||||
);
|
||||
|
||||
useFlowStore.getState().updateBuildStatus([vertexBuildData.id], status);
|
||||
|
|
@ -523,7 +524,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
const newFlowBuildStatus = { ...get().flowBuildStatus };
|
||||
// filter out the vertices that are not status
|
||||
const verticesToUpdate = verticesIds?.filter(
|
||||
(id) => newFlowBuildStatus[id]?.status !== BuildStatus.BUILT
|
||||
(id) => newFlowBuildStatus[id]?.status !== BuildStatus.BUILT,
|
||||
);
|
||||
|
||||
if (verticesToUpdate) {
|
||||
|
|
@ -588,7 +589,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
verticesLayers: VertexLayerElementType[][];
|
||||
runId: string;
|
||||
verticesToRun: string[];
|
||||
} | null
|
||||
} | null,
|
||||
) => {
|
||||
set({ verticesBuild: vertices });
|
||||
},
|
||||
|
|
@ -613,7 +614,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
// that are going to be built
|
||||
verticesIds: get().verticesBuild!.verticesIds.filter(
|
||||
// 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) {
|
||||
const { data, flows } = processFlows(dbData, false);
|
||||
const starterProjectsIds = starterProjects.flows!.map(
|
||||
(flow) => flow.id
|
||||
(flow) => flow.id,
|
||||
);
|
||||
get().setFlows(
|
||||
flows.filter((f) => !starterProjectsIds.includes(f.id))
|
||||
flows.filter((f) => !starterProjectsIds.includes(f.id)),
|
||||
);
|
||||
useTypesStore.setState((state) => ({
|
||||
data: { ...state.data, ["saved_components"]: data },
|
||||
|
|
@ -119,7 +119,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
if (get().currentFlow) {
|
||||
get().saveFlow(
|
||||
{ ...get().currentFlow!, data: { nodes, edges, viewport } },
|
||||
true
|
||||
true,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -145,7 +145,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
return updatedFlow;
|
||||
}
|
||||
return flow;
|
||||
})
|
||||
}),
|
||||
);
|
||||
//update tabs state
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
flow?: FlowType,
|
||||
override?: boolean,
|
||||
position?: XYPosition,
|
||||
fromDragAndDrop?: boolean
|
||||
fromDragAndDrop?: boolean,
|
||||
): Promise<string | undefined> => {
|
||||
if (newProject) {
|
||||
let flowData = flow
|
||||
|
|
@ -263,7 +263,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
.getState()
|
||||
.paste(
|
||||
{ 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)
|
||||
.then(() => {
|
||||
const { data, flows } = processFlows(
|
||||
get().flows.filter((flow) => !id.includes(flow.id))
|
||||
get().flows.filter((flow) => !id.includes(flow.id)),
|
||||
);
|
||||
get().setFlows(flows);
|
||||
set({ isLoading: false });
|
||||
|
|
@ -293,7 +293,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
deleteFlowFromDatabase(id)
|
||||
.then(() => {
|
||||
const { data, flows } = processFlows(
|
||||
get().flows.filter((flow) => flow.id !== id)
|
||||
get().flows.filter((flow) => flow.id !== id),
|
||||
);
|
||||
get().setFlows(flows);
|
||||
set({ isLoading: false });
|
||||
|
|
@ -315,7 +315,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
return new Promise<void>((resolve) => {
|
||||
let componentFlow = get().flows.find(
|
||||
(componentFlow) =>
|
||||
componentFlow.is_component && componentFlow.name === key
|
||||
componentFlow.is_component && componentFlow.name === key,
|
||||
);
|
||||
|
||||
if (componentFlow) {
|
||||
|
|
@ -363,7 +363,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
fileData,
|
||||
undefined,
|
||||
position,
|
||||
true
|
||||
true,
|
||||
);
|
||||
resolve(id);
|
||||
}
|
||||
|
|
@ -404,7 +404,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
return get().addFlow(
|
||||
true,
|
||||
createFlowComponent(component, useDarkStore.getState().version),
|
||||
override
|
||||
override,
|
||||
);
|
||||
},
|
||||
takeSnapshot: () => {
|
||||
|
|
@ -425,7 +425,7 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
if (pastLength > 0) {
|
||||
past[currentFlowId] = past[currentFlowId].slice(
|
||||
pastLength - defaultOptions.maxHistorySize + 1,
|
||||
pastLength
|
||||
pastLength,
|
||||
);
|
||||
|
||||
past[currentFlowId].push(newState);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const useFolderStore = create<FoldersStoreType>((set, get) => ({
|
|||
(res) => {
|
||||
set({ folders: res });
|
||||
const myCollectionId = res?.find(
|
||||
(f) => f.name === DEFAULT_FOLDER
|
||||
(f) => f.name === DEFAULT_FOLDER,
|
||||
)?.id;
|
||||
set({ myCollectionId });
|
||||
get().setLoading(false);
|
||||
|
|
@ -26,7 +26,7 @@ export const useFolderStore = create<FoldersStoreType>((set, get) => ({
|
|||
() => {
|
||||
set({ folders: [] });
|
||||
get().setLoading(false);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -45,7 +45,7 @@ export const useFolderStore = create<FoldersStoreType>((set, get) => ({
|
|||
},
|
||||
() => {
|
||||
get().setLoadingById(false);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { create } from "zustand";
|
||||
import { GlobalVariablesStore } from "../types/zustand/globalVariables";
|
||||
import { getUnavailableFields } from "../utils/utils";
|
||||
import { GlobalVariablesStore } from "../../types/zustand/globalVariables";
|
||||
import getUnavailableFields from "./utils/get-unavailable-fields";
|
||||
|
||||
export const useGlobalVariablesStore = create<GlobalVariablesStore>(
|
||||
(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?: (
|
||||
newNodeClass: APIClassType,
|
||||
code: string,
|
||||
name: string
|
||||
name: string,
|
||||
) => void;
|
||||
setShowState: (show: boolean | SetStateAction<boolean>) => void;
|
||||
isOutdated?: boolean;
|
||||
|
|
@ -565,7 +565,7 @@ export type chatMessagePropsType = {
|
|||
updateChat: (
|
||||
chat: ChatMessageType,
|
||||
message: string,
|
||||
stream_url?: string
|
||||
stream_url?: string,
|
||||
) => void;
|
||||
};
|
||||
|
||||
|
|
@ -657,12 +657,12 @@ export type codeTabsPropsType = {
|
|||
value: string,
|
||||
node: NodeType,
|
||||
template: TemplateVariableType,
|
||||
tweak: tweakType
|
||||
tweak: tweakType,
|
||||
) => string;
|
||||
buildTweakObject?: (
|
||||
tw: string,
|
||||
changes: string | string[] | boolean | number | Object[] | Object,
|
||||
template: TemplateVariableType
|
||||
template: TemplateVariableType,
|
||||
) => Promise<string | void>;
|
||||
};
|
||||
activeTweaks?: boolean;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export type FlowStoreType = {
|
|||
state:
|
||||
| FlowState
|
||||
| undefined
|
||||
| ((oldState: FlowState | undefined) => FlowState)
|
||||
| ((oldState: FlowState | undefined) => FlowState),
|
||||
) => void;
|
||||
nodes: Node[];
|
||||
edges: Edge[];
|
||||
|
|
@ -78,11 +78,11 @@ export type FlowStoreType = {
|
|||
onEdgesChange: OnEdgesChange;
|
||||
setNodes: (
|
||||
update: Node[] | ((oldState: Node[]) => Node[]),
|
||||
skipSave?: boolean
|
||||
skipSave?: boolean,
|
||||
) => void;
|
||||
setEdges: (
|
||||
update: Edge[] | ((oldState: Edge[]) => Edge[]),
|
||||
skipSave?: boolean
|
||||
skipSave?: boolean,
|
||||
) => void;
|
||||
setNode: (id: string, update: Node | ((oldState: Node) => Node)) => void;
|
||||
getNode: (id: string) => Node | undefined;
|
||||
|
|
@ -90,12 +90,12 @@ export type FlowStoreType = {
|
|||
deleteEdge: (edgeId: string | Array<string>) => void;
|
||||
paste: (
|
||||
selection: { nodes: any; edges: any },
|
||||
position: { x: number; y: number; paneX?: number; paneY?: number }
|
||||
position: { x: number; y: number; paneX?: number; paneY?: number },
|
||||
) => void;
|
||||
lastCopiedSelection: { nodes: any; edges: any } | null;
|
||||
setLastCopiedSelection: (
|
||||
newSelection: { nodes: any; edges: any } | null,
|
||||
isCrop?: boolean
|
||||
isCrop?: boolean,
|
||||
) => void;
|
||||
cleanFlow: () => void;
|
||||
setFilterEdge: (newState) => void;
|
||||
|
|
@ -119,7 +119,7 @@ export type FlowStoreType = {
|
|||
verticesLayers: VertexLayerElementType[][];
|
||||
runId: string;
|
||||
verticesToRun: string[];
|
||||
} | null
|
||||
} | null,
|
||||
) => void;
|
||||
addToVerticesBuild: (vertices: string[]) => void;
|
||||
removeFromVerticesBuild: (vertices: string[]) => void;
|
||||
|
|
@ -137,7 +137,7 @@ export type FlowStoreType = {
|
|||
updateFlowPool: (
|
||||
nodeId: string,
|
||||
data: FlowPoolObjectType | ChatOutputType | chatInputType,
|
||||
buildId?: string
|
||||
buildId?: string,
|
||||
) => void;
|
||||
getNodePosition: (nodeId: string) => { x: number; y: number };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export const handleUpdateValues = async (name: string, data: NodeDataType) => {
|
|||
code,
|
||||
template,
|
||||
name,
|
||||
data.node?.template[name]?.value
|
||||
data.node?.template[name]?.value,
|
||||
);
|
||||
if (res.status === 200 && data.node?.template) {
|
||||
return res.data.template;
|
||||
|
|
@ -34,5 +34,5 @@ export const handleUpdateValues = async (name: string, data: NodeDataType) => {
|
|||
|
||||
export const debouncedHandleUpdateValues = debounce(
|
||||
handleUpdateValues,
|
||||
SAVE_DEBOUNCE_TIME
|
||||
SAVE_DEBOUNCE_TIME,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -36,12 +36,9 @@ import {
|
|||
unselectAllNodesType,
|
||||
updateEdgesHandleIdsType,
|
||||
} from "../types/utils/reactflowUtils";
|
||||
import {
|
||||
createRandomKey,
|
||||
getFieldTitle,
|
||||
getRandomDescription,
|
||||
toTitleCase,
|
||||
} from "./utils";
|
||||
import { createRandomKey, toTitleCase } from "./utils";
|
||||
import { DESCRIPTIONS } from "../flow_constants";
|
||||
import getFieldTitle from "../customNodes/utils/get-field-title";
|
||||
const uid = new ShortUniqueId({ length: 5 });
|
||||
|
||||
export function checkChatInput(nodes: Node[]) {
|
||||
|
|
@ -102,18 +99,18 @@ export function unselectAllNodes({ updateNodes, data }: unselectAllNodesType) {
|
|||
export function isValidConnection(
|
||||
{ source, target, sourceHandle, targetHandle }: Connection,
|
||||
nodes: Node[],
|
||||
edges: Edge[]
|
||||
edges: Edge[],
|
||||
) {
|
||||
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
|
||||
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
|
||||
if (
|
||||
targetHandleObject.inputTypes?.some(
|
||||
(n) => n === sourceHandleObject.dataType
|
||||
(n) => n === sourceHandleObject.dataType,
|
||||
) ||
|
||||
sourceHandleObject.baseClasses.some(
|
||||
(t) =>
|
||||
targetHandleObject.inputTypes?.some((n) => n === t) ||
|
||||
t === targetHandleObject.type
|
||||
t === targetHandleObject.type,
|
||||
)
|
||||
) {
|
||||
let targetNode = nodes.find((node) => node.id === target!)?.data?.node;
|
||||
|
|
@ -146,7 +143,7 @@ export function removeApiKeys(flow: FlowType): FlowType {
|
|||
|
||||
export function updateTemplate(
|
||||
reference: APITemplateType,
|
||||
objectToUpdate: APITemplateType
|
||||
objectToUpdate: APITemplateType,
|
||||
): APITemplateType {
|
||||
let clonedObject: APITemplateType = cloneDeep(reference);
|
||||
|
||||
|
|
@ -206,7 +203,7 @@ export const processDataFromFlow = (flow: FlowType, refreshIds = true) => {
|
|||
|
||||
export function updateIds(
|
||||
{ edges, nodes }: { edges: Edge[]; nodes: Node[] },
|
||||
selection?: { edges: Edge[]; nodes: Node[] }
|
||||
selection?: { edges: Edge[]; nodes: Node[] },
|
||||
) {
|
||||
let idsMap = {};
|
||||
const selectionIds = selection?.nodes.map((n) => n.id);
|
||||
|
|
@ -234,7 +231,7 @@ export function updateIds(
|
|||
edge.source = idsMap[edge.source];
|
||||
edge.target = idsMap[edge.target];
|
||||
const sourceHandleObject: sourceHandleType = scapeJSONParse(
|
||||
edge.sourceHandle!
|
||||
edge.sourceHandle!,
|
||||
);
|
||||
edge.sourceHandle = scapedJSONStringfy({
|
||||
...sourceHandleObject,
|
||||
|
|
@ -244,7 +241,7 @@ export function updateIds(
|
|||
edge.data.sourceHandle.id = edge.source;
|
||||
}
|
||||
const targetHandleObject: targetHandleType = scapeJSONParse(
|
||||
edge.targetHandle!
|
||||
edge.targetHandle!,
|
||||
);
|
||||
edge.targetHandle = scapedJSONStringfy({
|
||||
...targetHandleObject,
|
||||
|
|
@ -290,11 +287,11 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
|
|||
(scapeJSONParse(edge.targetHandle!) as targetHandleType).fieldName ===
|
||||
t &&
|
||||
(scapeJSONParse(edge.targetHandle!) as targetHandleType).id ===
|
||||
node.id
|
||||
node.id,
|
||||
)
|
||||
) {
|
||||
errors.push(
|
||||
`${displayName || type} is missing ${getFieldTitle(template, t)}.`
|
||||
`${displayName || type} is missing ${getFieldTitle(template, t)}.`,
|
||||
);
|
||||
} else if (
|
||||
template[t].type === "dict" &&
|
||||
|
|
@ -308,15 +305,15 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
|
|||
errors.push(
|
||||
`${displayName || type} (${getFieldTitle(
|
||||
template,
|
||||
t
|
||||
)}) contains duplicate keys with the same values.`
|
||||
t,
|
||||
)}) contains duplicate keys with the same values.`,
|
||||
);
|
||||
if (hasEmptyKey(template[t].value))
|
||||
errors.push(
|
||||
`${displayName || type} (${getFieldTitle(
|
||||
template,
|
||||
t
|
||||
)}) field must not be empty.`
|
||||
t,
|
||||
)}) field must not be empty.`,
|
||||
);
|
||||
}
|
||||
return errors;
|
||||
|
|
@ -325,7 +322,7 @@ export function validateNode(node: NodeType, edges: Edge[]): Array<string> {
|
|||
|
||||
export function validateNodes(
|
||||
nodes: Node[],
|
||||
edges: Edge[]
|
||||
edges: Edge[],
|
||||
): // this returns an array of tuples with the node id and the errors
|
||||
Array<{ id: string; errors: Array<string> }> {
|
||||
if (nodes.length === 0) {
|
||||
|
|
@ -346,7 +343,7 @@ export function updateEdges(edges: Edge[]) {
|
|||
if (edges)
|
||||
edges.forEach((edge) => {
|
||||
const targetHandleObject: targetHandleType = scapeJSONParse(
|
||||
edge.targetHandle!
|
||||
edge.targetHandle!,
|
||||
);
|
||||
edge.className = "stroke-gray-900 stroke-connection";
|
||||
});
|
||||
|
|
@ -413,7 +410,7 @@ export function handleKeyDown(
|
|||
| React.KeyboardEvent<HTMLInputElement>
|
||||
| React.KeyboardEvent<HTMLTextAreaElement>,
|
||||
inputValue: string | string[] | null,
|
||||
block: string
|
||||
block: string,
|
||||
) {
|
||||
//condition to fix bug control+backspace on Windows/Linux
|
||||
if (
|
||||
|
|
@ -438,7 +435,7 @@ export function handleKeyDown(
|
|||
}
|
||||
|
||||
export function handleOnlyIntegerInput(
|
||||
event: React.KeyboardEvent<HTMLInputElement>
|
||||
event: React.KeyboardEvent<HTMLInputElement>,
|
||||
) {
|
||||
if (
|
||||
event.key === "." ||
|
||||
|
|
@ -454,7 +451,7 @@ export function handleOnlyIntegerInput(
|
|||
|
||||
export function getConnectedNodes(
|
||||
edge: Edge,
|
||||
nodes: Array<NodeType>
|
||||
nodes: Array<NodeType>,
|
||||
): Array<NodeType> {
|
||||
const sourceId = edge.source;
|
||||
const targetId = edge.target;
|
||||
|
|
@ -555,7 +552,7 @@ export function checkOldEdgesHandles(edges: Edge[]): boolean {
|
|||
!edge.sourceHandle ||
|
||||
!edge.targetHandle ||
|
||||
!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 keyValuePairs = keys.map(
|
||||
(key) => `"${key}":${customStringify(obj[key])}`
|
||||
(key) => `"${key}":${customStringify(obj[key])}`,
|
||||
);
|
||||
return `{${keyValuePairs.join(",")}}`;
|
||||
}
|
||||
|
|
@ -607,7 +604,7 @@ export function getHandleId(
|
|||
source: string,
|
||||
sourceHandle: string,
|
||||
target: string,
|
||||
targetHandle: string
|
||||
targetHandle: string,
|
||||
) {
|
||||
return (
|
||||
"reactflow__edge-" + source + sourceHandle + "-" + target + targetHandle
|
||||
|
|
@ -618,7 +615,7 @@ export function generateFlow(
|
|||
selection: OnSelectionChangeParams,
|
||||
nodes: Node[],
|
||||
edges: Edge[],
|
||||
name: string
|
||||
name: string,
|
||||
): generateFlowType {
|
||||
const newFlowData = { nodes, edges, viewport: { zoom: 1, x: 0, y: 0 } };
|
||||
const uid = new ShortUniqueId({ length: 5 });
|
||||
|
|
@ -627,7 +624,7 @@ export function generateFlow(
|
|||
newFlowData.edges = selection.edges.filter(
|
||||
(edge) =>
|
||||
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;
|
||||
|
||||
|
|
@ -648,7 +645,7 @@ export function generateFlow(
|
|||
(edge) =>
|
||||
(selection.nodes.some((node) => node.id === edge.target) ||
|
||||
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 lastNode = findLastNode(groupNode.data.node!.flow!.data!);
|
||||
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) => {
|
||||
if (lastNode && edge.source === lastNode.id) {
|
||||
edge.source = groupNode.id;
|
||||
let newSourceHandle: sourceHandleType = scapeJSONParse(
|
||||
edge.sourceHandle!
|
||||
edge.sourceHandle!,
|
||||
);
|
||||
newSourceHandle.id = groupNode.id;
|
||||
edge.sourceHandle = scapedJSONStringfy(newSourceHandle);
|
||||
|
|
@ -692,7 +689,7 @@ export function reconnectEdges(groupNode: NodeType, excludedEdges: Edge[]) {
|
|||
export function filterFlow(
|
||||
selection: OnSelectionChangeParams,
|
||||
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)));
|
||||
setEdges((edges) => edges.filter((edge) => !selection.edges.includes(edge)));
|
||||
|
|
@ -730,7 +727,7 @@ export function updateFlowPosition(NewPosition: XYPosition, flow: FlowType) {
|
|||
export function concatFlows(
|
||||
flow: FlowType,
|
||||
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!;
|
||||
setNodes((old) => [...old, ...nodes]);
|
||||
|
|
@ -739,7 +736,7 @@ export function concatFlows(
|
|||
|
||||
export function validateSelection(
|
||||
selection: OnSelectionChangeParams,
|
||||
edges: Edge[]
|
||||
edges: Edge[],
|
||||
): Array<string> {
|
||||
const clonedSelection = cloneDeep(selection);
|
||||
const clonedEdges = cloneDeep(edges);
|
||||
|
|
@ -753,7 +750,7 @@ export function validateSelection(
|
|||
let nodesSet = new Set(clonedSelection.nodes.map((n) => n.id));
|
||||
// then filter the edges that are connected to the nodes in the set
|
||||
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
|
||||
clonedSelection.edges = connectedEdges;
|
||||
|
|
@ -767,17 +764,17 @@ export function validateSelection(
|
|||
clonedSelection.nodes.some(
|
||||
(node) =>
|
||||
isInputNode(node.data as NodeDataType) ||
|
||||
isOutputNode(node.data as NodeDataType)
|
||||
isOutputNode(node.data as NodeDataType),
|
||||
)
|
||||
) {
|
||||
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
|
||||
if (
|
||||
clonedSelection.nodes.filter(
|
||||
(n) => !clonedSelection.edges.some((e) => e.source === n.id)
|
||||
(n) => !clonedSelection.edges.some((e) => e.source === n.id),
|
||||
).length > 1
|
||||
) {
|
||||
errorsArray.push("Please select only one node with free outputs");
|
||||
|
|
@ -788,7 +785,7 @@ export function validateSelection(
|
|||
clonedSelection.nodes.some(
|
||||
(node) =>
|
||||
!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");
|
||||
|
|
@ -845,8 +842,8 @@ export function mergeNodeTemplates({
|
|||
nodeTemplate[key].display_name
|
||||
? nodeTemplate[key].display_name
|
||||
: nodeTemplate[key].name
|
||||
? toTitleCase(nodeTemplate[key].name)
|
||||
: toTitleCase(key);
|
||||
? toTitleCase(nodeTemplate[key].name)
|
||||
: toTitleCase(key);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -857,7 +854,7 @@ function isHandleConnected(
|
|||
edges: Edge[],
|
||||
key: string,
|
||||
field: TemplateVariableType,
|
||||
nodeId: string
|
||||
nodeId: string,
|
||||
) {
|
||||
/*
|
||||
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,
|
||||
proxy: { id: field.proxy!.id, field: field.proxy!.field },
|
||||
inputTypes: field.input_types,
|
||||
} as targetHandleType)
|
||||
} as targetHandleType),
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
|
|
@ -888,7 +885,7 @@ function isHandleConnected(
|
|||
fieldName: key,
|
||||
id: nodeId,
|
||||
inputTypes: field.input_types,
|
||||
} as targetHandleType)
|
||||
} as targetHandleType),
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
|
|
@ -911,7 +908,7 @@ export function generateNodeTemplate(Flow: FlowType) {
|
|||
|
||||
export function generateNodeFromFlow(
|
||||
flow: FlowType,
|
||||
getNodeId: (type: string) => string
|
||||
getNodeId: (type: string) => string,
|
||||
): NodeType {
|
||||
const { nodes } = flow.data!;
|
||||
const outputNode = cloneDeep(findLastNode(flow.data!));
|
||||
|
|
@ -942,7 +939,7 @@ export function generateNodeFromFlow(
|
|||
export function connectedInputNodesOnHandle(
|
||||
nodeId: string,
|
||||
handleId: string,
|
||||
{ nodes, edges }: { nodes: NodeType[]; edges: Edge[] }
|
||||
{ nodes, edges }: { nodes: NodeType[]; edges: Edge[] },
|
||||
) {
|
||||
const connectedNodes: Array<{ name: string; id: string; isGroup: boolean }> =
|
||||
[];
|
||||
|
|
@ -979,7 +976,7 @@ export function connectedInputNodesOnHandle(
|
|||
|
||||
export function updateProxyIdsOnTemplate(
|
||||
template: APITemplateType,
|
||||
idsMap: { [key: string]: string }
|
||||
idsMap: { [key: string]: string },
|
||||
) {
|
||||
Object.keys(template).forEach((key) => {
|
||||
if (template[key].proxy && idsMap[template[key].proxy!.id]) {
|
||||
|
|
@ -990,7 +987,7 @@ export function updateProxyIdsOnTemplate(
|
|||
|
||||
export function updateEdgesIds(
|
||||
edges: Edge[],
|
||||
idsMap: { [key: string]: string }
|
||||
idsMap: { [key: string]: string },
|
||||
) {
|
||||
edges.forEach((edge) => {
|
||||
let targetHandle: targetHandleType = edge.data.targetHandle;
|
||||
|
|
@ -1022,7 +1019,7 @@ export function expandGroupNode(
|
|||
nodes: Node[],
|
||||
edges: Edge[],
|
||||
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!);
|
||||
updateProxyIdsOnTemplate(template, idsMap);
|
||||
|
|
@ -1065,7 +1062,7 @@ export function expandGroupNode(
|
|||
const lastNode = cloneDeep(findLastNode(flow!.data!));
|
||||
newEdge.source = lastNode!.id;
|
||||
let newSourceHandle: sourceHandleType = scapeJSONParse(
|
||||
newEdge.sourceHandle!
|
||||
newEdge.sourceHandle!,
|
||||
);
|
||||
newSourceHandle.id = lastNode!.id;
|
||||
newEdge.data.sourceHandle = newSourceHandle;
|
||||
|
|
@ -1122,7 +1119,7 @@ export function expandGroupNode(
|
|||
|
||||
export function getGroupStatus(
|
||||
flow: FlowType,
|
||||
ssData: { [key: string]: { valid: boolean; params: string } }
|
||||
ssData: { [key: string]: { valid: boolean; params: string } },
|
||||
) {
|
||||
let status = { valid: true, params: SUCCESS_BUILD };
|
||||
const { nodes } = flow.data!;
|
||||
|
|
@ -1141,7 +1138,7 @@ export function getGroupStatus(
|
|||
|
||||
export function createFlowComponent(
|
||||
nodeData: NodeDataType,
|
||||
version: string
|
||||
version: string,
|
||||
): FlowType {
|
||||
const flowNode: FlowType = {
|
||||
data: {
|
||||
|
|
@ -1177,7 +1174,7 @@ export function downloadNode(NodeFLow: FlowType) {
|
|||
|
||||
export function updateComponentNameAndType(
|
||||
data: any,
|
||||
component: NodeDataType
|
||||
component: NodeDataType,
|
||||
) {}
|
||||
|
||||
export function removeFileNameFromComponents(flow: FlowType) {
|
||||
|
|
@ -1251,7 +1248,7 @@ export function extractFieldsFromComponenents(data: APIObjectType) {
|
|||
export function downloadFlow(
|
||||
flow: FlowType,
|
||||
flowName: string,
|
||||
flowDescription?: string
|
||||
flowDescription?: string,
|
||||
) {
|
||||
let clonedFlow = cloneDeep(flow);
|
||||
removeFileNameFromComponents(clonedFlow);
|
||||
|
|
@ -1261,7 +1258,7 @@ export function downloadFlow(
|
|||
...clonedFlow,
|
||||
name: flowName,
|
||||
description: flowDescription,
|
||||
})
|
||||
}),
|
||||
)}`;
|
||||
|
||||
// create a link element and set its properties
|
||||
|
|
@ -1276,7 +1273,7 @@ export function downloadFlow(
|
|||
export function downloadFlows() {
|
||||
downloadFlowsFromDatabase().then((flows) => {
|
||||
const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
|
||||
JSON.stringify(flows)
|
||||
JSON.stringify(flows),
|
||||
)}`;
|
||||
|
||||
// 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 = (
|
||||
flowData: ReactFlowJsonObject,
|
||||
flow: FlowType
|
||||
flow: FlowType,
|
||||
) => {
|
||||
return {
|
||||
description: flow?.description ?? getRandomDescription(),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export default function cloneFLowWithParent(
|
|||
flow: FlowType,
|
||||
parent: string,
|
||||
is_component: boolean,
|
||||
keepId = false
|
||||
keepId = false,
|
||||
) {
|
||||
let childFLow = cloneDeep(flow);
|
||||
childFLow.parent = parent;
|
||||
|
|
@ -20,15 +20,6 @@ export default function cloneFLowWithParent(
|
|||
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[]) {
|
||||
let inputs: { 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 { priorityFields } from "../constants/constants";
|
||||
import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "../flow_constants";
|
||||
import { APIDataType, TemplateVariableType } from "../types/api";
|
||||
import {
|
||||
APIDataType,
|
||||
APITemplateType,
|
||||
TemplateVariableType,
|
||||
} from "../types/api";
|
||||
import {
|
||||
IVarHighlightType,
|
||||
groupedObjType,
|
||||
nodeGroupedObjType,
|
||||
tweakType,
|
||||
|
|
@ -92,20 +87,6 @@ export function toTitleCase(
|
|||
.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 function checkUpperWords(str: string): string {
|
||||
const words = str.split(" ").map((word) => {
|
||||
|
|
@ -117,8 +98,121 @@ export function checkUpperWords(str: string): string {
|
|||
return words.join(" ");
|
||||
}
|
||||
|
||||
export const isWrappedWithClass = (event: any, className: string | undefined) =>
|
||||
event.target.closest(`.${className}`);
|
||||
export function buildInputs(): string {
|
||||
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(
|
||||
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
|
||||
export function getSetFromObject(obj: object, key?: string): Set<string> {
|
||||
const set = new Set<string>();
|
||||
|
|
@ -640,67 +342,10 @@ export function getSetFromObject(obj: object, key?: string): Set<string> {
|
|||
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) {
|
||||
if (!obj) return 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 {
|
||||
const timestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3}Z)?$/;
|
||||
return timestampRegex.test(str);
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ test("add folder by drag and drop", async ({ page }) => {
|
|||
|
||||
const jsonContent = readFileSync(
|
||||
"tests/end-to-end/assets/collection.json",
|
||||
"utf-8"
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
// Create the DataTransfer and File
|
||||
|
|
@ -95,7 +95,7 @@ test("add folder by drag and drop", async ({ page }) => {
|
|||
"drop",
|
||||
{
|
||||
dataTransfer,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
await page.getByText("Getting Started").first().isVisible();
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ test("NestedComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showpool_threads"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpool_threads"]').isChecked()
|
||||
await page.locator('//*[@id="showpool_threads"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
//showtext_key
|
||||
|
|
@ -53,140 +53,140 @@ test("NestedComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
// showindex_name
|
||||
await page.locator('//*[@id="showindex_name"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked()
|
||||
await page.locator('//*[@id="showindex_name"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
// shownamespace
|
||||
await page.locator('//*[@id="shownamespace"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked()
|
||||
await page.locator('//*[@id="shownamespace"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
// showpinecone_api_key
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked()
|
||||
await page.locator('//*[@id="showpinecone_api_key"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
//showpool_threads
|
||||
await page.locator('//*[@id="showpool_threads"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showpool_threads"]').isChecked()
|
||||
await page.locator('//*[@id="showpool_threads"]').isChecked(),
|
||||
).toBeFalsy();
|
||||
|
||||
//showtext_key
|
||||
await page.locator('//*[@id="showtext_key"]').click();
|
||||
|
||||
expect(
|
||||
await page.locator('//*[@id="showtext_key"]').isChecked()
|
||||
await page.locator('//*[@id="showtext_key"]').isChecked(),
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"status": "failed",
|
||||
"failedTests": []
|
||||
"status": "failed",
|
||||
"failedTests": []
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue