diff --git a/src/frontend/src/components/ui/select-custom.tsx b/src/frontend/src/components/ui/select-custom.tsx new file mode 100644 index 000000000..5ed2fbd45 --- /dev/null +++ b/src/frontend/src/components/ui/select-custom.tsx @@ -0,0 +1,108 @@ +"use client"; + +import * as SelectPrimitive from "@radix-ui/react-select"; +import * as React from "react"; +import { cn } from "../../utils/utils"; + +const Select = SelectPrimitive.Root; + +const SelectGroup = SelectPrimitive.Group; + +const SelectValue = SelectPrimitive.Value; + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + {children} + + + +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + +export { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectSeparator, + SelectTrigger, + SelectValue, +}; diff --git a/src/frontend/src/modals/EditNodeModal/index.tsx b/src/frontend/src/modals/EditNodeModal/index.tsx index b4023b11f..8aeb81818 100644 --- a/src/frontend/src/modals/EditNodeModal/index.tsx +++ b/src/frontend/src/modals/EditNodeModal/index.tsx @@ -1,12 +1,5 @@ import { cloneDeep } from "lodash"; -import { - ReactNode, - forwardRef, - useContext, - useEffect, - useRef, - useState, -} from "react"; +import { ReactNode, forwardRef, useContext, useEffect, useState } from "react"; import CodeAreaComponent from "../../components/codeAreaComponent"; import DictComponent from "../../components/dictComponent"; import Dropdown from "../../components/dropdownComponent"; @@ -49,19 +42,22 @@ const EditNodeModal = forwardRef( setData, nodeLength, children, + open, + onClose, }: { data: NodeDataType; setData: (data: NodeDataType) => void; nodeLength: number; children: ReactNode; + open?: boolean; + onClose?: (close: boolean) => void; }, ref ) => { - const [modalOpen, setModalOpen] = useState(false); + const [modalOpen, setModalOpen] = useState(open ?? false); + const [myData, setMyData] = useState(data); const { setTabsState, tabId } = useContext(TabsContext); const { reactFlowInstance } = useContext(typesContext); - const myData = useRef(data); - let disabled = reactFlowInstance ?.getEdges() @@ -70,17 +66,18 @@ const EditNodeModal = forwardRef( function changeAdvanced(n) { let newData = cloneDeep(data); newData.node!.template[n].advanced = !newData.node!.template[n].advanced; - myData.current = newData; + setMyData(newData); } const handleOnNewValue = (newValue: any, name) => { let newData = cloneDeep(data); newData.node!.template[name].value = newValue; - myData.current = newData; + setMyData(newData); }; useEffect(() => { - myData.current = data; + setMyData(data); // reset data to what it is on node when opening modal + onClose!(modalOpen); }, [modalOpen]); const [obj, setObj] = useState({ @@ -109,11 +106,11 @@ const EditNodeModal = forwardRef( setOpen={setModalOpen} onChangeOpenModal={(open) => { let newData = cloneDeep(data); - myData.current = newData; + setMyData(newData); }} > {children} - + {myData.type} ID: {myData.id} @@ -148,65 +145,58 @@ const EditNodeModal = forwardRef( - {Object.keys(myData.current.node!.template) + {Object.keys(myData.node!.template) .filter( (templateParam) => templateParam.charAt(0) !== "_" && - myData.current.node?.template[templateParam].show && - (myData.current.node.template[templateParam] - .type === "str" || - myData.current.node.template[templateParam] - .type === "bool" || - myData.current.node.template[templateParam] - .type === "float" || - myData.current.node.template[templateParam] - .type === "code" || - myData.current.node.template[templateParam] - .type === "prompt" || - myData.current.node.template[templateParam] - .type === "file" || - myData.current.node.template[templateParam] - .type === "int") + myData.node?.template[templateParam].show && + (myData.node.template[templateParam].type === + "str" || + myData.node.template[templateParam].type === + "bool" || + myData.node.template[templateParam].type === + "float" || + myData.node.template[templateParam].type === + "code" || + myData.node.template[templateParam].type === + "prompt" || + myData.node.template[templateParam].type === + "file" || + myData.node.template[templateParam].type === + "int") ) .map((templateParam, index) => ( - {myData.current.node?.template[templateParam].name - ? myData.current.node.template[templateParam] - .name - : myData.current.node?.template[templateParam] + {myData.node?.template[templateParam].name + ? myData.node.template[templateParam].name + : myData.node?.template[templateParam] .display_name} - {myData.current.node?.template[templateParam] - .type === "str" && - !myData.current.node.template[templateParam] - .options ? ( + {myData.node?.template[templateParam].type === + "str" && + !myData.node.template[templateParam].options ? (
- {myData.current.node.template[templateParam] - .list ? ( + {myData.node.template[templateParam].list ? ( { handleOnNewValue(value, templateParam); }} /> - ) : myData.current.node?.template[ - templateParam - ].type === "NestedDict" ? ( + ) : myData.node?.template[templateParam] + .type === "NestedDict" ? (
- ) : myData.current.node?.template[ - templateParam - ].type === "dict" ? ( + ) : myData.node?.template[templateParam] + .type === "dict" ? (
- ) : myData.current.node.template[ - templateParam - ].multiline ? ( + ) : myData.node.template[templateParam] + .multiline ? ( { handleOnNewValue(value, templateParam); @@ -274,14 +259,12 @@ const EditNodeModal = forwardRef( editNode={true} disabled={disabled} password={ - myData.current.node.template[ - templateParam - ].password ?? false + myData.node.template[templateParam] + .password ?? false } value={ - myData.current.node.template[ - templateParam - ].value ?? "" + myData.node.template[templateParam] + .value ?? "" } onChange={(value) => { handleOnNewValue(value, templateParam); @@ -289,16 +272,14 @@ const EditNodeModal = forwardRef( /> )}
- ) : myData.current.node?.template[templateParam] - .type === "bool" ? ( + ) : myData.node?.template[templateParam].type === + "bool" ? (
{" "} { handleOnNewValue( @@ -309,84 +290,76 @@ const EditNodeModal = forwardRef( size="small" />
- ) : myData.current.node?.template[templateParam] - .type === "float" ? ( + ) : myData.node?.template[templateParam].type === + "float" ? (
{ handleOnNewValue(value, templateParam); }} />
- ) : myData.current.node?.template[templateParam] - .type === "str" && - myData.current.node.template[templateParam] - .options ? ( + ) : myData.node?.template[templateParam].type === + "str" && + myData.node.template[templateParam].options ? (
handleOnNewValue(value, templateParam) } value={ - myData.current.node.template[ - templateParam - ].value ?? "Choose an option" + myData.node.template[templateParam] + .value ?? "Choose an option" } >
- ) : myData.current.node?.template[templateParam] - .type === "int" ? ( + ) : myData.node?.template[templateParam].type === + "int" ? (
{ handleOnNewValue(value, templateParam); }} />
- ) : myData.current.node?.template[templateParam] - .type === "file" ? ( + ) : myData.node?.template[templateParam].type === + "file" ? (
{ handleOnNewValue(value, templateParam); }} fileTypes={ - myData.current.node.template[ - templateParam - ].fileTypes + myData.node.template[templateParam] + .fileTypes } suffixes={ - myData.current.node.template[ - templateParam - ].suffixes + myData.node.template[templateParam] + .suffixes } onFileChange={(filePath: string) => { data.node!.template[ @@ -395,29 +368,28 @@ const EditNodeModal = forwardRef( }} >
- ) : myData.current.node?.template[templateParam] - .type === "prompt" ? ( + ) : myData.node?.template[templateParam].type === + "prompt" ? (
{ - myData.current.node = nodeClass; + myData.node = nodeClass; }} value={ - myData.current.node.template[ - templateParam - ].value ?? "" + myData.node.template[templateParam] + .value ?? "" } onChange={(value: string | string[]) => { handleOnNewValue(value, templateParam); }} />
- ) : myData.current.node?.template[templateParam] - .type === "code" ? ( + ) : myData.node?.template[templateParam].type === + "code" ? (
{ handleOnNewValue(value, templateParam); }} />
- ) : myData.current.node?.template[templateParam] - .type === "Any" ? ( + ) : myData.node?.template[templateParam].type === + "Any" ? ( "-" ) : (
@@ -451,9 +422,8 @@ const EditNodeModal = forwardRef(
changeAdvanced(templateParam) diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx index 7b782a656..e1e3bd5c4 100644 --- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx @@ -2,10 +2,16 @@ import { useContext, useState } from "react"; import { useReactFlow, useUpdateNodeInternals } from "reactflow"; import ShadTooltip from "../../../../components/ShadTooltipComponent"; import IconComponent from "../../../../components/genericIconComponent"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, +} from "../../../../components/ui/select-custom"; import { TabsContext } from "../../../../contexts/tabsContext"; import EditNodeModal from "../../../../modals/EditNodeModal"; import { nodeToolbarPropsType } from "../../../../types/components"; -import { classNames } from "../../../../utils/utils"; +import { classNames, getRandomKeyByssmm } from "../../../../utils/utils"; export default function NodeToolbarComponent({ data, @@ -40,9 +46,24 @@ export default function NodeToolbarComponent({ if (countHandles > 1) return false; return true; } - + const isMinimal = canMinimize(); const { paste } = useContext(TabsContext); const reactFlowInstance = useReactFlow(); + const [showModalAdvanced, setShowModalAdvanced] = useState(false); + const [selectedValue, setSelectedValue] = useState(""); + + const handleSelectChange = (event) => { + setSelectedValue(event); + if (event.includes("advanced")) { + return setShowModalAdvanced(true); + } + setShowModalAdvanced(false); + if (event.includes("show")) { + setShowNode((prev) => !prev); + updateNodeInternals(data.id); + } + }; + return ( <>
@@ -110,6 +131,83 @@ export default function NodeToolbarComponent({ + {isMinimal ? ( + + ) : ( + +
+ +
+
+ )} + + {showModalAdvanced && ( + { + setShowModalAdvanced(modal); + }} + > + <> + + )} + + {/*
-
- - {canMinimize() && ( - - - - )} + */}