✨ (codeTabsComponent/index.tsx): add support for exporting code as a file
♻️ (codeTabsComponent/index.tsx): refactor code to use a switch statement instead of multiple if conditions for different template field types 🔧 (codeTabsComponent/index.tsx): fix import statements and remove unused imports 📝 (codeTabsComponent/index.tsx): add comments to improve code readability 📝 (codeTabsComponent/index.tsx): refactor code to use a switch statement instead of multiple if-else conditions for better readability and maintainability ♻️ (codeTabsComponent/index.tsx): refactor code to use a Case component for each condition in the switch statement to improve code organization and readability ✨ (index.tsx): remove unused import of React from "react" to improve code cleanliness ♻️ (index.tsx): refactor code to remove unused imports and variables, improve code readability and organization 📝 (index.tsx): add missing import of Case component from "../../../../shared/components/caseComponent" 🔧 (index.tsx): add missing import of TooltipRenderComponent from "../tooltipRenderComponent" ✅ (index.tsx): add missing hooks and functions to improve code functionality and maintainability 📝 (index.tsx): Refactor code to improve readability and maintainability 📝 (index.tsx): refactor the rendering logic in the ParameterComponent to improve readability and maintainability 🔧 (index.tsx): fix access to nested properties in the data object by using optional chaining operator (?.) to prevent potential errors when accessing undefined properties ✨ (tooltipRenderComponent): add a new component for rendering tooltips in the genericNode component 📝 (use-fetch-data-on-mount): add a new hook for fetching data on component mount 📝 (use-handle-new-value): add a new hook for handling new values in the component 📝 (use-handle-node-class): add a new hook for handling node class in the component 📝 (use-handle-refresh-buttons): add a new hook for handling refresh button press in the component ✨ (editNodeModal/index.tsx): import Case component to handle conditional rendering of different input components based on template type 📝 (editNodeModal/index.tsx): add comments to explain the purpose of the code and provide context for future developers ♻️ (editNodeModal/index.tsx): refactor code to use the Case component for conditional rendering instead of multiple if statements 📝 (file.js): update code formatting and indentation for better readability 📝 (editNodeModal/index.tsx): update code to fix a bug related to accessing nested properties in myData.node object ♻️ (editNodeModal/index.tsx): refactor code to use conditional rendering with Case component for better readability and maintainability ✨ (caseComponent/index.tsx): add a new component called Case that conditionally renders its children based on a given condition 📝 (components/index.ts): add an optional display_name property to the groupedObjType interface ♻️ (components/index.ts): remove unnecessary commas and fix indentation in the codeTabsPropsType interface 🐛 (reactflowUtils.ts): remove unused parameter 'edges' in isValidConnection function ♻️ (reactflowUtils.ts): refactor scapeJSONParse and scapeJSONStringfy functions to remove unnecessary exclamation marks 🐛 (reactflowUtils.ts): fix bug in updateIds function where it doesn't update the sourceHandle and targetHandle correctly 🐛 (reactflowUtils.ts): fix bug in validateNode function where it doesn't handle empty keys correctly 🐛 (reactflowUtils.ts): fix bug in validateNode function where it doesn't handle duplicate keys correctly 🐛 (reactflowUtils.ts): fix bug in validateNode function where it doesn't handle dict type correctly 🐛 (reactflowUtils.ts): fix bug in validateNodes function where it doesn't handle empty nodes correctly 🐛 (reactflowUtils.ts): fix bug in updateEdges function where it doesn't update the className correctly 🐛 (reactflowUtils.ts): fix bug in handleKeyDown function where it doesn't handle control+backspace on Windows/Linux correctly 🐛 (reactflowUtils.ts): fix bug in handleOnlyIntegerInput function where it doesn't handle decimal point correctly 🐛 (reactflowUtils.ts): fix bug in getConnectedNodes function where it doesn't return the correct connected nodes 🐛 (reactflowUtils.ts): fix bug in convertObjToArray function where it doesn't handle non-dict type correctly 🐛 (reactflowUtils.ts): fix bug in generateFlow function where it doesn't filter out edges correctly 🐛 (reactflowUtils.ts): fix bug in reconnectEdges function where it doesn't update the sourceHandle correctly 🐛 (reactflowUtils.ts): fix bug in filterFlow function where it doesn't filter out nodes and edges correctly 🐛 (reactflowUtils.ts): fix bug in validateSelection function where it doesn't handle selection mode correctly 📝 (reactflowUtils.ts): remove trailing commas and unnecessary whitespace to improve code readability and consistency ♻️ (reactflowUtils.ts): refactor validateSelection function to remove duplicate code and improve readability ♻️ (reactflowUtils.ts): refactor generateNodeTemplate function to simplify code and improve readability ♻️ (reactflowUtils.ts): refactor isHandleConnected function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor generateNodeFromFlow function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor connectedInputNodesOnHandle function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor updateProxyIdsOnTemplate function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor updateEdgesIds function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor expandGroupNode function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor getGroupStatus function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor createFlowComponent function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor updateComponentNameAndType function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor removeFileNameFromComponents function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor extractFieldsFromComponenents function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor downloadFlow function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor downloadFlows function to remove unnecessary parentheses and improve readability ♻️ (reactflowUtils.ts): refactor createNewFlow function to remove unnecessary parentheses and improve readability
This commit is contained in:
parent
c4e60d71bc
commit
8a4a346736
11 changed files with 791 additions and 541 deletions
|
|
@ -26,6 +26,8 @@ import {
|
||||||
TabsTrigger,
|
TabsTrigger,
|
||||||
} from "../../components/ui/tabs";
|
} from "../../components/ui/tabs";
|
||||||
import { LANGFLOW_SUPPORTED_TYPES } from "../../constants/constants";
|
import { LANGFLOW_SUPPORTED_TYPES } from "../../constants/constants";
|
||||||
|
import ExportModal from "../../modals/exportModal";
|
||||||
|
import { Case } from "../../shared/components/caseComponent";
|
||||||
import { useDarkStore } from "../../stores/darkStore";
|
import { useDarkStore } from "../../stores/darkStore";
|
||||||
import useFlowStore from "../../stores/flowStore";
|
import useFlowStore from "../../stores/flowStore";
|
||||||
import { codeTabsPropsType } from "../../types/components";
|
import { codeTabsPropsType } from "../../types/components";
|
||||||
|
|
@ -43,7 +45,6 @@ import KeypairListComponent from "../keypairListComponent";
|
||||||
import ShadTooltip from "../shadTooltipComponent";
|
import ShadTooltip from "../shadTooltipComponent";
|
||||||
import { Label } from "../ui/label";
|
import { Label } from "../ui/label";
|
||||||
import { Switch } from "../ui/switch";
|
import { Switch } from "../ui/switch";
|
||||||
import ExportModal from "../../modals/exportModal";
|
|
||||||
|
|
||||||
export default function CodeTabsComponent({
|
export default function CodeTabsComponent({
|
||||||
flow,
|
flow,
|
||||||
|
|
@ -87,6 +88,10 @@ export default function CodeTabsComponent({
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const type = (node, templateParam) => {
|
||||||
|
return node.data.node.template[templateParam].type;
|
||||||
|
};
|
||||||
|
|
||||||
const downloadAsFile = () => {
|
const downloadAsFile = () => {
|
||||||
const fileExtension = tabs[activeTab].language || ".txt";
|
const fileExtension = tabs[activeTab].language || ".txt";
|
||||||
const suggestedFileName = `${"generated-code."}${fileExtension}`;
|
const suggestedFileName = `${"generated-code."}${fileExtension}`;
|
||||||
|
|
@ -276,107 +281,71 @@ export default function CodeTabsComponent({
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="p-0 text-xs text-foreground">
|
<TableCell className="p-0 text-xs text-foreground">
|
||||||
<div className="m-auto w-[250px]">
|
<div className="m-auto w-[250px]">
|
||||||
{node.data.node.template[
|
<Case
|
||||||
templateField
|
condition={
|
||||||
].type === "str" &&
|
type(node, templateField) ===
|
||||||
!node.data.node.template[
|
"str" &&
|
||||||
templateField
|
!node.data.node.template[
|
||||||
].options ? (
|
|
||||||
<div className="mx-auto">
|
|
||||||
{node.data.node.template[
|
|
||||||
templateField
|
templateField
|
||||||
]?.list ? (
|
].options
|
||||||
<InputListComponent
|
}
|
||||||
componentName={
|
>
|
||||||
templateField
|
<Case
|
||||||
}
|
condition={
|
||||||
editNode={true}
|
node.data.node.template[
|
||||||
disabled={false}
|
|
||||||
value={
|
|
||||||
!node.data.node.template[
|
|
||||||
templateField
|
|
||||||
].value ||
|
|
||||||
node.data.node.template[
|
|
||||||
templateField
|
|
||||||
].value === ""
|
|
||||||
? [""]
|
|
||||||
: node.data.node
|
|
||||||
.template[
|
|
||||||
templateField
|
|
||||||
].value
|
|
||||||
}
|
|
||||||
onChange={(target) => {
|
|
||||||
setData((old) => {
|
|
||||||
let newInputList =
|
|
||||||
cloneDeep(old);
|
|
||||||
newInputList![
|
|
||||||
i
|
|
||||||
].data.node.template[
|
|
||||||
templateField
|
|
||||||
].value = target;
|
|
||||||
return newInputList;
|
|
||||||
});
|
|
||||||
tweaks?.buildTweakObject!(
|
|
||||||
node["data"]["id"],
|
|
||||||
target,
|
|
||||||
node.data.node.template[
|
|
||||||
templateField
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : node.data.node.template[
|
|
||||||
templateField
|
templateField
|
||||||
].multiline ? (
|
]?.list
|
||||||
<div>
|
}
|
||||||
<TextAreaComponent
|
>
|
||||||
disabled={false}
|
<InputListComponent
|
||||||
editNode={true}
|
componentName={templateField}
|
||||||
value={
|
editNode={true}
|
||||||
!node.data.node
|
disabled={false}
|
||||||
.template[
|
value={
|
||||||
|
!node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value ||
|
||||||
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
|
? [""]
|
||||||
|
: node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
].value ||
|
].value
|
||||||
node.data.node.template[
|
}
|
||||||
templateField
|
onChange={(target) => {
|
||||||
].value === ""
|
setData((old) => {
|
||||||
? ""
|
let newInputList =
|
||||||
: node.data.node
|
cloneDeep(old);
|
||||||
.template[
|
newInputList![
|
||||||
templateField
|
i
|
||||||
].value
|
].data.node.template[
|
||||||
}
|
templateField
|
||||||
onChange={(target) => {
|
].value = target;
|
||||||
setData((old) => {
|
return newInputList;
|
||||||
let newInputList =
|
});
|
||||||
cloneDeep(old);
|
tweaks?.buildTweakObject!(
|
||||||
newInputList![
|
node["data"]["id"],
|
||||||
i
|
target,
|
||||||
].data.node.template[
|
|
||||||
templateField
|
|
||||||
].value = target;
|
|
||||||
return newInputList;
|
|
||||||
});
|
|
||||||
tweaks?.buildTweakObject!(
|
|
||||||
node["data"]["id"],
|
|
||||||
target,
|
|
||||||
node.data.node
|
|
||||||
.template[
|
|
||||||
templateField
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<InputComponent
|
|
||||||
editNode={true}
|
|
||||||
disabled={false}
|
|
||||||
password={
|
|
||||||
node.data.node.template[
|
node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
].password ?? false
|
],
|
||||||
}
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Case>
|
||||||
|
|
||||||
|
<Case
|
||||||
|
condition={
|
||||||
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].multiline
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<TextAreaComponent
|
||||||
|
disabled={false}
|
||||||
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
!node.data.node.template[
|
!node.data.node.template[
|
||||||
templateField
|
templateField
|
||||||
|
|
@ -410,11 +379,68 @@ export default function CodeTabsComponent({
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</Case>
|
||||||
) : node.data.node.template[
|
|
||||||
templateField
|
<Case
|
||||||
].type === "bool" ? (
|
condition={
|
||||||
|
!node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].multiline &&
|
||||||
|
!node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].list
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<InputComponent
|
||||||
|
editNode={true}
|
||||||
|
disabled={false}
|
||||||
|
password={
|
||||||
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].password ?? false
|
||||||
|
}
|
||||||
|
value={
|
||||||
|
!node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value ||
|
||||||
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value === ""
|
||||||
|
? ""
|
||||||
|
: node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].value
|
||||||
|
}
|
||||||
|
onChange={(target) => {
|
||||||
|
setData((old) => {
|
||||||
|
let newInputList =
|
||||||
|
cloneDeep(old);
|
||||||
|
newInputList![
|
||||||
|
i
|
||||||
|
].data.node.template[
|
||||||
|
templateField
|
||||||
|
].value = target;
|
||||||
|
return newInputList;
|
||||||
|
});
|
||||||
|
tweaks?.buildTweakObject!(
|
||||||
|
node["data"]["id"],
|
||||||
|
target,
|
||||||
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Case>
|
||||||
|
</Case>
|
||||||
|
|
||||||
|
<Case
|
||||||
|
condition={
|
||||||
|
type(node, templateField) ===
|
||||||
|
"bool"
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="ml-auto">
|
<div className="ml-auto">
|
||||||
{" "}
|
{" "}
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
|
|
@ -446,9 +472,14 @@ export default function CodeTabsComponent({
|
||||||
disabled={false}
|
disabled={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : node.data.node.template[
|
</Case>
|
||||||
templateField
|
|
||||||
].type === "file" ? (
|
<Case
|
||||||
|
condition={
|
||||||
|
type(node, templateField) ===
|
||||||
|
"file"
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<InputFileComponent
|
<InputFileComponent
|
||||||
editNode={true}
|
editNode={true}
|
||||||
|
|
@ -473,9 +504,14 @@ export default function CodeTabsComponent({
|
||||||
}}
|
}}
|
||||||
></InputFileComponent>
|
></InputFileComponent>
|
||||||
</div>
|
</div>
|
||||||
) : node.data.node.template[
|
</Case>
|
||||||
templateField
|
|
||||||
].type === "float" ? (
|
<Case
|
||||||
|
condition={
|
||||||
|
type(node, templateField) ===
|
||||||
|
"float"
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<FloatComponent
|
<FloatComponent
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
|
@ -518,12 +554,17 @@ export default function CodeTabsComponent({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : node.data.node.template[
|
</Case>
|
||||||
templateField
|
|
||||||
].type === "str" &&
|
<Case
|
||||||
node.data.node.template[
|
condition={
|
||||||
templateField
|
type(node, templateField) ===
|
||||||
].options ? (
|
"str" &&
|
||||||
|
node.data.node.template[
|
||||||
|
templateField
|
||||||
|
].options
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
editNode={true}
|
editNode={true}
|
||||||
|
|
@ -565,9 +606,14 @@ export default function CodeTabsComponent({
|
||||||
}
|
}
|
||||||
></Dropdown>
|
></Dropdown>
|
||||||
</div>
|
</div>
|
||||||
) : node.data.node.template[
|
</Case>
|
||||||
templateField
|
|
||||||
].type === "int" ? (
|
<Case
|
||||||
|
condition={
|
||||||
|
type(node, templateField) ===
|
||||||
|
"int"
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<IntComponent
|
<IntComponent
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
|
@ -610,9 +656,14 @@ export default function CodeTabsComponent({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : node.data.node.template[
|
</Case>
|
||||||
templateField
|
|
||||||
].type === "prompt" ? (
|
<Case
|
||||||
|
condition={
|
||||||
|
type(node, templateField) ===
|
||||||
|
"prompt"
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<PromptAreaComponent
|
<PromptAreaComponent
|
||||||
readonly={true}
|
readonly={true}
|
||||||
|
|
@ -651,9 +702,14 @@ export default function CodeTabsComponent({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : node.data.node.template[
|
</Case>
|
||||||
templateField
|
|
||||||
].type === "code" ? (
|
<Case
|
||||||
|
condition={
|
||||||
|
type(node, templateField) ===
|
||||||
|
"code"
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<CodeAreaComponent
|
<CodeAreaComponent
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
|
@ -692,9 +748,14 @@ export default function CodeTabsComponent({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : node.data.node.template[
|
</Case>
|
||||||
templateField
|
|
||||||
].type === "dict" ? (
|
<Case
|
||||||
|
condition={
|
||||||
|
type(node, templateField) ===
|
||||||
|
"dict"
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mx-auto overflow-auto custom-scroll">
|
<div className="mx-auto overflow-auto custom-scroll">
|
||||||
<KeypairListComponent
|
<KeypairListComponent
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
|
@ -712,6 +773,10 @@ export default function CodeTabsComponent({
|
||||||
.template[
|
.template[
|
||||||
templateField
|
templateField
|
||||||
].value,
|
].value,
|
||||||
|
type(
|
||||||
|
node,
|
||||||
|
templateField,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
duplicateKey={
|
duplicateKey={
|
||||||
|
|
@ -755,9 +820,14 @@ export default function CodeTabsComponent({
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : node.data.node.template[
|
</Case>
|
||||||
templateField
|
|
||||||
].type === "NestedDict" ? (
|
<Case
|
||||||
|
condition={
|
||||||
|
type(node, templateField) ===
|
||||||
|
"NestedDict"
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<DictComponent
|
<DictComponent
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
|
@ -765,7 +835,7 @@ export default function CodeTabsComponent({
|
||||||
value={
|
value={
|
||||||
node.data.node!.template[
|
node.data.node!.template[
|
||||||
templateField
|
templateField
|
||||||
].value.toString() === "{}"
|
].value?.toString() === "{}"
|
||||||
? {
|
? {
|
||||||
// yourkey: "value",
|
// yourkey: "value",
|
||||||
}
|
}
|
||||||
|
|
@ -795,13 +865,16 @@ export default function CodeTabsComponent({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : node.data.node.template[
|
</Case>
|
||||||
templateField
|
|
||||||
].type === "Any" ? (
|
<Case
|
||||||
"-"
|
condition={
|
||||||
) : (
|
type(node, templateField) ===
|
||||||
<div className="hidden"></div>
|
"Any"
|
||||||
)}
|
}
|
||||||
|
>
|
||||||
|
<>-</>
|
||||||
|
</Case>
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import React, { ReactNode, useEffect, useRef, useState } from "react";
|
import { ReactNode, useEffect, useRef, useState } from "react";
|
||||||
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
||||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||||
import DictComponent from "../../../../components/dictComponent";
|
import DictComponent from "../../../../components/dictComponent";
|
||||||
|
|
@ -18,20 +18,15 @@ import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
||||||
import { Button } from "../../../../components/ui/button";
|
import { Button } from "../../../../components/ui/button";
|
||||||
import { RefreshButton } from "../../../../components/ui/refreshButton";
|
import { RefreshButton } from "../../../../components/ui/refreshButton";
|
||||||
import {
|
import {
|
||||||
INPUT_HANDLER_HOVER,
|
|
||||||
LANGFLOW_SUPPORTED_TYPES,
|
LANGFLOW_SUPPORTED_TYPES,
|
||||||
OUTPUT_HANDLER_HOVER,
|
|
||||||
TOOLTIP_EMPTY,
|
TOOLTIP_EMPTY,
|
||||||
} from "../../../../constants/constants";
|
} from "../../../../constants/constants";
|
||||||
|
import { Case } from "../../../../shared/components/caseComponent";
|
||||||
import useAlertStore from "../../../../stores/alertStore";
|
import useAlertStore from "../../../../stores/alertStore";
|
||||||
import useFlowStore from "../../../../stores/flowStore";
|
import useFlowStore from "../../../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||||
import { useTypesStore } from "../../../../stores/typesStore";
|
import { useTypesStore } from "../../../../stores/typesStore";
|
||||||
import {
|
import { APIClassType } from "../../../../types/api";
|
||||||
APIClassType,
|
|
||||||
ResponseErrorDetailAPI,
|
|
||||||
ResponseErrorTypeAPI,
|
|
||||||
} from "../../../../types/api";
|
|
||||||
import { ParameterComponentType } from "../../../../types/components";
|
import { ParameterComponentType } from "../../../../types/components";
|
||||||
import {
|
import {
|
||||||
debouncedHandleUpdateValues,
|
debouncedHandleUpdateValues,
|
||||||
|
|
@ -44,12 +39,13 @@ import {
|
||||||
isValidConnection,
|
isValidConnection,
|
||||||
scapedJSONStringfy,
|
scapedJSONStringfy,
|
||||||
} from "../../../../utils/reactflowUtils";
|
} from "../../../../utils/reactflowUtils";
|
||||||
import {
|
import { nodeColors } from "../../../../utils/styleUtils";
|
||||||
nodeColors,
|
|
||||||
nodeIconsLucide,
|
|
||||||
nodeNames,
|
|
||||||
} from "../../../../utils/styleUtils";
|
|
||||||
import { classNames, groupByFamily } from "../../../../utils/utils";
|
import { classNames, groupByFamily } from "../../../../utils/utils";
|
||||||
|
import useFetchDataOnMount from "../../../hooks/use-fetch-data-on-mount";
|
||||||
|
import useHandleOnNewValue from "../../../hooks/use-handle-new-value";
|
||||||
|
import useHandleNodeClass from "../../../hooks/use-handle-node-class";
|
||||||
|
import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons";
|
||||||
|
import TooltipRenderComponent from "../tooltipRenderComponent";
|
||||||
|
|
||||||
export default function ParameterComponent({
|
export default function ParameterComponent({
|
||||||
left,
|
left,
|
||||||
|
|
@ -75,175 +71,69 @@ export default function ParameterComponent({
|
||||||
const nodes = useFlowStore((state) => state.nodes);
|
const nodes = useFlowStore((state) => state.nodes);
|
||||||
const edges = useFlowStore((state) => state.edges);
|
const edges = useFlowStore((state) => state.edges);
|
||||||
const setNode = useFlowStore((state) => state.setNode);
|
const setNode = useFlowStore((state) => state.setNode);
|
||||||
|
const myData = useTypesStore((state) => state.data);
|
||||||
|
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
|
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||||
const flow = currentFlow?.data?.nodes ?? null;
|
const flow = currentFlow?.data?.nodes ?? null;
|
||||||
|
|
||||||
const groupedEdge = useRef(null);
|
const groupedEdge = useRef(null);
|
||||||
|
|
||||||
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
|
||||||
|
|
||||||
|
const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue(
|
||||||
|
data,
|
||||||
|
name,
|
||||||
|
takeSnapshot,
|
||||||
|
handleUpdateValues,
|
||||||
|
debouncedHandleUpdateValues,
|
||||||
|
setNode,
|
||||||
|
renderTooltips,
|
||||||
|
isLoading,
|
||||||
|
setIsLoading,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
|
||||||
|
data,
|
||||||
|
name,
|
||||||
|
takeSnapshot,
|
||||||
|
setNode,
|
||||||
|
updateNodeInternals,
|
||||||
|
renderTooltips,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
|
||||||
|
useHandleRefreshButtonPress(setIsLoading, setNode, renderTooltips);
|
||||||
|
|
||||||
let disabled =
|
let disabled =
|
||||||
edges.some(
|
edges.some(
|
||||||
(edge) =>
|
(edge) =>
|
||||||
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
|
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
|
||||||
) ?? false;
|
) ?? false;
|
||||||
|
|
||||||
const myData = useTypesStore((state) => state.data);
|
|
||||||
|
|
||||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
|
||||||
|
|
||||||
const handleRefreshButtonPress = async (name, data) => {
|
const handleRefreshButtonPress = async (name, data) => {
|
||||||
setIsLoading(true);
|
handleRefreshButtonPressHook(name, data);
|
||||||
try {
|
|
||||||
let newTemplate = await handleUpdateValues(name, data);
|
|
||||||
|
|
||||||
if (newTemplate) {
|
|
||||||
setNode(data.id, (oldNode) => {
|
|
||||||
let newNode = cloneDeep(oldNode);
|
|
||||||
newNode.data = {
|
|
||||||
...newNode.data,
|
|
||||||
};
|
|
||||||
newNode.data.node.template = newTemplate;
|
|
||||||
return newNode;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
let responseError = error as ResponseErrorDetailAPI;
|
|
||||||
|
|
||||||
setErrorData({
|
|
||||||
title: "Error while updating the Component",
|
|
||||||
list: [responseError.response.data.detail ?? "Unknown error"],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setIsLoading(false);
|
|
||||||
renderTooltips();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useFetchDataOnMount(
|
||||||
async function fetchData() {
|
data,
|
||||||
if (
|
name,
|
||||||
(data.node?.template[name]?.real_time_refresh ||
|
handleUpdateValues,
|
||||||
data.node?.template[name]?.refresh_button) &&
|
setNode,
|
||||||
// options can be undefined but not an empty array
|
renderTooltips,
|
||||||
(data.node?.template[name]?.options?.length ?? 0) === 0
|
setIsLoading,
|
||||||
) {
|
);
|
||||||
setIsLoading(true);
|
|
||||||
try {
|
|
||||||
let newTemplate = await handleUpdateValues(name, data);
|
|
||||||
|
|
||||||
if (newTemplate) {
|
|
||||||
setNode(data.id, (oldNode) => {
|
|
||||||
let newNode = cloneDeep(oldNode);
|
|
||||||
newNode.data = {
|
|
||||||
...newNode.data,
|
|
||||||
};
|
|
||||||
newNode.data.node.template = newTemplate;
|
|
||||||
return newNode;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
let responseError = error as ResponseErrorDetailAPI;
|
|
||||||
|
|
||||||
setErrorData({
|
|
||||||
title: "Error while updating the Component",
|
|
||||||
list: [responseError.response.data.detail ?? "Unknown error"],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setIsLoading(false);
|
|
||||||
renderTooltips();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fetchData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleOnNewValue = async (
|
const handleOnNewValue = async (
|
||||||
newValue: string | string[] | boolean | Object[],
|
newValue: string | string[] | boolean | Object[],
|
||||||
skipSnapshot: boolean | undefined = false,
|
skipSnapshot: boolean | undefined = false,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const nodeTemplate = data.node!.template[name];
|
handleOnNewValueHook(newValue, skipSnapshot);
|
||||||
const currentValue = nodeTemplate.value;
|
|
||||||
|
|
||||||
if (currentValue !== newValue && !skipSnapshot) {
|
|
||||||
takeSnapshot();
|
|
||||||
}
|
|
||||||
|
|
||||||
const shouldUpdate =
|
|
||||||
data.node?.template[name].real_time_refresh &&
|
|
||||||
!data.node?.template[name].refresh_button &&
|
|
||||||
currentValue !== newValue;
|
|
||||||
|
|
||||||
const typeToDebounce = nodeTemplate.type;
|
|
||||||
|
|
||||||
nodeTemplate.value = newValue;
|
|
||||||
|
|
||||||
let newTemplate;
|
|
||||||
if (shouldUpdate) {
|
|
||||||
setIsLoading(true);
|
|
||||||
try {
|
|
||||||
if (["int"].includes(typeToDebounce)) {
|
|
||||||
newTemplate = await handleUpdateValues(name, data);
|
|
||||||
} else {
|
|
||||||
newTemplate = await debouncedHandleUpdateValues(name, data);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
let responseError = error as ResponseErrorTypeAPI;
|
|
||||||
setErrorData({
|
|
||||||
title: "Error while updating the Component",
|
|
||||||
list: [responseError.response.data.detail.error ?? "Unknown error"],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
setNode(data.id, (oldNode) => {
|
|
||||||
const newNode = cloneDeep(oldNode);
|
|
||||||
newNode.data = {
|
|
||||||
...newNode.data,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (data.node?.template[name].real_time_refresh && newTemplate) {
|
|
||||||
newNode.data.node.template = newTemplate;
|
|
||||||
} else {
|
|
||||||
newNode.data.node.template[name].value = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newNode;
|
|
||||||
});
|
|
||||||
|
|
||||||
renderTooltips();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
|
||||||
|
|
||||||
const handleNodeClass = (newNodeClass: APIClassType, code?: string): void => {
|
const handleNodeClass = (newNodeClass: APIClassType, code?: string): void => {
|
||||||
if (!data.node) return;
|
handleNodeClassHook(newNodeClass, code);
|
||||||
if (data.node!.template[name].value !== code) {
|
|
||||||
takeSnapshot();
|
|
||||||
}
|
|
||||||
|
|
||||||
setNode(data.id, (oldNode) => {
|
|
||||||
let newNode = cloneDeep(oldNode);
|
|
||||||
|
|
||||||
newNode.data = {
|
|
||||||
...newNode.data,
|
|
||||||
node: newNodeClass,
|
|
||||||
description: newNodeClass.description ?? data.node!.description,
|
|
||||||
display_name: newNodeClass.display_name ?? data.node!.display_name,
|
|
||||||
};
|
|
||||||
|
|
||||||
newNode.data.node.template[name].value = code;
|
|
||||||
|
|
||||||
return newNode;
|
|
||||||
});
|
|
||||||
|
|
||||||
updateNodeInternals(data.id);
|
|
||||||
|
|
||||||
renderTooltips();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
infoHtml.current = (
|
infoHtml.current = (
|
||||||
|
|
@ -264,88 +154,7 @@ export default function ParameterComponent({
|
||||||
if (groupedObj && groupedObj.length > 0) {
|
if (groupedObj && groupedObj.length > 0) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
refHtml.current = groupedObj.map((item, index) => {
|
refHtml.current = groupedObj.map((item, index) => {
|
||||||
const Icon: any =
|
return <TooltipRenderComponent index={index} item={item} left={left} />;
|
||||||
nodeIconsLucide[item.family] ?? nodeIconsLucide["unknown"];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
data-testid={`available-${left ? "input" : "output"}-${
|
|
||||||
item.family
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{index === 0 && (
|
|
||||||
<span>{left ? INPUT_HANDLER_HOVER : OUTPUT_HANDLER_HOVER}</span>
|
|
||||||
)}
|
|
||||||
<span
|
|
||||||
key={index}
|
|
||||||
className={classNames(
|
|
||||||
index > 0 ? "mt-2 flex items-center" : "mt-3 flex items-center",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="h-5 w-5"
|
|
||||||
style={{
|
|
||||||
color: nodeColors[item.family],
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className="h-5 w-5"
|
|
||||||
strokeWidth={1.5}
|
|
||||||
style={{
|
|
||||||
color: nodeColors[item.family] ?? nodeColors.unknown,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
className="ps-2 text-xs text-foreground"
|
|
||||||
data-testid={`tooltip-${nodeNames[item.family] ?? "Other"}`}
|
|
||||||
>
|
|
||||||
{nodeNames[item.family] ?? "Other"}{" "}
|
|
||||||
{item?.display_name && item?.display_name?.length > 0 ? (
|
|
||||||
<span
|
|
||||||
className="text-xs"
|
|
||||||
data-testid={`tooltip-${item?.display_name}`}
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
{item.display_name === "" ? "" : " - "}
|
|
||||||
{item.display_name.split(", ").length > 2
|
|
||||||
? item.display_name.split(", ").map((el, index) => (
|
|
||||||
<React.Fragment key={el + name}>
|
|
||||||
<span>
|
|
||||||
{index ===
|
|
||||||
item.display_name.split(", ").length - 1
|
|
||||||
? el
|
|
||||||
: (el += `, `)}
|
|
||||||
</span>
|
|
||||||
</React.Fragment>
|
|
||||||
))
|
|
||||||
: item.display_name}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span
|
|
||||||
className="text-xs"
|
|
||||||
data-testid={`tooltip-${item?.type}`}
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
{item.type === "" ? "" : " - "}
|
|
||||||
{item.type.split(", ").length > 2
|
|
||||||
? item.type.split(", ").map((el, index) => (
|
|
||||||
<React.Fragment key={el + name}>
|
|
||||||
<span>
|
|
||||||
{index === item.type.split(", ").length - 1
|
|
||||||
? el
|
|
||||||
: (el += `, `)}
|
|
||||||
</span>
|
|
||||||
</React.Fragment>
|
|
||||||
))
|
|
||||||
: item.type}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
|
|
@ -354,6 +163,7 @@ export default function ParameterComponent({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If optionalHandle is an empty list, then it is not an optional handle
|
// If optionalHandle is an empty list, then it is not an optional handle
|
||||||
if (optionalHandle && optionalHandle.length === 0) {
|
if (optionalHandle && optionalHandle.length === 0) {
|
||||||
optionalHandle = null;
|
optionalHandle = null;
|
||||||
|
|
@ -362,6 +172,9 @@ export default function ParameterComponent({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
renderTooltips();
|
renderTooltips();
|
||||||
}, [tooltipTitle, flow]);
|
}, [tooltipTitle, flow]);
|
||||||
|
|
||||||
|
console.log(left === true && type === "dict");
|
||||||
|
|
||||||
return !showNode ? (
|
return !showNode ? (
|
||||||
left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
||||||
<></>
|
<></>
|
||||||
|
|
@ -427,11 +240,12 @@ export default function ParameterComponent({
|
||||||
(left ? "" : " justify-end")
|
(left ? "" : " justify-end")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{!left && data.node?.frozen && (
|
<Case condition={left && data.node?.frozen}>
|
||||||
<div className="pr-1">
|
<div className="pr-1">
|
||||||
<IconComponent className="h-5 w-5 text-ice" name={"Snowflake"} />
|
<IconComponent className="h-5 w-5 text-ice" name={"Snowflake"} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
</Case>
|
||||||
|
|
||||||
{proxy ? (
|
{proxy ? (
|
||||||
<ShadTooltip content={<span>{proxy.id}</span>}>
|
<ShadTooltip content={<span>{proxy.id}</span>}>
|
||||||
<span className={!left && data.node?.frozen ? " text-ice" : ""}>
|
<span className={!left && data.node?.frozen ? " text-ice" : ""}>
|
||||||
|
|
@ -477,45 +291,37 @@ export default function ParameterComponent({
|
||||||
}`}
|
}`}
|
||||||
type={left ? "target" : "source"}
|
type={left ? "target" : "source"}
|
||||||
position={left ? Position.Left : Position.Right}
|
position={left ? Position.Left : Position.Right}
|
||||||
key={
|
key={scapedJSONStringfy(proxy ? { ...id, proxy } : id)}
|
||||||
proxy
|
id={scapedJSONStringfy(proxy ? { ...id, proxy } : id)}
|
||||||
? scapedJSONStringfy({ ...id, proxy })
|
|
||||||
: scapedJSONStringfy(id)
|
|
||||||
}
|
|
||||||
id={
|
|
||||||
proxy
|
|
||||||
? scapedJSONStringfy({ ...id, proxy })
|
|
||||||
: scapedJSONStringfy(id)
|
|
||||||
}
|
|
||||||
isValidConnection={(connection) =>
|
isValidConnection={(connection) =>
|
||||||
isValidConnection(connection, nodes, edges)
|
isValidConnection(connection, nodes, edges)
|
||||||
}
|
}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
left ? "-ml-0.5 " : "-mr-0.5 ",
|
left ? "-ml-0.5" : "-mr-0.5",
|
||||||
"h-3 w-3 rounded-full border-2 bg-background",
|
"h-3 w-3 rounded-full border-2 bg-background",
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{ borderColor: color ?? nodeColors.unknown }}
|
||||||
borderColor: color ?? nodeColors.unknown,
|
onClick={() => setFilterEdge(groupedEdge.current)}
|
||||||
}}
|
/>
|
||||||
onClick={() => {
|
|
||||||
setFilterEdge(groupedEdge.current);
|
|
||||||
}}
|
|
||||||
></Handle>
|
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{left === true &&
|
<Case
|
||||||
type === "str" &&
|
condition={
|
||||||
!data.node?.template[name].options ? (
|
left === true &&
|
||||||
|
type === "str" &&
|
||||||
|
!data.node?.template[name]?.options
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
{data.node?.template[name].list ? (
|
<Case condition={data.node?.template[name]?.list}>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
// Commenting this out until we have a better
|
// Commenting this out until we have a better
|
||||||
// way to display
|
// way to display
|
||||||
// (data.node?.template[name].refresh ? "w-5/6 " : "") +
|
// (data.node?.template[name]?.refresh ? "w-5/6 " : "") +
|
||||||
"flex-grow"
|
"flex-grow"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
@ -523,39 +329,27 @@ export default function ParameterComponent({
|
||||||
componentName={name}
|
componentName={name}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={
|
value={
|
||||||
!data.node.template[name].value ||
|
!data.node!.template[name]?.value ||
|
||||||
data.node.template[name].value === ""
|
data.node!.template[name]?.value === ""
|
||||||
? [""]
|
? [""]
|
||||||
: data.node.template[name].value
|
: data.node!.template[name]?.value
|
||||||
}
|
}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
/>
|
/>
|
||||||
{/* {data.node?.template[name].refresh_button && (
|
|
||||||
<div className="w-1/6">
|
|
||||||
<RefreshButton
|
|
||||||
isLoading={isLoading}
|
|
||||||
disabled={disabled}
|
|
||||||
name={name}
|
|
||||||
data={data}
|
|
||||||
className="extra-side-bar-buttons ml-2 mt-1"
|
|
||||||
handleUpdateValues={handleRefreshButtonPress}
|
|
||||||
id={"refresh-button-" + name}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)} */}
|
|
||||||
</div>
|
</div>
|
||||||
) : data.node?.template[name].multiline ? (
|
</Case>
|
||||||
|
<Case condition={data.node?.template[name]?.multiline}>
|
||||||
<div className="mt-2 flex w-full flex-col ">
|
<div className="mt-2 flex w-full flex-col ">
|
||||||
<div className="flex-grow">
|
<div className="flex-grow">
|
||||||
<TextAreaComponent
|
<TextAreaComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node!.template[name]?.value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
id={"textarea-" + data.node.template[name].name}
|
id={"textarea-" + data.node!.template[name]?.name}
|
||||||
data-testid={"textarea-" + data.node.template[name].name}
|
data-testid={"textarea-" + data.node!.template[name]?.name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{data.node?.template[name].refresh_button && (
|
{data.node?.template[name]?.refresh_button && (
|
||||||
<div className="flex-grow">
|
<div className="flex-grow">
|
||||||
<RefreshButton
|
<RefreshButton
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
|
@ -563,7 +357,7 @@ export default function ParameterComponent({
|
||||||
name={name}
|
name={name}
|
||||||
data={data}
|
data={data}
|
||||||
button_text={
|
button_text={
|
||||||
data.node?.template[name].refresh_button_text ??
|
data.node?.template[name]?.refresh_button_text ??
|
||||||
"Refresh"
|
"Refresh"
|
||||||
}
|
}
|
||||||
className="extra-side-bar-buttons mt-1"
|
className="extra-side-bar-buttons mt-1"
|
||||||
|
|
@ -573,12 +367,18 @@ export default function ParameterComponent({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
</Case>
|
||||||
|
<Case
|
||||||
|
condition={
|
||||||
|
!data.node?.template[name]?.multiline &&
|
||||||
|
!data.node?.template[name]?.list
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mt-2 flex w-full items-center">
|
<div className="mt-2 flex w-full items-center">
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
"flex-grow " +
|
"flex-grow " +
|
||||||
(data.node?.template[name].refresh_button ? "w-5/6" : "")
|
(data.node?.template[name]?.refresh_button ? "w-5/6" : "")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<InputGlobalComponent
|
<InputGlobalComponent
|
||||||
|
|
@ -598,7 +398,7 @@ export default function ParameterComponent({
|
||||||
data={data}
|
data={data}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{data.node?.template[name].refresh_button && (
|
{data.node?.template[name]?.refresh_button && (
|
||||||
<div className="w-1/6">
|
<div className="w-1/6">
|
||||||
<RefreshButton
|
<RefreshButton
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
|
@ -606,7 +406,7 @@ export default function ParameterComponent({
|
||||||
name={name}
|
name={name}
|
||||||
data={data}
|
data={data}
|
||||||
button_text={
|
button_text={
|
||||||
data.node?.template[name].refresh_button_text ??
|
data.node?.template[name]?.refresh_button_text ??
|
||||||
"Refresh"
|
"Refresh"
|
||||||
}
|
}
|
||||||
className="extra-side-bar-buttons ml-2 mt-1"
|
className="extra-side-bar-buttons ml-2 mt-1"
|
||||||
|
|
@ -616,52 +416,61 @@ export default function ParameterComponent({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
</Case>
|
||||||
</div>
|
</div>
|
||||||
) : left === true && type === "bool" ? (
|
</Case>
|
||||||
|
|
||||||
|
<Case condition={left === true && type === "bool"}>
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
id={"toggle-" + name}
|
id={"toggle-" + name}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
enabled={data.node?.template[name].value ?? false}
|
enabled={data.node?.template[name]?.value ?? false}
|
||||||
setEnabled={handleOnNewValue}
|
setEnabled={handleOnNewValue}
|
||||||
size="large"
|
size="large"
|
||||||
editNode={false}
|
editNode={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : left === true && type === "float" ? (
|
</Case>
|
||||||
|
|
||||||
|
<Case condition={left === true && type === "float"}>
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<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>
|
||||||
) : left === true &&
|
</Case>
|
||||||
type === "str" &&
|
|
||||||
(data.node?.template[name].options ||
|
<Case
|
||||||
data.node?.template[name]?.real_time_refresh) ? (
|
condition={
|
||||||
// TODO: Improve CSS
|
left === true &&
|
||||||
|
type === "str" &&
|
||||||
|
(data.node?.template[name]?.options ||
|
||||||
|
data.node?.template[name]?.real_time_refresh)
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mt-2 flex w-full items-center">
|
<div className="mt-2 flex w-full items-center">
|
||||||
<div className="w-5/6 flex-grow">
|
<div className="w-5/6 flex-grow">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
options={data.node.template[name].options}
|
options={data.node!.template[name]?.options}
|
||||||
onSelect={handleOnNewValue}
|
onSelect={handleOnNewValue}
|
||||||
value={data.node.template[name].value}
|
value={data.node!.template[name]?.value}
|
||||||
id={"dropdown-" + name}
|
id={"dropdown-" + name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{data.node?.template[name].refresh_button && (
|
{data.node?.template[name]?.refresh_button && (
|
||||||
<div className="w-1/6">
|
<div className="w-1/6">
|
||||||
<RefreshButton
|
<RefreshButton
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
name={name}
|
name={name}
|
||||||
data={data}
|
data={data}
|
||||||
button_text={data.node?.template[name].refresh_button_text}
|
button_text={data.node?.template[name]?.refresh_button_text}
|
||||||
className="extra-side-bar-buttons ml-2 mt-1"
|
className="extra-side-bar-buttons ml-2 mt-1"
|
||||||
handleUpdateValues={handleRefreshButtonPress}
|
handleUpdateValues={handleRefreshButtonPress}
|
||||||
id={"refresh-button-" + name}
|
id={"refresh-button-" + name}
|
||||||
|
|
@ -669,46 +478,54 @@ export default function ParameterComponent({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : left === true && type === "code" ? (
|
</Case>
|
||||||
|
|
||||||
|
<Case condition={left === true && type === "code"}>
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<CodeAreaComponent
|
<CodeAreaComponent
|
||||||
readonly={
|
readonly={
|
||||||
data.node?.flow && data.node.template[name].dynamic
|
data.node?.flow && data.node.template[name]?.dynamic
|
||||||
? true
|
? true
|
||||||
: false
|
: false
|
||||||
}
|
}
|
||||||
dynamic={data.node?.template[name].dynamic ?? false}
|
dynamic={data.node?.template[name]?.dynamic ?? false}
|
||||||
setNodeClass={handleNodeClass}
|
setNodeClass={handleNodeClass}
|
||||||
nodeClass={data.node}
|
nodeClass={data.node}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node?.template[name].value ?? ""}
|
value={data.node?.template[name]?.value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
id={"code-input-" + name}
|
id={"code-input-" + name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : left === true && type === "file" ? (
|
</Case>
|
||||||
|
|
||||||
|
<Case condition={left === true && type === "file"}>
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<InputFileComponent
|
<InputFileComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node?.template[name].value ?? ""}
|
value={data.node?.template[name]?.value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
fileTypes={data.node?.template[name].fileTypes}
|
fileTypes={data.node?.template[name]?.fileTypes}
|
||||||
onFileChange={(filePath: string) => {
|
onFileChange={(filePath: string) => {
|
||||||
data.node!.template[name].file_path = filePath;
|
data.node!.template[name].file_path = filePath;
|
||||||
}}
|
}}
|
||||||
></InputFileComponent>
|
></InputFileComponent>
|
||||||
</div>
|
</div>
|
||||||
) : left === true && type === "int" ? (
|
</Case>
|
||||||
|
|
||||||
|
<Case condition={left === true && type === "int"}>
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<IntComponent
|
<IntComponent
|
||||||
rangeSpec={data.node?.template[name].rangeSpec}
|
rangeSpec={data.node?.template[name]?.rangeSpec}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node?.template[name].value ?? ""}
|
value={data.node?.template[name]?.value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
id={"int-input-" + name}
|
id={"int-input-" + name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : left === true && type === "prompt" ? (
|
</Case>
|
||||||
|
|
||||||
|
<Case condition={left === true && type === "prompt"}>
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<PromptAreaComponent
|
<PromptAreaComponent
|
||||||
readonly={data.node?.flow ? true : false}
|
readonly={data.node?.flow ? true : false}
|
||||||
|
|
@ -716,57 +533,59 @@ export default function ParameterComponent({
|
||||||
setNodeClass={handleNodeClass}
|
setNodeClass={handleNodeClass}
|
||||||
nodeClass={data.node}
|
nodeClass={data.node}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node?.template[name].value ?? ""}
|
value={data.node?.template[name]?.value ?? ""}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
id={"prompt-input-" + name}
|
id={"prompt-input-" + name}
|
||||||
data-testid={"prompt-input-" + name}
|
data-testid={"prompt-input-" + name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : left === true && type === "NestedDict" ? (
|
</Case>
|
||||||
|
|
||||||
|
<Case condition={left === true && type === "NestedDict"}>
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<DictComponent
|
<DictComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={false}
|
editNode={false}
|
||||||
value={
|
value={
|
||||||
!data.node!.template[name].value ||
|
!data.node!.template[name]?.value ||
|
||||||
data.node!.template[name].value?.toString() === "{}"
|
data.node!.template[name]?.value?.toString() === "{}"
|
||||||
? {
|
? {
|
||||||
// yourkey: "value",
|
// yourkey: "value",
|
||||||
}
|
}
|
||||||
: data.node!.template[name].value
|
: data.node!.template[name]?.value
|
||||||
}
|
}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
id="div-dict-input"
|
id="div-dict-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : left === true && type === "dict" ? (
|
</Case>
|
||||||
|
|
||||||
|
<Case condition={left === true && type === "dict"}>
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<KeypairListComponent
|
<KeypairListComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={false}
|
editNode={false}
|
||||||
value={
|
value={
|
||||||
data.node!.template[name].value?.length === 0 ||
|
data.node!.template[name]?.value?.length === 0 ||
|
||||||
!data.node!.template[name].value
|
!data.node!.template[name]?.value
|
||||||
? [{ "": "" }]
|
? [{ "": "" }]
|
||||||
: convertObjToArray(data.node!.template[name].value)
|
: convertObjToArray(data.node!.template[name]?.value, type!)
|
||||||
}
|
}
|
||||||
duplicateKey={errorDuplicateKey}
|
duplicateKey={errorDuplicateKey}
|
||||||
onChange={(newValue) => {
|
onChange={(newValue) => {
|
||||||
const valueToNumbers = convertValuesToNumbers(newValue);
|
const valueToNumbers = convertValuesToNumbers(newValue);
|
||||||
setErrorDuplicateKey(hasDuplicateKeys(valueToNumbers));
|
setErrorDuplicateKey(hasDuplicateKeys(valueToNumbers));
|
||||||
// if data.node?.template[name].list is true, then the value is an array of objects
|
// if data.node?.template[name]?.list is true, then the value is an array of objects
|
||||||
// else we need to get the first object of the array
|
// else we need to get the first object of the array
|
||||||
|
|
||||||
if (data.node?.template[name].list) {
|
if (data.node?.template[name]?.list) {
|
||||||
handleOnNewValue(valueToNumbers);
|
handleOnNewValue(valueToNumbers);
|
||||||
} else handleOnNewValue(valueToNumbers[0]);
|
} else handleOnNewValue(valueToNumbers[0]);
|
||||||
}}
|
}}
|
||||||
isList={data.node?.template[name].list ?? false}
|
isList={data.node?.template[name]?.list ?? false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
</Case>
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
INPUT_HANDLER_HOVER,
|
||||||
|
OUTPUT_HANDLER_HOVER,
|
||||||
|
} from "../../../../constants/constants";
|
||||||
|
import {
|
||||||
|
nodeColors,
|
||||||
|
nodeIconsLucide,
|
||||||
|
nodeNames,
|
||||||
|
} from "../../../../utils/styleUtils";
|
||||||
|
import { classNames } from "../../../../utils/utils";
|
||||||
|
|
||||||
|
const TooltipRenderComponent = ({ item, index, left }) => {
|
||||||
|
const Icon = nodeIconsLucide[item.family] ?? nodeIconsLucide["unknown"];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
data-testid={`available-${left ? "input" : "output"}-${item.family}`}
|
||||||
|
>
|
||||||
|
{index === 0 && (
|
||||||
|
<span>{left ? INPUT_HANDLER_HOVER : OUTPUT_HANDLER_HOVER}</span>
|
||||||
|
)}
|
||||||
|
<span
|
||||||
|
key={index}
|
||||||
|
className={classNames(
|
||||||
|
index > 0 ? "mt-2 flex items-center" : "mt-3 flex items-center",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="h-5 w-5"
|
||||||
|
style={{
|
||||||
|
color: nodeColors[item.family],
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
className="h-5 w-5"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
style={{
|
||||||
|
color: nodeColors[item.family] ?? nodeColors.unknown,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
className="ps-2 text-xs text-foreground"
|
||||||
|
data-testid={`tooltip-${nodeNames[item.family] ?? "Other"}`}
|
||||||
|
>
|
||||||
|
{nodeNames[item.family] ?? "Other"}{" "}
|
||||||
|
{item?.display_name && item?.display_name?.length > 0 ? (
|
||||||
|
<span
|
||||||
|
className="text-xs"
|
||||||
|
data-testid={`tooltip-${item?.display_name}`}
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
{item.display_name === "" ? "" : " - "}
|
||||||
|
{item.display_name.split(", ").length > 2
|
||||||
|
? item.display_name.split(", ").map((el, index) => (
|
||||||
|
<React.Fragment key={el + name}>
|
||||||
|
<span>
|
||||||
|
{index === item.display_name.split(", ").length - 1
|
||||||
|
? el
|
||||||
|
: (el += `, `)}
|
||||||
|
</span>
|
||||||
|
</React.Fragment>
|
||||||
|
))
|
||||||
|
: item.display_name}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-xs" data-testid={`tooltip-${item?.type}`}>
|
||||||
|
{" "}
|
||||||
|
{item.type === "" ? "" : " - "}
|
||||||
|
{item.type.split(", ").length > 2
|
||||||
|
? item.type.split(", ").map((el, index) => (
|
||||||
|
<React.Fragment key={el + name}>
|
||||||
|
<span>
|
||||||
|
{index === item.type.split(", ").length - 1
|
||||||
|
? el
|
||||||
|
: (el += `, `)}
|
||||||
|
</span>
|
||||||
|
</React.Fragment>
|
||||||
|
))
|
||||||
|
: item.type}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TooltipRenderComponent;
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import useAlertStore from "../../stores/alertStore";
|
||||||
|
import { ResponseErrorDetailAPI } from "../../types/api";
|
||||||
|
|
||||||
|
const useFetchDataOnMount = (
|
||||||
|
data,
|
||||||
|
name,
|
||||||
|
handleUpdateValues,
|
||||||
|
setNode,
|
||||||
|
renderTooltips,
|
||||||
|
setIsLoading,
|
||||||
|
) => {
|
||||||
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchData() {
|
||||||
|
if (
|
||||||
|
(data.node?.template[name]?.real_time_refresh ||
|
||||||
|
data.node?.template[name]?.refresh_button) &&
|
||||||
|
// options can be undefined but not an empty array
|
||||||
|
(data.node?.template[name]?.options?.length ?? 0) === 0
|
||||||
|
) {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
let newTemplate = await handleUpdateValues(name, data);
|
||||||
|
|
||||||
|
if (newTemplate) {
|
||||||
|
setNode(data.id, (oldNode) => {
|
||||||
|
let newNode = cloneDeep(oldNode);
|
||||||
|
newNode.data = {
|
||||||
|
...newNode.data,
|
||||||
|
};
|
||||||
|
newNode.data.node.template = newTemplate;
|
||||||
|
return newNode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
let responseError = error as ResponseErrorDetailAPI;
|
||||||
|
|
||||||
|
setErrorData({
|
||||||
|
title: "Error while updating the Component",
|
||||||
|
list: [responseError.response.data.detail ?? "Unknown error"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
renderTooltips();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fetchData();
|
||||||
|
}, []); // Empty dependency array ensures that this effect runs only once, on mount
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useFetchDataOnMount;
|
||||||
75
src/frontend/src/customNodes/hooks/use-handle-new-value.tsx
Normal file
75
src/frontend/src/customNodes/hooks/use-handle-new-value.tsx
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
|
import useAlertStore from "../../stores/alertStore";
|
||||||
|
import { ResponseErrorTypeAPI } from "../../types/api";
|
||||||
|
|
||||||
|
const useHandleOnNewValue = (
|
||||||
|
data,
|
||||||
|
name,
|
||||||
|
takeSnapshot,
|
||||||
|
handleUpdateValues,
|
||||||
|
debouncedHandleUpdateValues,
|
||||||
|
setNode,
|
||||||
|
renderTooltips,
|
||||||
|
isLoading,
|
||||||
|
setIsLoading,
|
||||||
|
) => {
|
||||||
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
|
|
||||||
|
const handleOnNewValue = async (newValue, skipSnapshot = false) => {
|
||||||
|
const nodeTemplate = data.node!.template[name];
|
||||||
|
const currentValue = nodeTemplate.value;
|
||||||
|
|
||||||
|
if (currentValue !== newValue && !skipSnapshot) {
|
||||||
|
takeSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
const shouldUpdate =
|
||||||
|
data.node?.template[name].real_time_refresh &&
|
||||||
|
!data.node?.template[name].refresh_button &&
|
||||||
|
currentValue !== newValue;
|
||||||
|
|
||||||
|
const typeToDebounce = nodeTemplate.type;
|
||||||
|
|
||||||
|
nodeTemplate.value = newValue;
|
||||||
|
|
||||||
|
let newTemplate;
|
||||||
|
if (shouldUpdate) {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
if (["int"].includes(typeToDebounce)) {
|
||||||
|
newTemplate = await handleUpdateValues(name, data);
|
||||||
|
} else {
|
||||||
|
newTemplate = await debouncedHandleUpdateValues(name, data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
let responseError = error as ResponseErrorTypeAPI;
|
||||||
|
setErrorData({
|
||||||
|
title: "Error while updating the Component",
|
||||||
|
list: [responseError.response.data.detail.error ?? "Unknown error"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
setNode(data.id, (oldNode) => {
|
||||||
|
const newNode = cloneDeep(oldNode);
|
||||||
|
newNode.data = {
|
||||||
|
...newNode.data,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (data.node?.template[name].real_time_refresh && newTemplate) {
|
||||||
|
newNode.data.node.template = newTemplate;
|
||||||
|
} else {
|
||||||
|
newNode.data.node.template[name].value = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
});
|
||||||
|
|
||||||
|
renderTooltips();
|
||||||
|
};
|
||||||
|
|
||||||
|
return { handleOnNewValue };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useHandleOnNewValue;
|
||||||
40
src/frontend/src/customNodes/hooks/use-handle-node-class.tsx
Normal file
40
src/frontend/src/customNodes/hooks/use-handle-node-class.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
|
|
||||||
|
const useHandleNodeClass = (
|
||||||
|
data,
|
||||||
|
name,
|
||||||
|
takeSnapshot,
|
||||||
|
setNode,
|
||||||
|
updateNodeInternals,
|
||||||
|
renderTooltips,
|
||||||
|
) => {
|
||||||
|
const handleNodeClass = (newNodeClass, code) => {
|
||||||
|
if (!data.node) return;
|
||||||
|
if (data.node!.template[name].value !== code) {
|
||||||
|
takeSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
setNode(data.id, (oldNode) => {
|
||||||
|
let newNode = cloneDeep(oldNode);
|
||||||
|
|
||||||
|
newNode.data = {
|
||||||
|
...newNode.data,
|
||||||
|
node: newNodeClass,
|
||||||
|
description: newNodeClass.description ?? data.node!.description,
|
||||||
|
display_name: newNodeClass.display_name ?? data.node!.display_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
newNode.data.node.template[name].value = code;
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
});
|
||||||
|
|
||||||
|
updateNodeInternals(data.id);
|
||||||
|
|
||||||
|
renderTooltips();
|
||||||
|
};
|
||||||
|
|
||||||
|
return { handleNodeClass };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useHandleNodeClass;
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
|
import useAlertStore from "../../stores/alertStore";
|
||||||
|
import { ResponseErrorDetailAPI } from "../../types/api";
|
||||||
|
import { handleUpdateValues } from "../../utils/parameterUtils";
|
||||||
|
|
||||||
|
const useHandleRefreshButtonPress = (setIsLoading, setNode, renderTooltips) => {
|
||||||
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
|
|
||||||
|
const handleRefreshButtonPress = async (name, data) => {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
let newTemplate = await handleUpdateValues(name, data);
|
||||||
|
|
||||||
|
if (newTemplate) {
|
||||||
|
setNode(data.id, (oldNode) => {
|
||||||
|
let newNode = cloneDeep(oldNode);
|
||||||
|
newNode.data = {
|
||||||
|
...newNode.data,
|
||||||
|
};
|
||||||
|
newNode.data.node.template = newTemplate;
|
||||||
|
return newNode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
let responseError = error as ResponseErrorDetailAPI;
|
||||||
|
|
||||||
|
setErrorData({
|
||||||
|
title: "Error while updating the Component",
|
||||||
|
list: [responseError.response.data.detail ?? "Unknown error"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
renderTooltips();
|
||||||
|
};
|
||||||
|
|
||||||
|
return { handleRefreshButtonPress };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useHandleRefreshButtonPress;
|
||||||
|
|
@ -28,6 +28,7 @@ import {
|
||||||
LANGFLOW_SUPPORTED_TYPES,
|
LANGFLOW_SUPPORTED_TYPES,
|
||||||
limitScrollFieldsModal,
|
limitScrollFieldsModal,
|
||||||
} from "../../constants/constants";
|
} from "../../constants/constants";
|
||||||
|
import { Case } from "../../shared/components/caseComponent";
|
||||||
import useFlowStore from "../../stores/flowStore";
|
import useFlowStore from "../../stores/flowStore";
|
||||||
import { NodeDataType } from "../../types/flow";
|
import { NodeDataType } from "../../types/flow";
|
||||||
import {
|
import {
|
||||||
|
|
@ -52,7 +53,7 @@ const EditNodeModal = forwardRef(
|
||||||
open: boolean;
|
open: boolean;
|
||||||
setOpen: (open: boolean) => void;
|
setOpen: (open: boolean) => void;
|
||||||
},
|
},
|
||||||
ref
|
ref,
|
||||||
) => {
|
) => {
|
||||||
const [myData, setMyData] = useState(data);
|
const [myData, setMyData] = useState(data);
|
||||||
|
|
||||||
|
|
@ -84,6 +85,10 @@ const EditNodeModal = forwardRef(
|
||||||
|
|
||||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||||
|
|
||||||
|
const type = (templateParam) => {
|
||||||
|
return myData.node?.template[templateParam].type;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseModal
|
<BaseModal
|
||||||
key={data.id}
|
key={data.id}
|
||||||
|
|
@ -116,7 +121,7 @@ const EditNodeModal = forwardRef(
|
||||||
"edit-node-modal-box",
|
"edit-node-modal-box",
|
||||||
nodeLength > limitScrollFieldsModal
|
nodeLength > limitScrollFieldsModal
|
||||||
? "overflow-scroll overflow-x-hidden custom-scroll"
|
? "overflow-scroll overflow-x-hidden custom-scroll"
|
||||||
: ""
|
: "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{nodeLength > 0 && (
|
{nodeLength > 0 && (
|
||||||
|
|
@ -138,8 +143,8 @@ const EditNodeModal = forwardRef(
|
||||||
templateParam.charAt(0) !== "_" &&
|
templateParam.charAt(0) !== "_" &&
|
||||||
myData.node?.template[templateParam].show &&
|
myData.node?.template[templateParam].show &&
|
||||||
LANGFLOW_SUPPORTED_TYPES.has(
|
LANGFLOW_SUPPORTED_TYPES.has(
|
||||||
myData.node.template[templateParam].type
|
myData.node!.template[templateParam].type,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
.map((templateParam, index) => {
|
.map((templateParam, index) => {
|
||||||
let id = {
|
let id = {
|
||||||
|
|
@ -161,8 +166,8 @@ const EditNodeModal = forwardRef(
|
||||||
myData.node?.template[templateParam]
|
myData.node?.template[templateParam]
|
||||||
.proxy,
|
.proxy,
|
||||||
}
|
}
|
||||||
: id
|
: id,
|
||||||
)
|
),
|
||||||
) ?? false;
|
) ?? false;
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
|
|
@ -170,8 +175,7 @@ const EditNodeModal = forwardRef(
|
||||||
className={
|
className={
|
||||||
"h-10 " +
|
"h-10 " +
|
||||||
((templateParam === "code" &&
|
((templateParam === "code" &&
|
||||||
myData.node?.template[templateParam].type ===
|
type(templateParam) === "code") ||
|
||||||
"code") ||
|
|
||||||
(templateParam.includes("code") &&
|
(templateParam.includes("code") &&
|
||||||
myData.node?.template[templateParam].proxy)
|
myData.node?.template[templateParam].proxy)
|
||||||
? " hidden "
|
? " hidden "
|
||||||
|
|
@ -190,7 +194,7 @@ const EditNodeModal = forwardRef(
|
||||||
<span>
|
<span>
|
||||||
{myData.node?.template[templateParam]
|
{myData.node?.template[templateParam]
|
||||||
.display_name
|
.display_name
|
||||||
? myData.node.template[templateParam]
|
? myData.node!.template[templateParam]
|
||||||
.display_name
|
.display_name
|
||||||
: myData.node?.template[templateParam]
|
: myData.node?.template[templateParam]
|
||||||
.name}
|
.name}
|
||||||
|
|
@ -198,58 +202,62 @@ const EditNodeModal = forwardRef(
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
||||||
{myData.node?.template[templateParam].type ===
|
<Case
|
||||||
"str" &&
|
condition={
|
||||||
!myData.node.template[templateParam].options ? (
|
type(templateParam) === "str" &&
|
||||||
|
!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}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={
|
value={
|
||||||
!myData.node.template[templateParam]
|
!myData.node!.template[templateParam]
|
||||||
.value ||
|
.value ||
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.value === ""
|
.value === ""
|
||||||
? [""]
|
? [""]
|
||||||
: myData.node.template[
|
: myData.node!.template[
|
||||||
templateParam
|
templateParam
|
||||||
].value
|
].value
|
||||||
}
|
}
|
||||||
onChange={(value: string[]) => {
|
onChange={(value: string[]) => {
|
||||||
handleOnNewValue(
|
handleOnNewValue(
|
||||||
value,
|
value,
|
||||||
templateParam
|
templateParam,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : myData.node.template[templateParam]
|
) : myData.node!.template[templateParam]
|
||||||
.multiline ? (
|
.multiline ? (
|
||||||
<TextAreaComponent
|
<TextAreaComponent
|
||||||
id={
|
id={
|
||||||
"textarea-edit-" +
|
"textarea-edit-" +
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.name
|
.name
|
||||||
}
|
}
|
||||||
data-testid={
|
data-testid={
|
||||||
"textarea-edit-" +
|
"textarea-edit-" +
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.name
|
.name
|
||||||
}
|
}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.value ?? ""
|
.value ?? ""
|
||||||
}
|
}
|
||||||
onChange={(
|
onChange={(
|
||||||
value: string | string[]
|
value: string | string[],
|
||||||
) => {
|
) => {
|
||||||
handleOnNewValue(
|
handleOnNewValue(
|
||||||
value,
|
value,
|
||||||
templateParam
|
templateParam,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -274,8 +282,13 @@ const EditNodeModal = forwardRef(
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "NestedDict" ? (
|
|
||||||
|
<Case
|
||||||
|
condition={
|
||||||
|
type(templateParam) === "NestedDict"
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className=" w-full">
|
<div className=" w-full">
|
||||||
<DictComponent
|
<DictComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
@ -296,21 +309,24 @@ const EditNodeModal = forwardRef(
|
||||||
].value = newValue;
|
].value = newValue;
|
||||||
handleOnNewValue(
|
handleOnNewValue(
|
||||||
newValue,
|
newValue,
|
||||||
templateParam
|
templateParam,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
id="editnode-div-dict-input"
|
id="editnode-div-dict-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "dict" ? (
|
|
||||||
|
<Case
|
||||||
|
condition={type(templateParam) === "dict"}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"max-h-48 w-full overflow-auto custom-scroll",
|
"max-h-48 w-full overflow-auto custom-scroll",
|
||||||
myData.node!.template[templateParam].value
|
myData.node!.template[templateParam].value
|
||||||
?.length > 1
|
?.length > 1
|
||||||
? "my-3"
|
? "my-3"
|
||||||
: ""
|
: "",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<KeypairListComponent
|
<KeypairListComponent
|
||||||
|
|
@ -325,7 +341,8 @@ const EditNodeModal = forwardRef(
|
||||||
: convertObjToArray(
|
: convertObjToArray(
|
||||||
myData.node!.template[
|
myData.node!.template[
|
||||||
templateParam
|
templateParam
|
||||||
].value
|
].value,
|
||||||
|
type(templateParam)!,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
duplicateKey={errorDuplicateKey}
|
duplicateKey={errorDuplicateKey}
|
||||||
|
|
@ -336,11 +353,11 @@ const EditNodeModal = forwardRef(
|
||||||
templateParam
|
templateParam
|
||||||
].value = valueToNumbers;
|
].value = valueToNumbers;
|
||||||
setErrorDuplicateKey(
|
setErrorDuplicateKey(
|
||||||
hasDuplicateKeys(valueToNumbers)
|
hasDuplicateKeys(valueToNumbers),
|
||||||
);
|
);
|
||||||
handleOnNewValue(
|
handleOnNewValue(
|
||||||
valueToNumbers,
|
valueToNumbers,
|
||||||
templateParam
|
templateParam,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
isList={
|
isList={
|
||||||
|
|
@ -349,32 +366,39 @@ const EditNodeModal = forwardRef(
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "bool" ? (
|
|
||||||
|
<Case
|
||||||
|
condition={type(templateParam) === "bool"}
|
||||||
|
>
|
||||||
<div className="ml-auto">
|
<div className="ml-auto">
|
||||||
{" "}
|
{" "}
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
id={
|
id={
|
||||||
"toggle-edit-" +
|
"toggle-edit-" +
|
||||||
myData.node.template[templateParam].name
|
myData.node!.template[templateParam]
|
||||||
|
.name
|
||||||
}
|
}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
enabled={
|
enabled={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.value
|
.value
|
||||||
}
|
}
|
||||||
setEnabled={(isEnabled) => {
|
setEnabled={(isEnabled) => {
|
||||||
handleOnNewValue(
|
handleOnNewValue(
|
||||||
isEnabled,
|
isEnabled,
|
||||||
templateParam
|
templateParam,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
editNode={true}
|
editNode={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "float" ? (
|
|
||||||
|
<Case
|
||||||
|
condition={type(templateParam) === "float"}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<FloatComponent
|
<FloatComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
@ -384,7 +408,7 @@ const EditNodeModal = forwardRef(
|
||||||
.rangeSpec
|
.rangeSpec
|
||||||
}
|
}
|
||||||
value={
|
value={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.value ?? ""
|
.value ?? ""
|
||||||
}
|
}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
|
|
@ -392,32 +416,38 @@ const EditNodeModal = forwardRef(
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "str" &&
|
|
||||||
myData.node.template[templateParam]
|
<Case
|
||||||
.options ? (
|
condition={
|
||||||
|
type(templateParam) === "str" &&
|
||||||
|
myData.node!.template[templateParam].options
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
editNode={true}
|
editNode={true}
|
||||||
options={
|
options={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.options
|
.options
|
||||||
}
|
}
|
||||||
onSelect={(value) =>
|
onSelect={(value) =>
|
||||||
handleOnNewValue(value, templateParam)
|
handleOnNewValue(value, templateParam)
|
||||||
}
|
}
|
||||||
value={
|
value={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.value ?? "Choose an option"
|
.value ?? "Choose an option"
|
||||||
}
|
}
|
||||||
id={
|
id={
|
||||||
"dropdown-edit-" +
|
"dropdown-edit-" +
|
||||||
myData.node.template[templateParam].name
|
myData.node!.template[templateParam]
|
||||||
|
.name
|
||||||
}
|
}
|
||||||
></Dropdown>
|
></Dropdown>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "int" ? (
|
|
||||||
|
<Case condition={type(templateParam) === "int"}>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<IntComponent
|
<IntComponent
|
||||||
rangeSpec={
|
rangeSpec={
|
||||||
|
|
@ -426,12 +456,13 @@ const EditNodeModal = forwardRef(
|
||||||
}
|
}
|
||||||
id={
|
id={
|
||||||
"edit-int-input-" +
|
"edit-int-input-" +
|
||||||
myData.node.template[templateParam].name
|
myData.node!.template[templateParam]
|
||||||
|
.name
|
||||||
}
|
}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.value ?? ""
|
.value ?? ""
|
||||||
}
|
}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
|
|
@ -439,21 +470,24 @@ const EditNodeModal = forwardRef(
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "file" ? (
|
|
||||||
|
<Case
|
||||||
|
condition={type(templateParam) === "file"}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<InputFileComponent
|
<InputFileComponent
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={
|
value={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.value ?? ""
|
.value ?? ""
|
||||||
}
|
}
|
||||||
onChange={(value: string | string[]) => {
|
onChange={(value: string | string[]) => {
|
||||||
handleOnNewValue(value, templateParam);
|
handleOnNewValue(value, templateParam);
|
||||||
}}
|
}}
|
||||||
fileTypes={
|
fileTypes={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.fileTypes
|
.fileTypes
|
||||||
}
|
}
|
||||||
onFileChange={(filePath: string) => {
|
onFileChange={(filePath: string) => {
|
||||||
|
|
@ -463,8 +497,11 @@ const EditNodeModal = forwardRef(
|
||||||
}}
|
}}
|
||||||
></InputFileComponent>
|
></InputFileComponent>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "prompt" ? (
|
|
||||||
|
<Case
|
||||||
|
condition={type(templateParam) === "prompt"}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<PromptAreaComponent
|
<PromptAreaComponent
|
||||||
readonly={
|
readonly={
|
||||||
|
|
@ -478,7 +515,7 @@ const EditNodeModal = forwardRef(
|
||||||
myData.node = nodeClass;
|
myData.node = nodeClass;
|
||||||
}}
|
}}
|
||||||
value={
|
value={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.value ?? ""
|
.value ?? ""
|
||||||
}
|
}
|
||||||
onChange={(value: string | string[]) => {
|
onChange={(value: string | string[]) => {
|
||||||
|
|
@ -486,21 +523,26 @@ const EditNodeModal = forwardRef(
|
||||||
}}
|
}}
|
||||||
id={
|
id={
|
||||||
"prompt-area-edit-" +
|
"prompt-area-edit-" +
|
||||||
myData.node.template[templateParam].name
|
myData.node!.template[templateParam]
|
||||||
|
.name
|
||||||
}
|
}
|
||||||
data-testid={
|
data-testid={
|
||||||
"modal-prompt-input-" +
|
"modal-prompt-input-" +
|
||||||
myData.node.template[templateParam].name
|
myData.node!.template[templateParam]
|
||||||
|
.name
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "code" ? (
|
|
||||||
|
<Case
|
||||||
|
condition={type(templateParam) === "code"}
|
||||||
|
>
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<CodeAreaComponent
|
<CodeAreaComponent
|
||||||
readonly={
|
readonly={
|
||||||
myData.node?.flow &&
|
myData.node?.flow &&
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.dynamic
|
.dynamic
|
||||||
? true
|
? true
|
||||||
: false
|
: false
|
||||||
|
|
@ -516,7 +558,7 @@ const EditNodeModal = forwardRef(
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
myData.node.template[templateParam]
|
myData.node!.template[templateParam]
|
||||||
.value ?? ""
|
.value ?? ""
|
||||||
}
|
}
|
||||||
onChange={(value: string | string[]) => {
|
onChange={(value: string | string[]) => {
|
||||||
|
|
@ -524,16 +566,16 @@ const EditNodeModal = forwardRef(
|
||||||
}}
|
}}
|
||||||
id={
|
id={
|
||||||
"code-area-edit" +
|
"code-area-edit" +
|
||||||
myData.node.template[templateParam].name
|
myData.node!.template[templateParam]
|
||||||
|
.name
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node?.template[templateParam]
|
</Case>
|
||||||
.type === "Any" ? (
|
|
||||||
"-"
|
<Case condition={type(templateParam) === "Any"}>
|
||||||
) : (
|
<>-</>
|
||||||
<div className="hidden"></div>
|
</Case>
|
||||||
)}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="p-0 text-right">
|
<TableCell className="p-0 text-right">
|
||||||
<div className="items-center text-center">
|
<div className="items-center text-center">
|
||||||
|
|
@ -588,7 +630,7 @@ const EditNodeModal = forwardRef(
|
||||||
</BaseModal.Footer>
|
</BaseModal.Footer>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export default EditNodeModal;
|
export default EditNodeModal;
|
||||||
|
|
|
||||||
15
src/frontend/src/shared/components/caseComponent/index.tsx
Normal file
15
src/frontend/src/shared/components/caseComponent/index.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { memo } from "react";
|
||||||
|
|
||||||
|
type BooleanLike = boolean | string | number | null | undefined;
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
condition: (() => BooleanLike) | BooleanLike;
|
||||||
|
children: React.ReactNode | any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Case = memo(({ condition, children }: Props) => {
|
||||||
|
const conditionResult =
|
||||||
|
typeof condition === "function" ? condition() : condition;
|
||||||
|
|
||||||
|
return conditionResult ? children : null;
|
||||||
|
});
|
||||||
|
|
@ -400,6 +400,7 @@ export type StoreApiKeyType = {
|
||||||
export type groupedObjType = {
|
export type groupedObjType = {
|
||||||
family: string;
|
family: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
display_name?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type nodeGroupedObjType = {
|
export type nodeGroupedObjType = {
|
||||||
|
|
|
||||||
|
|
@ -461,7 +461,8 @@ export function getConnectedNodes(
|
||||||
return nodes.filter((node) => node.id === targetId || node.id === sourceId);
|
return nodes.filter((node) => node.id === targetId || node.id === sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertObjToArray(singleObject: object | string) {
|
export function convertObjToArray(singleObject: object | string, type: string) {
|
||||||
|
if (type !== "dict") return [{ "": "" }];
|
||||||
if (typeof singleObject === "string") {
|
if (typeof singleObject === "string") {
|
||||||
singleObject = JSON.parse(singleObject);
|
singleObject = JSON.parse(singleObject);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue