Merge branch 'bug/undo-copy' into feature/store
This commit is contained in:
commit
52338db3c5
12 changed files with 155 additions and 171 deletions
|
|
@ -1,4 +1,3 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import React, {
|
||||
ReactNode,
|
||||
useContext,
|
||||
|
|
@ -29,6 +28,7 @@ import {
|
|||
import { alertContext } from "../../../../contexts/alertContext";
|
||||
import { FlowsContext } from "../../../../contexts/flowsContext";
|
||||
import { typesContext } from "../../../../contexts/typesContext";
|
||||
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
|
||||
import { postCustomComponentUpdate } from "../../../../controllers/API";
|
||||
import { ParameterComponentType } from "../../../../types/components";
|
||||
import { NodeDataType } from "../../../../types/flow";
|
||||
|
|
@ -50,7 +50,6 @@ export default function ParameterComponent({
|
|||
left,
|
||||
id,
|
||||
data,
|
||||
setData,
|
||||
tooltipTitle,
|
||||
title,
|
||||
color,
|
||||
|
|
@ -99,6 +98,8 @@ export default function ParameterComponent({
|
|||
|
||||
const { data: myData } = useContext(typesContext);
|
||||
|
||||
const { takeSnapshot } = useContext(undoRedoContext);
|
||||
|
||||
const handleUpdateValues = async (name: string, data: NodeDataType) => {
|
||||
const code = data.node?.template["code"]?.value;
|
||||
if (!code) {
|
||||
|
|
@ -121,9 +122,8 @@ export default function ParameterComponent({
|
|||
const handleOnNewValue = (
|
||||
newValue: string | string[] | boolean | Object[]
|
||||
): void => {
|
||||
let newData = cloneDeep(data);
|
||||
newData.node!.template[name].value = newValue;
|
||||
setData(newData);
|
||||
takeSnapshot();
|
||||
data.node!.template[name].value = newValue;
|
||||
// Set state to pending
|
||||
//@ts-ignore
|
||||
setTabsState((prev: TabsState) => {
|
||||
|
|
@ -484,9 +484,6 @@ export default function ParameterComponent({
|
|||
field_name={name}
|
||||
setNodeClass={(nodeClass) => {
|
||||
data.node = nodeClass;
|
||||
const clone = cloneDeep(data);
|
||||
clone.node = nodeClass;
|
||||
setData(clone);
|
||||
}}
|
||||
nodeClass={data.node}
|
||||
disabled={disabled}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { Textarea } from "../../components/ui/textarea";
|
|||
import { useSSE } from "../../contexts/SSEContext";
|
||||
import { FlowsContext } from "../../contexts/flowsContext";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import { undoRedoContext } from "../../contexts/undoRedoContext";
|
||||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||
import { validationStatusType } from "../../types/components";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
|
|
@ -22,7 +23,7 @@ import { classNames, getFieldTitle } from "../../utils/utils";
|
|||
import ParameterComponent from "./components/parameterComponent";
|
||||
|
||||
export default function GenericNode({
|
||||
data: olddata,
|
||||
data,
|
||||
xPos,
|
||||
yPos,
|
||||
selected,
|
||||
|
|
@ -32,7 +33,6 @@ export default function GenericNode({
|
|||
xPos: number;
|
||||
yPos: number;
|
||||
}): JSX.Element {
|
||||
const [data, setData] = useState(olddata);
|
||||
const { updateFlow, flows, tabId } = useContext(FlowsContext);
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
const { types, deleteNode, reactFlowInstance, setFilterEdge, getFilterEdge } =
|
||||
|
|
@ -46,10 +46,11 @@ export default function GenericNode({
|
|||
);
|
||||
const [validationStatus, setValidationStatus] =
|
||||
useState<validationStatusType | null>(null);
|
||||
const [showNode, setShowNode] = useState<boolean>(true);
|
||||
const [handles, setHandles] = useState<boolean[] | []>([]);
|
||||
let numberOfInputs: boolean[] = [];
|
||||
|
||||
const { takeSnapshot } = useContext(undoRedoContext);
|
||||
|
||||
function countHandles(): void {
|
||||
numberOfInputs = Object.keys(data.node!.template)
|
||||
.filter((templateField) => templateField.charAt(0) !== "_")
|
||||
|
|
@ -86,7 +87,6 @@ export default function GenericNode({
|
|||
// State for outline color
|
||||
const { sseData, isBuilding } = useSSE();
|
||||
useEffect(() => {
|
||||
olddata.node = data.node;
|
||||
let myFlow = flows.find((flow) => flow.id === tabId);
|
||||
if (reactFlowInstance && myFlow) {
|
||||
let flow = cloneDeep(myFlow);
|
||||
|
|
@ -108,10 +108,12 @@ export default function GenericNode({
|
|||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
updateNodeInternals(data.id);
|
||||
}, 300);
|
||||
}, [showNode]);
|
||||
setNodeDescription(data.node!.description);
|
||||
}, [data.node!.description]);
|
||||
|
||||
useEffect(() => {
|
||||
setNodeName(data.node!.display_name);
|
||||
}, [data.node!.display_name]);
|
||||
|
||||
// New useEffect to watch for changes in sseData and update validation status
|
||||
useEffect(() => {
|
||||
|
|
@ -123,15 +125,17 @@ export default function GenericNode({
|
|||
setValidationStatus(null);
|
||||
}
|
||||
}, [sseData, data.id]);
|
||||
|
||||
const showNode = data.showNode ?? true;
|
||||
|
||||
return (
|
||||
<>
|
||||
<NodeToolbar>
|
||||
<NodeToolbarComponent
|
||||
position={{ x: xPos, y: yPos }}
|
||||
data={data}
|
||||
setData={setData}
|
||||
deleteNode={deleteNode}
|
||||
setShowNode={setShowNode}
|
||||
setShowNode={(showNode: boolean) => {data.showNode = showNode}}
|
||||
numberOfHandles={handles}
|
||||
showNode={showNode}
|
||||
></NodeToolbarComponent>
|
||||
|
|
@ -180,7 +184,6 @@ export default function GenericNode({
|
|||
{data.node?.flow && inputName ? (
|
||||
<div>
|
||||
<InputComponent
|
||||
autoFocus
|
||||
onBlur={() => {
|
||||
setInputName(false);
|
||||
if (nodeName.trim() !== "") {
|
||||
|
|
@ -200,7 +203,10 @@ export default function GenericNode({
|
|||
<ShadTooltip content={data.node?.display_name}>
|
||||
<div
|
||||
className="flex"
|
||||
onDoubleClick={() => setInputName(true)}
|
||||
onDoubleClick={() => {
|
||||
setInputName(true);
|
||||
takeSnapshot();
|
||||
}}
|
||||
>
|
||||
<div className="generic-node-tooltip-div pr-3 text-primary">
|
||||
{data.node?.display_name}
|
||||
|
|
@ -237,7 +243,6 @@ export default function GenericNode({
|
|||
proxy: data.node!.template[templateField].proxy,
|
||||
})}
|
||||
data={data}
|
||||
setData={setData}
|
||||
color={
|
||||
nodeColors[
|
||||
types[data.node?.template[templateField].type!]
|
||||
|
|
@ -286,7 +291,6 @@ export default function GenericNode({
|
|||
dataType: data.type,
|
||||
})}
|
||||
data={data}
|
||||
setData={setData}
|
||||
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
|
||||
title={
|
||||
data.node?.output_types &&
|
||||
|
|
@ -417,7 +421,10 @@ export default function GenericNode({
|
|||
) : (
|
||||
<div
|
||||
className="generic-node-desc-text break-all"
|
||||
onDoubleClick={() => setInputDescription(true)}
|
||||
onDoubleClick={() => {
|
||||
setInputDescription(true);
|
||||
takeSnapshot();
|
||||
}}
|
||||
>
|
||||
{data.node?.description}
|
||||
</div>
|
||||
|
|
@ -449,7 +456,6 @@ export default function GenericNode({
|
|||
proxy: data.node!.template[templateField].proxy,
|
||||
})}
|
||||
data={data}
|
||||
setData={setData}
|
||||
color={
|
||||
nodeColors[
|
||||
types[data.node?.template[templateField].type!]
|
||||
|
|
@ -507,8 +513,7 @@ export default function GenericNode({
|
|||
dataType: data.type,
|
||||
})}
|
||||
data={data}
|
||||
setData={setData}
|
||||
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
|
||||
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
|
||||
title={
|
||||
data.node?.output_types && data.node.output_types.length > 0
|
||||
? data.node.output_types.join("|")
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ export default function KeypairListComponent({
|
|||
disabled,
|
||||
editNode = false,
|
||||
duplicateKey,
|
||||
advanced = false,
|
||||
dataValue,
|
||||
}: KeyPairListComponentType): JSX.Element {
|
||||
useEffect(() => {
|
||||
if (disabled) {
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
const insidePosition = position.paneX
|
||||
? { x: position.paneX + position.x, y: position.paneY! + position.y }
|
||||
: reactFlowInstance!.project({ x: position.x, y: position.y });
|
||||
: reactFlowInstance!.screenToFlowPosition({ x: position.x, y: position.y });
|
||||
|
||||
selectionInstance.nodes.forEach((node: NodeType) => {
|
||||
// Generate a unique node ID
|
||||
|
|
|
|||
|
|
@ -52,15 +52,23 @@ export function UndoRedoProvider({ children }) {
|
|||
|
||||
const takeSnapshot = useCallback(() => {
|
||||
// push the current graph to the past state
|
||||
setPast((old) => {
|
||||
let newPast = cloneDeep(old);
|
||||
newPast[tabIndex] = old[tabIndex].slice(
|
||||
old[tabIndex].length - defaultOptions.maxHistorySize + 1,
|
||||
old[tabIndex].length
|
||||
let newPast = cloneDeep(past);
|
||||
let newState = {
|
||||
nodes: cloneDeep(getNodes()),
|
||||
edges: cloneDeep(getEdges()),
|
||||
};
|
||||
if (
|
||||
past[tabIndex] &&
|
||||
JSON.stringify(past[tabIndex][past[tabIndex].length - 1]) !==
|
||||
JSON.stringify(newState)
|
||||
) {
|
||||
newPast[tabIndex] = past[tabIndex].slice(
|
||||
past[tabIndex].length - defaultOptions.maxHistorySize + 1,
|
||||
past[tabIndex].length
|
||||
);
|
||||
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
|
||||
return newPast;
|
||||
});
|
||||
newPast[tabIndex].push(newState);
|
||||
}
|
||||
setPast(newPast);
|
||||
|
||||
// whenever we take a new snapshot, the redo operations need to be cleared to avoid state mismatches
|
||||
setFuture((old) => {
|
||||
|
|
|
|||
|
|
@ -45,13 +45,11 @@ const EditNodeModal = forwardRef(
|
|||
(
|
||||
{
|
||||
data,
|
||||
setData,
|
||||
nodeLength,
|
||||
open,
|
||||
setOpen,
|
||||
}: {
|
||||
data: NodeDataType;
|
||||
setData: (data: NodeDataType) => void;
|
||||
nodeLength: number;
|
||||
open: boolean;
|
||||
setOpen: (open: boolean) => void;
|
||||
|
|
@ -60,7 +58,7 @@ const EditNodeModal = forwardRef(
|
|||
) => {
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
|
||||
let myData = useRef(data);
|
||||
const [myData, setMyData] = useState(data);
|
||||
|
||||
const { setTabsState, tabId } = useContext(FlowsContext);
|
||||
const { reactFlowInstance } = useContext(typesContext);
|
||||
|
|
@ -70,30 +68,31 @@ const EditNodeModal = forwardRef(
|
|||
.some((edge) => edge.targetHandle === data.id) ?? false;
|
||||
|
||||
function changeAdvanced(n) {
|
||||
myData.current.node!.template[n].advanced =
|
||||
!myData.current.node!.template[n].advanced;
|
||||
|
||||
myData.current = {
|
||||
...myData.current,
|
||||
};
|
||||
setAdv(!adv);
|
||||
setMyData((old) => {
|
||||
let newData = cloneDeep(old);
|
||||
newData.node!.template[n].advanced =
|
||||
!newData.node!.template[n].advanced;
|
||||
return newData;
|
||||
});
|
||||
}
|
||||
|
||||
const handleOnNewValue = (newValue: any, name) => {
|
||||
myData.current.node!.template[name].value = newValue;
|
||||
setDataValue(newValue);
|
||||
setMyData((old) => {
|
||||
let newData = cloneDeep(old);
|
||||
newData.node!.template[name].value = newValue;
|
||||
return newData;
|
||||
});
|
||||
updateNodeInternals(data.id);
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
myData.current = data; // reset data to what it is on node when opening modal
|
||||
setMyData(data); // reset data to what it is on node when opening modal
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
|
||||
const [adv, setAdv] = useState<boolean | null>(null);
|
||||
const [dataValue, setDataValue] = useState(data);
|
||||
|
||||
return (
|
||||
<BaseModal
|
||||
|
|
@ -102,15 +101,15 @@ const EditNodeModal = forwardRef(
|
|||
open={open}
|
||||
setOpen={setOpen}
|
||||
onChangeOpenModal={(open) => {
|
||||
myData.current = data;
|
||||
setMyData(data);
|
||||
}}
|
||||
>
|
||||
<BaseModal.Trigger>
|
||||
<></>
|
||||
</BaseModal.Trigger>
|
||||
<BaseModal.Header description={myData.current.node?.description!}>
|
||||
<span className="pr-2">{myData.current.type}</span>
|
||||
<Badge variant="secondary">ID: {myData.current.id}</Badge>
|
||||
<BaseModal.Header description={myData.node?.description!}>
|
||||
<span className="pr-2">{myData.type}</span>
|
||||
<Badge variant="secondary">ID: {myData.id}</Badge>
|
||||
</BaseModal.Header>
|
||||
<BaseModal.Content>
|
||||
<div className="flex pb-2">
|
||||
|
|
@ -143,13 +142,13 @@ const EditNodeModal = forwardRef(
|
|||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody className="p-0">
|
||||
{Object.keys(myData.current.node!.template)
|
||||
{Object.keys(myData.node!.template)
|
||||
.filter(
|
||||
(templateParam) =>
|
||||
templateParam.charAt(0) !== "_" &&
|
||||
myData.current.node?.template[templateParam].show &&
|
||||
myData.node?.template[templateParam].show &&
|
||||
LANGFLOW_SUPPORTED_TYPES.has(
|
||||
myData.current.node.template[templateParam].type
|
||||
myData.node.template[templateParam].type
|
||||
)
|
||||
)
|
||||
.map((templateParam, index) => (
|
||||
|
|
@ -157,46 +156,46 @@ const EditNodeModal = forwardRef(
|
|||
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
||||
<ShadTooltip
|
||||
content={
|
||||
myData.current.node?.template[templateParam]
|
||||
myData.node?.template[templateParam]
|
||||
.proxy
|
||||
? myData.current.node?.template[
|
||||
? myData.node?.template[
|
||||
templateParam
|
||||
].proxy?.id
|
||||
: null
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{myData.current.node?.template[templateParam]
|
||||
{myData.node?.template[templateParam]
|
||||
.display_name
|
||||
? myData.current.node.template[
|
||||
? myData.node.template[
|
||||
templateParam
|
||||
].display_name
|
||||
: myData.current.node?.template[
|
||||
: myData.node?.template[
|
||||
templateParam
|
||||
].name}
|
||||
</span>
|
||||
</ShadTooltip>
|
||||
</TableCell>
|
||||
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
||||
{myData.current.node?.template[templateParam]
|
||||
{myData.node?.template[templateParam]
|
||||
.type === "str" &&
|
||||
!myData.current.node.template[templateParam]
|
||||
!myData.node.template[templateParam]
|
||||
.options ? (
|
||||
<div className="mx-auto">
|
||||
{myData.current.node.template[templateParam]
|
||||
{myData.node.template[templateParam]
|
||||
.list ? (
|
||||
<InputListComponent
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
value={
|
||||
!myData.current.node.template[
|
||||
!myData.node.template[
|
||||
templateParam
|
||||
].value ||
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value === ""
|
||||
? [""]
|
||||
: myData.current.node.template[
|
||||
: myData.node.template[
|
||||
templateParam
|
||||
].value
|
||||
}
|
||||
|
|
@ -204,7 +203,7 @@ const EditNodeModal = forwardRef(
|
|||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
/>
|
||||
) : myData.current.node.template[
|
||||
) : myData.node.template[
|
||||
templateParam
|
||||
].multiline ? (
|
||||
<TextAreaComponent
|
||||
|
|
@ -212,7 +211,7 @@ const EditNodeModal = forwardRef(
|
|||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
}
|
||||
|
|
@ -226,12 +225,12 @@ const EditNodeModal = forwardRef(
|
|||
editNode={true}
|
||||
disabled={disabled}
|
||||
password={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].password ?? false
|
||||
}
|
||||
value={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
}
|
||||
|
|
@ -241,25 +240,25 @@ const EditNodeModal = forwardRef(
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "NestedDict" ? (
|
||||
<div className=" w-full">
|
||||
<DictComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData?.current?.node!.template[
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
]?.value?.toString() === "{}"
|
||||
? {
|
||||
yourkey: "value",
|
||||
}
|
||||
: myData.current.node!.template[
|
||||
: myData.node!.template[
|
||||
templateParam
|
||||
].value
|
||||
}
|
||||
onChange={(newValue) => {
|
||||
myData.current.node!.template[
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
].value = newValue;
|
||||
handleOnNewValue(newValue, templateParam);
|
||||
|
|
@ -267,32 +266,30 @@ const EditNodeModal = forwardRef(
|
|||
id="editnode-div-dict-input"
|
||||
/>
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "dict" ? (
|
||||
<div
|
||||
className={classNames(
|
||||
"max-h-48 w-full overflow-auto custom-scroll",
|
||||
myData.current.node!.template[templateParam]
|
||||
myData.node!.template[templateParam]
|
||||
.value?.length > 1
|
||||
? "my-3"
|
||||
: ""
|
||||
)}
|
||||
>
|
||||
<KeypairListComponent
|
||||
dataValue={dataValue}
|
||||
advanced={adv}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.current.node!.template[
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
].value?.length === 0 ||
|
||||
!myData.current.node!.template[
|
||||
!myData.node!.template[
|
||||
templateParam
|
||||
].value
|
||||
? [{ "": "" }]
|
||||
: convertObjToArray(
|
||||
myData.current.node!.template[
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
].value
|
||||
)
|
||||
|
|
@ -301,7 +298,7 @@ const EditNodeModal = forwardRef(
|
|||
onChange={(newValue) => {
|
||||
const valueToNumbers =
|
||||
convertValuesToNumbers(newValue);
|
||||
myData.current.node!.template[
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
].value = valueToNumbers;
|
||||
setErrorDuplicateKey(
|
||||
|
|
@ -314,7 +311,7 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "bool" ? (
|
||||
<div className="ml-auto">
|
||||
{" "}
|
||||
|
|
@ -322,7 +319,7 @@ const EditNodeModal = forwardRef(
|
|||
id={"toggle-edit-" + index}
|
||||
disabled={disabled}
|
||||
enabled={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value
|
||||
}
|
||||
|
|
@ -335,14 +332,14 @@ const EditNodeModal = forwardRef(
|
|||
size="small"
|
||||
/>
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "float" ? (
|
||||
<div className="mx-auto">
|
||||
<FloatComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
}
|
||||
|
|
@ -351,16 +348,16 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "str" &&
|
||||
myData.current.node.template[templateParam]
|
||||
myData.node.template[templateParam]
|
||||
.options ? (
|
||||
<div className="mx-auto">
|
||||
<Dropdown
|
||||
numberOfOptions={nodeLength}
|
||||
editNode={true}
|
||||
options={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].options
|
||||
}
|
||||
|
|
@ -368,14 +365,14 @@ const EditNodeModal = forwardRef(
|
|||
handleOnNewValue(value, templateParam)
|
||||
}
|
||||
value={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? "Choose an option"
|
||||
}
|
||||
id={"dropdown-edit-" + index}
|
||||
></Dropdown>
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "int" ? (
|
||||
<div className="mx-auto">
|
||||
<IntComponent
|
||||
|
|
@ -383,7 +380,7 @@ const EditNodeModal = forwardRef(
|
|||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
}
|
||||
|
|
@ -392,14 +389,14 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "file" ? (
|
||||
<div className="mx-auto">
|
||||
<InputFileComponent
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
value={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
}
|
||||
|
|
@ -407,12 +404,12 @@ const EditNodeModal = forwardRef(
|
|||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
fileTypes={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].fileTypes
|
||||
}
|
||||
suffixes={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].suffixes
|
||||
}
|
||||
|
|
@ -423,22 +420,22 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
></InputFileComponent>
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "prompt" ? (
|
||||
<div className="mx-auto">
|
||||
<PromptAreaComponent
|
||||
readonly={
|
||||
myData.current.node?.flow ? true : false
|
||||
myData.node?.flow ? true : false
|
||||
}
|
||||
field_name={templateParam}
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
nodeClass={myData.current.node}
|
||||
nodeClass={myData.node}
|
||||
setNodeClass={(nodeClass) => {
|
||||
myData.current.node = nodeClass;
|
||||
myData.node = nodeClass;
|
||||
}}
|
||||
value={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
}
|
||||
|
|
@ -448,13 +445,13 @@ const EditNodeModal = forwardRef(
|
|||
id={"prompt-area-edit" + index}
|
||||
/>
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "code" ? (
|
||||
<div className="mx-auto">
|
||||
<CodeAreaComponent
|
||||
readonly={
|
||||
myData.current.node?.flow &&
|
||||
myData.current.node.template[
|
||||
myData.node?.flow &&
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].dynamic
|
||||
? true
|
||||
|
|
@ -471,7 +468,7 @@ const EditNodeModal = forwardRef(
|
|||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.current.node.template[
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
}
|
||||
|
|
@ -481,7 +478,7 @@ const EditNodeModal = forwardRef(
|
|||
id={"code-area-edit" + index}
|
||||
/>
|
||||
</div>
|
||||
) : myData.current.node?.template[templateParam]
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "Any" ? (
|
||||
"-"
|
||||
) : (
|
||||
|
|
@ -493,11 +490,11 @@ const EditNodeModal = forwardRef(
|
|||
<ToggleShadComponent
|
||||
id={
|
||||
"show" +
|
||||
myData.current.node?.template[templateParam]
|
||||
myData.node?.template[templateParam]
|
||||
.name
|
||||
}
|
||||
enabled={
|
||||
!myData.current.node?.template[
|
||||
!myData.node?.template[
|
||||
templateParam
|
||||
].advanced
|
||||
}
|
||||
|
|
@ -524,8 +521,7 @@ const EditNodeModal = forwardRef(
|
|||
id={"saveChangesBtn"}
|
||||
className="mt-3"
|
||||
onClick={() => {
|
||||
const newData = cloneDeep(myData.current);
|
||||
myData.current = newData;
|
||||
data.node = myData.node
|
||||
//@ts-ignore
|
||||
setTabsState((prev: FlowsState) => {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -90,8 +90,6 @@ export default function Page({
|
|||
useState<OnSelectionChangeParams | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// this effect is used to attach the global event handlers
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
if (!isWrappedWithClass(event, "nocopy")) {
|
||||
if (
|
||||
|
|
@ -108,10 +106,9 @@ export default function Page({
|
|||
lastCopiedSelection
|
||||
) {
|
||||
event.preventDefault();
|
||||
let bounds = reactFlowWrapper.current?.getBoundingClientRect();
|
||||
paste(lastCopiedSelection, {
|
||||
x: position.x - bounds!.left,
|
||||
y: position.y - bounds!.top,
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
});
|
||||
}
|
||||
if (
|
||||
|
|
@ -133,18 +130,26 @@ export default function Page({
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("keydown", onKeyDown);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
};
|
||||
}, [lastCopiedSelection, lastSelection]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleMouseMove = (event) => {
|
||||
setPosition({ x: event.clientX, y: event.clientY });
|
||||
};
|
||||
|
||||
document.addEventListener("keydown", onKeyDown);
|
||||
document.addEventListener("mousemove", handleMouseMove);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
document.removeEventListener("mousemove", handleMouseMove);
|
||||
};
|
||||
}, [position, lastCopiedSelection, lastSelection]);
|
||||
}, [position]);
|
||||
|
||||
const [selectionMenuVisible, setSelectionMenuVisible] = useState(false);
|
||||
|
||||
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
|
||||
|
|
@ -152,58 +157,34 @@ export default function Page({
|
|||
const [nodes, setNodes, onNodesChange] = useNodesState(
|
||||
flow.data?.nodes ?? []
|
||||
);
|
||||
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(
|
||||
flow.data?.edges ?? []
|
||||
);
|
||||
const { setViewport } = useReactFlow();
|
||||
const edgeUpdateSuccessful = useRef(true);
|
||||
useEffect(() => {
|
||||
if (reactFlowInstance && flow) {
|
||||
flow.data = reactFlowInstance.toObject();
|
||||
updateFlow(flow);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [edges]);
|
||||
|
||||
//update flow when tabs change
|
||||
useEffect(() => {
|
||||
setNodes(flow?.data?.nodes ?? []);
|
||||
setEdges(flow?.data?.edges ?? []);
|
||||
if (reactFlowInstance) {
|
||||
setViewport(flow?.data?.viewport ?? { x: 1, y: 0, zoom: 0.5 });
|
||||
reactFlowInstance.fitView();
|
||||
}
|
||||
}, [flow, reactFlowInstance, setEdges, setNodes, setViewport]);
|
||||
//set extra sidebar
|
||||
useEffect(() => {
|
||||
setExtraComponent(<ExtraSidebar />);
|
||||
setExtraNavigation({ title: "Components" });
|
||||
}, [setExtraComponent, setExtraNavigation]);
|
||||
|
||||
const [seconds, setSeconds] = useState(0);
|
||||
}, [flow, reactFlowInstance]);
|
||||
|
||||
useEffect(() => {
|
||||
const index = flows.findIndex((flowId) => flowId.id === flow.id);
|
||||
|
||||
const interval = setInterval(() => {
|
||||
setSeconds((prevSeconds) => {
|
||||
let updatedSeconds = prevSeconds + 1;
|
||||
|
||||
if (updatedSeconds % 30 === 0) {
|
||||
saveFlow(
|
||||
{
|
||||
...flows[index]!,
|
||||
data: reactFlowInstance
|
||||
? reactFlowInstance!.toObject()
|
||||
: flow!.data,
|
||||
},
|
||||
true
|
||||
);
|
||||
updatedSeconds = 0;
|
||||
}
|
||||
|
||||
return updatedSeconds;
|
||||
});
|
||||
}, 1000);
|
||||
saveFlow(
|
||||
{
|
||||
...flows[index]!,
|
||||
data: reactFlowInstance ? reactFlowInstance!.toObject() : flow!.data,
|
||||
},
|
||||
true
|
||||
);
|
||||
}, 30000);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
|
|
@ -212,11 +193,11 @@ export default function Page({
|
|||
|
||||
const onEdgesChangeMod = useCallback(
|
||||
(change: EdgeChange[]) => {
|
||||
onEdgesChange(change);
|
||||
setNodes((node) => {
|
||||
let newX = _.cloneDeep(node);
|
||||
return newX;
|
||||
updateFlow({
|
||||
...flow!,
|
||||
data: reactFlowInstance ? reactFlowInstance!.toObject() : flow!.data,
|
||||
});
|
||||
onEdgesChange(change);
|
||||
//@ts-ignore
|
||||
setTabsState((prev: FlowsState) => {
|
||||
return {
|
||||
|
|
@ -383,6 +364,9 @@ export default function Page({
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
setExtraComponent(<ExtraSidebar />);
|
||||
setExtraNavigation({ title: "Components" });
|
||||
|
||||
return () => {
|
||||
if (tabsState && tabsState[flow.id]?.isPending) {
|
||||
saveFlow({
|
||||
|
|
@ -520,6 +504,7 @@ export default function Page({
|
|||
isVisible={selectionMenuVisible}
|
||||
nodes={lastSelection?.nodes}
|
||||
onClick={() => {
|
||||
takeSnapshot();
|
||||
if (
|
||||
validateSelection(lastSelection!, edges).length === 0
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
useEffect(() => {
|
||||
if (getFilterEdge.length === 0 && search === "") {
|
||||
setFilterData(data);
|
||||
setFilterEdge([]);
|
||||
setSearch("");
|
||||
}
|
||||
}, [getFilterEdge]);
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ import {
|
|||
updateFlowPosition,
|
||||
} from "../../../../utils/reactflowUtils";
|
||||
import { classNames } from "../../../../utils/utils";
|
||||
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
|
||||
|
||||
export default function NodeToolbarComponent({
|
||||
data,
|
||||
setData,
|
||||
deleteNode,
|
||||
position,
|
||||
setShowNode,
|
||||
|
|
@ -66,6 +66,7 @@ export default function NodeToolbarComponent({
|
|||
const isGroup = data.node?.flow ? true : false;
|
||||
|
||||
const { paste, saveComponent, version, flows } = useContext(FlowsContext);
|
||||
const { takeSnapshot } = useContext(undoRedoContext);
|
||||
const reactFlowInstance = useReactFlow();
|
||||
const [showModalAdvanced, setShowModalAdvanced] = useState(false);
|
||||
const [showconfirmShare, setShowconfirmShare] = useState(false);
|
||||
|
|
@ -84,6 +85,7 @@ export default function NodeToolbarComponent({
|
|||
setShowModalAdvanced(true);
|
||||
break;
|
||||
case "show":
|
||||
takeSnapshot();
|
||||
setShowNode((prev) => !prev);
|
||||
updateNodeInternals(data.id);
|
||||
break;
|
||||
|
|
@ -99,6 +101,7 @@ export default function NodeToolbarComponent({
|
|||
case "disabled":
|
||||
break;
|
||||
case "ungroup":
|
||||
takeSnapshot();
|
||||
updateFlowPosition(position, data.node?.flow!);
|
||||
expandGroupNode(data, reactFlowInstance, getNodeId);
|
||||
break;
|
||||
|
|
@ -301,7 +304,6 @@ export default function NodeToolbarComponent({
|
|||
</ConfirmationModal>
|
||||
<EditNodeModal
|
||||
data={data}
|
||||
setData={setData}
|
||||
nodeLength={nodeLength}
|
||||
open={showModalAdvanced}
|
||||
setOpen={setShowModalAdvanced}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ export type DropDownComponentType = {
|
|||
};
|
||||
export type ParameterComponentType = {
|
||||
data: NodeDataType;
|
||||
setData: (value: NodeDataType) => void;
|
||||
title: string;
|
||||
id: sourceHandleType | targetHandleType;
|
||||
color: string;
|
||||
|
|
@ -69,8 +68,6 @@ export type KeyPairListComponentType = {
|
|||
disabled: boolean;
|
||||
editNode?: boolean;
|
||||
duplicateKey?: boolean;
|
||||
advanced?: boolean | null;
|
||||
dataValue?: any;
|
||||
editNodeModal?: boolean;
|
||||
};
|
||||
|
||||
|
|
@ -470,7 +467,6 @@ export type fileCardPropsType = {
|
|||
export type nodeToolbarPropsType = {
|
||||
data: NodeDataType;
|
||||
deleteNode: (idx: string) => void;
|
||||
setData: (newState: NodeDataType) => void;
|
||||
position: XYPosition;
|
||||
setShowNode: (boolean: any) => void;
|
||||
numberOfHandles: boolean[] | [];
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export type NodeType = {
|
|||
};
|
||||
|
||||
export type NodeDataType = {
|
||||
showNode?: boolean;
|
||||
type: string;
|
||||
node?: APIClassType;
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -934,8 +934,6 @@ export function expandGroupNode(
|
|||
updateEdgesIds(flowEdges, idsMap);
|
||||
const gNodes: NodeType[] = flow?.data?.nodes!;
|
||||
const gEdges = flow!.data!.edges;
|
||||
//TODO update ids of intern nodes and proxy on edges before expanding
|
||||
console.log(gEdges);
|
||||
//redirect edges to correct proxy node
|
||||
let updatedEdges: Edge[] = [];
|
||||
flowEdges.forEach((edge) => {
|
||||
|
|
@ -1046,7 +1044,6 @@ export function getGroupStatus(
|
|||
let status = { valid: true, params: "Built sucessfully ✨" };
|
||||
const { nodes } = flow.data!;
|
||||
const ids = nodes.map((n: NodeType) => n.data.id);
|
||||
ids.forEach((id) => console.log(ssData[id]));
|
||||
ids.forEach((id) => {
|
||||
if (!ssData[id]) {
|
||||
status = ssData[id];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue