✨ (StringListInput.py): add a new custom component called "StringListInput" to handle string list inputs
✨ (KeyPairOutput.py): add a new custom component called "KeyPairOutput" to handle dictionary outputs ✨ (StringListOutput.py): add a new custom component called "StringListOutput" to handle string list outputs 🚀 (constants.ts): add "StringListInput" and "StringListOutput" to the list of supported input and output types ♻️ (index.tsx): refactor IOKeyPairInput component to accept an additional prop "isInputField" and disable input fields if it's false ♻️ (index.tsx): refactor IOFieldView component to handle rendering of "StringListInput" and "StringListOutput" components
This commit is contained in:
parent
b06501a4c9
commit
edabb31112
6 changed files with 92 additions and 3 deletions
|
|
@ -0,0 +1,13 @@
|
||||||
|
# from langflow.field_typing import Data
|
||||||
|
from langflow.schema import Record
|
||||||
|
from langflow.interface.custom.custom_component import CustomComponent
|
||||||
|
|
||||||
|
|
||||||
|
class StringListInput(CustomComponent):
|
||||||
|
display_name = "String List Input"
|
||||||
|
|
||||||
|
def build_config(self):
|
||||||
|
return {"param": {"display_name": "String List Input", "field_type": "str", "list": True}}
|
||||||
|
|
||||||
|
def build(self, param: list) -> Record:
|
||||||
|
return Record(data=param)
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
from langflow.base.io.text import TextComponent
|
||||||
|
from langflow.field_typing.constants import Data
|
||||||
|
|
||||||
|
|
||||||
|
class KeyPairOutput(TextComponent):
|
||||||
|
display_name = "Dictionary Output"
|
||||||
|
description = "Dictionary Output."
|
||||||
|
|
||||||
|
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
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
# from langflow.field_typing import Data
|
||||||
|
from langflow.schema import Record
|
||||||
|
from langflow.interface.custom.custom_component import CustomComponent
|
||||||
|
|
||||||
|
|
||||||
|
class StringListOutput(CustomComponent):
|
||||||
|
display_name = "String List Output"
|
||||||
|
|
||||||
|
def build_config(self):
|
||||||
|
return {"param": {"display_name": "String List Output", "field_type": "str", "list": True}}
|
||||||
|
|
||||||
|
def build(self, param: list) -> Record:
|
||||||
|
return Record(data=param)
|
||||||
|
|
@ -716,6 +716,7 @@ export const INPUT_TYPES = new Set([
|
||||||
"TextInput",
|
"TextInput",
|
||||||
"KeyPairInput",
|
"KeyPairInput",
|
||||||
"JsonInput",
|
"JsonInput",
|
||||||
|
"StringListInput",
|
||||||
]);
|
]);
|
||||||
export const OUTPUT_TYPES = new Set([
|
export const OUTPUT_TYPES = new Set([
|
||||||
"ChatOutput",
|
"ChatOutput",
|
||||||
|
|
@ -724,6 +725,8 @@ export const OUTPUT_TYPES = new Set([
|
||||||
"ImageOutput",
|
"ImageOutput",
|
||||||
"CSVOutput",
|
"CSVOutput",
|
||||||
"JsonOutput",
|
"JsonOutput",
|
||||||
|
"KeyPairOutput",
|
||||||
|
"StringListOutput",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const CHAT_FIRST_INITIAL_TEXT =
|
export const CHAT_FIRST_INITIAL_TEXT =
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,21 @@ import IconComponent from "../../../../../../components/genericIconComponent";
|
||||||
import { Input } from "../../../../../../components/ui/input";
|
import { Input } from "../../../../../../components/ui/input";
|
||||||
import { classNames } from "../../../../../../utils/utils";
|
import { classNames } from "../../../../../../utils/utils";
|
||||||
|
|
||||||
const IOKeyPairInput = ({ value, onChange, duplicateKey, isList = true }) => {
|
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) => {
|
const checkValueType = (value) => {
|
||||||
return Array.isArray(value) ? value : [value];
|
return Array.isArray(value) ? value : [value];
|
||||||
};
|
};
|
||||||
|
|
@ -39,6 +53,7 @@ const IOKeyPairInput = ({ value, onChange, duplicateKey, isList = true }) => {
|
||||||
className={classNames(duplicateKey ? "input-invalid" : "")}
|
className={classNames(duplicateKey ? "input-invalid" : "")}
|
||||||
placeholder="Type key..."
|
placeholder="Type key..."
|
||||||
onChange={(event) => handleChangeKey(event, index)}
|
onChange={(event) => handleChangeKey(event, index)}
|
||||||
|
disabled={!isInputField}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -48,9 +63,10 @@ const IOKeyPairInput = ({ value, onChange, duplicateKey, isList = true }) => {
|
||||||
onChange={(event) =>
|
onChange={(event) =>
|
||||||
handleChangeValue(event.target.value, index)
|
handleChangeValue(event.target.value, index)
|
||||||
}
|
}
|
||||||
|
disabled={!isInputField}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{isList && index === ref.current.length - 1 ? (
|
{isList && isInputField && index === ref.current.length - 1 ? (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
let newInputList = _.cloneDeep(ref.current);
|
let newInputList = _.cloneDeep(ref.current);
|
||||||
|
|
@ -63,7 +79,7 @@ const IOKeyPairInput = ({ value, onChange, duplicateKey, isList = true }) => {
|
||||||
className={"h-4 w-4 hover:text-accent-foreground"}
|
className={"h-4 w-4 hover:text-accent-foreground"}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
) : isList ? (
|
) : isList && isInputField ? (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
let newInputList = _.cloneDeep(ref.current);
|
let newInputList = _.cloneDeep(ref.current);
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ export default function IOFieldView({
|
||||||
}}
|
}}
|
||||||
duplicateKey={errorDuplicateKey}
|
duplicateKey={errorDuplicateKey}
|
||||||
isList={node.data.node!.template["input_value"]?.list ?? false}
|
isList={node.data.node!.template["input_value"]?.list ?? false}
|
||||||
|
isInputField
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -119,6 +120,9 @@ export default function IOFieldView({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case "StringListInput":
|
||||||
|
return <>diusahjduisahudsa</>;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<Textarea
|
<Textarea
|
||||||
|
|
@ -226,6 +230,27 @@ export default function IOFieldView({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case "KeyPairOutput":
|
||||||
|
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 "StringListOutput":
|
||||||
|
return <>diusahjduisahudsa</>;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<Textarea
|
<Textarea
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue