✨ (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,
|
||||
} from "../../components/ui/tabs";
|
||||
import { LANGFLOW_SUPPORTED_TYPES } from "../../constants/constants";
|
||||
import ExportModal from "../../modals/exportModal";
|
||||
import { Case } from "../../shared/components/caseComponent";
|
||||
import { useDarkStore } from "../../stores/darkStore";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
import { codeTabsPropsType } from "../../types/components";
|
||||
|
|
@ -43,7 +45,6 @@ import KeypairListComponent from "../keypairListComponent";
|
|||
import ShadTooltip from "../shadTooltipComponent";
|
||||
import { Label } from "../ui/label";
|
||||
import { Switch } from "../ui/switch";
|
||||
import ExportModal from "../../modals/exportModal";
|
||||
|
||||
export default function CodeTabsComponent({
|
||||
flow,
|
||||
|
|
@ -87,6 +88,10 @@ export default function CodeTabsComponent({
|
|||
});
|
||||
};
|
||||
|
||||
const type = (node, templateParam) => {
|
||||
return node.data.node.template[templateParam].type;
|
||||
};
|
||||
|
||||
const downloadAsFile = () => {
|
||||
const fileExtension = tabs[activeTab].language || ".txt";
|
||||
const suggestedFileName = `${"generated-code."}${fileExtension}`;
|
||||
|
|
@ -276,107 +281,71 @@ export default function CodeTabsComponent({
|
|||
</TableCell>
|
||||
<TableCell className="p-0 text-xs text-foreground">
|
||||
<div className="m-auto w-[250px]">
|
||||
{node.data.node.template[
|
||||
templateField
|
||||
].type === "str" &&
|
||||
!node.data.node.template[
|
||||
templateField
|
||||
].options ? (
|
||||
<div className="mx-auto">
|
||||
{node.data.node.template[
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"str" &&
|
||||
!node.data.node.template[
|
||||
templateField
|
||||
]?.list ? (
|
||||
<InputListComponent
|
||||
componentName={
|
||||
templateField
|
||||
}
|
||||
editNode={true}
|
||||
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[
|
||||
].options
|
||||
}
|
||||
>
|
||||
<Case
|
||||
condition={
|
||||
node.data.node.template[
|
||||
templateField
|
||||
].multiline ? (
|
||||
<div>
|
||||
<TextAreaComponent
|
||||
disabled={false}
|
||||
editNode={true}
|
||||
value={
|
||||
!node.data.node
|
||||
.template[
|
||||
]?.list
|
||||
}
|
||||
>
|
||||
<InputListComponent
|
||||
componentName={templateField}
|
||||
editNode={true}
|
||||
disabled={false}
|
||||
value={
|
||||
!node.data.node.template[
|
||||
templateField
|
||||
].value ||
|
||||
node.data.node.template[
|
||||
templateField
|
||||
].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
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<InputComponent
|
||||
editNode={true}
|
||||
disabled={false}
|
||||
password={
|
||||
].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
|
||||
].password ?? false
|
||||
}
|
||||
],
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
node.data.node.template[
|
||||
templateField
|
||||
].multiline
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<TextAreaComponent
|
||||
disabled={false}
|
||||
editNode={true}
|
||||
value={
|
||||
!node.data.node.template[
|
||||
templateField
|
||||
|
|
@ -410,11 +379,68 @@ export default function CodeTabsComponent({
|
|||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "bool" ? (
|
||||
</div>
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
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">
|
||||
{" "}
|
||||
<ToggleShadComponent
|
||||
|
|
@ -446,9 +472,14 @@ export default function CodeTabsComponent({
|
|||
disabled={false}
|
||||
/>
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "file" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"file"
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<InputFileComponent
|
||||
editNode={true}
|
||||
|
|
@ -473,9 +504,14 @@ export default function CodeTabsComponent({
|
|||
}}
|
||||
></InputFileComponent>
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "float" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"float"
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<FloatComponent
|
||||
disabled={false}
|
||||
|
|
@ -518,12 +554,17 @@ export default function CodeTabsComponent({
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "str" &&
|
||||
node.data.node.template[
|
||||
templateField
|
||||
].options ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"str" &&
|
||||
node.data.node.template[
|
||||
templateField
|
||||
].options
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<Dropdown
|
||||
editNode={true}
|
||||
|
|
@ -565,9 +606,14 @@ export default function CodeTabsComponent({
|
|||
}
|
||||
></Dropdown>
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "int" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"int"
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<IntComponent
|
||||
disabled={false}
|
||||
|
|
@ -610,9 +656,14 @@ export default function CodeTabsComponent({
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "prompt" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"prompt"
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<PromptAreaComponent
|
||||
readonly={true}
|
||||
|
|
@ -651,9 +702,14 @@ export default function CodeTabsComponent({
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "code" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"code"
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<CodeAreaComponent
|
||||
disabled={false}
|
||||
|
|
@ -692,9 +748,14 @@ export default function CodeTabsComponent({
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "dict" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"dict"
|
||||
}
|
||||
>
|
||||
<div className="mx-auto overflow-auto custom-scroll">
|
||||
<KeypairListComponent
|
||||
disabled={false}
|
||||
|
|
@ -712,6 +773,10 @@ export default function CodeTabsComponent({
|
|||
.template[
|
||||
templateField
|
||||
].value,
|
||||
type(
|
||||
node,
|
||||
templateField,
|
||||
),
|
||||
)
|
||||
}
|
||||
duplicateKey={
|
||||
|
|
@ -755,9 +820,14 @@ export default function CodeTabsComponent({
|
|||
}
|
||||
/>
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "NestedDict" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"NestedDict"
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<DictComponent
|
||||
disabled={false}
|
||||
|
|
@ -765,7 +835,7 @@ export default function CodeTabsComponent({
|
|||
value={
|
||||
node.data.node!.template[
|
||||
templateField
|
||||
].value.toString() === "{}"
|
||||
].value?.toString() === "{}"
|
||||
? {
|
||||
// yourkey: "value",
|
||||
}
|
||||
|
|
@ -795,13 +865,16 @@ export default function CodeTabsComponent({
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : node.data.node.template[
|
||||
templateField
|
||||
].type === "Any" ? (
|
||||
"-"
|
||||
) : (
|
||||
<div className="hidden"></div>
|
||||
)}
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(node, templateField) ===
|
||||
"Any"
|
||||
}
|
||||
>
|
||||
<>-</>
|
||||
</Case>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
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 CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||
import DictComponent from "../../../../components/dictComponent";
|
||||
|
|
@ -18,20 +18,15 @@ import ToggleShadComponent from "../../../../components/toggleShadComponent";
|
|||
import { Button } from "../../../../components/ui/button";
|
||||
import { RefreshButton } from "../../../../components/ui/refreshButton";
|
||||
import {
|
||||
INPUT_HANDLER_HOVER,
|
||||
LANGFLOW_SUPPORTED_TYPES,
|
||||
OUTPUT_HANDLER_HOVER,
|
||||
TOOLTIP_EMPTY,
|
||||
} from "../../../../constants/constants";
|
||||
import { Case } from "../../../../shared/components/caseComponent";
|
||||
import useAlertStore from "../../../../stores/alertStore";
|
||||
import useFlowStore from "../../../../stores/flowStore";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
import { useTypesStore } from "../../../../stores/typesStore";
|
||||
import {
|
||||
APIClassType,
|
||||
ResponseErrorDetailAPI,
|
||||
ResponseErrorTypeAPI,
|
||||
} from "../../../../types/api";
|
||||
import { APIClassType } from "../../../../types/api";
|
||||
import { ParameterComponentType } from "../../../../types/components";
|
||||
import {
|
||||
debouncedHandleUpdateValues,
|
||||
|
|
@ -44,12 +39,13 @@ import {
|
|||
isValidConnection,
|
||||
scapedJSONStringfy,
|
||||
} from "../../../../utils/reactflowUtils";
|
||||
import {
|
||||
nodeColors,
|
||||
nodeIconsLucide,
|
||||
nodeNames,
|
||||
} from "../../../../utils/styleUtils";
|
||||
import { nodeColors } from "../../../../utils/styleUtils";
|
||||
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({
|
||||
left,
|
||||
|
|
@ -75,175 +71,69 @@ export default function ParameterComponent({
|
|||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const edges = useFlowStore((state) => state.edges);
|
||||
const setNode = useFlowStore((state) => state.setNode);
|
||||
|
||||
const myData = useTypesStore((state) => state.data);
|
||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||
const flow = currentFlow?.data?.nodes ?? null;
|
||||
|
||||
const groupedEdge = useRef(null);
|
||||
|
||||
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 =
|
||||
edges.some(
|
||||
(edge) =>
|
||||
edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
|
||||
) ?? false;
|
||||
|
||||
const myData = useTypesStore((state) => state.data);
|
||||
|
||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||
|
||||
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();
|
||||
handleRefreshButtonPressHook(name, data);
|
||||
};
|
||||
|
||||
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();
|
||||
}, []);
|
||||
useFetchDataOnMount(
|
||||
data,
|
||||
name,
|
||||
handleUpdateValues,
|
||||
setNode,
|
||||
renderTooltips,
|
||||
setIsLoading,
|
||||
);
|
||||
|
||||
const handleOnNewValue = async (
|
||||
newValue: string | string[] | boolean | Object[],
|
||||
skipSnapshot: boolean | undefined = false,
|
||||
): Promise<void> => {
|
||||
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();
|
||||
handleOnNewValueHook(newValue, skipSnapshot);
|
||||
};
|
||||
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
|
||||
const handleNodeClass = (newNodeClass: APIClassType, code?: string): void => {
|
||||
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();
|
||||
handleNodeClassHook(newNodeClass, code);
|
||||
};
|
||||
|
||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-ignore
|
||||
infoHtml.current = (
|
||||
|
|
@ -264,88 +154,7 @@ export default function ParameterComponent({
|
|||
if (groupedObj && groupedObj.length > 0) {
|
||||
//@ts-ignore
|
||||
refHtml.current = groupedObj.map((item, index) => {
|
||||
const Icon: any =
|
||||
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>
|
||||
);
|
||||
return <TooltipRenderComponent index={index} item={item} left={left} />;
|
||||
});
|
||||
} else {
|
||||
//@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 && optionalHandle.length === 0) {
|
||||
optionalHandle = null;
|
||||
|
|
@ -362,6 +172,9 @@ export default function ParameterComponent({
|
|||
useEffect(() => {
|
||||
renderTooltips();
|
||||
}, [tooltipTitle, flow]);
|
||||
|
||||
console.log(left === true && type === "dict");
|
||||
|
||||
return !showNode ? (
|
||||
left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
||||
<></>
|
||||
|
|
@ -427,11 +240,12 @@ export default function ParameterComponent({
|
|||
(left ? "" : " justify-end")
|
||||
}
|
||||
>
|
||||
{!left && data.node?.frozen && (
|
||||
<Case condition={left && data.node?.frozen}>
|
||||
<div className="pr-1">
|
||||
<IconComponent className="h-5 w-5 text-ice" name={"Snowflake"} />
|
||||
</div>
|
||||
)}
|
||||
</Case>
|
||||
|
||||
{proxy ? (
|
||||
<ShadTooltip content={<span>{proxy.id}</span>}>
|
||||
<span className={!left && data.node?.frozen ? " text-ice" : ""}>
|
||||
|
|
@ -477,45 +291,37 @@ export default function ParameterComponent({
|
|||
}`}
|
||||
type={left ? "target" : "source"}
|
||||
position={left ? Position.Left : Position.Right}
|
||||
key={
|
||||
proxy
|
||||
? scapedJSONStringfy({ ...id, proxy })
|
||||
: scapedJSONStringfy(id)
|
||||
}
|
||||
id={
|
||||
proxy
|
||||
? scapedJSONStringfy({ ...id, proxy })
|
||||
: scapedJSONStringfy(id)
|
||||
}
|
||||
key={scapedJSONStringfy(proxy ? { ...id, proxy } : id)}
|
||||
id={scapedJSONStringfy(proxy ? { ...id, proxy } : id)}
|
||||
isValidConnection={(connection) =>
|
||||
isValidConnection(connection, nodes, edges)
|
||||
}
|
||||
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",
|
||||
)}
|
||||
style={{
|
||||
borderColor: color ?? nodeColors.unknown,
|
||||
}}
|
||||
onClick={() => {
|
||||
setFilterEdge(groupedEdge.current);
|
||||
}}
|
||||
></Handle>
|
||||
style={{ borderColor: color ?? nodeColors.unknown }}
|
||||
onClick={() => setFilterEdge(groupedEdge.current)}
|
||||
/>
|
||||
</ShadTooltip>
|
||||
</div>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{left === true &&
|
||||
type === "str" &&
|
||||
!data.node?.template[name].options ? (
|
||||
<Case
|
||||
condition={
|
||||
left === true &&
|
||||
type === "str" &&
|
||||
!data.node?.template[name]?.options
|
||||
}
|
||||
>
|
||||
<div className="w-full">
|
||||
{data.node?.template[name].list ? (
|
||||
<Case condition={data.node?.template[name]?.list}>
|
||||
<div
|
||||
className={
|
||||
// Commenting this out until we have a better
|
||||
// way to display
|
||||
// (data.node?.template[name].refresh ? "w-5/6 " : "") +
|
||||
// (data.node?.template[name]?.refresh ? "w-5/6 " : "") +
|
||||
"flex-grow"
|
||||
}
|
||||
>
|
||||
|
|
@ -523,39 +329,27 @@ export default function ParameterComponent({
|
|||
componentName={name}
|
||||
disabled={disabled}
|
||||
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}
|
||||
/>
|
||||
{/* {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>
|
||||
) : data.node?.template[name].multiline ? (
|
||||
</Case>
|
||||
<Case condition={data.node?.template[name]?.multiline}>
|
||||
<div className="mt-2 flex w-full flex-col ">
|
||||
<div className="flex-grow">
|
||||
<TextAreaComponent
|
||||
disabled={disabled}
|
||||
value={data.node.template[name].value ?? ""}
|
||||
value={data.node!.template[name]?.value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"textarea-" + data.node.template[name].name}
|
||||
data-testid={"textarea-" + data.node.template[name].name}
|
||||
id={"textarea-" + data.node!.template[name]?.name}
|
||||
data-testid={"textarea-" + data.node!.template[name]?.name}
|
||||
/>
|
||||
</div>
|
||||
{data.node?.template[name].refresh_button && (
|
||||
{data.node?.template[name]?.refresh_button && (
|
||||
<div className="flex-grow">
|
||||
<RefreshButton
|
||||
isLoading={isLoading}
|
||||
|
|
@ -563,7 +357,7 @@ export default function ParameterComponent({
|
|||
name={name}
|
||||
data={data}
|
||||
button_text={
|
||||
data.node?.template[name].refresh_button_text ??
|
||||
data.node?.template[name]?.refresh_button_text ??
|
||||
"Refresh"
|
||||
}
|
||||
className="extra-side-bar-buttons mt-1"
|
||||
|
|
@ -573,12 +367,18 @@ export default function ParameterComponent({
|
|||
</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={
|
||||
"flex-grow " +
|
||||
(data.node?.template[name].refresh_button ? "w-5/6" : "")
|
||||
(data.node?.template[name]?.refresh_button ? "w-5/6" : "")
|
||||
}
|
||||
>
|
||||
<InputGlobalComponent
|
||||
|
|
@ -598,7 +398,7 @@ export default function ParameterComponent({
|
|||
data={data}
|
||||
/>
|
||||
</div>
|
||||
{data.node?.template[name].refresh_button && (
|
||||
{data.node?.template[name]?.refresh_button && (
|
||||
<div className="w-1/6">
|
||||
<RefreshButton
|
||||
isLoading={isLoading}
|
||||
|
|
@ -606,7 +406,7 @@ export default function ParameterComponent({
|
|||
name={name}
|
||||
data={data}
|
||||
button_text={
|
||||
data.node?.template[name].refresh_button_text ??
|
||||
data.node?.template[name]?.refresh_button_text ??
|
||||
"Refresh"
|
||||
}
|
||||
className="extra-side-bar-buttons ml-2 mt-1"
|
||||
|
|
@ -616,52 +416,61 @@ export default function ParameterComponent({
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Case>
|
||||
</div>
|
||||
) : left === true && type === "bool" ? (
|
||||
</Case>
|
||||
|
||||
<Case condition={left === true && type === "bool"}>
|
||||
<div className="mt-2 w-full">
|
||||
<ToggleShadComponent
|
||||
id={"toggle-" + name}
|
||||
disabled={disabled}
|
||||
enabled={data.node?.template[name].value ?? false}
|
||||
enabled={data.node?.template[name]?.value ?? false}
|
||||
setEnabled={handleOnNewValue}
|
||||
size="large"
|
||||
editNode={false}
|
||||
/>
|
||||
</div>
|
||||
) : left === true && type === "float" ? (
|
||||
</Case>
|
||||
|
||||
<Case condition={left === true && type === "float"}>
|
||||
<div className="mt-2 w-full">
|
||||
<FloatComponent
|
||||
disabled={disabled}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
value={data.node?.template[name]?.value ?? ""}
|
||||
rangeSpec={data.node?.template[name]?.rangeSpec}
|
||||
onChange={handleOnNewValue}
|
||||
/>
|
||||
</div>
|
||||
) : left === true &&
|
||||
type === "str" &&
|
||||
(data.node?.template[name].options ||
|
||||
data.node?.template[name]?.real_time_refresh) ? (
|
||||
// TODO: Improve CSS
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
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="w-5/6 flex-grow">
|
||||
<Dropdown
|
||||
disabled={disabled}
|
||||
isLoading={isLoading}
|
||||
options={data.node.template[name].options}
|
||||
options={data.node!.template[name]?.options}
|
||||
onSelect={handleOnNewValue}
|
||||
value={data.node.template[name].value}
|
||||
value={data.node!.template[name]?.value}
|
||||
id={"dropdown-" + name}
|
||||
/>
|
||||
</div>
|
||||
{data.node?.template[name].refresh_button && (
|
||||
{data.node?.template[name]?.refresh_button && (
|
||||
<div className="w-1/6">
|
||||
<RefreshButton
|
||||
isLoading={isLoading}
|
||||
disabled={disabled}
|
||||
name={name}
|
||||
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"
|
||||
handleUpdateValues={handleRefreshButtonPress}
|
||||
id={"refresh-button-" + name}
|
||||
|
|
@ -669,46 +478,54 @@ export default function ParameterComponent({
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : left === true && type === "code" ? (
|
||||
</Case>
|
||||
|
||||
<Case condition={left === true && type === "code"}>
|
||||
<div className="mt-2 w-full">
|
||||
<CodeAreaComponent
|
||||
readonly={
|
||||
data.node?.flow && data.node.template[name].dynamic
|
||||
data.node?.flow && data.node.template[name]?.dynamic
|
||||
? true
|
||||
: false
|
||||
}
|
||||
dynamic={data.node?.template[name].dynamic ?? false}
|
||||
dynamic={data.node?.template[name]?.dynamic ?? false}
|
||||
setNodeClass={handleNodeClass}
|
||||
nodeClass={data.node}
|
||||
disabled={disabled}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
value={data.node?.template[name]?.value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"code-input-" + name}
|
||||
/>
|
||||
</div>
|
||||
) : left === true && type === "file" ? (
|
||||
</Case>
|
||||
|
||||
<Case condition={left === true && type === "file"}>
|
||||
<div className="mt-2 w-full">
|
||||
<InputFileComponent
|
||||
disabled={disabled}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
value={data.node?.template[name]?.value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
fileTypes={data.node?.template[name].fileTypes}
|
||||
fileTypes={data.node?.template[name]?.fileTypes}
|
||||
onFileChange={(filePath: string) => {
|
||||
data.node!.template[name].file_path = filePath;
|
||||
}}
|
||||
></InputFileComponent>
|
||||
</div>
|
||||
) : left === true && type === "int" ? (
|
||||
</Case>
|
||||
|
||||
<Case condition={left === true && type === "int"}>
|
||||
<div className="mt-2 w-full">
|
||||
<IntComponent
|
||||
rangeSpec={data.node?.template[name].rangeSpec}
|
||||
rangeSpec={data.node?.template[name]?.rangeSpec}
|
||||
disabled={disabled}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
value={data.node?.template[name]?.value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"int-input-" + name}
|
||||
/>
|
||||
</div>
|
||||
) : left === true && type === "prompt" ? (
|
||||
</Case>
|
||||
|
||||
<Case condition={left === true && type === "prompt"}>
|
||||
<div className="mt-2 w-full">
|
||||
<PromptAreaComponent
|
||||
readonly={data.node?.flow ? true : false}
|
||||
|
|
@ -716,57 +533,59 @@ export default function ParameterComponent({
|
|||
setNodeClass={handleNodeClass}
|
||||
nodeClass={data.node}
|
||||
disabled={disabled}
|
||||
value={data.node?.template[name].value ?? ""}
|
||||
value={data.node?.template[name]?.value ?? ""}
|
||||
onChange={handleOnNewValue}
|
||||
id={"prompt-input-" + name}
|
||||
data-testid={"prompt-input-" + name}
|
||||
/>
|
||||
</div>
|
||||
) : left === true && type === "NestedDict" ? (
|
||||
</Case>
|
||||
|
||||
<Case condition={left === true && type === "NestedDict"}>
|
||||
<div className="mt-2 w-full">
|
||||
<DictComponent
|
||||
disabled={disabled}
|
||||
editNode={false}
|
||||
value={
|
||||
!data.node!.template[name].value ||
|
||||
data.node!.template[name].value?.toString() === "{}"
|
||||
!data.node!.template[name]?.value ||
|
||||
data.node!.template[name]?.value?.toString() === "{}"
|
||||
? {
|
||||
// yourkey: "value",
|
||||
}
|
||||
: data.node!.template[name].value
|
||||
: data.node!.template[name]?.value
|
||||
}
|
||||
onChange={handleOnNewValue}
|
||||
id="div-dict-input"
|
||||
/>
|
||||
</div>
|
||||
) : left === true && type === "dict" ? (
|
||||
</Case>
|
||||
|
||||
<Case condition={left === true && type === "dict"}>
|
||||
<div className="mt-2 w-full">
|
||||
<KeypairListComponent
|
||||
disabled={disabled}
|
||||
editNode={false}
|
||||
value={
|
||||
data.node!.template[name].value?.length === 0 ||
|
||||
!data.node!.template[name].value
|
||||
data.node!.template[name]?.value?.length === 0 ||
|
||||
!data.node!.template[name]?.value
|
||||
? [{ "": "" }]
|
||||
: convertObjToArray(data.node!.template[name].value)
|
||||
: convertObjToArray(data.node!.template[name]?.value, type!)
|
||||
}
|
||||
duplicateKey={errorDuplicateKey}
|
||||
onChange={(newValue) => {
|
||||
const valueToNumbers = convertValuesToNumbers(newValue);
|
||||
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
|
||||
|
||||
if (data.node?.template[name].list) {
|
||||
if (data.node?.template[name]?.list) {
|
||||
handleOnNewValue(valueToNumbers);
|
||||
} else handleOnNewValue(valueToNumbers[0]);
|
||||
}}
|
||||
isList={data.node?.template[name].list ?? false}
|
||||
isList={data.node?.template[name]?.list ?? false}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</Case>
|
||||
</>
|
||||
</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,
|
||||
limitScrollFieldsModal,
|
||||
} from "../../constants/constants";
|
||||
import { Case } from "../../shared/components/caseComponent";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import {
|
||||
|
|
@ -52,7 +53,7 @@ const EditNodeModal = forwardRef(
|
|||
open: boolean;
|
||||
setOpen: (open: boolean) => void;
|
||||
},
|
||||
ref
|
||||
ref,
|
||||
) => {
|
||||
const [myData, setMyData] = useState(data);
|
||||
|
||||
|
|
@ -84,6 +85,10 @@ const EditNodeModal = forwardRef(
|
|||
|
||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||
|
||||
const type = (templateParam) => {
|
||||
return myData.node?.template[templateParam].type;
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseModal
|
||||
key={data.id}
|
||||
|
|
@ -116,7 +121,7 @@ const EditNodeModal = forwardRef(
|
|||
"edit-node-modal-box",
|
||||
nodeLength > limitScrollFieldsModal
|
||||
? "overflow-scroll overflow-x-hidden custom-scroll"
|
||||
: ""
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
{nodeLength > 0 && (
|
||||
|
|
@ -138,8 +143,8 @@ const EditNodeModal = forwardRef(
|
|||
templateParam.charAt(0) !== "_" &&
|
||||
myData.node?.template[templateParam].show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
myData.node.template[templateParam].type
|
||||
)
|
||||
myData.node!.template[templateParam].type,
|
||||
),
|
||||
)
|
||||
.map((templateParam, index) => {
|
||||
let id = {
|
||||
|
|
@ -161,8 +166,8 @@ const EditNodeModal = forwardRef(
|
|||
myData.node?.template[templateParam]
|
||||
.proxy,
|
||||
}
|
||||
: id
|
||||
)
|
||||
: id,
|
||||
),
|
||||
) ?? false;
|
||||
return (
|
||||
<TableRow
|
||||
|
|
@ -170,8 +175,7 @@ const EditNodeModal = forwardRef(
|
|||
className={
|
||||
"h-10 " +
|
||||
((templateParam === "code" &&
|
||||
myData.node?.template[templateParam].type ===
|
||||
"code") ||
|
||||
type(templateParam) === "code") ||
|
||||
(templateParam.includes("code") &&
|
||||
myData.node?.template[templateParam].proxy)
|
||||
? " hidden "
|
||||
|
|
@ -190,7 +194,7 @@ const EditNodeModal = forwardRef(
|
|||
<span>
|
||||
{myData.node?.template[templateParam]
|
||||
.display_name
|
||||
? myData.node.template[templateParam]
|
||||
? myData.node!.template[templateParam]
|
||||
.display_name
|
||||
: myData.node?.template[templateParam]
|
||||
.name}
|
||||
|
|
@ -198,58 +202,62 @@ const EditNodeModal = forwardRef(
|
|||
</ShadTooltip>
|
||||
</TableCell>
|
||||
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
||||
{myData.node?.template[templateParam].type ===
|
||||
"str" &&
|
||||
!myData.node.template[templateParam].options ? (
|
||||
<Case
|
||||
condition={
|
||||
type(templateParam) === "str" &&
|
||||
!myData.node!.template[templateParam]
|
||||
.options
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
{myData.node.template[templateParam]
|
||||
{myData.node!.template[templateParam]
|
||||
?.list ? (
|
||||
<InputListComponent
|
||||
componentName={templateParam}
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
value={
|
||||
!myData.node.template[templateParam]
|
||||
!myData.node!.template[templateParam]
|
||||
.value ||
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value === ""
|
||||
? [""]
|
||||
: myData.node.template[
|
||||
: myData.node!.template[
|
||||
templateParam
|
||||
].value
|
||||
}
|
||||
onChange={(value: string[]) => {
|
||||
handleOnNewValue(
|
||||
value,
|
||||
templateParam
|
||||
templateParam,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
) : myData.node.template[templateParam]
|
||||
) : myData.node!.template[templateParam]
|
||||
.multiline ? (
|
||||
<TextAreaComponent
|
||||
id={
|
||||
"textarea-edit-" +
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
data-testid={
|
||||
"textarea-edit-" +
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(
|
||||
value: string | string[]
|
||||
value: string | string[],
|
||||
) => {
|
||||
handleOnNewValue(
|
||||
value,
|
||||
templateParam
|
||||
templateParam,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
|
@ -274,8 +282,13 @@ const EditNodeModal = forwardRef(
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "NestedDict" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(templateParam) === "NestedDict"
|
||||
}
|
||||
>
|
||||
<div className=" w-full">
|
||||
<DictComponent
|
||||
disabled={disabled}
|
||||
|
|
@ -296,21 +309,24 @@ const EditNodeModal = forwardRef(
|
|||
].value = newValue;
|
||||
handleOnNewValue(
|
||||
newValue,
|
||||
templateParam
|
||||
templateParam,
|
||||
);
|
||||
}}
|
||||
id="editnode-div-dict-input"
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "dict" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "dict"}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
"max-h-48 w-full overflow-auto custom-scroll",
|
||||
myData.node!.template[templateParam].value
|
||||
?.length > 1
|
||||
? "my-3"
|
||||
: ""
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
<KeypairListComponent
|
||||
|
|
@ -325,7 +341,8 @@ const EditNodeModal = forwardRef(
|
|||
: convertObjToArray(
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
].value
|
||||
].value,
|
||||
type(templateParam)!,
|
||||
)
|
||||
}
|
||||
duplicateKey={errorDuplicateKey}
|
||||
|
|
@ -336,11 +353,11 @@ const EditNodeModal = forwardRef(
|
|||
templateParam
|
||||
].value = valueToNumbers;
|
||||
setErrorDuplicateKey(
|
||||
hasDuplicateKeys(valueToNumbers)
|
||||
hasDuplicateKeys(valueToNumbers),
|
||||
);
|
||||
handleOnNewValue(
|
||||
valueToNumbers,
|
||||
templateParam
|
||||
templateParam,
|
||||
);
|
||||
}}
|
||||
isList={
|
||||
|
|
@ -349,32 +366,39 @@ const EditNodeModal = forwardRef(
|
|||
}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "bool" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "bool"}
|
||||
>
|
||||
<div className="ml-auto">
|
||||
{" "}
|
||||
<ToggleShadComponent
|
||||
id={
|
||||
"toggle-edit-" +
|
||||
myData.node.template[templateParam].name
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
disabled={disabled}
|
||||
enabled={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value
|
||||
}
|
||||
setEnabled={(isEnabled) => {
|
||||
handleOnNewValue(
|
||||
isEnabled,
|
||||
templateParam
|
||||
templateParam,
|
||||
);
|
||||
}}
|
||||
size="small"
|
||||
editNode={true}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "float" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "float"}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<FloatComponent
|
||||
disabled={disabled}
|
||||
|
|
@ -384,7 +408,7 @@ const EditNodeModal = forwardRef(
|
|||
.rangeSpec
|
||||
}
|
||||
value={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
|
|
@ -392,32 +416,38 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "str" &&
|
||||
myData.node.template[templateParam]
|
||||
.options ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={
|
||||
type(templateParam) === "str" &&
|
||||
myData.node!.template[templateParam].options
|
||||
}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<Dropdown
|
||||
editNode={true}
|
||||
options={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.options
|
||||
}
|
||||
onSelect={(value) =>
|
||||
handleOnNewValue(value, templateParam)
|
||||
}
|
||||
value={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? "Choose an option"
|
||||
}
|
||||
id={
|
||||
"dropdown-edit-" +
|
||||
myData.node.template[templateParam].name
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
></Dropdown>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "int" ? (
|
||||
</Case>
|
||||
|
||||
<Case condition={type(templateParam) === "int"}>
|
||||
<div className="mx-auto">
|
||||
<IntComponent
|
||||
rangeSpec={
|
||||
|
|
@ -426,12 +456,13 @@ const EditNodeModal = forwardRef(
|
|||
}
|
||||
id={
|
||||
"edit-int-input-" +
|
||||
myData.node.template[templateParam].name
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
|
|
@ -439,21 +470,24 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "file" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "file"}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<InputFileComponent
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
value={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
fileTypes={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.fileTypes
|
||||
}
|
||||
onFileChange={(filePath: string) => {
|
||||
|
|
@ -463,8 +497,11 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
></InputFileComponent>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "prompt" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "prompt"}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<PromptAreaComponent
|
||||
readonly={
|
||||
|
|
@ -478,7 +515,7 @@ const EditNodeModal = forwardRef(
|
|||
myData.node = nodeClass;
|
||||
}}
|
||||
value={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value: string | string[]) => {
|
||||
|
|
@ -486,21 +523,26 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
id={
|
||||
"prompt-area-edit-" +
|
||||
myData.node.template[templateParam].name
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
data-testid={
|
||||
"modal-prompt-input-" +
|
||||
myData.node.template[templateParam].name
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "code" ? (
|
||||
</Case>
|
||||
|
||||
<Case
|
||||
condition={type(templateParam) === "code"}
|
||||
>
|
||||
<div className="mx-auto">
|
||||
<CodeAreaComponent
|
||||
readonly={
|
||||
myData.node?.flow &&
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.dynamic
|
||||
? true
|
||||
: false
|
||||
|
|
@ -516,7 +558,7 @@ const EditNodeModal = forwardRef(
|
|||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value: string | string[]) => {
|
||||
|
|
@ -524,16 +566,16 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
id={
|
||||
"code-area-edit" +
|
||||
myData.node.template[templateParam].name
|
||||
myData.node!.template[templateParam]
|
||||
.name
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "Any" ? (
|
||||
"-"
|
||||
) : (
|
||||
<div className="hidden"></div>
|
||||
)}
|
||||
</Case>
|
||||
|
||||
<Case condition={type(templateParam) === "Any"}>
|
||||
<>-</>
|
||||
</Case>
|
||||
</TableCell>
|
||||
<TableCell className="p-0 text-right">
|
||||
<div className="items-center text-center">
|
||||
|
|
@ -588,7 +630,7 @@ const EditNodeModal = forwardRef(
|
|||
</BaseModal.Footer>
|
||||
</BaseModal>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
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 = {
|
||||
family: string;
|
||||
type: string;
|
||||
display_name?: string;
|
||||
};
|
||||
|
||||
export type nodeGroupedObjType = {
|
||||
|
|
|
|||
|
|
@ -461,7 +461,8 @@ export function getConnectedNodes(
|
|||
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") {
|
||||
singleObject = JSON.parse(singleObject);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue