Fixed state handling of Prompt Component, undo working
This commit is contained in:
parent
fb3c1df882
commit
82ef6bc72a
7 changed files with 55 additions and 50 deletions
|
|
@ -31,9 +31,11 @@ import { FlowsContext } from "../../../../contexts/flowsContext";
|
||||||
import { typesContext } from "../../../../contexts/typesContext";
|
import { typesContext } from "../../../../contexts/typesContext";
|
||||||
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
|
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
|
||||||
import { postCustomComponentUpdate } from "../../../../controllers/API";
|
import { postCustomComponentUpdate } from "../../../../controllers/API";
|
||||||
|
import { APIClassType } from "../../../../types/api";
|
||||||
import { ParameterComponentType } from "../../../../types/components";
|
import { ParameterComponentType } from "../../../../types/components";
|
||||||
import { NodeDataType } from "../../../../types/flow";
|
import { NodeDataType } from "../../../../types/flow";
|
||||||
import {
|
import {
|
||||||
|
cleanEdges,
|
||||||
convertObjToArray,
|
convertObjToArray,
|
||||||
convertValuesToNumbers,
|
convertValuesToNumbers,
|
||||||
hasDuplicateKeys,
|
hasDuplicateKeys,
|
||||||
|
|
@ -69,7 +71,8 @@ export default function ParameterComponent({
|
||||||
const { setErrorData } = useContext(alertContext);
|
const { setErrorData } = useContext(alertContext);
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
const [position, setPosition] = useState(0);
|
const [position, setPosition] = useState(0);
|
||||||
const { setTabsState, tabId, flows, tabsState } = useContext(FlowsContext);
|
const { setTabsState, tabId, flows, tabsState, updateFlow } =
|
||||||
|
useContext(FlowsContext);
|
||||||
|
|
||||||
const flow = flows.find((flow) => flow.id === tabId)?.data?.nodes ?? null;
|
const flow = flows.find((flow) => flow.id === tabId)?.data?.nodes ?? null;
|
||||||
|
|
||||||
|
|
@ -139,6 +142,40 @@ export default function ParameterComponent({
|
||||||
renderTooltips();
|
renderTooltips();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleNodeClass = (newNodeClass: APIClassType, code?: string): void => {
|
||||||
|
if (data.node!.template[name].value !== newNodeClass.template[name].value) {
|
||||||
|
takeSnapshot();
|
||||||
|
}
|
||||||
|
data.node = newNodeClass;
|
||||||
|
data.node.template[name].value = code;
|
||||||
|
updateNodeInternals(data.id);
|
||||||
|
// Set state to pending
|
||||||
|
//@ts-ignore
|
||||||
|
if (data.node!.template[name].value !== code) {
|
||||||
|
const tabs = cloneDeep(tabsState);
|
||||||
|
tabs[tabId].isPending = false;
|
||||||
|
tabs[tabId].formKeysData = tabsState[tabId].formKeysData;
|
||||||
|
setTabsState({
|
||||||
|
...tabs,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
renderTooltips();
|
||||||
|
let flow = flows.find((flow) => flow.id === tabId);
|
||||||
|
if (reactFlowInstance && flow && flow.data) {
|
||||||
|
cleanEdges({
|
||||||
|
flow: {
|
||||||
|
edges: flow.data!.edges,
|
||||||
|
nodes: flow.data!.nodes,
|
||||||
|
},
|
||||||
|
updateEdge: (edge) => {
|
||||||
|
reactFlowInstance.setEdges(edge);
|
||||||
|
updateNodeInternals(data.id);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
updateFlow(flow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -443,9 +480,7 @@ export default function ParameterComponent({
|
||||||
: false
|
: false
|
||||||
}
|
}
|
||||||
dynamic={data.node?.template[name].dynamic ?? false}
|
dynamic={data.node?.template[name].dynamic ?? false}
|
||||||
setNodeClass={(nodeClass) => {
|
setNodeClass={handleNodeClass}
|
||||||
data.node = nodeClass;
|
|
||||||
}}
|
|
||||||
nodeClass={data.node}
|
nodeClass={data.node}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node?.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
|
|
@ -479,15 +514,11 @@ export default function ParameterComponent({
|
||||||
<PromptAreaComponent
|
<PromptAreaComponent
|
||||||
readonly={data.node?.flow ? true : false}
|
readonly={data.node?.flow ? true : false}
|
||||||
field_name={name}
|
field_name={name}
|
||||||
setNodeClass={(nodeClass) => {
|
setNodeClass={handleNodeClass}
|
||||||
data.node = nodeClass;
|
|
||||||
}}
|
|
||||||
nodeClass={data.node}
|
nodeClass={data.node}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node?.template[name].value ?? ""}
|
value={data.node?.template[name].value ?? ""}
|
||||||
onChange={(e) => {
|
onChange={handleOnNewValue}
|
||||||
handleOnNewValue(e);
|
|
||||||
}}
|
|
||||||
id={"prompt-input-" + index}
|
id={"prompt-input-" + index}
|
||||||
data-testid={"prompt-input-" + index}
|
data-testid={"prompt-input-" + index}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,7 @@ import { undoRedoContext } from "../../contexts/undoRedoContext";
|
||||||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||||
import { validationStatusType } from "../../types/components";
|
import { validationStatusType } from "../../types/components";
|
||||||
import { NodeDataType } from "../../types/flow";
|
import { NodeDataType } from "../../types/flow";
|
||||||
import {
|
import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils";
|
||||||
cleanEdges,
|
|
||||||
handleKeyDown,
|
|
||||||
scapedJSONStringfy,
|
|
||||||
} from "../../utils/reactflowUtils";
|
|
||||||
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
|
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
|
||||||
import { classNames, getFieldTitle } from "../../utils/utils";
|
import { classNames, getFieldTitle } from "../../utils/utils";
|
||||||
import ParameterComponent from "./components/parameterComponent";
|
import ParameterComponent from "./components/parameterComponent";
|
||||||
|
|
@ -85,27 +81,10 @@ export default function GenericNode({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
countHandles();
|
countHandles();
|
||||||
}, []);
|
}, [data, data.node]);
|
||||||
|
|
||||||
// State for outline color
|
// State for outline color
|
||||||
const { sseData, isBuilding } = useSSE();
|
const { sseData, isBuilding } = useSSE();
|
||||||
useEffect(() => {
|
|
||||||
let flow = flows.find((flow) => flow.id === tabId);
|
|
||||||
if (reactFlowInstance && flow && flow.data) {
|
|
||||||
cleanEdges({
|
|
||||||
flow: {
|
|
||||||
edges: flow.data!.edges,
|
|
||||||
nodes: flow.data!.nodes,
|
|
||||||
},
|
|
||||||
updateEdge: (edge) => {
|
|
||||||
reactFlowInstance.setEdges(edge);
|
|
||||||
updateNodeInternals(data.id);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
updateFlow(flow);
|
|
||||||
}
|
|
||||||
countHandles();
|
|
||||||
}, [modalContextOpen]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setNodeDescription(data.node!.description);
|
setNodeDescription(data.node!.description);
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,7 @@ export default function PromptAreaComponent({
|
||||||
value={value}
|
value={value}
|
||||||
buttonText="Check & Save"
|
buttonText="Check & Save"
|
||||||
modalTitle="Edit Prompt"
|
modalTitle="Edit Prompt"
|
||||||
setValue={(value: string) => {
|
setValue={onChange}
|
||||||
onChange(value);
|
|
||||||
}}
|
|
||||||
nodeClass={nodeClass}
|
nodeClass={nodeClass}
|
||||||
setNodeClass={setNodeClass}
|
setNodeClass={setNodeClass}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -150,9 +150,9 @@ const EditNodeModal = forwardRef(
|
||||||
.map((templateParam, index) => {
|
.map((templateParam, index) => {
|
||||||
let id = {
|
let id = {
|
||||||
inputTypes:
|
inputTypes:
|
||||||
data.node!.template[templateParam].input_types,
|
myData.node!.template[templateParam].input_types,
|
||||||
type: data.node!.template[templateParam].type,
|
type: myData.node!.template[templateParam].type,
|
||||||
id: data.id,
|
id: myData.id,
|
||||||
fieldName: templateParam,
|
fieldName: templateParam,
|
||||||
};
|
};
|
||||||
let disabled =
|
let disabled =
|
||||||
|
|
@ -160,11 +160,11 @@ const EditNodeModal = forwardRef(
|
||||||
(edge) =>
|
(edge) =>
|
||||||
edge.targetHandle ===
|
edge.targetHandle ===
|
||||||
scapedJSONStringfy(
|
scapedJSONStringfy(
|
||||||
data.node!.template[templateParam].proxy
|
myData.node!.template[templateParam].proxy
|
||||||
? {
|
? {
|
||||||
...id,
|
...id,
|
||||||
proxy:
|
proxy:
|
||||||
data.node?.template[templateParam]
|
myData.node?.template[templateParam]
|
||||||
.proxy,
|
.proxy,
|
||||||
}
|
}
|
||||||
: id
|
: id
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,7 @@ export default function CodeAreaModal({
|
||||||
.then((apiReturn) => {
|
.then((apiReturn) => {
|
||||||
const { data } = apiReturn;
|
const { data } = apiReturn;
|
||||||
if (data) {
|
if (data) {
|
||||||
setNodeClass(data);
|
setNodeClass(data, code);
|
||||||
setValue(code);
|
|
||||||
setError({ detail: { error: undefined, traceback: undefined } });
|
setError({ detail: { error: undefined, traceback: undefined } });
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,6 @@ export default function GenericModal({
|
||||||
// if field_name is an empty string, then we need to set it
|
// if field_name is an empty string, then we need to set it
|
||||||
// to the first key of the custom_fields object
|
// to the first key of the custom_fields object
|
||||||
if (field_name === "") {
|
if (field_name === "") {
|
||||||
console.log(apiReturn.data?.frontend_node?.custom_fields);
|
|
||||||
field_name = Array.isArray(
|
field_name = Array.isArray(
|
||||||
apiReturn.data?.frontend_node?.custom_fields?.[""]
|
apiReturn.data?.frontend_node?.custom_fields?.[""]
|
||||||
)
|
)
|
||||||
|
|
@ -134,9 +133,8 @@ export default function GenericModal({
|
||||||
JSON.stringify(apiReturn.data?.frontend_node) !==
|
JSON.stringify(apiReturn.data?.frontend_node) !==
|
||||||
JSON.stringify({})
|
JSON.stringify({})
|
||||||
) {
|
) {
|
||||||
setNodeClass!(apiReturn.data?.frontend_node);
|
setNodeClass!(apiReturn.data?.frontend_node, inputValue);
|
||||||
setModalOpen(closeModal);
|
setModalOpen(closeModal);
|
||||||
setValue(inputValue);
|
|
||||||
setIsEdit(false);
|
setIsEdit(false);
|
||||||
setSuccessData({
|
setSuccessData({
|
||||||
title: "Prompt is ready",
|
title: "Prompt is ready",
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ export type TextAreaComponentType = {
|
||||||
export type PromptAreaComponentType = {
|
export type PromptAreaComponentType = {
|
||||||
field_name?: string;
|
field_name?: string;
|
||||||
nodeClass?: APIClassType;
|
nodeClass?: APIClassType;
|
||||||
setNodeClass?: (value: APIClassType) => void;
|
setNodeClass?: (value: APIClassType, code?: string) => void;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
onChange: (value: string[] | string) => void;
|
onChange: (value: string[] | string) => void;
|
||||||
value: string;
|
value: string;
|
||||||
|
|
@ -110,7 +110,7 @@ export type CodeAreaComponentType = {
|
||||||
value: string;
|
value: string;
|
||||||
editNode?: boolean;
|
editNode?: boolean;
|
||||||
nodeClass?: APIClassType;
|
nodeClass?: APIClassType;
|
||||||
setNodeClass?: (value: APIClassType) => void;
|
setNodeClass?: (value: APIClassType, code?: string) => void;
|
||||||
dynamic?: boolean;
|
dynamic?: boolean;
|
||||||
id?: string;
|
id?: string;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
|
|
@ -500,7 +500,7 @@ export type codeAreaModalPropsType = {
|
||||||
setValue: (value: string) => void;
|
setValue: (value: string) => void;
|
||||||
value: string;
|
value: string;
|
||||||
nodeClass: APIClassType | undefined;
|
nodeClass: APIClassType | undefined;
|
||||||
setNodeClass: (Class: APIClassType) => void | undefined;
|
setNodeClass: (Class: APIClassType, code?: string) => void | undefined;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
dynamic?: boolean;
|
dynamic?: boolean;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
|
|
@ -526,7 +526,7 @@ export type genericModalPropsType = {
|
||||||
modalTitle: string;
|
modalTitle: string;
|
||||||
type: number;
|
type: number;
|
||||||
nodeClass?: APIClassType;
|
nodeClass?: APIClassType;
|
||||||
setNodeClass?: (Class: APIClassType) => void;
|
setNodeClass?: (Class: APIClassType, code?: string) => void;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
id?: string;
|
id?: string;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue