fixed validation

This commit is contained in:
anovazzi1 2023-04-28 23:03:13 -03:00
commit f97586813c
2 changed files with 166 additions and 187 deletions

View file

@ -62,5 +62,5 @@
"last 1 safari version" "last 1 safari version"
] ]
}, },
"proxy": "http://backend:7860" "proxy": "http://127.0.0.1:7860"
} }

View file

@ -1,10 +1,10 @@
import { TrashIcon } from "@heroicons/react/24/outline"; import { TrashIcon } from "@heroicons/react/24/outline";
import { useDebouncedCallback } from "use-debounce"; import { useDebouncedCallback } from "use-debounce";
import { import {
classNames, classNames,
nodeColors, nodeColors,
nodeIcons, nodeIcons,
snakeToNormalCase, snakeToNormalCase,
} from "../../utils"; } from "../../utils";
import ParameterComponent from "./components/parameterComponent"; import ParameterComponent from "./components/parameterComponent";
import { typesContext } from "../../contexts/typesContext"; import { typesContext } from "../../contexts/typesContext";
@ -12,198 +12,177 @@ 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";
import { TabsContext } from "../../contexts/tabsContext";
export default function GenericNode({ export default function GenericNode({
data, data,
selected, selected,
}: { }: {
data: NodeDataType; data: NodeDataType;
selected: boolean; selected: boolean;
}) { }) {
const { setErrorData } = useContext(alertContext); const { setErrorData } = useContext(alertContext);
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"); const [validationStatus, setValidationStatus] = useState("idle");
// State for outline color // State for outline color
const [isGreenOutline, setIsGreenOutline] = useState(false); const [isValid, setIsValid] = useState(false);
const [isRedOutline, setIsRedOutline] = useState(false); const {save} = useContext(TabsContext)
const { reactFlowInstance } = useContext(typesContext); const { reactFlowInstance } = useContext(typesContext);
const [params, setParams] = useState([]); const [params, setParams] = useState([]);
useEffect(() => { console.log();
if (reactFlowInstance) {
setParams(Object.values(reactFlowInstance.toObject()));
}
}, [reactFlowInstance]);
const debouncedValidateNode = useDebouncedCallback(async () => { useEffect(() => {
// Check if the validationStatus is "success" if (reactFlowInstance) {
// if (validationStatus === "success") return; setParams(Object.values(reactFlowInstance.toObject()));
}
}, [save]);
try { useEffect(() => {
const response = await fetch(`/validate/node/${data.id}`, { try {
method: "POST", fetch(`/validate/node/${data.id}`, {
headers: { method: "POST",
"Content-Type": "application/json", headers: {
}, "Content-Type": "application/json",
body: JSON.stringify(reactFlowInstance.toObject()), },
}); body: JSON.stringify(reactFlowInstance.toObject()),
}).then((response) => {
console.log(response.status, response.body);
if (response.status === 200) { if (response.status === 200) {
setValidationStatus("success"); setValidationStatus("success");
} else if (response.status === 500) { } else if (response.status === 500) {
setValidationStatus("error"); setValidationStatus("error");
} }
} catch (error) { });
console.error("Error validating node:", error); } catch (error) {
setValidationStatus("error"); console.error("Error validating node:", error);
} setValidationStatus("error");
}, 1000); }
}, [params]);
const validateNode = useCallback(() => { useEffect(() => {
debouncedValidateNode(); if (validationStatus === "success") {
}, [debouncedValidateNode]); setIsValid(true);
} else {
setIsValid(false);
}
}, [validationStatus]);
useEffect(() => { if (!Icon) {
validateNode(); if (showError.current) {
}, [validateNode, params]); setErrorData({
title: data.type
? `The ${data.type} node could not be rendered, please review your json file`
: "There was a node that can't be rendered, please review your json file",
});
showError.current = false;
}
deleteNode(data.id);
return;
}
useEffect(() => { return (
if (validationStatus === "success") { <div
setIsGreenOutline(true); className={classNames(
setIsRedOutline(false); isValid ? "animate-pulse-green" : "border-red-outline",
setTimeout(() => { selected ? "border border-blue-500" : "border dark:border-gray-700",
setIsGreenOutline(false); "prompt-node relative bg-white dark:bg-gray-900 w-96 rounded-lg flex flex-col justify-center"
}, 1000); )}
} else if (validationStatus === "error") { >
setIsRedOutline(true); <div className="w-full dark:text-white flex items-center justify-between p-4 gap-8 bg-gray-50 rounded-t-lg dark:bg-gray-800 border-b dark:border-b-gray-700 ">
setIsGreenOutline(false); <div className="w-full flex items-center truncate gap-4 text-lg">
} else { <Icon
setIsGreenOutline(false); className="w-10 h-10 p-1 rounded"
setIsRedOutline(false); style={{
} color: nodeColors[types[data.type]] ?? nodeColors.unknown,
}, [validationStatus]); }}
/>
<div className="truncate">{data.type}</div>
</div>
<button
onClick={() => {
deleteNode(data.id);
}}
>
<TrashIcon className="w-6 h-6 hover:text-red-500 dark:text-gray-500 dark:hover:text-red-500"></TrashIcon>
</button>
</div>
const outlineColor = isGreenOutline <div className="w-full h-full py-5">
? "animate-pulse-green" <div className="w-full text-gray-500 px-5 text-sm">
: isRedOutline {data.node.description}
? "border-red-outline" </div>
: "";
if (!Icon) { <>
if (showError.current) { {Object.keys(data.node.template)
setErrorData({ .filter((t) => t.charAt(0) !== "_")
title: data.type .map((t: string, idx) => (
? `The ${data.type} node could not be rendered, please review your json file` <div key={idx}>
: "There was a node that can't be rendered, please review your json file", {idx === 0 ? (
}); <div
showError.current = false; className={classNames(
} "px-5 py-2 mt-2 dark:text-white text-center",
deleteNode(data.id); Object.keys(data.node.template).filter(
return; (key) =>
} !key.startsWith("_") &&
data.node.template[key].show &&
return ( !data.node.template[key].advanced
<div ).length === 0
className={classNames( ? "hidden"
outlineColor, : ""
selected ? "border border-blue-500" : "border dark:border-gray-700", )}
"prompt-node relative bg-white dark:bg-gray-900 w-96 rounded-lg flex flex-col justify-center" >
)} Inputs
> </div>
<div className="w-full dark:text-white flex items-center justify-between p-4 gap-8 bg-gray-50 rounded-t-lg dark:bg-gray-800 border-b dark:border-b-gray-700 "> ) : (
<div className="w-full flex items-center truncate gap-4 text-lg"> <></>
<Icon )}
className="w-10 h-10 p-1 rounded" {data.node.template[t].show ? (
style={{ <ParameterComponent
color: nodeColors[types[data.type]] ?? nodeColors.unknown, data={data}
}} color={
/> nodeColors[types[data.node.template[t].type]] ??
<div className="truncate">{data.type}</div> nodeColors.unknown
</div> }
<button title={
onClick={() => { data.node.template[t].display_name
deleteNode(data.id); ? data.node.template[t].display_name
}} : data.node.template[t].name
> ? snakeToNormalCase(data.node.template[t].name)
<TrashIcon className="w-6 h-6 hover:text-red-500 dark:text-gray-500 dark:hover:text-red-500"></TrashIcon> : snakeToNormalCase(t)
</button> }
</div> name={t}
tooltipTitle={
<div className="w-full h-full py-5"> "Type: " +
<div className="w-full text-gray-500 px-5 text-sm"> data.node.template[t].type +
{data.node.description} (data.node.template[t].list ? " list" : "")
</div> }
required={data.node.template[t].required}
<> id={data.node.template[t].type + "|" + t + "|" + data.id}
{Object.keys(data.node.template) left={true}
.filter((t) => t.charAt(0) !== "_") type={data.node.template[t].type}
.map((t: string, idx) => ( />
<div key={idx}> ) : (
{idx === 0 ? ( <></>
<div )}
className={classNames( </div>
"px-5 py-2 mt-2 dark:text-white text-center", ))}
Object.keys(data.node.template).filter( <div className="px-5 py-2 mt-2 dark:text-white text-center">
(key) => Output
!key.startsWith("_") && </div>
data.node.template[key].show && <ParameterComponent
!data.node.template[key].advanced data={data}
).length === 0 color={nodeColors[types[data.type]] ?? nodeColors.unknown}
? "hidden" title={data.type}
: "" tooltipTitle={`Type: ${data.node.base_classes.join(" | ")}`}
)} id={[data.type, data.id, ...data.node.base_classes].join("|")}
> type={data.node.base_classes.join("|")}
Inputs left={false}
</div> />
) : ( </>
<></> </div>
)} </div>
{data.node.template[t].show ? ( );
<ParameterComponent
data={data}
color={
nodeColors[types[data.node.template[t].type]] ??
nodeColors.unknown
}
title={
data.node.template[t].display_name
? data.node.template[t].display_name
: data.node.template[t].name
? snakeToNormalCase(data.node.template[t].name)
: snakeToNormalCase(t)
}
name={t}
tooltipTitle={
"Type: " +
data.node.template[t].type +
(data.node.template[t].list ? " list" : "")
}
required={data.node.template[t].required}
id={data.node.template[t].type + "|" + t + "|" + data.id}
left={true}
type={data.node.template[t].type}
/>
) : (
<></>
)}
</div>
))}
<div className="px-5 py-2 mt-2 dark:text-white text-center">
Output
</div>
<ParameterComponent
data={data}
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
title={data.type}
tooltipTitle={`Type: ${data.node.base_classes.join(" | ")}`}
id={[data.type, data.id, ...data.node.base_classes].join("|")}
type={data.node.base_classes.join("|")}
left={false}
/>
</>
</div>
</div>
);
} }