+
- Run
+ Playground
) : (
diff --git a/src/frontend/src/components/codeTabsComponent/index.tsx b/src/frontend/src/components/codeTabsComponent/index.tsx
index 0a19ec273..a3c581313 100644
--- a/src/frontend/src/components/codeTabsComponent/index.tsx
+++ b/src/frontend/src/components/codeTabsComponent/index.tsx
@@ -267,7 +267,7 @@ export default function CodeTabsComponent({
{node.data.node.template[
templateField
- ].list ? (
+ ]?.list ? (
diff --git a/src/frontend/src/components/inputListComponent/index.tsx b/src/frontend/src/components/inputListComponent/index.tsx
index b43c6df86..f0aa8cca7 100644
--- a/src/frontend/src/components/inputListComponent/index.tsx
+++ b/src/frontend/src/components/inputListComponent/index.tsx
@@ -12,6 +12,7 @@ export default function InputListComponent({
disabled,
editNode = false,
componentName,
+ playgroundDisabled,
}: InputListComponentType): JSX.Element {
useEffect(() => {
if (disabled && value.length > 0 && value[0] !== "") {
@@ -24,7 +25,7 @@ export default function InputListComponent({
value = [value];
}
- if (!value.length) value = [""];
+ if (!value?.length) value = [""];
return (
)}
diff --git a/src/frontend/src/components/keypairListComponent/index.tsx b/src/frontend/src/components/keypairListComponent/index.tsx
index fcd35e01e..2fa12e3b8 100644
--- a/src/frontend/src/components/keypairListComponent/index.tsx
+++ b/src/frontend/src/components/keypairListComponent/index.tsx
@@ -20,7 +20,13 @@ export default function KeypairListComponent({
}
}, [disabled]);
- const ref = useRef(value.length === 0 ? [{ "": "" }] : value);
+ const checkValueType = (value) => {
+ return Array.isArray(value) ? value : [value];
+ };
+
+ const ref = useRef([]);
+ ref.current =
+ !value || value?.length === 0 ? [{ "": "" }] : checkValueType(value);
useEffect(() => {
if (JSON.stringify(value) !== JSON.stringify(ref.current)) {
diff --git a/src/frontend/src/constants/constants.ts b/src/frontend/src/constants/constants.ts
index 49483875c..6893d0d03 100644
--- a/src/frontend/src/constants/constants.ts
+++ b/src/frontend/src/constants/constants.ts
@@ -711,13 +711,22 @@ export const LANGFLOW_SUPPORTED_TYPES = new Set([
export const priorityFields = new Set(["code", "template"]);
-export const INPUT_TYPES = new Set(["ChatInput", "TextInput", "KeyPairInput"]);
+export const INPUT_TYPES = new Set([
+ "ChatInput",
+ "TextInput",
+ "KeyPairInput",
+ "JsonInput",
+ "StringListInput",
+]);
export const OUTPUT_TYPES = new Set([
"ChatOutput",
"TextOutput",
"PDFOutput",
"ImageOutput",
"CSVOutput",
+ "JsonOutput",
+ "KeyPairOutput",
+ "StringListOutput",
]);
export const CHAT_FIRST_INITIAL_TEXT =
diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts
index b7746f826..5569eb309 100644
--- a/src/frontend/src/controllers/API/index.ts
+++ b/src/frontend/src/controllers/API/index.ts
@@ -1,5 +1,5 @@
-import { AxiosResponse } from "axios";
-import { ReactFlowJsonObject } from "reactflow";
+import { AxiosRequestConfig, AxiosResponse } from "axios";
+import { Edge, ReactFlowJsonObject,Node } from "reactflow";
import { BASE_URL_API } from "../../constants/constants";
import { api } from "../../controllers/API/api";
import {
@@ -908,17 +908,26 @@ export async function updateGlobalVariable(
export async function getVerticesOrder(
flowId: string,
startNodeId?: string | null,
- stopNodeId?: string | null
+ stopNodeId?: string | null,
+ nodes?:Node[],
+ Edges?:Edge[]
): Promise> {
// nodeId is optional and is a query parameter
// if nodeId is not provided, the API will return all vertices
- const config = {};
+ const config:AxiosRequestConfig = {};
if (stopNodeId) {
config["params"] = { stop_component_id: stopNodeId };
} else if (startNodeId) {
config["params"] = { start_component_id: startNodeId };
}
- return await api.get(`${BASE_URL_API}build/${flowId}/vertices`, config);
+ const data = {
+ data:{}
+ }
+ if(nodes && Edges){
+ data["data"]["nodes"] = nodes
+ data["data"]["edges"] = Edges
+ }
+ return await api.post(`${BASE_URL_API}build/${flowId}/vertices`,data, config);
}
export async function postBuildVertex(
diff --git a/src/frontend/src/modals/EditNodeModal/index.tsx b/src/frontend/src/modals/EditNodeModal/index.tsx
index 17da8c73b..87c72d1df 100644
--- a/src/frontend/src/modals/EditNodeModal/index.tsx
+++ b/src/frontend/src/modals/EditNodeModal/index.tsx
@@ -203,7 +203,7 @@ const EditNodeModal = forwardRef(
!myData.node.template[templateParam].options ? (
{myData.node.template[templateParam]
- .list ? (
+ ?.list ? (
@@ -420,6 +420,10 @@ const EditNodeModal = forwardRef(
.type === "int" ? (
{
+ if (value) onChange(value);
+ }, [value]);
+ const isDark = useDarkStore((state) => state.dark);
+
+ const ref = useRef(null);
+ ref.current = value;
+
+ const getClassNames = () => {
+ if (!isDark && !left) return "json-view-playground-white";
+ if (!isDark && left) return "json-view-playground-white-left";
+ if (isDark && left) return "json-view-playground-dark-left";
+ if (isDark && !left) return "json-view-playground-dark";
+ };
+
+ return (
+
+ {
+ ref.current = edit["src"];
+ }}
+ onChange={(edit) => {
+ ref.current = edit["src"];
+ }}
+ src={ref.current}
+ />
+
+ );
+}
diff --git a/src/frontend/src/modals/IOModal/components/IOFieldView/components/keyPairInput/index.tsx b/src/frontend/src/modals/IOModal/components/IOFieldView/components/keyPairInput/index.tsx
new file mode 100644
index 000000000..2e95e78ef
--- /dev/null
+++ b/src/frontend/src/modals/IOModal/components/IOFieldView/components/keyPairInput/index.tsx
@@ -0,0 +1,107 @@
+import _ from "lodash";
+import { useRef } from "react";
+import IconComponent from "../../../../../../components/genericIconComponent";
+import { Input } from "../../../../../../components/ui/input";
+import { classNames } from "../../../../../../utils/utils";
+
+export type IOKeyPairInputProps = {
+ value: any;
+ onChange: (value: any) => void;
+ duplicateKey: boolean;
+ isList: boolean;
+ isInputField?: boolean;
+};
+
+const IOKeyPairInput = ({
+ value,
+ onChange,
+ duplicateKey,
+ isList = true,
+ isInputField,
+}: IOKeyPairInputProps) => {
+ const checkValueType = (value) => {
+ return Array.isArray(value) ? value : [value];
+ };
+
+ const ref = useRef([]);
+ ref.current =
+ !value || value?.length === 0 ? [{ "": "" }] : checkValueType(value);
+
+ const handleChangeKey = (event, idx) => {
+ const oldKey = Object.keys(ref.current[idx])[0];
+ const updatedObj = { [event.target.value]: ref.current[idx][oldKey] };
+ ref.current[idx] = updatedObj;
+ onChange(ref.current);
+ };
+
+ const handleChangeValue = (newValue, idx) => {
+ const key = Object.keys(ref.current[idx])[0];
+ ref.current[idx][key] = newValue;
+ onChange(ref.current);
+ };
+
+ return (
+ <>
+
+ >
+ );
+};
+
+export default IOKeyPairInput;
diff --git a/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx b/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx
index dd02d19ca..36d8be382 100644
--- a/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx
+++ b/src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx
@@ -1,6 +1,8 @@
import { cloneDeep } from "lodash";
+import { useState } from "react";
import ImageViewer from "../../../../components/ImageViewer";
import CsvOutputComponent from "../../../../components/csvOutputComponent";
+import InputListComponent from "../../../../components/inputListComponent";
import PdfViewer from "../../../../components/pdfViewer";
import {
Select,
@@ -15,7 +17,13 @@ import { PDFViewConstant } from "../../../../constants/constants";
import { InputOutput } from "../../../../constants/enums";
import useFlowStore from "../../../../stores/flowStore";
import { IOFieldViewProps } from "../../../../types/components";
+import {
+ convertValuesToNumbers,
+ hasDuplicateKeys,
+} from "../../../../utils/reactflowUtils";
import IOFileInput from "./components/FileInput";
+import IoJsonInput from "./components/JSONInput";
+import IOKeyPairInput from "./components/keyPairInput";
export default function IOFieldView({
type,
@@ -39,6 +47,7 @@ export default function IOFieldView({
}
}
};
+ const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
function handleOutputType() {
if (!node) return <>"No node found!">;
@@ -78,6 +87,57 @@ export default function IOFieldView({
/>
);
+ case "KeyPairInput":
+ return (
+ {
+ if (node) {
+ let newNode = cloneDeep(node);
+ newNode.data.node!.template["input_value"].value = e;
+ setNode(node.id, newNode);
+ }
+ const valueToNumbers = convertValuesToNumbers(e);
+ setErrorDuplicateKey(hasDuplicateKeys(valueToNumbers));
+ }}
+ duplicateKey={errorDuplicateKey}
+ isList={node.data.node!.template["input_value"]?.list ?? false}
+ isInputField
+ />
+ );
+
+ case "JsonInput":
+ return (
+ {
+ if (node) {
+ let newNode = cloneDeep(node);
+ newNode.data.node!.template["input_value"].value = e;
+ setNode(node.id, newNode);
+ }
+ }}
+ left={left}
+ />
+ );
+
+ case "StringListInput":
+ return (
+ <>
+ {
+ if (node) {
+ let newNode = cloneDeep(node);
+ newNode.data.node!.template["input_value"].value = e;
+ setNode(node.id, newNode);
+ }
+ }}
+ disabled={false}
+ />
+ >
+ );
+
default:
return (
);
+ case "JsonOutput":
+ return (
+ {
+ if (node) {
+ let newNode = cloneDeep(node);
+ newNode.data.node!.template["input_value"].value = e;
+ setNode(node.id, newNode);
+ }
+ }}
+ left={left}
+ output
+ />
+ );
+
+ case "KeyPairOutput":
+ return (
+ {
+ if (node) {
+ let newNode = cloneDeep(node);
+ newNode.data.node!.template["input_value"].value = e;
+ setNode(node.id, newNode);
+ }
+ const valueToNumbers = convertValuesToNumbers(e);
+ setErrorDuplicateKey(hasDuplicateKeys(valueToNumbers));
+ }}
+ duplicateKey={errorDuplicateKey}
+ isList={node.data.node!.template["input_value"]?.list ?? false}
+ />
+ );
+
+ case "StringListOutput":
+ return (
+ <>
+ {
+ if (node) {
+ let newNode = cloneDeep(node);
+ newNode.data.node!.template["input_value"].value = e;
+ setNode(node.id, newNode);
+ }
+ }}
+ playgroundDisabled
+ disabled={false}
+ />
+ >
+ );
+
default:
return (