Node edit modal done, bugs with handle and table
This commit is contained in:
parent
71cc9092f8
commit
70e66a51ec
2 changed files with 320 additions and 0 deletions
316
src/frontend/src/modals/EditNodeModal/index.tsx
Normal file
316
src/frontend/src/modals/EditNodeModal/index.tsx
Normal file
|
|
@ -0,0 +1,316 @@
|
||||||
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
|
import {
|
||||||
|
ChevronDoubleLeftIcon,
|
||||||
|
ChevronDoubleRightIcon,
|
||||||
|
PencilSquareIcon,
|
||||||
|
XMarkIcon,
|
||||||
|
} from "@heroicons/react/24/outline";
|
||||||
|
import { Fragment, useContext, useEffect, useRef, useState } from "react";
|
||||||
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
|
import { NodeDataType } from "../../types/flow";
|
||||||
|
import {
|
||||||
|
classNames,
|
||||||
|
limitScrollFieldsModal,
|
||||||
|
nodeColors,
|
||||||
|
nodeIcons,
|
||||||
|
toNormalCase,
|
||||||
|
toTitleCase,
|
||||||
|
} from "../../utils";
|
||||||
|
import { typesContext } from "../../contexts/typesContext";
|
||||||
|
const people = [
|
||||||
|
{
|
||||||
|
name: "Lindsay Walton",
|
||||||
|
title: "Front-end Developer",
|
||||||
|
email: "lindsay.walton@example.com",
|
||||||
|
role: "Member",
|
||||||
|
},
|
||||||
|
// More people...
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function EditNodeModal({ data }: { data: NodeDataType }) {
|
||||||
|
const [open, setOpen] = useState(true);
|
||||||
|
const { closePopUp } = useContext(PopUpContext);
|
||||||
|
const { types } = useContext(typesContext);
|
||||||
|
const ref = useRef();
|
||||||
|
function setModalOpen(x: boolean) {
|
||||||
|
setOpen(x);
|
||||||
|
if (x === false) {
|
||||||
|
setTimeout(() => {
|
||||||
|
closePopUp();
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const [advanced, setAdvanced] = useState([]);
|
||||||
|
const [parameters, setParameters] = useState([]);
|
||||||
|
const updateAdvancedParameters = () => {
|
||||||
|
setAdvanced(
|
||||||
|
Object.keys(data.node.template).filter(
|
||||||
|
(t) =>
|
||||||
|
t.charAt(0) !== "_" &&
|
||||||
|
data.node.template[t].advanced &&
|
||||||
|
data.node.template[t].show
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setParameters(
|
||||||
|
Object.keys(data.node.template).filter(
|
||||||
|
(t) =>
|
||||||
|
t.charAt(0) !== "_" &&
|
||||||
|
!data.node.template[t].advanced &&
|
||||||
|
data.node.template[t].show &&
|
||||||
|
(data.node.template[t].type === "str" ||
|
||||||
|
data.node.template[t].type === "bool" ||
|
||||||
|
data.node.template[t].type === "float" ||
|
||||||
|
data.node.template[t].type === "code" ||
|
||||||
|
data.node.template[t].type === "prompt" ||
|
||||||
|
data.node.template[t].type === "file" ||
|
||||||
|
data.node.template[t].type === "int")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
updateAdvancedParameters();
|
||||||
|
}, [data.node.template]);
|
||||||
|
const Icon = nodeIcons[types[data.type]];
|
||||||
|
return (
|
||||||
|
<Transition.Root show={open} appear={true} as={Fragment}>
|
||||||
|
<Dialog
|
||||||
|
as="div"
|
||||||
|
className="relative z-10"
|
||||||
|
onClose={setModalOpen}
|
||||||
|
initialFocus={ref}
|
||||||
|
>
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<div className="fixed inset-0 bg-gray-500 dark:bg-gray-600 dark:bg-opacity-75 bg-opacity-75 transition-opacity" />
|
||||||
|
</Transition.Child>
|
||||||
|
|
||||||
|
<div className="fixed inset-0 z-10 overflow-y-auto">
|
||||||
|
<div className="flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
|
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||||
|
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
|
>
|
||||||
|
<Dialog.Panel className="relative flex flex-col justify-between transform h-[600px] overflow-hidden rounded-lg bg-white dark:bg-gray-800 text-left shadow-xl transition-all sm:my-8 w-[700px]">
|
||||||
|
<div className=" z-50 absolute top-0 right-0 hidden pt-4 pr-4 sm:block">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="rounded-md text-gray-400 hover:text-gray-500"
|
||||||
|
onClick={() => {
|
||||||
|
setModalOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="sr-only">Close</span>
|
||||||
|
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="h-full w-full flex flex-col justify-center items-center">
|
||||||
|
<div className="flex w-full pb-4 z-10 justify-center shadow-sm">
|
||||||
|
<div className="mx-auto mt-4 flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-blue-100 dark:bg-gray-900 sm:mx-0 sm:h-10 sm:w-10">
|
||||||
|
<PencilSquareIcon
|
||||||
|
className="h-6 w-6 text-blue-600"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 text-center sm:ml-4 sm:text-left">
|
||||||
|
<Dialog.Title
|
||||||
|
as="h3"
|
||||||
|
className="text-lg font-medium dark:text-white leading-10 text-gray-900"
|
||||||
|
>
|
||||||
|
Edit Node
|
||||||
|
</Dialog.Title>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="h-full w-full bg-gray-200 dark:bg-gray-900 p-4 gap-4 flex flex-row justify-center items-center">
|
||||||
|
<div className="flex w-full h-[445px]">
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
"w-full rounded-lg bg-white dark:bg-gray-800 shadow",
|
||||||
|
Object.keys(data.node.template).filter(
|
||||||
|
(t) =>
|
||||||
|
t.charAt(0) !== "_" &&
|
||||||
|
data.node.template[t].advanced &&
|
||||||
|
data.node.template[t].show
|
||||||
|
).length > limitScrollFieldsModal ||
|
||||||
|
Object.keys(data.node.template).filter(
|
||||||
|
(t) =>
|
||||||
|
t.charAt(0) !== "_" &&
|
||||||
|
!data.node.template[t].advanced &&
|
||||||
|
data.node.template[t].show
|
||||||
|
).length > limitScrollFieldsModal
|
||||||
|
? "overflow-scroll overflow-x-hidden custom-scroll"
|
||||||
|
: "overflow-hidden"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col h-full gap-5">
|
||||||
|
<table className="table-fixed w-full h-full divide-y divide-gray-300">
|
||||||
|
<thead>
|
||||||
|
<tr className="divide-x divide-gray-200">
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
className="py-3.5 px-4 text-center text-sm font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
Parameters
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
className="px-4 py-3.5 text-center text-sm font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
Advanced
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="divide-y divide-gray-200 bg-white align-top">
|
||||||
|
{advanced.length > parameters.length
|
||||||
|
? advanced.map((t, idx) => (
|
||||||
|
<tr
|
||||||
|
key={idx}
|
||||||
|
className="divide-x divide-gray-200"
|
||||||
|
>
|
||||||
|
<td className="gap-3 py-4 px-4 text-sm font-medium text-gray-900">
|
||||||
|
{data.node.template[parameters[idx]] ? (
|
||||||
|
<button
|
||||||
|
className="flex gap-3 w-full items-center"
|
||||||
|
onClick={() => {
|
||||||
|
data.node.template[
|
||||||
|
parameters[idx]
|
||||||
|
].advanced = true;
|
||||||
|
updateAdvancedParameters();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{data.node.template[parameters[idx]]
|
||||||
|
.display_name
|
||||||
|
? data.node.template[
|
||||||
|
parameters[idx]
|
||||||
|
].display_name
|
||||||
|
: data.node.template[
|
||||||
|
parameters[idx]
|
||||||
|
].name
|
||||||
|
? toTitleCase(
|
||||||
|
data.node.template[
|
||||||
|
parameters[idx]
|
||||||
|
].name
|
||||||
|
)
|
||||||
|
: toTitleCase(t)}
|
||||||
|
<ChevronDoubleRightIcon className="h-5 w-5 text-gray-900" />
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="p-4 text-sm text-right font-medium text-gray-900">
|
||||||
|
<button
|
||||||
|
className="w-full flex justify-end gap-3 items-center"
|
||||||
|
onClick={() => {
|
||||||
|
data.node.template[t].advanced =
|
||||||
|
false;
|
||||||
|
updateAdvancedParameters();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ChevronDoubleLeftIcon className="h-5 w-5 text-gray-900" />
|
||||||
|
{data.node.template[t].display_name
|
||||||
|
? data.node.template[t].display_name
|
||||||
|
: data.node.template[t].name
|
||||||
|
? toTitleCase(
|
||||||
|
data.node.template[t].name
|
||||||
|
)
|
||||||
|
: toTitleCase(t)}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
: parameters.map((t, idx) => (
|
||||||
|
<tr
|
||||||
|
key={idx}
|
||||||
|
className="divide-x divide-gray-200"
|
||||||
|
>
|
||||||
|
<td className="gap-3 py-4 px-4 text-sm font-medium text-gray-900">
|
||||||
|
<button
|
||||||
|
className="
|
||||||
|
flex gap-3 w-full items-center"
|
||||||
|
onClick={() => {
|
||||||
|
data.node.template[t].advanced =
|
||||||
|
true;
|
||||||
|
updateAdvancedParameters();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{data.node.template[t].display_name
|
||||||
|
? data.node.template[t].display_name
|
||||||
|
: data.node.template[t].name
|
||||||
|
? toTitleCase(
|
||||||
|
data.node.template[t].name
|
||||||
|
)
|
||||||
|
: toTitleCase(t)}
|
||||||
|
<ChevronDoubleRightIcon className="h-5 w-5 text-gray-900" />
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
<td className="p-4 text-sm text-right font-medium text-gray-900">
|
||||||
|
{data.node.template[advanced[idx]] ? (
|
||||||
|
<button
|
||||||
|
className="w-full flex justify-end gap-3 items-center"
|
||||||
|
onClick={() => {
|
||||||
|
data.node.template[
|
||||||
|
advanced[idx]
|
||||||
|
].advanced = false;
|
||||||
|
updateAdvancedParameters();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ChevronDoubleLeftIcon className="h-5 w-5 text-gray-900" />
|
||||||
|
{data.node.template[advanced[idx]]
|
||||||
|
.display_name
|
||||||
|
? data.node.template[
|
||||||
|
advanced[idx]
|
||||||
|
].display_name
|
||||||
|
: data.node.template[
|
||||||
|
advanced[idx]
|
||||||
|
].name
|
||||||
|
? toTitleCase(
|
||||||
|
data.node.template[
|
||||||
|
advanced[idx]
|
||||||
|
].name
|
||||||
|
)
|
||||||
|
: toTitleCase(t)}
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="bg-gray-200 dark:bg-gray-900 w-full pb-3 flex flex-row-reverse px-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="inline-flex w-full justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
onClick={() => {
|
||||||
|
setModalOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Done
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog.Panel>
|
||||||
|
</Transition.Child>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</Transition.Root>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,7 @@ import { Fragment } from "react";
|
||||||
import NodeModal from "../../../../modals/NodeModal";
|
import NodeModal from "../../../../modals/NodeModal";
|
||||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||||
import { useReactFlow } from "reactflow";
|
import { useReactFlow } from "reactflow";
|
||||||
|
import EditNodeModal from "../../../../modals/EditNodeModal";
|
||||||
|
|
||||||
const NodeToolbarComponent = (props) => {
|
const NodeToolbarComponent = (props) => {
|
||||||
const { setLastCopiedSelection, paste } = useContext(TabsContext);
|
const { setLastCopiedSelection, paste } = useContext(TabsContext);
|
||||||
|
|
@ -109,6 +110,9 @@ const NodeToolbarComponent = (props) => {
|
||||||
<button
|
<button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
props.openPopUp(
|
||||||
|
<EditNodeModal data={props.data} />
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
active
|
active
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue