✨ (JsonInput.py): add a new component called "JsonInput" to handle JSON input data in the language flow system
✨ (KeyPairInput.py): add a new component called "KeyPairInput" to handle dictionary input data in the language flow system ✨ (CSVOutput.py): add a new component called "CSVOutput" to handle CSV output data in the language flow system ✨ (ImageOutput.py): add a new component called "ImageOutput" to handle image output data in the language flow system ✨ (JsonOutput.py): add a new component called "JsonOutput" to handle JSON output data in the language flow system ✨ (PDFOutput.py): add a new component called "PDFOutput" to handle PDF output data in the language flow system 📝 (App.css): update CSS to improve readability and formatting 📝 (parameterComponent/index.tsx): fix a bug where rangeSpec is not properly accessed in the FloatComponent 📝 (cardComponent/index.tsx): update the CollectionCardComponent to include a new button for opening the playground and handle the opening and closing of the IOModal 📝 (codeTabsComponent/index.tsx): fix conditional rendering of InputListComponent by using optional chaining operator to check if the list property exists in the template object 📝 (keypairListComponent/index.tsx): refactor the initialization of the ref variable to handle both empty and non-empty values correctly 📝 (constants.ts): add "JsonInput" and "JsonOutput" to the INPUT_TYPES and OUTPUT_TYPES constants to support JSON input and output components 📝 (editNodeModal/index.tsx): fix conditional rendering of InputListComponent by using optional chaining operator to check if the list property exists in the template object 📝 (ioFieldView/components/JSONInput/index.tsx): add JSONInput component to handle JSON input in the IOFieldView component 📝 (ioFieldView/components/keyPairInput/index.tsx): add keyPairInput component to handle key-value pair input in the IOFieldView component ✨ (IOFieldView/index.tsx): add useState import to use state hook in functional component ✨ (IOFieldView/index.tsx): add support for KeyPairInput component in IOFieldView ✨ (IOFieldView/index.tsx): add support for JsonInput component in IOFieldView ✨ (IOFieldView/index.tsx): add support for JsonOutput component in IOFieldView 📝 (dictAreaModal/index.tsx): add useDarkStore import to use dark mode state in DictAreaModal component 📝 (classes.css): add CSS classes for json-view component in different themes 📝 (types/components/index.ts): remove duplicate InputGlobalComponentType definition
This commit is contained in:
parent
9055eb0bc9
commit
b06501a4c9
19 changed files with 386 additions and 39 deletions
17
src/backend/base/langflow/components/inputs/JsonInput.py
Normal file
17
src/backend/base/langflow/components/inputs/JsonInput.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
from langflow.base.io.text import TextComponent
|
||||||
|
from langflow.field_typing.constants import Data, NestedDict
|
||||||
|
|
||||||
|
class JsonInput(TextComponent):
|
||||||
|
display_name = "JSON Input"
|
||||||
|
description = "JSON Input."
|
||||||
|
|
||||||
|
def build_config(self):
|
||||||
|
return {
|
||||||
|
"input_value": {
|
||||||
|
"display_name": "JSON",
|
||||||
|
"field_type": "NestedDict"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def build(self, input_value: NestedDict) -> NestedDict:
|
||||||
|
return input_value
|
||||||
19
src/backend/base/langflow/components/inputs/KeyPairInput.py
Normal file
19
src/backend/base/langflow/components/inputs/KeyPairInput.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
from langflow.base.io.text import TextComponent
|
||||||
|
from langflow.field_typing.constants import Data
|
||||||
|
|
||||||
|
|
||||||
|
class KeyPairInput(TextComponent):
|
||||||
|
display_name = "Dictionary Input"
|
||||||
|
description = "Dictionary Input."
|
||||||
|
|
||||||
|
def build_config(self):
|
||||||
|
return {
|
||||||
|
"input_value": {
|
||||||
|
"display_name": "Dictionaries",
|
||||||
|
"field_type": "dict",
|
||||||
|
"list": True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def build(self, input_value: dict) -> dict:
|
||||||
|
return input_value
|
||||||
17
src/backend/base/langflow/components/outputs/CSVOutput.py
Normal file
17
src/backend/base/langflow/components/outputs/CSVOutput.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from langflow.base.io.text import TextComponent
|
||||||
|
from langflow.field_typing import Text, Data
|
||||||
|
|
||||||
|
|
||||||
|
class CSVOutput(TextComponent):
|
||||||
|
display_name = "CSV Output"
|
||||||
|
description = "Used view csv files"
|
||||||
|
|
||||||
|
field_config = {
|
||||||
|
"input_value": {"display_name": "csv","info":"A csv blob","input_types":["Data"]},
|
||||||
|
"separator": {"display_name": "separator","info":"The separator used in the csv file","input_types":["Text"], "field_type":"Text","default_value":";","options":[";", ",", "|"]},
|
||||||
|
}
|
||||||
|
|
||||||
|
def build(self, input_value: Data, separator) -> Data:
|
||||||
|
return {"data": input_value, "separator": separator}
|
||||||
15
src/backend/base/langflow/components/outputs/ImageOutput.py
Normal file
15
src/backend/base/langflow/components/outputs/ImageOutput.py
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from langflow.base.io.text import TextComponent
|
||||||
|
from langflow.field_typing import Text
|
||||||
|
|
||||||
|
class ImageOutput(TextComponent):
|
||||||
|
display_name = "Image Output"
|
||||||
|
description = "Used view image files"
|
||||||
|
|
||||||
|
field_config = {
|
||||||
|
"input_value": {"display_name": "image","info":"A image url","input_types":["Text"]},
|
||||||
|
}
|
||||||
|
|
||||||
|
def build(self, input_value: Text) -> Text:
|
||||||
|
return input_value
|
||||||
17
src/backend/base/langflow/components/outputs/JsonOutput.py
Normal file
17
src/backend/base/langflow/components/outputs/JsonOutput.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
from langflow.base.io.text import TextComponent
|
||||||
|
from langflow.field_typing.constants import Data, NestedDict
|
||||||
|
|
||||||
|
class JsonOutput(TextComponent):
|
||||||
|
display_name = "JSON Output"
|
||||||
|
description = "JSON Output."
|
||||||
|
|
||||||
|
def build_config(self):
|
||||||
|
return {
|
||||||
|
"input_value": {
|
||||||
|
"display_name": "JSON",
|
||||||
|
"field_type": "NestedDict"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def build(self, input_value: NestedDict) -> NestedDict:
|
||||||
|
return input_value
|
||||||
16
src/backend/base/langflow/components/outputs/PDFOutput.py
Normal file
16
src/backend/base/langflow/components/outputs/PDFOutput.py
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from langflow.base.io.text import TextComponent
|
||||||
|
from langflow.field_typing import Text
|
||||||
|
|
||||||
|
|
||||||
|
class PDFOutput(TextComponent):
|
||||||
|
display_name = "PDF Output"
|
||||||
|
description = "Used view pdf files"
|
||||||
|
|
||||||
|
field_config = {
|
||||||
|
"input_value": {"display_name": "pdf","info":"A pdf url","input_types":["Text"]},
|
||||||
|
}
|
||||||
|
|
||||||
|
def build(self, input_value: Text) -> Text:
|
||||||
|
return input_value
|
||||||
|
|
@ -96,6 +96,18 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-hover:hover {
|
.custom-hover:hover {
|
||||||
background-color: rgba(99, 102, 241, 0.1); /* Medium indigo color with 20% opacity */
|
background-color: rgba(
|
||||||
|
99,
|
||||||
|
102,
|
||||||
|
241,
|
||||||
|
0.1
|
||||||
|
); /* Medium indigo color with 20% opacity */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.json-view-playground .json-view {
|
||||||
|
background-color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-view-flow .json-view {
|
||||||
|
background-color: #bbb !important;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -618,7 +618,7 @@ export default function ParameterComponent({
|
||||||
<FloatComponent
|
<FloatComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node?.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
rangeSpec={data.node?.template[name].rangeSpec}
|
rangeSpec={data.node?.template[name]?.rangeSpec}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { getComponent, postLikeComponent } from "../../controllers/API";
|
import { getComponent, postLikeComponent } from "../../controllers/API";
|
||||||
import DeleteConfirmationModal from "../../modals/DeleteConfirmationModal";
|
import DeleteConfirmationModal from "../../modals/DeleteConfirmationModal";
|
||||||
|
import IOModal from "../../modals/IOModal";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
|
import useFlowStore from "../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
import { useStoreStore } from "../../stores/storeStore";
|
import { useStoreStore } from "../../stores/storeStore";
|
||||||
import { storeComponent } from "../../types/store";
|
import { storeComponent } from "../../types/store";
|
||||||
|
|
@ -18,8 +20,6 @@ import {
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "../ui/card";
|
} from "../ui/card";
|
||||||
import IOModal from "../../modals/IOModal";
|
|
||||||
import useFlowStore from "../../stores/flowStore";
|
|
||||||
|
|
||||||
export default function CollectionCardComponent({
|
export default function CollectionCardComponent({
|
||||||
data,
|
data,
|
||||||
|
|
@ -27,7 +27,7 @@ export default function CollectionCardComponent({
|
||||||
disabled = false,
|
disabled = false,
|
||||||
button,
|
button,
|
||||||
onDelete,
|
onDelete,
|
||||||
playground
|
playground,
|
||||||
}: {
|
}: {
|
||||||
data: storeComponent;
|
data: storeComponent;
|
||||||
authorized?: boolean;
|
authorized?: boolean;
|
||||||
|
|
@ -55,9 +55,9 @@ export default function CollectionCardComponent({
|
||||||
const setNodes = useFlowStore((state) => state.setNodes);
|
const setNodes = useFlowStore((state) => state.setNodes);
|
||||||
const setEdges = useFlowStore((state) => state.setEdges);
|
const setEdges = useFlowStore((state) => state.setEdges);
|
||||||
const [openPlayground, setOpenPlayground] = useState(false);
|
const [openPlayground, setOpenPlayground] = useState(false);
|
||||||
const setCurrentFlowId = useFlowsManagerStore((state) => state.setCurrentFlowId);
|
const setCurrentFlowId = useFlowsManagerStore(
|
||||||
|
(state) => state.setCurrentFlowId
|
||||||
|
);
|
||||||
|
|
||||||
const name = data.is_component ? "Component" : "Flow";
|
const name = data.is_component ? "Component" : "Flow";
|
||||||
|
|
||||||
|
|
@ -86,16 +86,18 @@ export default function CollectionCardComponent({
|
||||||
addFlow(true, newFlow)
|
addFlow(true, newFlow)
|
||||||
.then((id) => {
|
.then((id) => {
|
||||||
setSuccessData({
|
setSuccessData({
|
||||||
title: `${name} ${isStore ? "Downloaded" : "Installed"
|
title: `${name} ${
|
||||||
} Successfully.`,
|
isStore ? "Downloaded" : "Installed"
|
||||||
|
} Successfully.`,
|
||||||
});
|
});
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setErrorData({
|
setErrorData({
|
||||||
title: `Error ${isStore ? "downloading" : "installing"
|
title: `Error ${
|
||||||
} the ${name}`,
|
isStore ? "downloading" : "installing"
|
||||||
|
} the ${name}`,
|
||||||
list: [error["response"]["data"]["detail"]],
|
list: [error["response"]["data"]["detail"]],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -362,15 +364,13 @@ export default function CollectionCardComponent({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{button && button}
|
{button && button}
|
||||||
{playground &&
|
{playground && (
|
||||||
<Button
|
<Button
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="whitespace-nowrap "
|
className="whitespace-nowrap "
|
||||||
data-testid={
|
data-testid={"playground-flow-button-" + data.id}
|
||||||
"playground-flow-button-" + data.id
|
|
||||||
}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentFlowId(data.id);
|
setCurrentFlowId(data.id);
|
||||||
setOpenPlayground(true);
|
setOpenPlayground(true);
|
||||||
|
|
@ -381,14 +381,16 @@ export default function CollectionCardComponent({
|
||||||
className="main-page-nav-button select-none"
|
className="main-page-nav-button select-none"
|
||||||
/>
|
/>
|
||||||
Playground
|
Playground
|
||||||
{openPlayground && < IOModal open={openPlayground} setOpen={setOpenPlayground}>
|
{openPlayground && (
|
||||||
<></>
|
<IOModal open={openPlayground} setOpen={setOpenPlayground}>
|
||||||
</IOModal>}
|
<></>
|
||||||
|
</IOModal>
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card >
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ export default function CodeTabsComponent({
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
{node.data.node.template[
|
{node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
].list ? (
|
]?.list ? (
|
||||||
<InputListComponent
|
<InputListComponent
|
||||||
componentName={
|
componentName={
|
||||||
templateField
|
templateField
|
||||||
|
|
@ -745,7 +745,7 @@ export default function CodeTabsComponent({
|
||||||
isList={
|
isList={
|
||||||
node.data.node!.template[
|
node.data.node!.template[
|
||||||
templateField
|
templateField
|
||||||
].list ?? false
|
]?.list ?? false
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,13 @@ export default function KeypairListComponent({
|
||||||
}
|
}
|
||||||
}, [disabled]);
|
}, [disabled]);
|
||||||
|
|
||||||
const ref = useRef(value.length === 0 ? [{ "": "" }] : value);
|
const checkValueType = (value) => {
|
||||||
|
return Array.isArray(value) ? value : [value];
|
||||||
|
};
|
||||||
|
|
||||||
|
const ref = useRef<any>([]);
|
||||||
|
ref.current =
|
||||||
|
!value || value?.length === 0 ? [{ "": "" }] : checkValueType(value);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (JSON.stringify(value) !== JSON.stringify(ref.current)) {
|
if (JSON.stringify(value) !== JSON.stringify(ref.current)) {
|
||||||
|
|
|
||||||
|
|
@ -711,13 +711,19 @@ export const LANGFLOW_SUPPORTED_TYPES = new Set([
|
||||||
|
|
||||||
export const priorityFields = new Set(["code", "template"]);
|
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",
|
||||||
|
]);
|
||||||
export const OUTPUT_TYPES = new Set([
|
export const OUTPUT_TYPES = new Set([
|
||||||
"ChatOutput",
|
"ChatOutput",
|
||||||
"TextOutput",
|
"TextOutput",
|
||||||
"PDFOutput",
|
"PDFOutput",
|
||||||
"ImageOutput",
|
"ImageOutput",
|
||||||
"CSVOutput",
|
"CSVOutput",
|
||||||
|
"JsonOutput",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const CHAT_FIRST_INITIAL_TEXT =
|
export const CHAT_FIRST_INITIAL_TEXT =
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ const EditNodeModal = forwardRef(
|
||||||
!myData.node.template[templateParam].options ? (
|
!myData.node.template[templateParam].options ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
{myData.node.template[templateParam]
|
{myData.node.template[templateParam]
|
||||||
.list ? (
|
?.list ? (
|
||||||
<InputListComponent
|
<InputListComponent
|
||||||
componentName={templateParam}
|
componentName={templateParam}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
|
|
@ -345,7 +345,7 @@ const EditNodeModal = forwardRef(
|
||||||
}}
|
}}
|
||||||
isList={
|
isList={
|
||||||
data.node?.template[templateParam]
|
data.node?.template[templateParam]
|
||||||
.list ?? false
|
?.list ?? false
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -420,6 +420,10 @@ const EditNodeModal = forwardRef(
|
||||||
.type === "int" ? (
|
.type === "int" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<IntComponent
|
<IntComponent
|
||||||
|
rangeSpec={
|
||||||
|
data.node?.template[templateParam]
|
||||||
|
?.rangeSpec
|
||||||
|
}
|
||||||
id={
|
id={
|
||||||
"edit-int-input-" +
|
"edit-int-input-" +
|
||||||
myData.node.template[templateParam].name
|
myData.node.template[templateParam].name
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
import JsonView from "react18-json-view";
|
||||||
|
import { useDarkStore } from "../../../../../../stores/darkStore";
|
||||||
|
import { DictComponentType } from "../../../../../../types/components";
|
||||||
|
|
||||||
|
export default function IoJsonInput({
|
||||||
|
value = [],
|
||||||
|
onChange,
|
||||||
|
left,
|
||||||
|
output,
|
||||||
|
}: DictComponentType): JSX.Element {
|
||||||
|
useEffect(() => {
|
||||||
|
if (value) onChange(value);
|
||||||
|
}, [value]);
|
||||||
|
const isDark = useDarkStore((state) => state.dark);
|
||||||
|
|
||||||
|
const ref = useRef<any>(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 (
|
||||||
|
<div className="w-full">
|
||||||
|
<JsonView
|
||||||
|
className={getClassNames()}
|
||||||
|
theme="vscode"
|
||||||
|
dark={isDark}
|
||||||
|
editable={!output}
|
||||||
|
enableClipboard
|
||||||
|
onEdit={(edit) => {
|
||||||
|
ref.current = edit["src"];
|
||||||
|
}}
|
||||||
|
onChange={(edit) => {
|
||||||
|
ref.current = edit["src"];
|
||||||
|
}}
|
||||||
|
src={ref.current}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useRef } from "react";
|
||||||
|
import IconComponent from "../../../../../../components/genericIconComponent";
|
||||||
|
import { Input } from "../../../../../../components/ui/input";
|
||||||
|
import { classNames } from "../../../../../../utils/utils";
|
||||||
|
|
||||||
|
const IOKeyPairInput = ({ value, onChange, duplicateKey, isList = true }) => {
|
||||||
|
const checkValueType = (value) => {
|
||||||
|
return Array.isArray(value) ? value : [value];
|
||||||
|
};
|
||||||
|
|
||||||
|
const ref = useRef<any>([]);
|
||||||
|
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 (
|
||||||
|
<>
|
||||||
|
<div className={classNames("flex h-full flex-col gap-3")}>
|
||||||
|
{ref.current?.map((obj, index) => {
|
||||||
|
return Object.keys(obj).map((key, idx) => {
|
||||||
|
return (
|
||||||
|
<div key={idx} className="flex w-full gap-2">
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={key.trim()}
|
||||||
|
className={classNames(duplicateKey ? "input-invalid" : "")}
|
||||||
|
placeholder="Type key..."
|
||||||
|
onChange={(event) => handleChangeKey(event, index)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={obj[key]}
|
||||||
|
placeholder="Type a value..."
|
||||||
|
onChange={(event) =>
|
||||||
|
handleChangeValue(event.target.value, index)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isList && index === ref.current.length - 1 ? (
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
let newInputList = _.cloneDeep(ref.current);
|
||||||
|
newInputList.push({ "": "" });
|
||||||
|
onChange(newInputList);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconComponent
|
||||||
|
name="Plus"
|
||||||
|
className={"h-4 w-4 hover:text-accent-foreground"}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
) : isList ? (
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
let newInputList = _.cloneDeep(ref.current);
|
||||||
|
newInputList.splice(index, 1);
|
||||||
|
onChange(newInputList);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconComponent
|
||||||
|
name="X"
|
||||||
|
className="h-4 w-4 hover:text-status-red"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default IOKeyPairInput;
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
|
import { useState } from "react";
|
||||||
import ImageViewer from "../../../../components/ImageViewer";
|
import ImageViewer from "../../../../components/ImageViewer";
|
||||||
import CsvOutputComponent from "../../../../components/csvOutputComponent";
|
import CsvOutputComponent from "../../../../components/csvOutputComponent";
|
||||||
import PdfViewer from "../../../../components/pdfViewer";
|
import PdfViewer from "../../../../components/pdfViewer";
|
||||||
|
|
@ -15,7 +16,13 @@ import { PDFViewConstant } from "../../../../constants/constants";
|
||||||
import { InputOutput } from "../../../../constants/enums";
|
import { InputOutput } from "../../../../constants/enums";
|
||||||
import useFlowStore from "../../../../stores/flowStore";
|
import useFlowStore from "../../../../stores/flowStore";
|
||||||
import { IOFieldViewProps } from "../../../../types/components";
|
import { IOFieldViewProps } from "../../../../types/components";
|
||||||
|
import {
|
||||||
|
convertValuesToNumbers,
|
||||||
|
hasDuplicateKeys,
|
||||||
|
} from "../../../../utils/reactflowUtils";
|
||||||
import IOFileInput from "./components/FileInput";
|
import IOFileInput from "./components/FileInput";
|
||||||
|
import IoJsonInput from "./components/JSONInput";
|
||||||
|
import IOKeyPairInput from "./components/keyPairInput";
|
||||||
|
|
||||||
export default function IOFieldView({
|
export default function IOFieldView({
|
||||||
type,
|
type,
|
||||||
|
|
@ -39,6 +46,7 @@ export default function IOFieldView({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||||
|
|
||||||
function handleOutputType() {
|
function handleOutputType() {
|
||||||
if (!node) return <>"No node found!"</>;
|
if (!node) return <>"No node found!"</>;
|
||||||
|
|
@ -78,6 +86,39 @@ export default function IOFieldView({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case "KeyPairInput":
|
||||||
|
return (
|
||||||
|
<IOKeyPairInput
|
||||||
|
value={node.data.node!.template["input_value"]?.value}
|
||||||
|
onChange={(e) => {
|
||||||
|
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 "JsonInput":
|
||||||
|
return (
|
||||||
|
<IoJsonInput
|
||||||
|
value={node.data.node!.template["input_value"]?.value}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (node) {
|
||||||
|
let newNode = cloneDeep(node);
|
||||||
|
newNode.data.node!.template["input_value"].value = e;
|
||||||
|
setNode(node.id, newNode);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
left={left}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<Textarea
|
<Textarea
|
||||||
|
|
@ -169,6 +210,22 @@ export default function IOFieldView({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case "JsonOutput":
|
||||||
|
return (
|
||||||
|
<IoJsonInput
|
||||||
|
value={node.data.node!.template["input_value"]?.value}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (node) {
|
||||||
|
let newNode = cloneDeep(node);
|
||||||
|
newNode.data.node!.template["input_value"].value = e;
|
||||||
|
setNode(node.id, newNode);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
left={left}
|
||||||
|
output
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<Textarea
|
<Textarea
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import "react18-json-view/src/style.css";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { CODE_DICT_DIALOG_SUBTITLE } from "../../constants/constants";
|
import { CODE_DICT_DIALOG_SUBTITLE } from "../../constants/constants";
|
||||||
|
import { useDarkStore } from "../../stores/darkStore";
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
|
|
||||||
export default function DictAreaModal({
|
export default function DictAreaModal({
|
||||||
|
|
@ -19,7 +20,7 @@ export default function DictAreaModal({
|
||||||
value,
|
value,
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const isDark = useDarkStore((state) => state.dark);
|
||||||
const ref = useRef(value);
|
const ref = useRef(value);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -41,7 +42,8 @@ export default function DictAreaModal({
|
||||||
<div className="flex h-full w-full flex-col transition-all ">
|
<div className="flex h-full w-full flex-col transition-all ">
|
||||||
<JsonView
|
<JsonView
|
||||||
theme="vscode"
|
theme="vscode"
|
||||||
dark={true}
|
dark={isDark}
|
||||||
|
className={!isDark ? "json-view-white" : "json-view-dark"}
|
||||||
editable
|
editable
|
||||||
enableClipboard
|
enableClipboard
|
||||||
onEdit={(edit) => {
|
onEdit={(edit) => {
|
||||||
|
|
|
||||||
|
|
@ -68,3 +68,31 @@ select:-webkit-autofill:focus {
|
||||||
background-color: #bbb;
|
background-color: #bbb;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.json-view-playground-white-left {
|
||||||
|
background-color: #fff !important;
|
||||||
|
height: fit-content !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-view-playground-dark {
|
||||||
|
background-color: #141924 !important;
|
||||||
|
height: fit-content !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-view-playground-white {
|
||||||
|
background-color: #f8fafc !important;
|
||||||
|
height: fit-content !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-view-playground-dark-left {
|
||||||
|
background-color: #0c101a !important;
|
||||||
|
height: fit-content !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-view-white {
|
||||||
|
background-color: #f8fafc !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-view-dark {
|
||||||
|
background-color: #141924 !important;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,15 +80,6 @@ export type InputGlobalComponentType = {
|
||||||
editNode?: boolean;
|
editNode?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InputGlobalComponentType = {
|
|
||||||
disabled: boolean;
|
|
||||||
onChange: (value: string) => void;
|
|
||||||
setDb: (value: boolean) => void;
|
|
||||||
name: string;
|
|
||||||
data: NodeDataType;
|
|
||||||
editNode?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type KeyPairListComponentType = {
|
export type KeyPairListComponentType = {
|
||||||
value: any;
|
value: any;
|
||||||
onChange: (value: Object[]) => void;
|
onChange: (value: Object[]) => void;
|
||||||
|
|
@ -102,9 +93,11 @@ export type KeyPairListComponentType = {
|
||||||
export type DictComponentType = {
|
export type DictComponentType = {
|
||||||
value: any;
|
value: any;
|
||||||
onChange: (value) => void;
|
onChange: (value) => void;
|
||||||
disabled: boolean;
|
disabled?: boolean;
|
||||||
editNode?: boolean;
|
editNode?: boolean;
|
||||||
id?: string;
|
id?: string;
|
||||||
|
left?: boolean;
|
||||||
|
output?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TextAreaComponentType = {
|
export type TextAreaComponentType = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue