Add parameterUtils.ts file with handleUpdateValues and throttledHandleUpdateValues functions
This commit is contained in:
parent
0044622d3a
commit
1a8891134c
2 changed files with 116 additions and 72 deletions
|
|
@ -23,14 +23,16 @@ import {
|
||||||
OUTPUT_HANDLER_HOVER,
|
OUTPUT_HANDLER_HOVER,
|
||||||
TOOLTIP_EMPTY,
|
TOOLTIP_EMPTY,
|
||||||
} from "../../../../constants/constants";
|
} from "../../../../constants/constants";
|
||||||
import { postCustomComponentUpdate } from "../../../../controllers/API";
|
|
||||||
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 { APIClassType } from "../../../../types/api";
|
import { APIClassType, ResponseErrorTypeAPI } from "../../../../types/api";
|
||||||
import { ParameterComponentType } from "../../../../types/components";
|
import { ParameterComponentType } from "../../../../types/components";
|
||||||
import { NodeDataType } from "../../../../types/flow";
|
import {
|
||||||
|
handleUpdateValues,
|
||||||
|
throttledHandleUpdateValues,
|
||||||
|
} from "../../../../utils/parameterUtils";
|
||||||
import {
|
import {
|
||||||
convertObjToArray,
|
convertObjToArray,
|
||||||
convertValuesToNumbers,
|
convertValuesToNumbers,
|
||||||
|
|
@ -86,81 +88,70 @@ export default function ParameterComponent({
|
||||||
|
|
||||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||||
|
|
||||||
const handleUpdateValues = async (
|
|
||||||
name: string,
|
|
||||||
data: NodeDataType,
|
|
||||||
delayAnimation: boolean = true
|
|
||||||
) => {
|
|
||||||
setIsLoading(true);
|
|
||||||
const code = data.node?.template["code"]?.value;
|
|
||||||
if (!code) {
|
|
||||||
console.error("Code not found in the template");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await postCustomComponentUpdate(
|
|
||||||
code,
|
|
||||||
name,
|
|
||||||
data.node?.template[name]?.value
|
|
||||||
)
|
|
||||||
.then((res) => {
|
|
||||||
if (res.status === 200 && data.node?.template) {
|
|
||||||
setNode(data.id, (oldNode) => {
|
|
||||||
let newNode = cloneDeep(oldNode);
|
|
||||||
|
|
||||||
newNode.data = {
|
|
||||||
...newNode.data,
|
|
||||||
};
|
|
||||||
|
|
||||||
newNode.data.node.template = res.data.template;
|
|
||||||
|
|
||||||
return newNode;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Error occurred while updating the node:", error);
|
|
||||||
setErrorData({
|
|
||||||
title: "Error while updating the Component",
|
|
||||||
list: [error.response.data.detail.error ?? "Unknown error"],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
renderTooltips();
|
|
||||||
if (delayAnimation) {
|
|
||||||
try {
|
|
||||||
// Wait for at least 500 milliseconds
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
||||||
// Continue with the request
|
|
||||||
// If the request takes longer than 500 milliseconds, it will not wait an additional 500 milliseconds
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error occurred while waiting for refresh:", error);
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
} else setIsLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function fetchData() {
|
async function fetchData() {
|
||||||
if (
|
if (
|
||||||
data.node?.template[name]?.refresh &&
|
data.node?.template[name]?.refresh &&
|
||||||
Object.keys(data.node?.template[name]?.options ?? {}).length === 0
|
// options can be undefined but not an empty array
|
||||||
|
(data.node?.template[name]?.options?.length ?? 0) === 0
|
||||||
) {
|
) {
|
||||||
handleUpdateValues(name, data, false);
|
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 ResponseErrorTypeAPI;
|
||||||
|
setErrorData({
|
||||||
|
title: "Error while updating the Component",
|
||||||
|
list: [responseError.response.data.detail.error ?? "Unknown error"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
renderTooltips();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fetchData();
|
fetchData();
|
||||||
}, []);
|
}, []);
|
||||||
const handleOnNewValue = (
|
const handleOnNewValue = async (
|
||||||
newValue: string | string[] | boolean | Object[]
|
newValue: string | string[] | boolean | Object[]
|
||||||
): void => {
|
): Promise<void> => {
|
||||||
if (data.node!.template[name].value !== newValue) {
|
if (data.node!.template[name].value !== newValue) {
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
}
|
}
|
||||||
|
const shouldUpdate =
|
||||||
|
data.node?.template[name].refresh &&
|
||||||
|
data.node!.template[name].value !== newValue;
|
||||||
|
console.log("shouldUpdate", shouldUpdate);
|
||||||
|
console.log(
|
||||||
|
"data.node!.template[name].value",
|
||||||
|
data.node!.template[name].value
|
||||||
|
);
|
||||||
|
console.log("newValue", newValue);
|
||||||
data.node!.template[name].value = newValue; // necessary to enable ctrl+z inside the input
|
data.node!.template[name].value = newValue; // necessary to enable ctrl+z inside the input
|
||||||
|
let newTemplate;
|
||||||
|
if (shouldUpdate) {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
newTemplate = await throttledHandleUpdateValues(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);
|
||||||
|
// this de
|
||||||
|
}
|
||||||
setNode(data.id, (oldNode) => {
|
setNode(data.id, (oldNode) => {
|
||||||
let newNode = cloneDeep(oldNode);
|
let newNode = cloneDeep(oldNode);
|
||||||
|
|
||||||
|
|
@ -168,7 +159,9 @@ export default function ParameterComponent({
|
||||||
...newNode.data,
|
...newNode.data,
|
||||||
};
|
};
|
||||||
|
|
||||||
newNode.data.node.template[name].value = newValue;
|
if (data.node?.template[name].refresh && newTemplate) {
|
||||||
|
newNode.data.node.template = newTemplate;
|
||||||
|
} else newNode.data.node.template[name].value = newValue;
|
||||||
|
|
||||||
return newNode;
|
return newNode;
|
||||||
});
|
});
|
||||||
|
|
@ -300,11 +293,14 @@ export default function ParameterComponent({
|
||||||
refHtml.current = <span>{TOOLTIP_EMPTY}</span>;
|
refHtml.current = <span>{TOOLTIP_EMPTY}</span>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If optionalHandle is an empty list, then it is not an optional handle
|
||||||
|
if (optionalHandle && optionalHandle.length === 0) {
|
||||||
|
optionalHandle = null;
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
renderTooltips();
|
renderTooltips();
|
||||||
}, [tooltipTitle, flow]);
|
}, [tooltipTitle, flow]);
|
||||||
|
|
||||||
return !showNode ? (
|
return !showNode ? (
|
||||||
left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? (
|
||||||
<></>
|
<></>
|
||||||
|
|
@ -451,7 +447,9 @@ export default function ParameterComponent({
|
||||||
{data.node?.template[name].list ? (
|
{data.node?.template[name].list ? (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
(data.node?.template[name].refresh ? "w-5/6 " : "") +
|
// Commenting this out until we have a better
|
||||||
|
// way to display
|
||||||
|
// (data.node?.template[name].refresh ? "w-5/6 " : "") +
|
||||||
"flex-grow"
|
"flex-grow"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
@ -465,7 +463,7 @@ export default function ParameterComponent({
|
||||||
}
|
}
|
||||||
onChange={handleOnNewValue}
|
onChange={handleOnNewValue}
|
||||||
/>
|
/>
|
||||||
{data.node?.template[name].refresh && (
|
{/* {data.node?.template[name].refresh && (
|
||||||
<div className="w-1/6">
|
<div className="w-1/6">
|
||||||
<RefreshButton
|
<RefreshButton
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
|
@ -477,7 +475,7 @@ export default function ParameterComponent({
|
||||||
id={"refresh-button-" + name}
|
id={"refresh-button-" + name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
) : data.node?.template[name].multiline ? (
|
) : data.node?.template[name].multiline ? (
|
||||||
<TextAreaComponent
|
<TextAreaComponent
|
||||||
|
|
@ -489,7 +487,12 @@ export default function ParameterComponent({
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<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={
|
||||||
|
"flex-grow " +
|
||||||
|
(data.node?.template[name].refresh ? "w-5/6" : "")
|
||||||
|
}
|
||||||
|
>
|
||||||
<InputComponent
|
<InputComponent
|
||||||
id={"input-" + name}
|
id={"input-" + name}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
@ -648,8 +651,14 @@ export default function ParameterComponent({
|
||||||
onChange={(newValue) => {
|
onChange={(newValue) => {
|
||||||
const valueToNumbers = convertValuesToNumbers(newValue);
|
const valueToNumbers = convertValuesToNumbers(newValue);
|
||||||
setErrorDuplicateKey(hasDuplicateKeys(valueToNumbers));
|
setErrorDuplicateKey(hasDuplicateKeys(valueToNumbers));
|
||||||
handleOnNewValue(valueToNumbers);
|
// 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) {
|
||||||
|
handleOnNewValue(valueToNumbers);
|
||||||
|
} else handleOnNewValue(valueToNumbers[0]);
|
||||||
}}
|
}}
|
||||||
|
isList={data.node?.template[name].list ?? false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
35
src/frontend/src/utils/parameterUtils.ts
Normal file
35
src/frontend/src/utils/parameterUtils.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { throttle } from "lodash";
|
||||||
|
import { postCustomComponentUpdate } from "../controllers/API";
|
||||||
|
import { ResponseErrorTypeAPI } from "../types/api";
|
||||||
|
import { NodeDataType } from "../types/flow";
|
||||||
|
|
||||||
|
export const handleUpdateValues = async (name: string, data: NodeDataType) => {
|
||||||
|
const code = data.node?.template["code"]?.value;
|
||||||
|
if (!code) {
|
||||||
|
console.error("Code not found in the template");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
let newTemplate = await postCustomComponentUpdate(
|
||||||
|
code,
|
||||||
|
name,
|
||||||
|
data.node?.template[name]?.value
|
||||||
|
)
|
||||||
|
.then((res) => {
|
||||||
|
console.log("res", res);
|
||||||
|
if (res.status === 200 && data.node?.template) {
|
||||||
|
return res.data.template;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
return newTemplate;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error occurred while updating the node:", error);
|
||||||
|
let errorType = error as ResponseErrorTypeAPI;
|
||||||
|
throw errorType;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const throttledHandleUpdateValues = throttle(handleUpdateValues, 10);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue