From 54e0eb5c7f11eba91a28373462002fc7337b8697 Mon Sep 17 00:00:00 2001 From: saga6569 Date: Mon, 23 Dec 2024 09:36:51 +0500 Subject: [PATCH] fix modals --- frontend/src/index.css | 8 + .../src/modals/FlowModal/CreateFlowModal.tsx | 447 +++++++++++------- .../src/modals/LocalStorage/LocalStorage.tsx | 168 ++++--- frontend/src/modals/NodeModal/NodeModal.tsx | 430 ++++++++++------- .../modals/ResponseModal/ResponseModal.tsx | 422 ++++++++++------- 5 files changed, 897 insertions(+), 578 deletions(-) diff --git a/frontend/src/index.css b/frontend/src/index.css index db0b6c25..9da4d240 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -396,4 +396,12 @@ table thead tr:nth-child(2) { .zoom-out { animation: zoom-out 0.2s ease-in forwards; +} + +.pCustom { + padding: 0px !important; +} + +.w-auto { + width: auto !important; } \ No newline at end of file diff --git a/frontend/src/modals/FlowModal/CreateFlowModal.tsx b/frontend/src/modals/FlowModal/CreateFlowModal.tsx index b369c1fd..f6aa3c8f 100644 --- a/frontend/src/modals/FlowModal/CreateFlowModal.tsx +++ b/frontend/src/modals/FlowModal/CreateFlowModal.tsx @@ -1,183 +1,292 @@ import { - Button, - Checkbox, - Input, - ModalBody, - ModalContent, - ModalFooter, - ModalHeader, - Select, - SelectItem, -} from "@nextui-org/react" -import { HelpCircle } from "lucide-react" -import { useContext, useState } from "react" -import ModalComponent from "../../components/ModalComponent" -import { FLOW_COLORS } from "../../consts" -import { flowContext } from "../../contexts/flowContext" -import { NotificationsContext } from "../../contexts/notificationsContext" -import { ModalType } from "../../types/ModalTypes" -import { generateNewFlow, validateFlowName } from "../../utils" + Button, + Checkbox, + Input, + // ModalBody, + ModalContent, + // ModalFooter, + // ModalHeader, + Select, + SelectItem, +} from "@nextui-org/react"; +import { Modal, ModalBody, ModalFooter, ModalHeader } from "../ModalComponents"; +import { HelpCircle } from "lucide-react"; +import { useContext, useState } from "react"; +import ModalComponent from "../../components/ModalComponent"; +import { FLOW_COLORS } from "../../consts"; +import { flowContext } from "../../contexts/flowContext"; +import { NotificationsContext } from "../../contexts/notificationsContext"; +import { ModalType } from "../../types/ModalTypes"; +import { generateNewFlow, validateFlowName } from "../../utils"; interface CreateFlowModalProps extends ModalType {} export type CreateFlowType = { - name: string - description: string - color: string - subflow: string -} + name: string; + description: string; + color: string; + subflow: string; +}; -const CreateFlowModal = ({ isOpen, onClose, size = "3xl" }: CreateFlowModalProps) => { - const { flows, setFlows, saveFlows } = useContext(flowContext) - const { notification: n } = useContext(NotificationsContext) - const [flow, setFlow] = useState({ +const CreateFlowModal = ({ + isOpen, + onClose, + size = "3xl", +}: CreateFlowModalProps) => { + const { flows, setFlows, saveFlows } = useContext(flowContext); + const { notification: n } = useContext(NotificationsContext); + const [flow, setFlow] = useState({ + name: "", + description: "", + color: "", + subflow: "Global", + }); + const [isSubFlow, setIsSubFlow] = useState(false); + + const onFlowChange = (e: React.ChangeEvent) => { + setFlow({ + ...flow, + [e.target.name]: e.target.value, + }); + }; + + const onFlowSave = () => { + if (!validateFlowName(flow.name, flows)) { + return n.add({ + title: "Warning!", + message: "Flow name is not valid.", + type: "warning", + }); + } + if (flow.color && flow.subflow) { + const newFlow = generateNewFlow(flow); + setFlows([...flows, newFlow]); + saveFlows([...flows, newFlow]); + setFlow({ name: "", description: "", color: "", subflow: "Global", - }) - const [isSubFlow, setIsSubFlow] = useState(false) - - const onFlowChange = (e: React.ChangeEvent) => { - setFlow({ - ...flow, - [e.target.name]: e.target.value, - }) + }); + setIsSubFlow(false); + onClose(); + } else { + n.add({ + title: "Creating error!", + message: "Please fill all the fields correctly.", + type: "error", + }); } + }; - const onFlowSave = () => { - if (!validateFlowName(flow.name, flows)) { - return n.add({ - title: "Warning!", - message: "Flow name is not valid.", - type: "warning", - }) - } - if (flow.color && flow.subflow) { - const newFlow = generateNewFlow(flow) - setFlows([...flows, newFlow]) - saveFlows([...flows, newFlow]) - setFlow({ - name: "", - description: "", - color: "", - subflow: "Global", - }) - setIsSubFlow(false) - onClose() - } else { - n.add({ - title: "Creating error!", - message: "Please fill all the fields correctly.", - type: "error", - }) - } - } + return ( + // + // + // {"Create flow"} + // + //
+ // + // + //
+ //
+ // + //
+ // {FLOW_COLORS.map((color) => ( + // + // ))} + //
+ //
+ //
+ //
+ // + // setIsSubFlow(!isSubFlow)} + // checked={isSubFlow} + // /> + //
+ //
+ //
+ // + //
+ //
+ //
+ //
+ // + //
+ // + //
+ //
+ // + //
+ //
+ //
+ //
- return ( - - - {"Create flow"} - -
- - -
-
- -
- {FLOW_COLORS.map((color) => ( - - ))} -
-
-
-
- - setIsSubFlow(!isSubFlow)} - checked={isSubFlow} - /> -
-
-
- -
-
-
-
- -
- -
-
- -
-
-
-
- ) -} + + {"Create flow"} + +
+ + +
+ +
+ {FLOW_COLORS.map((color) => ( + + ))} +
+
+
+ + setIsSubFlow(!isSubFlow)} checked={isSubFlow} /> +
+
+
+ +
+
+
+
+ +
+ +
+
+ +
+
+
+ ); +}; -export default CreateFlowModal +export default CreateFlowModal; diff --git a/frontend/src/modals/LocalStorage/LocalStorage.tsx b/frontend/src/modals/LocalStorage/LocalStorage.tsx index 1756db10..c274f714 100644 --- a/frontend/src/modals/LocalStorage/LocalStorage.tsx +++ b/frontend/src/modals/LocalStorage/LocalStorage.tsx @@ -1,58 +1,116 @@ import { - Modal, - ModalBody, - ModalContent, - ModalFooter, - ModalHeader, - Tab, - Tabs, -} from "@nextui-org/react" -import React from "react" + // Modal, + // ModalBody, + // ModalContent, + // ModalFooter, + // ModalHeader, + Tab, + Tabs, +} from "@nextui-org/react"; +import { Modal, ModalBody, ModalFooter, ModalHeader } from "../ModalComponents"; +const LocalStorage = ({ + isOpen, + onClose, +}: { + isOpen: boolean; + onClose: () => void; +}) => { + return ( + // + // + // Local Storage + // + // + // Components} + // > + // Coming soon... + // + // Conditions} + // > + // Coming soon... + // + // Slot snippets} + // > + // Coming soon... + // + // Presets} + // > + // Coming soon... + // + // + // + // + // + // -const LocalStorage = ({ isOpen, onClose }: { isOpen: boolean; onClose: () => void }) => { - return ( - - - Local Storage - - - Components}> - Coming soon... - - Conditions}> - Coming soon... - - Slot snippets}> - Coming soon... - - Presets}> - Coming soon... - - - - - - - ) -} + + + Local Storage + + + + Components} + > + Coming soon... + + Conditions} + > + Coming soon... + + Slot snippets} + > + Coming soon... + + Presets} + > + Coming soon... + + + + + {""} + + + ); +}; -export default LocalStorage +export default LocalStorage; diff --git a/frontend/src/modals/NodeModal/NodeModal.tsx b/frontend/src/modals/NodeModal/NodeModal.tsx index d21cf9b6..ba05856d 100644 --- a/frontend/src/modals/NodeModal/NodeModal.tsx +++ b/frontend/src/modals/NodeModal/NodeModal.tsx @@ -1,188 +1,272 @@ import { - Button, - Input, - ModalBody, - ModalContent, - ModalFooter, - ModalHeader, - ModalProps, -} from "@nextui-org/react" -import { Edge, useReactFlow } from "@xyflow/react" -import { HelpCircle, TrashIcon } from "lucide-react" -import React, { useCallback, useContext, useEffect } from "react" -import ModalComponent from "../../components/ModalComponent" -import { flowContext } from "../../contexts/flowContext" -import { undoRedoContext } from "../../contexts/undoRedoContext" -import EditPenIcon from "../../icons/EditPenIcon" -import { DefaultNodeDataType, DefaultNodeType } from "../../types/NodeTypes" -import ConditionRow from "./components/ConditionRow" + Button, + Input, + // ModalBody, + ModalContent, + // ModalFooter, + // ModalHeader, + ModalProps, +} from "@nextui-org/react"; +import { Modal, ModalBody, ModalFooter, ModalHeader } from "../ModalComponents"; +import { Edge, useReactFlow } from "@xyflow/react"; +import { HelpCircle, TrashIcon } from "lucide-react"; +import React, { useCallback, useContext, useEffect } from "react"; +// import ModalComponent from "../../components/ModalComponent"; +import { flowContext } from "../../contexts/flowContext"; +import { undoRedoContext } from "../../contexts/undoRedoContext"; +import EditPenIcon from "../../icons/EditPenIcon"; +import { DefaultNodeDataType, DefaultNodeType } from "../../types/NodeTypes"; +import ConditionRow from "./components/ConditionRow"; type NodeModalProps = { - data: DefaultNodeDataType - size?: ModalProps["size"] - isOpen: boolean - onClose: () => void - onResponseModalOpen: () => void - nodeDataState: DefaultNodeDataType - setNodeDataState: React.Dispatch> -} + data: DefaultNodeDataType; + size?: ModalProps["size"]; + isOpen: boolean; + onClose: () => void; + onResponseModalOpen: () => void; + nodeDataState: DefaultNodeDataType; + setNodeDataState: React.Dispatch>; +}; const NodeModal = ({ - data, - isOpen, - onClose, - size = "3xl", - onResponseModalOpen, - nodeDataState, - setNodeDataState, + data, + isOpen, + onClose, + size = "3xl", + onResponseModalOpen, + nodeDataState, + setNodeDataState, }: NodeModalProps) => { - const { getNodes, setNodes, updateNodeData } = useReactFlow() - const { quietSaveFlows, validateNodeDeletion } = useContext(flowContext) - const { takeSnapshot } = useContext(undoRedoContext) + const { getNodes, setNodes, updateNodeData } = useReactFlow< + DefaultNodeType, + Edge + >(); + const { quietSaveFlows, validateNodeDeletion } = useContext(flowContext); + const { takeSnapshot } = useContext(undoRedoContext); - useEffect(() => { - setNodeDataState(getNodes().find((node) => node.data.id === data.id)?.data ?? data) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isOpen]) + useEffect(() => { + setNodeDataState( + getNodes().find((node) => node.data.id === data.id)?.data ?? data + ); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isOpen]); - const setDataStateValue = useCallback( - (e: React.ChangeEvent) => { - setNodeDataState({ ...nodeDataState, [e.target.name]: e.target.value }) - }, - [nodeDataState, setNodeDataState] - ) + const setDataStateValue = useCallback( + (e: React.ChangeEvent) => { + setNodeDataState({ ...nodeDataState, [e.target.name]: e.target.value }); + }, + [nodeDataState, setNodeDataState] + ); - const setTextResponseValue = (e: React.ChangeEvent) => { - setNodeDataState({ - ...nodeDataState, - response: { - ...nodeDataState.response!, - type: "text", - data: [{ text: e.target.value, priority: 1 }], - }, - }) - } + const setTextResponseValue = (e: React.ChangeEvent) => { + setNodeDataState({ + ...nodeDataState, + response: { + ...nodeDataState.response!, + type: "text", + data: [{ text: e.target.value, priority: 1 }], + }, + }); + }; - const onNodeSave = () => { - takeSnapshot() - updateNodeData(data.id, { ...nodeDataState }) - quietSaveFlows() - onClose() - } + const onNodeSave = () => { + takeSnapshot(); + updateNodeData(data.id, { ...nodeDataState }); + quietSaveFlows(); + onClose(); + }; - const onNodeDelete = () => { - const is_deletion_valid = validateNodeDeletion({ - data, - id: data.id, - position: { x: 0, y: 0 }, - type: "default_node", - }) - if (!is_deletion_valid) return -1 - takeSnapshot() - const nodes = getNodes() - const new_nodes = nodes.filter((node) => node.data.id !== data.id) - setNodes(new_nodes) - quietSaveFlows() - onClose() - } + const onNodeDelete = () => { + const is_deletion_valid = validateNodeDeletion({ + data, + id: data.id, + position: { x: 0, y: 0 }, + type: "default_node", + }); + if (!is_deletion_valid) return -1; + takeSnapshot(); + const nodes = getNodes(); + const new_nodes = nodes.filter((node) => node.data.id !== data.id); + setNodes(new_nodes); + quietSaveFlows(); + onClose(); + }; - const deleteCondition = (id: string) => { - if (nodeDataState.conditions) { - setNodeDataState({ - ...nodeDataState, - conditions: nodeDataState.conditions.filter((c) => c.id !== id), - }) - } + const deleteCondition = (id: string) => { + if (nodeDataState.conditions) { + setNodeDataState({ + ...nodeDataState, + conditions: nodeDataState.conditions.filter((c) => c.id !== id), + }); } + }; + + return ( + <> + {/* + + {"Edit node"} + + +
+ + + + + +
+
+

Conditions (x)

+
+
+
NAME
+
PRIORITY
+
ACTIONS
+
+
+ {nodeDataState.conditions?.map((cnd) => ( + + ))} +
+
+
+
+ +
+ + +
+
+ +
+
+
+
*/} + + {"Edit node"} + + +
+ + + + + +
+
+

Conditions (x)

+
+
+
NAME
+
PRIORITY
+
ACTIONS
+
+
+ {nodeDataState.conditions?.map((cnd) => ( + + ))} +
+
+
+
+ +
+ + +
+
+ +
+
+
+ + ); +}; - return ( - <> - - - {"Edit node"} - - -
- - - - - -
-
-

Conditions (x)

-
-
-
NAME
-
PRIORITY
-
ACTIONS
-
-
- {nodeDataState.conditions?.map((cnd) => ( - - ))} -
-
-
-
- -
- - -
-
- -
-
-
-
- - ) -} +//flex py-4 px-6 flex-initial text-large font-semibold hedr +// class="flex flex-1 flex-col gap-3 px-6 py-2" body +//flex-row gap-2 px-6 py-4 flex justify-between items-center futer -export default NodeModal +export default NodeModal; diff --git a/frontend/src/modals/ResponseModal/ResponseModal.tsx b/frontend/src/modals/ResponseModal/ResponseModal.tsx index d2ab7e99..e42f4613 100644 --- a/frontend/src/modals/ResponseModal/ResponseModal.tsx +++ b/frontend/src/modals/ResponseModal/ResponseModal.tsx @@ -1,193 +1,253 @@ import { - Button, - Input, - ModalBody, - ModalContent, - ModalFooter, - ModalHeader, - ModalProps, - Tab, - Tabs, -} from "@nextui-org/react" -import { useReactFlow } from "@xyflow/react" -import { useContext, useMemo, useState } from "react" -import { useParams } from "react-router-dom" -import ModalComponent from "../../components/ModalComponent" -import { flowContext } from "../../contexts/flowContext" -import { NotificationsContext } from "../../contexts/notificationsContext" -import { DefaultNodeDataType } from "../../types/NodeTypes" -import { responseType, responseTypeType } from "../../types/ResponseTypes" -import PythonResponse from "./components/PythonResponse" -import TextResponse from "./components/TextResponse" - -type ResponseModalTab = "Using LLM" | "Python code" | "Custom" | "Text" + Button, + Input, + ModalProps, + Tab, + Tabs, +} from "@nextui-org/react"; +// import ModalComponent from "../../components/ModalComponent"; +import { useReactFlow } from "@xyflow/react"; +import { useContext, useMemo, useState } from "react"; +import { useParams } from "react-router-dom"; +import { flowContext } from "../../contexts/flowContext"; +import { NotificationsContext } from "../../contexts/notificationsContext"; +import { DefaultNodeDataType } from "../../types/NodeTypes"; +import { responseType, responseTypeType } from "../../types/ResponseTypes"; +import PythonResponse from "./components/PythonResponse"; +import TextResponse from "./components/TextResponse"; +import { Modal, ModalBody, ModalFooter, ModalHeader } from "../ModalComponents"; +type ResponseModalTab = "Using LLM" | "Python code" | "Custom" | "Text"; type ResponseModalProps = { - data: DefaultNodeDataType - setData: React.Dispatch> - response: responseType - size?: ModalProps["size"] - isOpen: boolean - onClose: () => void -} + data: DefaultNodeDataType; + setData: React.Dispatch>; + response: responseType; + size?: ModalProps["size"]; + isOpen: boolean; + onClose: () => void; +}; const ResponseModal = ({ - isOpen, - onClose, - data, - setData, - response, - size = "3xl", + isOpen, + onClose, + data, + setData, + response, + size = "3xl", }: ResponseModalProps) => { - const { getNode, setNodes, getNodes } = useReactFlow() - const { flows, quietSaveFlows } = useContext(flowContext) - const { flowId } = useParams() - const [selected, setSelected] = useState(response.type ?? "python") - // const [nodeDataState, setNodeDataState] = useState(data) - const [currentResponse, setCurrentResponse] = useState(response) - const setSelectedHandler = (key: responseTypeType) => { - setCurrentResponse({ ...currentResponse, type: key }) - setSelected(key) - } - const { notification: n } = useContext(NotificationsContext) + const { getNode, setNodes, getNodes } = useReactFlow(); + const { flows, quietSaveFlows } = useContext(flowContext); + const { flowId } = useParams(); + const [selected, setSelected] = useState( + response.type ?? "python" + ); + // const [nodeDataState, setNodeDataState] = useState(data) + const [currentResponse, setCurrentResponse] = useState(response); + const setSelectedHandler = (key: responseTypeType) => { + setCurrentResponse({ ...currentResponse, type: key }); + setSelected(key); + }; + const { notification: n } = useContext(NotificationsContext); - const tabItems: { - title: ResponseModalTab - value: responseTypeType - }[] = useMemo( - () => [ - { - title: "Python code", - value: "python", - }, - { - title: "Text", - value: "text", - }, - { - title: "Using LLM", - value: "llm", - }, - ], - [] - ) + const tabItems: { + title: ResponseModalTab; + value: responseTypeType; + }[] = useMemo( + () => [ + { + title: "Python code", + value: "python", + }, + { + title: "Text", + value: "text", + }, + { + title: "Using LLM", + value: "llm", + }, + ], + [] + ); - const bodyItems = useMemo( - () => ({ - llm:
llm
, - python: ( - - ), - custom:
Custom
, - text: ( - - ), - }), - [currentResponse] - ) + const bodyItems = useMemo( + () => ({ + llm:
llm
, + python: ( + + ), + custom:
Custom
, + text: ( + + ), + }), + [currentResponse] + ); - const saveResponse = () => { - if (!currentResponse.name) { - return n.add({ - title: "Saving error!", - message: "Response name is required!", - type: "error", - }) - } - if (flows.some((flow) => flow.data.nodes.some((node) => (node.type === "default_node" && node.data.response.name === currentResponse.name && node.id !== data.id)))) { - return n.add({ - title: "Saving error!", - message: "Response name must be unique!", - type: "error", - }) - } else { - const nodes = getNodes() - const node = getNode(data.id) - const currentFlow = flows.find((flow) => flow.name === flowId) - if (node && currentFlow) { - const new_node = { - ...node, - data: { - ...node.data, - response: currentResponse, - }, + const saveResponse = () => { + if (!currentResponse.name) { + return n.add({ + title: "Saving error!", + message: "Response name is required!", + type: "error", + }); + } + if ( + flows.some((flow) => + flow.data.nodes.some( + (node) => + node.type === "default_node" && + node.data.response.name === currentResponse.name && + node.id !== data.id + ) + ) + ) { + return n.add({ + title: "Saving error!", + message: "Response name must be unique!", + type: "error", + }); + } else { + const nodes = getNodes(); + const node = getNode(data.id); + const currentFlow = flows.find((flow) => flow.name === flowId); + if (node && currentFlow) { + const new_node = { + ...node, + data: { + ...node.data, + response: currentResponse, + }, + }; + const new_nodes = nodes.map((node) => + node.id === data.id ? new_node : node + ); + setNodes(() => new_nodes); + setData({ + ...data, + response: new_node.data.response, + }); + // currentFlow.data.nodes = nodes.map((node) => (node.id === data.id ? new_node : node)) + // updateFlow(currentFlow) + quietSaveFlows(); + onClose(); + } + } + }; + return ( + + Edit response + + +
+ + setCurrentResponse({ ...currentResponse, name: e.target.value }) } - } - } - - return ( - - - Edit response - - -
- setCurrentResponse({ ...currentResponse, name: e.target.value })} - /> -
-
{bodyItems[selected]}
-
- - - -
-
- ) -} + /> +
+
{bodyItems[selected]}
+
+ + + +
+ // + // + // Edit response + // + // + //
+ // + // setCurrentResponse({ ...currentResponse, name: e.target.value }) + // } + // /> + //
+ //
{bodyItems[selected]}
+ //
+ // + // + // + //
+ //
+ ); +}; -export default ResponseModal +export default ResponseModal;