feat(validate): add debounced validation for nodes in GenericNode component
fix(validate): set validation status to "success" or "error" based on response status feat(validate): add state for validation status and outline color in GenericNode component refactor(validate): use useDebouncedCallback hook for debouncing validation function refactor(validate): simplify useEffect dependencies in GenericNode component
This commit is contained in:
parent
f122151b12
commit
7af5f68861
2 changed files with 180 additions and 163 deletions
|
|
@ -46,7 +46,7 @@ def post_validate_node(node_id: str, data: dict):
|
||||||
node = graph.get_node(node_id)
|
node = graph.get_node(node_id)
|
||||||
if node is not None:
|
if node is not None:
|
||||||
_ = node.build()
|
_ = node.build()
|
||||||
return node.params
|
return str(node.params)
|
||||||
raise Exception(f"Node {node_id} not found")
|
raise Exception(f"Node {node_id} not found")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { TrashIcon } from "@heroicons/react/24/outline";
|
import { TrashIcon } from "@heroicons/react/24/outline";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import {
|
import {
|
||||||
classNames,
|
classNames,
|
||||||
nodeColors,
|
nodeColors,
|
||||||
|
|
@ -10,7 +11,7 @@ import { typesContext } from "../../contexts/typesContext";
|
||||||
import { useContext, useState, useEffect, useRef } from "react";
|
import { useContext, useState, useEffect, useRef } from "react";
|
||||||
import { NodeDataType } from "../../types/flow";
|
import { NodeDataType } from "../../types/flow";
|
||||||
import { alertContext } from "../../contexts/alertContext";
|
import { alertContext } from "../../contexts/alertContext";
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from "react";
|
||||||
|
|
||||||
export default function GenericNode({
|
export default function GenericNode({
|
||||||
data,
|
data,
|
||||||
|
|
@ -23,52 +24,68 @@ export default function GenericNode({
|
||||||
const showError = useRef(true);
|
const showError = useRef(true);
|
||||||
const { types, deleteNode } = useContext(typesContext);
|
const { types, deleteNode } = useContext(typesContext);
|
||||||
const Icon = nodeIcons[types[data.type]];
|
const Icon = nodeIcons[types[data.type]];
|
||||||
|
const [validationStatus, setValidationStatus] = useState("idle");
|
||||||
// State for outline color
|
// State for outline color
|
||||||
const [isGreenOutline, setIsGreenOutline] = useState(false);
|
const [isGreenOutline, setIsGreenOutline] = useState(false);
|
||||||
const [isRedOutline, setIsRedOutline] = useState(false);
|
const [isRedOutline, setIsRedOutline] = useState(false);
|
||||||
const { reactFlowInstance } = useContext(typesContext);
|
const { reactFlowInstance } = useContext(typesContext);
|
||||||
|
|
||||||
const validateNode = useCallback(async () => {
|
const debouncedValidateNode = useDebouncedCallback(async () => {
|
||||||
|
// Check if the validationStatus is "success"
|
||||||
|
if (validationStatus === "success") return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/validate/node/${data.id}`, {
|
const response = await fetch(`/validate/node/${data.id}`, {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(reactFlowInstance.toObject()),
|
body: JSON.stringify(reactFlowInstance.toObject()),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
setIsGreenOutline(true);
|
setValidationStatus("success");
|
||||||
setIsRedOutline(false);
|
|
||||||
} else if (response.status === 500) {
|
} else if (response.status === 500) {
|
||||||
setIsRedOutline(true);
|
setValidationStatus("error");
|
||||||
setIsGreenOutline(false);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error validating node:', error);
|
console.error("Error validating node:", error);
|
||||||
setIsRedOutline(true);
|
setValidationStatus("error");
|
||||||
}
|
}
|
||||||
}, [data.id, reactFlowInstance]);
|
}, 1000);
|
||||||
|
|
||||||
|
const validateNode = useCallback(() => {
|
||||||
|
debouncedValidateNode();
|
||||||
|
}, [debouncedValidateNode]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
validateNode();
|
validateNode();
|
||||||
}, [
|
}, [
|
||||||
validateNode,
|
validateNode,
|
||||||
...Object.values(data.node.template).flatMap((t) => Object.values(t)),
|
...Object.values(data.node.template).flatMap((t) => Object.values(t)),
|
||||||
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isGreenOutline) {
|
if (validationStatus === "success") {
|
||||||
|
setIsGreenOutline(true);
|
||||||
|
setIsRedOutline(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsGreenOutline(false);
|
setIsGreenOutline(false);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
} else if (validationStatus === "error") {
|
||||||
|
setIsRedOutline(true);
|
||||||
|
setIsGreenOutline(false);
|
||||||
|
} else {
|
||||||
|
setIsGreenOutline(false);
|
||||||
|
setIsRedOutline(false);
|
||||||
}
|
}
|
||||||
}, [isGreenOutline]);
|
}, [validationStatus]);
|
||||||
|
|
||||||
const outlineColor = isGreenOutline ? 'animate-pulse-green' : isRedOutline ? 'border-red-outline' : '';
|
const outlineColor = isGreenOutline
|
||||||
|
? "animate-pulse-green"
|
||||||
|
: isRedOutline
|
||||||
|
? "border-red-outline"
|
||||||
|
: "";
|
||||||
|
|
||||||
if (!Icon) {
|
if (!Icon) {
|
||||||
if (showError.current) {
|
if (showError.current) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue