🐛 fix(EditNodeModal): fix state mutation issue by using useRef instead of useState for myData variable
✨ feat(EditNodeModal): add onChangeOpenModal prop to BaseModal component to reset myData to original data when modal is closed 🔧 chore: fix indentation in setTabsState function call for better code readability 🔧 fix(baseModal): import useEffect from react to fix missing dependency warning 🔧 fix(baseModal): add missing onChangeOpenModal prop to BaseModal component 🔧 fix(baseModal): call onChangeOpenModal prop in useEffect to notify parent component of modal open state change 🔧 fix(genericModal): add empty onChangeOpenModal prop to BaseModal component to fix prop type error
This commit is contained in:
parent
144fdbd098
commit
bd9c53bf14
3 changed files with 127 additions and 65 deletions
|
|
@ -1,5 +1,12 @@
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import { ReactNode, forwardRef, useContext, useEffect, useState } from "react";
|
import {
|
||||||
|
ReactNode,
|
||||||
|
forwardRef,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
import CodeAreaComponent from "../../components/codeAreaComponent";
|
import CodeAreaComponent from "../../components/codeAreaComponent";
|
||||||
import Dropdown from "../../components/dropdownComponent";
|
import Dropdown from "../../components/dropdownComponent";
|
||||||
import FloatComponent from "../../components/floatComponent";
|
import FloatComponent from "../../components/floatComponent";
|
||||||
|
|
@ -44,40 +51,44 @@ const EditNodeModal = forwardRef(
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const [modalOpen, setModalOpen] = useState(false);
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
const [myData, setMyData] = useState(data);
|
|
||||||
const { setTabsState, tabId } = useContext(TabsContext);
|
const { setTabsState, tabId } = useContext(TabsContext);
|
||||||
const { reactFlowInstance } = useContext(typesContext);
|
const { reactFlowInstance } = useContext(typesContext);
|
||||||
|
const myData = useRef(data);
|
||||||
|
|
||||||
let disabled =
|
let disabled =
|
||||||
reactFlowInstance?.getEdges().some((e) => e.targetHandle === data.id) ??
|
reactFlowInstance?.getEdges().some((e) => e.targetHandle === data.id) ??
|
||||||
false;
|
false;
|
||||||
|
|
||||||
function changeAdvanced(n) {
|
function changeAdvanced(n) {
|
||||||
setMyData((old) => {
|
let newData = cloneDeep(data);
|
||||||
let newData = cloneDeep(old);
|
|
||||||
newData.node.template[n].advanced = !newData.node.template[n].advanced;
|
newData.node.template[n].advanced = !newData.node.template[n].advanced;
|
||||||
return newData;
|
myData.current = newData;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleOnNewValue = (newValue: any, name) => {
|
const handleOnNewValue = (newValue: any, name) => {
|
||||||
setMyData((old) => {
|
let newData = cloneDeep(data);
|
||||||
let newData = cloneDeep(old);
|
|
||||||
newData.node.template[name].value = newValue;
|
newData.node.template[name].value = newValue;
|
||||||
return newData;
|
myData.current = newData;
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMyData(data); // reset data to what it is on node when opening modal
|
myData.current = data;
|
||||||
}, [modalOpen]);
|
}, [modalOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseModal size="large-h-full" open={modalOpen} setOpen={setModalOpen}>
|
<BaseModal
|
||||||
|
size="large-h-full"
|
||||||
|
open={modalOpen}
|
||||||
|
setOpen={setModalOpen}
|
||||||
|
onChangeOpenModal={(open) => {
|
||||||
|
let newData = cloneDeep(data);
|
||||||
|
myData.current = newData;
|
||||||
|
}}
|
||||||
|
>
|
||||||
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
||||||
<BaseModal.Header description={myData.node?.description}>
|
<BaseModal.Header description={myData.current.node?.description}>
|
||||||
<span className="pr-2">{myData.type}</span>
|
<span className="pr-2">{myData.current.type}</span>
|
||||||
<Badge variant="secondary">ID: {myData.id}</Badge>
|
<Badge variant="secondary">ID: {myData.current.id}</Badge>
|
||||||
</BaseModal.Header>
|
</BaseModal.Header>
|
||||||
<BaseModal.Content>
|
<BaseModal.Content>
|
||||||
<div className="flex pb-2">
|
<div className="flex pb-2">
|
||||||
|
|
@ -110,50 +121,57 @@ const EditNodeModal = forwardRef(
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody className="p-0">
|
<TableBody className="p-0">
|
||||||
{Object.keys(myData.node.template)
|
{Object.keys(myData.current.node.template)
|
||||||
.filter(
|
.filter(
|
||||||
(t) =>
|
(t) =>
|
||||||
t.charAt(0) !== "_" &&
|
t.charAt(0) !== "_" &&
|
||||||
myData.node.template[t].show &&
|
myData.current.node.template[t].show &&
|
||||||
(myData.node.template[t].type === "str" ||
|
(myData.current.node.template[t].type === "str" ||
|
||||||
myData.node.template[t].type === "bool" ||
|
myData.current.node.template[t].type === "bool" ||
|
||||||
myData.node.template[t].type === "float" ||
|
myData.current.node.template[t].type ===
|
||||||
myData.node.template[t].type === "code" ||
|
"float" ||
|
||||||
myData.node.template[t].type === "prompt" ||
|
myData.current.node.template[t].type === "code" ||
|
||||||
myData.node.template[t].type === "file" ||
|
myData.current.node.template[t].type ===
|
||||||
myData.node.template[t].type === "int")
|
"prompt" ||
|
||||||
|
myData.current.node.template[t].type === "file" ||
|
||||||
|
myData.current.node.template[t].type === "int")
|
||||||
)
|
)
|
||||||
.map((n, i) => (
|
.map((n, i) => (
|
||||||
<TableRow key={i} className="h-10">
|
<TableRow key={i} className="h-10">
|
||||||
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
||||||
{myData.node.template[n].name
|
{myData.current.node.template[n].name
|
||||||
? myData.node.template[n].name
|
? myData.current.node.template[n].name
|
||||||
: myData.node.template[n].display_name}
|
: myData.current.node.template[n].display_name}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
||||||
{myData.node.template[n].type === "str" &&
|
{myData.current.node.template[n].type === "str" &&
|
||||||
!myData.node.template[n].options ? (
|
!myData.current.node.template[n].options ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
{myData.node.template[n].list ? (
|
{myData.current.node.template[n].list ? (
|
||||||
<InputListComponent
|
<InputListComponent
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={
|
value={
|
||||||
!myData.node.template[n].value ||
|
!myData.current.node.template[n]
|
||||||
myData.node.template[n].value === ""
|
.value ||
|
||||||
|
myData.current.node.template[n]
|
||||||
|
.value === ""
|
||||||
? [""]
|
? [""]
|
||||||
: myData.node.template[n].value
|
: myData.current.node.template[n]
|
||||||
|
.value
|
||||||
}
|
}
|
||||||
onChange={(t: string[]) => {
|
onChange={(t: string[]) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(t, n);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : myData.node.template[n].multiline ? (
|
) : myData.current.node.template[n]
|
||||||
|
.multiline ? (
|
||||||
<TextAreaComponent
|
<TextAreaComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={
|
value={
|
||||||
myData.node.template[n].value ?? ""
|
myData.current.node.template[n].value ??
|
||||||
|
""
|
||||||
}
|
}
|
||||||
onChange={(t: string) => {
|
onChange={(t: string) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(t, n);
|
||||||
|
|
@ -164,11 +182,12 @@ const EditNodeModal = forwardRef(
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
password={
|
password={
|
||||||
myData.node.template[n].password ??
|
myData.current.node.template[n]
|
||||||
false
|
.password ?? false
|
||||||
}
|
}
|
||||||
value={
|
value={
|
||||||
myData.node.template[n].value ?? ""
|
myData.current.node.template[n].value ??
|
||||||
|
""
|
||||||
}
|
}
|
||||||
onChange={(t) => {
|
onChange={(t) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(t, n);
|
||||||
|
|
@ -176,89 +195,114 @@ const EditNodeModal = forwardRef(
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "bool" ? (
|
) : myData.current.node.template[n].type ===
|
||||||
|
"bool" ? (
|
||||||
<div className="ml-auto">
|
<div className="ml-auto">
|
||||||
{" "}
|
{" "}
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
enabled={myData.node.template[n].value}
|
enabled={
|
||||||
|
myData.current.node.template[n].value
|
||||||
|
}
|
||||||
setEnabled={(t) => {
|
setEnabled={(t) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(t, n);
|
||||||
}}
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "float" ? (
|
) : myData.current.node.template[n].type ===
|
||||||
|
"float" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<FloatComponent
|
<FloatComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
|
myData.current.node.template[n].value ??
|
||||||
|
""
|
||||||
|
}
|
||||||
onChange={(t) => {
|
onChange={(t) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(t, n);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "str" &&
|
) : myData.current.node.template[n].type ===
|
||||||
myData.node.template[n].options ? (
|
"str" &&
|
||||||
|
myData.current.node.template[n].options ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
numberOfOptions={nodeLength}
|
numberOfOptions={nodeLength}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
options={myData.node.template[n].options}
|
options={
|
||||||
|
myData.current.node.template[n].options
|
||||||
|
}
|
||||||
onSelect={(t) => handleOnNewValue(t, n)}
|
onSelect={(t) => handleOnNewValue(t, n)}
|
||||||
value={
|
value={
|
||||||
myData.node.template[n].value ??
|
myData.current.node.template[n].value ??
|
||||||
"Choose an option"
|
"Choose an option"
|
||||||
}
|
}
|
||||||
></Dropdown>
|
></Dropdown>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "int" ? (
|
) : myData.current.node.template[n].type ===
|
||||||
|
"int" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<IntComponent
|
<IntComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
|
myData.current.node.template[n].value ??
|
||||||
|
""
|
||||||
|
}
|
||||||
onChange={(t) => {
|
onChange={(t) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(t, n);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "file" ? (
|
) : myData.current.node.template[n].type ===
|
||||||
|
"file" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<InputFileComponent
|
<InputFileComponent
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
|
myData.current.node.template[n].value ??
|
||||||
|
""
|
||||||
|
}
|
||||||
onChange={(t: string) => {
|
onChange={(t: string) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(t, n);
|
||||||
}}
|
}}
|
||||||
fileTypes={
|
fileTypes={
|
||||||
myData.node.template[n].fileTypes
|
myData.current.node.template[n].fileTypes
|
||||||
|
}
|
||||||
|
suffixes={
|
||||||
|
myData.current.node.template[n].suffixes
|
||||||
}
|
}
|
||||||
suffixes={myData.node.template[n].suffixes}
|
|
||||||
onFileChange={(t: string) => {
|
onFileChange={(t: string) => {
|
||||||
data.node.template[n].file_path = t;
|
data.node.template[n].file_path = t;
|
||||||
}}
|
}}
|
||||||
></InputFileComponent>
|
></InputFileComponent>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "prompt" ? (
|
) : myData.current.node.template[n].type ===
|
||||||
|
"prompt" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<PromptAreaComponent
|
<PromptAreaComponent
|
||||||
field_name={n}
|
field_name={n}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
nodeClass={myData.node}
|
nodeClass={myData.current.node}
|
||||||
setNodeClass={(nodeClass) => {
|
setNodeClass={(nodeClass) => {
|
||||||
myData.node = nodeClass;
|
myData.current.node = nodeClass;
|
||||||
}}
|
}}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
|
myData.current.node.template[n].value ??
|
||||||
|
""
|
||||||
|
}
|
||||||
onChange={(t: string) => {
|
onChange={(t: string) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(t, n);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "code" ? (
|
) : myData.current.node.template[n].type ===
|
||||||
|
"code" ? (
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
<CodeAreaComponent
|
<CodeAreaComponent
|
||||||
dynamic={
|
dynamic={
|
||||||
|
|
@ -270,13 +314,17 @@ const EditNodeModal = forwardRef(
|
||||||
nodeClass={data.node}
|
nodeClass={data.node}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
editNode={true}
|
editNode={true}
|
||||||
value={myData.node.template[n].value ?? ""}
|
value={
|
||||||
|
myData.current.node.template[n].value ??
|
||||||
|
""
|
||||||
|
}
|
||||||
onChange={(t: string) => {
|
onChange={(t: string) => {
|
||||||
handleOnNewValue(t, n);
|
handleOnNewValue(t, n);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : myData.node.template[n].type === "Any" ? (
|
) : myData.current.node.template[n].type ===
|
||||||
|
"Any" ? (
|
||||||
"-"
|
"-"
|
||||||
) : (
|
) : (
|
||||||
<div className="hidden"></div>
|
<div className="hidden"></div>
|
||||||
|
|
@ -285,7 +333,9 @@ const EditNodeModal = forwardRef(
|
||||||
<TableCell className="p-0 text-right">
|
<TableCell className="p-0 text-right">
|
||||||
<div className="items-center text-center">
|
<div className="items-center text-center">
|
||||||
<ToggleShadComponent
|
<ToggleShadComponent
|
||||||
enabled={!myData.node.template[n].advanced}
|
enabled={
|
||||||
|
!myData.current.node.template[n].advanced
|
||||||
|
}
|
||||||
setEnabled={(e) => changeAdvanced(n)}
|
setEnabled={(e) => changeAdvanced(n)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
size="small"
|
size="small"
|
||||||
|
|
@ -306,7 +356,7 @@ const EditNodeModal = forwardRef(
|
||||||
<Button
|
<Button
|
||||||
className="mt-3"
|
className="mt-3"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setData(cloneDeep(myData)); //saves data with actual state of modal
|
setData(cloneDeep(myData.current)); //saves data with actual state of modal
|
||||||
setTabsState((prev) => {
|
setTabsState((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ReactNode } from "react";
|
import { ReactNode, useEffect } from "react";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
|
|
@ -48,6 +48,7 @@ interface BaseModalProps {
|
||||||
setOpen?: (open: boolean) => void;
|
setOpen?: (open: boolean) => void;
|
||||||
disable?: boolean;
|
disable?: boolean;
|
||||||
size?: "smaller" | "small" | "medium" | "large" | "large-h-full";
|
size?: "smaller" | "small" | "medium" | "large" | "large-h-full";
|
||||||
|
onChangeOpenModal?: (open: boolean) => void;
|
||||||
}
|
}
|
||||||
function BaseModal({
|
function BaseModal({
|
||||||
open,
|
open,
|
||||||
|
|
@ -55,6 +56,7 @@ function BaseModal({
|
||||||
disable = false,
|
disable = false,
|
||||||
children,
|
children,
|
||||||
size = "large",
|
size = "large",
|
||||||
|
onChangeOpenModal,
|
||||||
}: BaseModalProps) {
|
}: BaseModalProps) {
|
||||||
const headerChild = React.Children.toArray(children).find(
|
const headerChild = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Header
|
(child) => (child as React.ReactElement).type === Header
|
||||||
|
|
@ -98,6 +100,12 @@ function BaseModal({
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (onChangeOpenModal) {
|
||||||
|
onChangeOpenModal(open);
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
//UPDATE COLORS AND STYLE CLASSSES
|
//UPDATE COLORS AND STYLE CLASSSES
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,11 @@ export default function GenericModal({
|
||||||
const [modalOpen, setModalOpen] = useState(false);
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseModal open={modalOpen} setOpen={setModalOpen}>
|
<BaseModal
|
||||||
|
onChangeOpenModal={(open) => {}}
|
||||||
|
open={modalOpen}
|
||||||
|
setOpen={setModalOpen}
|
||||||
|
>
|
||||||
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
||||||
<BaseModal.Header
|
<BaseModal.Header
|
||||||
description={(() => {
|
description={(() => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue